def test_set_elements(self): tm = self.tm elements = OrderedDict() elements["col1"] = StringArrayMeta() elements["col2"] = StringArrayMeta() tm.set_elements(elements) assert elements == tm.elements
class TestTableMetaSerialization(unittest.TestCase): def setUp(self): self.sam = StringArrayMeta() self.serialized = OrderedDict() self.serialized["typeid"] = "malcolm:core/TableMeta:1.0" self.serialized["elements"] = dict(c1=self.sam.to_dict()) self.serialized["description"] = "desc" self.serialized["tags"] = () self.serialized["writeable"] = True self.serialized["label"] = "Name" def test_to_dict(self): tm = TableMeta("desc") tm.set_label("Name") tm.set_elements(dict(c1=self.sam)) tm.set_writeable(True) assert tm.to_dict() == self.serialized def test_from_dict(self): tm = TableMeta.from_dict(self.serialized) assert tm.description == "desc" assert len(tm.elements) == 1 assert tm.elements["c1"].to_dict() == self.sam.to_dict() assert tm.tags == () assert tm.writeable == True assert tm.label == "Name"
class TestSerialization(unittest.TestCase): def setUp(self): self.sam = StringArrayMeta() self.serialized = OrderedDict() self.serialized["typeid"] = "malcolm:core/MapMeta:1.0" self.serialized["elements"] = dict(c1=self.sam.to_dict()) self.serialized["elements"]["c1"]["label"] = "C1" self.serialized["description"] = "desc" self.serialized["tags"] = () self.serialized["writeable"] = False self.serialized["label"] = "" self.serialized["required"] = ("c1",) def test_to_dict(self): tm = MapMeta("desc") tm.set_elements(dict(c1=self.sam)) tm.set_required(["c1"]) assert tm.to_dict() == self.serialized def test_from_dict(self): tm = MapMeta.from_dict(self.serialized) assert tm.description == "desc" assert len(tm.elements) == 1 expected = self.sam.to_dict() expected["label"] = "C1" assert tm.elements["c1"].to_dict() == expected assert tm.tags == () assert tm.required == ("c1",)
def create_attribute_models(self): for data in super(RunnableController, self).create_attribute_models(): yield data # Create sometimes writeable attribute for the current completed scan # step completed_steps_meta = NumberMeta( "int32", "Readback of number of scan steps", tags=[widget("textinput")]) completed_steps_meta.set_writeable_in(ss.PAUSED, ss.ARMED) self.completed_steps = completed_steps_meta.create_attribute_model(0) yield "completedSteps", self.completed_steps, self.set_completed_steps # Create read-only attribute for the number of configured scan steps configured_steps_meta = NumberMeta( "int32", "Number of steps currently configured", tags=[widget("textupdate")]) self.configured_steps = configured_steps_meta.create_attribute_model(0) yield "configuredSteps", self.configured_steps, None # Create read-only attribute for the total number scan steps total_steps_meta = NumberMeta( "int32", "Readback of number of scan steps", tags=[widget("textupdate")]) self.total_steps = total_steps_meta.create_attribute_model(0) yield "totalSteps", self.total_steps, None # Create sometimes writeable attribute for the default axis names axes_to_move_meta = StringArrayMeta( "Default axis names to scan for configure()", tags=[widget("table"), config()]) axes_to_move_meta.set_writeable_in(ss.READY) self.axes_to_move = axes_to_move_meta.create_attribute_model( self.params.axesToMove) yield "axesToMove", self.axes_to_move, self.set_axes_to_move
def test_set_elements_from_serialized(self): tm = self.tm elements = OrderedDict() elements["col1"] = StringArrayMeta().to_dict() elements["col2"] = StringArrayMeta().to_dict() tm.set_elements(elements) assert isinstance(tm.elements["col1"], StringArrayMeta) assert tm.elements["col1"].to_dict() == elements["col1"]
def create_attribute_models(self): for y in super(WebsocketClientComms, self).create_attribute_models(): yield y # Create read-only attribute for the remotely reachable blocks meta = StringArrayMeta("Remotely reachable blocks", tags=[widget("table")]) self.remote_blocks = meta.create_attribute_model() yield "remoteBlocks", self.remote_blocks, None
def setUp(self): self.sam = StringArrayMeta() self.serialized = OrderedDict() self.serialized["typeid"] = "malcolm:core/TableMeta:1.0" self.serialized["elements"] = dict(c1=self.sam.to_dict()) self.serialized["description"] = "desc" self.serialized["tags"] = () self.serialized["writeable"] = True self.serialized["label"] = "Name"
def setUp(self): self.sam = StringArrayMeta() self.serialized = OrderedDict() self.serialized["typeid"] = "malcolm:core/MapMeta:1.0" self.serialized["elements"] = dict(c1=self.sam.to_dict()) self.serialized["elements"]["c1"]["label"] = "C1" self.serialized["description"] = "desc" self.serialized["tags"] = () self.serialized["writeable"] = False self.serialized["label"] = "" self.serialized["required"] = ("c1",)
def test_init_with_dict(self): meta = Mock() meta.elements = { "e1": NumberArrayMeta("int32"), "e2": StringArrayMeta(), "e3": StringArrayMeta() } d = {"e1": [0, 1], "e3": ["value"]} t = Table(meta, d) assert [0, 1] == list(t.e1) assert () == t.e2 assert ("value", ) == t.e3 assert "malcolm:core/Table:1.0" == t.typeid
def setUp(self): meta = Mock() meta.elements = OrderedDict() meta.elements["e1"] = StringArrayMeta() meta.elements["e2"] = NumberArrayMeta("int32") meta.elements["e3"] = NumberArrayMeta("int32") self.meta = meta
class ScanTickerPart(ChildPart): """Provides control of a `counter_block` within a `RunnableController`""" # Generator instance generator = None # Where to start completed_steps = None # How many steps to do steps_to_do = None # When to blow up exception_step = None @RunnableController.Configure @RunnableController.PostRunArmed @RunnableController.Seek @method_takes( "generator", PointGeneratorMeta("Generator instance"), REQUIRED, "axesToMove", StringArrayMeta( "List of axes in inner dimension of generator that should be moved" ), REQUIRED, "exceptionStep", NumberMeta("int32", "If >0, raise an exception at the end of this step"), 0) def configure(self, context, completed_steps, steps_to_do, part_info, params): # If we are being asked to move if self.name in params.axesToMove: # Just store the generator and place we need to start self.generator = params.generator self.completed_steps = completed_steps self.steps_to_do = steps_to_do self.exception_step = params.exceptionStep else: # Flag nothing to do self.generator = None @RunnableController.Run @RunnableController.Resume def run(self, context, update_completed_steps): # Start time so everything is relative point_time = time.time() if self.generator: child = context.block_view(self.params.mri) for i in range(self.completed_steps, self.completed_steps + self.steps_to_do): self.log.debug("Starting point %s", i) # Get the point we are meant to be scanning point = self.generator.get_point(i) # Update the child counter_block to be the demand position position = point.positions[self.name] child.counter.put_value(position) # Wait until the next point is due point_time += point.duration wait_time = point_time - time.time() self.log.debug("%s Sleeping %s", self.name, wait_time) context.sleep(wait_time) # Update the point as being complete update_completed_steps(i + 1, self) # If this is the exception step then blow up assert i + 1 != self.exception_step, \ "Raising exception at step %s" % self.exception_step
def create_attribute_models(self): for data in super(ManagerController, self).create_attribute_models(): yield data assert os.path.isdir(self.params.configDir), \ "%s is not a directory" % self.params.configDir if not os.path.isdir(os.path.join(self.params.configDir, ".git")): # Try and make it a git repo, don't care if it fails self._run_git_cmd("init") self._run_git_cmd("commit", "--allow-empty", "-m", "Created repo") # Create writeable attribute table for the layout info we need elements = OrderedDict() elements["name"] = StringArrayMeta("Name of layout part") elements["mri"] = StringArrayMeta("Malcolm full name of child block") elements["x"] = NumberArrayMeta( "float64", "X Coordinate of child block") elements["y"] = NumberArrayMeta( "float64", "Y Coordinate of child block") elements["visible"] = BooleanArrayMeta("Whether child block is visible") layout_table_meta = TableMeta( "Layout of child blocks", elements=elements, tags=[widget("flowgraph")]) layout_table_meta.set_writeable_in(ss.READY) self.layout = layout_table_meta.create_attribute_model() yield "layout", self.layout, self.set_layout # Create writeable attribute for loading an existing layout design_meta = ChoiceMeta( "Design name to load", tags=[config(), widget("combo")]) design_meta.set_writeable_in(ss.READY) self.design = design_meta.create_attribute_model() yield "design", self.design, self.set_design # Create writeable attribute table for the exported fields elements = OrderedDict() elements["name"] = ChoiceArrayMeta("Name of exported block.field") elements["exportName"] = StringArrayMeta( "Name of the field within current block") exports_table_meta = TableMeta( "Exported fields of child blocks", tags=[widget("table")], elements=elements) exports_table_meta.set_writeable_in(ss.READY) self.exports = exports_table_meta.create_attribute_model() yield "exports", self.exports, self.set_exports # Create read-only indicator for when things are modified modified_meta = BooleanMeta( "Whether the design is modified", tags=[widget("led")]) self.modified = modified_meta.create_attribute_model() yield "modified", self.modified, None
class TestStringArrayMeta(unittest.TestCase): def setUp(self): self.meta = StringArrayMeta("test description") def test_init(self): assert "test description" == self.meta.description assert self.meta.label == "" assert self.meta.typeid == "malcolm:core/StringArrayMeta:1.0" def test_validate_none(self): assert self.meta.validate(None) == () def test_validate_array(self): array = ["test_string", 123, 123.456] with self.assertRaises(ValueError): self.meta.validate(array) def test_not_iterable_raises(self): value = 12346 with self.assertRaises(TypeError): self.meta.validate(value) def test_null_element_raises(self): array = ["test", None] with self.assertRaises(ValueError): self.meta.validate(array)
def test_init(self): meta = Mock() s = StringArrayMeta() meta.elements = {"e1": s, "e2": s, "e3": s} t = Table(meta) assert () == t.e1 assert () == t.e2 assert () == t.e3 assert "malcolm:core/Table:1.0" == t.typeid
snake_to_camel from malcolm.modules.ADCore.includes import adbase_parts from malcolm.modules.ADCore.infos import attribute_dataset_types from malcolm.modules.ADPandABlocks.parts import PandABlocksDriverPart, \ PandABlocksChildPart from malcolm.modules.builtin.controllers import StatefulController from malcolm.modules.builtin.parts import StringPart, ChoicePart from malcolm.modules.builtin.vmetas import StringMeta, StringArrayMeta from malcolm.modules.pandablocks.controllers import PandABlocksManagerController from malcolm.modules.scanning.controllers import RunnableController @method_also_takes("areaDetectorPrefix", StringMeta("Prefix for areaDetector records"), REQUIRED, "axesToMove", StringArrayMeta("Default value for configure() axesToMove"), []) class PandABlocksRunnableController(PandABlocksManagerController, RunnableController): def _make_child_controller(self, parts, mri): # Add some extra parts to determine the dataset name and type for # any CAPTURE field part new_parts = [] for existing_part in parts: new_parts.append(existing_part) if existing_part.name.endswith(".CAPTURE"): # Add capture dataset name and type part_name = existing_part.name.replace(".CAPTURE", ".DATASET_NAME") attr_name = snake_to_camel(part_name.replace(".", "_")) new_parts.append(
def setUp(self): self.meta = StringArrayMeta("test description")
self.READY, self.CONFIGURING, self.ARMED, self.RUNNING, self.POSTRUN, self.PAUSED, self.SEEKING] for state in normal_states: self.set_allowed(state, self.ABORTING) # Set transitions for aborted states self.set_allowed(self.ABORTING, self.ABORTED) self.set_allowed(self.ABORTED, self.RESETTING) ss = RunnableStates configure_args = ( "generator", PointGeneratorMeta("Generator instance"), REQUIRED, "axesToMove", StringArrayMeta( "List of axes in inner dimension of generator that should be moved"), [] ) validate_args = configure_args[:-1] + (REQUIRED,) @method_also_takes( "axesToMove", StringArrayMeta("Default value for configure() axesToMove"), [] ) class RunnableController(ManagerController): """RunnableDevice implementer that also exposes GUI for child parts""" # The stateSet that this controller implements stateSet = ss() Validate = Hook()
from malcolm.core import method_also_takes, REQUIRED from malcolm.modules.builtin.vmetas import ChoiceMeta, StringMeta, StringArrayMeta from .attributepart import AttributePart @method_also_takes( "choices", StringArrayMeta("Possible choices for this attribute"), REQUIRED, "initialValue", StringMeta("Initial value of attribute"), REQUIRED, ) class ChoicePart(AttributePart): def get_initial_value(self): return self.params.initialValue def create_meta(self, description, tags): return ChoiceMeta( choices=self.params.choices, description=description, tags=tags)
def test_set_elements(self): els = dict(sam=StringArrayMeta()) self.mm.set_elements(els) assert self.mm.elements == els
def setUp(self): self.tm = TableMeta("desc") self.tm.set_elements(dict(c1=StringArrayMeta()))
def test_init_with_none(self): meta = Mock() meta.elements = {"e1": StringArrayMeta()} t = Table(meta, None) assert () == t.e1 assert "malcolm:core/Table:1.0" == t.typeid
from malcolm.compat import OrderedDict from malcolm.core import Part, Table, method_takes, REQUIRED from malcolm.modules.ADCore.infos import DatasetProducedInfo, dataset_types from malcolm.modules.builtin.vmetas import StringArrayMeta, ChoiceArrayMeta, \ TableMeta, NumberArrayMeta, StringMeta from malcolm.modules.scanning.controllers import RunnableController from malcolm.tags import widget # Make a table for the dataset info we produce columns = OrderedDict() columns["name"] = StringArrayMeta("Dataset name") columns["filename"] = StringArrayMeta( "Filename of HDF file relative to fileDir") columns["type"] = ChoiceArrayMeta("Type of dataset", dataset_types) columns["rank"] = NumberArrayMeta("int32", "Rank (number of dimensions)") columns["path"] = StringArrayMeta("Dataset path within HDF file") columns["uniqueid"] = StringArrayMeta("UniqueID array path within HDF file") dataset_table_meta = TableMeta("Datsets produced in HDF file", elements=columns, tags=[widget("table")]) @method_takes("name", StringMeta("Name of the Part within the controller"), REQUIRED) class DatasetTablePart(Part): """Exposes an Attribute that reports the datasets that will be written during a scan""" def __init__(self, params): # Created attributes self.datasets = None super(DatasetTablePart, self).__init__(params.name)
TRIG_CAPTURE = 4 # Capture 1, Frame 0, Detector 0 TRIG_DEAD_FRAME = 2 # Capture 0, Frame 1, Detector 0 TRIG_LIVE_FRAME = 3 # Capture 0, Frame 1, Detector 1 TRIG_ZERO = 8 # Capture 0, Frame 0, Detector 0 # How many profile points to write each time PROFILE_POINTS = 10000 # All possible PMAC CS axis assignment cs_axis_names = list("ABCUVWXYZ") # Args for configure and validate configure_args = ( "generator", PointGeneratorMeta("Generator instance"), REQUIRED, "axesToMove", StringArrayMeta( "List of axes in inner dimension of generator that should be moved"), []) @method_also_takes("minTurnaround", NumberMeta("float64", "Min time for any gaps between frames"), 0.0) class PmacTrajectoryPart(StatefulChildPart): # Axis information stored from validate # {scannable_name: MotorInfo} axis_mapping = None # Lookup of the completed_step value for each point completed_steps_lookup = [] # If we are currently loading then block loading more points loading = False # Where we have generated into profile