Source code for pymodaq.control_modules.daq_viewer_ui.ui_base

# -*- coding: utf-8 -*-
"""
Created the 05/09/2022

@author: Sebastien Weber
"""


from typing import List, Union
import sys

from qtpy import QtWidgets, QtCore
from qtpy.QtWidgets import QVBoxLayout

from pymodaq.control_modules.enums import ActionIconNames
from pymodaq.utils.daq_utils import ThreadCommand
from pymodaq.control_modules.ui_utils import ControlModuleUI

from pymodaq_gui.utils import DockArea, Dock
from pymodaq_utils.config import GlobalConfig as Config
from pymodaq.control_modules.instruments import DET_TYPES
from pymodaq_gui.plotting.data_viewers.viewer import ViewerFactory, ViewerDispatcher
from pymodaq_gui.plotting.data_viewers import ViewersEnum
from pymodaq_gui.utils.styling import create_icon
from pymodaq.control_modules.thread_commands import UiToMainViewer
from pymodaq.control_modules.control_module_selector import add_category_layers
from pymodaq.control_modules.daq_viewer_ui.viewer_selector import SelectedModule, ViewerSelector

viewer_factory = ViewerFactory()
config = Config()


options = {
    'DAQ0D': [name for name in [plugin['name'] for plugin in DET_TYPES['DAQ0D']]],
    'DAQ1D': [name for name in [plugin['name'] for plugin in DET_TYPES['DAQ1D']]],
    'DAQ2D': [name for name in [plugin['name'] for plugin in DET_TYPES['DAQ2D']]],
    'DAQND': [name for name in [plugin['name'] for plugin in DET_TYPES['DAQND']]],
}
add_menu_entries = add_category_layers(options)


