pymodaq 5.0.17__py3-none-any.whl → 5.1.0__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.

Potentially problematic release.


This version of pymodaq might be problematic. Click here for more details.

Files changed (92) hide show
  1. pymodaq/__init__.py +23 -11
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +458 -246
  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.py → daq_move_ui/ui_base.py} +168 -210
  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 +113 -101
  13. pymodaq/control_modules/daq_viewer_ui.py +41 -31
  14. pymodaq/control_modules/mocks.py +2 -2
  15. pymodaq/control_modules/move_utility_classes.py +113 -41
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +107 -63
  19. pymodaq/control_modules/viewer_utility_classes.py +13 -17
  20. pymodaq/dashboard.py +1294 -625
  21. pymodaq/examples/qt_less_standalone_module.py +48 -11
  22. pymodaq/extensions/__init__.py +8 -3
  23. pymodaq/extensions/adaptive/__init__.py +2 -0
  24. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  25. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  26. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  27. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  28. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  29. pymodaq/extensions/adaptive/utils.py +123 -0
  30. pymodaq/extensions/bayesian/__init__.py +1 -1
  31. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  32. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  33. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  34. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  35. pymodaq/extensions/bayesian/utils.py +71 -297
  36. pymodaq/extensions/daq_logger/daq_logger.py +7 -12
  37. pymodaq/extensions/daq_logger/h5logging.py +1 -1
  38. pymodaq/extensions/daq_scan.py +30 -55
  39. pymodaq/extensions/data_mixer/__init__.py +0 -0
  40. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  41. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  42. pymodaq/extensions/data_mixer/model.py +108 -0
  43. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  44. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  45. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  46. pymodaq/extensions/data_mixer/parser.py +53 -0
  47. pymodaq/extensions/data_mixer/utils.py +23 -0
  48. pymodaq/extensions/h5browser.py +3 -34
  49. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  50. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  51. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  52. pymodaq/extensions/optimizers_base/utils.py +427 -0
  53. pymodaq/extensions/pid/actuator_controller.py +3 -2
  54. pymodaq/extensions/pid/daq_move_PID.py +107 -30
  55. pymodaq/extensions/pid/pid_controller.py +613 -287
  56. pymodaq/extensions/pid/utils.py +8 -5
  57. pymodaq/extensions/utils.py +17 -2
  58. pymodaq/resources/config_template.toml +57 -0
  59. pymodaq/resources/preset_default.xml +1 -1
  60. pymodaq/utils/config.py +13 -4
  61. pymodaq/utils/daq_utils.py +14 -0
  62. pymodaq/utils/data.py +1 -0
  63. pymodaq/utils/gui_utils/loader_utils.py +25 -15
  64. pymodaq/utils/h5modules/module_saving.py +134 -22
  65. pymodaq/utils/leco/daq_move_LECODirector.py +123 -84
  66. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +84 -97
  67. pymodaq/utils/leco/director_utils.py +32 -16
  68. pymodaq/utils/leco/leco_director.py +104 -27
  69. pymodaq/utils/leco/pymodaq_listener.py +186 -97
  70. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  71. pymodaq/utils/leco/utils.py +25 -25
  72. pymodaq/utils/managers/batchscan_manager.py +12 -11
  73. pymodaq/utils/managers/modules_manager.py +74 -33
  74. pymodaq/utils/managers/overshoot_manager.py +11 -10
  75. pymodaq/utils/managers/preset_manager.py +100 -64
  76. pymodaq/utils/managers/preset_manager_utils.py +163 -107
  77. pymodaq/utils/managers/remote_manager.py +21 -16
  78. pymodaq/utils/scanner/scan_factory.py +18 -4
  79. pymodaq/utils/scanner/scan_selector.py +1 -3
  80. pymodaq/utils/scanner/scanner.py +35 -6
  81. pymodaq/utils/scanner/scanners/_1d_scanners.py +15 -46
  82. pymodaq/utils/scanner/scanners/_2d_scanners.py +21 -68
  83. pymodaq/utils/scanner/scanners/sequential.py +50 -31
  84. pymodaq/utils/scanner/scanners/tabular.py +45 -28
  85. {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/METADATA +7 -6
  86. pymodaq-5.1.0.dist-info/RECORD +154 -0
  87. {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/entry_points.txt +0 -2
  88. pymodaq/extensions/bayesian/bayesian_optimisation.py +0 -685
  89. pymodaq/utils/leco/desktop.ini +0 -2
  90. pymodaq-5.0.17.dist-info/RECORD +0 -121
  91. {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/WHEEL +0 -0
  92. {pymodaq-5.0.17.dist-info → pymodaq-5.1.0.dist-info}/licenses/LICENSE +0 -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())
@@ -1,35 +1,28 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 28/07/2022
4
-
5
- @author: Sebastien Weber
6
- """
7
-
8
- from typing import List
9
- import sys
10
- from pint.errors import DimensionalityError
1
+ from abc import abstractmethod
11
2
 
3
+ from qtpy.QtWidgets import QComboBox
4
+ from pint import DimensionalityError
12
5
  from qtpy import QtWidgets
13
- from qtpy.QtCore import Signal, Qt
14
- from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QGridLayout, QWidget, QToolBar, QComboBox
6
+ from typing import Union, List
15
7
 
16
- from pymodaq_utils.utils import ThreadCommand
17
8
  from pymodaq_utils.config import Config
18
-
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
19
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
20
 
21
- from pymodaq_gui.utils.widgets import PushButtonIcon, LabelWithFont, SpinBox, QSpinBox_ro, QLED, QSpinBoxWithShortcut
22
- from pymodaq_gui.utils import DockArea
23
- from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher
24
-
25
- from pymodaq.control_modules.utils import ControlModuleUI
26
- from pymodaq.utils.data import DataToExport, DataActuator
27
-
28
-
29
- config = Config()
21
+ config_utils = Config()
22
+ config = ControlModulesConfig()
30
23
 
31
24
 
32
- class DAQ_Move_UI(ControlModuleUI):
25
+ class DAQ_Move_UI_Base(ControlModuleUI):
33
26
  """DAQ_Move user interface.
34
27
 
35
28
  This class manages the UI and emit dedicated signals depending on actions from the user
@@ -65,15 +58,44 @@ class DAQ_Move_UI(ControlModuleUI):
65
58
  pymodaq.utils.daq_utils.ThreadCommand
66
59
  """
67
60
 
68
- def __init__(self, parent, title="DAQ_Move"):
61
+ is_compact = False
69
62
 
63
+ def __init__(self, parent: Union[DockArea, QtWidgets.QWidget], title="DAQ_Move"):
70
64
  super().__init__(parent)
71
65
  self.title = title
72
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
+
73
92
  self.setup_ui()
74
93
 
75
94
  self.enable_move_buttons(False)
76
95
 
96
+ def show_data(self, data: DataToExport):
97
+ self.viewer.show_data(data)
98
+
77
99
  def display_value(self, value: DataActuator):
78
100
  try:
79
101
  self.current_value_sb.setValue(value.value(self._unit))
@@ -117,16 +139,14 @@ class DAQ_Move_UI(ControlModuleUI):
117
139
  def move_done(self, status):
118
140
  self.move_done_led.set_as(status)
119
141
 
120
- def set_settings_tree(self, tree):
121
- self.settings_ui.layout().addWidget(tree)
122
-
123
142
  def enable_move_buttons(self, status):
124
143
  self.abs_value_sb.setEnabled(status)
125
144
  self.abs_value_sb_2.setEnabled(status)
126
- self.control_ui.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)
127
148
 
128
- self.get_action('move_abs').setEnabled(status)
129
- self.get_action('move_abs_2').setEnabled(status)
149
+ self.control_widget.setEnabled(status)
130
150
 
131
151
  def set_abs_spinbox_properties(self, **properties):
132
152
  """ Change the Spinbox properties
@@ -159,185 +179,96 @@ class DAQ_Move_UI(ControlModuleUI):
159
179
  self.abs_value_sb_2.setSingleStep(properties['step'])
160
180
  self.abs_value_sb_bis.setSingleStep(properties['step'])
161
181
 
162
- def show_data(self, data: DataToExport):
163
- self.viewer.show_data(data)
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)
164
210
 
165
211
  def setup_docks(self):
166
- self.parent.setLayout(QVBoxLayout())
167
- #self.parent.layout().setSizeConstraint(QHBoxLayout.SetFixedSize)
168
- self.parent.layout().setContentsMargins(2, 2, 2, 2)
169
-
170
- widget = QWidget()
171
- widget.setLayout(QHBoxLayout())
172
- splitter_hor = QtWidgets.QSplitter(Qt.Orientation.Horizontal)
173
- widget.layout().addWidget(splitter_hor)
174
- self.parent.layout().addWidget(widget)
175
-
176
- self.main_ui = QWidget()
177
- self.control_ui = QWidget()
178
- self.settings_ui = QWidget()
179
- self.graph_ui = QWidget()
180
- self.graph_ui.setLayout(QtWidgets.QHBoxLayout())
181
- self.graph_ui.layout().setContentsMargins(0, 0, 0, 0)
182
- dockarea = DockArea()
183
- self.graph_ui.layout().addWidget(dockarea)
184
- self.viewer = ViewerDispatcher(dockarea)
185
212
 
186
- left_widget = QWidget()
187
- left_widget.setLayout(QVBoxLayout())
188
- left_widget.layout().addWidget(self.main_ui)
189
- left_widget.layout().addWidget(self.control_ui)
190
- left_widget.layout().setContentsMargins(0, 0, 0, 0)
191
- left_widget.layout().addStretch()
192
- splitter_hor.addWidget(left_widget)
193
- splitter_hor.addWidget(self.settings_ui)
194
- #widget.layout().addStretch()
195
-
196
- # populate the main ui
197
- self.move_toolbar = QToolBar()
198
- self.main_ui.setLayout(QGridLayout())
199
- self.main_ui.layout().setSpacing(0)
200
- self.main_ui.layout().setContentsMargins(0, 0, 0, 0)
201
-
202
- self.main_ui.layout().addWidget(self.toolbar, 0, 0, 1, 2)
203
- self.main_ui.layout().addWidget(self.move_toolbar, 1, 0, 1, 2)
213
+ self.control_widget = QtWidgets.QWidget()
204
214
 
215
+ self.actuators_combo = QComboBox()
205
216
  self.abs_value_sb = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
206
217
  self.abs_value_sb.setStyleSheet("background-color : lightgreen; color: black")
218
+
207
219
  self.abs_value_sb_2 = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
208
220
  self.abs_value_sb_2.setStyleSheet("background-color : lightcoral; color: black")
209
- self.move_toolbar.addWidget(self.abs_value_sb)
210
- self.move_toolbar.addWidget(self.abs_value_sb_2)
211
221
 
212
- self.main_ui.layout().addWidget(LabelWithFont('Actuator:'), 2, 0)
213
- self.actuators_combo = QComboBox()
214
- self.main_ui.layout().addWidget(self.actuators_combo, 2, 1)
222
+ self.abs_value_sb_bis = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
215
223
  self.ini_actuator_pb = PushButtonIcon('ini', 'Initialization', checkable=True,
216
- tip='Start This actuator initialization')
217
- self.main_ui.layout().addWidget(self.ini_actuator_pb, 3, 0)
224
+ tip='Start This actuator initialization')
218
225
  self.ini_state_led = QLED(readonly=True)
