Пример #1
0
    def __init__(self):
        self.__config_file = None

        # the active video sources (hardware sources). this list is updated when a video camera device is registered or
        # unregistered with the hardware source manager.
        self.video_sources = ListModel.ListModel()

        # the list of instances of video cameras. this is similar to the video sources but is the devices plus settings
        # for the device. some devices might not have instances if the factory to create the instance hasn't been
        # registered yet.
        self.__instances = list()

        # the list of video device factories. this is populated by responding to the registry messages.
        self.__video_device_factories = list()

        def component_registered(component, component_types):
            if "video_device_factory" in component_types:
                if not component in self.__video_device_factories:
                    self.__video_device_factories.append(component)
                self.__make_video_devices()

        def component_unregistered(component, component_types):
            if "video_device_factory" in component_types:
                if component in self.__video_device_factories:
                    self.__video_device_factories.remove(component)

        self.__component_registered_listener = Registry.listen_component_registered_event(
            component_registered)
        self.__component_unregistered_listener = Registry.listen_component_unregistered_event(
            component_unregistered)

        for component in Registry.get_components_by_type(
                "video_device_factory"):
            component_registered(component, {"video_device_factory"})
Пример #2
0
def run():
    def component_registered(component, component_types):
        if "video_device" in component_types:
            hardware_source = VideoHardwareSource(component)
            HardwareSource.HardwareSourceManager().register_hardware_source(
                hardware_source)
            video_configuration.video_sources.append_item(hardware_source)

    def component_unregistered(component, component_types):
        if "video_device" in component_types:
            for hardware_source in HardwareSource.HardwareSourceManager(
            ).hardware_sources:
                if getattr(hardware_source, "video_device",
                           None) and hardware_source.video_device == component:
                    video_configuration.video_sources.remove_item(
                        video_configuration.video_sources.items.index(
                            hardware_source))
                    video_configuration._remove_video_device(component)
                    HardwareSource.HardwareSourceManager(
                    ).unregister_hardware_source(hardware_source)

    global _component_registered_listener
    global _component_unregistered_listener

    _component_registered_listener = Registry.listen_component_registered_event(
        component_registered)
    _component_unregistered_listener = Registry.listen_component_unregistered_event(
        component_unregistered)

    for component in Registry.get_components_by_type("video_device"):
        component_registered(component, {"video_device"})
def run():
    def component_registered(component, component_types):
        if "scan_device" in component_types:
            stem_controller = HardwareSource.HardwareSourceManager(
            ).get_instrument_by_id(component.stem_controller_id)
            if not stem_controller:
                print("STEM Controller (" + component.stem_controller_id +
                      ") for (" + component.scan_device_id +
                      ") not found. Using proxy.")
                from nion.instrumentation import stem_controller
                stem_controller = stem_controller.STEMController()
            scan_hardware_source = ScanHardwareSource(
                stem_controller, component, component.scan_device_id,
                component.scan_device_name)
            HardwareSource.HardwareSourceManager().register_hardware_source(
                scan_hardware_source)

    def component_unregistered(component, component_types):
        if "scan_device" in component_types:
            HardwareSource.HardwareSourceManager().unregister_hardware_source(
                component)

    global _component_registered_listener
    global _component_unregistered_listener

    _component_registered_listener = Registry.listen_component_registered_event(
        component_registered)
    _component_unregistered_listener = Registry.listen_component_unregistered_event(
        component_unregistered)

    for component in Registry.get_components_by_type("scan_device"):
        component_registered(component, {"scan_device"})
def run():
    def component_registered(component, component_types):
        if "camera_device" in component_types:
            stem_controller_id = getattr(component, "stem_controller_id",
                                         "autostem_controller")
            camera_hardware_source = CameraHardwareSource(
                stem_controller_id, component)
            if hasattr(component, "priority"):
                camera_hardware_source.priority = component.priority
            component_types = {
                "hardware_source", "camera_hardware_source"
            }.union({component.camera_type + "_camera_hardware_source"})
            Registry.register_component(camera_hardware_source,
                                        component_types)
            HardwareSource.HardwareSourceManager().register_hardware_source(
                camera_hardware_source)
            component.hardware_source = camera_hardware_source

    def component_unregistered(component, component_types):
        if "camera_device" in component_types:
            camera_hardware_source = component.hardware_source
            Registry.unregister_component(camera_hardware_source)
            HardwareSource.HardwareSourceManager().unregister_hardware_source(
                camera_hardware_source)

    global _component_registered_listener
    global _component_unregistered_listener

    _component_registered_listener = Registry.listen_component_registered_event(
        component_registered)
    _component_unregistered_listener = Registry.listen_component_unregistered_event(
        component_unregistered)

    for component in Registry.get_components_by_type("camera_device"):
        component_registered(component, {"camera_device"})
def run():
    def component_registered(component, component_types):
        if "camera_device" in component_types:
            stem_controller_id = getattr(component, "stem_controller_id",
                                         "autostem_controller")
            camera_hardware_source = CameraHardwareSource(
                stem_controller_id, component)
            HardwareSource.HardwareSourceManager().register_hardware_source(
                camera_hardware_source)

    def component_unregistered(component, component_types):
        if "camera_device" in component_types:
            HardwareSource.HardwareSourceManager().unregister_hardware_source(
                component)

    global _component_registered_listener
    global _component_unregistered_listener

    _component_registered_listener = Registry.listen_component_registered_event(
        component_registered)
    _component_unregistered_listener = Registry.listen_component_unregistered_event(
        component_unregistered)

    for component in Registry.get_components_by_type("camera_device"):
        component_registered(component, {"camera_device"})
