pymodaq 5.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 06/12/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
import sys
|
|
8
|
+
from typing import List, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from qtpy import QtWidgets, QtCore
|
|
11
|
+
from qtpy.QtCore import Signal
|
|
12
|
+
|
|
13
|
+
from pymodaq_utils.utils import ThreadCommand
|
|
14
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
15
|
+
from pymodaq_utils.config import Config
|
|
16
|
+
|
|
17
|
+
from pymodaq_gui.utils import CustomApp
|
|
18
|
+
from pymodaq_gui.utils import DockArea, Dock
|
|
19
|
+
from pymodaq_gui.utils.widgets.spinbox import QSpinBox_ro
|
|
20
|
+
from pymodaq_gui.utils.widgets import QLED
|
|
21
|
+
from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher
|
|
22
|
+
from pymodaq_gui.plotting.data_viewers import ViewersEnum
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from pymodaq.utils.parameter import ParameterTree
|
|
27
|
+
|
|
28
|
+
config = Config()
|
|
29
|
+
logger = set_logger(get_module_name(__file__))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DAQScanUI(CustomApp, ViewerDispatcher):
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
command_sig = Signal(ThreadCommand)
|
|
37
|
+
|
|
38
|
+
def __init__(self, parent):
|
|
39
|
+
CustomApp.__init__(self, parent)
|
|
40
|
+
self.setup_docks()
|
|
41
|
+
ViewerDispatcher.__init__(self, self.dockarea, title='Scanner',
|
|
42
|
+
next_to_dock=self.dock_command)
|
|
43
|
+
|
|
44
|
+
self.setup_menu(self._menubar)
|
|
45
|
+
self.setup_actions()
|
|
46
|
+
self.connect_things()
|
|
47
|
+
|
|
48
|
+
def setup_actions(self):
|
|
49
|
+
self.add_action('quit', 'Quit the module', 'close2', menu=self.file_menu)
|
|
50
|
+
self.add_action('ini_positions', 'Init Positions', '', menu=self.action_menu)
|
|
51
|
+
self.add_action('start', 'Start Scan', 'run2', "Start the scan", menu=self.action_menu)
|
|
52
|
+
self.add_action('start_batch', 'Start ScanBatches', 'run_all', "Start the batch of scans", menu=self.action_menu)
|
|
53
|
+
self.add_action('stop', 'Stop Scan', 'stop', "Stop the scan", menu=self.action_menu)
|
|
54
|
+
self.add_action('move_at', 'Move at doubleClicked', 'move_contour',
|
|
55
|
+
"Move to positions where you double clicked", checkable=True, menu=self.action_menu)
|
|
56
|
+
self.add_action('log', 'Show Log file', 'information2', menu=self.file_menu)
|
|
57
|
+
|
|
58
|
+
self.add_action('load', 'Load File', 'Open', menu=self.file_menu, auto_toolbar=False)
|
|
59
|
+
self.file_menu.addSeparator()
|
|
60
|
+
self.add_action('save', 'Save file as', 'SaveAs', menu=self.file_menu, auto_toolbar=False)
|
|
61
|
+
self.add_action('show_file', 'Show file content', '', menu=self.file_menu, auto_toolbar=False)
|
|
62
|
+
|
|
63
|
+
self.add_action('navigator', 'Show Navigator', '', menu=self._extensions_menu, auto_toolbar=False)
|
|
64
|
+
self.add_action('batch', 'Show Batch Scanner', '', menu=self._extensions_menu, auto_toolbar=False)
|
|
65
|
+
self.set_action_visible('start_batch', False)
|
|
66
|
+
|
|
67
|
+
def enable_start_stop(self, enable=True):
|
|
68
|
+
"""If True enable main buttons to launch/stop scan"""
|
|
69
|
+
self.set_action_enabled('start', enable)
|
|
70
|
+
self.set_action_enabled('stop', enable)
|
|
71
|
+
|
|
72
|
+
def connect_things(self):
|
|
73
|
+
self.connect_action('quit', lambda: self.command_sig.emit(ThreadCommand('quit')))
|
|
74
|
+
self.connect_action('ini_positions', lambda: self.command_sig.emit(ThreadCommand('ini_positions')))
|
|
75
|
+
self.connect_action('start', lambda: self.command_sig.emit(ThreadCommand('start')))
|
|
76
|
+
self.connect_action('start_batch', lambda: self.command_sig.emit(ThreadCommand('start_batch')))
|
|
77
|
+
self.connect_action('stop', lambda: self.command_sig.emit(ThreadCommand('stop')))
|
|
78
|
+
self.connect_action('move_at', lambda: self.command_sig.emit(ThreadCommand('move_at')))
|
|
79
|
+
self.connect_action('log', lambda: self.command_sig.emit(ThreadCommand('show_log', )))
|
|
80
|
+
|
|
81
|
+
self.connect_action('load', lambda: self.command_sig.emit(ThreadCommand('load')))
|
|
82
|
+
self.connect_action('save', lambda: self.command_sig.emit(ThreadCommand('save')))
|
|
83
|
+
self.connect_action('show_file', lambda: self.command_sig.emit(ThreadCommand('show_file')))
|
|
84
|
+
self.connect_action('navigator', lambda: self.command_sig.emit(ThreadCommand('navigator')))
|
|
85
|
+
self.connect_action('batch', lambda: self.command_sig.emit(ThreadCommand('batch')))
|
|
86
|
+
|
|
87
|
+
def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
|
|
88
|
+
self.file_menu = menubar.addMenu('File')
|
|
89
|
+
self._extensions_menu = menubar.addMenu('Extensions')
|
|
90
|
+
self.action_menu = menubar.addMenu('Actions')
|
|
91
|
+
|
|
92
|
+
def setup_docks(self):
|
|
93
|
+
self.dock_command = Dock('Scan Command')
|
|
94
|
+
self.dockarea.addDock(self.dock_command)
|
|
95
|
+
|
|
96
|
+
widget_command = QtWidgets.QWidget()
|
|
97
|
+
widget_command.setLayout(QtWidgets.QVBoxLayout())
|
|
98
|
+
self.dock_command.addWidget(widget_command)
|
|
99
|
+
widget_command.layout().addWidget(self._toolbar)
|
|
100
|
+
|
|
101
|
+
splitter_widget = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
|
102
|
+
splitter_v_widget = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
|
103
|
+
widget_command.layout().addWidget(splitter_widget)
|
|
104
|
+
splitter_widget.addWidget(splitter_v_widget)
|
|
105
|
+
self.module_widget = QtWidgets.QWidget()
|
|
106
|
+
self.module_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
107
|
+
self.module_widget.setMinimumWidth(220)
|
|
108
|
+
self.module_widget.setMaximumWidth(400)
|
|
109
|
+
|
|
110
|
+
self.plotting_widget = QtWidgets.QWidget()
|
|
111
|
+
self.plotting_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
112
|
+
self.plotting_widget.setMinimumWidth(220)
|
|
113
|
+
self.plotting_widget.setMaximumWidth(400)
|
|
114
|
+
|
|
115
|
+
settings_widget = QtWidgets.QWidget()
|
|
116
|
+
settings_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
117
|
+
settings_widget.setMinimumWidth(220)
|
|
118
|
+
|
|
119
|
+
splitter_v_widget.addWidget(self.module_widget)
|
|
120
|
+
splitter_v_widget.addWidget(self.plotting_widget)
|
|
121
|
+
|
|
122
|
+
splitter_v_widget.setSizes([400, 400])
|
|
123
|
+
splitter_widget.addWidget(settings_widget)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
self._statusbar = QtWidgets.QStatusBar()
|
|
127
|
+
self.mainwindow.setStatusBar(self._statusbar)
|
|
128
|
+
self.populate_status_bar()
|
|
129
|
+
|
|
130
|
+
self.settings_toolbox = QtWidgets.QToolBox()
|
|
131
|
+
settings_widget.layout().addWidget(self.settings_toolbox)
|
|
132
|
+
self.scanner_widget = QtWidgets.QWidget()
|
|
133
|
+
self.scanner_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
134
|
+
self.settings_toolbox.addItem(self.scanner_widget, 'Scanner Settings')
|
|
135
|
+
|
|
136
|
+
def add_settings_toolbox_widget(self, widget: QtWidgets.QWidget, name: str):
|
|
137
|
+
"""Add a widget, usaually a ParameterTree to the SettingsToolbox"""
|
|
138
|
+
self.settings_toolbox.addItem(widget, name)
|
|
139
|
+
|
|
140
|
+
def add_scanner_settings(self, tree: 'ParameterTree'):
|
|
141
|
+
"""Adds a ParameterTree to the Scanner settings widget"""
|
|
142
|
+
self.scanner_widget.layout().addWidget(tree)
|
|
143
|
+
|
|
144
|
+
def populate_toolbox_widget(self, widgets: List[QtWidgets.QWidget], names: List[str]):
|
|
145
|
+
for widget, name in zip(widgets, names):
|
|
146
|
+
self.settings_toolbox.addItem(widget, name)
|
|
147
|
+
|
|
148
|
+
def set_scanner_settings(self, settings_tree: QtWidgets.QWidget):
|
|
149
|
+
while True:
|
|
150
|
+
child = self.scanner_widget.layout().takeAt(0)
|
|
151
|
+
if not child:
|
|
152
|
+
break
|
|
153
|
+
child.widget().deleteLater()
|
|
154
|
+
QtWidgets.QApplication.processEvents()
|
|
155
|
+
|
|
156
|
+
self.scanner_widget.layout().addWidget(settings_tree)
|
|
157
|
+
|
|
158
|
+
def set_modules_settings(self, settings_widget):
|
|
159
|
+
self.module_widget.layout().addWidget(settings_widget)
|
|
160
|
+
|
|
161
|
+
def set_plotting_settings(self, settings_plotting):
|
|
162
|
+
self.plotting_widget.layout().addWidget(settings_plotting)
|
|
163
|
+
|
|
164
|
+
def populate_status_bar(self):
|
|
165
|
+
self._status_message_label = QtWidgets.QLabel('Initializing')
|
|
166
|
+
self._n_scan_steps_sb = QSpinBox_ro()
|
|
167
|
+
self._n_scan_steps_sb.setToolTip('Total number of steps')
|
|
168
|
+
self._indice_scan_sb = QSpinBox_ro()
|
|
169
|
+
self._indice_scan_sb.setToolTip('Current step value')
|
|
170
|
+
self._indice_average_sb = QSpinBox_ro()
|
|
171
|
+
self._indice_average_sb.setToolTip('Current average value')
|
|
172
|
+
|
|
173
|
+
self._scan_done_LED = QLED()
|
|
174
|
+
self._scan_done_LED.set_as_false()
|
|
175
|
+
self._scan_done_LED.clickable = False
|
|
176
|
+
self._scan_done_LED.setToolTip('Scan done state')
|
|
177
|
+
self._statusbar.addPermanentWidget(self._status_message_label)
|
|
178
|
+
|
|
179
|
+
self._statusbar.addPermanentWidget(self._n_scan_steps_sb)
|
|
180
|
+
self._statusbar.addPermanentWidget(self._indice_scan_sb)
|
|
181
|
+
self._statusbar.addPermanentWidget(self._indice_average_sb)
|
|
182
|
+
self._indice_average_sb.setVisible(False)
|
|
183
|
+
self._statusbar.addPermanentWidget(self._scan_done_LED)
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def n_scan_steps(self):
|
|
187
|
+
return self._n_scan_steps_sb.value()
|
|
188
|
+
|
|
189
|
+
@n_scan_steps.setter
|
|
190
|
+
def n_scan_steps(self, nsteps: int):
|
|
191
|
+
self._n_scan_steps_sb.setValue(nsteps)
|
|
192
|
+
|
|
193
|
+
def display_status(self, status: str, wait_time=1000):
|
|
194
|
+
self._statusbar.showMessage(status, wait_time)
|
|
195
|
+
|
|
196
|
+
def set_permanent_status(self, status: str):
|
|
197
|
+
self._status_message_label.setText(status)
|
|
198
|
+
|
|
199
|
+
def set_scan_step(self, step_ind: int):
|
|
200
|
+
self._indice_scan_sb.setValue(step_ind)
|
|
201
|
+
|
|
202
|
+
def show_average_step(self, show: bool = True):
|
|
203
|
+
self._indice_average_sb.setVisible(show)
|
|
204
|
+
|
|
205
|
+
def set_scan_step_average(self, step_ind: int):
|
|
206
|
+
self._indice_average_sb.setValue(step_ind)
|
|
207
|
+
|
|
208
|
+
def set_scan_done(self, done=True):
|
|
209
|
+
self._scan_done_LED.set_as(done)
|
|
210
|
+
|
|
211
|
+
def update_viewers(self, viewers_type: List[ViewersEnum], viewers_name: List[str] = None, force=False):
|
|
212
|
+
super().update_viewers(viewers_type, viewers_name, force)
|
|
213
|
+
self.command_sig.emit(ThreadCommand('viewers_changed', attribute=dict(viewer_types=self.viewer_types,
|
|
214
|
+
viewers=self.viewers)))
|
|
215
|
+
|
|
216
|
+
def main():
|
|
217
|
+
|
|
218
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
219
|
+
|
|
220
|
+
win = QtWidgets.QMainWindow()
|
|
221
|
+
dockarea = DockArea()
|
|
222
|
+
win.setCentralWidget(dockarea)
|
|
223
|
+
win.resize(1000, 500)
|
|
224
|
+
win.setWindowTitle('DAQScan Extension')
|
|
225
|
+
|
|
226
|
+
prog = DAQScanUI(dockarea)
|
|
227
|
+
win.show()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def print_command_sig(cmd_sig):
|
|
231
|
+
print(cmd_sig)
|
|
232
|
+
prog.display_status(str(cmd_sig))
|
|
233
|
+
|
|
234
|
+
prog.command_sig.connect(print_command_sig)
|
|
235
|
+
prog.update_viewers([ViewersEnum['Viewer0D'], ViewersEnum['Viewer1D'], ViewersEnum['Viewer2D']])
|
|
236
|
+
|
|
237
|
+
sys.exit(app.exec_())
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
if __name__ == '__main__':
|
|
241
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from pymodaq_utils.utils import ThreadCommand
|
|
5
|
+
from pymodaq_data.data import DataToExport
|
|
6
|
+
from pymodaq_gui.parameter import Parameter
|
|
7
|
+
|
|
8
|
+
from pymodaq.control_modules.viewer_utility_classes import DAQ_Viewer_base, comon_parameters, main
|
|
9
|
+
from pymodaq.utils.data import DataFromPlugins
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from pymodaq.extensions.data_mixer import DataMixer
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DAQ_0DViewer_DataMixer(DAQ_Viewer_base):
|
|
16
|
+
""" Instrument plugin class for a OD viewer.
|
|
17
|
+
|
|
18
|
+
This object inherits all functionalities to communicate with PyMoDAQ’s DAQ_Viewer module through inheritance via
|
|
19
|
+
DAQ_Viewer_base. It makes a bridge between the DAQ_Viewer module and the Python wrapper of a particular instrument.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
-----------
|
|
23
|
+
controller: object
|
|
24
|
+
The particular object that allow the communication with the hardware, in general a python wrapper around the
|
|
25
|
+
hardware library.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
params = (comon_parameters+
|
|
29
|
+
[
|
|
30
|
+
{'title': 'Related Detectors', 'name': 'overridden_detectors', 'type': 'list',
|
|
31
|
+
'readonly': True} # mandatory to know what detectors are related to the DataMixer
|
|
32
|
+
])
|
|
33
|
+
|
|
34
|
+
def ini_attributes(self):
|
|
35
|
+
self.controller: DataMixer = None
|
|
36
|
+
|
|
37
|
+
def commit_settings(self, param: Parameter):
|
|
38
|
+
"""Apply the consequences of a change of value in the detector settings
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
param: Parameter
|
|
43
|
+
A given parameter (within detector_settings) whose value has been changed by the user
|
|
44
|
+
"""
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
def ini_detector(self, controller=None):
|
|
48
|
+
"""Detector communication initialization
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
controller: (object)
|
|
53
|
+
custom object of a PyMoDAQ plugin (Slave case). None if only one actuator/detector by controller
|
|
54
|
+
(Master case)
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
info: str
|
|
59
|
+
initialized: bool
|
|
60
|
+
False if initialization failed otherwise True
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
self.controller: DataMixer = controller
|
|
64
|
+
if self.controller is not None:
|
|
65
|
+
self.controller.dte_computed_signal.connect(self.grab_done)
|
|
66
|
+
|
|
67
|
+
info = "DataMixer Detector Initialized"
|
|
68
|
+
initialized = True
|
|
69
|
+
return info, initialized
|
|
70
|
+
|
|
71
|
+
def close(self):
|
|
72
|
+
"""Terminate the communication protocol"""
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def grab_done(self, dte: DataToExport):
|
|
76
|
+
self.dte_signal.emit(dte)
|
|
77
|
+
|
|
78
|
+
def grab_data(self, Naverage=1, **kwargs):
|
|
79
|
+
"""Start a grab from the detector
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
Naverage: int
|
|
84
|
+
Number of hardware averaging (if hardware averaging is possible, self.hardware_averaging should be set to
|
|
85
|
+
True in class preamble and you should code this implementation)
|
|
86
|
+
kwargs: dict
|
|
87
|
+
others optionals arguments
|
|
88
|
+
"""
|
|
89
|
+
self.controller.snap()
|
|
90
|
+
|
|
91
|
+
def stop(self):
|
|
92
|
+
"""Stop the current grab hardware wise if necessary"""
|
|
93
|
+
return ''
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == '__main__':
|
|
97
|
+
main(__file__)
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
from qtpy import QtWidgets, QtCore
|
|
2
|
+
import numpy as np
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from pymodaq_gui import utils as gutils
|
|
8
|
+
from pymodaq_utils.config import Config, ConfigError
|
|
9
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
10
|
+
from pymodaq_utils.utils import find_dict_in_list_from_key_val
|
|
11
|
+
from pymodaq_data.data import DataToExport, DataWithAxes
|
|
12
|
+
|
|
13
|
+
from pymodaq.utils.config import Config as PyMoConfig
|
|
14
|
+
from pymodaq.extensions.utils import CustomExt
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher
|
|
18
|
+
from pymodaq_gui.utils.widgets.qled import QLED
|
|
19
|
+
from pymodaq_gui.parameter import utils as putils
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from pymodaq.extensions.data_mixer.model import get_models, DataMixerModel
|
|
23
|
+
from pymodaq.extensions.data_mixer.utils import DataMixerConfig, find_key_in_nested_dict
|
|
24
|
+
|
|
25
|
+
logger = set_logger(get_module_name(__file__))
|
|
26
|
+
|
|
27
|
+
config_utils = Config()
|
|
28
|
+
config_pymodaq = PyMoConfig()
|
|
29
|
+
|
|
30
|
+
EXTENSION_NAME = 'Data Mixer' # the name that will be displayed in the extension list in the
|
|
31
|
+
# dashboard
|
|
32
|
+
CLASS_NAME = 'DataMixer' # this should be the name of your class defined below
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DataMixer(CustomExt):
|
|
36
|
+
settings_name = 'DataMixerSettings'
|
|
37
|
+
models = get_models()
|
|
38
|
+
params = [
|
|
39
|
+
{'title': 'Models', 'name': 'models', 'type': 'group', 'expanded': True, 'visible': True,
|
|
40
|
+
'children': [
|
|
41
|
+
{'title': 'Models class:', 'name': 'model_class', 'type': 'list',
|
|
42
|
+
'limits': [d['name'] for d in models]},
|
|
43
|
+
{'title': 'Ini Model', 'name': 'ini_model', 'type': 'action', },
|
|
44
|
+
{'title': 'Model params:', 'name': 'model_params', 'type': 'group', 'children': []},
|
|
45
|
+
|
|
46
|
+
]}]
|
|
47
|
+
|
|
48
|
+
dte_computed_signal = QtCore.Signal(DataToExport)
|
|
49
|
+
|
|
50
|
+
def __init__(self, parent: gutils.DockArea, dashboard):
|
|
51
|
+
super().__init__(parent, dashboard)
|
|
52
|
+
|
|
53
|
+
self.model_class: Optional[DataMixerModel] = None
|
|
54
|
+
self.datamixer_config = DataMixerConfig()
|
|
55
|
+
self.setup_ui()
|
|
56
|
+
|
|
57
|
+
self.settings.child('models', 'ini_model').sigActivated.connect(
|
|
58
|
+
self.get_action('ini_model').trigger)
|
|
59
|
+
|
|
60
|
+
def get_set_model_params(self, model_name):
|
|
61
|
+
self.settings.child('models', 'model_params').clearChildren()
|
|
62
|
+
if len(self.models) > 0:
|
|
63
|
+
model_class = find_dict_in_list_from_key_val(self.models, 'name', model_name)['class']
|
|
64
|
+
params = getattr(model_class, 'params')
|
|
65
|
+
self.settings.child('models', 'model_params').addChildren(params)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def setup_docks(self):
|
|
69
|
+
"""Mandatory method to be subclassed to setup the docks layout
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
self.docks['settings'] = gutils.Dock('Settings')
|
|
73
|
+
self.dockarea.addDock(self.docks['settings'])
|
|
74
|
+
splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
|
75
|
+
self.docks['settings'].addWidget(splitter)
|
|
76
|
+
splitter.addWidget(self.modules_manager.settings_tree)
|
|
77
|
+
self.modules_manager.tree.header().setVisible(False)
|
|
78
|
+
self.modules_manager.settings.child('modules', 'actuators').hide()
|
|
79
|
+
self.modules_manager.settings.child('move_done').hide()
|
|
80
|
+
self.modules_manager.settings.child('det_done').hide()
|
|
81
|
+
self.modules_manager.settings.child('data_dimensions',
|
|
82
|
+
'det_data_list0D').setOpts(height=150)
|
|
83
|
+
self.modules_manager.settings.child('data_dimensions').hide()
|
|
84
|
+
self.modules_manager.settings.child('actuators_positions').hide()
|
|
85
|
+
|
|
86
|
+
splitter.addWidget(self.settings_tree)
|
|
87
|
+
|
|
88
|
+
self.docks['computed'] = gutils.Dock('Computed data')
|
|
89
|
+
self.dockarea.addDock(self.docks['computed'], 'right')
|
|
90
|
+
|
|
91
|
+
self.area_computed = gutils.DockArea()
|
|
92
|
+
self.docks['computed'].addWidget(self.area_computed)
|
|
93
|
+
|
|
94
|
+
self.dte_computed_viewer = ViewerDispatcher(self.area_computed)
|
|
95
|
+
|
|
96
|
+
if len(self.models) != 0:
|
|
97
|
+
self.get_set_model_params(self.models[0]['name'])
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def config_path(self) -> Path:
|
|
101
|
+
return self.datamixer_config.config_path
|
|
102
|
+
|
|
103
|
+
def validate_config(self) -> bool:
|
|
104
|
+
""" Read eventually saved settings from self.datamixer_config
|
|
105
|
+
|
|
106
|
+
Example
|
|
107
|
+
-------
|
|
108
|
+
utility = find_key_in_nested_dict(self.datamixer_config.to_dict(), 'prediction')
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
def setup_actions(self):
|
|
114
|
+
"""Method where to create actions to be subclassed. Mandatory
|
|
115
|
+
|
|
116
|
+
"""
|
|
117
|
+
self.add_action('quit', 'Quit', 'close2', "Quit program")
|
|
118
|
+
combo_model = QtWidgets.QComboBox()
|
|
119
|
+
combo_model.addItems([model['name'] for model in self.models])
|
|
120
|
+
self.add_widget('models', combo_model, tip='List of available models')
|
|
121
|
+
self.add_action('ini_model', 'Init Model', 'ini')
|
|
122
|
+
self.add_widget('model_led', QLED, toolbar=self.toolbar)
|
|
123
|
+
self.add_action('snap', 'Snap Detectors', 'snap',
|
|
124
|
+
'Snap all selected detectors')
|
|
125
|
+
self.add_action('create_computed_detectors', 'Create Computed Detectors', 'Add_Step',
|
|
126
|
+
tip='Create a DAQ_Viewer Control Module')
|
|
127
|
+
|
|
128
|
+
def connect_things(self):
|
|
129
|
+
"""Connect actions and/or other widgets signal to methods"""
|
|
130
|
+
self.connect_action('quit', self.quit_fun)
|
|
131
|
+
self.connect_action('models', self.update_model_settings_from_action, signal_name='currentTextChanged')
|
|
132
|
+
self.connect_action('ini_model', self.ini_model)
|
|
133
|
+
self.modules_manager.det_done_signal.connect(self.process_data)
|
|
134
|
+
self.dte_computed_signal.connect(self.plot_computed_results)
|
|
135
|
+
self.connect_action('snap', self.snap)
|
|
136
|
+
self.modules_manager.detectors_changed.connect(self.update_connect_detectors)
|
|
137
|
+
self.connect_action('create_computed_detectors', self.create_computed_detectors)
|
|
138
|
+
|
|
139
|
+
def update_model_settings_from_action(self, model: str):
|
|
140
|
+
self.settings.child('models', 'model_class').setValue(model)
|
|
141
|
+
|
|
142
|
+
def process_data(self, dte: DataToExport):
|
|
143
|
+
if self.model_class is not None:
|
|
144
|
+
dte_computed = self.model_class.process_dte(dte)
|
|
145
|
+
self.dte_computed_signal.emit(dte_computed)
|
|
146
|
+
|
|
147
|
+
def snap(self):
|
|
148
|
+
self.modules_manager.grab_data(check_do_override=False)
|
|
149
|
+
|
|
150
|
+
def create_computed_detectors(self):
|
|
151
|
+
try:
|
|
152
|
+
self.dashboard.add_det_from_extension('DataMixer', 'DAQ0D', 'DataMixer', self)
|
|
153
|
+
self.dashboard.modules_manager.get_mod_from_name(
|
|
154
|
+
'DataMixer', 'det').settings.child('detector_settings', 'overridden_detectors').setOpts(
|
|
155
|
+
limits=self.modules_manager.selected_detectors_name)
|
|
156
|
+
self.set_action_enabled('create_computed_detectors', False)
|
|
157
|
+
#self.dashboard.override_det_from_extension(self.modules_manager.selected_detectors_name)
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.exception(str(e))
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
def update_connect_detectors(self):
|
|
163
|
+
try:
|
|
164
|
+
self.connect_detectors(False)
|
|
165
|
+
except :
|
|
166
|
+
pass
|
|
167
|
+
self.connect_detectors()
|
|
168
|
+
|
|
169
|
+
def connect_detectors(self, connect=True):
|
|
170
|
+
"""Connect detectors to DAQ_Logging do_save_continuous method
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
connect: bool
|
|
175
|
+
If True make the connection else disconnect
|
|
176
|
+
"""
|
|
177
|
+
self.modules_manager.connect_detectors(connect=connect)
|
|
178
|
+
|
|
179
|
+
def plot_computed_results(self, dte):
|
|
180
|
+
self.dte_computed_viewer.show_data(dte)
|
|
181
|
+
|
|
182
|
+
def ini_model(self):
|
|
183
|
+
if self.model_class is None:
|
|
184
|
+
self.set_model()
|
|
185
|
+
|
|
186
|
+
self.get_action('model_led').set_as_true()
|
|
187
|
+
self.set_action_enabled('ini_model', False)
|
|
188
|
+
self.settings.child('models', 'ini_model').setValue(True)
|
|
189
|
+
self.set_action_enabled('models', False)
|
|
190
|
+
self.settings.child('models', 'model_class').setOpts(enabled=False)
|
|
191
|
+
self.modules_manager.settings_tree.setEnabled(False)
|
|
192
|
+
|
|
193
|
+
self.update_connect_detectors()
|
|
194
|
+
|
|
195
|
+
def set_model(self):
|
|
196
|
+
model_name = self.settings['models', 'model_class']
|
|
197
|
+
self.model_class = find_dict_in_list_from_key_val(
|
|
198
|
+
self.models, 'name', model_name)['class'](self)
|
|
199
|
+
self.model_class.ini_model_base()
|
|
200
|
+
|
|
201
|
+
def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
|
|
202
|
+
"""Non mandatory method to be subclassed in order to create a menubar
|
|
203
|
+
|
|
204
|
+
create menu for actions contained into the self._actions, for instance:
|
|
205
|
+
|
|
206
|
+
Examples
|
|
207
|
+
--------
|
|
208
|
+
>>>file_menu = self.mainwindow.menuBar().addMenu('File')
|
|
209
|
+
>>>self.affect_to('load', file_menu)
|
|
210
|
+
>>>self.affect_to('save', file_menu)
|
|
211
|
+
|
|
212
|
+
>>>file_menu.addSeparator()
|
|
213
|
+
>>>self.affect_to('quit', file_menu)
|
|
214
|
+
|
|
215
|
+
See Also
|
|
216
|
+
--------
|
|
217
|
+
pymodaq.utils.managers.action_manager.ActionManager
|
|
218
|
+
"""
|
|
219
|
+
# todo create and populate menu using actions defined above in self.setup_actions
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
def value_changed(self, param):
|
|
223
|
+
""" Actions to perform when one of the param's value in self.settings is changed from the
|
|
224
|
+
user interface
|
|
225
|
+
|
|
226
|
+
For instance:
|
|
227
|
+
if param.name() == 'do_something':
|
|
228
|
+
if param.value():
|
|
229
|
+
print('Do something')
|
|
230
|
+
self.settings.child('main_settings', 'something_done').setValue(False)
|
|
231
|
+
|
|
232
|
+
Parameters
|
|
233
|
+
----------
|
|
234
|
+
param: (Parameter) the parameter whose value just changed
|
|
235
|
+
"""
|
|
236
|
+
if param.name() == 'model_class':
|
|
237
|
+
self.get_set_model_params(param.value())
|
|
238
|
+
self.get_action('models').setCurrentText(param.value())
|
|
239
|
+
elif param.name() in putils.iter_children(self.settings.child('models', 'model_params'), []):
|
|
240
|
+
if self.model_class is not None:
|
|
241
|
+
self.model_class.update_settings(param)
|
|
242
|
+
|
|
243
|
+
def quit_fun(self):
|
|
244
|
+
self.mainwindow.close()
|
|
245
|
+
self.dashboard.remove_modules(['DataMixer'])
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def main():
|
|
249
|
+
from pymodaq_gui.utils.utils import mkQApp
|
|
250
|
+
from pymodaq.utils.gui_utils.loader_utils import load_dashboard_with_preset
|
|
251
|
+
|
|
252
|
+
app = mkQApp('DataMixer')
|
|
253
|
+
|
|
254
|
+
preset_file_name = config_pymodaq('presets', 'default_preset_for_datamixer')
|
|
255
|
+
dashboard, extension, win = load_dashboard_with_preset(preset_file_name, EXTENSION_NAME)
|
|
256
|
+
app.exec()
|
|
257
|
+
|
|
258
|
+
return dashboard, extension, win
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
if __name__ == '__main__':
|
|
262
|
+
main()
|