Example #1
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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.")))
Example #6
0
 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 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
Example #8
0
    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())
Example #9
0
    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()
Example #10
0
    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
Example #12
0
    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")
Example #13
0
 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())
Example #14
0
    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
Example #15
0
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]