Пример #6
0
    def __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: Persistence.PersistentDictType) -> None:
        super().__init__(document_controller, panel_id, _("Toolbar"))

        self.__component_registered_listener = Registry.listen_component_registered_event(self.__component_registered)

        self.widget = self.ui.create_column_widget()

        # note: "maximum" here means the size hint is maximum and the widget can be smaller. Qt layout is atrocious.
        self.__toolbar_widget_row = self.ui.create_row_widget(properties={"size-policy-horizontal": "maximum"})

        toolbar_row_widget = self.ui.create_row_widget()
        toolbar_row_widget.add(self.__toolbar_widget_row)
        toolbar_row_widget.add_stretch()

        self.widget.add(toolbar_row_widget)

        # make a map from widget_id to widget factory.
        widget_factories = dict()
        for component in Registry.get_components_by_type("toolbar-widget"):
            widget_factories[component.toolbar_widget_id] = component

        # define the order of widgets.
        # this part is hard coded for now; needs some work to make it dynamically order widgets as they become
        # available from packages.
        widget_id_list = [
            "nion.swift.toolbar-widget.tool-mode",
            "nion.swift.toolbar-widget.raster-zoom",
            "nion.swift.toolbar-widget.workspace"
        ]

        # add the widgets.
        for widget_id in widget_id_list:
            widget_factory = widget_factories[widget_id]
            widget_handler = widget_factory(document_controller=self.document_controller)
            widget = Declarative.DeclarativeWidget(self.ui, self.document_controller.event_loop, widget_handler)
            widget_section = self.ui.create_row_widget()
            widget_section.add(widget)
            section_bar = self.ui.create_canvas_widget(properties={"width": 9, "size_policy_vertical": "expanding"})

            def draw(drawing_context: DrawingContext.DrawingContext, canvas_size: Geometry.IntSize, *args: typing.Any, **kwargs: typing.Any) -> None:
                with drawing_context.saver():
                    drawing_context.rect(0, 0, canvas_size.width, canvas_size.height)
                    drawing_context.fill_style = "#DDD"
                    drawing_context.stroke_style = "#AAA"
                    drawing_context.fill()
                    drawing_context.stroke()

            section_bar.canvas_item.add_canvas_item(CanvasItem.DrawCanvasItem(draw))
            self.__toolbar_widget_row.add(section_bar)
            self.__toolbar_widget_row.add_spacing(8)
            self.__toolbar_widget_row.add(widget_section)
            self.__toolbar_widget_row.add_spacing(8)

        end_divider = self.ui.create_canvas_widget(properties={"width": 1, "size_policy_vertical": "expanding"})
        end_divider.canvas_item.add_canvas_item(CanvasItem.DividerCanvasItem(color="#888"))
        self.__toolbar_widget_row.add(end_divider)
def run(configuration_location: pathlib.Path):
    def component_registered(component, component_types):
        if "camera_module" in component_types:
            camera_module = component
            stem_controller_id = getattr(camera_module, "stem_controller_id",
                                         "autostem_controller")
            camera_settings = camera_module.camera_settings
            camera_device = camera_module.camera_device
            camera_panel_type = getattr(camera_module, "camera_panel_type",
                                        None)
            camera_hardware_source = CameraHardwareSource(
                stem_controller_id, camera_device, camera_settings,
                configuration_location, camera_panel_type)
            if hasattr(camera_module, "priority"):
                camera_hardware_source.priority = camera_module.priority
            component_types = {
                "hardware_source", "camera_hardware_source"
            }.union({camera_device.camera_type + "_camera_hardware_source"})
            Registry.register_component(camera_hardware_source,
                                        component_types)
            HardwareSource.HardwareSourceManager().register_hardware_source(
                camera_hardware_source)
            camera_module.hardware_source = camera_hardware_source

    def component_unregistered(component, component_types):
        if "camera_module" in component_types:
            camera_hardware_source = component.hardware_source
            Registry.unregister_component(camera_hardware_source)
            HardwareSource.HardwareSourceManager().unregister_hardware_source(
                camera_hardware_source)

    global _component_registered_listener
    global _component_unregistered_listener

    _component_registered_listener = Registry.listen_component_registered_event(
        component_registered)
    _component_unregistered_listener = Registry.listen_component_unregistered_event(
        component_unregistered)

    for component in Registry.get_components_by_type("camera_module"):
        component_registered(component, {"camera_module"})
Пример #8
0
def subtract_background_from_signal(api, window):
    window._document_controller.event_loop.create_task(
        use_interval_as_background(api, window))


Symbolic.register_computation_type("eels.background_subtraction3",
                                   EELSBackgroundSubtraction)
Symbolic.register_computation_type("eels.mapping3", EELSMapping)

BackgroundModel = Schema.entity("background_model", None, None, {})


def component_registered(component, component_types):
    if "background-model" in component_types:
        # when a background model is registered, create an empty (for now) entity type, and register it with the data
        # structure so that an entity for use with the UI and computations can be created when the data structure loads.
        background_model_entity = Schema.entity(component.background_model_id,
                                                BackgroundModel, None, {})
        DataStructure.DataStructure.register_entity(
            background_model_entity,
            entity_name=component.title,
            entity_package_name=component.package_title)


_component_registered_listener = Registry.listen_component_registered_event(
    component_registered)

# handle any components that have already been registered.
for component in Registry.get_components_by_type("background-model"):
    component_registered(component, {"background-model"})