[docs] class DAQ_Viewer_UI(ControlModuleUI, ViewerDispatcher): """DAQ_Viewer user interface. This class manages the UI and emit dedicated signals depending on actions from the user Attributes ---------- command_sig: Signal[Threadcommand] This signal is emitted whenever some actions done by the user has to be applied on the main module. Possible commands are: * init * grab * snap * detector_changed * daq_type_changed * save_current Methods ------- display_value(value: float) Update the display of the actuator's value on the UI do_init() Programmatic init See Also -------- pymodaq.utils.daq_utils.ThreadCommand """ def __init__(self, app, parent: QtWidgets.QWidget, title="DAQ_Viewer", rois_dock: Dock = None, settings_dock: Dock = None, area: DockArea = None, **kwargs): ControlModuleUI.__init__(self, app, parent, title=title, settings_dock=settings_dock,) if area is not None: self.dockarea = area else: self.dockarea = DockArea() ViewerDispatcher.__init__(self, self.dockarea, title=title, rois_dock=rois_dock) self._data_ready = False self._detector_widget = None self.selector = ViewerSelector(add_menu_entries=add_menu_entries) self.setup_docks_and_widgets() self.setup_menus_and_toolbars(self.menubar) self.setup_actions() # see ActionManager MixIn class self.update_viewers([self.selector.selected_module.daq_type.to_viewer_type()]) self.connect_things() self.enable_actions(False, all_except=('ini_detector', 'selector', 'show_settings', 'show_graphs')) self._settings_widget.setVisible(False) # ------------------------------------------------------------------------- # Properties # ------------------------------------------------------------------------- @property def detector(self) -> SelectedModule: return self.selector.selected_module @detector.setter def detector(self, det: SelectedModule): self.selector.selected_module = det @property def detector_init(self): """bool: the internal init status.""" return self._ini_state @detector_init.setter def detector_init(self, status): self._ini_state = status self.enable_actions(status, all_except=('ini_detector', 'selector', 'show_settings', 'show_graphs')) self.set_action_enabled('selector', not status) self.update_init_icon(status, action_name='ini_detector') if self.has_action('ini_detector'): self.set_action_checked('ini_detector', status) @property def data_ready(self): return self._data_ready @data_ready.setter def data_ready(self, status): self._data_ready = status if status: icon = create_icon(ActionIconNames.SNAP, icon_color=self.get_theme().green, ) else: icon = create_icon(ActionIconNames.SNAP, icon_color=self.get_theme().red, ) self.get_action('snap').set_icon(icon) # ------------------------------------------------------------------------- # UI Construction # ------------------------------------------------------------------------- def setup_docks_and_widgets(self): widget = self.parent layout = QVBoxLayout() widget.setLayout(layout) layout.setContentsMargins(2, 2, 2, 2) layout.addWidget(self.dockarea) def setup_menus_and_toolbars(self, menubar: QtWidgets.QMenuBar = None): self.add_toolbar('viewer', 'DAQViewer') def setup_actions(self): # Common actions from ControlModuleUI self._setup_name_widget(toolbar=self.toolbar) self.add_widget('selector', self.selector.add_widget) self._setup_init_action(action_name='ini_detector', display_name='Ini. Detector', tip='Connect to selected detector') self._setup_settings_action() self.toolbar.addSeparator() # Detector-specific actions self.add_action('snap', 'Snap', ActionIconNames.SNAP, "Take a snapshot from the detector") self.add_action('grab', 'Grab', ActionIconNames.GRAB, "Grab data from the detector", checkable=True, icon_checked=ActionIconNames.GRAB_STOP, icon_checked_color=self.get_theme().green) self.add_action('reset_live', 'ResetLive', ActionIconNames.RESET, "Reset The current live averaging", visible=False) self.add_action('show_graphs', 'ShowGraphs', 'bid_landscape', 'Show/Hide the Graphs Area', checkable=True, icon_checked='bid_landscape_disabled', icon_color=self.get_theme().green, icon_checked_color=self.get_theme().red) self.add_action('save_current', 'Save Current Data', 'save_as', "Save Current Data") self.toolbar.addSeparator() self.add_action('background_snap', 'Snap Background', 'background_replace', tip='Take a snapshot a set it as background') self.add_action('background_subtract', 'Subtract Background', 'texture_minus', checkable=True, tip='If checked, apply background substraction', icon_checked_color=self.get_theme().green) def connect_things(self): self._connect_common_actions() self.connect_action('grab', self._grab) self.connect_action('snap', lambda: self.command_sig.emit(ThreadCommand(UiToMainViewer.SNAP, ))) self.connect_action('reset_live', lambda: self.command_sig.emit(ThreadCommand(UiToMainViewer.RESET_LIVE))) self.connect_action('save_current', lambda: self.command_sig.emit(ThreadCommand(UiToMainViewer.SAVE_CURRENT, ))) self.selector.module_changed.connect(self._detector_changed) self.connect_action('background_subtract', lambda checked: self.command_sig.emit(ThreadCommand(UiToMainViewer.DO_BKG, checked))) self.connect_action('background_snap', lambda: self.command_sig.emit(ThreadCommand(UiToMainViewer.TAKE_BKG))) self.connect_action('show_graphs', lambda checked: self.show_graphs(not checked)) # ------------------------------------------------------------------------- # Public API # -------------------------------------------------------------------------
[docs] def do_init(self, do_init=True): """Programmatically press the Init button API entry Parameters ---------- do_init: bool will fire the Init button depending on the argument value and the button check state """ if do_init is not self.is_action_checked('ini_detector'): self.get_action('ini_detector').trigger()
[docs] def do_grab(self, do_grab=True): """Programmatically press the Grab button API entry Parameters ---------- do_grab: bool will fire the Init button depending on the argument value and the button check state """ if (do_grab and not self.is_action_checked('grab')) or ((not do_grab) and self.is_action_checked('grab')): self.get_action('grab').trigger()
[docs] def do_snap(self): """Programmatically press the Snap button API entry """ self.get_action('snap').trigger()
[docs] def do_stop(self): """Programmatically uncheck the grab button API entry """ if self.is_action_checked('grab'): self.get_action('grab').trigger()
def update_viewers(self, viewers_type: List[Union[str, ViewersEnum]], viewers_name: List[str] = None, force=False): super().update_viewers(viewers_type, viewers_name=viewers_name) self.command_sig.emit(ThreadCommand(UiToMainViewer.VIEWERS_CHANGED, attribute=dict(viewer_types=self.viewer_types, viewers=self.viewers))) # ------------------------------------------------------------------------- # Slots / Event Handlers # ------------------------------------------------------------------------- def send_init(self, checked: bool): self.get_action('selector').widget.setEnabled(not checked) if not checked and self.is_action_checked('background_subtract'): self.get_action('background_subtract').setChecked(False) self.command_sig.emit(ThreadCommand(UiToMainViewer.INIT, [checked, self.selector.selected_module])) def quit_fun(self): return self.app.quit_fun() def _enable_detchoices(self, enable=True): self.get_action('selector').widget.setEnabled(enable) def _detector_changed(self, sel_mod: SelectedModule): try: self.command_sig.emit(ThreadCommand(UiToMainViewer.DETECTOR_CHANGED, sel_mod)) self.update_viewers([sel_mod.daq_type.to_viewer_type()]) except ValueError as e: pass def _grab(self): """Slot from the *grab* action""" self.command_sig.emit(ThreadCommand(UiToMainViewer.GRAB, attribute=self.is_action_checked('grab'))) self.enable_actions(not self.is_action_checked('grab'), all_except=('grab', 'selector', 'show_settings', 'show_graphs', 'reset_live')) if not self.config('pymodaq', 'viewer', 'allow_settings_edition'): self._settings_widget.setEnabled(not self.is_action_checked('grab')) # ------------------------------------------------------------------------- # Visibility / Lifecycle # ------------------------------------------------------------------------- def show_graphs(self, show: bool = True): self.parent.setVisible(show) self.parent.closeEvent = lambda event: self.set_action_checked('show_graphs', False) def close(self): for dock in self.viewer_docks: dock.close() super().close()
def main(init_qt=True): from pymodaq_gui.parameter import Parameter, ParameterTree from pymodaq.control_modules.viewer_utility_classes import params as daq_viewer_params from pymodaq.utils.shared_ui import SharedUI from pymodaq_gui.qt_utils import mkQApp if init_qt: # used for the test suite app = mkQApp("PyMoDAQ UI Viewer") param = Parameter.create(name='settings', type='group', children=daq_viewer_params) tree = ParameterTree() tree.setParameters(param, showTop=False) widget = QtWidgets.QWidget() prog = DAQ_Viewer_UI(widget, title='myViewer') shared_ui = SharedUI(widget) timer = QtCore.QTimer(shared_ui) def set_data_ready(ready=True): prog.data_ready = True def set_data_ready_loop(ready=True): prog.data_ready = True app.processEvents() QtCore.QThread.msleep(100) prog.data_ready = False app.processEvents() def print_command_sig(cmd_sig): print(cmd_sig) prog.update_status(str(cmd_sig)) if cmd_sig.command == UiToMainViewer.INIT: prog.detector_init = cmd_sig.attribute[0] elif cmd_sig.command == UiToMainViewer.SNAP: prog.data_ready = False timer.timeout.connect(set_data_ready) timer.setSingleShot(True) timer.start(500) elif cmd_sig.command == UiToMainViewer.GRAB: prog.data_ready = False if cmd_sig.attribute: timer.timeout.connect(set_data_ready_loop) timer.setSingleShot(False) timer.start(500) else: timer.stop() # prog.detectors = detectors prog.command_sig.connect(print_command_sig) prog.add_setting_tree(tree) #prog.update_viewers([prog.selector.selected_module.daq_type.to_viewer_type()]) shared_ui.add_toolbar('viewer', 'Viewer', toolbar=prog.toolbar, add_break=True) shared_ui.show() if init_qt: sys.exit(app.exec()) if __name__ == '__main__': main()