From 4cd5be3349d7ed17e5846077d073256f03b6095a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Sat, 12 Apr 2025 13:19:06 +0200 Subject: [PATCH] Update simple example to be a bit more complex --- README.md | 35 ++-- aiida_simple.ipynb | 280 +++++++++++++++++++++++++++++++- book/simple.md | 35 ++-- jobflow_simple.ipynb | 335 ++++++++++++++++++++++++++++++++++++++- pyiron_base_simple.ipynb | 316 +++++++++++++++++++++++++++++++++++- simple_workflow.py | 9 +- workflow_simple.json | 9 +- 7 files changed, 962 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 1e0cd35..a2f70ea 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,15 @@ different workflow engines to enable interoperability. As a first example we define two Python functions which add multiple inputs: ```python def add_x_and_y(x, y): - z = x + y - return x, y, z - -def add_x_and_y_and_z(x, y, z): - w = x + y + z - return w + return x + y + +def get_prod_and_div(x: float, y: float) -> dict: + return {"prod": x * y, "div": x / y} ``` These two Python functions are combined in the following example workflow: ```python -x, y, z = add_x_and_y(x=1, y=2) -w = add_x_and_y_and_z(x=x, y=y, z=z) +tmp_dict = get_prod_and_div(x=1, y=2) +result = add_x_and_y(x=tmp_dict["prod"], y=tmp_dict["div"]) ``` For the workflow representation of these Python functions the Python functions are stored in the [simple_workflow.py](simple_workflow.py) Python module. The connection of the Python functions are stored in the [workflow_simple.json](workflow_simple.json) @@ -35,23 +33,16 @@ JSON file: ``` { "nodes": [ - {"id": 0, "function": "simple_workflow.add_x_and_y_and_z"}, + {"id": 0, "function": "simple_workflow.get_prod_and_div"}, {"id": 1, "function": "simple_workflow.add_x_and_y"}, - {"id": 2, "function": "simple_workflow.add_x_and_y"}, - {"id": 3, "function": "simple_workflow.add_x_and_y"}, - {"id": 4, "value": 1}, - {"id": 5, "value": 2} + {"id": 2, "value": 1}, + {"id": 3, "value": 2} ], "edges": [ - {"target": 0, "targetPort": "x", "source": 1, "sourcePort": "x"}, - {"target": 1, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 1, "targetPort": "y", "source": 5, "sourcePort": null}, - {"target": 0, "targetPort": "y", "source": 2, "sourcePort": "y"}, - {"target": 2, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 2, "targetPort": "y", "source": 5, "sourcePort": null}, - {"target": 0, "targetPort": "z", "source": 3, "sourcePort": "z"}, - {"target": 3, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 3, "targetPort": "y", "source": 5, "sourcePort": null} + {"target": 0, "targetPort": "x", "source": 2, "sourcePort": null}, + {"target": 0, "targetPort": "y", "source": 3, "sourcePort": null}, + {"target": 1, "targetPort": "x", "source": 0, "sourcePort": "prod"}, + {"target": 1, "targetPort": "y", "source": 0, "sourcePort": "div"} ] } ``` diff --git a/aiida_simple.ipynb b/aiida_simple.ipynb index 9503b1b..e938ac4 100644 --- a/aiida_simple.ipynb +++ b/aiida_simple.ipynb @@ -1 +1,279 @@ -{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.8"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Aiida","metadata":{}},{"cell_type":"markdown","source":"## Define workflow with aiida","metadata":{}},{"cell_type":"code","source":"from python_workflow_definition.aiida import write_workflow_json\n\nfrom aiida_workgraph import WorkGraph, task\nfrom aiida import orm, load_profile\nload_profile()\n\nworkflow_json_filename = \"aiida_simple.json\"","metadata":{"trusted":false},"outputs":[],"execution_count":1},{"cell_type":"code","source":"from simple_workflow import add_x_and_y as _add_x_and_y\nfrom simple_workflow import add_x_and_y_and_z as _add_x_and_y_and_z","metadata":{"trusted":false},"outputs":[],"execution_count":2},{"cell_type":"code","source":"wg = WorkGraph(\"wg-simple\")","metadata":{"trusted":false},"outputs":[],"execution_count":4},{"cell_type":"code","source":"add_x_and_y_task = wg.add_task(\n task(outputs=['x', 'y', 'z'])(_add_x_and_y),\n name=\"add_x_and_y\",\n x=orm.Int(1),\n y=orm.Int(2),\n)","metadata":{"trusted":false},"outputs":[],"execution_count":5},{"cell_type":"code","source":"add_x_and_y_and_z_task = wg.add_task(\n _add_x_and_y_and_z,\n name=\"add_x_and_y_and_z\",\n x=add_x_and_y_task.outputs.x,\n y=add_x_and_y_task.outputs.y,\n z=add_x_and_y_task.outputs.z,\n)","metadata":{"trusted":false},"outputs":[],"execution_count":6},{"cell_type":"code","source":"write_workflow_json(wg=wg, file_name=workflow_json_filename)","metadata":{"trusted":false},"outputs":[{"data":{"text/plain":"{'nodes': {'0': 'simple_workflow.add_x_and_y',\n '1': 'simple_workflow.add_x_and_y_and_z',\n '2': 1,\n '3': 2},\n 'edges': [{'tn': 1, 'th': 'x', 'sn': 0, 'sh': 'x'},\n {'tn': 1, 'th': 'y', 'sn': 0, 'sh': 'y'},\n {'tn': 1, 'th': 'z', 'sn': 0, 'sh': 'z'},\n {'tn': 0, 'th': 'x', 'sn': 2, 'sh': None},\n {'tn': 0, 'th': 'y', 'sn': 3, 'sh': None}]}"},"execution_count":7,"metadata":{},"output_type":"execute_result"}],"execution_count":7},{"cell_type":"code","source":"!cat {workflow_json_filename}","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"{\n \"nodes\": {\n \"0\": \"simple_workflow.add_x_and_y\",\n \"1\": \"simple_workflow.add_x_and_y_and_z\",\n \"2\": 1,\n \"3\": 2\n },\n \"edges\": [\n {\n \"tn\": 1,\n \"th\": \"x\",\n \"sn\": 0,\n \"sh\": \"x\"\n },\n {\n \"tn\": 1,\n \"th\": \"y\",\n \"sn\": 0,\n \"sh\": \"y\"\n },\n {\n \"tn\": 1,\n \"th\": \"z\",\n \"sn\": 0,\n \"sh\": \"z\"\n },\n {\n \"tn\": 0,\n \"th\": \"x\",\n \"sn\": 2,\n \"sh\": null\n },\n {\n \"tn\": 0,\n \"th\": \"y\",\n \"sn\": 3,\n \"sh\": null\n }\n ]\n}"}],"execution_count":8},{"cell_type":"markdown","source":"## Load Workflow with jobflow","metadata":{}},{"cell_type":"code","source":"from python_workflow_definition.jobflow import load_workflow_json","metadata":{"trusted":false},"outputs":[{"name":"stderr","output_type":"stream","text":"/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n"}],"execution_count":9},{"cell_type":"code","source":"from jobflow.managers.local import run_locally","metadata":{"trusted":false},"outputs":[],"execution_count":10},{"cell_type":"code","source":"flow = load_workflow_json(file_name=workflow_json_filename)","metadata":{"trusted":false},"outputs":[],"execution_count":11},{"cell_type":"code","source":"result = run_locally(flow)\nresult","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"2025-04-02 14:36:37,425 INFO Started executing jobs locally\n2025-04-02 14:36:37,751 INFO Starting job - add_x_and_y (4bcb90c8-2c19-4981-a88e-56d5d24b5df9)\n2025-04-02 14:36:37,754 INFO Finished job - add_x_and_y (4bcb90c8-2c19-4981-a88e-56d5d24b5df9)\n2025-04-02 14:36:37,755 INFO Starting job - add_x_and_y_and_z (88bc90e5-09a0-443d-b24e-673cc6bc0819)\n2025-04-02 14:36:37,756 INFO Finished job - add_x_and_y_and_z (88bc90e5-09a0-443d-b24e-673cc6bc0819)\n2025-04-02 14:36:37,756 INFO Finished executing jobs locally\n"},{"data":{"text/plain":"{'4bcb90c8-2c19-4981-a88e-56d5d24b5df9': {1: Response(output={'x': 1, 'y': 2, 'z': 3}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))},\n '88bc90e5-09a0-443d-b24e-673cc6bc0819': {1: Response(output=6, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))}}"},"execution_count":12,"metadata":{},"output_type":"execute_result"}],"execution_count":12},{"cell_type":"markdown","source":"## Load Workflow with pyiron_base","metadata":{}},{"cell_type":"code","source":"from pyiron_base import Project","metadata":{"trusted":false},"outputs":[],"execution_count":13},{"cell_type":"code","source":"from python_workflow_definition.pyiron_base import load_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":14},{"cell_type":"code","source":"pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)","metadata":{"trusted":false},"outputs":[{"data":{"application/vnd.jupyter.widget-view+json":{"model_id":"278f490ab20c4eaf9d39a75a7ee5231d","version_major":2,"version_minor":0},"text/plain":"0it [00:00, ?it/s]"},"metadata":{},"output_type":"display_data"}],"execution_count":15},{"cell_type":"code","source":"delayed_object = load_workflow_json(project=pr, file_name=workflow_json_filename)\ndelayed_object.draw()","metadata":{"trusted":false},"outputs":[{"data":{"image/svg+xml":"\n\n\n\n\ncreate_function_job_988efa8422518ba29903b66c63607fb8\n\ncreate_function_job=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f740>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\nx=<pyiron_base.project.delayed.DelayedObject object at 0x71606f6efa70>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce\n\nx=1\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab\n\ny=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f6e0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220\n\nz=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f2f0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6\n\ny=2\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n","text/plain":""},"metadata":{},"output_type":"display_data"}],"execution_count":16},{"cell_type":"code","source":"delayed_object.pull()","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"The job add_x_and_y_68901482a2c5221cc845f828aabebd27 was saved and received the ID: 1\nThe job add_x_and_y_and_z_b671e81aaa4670d81d7eee509650af8d was saved and received the ID: 2\n"},{"data":{"text/plain":"6"},"execution_count":17,"metadata":{},"output_type":"execute_result"}],"execution_count":17}]} \ No newline at end of file +{ + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat_minor": 4, + "nbformat": 4, + "cells": [ + { + "cell_type": "markdown", + "source": "# Aiida", + "metadata": {} + }, + { + "cell_type": "markdown", + "source": "## Define workflow with aiida", + "metadata": {} + }, + { + "cell_type": "code", + "source": "from python_workflow_definition.aiida import write_workflow_json\n\nfrom aiida_workgraph import WorkGraph, task\nfrom aiida import orm, load_profile\nload_profile()\n\nworkflow_json_filename = \"aiida_simple.json\"", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "code", + "source": [ + "from simple_workflow import (\n", + " add_x_and_y as _add_x_and_y,\n", + " get_prod_and_div as _get_prod_and_div,\n", + ")" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "code", + "source": "wg = WorkGraph(\"wg-simple\")", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 4 + }, + { + "cell_type": "code", + "source": [ + "get_prod_and_div_task = wg.add_task(\n", + " task(outputs=['prod', 'div'])(_get_prod_and_div),\n", + " name=\"get_prod_and_div\",\n", + " x=orm.Float(1),\n", + " y=orm.Float(2),\n", + ")" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 5 + }, + { + "cell_type": "code", + "source": [ + "add_x_and_y_task = wg.add_task(\n", + " _add_x_and_y,\n", + " name=\"add_x_and_y\",\n", + " x=get_prod_and_div_task.outputs.prod,\n", + " y=get_prod_and_div_task.outputs.div,\n", + ")" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 6 + }, + { + "cell_type": "code", + "source": "write_workflow_json(wg=wg, file_name=workflow_json_filename)", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "data": { + "text/plain": "{'nodes': {'0': 'simple_workflow.add_x_and_y',\n '1': 'simple_workflow.add_x_and_y_and_z',\n '2': 1,\n '3': 2},\n 'edges': [{'tn': 1, 'th': 'x', 'sn': 0, 'sh': 'x'},\n {'tn': 1, 'th': 'y', 'sn': 0, 'sh': 'y'},\n {'tn': 1, 'th': 'z', 'sn': 0, 'sh': 'z'},\n {'tn': 0, 'th': 'x', 'sn': 2, 'sh': None},\n {'tn': 0, 'th': 'y', 'sn': 3, 'sh': None}]}" + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 7 + }, + { + "cell_type": "code", + "source": "!cat {workflow_json_filename}", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "{\n \"nodes\": {\n \"0\": \"simple_workflow.add_x_and_y\",\n \"1\": \"simple_workflow.add_x_and_y_and_z\",\n \"2\": 1,\n \"3\": 2\n },\n \"edges\": [\n {\n \"tn\": 1,\n \"th\": \"x\",\n \"sn\": 0,\n \"sh\": \"x\"\n },\n {\n \"tn\": 1,\n \"th\": \"y\",\n \"sn\": 0,\n \"sh\": \"y\"\n },\n {\n \"tn\": 1,\n \"th\": \"z\",\n \"sn\": 0,\n \"sh\": \"z\"\n },\n {\n \"tn\": 0,\n \"th\": \"x\",\n \"sn\": 2,\n \"sh\": null\n },\n {\n \"tn\": 0,\n \"th\": \"y\",\n \"sn\": 3,\n \"sh\": null\n }\n ]\n}" + } + ], + "execution_count": 8 + }, + { + "cell_type": "markdown", + "source": "## Load Workflow with jobflow", + "metadata": {} + }, + { + "cell_type": "code", + "source": "from python_workflow_definition.jobflow import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": "/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n" + } + ], + "execution_count": 9 + }, + { + "cell_type": "code", + "source": "from jobflow.managers.local import run_locally", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 10 + }, + { + "cell_type": "code", + "source": "flow = load_workflow_json(file_name=workflow_json_filename)", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 11 + }, + { + "cell_type": "code", + "source": "result = run_locally(flow)\nresult", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "2025-04-02 14:36:37,425 INFO Started executing jobs locally\n2025-04-02 14:36:37,751 INFO Starting job - add_x_and_y (4bcb90c8-2c19-4981-a88e-56d5d24b5df9)\n2025-04-02 14:36:37,754 INFO Finished job - add_x_and_y (4bcb90c8-2c19-4981-a88e-56d5d24b5df9)\n2025-04-02 14:36:37,755 INFO Starting job - add_x_and_y_and_z (88bc90e5-09a0-443d-b24e-673cc6bc0819)\n2025-04-02 14:36:37,756 INFO Finished job - add_x_and_y_and_z (88bc90e5-09a0-443d-b24e-673cc6bc0819)\n2025-04-02 14:36:37,756 INFO Finished executing jobs locally\n" + }, + { + "data": { + "text/plain": "{'4bcb90c8-2c19-4981-a88e-56d5d24b5df9': {1: Response(output={'x': 1, 'y': 2, 'z': 3}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))},\n '88bc90e5-09a0-443d-b24e-673cc6bc0819': {1: Response(output=6, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))}}" + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 12 + }, + { + "cell_type": "markdown", + "source": "## Load Workflow with pyiron_base", + "metadata": {} + }, + { + "cell_type": "code", + "source": "from pyiron_base import Project", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 13 + }, + { + "cell_type": "code", + "source": "from python_workflow_definition.pyiron_base import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 14 + }, + { + "cell_type": "code", + "source": "pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "278f490ab20c4eaf9d39a75a7ee5231d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": "0it [00:00, ?it/s]" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 15 + }, + { + "cell_type": "code", + "source": "delayed_object = load_workflow_json(project=pr, file_name=workflow_json_filename)\ndelayed_object.draw()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": "\n\n\n\n\ncreate_function_job_988efa8422518ba29903b66c63607fb8\n\ncreate_function_job=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f740>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\nx=<pyiron_base.project.delayed.DelayedObject object at 0x71606f6efa70>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce\n\nx=1\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab\n\ny=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f6e0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220\n\nz=<pyiron_base.project.delayed.DelayedObject object at 0x71606f71f2f0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6\n\ny=2\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n", + "text/plain": "" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 16 + }, + { + "cell_type": "code", + "source": "delayed_object.pull()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "The job add_x_and_y_68901482a2c5221cc845f828aabebd27 was saved and received the ID: 1\nThe job add_x_and_y_and_z_b671e81aaa4670d81d7eee509650af8d was saved and received the ID: 2\n" + }, + { + "data": { + "text/plain": "6" + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 17 + } + ] +} diff --git a/book/simple.md b/book/simple.md index 2330b8d..41ae7bc 100644 --- a/book/simple.md +++ b/book/simple.md @@ -2,17 +2,15 @@ As a first example we define two Python functions which add multiple inputs: ```python def add_x_and_y(x, y): - z = x + y - return x, y, z - -def add_x_and_y_and_z(x, y, z): - w = x + y + z - return w + return x + y + +def get_prod_and_div(x: float, y: float) -> dict: + return {"prod": x * y, "div": x / y} ``` These two Python functions are combined in the following example workflow: ```python -x, y, z = add_x_and_y(x=1, y=2) -w = add_x_and_y_and_z(x=x, y=y, z=z) +tmp_dict = get_prod_and_div(x=1, y=2) +result = add_x_and_y(x=tmp_dict["prod"], y=tmp_dict["div"]) ``` For the workflow representation of these Python functions the Python functions are stored in the [simple_workflow.py](simple_workflow.py) Python module. The connection of the Python functions are stored in the [workflow_simple.json](workflow_simple.json) @@ -20,23 +18,16 @@ JSON file: ``` { "nodes": [ - {"id": 0, "function": "simple_workflow.add_x_and_y_and_z"}, + {"id": 0, "function": "simple_workflow.get_prod_and_div"}, {"id": 1, "function": "simple_workflow.add_x_and_y"}, - {"id": 2, "function": "simple_workflow.add_x_and_y"}, - {"id": 3, "function": "simple_workflow.add_x_and_y"}, - {"id": 4, "value": 1}, - {"id": 5, "value": 2} + {"id": 2, "value": 1}, + {"id": 3, "value": 2} ], "edges": [ - {"target": 0, "targetPort": "x", "source": 1, "sourcePort": "x"}, - {"target": 1, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 1, "targetPort": "y", "source": 5, "sourcePort": null}, - {"target": 0, "targetPort": "y", "source": 2, "sourcePort": "y"}, - {"target": 2, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 2, "targetPort": "y", "source": 5, "sourcePort": null}, - {"target": 0, "targetPort": "z", "source": 3, "sourcePort": "z"}, - {"target": 3, "targetPort": "x", "source": 4, "sourcePort": null}, - {"target": 3, "targetPort": "y", "source": 5, "sourcePort": null} + {"target": 0, "targetPort": "x", "source": 2, "sourcePort": null}, + {"target": 0, "targetPort": "y", "source": 3, "sourcePort": null}, + {"target": 1, "targetPort": "x", "source": 0, "sourcePort": "prod"}, + {"target": 1, "targetPort": "y", "source": 0, "sourcePort": "div"} ] } ``` diff --git a/jobflow_simple.ipynb b/jobflow_simple.ipynb index ea246f0..d650e39 100644 --- a/jobflow_simple.ipynb +++ b/jobflow_simple.ipynb @@ -1 +1,334 @@ -{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.12.8","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":5,"nbformat":4,"cells":[{"id":"982a4fbe-7cf9-45dd-84ae-9854149db0b9","cell_type":"markdown","source":"# jobflow","metadata":{}},{"id":"e6180712-d081-45c7-ba41-fc5191f10427","cell_type":"markdown","source":"## Define workflow with jobflow","metadata":{}},{"id":"000bbd4a-f53c-4eea-9d85-76f0aa2ca10b","cell_type":"code","source":"from jobflow import job, Flow","metadata":{"trusted":false},"outputs":[{"name":"stderr","output_type":"stream","text":"/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n"}],"execution_count":1},{"id":"06c2bd9e-b2ac-4b88-9158-fa37331c3418","cell_type":"code","source":"from python_workflow_definition.jobflow import write_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":2},{"id":"fb847d49-7bf9-4839-9b99-c116d1b0e9ee","cell_type":"code","source":"from simple_workflow import (\n add_x_and_y as _add_x_and_y, \n add_x_and_y_and_z as _add_x_and_y_and_z,\n)","metadata":{"trusted":false},"outputs":[],"execution_count":3},{"id":"8f95244e","cell_type":"code","source":"workflow_json_filename = \"jobflow_simple.json\"","metadata":{"trusted":false},"outputs":[],"execution_count":4},{"id":"07598344-0f75-433b-8902-bea21a42088c","cell_type":"code","source":"add_x_and_y = job(_add_x_and_y, data=[\"x\", \"y\", \"z\"])\nadd_x_and_y_and_z = job(_add_x_and_y_and_z)","metadata":{"trusted":false},"outputs":[],"execution_count":5},{"id":"ecef1ed5-a8d3-48c3-9e01-4a40e55c1153","cell_type":"code","source":"obj = add_x_and_y(x=1, y=2)","metadata":{"trusted":false},"outputs":[],"execution_count":6},{"id":"2b88a30a-e26b-4802-89b7-79ca08cc0af9","cell_type":"code","source":"w = add_x_and_y_and_z(x=obj.output.x, y=obj.output.y, z=obj.output.z)","metadata":{"trusted":false},"outputs":[],"execution_count":7},{"id":"a5e5ca63-2906-47c9-bac6-adebf8643cba","cell_type":"code","source":"flow = Flow([obj, w])","metadata":{"trusted":false},"outputs":[],"execution_count":8},{"id":"e464da97-16a1-4772-9a07-0a47f152781d","cell_type":"code","source":"write_workflow_json(flow=flow, file_name=workflow_json_filename)","metadata":{"trusted":false},"outputs":[],"execution_count":9},{"id":"bca646b2-0a9a-4271-966a-e5903a8c9031","cell_type":"code","source":"!cat {workflow_json_filename}","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"{\"nodes\": {\"0\": \"simple_workflow.add_x_and_y\", \"1\": \"simple_workflow.add_x_and_y_and_z\", \"2\": 1, \"3\": 2}, \"edges\": [{\"tn\": 0, \"th\": \"x\", \"sn\": 2, \"sh\": null}, {\"tn\": 0, \"th\": \"y\", \"sn\": 3, \"sh\": null}, {\"tn\": 1, \"th\": \"x\", \"sn\": 0, \"sh\": \"x\"}, {\"tn\": 1, \"th\": \"y\", \"sn\": 0, \"sh\": \"y\"}, {\"tn\": 1, \"th\": \"z\", \"sn\": 0, \"sh\": \"z\"}]}"}],"execution_count":10},{"id":"87a27540-c390-4d34-ae75-4739bfc4c1b7","cell_type":"markdown","source":"## Load Workflow with aiida","metadata":{}},{"id":"66a1b3a6-3d3b-4caa-b58f-d8bc089b1074","cell_type":"code","source":"from aiida import load_profile\n\nload_profile()","metadata":{"trusted":false},"outputs":[{"execution_count":11,"output_type":"execute_result","data":{"text/plain":"Profile"},"metadata":{}}],"execution_count":11},{"id":"4679693b-039b-45cf-8c67-5b2b3d705a83","cell_type":"code","source":"from python_workflow_definition.aiida import load_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":12},{"id":"68c41a61-d185-47e8-ba31-eeff71d8b2c6","cell_type":"code","source":"wg = load_workflow_json(file_name=workflow_json_filename)\nwg","metadata":{"trusted":false},"outputs":[{"execution_count":13,"output_type":"execute_result","data":{"text/plain":"NodeGraphWidget(settings={'minimap': True}, style={'width': '90%', 'height': '600px'}, value={'name': 'WorkGra…","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":1,"model_id":"14e9a03e426b468dbfe338d7f734a41a"}},"metadata":{}}],"execution_count":13},{"id":"05228ece-643c-420c-8df8-4ce3df379515","cell_type":"code","source":"wg.run()","metadata":{"trusted":false},"outputs":[{"name":"stderr","output_type":"stream","text":"04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y1\n04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|update_task_state]: Task: add_x_and_y1, type: PyFunction, finished.\n04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y_and_z2\n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|update_task_state]: Task: add_x_and_y_and_z2, type: PyFunction, finished.\n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: \n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|finalize]: Finalize workgraph.\n"}],"execution_count":14},{"id":"2c942094-61b4-4e94-859a-64f87b5bec64","cell_type":"markdown","source":"## Load Workflow with pyiron_base","metadata":{}},{"id":"40672826-23bf-4c24-84e2-a6b9d87e2a3f","cell_type":"code","source":"from pyiron_base import Project","metadata":{"trusted":false},"outputs":[],"execution_count":15},{"id":"ea102341-84f7-4156-a7d1-c3ab1ea613a5","cell_type":"code","source":"from python_workflow_definition.pyiron_base import load_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":16},{"id":"f45684a8-2613-415a-ab0a-5cb2bafaffea","cell_type":"code","source":"pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)","metadata":{"trusted":false},"outputs":[{"output_type":"display_data","data":{"text/plain":"0it [00:00, ?it/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"f4514974ee9546f788ea311ec80db1c9"}},"metadata":{}}],"execution_count":17},{"id":"8f2a621d-b533-4ddd-8bcd-c22db2f922ec","cell_type":"code","source":"delayed_object = load_workflow_json(project=pr, file_name=workflow_json_filename)\ndelayed_object.draw()","metadata":{"trusted":false},"outputs":[{"output_type":"display_data","data":{"text/plain":"","image/svg+xml":"\n\n\n\n\ncreate_function_job_988efa8422518ba29903b66c63607fb8\n\ncreate_function_job=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcff020>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\nx=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfebd0>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce\n\nx=1\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab\n\ny=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfeba0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220\n\nz=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfe810>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6\n\ny=2\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n"},"metadata":{}}],"execution_count":18},{"id":"cf80267d-c2b0-4236-bf1d-a57596985fc1","cell_type":"code","source":"delayed_object.pull()","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"The job add_x_and_y_68901482a2c5221cc845f828aabebd27 was saved and received the ID: 1\nThe job add_x_and_y_and_z_b671e81aaa4670d81d7eee509650af8d was saved and received the ID: 2\n"},{"execution_count":19,"output_type":"execute_result","data":{"text/plain":"6"},"metadata":{}}],"execution_count":19},{"id":"9d819ed0-689c-46a7-9eff-0afb5ed66efc","cell_type":"code","source":"","metadata":{"trusted":false},"outputs":[],"execution_count":null}]} \ No newline at end of file +{ + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.8", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + } + }, + "nbformat_minor": 5, + "nbformat": 4, + "cells": [ + { + "id": "982a4fbe-7cf9-45dd-84ae-9854149db0b9", + "cell_type": "markdown", + "source": "# jobflow", + "metadata": {} + }, + { + "id": "e6180712-d081-45c7-ba41-fc5191f10427", + "cell_type": "markdown", + "source": "## Define workflow with jobflow", + "metadata": {} + }, + { + "id": "000bbd4a-f53c-4eea-9d85-76f0aa2ca10b", + "cell_type": "code", + "source": "from jobflow import job, Flow", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": "/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n" + } + ], + "execution_count": 1 + }, + { + "id": "06c2bd9e-b2ac-4b88-9158-fa37331c3418", + "cell_type": "code", + "source": "from python_workflow_definition.jobflow import write_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 2 + }, + { + "id": "fb847d49-7bf9-4839-9b99-c116d1b0e9ee", + "cell_type": "code", + "source": [ + "from simple_workflow import (\n", + " add_x_and_y as _add_x_and_y, \n", + " get_prod_and_div as _get_prod_and_div,\n", + ")" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 3 + }, + { + "id": "8f95244e", + "cell_type": "code", + "source": "workflow_json_filename = \"jobflow_simple.json\"", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 4 + }, + { + "id": "07598344-0f75-433b-8902-bea21a42088c", + "cell_type": "code", + "source": [ + "add_x_and_y = job(_add_x_and_y)\n", + "get_prod_and_div = job(_get_prod_and_div, data=[\"prod\", \"div\"])" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 5 + }, + { + "id": "ecef1ed5-a8d3-48c3-9e01-4a40e55c1153", + "cell_type": "code", + "source": "obj = get_prod_and_div(x=1, y=2)", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 6 + }, + { + "id": "2b88a30a-e26b-4802-89b7-79ca08cc0af9", + "cell_type": "code", + "source": "w = add_x_and_y(x=obj.output.prod, y=obj.output.div)", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 7 + }, + { + "id": "a5e5ca63-2906-47c9-bac6-adebf8643cba", + "cell_type": "code", + "source": "flow = Flow([obj, w])", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 8 + }, + { + "id": "e464da97-16a1-4772-9a07-0a47f152781d", + "cell_type": "code", + "source": "write_workflow_json(flow=flow, file_name=workflow_json_filename)", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 9 + }, + { + "id": "bca646b2-0a9a-4271-966a-e5903a8c9031", + "cell_type": "code", + "source": "!cat {workflow_json_filename}", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "{\"nodes\": {\"0\": \"simple_workflow.add_x_and_y\", \"1\": \"simple_workflow.add_x_and_y_and_z\", \"2\": 1, \"3\": 2}, \"edges\": [{\"tn\": 0, \"th\": \"x\", \"sn\": 2, \"sh\": null}, {\"tn\": 0, \"th\": \"y\", \"sn\": 3, \"sh\": null}, {\"tn\": 1, \"th\": \"x\", \"sn\": 0, \"sh\": \"x\"}, {\"tn\": 1, \"th\": \"y\", \"sn\": 0, \"sh\": \"y\"}, {\"tn\": 1, \"th\": \"z\", \"sn\": 0, \"sh\": \"z\"}]}" + } + ], + "execution_count": 10 + }, + { + "id": "87a27540-c390-4d34-ae75-4739bfc4c1b7", + "cell_type": "markdown", + "source": "## Load Workflow with aiida", + "metadata": {} + }, + { + "id": "66a1b3a6-3d3b-4caa-b58f-d8bc089b1074", + "cell_type": "code", + "source": "from aiida import load_profile\n\nload_profile()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "execution_count": 11, + "output_type": "execute_result", + "data": { + "text/plain": "Profile" + }, + "metadata": {} + } + ], + "execution_count": 11 + }, + { + "id": "4679693b-039b-45cf-8c67-5b2b3d705a83", + "cell_type": "code", + "source": "from python_workflow_definition.aiida import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 12 + }, + { + "id": "68c41a61-d185-47e8-ba31-eeff71d8b2c6", + "cell_type": "code", + "source": "wg = load_workflow_json(file_name=workflow_json_filename)\nwg", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "execution_count": 13, + "output_type": "execute_result", + "data": { + "text/plain": "NodeGraphWidget(settings={'minimap': True}, style={'width': '90%', 'height': '600px'}, value={'name': 'WorkGra…", + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 1, + "model_id": "14e9a03e426b468dbfe338d7f734a41a" + } + }, + "metadata": {} + } + ], + "execution_count": 13 + }, + { + "id": "05228ece-643c-420c-8df8-4ce3df379515", + "cell_type": "code", + "source": "wg.run()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": "04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y1\n04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|update_task_state]: Task: add_x_and_y1, type: PyFunction, finished.\n04/02/2025 02:37:38 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y_and_z2\n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|update_task_state]: Task: add_x_and_y_and_z2, type: PyFunction, finished.\n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|continue_workgraph]: tasks ready to run: \n04/02/2025 02:37:39 PM <422> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [16|WorkGraphEngine|finalize]: Finalize workgraph.\n" + } + ], + "execution_count": 14 + }, + { + "id": "2c942094-61b4-4e94-859a-64f87b5bec64", + "cell_type": "markdown", + "source": "## Load Workflow with pyiron_base", + "metadata": {} + }, + { + "id": "40672826-23bf-4c24-84e2-a6b9d87e2a3f", + "cell_type": "code", + "source": "from pyiron_base import Project", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 15 + }, + { + "id": "ea102341-84f7-4156-a7d1-c3ab1ea613a5", + "cell_type": "code", + "source": "from python_workflow_definition.pyiron_base import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 16 + }, + { + "id": "f45684a8-2613-415a-ab0a-5cb2bafaffea", + "cell_type": "code", + "source": "pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "0it [00:00, ?it/s]", + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "f4514974ee9546f788ea311ec80db1c9" + } + }, + "metadata": {} + } + ], + "execution_count": 17 + }, + { + "id": "8f2a621d-b533-4ddd-8bcd-c22db2f922ec", + "cell_type": "code", + "source": "delayed_object = load_workflow_json(project=pr, file_name=workflow_json_filename)\ndelayed_object.draw()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "", + "image/svg+xml": "\n\n\n\n\ncreate_function_job_988efa8422518ba29903b66c63607fb8\n\ncreate_function_job=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcff020>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\nx=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfebd0>\n\n\n\nx_b8003ea81f8e4a9bdbfd3b4eb1e68e2b->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce\n\nx=1\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab\n\ny=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfeba0>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220\n\nz=<pyiron_base.project.delayed.DelayedObject object at 0x75516fcfe810>\n\n\n\nx_1d847da32ecaabf6731c38f798c3d4ce->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n\ny_f60ae41b1c92823db71999ac596241ab->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\nz_a926da40ec18154feb3f3bb147af8220->create_function_job_988efa8422518ba29903b66c63607fb8\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6\n\ny=2\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->x_b8003ea81f8e4a9bdbfd3b4eb1e68e2b\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->y_f60ae41b1c92823db71999ac596241ab\n\n\n\n\n\ny_a9ec4f5f33f0d64e74ed5d9900bceac6->z_a926da40ec18154feb3f3bb147af8220\n\n\n\n\n" + }, + "metadata": {} + } + ], + "execution_count": 18 + }, + { + "id": "cf80267d-c2b0-4236-bf1d-a57596985fc1", + "cell_type": "code", + "source": "delayed_object.pull()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "The job add_x_and_y_68901482a2c5221cc845f828aabebd27 was saved and received the ID: 1\nThe job add_x_and_y_and_z_b671e81aaa4670d81d7eee509650af8d was saved and received the ID: 2\n" + }, + { + "execution_count": 19, + "output_type": "execute_result", + "data": { + "text/plain": "6" + }, + "metadata": {} + } + ], + "execution_count": 19 + }, + { + "id": "9d819ed0-689c-46a7-9eff-0afb5ed66efc", + "cell_type": "code", + "source": "", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": null + } + ] +} diff --git a/pyiron_base_simple.ipynb b/pyiron_base_simple.ipynb index 090c80d..8f2044c 100644 --- a/pyiron_base_simple.ipynb +++ b/pyiron_base_simple.ipynb @@ -1 +1,315 @@ -{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.12.8","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":5,"nbformat":4,"cells":[{"id":"c39b76fb-259f-4e16-a44d-02a295c82386","cell_type":"markdown","source":"# pyiron","metadata":{}},{"id":"3638419b-a0cb-49e2-b157-7fbb1acde90f","cell_type":"markdown","source":"## Define workflow with pyiron_base","metadata":{}},{"id":"b4a78447-e87c-4fb4-8d17-d9a280eb7254","cell_type":"code","source":"from pyiron_base import Project, job","metadata":{"trusted":false},"outputs":[],"execution_count":1},{"id":"06c2bd9e-b2ac-4b88-9158-fa37331c3418","cell_type":"code","source":"from python_workflow_definition.pyiron_base import write_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":2},{"id":"fb847d49-7bf9-4839-9b99-c116d1b0e9ee","cell_type":"code","source":"from simple_workflow import (\n add_x_and_y as _add_x_and_y, \n add_x_and_y_and_z as _add_x_and_y_and_z,\n)","metadata":{"trusted":false},"outputs":[],"execution_count":3},{"id":"8f95244e","cell_type":"code","source":"workflow_json_filename = \"pyiron_base_simple.json\"","metadata":{"trusted":false},"outputs":[],"execution_count":4},{"id":"07598344-0f75-433b-8902-bea21a42088c","cell_type":"code","source":"add_x_and_y = job(_add_x_and_y, output_key_lst=[\"x\", \"y\", \"z\"])\nadd_x_and_y_and_z = job(_add_x_and_y_and_z)","metadata":{"trusted":false},"outputs":[],"execution_count":5},{"id":"ecef1ed5-a8d3-48c3-9e01-4a40e55c1153","cell_type":"code","source":"pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)","metadata":{"trusted":false},"outputs":[{"output_type":"display_data","data":{"text/plain":" 0%| | 0/2 [00:00"},"metadata":{}}],"execution_count":11},{"id":"68a56b32-9f99-43d7-aaee-0c1cd9522681","cell_type":"code","source":"from python_workflow_definition.aiida import load_workflow_json","metadata":{"trusted":false},"outputs":[],"execution_count":12},{"id":"8f2a621d-b533-4ddd-8bcd-c22db2f922ec","cell_type":"code","source":"wg = load_workflow_json(file_name=workflow_json_filename)\nwg","metadata":{"trusted":false},"outputs":[{"execution_count":13,"output_type":"execute_result","data":{"text/plain":"NodeGraphWidget(settings={'minimap': True}, style={'width': '90%', 'height': '600px'}, value={'name': 'WorkGra…","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":1,"model_id":"dcfa2451385b4eb2b9204f7e196eeda4"}},"metadata":{}}],"execution_count":13},{"id":"cf80267d-c2b0-4236-bf1d-a57596985fc1","cell_type":"code","source":"\nwg.run()","metadata":{"trusted":false},"outputs":[{"name":"stderr","output_type":"stream","text":"04/02/2025 02:36:58 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y2\n04/02/2025 02:36:59 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|update_task_state]: Task: add_x_and_y2, type: PyFunction, finished.\n04/02/2025 02:36:59 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y_and_z1\n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|update_task_state]: Task: add_x_and_y_and_z1, type: PyFunction, finished.\n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: \n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|finalize]: Finalize workgraph.\n"}],"execution_count":14},{"id":"0c3503e1-0a32-40e1-845d-3fd9ec3c4c19","cell_type":"markdown","source":"## Load Workflow with jobflow","metadata":{}},{"id":"4abb0481-8e38-479d-ae61-6c46d091653e","cell_type":"code","source":"from python_workflow_definition.jobflow import load_workflow_json","metadata":{"trusted":false},"outputs":[{"name":"stderr","output_type":"stream","text":"/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n"}],"execution_count":15},{"id":"8253dd7c283bf3f7","cell_type":"code","source":"from jobflow.managers.local import run_locally","metadata":{"trusted":false},"outputs":[],"execution_count":16},{"id":"4b45e83b-945f-48c5-8e20-9df0ce0a14a1","cell_type":"code","source":"flow = load_workflow_json(file_name=workflow_json_filename)","metadata":{"trusted":false},"outputs":[],"execution_count":17},{"id":"8665c39c-220c-4982-b738-c31f6460530f","cell_type":"code","source":"result = run_locally(flow)\nresult","metadata":{"trusted":false},"outputs":[{"name":"stdout","output_type":"stream","text":"2025-04-02 14:37:00,813 INFO Started executing jobs locally\n2025-04-02 14:37:01,234 INFO Starting job - add_x_and_y (3cb63b3e-289b-4c08-a9e4-0ba051181adb)\n2025-04-02 14:37:01,238 INFO Finished job - add_x_and_y (3cb63b3e-289b-4c08-a9e4-0ba051181adb)\n2025-04-02 14:37:01,239 INFO Starting job - add_x_and_y_and_z (bff452ed-d3b3-4d6c-8162-feaa188b5660)\n2025-04-02 14:37:01,242 INFO Finished job - add_x_and_y_and_z (bff452ed-d3b3-4d6c-8162-feaa188b5660)\n2025-04-02 14:37:01,243 INFO Finished executing jobs locally\n"},{"execution_count":18,"output_type":"execute_result","data":{"text/plain":"{'3cb63b3e-289b-4c08-a9e4-0ba051181adb': {1: Response(output={'x': 1, 'y': 2, 'z': 3}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))},\n 'bff452ed-d3b3-4d6c-8162-feaa188b5660': {1: Response(output=6, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))}}"},"metadata":{}}],"execution_count":18},{"id":"cf76f305-24de-45a7-be8e-cfe45cd6458e","cell_type":"code","source":"","metadata":{"trusted":false},"outputs":[],"execution_count":null}]} \ No newline at end of file +{ + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.12.8", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + } + }, + "nbformat_minor": 5, + "nbformat": 4, + "cells": [ + { + "id": "c39b76fb-259f-4e16-a44d-02a295c82386", + "cell_type": "markdown", + "source": "# pyiron", + "metadata": {} + }, + { + "id": "3638419b-a0cb-49e2-b157-7fbb1acde90f", + "cell_type": "markdown", + "source": "## Define workflow with pyiron_base", + "metadata": {} + }, + { + "id": "b4a78447-e87c-4fb4-8d17-d9a280eb7254", + "cell_type": "code", + "source": "from pyiron_base import Project, job", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 1 + }, + { + "id": "06c2bd9e-b2ac-4b88-9158-fa37331c3418", + "cell_type": "code", + "source": "from python_workflow_definition.pyiron_base import write_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 2 + }, + { + "id": "fb847d49-7bf9-4839-9b99-c116d1b0e9ee", + "cell_type": "code", + "source": [ + "from simple_workflow import (\n", + " add_x_and_y as _add_x_and_y, \n", + " get_prod_and_div as _get_prod_and_div,\n", + ")" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 3 + }, + { + "id": "8f95244e", + "cell_type": "code", + "source": "workflow_json_filename = \"pyiron_base_simple.json\"", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 4 + }, + { + "id": "07598344-0f75-433b-8902-bea21a42088c", + "cell_type": "code", + "source": [ + "add_x_and_y = job(_add_x_and_y)\n", + "get_prod_and_div = job(_get_prod_and_div, output_key_lst=[\"prod\", \"div\"])" + ], + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 5 + }, + { + "id": "ecef1ed5-a8d3-48c3-9e01-4a40e55c1153", + "cell_type": "code", + "source": "pr = Project(\"test\")\npr.remove_jobs(recursive=True, silently=True)", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": " 0%| | 0/2 [00:00" + }, + "metadata": {} + } + ], + "execution_count": 11 + }, + { + "id": "68a56b32-9f99-43d7-aaee-0c1cd9522681", + "cell_type": "code", + "source": "from python_workflow_definition.aiida import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 12 + }, + { + "id": "8f2a621d-b533-4ddd-8bcd-c22db2f922ec", + "cell_type": "code", + "source": "wg = load_workflow_json(file_name=workflow_json_filename)\nwg", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "execution_count": 13, + "output_type": "execute_result", + "data": { + "text/plain": "NodeGraphWidget(settings={'minimap': True}, style={'width': '90%', 'height': '600px'}, value={'name': 'WorkGra…", + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 1, + "model_id": "dcfa2451385b4eb2b9204f7e196eeda4" + } + }, + "metadata": {} + } + ], + "execution_count": 13 + }, + { + "id": "cf80267d-c2b0-4236-bf1d-a57596985fc1", + "cell_type": "code", + "source": "\nwg.run()", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": "04/02/2025 02:36:58 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y2\n04/02/2025 02:36:59 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|update_task_state]: Task: add_x_and_y2, type: PyFunction, finished.\n04/02/2025 02:36:59 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: add_x_and_y_and_z1\n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|update_task_state]: Task: add_x_and_y_and_z1, type: PyFunction, finished.\n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|continue_workgraph]: tasks ready to run: \n04/02/2025 02:37:00 PM <248> aiida.orm.nodes.process.workflow.workchain.WorkChainNode: [REPORT] [3|WorkGraphEngine|finalize]: Finalize workgraph.\n" + } + ], + "execution_count": 14 + }, + { + "id": "0c3503e1-0a32-40e1-845d-3fd9ec3c4c19", + "cell_type": "markdown", + "source": "## Load Workflow with jobflow", + "metadata": {} + }, + { + "id": "4abb0481-8e38-479d-ae61-6c46d091653e", + "cell_type": "code", + "source": "from python_workflow_definition.jobflow import load_workflow_json", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": "/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/pkey.py:82: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"cipher\": algorithms.TripleDES,\n/srv/conda/envs/notebook/lib/python3.12/site-packages/paramiko/transport.py:253: CryptographyDeprecationWarning: TripleDES has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.\n \"class\": algorithms.TripleDES,\n" + } + ], + "execution_count": 15 + }, + { + "id": "8253dd7c283bf3f7", + "cell_type": "code", + "source": "from jobflow.managers.local import run_locally", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 16 + }, + { + "id": "4b45e83b-945f-48c5-8e20-9df0ce0a14a1", + "cell_type": "code", + "source": "flow = load_workflow_json(file_name=workflow_json_filename)", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": 17 + }, + { + "id": "8665c39c-220c-4982-b738-c31f6460530f", + "cell_type": "code", + "source": "result = run_locally(flow)\nresult", + "metadata": { + "trusted": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "2025-04-02 14:37:00,813 INFO Started executing jobs locally\n2025-04-02 14:37:01,234 INFO Starting job - add_x_and_y (3cb63b3e-289b-4c08-a9e4-0ba051181adb)\n2025-04-02 14:37:01,238 INFO Finished job - add_x_and_y (3cb63b3e-289b-4c08-a9e4-0ba051181adb)\n2025-04-02 14:37:01,239 INFO Starting job - add_x_and_y_and_z (bff452ed-d3b3-4d6c-8162-feaa188b5660)\n2025-04-02 14:37:01,242 INFO Finished job - add_x_and_y_and_z (bff452ed-d3b3-4d6c-8162-feaa188b5660)\n2025-04-02 14:37:01,243 INFO Finished executing jobs locally\n" + }, + { + "execution_count": 18, + "output_type": "execute_result", + "data": { + "text/plain": "{'3cb63b3e-289b-4c08-a9e4-0ba051181adb': {1: Response(output={'x': 1, 'y': 2, 'z': 3}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))},\n 'bff452ed-d3b3-4d6c-8162-feaa188b5660': {1: Response(output=6, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False, job_dir=PosixPath('/home/jovyan'))}}" + }, + "metadata": {} + } + ], + "execution_count": 18 + }, + { + "id": "cf76f305-24de-45a7-be8e-cfe45cd6458e", + "cell_type": "code", + "source": "", + "metadata": { + "trusted": false + }, + "outputs": [], + "execution_count": null + } + ] +} diff --git a/simple_workflow.py b/simple_workflow.py index a686a81..afc4d72 100644 --- a/simple_workflow.py +++ b/simple_workflow.py @@ -1,8 +1,7 @@ -def add_x_and_y(x, y): - z = x + y - return {"x": x, "y": y, "z": z} +def get_prod_and_div(x, y): + return {"prod": x * y, "div": x / y} -def add_x_and_y_and_z(x, y, z): - w = x + y + z +def add_x_and_y(x, y): + w = x + y return w \ No newline at end of file diff --git a/workflow_simple.json b/workflow_simple.json index 69b6e00..7e3bdcc 100644 --- a/workflow_simple.json +++ b/workflow_simple.json @@ -1,15 +1,14 @@ { "nodes": [ - {"id": 0, "function": "simple_workflow.add_x_and_y"}, - {"id": 1, "function": "simple_workflow.add_x_and_y_and_z"}, + {"id": 0, "function": "simple_workflow.get_prod_and_div"}, + {"id": 1, "function": "simple_workflow.add_x_and_y"}, {"id": 2, "value": 1}, {"id": 3, "value": 2} ], "edges": [ {"target": 0, "targetPort": "x", "source": 2, "sourcePort": null}, {"target": 0, "targetPort": "y", "source": 3, "sourcePort": null}, - {"target": 1, "targetPort": "x", "source": 0, "sourcePort": "x"}, - {"target": 1, "targetPort": "y", "source": 0, "sourcePort": "y"}, - {"target": 1, "targetPort": "z", "source": 0, "sourcePort": "z"} + {"target": 1, "targetPort": "x", "source": 0, "sourcePort": "prod"}, + {"target": 1, "targetPort": "y", "source": 0, "sourcePort": "div"} ] }