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,589 @@
1
+ from typing import List, Union, TYPE_CHECKING, Optional, Sequence
2
+
3
+ from collections import OrderedDict
4
+ from qtpy.QtCore import QObject, Signal, Slot, QThread
5
+ from qtpy import QtWidgets
6
+ import time
7
+
8
+ from pymodaq_utils.logger import set_logger, get_module_name
9
+ from pymodaq_utils import utils
10
+ from pymodaq_utils.config import Config
11
+
12
+ from pymodaq_data.data import DataToExport
13
+
14
+ from pymodaq_gui.managers.parameter_manager import ParameterManager
15
+ from pymodaq_gui.utils import Dock
16
+
17
+ from pymodaq.utils.data import DataActuator
18
+ from pymodaq.utils.config import Config as ControlModulesConfig
19
+
20
+ if TYPE_CHECKING:
21
+ from pymodaq.control_modules.daq_viewer import DAQ_Viewer
22
+ from pymodaq.control_modules.daq_move import DAQ_Move
23
+
24
+ logger = set_logger(get_module_name(__file__))
25
+
26
+ config_utils = Config()
27
+ config = ControlModulesConfig()
28
+
29
+
30
+ class ModulesManager(QObject, ParameterManager):
31
+ """Class to manage DAQ_Viewers and DAQ_Moves with UI to select some
32
+
33
+ Easier to connect control modules signals to slots, test, ...
34
+
35
+ Parameters
36
+ ----------
37
+ detectors: list of DAQ_Viewer
38
+ actuators: list of DAQ_Move
39
+ selected_detectors: list of DAQ_Viewer
40
+ sublist of detectors
41
+ selected_actuators: list of DAQ_Move
42
+ sublist of actuators
43
+ """
44
+ settings_name = 'ModulesManagerSettings'
45
+ detectors_changed = Signal(list)
46
+ actuators_changed = Signal(list)
47
+ det_done_signal = Signal(DataToExport) # dte here contains DataWithAxes
48
+ move_done_signal = Signal(DataToExport) # dte here contains DataActuators
49
+ timeout_signal = Signal(bool)
50
+
51
+ params = [
52
+ {'title': 'Actuators/Detectors Selection', 'name': 'modules', 'type': 'group', 'children': [
53
+ {'title': 'detectors', 'name': 'detectors', 'type': 'itemselect', 'checkbox': True},
54
+ {'title': 'Actuators', 'name': 'actuators', 'type': 'itemselect', 'checkbox': True},
55
+ ]},
56
+
57
+ {'title': "Moves done?", 'name': 'move_done', 'type': 'led', 'value': False},
58
+ {'title': "Detections done?", 'name': 'det_done', 'type': 'led', 'value': False},
59
+
60
+ {'title': 'Data dimensions', 'name': 'data_dimensions', 'type': 'group', 'children': [
61
+ {'title': "Probe detector's data", 'name': 'probe_data', 'type': 'action'},
62
+ {'title': 'Data0D list:', 'name': 'det_data_list0D', 'type': 'itemselect'},
63
+ {'title': 'Data1D list:', 'name': 'det_data_list1D', 'type': 'itemselect'},
64
+ {'title': 'Data2D list:', 'name': 'det_data_list2D', 'type': 'itemselect'},
65
+ {'title': 'DataND list:', 'name': 'det_data_listND', 'type': 'itemselect'},
66
+ ]},
67
+ {'title': 'Actuators positions', 'name': 'actuators_positions', 'type': 'group', 'children': [
68
+ {'title': "Test actuators", 'name': 'test_actuator', 'type': 'action'},
69
+ {'title': 'Positions:', 'name': 'positions_list', 'type': 'itemselect'},
70
+ ]},
71
+ ]
72
+
73
+ def __init__(self,
74
+ detectors: Optional[Sequence['DAQ_Viewer']] = None,
75
+ actuators: Optional[Sequence['DAQ_Move']] = None,
76
+ selected_detectors: Optional[Sequence['DAQ_Viewer']] = None,
77
+ selected_actuators: Optional[Sequence['DAQ_Move']] = None,
78
+ parent_name='',
79
+ **kwargs):
80
+
81
+ QObject.__init__(self)
82
+ ParameterManager.__init__(self)
83
+ if detectors is None:
84
+ detectors = []
85
+ if actuators is None:
86
+ actuators = []
87
+ if selected_detectors is None:
88
+ selected_detectors = []
89
+ if selected_actuators is None:
90
+ selected_actuators = []
91
+
92
+ self.parent_name = parent_name
93
+
94
+ for mod in selected_actuators:
95
+ assert mod in actuators
96
+ for mod in selected_detectors:
97
+ assert mod in detectors
98
+
99
+ self.actuator_timeout = config('actuator', 'timeout')
100
+ self.detector_timeout = config('viewer', 'timeout')
101
+
102
+ self.det_done_datas: DataToExport = None
103
+ self.det_done_flag = False
104
+ self.move_done_positions: DataToExport = None
105
+ self.move_done_flag = False
106
+
107
+ self.settings.child('data_dimensions', 'probe_data').sigActivated.connect(self.get_det_data_list)
108
+ self.settings.child('actuators_positions', 'test_actuator').sigActivated.connect(self.test_move_actuators)
109
+
110
+ self._detectors = []
111
+ self._actuators = []
112
+
113
+ self.grab_done_signals = []
114
+ self.det_commands_signal = []
115
+
116
+ self.actuators_connected = False
117
+ self.detectors_connected = False
118
+
119
+ self.set_actuators(actuators, selected_actuators)
120
+ self.set_detectors(detectors, selected_detectors)
121
+
122
+ def __repr__(self):
123
+ return f'ModulesManager of "{self.parent_name}" with control modules: {self.get_names(self.modules_all)}'
124
+
125
+ def show_only_control_modules(self, show: True):
126
+ self.settings.child('move_done').show(not show)
127
+ self.settings.child('det_done').show(not show)
128
+ self.settings.child('data_dimensions').show(not show)
129
+ self.settings.child('actuators_positions').show(not show)
130
+
131
+ @classmethod
132
+ def get_names(cls, modules):
133
+ """Get the titles of a list of Control Modules
134
+
135
+ Parameters
136
+ ----------
137
+ modules: list of DAQ_Move and/or DAQ_Viewer
138
+ """
139
+ if not hasattr(modules, '__iter__'):
140
+ modules = [modules]
141
+ return [mod.title for mod in modules]
142
+
143
+ def get_mods_from_names(self, names, mod='det') -> List[Union['DAQ_Move', 'DAQ_Viewer']]:
144
+ """Getter of a list of given modules from their name (title)
145
+
146
+ Parameters
147
+ ----------
148
+ names: list of str
149
+ mod: str
150
+ either 'det' for DAQ_Viewer modules or 'act' for DAQ_Move modules
151
+ """
152
+ mods = []
153
+ for name in names:
154
+ d = self.get_mod_from_name(name, mod)
155
+ if d is not None:
156
+ mods.append(d)
157
+ return mods
158
+
159
+ def get_mod_from_name(self, name, mod='det') -> Union['DAQ_Move', 'DAQ_Viewer']:
160
+ """Getter of a given module from its name (title)
161
+
162
+ Parameters
163
+ ----------
164
+ name: str
165
+ mod: str
166
+ either 'det' for DAQ_Viewer modules or 'act' for DAQ_Move modules
167
+ """
168
+ if mod == 'det':
169
+ modules = self._detectors
170
+ else:
171
+ modules = self._actuators
172
+
173
+ if name in self.get_names(modules):
174
+ return modules[self.get_names(modules).index(name)]
175
+ else:
176
+ logger.warning(f'No detector with this name: {name}')
177
+ return None
178
+
179
+ def set_actuators(self, actuators, selected_actuators):
180
+ """Populates actuators and the subset to be selected in the UI"""
181
+ self._actuators = actuators
182
+ self.settings.child('modules', 'actuators').setValue(dict(all_items=self.get_names(actuators),
183
+ selected=self.get_names(selected_actuators)))
184
+
185
+ def set_detectors(self, detectors, selected_detectors):
186
+ """Populates detectors and the subset to be selected in the UI"""
187
+ self._detectors = detectors
188
+ self.settings.child('modules', 'detectors').setValue(dict(all_items=self.get_names(detectors),
189
+ selected=self.get_names(selected_detectors)))
190
+
191
+ @property
192
+ def detectors(self) -> List['DAQ_Viewer']:
193
+ """Get the list of selected detectors"""
194
+ return self.get_mods_from_names(self.selected_detectors_name)
195
+
196
+ @property
197
+ def detectors_all(self) -> List['DAQ_Viewer']:
198
+ """Get/Set the list of all detectors"""
199
+ return self._detectors
200
+
201
+ @detectors_all.setter
202
+ def detectors_all(self, detectors: List['DAQ_Viewer']):
203
+ self._detectors = detectors
204
+
205
+ @property
206
+ def actuators(self) -> List['DAQ_Move']:
207
+ """Get the list of selected actuators"""
208
+ return self.get_mods_from_names(self.selected_actuators_name, mod='act')
209
+
210
+ @property
211
+ def actuators_all(self):
212
+ """Get the list of all actuators"""
213
+ return self._actuators
214
+
215
+ @actuators_all.setter
216
+ def actuators_all(self, actuators: List['DAQ_Move']):
217
+ self._actuators = actuators
218
+
219
+ @property
220
+ def modules(self):
221
+ """Get the list of detectors and actuators"""
222
+ return self.detectors + self.actuators
223
+
224
+ @property
225
+ def modules_all(self):
226
+ """Get the list of all detectors and actuators"""
227
+ return self.detectors_all + self.actuators_all
228
+
229
+ @property
230
+ def Ndetectors(self):
231
+ """Get the number of selected detectors"""
232
+ return len(self.detectors)
233
+
234
+ @property
235
+ def Nactuators(self):
236
+ """Get the number of selected actuators"""
237
+ return len(self.actuators)
238
+
239
+ @property
240
+ def detectors_name(self):
241
+ """Get all the names of the detectors"""
242
+ return self.settings.child('modules', 'detectors').value()['all_items']
243
+
244
+ @property
245
+ def selected_detectors_name(self):
246
+ """Get/Set the names of the selected detectors"""
247
+ return self.settings.child('modules', 'detectors').value()['selected']
248
+
249
+ @selected_detectors_name.setter
250
+ def selected_detectors_name(self, detectors):
251
+ if set(detectors).issubset(self.detectors_name):
252
+ self.settings.child('modules', 'detectors').setValue(dict(all_items=self.detectors_name,
253
+ selected=detectors))
254
+
255
+ @property
256
+ def actuators_name(self):
257
+ """Get all the names of the actuators"""
258
+ return self.settings.child('modules', 'actuators').value()['all_items']
259
+
260
+ @property
261
+ def selected_actuators_name(self) -> List[str]:
262
+ """Get/Set the names of the selected actuators"""
263
+ return self.settings.child('modules', 'actuators').value()['selected']
264
+
265
+ @selected_actuators_name.setter
266
+ def selected_actuators_name(self, actuators):
267
+ if set(actuators).issubset(self.actuators_name):
268
+ self.settings.child('modules', 'actuators').setValue(dict(all_items=self.actuators_name,
269
+ selected=actuators))
270
+
271
+ def value_changed(self, param):
272
+ if param.name() == 'detectors':
273
+ self.detectors_changed.emit(param.value()['selected'])
274
+
275
+ elif param.name() == 'actuators':
276
+ self.actuators_changed.emit(param.value()['selected'])
277
+
278
+ def get_det_data_list(self) -> DataToExport:
279
+ """Do a snap of selected detectors, to get the list of all the data and processed data"""
280
+
281
+ if len(self.detectors) == 0:
282
+ return DataToExport(name=__class__.__name__, control_module='DAQ_Viewer')
283
+ else:
284
+ self.connect_detectors()
285
+ datas: DataToExport = self.grab_data()
286
+
287
+ data_list0D = datas.get_full_names('data0D')
288
+ data_list1D = datas.get_full_names('data1D')
289
+ data_list2D = datas.get_full_names('data2D')
290
+ data_listND = datas.get_full_names('dataND')
291
+
292
+ self.settings.child('data_dimensions', 'det_data_list0D').setValue(
293
+ dict(all_items=data_list0D, selected=[]))
294
+ self.settings.child('data_dimensions', 'det_data_list1D').setValue(
295
+ dict(all_items=data_list1D, selected=[]))
296
+ self.settings.child('data_dimensions', 'det_data_list2D').setValue(
297
+ dict(all_items=data_list2D, selected=[]))
298
+ self.settings.child('data_dimensions', 'det_data_listND').setValue(
299
+ dict(all_items=data_listND, selected=[]))
300
+
301
+ self.connect_detectors(False)
302
+ return datas
303
+
304
+ def get_selected_probed_data(self, dim='0D'):
305
+ """Get the name of selected data names of a given dimensionality
306
+
307
+ Parameters
308
+ ----------
309
+ dim: str
310
+ either '0D', '1D', '2D' or 'ND'
311
+ """
312
+ return self.settings.child('data_dimensions', f'det_data_list{dim.upper()}').value()['selected']
313
+
314
+ def grab_data(self, check_do_override=True, **kwargs):
315
+ """Do a single grab of connected and selected detectors
316
+
317
+ Parameter
318
+ ---------
319
+ check_do_override: bool
320
+ If this is True the signal emission to the DAQ_Viewers will be conditionned to the status of their internal
321
+ override_grab_from_extension attribute
322
+ """
323
+ self.det_done_datas = DataToExport(name=__class__.__name__, control_module='DAQ_Viewer')
324
+ self._received_data = 0
325
+ self.det_done_flag = False
326
+ self.settings.child('det_done').setValue(self.det_done_flag)
327
+ tzero = time.perf_counter()
328
+
329
+ if 'DataMixer' in self.selected_detectors_name:
330
+ overridden_detectors = self.get_mod_from_name(
331
+ 'DataMixer', 'det').settings.child(
332
+ 'detector_settings', 'overridden_detectors').opts['limits']
333
+ else:
334
+ overridden_detectors = []
335
+
336
+ for mod in self.detectors:
337
+ #if not (check_do_override and mod.override_grab_from_extension):
338
+ if mod.title not in overridden_detectors:
339
+ kwargs.update(dict(Naverage=mod.Naverage))
340
+ mod.command_hardware.emit(utils.ThreadCommand("single", kwargs))
341
+
342
+ while not self.det_done_flag:
343
+ # wait for grab done signals to end
344
+ QtWidgets.QApplication.processEvents() # mandatory for the det_done_flag boolean to be modified in the corresponding method
345
+ if time.perf_counter() - tzero > self.detector_timeout / 1000:
346
+ self.timeout_signal.emit(True)
347
+ logger.error('Timeout Fired during waiting for data to be acquired')
348
+ break
349
+ QThread.msleep(10)
350
+
351
+ self.det_done_signal.emit(self.det_done_datas)
352
+ return self.det_done_datas
353
+
354
+ def grab_datas(self, **kwargs):
355
+ """ For back compatibility but use self.grab_data"""
356
+ return self.grab_data(**kwargs)
357
+
358
+ def connect_actuators(self, connect=True, slot=None, signal='move_done'):
359
+ """Connect the selected actuators signal to a given or default slot
360
+
361
+ Parameters
362
+ ----------
363
+ connect: bool
364
+ slot: builtin_function_or_method
365
+ method or function the chosen signal will be connected to
366
+ if None, then the default move_done slot is used
367
+ signal: str
368
+ What kind of signal is to be used:
369
+
370
+ * 'move_done' will connect the `move_done_signal` to the slot
371
+ * 'current_value' will connect the 'current_value_signal' to the slot
372
+
373
+ See Also
374
+ --------
375
+ :meth:`move_done`
376
+ """
377
+ if slot is None:
378
+ slot = self.move_done
379
+ if connect:
380
+ for sig in [mod.move_done_signal if signal == 'move_done' else mod.current_value_signal
381
+ for mod in self.actuators]:
382
+ sig.connect(slot)
383
+
384
+ else:
385
+ try:
386
+ for sig in [mod.move_done_signal if signal == 'move_done' else mod.current_value_signal
387
+ for mod in self.actuators]:
388
+ sig.disconnect(slot)
389
+ except Exception as e:
390
+ logger.error(str(e))
391
+
392
+ self.actuators_connected = connect
393
+
394
+ def connect_detectors(self, connect=True, slot=None):
395
+ """
396
+ Connect selected DAQ_Viewers's grab_done_signal to the given slot
397
+
398
+ Parameters
399
+ ----------
400
+ connect: bool
401
+ if True, connect to the given slot (or default slot)
402
+ if False, disconnect all detectors (not only the currently selected ones.
403
+ This is made because when selected detectors changed if you only disconnect those one,
404
+ the previously connected ones will stay connected)
405
+ slot: method
406
+ A method that should be connected, if None self.det_done is connected by default
407
+ """
408
+
409
+ if slot is None:
410
+ slot = self.det_done
411
+
412
+ if connect:
413
+ for sig in [mod.grab_done_signal for mod in self.detectors]:
414
+ sig.connect(slot)
415
+ else:
416
+
417
+ for sig in [mod.grab_done_signal for mod in self.detectors]:
418
+ try:
419
+ sig.disconnect(slot)
420
+ except TypeError as e:
421
+ # means the slot was not previously connected
422
+ logger.info(f'Could not disconnect grab signal from the {slot} slot', stacklevel=2)
423
+
424
+ self.detectors_connected = connect
425
+
426
+ def test_move_actuators(self):
427
+ """Do a move of selected actuator"""
428
+ dte_act = DataToExport('Actuators', control_module='DAQ_MOVE')
429
+ for act in self.get_names(self.actuators):
430
+ pos, done = QtWidgets.QInputDialog.getDouble(None, f'Enter a target position for actuator {act}',
431
+ 'Position:')
432
+ if not done:
433
+ pos = 0.
434
+ dte_act.append(DataActuator(act, data=pos))
435
+
436
+ self.connect_actuators()
437
+
438
+ self.move_actuators(dte_act)
439
+
440
+ self.settings.child('actuators_positions',
441
+ 'positions_list').setValue(dict(all_items=[f'{dact.name}: {dact.value()}' for dact
442
+ in dte_act],
443
+ selected=[]))
444
+
445
+ self.connect_actuators(False)
446
+
447
+ def move_actuators(self, dte_act: DataToExport, mode='abs', polling=True) -> DataToExport:
448
+ """will apply positions to each currently selected actuators. By Default the mode is absolute but can be
449
+
450
+ Parameters
451
+ ----------
452
+ dte_act: DataToExport
453
+ the DataToExport of position to apply. Its length must be equal to the number of selected actuators
454
+ mode: str
455
+ either 'abs' for absolute positionning or 'rel' for relative
456
+ polling: bool
457
+ if True will wait for the selected actuators to reach their target positions (they have to be
458
+ connected to a method checking for the position and letting the programm know the move is done (default
459
+ connection is this object `move_done` method)
460
+
461
+ Returns
462
+ -------
463
+ DataToExport with the selected actuators's name as key and current actuators's value as value
464
+ """
465
+ self.move_done_positions = DataToExport(name=__class__.__name__, control_module='DAQ_Move')
466
+ self.move_done_flag = False
467
+ self.settings.child('move_done').setValue(self.move_done_flag)
468
+
469
+ if mode == 'abs':
470
+ command = 'move_abs'
471
+ elif mode == 'rel':
472
+ command = 'move_rel'
473
+ else:
474
+ logger.error(f'Invalid positioning mode: {mode}')
475
+ return self.move_done_positions
476
+
477
+ if len(dte_act) == self.Nactuators:
478
+ for dact in dte_act:
479
+ act = self.get_mod_from_name(dact.name, 'act')
480
+ if act is not None:
481
+ act.command_hardware.emit(
482
+ utils.ThreadCommand(command=command, attribute=[dact, polling]))
483
+ # else:
484
+ # for ind, act in enumerate(self.actuators):
485
+ # #getattr(act, command)(positions[ind])
486
+ # act.command_hardware.emit(utils.ThreadCommand(command=command, attribute=[positions[ind], polling]))
487
+
488
+ else:
489
+ logger.error('Invalid number of positions compared to selected actuators')
490
+ return self.move_done_positions
491
+
492
+ tzero = time.perf_counter()
493
+ if polling:
494
+ while not self.move_done_flag: # polling move done
495
+
496
+ QtWidgets.QApplication.processEvents() # mandatory for the det_done_flag boolean to be modified in the corresponding method
497
+ if time.perf_counter() - tzero > self.actuator_timeout / 1000: # timeout in seconds
498
+ self.timeout_signal.emit(True)
499
+ logger.error('Timeout Fired during waiting for actuators to be moved')
500
+ break
501
+ QThread.msleep(10)
502
+
503
+ self.move_done_signal.emit(self.move_done_positions)
504
+ return self.move_done_positions
505
+
506
+ def reset_signals(self):
507
+ self.move_done_flag = True
508
+ self.det_done_flag = True
509
+
510
+ def order_positions(self, positions: DataToExport):
511
+ """ Reorder the content of the DataToExport given the order of the selected actuators"""
512
+ actuators = self.selected_actuators_name
513
+ pos = DataToExport('actuators')
514
+ for act in actuators:
515
+ pos.append(positions.get_data_from_name(act))
516
+ return pos
517
+
518
+ @Slot(DataActuator)
519
+ def move_done(self, data_act: DataActuator):
520
+ try:
521
+ if data_act.name not in self.move_done_positions.get_names():
522
+ self.move_done_positions.append(data_act)
523
+
524
+ if len(self.move_done_positions) == len(self.actuators):
525
+ self.move_done_flag = True
526
+ self.settings.child('move_done').setValue(self.move_done_flag)
527
+ except Exception as e:
528
+ logger.exception(str(e))
529
+
530
+ def det_done(self, data: DataToExport):
531
+ if self.det_done_datas is not None: # means that somehow data are not initialized so no further processing
532
+ self._received_data += 1
533
+ if len(data) != 0:
534
+ self.det_done_datas.append(data)
535
+
536
+ if self._received_data == len(self.detectors):
537
+ self.det_done_flag = True
538
+ self.settings.child('det_done').setValue(self.det_done_flag)
539
+
540
+
541
+ if __name__ == '__main__':
542
+ import sys
543
+
544
+ app = QtWidgets.QApplication(sys.argv)
545
+ from qtpy.QtCore import QThread
546
+ from pymodaq.utils.gui_utils import DockArea
547
+ from pymodaq.control_modules.daq_viewer import DAQ_Viewer
548
+ from pymodaq.control_modules.daq_move import DAQ_Move
549
+
550
+ win = QtWidgets.QMainWindow()
551
+ area = DockArea()
552
+ win.setCentralWidget(area)
553
+ win.resize(1000, 500)
554
+ win.setWindowTitle('pymodaq main')
555
+
556
+ prog = DAQ_Viewer(area, title="Testing2D", daq_type='DAQ2D')
557
+ prog2 = DAQ_Viewer(area, title="Testing1D", daq_type='DAQ1D')
558
+ prog3 = DAQ_Viewer(area, title="Testing0D", daq_type='DAQ0D')
559
+
560
+ act1_widget = QtWidgets.QWidget()
561
+ act2_widget = QtWidgets.QWidget()
562
+ act1 = DAQ_Move(act1_widget, title='X_axis')
563
+ act2 = DAQ_Move(act2_widget, title='Y_axis')
564
+ act1.actuator = 'Mock'
565
+ act2.actuator = 'Mock'
566
+
567
+ QThread.msleep(1000)
568
+ prog.init_hardware_ui()
569
+ prog2.init_hardware_ui()
570
+ prog3.init_hardware_ui()
571
+
572
+ dock1 = Dock('actuator 1')
573
+ dock1.addWidget(act1_widget)
574
+ area.addDock(dock1)
575
+
576
+ dock2 = Dock('actuator 2')
577
+ dock2.addWidget(act2_widget)
578
+ area.addDock(dock2)
579
+
580
+ act1.init_hardware_ui()
581
+ act2.init_hardware_ui()
582
+
583
+ QtWidgets.QApplication.processEvents()
584
+ win.show()
585
+
586
+ manager = ModulesManager(actuators=[act1, act2], detectors=[prog, prog2, prog3], selected_detectors=[prog2])
587
+ manager.settings_tree.show()
588
+
589
+ sys.exit(app.exec_())