diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..e651121 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,29 @@ +name: python + +on: + push: + branches: [ main ] + pull_request: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + auto-update-conda: true + python-version: "3.12" + environment-file: environment.yml + auto-activate-base: false + - name: Tests + shell: bash -l {0} + run: | + pip install -e adis_tools + pip install -e python_workflow_definition + conda install -c conda-forge jupyter papermill + export ESPRESSO_PSEUDO=$(pwd)/espresso/pseudo + papermill universal_simple_to_python.ipynb universal_simple_to_python_out.ipynb -k "python3" + papermill universal_qe_to_python.ipynb universal_qe_to_python_out.ipynb -k "python3" diff --git a/python_workflow_definition/src/python_workflow_definition/purepython.py b/python_workflow_definition/src/python_workflow_definition/purepython.py new file mode 100644 index 0000000..a916c79 --- /dev/null +++ b/python_workflow_definition/src/python_workflow_definition/purepython.py @@ -0,0 +1,105 @@ +import json +from importlib import import_module +from inspect import isfunction + + +def get_dict(**kwargs): + return {k: v for k, v in kwargs.items()} + + +def get_list(**kwargs): + return list(kwargs.values()) + + +def get_kwargs(lst): + return {t['targetHandle']: {'source': t['source'], 'sourceHandle': t['sourceHandle']} for t in lst} + + +def resort_total_lst(total_lst, nodes_dict): + nodes_with_dep_lst = list(sorted([v[0] for v in total_lst])) + nodes_without_dep_lst = [k for k in nodes_dict.keys() if k not in nodes_with_dep_lst] + ordered_lst, total_new_lst = [], [] + while len(total_new_lst) < len(total_lst): + for ind, connect in total_lst: + if ind not in ordered_lst: + source_lst = [sd["source"] for sd in connect.values()] + if all([s in ordered_lst or s in nodes_without_dep_lst for s in source_lst]): + ordered_lst.append(ind) + total_new_lst.append([ind, connect]) + return total_new_lst + + +def group_edges(edges_lst): + edges_sorted_lst = sorted(edges_lst, key=lambda x: x['target'], reverse=True) + total_lst, tmp_lst = [], [] + target_id = edges_sorted_lst[0]['target'] + for ed in edges_sorted_lst: + if target_id == ed["target"]: + tmp_lst.append(ed) + else: + total_lst.append((target_id, get_kwargs(lst=tmp_lst))) + target_id = ed["target"] + tmp_lst = [ed] + total_lst.append((target_id, get_kwargs(lst=tmp_lst))) + return total_lst + + +def get_source_handles(edges_lst): + source_handle_dict = {} + for ed in edges_lst: + if ed['source'] not in source_handle_dict.keys(): + source_handle_dict[ed['source']] = [ed['sourceHandle']] + else: + source_handle_dict[ed['source']].append(ed['sourceHandle']) + return { + k: list(range(len(v))) if len(v) > 1 and all([el is None for el in v]) else v + for k, v in source_handle_dict.items() + } + + +def get_value(result_dict, nodes_new_dict, link_dict): + source, source_handle = link_dict["source"], link_dict["sourceHandle"] + if source in result_dict.keys(): + result = result_dict[source] + elif source in nodes_new_dict.keys(): + result = nodes_new_dict[source] + else: + raise KeyError() + if source_handle is None: + return result + else: + return result[source_handle] + + +def load_workflow_json(file_name): + with open(file_name, "r") as f: + content = json.load(f) + + edges_new_lst = content["edges"] + nodes_new_dict = {} + for k, v in content["nodes"].items(): + if isinstance(v, str) and "." in v: + p, m = v.rsplit('.', 1) + if p == "python_workflow_definition.pyiron_base": + p = "python_workflow_definition.purepython" + mod = import_module(p) + nodes_new_dict[int(k)] = getattr(mod, m) + else: + nodes_new_dict[int(k)] = v + + total_lst = group_edges(edges_new_lst) + total_new_lst = resort_total_lst(total_lst=total_lst, nodes_dict=nodes_new_dict) + + result_dict = {} + last_key = None + for lst in total_new_lst: + node = nodes_new_dict[lst[0]] + if isfunction(node): + kwargs = { + k: get_value(result_dict=result_dict, nodes_new_dict=nodes_new_dict, link_dict=v) + for k, v in lst[1].items() + } + result_dict[lst[0]] = node(**kwargs) + last_key = lst[0] + + return result_dict[last_key] diff --git a/universal_qe_to_python.ipynb b/universal_qe_to_python.ipynb new file mode 100644 index 0000000..e071776 --- /dev/null +++ b/universal_qe_to_python.ipynb @@ -0,0 +1,45 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b0f920a2-c646-485b-af0f-48251e061163", + "metadata": {}, + "outputs": [], + "source": [ + "from python_workflow_definition.purepython import load_workflow_json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46559120-d58a-492f-b734-db27424b5659", + "metadata": {}, + "outputs": [], + "source": [ + "load_workflow_json(file_name=\"workflow_qe.json\")" + ] + } + ], + "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.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/universal_simple_to_python.ipynb b/universal_simple_to_python.ipynb new file mode 100644 index 0000000..a81cd57 --- /dev/null +++ b/universal_simple_to_python.ipynb @@ -0,0 +1,45 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "b0f920a2-c646-485b-af0f-48251e061163", + "metadata": {}, + "outputs": [], + "source": [ + "from python_workflow_definition.purepython import load_workflow_json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46559120-d58a-492f-b734-db27424b5659", + "metadata": {}, + "outputs": [], + "source": [ + "load_workflow_json(file_name=\"workflow_simple.json\")" + ] + } + ], + "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.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}