219
- self.main_ui.layout().addWidget(self.ini_state_led, 3, 1)
220
- self.main_ui.layout().addWidget(LabelWithFont('Current value:'), 4, 0)
221
226
  self.move_done_led = QLED(readonly=True)
222
- self.main_ui.layout().addWidget(self.move_done_led, 4, 1)
223
227
  self.current_value_sb = QSpinBox_ro(font_size=20, min_height=27,
224
228
  siPrefix=config('actuator', 'siprefix'),
225
229
  )
226
- self.main_ui.layout().addWidget(self.current_value_sb, 5, 0, 1, 2)
227
-
228
- # populate the control ui
229
- self.control_ui.setLayout(QGridLayout())
230
- self.control_ui.layout().addWidget(LabelWithFont('Abs. Value'), 0, 0)
231
230
  self.find_home_pb = PushButtonIcon('home2', 'Find Home')
232
- self.control_ui.layout().addWidget(self.find_home_pb, 0, 1)
233
- self.abs_value_sb_bis = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'))
234
- self.control_ui.layout().addWidget(self.abs_value_sb_bis, 1, 0)
231
+ self.move_rel_plus_pb = PushButtonIcon('MoveUp', 'Set Rel. (+)')
235
232
  self.move_abs_pb = PushButtonIcon('Move', 'Set Abs.',
236
233
  tip='Set the value of the actuator to the set absolute value')
