def __init__( self, ui: UserInterface.UserInterface, rgba_bitmap_data: typing.Optional[DrawingContext.RGBA32Type] = None, properties: typing.Optional[typing.Mapping[str, typing.Any]] = None ) -> None: column_widget = ui.create_column_widget(properties=properties) super().__init__(column_widget) self.ui = ui self.on_clicked = None self.__image_binding: typing.Optional[Binding.Binding] = None def button_clicked() -> None: if callable(self.on_clicked): self.on_clicked() self.__bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem( rgba_bitmap_data) self.__bitmap_canvas_item.on_button_clicked = button_clicked bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item( self.__bitmap_canvas_item) column_widget.add(bitmap_canvas_widget) self.image = rgba_bitmap_data
def image(self, rgba_bitmap_data: typing.Optional[numpy.ndarray]) -> None: self.content_widget.remove_all() if rgba_bitmap_data is not None: height, width = rgba_bitmap_data.shape bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem(rgba_bitmap_data) # bitmap_canvas_item.update_sizing(bitmap_canvas_item.sizing.with_fixed_size(Geometry.IntSize(height=height, width=width))) def button_clicked(): if callable(self.on_clicked): self.on_clicked() bitmap_canvas_item.on_button_clicked = button_clicked bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item(bitmap_canvas_item) self.content_widget.add(bitmap_canvas_widget) self.__rgba_bitmap_data = rgba_bitmap_data
def __init__( self, ui: UserInterface.UserInterface, properties: typing.Optional[typing.Mapping[str, typing.Any]] = None): column_widget = ui.create_column_widget(properties=properties) super().__init__(column_widget) self.ui = ui self.on_clicked: typing.Optional[typing.Callable[[], None]] = None self.__bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem( None, border_color="#CCC") self.__bitmap_canvas_item.on_button_clicked = self.__handle_clicked self.__value: typing.Optional[int] = None self.__group_value: typing.Optional[int] = None self.__on_group_value_changed: typing.Optional[typing.Callable[ [typing.Optional[int]], None]] = None self.__group_value_binding: typing.Optional[Binding.Binding] = None self.__icon_binding: typing.Optional[Binding.Binding] = None self.__enabled = True self.__checked = False bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item( self.__bitmap_canvas_item) column_widget.add(bitmap_canvas_widget)
def __init__(self, document_controller, panel_id, properties): super(ToolbarPanel, self).__init__(document_controller, panel_id, _("Toolbar")) self.widget = self.ui.create_column_widget() toolbar_row_widget = self.ui.create_row_widget() # see https://www.iconfinder.com ui = document_controller.ui document_controller_weak_ref = weakref.ref(document_controller) icon_size = Geometry.IntSize(height=24, width=32) border_color = "#CCC" margins = Geometry.Margins(left=2, right=2, top=3, bottom=3) tool_palette_grid_canvas_item = CanvasItem.CanvasItemComposition() tool_palette_grid_canvas_item.layout = CanvasItem.CanvasItemGridLayout( size=Geometry.IntSize(height=2, width=6), margins=margins) pointer_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/pointer_icon.png")), border_color=border_color) pointer_tool_button.size = icon_size pointer_tool_button.tool_tip = _("Pointer tool for selecting graphics") hand_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/hand_icon.png")), border_color=border_color) hand_tool_button.size = icon_size hand_tool_button.tool_tip = _( "Hand tool for dragging images within panel") line_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/line_icon.png")), border_color=border_color) line_tool_button.size = icon_size line_tool_button.tool_tip = _( "Line tool for making line regions on images") rectangle_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/rectangle_icon.png")), border_color=border_color) rectangle_tool_button.size = icon_size rectangle_tool_button.tool_tip = _( "Rectangle tool for making rectangle regions on images") ellipse_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/ellipse_icon.png")), border_color=border_color) ellipse_tool_button.size = icon_size ellipse_tool_button.tool_tip = _( "Ellipse tool for making ellipse regions on images") point_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/point_icon.png")), border_color=border_color) point_tool_button.size = icon_size point_tool_button.tool_tip = _( "Point tool for making point regions on images") line_profile_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/line_profile_icon.png")), border_color=border_color) line_profile_tool_button.size = icon_size line_profile_tool_button.tool_tip = _( "Line profile tool for making line profiles on images") interval_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/interval_icon.png")), border_color=border_color) interval_tool_button.size = icon_size interval_tool_button.tool_tip = _( "Interval tool for making intervals on line plots") spot_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/spot_icon.png")), border_color=border_color) spot_tool_button.size = icon_size spot_tool_button.tool_tip = _("Spot tool for creating spot masks") wedge_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/wedge_icon.png")), border_color=border_color) wedge_tool_button.size = icon_size wedge_tool_button.tool_tip = _("Wedge tool for creating wedge masks") ring_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/annular_ring.png")), border_color=border_color) ring_tool_button.size = icon_size ring_tool_button.tool_tip = _("Ring tool for creating ring masks") lattice_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/lattice_icon.png")), border_color=border_color) lattice_tool_button.size = icon_size lattice_tool_button.tool_tip = _( "Lattice tool for creating periodic lattice masks") tool_palette_grid_canvas_item.add_canvas_item( pointer_tool_button, Geometry.IntPoint(x=0, y=0)) tool_palette_grid_canvas_item.add_canvas_item( hand_tool_button, Geometry.IntPoint(x=0, y=1)) tool_palette_grid_canvas_item.add_canvas_item( line_tool_button, Geometry.IntPoint(x=1, y=0)) tool_palette_grid_canvas_item.add_canvas_item( ellipse_tool_button, Geometry.IntPoint(x=1, y=1)) tool_palette_grid_canvas_item.add_canvas_item( rectangle_tool_button, Geometry.IntPoint(x=2, y=0)) tool_palette_grid_canvas_item.add_canvas_item( point_tool_button, Geometry.IntPoint(x=2, y=1)) tool_palette_grid_canvas_item.add_canvas_item( line_profile_tool_button, Geometry.IntPoint(x=3, y=0)) tool_palette_grid_canvas_item.add_canvas_item( interval_tool_button, Geometry.IntPoint(x=3, y=1)) tool_palette_grid_canvas_item.add_canvas_item( spot_tool_button, Geometry.IntPoint(x=4, y=0)) tool_palette_grid_canvas_item.add_canvas_item( wedge_tool_button, Geometry.IntPoint(x=4, y=1)) tool_palette_grid_canvas_item.add_canvas_item( ring_tool_button, Geometry.IntPoint(x=5, y=0)) tool_palette_grid_canvas_item.add_canvas_item( lattice_tool_button, Geometry.IntPoint(x=5, y=1)) modes = "pointer", "hand", "line", "rectangle", "ellipse", "point", "line-profile", "interval", "spot", "wedge", "ring", "lattice" self.__tool_button_group = CanvasItem.RadioButtonGroup([ pointer_tool_button, hand_tool_button, line_tool_button, rectangle_tool_button, ellipse_tool_button, point_tool_button, line_profile_tool_button, interval_tool_button, spot_tool_button, wedge_tool_button, ring_tool_button ]) def tool_mode_changed(tool_mode): self.__tool_button_group.current_index = modes.index(tool_mode) self.__tool_mode_changed_event_listener = document_controller.tool_mode_changed_event.listen( tool_mode_changed) self.__tool_button_group.current_index = modes.index( document_controller.tool_mode) self.__tool_button_group.on_current_index_changed = lambda index: setattr( document_controller_weak_ref(), "tool_mode", modes[index]) tool_mode_changed(document_controller.tool_mode) new_group_button = self.ui.create_push_button_widget() new_group_button.tool_tip = _("New Group") new_group_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/new_group_icon.png")) new_group_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("project.add_group") delete_button = self.ui.create_push_button_widget() delete_button.tool_tip = _("Delete") delete_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/delete_icon.png")) delete_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("window.delete") export_button = self.ui.create_push_button_widget() export_button.tool_tip = _("Export") export_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/export_icon.png")) export_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("file.export") view_palette_grid_canvas_item = CanvasItem.CanvasItemComposition() view_palette_grid_canvas_item.layout = CanvasItem.CanvasItemGridLayout( size=Geometry.IntSize(height=2, width=2), margins=margins) fit_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/fit_icon.png")), border_color=border_color) fit_view_button.size = icon_size fit_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._fit_view_action.trigger() fit_view_button.tool_tip = _("Zoom to fit to enclosing space") fill_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/fill_icon.png")), border_color=border_color) fill_view_button.size = icon_size fill_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._fill_view_action.trigger() fill_view_button.tool_tip = _("Zoom to fill enclosing space") one_to_one_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/1x1_icon.png")), border_color=border_color) one_to_one_view_button.size = icon_size one_to_one_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._one_to_one_view_action.trigger() one_to_one_view_button.tool_tip = _( "Zoom to one image pixel per screen pixel") two_to_one_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/2x1_icon.png")), border_color=border_color) two_to_one_view_button.size = icon_size two_to_one_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._two_to_one_view_action.trigger() two_to_one_view_button.tool_tip = _( "Zoom to two image pixels per screen pixel") view_palette_grid_canvas_item.add_canvas_item( fit_view_button, Geometry.IntPoint(x=0, y=0)) view_palette_grid_canvas_item.add_canvas_item( fill_view_button, Geometry.IntPoint(x=0, y=1)) view_palette_grid_canvas_item.add_canvas_item( one_to_one_view_button, Geometry.IntPoint(x=1, y=0)) view_palette_grid_canvas_item.add_canvas_item( two_to_one_view_button, Geometry.IntPoint(x=1, y=1)) toggle_filter_button = self.ui.create_push_button_widget() toggle_filter_button.tool_tip = _("Toggle Filter Panel") toggle_filter_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/filter_icon.png")) toggle_filter_button.on_clicked = lambda: document_controller_weak_ref( )._toggle_filter_action.trigger() tool_palette_widget = ui.create_canvas_widget(properties={ "height": 54, "width": 164 }) tool_palette_widget.canvas_item.add_canvas_item( tool_palette_grid_canvas_item) tool_group_widget = self.ui.create_row_widget() tool_group_widget.add(tool_palette_widget) commands_group_widget = self.ui.create_row_widget() commands_group_widget.add(new_group_button) commands_group_widget.add(delete_button) commands_group_widget.add(export_button) view_palette_widget = ui.create_canvas_widget(properties={ "height": 54, "width": 68 }) view_palette_widget.canvas_item.add_canvas_item( view_palette_grid_canvas_item) view_group_widget = self.ui.create_row_widget() view_group_widget.add(view_palette_widget) filter_group_widget = self.ui.create_row_widget() filter_group_widget.add(toggle_filter_button) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(tool_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(commands_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(view_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(filter_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add_stretch() self.widget.add(toolbar_row_widget)
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 __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: typing.Dict): super().__init__(document_controller, panel_id, _("Data Items")) ui = document_controller.ui def show_context_menu(display_item: typing.Optional[DisplayItem.DisplayItem], x: int, y: int, gx: int, gy: int) -> bool: menu = document_controller.create_context_menu_for_display(display_item, use_selection=True) menu.popup(gx, gy) return True def map_display_item_to_display_item_adapter(display_item: DisplayItem.DisplayItem) -> DisplayItemAdapter: return DisplayItemAdapter(display_item, ui) def unmap_display_item_to_display_item_adapter(display_item_adapter: DisplayItemAdapter) -> None: display_item_adapter.close() self.__filtered_display_item_adapters_model = ListModel.MappedListModel(container=document_controller.filtered_display_items_model, master_items_key="display_items", items_key="display_item_adapters", map_fn=map_display_item_to_display_item_adapter, unmap_fn=unmap_display_item_to_display_item_adapter) self.__selection = self.document_controller.selection self.__focused = False def selection_changed() -> None: # called when the selection changes; notify selected display item changed if focused. self.__notify_focus_changed() self.__selection_changed_event_listener = self.__selection.changed_event.listen(selection_changed) def display_item_adapter_selection_changed(display_item_adapters: typing.List[DisplayItemAdapter]) -> None: indexes = set() for index, display_item_adapter in enumerate(self.__filtered_display_item_adapters_model.display_item_adapters): if display_item_adapter in display_item_adapters: indexes.add(index) self.__selection.set_multiple(indexes) self.__notify_focus_changed() def focus_changed(focused: bool) -> None: self.focused = focused def delete_display_item_adapters(display_item_adapters: typing.List[DisplayItemAdapter]) -> None: document_controller.delete_display_items([display_item_adapter.display_item for display_item_adapter in display_item_adapters if display_item_adapter.display_item]) self.data_list_controller = DataListController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection) self.data_list_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed self.data_list_controller.on_context_menu_event = show_context_menu self.data_list_controller.on_focus_changed = focus_changed self.data_list_controller.on_delete_display_item_adapters = delete_display_item_adapters self.data_grid_controller = DataGridController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection) self.data_grid_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed self.data_grid_controller.on_context_menu_event = show_context_menu self.data_grid_controller.on_focus_changed = focus_changed self.data_grid_controller.on_delete_display_item_adapters = delete_display_item_adapters data_list_widget = DataListWidget(ui, self.data_list_controller) data_grid_widget = DataGridWidget(ui, self.data_grid_controller) list_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/list_icon_20.png"))) grid_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/grid_icon_20.png"))) list_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20)) grid_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20)) button_row = CanvasItem.CanvasItemComposition() button_row.layout = CanvasItem.CanvasItemRowLayout(spacing=4) button_row.add_canvas_item(list_icon_button) button_row.add_canvas_item(grid_icon_button) buttons_widget = ui.create_canvas_widget(properties={"height": 20, "width": 44}) buttons_widget.canvas_item.add_canvas_item(button_row) search_widget = ui.create_row_widget() search_widget.add_spacing(8) search_widget.add(ui.create_label_widget(_("Filter"))) search_widget.add_spacing(8) search_line_edit = ui.create_line_edit_widget() search_line_edit.placeholder_text = _("No Filter") search_line_edit.clear_button_enabled = True # Qt 5.3 doesn't signal text edited or editing finished when clearing. useless so disabled. search_line_edit.on_text_edited = self.document_controller.filter_controller.text_filter_changed search_line_edit.on_editing_finished = self.document_controller.filter_controller.text_filter_changed search_widget.add(search_line_edit) search_widget.add_spacing(6) search_widget.add(buttons_widget) search_widget.add_spacing(8) self.data_view_widget = ui.create_stack_widget() self.data_view_widget.add(data_list_widget) self.data_view_widget.add(data_grid_widget) self.data_view_widget.current_index = 0 self.__view_button_group = CanvasItem.RadioButtonGroup([list_icon_button, grid_icon_button]) self.__view_button_group.current_index = 0 self.__view_button_group.on_current_index_changed = lambda index: setattr(self.data_view_widget, "current_index", index) widget = ui.create_column_widget(properties=properties) widget.add(self.data_view_widget) widget.add_spacing(6) widget.add(search_widget) widget.add_spacing(6) self.widget = widget self._data_list_widget = data_list_widget self._data_grid_widget = data_grid_widget
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