Пример #9
0
    def create_panel_widget(self, ui, document_controller):
        self.ui = ui
        self.document_controller = document_controller

        def start_clicked():
            if self.__acquisition_running:
                self.multi_acquire_controller.cancel()
            else:
                self.multi_acquire_controller.stem_controller = self.stem_controller
                self.multi_acquire_controller.camera = self.camera_choice_combo_box.current_item

                def run_multi_eels():
                    data_dict = self.multi_acquire_controller.acquire_multi_eels_spectrum(
                    )

                    def create_and_display_data_item():
                        self.create_result_data_item(data_dict)

                    document_controller.queue_task(create_and_display_data_item
                                                   )  # must occur on UI thread

                self.__acquisition_thread = threading.Thread(
                    target=run_multi_eels, daemon=True)
                self.__acquisition_thread.start()

        def start_si_clicked():
            if self.__acquisition_running:
                self.multi_acquire_controller.cancel()
            else:
                self.multi_acquire_controller.stem_controller = self.stem_controller
                self.multi_acquire_controller.camera = self.camera_choice_combo_box.current_item
                self.multi_acquire_controller.superscan = self.superscan
                self.result_data_items = {}
                self.__new_data_ready_event_listener = self.multi_acquire_controller.new_data_ready_event.listen(
                    self.add_to_display_queue)
                self.__data_processed_event.clear()
                self.__display_thread = threading.Thread(
                    target=self.process_display_queue)
                self.__display_thread.start()
                self.__acquisition_thread = threading.Thread(
                    target=self.multi_acquire_controller.
                    acquire_multi_eels_spectrum_image,
                    daemon=True)
                self.__acquisition_thread.start()

        def settings_button_clicked():
            if not self.settings_window_open:
                self.settings_window_open = True
                self.show_config_box()

        def camera_changed(current_item):
            if current_item:
                self.multi_acquire_controller.settings[
                    'camera_hardware_source_id'] = current_item.hardware_source_id

        camera_choice_row = ui.create_row_widget()
        settings_button = ui.create_push_button_widget('Settings...')
        settings_button.on_clicked = settings_button_clicked
        self.camera_choice_combo_box = ui.create_combo_box_widget(
            item_text_getter=lambda camera: getattr(camera, 'display_name'))
        self.camera_choice_combo_box.on_current_item_changed = camera_changed
        camera_choice_row.add_spacing(5)
        camera_choice_row.add(ui.create_label_widget('Camera: '))
        camera_choice_row.add(self.camera_choice_combo_box)
        camera_choice_row.add_stretch()
        camera_choice_row.add_spacing(5)
        camera_choice_row.add(settings_button)
        camera_choice_row.add_spacing(5)
        self.update_camera_list()
        self.update_current_camera()
        self.__settings_changed_event_listener = self.multi_acquire_controller.settings.settings_changed_event.listen(
            self.update_current_camera)

        def component_changed(component, component_types):
            if 'camera_hardware_source' in component_types:
                self.update_camera_list()

        self.__component_registered_event_listener = Registry.listen_component_registered_event(
            component_changed)
        self.__component_unregistered_event_listener = Registry.listen_component_unregistered_event(
            component_changed)

        change_parameters_row = ui.create_row_widget()
        change_parameters_row.add_spacing(5)
        change_parameters_row.add(
            ui.create_label_widget('MultiAcquire parameters:'))
        change_parameters_row.add_stretch()
        change_parameters_row.add_spacing(20)

        parameter_description_row = ui.create_row_widget()
        parameter_description_row.add_spacing(5)
        parameter_description_row.add(ui.create_label_widget('#'))
        parameter_description_row.add_spacing(20)
        parameter_description_row.add(ui.create_label_widget('X Offset (eV)'))
        parameter_description_row.add_spacing(25)
        parameter_description_row.add_stretch()
        parameter_description_row.add(ui.create_label_widget('Exposure (ms)'))
        parameter_description_row.add_spacing(25)
        parameter_description_row.add_stretch()
        parameter_description_row.add(ui.create_label_widget('Frames'))
        parameter_description_row.add_spacing(5)
        parameter_description_row.add_stretch()

        add_remove_parameters_row = ui.create_row_widget()
        add_parameters_button = ui.create_push_button_widget('+')
        add_parameters_button._widget.set_property('width', 40)
        add_parameters_button.on_clicked = self.multi_acquire_controller.add_spectrum
        remove_parameters_button = ui.create_push_button_widget('-')
        remove_parameters_button._widget.set_property('width', 40)
        remove_parameters_button.on_clicked = self.multi_acquire_controller.remove_spectrum

        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(add_parameters_button)
        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(remove_parameters_button)
        add_remove_parameters_row.add_spacing(20)
        add_remove_parameters_row.add_stretch()

        progress_row = ui.create_row_widget()
        progress_row.add_spacing(180)
        self.progress_bar = ui.create_progress_bar_widget()
        progress_row.add(self.progress_bar)
        progress_row.add_spacing(5)

        time_estimate_row = ui.create_row_widget()
        time_estimate_row.add_spacing(6)
        self.time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.time_estimate_label)
        time_estimate_row.add_spacing(5)
        time_estimate_row.add_stretch()
        self.si_time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.si_time_estimate_label)
        time_estimate_row.add_spacing(6)
        self.multi_acquire_controller.stem_controller = self.stem_controller
        self.multi_acquire_controller.superscan = self.superscan

        def frame_parameters_changed(profile_index, frame_parameters):
            self.update_time_estimate()

        self.__superscan_frame_parameters_changed_event_listener = self.superscan.frame_parameters_changed_event.listen(
            frame_parameters_changed)
        self.update_camera_list()

        self.start_button = ui.create_push_button_widget('Start Multi-Acquire')
        self.start_button.on_clicked = start_clicked
        self.start_si_button = ui.create_push_button_widget(
            'Start Multi-Acquire spectrum image')
        self.start_si_button.on_clicked = start_si_clicked
        start_row = ui.create_row_widget()
        start_row.add_spacing(5)
        start_row.add(self.start_button)
        start_row.add_spacing(5)
        start_row.add_stretch()
        start_row.add(self.start_si_button)
        start_row.add_spacing(5)

        column = ui.create_column_widget()
        column.add_spacing(5)
        column.add(camera_choice_row)
        column.add_spacing(5)
        column.add(change_parameters_row)
        column.add_spacing(10)
        column.add(parameter_description_row)
        column.add_spacing(10)
        self.parameter_column = ui.create_column_widget()
        for spectrum_parameters in self.multi_acquire_controller.spectrum_parameters:
            line = self.create_parameter_line(spectrum_parameters)
            self.parameter_column.add(line)
        column.add(self.parameter_column)
        column.add_spacing(5)
        column.add(add_remove_parameters_row)
        column.add_spacing(5)
        column.add(progress_row)
        column.add_spacing(10)
        column.add(time_estimate_row)
        column.add_spacing(5)
        column.add(start_row)
        column.add_spacing(5)
        column.add_stretch()
        return column
    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.

        if not self.stem_controller:
            return ui.create_column_widget()

        self.line_edit_widgets = dict()
        self._stem_controller = None
        self._camera = None
        self._scan_controller = None
        self.multi_acquire_controller = MultiAcquire.MultiAcquireController(
            self.stem_controller,
            savepath=os.path.join(os.path.expanduser('~'), 'MultiAcquire'))
        self.__acquisition_state_changed_event_listener = self.multi_acquire_controller.acquisition_state_changed_event.listen(
            self.acquisition_state_changed)
        self.__multi_eels_parameters_changed_event_listener = self.multi_acquire_controller.spectrum_parameters.parameters_changed_event.listen(
            self.spectrum_parameters_changed)
        self.__progress_updated_event_listener = self.multi_acquire_controller.progress_updated_event.listen(
            self.update_progress_bar)
        self.__settings_changed_event_listener = None
        self.__component_registered_event_listener = None
        self.__component_unregistered_event_listener = None
        self.__scan_frame_parameters_changed_event_listener = None
        self.__new_scan_data_ready_event_listener = None

        self.settings_window_open = False
        self.parameter_column = None
        self.result_data_items = None
        self.__acquisition_running = False
        self.__acquisition_thread = None

        self.ui = ui
        self.document_controller = document_controller

        def start_clicked() -> None:
            multi_acquire_controller = self.multi_acquire_controller
            if not multi_acquire_controller:
                return
            if self.__acquisition_running:
                multi_acquire_controller.cancel()
            else:
                multi_acquire_controller.stem_controller = self.stem_controller
                multi_acquire_controller.camera = self.camera

                def run_multi_eels() -> None:
                    assert multi_acquire_controller
                    data_dict = multi_acquire_controller.acquire_multi_eels_spectrum(
                    )

                    def create_and_display_data_item() -> None:
                        self.create_result_data_item(data_dict)

                    document_controller.queue_task(create_and_display_data_item
                                                   )  # must occur on UI thread

                self.__acquisition_thread = threading.Thread(
                    target=run_multi_eels, daemon=True)
                self.__acquisition_thread.start()

        def start_si_clicked() -> None:
            multi_acquire_controller = self.multi_acquire_controller
            if not multi_acquire_controller:
                return
            if self.__acquisition_running:
                multi_acquire_controller.cancel()
            else:
                # Camera must be accessed from the UI thread, so do it here and re-use later
                camera = self.camera
                scan_controller = self.scan_controller
                assert camera
                assert scan_controller

                multi_acquire_controller.stem_controller = self.stem_controller
                multi_acquire_controller.camera = camera
                multi_acquire_controller.scan_controller = scan_controller

                def create_acquisition_handler(
                    multi_acquire_parameters: MultiAcquire.MultiEELSParameters,
                    current_parameters_index: int,
                    multi_acquire_settings: MultiAcquire.MultiEELSSettings
                ) -> MultiAcquire.SISequenceAcquisitionHandler:
                    assert camera
                    assert scan_controller
                    assert multi_acquire_controller
                    document_model = self.document_controller._document_controller.document_model
                    camera_frame_parameters = camera.get_current_frame_parameters(
                    )
                    scan_frame_parameters = scan_controller.get_current_frame_parameters(
                    )
                    camera_frame_parameters.exposure_ms = multi_acquire_parameters[
                        current_parameters_index]['exposure_ms']
                    camera_frame_parameters.processing = multi_acquire_settings[
                        'processing']
                    scan_frame_parameters.scan_id = scan_frame_parameters.scan_id or uuid.uuid4(
                    )
                    grab_synchronized_info = scan_controller.grab_synchronized_get_info(
                        scan_frame_parameters=scan_frame_parameters,
                        camera=camera,
                        camera_frame_parameters=camera_frame_parameters)
                    camera_data_channel: typing.Optional[
                        MultiAcquire.CameraDataChannel] = None
                    scan_data_channel: typing.Optional[
                        MultiAcquire.ScanDataChannel] = None
                    channels_ready_event = threading.Event()

                    def create_channels() -> None:
                        assert camera
                        assert scan_controller
                        nonlocal camera_data_channel, scan_data_channel
                        stack_metadata_keys = getattr(camera.camera,
                                                      'stack_metadata_keys',
                                                      None)
                        camera_data_channel = MultiAcquire.CameraDataChannel(
                            document_model,
                            camera.display_name,
                            grab_synchronized_info,
                            multi_acquire_parameters,
                            multi_acquire_settings,
                            current_parameters_index,
                            stack_metadata_keys=stack_metadata_keys)
                        enabled_channels = scan_controller.get_enabled_channels(
                        )
                        enabled_channel_names = [
                            scan_controller.data_channels[i].name or str()
                            for i in enabled_channels
                        ]
                        scan_data_channel = MultiAcquire.ScanDataChannel(
                            document_model, enabled_channel_names,
                            grab_synchronized_info, multi_acquire_parameters,
                            multi_acquire_settings, current_parameters_index)
                        camera_data_channel.start()
                        scan_data_channel.start()
                        channels_ready_event.set()

                    self.document_controller.queue_task(create_channels)
                    assert channels_ready_event.wait(10)

                    assert camera_data_channel
                    assert scan_data_channel

                    sequence_behavior = MultiAcquire.SequenceBehavior(
                        multi_acquire_controller, current_parameters_index)
                    si_sequence_behavior = MultiAcquire.SISequenceBehavior(
                        None, None, sequence_behavior, 1)
                    handler = MultiAcquire.SISequenceAcquisitionHandler(
                        camera, camera_data_channel, camera_frame_parameters,
                        scan_controller, scan_data_channel,
                        scan_frame_parameters, si_sequence_behavior)

                    listener = handler.camera_data_channel.progress_updated_event.listen(
                        multi_acquire_controller.set_progress_counter)

                    def finish_fn() -> None:
                        listener.close()

                        def close_channels() -> None:
                            handler.camera_data_channel.stop()
                            handler.scan_data_channel.stop()

                        self.document_controller.queue_task(close_channels)

                    handler.finish_fn = finish_fn

                    return handler

                self.__acquisition_thread = threading.Thread(
                    target=multi_acquire_controller.
                    start_multi_acquire_spectrum_image,
                    args=(create_acquisition_handler, ))
                self.__acquisition_thread.start()

        def settings_button_clicked() -> None:
            if not self.settings_window_open:
                self.settings_window_open = True
                self.show_config_box()

        def help_clicked() -> None:
            webbrowser.open(
                'https://nionswift-instrumentation.readthedocs.io/en/latest/userguide.html#multi-acquire-panel',
                new=2)

        def camera_changed(
                current_item: camera_base.CameraHardwareSource) -> None:
            multi_acquire_controller = self.multi_acquire_controller
            if current_item and multi_acquire_controller:
                multi_acquire_controller.settings[
                    'camera_hardware_source_id'] = current_item.hardware_source_id
                if current_item.features.get("has_masked_sum_option"):
                    self.binning_choice_combo_box.items = [
                        'Spectra', 'Images', 'MultiEELS Spectra',
                        'Virtual Detectors'
                    ]
                else:
                    self.binning_choice_combo_box.items = [
                        'Spectra', 'Images', 'MultiEELS Spectra'
                    ]
                binning_changed(
                    typing.cast(str,
                                self.binning_choice_combo_box.current_item))

        def binning_changed(current_item: str) -> None:
            multi_acquire_controller = self.multi_acquire_controller
            if not multi_acquire_controller:
                return
            if not self.__acquisition_running:
                self.start_button._widget.enabled = True
            if current_item == 'Spectra':
                multi_acquire_controller.settings['processing'] = 'sum_project'
                multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = False
            elif current_item == 'Images':
                multi_acquire_controller.settings['processing'] = None
                multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = False
            elif current_item == 'MultiEELS Spectra':
                multi_acquire_controller.settings['processing'] = 'sum_project'
                multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = True
            elif current_item == 'Virtual Detectors':
                multi_acquire_controller.settings['processing'] = 'sum_masked'
                multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = False
                self.start_button._widget.enabled = False

        camera_choice_row = ui.create_row_widget()
        self.binning_choice_combo_box = ui.create_combo_box_widget()
        # Delay connecting the callback functions because otherwise loading the plugin fails because "start button" is not defined yet
        self.binning_choice_combo_box.items = [
            'Spectra', 'Images', 'MultiEELS Spectra'
        ]
        sliders_icon_png = pkgutil.get_data(__name__,
                                            "resources/sliders_icon_24.png")
        assert sliders_icon_png
        settings_button = CanvasItem.BitmapButtonCanvasItem(
            CanvasItem.load_rgba_data_from_bytes(sliders_icon_png, "png"))
        settings_widget = ui._ui.create_canvas_widget(properties={
            "height": 24,
            "width": 24
        })
        settings_widget.canvas_item.add_canvas_item(settings_button)
        settings_button.on_button_clicked = settings_button_clicked
        help_icon_png = pkgutil.get_data(__name__,
                                         "resources/help_icon_24.png")
        assert help_icon_png
        help_button = CanvasItem.BitmapButtonCanvasItem(
            CanvasItem.load_rgba_data_from_bytes(help_icon_png, "png"))
        help_widget = ui._ui.create_canvas_widget(properties={
            "height": 24,
            "width": 24
        })
        help_widget.canvas_item.add_canvas_item(help_button)
        help_button.on_button_clicked = help_clicked
        self.camera_choice_combo_box = ui.create_combo_box_widget(
            item_text_getter=lambda camera: typing.cast(
                str, getattr(camera, 'display_name')))
        camera_choice_row.add_spacing(5)
        camera_choice_row.add(self.camera_choice_combo_box)
        camera_choice_row.add_spacing(10)
        camera_choice_row.add(self.binning_choice_combo_box)
        camera_choice_row.add_stretch()
        camera_choice_row.add_spacing(10)
        typing.cast(UserInterface.BoxWidget,
                    camera_choice_row._widget).add(help_widget)
        camera_choice_row.add_spacing(10)
        typing.cast(UserInterface.BoxWidget,
                    camera_choice_row._widget).add(settings_widget)
        camera_choice_row.add_spacing(10)
        self.update_camera_list()
        self.update_current_camera()
        self.__settings_changed_event_listener = self.multi_acquire_controller.settings.settings_changed_event.listen(
            self.update_current_camera)
        self.__settings_changed_event_listener_2 = self.multi_acquire_controller.settings.settings_changed_event.listen(
            self.update_binning_combo_box)

        def component_changed(component: typing.Any,
                              component_types: typing.Set[str]) -> None:
            if 'camera_hardware_source' in component_types:
                self.update_camera_list()

        self.__component_registered_event_listener = Registry.listen_component_registered_event(
            component_changed)
        self.__component_unregistered_event_listener = Registry.listen_component_unregistered_event(
            component_changed)

        change_parameters_row = ui.create_row_widget()
        change_parameters_row.add_spacing(5)
        change_parameters_row.add(
            ui.create_label_widget('MultiAcquire parameters:'))
        change_parameters_row.add_stretch()
        change_parameters_row.add_spacing(20)

        parameter_description_row = ui.create_row_widget()
        parameter_description_row.add_spacing(5)
        parameter_description_row.add(ui.create_label_widget('#'))
        parameter_description_row.add_spacing(20)
        offset_label = ui.create_label_widget('Offset')
        parameter_description_row.add(offset_label)
        parameter_description_row.add_stretch()
        parameter_description_row.add(ui.create_label_widget('Exposure (ms)'))
        parameter_description_row.add_stretch()
        parameter_description_row.add_stretch()
        parameter_description_row.add_stretch()
        frames_label = ui.create_label_widget('Frames')
        parameter_description_row.add(frames_label)
        parameter_description_row.add_stretch()

        def update_offset_label() -> None:
            multi_acquire_controller = self.multi_acquire_controller
            if not multi_acquire_controller:
                return
            if multi_acquire_controller.settings['shift_each_sequence_slice']:
                offset_label.text = 'Offset (per frame)  '
            else:
                offset_label.text = 'Offset                   '
            if multi_acquire_controller.settings['sum_frames']:
                frames_label.text = 'Frames (summed)'
            else:
                frames_label.text = 'Frames              '

        update_offset_label()
        self.__settings_changed_event_listener_3 = self.multi_acquire_controller.settings.settings_changed_event.listen(
            update_offset_label)

        add_remove_parameters_row = ui.create_row_widget()
        add_parameters_button = ui.create_push_button_widget('+')
        add_parameters_button._widget.set_property('width', 40)
        add_parameters_button.on_clicked = self.multi_acquire_controller.add_spectrum
        remove_parameters_button = ui.create_push_button_widget('-')
        remove_parameters_button._widget.set_property('width', 40)
        remove_parameters_button.on_clicked = self.multi_acquire_controller.remove_spectrum

        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(add_parameters_button)
        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(remove_parameters_button)
        add_remove_parameters_row.add_spacing(90)
        self.progress_bar = ui.create_progress_bar_widget()
        add_remove_parameters_row.add(self.progress_bar)
        add_remove_parameters_row.add_spacing(5)

        time_estimate_row = ui.create_row_widget()
        time_estimate_row.add_spacing(6)
        self.time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.time_estimate_label)
        time_estimate_row.add_spacing(5)
        time_estimate_row.add_stretch()
        self.si_time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.si_time_estimate_label)
        time_estimate_row.add_spacing(6)
        self.multi_acquire_controller.stem_controller = self.stem_controller
        self.multi_acquire_controller.scan_controller = self.scan_controller

        def frame_parameters_changed(
                profile_index: int,
                frame_parameters: scan_base.ScanFrameParameters) -> None:
            self.update_time_estimate()

        if self.scan_controller:
            self.__scan_frame_parameters_changed_event_listener = self.scan_controller.frame_parameters_changed_event.listen(
                frame_parameters_changed)
        self.update_camera_list()

        self.start_button = ui.create_push_button_widget('Start MultiAcquire')
        self.start_button.on_clicked = start_clicked
        self.start_si_button = ui.create_push_button_widget(
            'Start MultiAcquire spectrum image')
        self.start_si_button.on_clicked = start_si_clicked
        start_row = ui.create_row_widget()
        start_row.add_spacing(5)
        start_row.add(self.start_button)
        start_row.add_spacing(5)
        start_row.add_stretch()
        start_row.add(self.start_si_button)
        start_row.add_spacing(5)

        column = ui.create_column_widget()
        column.add_spacing(5)
        column.add(camera_choice_row)
        column.add_spacing(10)
        column.add(change_parameters_row)
        column.add_spacing(5)
        column.add(parameter_description_row)
        column.add_spacing(10)
        self.parameter_column = ui.create_column_widget()
        for spectrum_parameters in self.multi_acquire_controller.spectrum_parameters:
            line = self.create_parameter_line(spectrum_parameters)
            self.parameter_column.add(line)
        column.add(self.parameter_column)
        column.add_spacing(5)
        column.add(add_remove_parameters_row)
        column.add_spacing(15)
        column.add(time_estimate_row)
        column.add_spacing(5)
        column.add(start_row)
        column.add_spacing(10)
        column.add_stretch()
        # Make sure we update the available options in the binning combo box.
        camera_changed(
            typing.cast(camera_base.CameraHardwareSource,
                        self.camera_choice_combo_box.current_item))
        # Make sure the binning combo box shows the actual settings
        self.update_binning_combo_box()
        # Delay setting up the callbacks until the end to make sure loading the plugin doesn't fail due to missing attributes
        self.binning_choice_combo_box.on_current_item_changed = binning_changed
        self.camera_choice_combo_box.on_current_item_changed = camera_changed
        return column
    def create_panel_widget(self, ui, document_controller):
        # note: anything created here should be disposed in close.
        # this method may be called more than once.

        self.line_edit_widgets = {}
        self._stem_controller = None
        self._camera = None
        self._scan_controller = None
        self.multi_acquire_controller = MultiAcquire.MultiAcquireController(
            self.stem_controller,
            savepath=os.path.join(os.path.expanduser('~'), 'MultiAcquire'))
        self.__acquisition_state_changed_event_listener = self.multi_acquire_controller.acquisition_state_changed_event.listen(
            self.acquisition_state_changed)
        self.__multi_eels_parameters_changed_event_listener = self.multi_acquire_controller.spectrum_parameters.parameters_changed_event.listen(
            self.spectrum_parameters_changed)
        self.__progress_updated_event_listener = self.multi_acquire_controller.progress_updated_event.listen(
            self.update_progress_bar)
        self.__settings_changed_event_listener = None
        self.__component_registered_event_listener = None
        self.__component_unregistered_event_listener = None
        self.__scan_frame_parameters_changed_event_listener = None
        self.__new_scan_data_ready_event_listener = None

        self.settings_window_open = False
        self.parameter_column = None
        self.result_data_items = None
        self.__acquisition_running = False
        self.__display_queue = None
        self.__display_thread = None
        self.__acquisition_thread = None

        self.ui = ui
        self.document_controller = document_controller

        def start_clicked():
            if self.__acquisition_running:
                self.multi_acquire_controller.cancel()
            else:
                self.multi_acquire_controller.stem_controller = self.stem_controller
                self.multi_acquire_controller.camera = self.camera

                def run_multi_eels():
                    data_dict = self.multi_acquire_controller.acquire_multi_eels_spectrum(
                    )

                    def create_and_display_data_item():
                        self.create_result_data_item(data_dict)

                    document_controller.queue_task(create_and_display_data_item
                                                   )  # must occur on UI thread

                self.__acquisition_thread = threading.Thread(
                    target=run_multi_eels, daemon=True)
                self.__acquisition_thread.start()

        def start_si_clicked():
            if self.__acquisition_running:
                self.multi_acquire_controller.cancel()
            else:
                # Camera must be accessed from the UI thread, so do it here and re-use later
                camera = self.camera
                self.multi_acquire_controller.stem_controller = self.stem_controller
                self.multi_acquire_controller.camera = camera
                self.multi_acquire_controller.scan_controller = self.scan_controller

                def create_acquisition_handler(multi_acquire_parameters: list,
                                               current_parameters_index: int,
                                               multi_acquire_settings: dict):
                    document_model = self.document_controller._document_controller.document_model
                    camera_frame_parameters = camera.get_current_frame_parameters(
                    )
                    scan_frame_parameters = self.scan_controller.get_current_frame_parameters(
                    )
                    camera_frame_parameters[
                        'exposure_ms'] = multi_acquire_parameters[
                            current_parameters_index]['exposure_ms']
                    camera_frame_parameters[
                        'processing'] = 'sum_project' if multi_acquire_settings[
                            'bin_spectra'] else None
                    scan_frame_parameters.setdefault('scan_id',
                                                     str(uuid.uuid4()))
                    grab_synchronized_info = self.scan_controller.grab_synchronized_get_info(
                        scan_frame_parameters=scan_frame_parameters,
                        camera=camera,
                        camera_frame_parameters=camera_frame_parameters)
                    camera_data_channel = None
                    scan_data_channel = None
                    channels_ready_event = threading.Event()

                    def create_channels():
                        nonlocal camera_data_channel, scan_data_channel
                        camera_data_channel = MultiAcquire.CameraDataChannel(
                            document_model, camera.display_name,
                            grab_synchronized_info, multi_acquire_parameters,
                            multi_acquire_settings, current_parameters_index)
                        enabled_channels = self.scan_controller.get_enabled_channels(
                        )
                        enabled_channel_names = [
                            self.scan_controller.data_channels[i].name
                            for i in enabled_channels
                        ]
                        scan_data_channel = MultiAcquire.ScanDataChannel(
                            document_model, enabled_channel_names,
                            grab_synchronized_info, multi_acquire_parameters,
                            multi_acquire_settings, current_parameters_index)
                        camera_data_channel.start()
                        scan_data_channel.start()
                        channels_ready_event.set()

                    self.document_controller.queue_task(create_channels)
                    assert channels_ready_event.wait(10)

                    si_sequence_behavior = MultiAcquire.SISequenceBehavior(
                        None, None, None, None)
                    handler = MultiAcquire.SISequenceAcquisitionHandler(
                        camera, camera_data_channel, camera_frame_parameters,
                        self.scan_controller, scan_data_channel,
                        scan_frame_parameters, si_sequence_behavior)

                    listener = handler.camera_data_channel.progress_updated_event.listen(
                        self.multi_acquire_controller.set_progress_counter)

                    def finish_fn():
                        listener.close()

                        def close_channels():
                            handler.camera_data_channel.stop()
                            handler.scan_data_channel.stop()

                        self.document_controller.queue_task(close_channels)

                    handler.finish_fn = finish_fn

                    return handler

                self.__acquisition_thread = threading.Thread(
                    target=self.multi_acquire_controller.
                    start_multi_acquire_spectrum_image,
                    args=(create_acquisition_handler, ))
                self.__acquisition_thread.start()

        def settings_button_clicked():
            if not self.settings_window_open:
                self.settings_window_open = True
                self.show_config_box()

        def camera_changed(current_item):
            if current_item:
                self.multi_acquire_controller.settings[
                    'camera_hardware_source_id'] = current_item.hardware_source_id

        def binning_changed(current_item):
            if current_item == 'Spectra':
                self.multi_acquire_controller.settings['bin_spectra'] = True
                self.multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = False
            elif current_item == 'Images':
                self.multi_acquire_controller.settings['bin_spectra'] = False
                self.multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = False
            elif current_item == 'MultiEELS Spectra':
                self.multi_acquire_controller.settings['bin_spectra'] = True
                self.multi_acquire_controller.settings[
                    'use_multi_eels_calibration'] = True

        camera_choice_row = ui.create_row_widget()
        self.binning_choice_combo_box = ui.create_combo_box_widget()
        self.binning_choice_combo_box.on_current_item_changed = binning_changed
        self.binning_choice_combo_box.items = [
            'Spectra', 'Images', 'MultiEELS Spectra'
        ]
        settings_button = CanvasItem.BitmapButtonCanvasItem(
            CanvasItem.load_rgba_data_from_bytes(
                pkgutil.get_data(__name__, "resources/sliders_icon_24.png"),
                "png"))
        settings_widget = ui._ui.create_canvas_widget(properties={
            "height": 24,
            "width": 24
        })
        settings_widget.canvas_item.add_canvas_item(settings_button)
        settings_button.on_button_clicked = settings_button_clicked
        self.camera_choice_combo_box = ui.create_combo_box_widget(
            item_text_getter=lambda camera: getattr(camera, 'display_name'))
        self.camera_choice_combo_box.on_current_item_changed = camera_changed
        camera_choice_row.add_spacing(5)
        camera_choice_row.add(self.camera_choice_combo_box)
        camera_choice_row.add_spacing(10)
        camera_choice_row.add(self.binning_choice_combo_box)
        camera_choice_row.add_stretch()
        camera_choice_row.add_spacing(10)
        camera_choice_row._widget.add(settings_widget)
        camera_choice_row.add_spacing(10)
        self.update_camera_list()
        self.update_current_camera()
        self.__settings_changed_event_listener = self.multi_acquire_controller.settings.settings_changed_event.listen(
            self.update_current_camera)
        self.__settings_changed_event_listener_2 = self.multi_acquire_controller.settings.settings_changed_event.listen(
            self.update_binning_combo_box)

        def component_changed(component, component_types):
            if 'camera_hardware_source' in component_types:
                self.update_camera_list()

        self.__component_registered_event_listener = Registry.listen_component_registered_event(
            component_changed)
        self.__component_unregistered_event_listener = Registry.listen_component_unregistered_event(
            component_changed)

        change_parameters_row = ui.create_row_widget()
        change_parameters_row.add_spacing(5)
        change_parameters_row.add(
            ui.create_label_widget('MultiAcquire parameters:'))
        change_parameters_row.add_stretch()
        change_parameters_row.add_spacing(20)

        parameter_description_row = ui.create_row_widget()
        parameter_description_row.add_spacing(5)
        parameter_description_row.add(ui.create_label_widget('#'))
        parameter_description_row.add_spacing(20)
        parameter_description_row.add(ui.create_label_widget('Offset'))
        parameter_description_row.add_spacing(36)
        parameter_description_row.add_stretch()
        parameter_description_row.add(ui.create_label_widget('Exposure (ms)'))
        parameter_description_row.add_stretch()
        parameter_description_row.add(ui.create_label_widget('Frames'))
        parameter_description_row.add_spacing(5)
        parameter_description_row.add_stretch()

        add_remove_parameters_row = ui.create_row_widget()
        add_parameters_button = ui.create_push_button_widget('+')
        add_parameters_button._widget.set_property('width', 40)
        add_parameters_button.on_clicked = self.multi_acquire_controller.add_spectrum
        remove_parameters_button = ui.create_push_button_widget('-')
        remove_parameters_button._widget.set_property('width', 40)
        remove_parameters_button.on_clicked = self.multi_acquire_controller.remove_spectrum

        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(add_parameters_button)
        add_remove_parameters_row.add_spacing(5)
        add_remove_parameters_row.add(remove_parameters_button)
        add_remove_parameters_row.add_spacing(90)
        self.progress_bar = ui.create_progress_bar_widget()
        add_remove_parameters_row.add(self.progress_bar)
        add_remove_parameters_row.add_spacing(5)

        time_estimate_row = ui.create_row_widget()
        time_estimate_row.add_spacing(6)
        self.time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.time_estimate_label)
        time_estimate_row.add_spacing(5)
        time_estimate_row.add_stretch()
        self.si_time_estimate_label = ui.create_label_widget()
        time_estimate_row.add(self.si_time_estimate_label)
        time_estimate_row.add_spacing(6)
        self.multi_acquire_controller.stem_controller = self.stem_controller
        self.multi_acquire_controller.scan_controller = self.scan_controller

        def frame_parameters_changed(profile_index, frame_parameters):
            self.update_time_estimate()

        if self.scan_controller:
            self.__scan_frame_parameters_changed_event_listener = self.scan_controller.frame_parameters_changed_event.listen(
                frame_parameters_changed)
        self.update_camera_list()

        self.start_button = ui.create_push_button_widget('Start MultiAcquire')
        self.start_button.on_clicked = start_clicked
        self.start_si_button = ui.create_push_button_widget(
            'Start MultiAcquire spectrum image')
        self.start_si_button.on_clicked = start_si_clicked
        start_row = ui.create_row_widget()
        start_row.add_spacing(5)
        start_row.add(self.start_button)
        start_row.add_spacing(5)
        start_row.add_stretch()
        start_row.add(self.start_si_button)
        start_row.add_spacing(5)

        column = ui.create_column_widget()
        column.add_spacing(5)
        column.add(camera_choice_row)
        column.add_spacing(10)
        column.add(change_parameters_row)
        column.add_spacing(5)
        column.add(parameter_description_row)
        column.add_spacing(10)
        self.parameter_column = ui.create_column_widget()
        for spectrum_parameters in self.multi_acquire_controller.spectrum_parameters:
            line = self.create_parameter_line(spectrum_parameters)
            self.parameter_column.add(line)
        column.add(self.parameter_column)
        column.add_spacing(5)
        column.add(add_remove_parameters_row)
        column.add_spacing(15)
        column.add(time_estimate_row)
        column.add_spacing(5)
        column.add(start_row)
        column.add_spacing(10)
        column.add_stretch()
        # Make sure the binning combo box shows the actual settings
        self.update_binning_combo_box()
        return column