237
- self.control_ui.layout().addWidget(self.move_abs_pb, 1, 1)
238
- self.control_ui.layout().addWidget(LabelWithFont('Rel. Increment'), 2, 0)
239
- self.move_rel_plus_pb = PushButtonIcon('MoveUp', 'Set Rel. (+)')
240
- self.control_ui.layout().addWidget(self.move_rel_plus_pb, 2, 1)
241
-
242
234
  self.rel_value_sb = QSpinBoxWithShortcut(step=0.1, dec=True, siPrefix=config('actuator', 'siprefix'),
243
235
  key_sequences=("Ctrl+E","Ctrl+Shift+E"),)
244
- self.control_ui.layout().addWidget(self.rel_value_sb, 3, 0)
245
236
  self.move_rel_minus_pb = PushButtonIcon('MoveDown', 'Set Rel. (-)')
246
- self.control_ui.layout().addWidget(self.move_rel_minus_pb, 3, 1)
247
237
  self.stop_pb = PushButtonIcon('stop', 'Stop')
248
- self.control_ui.layout().addWidget(self.stop_pb, 4, 0)
249
238
  self.get_value_pb = PushButtonIcon('Help_32', 'Update Value')
250
- self.control_ui.layout().addWidget(self.get_value_pb, 4, 1)
251
- self.control_ui.layout().setContentsMargins(0, 0, 0, 0)
252
-
253
- self.settings_ui.setLayout(QHBoxLayout())
254
- self.settings_ui.layout().setContentsMargins(0, 0, 0, 0)
255
-
256
- self.control_ui.setVisible(False)
257
- self.settings_ui.setVisible(False)
258
-
259
239
  self.statusbar = QtWidgets.QStatusBar()
