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.
Files changed (154) hide show
  1. pymodaq/__init__.py +98 -0
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +1238 -0
  4. pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  5. pymodaq/control_modules/daq_move_ui/factory.py +48 -0
  6. pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
  7. pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  8. pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
  9. pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
  10. pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
  11. pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
  12. pymodaq/control_modules/daq_viewer.py +1517 -0
  13. pymodaq/control_modules/daq_viewer_ui.py +407 -0
  14. pymodaq/control_modules/mocks.py +57 -0
  15. pymodaq/control_modules/move_utility_classes.py +1141 -0
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +591 -0
  19. pymodaq/control_modules/viewer_utility_classes.py +670 -0
  20. pymodaq/daq_utils/__init__.py +0 -0
  21. pymodaq/daq_utils/daq_utils.py +6 -0
  22. pymodaq/dashboard.py +2396 -0
  23. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
  24. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
  25. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
  26. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
  27. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
  28. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
  29. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
  30. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
  31. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
  32. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
  33. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
  34. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
  35. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
  36. pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
  37. pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
  38. pymodaq/examples/__init__.py +0 -0
  39. pymodaq/examples/function_plotter.py +160 -0
  40. pymodaq/examples/nonlinearscanner.py +126 -0
  41. pymodaq/examples/qt_less_standalone_module.py +165 -0
  42. pymodaq/examples/tcp_client.py +97 -0
  43. pymodaq/extensions/__init__.py +25 -0
  44. pymodaq/extensions/adaptive/__init__.py +2 -0
  45. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  46. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  47. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  48. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  49. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  50. pymodaq/extensions/adaptive/utils.py +123 -0
  51. pymodaq/extensions/bayesian/__init__.py +2 -0
  52. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  53. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  54. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  55. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  56. pymodaq/extensions/bayesian/utils.py +180 -0
  57. pymodaq/extensions/console.py +73 -0
  58. pymodaq/extensions/daq_logger/__init__.py +1 -0
  59. pymodaq/extensions/daq_logger/abstract.py +52 -0
  60. pymodaq/extensions/daq_logger/daq_logger.py +519 -0
  61. pymodaq/extensions/daq_logger/db/__init__.py +0 -0
  62. pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
  63. pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
  64. pymodaq/extensions/daq_logger/h5logging.py +84 -0
  65. pymodaq/extensions/daq_scan.py +1218 -0
  66. pymodaq/extensions/daq_scan_ui.py +241 -0
  67. pymodaq/extensions/data_mixer/__init__.py +0 -0
  68. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  69. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  70. pymodaq/extensions/data_mixer/model.py +108 -0
  71. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  72. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  73. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  74. pymodaq/extensions/data_mixer/parser.py +53 -0
  75. pymodaq/extensions/data_mixer/utils.py +23 -0
  76. pymodaq/extensions/h5browser.py +9 -0
  77. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  78. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  79. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  80. pymodaq/extensions/optimizers_base/utils.py +427 -0
  81. pymodaq/extensions/pid/__init__.py +16 -0
  82. pymodaq/extensions/pid/actuator_controller.py +14 -0
  83. pymodaq/extensions/pid/daq_move_PID.py +154 -0
  84. pymodaq/extensions/pid/pid_controller.py +1016 -0
  85. pymodaq/extensions/pid/utils.py +189 -0
  86. pymodaq/extensions/utils.py +111 -0
  87. pymodaq/icon.ico +0 -0
  88. pymodaq/post_treatment/__init__.py +6 -0
  89. pymodaq/post_treatment/load_and_plot.py +352 -0
  90. pymodaq/resources/__init__.py +0 -0
  91. pymodaq/resources/config_template.toml +57 -0
  92. pymodaq/resources/preset_default.xml +1 -0
  93. pymodaq/resources/setup_plugin.py +73 -0
  94. pymodaq/splash.png +0 -0
  95. pymodaq/utils/__init__.py +0 -0
  96. pymodaq/utils/array_manipulation.py +6 -0
  97. pymodaq/utils/calibration_camera.py +180 -0
  98. pymodaq/utils/chrono_timer.py +203 -0
  99. pymodaq/utils/config.py +53 -0
  100. pymodaq/utils/conftests.py +5 -0
  101. pymodaq/utils/daq_utils.py +158 -0
  102. pymodaq/utils/data.py +128 -0
  103. pymodaq/utils/enums.py +6 -0
  104. pymodaq/utils/exceptions.py +38 -0
  105. pymodaq/utils/gui_utils/__init__.py +10 -0
  106. pymodaq/utils/gui_utils/loader_utils.py +75 -0
  107. pymodaq/utils/gui_utils/utils.py +18 -0
  108. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  109. pymodaq/utils/h5modules/__init__.py +2 -0
  110. pymodaq/utils/h5modules/module_saving.py +526 -0
  111. pymodaq/utils/leco/__init__.py +25 -0
  112. pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
  113. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
  114. pymodaq/utils/leco/director_utils.py +74 -0
  115. pymodaq/utils/leco/leco_director.py +166 -0
  116. pymodaq/utils/leco/pymodaq_listener.py +364 -0
  117. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  118. pymodaq/utils/leco/utils.py +74 -0
  119. pymodaq/utils/logger.py +6 -0
  120. pymodaq/utils/managers/__init__.py +0 -0
  121. pymodaq/utils/managers/batchscan_manager.py +346 -0
  122. pymodaq/utils/managers/modules_manager.py +589 -0
  123. pymodaq/utils/managers/overshoot_manager.py +242 -0
  124. pymodaq/utils/managers/preset_manager.py +229 -0
  125. pymodaq/utils/managers/preset_manager_utils.py +262 -0
  126. pymodaq/utils/managers/remote_manager.py +484 -0
  127. pymodaq/utils/math_utils.py +6 -0
  128. pymodaq/utils/messenger.py +6 -0
  129. pymodaq/utils/parameter/__init__.py +10 -0
  130. pymodaq/utils/parameter/utils.py +6 -0
  131. pymodaq/utils/scanner/__init__.py +5 -0
  132. pymodaq/utils/scanner/scan_config.py +16 -0
  133. pymodaq/utils/scanner/scan_factory.py +259 -0
  134. pymodaq/utils/scanner/scan_selector.py +477 -0
  135. pymodaq/utils/scanner/scanner.py +324 -0
  136. pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
  137. pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
  138. pymodaq/utils/scanner/scanners/__init__.py +1 -0
  139. pymodaq/utils/scanner/scanners/sequential.py +224 -0
  140. pymodaq/utils/scanner/scanners/tabular.py +319 -0
  141. pymodaq/utils/scanner/utils.py +110 -0
  142. pymodaq/utils/svg/__init__.py +6 -0
  143. pymodaq/utils/svg/svg_renderer.py +20 -0
  144. pymodaq/utils/svg/svg_view.py +35 -0
  145. pymodaq/utils/svg/svg_viewer2D.py +50 -0
  146. pymodaq/utils/tcp_ip/__init__.py +6 -0
  147. pymodaq/utils/tcp_ip/mysocket.py +12 -0
  148. pymodaq/utils/tcp_ip/serializer.py +13 -0
  149. pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
  150. pymodaq-5.1.6.dist-info/METADATA +238 -0
  151. pymodaq-5.1.6.dist-info/RECORD +154 -0
  152. pymodaq-5.1.6.dist-info/WHEEL +4 -0
  153. pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
  154. 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()