From 9242fe6a84fadbb5bdea371c55db9fc05dc57a76 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 29 Jun 2025 22:13:10 -0700 Subject: [PATCH 01/26] update: bandgap nb prototype (wip) --- .../run_bandgap_workflow.ipynb | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 other/materials_designer/specific_examples/run_bandgap_workflow.ipynb diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb new file mode 100644 index 00000000..5f536ff3 --- /dev/null +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Bandgap Workflow Example\n", + " This notebook demonstrates how to build and run a bandgap workflow for a material.\n", + "\n", + "## Process Overview\n", + "### 1. Set up the environment and parameters.\n", + "### 2. Load the target material.\n", + "### 3. Import workflow builder and related analyzers.\n", + "### 4. Analyze material to get parameters for the workflow configuration.\n", + "### 5. Create the workflow configuration.\n", + "### 6. Create a job with material and workflow configuration.\n", + "### 7. Log in to get the API token\n", + "### 8. Submit the job to the server.\n", + "### 9. Monitor the job status and retrieve results." + ], + "id": "ed24b225263ae3c3" + }, + { + "cell_type": "code", + "id": "initial_id", + "metadata": { + "collapsed": true + }, + "source": [ + "from utils.visualize import visualize_materials as visualize\n", + "from utils.jupyterlite import load_material_from_folder\n", + "\n", + "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", + "visualize(material)" + ], + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": [ + "from mat3ra.api import ApiClient\n", + "# Log in to get the API token\n", + "auth_config = await ApiClient().login()" + ], + "id": "23626cb27f6e7206", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from mat3ra.wode.analyzers.electronic import KPointAnalyzer, CutoffAnalyzer, SmearingAnalyzer, BandsAnalyzer\n", + "\n", + "kpoint_analyzer = KPointAnalyzer(material=material)\n", + "cutoff_analyzer = CutoffAnalyzer(material=material)\n", + "smearing_analyzer = SmearingAnalyzer(material=material)\n", + "bands_analyzer = BandsAnalyzer(material=material)\n", + "\n", + "kpoints = kpoint_analyzer.get_kpoints()\n", + "cutoff = cutoff_analyzer.get_cutoff()\n", + "smearing = smearing_analyzer.get_smearing()\n", + "number_of_bands = bands_analyzer.get_number_of_bands()\n", + "\n" + ], + "id": "5ead702c417eff62" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from mat3ra.wode.workflow.vasp import create_vasp_workflow\n", + "\n", + "band_gap_workflow = create_vasp_workflow(\n", + " material=material,\n", + " kpoints=kpoints,\n", + " cutoff=cutoff,\n", + " smearing=smearing,\n", + " number_of_bands=number_of_bands)" + ], + "id": "68d43f6c797f2fc4" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from mat3ra.wode.compute import ComputeConfiguration, QueueTypes\n", + "compute_config = ComputeConfiguration(\n", + " queue = QueueTypes.OR8,\n", + " nodes = 1,\n", + " cores = 8,\n", + ")" + ], + "id": "60e880dc581dafe1" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from mat3ra.wode.job import JobConfiguration, create_job\n", + "job_config = JobConfiguration(workflow=band_gap_workflow, material=material, compute = compute_config)\n", + "job = create_job(job_config, auth_config=auth_config)\n", + "job.run()\n", + "job.wait_for_complete()\n", + "# job.check_status()\n", + "# job.get_current_output()\n", + "# AFTER Finished\n", + "job.get_results(PropertyEnum.BANDGAP)" + ], + "id": "53c8a2cd99e5c26d" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 74069acfa25e64ad42a190db0f04387b84d2674e Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 30 Jun 2025 10:14:47 -0700 Subject: [PATCH 02/26] update: add headers --- .../run_bandgap_workflow.ipynb | 89 ++++++++++++++----- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb index 5f536ff3..1ba93db4 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -9,23 +9,54 @@ "\n", "## Process Overview\n", "### 1. Set up the environment and parameters.\n", - "### 2. Load the target material.\n", - "### 3. Import workflow builder and related analyzers.\n", - "### 4. Analyze material to get parameters for the workflow configuration.\n", - "### 5. Create the workflow configuration.\n", - "### 6. Create a job with material and workflow configuration.\n", - "### 7. Log in to get the API token\n", - "### 8. Submit the job to the server.\n", - "### 9. Monitor the job status and retrieve results." + "### 1. Log in to get the API token\n", + "### 1. Load the target material.\n", + "### 1. Import workflow builder and related analyzers.\n", + "### 1. Analyze material to get parameters for the workflow configuration.\n", + "### 1. Create the workflow configuration.\n", + "### 1. Create a job with material and workflow configuration.\n", + "### 1. Submit the job to the server.\n", + "### 1. Monitor the job status and retrieve results." ], "id": "ed24b225263ae3c3" }, { + "metadata": {}, + "cell_type": "markdown", + "source": "## 1. Set up the environment and parameters", + "id": "598da5f8c4f507ec" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 2. Log in to get the API token", + "id": "51105b005c535ca" + }, + { + "metadata": {}, "cell_type": "code", - "id": "initial_id", + "source": [ + "from mat3ra.api import ApiClient\n", + "# Log in to get the API token\n", + "auth_config = await ApiClient().login()" + ], + "id": "23626cb27f6e7206", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 3. Load the target material", + "id": "ba816c64f28f6a3d" + }, + { "metadata": { "collapsed": true }, + "cell_type": "code", + "outputs": [], + "execution_count": null, "source": [ "from utils.visualize import visualize_materials as visualize\n", "from utils.jupyterlite import load_material_from_folder\n", @@ -33,20 +64,13 @@ "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", "visualize(material)" ], - "outputs": [], - "execution_count": null + "id": "initial_id" }, { "metadata": {}, - "cell_type": "code", - "source": [ - "from mat3ra.api import ApiClient\n", - "# Log in to get the API token\n", - "auth_config = await ApiClient().login()" - ], - "id": "23626cb27f6e7206", - "outputs": [], - "execution_count": null + "cell_type": "markdown", + "source": "## 4. Import workflow builder and related analyzers", + "id": "f8d7e25a7c9cc2e" }, { "metadata": {}, @@ -69,23 +93,36 @@ ], "id": "5ead702c417eff62" }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 5. Create workflow", + "id": "9bdd00f870caaeeb" + }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, "source": [ - "from mat3ra.wode.workflow.vasp import create_vasp_workflow\n", + "from mat3ra.wode.workflow.vasp.band_structure import create_band_structure_workflow\n", "\n", - "band_gap_workflow = create_vasp_workflow(\n", + "band_gap_workflow = create_band_structure_workflow(\n", " material=material,\n", " kpoints=kpoints,\n", " cutoff=cutoff,\n", " smearing=smearing,\n", - " number_of_bands=number_of_bands)" + " number_of_bands=number_of_bands\n", + ")" ], "id": "68d43f6c797f2fc4" }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 6. Create the job configuration", + "id": "1f15e054ddb9a08c" + }, { "metadata": {}, "cell_type": "code", @@ -101,6 +138,12 @@ ], "id": "60e880dc581dafe1" }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 7. Submit the job and monitor the status", + "id": "8d5740e099512107" + }, { "metadata": {}, "cell_type": "code", From 35aa49bdd778773cdf3df9b585a5bffe5d62a90c Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 30 Jun 2025 14:00:05 -0700 Subject: [PATCH 03/26] update: set pseudo --- .../run_bandgap_workflow.ipynb | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb index 1ba93db4..2cc7efee 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -33,7 +33,12 @@ "id": "51105b005c535ca" }, { - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2025-06-30T17:49:35.443494Z", + "start_time": "2025-06-30T17:49:35.381267Z" + } + }, "cell_type": "code", "source": [ "from mat3ra.api import ApiClient\n", @@ -41,8 +46,20 @@ "auth_config = await ApiClient().login()" ], "id": "23626cb27f6e7206", - "outputs": [], - "execution_count": null + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'mat3ra.api'", + "output_type": "error", + "traceback": [ + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mModuleNotFoundError\u001B[0m Traceback (most recent call last)", + "Cell \u001B[0;32mIn[2], line 1\u001B[0m\n\u001B[0;32m----> 1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;21;01mmat3ra\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mapi\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m ApiClient\n\u001B[1;32m 2\u001B[0m \u001B[38;5;66;03m# Log in to get the API token\u001B[39;00m\n\u001B[1;32m 3\u001B[0m auth_config \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mawait\u001B[39;00m ApiClient()\u001B[38;5;241m.\u001B[39mlogin()\n", + "\u001B[0;31mModuleNotFoundError\u001B[0m: No module named 'mat3ra.api'" + ] + } + ], + "execution_count": 2 }, { "metadata": {}, @@ -96,7 +113,7 @@ { "metadata": {}, "cell_type": "markdown", - "source": "## 5. Create workflow", + "source": "## 5. Get workflow and adjust its parameters", "id": "9bdd00f870caaeeb" }, { @@ -105,15 +122,12 @@ "outputs": [], "execution_count": null, "source": [ - "from mat3ra.wode.workflow.vasp.band_structure import create_band_structure_workflow\n", + "from mat3ra.wode.workflow.vasp.band_structure import BandStructureWorkflow\n", + "from mat3ra.wode.pseudopotentials import PseudopotentialEnum\n", "\n", - "band_gap_workflow = create_band_structure_workflow(\n", - " material=material,\n", - " kpoints=kpoints,\n", - " cutoff=cutoff,\n", - " smearing=smearing,\n", - " number_of_bands=number_of_bands\n", - ")" + "workflow = BandStructureWorkflow()\n", + "workflow.set_kpoints(kpoints)\n", + "workflow.set_pseudopotential(PseudopotentialEnum.PAW_HSE) # elements will be set automatically based on the material" ], "id": "68d43f6c797f2fc4" }, @@ -129,9 +143,9 @@ "outputs": [], "execution_count": null, "source": [ - "from mat3ra.wode.compute import ComputeConfiguration, QueueTypes\n", + "from mat3ra.wode.compute import ComputeConfiguration, QueueEnum\n", "compute_config = ComputeConfiguration(\n", - " queue = QueueTypes.OR8,\n", + " queue = QueueEnum.OR8,\n", " nodes = 1,\n", " cores = 8,\n", ")" @@ -150,9 +164,8 @@ "outputs": [], "execution_count": null, "source": [ - "from mat3ra.wode.job import JobConfiguration, create_job\n", - "job_config = JobConfiguration(workflow=band_gap_workflow, material=material, compute = compute_config)\n", - "job = create_job(job_config, auth_config=auth_config)\n", + "from mat3ra.wode.job import create_job\n", + "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)\n", "job.run()\n", "job.wait_for_complete()\n", "# job.check_status()\n", From dfe43aab5ac1ee6a3d4686b9e778385160628b2e Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 23 Nov 2025 21:30:27 -0800 Subject: [PATCH 04/26] update: wf from standata --- .../run_bandgap_workflow.ipynb | 72 +++++++++---------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb index 2cc7efee..79de1ef1 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -33,12 +33,7 @@ "id": "51105b005c535ca" }, { - "metadata": { - "ExecuteTime": { - "end_time": "2025-06-30T17:49:35.443494Z", - "start_time": "2025-06-30T17:49:35.381267Z" - } - }, + "metadata": {}, "cell_type": "code", "source": [ "from mat3ra.api import ApiClient\n", @@ -46,20 +41,8 @@ "auth_config = await ApiClient().login()" ], "id": "23626cb27f6e7206", - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'mat3ra.api'", - "output_type": "error", - "traceback": [ - "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[0;31mModuleNotFoundError\u001B[0m Traceback (most recent call last)", - "Cell \u001B[0;32mIn[2], line 1\u001B[0m\n\u001B[0;32m----> 1\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;21;01mmat3ra\u001B[39;00m\u001B[38;5;21;01m.\u001B[39;00m\u001B[38;5;21;01mapi\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;28;01mimport\u001B[39;00m ApiClient\n\u001B[1;32m 2\u001B[0m \u001B[38;5;66;03m# Log in to get the API token\u001B[39;00m\n\u001B[1;32m 3\u001B[0m auth_config \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mawait\u001B[39;00m ApiClient()\u001B[38;5;241m.\u001B[39mlogin()\n", - "\u001B[0;31mModuleNotFoundError\u001B[0m: No module named 'mat3ra.api'" - ] - } - ], - "execution_count": 2 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -72,8 +55,6 @@ "collapsed": true }, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "from utils.visualize import visualize_materials as visualize\n", "from utils.jupyterlite import load_material_from_folder\n", @@ -81,7 +62,9 @@ "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", "visualize(material)" ], - "id": "initial_id" + "id": "initial_id", + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -92,8 +75,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "from mat3ra.wode.analyzers.electronic import KPointAnalyzer, CutoffAnalyzer, SmearingAnalyzer, BandsAnalyzer\n", "\n", @@ -105,31 +86,34 @@ "kpoints = kpoint_analyzer.get_kpoints()\n", "cutoff = cutoff_analyzer.get_cutoff()\n", "smearing = smearing_analyzer.get_smearing()\n", - "number_of_bands = bands_analyzer.get_number_of_bands()\n", - "\n" + "number_of_bands = bands_analyzer.get_number_of_bands()" ], - "id": "5ead702c417eff62" + "id": "5ead702c417eff62", + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "markdown", - "source": "## 5. Get workflow and adjust its parameters", + "source": "## 5. Create workflow and set its parameters", "id": "9bdd00f870caaeeb" }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ - "from mat3ra.wode.workflow.vasp.band_structure import BandStructureWorkflow\n", + "from mat3ra.standata.workflows import Workflows\n", + "from mat3ra.wode.workflows import Workflow\n", "from mat3ra.wode.pseudopotentials import PseudopotentialEnum\n", "\n", - "workflow = BandStructureWorkflow()\n", + "workflow_config = Workflows.get_by_name_first_match(\"band_structure\")\n", + "workflow = Workflow.create(workflow_config)\n", "workflow.set_kpoints(kpoints)\n", "workflow.set_pseudopotential(PseudopotentialEnum.PAW_HSE) # elements will be set automatically based on the material" ], - "id": "68d43f6c797f2fc4" + "id": "68d43f6c797f2fc4", + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -140,8 +124,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "from mat3ra.wode.compute import ComputeConfiguration, QueueEnum\n", "compute_config = ComputeConfiguration(\n", @@ -150,7 +132,9 @@ " cores = 8,\n", ")" ], - "id": "60e880dc581dafe1" + "id": "60e880dc581dafe1", + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -161,8 +145,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "from mat3ra.wode.job import create_job\n", "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)\n", @@ -173,7 +155,17 @@ "# AFTER Finished\n", "job.get_results(PropertyEnum.BANDGAP)" ], - "id": "53c8a2cd99e5c26d" + "id": "53c8a2cd99e5c26d", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "", + "id": "978bb38b10c15976" } ], "metadata": { From 975cdbb7783dad475c693ffd1b167c72dbaeba6e Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 30 Nov 2025 13:55:03 -0800 Subject: [PATCH 05/26] update: use CPs --- .../run_bandgap_workflow.ipynb | 106 +++++++++++++----- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb index 79de1ef1..8abe9d02 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -9,14 +9,15 @@ "\n", "## Process Overview\n", "### 1. Set up the environment and parameters.\n", - "### 1. Log in to get the API token\n", - "### 1. Load the target material.\n", - "### 1. Import workflow builder and related analyzers.\n", - "### 1. Analyze material to get parameters for the workflow configuration.\n", - "### 1. Create the workflow configuration.\n", - "### 1. Create a job with material and workflow configuration.\n", - "### 1. Submit the job to the server.\n", - "### 1. Monitor the job status and retrieve results." + "### 2. Log in to get the API token\n", + "### 3. Load the target material.\n", + "### 4. Import workflow builder and related analyzers.\n", + "### 5. Analyze material to get parameters for the workflow configuration.\n", + "### 6. Create the workflow configuration.\n", + "### 7. Create a job with material and workflow configuration.\n", + "### 8. Submit the job to the server.\n", + "### 9. Monitor the job status and retrieve results.\n", + "### 10. Display the results." ], "id": "ed24b225263ae3c3" }, @@ -76,17 +77,23 @@ "metadata": {}, "cell_type": "code", "source": [ - "from mat3ra.wode.analyzers.electronic import KPointAnalyzer, CutoffAnalyzer, SmearingAnalyzer, BandsAnalyzer\n", + "from mat3ra.wode.context_providers import (\n", + " PointsGridFormDataProvider, # exists - for k-points\n", + " PlanewaveCutoffsContextProvider, # exists - for cutoffs\n", + " SmearingContextProvider, # no JS implementation yet\n", + " BandsContextProvider # no JS implementation yet\n", + ")\n", "\n", - "kpoint_analyzer = KPointAnalyzer(material=material)\n", - "cutoff_analyzer = CutoffAnalyzer(material=material)\n", - "smearing_analyzer = SmearingAnalyzer(material=material)\n", - "bands_analyzer = BandsAnalyzer(material=material)\n", "\n", - "kpoints = kpoint_analyzer.get_kpoints()\n", - "cutoff = cutoff_analyzer.get_cutoff()\n", - "smearing = smearing_analyzer.get_smearing()\n", - "number_of_bands = bands_analyzer.get_number_of_bands()" + "kgrid_provider = PointsGridFormDataProvider(material=material)\n", + "cutoffs_provider = PlanewaveCutoffsContextProvider(material=material)\n", + "smearing_provider = SmearingContextProvider(material=material)\n", + "bands_provider = BandsContextProvider(material=material)\n", + "\n", + "kpoints = kgrid_provider.get_dimensions() # or calculate_dimensions()\n", + "cutoff = cutoffs_provider.get_cutoff() # defaultECUTWFC, defaultECUTRHO\n", + "smearing = smearing_provider.get_smearing()\n", + "number_of_bands = bands_provider.get_number_of_bands()" ], "id": "5ead702c417eff62", "outputs": [], @@ -118,14 +125,14 @@ { "metadata": {}, "cell_type": "markdown", - "source": "## 6. Create the job configuration", + "source": "## 6. Create the compute configuration", "id": "1f15e054ddb9a08c" }, { "metadata": {}, "cell_type": "code", "source": [ - "from mat3ra.wode.compute import ComputeConfiguration, QueueEnum\n", + "from mat3ra.ide.compute import ComputeConfiguration, QueueEnum\n", "compute_config = ComputeConfiguration(\n", " queue = QueueEnum.OR8,\n", " nodes = 1,\n", @@ -139,32 +146,75 @@ { "metadata": {}, "cell_type": "markdown", - "source": "## 7. Submit the job and monitor the status", + "source": "## 7. Create the job with material and workflow configuration", + "id": "cbc16438ad5b0ce0" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from mat3ra.jode.job import create_job\n", + "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)" + ], + "id": "20b3bf702b6e084c" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 8. Submit the job and monitor the status", "id": "8d5740e099512107" }, { "metadata": {}, "cell_type": "code", + "outputs": [], + "execution_count": null, "source": [ - "from mat3ra.wode.job import create_job\n", - "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)\n", + "from mat3ra.prode import PropertyEnum\n", "job.run()\n", "job.wait_for_complete()\n", "# job.check_status()\n", - "# job.get_current_output()\n", - "# AFTER Finished\n", - "job.get_results(PropertyEnum.BANDGAP)" + "# job.get_current_output()" ], - "id": "53c8a2cd99e5c26d", + "id": "df29a9065e8b5eae" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 9. Retrieve results", + "id": "349d46228a98bcd9" + }, + { + "metadata": {}, + "cell_type": "code", "outputs": [], - "execution_count": null + "execution_count": null, + "source": [ + "# AFTER Finished\n", + "# A class from Prode to handle results\n", + "results = job.get_results(PropertyEnum.BAND_GAP, PropertyEnum.BAND_STRUCTURE)" + ], + "id": "ce79fc805900503a" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "## 10. Display results", + "id": "6f864b5134b53eac" }, { "metadata": {}, "cell_type": "code", "outputs": [], "execution_count": null, - "source": "", + "source": [ + "# Visual library that can visualize any property defined in Prode\n", + "from mat3ra.prove import visualize_property\n", + "visualize_property(results.band_structure)\n", + "print(results.band_gap)" + ], "id": "978bb38b10c15976" } ], From 8ce197f5f30b18bb660fbd48a9b94492b7f4187e Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 1 Dec 2025 10:17:43 -0800 Subject: [PATCH 06/26] update: updates --- .../run_bandgap_workflow.ipynb | 243 ++++++++++++------ 1 file changed, 164 insertions(+), 79 deletions(-) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb index 8abe9d02..7fa0a23b 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb @@ -1,8 +1,9 @@ { "cells": [ { - "metadata": {}, "cell_type": "markdown", + "id": "0", + "metadata": {}, "source": [ "# Bandgap Workflow Example\n", " This notebook demonstrates how to build and run a bandgap workflow for a material.\n", @@ -18,64 +19,76 @@ "### 8. Submit the job to the server.\n", "### 9. Monitor the job status and retrieve results.\n", "### 10. Display the results." - ], - "id": "ed24b225263ae3c3" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 1. Set up the environment and parameters", - "id": "598da5f8c4f507ec" + "id": "1", + "metadata": {}, + "source": [ + "## 1. Set up the environment and parameters" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 2. Log in to get the API token", - "id": "51105b005c535ca" + "id": "2", + "metadata": {}, + "source": [ + "## 2. Log in to get the API token" + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.api import ApiClient\n", + "\n", + "from examples.reproducing_publications.band_gaps_for_interface_bilayer_twisted_molybdenum_disulfide import \\\n", + " unit_flowchart_id\n", + "\n", "# Log in to get the API token\n", "auth_config = await ApiClient().login()" - ], - "id": "23626cb27f6e7206", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 3. Load the target material", - "id": "ba816c64f28f6a3d" + "id": "4", + "metadata": {}, + "source": [ + "## 3. Load the target material" + ] }, { - "metadata": { - "collapsed": true - }, "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], "source": [ "from utils.visualize import visualize_materials as visualize\n", "from utils.jupyterlite import load_material_from_folder\n", "\n", "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", "visualize(material)" - ], - "id": "initial_id", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 4. Import workflow builder and related analyzers", - "id": "f8d7e25a7c9cc2e" + "id": "6", + "metadata": {}, + "source": [ + "## 4. Import workflow builder and related analyzers" + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.wode.context_providers import (\n", " PointsGridFormDataProvider, # exists - for k-points\n", @@ -94,43 +107,58 @@ "cutoff = cutoffs_provider.get_cutoff() # defaultECUTWFC, defaultECUTRHO\n", "smearing = smearing_provider.get_smearing()\n", "number_of_bands = bands_provider.get_number_of_bands()" - ], - "id": "5ead702c417eff62", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 5. Create workflow and set its parameters", - "id": "9bdd00f870caaeeb" + "id": "8", + "metadata": {}, + "source": [ + "## 5. Create workflow and set its parameters" + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.standata.workflows import Workflows\n", "from mat3ra.wode.workflows import Workflow\n", "from mat3ra.wode.pseudopotentials import PseudopotentialEnum\n", "\n", + "# Get Applications list (with versions, build)\n", + "# Search WF by name and and n\n", "workflow_config = Workflows.get_by_name_first_match(\"band_structure\")\n", "workflow = Workflow.create(workflow_config)\n", - "workflow.set_kpoints(kpoints)\n", - "workflow.set_pseudopotential(PseudopotentialEnum.PAW_HSE) # elements will be set automatically based on the material" - ], - "id": "68d43f6c797f2fc4", - "outputs": [], - "execution_count": null + "\n", + "# View workflow to understand its structure\n", + "visualize(workflow)\n", + "# Get workflow's specific unit that needs to be modified\n", + "unit_to_modify = workflow.get_unit_by_name(name=\"scf\", subworkflow_name=\"xxx\", order_in_subworkflow=1)\n", + "new_context = kgrid_context_provider.get_data(dimentions=[6,6,6])\n", + "unit_to_modify.context.add_context(new_context)\n", + "workflow.set_unit(unit_flowchart_id=unit_to_modify.flowchart_id, new_unit=unit_to_modify)\n", + "\n", + "workflow.set_context_providers(kpoints)\n", + "workflow.set_pseudopotential(PseudopotentialEnum.Funtional_GGA) # elements will be set automatically based on the material" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 6. Create the compute configuration", - "id": "1f15e054ddb9a08c" + "id": "10", + "metadata": {}, + "source": [ + "## 6. Create the compute configuration" + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.ide.compute import ComputeConfiguration, QueueEnum\n", "compute_config = ComputeConfiguration(\n", @@ -138,84 +166,141 @@ " nodes = 1,\n", " cores = 8,\n", ")" - ], - "id": "60e880dc581dafe1", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 7. Create the job with material and workflow configuration", - "id": "cbc16438ad5b0ce0" + "id": "12", + "metadata": {}, + "source": [ + "## 7. Create the job with material and workflow configuration" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.jode.job import create_job\n", - "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)" - ], - "id": "20b3bf702b6e084c" + "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)\n" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 8. Submit the job and monitor the status", - "id": "8d5740e099512107" + "id": "14", + "metadata": {}, + "source": [ + "## 8. Submit the job and monitor the status" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.prode import PropertyEnum\n", "job.run()\n", "job.wait_for_complete()\n", "# job.check_status()\n", "# job.get_current_output()" - ], - "id": "df29a9065e8b5eae" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 9. Retrieve results", - "id": "349d46228a98bcd9" + "id": "16", + "metadata": {}, + "source": [ + "## 9. Retrieve results" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], "source": [ "# AFTER Finished\n", "# A class from Prode to handle results\n", "results = job.get_results(PropertyEnum.BAND_GAP, PropertyEnum.BAND_STRUCTURE)" - ], - "id": "ce79fc805900503a" + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "## 10. Display results", - "id": "6f864b5134b53eac" + "id": "18", + "metadata": {}, + "source": [ + "## 10. Display results" + ] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, + "id": "19", + "metadata": {}, + "outputs": [], "source": [ "# Visual library that can visualize any property defined in Prode\n", "from mat3ra.prove import visualize_property\n", "visualize_property(results.band_structure)\n", "print(results.band_gap)" - ], - "id": "978bb38b10c15976" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20", + "metadata": {}, + "outputs": [], + "source": [ + "import pydot\n", + "import json\n", + "\n", + "# Example JSON data (you would load this from a file)\n", + "json_data = {\n", + " \"nodes\": [\n", + " {\"name\": \"A\", \"shape\": \"box\", \"label\": \"Start\"},\n", + " {\"name\": \"B\", \"shape\": \"box\", \"label\": \"Process 1\"},\n", + " {\"name\": \"C\", \"shape\": \"diamond\", \"label\": \"Decision\"},\n", + " {\"name\": \"D\", \"shape\": \"box\", \"label\": \"End\"}\n", + " ],\n", + " \"edges\": [\n", + " {\"source\": \"A\", \"target\": \"B\", \"label\": \"\"},\n", + " {\"source\": \"B\", \"target\": \"C\", \"label\": \"\"},\n", + " {\"source\": \"C\", \"target\": \"D\", \"label\": \"Yes\"},\n", + " {\"source\": \"C\", \"target\": \"B\", \"label\": \"No\"}\n", + " ]\n", + "}\n", + "\n", + "# Create a new directed graph\n", + "dot_graph = pydot.Dot(\"my_flowchart\", graph_type=\"digraph\")\n", + "\n", + "# Add nodes\n", + "for node_data in json_data[\"nodes\"]:\n", + " node = pydot.Node(node_data[\"name\"], shape=node_data[\"shape\"], label=node_data[\"label\"])\n", + " dot_graph.add_node(node)\n", + "\n", + "# Add edges\n", + "for edge_data in json_data[\"edges\"]:\n", + " edge = pydot.Edge(edge_data[\"source\"], edge_data[\"target\"], label=edge_data[\"label\"])\n", + " dot_graph.add_edge(edge)\n", + "\n", + "# Save the flowchart as a PNG\n", + "dot_graph.write_png(\"flowchart.png\")\n", + "print(\"Flowchart rendered to flowchart.png\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 13f23e8cd4f74d5189407334768a07f77f359d24 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 1 Dec 2025 19:19:34 -0800 Subject: [PATCH 07/26] update: adjust max version --- .../run_bandgap_workflow_max.ipynb} | 236 +++++++++++------- 1 file changed, 149 insertions(+), 87 deletions(-) rename other/materials_designer/{specific_examples/run_bandgap_workflow.ipynb => workflows/run_bandgap_workflow_max.ipynb} (54%) diff --git a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb similarity index 54% rename from other/materials_designer/specific_examples/run_bandgap_workflow.ipynb rename to other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 7fa0a23b..e89c7751 100644 --- a/other/materials_designer/specific_examples/run_bandgap_workflow.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -7,6 +7,7 @@ "source": [ "# Bandgap Workflow Example\n", " This notebook demonstrates how to build and run a bandgap workflow for a material.\n", + " Example of building and running a bandgap workflow for twisted MoS2 interface from specific_examples.\n", "\n", "## Process Overview\n", "### 1. Set up the environment and parameters.\n", @@ -46,9 +47,6 @@ "source": [ "from mat3ra.api import ApiClient\n", "\n", - "from examples.reproducing_publications.band_gaps_for_interface_bilayer_twisted_molybdenum_disulfide import \\\n", - " unit_flowchart_id\n", - "\n", "# Log in to get the API token\n", "auth_config = await ApiClient().login()" ] @@ -90,23 +88,23 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.wode.context_providers import (\n", - " PointsGridFormDataProvider, # exists - for k-points\n", - " PlanewaveCutoffsContextProvider, # exists - for cutoffs\n", - " SmearingContextProvider, # no JS implementation yet\n", - " BandsContextProvider # no JS implementation yet\n", - ")\n", - "\n", - "\n", - "kgrid_provider = PointsGridFormDataProvider(material=material)\n", - "cutoffs_provider = PlanewaveCutoffsContextProvider(material=material)\n", - "smearing_provider = SmearingContextProvider(material=material)\n", - "bands_provider = BandsContextProvider(material=material)\n", - "\n", - "kpoints = kgrid_provider.get_dimensions() # or calculate_dimensions()\n", - "cutoff = cutoffs_provider.get_cutoff() # defaultECUTWFC, defaultECUTRHO\n", - "smearing = smearing_provider.get_smearing()\n", - "number_of_bands = bands_provider.get_number_of_bands()" + "# from mat3ra.wode.context_providers import (\n", + "# PointsGridFormDataProvider, # exists - for k-points\n", + "# PlanewaveCutoffsContextProvider, # exists - for cutoffs\n", + "# SmearingContextProvider, # no JS implementation yet\n", + "# BandsContextProvider # no JS implementation yet\n", + "# )\n", + "#\n", + "#\n", + "# kgrid_provider = PointsGridFormDataProvider(material=material)\n", + "# cutoffs_provider = PlanewaveCutoffsContextProvider(material=material)\n", + "# smearing_provider = SmearingContextProvider(material=material)\n", + "# bands_provider = BandsContextProvider(material=material)\n", + "#\n", + "# kpoints = kgrid_provider.get_dimensions() # or calculate_dimensions()\n", + "# cutoff = cutoffs_provider.get_cutoff() # defaultECUTWFC, defaultECUTRHO\n", + "# smearing = smearing_provider.get_smearing()\n", + "# number_of_bands = bands_provider.get_number_of_bands()" ] }, { @@ -114,7 +112,8 @@ "id": "8", "metadata": {}, "source": [ - "## 5. Create workflow and set its parameters" + "## 5. Create workflow and set its parameters\n", + "### 5.1. Get list of applications and select one" ] }, { @@ -123,31 +122,138 @@ "id": "9", "metadata": {}, "outputs": [], + "source": [ + "from mat3ra.standata.applications import Applications\n", + "\n", + "# Get Applications list (with versions, build)\n", + "apps_list = Applications.list_all()\n", + "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", + "\n", + "app = Applications.get_by_name_first_match(\"espresso\")\n", + "# returns name, version, build config" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "### 5.2. Create workflow from standard workflows and preview it" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.standata.workflows import Workflows\n", "from mat3ra.wode.workflows import Workflow\n", - "from mat3ra.wode.pseudopotentials import PseudopotentialEnum\n", + "from utils.visualize import visualize_workflow\n", "\n", - "# Get Applications list (with versions, build)\n", - "# Search WF by name and and n\n", - "workflow_config = Workflows.get_by_name_first_match(\"band_structure\")\n", + "# Search WF by name and application\n", + "workflow_config = Workflows.filter_by_app(app).get_by_name_first_match(\"band_gap\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", - "visualize(workflow)\n", + "visualize_workflow(workflow)" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "### 5.3. Toggle relaxation subworkflow" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "workflow.toggle_relaxation(True)\n", + "visualize_workflow(workflow)\n", + "# Relaxation subworkflow is added as the first subworkflow" + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": {}, + "source": [ + "### 5.4. Change subworkflow details (Model subtype)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.standata.model_tree import ModelTreeStandata\n", + "swf_0 = workflow.subworkflows[0] # relaxation subworkflow\n", + "swf_1 = workflow.subworkflows[1] # band structure subworkflow\n", + "\n", + "# Change model subtype for relaxation subworkflow\n", + "swf_0.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\") # find LDA, functional \"pz\"" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "### 5.5. Modify workflow units found in preview" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.wode.context_providers import PointsGridFormDataProvider\n", + "\n", + "# Values from publication\n", + "kgrid_scf = [6, 6, 1]\n", + "kgrid_nscf = [12, 12, 1]\n", + "kgrid_relax = kgrid_scf\n", + "\n", + "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", + "\n", + "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", + "new_context_scf = kgrid_context_provider.get_data(dimensions=kgrid_scf)\n", + "new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", + "\n", "# Get workflow's specific unit that needs to be modified\n", - "unit_to_modify = workflow.get_unit_by_name(name=\"scf\", subworkflow_name=\"xxx\", order_in_subworkflow=1)\n", - "new_context = kgrid_context_provider.get_data(dimentions=[6,6,6])\n", - "unit_to_modify.context.add_context(new_context)\n", - "workflow.set_unit(unit_flowchart_id=unit_to_modify.flowchart_id, new_unit=unit_to_modify)\n", + "# Option 1: search is done by unit name regex across the entire workflow\n", + "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", + "unit_to_modify_relax.context.add_context(new_context_relax)\n", + "\n", + "# Option 2: search is done by unit name within a specific subworkflow\n", + "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", + "unit_to_modify_scf.context.add_context(new_context_scf)\n", + "unit_to_modify_nscf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_nscf\")\n", + "unit_to_modify_nscf.context.add_context(new_context_nscf)\n", "\n", - "workflow.set_context_providers(kpoints)\n", - "workflow.set_pseudopotential(PseudopotentialEnum.Funtional_GGA) # elements will be set automatically based on the material" + "# Set the modified unit back to the workflow\n", + "# Option 1: direct set by unit object, replacing the existing one\n", + "workflow.set_unit(unit_to_modify_relax)\n", + "\n", + "# Option 2: set by unit flowchart id and new unit object\n", + "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", + "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)" ] }, { "cell_type": "markdown", - "id": "10", + "id": "18", "metadata": {}, "source": [ "## 6. Create the compute configuration" @@ -156,7 +262,7 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -170,7 +276,7 @@ }, { "cell_type": "markdown", - "id": "12", + "id": "20", "metadata": {}, "source": [ "## 7. Create the job with material and workflow configuration" @@ -179,7 +285,7 @@ { "cell_type": "code", "execution_count": null, - "id": "13", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -189,7 +295,7 @@ }, { "cell_type": "markdown", - "id": "14", + "id": "22", "metadata": {}, "source": [ "## 8. Submit the job and monitor the status" @@ -198,7 +304,7 @@ { "cell_type": "code", "execution_count": null, - "id": "15", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -211,7 +317,7 @@ }, { "cell_type": "markdown", - "id": "16", + "id": "24", "metadata": {}, "source": [ "## 9. Retrieve results" @@ -220,7 +326,7 @@ { "cell_type": "code", "execution_count": null, - "id": "17", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -231,7 +337,7 @@ }, { "cell_type": "markdown", - "id": "18", + "id": "26", "metadata": {}, "source": [ "## 10. Display results" @@ -240,7 +346,7 @@ { "cell_type": "code", "execution_count": null, - "id": "19", + "id": "27", "metadata": {}, "outputs": [], "source": [ @@ -253,51 +359,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20", - "metadata": {}, - "outputs": [], - "source": [ - "import pydot\n", - "import json\n", - "\n", - "# Example JSON data (you would load this from a file)\n", - "json_data = {\n", - " \"nodes\": [\n", - " {\"name\": \"A\", \"shape\": \"box\", \"label\": \"Start\"},\n", - " {\"name\": \"B\", \"shape\": \"box\", \"label\": \"Process 1\"},\n", - " {\"name\": \"C\", \"shape\": \"diamond\", \"label\": \"Decision\"},\n", - " {\"name\": \"D\", \"shape\": \"box\", \"label\": \"End\"}\n", - " ],\n", - " \"edges\": [\n", - " {\"source\": \"A\", \"target\": \"B\", \"label\": \"\"},\n", - " {\"source\": \"B\", \"target\": \"C\", \"label\": \"\"},\n", - " {\"source\": \"C\", \"target\": \"D\", \"label\": \"Yes\"},\n", - " {\"source\": \"C\", \"target\": \"B\", \"label\": \"No\"}\n", - " ]\n", - "}\n", - "\n", - "# Create a new directed graph\n", - "dot_graph = pydot.Dot(\"my_flowchart\", graph_type=\"digraph\")\n", - "\n", - "# Add nodes\n", - "for node_data in json_data[\"nodes\"]:\n", - " node = pydot.Node(node_data[\"name\"], shape=node_data[\"shape\"], label=node_data[\"label\"])\n", - " dot_graph.add_node(node)\n", - "\n", - "# Add edges\n", - "for edge_data in json_data[\"edges\"]:\n", - " edge = pydot.Edge(edge_data[\"source\"], edge_data[\"target\"], label=edge_data[\"label\"])\n", - " dot_graph.add_edge(edge)\n", - "\n", - "# Save the flowchart as a PNG\n", - "dot_graph.write_png(\"flowchart.png\")\n", - "print(\"Flowchart rendered to flowchart.png\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "21", + "id": "28", "metadata": {}, "outputs": [], "source": [] From 8716dd8812b69f49ba58561836850fdc1ccc8bb7 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 1 Dec 2025 20:13:50 -0800 Subject: [PATCH 08/26] update: cleanup --- .../workflows/run_bandgap_workflow_max.ipynb | 107 +++++++++--------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index e89c7751..9e182c02 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -77,40 +77,6 @@ "cell_type": "markdown", "id": "6", "metadata": {}, - "source": [ - "## 4. Import workflow builder and related analyzers" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7", - "metadata": {}, - "outputs": [], - "source": [ - "# from mat3ra.wode.context_providers import (\n", - "# PointsGridFormDataProvider, # exists - for k-points\n", - "# PlanewaveCutoffsContextProvider, # exists - for cutoffs\n", - "# SmearingContextProvider, # no JS implementation yet\n", - "# BandsContextProvider # no JS implementation yet\n", - "# )\n", - "#\n", - "#\n", - "# kgrid_provider = PointsGridFormDataProvider(material=material)\n", - "# cutoffs_provider = PlanewaveCutoffsContextProvider(material=material)\n", - "# smearing_provider = SmearingContextProvider(material=material)\n", - "# bands_provider = BandsContextProvider(material=material)\n", - "#\n", - "# kpoints = kgrid_provider.get_dimensions() # or calculate_dimensions()\n", - "# cutoff = cutoffs_provider.get_cutoff() # defaultECUTWFC, defaultECUTRHO\n", - "# smearing = smearing_provider.get_smearing()\n", - "# number_of_bands = bands_provider.get_number_of_bands()" - ] - }, - { - "cell_type": "markdown", - "id": "8", - "metadata": {}, "source": [ "## 5. Create workflow and set its parameters\n", "### 5.1. Get list of applications and select one" @@ -119,7 +85,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "7", "metadata": {}, "outputs": [], "source": [ @@ -135,7 +101,7 @@ }, { "cell_type": "markdown", - "id": "10", + "id": "8", "metadata": {}, "source": [ "### 5.2. Create workflow from standard workflows and preview it" @@ -144,7 +110,7 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "9", "metadata": {}, "outputs": [], "source": [ @@ -153,7 +119,7 @@ "from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", - "workflow_config = Workflows.filter_by_app(app).get_by_name_first_match(\"band_gap\")\n", + "workflow_config = Workflows.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", @@ -162,27 +128,27 @@ }, { "cell_type": "markdown", - "id": "12", + "id": "10", "metadata": {}, "source": [ - "### 5.3. Toggle relaxation subworkflow" + "### 5.3. Add relaxation subworkflow" ] }, { "cell_type": "code", "execution_count": null, - "id": "13", + "id": "11", "metadata": {}, "outputs": [], "source": [ - "workflow.toggle_relaxation(True)\n", + "workflow.add_relaxation()\n", "visualize_workflow(workflow)\n", "# Relaxation subworkflow is added as the first subworkflow" ] }, { "cell_type": "markdown", - "id": "14", + "id": "12", "metadata": {}, "source": [ "### 5.4. Change subworkflow details (Model subtype)" @@ -191,21 +157,23 @@ { "cell_type": "code", "execution_count": null, - "id": "15", + "id": "13", "metadata": {}, "outputs": [], "source": [ "from mat3ra.standata.model_tree import ModelTreeStandata\n", + "\n", "swf_0 = workflow.subworkflows[0] # relaxation subworkflow\n", "swf_1 = workflow.subworkflows[1] # band structure subworkflow\n", "\n", "# Change model subtype for relaxation subworkflow\n", - "swf_0.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\") # find LDA, functional \"pz\"" + "swf_0.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\") # find LDA, functional \"pz\"\n", + "swf_1.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\")\n" ] }, { "cell_type": "markdown", - "id": "16", + "id": "14", "metadata": {}, "source": [ "### 5.5. Modify workflow units found in preview" @@ -214,7 +182,7 @@ { "cell_type": "code", "execution_count": null, - "id": "17", + "id": "15", "metadata": {}, "outputs": [], "source": [ @@ -251,12 +219,35 @@ "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)" ] }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "## 6. Create the compute configuration\n", + "### 6.1. View available clusters and providers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [ + "# List available compute providers and clusters\n", + "from mat3ra.ide.compute import ComputeProvider, ComputeCluster\n", + "\n", + "providers = ComputeProvider.list_all()\n", + "clusters = ComputeCluster.list_all()" + ] + }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ - "## 6. Create the compute configuration" + "### 6.2. Create compute configuration" ] }, { @@ -266,11 +257,13 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.ide.compute import ComputeConfiguration, QueueEnum\n", + "from mat3ra.ide.compute import ComputeConfiguration, QueueTypesEnum\n", + "\n", "compute_config = ComputeConfiguration(\n", - " queue = QueueEnum.OR8,\n", - " nodes = 1,\n", - " cores = 8,\n", + " queue=QueueTypesEnum.OR8,\n", + " nodes=1,\n", + " ppn=8,\n", + " cluster=clusters[0], # select first available cluster\n", ")" ] }, @@ -290,7 +283,13 @@ "outputs": [], "source": [ "from mat3ra.jode.job import create_job\n", - "job = create_job(workflow=workflow, material=material, compute = compute_config, auth_config=auth_config)\n" + "\n", + "job = create_job(\n", + " workflow=workflow,\n", + " material=material,\n", + " compute=compute_config,\n", + " auth_config=auth_config\n", + ")\n" ] }, { @@ -309,6 +308,7 @@ "outputs": [], "source": [ "from mat3ra.prode import PropertyEnum\n", + "\n", "job.run()\n", "job.wait_for_complete()\n", "# job.check_status()\n", @@ -352,6 +352,7 @@ "source": [ "# Visual library that can visualize any property defined in Prode\n", "from mat3ra.prove import visualize_property\n", + "\n", "visualize_property(results.band_structure)\n", "print(results.band_gap)" ] From 1f7ff6057ff2d5921e12ebcfed2040f93596fb17 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Tue, 2 Dec 2025 09:05:58 -0800 Subject: [PATCH 09/26] update: set model --- .../workflows/run_bandgap_workflow_max.ipynb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 9e182c02..5f529bef 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -167,8 +167,17 @@ "swf_1 = workflow.subworkflows[1] # band structure subworkflow\n", "\n", "# Change model subtype for relaxation subworkflow\n", - "swf_0.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\") # find LDA, functional \"pz\"\n", - "swf_1.model.subtype = ModelTreeStandata.get_method_types_by_model(\"dft\")\n" + "# For preview:\n", + "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"]\n", + "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\"]\n", + "\n", + "model = ModelTreeStandata.get_model_by_parameters(\n", + " model_type=\"dft\",\n", + " subtype=\"lda\",\n", + " functional=\"pz\"\n", + ")\n", + "swf_0.model = model\n", + "swf_1.model = model" ] }, { From 21301f5607d0e81942771eb1db7faf876e14e413 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Tue, 2 Dec 2025 09:50:17 -0800 Subject: [PATCH 10/26] update: model enums --- .../workflows/run_bandgap_workflow_max.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 5f529bef..8b709609 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -168,13 +168,13 @@ "\n", "# Change model subtype for relaxation subworkflow\n", "# For preview:\n", - "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"]\n", - "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\"]\n", + "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"] as enum\n", + "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\", ...] as enum\n", "\n", "model = ModelTreeStandata.get_model_by_parameters(\n", " model_type=\"dft\",\n", - " subtype=\"lda\",\n", - " functional=\"pz\"\n", + " subtype=subtypes.LDA,\n", + " functional=functionals.PZ,\n", ")\n", "swf_0.model = model\n", "swf_1.model = model" From be40a183e71ab306c63cc3459b455e98c086d7dc Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Tue, 2 Dec 2025 11:59:53 -0800 Subject: [PATCH 11/26] update: add min version --- .../workflows/run_bandgap_workflow_min.ipynb | 565 ++++++++++++++++++ 1 file changed, 565 insertions(+) create mode 100644 other/materials_designer/workflows/run_bandgap_workflow_min.ipynb diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb new file mode 100644 index 00000000..9c3bff5f --- /dev/null +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -0,0 +1,565 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Bandgap Workflow Example\n", + " This notebook demonstrates how to build and run a bandgap workflow for a material.\n", + " Example of building and running a bandgap workflow for twisted MoS2 interface from specific_examples.\n", + "\n", + "## Process Overview\n", + "### 1. Set up the environment and parameters.\n", + "### 2. Log in to get the API token\n", + "### 3. Load the target material.\n", + "### 4. Import workflow builder and related analyzers.\n", + "### 5. Analyze material to get parameters for the workflow configuration.\n", + "### 6. Create the workflow configuration.\n", + "### 7. Create a job with material and workflow configuration.\n", + "### 8. Submit the job to the server.\n", + "### 9. Monitor the job status and retrieve results.\n", + "### 10. Display the results." + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## 1. Set up the environment and parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "if sys.platform == \"emscripten\":\n", + " import micropip\n", + "\n", + " await micropip.install(\"mat3ra-api-examples\", deps=False)\n", + " await micropip.install(\"mat3ra-utils\")\n", + " from mat3ra.utils.jupyterlite.packages import install_packages\n", + "\n", + " await install_packages(\"api_examples\")" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "## 2. Log in to get the API token" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "ACCOUNT_ID = \"ACCOUNT_ID\"\n", + "AUTH_TOKEN = \"AUTH_TOKEN\"\n", + "ORGANIZATION_ID = \"ORGANIZATION_ID\"\n", + "\n", + "import os\n", + "import sys\n", + "\n", + "if sys.platform == \"emscripten\":\n", + " # Only works if launched within the Platform, otherwise requires redirect to Login\n", + " apiConfig = data_from_host.get(\"apiConfig\")\n", + " os.environ.update(data_from_host.get(\"environ\", {}))\n", + " os.environ.update(\n", + " dict(\n", + " ACCOUNT_ID=apiConfig.get(\"accountId\"),\n", + " AUTH_TOKEN=apiConfig.get(\"authToken\"),\n", + " ORGANIZATION_ID=apiConfig.get(\"organizationId\") or \"\",\n", + " )\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": [ + "## 3. Create material\n", + "### 3.1. Load material from local file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "from utils.visualize import visualize_materials as visualize\n", + "from utils.jupyterlite import load_material_from_folder\n", + "\n", + "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", + "visualize(material)" + ] + }, + { + "cell_type": "markdown", + "id": "7", + "metadata": {}, + "source": [ + "### 3.2. Save material to the platform" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", + "from utils.generic import display_JSON\n", + "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", + "\n", + "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", + "endpoint = MaterialEndpoints(*ENDPOINT_ARGS)\n", + "\n", + "RAW_CONFIG = material.to_dict()\n", + "fields = [\"name\", \"lattice\", \"basis\"]\n", + "CONFIG = {key: RAW_CONFIG[key] for key in fields}\n", + "\n", + "saved_material = endpoint.create(CONFIG, OWNER_ID)" + ] + }, + { + "cell_type": "markdown", + "id": "9", + "metadata": {}, + "source": [ + "### 3.3. Get material id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10", + "metadata": {}, + "outputs": [], + "source": [ + "material_id = saved_material.get(\"_id\")\n", + "print(\"Material IDs:\", material_id)" + ] + }, + { + "cell_type": "markdown", + "id": "11", + "metadata": {}, + "source": [ + "## 5. Create workflow and set its parameters\n", + "### 5.1. Get list of applications and select one" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.standata.applications import Applications\n", + "\n", + "# Get Applications list (with versions, build)\n", + "apps_list = Applications.list_all()\n", + "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", + "\n", + "app = Applications.get_by_name_first_match(\"espresso\")\n", + "# returns name, version, build config" + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": {}, + "source": [ + "### 5.2. Create workflow from standard workflows and preview it" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.standata.workflows import Workflows\n", + "from mat3ra.wode.workflows import Workflow\n", + "from utils.visualize import visualize_workflow\n", + "\n", + "# Search WF by name and application\n", + "workflow_config = Workflows.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", + "workflow = Workflow.create(workflow_config)\n", + "\n", + "# View workflow to understand its structure\n", + "visualize_workflow(workflow)" + ] + }, + { + "cell_type": "markdown", + "id": "15", + "metadata": {}, + "source": [ + "### 5.3. Add relaxation subworkflow" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16", + "metadata": {}, + "outputs": [], + "source": [ + "workflow.add_relaxation()\n", + "visualize_workflow(workflow)\n", + "# Relaxation subworkflow is added as the first subworkflow" + ] + }, + { + "cell_type": "markdown", + "id": "17", + "metadata": {}, + "source": [ + "### 5.4. Change subworkflow details (Model subtype)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.standata.model_tree import ModelTreeStandata\n", + "\n", + "swf_0 = workflow.subworkflows[0] # relaxation subworkflow\n", + "swf_1 = workflow.subworkflows[1] # band structure subworkflow\n", + "\n", + "# Change model subtype for relaxation subworkflow\n", + "# For preview:\n", + "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"] as enum\n", + "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\", ...] as enum\n", + "\n", + "model = ModelTreeStandata.get_model_by_parameters(\n", + " model_type=\"dft\",\n", + " subtype=subtypes.LDA,\n", + " functional=functionals.PZ,\n", + ")\n", + "swf_0.model = model\n", + "swf_1.model = model" + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "### 5.5. Modify workflow units found in preview" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20", + "metadata": {}, + "outputs": [], + "source": [ + "from mat3ra.wode.context_providers import PointsGridFormDataProvider\n", + "\n", + "# Values from publication\n", + "kgrid_scf = [6, 6, 1]\n", + "kgrid_nscf = [12, 12, 1]\n", + "kgrid_relax = kgrid_scf\n", + "\n", + "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", + "\n", + "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", + "new_context_scf = kgrid_context_provider.get_data(dimensions=kgrid_scf)\n", + "new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", + "\n", + "# Get workflow's specific unit that needs to be modified\n", + "# Option 1: search is done by unit name regex across the entire workflow\n", + "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", + "unit_to_modify_relax.context.add_context(new_context_relax)\n", + "\n", + "# Option 2: search is done by unit name within a specific subworkflow\n", + "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", + "unit_to_modify_scf.context.add_context(new_context_scf)\n", + "unit_to_modify_nscf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_nscf\")\n", + "unit_to_modify_nscf.context.add_context(new_context_nscf)\n", + "\n", + "# Set the modified unit back to the workflow\n", + "# Option 1: direct set by unit object, replacing the existing one\n", + "workflow.set_unit(unit_to_modify_relax)\n", + "\n", + "# Option 2: set by unit flowchart id and new unit object\n", + "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", + "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)" + ] + }, + { + "cell_type": "markdown", + "id": "21", + "metadata": {}, + "source": [ + "### 5.6. Save workflow to collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22", + "metadata": {}, + "outputs": [], + "source": [ + "from exabyte_api_client import WorkflowEndpoints\n", + "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", + "\n", + "workflow_endpoints = WorkflowEndpoints(*ENDPOINT_ARGS)\n", + "\n", + "saved_workflow_data = workflow_endpoints.create(config=workflow.to_dict(), owner_id=ACCOUNT_ID)" + ] + }, + { + "cell_type": "markdown", + "id": "23", + "metadata": {}, + "source": [ + "## 6. Create the compute configuration\n", + "### 6.1. View available clusters and providers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24", + "metadata": {}, + "outputs": [], + "source": [ + "# N/A in minimal version" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": {}, + "source": [ + "### 6.2. Create compute configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26", + "metadata": {}, + "outputs": [], + "source": [ + "from exabyte_api_client.endpoints.jobs import JobEndpoints\n", + "exabyte_jobs_endpoint = JobEndpoints(*ENDPOINT_ARGS)\n", + "job_config = {\"ppn\": 8,\n", + " \"queue\": \"OR8\",\n", + " \"nodes\": 1,\n", + " \"time_limit\": \"00:30:00\",\n", + " \"cluster\": \"cluster-001\"\n", + " }\n", + "compute = exabyte_jobs_endpoint.get_compute(**job_config)" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": {}, + "source": [ + "## 7. Create the job with material and workflow configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28", + "metadata": {}, + "outputs": [], + "source": [ + "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", + "from exabyte_api_client.endpoints.projects import ProjectEndpoints\n", + "\n", + "from datetime import datetime\n", + "\n", + "material_endpoints = MaterialEndpoints(*ENDPOINT_ARGS)\n", + "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", + "\n", + "project_endpoints = ProjectEndpoints(*ENDPOINT_ARGS)\n", + "project_id = project_endpoints.list({\"isDefault\": True, \"owner._id\": OWNER_ID})[0][\"_id\"]\n", + "\n", + "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", + "\n", + "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\") # for name to be found easily\n", + "\n", + "JOB_NAME = f\"Band Gap {timestamp}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29", + "metadata": {}, + "outputs": [], + "source": [ + "jobs = job_endpoints.create_by_ids(\n", + " materials=material, workflow_id=workflow[\"_id\"], project_id=project_id, prefix=JOB_NAME, owner_id=OWNER_ID\n", + ")\n", + "\n", + "display_JSON(jobs)" + ] + }, + { + "cell_type": "markdown", + "id": "30", + "metadata": {}, + "source": [ + "## 8. Submit the job and monitor the status" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31", + "metadata": {}, + "outputs": [], + "source": [ + "job_endpoints.submit(jobs[\"_id\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32", + "metadata": {}, + "outputs": [], + "source": [ + "from utils.generic import wait_for_jobs_to_finish\n", + "\n", + "job_ids = [job[\"_id\"] for job in jobs]\n", + "\n", + "wait_for_jobs_to_finish(job_endpoints, job_ids, poll_interval=60)" + ] + }, + { + "cell_type": "markdown", + "id": "33", + "metadata": {}, + "source": [ + "## 9. Retrieve results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34", + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "from utils.generic import get_property_by_subworkflow_and_unit_indicies\n", + "from exabyte_api_client.endpoints.properties import PropertiesEndpoints\n", + "\n", + "property_endpoints = PropertiesEndpoints(*ENDPOINT_ARGS)\n", + "\n", + "results = []\n", + "# Iterate in general, but we have only 1 material here\n", + "for material in [saved_material]:\n", + " job = next((job for job in jobs if job[\"_material\"][\"_id\"] == material[\"_id\"]))\n", + " final_structure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"final_structure\", job, 0, 0)[\n", + " \"data\"\n", + " ]\n", + " pressure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"pressure\", job, 0, 0)[\"data\"][\"value\"]\n", + " unit_flowchart_id = job[\"workflow\"][\"subworkflows\"][1][\"units\"][1][\"flowchartId\"]\n", + " band_gap_direct = property_endpoints.get_direct_band_gap(job[\"_id\"], unit_flowchart_id)\n", + " band_gap_indirect = property_endpoints.get_indirect_band_gap(job[\"_id\"], unit_flowchart_id)\n", + "\n", + " results.append(\n", + " {\n", + " \"material_id\": material[\"_id\"],\n", + " \"angle_deg\": re.search(r\"(\\d+(?:\\.\\d+)?) degrees\", material[\"name\"]).group(1),\n", + " \"band_gap_direct\": band_gap_direct,\n", + " \"band_gap_indirect\": band_gap_indirect,\n", + " }\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "35", + "metadata": {}, + "source": [ + "## 10. Display results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36", + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot as plt\n", + "import pandas as pd\n", + "\n", + "df = pd.DataFrame(results).dropna(subset=[\"band_gap_direct\", \"band_gap_indirect\"]).sort_values(\"angle_deg\")\n", + "display(df)\n", + "\n", + "plt.figure(figsize=(5, 3.6), dpi=130)\n", + "plt.scatter(df[\"angle_deg\"], df[\"band_gap_direct\"], marker=\">\", label=\"K-valley bandgap (direct)\")\n", + "plt.scatter(df[\"angle_deg\"], df[\"band_gap_indirect\"], marker=\"<\", label=\"Indirect bandgap\")\n", + "plt.xlabel(r\"$\\theta$ (°)\")\n", + "plt.ylabel(\"Energy (eV)\")\n", + "plt.xlim(-2, 62)\n", + "plt.legend(frameon=False, loc=\"best\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 8564836974880c6d378e5bda2340dc7d9bf30eed Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Tue, 2 Dec 2025 13:00:54 -0800 Subject: [PATCH 12/26] update: min version --- .../workflows/run_bandgap_workflow_min.ipynb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 9c3bff5f..cb77d4e1 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -368,6 +368,7 @@ "outputs": [], "source": [ "from exabyte_api_client.endpoints.jobs import JobEndpoints\n", + "\n", "exabyte_jobs_endpoint = JobEndpoints(*ENDPOINT_ARGS)\n", "job_config = {\"ppn\": 8,\n", " \"queue\": \"OR8\",\n", @@ -404,8 +405,6 @@ "project_endpoints = ProjectEndpoints(*ENDPOINT_ARGS)\n", "project_id = project_endpoints.list({\"isDefault\": True, \"owner._id\": OWNER_ID})[0][\"_id\"]\n", "\n", - "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", - "\n", "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\") # for name to be found easily\n", "\n", "JOB_NAME = f\"Band Gap {timestamp}\"" @@ -418,8 +417,15 @@ "metadata": {}, "outputs": [], "source": [ + "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", + "\n", "jobs = job_endpoints.create_by_ids(\n", - " materials=material, workflow_id=workflow[\"_id\"], project_id=project_id, prefix=JOB_NAME, owner_id=OWNER_ID\n", + " materials=material,\n", + " workflow_id=workflow[\"_id\"],\n", + " project_id=project_id,\n", + " prefix=JOB_NAME,\n", + " owner_id=OWNER_ID,\n", + " compute=compute\n", ")\n", "\n", "display_JSON(jobs)" From d3fd2302181c5388f7a30f5371bf2bfe24a73ecc Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Wed, 3 Dec 2025 15:44:25 -0800 Subject: [PATCH 13/26] update: adjust values extraction --- .../workflows/run_bandgap_workflow_max.ipynb | 20 ++++++-- .../workflows/run_bandgap_workflow_min.ipynb | 49 ++++++++++++------- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 8b709609..186f9f60 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -169,7 +169,7 @@ "# Change model subtype for relaxation subworkflow\n", "# For preview:\n", "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"] as enum\n", - "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\", ...] as enum\n", + "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", subtypes.LDA) # [\"pz\", ...] as enum\n", "\n", "model = ModelTreeStandata.get_model_by_parameters(\n", " model_type=\"dft\",\n", @@ -345,9 +345,20 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "26", "metadata": {}, + "outputs": [], + "source": [ + "# Prode has property analyzer to get all eigen_values and return occupied and unoccupied states\n", + "# Gets data from express that has parser" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": {}, "source": [ "## 10. Display results" ] @@ -355,11 +366,12 @@ { "cell_type": "code", "execution_count": null, - "id": "27", + "id": "28", "metadata": {}, "outputs": [], "source": [ "# Visual library that can visualize any property defined in Prode\n", + "# Use similar to Wave\n", "from mat3ra.prove import visualize_property\n", "\n", "visualize_property(results.band_structure)\n", @@ -369,7 +381,7 @@ { "cell_type": "code", "execution_count": null, - "id": "28", + "id": "29", "metadata": {}, "outputs": [], "source": [] diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index cb77d4e1..ab9c3146 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -70,6 +70,7 @@ "\n", "import os\n", "import sys\n", + "import json\n", "\n", "if sys.platform == \"emscripten\":\n", " # Only works if launched within the Platform, otherwise requires redirect to Login\n", @@ -79,7 +80,8 @@ " dict(\n", " ACCOUNT_ID=apiConfig.get(\"accountId\"),\n", " AUTH_TOKEN=apiConfig.get(\"authToken\"),\n", - " ORGANIZATION_ID=apiConfig.get(\"organizationId\") or \"\",\n", + " ORGANIZATION_ID=apiConfig.get(\"organizationId\", \"\"),\n", + " CLUSTERS=json.dumps(apiConfig.get(\"clusters\", [])),\n", " )\n", " )" ] @@ -251,7 +253,7 @@ "# Change model subtype for relaxation subworkflow\n", "# For preview:\n", "subtypes = ModelTreeStandata.get_subtypes_by_model_type(\"dft\") # [\"gga\", \"lda\"] as enum\n", - "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", \"lda\") # [\"pz\", ...] as enum\n", + "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", subtypes.LDA) # [\"pz\", ...] as enum\n", "\n", "model = ModelTreeStandata.get_model_by_parameters(\n", " model_type=\"dft\",\n", @@ -267,7 +269,7 @@ "id": "19", "metadata": {}, "source": [ - "### 5.5. Modify workflow units found in preview" + "### 5.5. Modify k-grid in subworkflow units" ] }, { @@ -284,6 +286,7 @@ "kgrid_nscf = [12, 12, 1]\n", "kgrid_relax = kgrid_scf\n", "\n", + "# In future: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", "\n", "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", @@ -307,7 +310,7 @@ "\n", "# Option 2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", - "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)" + "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n" ] }, { @@ -349,7 +352,10 @@ "metadata": {}, "outputs": [], "source": [ - "# N/A in minimal version" + "cluster_config = next(iter(json.loads(os.getenv(\"CLUSTERS\"))), {})\n", + "queue_configs = cluster_config.get(\"queues\", [])\n", + "\n", + "CLUSTER_NAME = cluster_config.get(\"displayName\", \"cluster-001\")" ] }, { @@ -370,13 +376,14 @@ "from exabyte_api_client.endpoints.jobs import JobEndpoints\n", "\n", "exabyte_jobs_endpoint = JobEndpoints(*ENDPOINT_ARGS)\n", - "job_config = {\"ppn\": 8,\n", - " \"queue\": \"OR8\",\n", - " \"nodes\": 1,\n", - " \"time_limit\": \"00:30:00\",\n", - " \"cluster\": \"cluster-001\"\n", - " }\n", - "compute = exabyte_jobs_endpoint.get_compute(**job_config)" + "\n", + "compute = exabyte_jobs_endpoint.get_compute(\n", + " ppn=8,\n", + " queue=\"OR8\",\n", + " nodes=1,\n", + " time_limit=\"00:30:00\",\n", + " cluster=CLUSTER_NAME\n", + ")" ] }, { @@ -399,9 +406,11 @@ "\n", "from datetime import datetime\n", "\n", + "# Add helper to AX utils: create_material(material, owner_id: Optional)\n", "material_endpoints = MaterialEndpoints(*ENDPOINT_ARGS)\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "\n", + "# Add helper to AX utils: create_workflow(workflow, owner_id: Optional)\n", "project_endpoints = ProjectEndpoints(*ENDPOINT_ARGS)\n", "project_id = project_endpoints.list({\"isDefault\": True, \"owner._id\": OWNER_ID})[0][\"_id\"]\n", "\n", @@ -417,6 +426,7 @@ "metadata": {}, "outputs": [], "source": [ + "from types import SimpleNamespace\n", "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", "jobs = job_endpoints.create_by_ids(\n", @@ -428,6 +438,8 @@ " compute=compute\n", ")\n", "\n", + "jobs = SimpleNamespace(**jobs)\n", + "\n", "display_JSON(jobs)" ] }, @@ -487,19 +499,20 @@ "results = []\n", "# Iterate in general, but we have only 1 material here\n", "for material in [saved_material]:\n", - " job = next((job for job in jobs if job[\"_material\"][\"_id\"] == material[\"_id\"]))\n", + " job = next((job for job in jobs if job._meterial._id == material._id))\n", " final_structure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"final_structure\", job, 0, 0)[\n", " \"data\"\n", " ]\n", " pressure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"pressure\", job, 0, 0)[\"data\"][\"value\"]\n", - " unit_flowchart_id = job[\"workflow\"][\"subworkflows\"][1][\"units\"][1][\"flowchartId\"]\n", - " band_gap_direct = property_endpoints.get_direct_band_gap(job[\"_id\"], unit_flowchart_id)\n", - " band_gap_indirect = property_endpoints.get_indirect_band_gap(job[\"_id\"], unit_flowchart_id)\n", + "\n", + " unit_flowchart_id = Workflow(job[\"workflow\"]).get_unit_by_name(name=\"pw_scf\").flowchart_id\n", + " band_gap_direct = property_endpoints.get_direct_band_gap(job._id, unit_flowchart_id)\n", + " band_gap_indirect = property_endpoints.get_indirect_band_gap(job._id, unit_flowchart_id)\n", "\n", " results.append(\n", " {\n", - " \"material_id\": material[\"_id\"],\n", - " \"angle_deg\": re.search(r\"(\\d+(?:\\.\\d+)?) degrees\", material[\"name\"]).group(1),\n", + " \"material_id\": material._id,\n", + " \"angle_deg\": re.search(r\"(\\d+(?:\\.\\d+)?) degrees\", material.name).group(1),\n", " \"band_gap_direct\": band_gap_direct,\n", " \"band_gap_indirect\": band_gap_indirect,\n", " }\n", From d5cb17b1d0e3de09369254b5ba70e8b71cd1c389 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Wed, 3 Dec 2025 15:55:03 -0800 Subject: [PATCH 14/26] update: use namespace --- .../workflows/run_bandgap_workflow_min.ipynb | 123 +++++++++++------- 1 file changed, 79 insertions(+), 44 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index ab9c3146..87424681 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -50,9 +50,29 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "3", "metadata": {}, + "outputs": [], + "source": [ + "from types import SimpleNamespace\n", + "\n", + "# TODO: move to AX utils\n", + "# Helper function to convert dictionaries to SimpleNamespace objects for dot notation access\n", + "def dict_to_namespace(obj):\n", + " if isinstance(obj, dict):\n", + " return SimpleNamespace(**{k: dict_to_namespace(v) for k, v in obj.items()})\n", + " elif isinstance(obj, list):\n", + " return [dict_to_namespace(item) for item in obj]\n", + " else:\n", + " return obj" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, "source": [ "## 2. Log in to get the API token" ] @@ -60,7 +80,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4", + "id": "5", "metadata": {}, "outputs": [], "source": [ @@ -88,7 +108,7 @@ }, { "cell_type": "markdown", - "id": "5", + "id": "6", "metadata": {}, "source": [ "## 3. Create material\n", @@ -98,7 +118,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6", + "id": "7", "metadata": {}, "outputs": [], "source": [ @@ -111,7 +131,7 @@ }, { "cell_type": "markdown", - "id": "7", + "id": "8", "metadata": {}, "source": [ "### 3.2. Save material to the platform" @@ -120,7 +140,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8", + "id": "9", "metadata": {}, "outputs": [], "source": [ @@ -128,6 +148,8 @@ "from utils.generic import display_JSON\n", "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", "\n", + "\n", + "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "endpoint = MaterialEndpoints(*ENDPOINT_ARGS)\n", "\n", @@ -135,12 +157,13 @@ "fields = [\"name\", \"lattice\", \"basis\"]\n", "CONFIG = {key: RAW_CONFIG[key] for key in fields}\n", "\n", - "saved_material = endpoint.create(CONFIG, OWNER_ID)" + "saved_material_response = endpoint.create(CONFIG, OWNER_ID)\n", + "saved_material = dict_to_namespace(saved_material_response)" ] }, { "cell_type": "markdown", - "id": "9", + "id": "10", "metadata": {}, "source": [ "### 3.3. Get material id" @@ -149,7 +172,7 @@ { "cell_type": "code", "execution_count": null, - "id": "10", + "id": "11", "metadata": {}, "outputs": [], "source": [ @@ -159,7 +182,7 @@ }, { "cell_type": "markdown", - "id": "11", + "id": "12", "metadata": {}, "source": [ "## 5. Create workflow and set its parameters\n", @@ -169,7 +192,7 @@ { "cell_type": "code", "execution_count": null, - "id": "12", + "id": "13", "metadata": {}, "outputs": [], "source": [ @@ -185,7 +208,7 @@ }, { "cell_type": "markdown", - "id": "13", + "id": "14", "metadata": {}, "source": [ "### 5.2. Create workflow from standard workflows and preview it" @@ -194,7 +217,7 @@ { "cell_type": "code", "execution_count": null, - "id": "14", + "id": "15", "metadata": {}, "outputs": [], "source": [ @@ -212,7 +235,7 @@ }, { "cell_type": "markdown", - "id": "15", + "id": "16", "metadata": {}, "source": [ "### 5.3. Add relaxation subworkflow" @@ -221,7 +244,7 @@ { "cell_type": "code", "execution_count": null, - "id": "16", + "id": "17", "metadata": {}, "outputs": [], "source": [ @@ -232,7 +255,7 @@ }, { "cell_type": "markdown", - "id": "17", + "id": "18", "metadata": {}, "source": [ "### 5.4. Change subworkflow details (Model subtype)" @@ -241,7 +264,7 @@ { "cell_type": "code", "execution_count": null, - "id": "18", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -266,7 +289,7 @@ }, { "cell_type": "markdown", - "id": "19", + "id": "20", "metadata": {}, "source": [ "### 5.5. Modify k-grid in subworkflow units" @@ -275,7 +298,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -315,7 +338,7 @@ }, { "cell_type": "markdown", - "id": "21", + "id": "22", "metadata": {}, "source": [ "### 5.6. Save workflow to collection" @@ -324,7 +347,7 @@ { "cell_type": "code", "execution_count": null, - "id": "22", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -338,7 +361,7 @@ }, { "cell_type": "markdown", - "id": "23", + "id": "24", "metadata": {}, "source": [ "## 6. Create the compute configuration\n", @@ -348,7 +371,7 @@ { "cell_type": "code", "execution_count": null, - "id": "24", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -360,7 +383,7 @@ }, { "cell_type": "markdown", - "id": "25", + "id": "26", "metadata": {}, "source": [ "### 6.2. Create compute configuration" @@ -369,7 +392,7 @@ { "cell_type": "code", "execution_count": null, - "id": "26", + "id": "27", "metadata": {}, "outputs": [], "source": [ @@ -388,7 +411,7 @@ }, { "cell_type": "markdown", - "id": "27", + "id": "28", "metadata": {}, "source": [ "## 7. Create the job with material and workflow configuration" @@ -397,7 +420,7 @@ { "cell_type": "code", "execution_count": null, - "id": "28", + "id": "29", "metadata": {}, "outputs": [], "source": [ @@ -422,14 +445,13 @@ { "cell_type": "code", "execution_count": null, - "id": "29", + "id": "30", "metadata": {}, "outputs": [], "source": [ - "from types import SimpleNamespace\n", "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", - "jobs = job_endpoints.create_by_ids(\n", + "jobs_response = job_endpoints.create_by_ids(\n", " materials=material,\n", " workflow_id=workflow[\"_id\"],\n", " project_id=project_id,\n", @@ -438,14 +460,15 @@ " compute=compute\n", ")\n", "\n", - "jobs = SimpleNamespace(**jobs)\n", + "# Convert jobs list to SimpleNamespace objects for dot notation access\n", + "jobs = dict_to_namespace(jobs_response)\n", "\n", - "display_JSON(jobs)" + "display_JSON(jobs_response)" ] }, { "cell_type": "markdown", - "id": "30", + "id": "31", "metadata": {}, "source": [ "## 8. Submit the job and monitor the status" @@ -454,30 +477,40 @@ { "cell_type": "code", "execution_count": null, - "id": "31", + "id": "32", "metadata": {}, "outputs": [], "source": [ - "job_endpoints.submit(jobs[\"_id\"])\n" + "# Submit each job (assuming jobs is a list of job objects)\n", + "if isinstance(jobs, list):\n", + " for job in jobs:\n", + " job_endpoints.submit(job._id)\n", + "else:\n", + " # If jobs is a single job object\n", + " job_endpoints.submit(jobs._id)\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "32", + "id": "33", "metadata": {}, "outputs": [], "source": [ "from utils.generic import wait_for_jobs_to_finish\n", "\n", - "job_ids = [job[\"_id\"] for job in jobs]\n", + "# Extract job IDs using dot notation\n", + "if isinstance(jobs, list):\n", + " job_ids = [job._id for job in jobs]\n", + "else:\n", + " job_ids = [jobs._id]\n", "\n", "wait_for_jobs_to_finish(job_endpoints, job_ids, poll_interval=60)" ] }, { "cell_type": "markdown", - "id": "33", + "id": "34", "metadata": {}, "source": [ "## 9. Retrieve results" @@ -486,7 +519,7 @@ { "cell_type": "code", "execution_count": null, - "id": "34", + "id": "35", "metadata": {}, "outputs": [], "source": [ @@ -499,13 +532,15 @@ "results = []\n", "# Iterate in general, but we have only 1 material here\n", "for material in [saved_material]:\n", - " job = next((job for job in jobs if job._meterial._id == material._id))\n", + " # Find the job that matches this material - fix typo: _meterial -> _material\n", + " job = next((job for job in jobs if job._material._id == material._id))\n", " final_structure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"final_structure\", job, 0, 0)[\n", " \"data\"\n", " ]\n", " pressure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"pressure\", job, 0, 0)[\"data\"][\"value\"]\n", "\n", - " unit_flowchart_id = Workflow(job[\"workflow\"]).get_unit_by_name(name=\"pw_scf\").flowchart_id\n", + " # Use dot notation to access workflow property\n", + " unit_flowchart_id = Workflow(job.workflow).get_unit_by_name(name=\"pw_scf\").flowchart_id\n", " band_gap_direct = property_endpoints.get_direct_band_gap(job._id, unit_flowchart_id)\n", " band_gap_indirect = property_endpoints.get_indirect_band_gap(job._id, unit_flowchart_id)\n", "\n", @@ -521,7 +556,7 @@ }, { "cell_type": "markdown", - "id": "35", + "id": "36", "metadata": {}, "source": [ "## 10. Display results" @@ -530,7 +565,7 @@ { "cell_type": "code", "execution_count": null, - "id": "36", + "id": "37", "metadata": {}, "outputs": [], "source": [ @@ -554,7 +589,7 @@ { "cell_type": "code", "execution_count": null, - "id": "37", + "id": "38", "metadata": {}, "outputs": [], "source": [] From c030a11e7e95d9d3ce54768b920da9249f3c49ff Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Wed, 3 Dec 2025 16:10:06 -0800 Subject: [PATCH 15/26] update: adjust assignment --- .../workflows/run_bandgap_workflow_max.ipynb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 186f9f60..c965847b 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -185,7 +185,7 @@ "id": "14", "metadata": {}, "source": [ - "### 5.5. Modify workflow units found in preview" + "### 5.5. Modify k-grid in subworkflow units" ] }, { @@ -202,6 +202,7 @@ "kgrid_nscf = [12, 12, 1]\n", "kgrid_relax = kgrid_scf\n", "\n", + "# TODO: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", "\n", "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", @@ -209,23 +210,24 @@ "new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", "\n", "# Get workflow's specific unit that needs to be modified\n", - "# Option 1: search is done by unit name regex across the entire workflow\n", + "# Option A-1: search is done by unit name regex across the entire workflow\n", "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", "unit_to_modify_relax.context.add_context(new_context_relax)\n", "\n", - "# Option 2: search is done by unit name within a specific subworkflow\n", + "# Option A-2: search is done by unit name within a specific subworkflow\n", "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", "unit_to_modify_scf.context.add_context(new_context_scf)\n", - "unit_to_modify_nscf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_nscf\")\n", - "unit_to_modify_nscf.context.add_context(new_context_nscf)\n", "\n", "# Set the modified unit back to the workflow\n", - "# Option 1: direct set by unit object, replacing the existing one\n", + "# Option B-1: direct set by unit object, replacing the existing one\n", "workflow.set_unit(unit_to_modify_relax)\n", "\n", - "# Option 2: set by unit flowchart id and new unit object\n", + "# Option B-2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", - "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)" + "\n", + "# Option B-3: set context to unit directly\n", + "workflow.get_unit_by_name(name=\"pw_nscf\").set_context(new_context_nscf)\n", + "# workflow.set_context_to_unit(unit_name=\"pw_nscf\", new_context=new_context_nscf)" ] }, { From f244e20058cf01c60e4cea1b2275c56455ec1ef6 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Wed, 3 Dec 2025 19:27:04 -0800 Subject: [PATCH 16/26] chore: adjust --- .../workflows/run_bandgap_workflow_max.ipynb | 10 +++++----- .../workflows/run_bandgap_workflow_min.ipynb | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index c965847b..eb43d4e0 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -89,13 +89,13 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.standata.applications import Applications\n", + "from mat3ra.standata.applications import ApplicationStandata\n", "\n", "# Get Applications list (with versions, build)\n", - "apps_list = Applications.list_all()\n", + "apps_list = ApplicationStandata.list_all()\n", "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", "\n", - "app = Applications.get_by_name_first_match(\"espresso\")\n", + "app = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", "# returns name, version, build config" ] }, @@ -114,12 +114,12 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.standata.workflows import Workflows\n", + "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", "from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", - "workflow_config = Workflows.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", + "workflow_config = WorkflowStandata.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 87424681..a081913c 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -196,13 +196,13 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.standata.applications import Applications\n", + "from mat3ra.standata.applications import ApplicationStandata\n", "\n", "# Get Applications list (with versions, build)\n", - "apps_list = Applications.list_all()\n", + "apps_list = ApplicationStandata.list_all()\n", "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", "\n", - "app = Applications.get_by_name_first_match(\"espresso\")\n", + "app = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", "# returns name, version, build config" ] }, @@ -221,12 +221,12 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.standata.workflows import Workflows\n", + "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", "from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", - "workflow_config = Workflows.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", + "workflow_config = WorkflowStandata.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", From c786934470116944e901209bf67e3802b2eaa7f1 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 5 Dec 2025 18:33:15 -0800 Subject: [PATCH 17/26] update: adjustments --- .../workflows/run_bandgap_workflow_min.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index a081913c..7b50747a 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -197,13 +197,15 @@ "outputs": [], "source": [ "from mat3ra.standata.applications import ApplicationStandata\n", + "from mat3ra.ade.application import Application\n", "\n", "# Get Applications list (with versions, build)\n", "apps_list = ApplicationStandata.list_all()\n", "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", "\n", - "app = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", - "# returns name, version, build config" + "app_config = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", + "# returns name, version, build config\n", + "app=Application(**app_config)" ] }, { @@ -226,10 +228,11 @@ "from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", - "workflow_config = WorkflowStandata.filter_by_application(app).get_by_name_first_match(\"band_gap\")\n", + "workflow_config = WorkflowStandata.filter_by_application(app.name).get_by_name_first_match(\"band_gap\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", + "# workflow\n", "visualize_workflow(workflow)" ] }, From d0a42090493c408b3cbdf6d81593d9ce773bc711 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 8 Dec 2025 11:18:05 -0800 Subject: [PATCH 18/26] update: context --- .../workflows/run_bandgap_workflow_max.ipynb | 4 ++-- .../workflows/run_bandgap_workflow_min.ipynb | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index eb43d4e0..24e557cb 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -212,11 +212,11 @@ "# Get workflow's specific unit that needs to be modified\n", "# Option A-1: search is done by unit name regex across the entire workflow\n", "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", - "unit_to_modify_relax.context.add_context(new_context_relax)\n", + "unit_to_modify_relax.add_context(new_context_relax)\n", "\n", "# Option A-2: search is done by unit name within a specific subworkflow\n", "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", - "unit_to_modify_scf.context.add_context(new_context_scf)\n", + "unit_to_modify_scf.add_context(new_context_scf)\n", "\n", "# Set the modified unit back to the workflow\n", "# Option B-1: direct set by unit object, replacing the existing one\n", diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 7b50747a..437ee15f 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -225,7 +225,7 @@ "source": [ "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", - "from utils.visualize import visualize_workflow\n", + "# from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", "workflow_config = WorkflowStandata.filter_by_application(app.name).get_by_name_first_match(\"band_gap\")\n", @@ -233,7 +233,7 @@ "\n", "# View workflow to understand its structure\n", "# workflow\n", - "visualize_workflow(workflow)" + "# visualize_workflow(workflow)" ] }, { @@ -282,7 +282,7 @@ "functionals = ModelTreeStandata.get_functionals_by_subtype(\"dft\", subtypes.LDA) # [\"pz\", ...] as enum\n", "\n", "model = ModelTreeStandata.get_model_by_parameters(\n", - " model_type=\"dft\",\n", + " type=\"dft\",\n", " subtype=subtypes.LDA,\n", " functional=functionals.PZ,\n", ")\n", @@ -326,9 +326,9 @@ "\n", "# Option 2: search is done by unit name within a specific subworkflow\n", "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", - "unit_to_modify_scf.context.add_context(new_context_scf)\n", + "unit_to_modify_scf.add_context(new_context_scf)\n", "unit_to_modify_nscf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_nscf\")\n", - "unit_to_modify_nscf.context.add_context(new_context_nscf)\n", + "unit_to_modify_nscf.add_context(new_context_nscf)\n", "\n", "# Set the modified unit back to the workflow\n", "# Option 1: direct set by unit object, replacing the existing one\n", From da3c2a9af7b3e32630a2a9d5e4e7e5b15dbcb865 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Wed, 10 Dec 2025 17:34:41 -0800 Subject: [PATCH 19/26] update: mvp works --- .../workflows/run_bandgap_workflow_max.ipynb | 4 ++-- .../workflows/run_bandgap_workflow_min.ipynb | 10 +++++----- pyproject.toml | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb index 24e557cb..a307b174 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_max.ipynb @@ -195,7 +195,7 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.wode.context_providers import PointsGridFormDataProvider\n", + "from mat3ra.wode.context.providers import PointsGridDataProvider\n", "\n", "# Values from publication\n", "kgrid_scf = [6, 6, 1]\n", @@ -203,7 +203,7 @@ "kgrid_relax = kgrid_scf\n", "\n", "# TODO: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", - "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", + "kgrid_context_provider = PointsGridDataProvider(material=material)\n", "\n", "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", "new_context_scf = kgrid_context_provider.get_data(dimensions=kgrid_scf)\n", diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 437ee15f..fbe78c82 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -232,7 +232,7 @@ "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", - "# workflow\n", + "workflow\n", "# visualize_workflow(workflow)" ] }, @@ -252,7 +252,7 @@ "outputs": [], "source": [ "workflow.add_relaxation()\n", - "visualize_workflow(workflow)\n", + "# visualize_workflow(workflow)\n", "# Relaxation subworkflow is added as the first subworkflow" ] }, @@ -305,7 +305,7 @@ "metadata": {}, "outputs": [], "source": [ - "from mat3ra.wode.context_providers import PointsGridFormDataProvider\n", + "from mat3ra.wode.context.providers import PointsGridDataProvider\n", "\n", "# Values from publication\n", "kgrid_scf = [6, 6, 1]\n", @@ -313,7 +313,7 @@ "kgrid_relax = kgrid_scf\n", "\n", "# In future: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", - "kgrid_context_provider = PointsGridFormDataProvider(material=material)\n", + "kgrid_context_provider = PointsGridDataProvider()\n", "\n", "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", "new_context_scf = kgrid_context_provider.get_data(dimensions=kgrid_scf)\n", @@ -322,7 +322,7 @@ "# Get workflow's specific unit that needs to be modified\n", "# Option 1: search is done by unit name regex across the entire workflow\n", "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", - "unit_to_modify_relax.context.add_context(new_context_relax)\n", + "unit_to_modify_relax.add_context(new_context_relax)\n", "\n", "# Option 2: search is done by unit name within a specific subworkflow\n", "unit_to_modify_scf = workflow.subworkflows[1].get_unit_by_name(name=\"pw_scf\")\n", diff --git a/pyproject.toml b/pyproject.toml index f5feb0f7..1fbda5cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ dependencies = [ "pymatgen==2024.4.13", "mat3ra-made>=2025.8.13.post0", "mat3ra-utils>=2024.6.11.post0", + "mat3ra-wode @ git+https://github.com/Exabyte-io/wode.git@ffc88d15184b2bedae558c47c2a7ba2e49624c52" ] [project.optional-dependencies] From 2eadf29dbe96001704639be012c8dffe1f8ac0ab Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Thu, 11 Dec 2025 09:22:36 -0800 Subject: [PATCH 20/26] update: adjust --- .../workflows/run_bandgap_workflow_min.ipynb | 60 +++++++++++-------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index fbe78c82..2a563661 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -253,7 +253,8 @@ "source": [ "workflow.add_relaxation()\n", "# visualize_workflow(workflow)\n", - "# Relaxation subworkflow is added as the first subworkflow" + "# Relaxation subworkflow is added as the first subworkflow\n", + "workflow.subworkflows[0]" ] }, { @@ -287,7 +288,8 @@ " functional=functionals.PZ,\n", ")\n", "swf_0.model = model\n", - "swf_1.model = model" + "swf_1.model = model\n", + "model" ] }, { @@ -313,11 +315,21 @@ "kgrid_relax = kgrid_scf\n", "\n", "# In future: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", - "kgrid_context_provider = PointsGridDataProvider()\n", + "kgrid_context_provider = PointsGridDataProvider(dimensions=kgrid_scf)\n", "\n", - "new_context_relax = kgrid_context_provider.get_data(dimensions=kgrid_relax)\n", - "new_context_scf = kgrid_context_provider.get_data(dimensions=kgrid_scf)\n", - "new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", + "new_context_relax = kgrid_context_provider\n", + "new_context_relax." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22", + "metadata": {}, + "outputs": [], + "source": [ + "# new_context_scf = kgrid_context_provider.\n", + "# new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", "\n", "# Get workflow's specific unit that needs to be modified\n", "# Option 1: search is done by unit name regex across the entire workflow\n", @@ -341,7 +353,7 @@ }, { "cell_type": "markdown", - "id": "22", + "id": "23", "metadata": {}, "source": [ "### 5.6. Save workflow to collection" @@ -350,7 +362,7 @@ { "cell_type": "code", "execution_count": null, - "id": "23", + "id": "24", "metadata": {}, "outputs": [], "source": [ @@ -364,7 +376,7 @@ }, { "cell_type": "markdown", - "id": "24", + "id": "25", "metadata": {}, "source": [ "## 6. Create the compute configuration\n", @@ -374,7 +386,7 @@ { "cell_type": "code", "execution_count": null, - "id": "25", + "id": "26", "metadata": {}, "outputs": [], "source": [ @@ -386,7 +398,7 @@ }, { "cell_type": "markdown", - "id": "26", + "id": "27", "metadata": {}, "source": [ "### 6.2. Create compute configuration" @@ -395,7 +407,7 @@ { "cell_type": "code", "execution_count": null, - "id": "27", + "id": "28", "metadata": {}, "outputs": [], "source": [ @@ -414,7 +426,7 @@ }, { "cell_type": "markdown", - "id": "28", + "id": "29", "metadata": {}, "source": [ "## 7. Create the job with material and workflow configuration" @@ -423,7 +435,7 @@ { "cell_type": "code", "execution_count": null, - "id": "29", + "id": "30", "metadata": {}, "outputs": [], "source": [ @@ -432,7 +444,7 @@ "\n", "from datetime import datetime\n", "\n", - "# Add helper to AX utils: create_material(material, owner_id: Optional)\n", + "# TODO: Add helper to AX utils: create_material(material, owner_id: Optional)\n", "material_endpoints = MaterialEndpoints(*ENDPOINT_ARGS)\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "\n", @@ -448,7 +460,7 @@ { "cell_type": "code", "execution_count": null, - "id": "30", + "id": "31", "metadata": {}, "outputs": [], "source": [ @@ -471,7 +483,7 @@ }, { "cell_type": "markdown", - "id": "31", + "id": "32", "metadata": {}, "source": [ "## 8. Submit the job and monitor the status" @@ -480,7 +492,7 @@ { "cell_type": "code", "execution_count": null, - "id": "32", + "id": "33", "metadata": {}, "outputs": [], "source": [ @@ -496,7 +508,7 @@ { "cell_type": "code", "execution_count": null, - "id": "33", + "id": "34", "metadata": {}, "outputs": [], "source": [ @@ -513,7 +525,7 @@ }, { "cell_type": "markdown", - "id": "34", + "id": "35", "metadata": {}, "source": [ "## 9. Retrieve results" @@ -522,7 +534,7 @@ { "cell_type": "code", "execution_count": null, - "id": "35", + "id": "36", "metadata": {}, "outputs": [], "source": [ @@ -559,7 +571,7 @@ }, { "cell_type": "markdown", - "id": "36", + "id": "37", "metadata": {}, "source": [ "## 10. Display results" @@ -568,7 +580,7 @@ { "cell_type": "code", "execution_count": null, - "id": "37", + "id": "38", "metadata": {}, "outputs": [], "source": [ @@ -592,7 +604,7 @@ { "cell_type": "code", "execution_count": null, - "id": "38", + "id": "39", "metadata": {}, "outputs": [], "source": [] From 069c8e2a42a76da08ae5d47b9a03f1479c1c7927 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Thu, 11 Dec 2025 19:58:14 -0800 Subject: [PATCH 21/26] update: adjust for more features to work --- .../MoS2(001)-MoS2(001), Interface.json | 1 + .../workflows/run_bandgap_workflow_min.ipynb | 212 +++++++++--------- utils/generic.py | 14 +- 3 files changed, 125 insertions(+), 102 deletions(-) create mode 100644 other/materials_designer/uploads/MoS2(001)-MoS2(001), Interface.json diff --git a/other/materials_designer/uploads/MoS2(001)-MoS2(001), Interface.json b/other/materials_designer/uploads/MoS2(001)-MoS2(001), Interface.json new file mode 100644 index 00000000..41cd91a3 --- /dev/null +++ b/other/materials_designer/uploads/MoS2(001)-MoS2(001), Interface.json @@ -0,0 +1 @@ +{"description": null, "descriptionObject": null, "metadata": {"build": [{"configuration": {"stack_components": [{"xy_supercell_matrix": [[-3, -1], [-2, -3]], "strain_matrix": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], "stack_components": [{"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, {"direction": "z", "size": 20.0, "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [{"configuration": {"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, "build_parameters": {}}], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "MoS2(001), termination S_P6/mmm_1", "isDefault": false, "formula": "MoS2", "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.067864]}, {"id": 1, "value": [0.333333333, 0.666666667, 1e-06]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.135727]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "type": "VacuumConfiguration"}], "direction": "z", "gaps": [], "type": "SlabConfiguration", "termination_top": null, "termination_bottom": null}, {"xy_supercell_matrix": [[-3, -2], [-1, -3]], "strain_matrix": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], "stack_components": [{"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, {"direction": "z", "size": 20.0, "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [{"configuration": {"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, "build_parameters": {}}], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "MoS2(001), termination S_P6/mmm_1", "isDefault": false, "formula": "MoS2", "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.067864]}, {"id": 1, "value": [0.333333333, 0.666666667, 1e-06]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.135727]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "type": "VacuumConfiguration"}], "direction": "z", "gaps": [], "type": "SlabConfiguration", "termination_top": null, "termination_bottom": null}, {"direction": "z", "size": 20.0, "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [{"configuration": {"xy_supercell_matrix": [[-3, -1], [-2, -3]], "strain_matrix": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], "stack_components": [{"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, {"direction": "z", "size": 20.0, "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [{"configuration": {"termination_top": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}, "number_of_repetitions": 1, "miller_indices": [0, 0, 1], "crystal": {"description": null, "descriptionObject": null, "metadata": {"build": [], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "Mo1 S2", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.5]}, {"id": 1, "value": [0.333333333, 0.666666667, 0.432137]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.567863]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "use_conventional_cell": true, "termination_bottom": {"chemical_elements": "S", "space_group_symmetry_label": "P6/mmm_1"}}, "build_parameters": {}}], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "MoS2(001), termination S_P6/mmm_1", "isDefault": false, "formula": "MoS2", "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666667, 0.333333333, 0.067864]}, {"id": 1, "value": [0.333333333, 0.666666667, 1e-06]}, {"id": 2, "value": [0.333333333, 0.666666667, 0.135727]}], "units": "crystal", "labels": [], "constraints": []}, "lattice": {"a": 3.196223, "b": 3.196223, "c": 23.12983, "alpha": 90.0, "beta": 90.0, "gamma": 120.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "type": "VacuumConfiguration"}], "direction": "z", "gaps": [], "type": "SlabConfiguration", "termination_top": null, "termination_bottom": null}, "build_parameters": {"use_orthogonal_c": true, "xy_supercell_matrix": [[1, 0], [0, 1]]}}], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "MoS2(001), termination S_P6/mmm_1, Slab", "isDefault": false, "formula": "MoS2", "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}, {"id": 3, "value": "Mo"}, {"id": 4, "value": "S"}, {"id": 5, "value": "S"}, {"id": 6, "value": "Mo"}, {"id": 7, "value": "S"}, {"id": 8, "value": "S"}, {"id": 9, "value": "Mo"}, {"id": 10, "value": "S"}, {"id": 11, "value": "S"}, {"id": 12, "value": "Mo"}, {"id": 13, "value": "S"}, {"id": 14, "value": "S"}, {"id": 15, "value": "Mo"}, {"id": 16, "value": "S"}, {"id": 17, "value": "S"}, {"id": 18, "value": "Mo"}, {"id": 19, "value": "S"}, {"id": 20, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666666, 0.666666667, 0.036394365]}, {"id": 1, "value": [0.904761905, 0.476190476, 5.36e-07]}, {"id": 2, "value": [0.904761905, 0.476190476, 0.072788194]}, {"id": 3, "value": [0.238095238, 0.80952381, 0.036394365]}, {"id": 4, "value": [0.476190476, 0.619047619, 5.36e-07]}, {"id": 5, "value": [0.476190476, 0.619047619, 0.072788194]}, {"id": 6, "value": [0.523809524, 0.380952381, 0.036394365]}, {"id": 7, "value": [0.761904762, 0.19047619, 5.36e-07]}, {"id": 8, "value": [0.761904762, 0.19047619, 0.072788194]}, {"id": 9, "value": [0.095238095, 0.523809524, 0.036394365]}, {"id": 10, "value": [0.333333334, 0.333333333, 5.36e-07]}, {"id": 11, "value": [0.333333334, 0.333333333, 0.072788194]}, {"id": 12, "value": [0.380952381, 0.095238095, 0.036394365]}, {"id": 13, "value": [0.619047619, 0.904761905, 5.36e-07]}, {"id": 14, "value": [0.619047619, 0.904761905, 0.072788194]}, {"id": 15, "value": [0.952380952, 0.238095238, 0.036394365]}, {"id": 16, "value": [0.190476191, 0.047619047, 5.36e-07]}, {"id": 17, "value": [0.190476191, 0.047619047, 0.072788194]}, {"id": 18, "value": [0.809523809, 0.952380953, 0.036394365]}, {"id": 19, "value": [0.047619048, 0.761904762, 5.36e-07]}, {"id": 20, "value": [0.047619048, 0.761904762, 0.072788194]}], "units": "crystal", "labels": [{"id": 0, "value": 0}, {"id": 1, "value": 0}, {"id": 2, "value": 0}, {"id": 3, "value": 0}, {"id": 4, "value": 0}, {"id": 5, "value": 0}, {"id": 6, "value": 0}, {"id": 7, "value": 0}, {"id": 8, "value": 0}, {"id": 9, "value": 0}, {"id": 10, "value": 0}, {"id": 11, "value": 0}, {"id": 12, "value": 0}, {"id": 13, "value": 0}, {"id": 14, "value": 0}, {"id": 15, "value": 0}, {"id": 16, "value": 0}, {"id": 17, "value": 0}, {"id": 18, "value": 0}, {"id": 19, "value": 0}, {"id": 20, "value": 0}], "constraints": []}, "lattice": {"a": 8.456411193, "b": 8.456411193, "c": 43.12983, "alpha": 90.0, "beta": 90.0, "gamma": 59.999999999999986, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"}, "type": "VacuumConfiguration"}], "direction": "z", "xy_shift": [0.0, 0.0], "gaps": [{"id": 0, "value": 6.5}, {"id": 1, "value": 6.5}], "type": "InterfaceConfiguration"}, "build_parameters": {"make_primitive": true}}], "boundaryConditions": {"type": "pbc", "offset": 0}}, "name": "MoS2(001)-MoS2(001), Interface", "isDefault": false, "formula": null, "unitCellFormula": null, "basis": {"elements": [{"id": 0, "value": "Mo"}, {"id": 1, "value": "S"}, {"id": 2, "value": "S"}, {"id": 3, "value": "Mo"}, {"id": 4, "value": "S"}, {"id": 5, "value": "S"}, {"id": 6, "value": "Mo"}, {"id": 7, "value": "S"}, {"id": 8, "value": "S"}, {"id": 9, "value": "Mo"}, {"id": 10, "value": "S"}, {"id": 11, "value": "S"}, {"id": 12, "value": "Mo"}, {"id": 13, "value": "S"}, {"id": 14, "value": "S"}, {"id": 15, "value": "Mo"}, {"id": 16, "value": "S"}, {"id": 17, "value": "S"}, {"id": 18, "value": "Mo"}, {"id": 19, "value": "S"}, {"id": 20, "value": "S"}, {"id": 21, "value": "Mo"}, {"id": 22, "value": "S"}, {"id": 23, "value": "S"}, {"id": 24, "value": "Mo"}, {"id": 25, "value": "S"}, {"id": 26, "value": "S"}, {"id": 27, "value": "Mo"}, {"id": 28, "value": "S"}, {"id": 29, "value": "S"}, {"id": 30, "value": "Mo"}, {"id": 31, "value": "S"}, {"id": 32, "value": "S"}, {"id": 33, "value": "Mo"}, {"id": 34, "value": "S"}, {"id": 35, "value": "S"}, {"id": 36, "value": "Mo"}, {"id": 37, "value": "S"}, {"id": 38, "value": "S"}, {"id": 39, "value": "Mo"}, {"id": 40, "value": "S"}, {"id": 41, "value": "S"}], "coordinates": [{"id": 0, "value": [0.666666666, 0.666666667, 0.039962712]}, {"id": 1, "value": [0.904761905, 0.476190476, 5.88e-07]}, {"id": 2, "value": [0.904761905, 0.476190476, 0.079924836]}, {"id": 3, "value": [0.238095238, 0.80952381, 0.039962712]}, {"id": 4, "value": [0.476190476, 0.619047619, 5.88e-07]}, {"id": 5, "value": [0.476190476, 0.619047619, 0.079924836]}, {"id": 6, "value": [0.523809524, 0.380952381, 0.039962712]}, {"id": 7, "value": [0.761904762, 0.19047619, 5.88e-07]}, {"id": 8, "value": [0.761904762, 0.19047619, 0.079924836]}, {"id": 9, "value": [0.095238095, 0.523809524, 0.039962712]}, {"id": 10, "value": [0.333333334, 0.333333333, 5.88e-07]}, {"id": 11, "value": [0.333333334, 0.333333333, 0.079924836]}, {"id": 12, "value": [0.380952381, 0.095238095, 0.039962712]}, {"id": 13, "value": [0.619047619, 0.904761905, 5.88e-07]}, {"id": 14, "value": [0.619047619, 0.904761905, 0.079924836]}, {"id": 15, "value": [0.952380952, 0.238095238, 0.039962712]}, {"id": 16, "value": [0.190476191, 0.047619047, 5.88e-07]}, {"id": 17, "value": [0.190476191, 0.047619047, 0.079924836]}, {"id": 18, "value": [0.809523809, 0.952380953, 0.039962712]}, {"id": 19, "value": [0.047619048, 0.761904762, 5.88e-07]}, {"id": 20, "value": [0.047619048, 0.761904762, 0.079924836]}, {"id": 21, "value": [0.476190476, 0.904761905, 0.285371704]}, {"id": 22, "value": [0.666666667, 0.666666666, 0.24540958]}, {"id": 23, "value": [0.666666667, 0.666666666, 0.325333827]}, {"id": 24, "value": [0.619047619, 0.476190476, 0.285371704]}, {"id": 25, "value": [0.80952381, 0.238095238, 0.24540958]}, {"id": 26, "value": [0.80952381, 0.238095238, 0.325333827]}, {"id": 27, "value": [0.19047619, 0.761904762, 0.285371704]}, {"id": 28, "value": [0.380952381, 0.523809524, 0.24540958]}, {"id": 29, "value": [0.380952381, 0.523809524, 0.325333827]}, {"id": 30, "value": [0.333333333, 0.333333334, 0.285371704]}, {"id": 31, "value": [0.523809524, 0.095238095, 0.24540958]}, {"id": 32, "value": [0.523809524, 0.095238095, 0.325333827]}, {"id": 33, "value": [0.904761905, 0.619047619, 0.285371704]}, {"id": 34, "value": [0.095238095, 0.380952381, 0.24540958]}, {"id": 35, "value": [0.095238095, 0.380952381, 0.325333827]}, {"id": 36, "value": [0.047619047, 0.190476191, 0.285371704]}, {"id": 37, "value": [0.238095238, 0.952380952, 0.24540958]}, {"id": 38, "value": [0.238095238, 0.952380952, 0.325333827]}, {"id": 39, "value": [0.761904762, 0.047619048, 0.285371704]}, {"id": 40, "value": [0.952380953, 0.809523809, 0.24540958]}, {"id": 41, "value": [0.952380953, 0.809523809, 0.325333827]}], "units": "crystal", "labels": [{"id": 0, "value": 0}, {"id": 1, "value": 0}, {"id": 2, "value": 0}, {"id": 3, "value": 0}, {"id": 4, "value": 0}, {"id": 5, "value": 0}, {"id": 6, "value": 0}, {"id": 7, "value": 0}, {"id": 8, "value": 0}, {"id": 9, "value": 0}, {"id": 10, "value": 0}, {"id": 11, "value": 0}, {"id": 12, "value": 0}, {"id": 13, "value": 0}, {"id": 14, "value": 0}, {"id": 15, "value": 0}, {"id": 16, "value": 0}, {"id": 17, "value": 0}, {"id": 18, "value": 0}, {"id": 19, "value": 0}, {"id": 20, "value": 0}, {"id": 21, "value": 1}, {"id": 22, "value": 1}, {"id": 23, "value": 1}, {"id": 24, "value": 1}, {"id": 25, "value": 1}, {"id": 26, "value": 1}, {"id": 27, "value": 1}, {"id": 28, "value": 1}, {"id": 29, "value": 1}, {"id": 30, "value": 1}, {"id": 31, "value": 1}, {"id": 32, "value": 1}, {"id": 33, "value": 1}, {"id": 34, "value": 1}, {"id": 35, "value": 1}, {"id": 36, "value": 1}, {"id": 37, "value": 1}, {"id": 38, "value": 1}, {"id": 39, "value": 1}, {"id": 40, "value": 1}, {"id": 41, "value": 1}], "constraints": []}, "lattice": {"a": 8.456411193, "b": 8.456411193, "c": 39.278684866, "alpha": 90.0, "beta": 90.0, "gamma": 60.0, "units": {"length": "angstrom", "angle": "degree"}, "type": "TRI"}, "derivedProperties": null, "external": null, "src": null, "scaledHash": null, "icsdId": null, "isNonPeriodic": false, "consistencyChecks": null, "field_id": null, "slug": null, "systemName": null, "schemaVersion": "2022.8.16"} \ No newline at end of file diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 2a563661..519f1c0f 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -32,10 +32,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "2", "metadata": {}, - "outputs": [], "source": [ "import sys\n", "\n", @@ -47,27 +45,9 @@ " from mat3ra.utils.jupyterlite.packages import install_packages\n", "\n", " await install_packages(\"api_examples\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3", - "metadata": {}, + ], "outputs": [], - "source": [ - "from types import SimpleNamespace\n", - "\n", - "# TODO: move to AX utils\n", - "# Helper function to convert dictionaries to SimpleNamespace objects for dot notation access\n", - "def dict_to_namespace(obj):\n", - " if isinstance(obj, dict):\n", - " return SimpleNamespace(**{k: dict_to_namespace(v) for k, v in obj.items()})\n", - " elif isinstance(obj, list):\n", - " return [dict_to_namespace(item) for item in obj]\n", - " else:\n", - " return obj" - ] + "execution_count": null }, { "cell_type": "markdown", @@ -79,10 +59,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "5", "metadata": {}, - "outputs": [], "source": [ "ACCOUNT_ID = \"ACCOUNT_ID\"\n", "AUTH_TOKEN = \"AUTH_TOKEN\"\n", @@ -92,6 +70,7 @@ "import sys\n", "import json\n", "\n", + "# TODO: add OIDC\n", "if sys.platform == \"emscripten\":\n", " # Only works if launched within the Platform, otherwise requires redirect to Login\n", " apiConfig = data_from_host.get(\"apiConfig\")\n", @@ -104,7 +83,9 @@ " CLUSTERS=json.dumps(apiConfig.get(\"clusters\", [])),\n", " )\n", " )" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -117,17 +98,17 @@ }, { "cell_type": "code", - "execution_count": null, "id": "7", "metadata": {}, - "outputs": [], "source": [ "from utils.visualize import visualize_materials as visualize\n", "from utils.jupyterlite import load_material_from_folder\n", "\n", - "material = load_material_from_folder(\"/uploads\", \"MoS2_twisted_interface_60_degrees.json\")\n", + "material = load_material_from_folder(\"../uploads\", \"MoS2(001)-MoS2(001), Interface\")\n", "visualize(material)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -139,17 +120,13 @@ }, { "cell_type": "code", - "execution_count": null, "id": "9", "metadata": {}, - "outputs": [], "source": [ "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", - "from utils.generic import display_JSON\n", + "from utils.generic import display_JSON, dict_to_namespace\n", "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", "\n", - "\n", - "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "endpoint = MaterialEndpoints(*ENDPOINT_ARGS)\n", "\n", @@ -159,7 +136,9 @@ "\n", "saved_material_response = endpoint.create(CONFIG, OWNER_ID)\n", "saved_material = dict_to_namespace(saved_material_response)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -171,14 +150,14 @@ }, { "cell_type": "code", - "execution_count": null, "id": "11", "metadata": {}, - "outputs": [], "source": [ "material_id = saved_material.get(\"_id\")\n", "print(\"Material IDs:\", material_id)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -190,23 +169,32 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "13", "metadata": {}, - "outputs": [], + "cell_type": "code", "source": [ "from mat3ra.standata.applications import ApplicationStandata\n", "from mat3ra.ade.application import Application\n", "\n", "# Get Applications list (with versions, build)\n", "apps_list = ApplicationStandata.list_all()\n", - "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]\n", - "\n", + "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]" + ], + "id": "66051fbafd8c1e87", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": [ "app_config = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", "# returns name, version, build config\n", - "app=Application(**app_config)" - ] + "app = Application(**app_config)\n", + "app.name" + ], + "id": "e661138b8755f3ab", + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -218,13 +206,12 @@ }, { "cell_type": "code", - "execution_count": null, "id": "15", "metadata": {}, - "outputs": [], "source": [ "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", + "\n", "# from utils.visualize import visualize_workflow\n", "\n", "# Search WF by name and application\n", @@ -234,7 +221,9 @@ "# View workflow to understand its structure\n", "workflow\n", "# visualize_workflow(workflow)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -246,16 +235,16 @@ }, { "cell_type": "code", - "execution_count": null, "id": "17", "metadata": {}, - "outputs": [], "source": [ "workflow.add_relaxation()\n", "# visualize_workflow(workflow)\n", "# Relaxation subworkflow is added as the first subworkflow\n", - "workflow.subworkflows[0]" - ] + "print(workflow.subworkflows[0].name, \"\\n\", workflow.subworkflows[1].name)" + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -267,10 +256,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "19", "metadata": {}, - "outputs": [], "source": [ "from mat3ra.standata.model_tree import ModelTreeStandata\n", "\n", @@ -290,22 +277,22 @@ "swf_0.model = model\n", "swf_1.model = model\n", "model" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ - "### 5.5. Modify k-grid in subworkflow units" + "### 5.5. Modify k-grid in subworkflow units\n", + "#### 5.5.1. Define k-grid values and create context providers" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "21", "metadata": {}, - "outputs": [], + "cell_type": "code", "source": [ "from mat3ra.wode.context.providers import PointsGridDataProvider\n", "\n", @@ -315,22 +302,43 @@ "kgrid_relax = kgrid_scf\n", "\n", "# In future: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", - "kgrid_context_provider = PointsGridDataProvider(dimensions=kgrid_scf)\n", - "\n", - "new_context_relax = kgrid_context_provider\n", - "new_context_relax." - ] + "kgrid_context_provider_relax = PointsGridDataProvider(dimensions=kgrid_scf)\n", + "kgrid_context_provider_scf = PointsGridDataProvider(dimensions=kgrid_scf)\n", + "kgrid_context_provider_nscf = PointsGridDataProvider(dimensions=kgrid_nscf)" + ], + "id": "fcf79eceb2b43083", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "#### 5.5.2. Get new context data and set it to workflow units", + "id": "d4185422ad5334dd" + }, + { + "metadata": {}, + "cell_type": "code", + "source": [ + "new_context_relax = kgrid_context_provider_relax.get_data()\n", + "new_context_scf = kgrid_context_provider_scf.get_data()\n", + "new_context_nscf = kgrid_context_provider_nscf.get_data()" + ], + "id": "f90491e54e2aa731", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "#### 5.5.3. Modify workflow units with new context", + "id": "624fdb2666c705d7" }, { "cell_type": "code", - "execution_count": null, "id": "22", "metadata": {}, - "outputs": [], "source": [ - "# new_context_scf = kgrid_context_provider.\n", - "# new_context_nscf = kgrid_context_provider.get_data(dimensions=kgrid_nscf)\n", - "\n", "# Get workflow's specific unit that needs to be modified\n", "# Option 1: search is done by unit name regex across the entire workflow\n", "unit_to_modify_relax = workflow.get_unit_by_name(name_regex=\"relax\")\n", @@ -349,7 +357,9 @@ "# Option 2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -361,10 +371,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "24", "metadata": {}, - "outputs": [], "source": [ "from exabyte_api_client import WorkflowEndpoints\n", "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", @@ -372,7 +380,9 @@ "workflow_endpoints = WorkflowEndpoints(*ENDPOINT_ARGS)\n", "\n", "saved_workflow_data = workflow_endpoints.create(config=workflow.to_dict(), owner_id=ACCOUNT_ID)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -385,16 +395,16 @@ }, { "cell_type": "code", - "execution_count": null, "id": "26", "metadata": {}, - "outputs": [], "source": [ "cluster_config = next(iter(json.loads(os.getenv(\"CLUSTERS\"))), {})\n", "queue_configs = cluster_config.get(\"queues\", [])\n", "\n", "CLUSTER_NAME = cluster_config.get(\"displayName\", \"cluster-001\")" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -406,10 +416,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "28", "metadata": {}, - "outputs": [], "source": [ "from exabyte_api_client.endpoints.jobs import JobEndpoints\n", "\n", @@ -422,7 +430,9 @@ " time_limit=\"00:30:00\",\n", " cluster=CLUSTER_NAME\n", ")" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -434,10 +444,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "30", "metadata": {}, - "outputs": [], "source": [ "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", "from exabyte_api_client.endpoints.projects import ProjectEndpoints\n", @@ -455,14 +463,14 @@ "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\") # for name to be found easily\n", "\n", "JOB_NAME = f\"Band Gap {timestamp}\"" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "id": "31", "metadata": {}, - "outputs": [], "source": [ "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", @@ -479,7 +487,9 @@ "jobs = dict_to_namespace(jobs_response)\n", "\n", "display_JSON(jobs_response)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -491,10 +501,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "33", "metadata": {}, - "outputs": [], "source": [ "# Submit each job (assuming jobs is a list of job objects)\n", "if isinstance(jobs, list):\n", @@ -503,14 +511,14 @@ "else:\n", " # If jobs is a single job object\n", " job_endpoints.submit(jobs._id)\n" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "id": "34", "metadata": {}, - "outputs": [], "source": [ "from utils.generic import wait_for_jobs_to_finish\n", "\n", @@ -521,7 +529,9 @@ " job_ids = [jobs._id]\n", "\n", "wait_for_jobs_to_finish(job_endpoints, job_ids, poll_interval=60)" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -533,10 +543,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "36", "metadata": {}, - "outputs": [], "source": [ "import re\n", "from utils.generic import get_property_by_subworkflow_and_unit_indicies\n", @@ -567,7 +575,9 @@ " \"band_gap_indirect\": band_gap_indirect,\n", " }\n", " )" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "markdown", @@ -579,10 +589,8 @@ }, { "cell_type": "code", - "execution_count": null, "id": "38", "metadata": {}, - "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", "import pandas as pd\n", @@ -599,15 +607,17 @@ "plt.legend(frameon=False, loc=\"best\")\n", "plt.tight_layout()\n", "plt.show()" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "id": "39", "metadata": {}, + "source": [], "outputs": [], - "source": [] + "execution_count": null } ], "metadata": { diff --git a/utils/generic.py b/utils/generic.py index 8c903265..818e9ae0 100644 --- a/utils/generic.py +++ b/utils/generic.py @@ -5,18 +5,20 @@ import time import urllib.request import uuid +from types import SimpleNamespace from typing import List, Union +from IPython.display import HTML, display from exabyte_api_client.endpoints.bank_workflows import BankWorkflowEndpoints from exabyte_api_client.endpoints.jobs import JobEndpoints from exabyte_api_client.endpoints.properties import PropertiesEndpoints -from IPython.display import HTML, display from pandas import DataFrame from pandas.io.formats.style import Styler from tabulate import tabulate from . import settings + # GENERIC UTILITIES @@ -223,3 +225,13 @@ def display_JSON( ) else: print(json.dumps(obj, indent=4)) + + +# Helper function to convert dictionaries to SimpleNamespace objects for dot notation access +def dict_to_namespace(obj): + if isinstance(obj, dict): + return SimpleNamespace(**{k: dict_to_namespace(v) for k, v in obj.items()}) + elif isinstance(obj, list): + return [dict_to_namespace(item) for item in obj] + else: + return obj From 15d86724bcf9b91ccab76c06fd9bd0a435d30601 Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Thu, 11 Dec 2025 21:33:37 -0800 Subject: [PATCH 22/26] update: move functions to utils --- .../workflows/run_bandgap_workflow_min.ipynb | 282 +++++++++--------- utils/api.py | 65 ++++ 2 files changed, 198 insertions(+), 149 deletions(-) create mode 100644 utils/api.py diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 519f1c0f..598bb257 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -32,8 +32,10 @@ }, { "cell_type": "code", + "execution_count": null, "id": "2", "metadata": {}, + "outputs": [], "source": [ "import sys\n", "\n", @@ -45,13 +47,11 @@ " from mat3ra.utils.jupyterlite.packages import install_packages\n", "\n", " await install_packages(\"api_examples\")" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "4", + "id": "3", "metadata": {}, "source": [ "## 2. Log in to get the API token" @@ -59,8 +59,10 @@ }, { "cell_type": "code", - "id": "5", + "execution_count": null, + "id": "4", "metadata": {}, + "outputs": [], "source": [ "ACCOUNT_ID = \"ACCOUNT_ID\"\n", "AUTH_TOKEN = \"AUTH_TOKEN\"\n", @@ -83,13 +85,11 @@ " CLUSTERS=json.dumps(apiConfig.get(\"clusters\", [])),\n", " )\n", " )" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "6", + "id": "5", "metadata": {}, "source": [ "## 3. Create material\n", @@ -98,21 +98,21 @@ }, { "cell_type": "code", - "id": "7", + "execution_count": null, + "id": "6", "metadata": {}, + "outputs": [], "source": [ "from utils.visualize import visualize_materials as visualize\n", "from utils.jupyterlite import load_material_from_folder\n", "\n", "material = load_material_from_folder(\"../uploads\", \"MoS2(001)-MoS2(001), Interface\")\n", "visualize(material)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "8", + "id": "7", "metadata": {}, "source": [ "### 3.2. Save material to the platform" @@ -120,29 +120,24 @@ }, { "cell_type": "code", - "id": "9", + "execution_count": null, + "id": "8", "metadata": {}, + "outputs": [], "source": [ - "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", - "from utils.generic import display_JSON, dict_to_namespace\n", - "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", + "from utils.settings import ACCOUNT_ID\n", + "from utils.generic import dict_to_namespace\n", + "from utils.api import create_material\n", "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", - "endpoint = MaterialEndpoints(*ENDPOINT_ARGS)\n", "\n", - "RAW_CONFIG = material.to_dict()\n", - "fields = [\"name\", \"lattice\", \"basis\"]\n", - "CONFIG = {key: RAW_CONFIG[key] for key in fields}\n", - "\n", - "saved_material_response = endpoint.create(CONFIG, OWNER_ID)\n", + "saved_material_response = create_material(material, OWNER_ID)\n", "saved_material = dict_to_namespace(saved_material_response)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "10", + "id": "9", "metadata": {}, "source": [ "### 3.3. Get material id" @@ -150,18 +145,18 @@ }, { "cell_type": "code", - "id": "11", + "execution_count": null, + "id": "10", "metadata": {}, + "outputs": [], "source": [ "material_id = saved_material.get(\"_id\")\n", "print(\"Material IDs:\", material_id)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "12", + "id": "11", "metadata": {}, "source": [ "## 5. Create workflow and set its parameters\n", @@ -169,8 +164,11 @@ ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.standata.applications import ApplicationStandata\n", "from mat3ra.ade.application import Application\n", @@ -178,23 +176,20 @@ "# Get Applications list (with versions, build)\n", "apps_list = ApplicationStandata.list_all()\n", "# returns apps_list[0] = [{\"name\" : \"espresso\", \"version\": \"7.2\", \"build\": \"GNU\"}]" - ], - "id": "66051fbafd8c1e87", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], "source": [ "app_config = ApplicationStandata.get_by_name_first_match(\"espresso\")\n", "# returns name, version, build config\n", "app = Application(**app_config)\n", "app.name" - ], - "id": "e661138b8755f3ab", - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -206,8 +201,10 @@ }, { "cell_type": "code", + "execution_count": null, "id": "15", "metadata": {}, + "outputs": [], "source": [ "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", @@ -221,9 +218,7 @@ "# View workflow to understand its structure\n", "workflow\n", "# visualize_workflow(workflow)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -235,16 +230,16 @@ }, { "cell_type": "code", + "execution_count": null, "id": "17", "metadata": {}, + "outputs": [], "source": [ "workflow.add_relaxation()\n", "# visualize_workflow(workflow)\n", "# Relaxation subworkflow is added as the first subworkflow\n", "print(workflow.subworkflows[0].name, \"\\n\", workflow.subworkflows[1].name)" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -256,8 +251,10 @@ }, { "cell_type": "code", + "execution_count": null, "id": "19", "metadata": {}, + "outputs": [], "source": [ "from mat3ra.standata.model_tree import ModelTreeStandata\n", "\n", @@ -277,9 +274,7 @@ "swf_0.model = model\n", "swf_1.model = model\n", "model" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", @@ -291,8 +286,11 @@ ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "21", + "metadata": {}, + "outputs": [], "source": [ "from mat3ra.wode.context.providers import PointsGridDataProvider\n", "\n", @@ -305,39 +303,42 @@ "kgrid_context_provider_relax = PointsGridDataProvider(dimensions=kgrid_scf)\n", "kgrid_context_provider_scf = PointsGridDataProvider(dimensions=kgrid_scf)\n", "kgrid_context_provider_nscf = PointsGridDataProvider(dimensions=kgrid_nscf)" - ], - "id": "fcf79eceb2b43083", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "#### 5.5.2. Get new context data and set it to workflow units", - "id": "d4185422ad5334dd" + "id": "22", + "metadata": {}, + "source": [ + "#### 5.5.2. Get new context data and set it to workflow units" + ] }, { - "metadata": {}, "cell_type": "code", + "execution_count": null, + "id": "23", + "metadata": {}, + "outputs": [], "source": [ "new_context_relax = kgrid_context_provider_relax.get_data()\n", "new_context_scf = kgrid_context_provider_scf.get_data()\n", "new_context_nscf = kgrid_context_provider_nscf.get_data()" - ], - "id": "f90491e54e2aa731", - "outputs": [], - "execution_count": null + ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "#### 5.5.3. Modify workflow units with new context", - "id": "624fdb2666c705d7" + "id": "24", + "metadata": {}, + "source": [ + "#### 5.5.3. Modify workflow units with new context" + ] }, { "cell_type": "code", - "id": "22", + "execution_count": null, + "id": "25", "metadata": {}, + "outputs": [], "source": [ "# Get workflow's specific unit that needs to be modified\n", "# Option 1: search is done by unit name regex across the entire workflow\n", @@ -357,13 +358,11 @@ "# Option 2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "23", + "id": "26", "metadata": {}, "source": [ "### 5.6. Save workflow to collection" @@ -371,22 +370,20 @@ }, { "cell_type": "code", - "id": "24", + "execution_count": null, + "id": "27", "metadata": {}, + "outputs": [], "source": [ - "from exabyte_api_client import WorkflowEndpoints\n", - "from utils.settings import ENDPOINT_ARGS, ACCOUNT_ID\n", - "\n", - "workflow_endpoints = WorkflowEndpoints(*ENDPOINT_ARGS)\n", + "from utils.settings import ACCOUNT_ID\n", + "from utils.api import create_workflow\n", "\n", - "saved_workflow_data = workflow_endpoints.create(config=workflow.to_dict(), owner_id=ACCOUNT_ID)" - ], - "outputs": [], - "execution_count": null + "saved_workflow_data = create_workflow(workflow, ACCOUNT_ID)" + ] }, { "cell_type": "markdown", - "id": "25", + "id": "28", "metadata": {}, "source": [ "## 6. Create the compute configuration\n", @@ -395,20 +392,20 @@ }, { "cell_type": "code", - "id": "26", + "execution_count": null, + "id": "29", "metadata": {}, + "outputs": [], "source": [ "cluster_config = next(iter(json.loads(os.getenv(\"CLUSTERS\"))), {})\n", "queue_configs = cluster_config.get(\"queues\", [])\n", "\n", "CLUSTER_NAME = cluster_config.get(\"displayName\", \"cluster-001\")" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "27", + "id": "30", "metadata": {}, "source": [ "### 6.2. Create compute configuration" @@ -416,10 +413,13 @@ }, { "cell_type": "code", - "id": "28", + "execution_count": null, + "id": "31", "metadata": {}, + "outputs": [], "source": [ "from exabyte_api_client.endpoints.jobs import JobEndpoints\n", + "from utils.settings import ENDPOINT_ARGS\n", "\n", "exabyte_jobs_endpoint = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", @@ -430,13 +430,11 @@ " time_limit=\"00:30:00\",\n", " cluster=CLUSTER_NAME\n", ")" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "29", + "id": "32", "metadata": {}, "source": [ "## 7. Create the job with material and workflow configuration" @@ -444,37 +442,37 @@ }, { "cell_type": "code", - "id": "30", + "execution_count": null, + "id": "33", "metadata": {}, + "outputs": [], "source": [ - "from exabyte_api_client.endpoints.materials import MaterialEndpoints\n", - "from exabyte_api_client.endpoints.projects import ProjectEndpoints\n", - "\n", "from datetime import datetime\n", "\n", - "# TODO: Add helper to AX utils: create_material(material, owner_id: Optional)\n", - "material_endpoints = MaterialEndpoints(*ENDPOINT_ARGS)\n", + "from utils.settings import ACCOUNT_ID\n", + "from utils.api import get_default_project\n", + "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "\n", - "# Add helper to AX utils: create_workflow(workflow, owner_id: Optional)\n", - "project_endpoints = ProjectEndpoints(*ENDPOINT_ARGS)\n", - "project_id = project_endpoints.list({\"isDefault\": True, \"owner._id\": OWNER_ID})[0][\"_id\"]\n", + "project_id = get_default_project(OWNER_ID)\n", "\n", - "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\") # for name to be found easily\n", + "timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M\")\n", "\n", "JOB_NAME = f\"Band Gap {timestamp}\"" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", - "id": "31", + "execution_count": null, + "id": "34", "metadata": {}, + "outputs": [], "source": [ + "from utils.generic import display_JSON\n", + "\n", "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", - "jobs_response = job_endpoints.create_by_ids(\n", + "job_response = job_endpoints.create_by_ids(\n", " materials=material,\n", " workflow_id=workflow[\"_id\"],\n", " project_id=project_id,\n", @@ -484,16 +482,14 @@ ")\n", "\n", "# Convert jobs list to SimpleNamespace objects for dot notation access\n", - "jobs = dict_to_namespace(jobs_response)\n", + "job = dict_to_namespace(job_response)\n", "\n", - "display_JSON(jobs_response)" - ], - "outputs": [], - "execution_count": null + "display_JSON(job_response)" + ] }, { "cell_type": "markdown", - "id": "32", + "id": "35", "metadata": {}, "source": [ "## 8. Submit the job and monitor the status" @@ -501,41 +497,29 @@ }, { "cell_type": "code", - "id": "33", + "execution_count": null, + "id": "36", "metadata": {}, - "source": [ - "# Submit each job (assuming jobs is a list of job objects)\n", - "if isinstance(jobs, list):\n", - " for job in jobs:\n", - " job_endpoints.submit(job._id)\n", - "else:\n", - " # If jobs is a single job object\n", - " job_endpoints.submit(jobs._id)\n" - ], "outputs": [], - "execution_count": null + "source": [ + "job_endpoints.submit(job._id)\n" + ] }, { "cell_type": "code", - "id": "34", + "execution_count": null, + "id": "37", "metadata": {}, + "outputs": [], "source": [ "from utils.generic import wait_for_jobs_to_finish\n", "\n", - "# Extract job IDs using dot notation\n", - "if isinstance(jobs, list):\n", - " job_ids = [job._id for job in jobs]\n", - "else:\n", - " job_ids = [jobs._id]\n", - "\n", - "wait_for_jobs_to_finish(job_endpoints, job_ids, poll_interval=60)" - ], - "outputs": [], - "execution_count": null + "wait_for_jobs_to_finish(job_endpoints, [job._id], poll_interval=60)" + ] }, { "cell_type": "markdown", - "id": "35", + "id": "38", "metadata": {}, "source": [ "## 9. Retrieve results" @@ -543,8 +527,10 @@ }, { "cell_type": "code", - "id": "36", + "execution_count": null, + "id": "39", "metadata": {}, + "outputs": [], "source": [ "import re\n", "from utils.generic import get_property_by_subworkflow_and_unit_indicies\n", @@ -575,13 +561,11 @@ " \"band_gap_indirect\": band_gap_indirect,\n", " }\n", " )" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "markdown", - "id": "37", + "id": "40", "metadata": {}, "source": [ "## 10. Display results" @@ -589,8 +573,10 @@ }, { "cell_type": "code", - "id": "38", + "execution_count": null, + "id": "41", "metadata": {}, + "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", "import pandas as pd\n", @@ -607,17 +593,15 @@ "plt.legend(frameon=False, loc=\"best\")\n", "plt.tight_layout()\n", "plt.show()" - ], - "outputs": [], - "execution_count": null + ] }, { "cell_type": "code", - "id": "39", + "execution_count": null, + "id": "42", "metadata": {}, - "source": [], "outputs": [], - "execution_count": null + "source": [] } ], "metadata": { diff --git a/utils/api.py b/utils/api.py new file mode 100644 index 00000000..0efeed07 --- /dev/null +++ b/utils/api.py @@ -0,0 +1,65 @@ +from typing import Any, Dict, Optional + +from exabyte_api_client.endpoints.materials import MaterialEndpoints +from exabyte_api_client.endpoints.projects import ProjectEndpoints +from exabyte_api_client.endpoints.workflows import WorkflowEndpoints + +from .settings import ACCOUNT_ID, ENDPOINT_ARGS + + +def create_material(material: Any, owner_id: Optional[str] = None) -> Dict[str, Any]: + """ + Creates a material on the platform. + + Args: + material: Material object with a to_dict() method + owner_id: Optional owner ID. Defaults to ACCOUNT_ID from settings + + Returns: + dict: Created material response from the API + """ + endpoint = MaterialEndpoints(*ENDPOINT_ARGS) + owner = owner_id or ACCOUNT_ID + + raw_config = material.to_dict() + fields = ["name", "lattice", "basis"] + config = {key: raw_config[key] for key in fields} + + return endpoint.create(config, owner) + + +def create_workflow(workflow: Any, owner_id: Optional[str] = None) -> Dict[str, Any]: + """ + Creates a workflow on the platform. + + Args: + workflow: Workflow object with a to_dict() method + owner_id: Optional owner ID. Defaults to ACCOUNT_ID from settings + + Returns: + dict: Created workflow response from the API + """ + endpoint = WorkflowEndpoints(*ENDPOINT_ARGS) + owner = owner_id or ACCOUNT_ID + + config = workflow.to_dict() + + return endpoint.create(config, owner) + + +def get_default_project(owner_id: Optional[str] = None) -> str: + """ + Gets the default project ID for an owner. + + Args: + owner_id: Optional owner ID. Defaults to ACCOUNT_ID from settings + + Returns: + str: Default project ID + """ + endpoint = ProjectEndpoints(*ENDPOINT_ARGS) + owner = owner_id or ACCOUNT_ID + + projects = endpoint.list({"isDefault": True, "owner._id": owner}) + + return projects[0]["_id"] From c244989788c2a5a393d9e973329dc3f138c2daee Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Fri, 12 Dec 2025 12:57:34 -0800 Subject: [PATCH 23/26] update: add simple visualizer --- .../workflows/run_bandgap_workflow_min.ipynb | 62 +++++++++---------- utils/visualize.py | 17 +++++ 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 598bb257..c2100f47 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -126,7 +126,7 @@ "outputs": [], "source": [ "from utils.settings import ACCOUNT_ID\n", - "from utils.generic import dict_to_namespace\n", + "from utils.generic import dict_to_namespace, display_JSON\n", "from utils.api import create_material\n", "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", @@ -208,16 +208,15 @@ "source": [ "from mat3ra.standata.workflows import WorkflowStandata\n", "from mat3ra.wode.workflows import Workflow\n", + "from utils.visualize import visualize_workflow\n", "\n", - "# from utils.visualize import visualize_workflow\n", - "\n", + "# TODO: adjust Standata to search for human readable `name`, or regex, or filename\n", "# Search WF by name and application\n", - "workflow_config = WorkflowStandata.filter_by_application(app.name).get_by_name_first_match(\"band_gap\")\n", + "workflow_config = WorkflowStandata.filter_by_application(app.name).get_by_name_first_match(\"band_gap.json\")\n", "workflow = Workflow.create(workflow_config)\n", "\n", "# View workflow to understand its structure\n", - "workflow\n", - "# visualize_workflow(workflow)" + "visualize_workflow(workflow)" ] }, { @@ -235,10 +234,11 @@ "metadata": {}, "outputs": [], "source": [ + "from utils.visualize import visualize_workflow\n", + "\n", "workflow.add_relaxation()\n", - "# visualize_workflow(workflow)\n", "# Relaxation subworkflow is added as the first subworkflow\n", - "print(workflow.subworkflows[0].name, \"\\n\", workflow.subworkflows[1].name)" + "visualize_workflow(workflow)" ] }, { @@ -295,9 +295,8 @@ "from mat3ra.wode.context.providers import PointsGridDataProvider\n", "\n", "# Values from publication\n", - "kgrid_scf = [6, 6, 1]\n", + "kgrid_relax = kgrid_scf = [6, 6, 1]\n", "kgrid_nscf = [12, 12, 1]\n", - "kgrid_relax = kgrid_scf\n", "\n", "# In future: helper to workflow.set_context_to_unit_by_name_regex(context_provider, unit_name_regex)\n", "kgrid_context_provider_relax = PointsGridDataProvider(dimensions=kgrid_scf)\n", @@ -357,7 +356,8 @@ "\n", "# Option 2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", - "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n" + "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n", + "visualize_workflow(workflow)" ] }, { @@ -539,28 +539,24 @@ "property_endpoints = PropertiesEndpoints(*ENDPOINT_ARGS)\n", "\n", "results = []\n", - "# Iterate in general, but we have only 1 material here\n", - "for material in [saved_material]:\n", - " # Find the job that matches this material - fix typo: _meterial -> _material\n", - " job = next((job for job in jobs if job._material._id == material._id))\n", - " final_structure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"final_structure\", job, 0, 0)[\n", - " \"data\"\n", - " ]\n", - " pressure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"pressure\", job, 0, 0)[\"data\"][\"value\"]\n", - "\n", - " # Use dot notation to access workflow property\n", - " unit_flowchart_id = Workflow(job.workflow).get_unit_by_name(name=\"pw_scf\").flowchart_id\n", - " band_gap_direct = property_endpoints.get_direct_band_gap(job._id, unit_flowchart_id)\n", - " band_gap_indirect = property_endpoints.get_indirect_band_gap(job._id, unit_flowchart_id)\n", - "\n", - " results.append(\n", - " {\n", - " \"material_id\": material._id,\n", - " \"angle_deg\": re.search(r\"(\\d+(?:\\.\\d+)?) degrees\", material.name).group(1),\n", - " \"band_gap_direct\": band_gap_direct,\n", - " \"band_gap_indirect\": band_gap_indirect,\n", - " }\n", - " )" + "final_structure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"final_structure\", job, 0, 0)[\n", + " \"data\"\n", + "]\n", + "pressure = get_property_by_subworkflow_and_unit_indicies(property_endpoints, \"pressure\", job, 0, 0)[\"data\"][\"value\"]\n", + "\n", + "# Use dot notation to access workflow property\n", + "unit_flowchart_id = Workflow(job.workflow).get_unit_by_name(name=\"pw_scf\").flowchart_id\n", + "band_gap_direct = property_endpoints.get_direct_band_gap(job._id, unit_flowchart_id)\n", + "band_gap_indirect = property_endpoints.get_indirect_band_gap(job._id, unit_flowchart_id)\n", + "\n", + "results.append(\n", + " {\n", + " \"material_id\": material._id,\n", + " \"angle_deg\": re.search(r\"(\\d+(?:\\.\\d+)?) degrees\", material.name).group(1),\n", + " \"band_gap_direct\": band_gap_direct,\n", + " \"band_gap_indirect\": band_gap_indirect,\n", + " }\n", + ")" ] }, { diff --git a/utils/visualize.py b/utils/visualize.py index c76e81f7..d2d111f4 100644 --- a/utils/visualize.py +++ b/utils/visualize.py @@ -12,6 +12,8 @@ from mat3ra.utils.array import convert_to_array_if_not from pydantic import BaseModel +from .generic import display_JSON + class ViewersEnum(str, Enum): wave = "wave" @@ -255,3 +257,18 @@ def visualize_materials( items.append((image_data, image_title)) display(create_responsive_image_grid(items)) + + +def visualize_workflow(workflow, level: int = 2) -> None: + """ + Visualize a workflow by displaying its JSON configuration. + + Args: + workflow: Workflow object with a to_dict() method + level: Expansion level for the JSON viewer (default: 2) + + Returns: + None + """ + workflow_config = workflow.to_dict() + display_JSON(workflow_config, level=level) From c3adf545abdf3a08e136d81e11134d39bf7d3c1c Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Sun, 14 Dec 2025 21:01:55 -0800 Subject: [PATCH 24/26] update: use default compute --- .../workflows/run_bandgap_workflow_min.ipynb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index c2100f47..907f08a1 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -424,10 +424,6 @@ "exabyte_jobs_endpoint = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", "compute = exabyte_jobs_endpoint.get_compute(\n", - " ppn=8,\n", - " queue=\"OR8\",\n", - " nodes=1,\n", - " time_limit=\"00:30:00\",\n", " cluster=CLUSTER_NAME\n", ")" ] From d1004b89b070f72b3fd92008e31e8e3f755cae3c Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 15 Dec 2025 17:24:44 -0800 Subject: [PATCH 25/26] chore: import AX --- .../materials_designer/workflows/run_bandgap_workflow_min.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 907f08a1..50238e75 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -42,7 +42,7 @@ "if sys.platform == \"emscripten\":\n", " import micropip\n", "\n", - " await micropip.install(\"mat3ra-api-examples\", deps=False)\n", + " await micropip.install(\"https://exabyte-io.github.io/api-examples/mat3ra_api_examples-0.1.dev1+gc24498978-py3-none-any.whl\", deps=False)\n", " await micropip.install(\"mat3ra-utils\")\n", " from mat3ra.utils.jupyterlite.packages import install_packages\n", "\n", From cd8ce0b0babbda37be6e55790ebe35ecd5a791fb Mon Sep 17 00:00:00 2001 From: VsevolodX Date: Mon, 15 Dec 2025 18:16:51 -0800 Subject: [PATCH 26/26] update: fixes to run nb --- config.yml | 2 ++ other/materials_designer/uploads/0-Ni.json | 2 +- .../workflows/run_bandgap_workflow_min.ipynb | 13 ++++++------- utils/api.py | 16 +++++++++++----- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/config.yml b/config.yml index 7358d270..e10322fe 100644 --- a/config.yml +++ b/config.yml @@ -66,3 +66,5 @@ notebooks: packages_common: - mat3ra-standata - exabyte-api-client + - mat3ra-ade + - mat3ra-wode diff --git a/other/materials_designer/uploads/0-Ni.json b/other/materials_designer/uploads/0-Ni.json index 2adc9475..cd92b2d0 100644 --- a/other/materials_designer/uploads/0-Ni.json +++ b/other/materials_designer/uploads/0-Ni.json @@ -54,7 +54,7 @@ }, "external": { "id": "mp-23", - "source": "Materials Project", + "source": "MaterialsProject", "doi": "10.17188/1199153", "url": "https://next-gen.materialsproject.org/materials/mp-23", "origin": true diff --git a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb index 50238e75..73b5507c 100644 --- a/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb +++ b/other/materials_designer/workflows/run_bandgap_workflow_min.ipynb @@ -131,8 +131,7 @@ "\n", "OWNER_ID = os.getenv(\"ORGANIZATION_ID\") or ACCOUNT_ID\n", "\n", - "saved_material_response = create_material(material, OWNER_ID)\n", - "saved_material = dict_to_namespace(saved_material_response)" + "saved_material_data = create_material(material, OWNER_ID)" ] }, { @@ -150,8 +149,7 @@ "metadata": {}, "outputs": [], "source": [ - "material_id = saved_material.get(\"_id\")\n", - "print(\"Material IDs:\", material_id)" + "print(\"Material ID:\", saved_material_data[\"_id\"])" ] }, { @@ -357,7 +355,8 @@ "# Option 2: set by unit flowchart id and new unit object\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_scf.flowchart_id, new_unit=unit_to_modify_scf)\n", "workflow.set_unit(unit_flowchart_id=unit_to_modify_nscf.flowchart_id, new_unit=unit_to_modify_nscf)\n", - "visualize_workflow(workflow)" + "visualize_workflow(workflow)\n", + "workflow.to_dict()" ] }, { @@ -469,8 +468,8 @@ "job_endpoints = JobEndpoints(*ENDPOINT_ARGS)\n", "\n", "job_response = job_endpoints.create_by_ids(\n", - " materials=material,\n", - " workflow_id=workflow[\"_id\"],\n", + " materials=[saved_material_data],\n", + " workflow_id=saved_workflow_data[\"_id\"],\n", " project_id=project_id,\n", " prefix=JOB_NAME,\n", " owner_id=OWNER_ID,\n", diff --git a/utils/api.py b/utils/api.py index 0efeed07..652003c3 100644 --- a/utils/api.py +++ b/utils/api.py @@ -1,8 +1,9 @@ -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Union from exabyte_api_client.endpoints.materials import MaterialEndpoints from exabyte_api_client.endpoints.projects import ProjectEndpoints from exabyte_api_client.endpoints.workflows import WorkflowEndpoints +from mat3ra.wode.workflows import Workflow from .settings import ACCOUNT_ID, ENDPOINT_ARGS @@ -21,14 +22,17 @@ def create_material(material: Any, owner_id: Optional[str] = None) -> Dict[str, endpoint = MaterialEndpoints(*ENDPOINT_ARGS) owner = owner_id or ACCOUNT_ID - raw_config = material.to_dict() + if isinstance(material, dict): + raw_config = material + else: + raw_config = material.to_dict() fields = ["name", "lattice", "basis"] config = {key: raw_config[key] for key in fields} return endpoint.create(config, owner) -def create_workflow(workflow: Any, owner_id: Optional[str] = None) -> Dict[str, Any]: +def create_workflow(workflow: Union[Workflow, Dict], owner_id: Optional[str] = None) -> Dict[str, Any]: """ Creates a workflow on the platform. @@ -41,8 +45,10 @@ def create_workflow(workflow: Any, owner_id: Optional[str] = None) -> Dict[str, """ endpoint = WorkflowEndpoints(*ENDPOINT_ARGS) owner = owner_id or ACCOUNT_ID - - config = workflow.to_dict() + if isinstance(workflow, dict): + config = workflow + else: + config = workflow.to_dict() return endpoint.create(config, owner)