260
240
  self.statusbar.setMaximumHeight(30)
261
- self.parent.layout().addWidget(self.statusbar)
262
-
263
- def set_abs_value_red(self, value: Q_):
264
- self.abs_value_sb_2.setValue(value.m_as(self._unit))
265
-
266
- def set_abs_value_green(self, value: Q_):
267
- self.abs_value_sb.setValue(value.m_as(self._unit))
268
-
269
- def set_abs_value(self, value: Q_):
270
- self.abs_value_sb_bis.setValue(value.m_as(self._unit))
271
-
272
- def set_rel_value(self, value: Q_):
273
- self.rel_value_sb.setValue(value.m_as(self._unit))
274
241
 
275
- def set_unit_as_suffix(self, unit: str):
276
- """Will append the actuator units in the value display"""
277
- self._unit = unit
278
- self.current_value_sb.setOpts(suffix=unit)
279
- self.abs_value_sb_bis.setOpts(suffix=unit)
280
- self.abs_value_sb.setOpts(suffix=unit)
281
- self.abs_value_sb_2.setOpts(suffix=unit)
282
- self.rel_value_sb.setOpts(suffix=unit)
283
-
284
- def setup_actions(self):
285
- self.add_action('move_abs', 'Move Abs', 'go_to_1', "Move to the set absolute value",
286
- toolbar=self.move_toolbar)
287
- self.add_action('move_abs_2', 'Move Abs', 'go_to_2', "Move to the other set absolute value",
288
- toolbar=self.move_toolbar)
289
- self.add_action('show_controls', 'Show Controls', 'Add_Step', "Show more controls", checkable=True,
290
- toolbar=self.toolbar)
291
- self.add_action('show_settings', 'Show Settings', 'tree', "Show Settings", checkable=True,
292
- toolbar=self.toolbar)
293
- self.add_action('show_config', 'Show Config', 'Settings', "Show PyMoDAQ Config", checkable=False,
294
- toolbar=self.toolbar)
295
- self.add_action('show_graph', 'Show Graph', 'graph', "Show Graph", checkable=True,
296
- toolbar=self.toolbar)
297
- self.add_action('refresh_value', 'Refresh', 'Refresh2', "Refresh Value", checkable=True,
298
- toolbar=self.toolbar)
299
- self.add_action('stop', 'Stop', 'stop', "Stop Motion", checkable=False,
300
- toolbar=self.toolbar)
301
- self.add_action('quit', 'Quit the module', 'close2')
302
- self.add_action('log', 'Show Log file', 'information2')
303
-
304
- self.toolbar.addWidget(LabelWithFont(self.title, font_name="Tahoma", font_size=14, isbold=True, isitalic=True))
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)
305
248
 
