def __init__(self, ui, statistics_model): super().__init__( ui.create_column_widget(properties={ "min-height": 18 * 3, "max-height": 18 * 3 })) # create property models for the UI self._stats1_property = Model.PropertyModel(str()) self._stats2_property = Model.PropertyModel(str()) self.__statistics_model = statistics_model def statistics_changed(key: str) -> None: if key == "value": statistics_data = self.__statistics_model.value statistic_strings = list() for key in sorted(statistics_data.keys()): value = statistics_data[key] if value is not None: statistic_str = "{0} {1}".format(key, value) else: statistic_str = "{0} {1}".format(key, _("N/A")) statistic_strings.append(statistic_str) self._stats1_property.value = "\n".join( statistic_strings[:(len(statistic_strings) + 1) // 2]) self._stats2_property.value = "\n".join( statistic_strings[(len(statistic_strings) + 1) // 2:]) self.__statistics_property_changed_event_listener = self.__statistics_model.property_changed_event.listen( statistics_changed) statistics_changed("value") stats_column1 = ui.create_column_widget(properties={ "min-width": 140, "max-width": 140 }) stats_column2 = ui.create_column_widget(properties={ "min-width": 140, "max-width": 140 }) stats_column1_label = ui.create_label_widget() stats_column2_label = ui.create_label_widget() stats_column1.add(stats_column1_label) stats_column2.add(stats_column2_label) stats_section = ui.create_row_widget() stats_section.add_spacing(13) stats_section.add(stats_column1) stats_section.add_stretch() stats_section.add(stats_column2) stats_section.add_spacing(13) stats_column1_label.bind_text( Binding.PropertyBinding(self._stats1_property, "value")) stats_column2_label.bind_text( Binding.PropertyBinding(self._stats2_property, "value")) self.content_widget.add(stats_section)
def create_combo_box(self, ui): combo_box = ui.create_combo_box_widget( self.hardware_sources_model.value, item_getter=operator.attrgetter("display_name")) combo_box.bind_items( Binding.PropertyBinding(self.hardware_sources_model, "value")) combo_box.bind_current_index( Binding.PropertyBinding(self.hardware_source_index_model, "value")) return combo_box
def test_tuple_binding_pads_to_index_if_necessary(self) -> None: # this allows the source to more easily go from None to a partialy tuple None -> (3, None) -> (3, 4) source = typing.cast(typing.Any, TupleModel()) self.assertEqual(None, source.tuple) binding0 = Binding.TuplePropertyBinding(source, "tuple", 0) binding2 = Binding.TuplePropertyBinding(source, "tuple", 2) binding0.update_source("abc") self.assertEqual(("abc", ), source.tuple) binding2.update_source("ghi") self.assertEqual(("abc", None, "ghi"), source.tuple)
def __connect_pick_graphic(self, src, target, pick_graphic, computation): def _update_collection_index(axis, value): libertem_metadata = copy.deepcopy(src.metadata.get('libertem-io')) if not libertem_metadata: return file_parameters = libertem_metadata['file_parameters'] file_type = file_parameters.pop('type') current_index = libertem_metadata['display_slice']['start'] current_index = np.unravel_index(current_index, target.data.shape) if value == current_index[axis]: return executor = Registry.get_component('libertem_executor') if not executor: return executor = executor.ensure_sync() ds = dataset.load(file_type, executor, **file_parameters) roi = np.zeros(ds.shape.nav, dtype=bool) if axis == 0: roi[value, current_index[1]] = True current_index = (value, current_index[1]) else: roi[current_index[0], value] = True current_index = (current_index[0], value) result = UDFRunner(PickUDF()).run_for_dataset(ds, executor, roi=roi) result_array = np.squeeze(np.array(result['intensity'])) new_metadata = copy.deepcopy(src.metadata) new_display_slice = np.ravel_multi_index(current_index, target.data.shape) new_metadata['libertem-io']['display_slice'][ 'start'] = new_display_slice new_xdata = self.__api.create_data_and_metadata( result_array, metadata=new_metadata) src.set_data_and_metadata(new_xdata) computation.pick_graphic_binding_0 = Binding.TuplePropertyBinding( pick_graphic._graphic, 'position', 0, converter=FloatTupleToIntTupleConverter(target.data.shape[0], 0)) computation.pick_graphic_binding_1 = Binding.TuplePropertyBinding( pick_graphic._graphic, 'position', 1, converter=FloatTupleToIntTupleConverter(target.data.shape[1], 1)) computation.pick_graphic_binding_0.target_setter = functools.partial( _update_collection_index, 0) computation.pick_graphic_binding_1.target_setter = functools.partial( _update_collection_index, 1)
def connect_camera_hardware_source(self, camera_hardware_source): self.__exposure_time_ms_value_model = Model.PropertyModel() def update_exposure_time_ms(exposure_time_ms): if exposure_time_ms > 0: frame_parameters = camera_hardware_source.get_frame_parameters(0) frame_parameters.exposure_ms = exposure_time_ms camera_hardware_source.set_frame_parameters(0, frame_parameters) self.__update_estimate() self.__exposure_time_ms_value_model.on_value_changed = update_exposure_time_ms exposure_time_ms_value_binding = Binding.PropertyBinding(self.__exposure_time_ms_value_model, "value", converter=Converter.FloatToStringConverter("{0:.1f}")) def eels_profile_parameters_changed(profile_index, frame_parameters): if profile_index == 0: expected_dimensions = camera_hardware_source.get_expected_dimensions(frame_parameters.binning) self.__camera_width = expected_dimensions[1] self.__camera_height = expected_dimensions[0] self.__exposure_time_ms_value_model.value = frame_parameters.exposure_ms self.__update_estimate() self.__eels_frame_parameters_changed_event_listener = camera_hardware_source.frame_parameters_changed_event.listen(eels_profile_parameters_changed) eels_profile_parameters_changed(0, camera_hardware_source.get_frame_parameters(0)) self.__exposure_time_widget._widget.bind_text(exposure_time_ms_value_binding) # the widget will close the binding
def connect_scan_hardware_source(self, scan_hardware_source): self.__scan_width_model = Model.PropertyModel() self.__scan_height_model = Model.PropertyModel() scan_width_binding = Binding.PropertyBinding( self.__scan_width_model, "value", converter=Converter.IntegerToStringConverter()) scan_height_binding = Binding.PropertyBinding( self.__scan_height_model, "value", converter=Converter.IntegerToStringConverter()) def scan_profile_parameters_changed(profile_index, frame_parameters): if profile_index == 2: self.__scan_width_model.value = frame_parameters.size[1] self.__scan_height_model.value = frame_parameters.size[0] self.__scan_frame_parameters_changed_event_listener = scan_hardware_source.frame_parameters_changed_event.listen( scan_profile_parameters_changed) scan_profile_parameters_changed( 2, scan_hardware_source.get_frame_parameters(2)) def update_scan_width(scan_width): if scan_width > 0: frame_parameters = scan_hardware_source.get_frame_parameters(2) frame_parameters.size = frame_parameters.size[0], scan_width scan_hardware_source.set_frame_parameters(2, frame_parameters) self.__update_estimate() def update_scan_height(scan_height): if scan_height > 0: frame_parameters = scan_hardware_source.get_frame_parameters(2) frame_parameters.size = scan_height, frame_parameters.size[1] scan_hardware_source.set_frame_parameters(2, frame_parameters) self.__update_estimate() # only connect model to update hardware source after it has been initialized. self.__scan_width_model.on_value_changed = update_scan_width self.__scan_height_model.on_value_changed = update_scan_height self.__scan_width_widget._widget.bind_text( scan_width_binding) # the widget will close the binding self.__scan_height_widget._widget.bind_text( scan_height_binding) # the widget will close the binding
def __init__(self, ui, app=None): super().__init__(ui, app) # a text model to hold the label widget text text_model = Model.PropertyModel(0) # make bitmap_data (random static) for icon push button bitmap = numpy.zeros((32, 32, 4), numpy.uint8) bitmap[..., 0] = (numpy.random.randn(32, 32) * 255).astype( numpy.uint8) # blue bitmap[..., 1] = (numpy.random.randn(32, 32) * 255).astype( numpy.uint8) # green bitmap[..., 2] = (numpy.random.randn(32, 32) * 255).astype( numpy.uint8) # red bitmap[..., 3] = 255 bitmap_data = bitmap.view(numpy.uint32).reshape(bitmap.shape[:-1]) # create the widgets for the window label_widget = self.ui.create_label_widget() push_button_widget = self.ui.create_push_button_widget("Push Me") icon_button_widget = self.ui.create_push_button_widget() icon_button_widget.icon = bitmap_data # create a row for the buttons button_row = self.ui.create_row_widget() button_row.add_spacing(13) button_row.add(push_button_widget) button_row.add_spacing(13) button_row.add(icon_button_widget) button_row.add_stretch() # create a row for the label label_row = self.ui.create_row_widget() label_row.add_spacing(13) label_row.add(label_widget) label_row.add_stretch() # create a column to hold the two rows and attach it to the window content = self.ui.create_column_widget() content.add(button_row) content.add(label_row) self.attach_widget(content) # when either button is clicked, this will be called def button_clicked(): text_model.value = text_model.value + 1 # connect the buttons to the button_clicked function push_button_widget.on_clicked = button_clicked icon_button_widget.on_clicked = button_clicked # and bind the label txt to the 'value' property of the text_model, but attach an integer-to-string converter to it. label_widget.bind_text( Binding.PropertyBinding( text_model, "value", converter=Converter.IntegerToStringConverter( format="You have clicked {:d} times.")))
def configure_binding(): if self._source and self._target: assert not self.__binding self.__binding = Binding.PropertyBinding( self._source, self.source_property) self.__binding.target_setter = self.__set_target_from_source # while reading, the data item in the display data channel will not be connected; # we still set its value here. when the data item becomes valid, it will update. self.__binding.update_target_direct( self.__binding.get_target_value())
def test_should_be_able_to_get_items_from_list_binding(self): list_model = ListModel.ListModel("items") list_model.insert_item(0, "zero") list_model.insert_item(1, "one") list_model.insert_item(2, "two") binding = Binding.ListBinding(list_model, "items") items = binding.items self.assertEqual(len(items), 3) self.assertEqual(items[2], "two") list_model.insert_item(0, "negative") self.assertEqual(len(items), 4) self.assertEqual(items[3], "two")
def connect_camera_hardware_source( self, camera_hardware_source: HardwareSource.HardwareSource) -> None: assert isinstance(camera_hardware_source, camera_base.CameraHardwareSource) self.__exposure_time_ms_value_model = Model.PropertyModel[float]() def update_exposure_time_ms( exposure_time_ms: typing.Optional[float]) -> None: if exposure_time_ms is not None and exposure_time_ms > 0 and isinstance( camera_hardware_source, camera_base.CameraHardwareSource): frame_parameters = camera_hardware_source.get_frame_parameters( 0) frame_parameters.exposure_ms = exposure_time_ms camera_hardware_source.set_frame_parameters( 0, frame_parameters) self.__update_estimate() self.__exposure_time_ms_value_model.on_value_changed = update_exposure_time_ms exposure_time_ms_value_binding = Binding.PropertyBinding( self.__exposure_time_ms_value_model, "value", converter=Converter.FloatToStringConverter("{0:.1f}")) def eels_profile_parameters_changed( profile_index: int, frame_parameters: camera_base.CameraFrameParameters) -> None: if profile_index == 0 and isinstance( camera_hardware_source, camera_base.CameraHardwareSource): expected_dimensions = camera_hardware_source.get_expected_dimensions( frame_parameters.binning) self.__camera_width = expected_dimensions[1] self.__camera_height = expected_dimensions[0] if self.__exposure_time_ms_value_model: self.__exposure_time_ms_value_model.value = frame_parameters.exposure_ms self.__update_estimate() self.__eels_frame_parameters_changed_event_listener = camera_hardware_source.frame_parameters_changed_event.listen( eels_profile_parameters_changed) eels_profile_parameters_changed( 0, camera_hardware_source.get_frame_parameters(0)) typing.cast(UserInterfaceModule.LineEditWidget, self.__exposure_time_widget._widget).bind_text( exposure_time_ms_value_binding ) # the widget will close the binding
def __init__(self, window: Window.Window, profile: Profile.Profile): content_widget = window.ui.create_column_widget() super().__init__(content_widget) ui = window.ui self._tree_model = TreeModel(profile) def closed_items_changed(closed_items: typing.Set[str]) -> None: profile.closed_items = list(closed_items) self._tree_model.on_closed_items_changed = closed_items_changed self._tree_selection = Selection.IndexedSelection( Selection.Style.multiple) projects_list_widget = Widgets.ListWidget( ui, ProjectTreeCanvasItemDelegate(window, self._tree_model), selection=self._tree_selection, v_scroll_enabled=False, v_auto_resize=True) projects_list_widget.wants_drag_events = True projects_list_widget.bind_items( Binding.PropertyBinding(self._tree_model, "value")) projects_section = Widgets.SectionWidget(ui, _("Projects"), projects_list_widget) projects_section.expanded = True content_widget.add(projects_section) # configure an observer for watching for project references changes. # this serves as the master updater for changes. move to document controller? def project_references_changed(item: Observer.ItemValue) -> None: # update the tree model. project_references = typing.cast( typing.Sequence[Profile.ProjectReference], item) self._tree_model.update_project_references(project_references) oo = Observer.ObserverBuilder() oo.source(profile).ordered_sequence_from_array( "project_references").collect_list().action_fn( project_references_changed) self.__projects_model_observer = typing.cast( Observer.AbstractItemSource, oo.make_observable())
def test_table_widget_handles_pending_updates_in_close(self): from nion.ui import Widgets ui = TestUI.UserInterface() def create_item(item): return ui.create_label_widget(item) widget = Widgets.TableWidget(ui, create_item) list_model = ListModel.ListModel() widget.bind_items(Binding.ListBinding(list_model, "items")) with contextlib.closing(widget): list_model.insert_item(0, "abc") list_model.insert_item(1, "abc") list_model.remove_item(0) self.assertEqual(3, len(widget.pending_queued_tasks)) self.assertEqual(0, len(widget.pending_queued_tasks)) widget.run_pending_keyed_tasks()
def test_inserting_and_removing_item_into_binding_notifies_target(self): list_model = ListModel.ListModel("items") binding = Binding.ListBinding(list_model, "items") list_copy = list() def inserter(value: str, index: int) -> None: list_copy.insert(index, value) def remover(index: int) -> None: del list_copy[index] binding.inserter = inserter binding.remover = remover list_model.insert_item(0, "zero") list_model.insert_item(1, "one") self.assertEqual(len(list_copy), 2) self.assertEqual(list_copy[1], "one") list_model.remove_item(0) self.assertEqual(len(list_copy), 1) self.assertEqual(list_copy[0], "one")
def create_panel_widget(self, ui, document_controller): self.__scan_hardware_source_choice = HardwareSourceChoice.HardwareSourceChoice( ui._ui, "scan_acquisition_hardware_source_id", lambda hardware_source: hardware_source.features.get("is_scanning")) column = ui.create_column_widget() # define the main controls source_combo_box = self.__scan_hardware_source_choice.create_combo_box( ui._ui) count_line_edit = ui.create_line_edit_widget() grab_button = ui.create_push_button_widget(_("Grab Previous")) record_button = ui.create_push_button_widget(_("Record Next")) cancel_button = ui.create_push_button_widget(_("Cancel")) progress_bar = ui._ui.create_progress_bar_widget(properties={ "height": 18, "min-width": 200 }) progress_bar.minimum = 0 progress_bar.maximum = 100 # define the layout source_row = ui.create_row_widget() source_row.add_spacing(12) source_row.add(WidgetWrapper(source_combo_box)) source_row.add_spacing(12) source_row.add_stretch() count_row = ui.create_row_widget() count_row.add_spacing(12) count_row.add(ui.create_label_widget(_("Frames"))) count_row.add_spacing(12) count_row.add(count_line_edit) count_row.add_spacing(12) count_row.add_stretch() button_row = ui.create_row_widget() button_row.add_spacing(12) button_row.add(grab_button) button_row.add_spacing(12) button_row.add(record_button) button_row.add_spacing(12) button_row.add(cancel_button) button_row.add_spacing(12) button_row.add_stretch() progress_bar_row = ui.create_row_widget() progress_bar_row.add_stretch() progress_bar_row.add_spacing(12) progress_bar_row.add(WidgetWrapper(progress_bar)) progress_bar_row.add_spacing(12) progress_bar_row.add_stretch() column.add_spacing(8) column.add(source_row) column.add(count_row) column.add(button_row) column.add(progress_bar_row) column.add_spacing(8) column.add_stretch() # connect the pieces def state_property_changed(property): if not self.__scan_hardware_source: source_combo_box.enabled = True count_line_edit._widget.enabled = False grab_button._widget.enabled = False record_button._widget.enabled = False cancel_button._widget.enabled = False elif self.__controller.state.value == "idle": source_combo_box.enabled = True count_line_edit._widget.enabled = True grab_button._widget.enabled = True record_button._widget.enabled = True cancel_button._widget.enabled = False elif self.__controller.state.value == "running": source_combo_box.enabled = False count_line_edit._widget.enabled = False grab_button._widget.enabled = False record_button._widget.enabled = False cancel_button._widget.enabled = True def scan_hardware_source_changed(hardware_source): self.__scan_hardware_source = hardware_source state_property_changed("value") self.__scan_hardware_changed_event_listener = self.__scan_hardware_source_choice.hardware_source_changed_event.listen( scan_hardware_source_changed) count_line_edit._widget.bind_text( Binding.PropertyBinding( self.__controller.frame_count_model, "value", converter=Converter.IntegerToStringConverter(), validator=Validator.IntegerRangeValidator(1, 100))) self.__state_changed_listener = self.__controller.state.property_changed_event.listen( state_property_changed) progress_bar.bind_value( Binding.PropertyBinding(self.__controller.progress_model, "value")) event_loop = document_controller._document_controller.event_loop def grab(): event_loop.create_task( self.__controller.grab( document_controller._document_controller, self.__scan_hardware_source, False)) def record(): event_loop.create_task( self.__controller.grab( document_controller._document_controller, self.__scan_hardware_source, True)) grab_button.on_clicked = grab record_button.on_clicked = record cancel_button.on_clicked = self.__controller.cancel scan_hardware_source_changed( self.__scan_hardware_source_choice.hardware_source) return column
def create_panel_widget( self, ui: Facade.UserInterface, document_controller: Facade.DocumentWindow) -> Facade.ColumnWidget: stem_controller_ = typing.cast( stem_controller.STEMController, Registry.get_component("stem_controller")) self.__scan_hardware_source_choice_model = ui._ui.create_persistent_string_model( "scan_acquisition_hardware_source_id") self.__scan_hardware_source_choice = HardwareSourceChoice.HardwareSourceChoice( self.__scan_hardware_source_choice_model, lambda hardware_source: hardware_source.features.get( "is_scanning", False)) self.__camera_hardware_source_choice_model = ui._ui.create_persistent_string_model( "scan_acquisition_camera_hardware_source_id") self.__camera_hardware_source_choice = HardwareSourceChoice.HardwareSourceChoice( self.__camera_hardware_source_choice_model, lambda hardware_source: hardware_source.features.get( "is_camera", False)) self.__scan_hardware_source_stream = HardwareSourceChoice.HardwareSourceChoiceStream( self.__scan_hardware_source_choice).add_ref() self.__camera_hardware_source_stream = HardwareSourceChoice.HardwareSourceChoiceStream( self.__camera_hardware_source_choice).add_ref() def clear_scan_context_fields() -> None: self.__roi_description.text = _("Scan context not active") self.__scan_label_widget.text = None self.__scan_specifier.scan_context = stem_controller.ScanContext() self.__scan_specifier.scan_count = 1 self.__scan_specifier.size = None self.__scan_specifier.drift_interval_lines = 0 self.__scan_specifier.drift_interval_scans = 0 self.__acquire_button._widget.enabled = self.__acquisition_state == SequenceState.scanning # focus will be on the SI data, so enable if scanning self.__scan_pixels = 0 def update_context() -> None: assert self.__scan_hardware_source_choice scan_hardware_source = typing.cast( scan_base.ScanHardwareSource, self.__scan_hardware_source_choice.hardware_source) if not scan_hardware_source: clear_scan_context_fields() return scan_context = scan_hardware_source.scan_context scan_context_size = scan_context.size exposure_ms = self.__exposure_time_ms_value_model.value or 0.0 if self.__exposure_time_ms_value_model else 0.0 if scan_context.is_valid and scan_hardware_source.line_scan_enabled and scan_hardware_source.line_scan_vector: assert scan_context_size calibration = scan_context.calibration start = Geometry.FloatPoint.make( scan_hardware_source.line_scan_vector[0]) end = Geometry.FloatPoint.make( scan_hardware_source.line_scan_vector[1]) length = int( Geometry.distance(start, end) * scan_context_size.height) max_dim = max(scan_context_size.width, scan_context_size.height) length_str = calibration.convert_to_calibrated_size_str( length, value_range=(0, max_dim), samples=max_dim) line_str = _("Line Scan") self.__roi_description.text = f"{line_str} {length_str} ({length} px)" scan_str = _("Scan (1D)") scan_length = max(self.__scan_width, 1) self.__scan_label_widget.text = f"{scan_str} {scan_length} px" self.__scan_pixels = scan_length self.__scan_specifier.scan_context = copy.deepcopy( scan_context) self.__scan_specifier.scan_count = max(self.__scan_count, 1) self.__scan_specifier.size = 1, scan_length self.__scan_specifier.drift_interval_lines = 0 self.__scan_specifier.drift_interval_scans = 0 self.__acquire_button._widget.enabled = True elif scan_context.is_valid and scan_hardware_source.subscan_enabled and scan_hardware_source.subscan_region: assert scan_context_size calibration = scan_context.calibration width = scan_hardware_source.subscan_region.width * scan_context_size.width height = scan_hardware_source.subscan_region.height * scan_context_size.height width_str = calibration.convert_to_calibrated_size_str( width, value_range=(0, scan_context_size.width), samples=scan_context_size.width) height_str = calibration.convert_to_calibrated_size_str( height, value_range=(0, scan_context_size.height), samples=scan_context_size.height) rect_str = _("Subscan") self.__roi_description.text = f"{rect_str} {width_str} x {height_str} ({int(width)} px x {int(height)} px)" scan_str = _("Scan (2D)") scan_width = self.__scan_width scan_height = int(self.__scan_width * height / width) drift_lines = scan_hardware_source.calculate_drift_lines( scan_width, exposure_ms / 1000) if scan_hardware_source else 0 drift_str = f" / Drift {drift_lines} lines" if drift_lines > 0 else str( ) drift_scans = scan_hardware_source.calculate_drift_scans() drift_str = f" / Drift {drift_scans} scans" if drift_scans > 0 else drift_str self.__scan_label_widget.text = f"{scan_str} {scan_width} x {scan_height} px" + drift_str self.__scan_pixels = scan_width * scan_height self.__scan_specifier.scan_context = copy.deepcopy( scan_context) self.__scan_specifier.scan_count = max(self.__scan_count, 1) self.__scan_specifier.size = scan_height, scan_width self.__scan_specifier.drift_interval_lines = drift_lines self.__scan_specifier.drift_interval_scans = drift_scans self.__acquire_button._widget.enabled = True elif scan_context.is_valid: assert scan_context_size calibration = scan_context.calibration width = scan_context_size.width height = scan_context_size.height width_str = calibration.convert_to_calibrated_size_str( width, value_range=(0, scan_context_size.width), samples=scan_context_size.width) height_str = calibration.convert_to_calibrated_size_str( height, value_range=(0, scan_context_size.height), samples=scan_context_size.height) data_str = _("Context Scan") self.__roi_description.text = f"{data_str} {width_str} x {height_str} ({int(width)} x {int(height)})" scan_str = _("Scan (2D)") scan_width = self.__scan_width scan_height = int(self.__scan_width * height / width) drift_lines = scan_hardware_source.calculate_drift_lines( scan_width, exposure_ms / 1000) if scan_hardware_source else 0 drift_str = f" / Drift {drift_lines} lines" if drift_lines > 0 else str( ) drift_scans = scan_hardware_source.calculate_drift_scans() drift_str = f" / Drift {drift_scans} scans" if drift_scans > 0 else drift_str self.__scan_label_widget.text = f"{scan_str} {scan_width} x {scan_height} px" + drift_str self.__scan_pixels = scan_width * scan_height self.__scan_specifier.scan_context = copy.deepcopy( scan_context) self.__scan_specifier.scan_count = max(self.__scan_count, 1) self.__scan_specifier.size = scan_height, scan_width self.__scan_specifier.drift_interval_lines = drift_lines self.__scan_specifier.drift_interval_scans = drift_scans self.__acquire_button._widget.enabled = True else: clear_scan_context_fields() self.__scan_count_widget.text = Converter.IntegerToStringConverter( ).convert(self.__scan_count) self.__scan_width_widget.text = Converter.IntegerToStringConverter( ).convert(self.__scan_width) self.__update_estimate() def stem_controller_property_changed(key: str) -> None: if key in ("subscan_state", "subscan_region", "subscan_rotation", "line_scan_state", "line_scan_vector", "drift_channel_id", "drift_region", "drift_settings"): document_controller._document_controller.event_loop.call_soon_threadsafe( update_context) def scan_context_changed() -> None: # this can be triggered from a thread, so use call soon to transfer it to the UI thread. document_controller._document_controller.event_loop.call_soon_threadsafe( update_context) self.__stem_controller_property_listener = None self.__scan_context_changed_listener = None if stem_controller_: self.__stem_controller_property_listener = stem_controller_.property_changed_event.listen( stem_controller_property_changed) self.__scan_context_changed_listener = stem_controller_.scan_context_changed_event.listen( scan_context_changed) column = ui.create_column_widget() self.__styles_list_model = ListModel.ListModel[ ScanAcquisitionProcessing](items=[ ScanAcquisitionProcessing.SUM_PROJECT, ScanAcquisitionProcessing.NONE ]) self.__styles_list_property_model = ListModel.ListPropertyModel( self.__styles_list_model) self.__style_combo_box = ui.create_combo_box_widget( self.__styles_list_property_model.value, item_text_getter=operator.attrgetter("value.display_name")) self.__style_combo_box._widget.set_property("min-width", 100) items_binding = Binding.PropertyBinding( self.__styles_list_property_model, "value") items_binding.source_setter = None typing.cast(UserInterfaceModule.ComboBoxWidget, self.__style_combo_box._widget).bind_items(items_binding) self.__style_combo_box.current_index = 0 self.__acquire_button = ui.create_push_button_widget(_("Acquire")) self.__progress_bar = ui.create_progress_bar_widget() # self.__progress_bar.enabled = False self.__roi_description = ui.create_label_widget() self.__scan_count_widget = ui.create_line_edit_widget() self.__scan_count_widget._widget.set_property("width", 72) self.__scan_processing_widget = ui.create_combo_box_widget( items=["Raw", "Sum", "Raw + Sum"]) self.__scan_width_widget = ui.create_line_edit_widget() self.__exposure_time_widget = ui.create_line_edit_widget() self.__estimate_label_widget = ui.create_label_widget() self.__scan_label_widget = ui.create_label_widget() class ComboBoxWidget: def __init__(self, widget: UserInterfaceModule.ComboBoxWidget) -> None: self.__combo_box_widget = widget @property def _widget(self) -> UserInterfaceModule.ComboBoxWidget: return self.__combo_box_widget camera_row = ui.create_row_widget() camera_row.add_spacing(12) camera_row.add( ComboBoxWidget( self.__camera_hardware_source_choice.create_combo_box(ui._ui))) camera_row.add_spacing(12) camera_row.add(self.__style_combo_box) camera_row.add_spacing(12) camera_row.add_stretch() scan_choice_row = ui.create_row_widget() scan_choice_row.add_spacing(12) scan_choice_row.add( ComboBoxWidget( self.__scan_hardware_source_choice.create_combo_box(ui._ui))) scan_choice_row.add_spacing(12) scan_choice_row.add_stretch() scan_count_row = ui.create_row_widget() scan_count_row.add_spacing(12) scan_count_row.add(ui.create_label_widget("Scan Count")) scan_count_row.add_spacing(12) scan_count_row.add(self.__scan_count_widget) scan_count_row.add_spacing(12) scan_count_row.add(self.__scan_processing_widget) scan_count_row.add_spacing(12) scan_count_row.add_stretch() roi_size_row = ui.create_row_widget() roi_size_row.add_spacing(12) roi_size_row.add(self.__roi_description) roi_size_row.add_spacing(12) roi_size_row.add_stretch() scan_spacing_pixels_row = ui.create_row_widget() scan_spacing_pixels_row.add_spacing(12) scan_spacing_pixels_row.add( ui.create_label_widget("Scan Width (pixels)")) scan_spacing_pixels_row.add_spacing(12) scan_spacing_pixels_row.add(self.__scan_width_widget) scan_spacing_pixels_row.add_spacing(12) scan_spacing_pixels_row.add_stretch() eels_exposure_row = ui.create_row_widget() eels_exposure_row.add_spacing(12) eels_exposure_row.add( ui.create_label_widget("Camera Exposure Time (ms)")) eels_exposure_row.add_spacing(12) eels_exposure_row.add(self.__exposure_time_widget) eels_exposure_row.add_spacing(12) eels_exposure_row.add_stretch() scan_row = ui.create_row_widget() scan_row.add_spacing(12) scan_row.add(self.__scan_label_widget) scan_row.add_stretch() estimate_row = ui.create_row_widget() estimate_row.add_spacing(12) estimate_row.add(self.__estimate_label_widget) estimate_row.add_stretch() acquire_sequence_button_row = ui.create_row_widget() acquire_sequence_button_row.add(self.__acquire_button) acquire_sequence_button_row.add_spacing(8) acquire_sequence_button_row.add(self.__progress_bar) acquire_sequence_button_row.add_spacing(8) if self.__scan_hardware_source_choice.hardware_source_count > 1: column.add_spacing(8) column.add(scan_choice_row) column.add_spacing(8) column.add(camera_row) column.add_spacing(8) column.add(scan_count_row) column.add_spacing(8) column.add(roi_size_row) column.add_spacing(8) column.add(scan_spacing_pixels_row) column.add_spacing(8) column.add(eels_exposure_row) column.add_spacing(8) column.add(scan_row) column.add_spacing(8) column.add(estimate_row) column.add_spacing(8) column.add(acquire_sequence_button_row) column.add_spacing(8) column.add_stretch() def camera_hardware_source_changed( hardware_source: typing.Optional[HardwareSource.HardwareSource] ) -> None: styles_list_model = self.__styles_list_model self.disconnect_camera_hardware_source() if hardware_source and styles_list_model: self.connect_camera_hardware_source(hardware_source) if hardware_source.features.get("has_masked_sum_option"): styles_list_model.items = [ ScanAcquisitionProcessing.SUM_PROJECT, ScanAcquisitionProcessing.NONE, ScanAcquisitionProcessing.SUM_MASKED ] else: styles_list_model.items = [ ScanAcquisitionProcessing.SUM_PROJECT, ScanAcquisitionProcessing.NONE ] self.__camera_hardware_changed_event_listener = self.__camera_hardware_source_choice.hardware_source_changed_event.listen( camera_hardware_source_changed) camera_hardware_source_changed( self.__camera_hardware_source_choice.hardware_source) def style_current_item_changed(current_item: str) -> None: self.__update_estimate() self.__style_combo_box.on_current_item_changed = style_current_item_changed def scan_count_changed(text: str) -> None: scan_count = Converter.IntegerToStringConverter().convert_back( text) or 1 scan_count = max(scan_count, 1) if scan_count != self.__scan_count: self.__scan_count = scan_count update_context() self.__scan_count_widget.request_refocus() self.__scan_count_widget.on_editing_finished = scan_count_changed def scan_width_changed(text: str) -> None: scan_width = Converter.IntegerToStringConverter().convert_back( text) or 1 scan_width = max(scan_width, 1) if scan_width != self.__scan_width: self.__scan_width = scan_width update_context() self.__scan_width_widget.request_refocus() self.__scan_width_widget.on_editing_finished = scan_width_changed def acquisition_state_changed( acquisition_state: SequenceState) -> None: self.__acquisition_state = acquisition_state async def update_state(is_idle: bool) -> None: self.__acquire_button.text = _("Acquire") if is_idle else _( "Cancel") # self.__progress_bar.enabled = not is_idle update_context() # update the cancel button if is_idle and self.__progress_task: self.__progress_task.cancel() self.__progress_task = None self.__progress_bar.value = 100 if not is_idle and not self.__progress_task: async def update_progress() -> None: while True: if self.__scan_acquisition_controller: self.__progress_bar.value = int( 100 * self.__scan_acquisition_controller.progress ) await asyncio.sleep(0.25) self.__progress_task = document_controller._document_window.event_loop.create_task( update_progress()) if acquisition_state == SequenceState.idle: self.__scan_acquisition_controller = None if self.__acquisition_state_changed_event_listener: self.__acquisition_state_changed_event_listener.close() self.__acquisition_state_changed_event_listener = None document_controller._document_window.event_loop.create_task( update_state(True)) else: document_controller._document_window.event_loop.create_task( update_state(False)) def acquire_sequence() -> None: if self.__scan_acquisition_controller: if self.__scan_acquisition_controller: self.__scan_acquisition_controller.cancel() else: scan_hardware_source_choice = self.__scan_hardware_source_choice assert scan_hardware_source_choice if scan_hardware_source_choice.hardware_source: scan_hardware_source = self.__api.get_hardware_source_by_id( scan_hardware_source_choice.hardware_source. hardware_source_id, version="1.0") else: scan_hardware_source = None camera_hardware_source_choice = self.__camera_hardware_source_choice assert camera_hardware_source_choice if camera_hardware_source_choice.hardware_source: camera_hardware_source = self.__api.get_hardware_source_by_id( camera_hardware_source_choice.hardware_source. hardware_source_id, version="1.0") else: camera_hardware_source = None if scan_hardware_source and camera_hardware_source: self.__scan_acquisition_controller = ScanAcquisitionController( self.__api, document_controller, scan_hardware_source, camera_hardware_source, self.__scan_specifier) self.__acquisition_state_changed_event_listener = self.__scan_acquisition_controller.acquisition_state_changed_event.listen( acquisition_state_changed) scan_processing = ScanProcessing( self.__scan_processing_widget.current_index in (0, 2), self.__scan_processing_widget.current_index in (1, 2)) scan_acquisition_processing = self.__style_combo_box.current_item if self.__style_combo_box and self.__style_combo_box.current_item else ScanAcquisitionProcessing.NONE self.__scan_acquisition_controller.start( scan_acquisition_processing, scan_processing) self.__acquire_button.on_clicked = acquire_sequence self.__update_estimate() update_context() return column
def __init__(self, document_controller: DocumentController.DocumentController, data_item: DataItem.DataItem) -> None: ui = document_controller.ui super().__init__(ui, _("Recorder"), parent_window=document_controller, persistent_id="Recorder" + str(data_item.uuid)) self.__recorder = Recorder(document_controller, data_item) self.ui = ui self.document_controller = document_controller self.__data_item = data_item self.__record_button = ui.create_push_button_widget(_("Record")) def thumbnail_widget_drag(mime_data: UserInterface.MimeData, thumbnail: typing.Optional[ DrawingContext.RGBA32Type], hot_spot_x: int, hot_spot_y: int) -> None: # use this convoluted base object for drag so that it doesn't disappear after the drag. self.content.drag(mime_data, thumbnail, hot_spot_x, hot_spot_y) display_item = document_controller.document_model.get_display_item_for_data_item( data_item) data_item_thumbnail_source = DataItemThumbnailWidget.DataItemThumbnailSource( ui, display_item=display_item) data_item_chooser_widget = DataItemThumbnailWidget.ThumbnailWidget( ui, data_item_thumbnail_source, Geometry.IntSize(48, 48)) data_item_chooser_widget.on_drag = thumbnail_widget_drag self.__recording_interval_property = Model.PropertyModel(1000) self.__recording_count_property = Model.PropertyModel(20) recording_period_widget = ui.create_line_edit_widget( properties={"width": 60}) recording_period_widget.bind_text( Binding.PropertyBinding( self.__recording_interval_property, "value", converter=Converter.IntegerToStringConverter())) recording_count_widget = ui.create_line_edit_widget( properties={"width": 60}) recording_count_widget.bind_text( Binding.PropertyBinding( self.__recording_count_property, "value", converter=Converter.IntegerToStringConverter())) row0 = ui.create_row_widget() row0.add_stretch() row0.add_spacing(8) row0.add(self.__record_button) row0.add_spacing(8) row1 = ui.create_row_widget() row1.add(ui.create_label_widget(_("Interval"))) row1.add_spacing(8) row1.add(recording_period_widget) row1.add_spacing(4) row1.add(ui.create_label_widget(_("msec"))) row1.add_spacing(8) row1.add_stretch() row2 = ui.create_row_widget() row2.add(ui.create_label_widget(_("Frames"))) row2.add_spacing(8) row2.add(recording_count_widget) row2.add_spacing(8) row2.add_stretch() column1 = ui.create_column_widget() column1.add(row1) column1.add_spacing(4) column1.add(row2) column1.add_spacing(4) column1.add(row0) button_row = ui.create_row_widget() button_row.add_spacing(8) button_row.add(data_item_chooser_widget) button_row.add_spacing(8) button_row.add_stretch() button_row.add_spacing(8) button_row.add(column1) button_row.add_spacing(8) def record_pressed() -> None: if self.__recorder.recording_state == "recording": self.__recorder.stop_recording() else: recording_interval = self.__recording_interval_property.value or 0.0 recording_count = self.__recording_count_property.value or 1 self.__recorder.start_recording(time.time(), recording_interval / 1000, recording_count) self.__record_button.on_clicked = record_pressed column = self.content column.add_spacing(6) column.add(button_row) column.add_spacing(6) def live_state_changed(is_live: bool) -> None: self.__record_button.enabled = is_live def recording_state_changed(recording_state: str) -> None: if recording_state == "recording": self.__record_button.text = _("Stop") else: self.__record_button.text = _("Record") def data_item_removed() -> None: self.request_close() self.__recorder.on_live_state_changed = live_state_changed self.__recorder.on_recording_state_changed = recording_state_changed self.__recorder.on_data_item_removed = data_item_removed live_state_changed(data_item.is_live) recording_state_changed("stopped")
def create_panel_widget( self, ui: Facade.UserInterface, document_controller: Facade.DocumentWindow) -> Facade.ColumnWidget: # note: anything created here should be disposed in close. # this method may be called more than once. self.__controller = Controller() self.__scan_hardware_source_choice_model = ui._ui.create_persistent_string_model( "scan_acquisition_hardware_source_id") self.__scan_hardware_source_choice = HardwareSourceChoice.HardwareSourceChoice( self.__scan_hardware_source_choice_model, lambda hardware_source: hardware_source.features.get( "is_scanning", False)) column = ui.create_column_widget() # define the main controls source_combo_box = self.__scan_hardware_source_choice.create_combo_box( ui._ui) count_line_edit = ui.create_line_edit_widget() grab_button = ui.create_push_button_widget(_("Grab Previous")) record_button = ui.create_push_button_widget(_("Record Next")) cancel_button = ui.create_push_button_widget(_("Cancel")) progress_bar = ui._ui.create_progress_bar_widget(properties={ "height": 18, "min-width": 200 }) progress_bar.minimum = 0 progress_bar.maximum = 100 # define the layout source_row = ui.create_row_widget() source_row.add_spacing(12) source_row.add(WidgetWrapper[UserInterfaceModule.ComboBoxWidget]( source_combo_box)) source_row.add_spacing(12) source_row.add_stretch() count_row = ui.create_row_widget() count_row.add_spacing(12) count_row.add(ui.create_label_widget(_("Frames"))) count_row.add_spacing(12) count_row.add(count_line_edit) count_row.add_spacing(12) count_row.add_stretch() button_row = ui.create_row_widget() button_row.add_spacing(12) button_row.add(grab_button) button_row.add_spacing(12) button_row.add(record_button) button_row.add_spacing(12) button_row.add(cancel_button) button_row.add_spacing(12) button_row.add_stretch() progress_bar_row = ui.create_row_widget() progress_bar_row.add_stretch() progress_bar_row.add_spacing(12) progress_bar_row.add( WidgetWrapper[UserInterfaceModule.ProgressBarWidget](progress_bar)) progress_bar_row.add_spacing(12) progress_bar_row.add_stretch() column.add_spacing(8) column.add(source_row) column.add(count_row) column.add(button_row) column.add(progress_bar_row) column.add_spacing(8) column.add_stretch() # connect the pieces def state_property_changed(property: str) -> None: if not self.__scan_hardware_source: source_combo_box.enabled = True count_line_edit._widget.enabled = False grab_button._widget.enabled = False record_button._widget.enabled = False cancel_button._widget.enabled = False elif self.__controller and self.__controller.state.value == "idle": source_combo_box.enabled = True count_line_edit._widget.enabled = True grab_button._widget.enabled = True record_button._widget.enabled = True cancel_button._widget.enabled = False elif self.__controller and self.__controller.state.value == "running": source_combo_box.enabled = False count_line_edit._widget.enabled = False grab_button._widget.enabled = False record_button._widget.enabled = False cancel_button._widget.enabled = True def scan_hardware_source_changed( hardware_source: typing.Optional[HardwareSource.HardwareSource] ) -> None: if isinstance(hardware_source, scan_base.ScanHardwareSource): self.__scan_hardware_source = hardware_source state_property_changed("value") self.__scan_hardware_changed_event_listener = self.__scan_hardware_source_choice.hardware_source_changed_event.listen( scan_hardware_source_changed) typing.cast(UserInterfaceModule.LineEditWidget, count_line_edit._widget).bind_text( Binding.PropertyBinding( self.__controller.frame_count_model, "value", converter=Converter.IntegerToStringConverter(), validator=Validator.IntegerRangeValidator(1, 100))) self.__state_changed_listener = self.__controller.state.property_changed_event.listen( state_property_changed) progress_bar.bind_value( Binding.PropertyBinding(self.__controller.progress_model, "value")) event_loop = document_controller._document_controller.event_loop def grab() -> None: if self.__controller and self.__scan_hardware_source: event_loop.create_task( self.__controller.grab( document_controller._document_controller, self.__scan_hardware_source, False)) def record() -> None: if self.__controller and self.__scan_hardware_source: event_loop.create_task( self.__controller.grab( document_controller._document_controller, self.__scan_hardware_source, True)) grab_button.on_clicked = grab record_button.on_clicked = record cancel_button.on_clicked = self.__controller.cancel scan_hardware_source_changed( self.__scan_hardware_source_choice.hardware_source) return column
def test_tuple_property_binding_refcount(self) -> None: binding = Binding.TuplePropertyBinding(Model.PropertyModel((1, 2, 3)), "value", 1) binding_ref = weakref.ref(binding) del binding self.assertIsNone(binding_ref())
def test_property_attribute_binding_refcount(self) -> None: binding = Binding.PropertyAttributeBinding( Model.PropertyModel(Geometry.FloatPoint()), "value", "x") binding_ref = weakref.ref(binding) del binding self.assertIsNone(binding_ref())
def test_property_binding_refcount(self) -> None: binding = Binding.PropertyBinding(Model.PropertyModel(0), "value") binding_ref = weakref.ref(binding) del binding self.assertIsNone(binding_ref())
def __connect_pick_graphic(self, src, target, pick_graphic, computation, do_wait=-1): def _update_collection_index(axis, value): if src.xdata.is_collection or src.xdata.is_sequence: display_item = self.__api.application._application.document_model.get_display_item_for_data_item( src._data_item) collection_index = display_item.display_data_channel.collection_index if axis == 0: if value != collection_index[0]: display_item.display_data_channel.collection_index = ( value, collection_index[1], 0) else: if value != collection_index[1]: display_item.display_data_channel.collection_index = ( collection_index[0], value, 0) else: libertem_metadata = copy.deepcopy( src.metadata.get('libertem-io')) if not libertem_metadata: return file_parameters = libertem_metadata['file_parameters'] file_type = file_parameters.pop('type') current_index = libertem_metadata['display_slice']['start'] current_index = np.unravel_index(current_index, target.data.shape) if value == current_index[axis]: return executor = Registry.get_component('libertem_executor') if not executor: return executor = executor.ensure_sync() ds = dataset.load(file_type, executor, **file_parameters) roi = np.zeros(ds.shape.nav, dtype=bool) if axis == 0: roi[value, current_index[1]] = True current_index = (value, current_index[1]) else: roi[current_index[0], value] = True current_index = (current_index[0], value) result = UDFRunner(PickUDF()).run_for_dataset(ds, executor, roi=roi) result_array = np.squeeze(np.array(result['intensity'])) new_metadata = copy.deepcopy(src.metadata) new_display_slice = np.ravel_multi_index( current_index, target.data.shape) new_metadata['libertem-io']['display_slice'][ 'start'] = new_display_slice new_xdata = self.__api.create_data_and_metadata( result_array, metadata=new_metadata) src.set_data_and_metadata(new_xdata) if do_wait > 0: starttime = time.time() while target.data is None: if time.time() - starttime > do_wait: break time.sleep(0.1) if target.data is None: return shape = target.data.shape computation.pick_graphic_binding_0 = Binding.TuplePropertyBinding( pick_graphic._graphic, 'position', 0, converter=FloatTupleToIntTupleConverter(shape[0], 0)) computation.pick_graphic_binding_1 = Binding.TuplePropertyBinding( pick_graphic._graphic, 'position', 1, converter=FloatTupleToIntTupleConverter(shape[1], 1)) computation.pick_graphic_binding_0.target_setter = functools.partial( _update_collection_index, 0) computation.pick_graphic_binding_1.target_setter = functools.partial( _update_collection_index, 1) def collection_index_changed(key): if src.xdata.is_collection: display_item = self.__api.application._application.document_model.get_display_item_for_data_item( src._data_item) if key == 'collection_index': collection_index = display_item.display_data_channel.collection_index if int(pick_graphic.position[0] * shape[0]) != collection_index[0]: computation.pick_graphic_binding_0.update_source( collection_index) if int(pick_graphic.position[1] * shape[1]) != collection_index[1]: computation.pick_graphic_binding_1.update_source( collection_index) if src.xdata.is_collection: display_item = self.__api.application._application.document_model.get_display_item_for_data_item( src._data_item) computation.collection_index_changed_event_listener = display_item.display_data_channel.property_changed_event.listen( collection_index_changed)
def __init__(self, document_controller, instrument: InstrumentDevice.Instrument): super().__init__( document_controller.ui.create_column_widget(properties={ "margin": 6, "spacing": 2 })) self.document_controller = document_controller ui = document_controller.ui sample_combo_box = ui.create_combo_box_widget(instrument.sample_titles) sample_combo_box.current_index = instrument.sample_index sample_combo_box.bind_current_index( Binding.PropertyBinding(instrument, "sample_index")) voltage_field = ui.create_line_edit_widget() voltage_field.bind_text( Binding.PropertyBinding( instrument, "voltage", converter=Converter.PhysicalValueToStringConverter( units="keV", multiplier=1E-3))) beam_current_field = ui.create_line_edit_widget() beam_current_field.bind_text( ControlBinding(instrument, "BeamCurrent", converter=Converter.PhysicalValueToStringConverter( units="pA", multiplier=1E12))) stage_position_widget = PositionWidget(ui, _("Stage"), instrument, "stage_position_m") drift_widget = PositionWidget(ui, _("Drift"), instrument, "Drift") beam_shift_widget = PositionWidget(ui, _("Beam"), instrument, "beam_shift_m") defocus_field = ui.create_line_edit_widget() defocus_field.bind_text( ControlBinding(instrument, "C10", converter=Converter.PhysicalValueToStringConverter( units="nm", multiplier=1E9))) c12_widget = PositionWidget(ui, _("C12"), instrument, "C12") c21_widget = PositionWidget(ui, _("C21"), instrument, "C21") c23_widget = PositionWidget(ui, _("C23"), instrument, "C23") c3_field = ui.create_line_edit_widget() c3_field.bind_text( ControlBinding(instrument, "C30", converter=Converter.PhysicalValueToStringConverter( units="nm", multiplier=1E9))) c32_widget = PositionWidget(ui, _("C32"), instrument, "C32") c34_widget = PositionWidget(ui, _("C34"), instrument, "C34") blanked_checkbox = ui.create_check_box_widget(_("Beam Blanked")) blanked_checkbox.bind_checked( Binding.PropertyBinding(instrument, "is_blanked")) slit_in_checkbox = ui.create_check_box_widget(_("Slit In")) slit_in_checkbox.bind_checked( Binding.PropertyBinding(instrument, "is_slit_in")) voa_in_checkbox = ui.create_check_box_widget(_("VOA In")) voa_in_checkbox.bind_checked(ControlBinding(instrument, "S_VOA")) convergenve_angle_field = ui.create_line_edit_widget() convergenve_angle_field.bind_text( ControlBinding(instrument, "ConvergenceAngle", converter=Converter.PhysicalValueToStringConverter( units="mrad", multiplier=1E3))) c_aperture_widget = PositionWidget(ui, _("CAperture"), instrument, "CAperture", unit="mrad", multiplier=1E3) aperture_round_widget = PositionWidget(ui, _("ApertureRound"), instrument, "ApertureRound", unit="", multiplier=1) energy_offset_field = ui.create_line_edit_widget() energy_offset_field.bind_text( Binding.PropertyBinding( instrument, "energy_offset_eV", converter=Converter.FloatToStringConverter())) energy_dispersion_field = ui.create_line_edit_widget() energy_dispersion_field.bind_text( Binding.PropertyBinding( instrument, "energy_per_channel_eV", converter=Converter.FloatToStringConverter())) beam_row = ui.create_row_widget() beam_row.add_spacing(8) beam_row.add(blanked_checkbox) beam_row.add_spacing(8) beam_row.add(voa_in_checkbox) beam_row.add_stretch() eels_row = ui.create_row_widget() eels_row.add_spacing(8) eels_row.add(slit_in_checkbox) eels_row.add_spacing(8) eels_row.add(ui.create_label_widget("+eV")) eels_row.add_spacing(4) eels_row.add(energy_offset_field) eels_row.add_spacing(8) eels_row.add(ui.create_label_widget("eV/ch")) eels_row.add_spacing(4) eels_row.add(energy_dispersion_field) eels_row.add_stretch() defocus_row = ui.create_row_widget() defocus_row.add_spacing(8) defocus_row.add_spacing(8) defocus_row.add(ui.create_label_widget("Defocus")) defocus_row.add(defocus_field) defocus_row.add_stretch() c3_row = ui.create_row_widget() c3_row.add_spacing(8) c3_row.add_spacing(8) c3_row.add(ui.create_label_widget("Spherical Aberration")) c3_row.add(c3_field) c3_row.add_stretch() sample_row = ui.create_row_widget() sample_row.add_spacing(8) sample_row.add_spacing(8) sample_row.add(sample_combo_box) sample_row.add_stretch() voltage_row = ui.create_row_widget() voltage_row.add_spacing(8) voltage_row.add_spacing(8) voltage_row.add(ui.create_label_widget("Voltage")) voltage_row.add(voltage_field) voltage_row.add_stretch() beam_current_row = ui.create_row_widget() beam_current_row.add_spacing(8) beam_current_row.add_spacing(8) beam_current_row.add(ui.create_label_widget("Beam Current")) beam_current_row.add(beam_current_field) beam_current_row.add_stretch() convergence_angle_row = ui.create_row_widget() convergence_angle_row.add_spacing(8) convergence_angle_row.add_spacing(8) convergence_angle_row.add(ui.create_label_widget("Convergence Angle")) convergence_angle_row.add(convergenve_angle_field) convergence_angle_row.add_stretch() column = self.content_widget column.add(sample_row) column.add(voltage_row) column.add(beam_current_row) column.add(stage_position_widget) column.add(drift_widget) column.add(beam_shift_widget) column.add(defocus_row) column.add(c12_widget) column.add(c21_widget) column.add(c23_widget) column.add(c3_row) column.add(c32_widget) column.add(c34_widget) column.add(beam_row) column.add(convergence_angle_row) column.add(c_aperture_widget) column.add(aperture_round_widget) column.add(eels_row) column.add_stretch()
def make_image_chooser(document_controller, computation, variable): ui = document_controller.ui document_model = document_controller.document_model column = ui.create_column_widget() row = ui.create_row_widget() label_column = ui.create_column_widget() label_widget = ui.create_label_widget(variable.display_label, properties={"width": 80}) label_widget.bind_text(Binding.PropertyBinding(variable, "display_label")) label_column.add(label_widget) label_column.add_stretch() row.add(label_column) row.add_spacing(8) def drop_mime_data(mime_data, x, y): if mime_data.has_format(MimeTypes.DISPLAY_ITEM_MIME_TYPE): display_item_uuid = uuid.UUID( mime_data.data_as_string(MimeTypes.DISPLAY_ITEM_MIME_TYPE)) display_item = document_model.get_display_item_by_uuid( display_item_uuid) data_item = display_item.data_item if display_item else None if data_item: variable_specifier = document_model.get_object_specifier( display_item.display_data_channel) if variable.objects_model.items: variable.objects_model.remove_item(0) variable.objects_model.append_item(variable_specifier) return "copy" return None def data_item_delete(): if variable.objects_model.items: variable.objects_model.remove_item(0) display_item = None if variable.object_specifiers: base_variable_specifier = copy.copy(variable.object_specifiers[0]) bound_data_source = document_model.resolve_object_specifier( base_variable_specifier) data_item = bound_data_source.value.data_item if bound_data_source else None display_item = document_model.get_display_item_for_data_item(data_item) data_item_thumbnail_source = DataItemThumbnailWidget.DataItemThumbnailSource( ui, display_item=display_item) data_item_chooser_widget = DataItemThumbnailWidget.ThumbnailWidget( ui, data_item_thumbnail_source, Geometry.IntSize(80, 80)) def thumbnail_widget_drag(mime_data, thumbnail, hot_spot_x, hot_spot_y): # use this convoluted base object for drag so that it doesn't disappear after the drag. try: column.drag(mime_data, thumbnail, hot_spot_x, hot_spot_y) except Exception as e: print(e) import traceback traceback.print_exc() data_item_chooser_widget.on_drag = thumbnail_widget_drag data_item_chooser_widget.on_drop_mime_data = drop_mime_data data_item_chooser_widget.on_delete = data_item_delete def property_changed(key): if key == "object_specifiers": if variable.object_specifiers: base_variable_specifier = copy.copy( variable.object_specifiers[0]) bound_data_item = document_model.resolve_object_specifier( base_variable_specifier) data_item = bound_data_item.value.data_item if bound_data_item else None display_item = document_model.get_display_item_for_data_item( data_item) data_item_thumbnail_source.set_display_item(display_item) else: data_item_thumbnail_source.set_display_item(None) property_changed_listener = variable.property_changed_event.listen( property_changed) row.add(data_item_chooser_widget) row.add_stretch() column.add(row) column.add_spacing(4) return column, [property_changed_listener]