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
File without changes
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+ from typing import Callable, TYPE_CHECKING
3
+
4
+ from pymodaq_utils.logger import set_logger, get_module_name
5
+
6
+ if TYPE_CHECKING:
7
+ from .ui_base import DAQ_Move_UI_Base
8
+
9
+ logger = set_logger(get_module_name(__file__))
10
+
11
+
12
+
13
+ class ActuatorUIFactory:
14
+ _builders: dict[str, type['DAQ_Move_UI_Base']] = {}
15
+
16
+ @classmethod
17
+ def register(cls, identifier: str) -> Callable:
18
+ """ To be used as a decorator
19
+
20
+ Register in the class registry a new scanner class using its 1 identifier
21
+ """
22
+
23
+ def inner_wrapper(wrapped_class: type['DAQ_Move_UI_Base']) -> type['DAQ_Move_UI_Base']:
24
+ key = identifier
25
+
26
+ if key not in cls._builders:
27
+ cls._builders[key] = wrapped_class
28
+ else:
29
+ logger.warning(f'The {key} builder is already registered. Replacing it')
30
+ return wrapped_class
31
+
32
+ return inner_wrapper
33
+
34
+
35
+ @classmethod
36
+ def get(cls, key : str) -> type['DAQ_Move_UI_Base']:
37
+ builder = cls._builders.get(key)
38
+ if not builder:
39
+ raise ValueError(key)
40
+ return builder
41
+
42
+ @classmethod
43
+ def create(cls, key: str, **kwargs) -> 'DAQ_Move_UI_Base':
44
+ return cls._builders[key](**kwargs)
45
+
46
+ @classmethod
47
+ def keys(cls) -> list[str]:
48
+ return list(cls._builders.keys())
@@ -0,0 +1,359 @@
1
+ from abc import abstractmethod
2
+
3
+ from qtpy.QtWidgets import QComboBox
4
+ from pint import DimensionalityError
5
+ from qtpy import QtWidgets
6
+ from typing import Union, List
7
+
8
+ from pymodaq_utils.config import Config
9
+ from pymodaq.control_modules.thread_commands import UiToMainMove
10
+ from pymodaq.control_modules.ui_utils import ControlModuleUI
11
+ from pymodaq.utils.data import DataActuator
12
+ from pymodaq_data import Q_
13
+ from pymodaq_data import DataToExport
14
+ from pymodaq_gui.plotting.data_viewers import ViewerDispatcher
15
+ from pymodaq_gui.utils import DockArea, QSpinBoxWithShortcut, PushButtonIcon, QLED, QSpinBox_ro
16
+ from pymodaq_gui.parameter import ParameterTree
17
+ from pymodaq_gui.utils.widgets import LabelWithFont
18
+ from pymodaq_utils.utils import ThreadCommand
19
+ from pymodaq.utils.config import Config as ControlModulesConfig
20
+
21
+ config_utils = Config()
22
+ config = ControlModulesConfig()
23
+
24
+
25
+ class DAQ_Move_UI_Base(ControlModuleUI):
26
+ """DAQ_Move user interface.
27
+
28
+ This class manages the UI and emit dedicated signals depending on actions from the user
29
+
30
+ Attributes
31
+ ----------
32
+ command_sig: Signal[Threadcommand]
33
+ This signal is emitted whenever some actions done by the user has to be
34
+ applied on the main module. Possible commands are:
35
+ * init
36
+ * quit
37
+ * get_value
38
+ * loop_get_value
39
+ * find_home
40
+ * stop
41
+ * move_abs
42
+ * move_rel
43
+ * show_log
44
+ * actuator_changed
45
+ * rel_value
46
+ * show_config
47
+ * show_plugin_config
48
+
49
+ Methods
50
+ -------
51
+ display_value(value: float)
52
+ Update the display of the actuator's value on the UI
53
+ do_init()
54
+ Programmatic init
55
+
56
+ See Also
57
+ --------
58
+ pymodaq.utils.daq_utils.ThreadCommand
59
+ """
60
+
61
+ is_compact = False
62
+
63
+ def __init__(self, parent: Union[DockArea, QtWidgets.QWidget], title="DAQ_Move"):
64
+ super().__init__(parent)
65
+ self.title = title
66
+ self._unit = ''
67
+
68
+ self.actuators_combo: QComboBox = None
69
+ self.abs_value_sb: QSpinBoxWithShortcut = None
70
+ self.abs_value_sb_2: QSpinBoxWithShortcut = None
71
+ self.abs_value_sb_bis: QSpinBoxWithShortcut = None
72
+ self.ini_actuator_pb: PushButtonIcon = None
73
+ self.ini_state_led: QLED = None
74
+ self.move_done_led: QLED = None
75
+ self.current_value_sb: QSpinBox_ro = None
76
+ self.find_home_pb: PushButtonIcon = None
77
+ self.move_rel_plus_pb: PushButtonIcon = None
78
+ self.move_abs_pb: PushButtonIcon = None
79
+ self.rel_value_sb: QSpinBoxWithShortcut = None
80
+ self.move_rel_minus_pb: PushButtonIcon = None
81
+ self.stop_pb: PushButtonIcon = None
82
+ self.get_value_pb: PushButtonIcon = None
83
+ self.statusbar: QtWidgets.QStatusBar = None
84
+
85
+ self.control_widget: QtWidgets.QWidget = None
86
+ self.graph_widget: QtWidgets.QWidget = None
87
+ self.viewer: ViewerDispatcher = None
88
+
89
+ self._tree: ParameterTree = None
90
+
91
+
92
+ self.setup_ui()
93
+
94
+ self.enable_move_buttons(False)
95
+
96
+ def show_data(self, data: DataToExport):
97
+ self.viewer.show_data(data)
98
+
99
+ def display_value(self, value: DataActuator):
100
+ try:
101
+ self.current_value_sb.setValue(value.value(self._unit))
102
+ except DimensionalityError as e:
103
+ value.force_units(self._unit)
104
+ self.current_value_sb.setValue(value.value())
105
+
106
+ @property
107
+ def actuator_init(self):
108
+ """bool: the status of the init LED."""
109
+ return self.ini_state_led.get_state()
110
+
111
+ @actuator_init.setter
112
+ def actuator_init(self, status):
113
+ self.ini_state_led.set_as(status)
114
+ self.enable_move_buttons(status)
115
+
116
+ @property
117
+ def actuator(self):
118
+ return self.actuators_combo.currentText()
119
+
120
+ @actuator.setter
121
+ def actuator(self, act_name: str):
122
+ self.actuators_combo.setCurrentText(act_name)
123
+
124
+ @property
125
+ def actuators(self):
126
+ return [self.actuators_combo.itemText(ind) for ind in range(self.actuators_combo.count())]
127
+
128
+ @actuators.setter
129
+ def actuators(self, actuators: List[str]):
130
+ self.actuators_combo.clear()
131
+ self.actuators_combo.addItems(actuators)
132
+
133
+ @property
134
+ def move_done(self):
135
+ """bool: the status of the move_done LED."""
136
+ return self.move_done_led.get_state()
137
+
138
+ @move_done.setter
139
+ def move_done(self, status):
140
+ self.move_done_led.set_as(status)
141
+
142
+ def enable_move_buttons(self, status):
143
+ self.abs_value_sb.setEnabled(status)
144
+ self.abs_value_sb_2.setEnabled(status)
145
+ for action_name in ('move_abs', 'move_abs_2', 'move_rel'):
146
+ if action_name in self.actions_names:
147
+ self.get_action(action_name).setEnabled(status)
148
+
149
+ self.control_widget.setEnabled(status)
150
+
151
+ def set_abs_spinbox_properties(self, **properties):
152
+ """ Change the Spinbox properties
153
+
154
+ Parameters
155
+ --------
156
+ properties: dict or named parameters
157
+ possible keys are :
158
+
159
+ * decimals: to set the number of displayed decimals
160
+ * 'minimum': to set the minimum value
161
+ * 'maximum': to set the maximum value
162
+ * 'step': to set the step value
163
+
164
+ """
165
+ if 'decimals' in properties:
166
+ self.abs_value_sb.setDecimals(properties['decimals'])
167
+ self.abs_value_sb_2.setDecimals(properties['decimals'])
168
+ self.abs_value_sb_bis.setDecimals(properties['decimals'])
169
+ if 'minimum' in properties:
170
+ self.abs_value_sb.setMinimum(properties['minimum'])
171
+ self.abs_value_sb_2.setMinimum(properties['minimum'])
172
+ self.abs_value_sb_bis.setMinimum(properties['minimum'])
173
+ if 'maximum' in properties:
174
+ self.abs_value_sb.setMaximum(properties['maximum'])
175
+ self.abs_value_sb_2.setMaximum(properties['maximum'])
176
+ self.abs_value_sb_bis.setMaximum(properties['maximum'])
177
+ if 'step' in properties:
178
+ self.abs_value_sb.setSingleStep(properties['step'])
179
+ self.abs_value_sb_2.setSingleStep(properties['step'])
180
+ self.abs_value_sb_bis.setSingleStep(properties['step'])
181
+
182
+ def set_abs_value_red(self, value: Q_):
183
+ self.abs_value_sb_2.setValue(value.m_as(self._unit))
184
+
185
+ def set_abs_value_green(self, value: Q_):
186
+ self.abs_value_sb.setValue(value.m_as(self._unit))
187
+
188
+ def set_abs_value(self, value: Q_):
189
+ self.abs_value_sb_bis.setValue(value.m_as(self._unit))
190
+
191
+ def set_rel_value(self, value: Q_):
192
+ self.rel_value_sb.setValue(value.m_as(self._unit))
193
+
194
+ def set_unit_as_suffix(self, unit: str):
195
+ """Will append the actuator units in the value display"""
196
+ self._unit = unit
197
+ self.current_value_sb.setOpts(suffix=unit)
198
+ self.abs_value_sb_bis.setOpts(suffix=unit)
199
+ self.abs_value_sb.setOpts(suffix=unit)
200
+ self.abs_value_sb_2.setOpts(suffix=unit)
201
+ self.rel_value_sb.setOpts(suffix=unit)
202
+
203
+ def set_unit_prefix(self, show=True):
204
+ """ Change the display status of the spinbox SI prefix"""
205
+ self.current_value_sb.setOpts(siPrefix=show)
206
+ self.abs_value_sb_bis.setOpts(siPrefix=show)
207
+ self.abs_value_sb.setOpts(siPrefix=show)
208
+ self.abs_value_sb_2.setOpts(siPrefix=show)
209
+ self.rel_value_sb.setOpts(siPrefix=show)
210
+
211
+ def setup_docks(self):
212
+
213
+ self.control_widget = QtWidgets.QWidget()
214
+
215
+ self.actuators_combo = QComboBox()
216
+ self.abs_value_sb = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
217
+ self.abs_value_sb.setStyleSheet("background-color : lightgreen; color: black")
218
+
219
+ self.abs_value_sb_2 = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
220
+ self.abs_value_sb_2.setStyleSheet("background-color : lightcoral; color: black")
221
+
222
+ self.abs_value_sb_bis = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
223
+ self.ini_actuator_pb = PushButtonIcon('ini', 'Initialization', checkable=True,
224
+ tip='Start This actuator initialization')
225
+ self.ini_state_led = QLED(readonly=True)
226
+ self.move_done_led = QLED(readonly=True)
227
+ self.current_value_sb = QSpinBox_ro(font_size=20, min_height=27,
228
+ siPrefix=config('actuator', 'siprefix'),
229
+ )
230
+ self.find_home_pb = PushButtonIcon('home2', 'Find Home')
231
+ self.move_rel_plus_pb = PushButtonIcon('MoveUp', 'Set Rel. (+)')
232
+ self.move_abs_pb = PushButtonIcon('Move', 'Set Abs.',
233
+ tip='Set the value of the actuator to the set absolute value')
234
+ self.rel_value_sb = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'),
235
+ key_sequences=("Ctrl+E","Ctrl+Shift+E"),)
236
+ self.move_rel_minus_pb = PushButtonIcon('MoveDown', 'Set Rel. (-)')
237
+ self.stop_pb = PushButtonIcon('stop', 'Stop')
238
+ self.get_value_pb = PushButtonIcon('Help_32', 'Update Value')
239
+ self.statusbar = QtWidgets.QStatusBar()
240
+ self.statusbar.setMaximumHeight(30)
241
+
242
+ self.graph_widget = QtWidgets.QWidget()
243
+ self.graph_widget.setLayout(QtWidgets.QHBoxLayout())
244
+ self.graph_widget.layout().setContentsMargins(0, 0, 0, 0)
245
+ dockarea = DockArea()
246
+ self.graph_widget.layout().addWidget(dockarea)
247
+ self.viewer = ViewerDispatcher(dockarea)
248
+
249
+ def populate_control_ui(self, widget: QtWidgets.QWidget):
250
+ widget.setLayout(QtWidgets.QGridLayout())
251
+ widget.layout().addWidget(LabelWithFont('Abs. Value'), 0, 0)
252
+
253
+ widget.layout().addWidget(self.find_home_pb, 0, 1)
254
+
255
+ widget.layout().addWidget(self.abs_value_sb_bis, 1, 0)
256
+ widget.layout().addWidget(self.move_abs_pb, 1, 1)
257
+ widget.layout().addWidget(LabelWithFont('Rel. Increment'), 2, 0)
258
+ widget.layout().addWidget(self.move_rel_plus_pb, 2, 1)
259
+
260
+ widget.layout().addWidget(self.rel_value_sb, 3, 0)
261
+
262
+ widget.layout().addWidget(self.move_rel_minus_pb, 3, 1)
263
+ widget.layout().addWidget(self.stop_pb, 4, 0)
264
+
265
+ widget.layout().addWidget(self.get_value_pb, 4, 1)
266
+ widget.layout().setContentsMargins(0, 0, 0, 0)
267
+ widget.setVisible(False)
268
+
269
+ def close(self):
270
+ self.parent.close()
271
+ self.graph_widget.close()
272
+
273
+ def do_init(self, do_init=True):
274
+ """Programmatically press the Init button
275
+ API entry
276
+ Parameters
277
+ ----------
278
+ do_init: bool
279
+ will fire the Init button depending on the argument value and the button check state
280
+ """
281
+ if do_init is not self.ini_actuator_pb.isChecked():
282
+ self.ini_actuator_pb.click()
283
+
284
+ def send_init(self, checked):
285
+ self.actuators_combo.setEnabled(not checked)
286
+ self.command_sig.emit(ThreadCommand(UiToMainMove.INIT, [self.ini_actuator_pb.isChecked(),
287
+ self.actuators_combo.currentText()]))
288
+
289
+ def emit_move_abs(self, spinbox):
290
+ spinbox.editingFinished.emit()
291
+ self.command_sig.emit(ThreadCommand(UiToMainMove.MOVE_ABS, DataActuator(data=spinbox.value(),
292
+ units=self._unit)))
293
+
294
+ def emit_move_rel(self, sign):
295
+ self.command_sig.emit(ThreadCommand(
296
+ UiToMainMove.MOVE_REL,
297
+ DataActuator(data=self.rel_value_sb.value() * (1 if sign == '+' else -1),
298
+ units=self._unit)))
299
+
300
+ def set_settings_tree(self, tree):
301
+ self._tree = tree
302
+
303
+ def connect_things(self):
304
+ if 'show_controls' in self.actions_names:
305
+ self.connect_action('show_controls', self.show_controls)
306
+ if 'show_settings' in self.actions_names:
307
+ self.connect_action('show_settings', self.show_tree)
308
+ if 'show_graph' in self.actions_names:
309
+ self.connect_action('show_graph', self.show_graph)
310
+ if 'move_abs' in self.actions_names:
311
+ self.connect_action('move_abs', lambda: self.emit_move_abs(self.abs_value_sb))
312
+ if 'move_abs_2' in self.actions_names:
313
+ self.connect_action('move_abs_2', lambda: self.emit_move_abs(self.abs_value_sb_2))
314
+ if 'log' in self.actions_names:
315
+ self.connect_action('log', lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.SHOW_LOG, )))
316
+ if 'stop' in self.actions_names:
317
+ self.connect_action('stop', lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.STOP, )))
318
+ if 'show_config' in self.actions_names:
319
+ self.connect_action('show_config', lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.SHOW_CONFIG, )))
320
+ if 'ini_actuator' in self.actions_names:
321
+ self.connect_action('ini_actuator', self.ini_actuator_pb.click)
322
+
323
+ self.move_abs_pb.clicked.connect(lambda: self.emit_move_abs(self.abs_value_sb_bis))
324
+ self.abs_value_sb.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb))
325
+ self.abs_value_sb_2.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb_2))
326
+ self.abs_value_sb_bis.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb_bis))
327
+ self.rel_value_sb.valueChanged.connect(lambda: self.command_sig.emit(
328
+ ThreadCommand(UiToMainMove.REL_VALUE, self.rel_value_sb.value())))
329
+ self.move_rel_plus_pb.clicked.connect(lambda: self.emit_move_rel('+'))
330
+ self.move_rel_minus_pb.clicked.connect(lambda: self.emit_move_rel('-'))
331
+ self.rel_value_sb.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_rel('+'))
332
+ self.rel_value_sb.shortcut["Ctrl+Shift+E"].activated.connect(lambda: self.emit_move_rel('-'))
333
+
334
+ self.find_home_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.FIND_HOME, )))
335
+ self.stop_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.STOP, )))
336
+ self.get_value_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.GET_VALUE, )))
337
+
338
+ self.ini_actuator_pb.clicked.connect(self.send_init)
339
+
340
+ self.actuators_combo.currentTextChanged.connect(
341
+ lambda act: self.command_sig.emit(ThreadCommand(UiToMainMove.ACTUATOR_CHANGED, act)))
342
+ if 'quit' in self.actions_names:
343
+ self.connect_action('quit', lambda: self.command_sig.emit(ThreadCommand(UiToMainMove.QUIT, )))
344
+ if 'refresh_value' in self.actions_names:
345
+ self.connect_action('refresh_value',
346
+ lambda do_refresh: self.command_sig.emit(ThreadCommand(UiToMainMove.LOOP_GET_VALUE,
347
+ do_refresh)))
348
+
349
+ def show_tree(self, show: bool = True):
350
+ self._tree.setVisible(show)
351
+ self._tree.closeEvent = lambda event: self.set_action_checked('show_settings', False)
352
+
353
+ def show_controls(self, show: bool = True):
354
+ self.control_widget.setVisible(show)
355
+ self.control_widget.closeEvent = lambda event: self.set_action_checked('show_controls', False)
356
+
357
+ def show_graph(self, show: bool = True):
358
+ self.graph_widget.setVisible(show)
359
+ self.graph_widget.closeEvent = lambda event: self.set_action_checked('show_graph', False)
File without changes
@@ -0,0 +1,139 @@
1
+ import sys
2
+ from typing import Union
3
+
4
+ from qtpy.QtWidgets import QVBoxLayout, QToolBar
5
+ from qtpy import QtWidgets
6
+
7
+ from pymodaq.control_modules.daq_move_ui.ui_base import DAQ_Move_UI_Base
8
+ from pymodaq.control_modules.thread_commands import UiToMainMove
9
+ from pymodaq_gui.utils.widgets import LabelWithFont
10
+
11
+ from pymodaq.utils.data import DataActuator
12
+
13
+ from pymodaq_utils.utils import ThreadCommand
14
+ from pymodaq_utils.config import Config
15
+
16
+ from pymodaq.control_modules.daq_move_ui.factory import ActuatorUIFactory
17
+ from pymodaq.control_modules.daq_move_ui.uis.simple import DAQ_Move_UI_Simple
18
+ from pymodaq.utils.config import Config as ControlModulesConfig
19
+ from enum import Enum
20
+
21
+ config = ControlModulesConfig()
22
+
23
+
24
+ class BinaryValue(Enum):
25
+ VALUE_ONE = config('actuator', 'binary', 'value_1')
26
+ VALUE_TWO = config('actuator', 'binary', 'value_2')
27
+
28
+
29
+ @ActuatorUIFactory.register('Binary')
30
+ class DAQ_Move_UI_Binary(DAQ_Move_UI_Simple):
31
+ """ UI for Actuators where only two values are encoded: 0 or 1 for instance
32
+
33
+ Some other numerical values can be set in the config: 'actuator', 'binary', 'value_1'
34
+ The green arrow button will fire the 'value_1'
35
+ The red arrow button will fire the 'value_2'
36
+
37
+ Could be used for 2 positions only actuators such as a Flip
38
+ """
39
+
40
+
41
+ is_compact = True
42
+
43
+ def setup_actions(self):
44
+ self.add_widget('name', LabelWithFont(f'{self.title}: ', font_name="Tahoma",
45
+ font_size=14, isbold=True, isitalic=True),
46
+ toolbar=self.move_toolbar)
47
+
48
+ self.add_widget('actuators_combo', self.actuators_combo, toolbar=self.move_toolbar)
49
+ self.add_action('ini_actuator', 'Ini. Actuator', 'ini', toolbar=self.move_toolbar)
50
+ self.add_widget('ini_led', self.ini_state_led, toolbar=self.move_toolbar)
51
+ self.add_widget('current', self.current_value_sb, toolbar=self.move_toolbar)
52
+ self.add_widget('move_done', self.move_done_led, toolbar=self.move_toolbar)
53
+ self.add_action('move_abs', 'Move Abs', 'go_to_1', "Move to the set absolute value",
54
+ toolbar=self.move_toolbar)
55
+ self.add_action('move_abs_2', 'Move Abs', 'go_to_2', "Move to the other set absolute"
56
+ " value",
57
+ toolbar=self.move_toolbar)
58
+
59
+
60
+ self.add_action('stop', 'Stop', 'stop', "Stop Motion", toolbar=self.move_toolbar)
61
+
62
+ self.add_action('show_settings', 'Show Settings', 'tree', "Show Settings", checkable=True,
63
+ toolbar=self.move_toolbar)
64
+ self.add_action('show_controls', 'Show Controls', 'Add_Step', "Show more controls", checkable=True,
65
+ toolbar=self.move_toolbar)
66
+ self.add_action('show_graph', 'Show Graph', 'graph', "Show Graph", checkable=True,
67
+ toolbar=self.move_toolbar)
68
+ self.add_action('refresh_value', 'Refresh', 'Refresh2', "Refresh Value", checkable=True,
69
+ toolbar=self.move_toolbar)
70
+ self.move_toolbar.addSeparator()
71
+ self.add_action('show_config', 'Show Config', 'Settings', "Show PyMoDAQ Config", checkable=False,
72
+ toolbar=self.move_toolbar)
73
+ self.add_action('quit', 'Quit the module', 'close2', toolbar=self.move_toolbar)
74
+ self.add_action('log', 'Show Log file', 'information2', toolbar=self.move_toolbar)
75
+ self.add_widget('status', self.statusbar, toolbar=self.move_toolbar)
76
+
77
+ def connect_things(self):
78
+ super().connect_things()
79
+ # first disconnect actions from the base class
80
+ self.connect_action('move_abs', None, connect=False)
81
+ self.connect_action('move_abs_2', None, connect=False)
82
+
83
+ #then connect to the ones reimplemented here
84
+ self.connect_action('move_abs', lambda: self.emit_move_abs(BinaryValue.VALUE_ONE.value))
85
+ self.connect_action('move_abs_2', lambda: self.emit_move_abs(BinaryValue.VALUE_TWO.value))
86
+
87
+ def emit_move_abs(self, abs_value: Union[float, int]):
88
+ self.command_sig.emit(ThreadCommand(UiToMainMove.MOVE_ABS, DataActuator(data=abs_value,
89
+ units=self._unit)))
90
+
91
+ def main(init_qt=True):
92
+ from pymodaq_gui.utils.dock import DockArea, Dock
93
+ if init_qt: # used for the test suite
94
+ app = QtWidgets.QApplication(sys.argv)
95
+
96
+ actuators = [f'act{ind}' for ind in range(5)]
97
+
98
+ win = QtWidgets.QMainWindow()
99
+ area = DockArea()
100
+ win.setCentralWidget(area)
101
+ win.resize(1000, 500)
102
+ win.setWindowTitle('extension_name')
103
+
104
+
105
+ dock = Dock('Test')
106
+ dock.layout.setSpacing(0)
107
+ dock.layout.setContentsMargins(0,0,0,0)
108
+ area.addDock(dock)
109
+ widget = QtWidgets.QWidget()
110
+ widget.setMaximumHeight(60)
111
+ prog = DAQ_Move_UI_Simple(widget, title="test")
112
+ widget.show()
113
+
114
+ for ind in range(10):
115
+ widget = QtWidgets.QWidget()
116
+ widget.setMaximumHeight(60)
117
+ dock.addWidget(widget)
118
+ prog = DAQ_Move_UI_Binary(widget, title="test")
119
+
120
+
121
+ def print_command_sig(cmd_sig):
122
+ print(cmd_sig)
123
+ if cmd_sig.command == UiToMainMove.INIT:
124
+ prog.enable_move_buttons(True)
125
+ elif cmd_sig.command == UiToMainMove.MOVE_ABS:
126
+ prog.display_value(cmd_sig.attribute)
127
+
128
+ prog.command_sig.connect(print_command_sig)
129
+ prog.actuators = actuators
130
+
131
+ win.show()
132
+ if init_qt:
133
+ sys.exit(app.exec_())
134
+ return prog, widget
135
+
136
+
137
+ if __name__ == '__main__':
138
+ main()
139
+
@@ -0,0 +1,120 @@
1
+ from qtpy.QtCore import Qt
2
+ from qtpy.QtWidgets import QVBoxLayout, QWidget, QHBoxLayout, QToolBar, QGridLayout
3
+ from qtpy import QtWidgets
4
+
5
+ from pymodaq.control_modules.daq_move_ui.ui_base import DAQ_Move_UI_Base
6
+ from pymodaq.control_modules.thread_commands import UiToMainMove
7
+ from pymodaq_data import DataToExport
8
+ from pymodaq_gui.plotting.data_viewers import ViewerDispatcher
9
+ from pymodaq_gui.utils import DockArea
10
+ from pymodaq_gui.utils.widgets import LabelWithFont
11
+ from pymodaq_utils.utils import ThreadCommand
12
+
13
+
14
+ from ..factory import ActuatorUIFactory
15
+
16
+
17
+ @ActuatorUIFactory.register('Original')
18
+ class DAQ_Move_UI(DAQ_Move_UI_Base):
19
+ is_compact = False
20
+
21
+ def __init__(self, parent, title="DAQ_Move"):
22
+ super().__init__(parent, title)
23
+
24
+ def setup_docks(self):
25
+ super().setup_docks()
26
+
27
+ self.parent.setLayout(QVBoxLayout())
28
+ #self.parent.layout().setSizeConstraint(QHBoxLayout.SetFixedSize)
29
+ self.parent.layout().setContentsMargins(2, 2, 2, 2)
30
+
31
+ widget = QWidget()
32
+ widget.setLayout(QHBoxLayout())
33
+ splitter_hor = QtWidgets.QSplitter(Qt.Orientation.Horizontal)
34
+ widget.layout().addWidget(splitter_hor)
35
+ self.parent.layout().addWidget(widget)
36
+
37
+ self.main_ui = QWidget()
38
+
39
+ self.control_widget = QWidget()
40
+ self.populate_control_ui(self.control_widget)
41
+
42
+ self.settings_ui = QWidget()
43
+
44
+
45
+ left_widget = QWidget()
46
+ left_widget.setLayout(QVBoxLayout())
47
+ left_widget.layout().addWidget(self.main_ui)
48
+ left_widget.layout().addWidget(self.control_widget)
49
+ left_widget.layout().setContentsMargins(0, 0, 0, 0)
50
+ left_widget.layout().addStretch()
51
+ splitter_hor.addWidget(left_widget)
52
+ splitter_hor.addWidget(self.settings_ui)
53
+ #widget.layout().addStretch()
54
+
55
+ # populate the main ui
56
+ self.move_toolbar = QToolBar()
57
+ self.main_ui.setLayout(QGridLayout())
58
+ self.main_ui.layout().setSpacing(0)
59
+ self.main_ui.layout().setContentsMargins(0, 0, 0, 0)
60
+
61
+ self.main_ui.layout().addWidget(self.toolbar, 0, 0, 1, 2)
62
+ self.main_ui.layout().addWidget(self.move_toolbar, 1, 0, 1, 2)
63
+
64
+
65
+ self.move_toolbar.addWidget(self.abs_value_sb)
66
+ self.move_toolbar.addWidget(self.abs_value_sb_2)
67
+
68
+ self.main_ui.layout().addWidget(LabelWithFont('Actuator:'), 2, 0)
69
+
70
+ self.main_ui.layout().addWidget(self.actuators_combo, 2, 1)
71
+
72
+ self.main_ui.layout().addWidget(self.ini_actuator_pb, 3, 0)
73
+ self.main_ui.layout().addWidget(self.ini_state_led, 3, 1)
74
+ self.main_ui.layout().addWidget(LabelWithFont('Current value:'), 4, 0)
75
+ self.main_ui.layout().addWidget(self.move_done_led, 4, 1)
76
+
77
+ self.main_ui.layout().addWidget(self.current_value_sb, 5, 0, 1, 2)
78
+
79
+ self.settings_ui.setLayout(QHBoxLayout())
80
+ self.settings_ui.layout().setContentsMargins(0, 0, 0, 0)
81
+ self.settings_ui.setVisible(False)
82
+
83
+ self.statusbar = QtWidgets.QStatusBar()
84
+ self.statusbar.setMaximumHeight(30)
85
+ self.parent.layout().addWidget(self.statusbar)
86
+
87
+ def setup_actions(self):
88
+ self.add_widget('name', LabelWithFont(f'{self.title}', font_name="Tahoma",
89
+ font_size=14, isbold=True, isitalic=True),
90
+ toolbar=self.toolbar)
91
+ self.add_action('move_abs', 'Move Abs', 'go_to_1', "Move to the set absolute value",
92
+ toolbar=self.move_toolbar)
93
+ self.add_action('move_abs_2', 'Move Abs', 'go_to_2', "Move to the other set absolute value",
94
+ toolbar=self.move_toolbar)
95
+
96
+ self.add_action('show_controls', 'Show Controls', 'Add_Step', "Show more controls", checkable=True,
97
+ toolbar=self.toolbar)
98
+ self.add_action('show_settings', 'Show Settings', 'tree', "Show Settings", checkable=True,
99
+ toolbar=self.toolbar)
100
+ self.add_action('show_config', 'Show Config', 'Settings', "Show PyMoDAQ Config", checkable=False,
101
+ toolbar=self.toolbar)
102
+ self.add_action('show_graph', 'Show Graph', 'graph', "Show Graph", checkable=True,
103
+ toolbar=self.toolbar)
104
+ self.add_action('refresh_value', 'Refresh', 'Refresh2', "Refresh Value", checkable=True,
105
+ toolbar=self.toolbar)
106
+ self.add_action('stop', 'Stop', 'stop', "Stop Motion", checkable=False,
107
+ toolbar=self.toolbar)
108
+ self.add_action('quit', 'Quit the module', 'close2')
109
+ self.add_action('log', 'Show Log file', 'information2')
110
+
111
+ def connect_things(self):
112
+ super().connect_things()
113
+
114
+ def set_settings_tree(self, tree):
115
+ super().set_settings_tree(tree)
116
+ self.settings_ui.layout().addWidget(tree)
117
+
118
+ def show_tree(self, show: bool = True):
119
+ super().show_tree(show)
120
+ self.settings_ui.setVisible(show)