-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(PR #50) Adding support for new cycling workflow
This PR adds frontend support for the new cycling workflow. A new protocol (multi-)selector has been added, with the previous custom protocol widget moved to a "create" tab allowing users to create/save new protocols to be selected from the "select" tab. The tomato settings widget was modified to support multiple protocols, each with its own settings/monitors. The experiment builder was modified w.r.t. these changes. Finally, the submission process was modified to support the above features, including a newly improved input preview section providing a quick overview of selected protocols/settings/monitoring.
- Loading branch information
Showing
9 changed files
with
1,133 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,3 +130,4 @@ dmypy.json | |
|
||
# Project-specific | ||
.aurora-*.ipynb | ||
*.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,167 @@ | ||
# from time import sleep | ||
from typing import Dict, List | ||
|
||
import aiida | ||
from aiida.engine import submit | ||
from aiida.manage.configuration import load_profile | ||
from aiida.orm import Dict, load_code, load_group | ||
from aiida.orm import Dict as AiiDADict | ||
from aiida.orm import List as AiiDAList | ||
from aiida.orm import load_code, load_group | ||
from aiida_aurora.data import (BatterySampleData, CyclingSpecsData, | ||
TomatoSettingsData) | ||
from aiida_aurora.schemas.battery import BatterySample | ||
from aiida_aurora.schemas.cycling import ElectroChemSequence | ||
from aiida_aurora.schemas.dgbowl import Tomato_0p2 | ||
from aiida_aurora.workflows import CyclingSequenceWorkChain | ||
|
||
load_profile() | ||
|
||
BatterySampleData = aiida.plugins.DataFactory('aurora.batterysample') | ||
CyclingSpecsData = aiida.plugins.DataFactory('aurora.cyclingspecs') | ||
TomatoSettingsData = aiida.plugins.DataFactory('aurora.tomatosettings') | ||
BatteryCyclerExperiment = aiida.plugins.CalculationFactory('aurora.cycler') | ||
SAMPLES_GROUP = load_group("BatterySamples") | ||
PROTOCOLS_GROUP = load_group("CyclingSpecs") | ||
WORKFLOWS_GROUP = load_group("WorkChains") | ||
|
||
GROUP_SAMPLES = load_group("BatterySamples") | ||
GROUP_METHODS = load_group("CyclingSpecs") | ||
GROUP_CALCJOBS = load_group("CalcJobs") | ||
|
||
|
||
def submit_experiment(sample, | ||
method, | ||
tomato_settings, | ||
monitor_settings, | ||
code_name, | ||
sample_node_label="", | ||
method_node_label="", | ||
calcjob_node_label=""): | ||
def submit_experiment( | ||
sample: BatterySample, | ||
protocols: List[ElectroChemSequence], | ||
settings: List[Tomato_0p2], | ||
monitors: List[dict], | ||
code_name: str, | ||
sample_node_label="", | ||
protocol_node_label="", | ||
workchain_node_label="", | ||
) -> CyclingSequenceWorkChain: | ||
""" | ||
sample : `aiida_aurora.schemas.battery.BatterySample` | ||
method : `aiida_aurora.schemas.cycling.ElectroChemSequence` | ||
tomato_settings : `aiida_aurora.schemas.dgbowl_schemas.Tomato_0p2` | ||
""" | ||
|
||
inputs = get_inputs( | ||
sample, | ||
sample_node_label, | ||
code_name, | ||
protocols, | ||
settings, | ||
monitors, | ||
protocol_node_label, | ||
) | ||
|
||
return submit_job(inputs, workchain_node_label) | ||
|
||
|
||
def get_inputs( | ||
sample: BatterySample, | ||
sample_node_label: str, | ||
code_name: str, | ||
protocols: List[ElectroChemSequence], | ||
settings: List[Tomato_0p2], | ||
monitors: List[dict], | ||
protocol_node_label: str, | ||
) -> dict: | ||
"""Prepare input dictionaries for workflow.""" | ||
|
||
inputs = { | ||
"battery_sample": build_sample_node(sample, sample_node_label), | ||
"tomato_code": load_code(code_name), | ||
"protocol_order": AiiDAList(), | ||
"protocols": {}, | ||
"control_settings": {}, | ||
"monitor_settings": {}, | ||
} | ||
|
||
# push cycler locking (if requested) to final workflow step | ||
if any(not ts.unlock_when_done for ts in settings): | ||
for ts in settings: | ||
ts.unlock_when_done = True | ||
settings[-1].unlock_when_done = False | ||
|
||
for protocol, settings, protocol_monitors in zip( | ||
protocols, | ||
settings, | ||
monitors, | ||
): | ||
|
||
step = protocol.name | ||
|
||
inputs["protocol_order"].append(step) | ||
|
||
inputs["protocols"][step] = build_protocol_node( | ||
protocol, | ||
protocol_node_label, | ||
) | ||
|
||
inputs["control_settings"][step] = build_settings_node(settings) | ||
|
||
inputs["monitor_settings"][step] = build_monitors_input( | ||
protocol, | ||
protocol_monitors, | ||
) | ||
|
||
return inputs | ||
|
||
|
||
def build_sample_node( | ||
sample: BatterySample, | ||
sample_node_label: str, | ||
) -> BatterySampleData: | ||
"""Construct an AiiDA data node from battery sample data.""" | ||
sample_node = BatterySampleData(sample.dict()) | ||
if sample_node_label: | ||
sample_node.label = sample_node_label | ||
sample_node.label = sample_node_label | ||
sample_node.store() | ||
GROUP_SAMPLES.add_nodes(sample_node) | ||
SAMPLES_GROUP.add_nodes(sample_node) | ||
return sample_node | ||
|
||
|
||
def build_protocol_node( | ||
protocol: ElectroChemSequence, | ||
protocol_node_label: str, | ||
) -> CyclingSpecsData: | ||
"""Construct an AiiDA data node from cycling protocol data.""" | ||
protocol_node = CyclingSpecsData(protocol.dict()) | ||
protocol_node.label = protocol_node_label | ||
protocol_node.store() | ||
PROTOCOLS_GROUP.add_nodes(protocol_node) | ||
return protocol_node | ||
|
||
|
||
method_node = CyclingSpecsData(method.dict()) | ||
if method_node_label: | ||
method_node.label = method_node_label | ||
method_node.store() | ||
GROUP_METHODS.add_nodes(method_node) | ||
def build_settings_node(settings: Tomato_0p2) -> TomatoSettingsData: | ||
"""Construct an AiiDA data node from tomato settings data.""" | ||
settings_node = TomatoSettingsData(settings.dict()) | ||
settings_node.label = "" | ||
settings_node.store() | ||
return settings_node | ||
|
||
tomato_settings_node = TomatoSettingsData(tomato_settings.dict()) | ||
tomato_settings_node.label = "" # TODO? write default name generator - e.g. "tomato-True-monitor_600" | ||
tomato_settings_node.store() | ||
|
||
code = load_code(code_name) | ||
def build_monitors_input( | ||
protocol: ElectroChemSequence, | ||
protocol_monitors: Dict[str, dict], | ||
) -> dict: | ||
"""Construct a dictionary of `Dict` monitors for the protocol.""" | ||
|
||
builder = BatteryCyclerExperiment.get_builder() | ||
builder.battery_sample = sample_node | ||
builder.code = code | ||
builder.protocol = method_node | ||
builder.control_settings = tomato_settings_node | ||
monitors: Dict[str, dict] = {} | ||
|
||
if monitor_settings: | ||
for label, monitor_settings in protocol_monitors.items(): | ||
refresh_rate = monitor_settings.pop("refresh_rate", 600) | ||
builder.monitors = { | ||
"capacity": | ||
Dict({ | ||
monitor_name = f"{protocol.name}_{label}" | ||
monitors[monitor_name] = AiiDADict( | ||
dict={ | ||
"entry_point": "aurora.monitors.capacity_threshold", | ||
"minimum_poll_interval": refresh_rate, | ||
"kwargs": { | ||
"settings": monitor_settings, | ||
"filename": "snapshot.json", | ||
}, | ||
}), | ||
} | ||
}) | ||
|
||
job = submit(builder) | ||
job.label = calcjob_node_label | ||
print(f"Job <{job.pk}> submitted to AiiDA...") | ||
GROUP_CALCJOBS.add_nodes(job) | ||
return monitors | ||
|
||
if monitor_settings: | ||
job.set_extra('monitored', True) | ||
else: | ||
job.set_extra('monitored', False) | ||
|
||
return job | ||
def submit_job( | ||
inputs: dict, | ||
workchain_node_label: str, | ||
) -> CyclingSequenceWorkChain: | ||
"""docstring""" | ||
workchain = submit(CyclingSequenceWorkChain, **inputs) | ||
workchain.label = workchain_node_label | ||
print(f"Workflow <{workchain.pk}> submitted to AiiDA...") | ||
WORKFLOWS_GROUP.add_nodes(workchain) | ||
return workchain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
from .custom import CyclingCustom | ||
from .selector import ProtocolSelector | ||
from .standard import CyclingStandard | ||
|
||
__all__ = [ | ||
"CyclingCustom", | ||
"ProtocolSelector", | ||
"CyclingStandard", | ||
] |
Oops, something went wrong.