-
Notifications
You must be signed in to change notification settings - Fork 0
feat(yaml): adds a hera version of the example.yaml template from workflows #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,9 @@ dev = [ | |
| "tox-uv", | ||
| "types-mock", | ||
| "PyYAML", | ||
| "pillow", | ||
| "numpy", | ||
| "h5py", | ||
| ] | ||
|
|
||
| [project.scripts] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| apiVersion: argoproj.io/v1alpha1 | ||
| kind: Workflow | ||
| metadata: | ||
| generateName: hera-example- | ||
| namespace: ks10000-3 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: best to avoid surfacing ks10000 developer test namespaces in user facing documentation if possible |
||
| annotations: | ||
| workflows.argoproj.io/description: |- | ||
| Replicates the functionality of | ||
| example.yaml | ||
| workflows.argoproj.io/title: example remade via hera | ||
| workflows.diamond.ac.uk/repository: https://github.com/DiamondLightSource/python-interface-to-workflows | ||
| labels: | ||
| workflows.diamond.ac.uk/science-group-examples: 'true' | ||
| spec: | ||
| entrypoint: workflowentry | ||
| templates: | ||
| - name: workflowentry | ||
| dag: | ||
| tasks: | ||
| - name: install | ||
| template: install-dependencies | ||
| - name: params | ||
| template: generate-parameters | ||
| arguments: | ||
| parameters: | ||
| - name: png | ||
| value: 'True' | ||
| - name: jpg | ||
| value: 'True' | ||
| - name: jpeg | ||
| value: 'True' | ||
| - name: tif | ||
| value: 'True' | ||
| - name: tiff | ||
| value: 'True' | ||
| - name: create-image | ||
| depends: install && params | ||
| template: create-image | ||
| withParam: '{{tasks.params.outputs.parameters.out-parameters}}' | ||
| arguments: | ||
| parameters: | ||
| - name: width | ||
| value: '{{item.width}}' | ||
| - name: height | ||
| value: '{{item.height}}' | ||
| - name: weights | ||
| value: '{{item.weights}}' | ||
| - name: extension | ||
| value: '{{item.extension}}' | ||
| - name: to-hdf5 | ||
| depends: create-image | ||
| template: to-hdf5 | ||
| arguments: | ||
| parameters: | ||
| - name: paths | ||
| value: '{{tasks.create-image.outputs.parameters.out-paths}}' | ||
| - name: install-dependencies | ||
| script: | ||
| image: python:3.10 | ||
| source: |- | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment for the future, not for this PR: I know that you are doing this because you are re-implementing the example template that does this. I think that if this repo is going to model best user practices for Analysis Platform using pythonistas, we want to encourage building dependencies into the container itself. Installing dependencies in workflow steps is bad practice. |
||
| import os | ||
| import sys | ||
| sys.path.append(os.getcwd()) | ||
| import subprocess | ||
| print('creating venv') | ||
| subprocess.check_call(['python', '-m', 'venv', '/tmp/venv']) | ||
| subprocess.check_call(['/tmp/venv/bin/pip', 'install', 'pillow', 'h5py', 'numpy', 'hera']) | ||
| command: | ||
| - python | ||
| volumeMounts: | ||
| - name: tmpdir | ||
| mountPath: /tmp | ||
| - name: generate-parameters | ||
| inputs: | ||
| parameters: | ||
| - name: png | ||
| - name: jpg | ||
| - name: jpeg | ||
| - name: tif | ||
| - name: tiff | ||
| outputs: | ||
| parameters: | ||
| - name: out-parameters | ||
| valueFrom: | ||
| path: /tmp/parameters.json | ||
| script: | ||
| image: python:3.10 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: python:3.10 is almost end of life. user facing examples should have more up to date version if possible |
||
| source: |- | ||
| import os | ||
| import sys | ||
| sys.path.append(os.getcwd()) | ||
| import json | ||
| try: jpeg = json.loads(r'''{{inputs.parameters.jpeg}}''') | ||
| except: jpeg = r'''{{inputs.parameters.jpeg}}''' | ||
| try: jpg = json.loads(r'''{{inputs.parameters.jpg}}''') | ||
| except: jpg = r'''{{inputs.parameters.jpg}}''' | ||
| try: png = json.loads(r'''{{inputs.parameters.png}}''') | ||
| except: png = r'''{{inputs.parameters.png}}''' | ||
| try: tif = json.loads(r'''{{inputs.parameters.tif}}''') | ||
| except: tif = r'''{{inputs.parameters.tif}}''' | ||
| try: tiff = json.loads(r'''{{inputs.parameters.tiff}}''') | ||
| except: tiff = r'''{{inputs.parameters.tiff}}''' | ||
|
|
||
| import json | ||
| params: list[dict[str, int | list[int] | str] | None] = [{'width': 500, 'height': 500, 'weights': [255, 1, 100], 'extension': 'png'} if png.lower() == 'true' else None, {'width': 600, 'height': 200, 'weights': [100, 150, 100], 'extension': 'jpg'} if jpg.lower() == 'true' else None, {'width': 300, 'height': 400, 'weights': [100, 150, 100], 'extension': 'jpeg'} if jpeg.lower() == 'true' else None, {'width': 300, 'height': 200, 'weights': [230, 100, 1], 'extension': 'tif'} if tif.lower() == 'true' else None, {'width': 200, 'height': 300, 'weights': [230, 100, 1], 'extension': 'tiff'} if tiff.lower() == 'true' else None] | ||
| params_to_write: list[dict[str, int | list[int] | str]] = [image_params for image_params in params if image_params is not None] | ||
| with open('/tmp/parameters.json', 'w') as f: | ||
| json.dump(params_to_write, f) | ||
| command: | ||
| - python | ||
| volumeMounts: | ||
| - name: tmpdir | ||
| mountPath: /tmp | ||
| - name: create-image | ||
| inputs: | ||
| parameters: | ||
| - name: width | ||
| - name: height | ||
| - name: weights | ||
| - name: extension | ||
| outputs: | ||
| artifacts: | ||
| - name: '{{inputs.parameters.extension}}-image' | ||
| path: /tmp/{{inputs.parameters.extension}}-image.{{inputs.parameters.extension}} | ||
| archive: | ||
| none: {} | ||
| parameters: | ||
| - name: out-paths | ||
| valueFrom: | ||
| path: /tmp/{{inputs.parameters.extension}}-path.json | ||
| script: | ||
| image: python:3.10 | ||
| source: |- | ||
| import os | ||
| import sys | ||
| sys.path.append(os.getcwd()) | ||
| import json | ||
| try: extension = json.loads(r'''{{inputs.parameters.extension}}''') | ||
| except: extension = r'''{{inputs.parameters.extension}}''' | ||
| try: height = json.loads(r'''{{inputs.parameters.height}}''') | ||
| except: height = r'''{{inputs.parameters.height}}''' | ||
| try: weights = json.loads(r'''{{inputs.parameters.weights}}''') | ||
| except: weights = r'''{{inputs.parameters.weights}}''' | ||
| try: width = json.loads(r'''{{inputs.parameters.width}}''') | ||
| except: width = r'''{{inputs.parameters.width}}''' | ||
|
|
||
| import json | ||
| from PIL import Image | ||
|
|
||
| def create_pattern(width: int, height: int, weights: tuple[int, int, int]) -> Image.Image: | ||
| print(f'width: {width}') | ||
| print(f'height: {height}') | ||
| print(f'RBG weights: {weights}') | ||
| image = Image.new('RGB', (width, height)) | ||
| pixels = image.load() | ||
| for i in range(width): | ||
| for j in range(height): | ||
| pixels[i, j] = ((i + j * 50) % weights[0], weights[1], (i * 300 + j) % weights[2]) | ||
| return image | ||
| image = create_pattern(width, height, weights) | ||
| path = f'/tmp/{extension}-image.{extension}' | ||
| image.save(path) | ||
| with open(f'/tmp/{extension}-path.json', 'w') as f: | ||
| json.dump(path, f) | ||
| command: | ||
| - /tmp/venv/bin/python | ||
| volumeMounts: | ||
| - name: tmpdir | ||
| mountPath: /tmp | ||
| - name: to-hdf5 | ||
| inputs: | ||
| parameters: | ||
| - name: paths | ||
| outputs: | ||
| artifacts: | ||
| - name: hdf5output | ||
| path: /tmp/images.hdf5 | ||
| archive: | ||
| none: {} | ||
| script: | ||
| image: python:3.10 | ||
| source: |- | ||
| import os | ||
| import sys | ||
| sys.path.append(os.getcwd()) | ||
| import json | ||
| try: paths = json.loads(r'''{{inputs.parameters.paths}}''') | ||
| except: paths = r'''{{inputs.parameters.paths}}''' | ||
|
|
||
| import h5py | ||
| import numpy as np | ||
| from PIL import Image | ||
| print('creating hdf5 file') | ||
| with h5py.File('/tmp/images.hdf5', 'w') as f: | ||
| for i, path in enumerate(paths): | ||
| path = path.strip('"') | ||
| print(f'Got {path}') | ||
| with Image.open(path) as image: | ||
| arr = np.array(image) | ||
| f.create_dataset(f'image_{i}', data=arr, dtype=arr.dtype) | ||
| print('done') | ||
| command: | ||
| - /tmp/venv/bin/python | ||
| volumeMounts: | ||
| - name: tmpdir | ||
| mountPath: /tmp | ||
| volumeClaimTemplates: | ||
| - metadata: | ||
| name: tmpdir | ||
| spec: | ||
| accessModes: | ||
| - ReadWriteOnce | ||
| resources: | ||
| requests: | ||
| storage: 1Gi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional that a generated Workflow yaml (i.e. not a ClusterWorkflowTemplate) is committed to the repo?