pymodaq 4.0.5__py3-none-any.whl → 4.0.7__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.
- pymodaq/control_modules/daq_move.py +20 -4
- pymodaq/control_modules/daq_move_ui.py +5 -0
- pymodaq/control_modules/daq_viewer.py +23 -6
- pymodaq/control_modules/daq_viewer_ui.py +1 -1
- pymodaq/control_modules/move_utility_classes.py +103 -126
- pymodaq/control_modules/utils.py +9 -0
- pymodaq/control_modules/viewer_utility_classes.py +1 -0
- pymodaq/dashboard.py +24 -9
- pymodaq/examples/custom_app.py +19 -29
- pymodaq/examples/custom_viewer.py +13 -10
- pymodaq/extensions/utils.py +24 -8
- pymodaq/resources/VERSION +1 -1
- pymodaq/utils/config.py +21 -3
- pymodaq/utils/daq_utils.py +14 -12
- pymodaq/utils/parameter/ioxml.py +12 -12
- pymodaq/utils/parameter/pymodaq_ptypes/list.py +1 -0
- pymodaq/utils/parameter/utils.py +9 -4
- pymodaq/utils/plotting/data_viewers/viewerND.py +8 -2
- {pymodaq-4.0.5.dist-info → pymodaq-4.0.7.dist-info}/METADATA +1 -1
- {pymodaq-4.0.5.dist-info → pymodaq-4.0.7.dist-info}/RECORD +23 -23
- {pymodaq-4.0.5.dist-info → pymodaq-4.0.7.dist-info}/WHEEL +0 -0
- {pymodaq-4.0.5.dist-info → pymodaq-4.0.7.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.0.5.dist-info → pymodaq-4.0.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,6 +7,8 @@ Created the 29/07/2022
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from importlib import import_module
|
|
11
|
+
from numbers import Number
|
|
10
12
|
import sys
|
|
11
13
|
from typing import List, Tuple, Union
|
|
12
14
|
import numpy as np
|
|
@@ -143,6 +145,7 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
143
145
|
* show_log
|
|
144
146
|
* actuator_changed
|
|
145
147
|
* rel_value
|
|
148
|
+
* show_config
|
|
146
149
|
"""
|
|
147
150
|
if cmd.command == 'init':
|
|
148
151
|
self.init_hardware(cmd.attribute[0])
|
|
@@ -162,6 +165,8 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
162
165
|
self.move_rel(cmd.attribute)
|
|
163
166
|
elif cmd.command == 'show_log':
|
|
164
167
|
self.show_log()
|
|
168
|
+
elif cmd.command == 'show_config':
|
|
169
|
+
self.show_config(config)
|
|
165
170
|
elif cmd.command == 'actuator_changed':
|
|
166
171
|
self.actuator = cmd.attribute
|
|
167
172
|
elif cmd.command == 'rel_value':
|
|
@@ -251,7 +256,7 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
251
256
|
"""
|
|
252
257
|
try:
|
|
253
258
|
self._send_to_tcpip = send_to_tcpip
|
|
254
|
-
if
|
|
259
|
+
if np.all(value != self._current_value): # in case value is a ndarray (very specific cases...)
|
|
255
260
|
if self.ui is not None:
|
|
256
261
|
self.ui.move_done = False
|
|
257
262
|
self._move_done_bool = False
|
|
@@ -362,7 +367,7 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
362
367
|
self._hardware_thread.hardware = hardware
|
|
363
368
|
self._hardware_thread.start()
|
|
364
369
|
self.command_hardware.emit(
|
|
365
|
-
ThreadCommand(command="ini_stage", attribute=[self.settings.child(
|
|
370
|
+
ThreadCommand(command="ini_stage", attribute=[self.settings.child('move_settings').saveState(),
|
|
366
371
|
self.controller]))
|
|
367
372
|
except Exception as e:
|
|
368
373
|
self.logger.exception(str(e))
|
|
@@ -394,6 +399,9 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
394
399
|
elif param.name() == 'refresh_timeout':
|
|
395
400
|
self._refresh_timer.setInterval(param.value())
|
|
396
401
|
|
|
402
|
+
elif param.name() == 'plugin_config':
|
|
403
|
+
self.show_config(self.plugin_config)
|
|
404
|
+
|
|
397
405
|
path = self.settings.childPath(param)
|
|
398
406
|
if path is not None:
|
|
399
407
|
if 'main_settings' not in path:
|
|
@@ -543,12 +551,19 @@ class DAQ_Move(ParameterManager, ControlModule):
|
|
|
543
551
|
def actuator(self, act_type):
|
|
544
552
|
if act_type in ACTUATOR_TYPES:
|
|
545
553
|
self._actuator_type = act_type
|
|
554
|
+
self.update_plugin_config()
|
|
546
555
|
if self.ui is not None:
|
|
547
556
|
self.ui.actuator = act_type
|
|
548
557
|
self.update_settings()
|
|
549
558
|
else:
|
|
550
559
|
raise ActuatorError(f'{act_type} is an invalid actuator, should be within {ACTUATOR_TYPES}')
|
|
551
560
|
|
|
561
|
+
def update_plugin_config(self):
|
|
562
|
+
parent_module = utils.find_dict_in_list_from_key_val(DAQ_Move_Actuators, 'name', self.actuator)
|
|
563
|
+
mod = import_module(parent_module['module'].__package__.split('.')[0])
|
|
564
|
+
if hasattr(mod, 'config'):
|
|
565
|
+
self.plugin_config = mod.config
|
|
566
|
+
|
|
552
567
|
@property
|
|
553
568
|
def units(self):
|
|
554
569
|
return self.settings['move_settings', 'units']
|
|
@@ -734,8 +749,9 @@ class DAQ_Move_Hardware(QObject):
|
|
|
734
749
|
--------
|
|
735
750
|
move_Abs
|
|
736
751
|
"""
|
|
737
|
-
|
|
738
|
-
|
|
752
|
+
if isinstance(position, Number):
|
|
753
|
+
position = float(position) # because it may be a numpy float and could cause issues
|
|
754
|
+
# see https://github.com/pythonnet/pythonnet/issues/1833
|
|
739
755
|
self._target_value = position
|
|
740
756
|
self.hardware.move_is_done = False
|
|
741
757
|
self.hardware.ispolling = polling
|
|
@@ -39,6 +39,8 @@ class DAQ_Move_UI(ControlModuleUI):
|
|
|
39
39
|
* show_log
|
|
40
40
|
* actuator_changed
|
|
41
41
|
* rel_value
|
|
42
|
+
* show_config
|
|
43
|
+
* show_plugin_config
|
|
42
44
|
|
|
43
45
|
Methods
|
|
44
46
|
-------
|
|
@@ -237,6 +239,8 @@ class DAQ_Move_UI(ControlModuleUI):
|
|
|
237
239
|
toolbar=self.toolbar)
|
|
238
240
|
self.add_action('show_settings', 'Show Settings', 'Settings', "Show Settings", checkable=True,
|
|
239
241
|
toolbar=self.toolbar)
|
|
242
|
+
self.add_action('show_config', 'Show Config', 'tree', "Show Plugin Config", checkable=False,
|
|
243
|
+
toolbar=self.toolbar)
|
|
240
244
|
self.add_action('refresh_value', 'Refresh', 'Refresh2', "Refresh Value", checkable=True,
|
|
241
245
|
toolbar=self.toolbar)
|
|
242
246
|
self.add_action('stop', 'Stop', 'stop', "Stop Motion", checkable=False,
|
|
@@ -256,6 +260,7 @@ class DAQ_Move_UI(ControlModuleUI):
|
|
|
256
260
|
self.connect_action('move_abs_2', lambda: self.emit_move_abs(self.abs_value_sb_2))
|
|
257
261
|
self.connect_action('log', lambda: self.command_sig.emit(ThreadCommand('show_log', )))
|
|
258
262
|
self.connect_action('stop', lambda: self.command_sig.emit(ThreadCommand('stop', )))
|
|
263
|
+
self.connect_action('show_config', lambda : self.command_sig.emit(ThreadCommand('show_config', )))
|
|
259
264
|
|
|
260
265
|
self.move_abs_pb.clicked.connect(lambda: self.emit_move_abs(self.abs_value_sb_bis))
|
|
261
266
|
|
|
@@ -5,7 +5,7 @@ Created on Wed Jan 10 16:54:14 2018
|
|
|
5
5
|
@author: Weber Sébastien
|
|
6
6
|
"""
|
|
7
7
|
from __future__ import annotations
|
|
8
|
-
|
|
8
|
+
from importlib import import_module
|
|
9
9
|
from collections import OrderedDict
|
|
10
10
|
import copy
|
|
11
11
|
import os
|
|
@@ -250,6 +250,12 @@ class DAQ_Viewer(ParameterManager, ControlModule):
|
|
|
250
250
|
if self.ui is not None:
|
|
251
251
|
return self.ui.viewer_docks
|
|
252
252
|
|
|
253
|
+
@property
|
|
254
|
+
def viewers_docks(self) -> List[Dock]:
|
|
255
|
+
"""list of Viewer Docks from the UI, for back compatibility"""
|
|
256
|
+
deprecation_msg('viewers_docks is a deprecated property use viewer_docks instead')
|
|
257
|
+
return self.viewer_docks
|
|
258
|
+
|
|
253
259
|
def daq_type_changed_from_ui(self, daq_type: DAQTypesEnum):
|
|
254
260
|
""" Apply changes from the selection of a different DAQTypesEnum in the UI
|
|
255
261
|
|
|
@@ -289,6 +295,7 @@ class DAQ_Viewer(ParameterManager, ControlModule):
|
|
|
289
295
|
|
|
290
296
|
def detector_changed_from_ui(self, detector: str):
|
|
291
297
|
self._detector = detector
|
|
298
|
+
self.update_plugin_config()
|
|
292
299
|
self._set_setting_tree()
|
|
293
300
|
|
|
294
301
|
@property
|
|
@@ -301,10 +308,17 @@ class DAQ_Viewer(ParameterManager, ControlModule):
|
|
|
301
308
|
if det not in self.detectors:
|
|
302
309
|
raise ValueError(f'{det} is not a valid Detector: {self.detectors}')
|
|
303
310
|
self._detector = det
|
|
311
|
+
self.update_plugin_config()
|
|
304
312
|
if self.ui is not None:
|
|
305
313
|
self.ui.detector = det
|
|
306
314
|
self._set_setting_tree()
|
|
307
315
|
|
|
316
|
+
def update_plugin_config(self):
|
|
317
|
+
parent_module = utils.find_dict_in_list_from_key_val(DET_TYPES[self.daq_type.name], 'name', self.detector)
|
|
318
|
+
mod = import_module(parent_module['module'].__package__.split('.')[0])
|
|
319
|
+
if hasattr(mod, 'config'):
|
|
320
|
+
self.plugin_config = mod.config
|
|
321
|
+
|
|
308
322
|
def detectors_changed_from_ui(self, detectors: List[str]):
|
|
309
323
|
self._detectors = detectors
|
|
310
324
|
|
|
@@ -906,10 +920,13 @@ class DAQ_Viewer(ParameterManager, ControlModule):
|
|
|
906
920
|
|
|
907
921
|
elif param.name() == 'ip_address' or param.name == 'port':
|
|
908
922
|
self._command_tcpip.emit(
|
|
909
|
-
ThreadCommand('update_connection', dict(ipaddress=self.settings
|
|
910
|
-
'ip_address'
|
|
911
|
-
port=self.settings
|
|
912
|
-
'port')
|
|
923
|
+
ThreadCommand('update_connection', dict(ipaddress=self.settings['main_settings', 'tcpip',
|
|
924
|
+
'ip_address'],
|
|
925
|
+
port=self.settings['main_settings', 'tcpip',
|
|
926
|
+
'port'])))
|
|
927
|
+
|
|
928
|
+
elif param.name() == 'plugin_config':
|
|
929
|
+
self.show_config(self.plugin_config)
|
|
913
930
|
|
|
914
931
|
if path is not None:
|
|
915
932
|
if 'main_settings' not in path:
|
|
@@ -1319,7 +1336,7 @@ class DAQ_Detector(QObject):
|
|
|
1319
1336
|
if not self.grab_state:
|
|
1320
1337
|
self.detector.stop()
|
|
1321
1338
|
|
|
1322
|
-
def single(self, Naverage=1, **kwargs):
|
|
1339
|
+
def single(self, Naverage=1, *args, **kwargs):
|
|
1323
1340
|
""" Convenience function to grab a single set of data
|
|
1324
1341
|
|
|
1325
1342
|
Parameters
|
|
@@ -206,7 +206,7 @@ class DAQ_Viewer_UI(ControlModuleUI, ViewerDispatcher):
|
|
|
206
206
|
|
|
207
207
|
self.add_action('show_controls', 'Show Controls', 'Settings', "Show Controls to set DAQ and Detector type",
|
|
208
208
|
checkable=True)
|
|
209
|
-
self.add_action('show_settings', 'Show Settings', '
|
|
209
|
+
self.add_action('show_settings', 'Show Settings', 'tree', "Show Settings", checkable=True)
|
|
210
210
|
|
|
211
211
|
self.add_action('quit', 'Quit the module', 'close2')
|
|
212
212
|
self.add_action('log', 'Show Log file', 'information2')
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
from time import perf_counter
|
|
2
|
+
from typing import Union, List, Dict
|
|
3
|
+
|
|
4
|
+
from easydict import EasyDict as edict
|
|
5
|
+
import numpy as np
|
|
1
6
|
from qtpy import QtWidgets
|
|
2
7
|
from qtpy.QtCore import QObject, Slot, Signal, QTimer
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
from easydict import EasyDict as edict
|
|
6
9
|
import pymodaq.utils.daq_utils as utils
|
|
7
10
|
import pymodaq.utils.parameter.utils as putils
|
|
8
|
-
from pymodaq.utils.
|
|
11
|
+
from pymodaq.utils.parameter import Parameter
|
|
12
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
9
13
|
from pymodaq.utils.parameter import ioxml
|
|
10
|
-
|
|
11
|
-
from pymodaq.utils.daq_utils import ThreadCommand, getLineInfo
|
|
12
|
-
from pymodaq.utils
|
|
14
|
+
|
|
15
|
+
from pymodaq.utils.daq_utils import ThreadCommand, getLineInfo, find_keys_from_val
|
|
16
|
+
from pymodaq.utils import config as configmod
|
|
13
17
|
from pymodaq.utils.tcp_server_client import TCPServer, tcp_parameters
|
|
14
18
|
from pymodaq.utils.messenger import deprecation_msg
|
|
15
|
-
|
|
16
|
-
from time import perf_counter
|
|
19
|
+
|
|
17
20
|
|
|
18
21
|
logger = set_logger(get_module_name(__file__))
|
|
19
|
-
config = Config()
|
|
22
|
+
config = configmod.Config()
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
def comon_parameters(epsilon=config('actuator', 'epsilon_default')):
|
|
@@ -94,6 +97,7 @@ params = [
|
|
|
94
97
|
{'title': 'Main Settings:', 'name': 'main_settings', 'type': 'group', 'children': [
|
|
95
98
|
{'title': 'Actuator type:', 'name': 'move_type', 'type': 'str', 'value': '', 'readonly': True},
|
|
96
99
|
{'title': 'Actuator name:', 'name': 'module_name', 'type': 'str', 'value': '', 'readonly': True},
|
|
100
|
+
{'title': 'Plugin Config:', 'name': 'plugin_config', 'type': 'bool_push', 'label': 'Show Config', },
|
|
97
101
|
{'title': 'Controller ID:', 'name': 'controller_ID', 'type': 'int', 'value': 0, 'default': 0},
|
|
98
102
|
{'title': 'Refresh value (ms):', 'name': 'refresh_timeout', 'type': 'int',
|
|
99
103
|
'value': config('actuator', 'refresh_timeout_ms')},
|
|
@@ -138,45 +142,43 @@ def main(plugin_file, init=True, title='test'):
|
|
|
138
142
|
|
|
139
143
|
|
|
140
144
|
class DAQ_Move_base(QObject):
|
|
141
|
-
""" The base class to be
|
|
145
|
+
""" The base class to be inherited by all actuator modules
|
|
142
146
|
|
|
143
147
|
This base class implements all necessary parameters and methods for the plugin to communicate with its parent (the
|
|
144
148
|
DAQ_Move module)
|
|
145
149
|
|
|
146
150
|
Parameters
|
|
147
151
|
----------
|
|
148
|
-
parent :
|
|
149
|
-
params_state : Parameter
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
152
|
+
parent : DAQ_Move_Hardware
|
|
153
|
+
params_state : Parameter
|
|
154
|
+
pyqtgraph Parameter instance from which the module will get the initial settings (as defined in the preset)
|
|
155
|
+
Attributes
|
|
156
|
+
----------
|
|
157
|
+
move_done_signal: Signal
|
|
158
|
+
signal represented by a float. Is emitted each time the hardware reached the target position within the epsilon
|
|
159
|
+
precision (see comon_parameters variable)
|
|
160
|
+
controller: object
|
|
161
|
+
the object representing the hardware in the plugin. Used to access hardware functionality
|
|
162
|
+
settings: Parameter
|
|
163
|
+
instance representing the hardware settings defined from the params attribute. Modifications on the GUI settings
|
|
164
|
+
will be transferred to this attribute. It stores at all times the current state of the hardware/plugin settings
|
|
165
|
+
params: List of dict used to create a Parameter object.
|
|
166
|
+
Its definition on the class level enable the automatic update of the GUI settings when changing plugins
|
|
167
|
+
(even in managers mode creation). To be populated on the plugin level as the base class does't represents a
|
|
168
|
+
real hardware
|
|
169
|
+
is_multiaxes: bool
|
|
170
|
+
class level attribute. Defines if the plugin controller controls multiple axes. If True, one has to define
|
|
171
|
+
a Master instance of this plugin and slave instances of this plugin (all sharing the same controller_ID
|
|
172
|
+
parameter)
|
|
173
|
+
current_value: float
|
|
174
|
+
stores the current position after each call to the get_actuator_value in the plugin
|
|
175
|
+
target_value: float
|
|
176
|
+
stores the target position the controller should reach within epsilon
|
|
174
177
|
"""
|
|
175
178
|
|
|
176
179
|
move_done_signal = Signal(float)
|
|
177
180
|
is_multiaxes = False
|
|
178
181
|
stage_names = []
|
|
179
|
-
axes_name = []
|
|
180
182
|
params = []
|
|
181
183
|
_controller_units = ''
|
|
182
184
|
_epsilon = 1
|
|
@@ -210,7 +212,40 @@ class DAQ_Move_base(QObject):
|
|
|
210
212
|
|
|
211
213
|
self.ini_attributes()
|
|
212
214
|
|
|
215
|
+
@property
|
|
216
|
+
def axis_name(self) -> str:
|
|
217
|
+
"""Get/Set the current axis using its string identifier"""
|
|
218
|
+
limits = self.settings.child('multiaxes', 'axis').opts['limits']
|
|
219
|
+
if isinstance(limits, list):
|
|
220
|
+
return self.settings.child('multiaxes', 'axis').value()
|
|
221
|
+
elif isinstance(limits, dict):
|
|
222
|
+
return find_keys_from_val(limits, val=self.settings.child('multiaxes', 'axis').value())[0]
|
|
223
|
+
|
|
224
|
+
@axis_name.setter
|
|
225
|
+
def axis_name(self, name: str):
|
|
226
|
+
limits = self.settings.child('multiaxes', 'axis').opts['limits']
|
|
227
|
+
if name in limits:
|
|
228
|
+
if isinstance(limits, list):
|
|
229
|
+
self.settings.child('multiaxes', 'axis').setValue(name)
|
|
230
|
+
elif isinstance(limits, dict):
|
|
231
|
+
self.settings.child('multiaxes', 'axis').setValue(limits[name])
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def axis_names(self) -> Union[List, Dict]:
|
|
235
|
+
""" Get/Set the names of all axes controlled by this instrument plugin
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
List of string or dictionary mapping names to integers
|
|
240
|
+
"""
|
|
241
|
+
return self.settings.child('multiaxes', 'axis').opts['limits']
|
|
242
|
+
|
|
243
|
+
@axis_names.setter
|
|
244
|
+
def axis_names(self, names: Union[List, Dict]):
|
|
245
|
+
self.settings.child('multiaxes', 'axis').opts['limits'] = names
|
|
246
|
+
|
|
213
247
|
def ini_attributes(self):
|
|
248
|
+
""" To be subclassed, in order to init specific attributes needed by the real implementation"""
|
|
214
249
|
self.controller = None
|
|
215
250
|
|
|
216
251
|
def ini_stage_init(self, old_controller=None, new_controller=None):
|
|
@@ -262,6 +297,7 @@ class DAQ_Move_base(QObject):
|
|
|
262
297
|
|
|
263
298
|
@property
|
|
264
299
|
def controller_units(self):
|
|
300
|
+
""" Get/Set the units of this plugin"""
|
|
265
301
|
return self._controller_units
|
|
266
302
|
|
|
267
303
|
@controller_units.setter
|
|
@@ -274,22 +310,17 @@ class DAQ_Move_base(QObject):
|
|
|
274
310
|
|
|
275
311
|
@property
|
|
276
312
|
def ispolling(self):
|
|
313
|
+
""" Get/Set the polling status"""
|
|
277
314
|
return self._ispolling
|
|
278
315
|
|
|
279
316
|
@ispolling.setter
|
|
280
317
|
def ispolling(self, polling=True):
|
|
281
318
|
self._ispolling = polling
|
|
282
319
|
|
|
283
|
-
def check_bound(self, position):
|
|
284
|
-
"""
|
|
285
|
-
|
|
286
|
-
Parameters
|
|
287
|
-
----------
|
|
288
|
-
position
|
|
289
|
-
|
|
290
|
-
Returns
|
|
291
|
-
-------
|
|
320
|
+
def check_bound(self, position: float) -> float:
|
|
321
|
+
""" Check if the current position is within the software bounds
|
|
292
322
|
|
|
323
|
+
Return the new position eventually coerced within the bounds
|
|
293
324
|
"""
|
|
294
325
|
if self.settings.child('bounds', 'is_bounds').value():
|
|
295
326
|
if position > self.settings.child('bounds', 'max_bound').value():
|
|
@@ -329,19 +360,7 @@ class DAQ_Move_base(QObject):
|
|
|
329
360
|
raise NotImplementedError
|
|
330
361
|
|
|
331
362
|
def emit_status(self, status: ThreadCommand):
|
|
332
|
-
"""
|
|
333
|
-
| Emit the statut signal from the given status parameter.
|
|
334
|
-
|
|
|
335
|
-
| The signal is sended to the gui to update the user interface.
|
|
336
|
-
|
|
337
|
-
=============== ===================== ========================================================================================================================================
|
|
338
|
-
**Parameters** **Type** **Description**
|
|
339
|
-
*status* ordered dictionnary dictionnary containing keys:
|
|
340
|
-
* *info* : string displaying various info
|
|
341
|
-
* *controller*: instance of the controller object in order to control other axes without the need to init the same controller twice
|
|
342
|
-
* *stage*: instance of the stage (axis or whatever) object
|
|
343
|
-
* *initialized*: boolean indicating if initialization has been done corretly
|
|
344
|
-
=============== ===================== ========================================================================================================================================
|
|
363
|
+
""" Emit the status_sig signal with the given status ThreadCommand back to the main GUI.
|
|
345
364
|
"""
|
|
346
365
|
if self.parent is not None:
|
|
347
366
|
self.parent.status_sig.emit(status)
|
|
@@ -349,37 +368,19 @@ class DAQ_Move_base(QObject):
|
|
|
349
368
|
else:
|
|
350
369
|
print(status)
|
|
351
370
|
|
|
352
|
-
def emit_value(self, pos):
|
|
371
|
+
def emit_value(self, pos: float):
|
|
372
|
+
"""Convenience method to emit the current actuator value back to the UI"""
|
|
373
|
+
|
|
353
374
|
self.emit_status(ThreadCommand('get_actuator_value', [pos]))
|
|
354
375
|
|
|
355
|
-
def commit_settings(self, param):
|
|
376
|
+
def commit_settings(self, param: Parameter):
|
|
356
377
|
"""
|
|
357
378
|
to subclass to transfer parameters to hardware
|
|
358
379
|
"""
|
|
359
|
-
pass
|
|
360
380
|
|
|
361
381
|
def commit_common_settings(self, param):
|
|
362
382
|
pass
|
|
363
383
|
|
|
364
|
-
def get_position_with_scaling(self, pos):
|
|
365
|
-
"""
|
|
366
|
-
Get the current position from the hardware with scaling conversion.
|
|
367
|
-
|
|
368
|
-
=============== ========= =====================
|
|
369
|
-
**Parameters** **Type** **Description**
|
|
370
|
-
*pos* float the current position
|
|
371
|
-
=============== ========= =====================
|
|
372
|
-
|
|
373
|
-
Returns
|
|
374
|
-
=======
|
|
375
|
-
float
|
|
376
|
-
the computed position.
|
|
377
|
-
"""
|
|
378
|
-
if self.settings.child('scaling', 'use_scaling').value():
|
|
379
|
-
pos = (pos - self.settings.child('scaling', 'offset').value()) * self.settings.child('scaling',
|
|
380
|
-
'scaling').value()
|
|
381
|
-
return pos
|
|
382
|
-
|
|
383
384
|
def move_done(self, position=None): # the position argument is just there to match some signature of child classes
|
|
384
385
|
"""
|
|
385
386
|
| Emit a move done signal transmitting the float position to hardware.
|
|
@@ -397,12 +398,11 @@ class DAQ_Move_base(QObject):
|
|
|
397
398
|
self.move_is_done = True
|
|
398
399
|
|
|
399
400
|
def poll_moving(self):
|
|
400
|
-
"""
|
|
401
|
-
Poll the current moving. In case of timeout emit the raise timeout Thread command.
|
|
401
|
+
""" Poll the current moving. In case of timeout emit the raise timeout Thread command.
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
403
|
+
See Also
|
|
404
|
+
--------
|
|
405
|
+
DAQ_utils.ThreadCommand, move_done
|
|
406
406
|
"""
|
|
407
407
|
if 'TCPServer' not in self.__class__.__name__:
|
|
408
408
|
self.start_time = perf_counter()
|
|
@@ -437,19 +437,9 @@ class DAQ_Move_base(QObject):
|
|
|
437
437
|
self.move_done(self.current_value)
|
|
438
438
|
|
|
439
439
|
def send_param_status(self, param, changes):
|
|
440
|
-
"""
|
|
441
|
-
| Send changes value updates to the gui to update consequently the User Interface.
|
|
442
|
-
| The message passing is made via the Thread Command "update_settings".
|
|
440
|
+
""" Send changes value updates to the gui to update consequently the User Interface
|
|
443
441
|
|
|
444
|
-
|
|
445
|
-
**Parameters** **Type** **Description**
|
|
446
|
-
*param* instance of pyqtgraph parameter The parameter to be checked
|
|
447
|
-
*changes* (parameter,change,infos)tuple list The (parameter,change,infos) list to be treated
|
|
448
|
-
=============== =================================== ==================================================
|
|
449
|
-
|
|
450
|
-
See Also
|
|
451
|
-
========
|
|
452
|
-
DAQ_utils.ThreadCommand
|
|
442
|
+
The message passing is made via the ThreadCommand "update_settings".
|
|
453
443
|
"""
|
|
454
444
|
|
|
455
445
|
for param, change, data in changes:
|
|
@@ -464,28 +454,24 @@ class DAQ_Move_base(QObject):
|
|
|
464
454
|
elif change == 'parent':
|
|
465
455
|
pass
|
|
466
456
|
|
|
467
|
-
def
|
|
457
|
+
def get_position_with_scaling(self, pos: float):
|
|
458
|
+
""" Get the current position from the hardware with scaling conversion.
|
|
468
459
|
"""
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
*pos* float the position to be setted
|
|
474
|
-
=============== ========= ==========================
|
|
460
|
+
if self.settings.child('scaling', 'use_scaling').value():
|
|
461
|
+
pos = (pos - self.settings.child('scaling', 'offset').value()) * self.settings.child('scaling',
|
|
462
|
+
'scaling').value()
|
|
463
|
+
return pos
|
|
475
464
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
float
|
|
479
|
-
the computed position.
|
|
465
|
+
def set_position_with_scaling(self, pos: float):
|
|
466
|
+
""" Set the current position from the parameter and hardware with scaling conversion.
|
|
480
467
|
"""
|
|
481
468
|
if self.settings.child('scaling', 'use_scaling').value():
|
|
482
469
|
pos = pos / self.settings.child('scaling', 'scaling').value() + self.settings.child('scaling',
|
|
483
470
|
'offset').value()
|
|
484
471
|
return pos
|
|
485
472
|
|
|
486
|
-
def set_position_relative_with_scaling(self, pos):
|
|
487
|
-
"""
|
|
488
|
-
Set the scaled positions in case of relative moves
|
|
473
|
+
def set_position_relative_with_scaling(self, pos: float):
|
|
474
|
+
""" Set the scaled positions in case of relative moves
|
|
489
475
|
"""
|
|
490
476
|
if self.settings.child('scaling', 'use_scaling').value():
|
|
491
477
|
pos = pos / self.settings.child('scaling', 'scaling').value()
|
|
@@ -493,17 +479,8 @@ class DAQ_Move_base(QObject):
|
|
|
493
479
|
|
|
494
480
|
@Slot(edict)
|
|
495
481
|
def update_settings(self, settings_parameter_dict): # settings_parameter_dict=edict(path=path,param=param)
|
|
496
|
-
"""
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
========================== =========== ==========================================================================================================
|
|
500
|
-
**Arguments** **Type** **Description**
|
|
501
|
-
*settings_parameter_dict* dictionnary Dictionnary with the path of the parameter in hardware structure as key and the parameter name as element
|
|
502
|
-
========================== =========== ==========================================================================================================
|
|
503
|
-
|
|
504
|
-
See Also
|
|
505
|
-
--------
|
|
506
|
-
send_param_status, commit_settings
|
|
482
|
+
""" Receive the settings_parameter signal from the param_tree_changed method and make hardware updates of
|
|
483
|
+
modified values.
|
|
507
484
|
"""
|
|
508
485
|
path = settings_parameter_dict['path']
|
|
509
486
|
param = settings_parameter_dict['param']
|
|
@@ -564,9 +541,9 @@ class DAQ_Move_TCP_server(DAQ_Move_base, TCPServer):
|
|
|
564
541
|
"""
|
|
565
542
|
self.client_type = "ACTUATOR"
|
|
566
543
|
DAQ_Move_base.__init__(self, parent, params_state) # initialize base class with commom attribute and methods
|
|
567
|
-
self.settings.child(
|
|
568
|
-
self.settings.child(
|
|
569
|
-
self.settings.child(
|
|
544
|
+
self.settings.child('bounds').hide()
|
|
545
|
+
self.settings.child('scaling').hide()
|
|
546
|
+
self.settings.child('epsilon').setValue(1)
|
|
570
547
|
|
|
571
548
|
TCPServer.__init__(self, self.client_type)
|
|
572
549
|
|
pymodaq/control_modules/utils.py
CHANGED
|
@@ -15,6 +15,7 @@ from pymodaq.utils.parameter import Parameter
|
|
|
15
15
|
from pymodaq.utils.enums import BaseEnum, enum_checker
|
|
16
16
|
from pymodaq.utils.plotting.data_viewers.viewer import ViewersEnum
|
|
17
17
|
from pymodaq.utils.exceptions import DetectorError
|
|
18
|
+
from pymodaq.utils import config as configmod
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class DAQTypesEnum(BaseEnum):
|
|
@@ -114,6 +115,7 @@ class ControlModule(QObject):
|
|
|
114
115
|
self._tcpclient_thread = None
|
|
115
116
|
self._hardware_thread = None
|
|
116
117
|
self.module_and_data_saver = None
|
|
118
|
+
self.plugin_config: configmod.Config = None
|
|
117
119
|
|
|
118
120
|
def __repr__(self):
|
|
119
121
|
return f'{self.__class__.__name__}: {self.title}'
|
|
@@ -135,6 +137,7 @@ class ControlModule(QObject):
|
|
|
135
137
|
* raise_timeout:
|
|
136
138
|
* show_splash: Display the splash screen with attribute as message
|
|
137
139
|
* close_splash
|
|
140
|
+
* show_config: display the plugin configuration
|
|
138
141
|
"""
|
|
139
142
|
|
|
140
143
|
if status.command == "Update_Status":
|
|
@@ -284,6 +287,12 @@ class ControlModule(QObject):
|
|
|
284
287
|
import webbrowser
|
|
285
288
|
webbrowser.open(self.logger.parent.handlers[0].baseFilename)
|
|
286
289
|
|
|
290
|
+
def show_config(self, config: Config):
|
|
291
|
+
""" Display in a tree the current configuration"""
|
|
292
|
+
if config is not None:
|
|
293
|
+
config_tree = configmod.TreeFromToml(config)
|
|
294
|
+
config_tree.show_dialog()
|
|
295
|
+
|
|
287
296
|
def update_status(self, txt, log=True):
|
|
288
297
|
"""Display a message in the ui status bar and eventually log the message
|
|
289
298
|
|
|
@@ -36,6 +36,7 @@ params = [
|
|
|
36
36
|
'readonly': True},
|
|
37
37
|
{'title': 'Detector type:', 'name': 'detector_type', 'type': 'str', 'value': '', 'readonly': True},
|
|
38
38
|
{'title': 'Detector Name:', 'name': 'module_name', 'type': 'str', 'value': '', 'readonly': True},
|
|
39
|
+
{'title': 'Plugin Config:', 'name': 'plugin_config', 'type': 'bool_push', 'label': 'Show Config', },
|
|
39
40
|
{'title': 'Controller ID:', 'name': 'controller_ID', 'type': 'int', 'value': 0, 'default': 0, 'readonly': False},
|
|
40
41
|
{'title': 'Show data and process:', 'name': 'show_data', 'type': 'bool', 'value': True, },
|
|
41
42
|
{'title': 'Refresh time (ms):', 'name': 'refresh_time', 'type': 'float', 'value': 50., 'min': 0.},
|
pymodaq/dashboard.py
CHANGED
|
@@ -213,18 +213,33 @@ class DashBoard(QObject):
|
|
|
213
213
|
|
|
214
214
|
return qtconsole
|
|
215
215
|
|
|
216
|
-
def load_extensions_module(self, ext):
|
|
216
|
+
def load_extensions_module(self, ext: dict):
|
|
217
|
+
""" Init and load an extension from a plugin package
|
|
218
|
+
|
|
219
|
+
ext: dict
|
|
220
|
+
dictionary containing info on the extension plugin package and class to be loaded, it contains four
|
|
221
|
+
keys:
|
|
222
|
+
|
|
223
|
+
* pkg: the name of the plugin package
|
|
224
|
+
* module: the module name where your extension class is defined
|
|
225
|
+
* class_name: the name of the class defining the extension
|
|
226
|
+
* name: a nice name for your extension to be displayed in the menu
|
|
227
|
+
|
|
228
|
+
See Also
|
|
229
|
+
--------
|
|
230
|
+
pymodaq.extensions.utils.get_extensions
|
|
231
|
+
"""
|
|
232
|
+
|
|
217
233
|
self.extension_windows.append(QtWidgets.QMainWindow())
|
|
218
234
|
area = DockArea()
|
|
219
235
|
self.extension_windows[-1].setCentralWidget(area)
|
|
220
236
|
self.extension_windows[-1].resize(1000, 500)
|
|
221
237
|
self.extension_windows[-1].setWindowTitle(ext['name'])
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
self.extensions[pkg.klass_name] = klass(dockarea=area, dashboard=self)
|
|
238
|
+
module = import_module(f"{ext['pkg']}.extensions.{ext['module']}")
|
|
239
|
+
klass = getattr(module, ext['class_name'])
|
|
240
|
+
self.extensions[ext['class_name']] = klass(dockarea=area, dashboard=self)
|
|
226
241
|
self.extension_windows[-1].show()
|
|
227
|
-
return self.extensions[
|
|
242
|
+
return self.extensions[ext['class_name']]
|
|
228
243
|
|
|
229
244
|
def create_menu(self, menubar):
|
|
230
245
|
"""
|
|
@@ -604,7 +619,7 @@ class DashBoard(QObject):
|
|
|
604
619
|
self.logger_dock.area.addDock(det_docks_settings[-1], 'bottom') # dockarea of the logger dock
|
|
605
620
|
else:
|
|
606
621
|
self.dockarea.addDock(det_docks_settings[-1], 'right',
|
|
607
|
-
detector_modules[-1].
|
|
622
|
+
detector_modules[-1].viewer_docks[-1])
|
|
608
623
|
self.dockarea.addDock(det_docks_viewer[-1], 'right', det_docks_settings[-1])
|
|
609
624
|
det_mod_tmp = DAQ_Viewer(self.dockarea, title=plug_name, daq_type=plug_type,
|
|
610
625
|
dock_settings=det_docks_settings[-1],
|
|
@@ -1269,9 +1284,9 @@ class DashBoard(QObject):
|
|
|
1269
1284
|
def check_version(self, show=True):
|
|
1270
1285
|
try:
|
|
1271
1286
|
current_version = version_mod.parse(get_version())
|
|
1272
|
-
available_version =
|
|
1287
|
+
available_version = version_mod.parse(get_pypi_pymodaq('pymodaq')['version'])
|
|
1273
1288
|
msgBox = QtWidgets.QMessageBox()
|
|
1274
|
-
if
|
|
1289
|
+
if available_version > current_version:
|
|
1275
1290
|
msgBox.setText(f"A new version of PyMoDAQ is available, {str(max(available_version))}!")
|
|
1276
1291
|
msgBox.setInformativeText("Do you want to install it?")
|
|
1277
1292
|
msgBox.setStandardButtons(msgBox.Ok | msgBox.Cancel)
|
pymodaq/examples/custom_app.py
CHANGED
|
@@ -16,7 +16,11 @@ from pymodaq.utils.parameter import ioxml
|
|
|
16
16
|
from pymodaq.control_modules.daq_viewer import DAQ_Viewer
|
|
17
17
|
from pymodaq.utils.plotting.data_viewers.viewer0D import Viewer0D
|
|
18
18
|
|
|
19
|
-
from pymodaq.utils.h5modules import H5Browser
|
|
19
|
+
from pymodaq.utils.h5modules.browsing import H5Browser
|
|
20
|
+
from pymodaq.utils.h5modules.saving import H5Saver
|
|
21
|
+
from pymodaq.utils.h5modules.data_saving import DataToExportSaver
|
|
22
|
+
from pymodaq.utils.data import DataToExport
|
|
23
|
+
|
|
20
24
|
|
|
21
25
|
config = Config()
|
|
22
26
|
logger = set_logger(get_module_name(__file__))
|
|
@@ -51,7 +55,7 @@ class CustomAppExample(CustomApp):
|
|
|
51
55
|
super().__init__(dockarea)
|
|
52
56
|
|
|
53
57
|
# init the object parameters
|
|
54
|
-
self.raw_data =
|
|
58
|
+
self.raw_data: DataToExport = None
|
|
55
59
|
self.setup_ui()
|
|
56
60
|
|
|
57
61
|
def setup_actions(self):
|
|
@@ -98,11 +102,12 @@ class CustomAppExample(CustomApp):
|
|
|
98
102
|
# init one daq_viewer object named detector
|
|
99
103
|
|
|
100
104
|
self.detector = DAQ_Viewer(self.dockarea, dock_settings=self.dock_detector_settings,
|
|
101
|
-
dock_viewer=self.dock_detector, title="A detector"
|
|
105
|
+
dock_viewer=self.dock_detector, title="A detector")
|
|
102
106
|
# set its type to 'Mock'
|
|
103
|
-
self.detector.daq_type = '
|
|
107
|
+
self.detector.daq_type = 'DAQ0D'
|
|
108
|
+
self.detector.detector = 'Mock'
|
|
104
109
|
# init the detector and wait 1000ms for the completion
|
|
105
|
-
self.detector.
|
|
110
|
+
self.detector.init_hardware()
|
|
106
111
|
self.detector.settings.child('main_settings', 'wait_time').setValue(100)
|
|
107
112
|
QtWidgets.QApplication.processEvents()
|
|
108
113
|
QThread.msleep(1000)
|
|
@@ -159,30 +164,21 @@ class CustomAppExample(CustomApp):
|
|
|
159
164
|
|
|
160
165
|
logger.debug(f'Value change applied')
|
|
161
166
|
|
|
162
|
-
@Slot(OrderedDict)
|
|
163
167
|
def data_done(self, data):
|
|
164
168
|
# print(data)
|
|
165
169
|
pass
|
|
166
170
|
|
|
167
|
-
|
|
168
|
-
def show_data(self, data):
|
|
171
|
+
def show_data(self, data: DataToExport):
|
|
169
172
|
"""
|
|
170
173
|
do stuff with data from the detector if its grab_done_signal has been connected
|
|
171
174
|
Parameters
|
|
172
175
|
----------
|
|
173
|
-
data:
|
|
176
|
+
data: DataToExport
|
|
174
177
|
"""
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
self.raw_data = data0D
|
|
178
|
-
else:
|
|
179
|
-
if len(self.raw_data) != len(data0D):
|
|
180
|
-
self.raw_data = data0D
|
|
181
|
-
else:
|
|
182
|
-
for ind in range(len(data0D)):
|
|
183
|
-
self.raw_data[ind].append(data0D[ind][0])
|
|
178
|
+
self.raw_data = data
|
|
179
|
+
data0D = data.get_data_from_dim('Data0D')
|
|
184
180
|
|
|
185
|
-
self.target_viewer.show_data(data0D)
|
|
181
|
+
self.target_viewer.show_data(data0D.data[0])
|
|
186
182
|
|
|
187
183
|
def load_file(self):
|
|
188
184
|
# init the data browser module
|
|
@@ -207,6 +203,8 @@ class CustomAppExample(CustomApp):
|
|
|
207
203
|
# init the file object with an addhoc name given by the user
|
|
208
204
|
h5saver = H5Saver(save_type='custom')
|
|
209
205
|
h5saver.init_file(update_h5=True, addhoc_file_path=path)
|
|
206
|
+
datasaver = DataToExportSaver(h5saver)
|
|
207
|
+
|
|
210
208
|
|
|
211
209
|
# save all metadata
|
|
212
210
|
settings_str = ioxml.parameter_to_xml_string(self.settings)
|
|
@@ -214,22 +212,14 @@ class CustomAppExample(CustomApp):
|
|
|
214
212
|
settings_str += ioxml.parameter_to_xml_string(self.detector.settings) + ioxml.parameter_to_xml_string(
|
|
215
213
|
h5saver.settings) + b'</All_settings>'
|
|
216
214
|
|
|
217
|
-
|
|
218
|
-
title='data from custom app',
|
|
219
|
-
settings_as_xml=settings_str)
|
|
215
|
+
datasaver.add_data(h5saver.root(), self.raw_data, settings_as_xml=settings_str)
|
|
220
216
|
|
|
221
|
-
|
|
222
|
-
channel = h5saver.add_CH_group(data_group)
|
|
223
|
-
data_dict = dict(data=np.array(dat),
|
|
224
|
-
x_axis=dict(data=np.linspace(0, len(dat) - 1, len(dat)), units='pxl'))
|
|
225
|
-
h5saver.add_data(channel, data_dict=data_dict, scan_type='')
|
|
217
|
+
h5saver.close_file()
|
|
226
218
|
|
|
227
219
|
st = 'file {:s} has been saved'.format(str(path))
|
|
228
220
|
self.add_log(st)
|
|
229
221
|
self.settings.child('main_settings', 'info').setValue(st)
|
|
230
222
|
|
|
231
|
-
h5saver.close_file()
|
|
232
|
-
|
|
233
223
|
except Exception as e:
|
|
234
224
|
logger.exception(str(e))
|
|
235
225
|
|
|
@@ -5,7 +5,7 @@ from pymodaq.utils import gui_utils as gutils
|
|
|
5
5
|
from pyqtgraph.dockarea import Dock
|
|
6
6
|
from pyqtgraph.parametertree import ParameterTree, Parameter
|
|
7
7
|
from pymodaq.utils.parameter.pymodaq_ptypes.tableview import TableViewCustom
|
|
8
|
-
from pymodaq.utils.scanner import TableModelTabular
|
|
8
|
+
from pymodaq.utils.scanner.scanners.tabular import TableModelTabular
|
|
9
9
|
from qtpy.QtCore import QObject, Qt, Slot
|
|
10
10
|
from qtpy import QtWidgets
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ class ViewerPointList(QObject):
|
|
|
14
14
|
def __init__(self, area):
|
|
15
15
|
super().__init__()
|
|
16
16
|
self.area = area
|
|
17
|
-
self.viewer = None
|
|
17
|
+
self.viewer: Viewer2D = None
|
|
18
18
|
|
|
19
19
|
self.set_viewer()
|
|
20
20
|
self.set_point_list()
|
|
@@ -22,13 +22,13 @@ class ViewerPointList(QObject):
|
|
|
22
22
|
|
|
23
23
|
@Slot(float, float)
|
|
24
24
|
def double_click_action(self, posx, posy):
|
|
25
|
-
xs, ys = self.viewer.
|
|
26
|
-
data_at = self.viewer.get_data_at('red', (
|
|
25
|
+
xs, ys = self.viewer.view.unscale_axis(posx, posy)
|
|
26
|
+
data_at = self.viewer.view.get_data_at('red', (xs, ys))
|
|
27
27
|
if data_at is not None:
|
|
28
|
-
self.table_model.add_data(self.table_view.currentIndex().row() + 1, [
|
|
28
|
+
self.table_model.add_data(self.table_view.currentIndex().row() + 1, [posx, posy, data_at])
|
|
29
29
|
|
|
30
|
-
def
|
|
31
|
-
self.viewer.
|
|
30
|
+
def show_data(self, data):
|
|
31
|
+
self.viewer.show_data(data)
|
|
32
32
|
|
|
33
33
|
def setXaxis(self, xaxis):
|
|
34
34
|
self.viewer.x_axis = xaxis
|
|
@@ -58,7 +58,7 @@ class ViewerPointList(QObject):
|
|
|
58
58
|
self.table_view = get_widget_from_tree(self.settings_tree, TableViewCustom)[0]
|
|
59
59
|
self.settings.child(('tabular_table')).setValue(self.table_model)
|
|
60
60
|
|
|
61
|
-
self.table_view.horizontalHeader().
|
|
61
|
+
self.table_view.horizontalHeader().ResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
|
62
62
|
self.table_view.horizontalHeader().setStretchLastSection(True)
|
|
63
63
|
self.table_view.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
|
|
64
64
|
self.table_view.setSelectionMode(QtWidgets.QTableView.SingleSelection)
|
|
@@ -82,7 +82,7 @@ class ViewerPointList(QObject):
|
|
|
82
82
|
|
|
83
83
|
if __name__ == '__main__':
|
|
84
84
|
from pymodaq.utils.gui_utils import DockArea
|
|
85
|
-
from pymodaq.utils.data import Axis
|
|
85
|
+
from pymodaq.utils.data import Axis, DataFromPlugins
|
|
86
86
|
import sys
|
|
87
87
|
import numpy as np
|
|
88
88
|
|
|
@@ -100,8 +100,11 @@ if __name__ == '__main__':
|
|
|
100
100
|
|
|
101
101
|
data_red = 3 * gauss2D(x, np.mean(x), (np.max(x)-np.min(x)) / 5, y, np.mean(y), (np.max(y)-np.min(y)) / 5, 1)
|
|
102
102
|
data_red += np.random.random(data_red.shape)
|
|
103
|
+
data_to_plot = DataFromPlugins(name='mydata', distribution='uniform', data=[data_red],
|
|
104
|
+
axes=[Axis('xaxis', units='xpxl', data=x, index=1),
|
|
105
|
+
Axis('yaxis', units='ypxl', data=y, index=0), ])
|
|
103
106
|
|
|
104
|
-
viewer.
|
|
107
|
+
viewer.show_data(data_to_plot)
|
|
105
108
|
viewer.setXaxis(Axis(data=x, label='This is x axis', units='au'))
|
|
106
109
|
viewer.setYaxis(Axis(data=y, label='This is y axis', units='au'))
|
|
107
110
|
win.show()
|
pymodaq/extensions/utils.py
CHANGED
|
@@ -5,18 +5,35 @@ Created the 27/10/2022
|
|
|
5
5
|
@author: Sebastien Weber
|
|
6
6
|
"""
|
|
7
7
|
import importlib
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import pkgutil
|
|
10
|
+
|
|
8
11
|
from pymodaq.utils import logger as logger_module
|
|
9
12
|
from pymodaq.utils.daq_utils import get_entrypoints
|
|
10
13
|
logger = logger_module.set_logger(logger_module.get_module_name(__file__))
|
|
11
14
|
|
|
12
15
|
|
|
16
|
+
def get_ext_modules(path: Path):
|
|
17
|
+
modules = []
|
|
18
|
+
for mod in pkgutil.iter_modules([path]):
|
|
19
|
+
modules.append(mod.name)
|
|
20
|
+
return modules
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
def get_extensions():
|
|
14
24
|
"""
|
|
15
25
|
Get pymodaq extensions as a list
|
|
16
26
|
|
|
17
27
|
Returns
|
|
18
28
|
-------
|
|
19
|
-
list: list of dict
|
|
29
|
+
list: list of dict containing the name and module of the found extension
|
|
30
|
+
|
|
31
|
+
Each dict is defined with four keys:
|
|
32
|
+
* pkg: the name of the plugin package
|
|
33
|
+
* module: the module name where your extension class is defined
|
|
34
|
+
* class_name: the name of the class defining the extension
|
|
35
|
+
* name: a nice name for your extension to be displayed in the menu
|
|
36
|
+
|
|
20
37
|
"""
|
|
21
38
|
extension_import = []
|
|
22
39
|
discovered_extension = get_entrypoints(group='pymodaq.extensions')
|
|
@@ -24,14 +41,13 @@ def get_extensions():
|
|
|
24
41
|
for pkg in discovered_extension:
|
|
25
42
|
try:
|
|
26
43
|
module = importlib.import_module(pkg.value)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
extension_import.append(extension)
|
|
44
|
+
modules = get_ext_modules(Path(module.__path__[0]).joinpath('extensions'))
|
|
45
|
+
for mod in modules:
|
|
46
|
+
mod_in = importlib.import_module(f'{pkg.value}.extensions.{mod}')
|
|
47
|
+
extension_import.append({'pkg': pkg.value, 'module': mod, 'name': mod_in.EXTENSION_NAME,
|
|
48
|
+
'class_name': mod_in.CLASS_NAME})
|
|
33
49
|
|
|
34
50
|
except Exception as e: # pragma: no cover
|
|
35
|
-
logger.warning(f'Impossible to import the {pkg.value} extension: {str(e)}')
|
|
51
|
+
logger.warning(f'Impossible to import the {pkg.value}.extensions.{mod} extension: {str(e)}')
|
|
36
52
|
|
|
37
53
|
return extension_import
|
pymodaq/resources/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = '4.0.
|
|
1
|
+
version = '4.0.7'
|
pymodaq/utils/config.py
CHANGED
|
@@ -4,13 +4,14 @@ from os import environ
|
|
|
4
4
|
import sys
|
|
5
5
|
import datetime
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Union
|
|
7
|
+
from typing import Union, Dict, TypeVar, Any
|
|
8
8
|
|
|
9
9
|
import toml
|
|
10
10
|
from qtpy.QtCore import QObject
|
|
11
11
|
from pyqtgraph.parametertree import Parameter, ParameterTree
|
|
12
12
|
from qtpy import QtWidgets, QtCore
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
try:
|
|
15
16
|
USER = environ['USERNAME'] if sys.platform == 'win32' else environ['USER']
|
|
16
17
|
except:
|
|
@@ -20,6 +21,23 @@ CONFIG_BASE_PATH = Path(environ['PROGRAMDATA']) if sys.platform == 'win32' else
|
|
|
20
21
|
Path('Library/Application Support') if sys.platform == 'darwin' else Path('/etc')
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
KeyType = TypeVar('KeyType')
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def deep_update(mapping: Dict[KeyType, Any], *updating_mappings: Dict[KeyType, Any]) -> Dict[KeyType, Any]:
|
|
28
|
+
""" Make sure a dictionary is updated using another dict in any nested level
|
|
29
|
+
Taken from Pydantic v1
|
|
30
|
+
"""
|
|
31
|
+
updated_mapping = mapping.copy()
|
|
32
|
+
for updating_mapping in updating_mappings:
|
|
33
|
+
for k, v in updating_mapping.items():
|
|
34
|
+
if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict):
|
|
35
|
+
updated_mapping[k] = deep_update(updated_mapping[k], v)
|
|
36
|
+
else:
|
|
37
|
+
updated_mapping[k] = v
|
|
38
|
+
return updated_mapping
|
|
39
|
+
|
|
40
|
+
|
|
23
41
|
def replace_file_extension(filename: str, ext: str):
|
|
24
42
|
"""Replace the extension of a file by the specified one, without the dot"""
|
|
25
43
|
file_name = Path(filename).stem # remove eventual extensions
|
|
@@ -245,7 +263,7 @@ def load_system_config_and_update_from_user(config_file_name: str):
|
|
|
245
263
|
config_dict = toml.load(toml_base_path)
|
|
246
264
|
toml_user_path = get_config_file(config_file_name, user=True)
|
|
247
265
|
if toml_user_path.is_file():
|
|
248
|
-
config_dict
|
|
266
|
+
config_dict = deep_update(config_dict, toml.load(toml_user_path))
|
|
249
267
|
return config_dict
|
|
250
268
|
|
|
251
269
|
|
|
@@ -324,7 +342,7 @@ class BaseConfig:
|
|
|
324
342
|
|
|
325
343
|
def dict_to_add_to_user(self):
|
|
326
344
|
"""To subclass"""
|
|
327
|
-
return
|
|
345
|
+
return dict([])
|
|
328
346
|
|
|
329
347
|
@property
|
|
330
348
|
def config_path(self):
|
pymodaq/utils/daq_utils.py
CHANGED
|
@@ -8,7 +8,6 @@ import functools
|
|
|
8
8
|
import re
|
|
9
9
|
import time
|
|
10
10
|
import warnings
|
|
11
|
-
|
|
12
11
|
from packaging import version as version_mod
|
|
13
12
|
from pathlib import Path
|
|
14
13
|
import pkgutil
|
|
@@ -450,6 +449,11 @@ def elt_as_first_element_dicts(elt_list, match_word='Mock', key='name'):
|
|
|
450
449
|
return plugins
|
|
451
450
|
|
|
452
451
|
|
|
452
|
+
def find_keys_from_val(dict_tmp: dict, val: object):
|
|
453
|
+
"""Returns the keys from a dict if its value is matching val"""
|
|
454
|
+
return [k for k, v in dict_tmp.items() if v == val]
|
|
455
|
+
|
|
456
|
+
|
|
453
457
|
def find_object_if_matched_attr_name_val(obj, attr_name, attr_value):
|
|
454
458
|
"""check if an attribute key/value pair match in a given object
|
|
455
459
|
|
|
@@ -534,8 +538,6 @@ def find_dict_if_matched_key_val(dict_tmp, key, value):
|
|
|
534
538
|
return False
|
|
535
539
|
|
|
536
540
|
|
|
537
|
-
|
|
538
|
-
|
|
539
541
|
def find_dict_in_list_from_key_val(dicts, key, value, return_index=False):
|
|
540
542
|
""" lookup within a list of dicts. Look for the dict within the list which has the correct key, value pair
|
|
541
543
|
|
|
@@ -596,7 +598,7 @@ def get_plugins(plugin_type='daq_0Dviewer'): # pragma: no cover
|
|
|
596
598
|
"""
|
|
597
599
|
plugins_import = []
|
|
598
600
|
discovered_plugins = get_entrypoints(group='pymodaq.plugins')
|
|
599
|
-
logger.
|
|
601
|
+
logger.debug(f'Found {len(discovered_plugins)} installed plugins, trying to import them')
|
|
600
602
|
for module in discovered_plugins:
|
|
601
603
|
try:
|
|
602
604
|
if plugin_type == 'daq_move':
|
|
@@ -619,20 +621,20 @@ def get_plugins(plugin_type='daq_0Dviewer'): # pragma: no cover
|
|
|
619
621
|
plugins_import.append(mod)
|
|
620
622
|
except Exception as e: # pragma: no cover
|
|
621
623
|
"""If an error is generated at the import, then exclude this plugin"""
|
|
622
|
-
logger.
|
|
623
|
-
|
|
624
|
+
logger.debug(f'Impossible to import Instrument plugin {mod["name"]}'
|
|
625
|
+
f' from module: {submodule.__package__}')
|
|
624
626
|
except Exception as e: # pragma: no cover
|
|
625
|
-
logger.
|
|
627
|
+
logger.debug(str(e))
|
|
626
628
|
|
|
627
|
-
#add utility plugin for PID
|
|
629
|
+
# add utility plugin for PID
|
|
628
630
|
if plugin_type == 'daq_move':
|
|
629
631
|
try:
|
|
630
|
-
submodule = importlib.import_module('pymodaq.pid')
|
|
631
|
-
|
|
632
|
+
submodule = importlib.import_module('pymodaq.extensions.pid')
|
|
632
633
|
plugins_import.append({'name': 'PID', 'module': submodule})
|
|
633
634
|
|
|
634
|
-
except Exception
|
|
635
|
-
|
|
635
|
+
except Exception as e:
|
|
636
|
+
logger.debug(f'Impossible to import the Fake PID Instrument plugin\n'
|
|
637
|
+
f'{str(e)}')
|
|
636
638
|
|
|
637
639
|
plugins_import = elt_as_first_element_dicts(plugins_import, match_word='Mock', key='name')
|
|
638
640
|
return plugins_import
|
pymodaq/utils/parameter/ioxml.py
CHANGED
|
@@ -163,14 +163,14 @@ def dict_from_param(param):
|
|
|
163
163
|
readonly = '0'
|
|
164
164
|
opts.update(dict(readonly=readonly))
|
|
165
165
|
|
|
166
|
-
if 'limits' in param.opts:
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
# if 'limits' in param.opts:
|
|
167
|
+
# values = str(param.opts['limits'])
|
|
168
|
+
# opts.update(dict(values=values))
|
|
169
169
|
|
|
170
170
|
if 'limits' in param.opts:
|
|
171
171
|
limits = str(param.opts['limits'])
|
|
172
172
|
opts.update(dict(limits=limits))
|
|
173
|
-
opts.update(dict(values=limits))
|
|
173
|
+
# opts.update(dict(values=limits))
|
|
174
174
|
|
|
175
175
|
if 'addList' in param.opts:
|
|
176
176
|
addList = str(param.opts['addList'])
|
|
@@ -273,13 +273,13 @@ def elt_to_dict(el):
|
|
|
273
273
|
addText = str(el.get('addText'))
|
|
274
274
|
param.update(dict(addText=addText))
|
|
275
275
|
|
|
276
|
-
if 'limits' in el.attrib.keys():
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
276
|
+
# if 'limits' in el.attrib.keys():
|
|
277
|
+
# try:
|
|
278
|
+
# values = list(eval(el.get('limits'))) # make sure the evaluated values are returned as list (in case another
|
|
279
|
+
# # iterator type has been used
|
|
280
|
+
# param.update(dict(values=values))
|
|
281
|
+
# except:
|
|
282
|
+
# pass
|
|
283
283
|
|
|
284
284
|
if 'limits' in el.attrib.keys():
|
|
285
285
|
try:
|
|
@@ -531,4 +531,4 @@ def XML_string_to_pobject(xml_string):
|
|
|
531
531
|
--------
|
|
532
532
|
parameter_to_xml_string
|
|
533
533
|
"""
|
|
534
|
-
return Parameter.create(name='settings', type='group', children=
|
|
534
|
+
return Parameter.create(name='settings', type='group', children=XML_string_to_parameter(xml_string))
|
pymodaq/utils/parameter/utils.py
CHANGED
|
@@ -121,7 +121,6 @@ def get_param_dict_from_name(parent_list, name, pop=False):
|
|
|
121
121
|
return ch
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
|
|
125
124
|
if __name__ == '__main__': # pragma: no cover
|
|
126
125
|
parent = [
|
|
127
126
|
{'title': 'Spectro Settings:', 'name': 'spectro_settings', 'type': 'group', 'expanded': True,
|
|
@@ -156,9 +155,15 @@ def set_param_from_param(param_old, param_new):
|
|
|
156
155
|
|
|
157
156
|
if 'group' not in param_type: # covers 'group', custom 'groupmove'...
|
|
158
157
|
# try:
|
|
159
|
-
if 'list' in param_type: # check if the value is in the limits of the old params
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
if 'list' in param_type: # check if the value is in the limits of the old params
|
|
159
|
+
# (limits are usually set at initialization) but carefull as such paramater limits can be a list or a
|
|
160
|
+
# dict object
|
|
161
|
+
if isinstance(child_old.opts['limits'], list):
|
|
162
|
+
if child_new.value() not in child_old.opts['limits']:
|
|
163
|
+
child_old.opts['limits'].append(child_new.value())
|
|
164
|
+
elif isinstance(child_old.opts['limits'], dict):
|
|
165
|
+
if child_new.value() not in child_old.opts['limits'].values():
|
|
166
|
+
child_old.opts['limits'].update(dict(str(child_new.value()), child_new.value()))
|
|
162
167
|
|
|
163
168
|
child_old.setValue(child_new.value())
|
|
164
169
|
elif 'str' in param_type or 'browsepath' in param_type or 'text' in param_type:
|
|
@@ -3,8 +3,14 @@ import sys
|
|
|
3
3
|
from typing import List, Tuple, Union
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from scipy.spatial import QhullError # works for newer version of scipy
|
|
9
|
+
from scipy.spatial import Delaunay as Triangulation
|
|
10
|
+
except ImportError:
|
|
11
|
+
from scipy.spatial.qhull import QhullError # works for old version of scipy
|
|
12
|
+
from scipy.spatial.qhull import Delaunay as Triangulation
|
|
13
|
+
|
|
8
14
|
from qtpy import QtWidgets
|
|
9
15
|
from qtpy.QtCore import QObject, Slot, Signal, QRectF, QPointF
|
|
10
16
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
pymodaq/__init__.py,sha256=HzsUe4yEzUskSKMBL4AP1NVHcoBetXoKUP4VKEt9Kmc,3290
|
|
2
2
|
pymodaq/daq_utils.py,sha256=Wgaoj9V7cUHiy6lgFebopw47IoJbLocU5T_fg0dDx7k,8738
|
|
3
|
-
pymodaq/dashboard.py,sha256=
|
|
3
|
+
pymodaq/dashboard.py,sha256=TEQ9aZ3HIBfisDVFIvJONjrmRphj_AzPM9d7Sd4MRZo,62296
|
|
4
4
|
pymodaq/icon.ico,sha256=hOHHfNDENKphQvG1WDleSEYcHukneR2eRFJu8isIlD4,74359
|
|
5
5
|
pymodaq/splash.png,sha256=ow8IECF3tPRUMA4tf2tMu1aRiMaxx91_Y2ckVxkrmF0,53114
|
|
6
6
|
pymodaq/control_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
pymodaq/control_modules/daq_move.py,sha256=
|
|
8
|
-
pymodaq/control_modules/daq_move_ui.py,sha256=
|
|
9
|
-
pymodaq/control_modules/daq_viewer.py,sha256=
|
|
10
|
-
pymodaq/control_modules/daq_viewer_ui.py,sha256=
|
|
7
|
+
pymodaq/control_modules/daq_move.py,sha256=VpNdzSwG7TNdFeO5EbMT_ukIZiezLXI2TjPRhFxXTak,36635
|
|
8
|
+
pymodaq/control_modules/daq_move_ui.py,sha256=YE_gQFkP2W1xlUGcN2wSoPsjSzllNolq5UoRsp6cL9c,13614
|
|
9
|
+
pymodaq/control_modules/daq_viewer.py,sha256=AXjCDAJywbVSkhL4qvtB_uHYGXvb9nJZgGokWgd-1ow,57403
|
|
10
|
+
pymodaq/control_modules/daq_viewer_ui.py,sha256=vPvRKeZT1847KR6Bjxc4nptGFAGXiXv2VjisB5KeaP8,15458
|
|
11
11
|
pymodaq/control_modules/mocks.py,sha256=hh_xSWp9g1UV3NAQVD9Ft9tNWfTsSvKU0OU0trgzP2w,1956
|
|
12
|
-
pymodaq/control_modules/move_utility_classes.py,sha256=
|
|
13
|
-
pymodaq/control_modules/utils.py,sha256=
|
|
14
|
-
pymodaq/control_modules/viewer_utility_classes.py,sha256=
|
|
12
|
+
pymodaq/control_modules/move_utility_classes.py,sha256=UumAnTidek8vK8Dz379EZtMyKmTXVA_WV4efQZNCleo,29412
|
|
13
|
+
pymodaq/control_modules/utils.py,sha256=jsidfQFs5jz8rNPXHND2g2iUrVHsgACSHOUI9JZzEoU,13636
|
|
14
|
+
pymodaq/control_modules/viewer_utility_classes.py,sha256=A58qegvBErr-prayw2vh_NZgL0xE-1PoC4PsxVvZkbA,26925
|
|
15
15
|
pymodaq/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
pymodaq/examples/custom_app.py,sha256=
|
|
17
|
-
pymodaq/examples/custom_viewer.py,sha256=
|
|
16
|
+
pymodaq/examples/custom_app.py,sha256=2wQR0hlPWjZrWK0abNF6ASv8iQyJqRn2CKnBa_nAgN4,10452
|
|
17
|
+
pymodaq/examples/custom_viewer.py,sha256=Y2tbqpWya3ZqsYRQjSCksJ4VjgjUDDnD77T6wOuB5Pg,4813
|
|
18
18
|
pymodaq/examples/function_plotter.py,sha256=T-VT0Rd3jHP9GcR2h6Nao6lwZE06P8zWUbOlz8b8Rxk,6104
|
|
19
19
|
pymodaq/examples/nonlinearscanner.py,sha256=x0R2_FP0YnuOCCAmYRiAiZ1jfUdRxu5RqIYLyGQMZ0U,3790
|
|
20
20
|
pymodaq/examples/parameter_ex.py,sha256=cnGXD-g5yNLlklNTondw-6A0u8w_TW5ZDaijIP27aQI,7187
|
|
@@ -40,7 +40,7 @@ pymodaq/extensions/daq_logger.py,sha256=xsd0rmU8FfJmjuKwpYzSgSQ2Jadm_yA8FN_esO_B
|
|
|
40
40
|
pymodaq/extensions/daq_scan.py,sha256=WhO5ud8-ahekb5AqNQmajNk4o8BYHL2Ue6NNfFRnhIY,56505
|
|
41
41
|
pymodaq/extensions/daq_scan_ui.py,sha256=zp9dCOnsWdPRe0LuU8hxhTf8L3t2eo-MjBd8xiHX_mk,10134
|
|
42
42
|
pymodaq/extensions/h5browser.py,sha256=3hX53yA67WD-m5S5ifilCNuHnreSdXyOtBNfD8UXYFU,513
|
|
43
|
-
pymodaq/extensions/utils.py,sha256=
|
|
43
|
+
pymodaq/extensions/utils.py,sha256=CMa3t2S165PCZC3jsSHmIrImyou6gh5FuA11tXd1Xk8,1815
|
|
44
44
|
pymodaq/extensions/pid/__init__.py,sha256=YP5CemFZ54mFlFIhktct2SeOmkAuvxQm2y1Fiq5HiMQ,534
|
|
45
45
|
pymodaq/extensions/pid/daq_move_PID.py,sha256=UVtxY0PJT2HMhVKzPPCMwI__pkjmzDWAKXvaPmtHLCw,3139
|
|
46
46
|
pymodaq/extensions/pid/pid_controller.py,sha256=hxY6mMZ7-Odbb06aEepCd8Y36DABlkCyJmIIR5ifW3o,29797
|
|
@@ -55,7 +55,7 @@ pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py,sha256=1u7hWDaiwsZ
|
|
|
55
55
|
pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui,sha256=PyzbCWPMkh5oIYYteZczXyWMeHKW9EJmM1QlzXhnyTk,7037
|
|
56
56
|
pymodaq/post_treatment/daq_measurement/daq_measurement_main.py,sha256=CAKwcWMOD86aXB8mbdxOK7e8nZRos5d59FzDtqK1QoY,17093
|
|
57
57
|
pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat,sha256=e1tu2A67MS9fk3jhriF6saQgRxWIucIvNW92iWXFP6E,164
|
|
58
|
-
pymodaq/resources/VERSION,sha256=
|
|
58
|
+
pymodaq/resources/VERSION,sha256=D_XUFwf7uSH7qBRyE1Pv0kAqfkza3SalQAlYEN0aRMg,18
|
|
59
59
|
pymodaq/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
60
|
pymodaq/resources/config_template.toml,sha256=SvUTT3mkizOcergQ6uz8uZYn0ZpB_qPtIHzpJuoASIc,3280
|
|
61
61
|
pymodaq/resources/preset_default.xml,sha256=uAnnhgbQmng8dSK3c4bfICHv8nZV8V3C7hbe-lBAw2A,31882
|
|
@@ -295,9 +295,9 @@ pymodaq/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
295
295
|
pymodaq/utils/array_manipulation.py,sha256=uMdiVVR2mU7j6Z4DKL5VGhUPqiWvFX2YK7RLMGdLyC8,10415
|
|
296
296
|
pymodaq/utils/calibration_camera.py,sha256=Hs-kZbGj9d8oNOqey6ONly60Ghf3JMBz4-Ls2yXeoKM,8921
|
|
297
297
|
pymodaq/utils/chrono_timer.py,sha256=rwX8apS8B-IKhA0Cp2H9tLz0BRN7G3Pg5ptozvd3MKM,7244
|
|
298
|
-
pymodaq/utils/config.py,sha256=
|
|
298
|
+
pymodaq/utils/config.py,sha256=ghaTFrV0Z9rgJJ23xUMk8lY99lxEWXB_oLFKE5s0iRs,16094
|
|
299
299
|
pymodaq/utils/conftests.py,sha256=3Ak8WEpa3EhAp73Yb1LLq8YFONhPqiL7gG9eSDIoTNc,58
|
|
300
|
-
pymodaq/utils/daq_utils.py,sha256=
|
|
300
|
+
pymodaq/utils/daq_utils.py,sha256=kKYlDgOXuGKbE_i80qdJO3kdFFrjSCORgIqGiCq10ys,28217
|
|
301
301
|
pymodaq/utils/data.py,sha256=xUj2El6d8aApZPn89q-ckt6NzknZEICTu-JdOerNO74,71226
|
|
302
302
|
pymodaq/utils/enums.py,sha256=WNU6w3tsNpP7HQnNrQ6eKnDTXulOlZufQRr11__-l0M,1822
|
|
303
303
|
pymodaq/utils/exceptions.py,sha256=_pm9vcJI7M-4aO_Hb0jBfXzefrs8J5w1kbrxdwUU5BQ,584
|
|
@@ -354,15 +354,15 @@ pymodaq/utils/managers/preset_manager_utils.py,sha256=8A4z0pW2lyzjg3K1AYxX-pIhMN
|
|
|
354
354
|
pymodaq/utils/managers/remote_manager.py,sha256=-BtQvHy32ltZehej8jyK0GzfIdu9OnO8ukLAGrsWvMw,22216
|
|
355
355
|
pymodaq/utils/managers/roi_manager.py,sha256=MDW-emef7uoIC3m3Ps71xjfWXwfVj1otBJf9eDcNzxM,28454
|
|
356
356
|
pymodaq/utils/parameter/__init__.py,sha256=rfXpqq0yxkKwCCxuiTHTB8Z54o9MtO_vn8zVgUn-k-g,106
|
|
357
|
-
pymodaq/utils/parameter/ioxml.py,sha256
|
|
358
|
-
pymodaq/utils/parameter/utils.py,sha256=
|
|
357
|
+
pymodaq/utils/parameter/ioxml.py,sha256=-GLKr_csnvc7IcGRZifFZHwK4F_vKST_Gl6cH9EF0TA,16560
|
|
358
|
+
pymodaq/utils/parameter/utils.py,sha256=IYcHQ0iDSxJgAOEH5oOiO0NGfyy7HOeBxbF8L3zfIWE,6836
|
|
359
359
|
pymodaq/utils/parameter/pymodaq_ptypes/__init__.py,sha256=NNPGOTfpft27W4mxHbqcgfq6bFdaFW0NlfFHx-kwjP4,1988
|
|
360
360
|
pymodaq/utils/parameter/pymodaq_ptypes/bool.py,sha256=yz9-zn6T5NN7SDEWwf8tfw8Ezbllbt1rOd8vHGqw3mI,761
|
|
361
361
|
pymodaq/utils/parameter/pymodaq_ptypes/date.py,sha256=7mOGlw0ViJWD8au0HNsh-C9Fr4woZzkXhFs5Lno7yik,3706
|
|
362
362
|
pymodaq/utils/parameter/pymodaq_ptypes/filedir.py,sha256=IVFbN08Dr3NdRNMufBef1vWr2igiULq3CBu10-yLqSQ,4571
|
|
363
363
|
pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py,sha256=dnj1qBzxwmdPpQ2Sk5lfmOolb1rgWqhGikhItoARuoo,5553
|
|
364
364
|
pymodaq/utils/parameter/pymodaq_ptypes/led.py,sha256=oDKM3k4aPy_CArgQIEqjLx3KG5CR7NrywacJKalmKQ4,1129
|
|
365
|
-
pymodaq/utils/parameter/pymodaq_ptypes/list.py,sha256=
|
|
365
|
+
pymodaq/utils/parameter/pymodaq_ptypes/list.py,sha256=v5XVMWCkUle2-cgbdNAO9JHNTQIfVufFv6j14tX18C4,4981
|
|
366
366
|
pymodaq/utils/parameter/pymodaq_ptypes/numeric.py,sha256=lzklQWAnzh9LDC20hdlGbAj2NdVzNDDeJke1KnPi7GU,560
|
|
367
367
|
pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py,sha256=PnSEU8uT29UhbiL4uNsoc_dnKDCeGTBuEz_28K3unsE,5228
|
|
368
368
|
pymodaq/utils/parameter/pymodaq_ptypes/slide.py,sha256=x3n6CNezOboFsK-vjjciGT_4CDrUGdgsW7LwLDGHRPk,4716
|
|
@@ -382,7 +382,7 @@ pymodaq/utils/plotting/data_viewers/viewer1D.py,sha256=kdfntqTVr_7Bay-gCD6AOy5nL
|
|
|
382
382
|
pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py,sha256=sfqiuNPlsF2SbhFwVfLD7CzfKD7UUlHITb5LC1clXE0,7407
|
|
383
383
|
pymodaq/utils/plotting/data_viewers/viewer2D.py,sha256=9I8ge0zHRBGzr6MO78feCFyqImZL0F2g6JTDsePwzfk,41922
|
|
384
384
|
pymodaq/utils/plotting/data_viewers/viewer2D_basic.py,sha256=MgxQBiPrMOTYB3KReylS7XGeoVoFP059HW0D33Z5zsc,5567
|
|
385
|
-
pymodaq/utils/plotting/data_viewers/viewerND.py,sha256=
|
|
385
|
+
pymodaq/utils/plotting/data_viewers/viewerND.py,sha256=C_ynk1agkvvz8Lo2qmDkyPy9owomj3p6jbTnHu0Fjd8,35144
|
|
386
386
|
pymodaq/utils/plotting/items/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
387
387
|
pymodaq/utils/plotting/items/axis_scaled.py,sha256=YVSqpSs2gfALdsH_wKheYf6fgEQ0-7tU2zWu709K3h4,3245
|
|
388
388
|
pymodaq/utils/plotting/items/crosshair.py,sha256=hVoM3dDtRmYGfzZJsP-Yhyfnx2HV1g-nLSQMVl6ZZXY,3064
|
|
@@ -406,8 +406,8 @@ pymodaq/utils/svg/__init__.py,sha256=QWpeotkNhAQkoVTdWBH8t6MRr9-lrPJx4bXn7J6fCNA
|
|
|
406
406
|
pymodaq/utils/svg/svg_renderer.py,sha256=USEcrOWmQAq8UM620e_XIGPI6z9IQmhyJuqbPo3jLzE,406
|
|
407
407
|
pymodaq/utils/svg/svg_view.py,sha256=bmXpDqnw9S-Bp3F8Hi_oeYB5Y9gebiCNsQWVJzCq-PA,901
|
|
408
408
|
pymodaq/utils/svg/svg_viewer2D.py,sha256=LTJ3Ulb5zWXdRPr7vqcWumbpq7ZctzrYUMtD5QV3x60,1523
|
|
409
|
-
pymodaq-4.0.
|
|
410
|
-
pymodaq-4.0.
|
|
411
|
-
pymodaq-4.0.
|
|
412
|
-
pymodaq-4.0.
|
|
413
|
-
pymodaq-4.0.
|
|
409
|
+
pymodaq-4.0.7.dist-info/METADATA,sha256=RGbvyltfaKJaGuJa2W2EteKxvsojHDvLefmSFQxpHII,7571
|
|
410
|
+
pymodaq-4.0.7.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
|
411
|
+
pymodaq-4.0.7.dist-info/entry_points.txt,sha256=RAzdYNjvUT28I2eiCKki_g2NzXq0woWxhev6lwzwRv8,348
|
|
412
|
+
pymodaq-4.0.7.dist-info/licenses/LICENSE,sha256=VKOejxexXAe3XwfhAhcFGqeXQ12irxVHdeAojZwFEI8,1108
|
|
413
|
+
pymodaq-4.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|