def __init__( self, name: APartName, mri: AMri, runs_on_windows: APartRunsOnWindows = False, write_all_nd_attributes: AWriteAllNDAttributes = True, ) -> None: super().__init__(name, mri) # Future for the start action self.start_future: Optional[Future] = None self.array_future: Optional[Future] = None self.done_when_reaches = 0 # This is when uniqueId last updated self.last_id_update: Optional[float] = None # CompletedSteps = arrayCounter + self.uniqueid_offset self.uniqueid_offset = 0 # The HDF5 layout file we write to say where the datasets go self.layout_filename: Optional[str] = None self.runs_on_windows = runs_on_windows # How long to wait between frame updates before error self.frame_timeout = 0.0 self.write_all_nd_attributes = BooleanMeta( "Toggles whether all NDAttributes are written to " "file, or only those specified in the dataset", writeable=True, tags=[Widget.CHECKBOX.tag(), config_tag()], ).create_attribute_model(write_all_nd_attributes)
def __init__( self, name: APartName, mri: AMri, runs_on_windows: APartRunsOnWindows = False, write_all_nd_attributes: AWriteAllNDAttributes = True, required_version: AVersionRequirement = None, ) -> None: super().__init__(name, mri) # Future for the start action self.start_future: Optional[Future] = None self.first_array_future: Optional[Future] = None self.done_when_captured = 0 # This is when the readback for number of frames captured last updated self.last_capture_update: Optional[float] = None # Store number of frames captured for progress reporting self.num_captured_offset = 0 # The HDF5 layout file we write to say where the datasets go self.layout_filename: Optional[str] = None self.runs_on_windows = runs_on_windows # How long to wait between frame updates before error self.frame_timeout = 0.0 self.write_all_nd_attributes = BooleanMeta( "Toggles whether all NDAttributes are written to " "file, or only those specified in the dataset", writeable=True, tags=[Widget.CHECKBOX.tag(), config_tag()], ).create_attribute_model(write_all_nd_attributes) self.required_version = required_version
def set_tags( meta: VMeta, writeable: AWriteable = False, config: AConfig = 1, group: AGroup = None, widget: AWidget = None, sink_port: ASinkPort = None, port_badge: APortBadge = None, ) -> None: tags = [] meta.set_writeable(writeable) if widget is None: widget = meta.default_widget() if widget is not Widget.NONE: tags.append(widget.tag()) if config and writeable: # We only allow config tags on writeable functions tags.append(config_tag(config)) if group: # If we have a group then add the tag tags.append(group_tag(group)) if sink_port: tags.append(sink_port.sink_port_tag(disconnected_value="")) if port_badge: tags.append(port_badge) meta.set_tags(tags)
def _make_table(self, field_name: str, field_data: FieldData) -> None: group = self._make_group("parameters") tags = [Widget.TABLE.tag(), group, config_tag()] meta = TableMeta(field_data.description, tags, writeable=True) part = PandATablePart(self.client, meta, self.block_name, field_name) self.add_part(part) self.field_parts[field_name] = part
def _make_table(self, field_name, field_data): group = self._make_group("parameters") tags = [Widget.TABLE.tag(), group, config_tag()] meta = TableMeta(field_data.description, tags, writeable=True) part = PandABlocksTablePart(self.client, meta, self.block_name, field_name) self._add_part(field_name, part)
def __init__(self, name: APartName = "simultaneousAxes", value: USimultaneousAxes = None) -> None: super().__init__(name) self.attr = StringArrayMeta( "Set of axes that can be specified in axesToMove at configure", tags=[Widget.TEXTINPUT.tag(), config_tag()], ).create_attribute_model(value)
def __init__(self, name="simultaneousAxes", value=None): # type: (APartName, USimultaneousAxes) -> None super(SimultaneousAxesPart, self).__init__(name) self.attr = StringArrayMeta( "Set of axes that can be specified in axesToMove at configure", tags=[Widget.TEXTINPUT.tag(), config_tag()]).create_attribute_model(value) # Hooks self.register_hooked(ValidateHook, self.validate)
def __init__( self, name: APartName = "minTurnaround", gap: AMinTurnaround = None, interval: ATurnaroundInterval = None, ) -> None: super().__init__(name) self.gap = NumberMeta( "float64", "Minimum time for any gaps between non-joined points", tags=[Widget.TEXTINPUT.tag(), config_tag()], display=Display(precision=6, units="s"), ).create_attribute_model(gap) self.interval = NumberMeta( "float64", "Minimum interval between turnaround points", tags=[Widget.TEXTINPUT.tag(), config_tag()], display=Display(precision=6, units="s"), ).create_attribute_model(interval)
def __init__(self, name): # type: (APartName) -> None super(CounterPart, self).__init__(name) # TODO: why doesn't this show up in the docs for CounterPart? self.counter = NumberMeta("float64", "The current value of the counter", tags=[config_tag(), Widget.TEXTINPUT.tag() ]).create_attribute_model() """Attribute holding the current counter value"""
def __init__( self, name: APartName, initial_windows_drive_letter: ADriveLetter, initial_path_prefix: APathPrefix = "/dls", initial_network_prefix: ANetworkPrefix = "", ) -> None: super().__init__(name) self.windows_drive_letter = StringMeta( drive_letter_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()], ).create_attribute_model(initial_windows_drive_letter) self.path_prefix = StringMeta( path_prefix_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()], ).create_attribute_model(initial_path_prefix) self.network_prefix = StringMeta( network_prefix_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()], ).create_attribute_model(initial_network_prefix)
def _make_field_part( self, field_name, meta, writeable, initial_value=None, iteration=1 ): if writeable: meta.set_tags(list(meta.tags) + [config_tag(iteration)]) meta.set_writeable(True) part = PandAFieldPart( self.client, meta, self.block_name, field_name, initial_value ) self.add_part(part) self.field_parts[field_name] = part
def setup(self, registrar: PartRegistrar) -> None: super(PortsPart, self).setup(registrar) attr = StringMeta(tags=[Port.INT32.sink_port_tag(""), config_tag(1)]).create_attribute_model() registrar.add_attribute_model("sinkportConnector", attr, attr.set_value) attr = StringMeta(tags=[Port.INT32.source_port_tag(self.name) ]).create_attribute_model() registrar.add_attribute_model("sourceportConnector", attr, attr.set_value)
def setup(self, registrar: PartRegistrar) -> None: super().setup(registrar) # Add some Attribute and Methods to the Block self.counter = NumberMeta( "float64", "The current value of the counter", tags=[config_tag(), Widget.TEXTINPUT.tag()], ).create_attribute_model() registrar.add_attribute_model("counter", self.counter, self.counter.set_value) self.delta = NumberMeta( "float64", "The amount to increment() by", tags=[config_tag(), Widget.TEXTINPUT.tag()], ).create_attribute_model(initial_value=1) registrar.add_attribute_model("delta", self.delta, self.delta.set_value) registrar.add_method_model(self.zero) registrar.add_method_model(self.increment)
def __init__( self, name: APartName, initial_readout_time: AInitialReadoutTime = 0.0, initial_frequency_accuracy: AInitialAccuracy = 50.0, min_exposure: AMinExposure = 0.0, ) -> None: super().__init__(name) self.readout_time = NumberMeta( "float64", readout_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()], display=Display(precision=6, units="s"), ).create_attribute_model(initial_readout_time) self.frequency_accuracy = NumberMeta( "float64", frequency_accuracy_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()], display=Display(precision=3, units="ppm"), ).create_attribute_model(initial_frequency_accuracy) self.min_exposure = min_exposure self.exposure = exposure_attribute(min_exposure)
def setup(self, registrar: PartRegistrar) -> None: self.bits = TableMeta.from_table( self.bits_table_cls, "Current values and capture status of Bit fields", writeable=[ x for x in self.bits_table_cls.call_types if x not in ("name", "value") ], extra_tags=[config_tag()], ).create_attribute_model() self.positions = TableMeta.from_table( self.positions_table_cls, "Current values, scaling, and capture status of Position fields", writeable=[ x for x in self.positions_table_cls.call_types if x not in ("name", "value") ], extra_tags=[config_tag()], ).create_attribute_model() registrar.add_attribute_model("bits", self.bits, self.set_bits) registrar.add_attribute_model("positions", self.positions, self.set_positions)
def __init__( self, name, # type: APartName initial_readout_time=0.0, # type: AInitialReadoutTime initial_frequency_accuracy=50.0 # type: AInitialAccuracy ): # type: (...) -> None super(ExposureDeadtimePart, self).__init__(name) self.readout_time = NumberMeta( "float64", readout_desc, tags=[Widget.TEXTINPUT.tag(), config_tag()]).create_attribute_model(initial_readout_time) self.frequency_accuracy = NumberMeta( "float64", frequency_accuracy_desc, tags=[Widget.TEXTINPUT.tag(), config_tag() ]).create_attribute_model(initial_frequency_accuracy) # Hooks self.register_hooked(scanning.hooks.ReportStatusHook, self.report_status) self.register_hooked(scanning.hooks.ValidateHook, self.validate)
def __init__(self, name: APartName, mri: AMri) -> None: super().__init__(name, mri, stateful=False, initial_visibility=True) self.runner_config = None self.context: Optional[AContext] = None self.scan_sets: Dict[str, Scan] = {} self.runner_state = StringMeta( "Runner state", tags=Widget.TEXTUPDATE.tag()).create_attribute_model("Idle") self.runner_status_message = StringMeta( "Runner status message", tags=Widget.TEXTUPDATE.tag()).create_attribute_model("Idle") self.scan_file = StringMeta( "Path to input scan file", tags=[config_tag(), Widget.TEXTINPUT.tag()]).create_attribute_model() self.scans_configured = NumberMeta( "int64", "Number of configured scans", tags=Widget.TEXTUPDATE.tag()).create_attribute_model() self.current_scan_set = StringMeta( "Current scan set", tags=Widget.TEXTUPDATE.tag()).create_attribute_model() self.scans_completed = NumberMeta( "int64", "Number of scans completed", tags=Widget.TEXTUPDATE.tag()).create_attribute_model() self.scan_successes = NumberMeta("int64", "Successful scans", tags=[Widget.TEXTUPDATE.tag() ]).create_attribute_model() self.scan_failures = NumberMeta("int64", "Failed scans", tags=[Widget.TEXTUPDATE.tag() ]).create_attribute_model() self.output_directory = StringMeta( "Root output directory (will create a sub-directory inside)", tags=[config_tag(), Widget.TEXTINPUT.tag()], ).create_attribute_model()
def __init__( self, name: APartName, mri: AMri, soft_trigger_modes: USoftTriggerModes = None, multiple_image_mode: AMultipleImageMode = "Multiple", main_dataset_useful: AMainDatasetUseful = True, runs_on_windows: APartRunsOnWindows = False, required_version: AVersionRequirement = None, min_acquire_period: AMinAcquirePeriod = 0.0, ) -> None: super().__init__(name, mri) self.required_version = required_version self.min_acquire_period = min_acquire_period self.soft_trigger_modes = soft_trigger_modes self.multiple_image_mode = multiple_image_mode self.is_hardware_triggered = True self.main_dataset_useful = main_dataset_useful self.attributes_filename = "" self.extra_attributes = TableMeta.from_table( ExtraAttributesTable, "Extra attributes to be added to the dataset", writeable=[ "name", "pv", "description", "sourceId", "sourceType", "dataType", "datasetType", ], extra_tags=[config_tag()], ).create_attribute_model() self.runs_on_windows = runs_on_windows # How long to wait between frame updates before error self.frame_timeout = 0.0 # When arrayCounter gets to here we are done self.done_when_reaches = 0 # CompletedSteps = arrayCounter + self.uniqueid_offset self.uniqueid_offset = 0 # A future that completes when detector start calls back self.start_future: Optional[Future] = None
def __init__( self, name, # type: builtin.parts.APartName mri, # type: builtin.parts.AMri initial_min_turnaround=0.0 # type: AMinTurnaround ): # type: (...) -> None super(PmacTrajectoryPart, self).__init__(name, mri, initial_visibility=True) # Axis information stored from validate self.axis_mapping = None # type: Dict[str, MotorInfo] # Lookup of the completed_step value for each point self.completed_steps_lookup = [] # type: List[int] # If we are currently loading then block loading more points self.loading = False # Where we have generated into profile self.end_index = 0 # Where we should stop loading points self.steps_up_to = 0 # Profile points that haven't been sent yet # {time_array/velocity_mode/trajectory/user_programs: [elements]} self.profile = {} # Stored generator for positions self.generator = None # type: CompoundGenerator # Attribute info self.min_turnaround = NumberMeta( "float64", "Min time for any gaps between frames", tags=[Widget.TEXTINPUT.tag(), config_tag()]).create_attribute_model(initial_min_turnaround) # Hooks self.register_hooked(scanning.hooks.ValidateHook, self.validate) self.register_hooked( (scanning.hooks.ConfigureHook, scanning.hooks.PostRunArmedHook, scanning.hooks.SeekHook), self.configure) self.register_hooked( (scanning.hooks.RunHook, scanning.hooks.ResumeHook), self.run) self.register_hooked( (scanning.hooks.AbortHook, scanning.hooks.PauseHook), self.abort)
def set_tags( meta, # type: VMeta writeable=False, # type: AWriteable config=1, # type: AConfig group=None, # type: AGroup widget=None, # type: AWidget sink_port=None, # type: ASinkPort ): # type: (...) -> None tags = [] meta.set_writeable(writeable) if widget is None: widget = meta.default_widget() if widget is not Widget.NONE: tags.append(widget.tag()) if config and writeable: # We only allow config tags on writeable functions tags.append(config_tag(config)) if group: # If we have a group then add the tag tags.append(group_tag(group)) if sink_port: tags.append(sink_port.sink_port_tag(disconnected_value="")) meta.set_tags(tags)
def __init__( self, mri: AMri, config_dir: AConfigDir, template_designs: ATemplateDesigns = "", initial_design: AInitialDesign = "", use_git: AUseGit = True, description: ADescription = "", ) -> None: super().__init__(mri=mri, description=description) assert os.path.isdir(config_dir), "%s is not a directory" % config_dir self.config_dir = config_dir self.initial_design = initial_design self.use_git = use_git self.template_designs = template_designs self.git_config: Tuple[str, ...] if use_git: if check_git_version("1.7.2"): self.git_email = os.environ["USER"] + "@" + socket.gethostname( ) self.git_name = "Malcolm" self.git_config = ( "-c", "user.name=%s" % self.git_name, "-c", 'user.email="%s"' % self.git_email, ) else: self.git_config = () # last saved layout and exports self.saved_visibility = None self.saved_exports = None # ((name, AttributeModel/MethodModel, setter, needs_context)) self._current_part_fields = () self._subscriptions: List[Subscribe] = [] self.port_info: Dict[APartName, List[PortInfo]] = {} self.part_exportable: Dict[Part, List[AAttributeName]] = {} # TODO: turn this into "exported attribute modified" self.context_modified: Dict[Part, Set[str]] = {} self.part_modified: Dict[Part, PartModifiedInfo] = {} # The attributes our part has published self.our_config_attributes: Dict[str, AttributeModel] = {} # The reportable infos we are listening for self.info_registry.add_reportable(PartModifiedInfo, self.update_modified) # Update queue of exportable fields self.info_registry.add_reportable(PartExportableInfo, self.update_exportable) # Create a port for ourself self.field_registry.add_attribute_model( "mri", StringMeta( "A port for giving our MRI to things that might use us", tags=[Port.BLOCK.source_port_tag(self.mri)], ).create_attribute_model(self.mri), ) # Create a layout table attribute for setting block positions self.layout = TableMeta.from_table( LayoutTable, "Layout of child blocks", Widget.FLOWGRAPH, writeable=["x", "y", "visible"], ).create_attribute_model() self.set_writeable_in(self.layout, ss.READY) self.field_registry.add_attribute_model("layout", self.layout, self.set_layout) # Create a design attribute for loading an existing layout self.design = ChoiceMeta("Design name to load", tags=[config_tag(), Widget.COMBO.tag() ]).create_attribute_model() self.field_registry.add_attribute_model("design", self.design, self.set_design) self.set_writeable_in(self.design, ss.READY) # Create an export table for mirroring exported fields self.exports = TableMeta.from_table( ExportTable, "Exported fields of child blocks", writeable=list(ExportTable.call_types), ).create_attribute_model() # Overwrite the sources meta to be a ChoiceArrayMeta self.exports.meta.elements["source"] = ChoiceArrayMeta( "Name of the block.field to export", writeable=True, tags=[Widget.COMBO.tag()], ) self.set_writeable_in(self.exports, ss.READY) self.field_registry.add_attribute_model("exports", self.exports, self.set_exports) # Create read-only indicator for when things are modified self.modified = BooleanMeta("Whether the design is modified", tags=[Widget.LED.tag() ]).create_attribute_model() self.field_registry.add_attribute_model("modified", self.modified) # Create the save method self.set_writeable_in(self.field_registry.add_method_model(self.save), ss.READY)
def setup(self, registrar): # type: (PartRegistrar) -> None self.attr = StringMeta(tags=[config_tag( ), Widget.TEXTINPUT.tag()]).create_attribute_model("defaultv") registrar.add_attribute_model("attr", self.attr, self.attr.set_value)