pymodaq 5.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
from qtpy import QtWidgets
|
|
2
|
+
from qtpy.QtWidgets import QMessageBox, QDialogButtonBox, QDialog
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from pymodaq_gui.parameter import ioxml, Parameter, ParameterTree
|
|
7
|
+
from pymodaq_gui.parameter.pymodaq_ptypes import registerParameterType, GroupParameter
|
|
8
|
+
from pymodaq_gui.utils import select_file
|
|
9
|
+
|
|
10
|
+
# check if overshoot_configurations directory exists on the drive
|
|
11
|
+
from pymodaq.utils.config import get_set_overshoot_path
|
|
12
|
+
|
|
13
|
+
overshoot_path = get_set_overshoot_path()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PresetScalableGroupMove(GroupParameter):
|
|
17
|
+
"""
|
|
18
|
+
|
|
|
19
|
+
|
|
20
|
+
================ =============
|
|
21
|
+
**Attributes** **Type**
|
|
22
|
+
*opts* dictionnary
|
|
23
|
+
================ =============
|
|
24
|
+
|
|
25
|
+
See Also
|
|
26
|
+
--------
|
|
27
|
+
hardware.DAQ_Move_Stage_type
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, **opts):
|
|
31
|
+
opts['type'] = 'groupmoveover'
|
|
32
|
+
opts['addText'] = "Add"
|
|
33
|
+
opts['addList'] = opts['movelist']
|
|
34
|
+
super().__init__(**opts)
|
|
35
|
+
|
|
36
|
+
def addNew(self, name):
|
|
37
|
+
"""
|
|
38
|
+
Add a child.
|
|
39
|
+
|
|
40
|
+
=============== ===========
|
|
41
|
+
**Parameters** **Type**
|
|
42
|
+
*typ* string
|
|
43
|
+
=============== ===========
|
|
44
|
+
"""
|
|
45
|
+
name_prefix = 'move'
|
|
46
|
+
child_indexes = [int(par.name()[len(name_prefix) + 1:]) for par in self.children()]
|
|
47
|
+
if not child_indexes:
|
|
48
|
+
newindex = 0
|
|
49
|
+
else:
|
|
50
|
+
newindex = max(child_indexes) + 1
|
|
51
|
+
|
|
52
|
+
child = {'title': name, 'name': f'{name_prefix}{newindex:02.0f}', 'type': 'group', 'removable': True,
|
|
53
|
+
'children': [
|
|
54
|
+
{'title': 'Move if overshoot?:', 'name': 'move_overshoot', 'type': 'bool', 'value': True},
|
|
55
|
+
{'title': 'Position:', 'name': 'position', 'type': 'float', 'value': 0}], 'removable': True,
|
|
56
|
+
'renamable': False}
|
|
57
|
+
|
|
58
|
+
self.addChild(child)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
registerParameterType('groupmoveover', PresetScalableGroupMove, override=True)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class PresetScalableGroupDet(GroupParameter):
|
|
65
|
+
"""
|
|
66
|
+
=============== ==============
|
|
67
|
+
**Attributes** **Type**
|
|
68
|
+
*opts* dictionnary
|
|
69
|
+
*options* string list
|
|
70
|
+
=============== ==============
|
|
71
|
+
|
|
72
|
+
See Also
|
|
73
|
+
--------
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self, **opts):
|
|
77
|
+
opts['type'] = 'groupdetover'
|
|
78
|
+
opts['addText'] = "Add"
|
|
79
|
+
opts['addList'] = opts['detlist']
|
|
80
|
+
opts['movelist'] = opts['movelist']
|
|
81
|
+
|
|
82
|
+
super().__init__(**opts)
|
|
83
|
+
|
|
84
|
+
def addNew(self, name):
|
|
85
|
+
"""
|
|
86
|
+
Add a child.
|
|
87
|
+
|
|
88
|
+
=============== =========== ================
|
|
89
|
+
**Parameters** **Type** **Description*
|
|
90
|
+
*typ* string the viewer name
|
|
91
|
+
=============== =========== ================
|
|
92
|
+
"""
|
|
93
|
+
try:
|
|
94
|
+
name_prefix = 'det'
|
|
95
|
+
child_indexes = [int(par.name()[len(name_prefix) + 1:]) for par in self.children()]
|
|
96
|
+
if not child_indexes:
|
|
97
|
+
newindex = 0
|
|
98
|
+
else:
|
|
99
|
+
newindex = max(child_indexes) + 1
|
|
100
|
+
|
|
101
|
+
child = {'title': name, 'name': f'{name_prefix}{newindex:02.0f}', 'type': 'group', 'children': [
|
|
102
|
+
{'title': 'Trig overshoot?:', 'name': 'trig_overshoot', 'type': 'bool', 'value': True},
|
|
103
|
+
{'title': 'Overshoot value:', 'name': 'overshoot_value', 'type': 'float', 'value': 20},
|
|
104
|
+
{'title': 'Triggered Moves:', 'name': 'params', 'type': 'groupmoveover',
|
|
105
|
+
'movelist': self.opts['movelist']}], 'removable': True, 'renamable': False}
|
|
106
|
+
|
|
107
|
+
self.addChild(child)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(str(e))
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
registerParameterType('groupdetover', PresetScalableGroupDet, override=True)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class OvershootManager:
|
|
116
|
+
def __init__(self, msgbox=False, det_modules=[], actuators_modules=[]):
|
|
117
|
+
|
|
118
|
+
self.overshoot_params = None
|
|
119
|
+
self.det_modules = det_modules
|
|
120
|
+
self.actuators_modules = actuators_modules
|
|
121
|
+
|
|
122
|
+
self._activated = False
|
|
123
|
+
|
|
124
|
+
if msgbox:
|
|
125
|
+
msgBox = QMessageBox()
|
|
126
|
+
msgBox.setText("Overshoot Manager?")
|
|
127
|
+
msgBox.setInformativeText("What do you want to do?")
|
|
128
|
+
cancel_button = msgBox.addButton(QMessageBox.StandardButton.Cancel)
|
|
129
|
+
new_button = msgBox.addButton("New", QMessageBox.ButtonRole.ActionRole)
|
|
130
|
+
modify_button = msgBox.addButton("Modify", QMessageBox.ButtonRole.AcceptRole)
|
|
131
|
+
msgBox.setDefaultButton(QMessageBox.StandardButton.Cancel)
|
|
132
|
+
ret = msgBox.exec()
|
|
133
|
+
|
|
134
|
+
if msgBox.clickedButton() == new_button:
|
|
135
|
+
self.set_new_overshoot()
|
|
136
|
+
|
|
137
|
+
elif msgBox.clickedButton() == modify_button:
|
|
138
|
+
path = select_file(start_path=overshoot_path, save=False, ext='xml')
|
|
139
|
+
if path != '':
|
|
140
|
+
self.set_file_overshoot(str(path))
|
|
141
|
+
else: # cancel
|
|
142
|
+
pass
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def activated(self) -> bool:
|
|
146
|
+
return self._activated
|
|
147
|
+
|
|
148
|
+
@activated.setter
|
|
149
|
+
def activated(self, status: bool):
|
|
150
|
+
self._activated = status
|
|
151
|
+
|
|
152
|
+
def set_file_overshoot(self, filename, show=True):
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
"""
|
|
156
|
+
children = ioxml.XML_file_to_parameter(filename)
|
|
157
|
+
self.overshoot_params = Parameter.create(title='Overshoot', name='Overshoot', type='group',
|
|
158
|
+
children=children)
|
|
159
|
+
if show:
|
|
160
|
+
self.show_overshoot()
|
|
161
|
+
|
|
162
|
+
def set_new_overshoot(self, file=None):
|
|
163
|
+
if file is None:
|
|
164
|
+
file = 'overshoot_default'
|
|
165
|
+
param = [{'title': 'Filename:', 'name': 'filename', 'type': 'str', 'value': file}]
|
|
166
|
+
params_det = [{'title': 'Detectors:', 'name': 'Detectors', 'type': 'groupdetover', 'detlist': self.det_modules,
|
|
167
|
+
'movelist': self.actuators_modules}] # [PresetScalableGroupDet(name="Detectors")]
|
|
168
|
+
self.overshoot_params = Parameter.create(title='Preset', name='Preset', type='group',
|
|
169
|
+
children=param + params_det)
|
|
170
|
+
|
|
171
|
+
self.show_overshoot()
|
|
172
|
+
|
|
173
|
+
def show_overshoot(self):
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
"""
|
|
177
|
+
dialog = QDialog()
|
|
178
|
+
vlayout = QtWidgets.QVBoxLayout()
|
|
179
|
+
tree = ParameterTree()
|
|
180
|
+
tree.setMinimumWidth(400)
|
|
181
|
+
tree.setMinimumHeight(500)
|
|
182
|
+
tree.setParameters(self.overshoot_params, showTop=False)
|
|
183
|
+
|
|
184
|
+
vlayout.addWidget(tree)
|
|
185
|
+
dialog.setLayout(vlayout)
|
|
186
|
+
buttonBox = QDialogButtonBox(parent=dialog)
|
|
187
|
+
|
|
188
|
+
buttonBox.addButton("Save", QDialogButtonBox.ButtonRole.AcceptRole)
|
|
189
|
+
buttonBox.accepted.connect(dialog.accept)
|
|
190
|
+
buttonBox.addButton("Cancel", QDialogButtonBox.ButtonRole.RejectRole)
|
|
191
|
+
buttonBox.rejected.connect(dialog.reject)
|
|
192
|
+
|
|
193
|
+
vlayout.addWidget(buttonBox)
|
|
194
|
+
dialog.setWindowTitle('Fill in information about this managers')
|
|
195
|
+
res = dialog.exec()
|
|
196
|
+
|
|
197
|
+
if res == QDialog.DialogCode.Accepted:
|
|
198
|
+
# save managers parameters in a xml file
|
|
199
|
+
# start = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0]
|
|
200
|
+
# start = os.path.join("..",'daq_scan')
|
|
201
|
+
ioxml.parameter_to_xml_file(
|
|
202
|
+
self.overshoot_params, os.path.join(overshoot_path, self.overshoot_params.child('filename').value()))
|
|
203
|
+
|
|
204
|
+
def activate_overshoot(self, det_modules, act_modules, status: bool):
|
|
205
|
+
det_titles = [det.title for det in det_modules]
|
|
206
|
+
move_titles = [move.title for move in act_modules]
|
|
207
|
+
|
|
208
|
+
if self.overshoot_params is not None:
|
|
209
|
+
for det_param in self.overshoot_params.child(
|
|
210
|
+
'Detectors').children():
|
|
211
|
+
if det_param['trig_overshoot']:
|
|
212
|
+
det_index = det_titles.index(det_param.opts['title'])
|
|
213
|
+
det_module = det_modules[det_index]
|
|
214
|
+
det_module.settings.child(
|
|
215
|
+
'main_settings', 'overshoot', 'stop_overshoot').setValue(status)
|
|
216
|
+
det_module.settings.child(
|
|
217
|
+
'main_settings', 'overshoot', 'overshoot_value').setValue(
|
|
218
|
+
det_param['overshoot_value'])
|
|
219
|
+
for move_param in det_param.child('params').children():
|
|
220
|
+
if move_param['move_overshoot']:
|
|
221
|
+
move_index = move_titles.index(move_param.opts['title'])
|
|
222
|
+
move_module = act_modules[move_index]
|
|
223
|
+
if status:
|
|
224
|
+
det_module.overshoot_signal.connect(
|
|
225
|
+
self.create_overshoot_fun(
|
|
226
|
+
move_module, move_param['position']))
|
|
227
|
+
else:
|
|
228
|
+
try:
|
|
229
|
+
det_module.overshoot_signal.disconnect()
|
|
230
|
+
except Exception as e:
|
|
231
|
+
pass
|
|
232
|
+
|
|
233
|
+
@staticmethod
|
|
234
|
+
def create_overshoot_fun(move_module, position):
|
|
235
|
+
return lambda: move_module.move_abs(position)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
if __name__ == '__main__':
|
|
239
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
240
|
+
prog = OvershootManager(True, ['det camera', 'det current'], ['Move X', 'Move Y'])
|
|
241
|
+
|
|
242
|
+
sys.exit(app.exec_())
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from qtpy import QtWidgets
|
|
6
|
+
from qtpy.QtWidgets import QMessageBox, QDialogButtonBox, QDialog
|
|
7
|
+
|
|
8
|
+
import pymodaq_utils.config as config_mod
|
|
9
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
10
|
+
|
|
11
|
+
from pymodaq_gui.utils.file_io import select_file
|
|
12
|
+
from pymodaq_gui.parameter import ParameterTree, Parameter
|
|
13
|
+
from pymodaq_gui.parameter import ioxml
|
|
14
|
+
from pymodaq_gui.messenger import dialog as dialogbox
|
|
15
|
+
from pymodaq.utils import config as config_mod_pymodaq
|
|
16
|
+
from pymodaq.extensions import get_models
|
|
17
|
+
|
|
18
|
+
import pymodaq.utils.managers.preset_manager_utils # to register move and det types
|
|
19
|
+
|
|
20
|
+
logger = set_logger(get_module_name(__file__))
|
|
21
|
+
|
|
22
|
+
# check if preset_mode directory exists on the drive
|
|
23
|
+
preset_path = config_mod_pymodaq.get_set_preset_path()
|
|
24
|
+
overshoot_path = config_mod_pymodaq.get_set_overshoot_path()
|
|
25
|
+
layout_path = config_mod_pymodaq.get_set_layout_path()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PresetManager:
|
|
29
|
+
def __init__(self, msgbox=False, path=None, extra_params=[], param_options=[]):
|
|
30
|
+
if path is None:
|
|
31
|
+
path = preset_path
|
|
32
|
+
else:
|
|
33
|
+
assert isinstance(path, Path)
|
|
34
|
+
|
|
35
|
+
self.extra_params = extra_params
|
|
36
|
+
self.param_options = param_options
|
|
37
|
+
self.preset_path = path
|
|
38
|
+
self.preset_params: Parameter = None
|
|
39
|
+
|
|
40
|
+
if msgbox:
|
|
41
|
+
msgBox = QMessageBox()
|
|
42
|
+
msgBox.setText("Preset Manager?")
|
|
43
|
+
msgBox.setInformativeText("What do you want to do?")
|
|
44
|
+
cancel_button = msgBox.addButton(QMessageBox.StandardButton.Cancel)
|
|
45
|
+
new_button = msgBox.addButton(
|
|
46
|
+
"New", QMessageBox.ButtonRole.ActionRole
|
|
47
|
+
)
|
|
48
|
+
modify_button = msgBox.addButton(
|
|
49
|
+
"Modify", QMessageBox.ButtonRole.AcceptRole
|
|
50
|
+
)
|
|
51
|
+
msgBox.setDefaultButton(QMessageBox.StandardButton.Cancel)
|
|
52
|
+
ret = msgBox.exec()
|
|
53
|
+
|
|
54
|
+
if msgBox.clickedButton() == new_button:
|
|
55
|
+
self.set_new_preset()
|
|
56
|
+
|
|
57
|
+
elif msgBox.clickedButton() == modify_button:
|
|
58
|
+
path = select_file(start_path=self.preset_path, save=False, ext="xml")
|
|
59
|
+
if path != "":
|
|
60
|
+
self.set_file_preset(str(path))
|
|
61
|
+
else: # cancel
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def filename(self) -> str:
|
|
66
|
+
try:
|
|
67
|
+
return self.preset_params["filename"]
|
|
68
|
+
except:
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
def set_file_preset(self, filename, show=True):
|
|
72
|
+
""" """
|
|
73
|
+
status = False
|
|
74
|
+
children = ioxml.XML_file_to_parameter(filename)
|
|
75
|
+
self.preset_params = Parameter.create(
|
|
76
|
+
title="Preset", name="Preset", type="group", children=children
|
|
77
|
+
)
|
|
78
|
+
if show:
|
|
79
|
+
status = self.show_preset()
|
|
80
|
+
return status
|
|
81
|
+
|
|
82
|
+
def set_new_preset(self):
|
|
83
|
+
param = [
|
|
84
|
+
{
|
|
85
|
+
"title": "Filename:",
|
|
86
|
+
"name": "filename",
|
|
87
|
+
"type": "str",
|
|
88
|
+
"value": "preset_default",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"title": "Model Settings:",
|
|
92
|
+
"name": "model_settings",
|
|
93
|
+
"type": "group",
|
|
94
|
+
"visible": False,
|
|
95
|
+
"children": [],
|
|
96
|
+
},
|
|
97
|
+
]
|
|
98
|
+
params_move = [
|
|
99
|
+
{"title": "Moves:", "name": "Moves", "type": "groupmove"}
|
|
100
|
+
] # PresetScalableGroupMove(name="Moves")]
|
|
101
|
+
params_det = [
|
|
102
|
+
{"title": "Detectors:", "name": "Detectors", "type": "groupdet"}
|
|
103
|
+
] # [PresetScalableGroupDet(name="Detectors")]
|
|
104
|
+
self.preset_params = Parameter.create(
|
|
105
|
+
title="Preset",
|
|
106
|
+
name="Preset",
|
|
107
|
+
type="group",
|
|
108
|
+
children=param + self.extra_params + params_move + params_det,
|
|
109
|
+
)
|
|
110
|
+
try:
|
|
111
|
+
for option in self.param_options:
|
|
112
|
+
if "path" in option and "options_dict" in option:
|
|
113
|
+
self.preset_params.child(option["path"]).setOpts(
|
|
114
|
+
**option["options_dict"]
|
|
115
|
+
)
|
|
116
|
+
except Exception as e:
|
|
117
|
+
logger.exception(str(e))
|
|
118
|
+
|
|
119
|
+
self.preset_params.sigTreeStateChanged.connect(self.parameter_tree_changed)
|
|
120
|
+
|
|
121
|
+
status = self.show_preset()
|
|
122
|
+
return status
|
|
123
|
+
|
|
124
|
+
def parameter_tree_changed(self, param, changes):
|
|
125
|
+
"""
|
|
126
|
+
Check for changes in the given (parameter,change,information) tuple list.
|
|
127
|
+
In case of value changed, update the DAQscan_settings tree consequently.
|
|
128
|
+
|
|
129
|
+
=============== ============================================ ==============================
|
|
130
|
+
**Parameters** **Type** **Description**
|
|
131
|
+
*param* instance of pyqtgraph parameter the parameter to be checked
|
|
132
|
+
*changes* (parameter,change,information) tuple list the current changes state
|
|
133
|
+
=============== ============================================ ==============================
|
|
134
|
+
"""
|
|
135
|
+
for param, change, data in changes:
|
|
136
|
+
path = self.preset_params.childPath(param)
|
|
137
|
+
if change == "childAdded":
|
|
138
|
+
if len(data) > 1:
|
|
139
|
+
if "params" in data[0].children():
|
|
140
|
+
data[0].child(
|
|
141
|
+
"params", "main_settings", "module_name"
|
|
142
|
+
).setValue(data[0].child("name").value())
|
|
143
|
+
|
|
144
|
+
elif change == "value":
|
|
145
|
+
if param.name() == "name":
|
|
146
|
+
param.parent().child(
|
|
147
|
+
"params", "main_settings", "module_name"
|
|
148
|
+
).setValue(param.value())
|
|
149
|
+
|
|
150
|
+
elif change == "parent":
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
def show_preset(self):
|
|
154
|
+
""" """
|
|
155
|
+
dialog = QDialog()
|
|
156
|
+
vlayout = QtWidgets.QVBoxLayout()
|
|
157
|
+
tree = ParameterTree()
|
|
158
|
+
# tree.setMinimumWidth(400)
|
|
159
|
+
# tree.setMinimumHeight(500)
|
|
160
|
+
tree.setParameters(self.preset_params, showTop=False)
|
|
161
|
+
tree.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
|
162
|
+
|
|
163
|
+
vlayout.addWidget(tree)
|
|
164
|
+
dialog.setLayout(vlayout)
|
|
165
|
+
buttonBox = QDialogButtonBox(parent=dialog)
|
|
166
|
+
|
|
167
|
+
buttonBox.addButton("Save", QDialogButtonBox.ButtonRole.AcceptRole)
|
|
168
|
+
buttonBox.accepted.connect(dialog.accept)
|
|
169
|
+
buttonBox.addButton("Cancel", QDialogButtonBox.ButtonRole.RejectRole)
|
|
170
|
+
buttonBox.rejected.connect(dialog.reject)
|
|
171
|
+
|
|
172
|
+
vlayout.addWidget(buttonBox)
|
|
173
|
+
dialog.setWindowTitle("Fill in information about this manager")
|
|
174
|
+
res = dialog.exec()
|
|
175
|
+
|
|
176
|
+
path = self.preset_path
|
|
177
|
+
file = None
|
|
178
|
+
|
|
179
|
+
if res == QDialog.DialogCode.Accepted:
|
|
180
|
+
# save managers parameters in a xml file
|
|
181
|
+
# start = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0]
|
|
182
|
+
# start = os.path.join("..",'daq_scan')
|
|
183
|
+
filename_without_extension = self.filename
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
ioxml.parameter_to_xml_file(
|
|
187
|
+
self.preset_params,
|
|
188
|
+
path.joinpath(filename_without_extension),
|
|
189
|
+
overwrite=False,
|
|
190
|
+
)
|
|
191
|
+
except FileExistsError as currenterror:
|
|
192
|
+
# logger.warning(str(currenterror)+"File " + filename_without_extension + ".xml exists")
|
|
193
|
+
logger.warning(
|
|
194
|
+
f"{currenterror} File {filename_without_extension}.xml exists"
|
|
195
|
+
)
|
|
196
|
+
user_agreed = dialogbox(
|
|
197
|
+
title="Overwrite confirmation",
|
|
198
|
+
message="File exist do you want to overwrite it ?",
|
|
199
|
+
)
|
|
200
|
+
if user_agreed:
|
|
201
|
+
ioxml.parameter_to_xml_file(
|
|
202
|
+
self.preset_params, path.joinpath(filename_without_extension)
|
|
203
|
+
)
|
|
204
|
+
logger.warning(
|
|
205
|
+
f"File {filename_without_extension}.xml overwriten at user request"
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
logger.warning(
|
|
209
|
+
f"File {filename_without_extension}.xml wasn't saved at user request"
|
|
210
|
+
)
|
|
211
|
+
# emit status signal to dashboard to write : did not save ?
|
|
212
|
+
pass
|
|
213
|
+
|
|
214
|
+
# check if overshoot configuration and layout configuration with same name exists => delete them if yes
|
|
215
|
+
over_shoot_file = overshoot_path.joinpath(self.filename + ".xml")
|
|
216
|
+
over_shoot_file.unlink(missing_ok=True)
|
|
217
|
+
|
|
218
|
+
layout_file = layout_path.joinpath(self.filename + ".dock")
|
|
219
|
+
layout_file.unlink(missing_ok=True)
|
|
220
|
+
|
|
221
|
+
return res == QDialog.DialogCode.Accepted
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if __name__ == "__main__":
|
|
225
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
226
|
+
# prog = PresetManager(True)
|
|
227
|
+
prog = PresetManager(True)
|
|
228
|
+
|
|
229
|
+
sys.exit(app.exec_())
|