Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 59 additions & 6 deletions pytrms/compose/composition.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import sys
import json
import itertools
Expand All @@ -7,6 +8,8 @@
from itertools import tee
from functools import wraps

from ..helpers import parse_presets_file

__all__ = ['Step', 'Composition']

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -251,7 +254,7 @@ def dump(self, ofstream):
}
json.dump(self, ofstream, indent=2, default=vars)

def translate_op_modes(self, preset_items, check=True):
def translate_op_modes(self, preset_items, carry=True, check=True):
'''Given the `preset_items` (from a presets-file), compile a list of set_values.

>>> presets = {}
Expand Down Expand Up @@ -323,16 +326,66 @@ def translate_op_modes(self, preset_items, check=True):

del entry['OP_Mode']

# Note: each preset is only an update of set-values over what has already
# been set. thus, when following the sequence of OP_Modes, each one must
# carry with it the set-values of all its predecessors:
carry.update(entry)
entry.update(carry)
if carry:
# Note: each preset is only an update of set-values over what has already
# been set. thus, when following the sequence of OP_Modes, each one must
# carry with it the set-values of all its predecessors:
carry.update(entry)
entry.update(carry)
if check:
assert all(key in entry for key in all_parIDs), "reaction-data missing in presets"

return set_values

def expand_op_modes(self, presets):
'''Return a new Composition with `OP_Mode` replaced by concrete set-values.

`presets` is either a path to a presets XML file (see
:func:`pytrms.helpers.parse_presets_file`) or the dict returned by that
function. Other composition parameters are copied unchanged.

>>> presets = {}
>>> _key = namedtuple('preset_item', ['name', 'ads_path', 'dtype'])
>>> presets[0] = ('H3O+', {_key('Drift', 'Global_System.DriftPressureSet', 'FLOAT'): 2.6})
>>> presets[2] = ('O3+', {_key('T-Drift[°C]', 'Global_Temperatures.TempsSet[0]', 'FLOAT'): 75.0})
>>> steps = [
... Step('uno', {'OP_Mode': 0}, 10, 2),
... Step('due', {'Udrift': 420.0, 'T-Drift': 81.0}, 10, 2),
... Step('tre', {'OP_Mode': 2}, 10, 2),
... ]
>>> co = Composition(steps, max_runs=3, start_cycle=5)
>>> expanded = co.expand_op_modes(presets)
>>> expanded is not co
True
>>> expanded.max_runs
3
>>> expanded.start_cycle
5
>>> co.steps[0].set_values
{'OP_Mode': 0}
>>> expanded.steps[0].set_values
{'DPS_Pdrift_Ctrl_Val': 2.6}
>>> expanded.steps[2].set_values
{'T-Drift': 75.0, 'DPS_Pdrift_Ctrl_Val': 2.6, 'Udrift': 420.0}

'''
if isinstance(presets, (str, os.PathLike)):
preset_items = parse_presets_file(presets)
else:
preset_items = presets

translated = self.translate_op_modes(preset_items, carry=False, check=False)
steps = [
Step(step.name, set_values, step.duration, step.start_delay)
for step, set_values in zip(self.steps, translated)
]
return Composition(
steps,
max_runs=self.max_runs,
start_cycle=self.start_cycle,
spec_duration_ms=self.spec_duration_ms,
)

def sequence(self, generate_automation=False):
'''A (possibly infinite) iterator over this Composition's future_cycles and steps.

Expand Down