306
- def connect_things(self):
307
- self.connect_action('show_controls', lambda show: self.control_ui.setVisible(show))
308
- self.connect_action('show_settings', lambda show: self.settings_ui.setVisible(show))
309
- self.connect_action('show_graph', lambda show: self.graph_ui.setVisible(show))
310
-
311
- self.connect_action('quit', lambda: self.command_sig.emit(ThreadCommand('quit', )))
312
- self.connect_action('refresh_value',
313
- lambda do_refresh: self.command_sig.emit(ThreadCommand('loop_get_value', do_refresh)))
314
- self.connect_action('move_abs', lambda: self.emit_move_abs(self.abs_value_sb))
315
- self.connect_action('move_abs_2', lambda: self.emit_move_abs(self.abs_value_sb_2))
316
- self.connect_action('log', lambda: self.command_sig.emit(ThreadCommand('show_log', )))
317
- self.connect_action('stop', lambda: self.command_sig.emit(ThreadCommand('stop', )))
318
- self.connect_action('show_config', lambda: self.command_sig.emit(ThreadCommand('show_config', )))
249
+ def populate_control_ui(self, widget: QtWidgets.QWidget):
250
+ widget.setLayout(QtWidgets.QGridLayout())
251
+ widget.layout().addWidget(LabelWithFont('Abs. Value'), 0, 0)
319
252
 
320
- self.move_abs_pb.clicked.connect(lambda: self.emit_move_abs(self.abs_value_sb_bis))
321
- self.abs_value_sb.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb))
322
- self.abs_value_sb_2.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb_2))
323
- self.abs_value_sb_bis.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_abs(self.abs_value_sb_bis))
253
+ widget.layout().addWidget(self.find_home_pb, 0, 1)
324
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)
325
259
 
326
- self.rel_value_sb.valueChanged.connect(lambda: self.command_sig.emit(
327
- ThreadCommand('rel_value', self.rel_value_sb.value())))
328
- self.move_rel_plus_pb.clicked.connect(lambda: self.emit_move_rel('+'))
329
- self.move_rel_minus_pb.clicked.connect(lambda: self.emit_move_rel('-'))
330
- self.rel_value_sb.shortcut["Ctrl+E"].activated.connect(lambda: self.emit_move_rel('+'))
331
- self.rel_value_sb.shortcut["Ctrl+Shift+E"].activated.connect(lambda: self.emit_move_rel('-'))
260
+ widget.layout().addWidget(self.rel_value_sb, 3, 0)
332
261
 
