pymodaq 4.1.5__py3-none-any.whl → 4.2.1__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/__init__.py +23 -4
- pymodaq/control_modules/daq_move.py +32 -73
- pymodaq/control_modules/daq_viewer.py +73 -98
- pymodaq/control_modules/daq_viewer_ui.py +2 -1
- pymodaq/control_modules/move_utility_classes.py +17 -7
- pymodaq/control_modules/utils.py +153 -5
- pymodaq/control_modules/viewer_utility_classes.py +31 -20
- pymodaq/dashboard.py +23 -5
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +4 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +673 -0
- pymodaq/extensions/bayesian/utils.py +403 -0
- pymodaq/extensions/daq_scan.py +4 -4
- pymodaq/extensions/daq_scan_ui.py +2 -1
- pymodaq/extensions/pid/pid_controller.py +12 -7
- pymodaq/extensions/pid/utils.py +9 -26
- pymodaq/extensions/utils.py +3 -0
- pymodaq/post_treatment/load_and_plot.py +42 -19
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +9 -24
- pymodaq/resources/setup_plugin.py +1 -1
- pymodaq/utils/config.py +103 -5
- pymodaq/utils/daq_utils.py +35 -134
- pymodaq/utils/data.py +614 -95
- pymodaq/utils/enums.py +17 -1
- pymodaq/utils/factory.py +2 -2
- pymodaq/utils/gui_utils/custom_app.py +5 -2
- pymodaq/utils/gui_utils/dock.py +33 -4
- pymodaq/utils/gui_utils/utils.py +14 -1
- pymodaq/utils/h5modules/backends.py +9 -1
- pymodaq/utils/h5modules/data_saving.py +254 -57
- pymodaq/utils/h5modules/saving.py +1 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +172 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +170 -0
- pymodaq/utils/leco/desktop.ini +2 -0
- pymodaq/utils/leco/director_utils.py +58 -0
- pymodaq/utils/leco/leco_director.py +88 -0
- pymodaq/utils/leco/pymodaq_listener.py +279 -0
- pymodaq/utils/leco/utils.py +41 -0
- pymodaq/utils/managers/action_manager.py +20 -6
- pymodaq/utils/managers/parameter_manager.py +6 -4
- pymodaq/utils/managers/roi_manager.py +63 -54
- pymodaq/utils/math_utils.py +1 -1
- pymodaq/utils/plotting/data_viewers/__init__.py +3 -1
- pymodaq/utils/plotting/data_viewers/base.py +286 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +29 -202
- pymodaq/utils/plotting/data_viewers/viewer0D.py +94 -47
- pymodaq/utils/plotting/data_viewers/viewer1D.py +341 -174
- pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +1 -1
- pymodaq/utils/plotting/data_viewers/viewer2D.py +271 -181
- pymodaq/utils/plotting/data_viewers/viewerND.py +26 -22
- pymodaq/utils/plotting/items/crosshair.py +3 -3
- pymodaq/utils/plotting/items/image.py +2 -1
- pymodaq/utils/plotting/plotter/plotter.py +94 -0
- pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
- pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +134 -0
- pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +78 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +1 -1
- pymodaq/utils/plotting/utils/filter.py +194 -147
- pymodaq/utils/plotting/utils/lineout.py +13 -11
- pymodaq/utils/plotting/utils/plot_utils.py +89 -12
- pymodaq/utils/scanner/__init__.py +0 -3
- pymodaq/utils/scanner/scan_config.py +1 -9
- pymodaq/utils/scanner/scan_factory.py +10 -36
- pymodaq/utils/scanner/scanner.py +3 -2
- pymodaq/utils/scanner/scanners/_1d_scanners.py +7 -5
- pymodaq/utils/scanner/scanners/_2d_scanners.py +36 -49
- pymodaq/utils/scanner/scanners/sequential.py +10 -4
- pymodaq/utils/scanner/scanners/tabular.py +10 -5
- pymodaq/utils/slicing.py +1 -1
- pymodaq/utils/tcp_ip/serializer.py +38 -5
- pymodaq/utils/tcp_ip/tcp_server_client.py +25 -17
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/METADATA +4 -2
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/RECORD +79 -63
- pymodaq/resources/config_scan_template.toml +0 -42
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/WHEEL +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,15 +6,20 @@ Created the 22/01/2023
|
|
|
6
6
|
"""
|
|
7
7
|
import os
|
|
8
8
|
import sys
|
|
9
|
-
from typing import List, Union, Callable, Iterable
|
|
9
|
+
from typing import List, Union, Callable, Iterable, Dict
|
|
10
10
|
|
|
11
11
|
from qtpy import QtWidgets, QtCore
|
|
12
12
|
|
|
13
13
|
from pymodaq.utils.data import DataToExport, DataFromPlugins, DataDim, enum_checker
|
|
14
14
|
from pymodaq.utils.h5modules.data_saving import DataLoader
|
|
15
15
|
from pymodaq.utils.h5modules.saving import H5Saver
|
|
16
|
-
from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase,
|
|
16
|
+
from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase, ViewerDispatcher
|
|
17
|
+
from pymodaq.utils.plotting.data_viewers import ViewersEnum, Viewer1D, Viewer2D, ViewerND
|
|
17
18
|
from pymodaq.utils.gui_utils import Dock, DockArea
|
|
19
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
logger = set_logger(get_module_name(__file__))
|
|
18
23
|
|
|
19
24
|
|
|
20
25
|
class LoaderPlotter:
|
|
@@ -182,20 +187,25 @@ class LoaderPlotter:
|
|
|
182
187
|
|
|
183
188
|
target_at = kwargs.pop('target_at') if 'target_at' in kwargs else None
|
|
184
189
|
last_step = kwargs.pop('last_step') if 'last_step' in kwargs else False
|
|
190
|
+
crosshair_at = kwargs.pop('crosshair_at') if 'crosshair_at' in kwargs else None
|
|
185
191
|
|
|
186
192
|
self.load_data(**kwargs)
|
|
187
|
-
self.show_data(target_at=target_at
|
|
193
|
+
self.show_data(target_at=target_at,
|
|
194
|
+
crosshair_at=crosshair_at)
|
|
188
195
|
if (last_step and 'average_index' in kwargs and kwargs['average_index']
|
|
189
196
|
is not None):
|
|
190
197
|
kwargs['last_step'] = last_step
|
|
191
198
|
self.load_data(**kwargs)
|
|
192
|
-
self.show_data(target_at=target_at
|
|
199
|
+
self.show_data(target_at=target_at,
|
|
200
|
+
crosshair_at=crosshair_at)
|
|
193
201
|
|
|
194
202
|
def show_data(self, **kwargs):
|
|
195
203
|
"""Send data to their dedicated viewers
|
|
196
204
|
"""
|
|
197
|
-
|
|
198
|
-
|
|
205
|
+
try:
|
|
206
|
+
self.set_data_to_viewers(self._data, **kwargs)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
logger.warning(f'Could not show data: {str(e)}')
|
|
199
209
|
|
|
200
210
|
def _init_show_data(self, data: DataToExport):
|
|
201
211
|
"""Processing before showing data
|
|
@@ -203,7 +213,9 @@ class LoaderPlotter:
|
|
|
203
213
|
self._viewer_types = [ViewersEnum(data.dim.name) for data in data]
|
|
204
214
|
self.prepare_viewers(self._viewer_types)
|
|
205
215
|
|
|
206
|
-
def prepare_viewers(self, viewers_enum: List[ViewersEnum
|
|
216
|
+
def prepare_viewers(self, viewers_enum: List[Union[ViewersEnum, str]],
|
|
217
|
+
viewers_name: List[str] = None) -> List[ViewerBase]:
|
|
218
|
+
|
|
207
219
|
if self._viewers is not None:
|
|
208
220
|
while len(self._viewers) > 0:
|
|
209
221
|
self._viewers.pop(list(self._viewers.keys())[0])
|
|
@@ -214,13 +226,16 @@ class LoaderPlotter:
|
|
|
214
226
|
viewers_name = [f'DataPlot{ind:02d}' for ind in range(len(self._viewer_types))]
|
|
215
227
|
|
|
216
228
|
if self.dispatcher.viewer_types != self._viewer_types:
|
|
217
|
-
self.dispatcher.update_viewers(self._viewer_types
|
|
229
|
+
self.dispatcher.update_viewers(self._viewer_types,
|
|
230
|
+
viewers_name=viewers_name)
|
|
218
231
|
|
|
219
232
|
self._viewers = dict(zip(viewers_name, self.dispatcher.viewers))
|
|
220
233
|
self._viewer_docks = dict(zip(viewers_name, self.dispatcher.viewer_docks))
|
|
234
|
+
return self.dispatcher.viewers
|
|
221
235
|
|
|
222
236
|
def set_data_to_viewers(self, data: DataToExport, temp=False,
|
|
223
|
-
target_at: Iterable[float] = None
|
|
237
|
+
target_at: Iterable[float] = None,
|
|
238
|
+
crosshair_at: Iterable[float] = None):
|
|
224
239
|
"""Process data dimensionality and send appropriate data to their data viewers
|
|
225
240
|
|
|
226
241
|
Parameters
|
|
@@ -230,6 +245,8 @@ class LoaderPlotter:
|
|
|
230
245
|
if True notify the data viewers to display data as temporary (meaning not exporting processed data from roi)
|
|
231
246
|
target_at: Iterable[float]
|
|
232
247
|
if specified show and plot the roi_target of each viewer at the given position
|
|
248
|
+
crosshair_at: Iterable[float]
|
|
249
|
+
if specified show and plot the viewer crosshair of each viewer at the given position
|
|
233
250
|
See Also
|
|
234
251
|
--------
|
|
235
252
|
ViewerBase, Viewer0D, Viewer1D, Viewer2D
|
|
@@ -246,21 +263,27 @@ class LoaderPlotter:
|
|
|
246
263
|
viewer.show_data_temp(_data)
|
|
247
264
|
else:
|
|
248
265
|
viewer.show_data(_data)
|
|
266
|
+
if crosshair_at is not None:
|
|
267
|
+
if not viewer.is_action_checked('crosshair'):
|
|
268
|
+
viewer.get_action('crosshair').trigger()
|
|
269
|
+
viewer.double_clicked(*crosshair_at)
|
|
249
270
|
if target_at is not None:
|
|
250
271
|
viewer.show_roi_target(True)
|
|
251
|
-
if
|
|
272
|
+
if isinstance(viewer, Viewer1D):
|
|
252
273
|
viewer.move_roi_target(target_at)
|
|
253
|
-
elif
|
|
274
|
+
elif isinstance(viewer, Viewer2D):
|
|
254
275
|
_target_at = target_at.copy()
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
276
|
+
if _data.distribution == 'uniform':
|
|
277
|
+
size = [_data.get_axis_from_index(1)[0].scaling]
|
|
278
|
+
if len(_target_at) == 1: # means concatenation of 1D data
|
|
279
|
+
axis = _data.get_axis_from_index(0)[0]
|
|
280
|
+
size.append(axis.scaling * axis.size)
|
|
281
|
+
_target_at = list(_target_at) + [axis.offset]
|
|
282
|
+
else:
|
|
283
|
+
size.append(_data.get_axis_from_index(0)[0].scaling)
|
|
284
|
+
viewer.move_roi_target(_target_at, size)
|
|
261
285
|
else:
|
|
262
|
-
|
|
263
|
-
viewer.move_roi_target(_target_at, size)
|
|
286
|
+
viewer.move_roi_target(_target_at)
|
|
264
287
|
|
|
265
288
|
def main(init_qt=True):
|
|
266
289
|
if init_qt: # used for the test suite
|
pymodaq/resources/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = '4.1
|
|
1
|
+
version = '4.2.1'
|
|
@@ -41,6 +41,9 @@ viewer_in_thread = true
|
|
|
41
41
|
timeout = 10000 # default duration in ms to wait for data to be acquirred
|
|
42
42
|
allow_settings_edition = false
|
|
43
43
|
|
|
44
|
+
[plotting]
|
|
45
|
+
backend = 'matplotlib' # either 'matplotlib' or 'qt' or any other custom backend
|
|
46
|
+
|
|
44
47
|
[network]
|
|
45
48
|
[network.logging]
|
|
46
49
|
[network.logging.user]
|
|
@@ -55,6 +58,11 @@ allow_settings_edition = false
|
|
|
55
58
|
ip = "10.47.0.39"
|
|
56
59
|
port = 6341
|
|
57
60
|
|
|
61
|
+
[network.leco-server]
|
|
62
|
+
run_coordinator_at_startup = false
|
|
63
|
+
host = "localhost"
|
|
64
|
+
port = 12300 # pyleco default Coordinator port
|
|
65
|
+
|
|
58
66
|
[presets]
|
|
59
67
|
default_preset_for_scan = "preset_default"
|
|
60
68
|
default_preset_for_logger = "preset_default"
|
|
@@ -62,7 +70,7 @@ default_preset_for_pid = "beam_steering_mock"
|
|
|
62
70
|
|
|
63
71
|
[actuator]
|
|
64
72
|
epsilon_default = 1
|
|
65
|
-
polling_interval_ms = 100 # ms
|
|
73
|
+
polling_interval_ms = 100 # ms Careful when using TCP/IP connection as you can saturate the connection with too much polling
|
|
66
74
|
polling_timeout_s = 20 # s
|
|
67
75
|
refresh_timeout_ms = 500 # ms
|
|
68
76
|
timeout = 10000 # default duration in ms to wait for data to be acquirred
|
|
@@ -80,26 +88,3 @@ default_preset_for_pid = "beam_steering_mock"
|
|
|
80
88
|
wait_time_between = 0
|
|
81
89
|
timeout = 10000 # in millisecond
|
|
82
90
|
|
|
83
|
-
[scan.scan1D]
|
|
84
|
-
type = "Linear" # either "Linear", "Adaptive", "Linear back to start", "Random" see pymodaq.utils.scanner.py
|
|
85
|
-
start = 1.0
|
|
86
|
-
stop = 2.0
|
|
87
|
-
step = 0.01
|
|
88
|
-
[scan.scan2D]
|
|
89
|
-
type = "Spiral" # either "Spiral", "Linear", "Adaptive", "Back&Forth", "Random" see pymodaq.utils.scanner.py
|
|
90
|
-
[scan.scan2D.spiral]
|
|
91
|
-
center1 = -5
|
|
92
|
-
center2 = 5
|
|
93
|
-
rmax1 = 10
|
|
94
|
-
rmax2 = 5
|
|
95
|
-
npts = 10
|
|
96
|
-
[scan.scan2D.linear]
|
|
97
|
-
start1 = -5
|
|
98
|
-
start2 = -5
|
|
99
|
-
stop1 = 5
|
|
100
|
-
stop2 = 5
|
|
101
|
-
step1 = 0.5
|
|
102
|
-
step2 = 0.5
|
|
103
|
-
[scan.tabular]
|
|
104
|
-
type = "Linear" #either "Linear", "Adaptive" see pymodaq.utils.scanner.py
|
|
105
|
-
curvilinear = 0.1
|
|
@@ -47,7 +47,7 @@ def setup(path: Path):
|
|
|
47
47
|
entrypoints['pymodaq.instruments'] = f'{SHORT_PLUGIN_NAME} = {PLUGIN_NAME}'
|
|
48
48
|
if config['features'].get('extensions', False):
|
|
49
49
|
entrypoints['pymodaq.extensions'] = f'{SHORT_PLUGIN_NAME} = {PLUGIN_NAME}'
|
|
50
|
-
if config['features'].get('pid_models', False):
|
|
50
|
+
if config['features'].get('pid_models', False): # deprecated use 'models'
|
|
51
51
|
entrypoints['pymodaq.pid_models'] = f'{SHORT_PLUGIN_NAME} = {PLUGIN_NAME}'
|
|
52
52
|
if config['features'].get('models', False):
|
|
53
53
|
entrypoints['pymodaq.models'] = f'{SHORT_PLUGIN_NAME} = {PLUGIN_NAME}'
|
pymodaq/utils/config.py
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
from abc import abstractproperty
|
|
2
|
+
from collections.abc import Iterable
|
|
2
3
|
|
|
3
4
|
from os import environ
|
|
4
5
|
import sys
|
|
5
6
|
import datetime
|
|
6
7
|
from pathlib import Path
|
|
7
|
-
from typing import Union, Dict, TypeVar, Any
|
|
8
|
+
from typing import Union, Dict, TypeVar, Any, List, TYPE_CHECKING
|
|
9
|
+
from typing import Iterable as IterableType
|
|
8
10
|
|
|
9
11
|
import toml
|
|
10
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from pymodaq.utils.parameter import Parameter
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
try:
|
|
13
18
|
USER = environ['USERNAME'] if sys.platform == 'win32' else environ['USER']
|
|
@@ -80,6 +85,16 @@ def getitem_recursive(dic, *args, ndepth=0, create_if_missing=False):
|
|
|
80
85
|
return dic
|
|
81
86
|
|
|
82
87
|
|
|
88
|
+
def recursive_iterable_flattening(aniterable: IterableType):
|
|
89
|
+
flatten_iter = []
|
|
90
|
+
for elt in aniterable:
|
|
91
|
+
if not isinstance(elt, str) and isinstance(elt, Iterable):
|
|
92
|
+
flatten_iter.extend(recursive_iterable_flattening(elt))
|
|
93
|
+
else:
|
|
94
|
+
flatten_iter.append(elt)
|
|
95
|
+
return flatten_iter
|
|
96
|
+
|
|
97
|
+
|
|
83
98
|
def get_set_path(a_base_path: Path, dir_name: str) -> Path:
|
|
84
99
|
path_to_get = a_base_path.joinpath(dir_name)
|
|
85
100
|
if not path_to_get.is_dir():
|
|
@@ -249,7 +264,7 @@ def copy_template_config(config_file_name: str = 'config', source_path: Union[Pa
|
|
|
249
264
|
dest_path_with_filename = dest_path.joinpath(file_name)
|
|
250
265
|
|
|
251
266
|
if source_path is None:
|
|
252
|
-
config_template_dict =
|
|
267
|
+
config_template_dict = {}
|
|
253
268
|
else:
|
|
254
269
|
config_template_dict = toml.load(Path(source_path))
|
|
255
270
|
|
|
@@ -322,9 +337,18 @@ class BaseConfig:
|
|
|
322
337
|
else:
|
|
323
338
|
return self._config[item]
|
|
324
339
|
|
|
340
|
+
# def __setitem__(self, key, value):
|
|
341
|
+
# if isinstance(key, tuple):
|
|
342
|
+
# dic = getitem_recursive(self._config, *key, ndepth=1, create_if_missing=False)
|
|
343
|
+
# dic[key[-1]] = value
|
|
344
|
+
# else:
|
|
345
|
+
# self._config[key] = value
|
|
346
|
+
|
|
325
347
|
def __setitem__(self, key, value):
|
|
326
348
|
if isinstance(key, tuple):
|
|
327
|
-
dic = getitem_recursive(self._config, *key, ndepth=1, create_if_missing=
|
|
349
|
+
dic = getitem_recursive(self._config, *key, ndepth=1, create_if_missing=True)
|
|
350
|
+
if value is None: # means the setting is a group
|
|
351
|
+
value = {}
|
|
328
352
|
dic[key[-1]] = value
|
|
329
353
|
else:
|
|
330
354
|
self._config[key] = value
|
|
@@ -337,7 +361,10 @@ class BaseConfig:
|
|
|
337
361
|
toml_user_path = get_config_file(config_file_name, user=True)
|
|
338
362
|
if toml_base_path.is_file():
|
|
339
363
|
config = toml.load(toml_base_path)
|
|
340
|
-
|
|
364
|
+
if template_path is not None:
|
|
365
|
+
config_template = toml.load(template_path)
|
|
366
|
+
else:
|
|
367
|
+
config_template = {}
|
|
341
368
|
if check_config(config_template, config): # check if all fields from template are there
|
|
342
369
|
# (could have been modified by some commits)
|
|
343
370
|
create_toml_from_dict(config, toml_base_path)
|
|
@@ -383,8 +410,79 @@ class Config(BaseConfig):
|
|
|
383
410
|
return dict(user=dict(name=USER))
|
|
384
411
|
|
|
385
412
|
|
|
413
|
+
class ConfigSaverLoader:
|
|
414
|
+
""" Allows to set Parameters values from previously saved one in a configuration file
|
|
415
|
+
|
|
416
|
+
This plays the role of a cache for these Parameters
|
|
417
|
+
|
|
418
|
+
Parameters
|
|
419
|
+
----------
|
|
420
|
+
base_param: Parameter
|
|
421
|
+
The parent Parameter whose children should be cached in the config file
|
|
422
|
+
config: BaseConfig
|
|
423
|
+
The Config object that will cache the Parameter values
|
|
424
|
+
base_path: Iterable[str]
|
|
425
|
+
an iterable of string defining a "category"
|
|
426
|
+
"""
|
|
427
|
+
|
|
428
|
+
def __init__(self, base_param: 'Parameter', config: BaseConfig,
|
|
429
|
+
base_path: IterableType[str] = None):
|
|
430
|
+
self.config = config
|
|
431
|
+
if base_path is None:
|
|
432
|
+
base_path = []
|
|
433
|
+
self._base_path: List[str] = list(recursive_iterable_flattening(base_path))
|
|
434
|
+
self._base_param = base_param
|
|
435
|
+
|
|
436
|
+
@property
|
|
437
|
+
def base_path(self):
|
|
438
|
+
""" Get/Set the iterable of string defining a particular configuration to be loaded/saved"""
|
|
439
|
+
return self._base_path
|
|
440
|
+
|
|
441
|
+
@base_path.setter
|
|
442
|
+
def base_path(self, path: IterableType[str]):
|
|
443
|
+
self._base_path = list(recursive_iterable_flattening(path))
|
|
444
|
+
|
|
445
|
+
@property
|
|
446
|
+
def base_param(self):
|
|
447
|
+
""" Get/Set the parent Parameter whose children should be saved in the config file"""
|
|
448
|
+
return self._base_param
|
|
449
|
+
|
|
450
|
+
@base_param.setter
|
|
451
|
+
def base_param(self, param: 'Parameter'):
|
|
452
|
+
self._base_param = param
|
|
453
|
+
|
|
454
|
+
def load_config(self, param: 'Parameter' = None):
|
|
455
|
+
from pymodaq.utils.parameter import utils as putils
|
|
456
|
+
|
|
457
|
+
if param is None:
|
|
458
|
+
param = self.base_param
|
|
459
|
+
base_path = self.base_path[:]
|
|
460
|
+
for child in putils.iter_children_params(param, []):
|
|
461
|
+
if len(child.children()) == 0: # means it is not a group parameter
|
|
462
|
+
|
|
463
|
+
path = base_path + putils.get_param_path(child)[1:]
|
|
464
|
+
|
|
465
|
+
try:
|
|
466
|
+
child.setValue(self.config(
|
|
467
|
+
*path)) # first try to load the config including the actuators name
|
|
468
|
+
except ConfigError as e:
|
|
469
|
+
pass
|
|
470
|
+
else:
|
|
471
|
+
self.load_config(child)
|
|
472
|
+
|
|
473
|
+
def save_config(self):
|
|
474
|
+
from pymodaq.utils.parameter import utils as putils
|
|
475
|
+
|
|
476
|
+
for param in putils.iter_children_params(self.base_param, []):
|
|
477
|
+
path_param = self.base_path[:]
|
|
478
|
+
path_param.extend(putils.get_param_path(param)[1:])
|
|
479
|
+
try:
|
|
480
|
+
self.config[tuple(path_param)] = param.value()
|
|
481
|
+
except Exception as e:
|
|
482
|
+
pass
|
|
483
|
+
self.config.save()
|
|
484
|
+
|
|
386
485
|
|
|
387
|
-
|
|
388
486
|
if __name__ == '__main__':
|
|
389
487
|
|
|
390
488
|
config = Config()
|
pymodaq/utils/daq_utils.py
CHANGED
|
@@ -15,6 +15,8 @@ import pkgutil
|
|
|
15
15
|
import traceback
|
|
16
16
|
import platform
|
|
17
17
|
from typing import Union, List
|
|
18
|
+
from typing import Iterable as IterableType
|
|
19
|
+
from collections.abc import Iterable
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
20
22
|
from qtpy import QtCore
|
|
@@ -44,32 +46,6 @@ plot_colors = [(255, 255, 255), (255, 0, 0), (0, 255, 0), (0, 0, 255), (14, 207,
|
|
|
44
46
|
config = Config()
|
|
45
47
|
|
|
46
48
|
|
|
47
|
-
def __getattr__(name):
|
|
48
|
-
if name in ['Axis', 'NavAxis', 'ScaledAxis', 'ScalingOptions', 'Data', 'DataTimeStamped', 'DataFromPlugins',
|
|
49
|
-
'DataToEmit', 'DataToExport']:
|
|
50
|
-
data_mod = importlib.import_module('.data', 'pymodaq.utils')
|
|
51
|
-
deprecation_msg('Loading Axis or Data and their derived classes from daq_utils is deprecated, import them from'
|
|
52
|
-
' pymodaq.utils.data module', 3)
|
|
53
|
-
return getattr(data_mod, name)
|
|
54
|
-
else:
|
|
55
|
-
raise AttributeError
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def load_config():
|
|
59
|
-
deprecation_msg(f'config methods must now be imported from the pymodaq.utils.messenger.cnfig module')
|
|
60
|
-
return Config()
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def set_logger(*args, **kwargs):
|
|
64
|
-
deprecation_msg(f'Logger methods must now be imported from the pymodaq.utils.logger module', 3)
|
|
65
|
-
return logger_module.set_logger(*args, **kwargs)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def get_module_name(*args, **kwargs):
|
|
69
|
-
deprecation_msg(f'Logger methods must now be imported from the pymodaq.utils.logger module', 3)
|
|
70
|
-
return logger_module.get_module_name(*args, **kwargs)
|
|
71
|
-
|
|
72
|
-
|
|
73
49
|
def is_64bits():
|
|
74
50
|
return sys.maxsize > 2**32
|
|
75
51
|
|
|
@@ -255,7 +231,7 @@ class ThreadCommand:
|
|
|
255
231
|
raise TypeError(f'The command in a Threadcommand object should be a string, not a {type(command)}')
|
|
256
232
|
self.command = command
|
|
257
233
|
if attribute is None and attributes is not None:
|
|
258
|
-
deprecation_msg('ThreadCommand signature changed, use attribute in place of
|
|
234
|
+
deprecation_msg('ThreadCommand signature changed, use attribute in place of attributes')
|
|
259
235
|
self.attribute = attributes
|
|
260
236
|
self.attributes = attributes
|
|
261
237
|
self.attribute = attribute
|
|
@@ -548,7 +524,7 @@ def find_dict_in_list_from_key_val(dicts, key, value, return_index=False):
|
|
|
548
524
|
return None
|
|
549
525
|
|
|
550
526
|
|
|
551
|
-
def get_entrypoints(group='pymodaq.plugins'):
|
|
527
|
+
def get_entrypoints(group='pymodaq.plugins') -> List[metadata.EntryPoint]:
|
|
552
528
|
""" Get the list of modules defined from a group entry point
|
|
553
529
|
|
|
554
530
|
Because of evolution in the package, one or another of the forms below may be deprecated.
|
|
@@ -568,6 +544,8 @@ def get_entrypoints(group='pymodaq.plugins'):
|
|
|
568
544
|
discovered_entrypoints = metadata.entry_points().get(group, [])
|
|
569
545
|
if isinstance(discovered_entrypoints, tuple): # API for python > 3.8
|
|
570
546
|
discovered_entrypoints = list(discovered_entrypoints)
|
|
547
|
+
if not isinstance(discovered_entrypoints, list):
|
|
548
|
+
discovered_entrypoints = list(discovered_entrypoints)
|
|
571
549
|
return discovered_entrypoints
|
|
572
550
|
|
|
573
551
|
|
|
@@ -586,16 +564,18 @@ def get_instrument_plugins(): # pragma: no cover
|
|
|
586
564
|
"""
|
|
587
565
|
plugins_import = []
|
|
588
566
|
discovered_plugins = []
|
|
589
|
-
discovered_plugins_all = get_entrypoints(group='pymodaq.plugins') # old naming of the instrument plugins
|
|
590
|
-
discovered_plugins_all.extend(get_entrypoints(group='pymodaq.instruments')) # new naming convention
|
|
567
|
+
discovered_plugins_all = list(get_entrypoints(group='pymodaq.plugins')) # old naming of the instrument plugins
|
|
568
|
+
discovered_plugins_all.extend(list(get_entrypoints(group='pymodaq.instruments'))) # new naming convention
|
|
591
569
|
for entry in discovered_plugins_all:
|
|
592
570
|
if entry.name not in [ent.name for ent in discovered_plugins]:
|
|
593
571
|
discovered_plugins.append(entry)
|
|
572
|
+
discovered_plugins = list(set(discovered_plugins))
|
|
594
573
|
logger.debug(f'Found {len(discovered_plugins)} installed plugins, trying to import them')
|
|
595
574
|
viewer_types = ['0D', '1D', '2D', 'ND']
|
|
575
|
+
plugin_list = []
|
|
596
576
|
for entrypoint in discovered_plugins:
|
|
597
577
|
#print(f'Looking for valid instrument plugins in package: {module.value}')
|
|
598
|
-
|
|
578
|
+
|
|
599
579
|
try:
|
|
600
580
|
try:
|
|
601
581
|
movemodule = importlib.import_module(f'{entrypoint.value}.daq_move_plugins', entrypoint.value)
|
|
@@ -606,9 +586,11 @@ def get_instrument_plugins(): # pragma: no cover
|
|
|
606
586
|
for mod in [mod[1] for mod in pkgutil.iter_modules([str(movemodule.path.parent)])]
|
|
607
587
|
if 'daq_move' in mod])
|
|
608
588
|
if len(plugin_list) > 0:
|
|
609
|
-
logger.
|
|
589
|
+
logger.debug(f"Found Move Instrument:"
|
|
590
|
+
f" {plugin_list[-1]['module'].__name__}/{plugin_list[-1]['name']}")
|
|
610
591
|
except ModuleNotFoundError:
|
|
611
592
|
pass
|
|
593
|
+
|
|
612
594
|
viewer_modules = {}
|
|
613
595
|
for vtype in viewer_types:
|
|
614
596
|
try:
|
|
@@ -621,28 +603,31 @@ def get_instrument_plugins(): # pragma: no cover
|
|
|
621
603
|
for mod in [mod[1] for mod in pkgutil.iter_modules([str(viewer_modules[vtype].path.parent)])]
|
|
622
604
|
if f'daq_{vtype}viewer' in mod])
|
|
623
605
|
if len(plugin_list) > 0:
|
|
624
|
-
logger.
|
|
606
|
+
logger.debug(f"Found Viewer Instrument: "
|
|
607
|
+
f"{plugin_list[-1]['module'].__name__}/{plugin_list[-1]['name']}")
|
|
625
608
|
except ModuleNotFoundError:
|
|
626
609
|
pass
|
|
627
610
|
|
|
628
|
-
# check if modules are importable
|
|
629
|
-
for mod in plugin_list:
|
|
630
|
-
try:
|
|
631
|
-
plugin_type = mod['type']
|
|
632
|
-
if plugin_type == 'daq_move':
|
|
633
|
-
submodule = mod['module']
|
|
634
|
-
importlib.import_module(f'{submodule.__package__}.daq_move_{mod["name"]}')
|
|
635
|
-
else:
|
|
636
|
-
submodule = mod['module']
|
|
637
|
-
importlib.import_module(f'{submodule.__package__}.daq_{plugin_type[4:6]}viewer_{mod["name"]}')
|
|
638
|
-
plugins_import.append(mod)
|
|
639
|
-
except Exception as e: # pragma: no cover
|
|
640
|
-
"""If an error is generated at the import, then exclude this plugin"""
|
|
641
|
-
logger.debug(f'Impossible to import Instrument plugin {mod["name"]}'
|
|
642
|
-
f' from module: {mod["parent_module"].__package__}')
|
|
643
611
|
except Exception as e: # pragma: no cover
|
|
644
612
|
logger.debug(str(e))
|
|
645
|
-
|
|
613
|
+
|
|
614
|
+
for mod in plugin_list:
|
|
615
|
+
try:
|
|
616
|
+
plugin_type = mod['type']
|
|
617
|
+
if plugin_type == 'daq_move':
|
|
618
|
+
submodule = mod['module']
|
|
619
|
+
importlib.import_module(f'{submodule.__package__}.daq_move_{mod["name"]}')
|
|
620
|
+
else:
|
|
621
|
+
submodule = mod['module']
|
|
622
|
+
importlib.import_module(f'{submodule.__package__}.daq_{plugin_type[4:6]}viewer_{mod["name"]}')
|
|
623
|
+
plugins_import.append(mod)
|
|
624
|
+
logger.info(f"{mod['module'].__name__}/{mod['name']} available")
|
|
625
|
+
except Exception as e: # pragma: no cover
|
|
626
|
+
"""If an error is generated at the import, then exclude this plugin"""
|
|
627
|
+
logger.debug(f'Impossible to import Instrument plugin {mod["name"]}'
|
|
628
|
+
f' from module: {mod["parent_module"].__package__}')
|
|
629
|
+
|
|
630
|
+
|
|
646
631
|
# add utility plugin for PID
|
|
647
632
|
try:
|
|
648
633
|
pidmodule = importlib.import_module('pymodaq.extensions.pid')
|
|
@@ -658,6 +643,7 @@ def get_instrument_plugins(): # pragma: no cover
|
|
|
658
643
|
|
|
659
644
|
return plugins_import
|
|
660
645
|
|
|
646
|
+
|
|
661
647
|
def get_plugins(plugin_type='daq_0Dviewer'): # pragma: no cover
|
|
662
648
|
"""
|
|
663
649
|
Get plugins names as a list
|
|
@@ -766,91 +752,6 @@ def get_new_file_name(base_path=Path(config('data_saving', 'h5file', 'save_path'
|
|
|
766
752
|
return file, curr_dir
|
|
767
753
|
|
|
768
754
|
|
|
769
|
-
# ##############
|
|
770
|
-
# Math utilities
|
|
771
|
-
# math utility functions, should now be imported from the math_utils module
|
|
772
|
-
import pymodaq.utils.math_utils as mutils
|
|
773
|
-
|
|
774
|
-
def my_moment(x, y):
|
|
775
|
-
deprecation_msg(f'my_moment function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
776
|
-
return mutils.my_moment(x, y)
|
|
777
|
-
|
|
778
|
-
def normalize(x):
|
|
779
|
-
deprecation_msg(f'normalize function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
780
|
-
return mutils.normalize(x)
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
def odd_even(x):
|
|
784
|
-
deprecation_msg(f'odd_even function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
785
|
-
return mutils.odd_even(x)
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
def greater2n(x):
|
|
789
|
-
deprecation_msg(f'greater2n function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
790
|
-
return mutils.greater2n(x)
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
def linspace_step(start, stop, step):
|
|
794
|
-
deprecation_msg(f'linspace_step function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
795
|
-
return mutils.linspace_step(start, stop, step)
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
def linspace_step_N(start, step, Npts):
|
|
799
|
-
deprecation_msg(f'linspace_step_N function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
800
|
-
return mutils.linspace_step_N(start, step, Npts)
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
def find_index(x, threshold):
|
|
804
|
-
deprecation_msg(f'find_index function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
805
|
-
return mutils.find_index(x, threshold)
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
def find_common_index(x, y, x0, y0):
|
|
809
|
-
deprecation_msg(f'find_common_index function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
810
|
-
return mutils.find_common_index(x, y, x0, y0)
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
def gauss1D(x, x0, dx, n=1):
|
|
814
|
-
deprecation_msg(f'gauss1D function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
815
|
-
return mutils.gauss1D(x, x0, dx, n=n)
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
def gauss2D(x, x0, dx, y, y0, dy, n=1, angle=0):
|
|
819
|
-
deprecation_msg(f'gauss2D function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
820
|
-
return mutils.gauss2D(x, x0, dx, y, y0, dy, n, angle)
|
|
821
|
-
|
|
822
|
-
def ftAxis(Npts, omega_max):
|
|
823
|
-
deprecation_msg(f'ftAxis function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
824
|
-
return mutils.ftAxis(Npts, omega_max)
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
def ftAxis_time(Npts, time_max):
|
|
828
|
-
deprecation_msg(f'ftAxis_time function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
829
|
-
return mutils.ftAxis_time(Npts, time_max)
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
def ft(x, dim=-1):
|
|
833
|
-
deprecation_msg(f'ft function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
834
|
-
return mutils.ft(x, dim)
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
def ift(x, dim=0):
|
|
838
|
-
deprecation_msg(f'ift function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
839
|
-
return mutils.ift(x, dim)
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
def ft2(x, dim=(-2, -1)):
|
|
843
|
-
deprecation_msg(f'ft2 function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
844
|
-
return mutils.ft2(x, dim)
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
def ift2(x, dim=(-2, -1)):
|
|
848
|
-
deprecation_msg(f'ift2 function should now be imported from the {mutils.__name__} module', stacklevel=3)
|
|
849
|
-
return mutils.ift2(x, dim)
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
755
|
if __name__ == '__main__':
|
|
855
756
|
#paths = recursive_find_expr_in_files('C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git', 'visa')
|
|
856
757
|
# for p in paths:
|