333
- self.find_home_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand('find_home', )))
334
- self.stop_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand('stop', )))
335
- self.get_value_pb.clicked.connect(lambda: self.command_sig.emit(ThreadCommand('get_value', )))
262
+ widget.layout().addWidget(self.move_rel_minus_pb, 3, 1)
263
+ widget.layout().addWidget(self.stop_pb, 4, 0)
336
264
 
337
- self.ini_actuator_pb.clicked.connect(self.send_init)
265
+ widget.layout().addWidget(self.get_value_pb, 4, 1)
266
+ widget.layout().setContentsMargins(0, 0, 0, 0)
267
+ widget.setVisible(False)
338
268
 
339
- self.actuators_combo.currentTextChanged.connect(
340
- lambda act: self.command_sig.emit(ThreadCommand('actuator_changed', act)))
269
+ def close(self):
270
+ self.parent.close()
271
+ self.graph_widget.close()
341
272
 
342
273
  def do_init(self, do_init=True):
343
274
  """Programmatically press the Init button
@@ -352,50 +283,77 @@ class DAQ_Move_UI(ControlModuleUI):
352
283
 
353
284
  def send_init(self, checked):
354
285
  self.actuators_combo.setEnabled(not checked)
355
- self.command_sig.emit(ThreadCommand('init', [self.ini_actuator_pb.isChecked(),
356
- self.actuators_combo.currentText()]))
286
+ self.command_sig.emit(ThreadCommand(UiToMainMove.INIT, [self.ini_actuator_pb.isChecked(),
287
+ self.actuators_combo.currentText()]))
357
288
 
358
289
  def emit_move_abs(self, spinbox):
359
290
  spinbox.editingFinished.emit()
360
- self.command_sig.emit(ThreadCommand('move_abs', DataActuator(data=spinbox.value(),
361
- units=self._unit)))
291
+ self.command_sig.emit(ThreadCommand(UiToMainMove.MOVE_ABS, DataActuator(data=spinbox.value(),
292
+ units=self._unit)))
362
293
 
363
294
  def emit_move_rel(self, sign):
364
295
  self.command_sig.emit(ThreadCommand(
365
- 'move_rel',
296
+ UiToMainMove.MOVE_REL,
366
297
  DataActuator(data=self.rel_value_sb.value() * (1 if sign == '+' else -1),
367
298
  units=self._unit)))
368
299
 
369
- def close(self):
370
- self.graph_ui.close()
371
- self.parent.close()
372
-
373
-
374
- def main(init_qt=True):
375
- from pymodaq_gui.utils.dock import DockArea
376
- if init_qt: # used for the test suite
377
- app = QtWidgets.QApplication(sys.argv)
378
-
379
- actuators = [f'act{ind}' for ind in range(5)]
300
+ def set_settings_tree(self, tree):
301
+ self._tree = tree
380
302
 
381
- widget = QtWidgets.QWidget()
382
- prog = DAQ_Move_UI(widget, title="test")
383
- widget.show()
384
-
385
- def print_command_sig(cmd_sig):
386
- print(cmd_sig)
387
- if cmd_sig.command == 'init':
388
- prog.enable_move_buttons(True)
389
-
390
- prog.command_sig.connect(print_command_sig)
391
- prog.actuators = actuators
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)
392
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('-'))
393
333
 
394
-
395
- if init_qt:
396
- sys.exit(app.exec_())
397
- return prog, widget
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, )))
398
337
 
338
+ self.ini_actuator_pb.clicked.connect(self.send_init)
399
339
 
400
- if __name__ == '__main__':
401
- main()
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
+