pymodaq 3.6.12__py3-none-any.whl → 4.0.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 +13 -6
- pymodaq/control_modules/__init__.py +0 -7
- pymodaq/control_modules/daq_move.py +965 -2
- pymodaq/control_modules/daq_move_ui.py +319 -0
- pymodaq/control_modules/daq_viewer.py +1573 -3
- pymodaq/control_modules/daq_viewer_ui.py +393 -0
- pymodaq/control_modules/mocks.py +51 -0
- pymodaq/control_modules/move_utility_classes.py +709 -8
- pymodaq/control_modules/utils.py +256 -0
- pymodaq/control_modules/viewer_utility_classes.py +663 -6
- pymodaq/daq_utils.py +89 -0
- pymodaq/dashboard.py +91 -72
- pymodaq/examples/custom_app.py +12 -11
- pymodaq/examples/custom_viewer.py +10 -10
- pymodaq/examples/function_plotter.py +16 -13
- pymodaq/examples/nonlinearscanner.py +8 -6
- pymodaq/examples/parameter_ex.py +7 -7
- pymodaq/examples/preset_MockCamera.xml +1 -0
- pymodaq/extensions/__init__.py +16 -0
- pymodaq/extensions/console.py +76 -0
- pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
- pymodaq/extensions/daq_scan.py +1339 -0
- pymodaq/extensions/daq_scan_ui.py +240 -0
- pymodaq/extensions/h5browser.py +23 -0
- pymodaq/{pid → extensions/pid}/__init__.py +4 -2
- pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
- pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
- pymodaq/{pid → extensions/pid}/utils.py +52 -6
- pymodaq/extensions/utils.py +40 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
- pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
- pymodaq/post_treatment/load_and_plot.py +219 -0
- pymodaq/post_treatment/process_to_scalar.py +263 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
- pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +32 -13
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
- pymodaq/utils/__init__.py +0 -29
- pymodaq/utils/abstract/__init__.py +48 -0
- pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
- pymodaq/utils/array_manipulation.py +379 -8
- pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
- pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
- pymodaq/utils/config.py +448 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +828 -8
- pymodaq/utils/data.py +1873 -7
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
- pymodaq/{daq_utils → utils}/enums.py +12 -7
- pymodaq/utils/exceptions.py +37 -0
- pymodaq/utils/factory.py +82 -0
- pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
- pymodaq/utils/gui_utils/custom_app.py +129 -0
- pymodaq/utils/gui_utils/file_io.py +66 -0
- pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
- pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
- pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
- pymodaq/utils/gui_utils/widgets/label.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
- pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
- pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
- pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
- pymodaq/utils/h5modules/__init__.py +1 -0
- pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
- pymodaq/utils/h5modules/browsing.py +683 -0
- pymodaq/utils/h5modules/data_saving.py +839 -0
- pymodaq/utils/h5modules/h5logging.py +110 -0
- pymodaq/utils/h5modules/module_saving.py +350 -0
- pymodaq/utils/h5modules/saving.py +914 -0
- pymodaq/utils/h5modules/utils.py +85 -0
- pymodaq/utils/logger.py +64 -6
- pymodaq/utils/managers/action_manager.py +460 -0
- pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
- pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
- pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
- pymodaq/utils/managers/parameter_manager.py +110 -0
- pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
- pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
- pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
- pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
- pymodaq/utils/math_utils.py +546 -10
- pymodaq/{daq_utils → utils}/messenger.py +5 -1
- pymodaq/utils/parameter/__init__.py +2 -15
- pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
- pymodaq/utils/parameter/utils.py +206 -11
- pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
- pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
- pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
- pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
- pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
- pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
- pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
- pymodaq/utils/plotting/navigator.py +355 -0
- pymodaq/utils/plotting/scan_selector.py +480 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
- pymodaq/utils/plotting/utils/filter.py +538 -0
- pymodaq/utils/plotting/utils/lineout.py +224 -0
- pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
- pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
- pymodaq/utils/plotting/widgets.py +76 -0
- pymodaq/utils/scanner/__init__.py +10 -0
- pymodaq/utils/scanner/scan_factory.py +204 -0
- pymodaq/utils/scanner/scanner.py +271 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
- pymodaq/utils/scanner/scanners/sequential.py +192 -0
- pymodaq/utils/scanner/scanners/tabular.py +294 -0
- pymodaq/utils/scanner/utils.py +83 -0
- pymodaq/utils/slicing.py +47 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +51 -0
- pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
- pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
- pymodaq/utils/units.py +216 -0
- pymodaq-4.0.1.dist-info/METADATA +159 -0
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
- pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
- pymodaq/daq_move/daq_move_gui.py +0 -279
- pymodaq/daq_move/daq_move_gui.ui +0 -534
- pymodaq/daq_move/daq_move_main.py +0 -1042
- pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
- pymodaq/daq_move/utility_classes.py +0 -671
- pymodaq/daq_scan.py +0 -2160
- pymodaq/daq_utils/array_manipulation.py +0 -386
- pymodaq/daq_utils/config.py +0 -273
- pymodaq/daq_utils/conftests.py +0 -7
- pymodaq/daq_utils/custom_parameter_tree.py +0 -9
- pymodaq/daq_utils/daq_enums.py +0 -133
- pymodaq/daq_utils/daq_utils.py +0 -1402
- pymodaq/daq_utils/exceptions.py +0 -71
- pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
- pymodaq/daq_utils/gui_utils/file_io.py +0 -75
- pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
- pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
- pymodaq/daq_utils/h5exporters.py +0 -242
- pymodaq/daq_utils/h5modules.py +0 -1559
- pymodaq/daq_utils/h5utils.py +0 -241
- pymodaq/daq_utils/managers/action_manager.py +0 -236
- pymodaq/daq_utils/managers/parameter_manager.py +0 -57
- pymodaq/daq_utils/math_utils.py +0 -705
- pymodaq/daq_utils/parameter/__init__.py +0 -1
- pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
- pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
- pymodaq/daq_utils/parameter/utils.py +0 -136
- pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
- pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
- pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
- pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
- pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
- pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
- pymodaq/daq_utils/plotting/items/__init__.py +0 -0
- pymodaq/daq_utils/plotting/navigator.py +0 -500
- pymodaq/daq_utils/plotting/scan_selector.py +0 -289
- pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
- pymodaq/daq_utils/plotting/utils/filter.py +0 -236
- pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
- pymodaq/daq_utils/scanner.py +0 -1289
- pymodaq/daq_utils/tree_layout/__init__.py +0 -0
- pymodaq/daq_viewer/__init__.py +0 -0
- pymodaq/daq_viewer/daq_gui_settings.py +0 -237
- pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
- pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
- pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
- pymodaq/daq_viewer/utility_classes.py +0 -673
- pymodaq/examples/logger_image/__init__.py +0 -0
- pymodaq/examples/logger_image/logger_displayer.py +0 -121
- pymodaq/examples/logger_image/setup.svg +0 -3119
- pymodaq/examples/logger_image/setup_svg.py +0 -114
- pymodaq/h5browser.py +0 -39
- pymodaq/utils/scanner.py +0 -15
- pymodaq-3.6.12.dist-info/METADATA +0 -39
- pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.12.dist-info/top_level.txt +0 -1
- /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
- /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
- /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
- /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
- /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
- /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
- /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
- /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 15/11/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from pymodaq.utils.logger import set_logger, get_module_name, get_module_name
|
|
12
|
+
from pymodaq.utils.config import Config
|
|
13
|
+
|
|
14
|
+
from pymodaq.utils.abstract.logger import AbstractLogger
|
|
15
|
+
from pymodaq.utils import daq_utils as utils
|
|
16
|
+
from .saving import H5Saver
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
config = Config()
|
|
20
|
+
|
|
21
|
+
logger = set_logger(get_module_name(__file__))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class H5LogHandler(logging.StreamHandler):
|
|
25
|
+
def __init__(self, h5saver):
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.h5saver = h5saver
|
|
28
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
29
|
+
self.setFormatter(formatter)
|
|
30
|
+
|
|
31
|
+
def emit(self, record):
|
|
32
|
+
msg = self.format(record)
|
|
33
|
+
self.h5saver.add_log(msg)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class H5Logger(AbstractLogger):
|
|
37
|
+
def __init__(self, *args, **kwargs):
|
|
38
|
+
self.h5saver = H5Saver(*args, save_type='logger', **kwargs)
|
|
39
|
+
|
|
40
|
+
def close(self):
|
|
41
|
+
self.h5saver.close_file()
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def settings_tree(self):
|
|
45
|
+
return self.h5saver.settings_tree
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def settings(self):
|
|
49
|
+
return self.h5saver.settings
|
|
50
|
+
|
|
51
|
+
def init_logger(self, settings):
|
|
52
|
+
self.h5saver.init_file(update_h5=True, metadata=dict(settings=settings))
|
|
53
|
+
self.h5saver.flush()
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
def get_handler(self):
|
|
57
|
+
return H5LogHandler(self.h5saver)
|
|
58
|
+
|
|
59
|
+
def add_detector(self, name, settings):
|
|
60
|
+
if name not in self.h5saver.raw_group.children_name():
|
|
61
|
+
group = self.h5saver.add_det_group(self.h5saver.raw_group, name, settings)
|
|
62
|
+
self.h5saver.add_navigation_axis(np.array([0.0, ]),
|
|
63
|
+
group, 'time_axis', enlargeable=True,
|
|
64
|
+
title='Time axis',
|
|
65
|
+
metadata=dict(label='Time axis', units='s', nav_index=0))
|
|
66
|
+
|
|
67
|
+
def add_actuator(self, name, settings):
|
|
68
|
+
if name not in self.h5saver.raw_group.children_name():
|
|
69
|
+
group = self.h5saver.add_move_group(self.h5saver.raw_group, name, settings)
|
|
70
|
+
self.h5saver.add_navigation_axis(np.array([0.0, ]),
|
|
71
|
+
group, 'time_axis', enlargeable=True,
|
|
72
|
+
title='Time axis',
|
|
73
|
+
metadata=dict(label='Time axis', units='s', nav_index=0))
|
|
74
|
+
|
|
75
|
+
def add_data(self, data):
|
|
76
|
+
name = data['name']
|
|
77
|
+
group = self.h5saver.get_group_by_title(self.h5saver.raw_group, name)
|
|
78
|
+
time_array = self.h5saver.get_node(group, 'Logger_time_axis')
|
|
79
|
+
time_array.append(np.array([data['acq_time_s']]))
|
|
80
|
+
|
|
81
|
+
data_types = ['data0D', 'data1D']
|
|
82
|
+
if self.settings['save_2D']:
|
|
83
|
+
data_types.extend(['data2D', 'dataND'])
|
|
84
|
+
|
|
85
|
+
for data_type in data_types:
|
|
86
|
+
if data_type in data.keys() and len(data[data_type]) != 0:
|
|
87
|
+
if not self.h5saver.is_node_in_group(group, data_type):
|
|
88
|
+
data_group = self.h5saver.add_data_group(group, data_type, metadata=dict(type='scan'))
|
|
89
|
+
else:
|
|
90
|
+
data_group = self.h5saver.get_node(group, utils.capitalize(data_type))
|
|
91
|
+
for ind_channel, channel in enumerate(data[data_type]):
|
|
92
|
+
channel_group = self.h5saver.get_group_by_title(data_group, channel)
|
|
93
|
+
if channel_group is None:
|
|
94
|
+
channel_group = self.h5saver.add_CH_group(data_group, title=channel)
|
|
95
|
+
data_array = self.h5saver.add_data(channel_group, data[data_type][channel],
|
|
96
|
+
scan_type='scan1D', enlargeable=True)
|
|
97
|
+
else:
|
|
98
|
+
data_array = self.h5saver.get_node(channel_group, 'Data')
|
|
99
|
+
if data_type == 'data0D' and not isinstance(data[data_type][channel]['data'], np.ndarray):
|
|
100
|
+
#this is a security as accessing an element in an array can be converted
|
|
101
|
+
# to a scalar... Made some other attempts but found this is the most reliable here.
|
|
102
|
+
logger.debug('Some data seems to not be properly formated as ndarrays')
|
|
103
|
+
data_array.append(np.array([data[data_type][channel]['data']]))
|
|
104
|
+
else:
|
|
105
|
+
data_array.append(data[data_type][channel]['data'])
|
|
106
|
+
self.h5saver.flush()
|
|
107
|
+
self.settings.child('N_saved').setValue(self.settings.child('N_saved').value() + 1)
|
|
108
|
+
|
|
109
|
+
def stop_logger(self):
|
|
110
|
+
self.h5saver.flush()
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 23/11/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Union, List, Dict, Tuple, TYPE_CHECKING
|
|
10
|
+
import xml.etree.ElementTree as ET
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
from pymodaq.utils.abstract import ABCMeta, abstract_attribute, abstractmethod
|
|
16
|
+
from pymodaq.utils.daq_utils import capitalize
|
|
17
|
+
from pymodaq.utils.data import Axis, DataDim, DataWithAxes, DataToExport, DataDistribution
|
|
18
|
+
from .saving import H5SaverLowLevel
|
|
19
|
+
from .backends import GROUP, CARRAY, Node, GroupType
|
|
20
|
+
from .data_saving import DataToExportSaver, AxisSaverLoader, DataToExportTimedSaver, DataToExportExtendedSaver
|
|
21
|
+
from pymodaq.utils.parameter import ioxml
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from pymodaq.extensions.daq_scan import DAQScan
|
|
25
|
+
from pymodaq.control_modules.daq_viewer import DAQ_Viewer
|
|
26
|
+
from pymodaq.control_modules.daq_move import DAQ_Move
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ModuleSaver(metaclass=ABCMeta):
|
|
30
|
+
"""Abstract base class to save info and data from main modules (DAQScan, DAQViewer, DAQMove, ...)"""
|
|
31
|
+
group_type: GroupType = abstract_attribute()
|
|
32
|
+
_module = abstract_attribute()
|
|
33
|
+
_h5saver: H5SaverLowLevel = abstract_attribute()
|
|
34
|
+
_module_group: GROUP = abstract_attribute()
|
|
35
|
+
main_module = True
|
|
36
|
+
|
|
37
|
+
def get_set_node(self, where: Union[Node, str] = None, name: str = None) -> GROUP:
|
|
38
|
+
"""Get the node corresponding to this particular Module instance
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
where: Union[Node, str]
|
|
43
|
+
the path of a given node or the node itself
|
|
44
|
+
new: bool
|
|
45
|
+
if True force the creation of a new indexed node of this class type
|
|
46
|
+
if False return the last node (or create one if None)
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
GROUP: the Node associated with this module which should be a GROUP node
|
|
51
|
+
"""
|
|
52
|
+
if where is None:
|
|
53
|
+
where = self._h5saver.raw_group
|
|
54
|
+
if name is None:
|
|
55
|
+
name = self._module.title
|
|
56
|
+
group = self._h5saver.get_node_from_title(where, name)
|
|
57
|
+
if group is not None:
|
|
58
|
+
self._module_group = group
|
|
59
|
+
return group # if I got one I return it else I create one
|
|
60
|
+
|
|
61
|
+
self._module_group = self._add_module(where)
|
|
62
|
+
return self._module_group
|
|
63
|
+
|
|
64
|
+
def get_last_node(self, where: Union[Node, str] = None):
|
|
65
|
+
"""Get the last node corresponding to this particular Module instance
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
where: Union[Node, str]
|
|
70
|
+
the path of a given node or the node itself
|
|
71
|
+
new: bool
|
|
72
|
+
if True force the creation of a new indexed node of this class type
|
|
73
|
+
if False return the last node (or create one if None)
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
GROUP: the Node associated with this module which should be a GROUP node
|
|
78
|
+
"""
|
|
79
|
+
if where is None:
|
|
80
|
+
where = self._h5saver.raw_group
|
|
81
|
+
|
|
82
|
+
group = self._h5saver.get_last_group(where, self.group_type)
|
|
83
|
+
self._module_group = group
|
|
84
|
+
return self._module_group
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def _add_module(self, where: Union[Node, str] = None, metadata={}):
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def module(self):
|
|
92
|
+
return self._module
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def module_group(self):
|
|
96
|
+
return self._module_group
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def h5saver(self):
|
|
100
|
+
return self._h5saver
|
|
101
|
+
|
|
102
|
+
@h5saver.setter
|
|
103
|
+
def h5saver(self, _h5saver: H5SaverLowLevel):
|
|
104
|
+
self._h5saver = _h5saver
|
|
105
|
+
self.update_after_h5changed()
|
|
106
|
+
|
|
107
|
+
@abstractmethod
|
|
108
|
+
def update_after_h5changed(self):
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
def get_last_node_index(self, where: Union[Node, str] = None):
|
|
112
|
+
node = self.get_last_node(where)
|
|
113
|
+
return int(node.name.split(capitalize(self.group_type.name))[1])
|
|
114
|
+
|
|
115
|
+
def get_next_node_name(self, where: Union[Node, str] = None):
|
|
116
|
+
index = self.get_last_node_index(where)
|
|
117
|
+
return f'{capitalize(self.group_type.name)}{index+1:03d}'
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class DetectorSaver(ModuleSaver):
|
|
121
|
+
"""Implementation of the ModuleSaver class dedicated to DAQ_Viewer modules
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
module
|
|
126
|
+
"""
|
|
127
|
+
group_type = GroupType['detector']
|
|
128
|
+
|
|
129
|
+
def __init__(self, module: DAQ_Viewer):
|
|
130
|
+
self._datatoexport_saver: DataToExportSaver = None
|
|
131
|
+
|
|
132
|
+
self._module: 'DAQ_Viewer' = module
|
|
133
|
+
self._module_group: GROUP = None
|
|
134
|
+
self._h5saver = None
|
|
135
|
+
|
|
136
|
+
def update_after_h5changed(self, ):
|
|
137
|
+
self._datatoexport_saver = DataToExportSaver(self.h5saver)
|
|
138
|
+
|
|
139
|
+
def _add_module(self, where: Union[Node, str] = None, metadata={}) -> Node:
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
where: Union[Node, str]
|
|
145
|
+
the path of a given node or the node itself
|
|
146
|
+
metadata: dict
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
if where is None:
|
|
153
|
+
where = self._h5saver.raw_group
|
|
154
|
+
|
|
155
|
+
settings_xml = ET.Element('All_settings', type='group')
|
|
156
|
+
settings_xml.append(ioxml.walk_parameters_to_xml(param=self._module.settings))
|
|
157
|
+
if self.main_module:
|
|
158
|
+
saver_xml = ET.SubElement(settings_xml, 'H5Saver', type='group')
|
|
159
|
+
saver_xml.append(ioxml.walk_parameters_to_xml(param=self._h5saver.settings))
|
|
160
|
+
|
|
161
|
+
if self._module.ui is not None:
|
|
162
|
+
for ind, viewer in enumerate(self._module.viewers):
|
|
163
|
+
if hasattr(viewer, 'roi_manager'):
|
|
164
|
+
roi_xml = ET.SubElement(settings_xml, f'ROI_Viewer_{ind:02d}', type='group')
|
|
165
|
+
roi_xml.append(ioxml.walk_parameters_to_xml(param=viewer.roi_manager.settings))
|
|
166
|
+
|
|
167
|
+
return self._h5saver.add_det_group(where, title=self._module.title, settings_as_xml=ET.tostring(settings_xml),
|
|
168
|
+
metadata=metadata)
|
|
169
|
+
|
|
170
|
+
def add_data(self, where: Union[Node, str], data: DataToExport):
|
|
171
|
+
self._datatoexport_saver.add_data(where, data)
|
|
172
|
+
|
|
173
|
+
def add_bkg(self, where: Union[Node, str], data_bkg: DataToExport):
|
|
174
|
+
self._datatoexport_saver.add_bkg(where, data_bkg)
|
|
175
|
+
|
|
176
|
+
def add_external_h5(self, other_h5data: H5SaverLowLevel):
|
|
177
|
+
if other_h5data is not None:
|
|
178
|
+
external_group = self._h5saver.add_group('external_data', 'external_h5', self.module_group)
|
|
179
|
+
try:
|
|
180
|
+
if not other_h5data.isopen:
|
|
181
|
+
h5saver = H5SaverLowLevel()
|
|
182
|
+
h5saver.init_file(addhoc_file_path=other_h5data.filename)
|
|
183
|
+
h5_file = h5saver.h5_file
|
|
184
|
+
else:
|
|
185
|
+
h5_file = other_h5data
|
|
186
|
+
h5_file.copy_children(h5_file.get_node('/'), external_group, recursive=True)
|
|
187
|
+
h5_file.flush()
|
|
188
|
+
h5_file.close()
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
self.logger.exception(str(e))
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class DetectorEnlargeableSaver(DetectorSaver):
|
|
195
|
+
"""Implementation of the ModuleSaver class dedicated to DAQ_Viewer modules in order to save enlargeable data
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
module
|
|
200
|
+
"""
|
|
201
|
+
group_type = GroupType['detector']
|
|
202
|
+
|
|
203
|
+
def __init__(self, module: DAQ_Viewer):
|
|
204
|
+
super().__init__(module)
|
|
205
|
+
self._datatoexport_saver: DataToExportTimedSaver = None
|
|
206
|
+
|
|
207
|
+
def update_after_h5changed(self, ):
|
|
208
|
+
self._datatoexport_saver = DataToExportTimedSaver(self.h5saver)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class DetectorExtendedSaver(DetectorSaver):
|
|
212
|
+
"""Implementation of the ModuleSaver class dedicated to DAQ_Viewer modules in order to save enlargeable data
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
module
|
|
217
|
+
"""
|
|
218
|
+
group_type = GroupType['detector']
|
|
219
|
+
|
|
220
|
+
def __init__(self, module: DAQ_Viewer, extended_shape: Tuple[int]):
|
|
221
|
+
super().__init__(module)
|
|
222
|
+
self._extended_shape = extended_shape
|
|
223
|
+
self._datatoexport_saver: DataToExportExtendedSaver = None
|
|
224
|
+
|
|
225
|
+
def update_after_h5changed(self, ):
|
|
226
|
+
self._datatoexport_saver = DataToExportExtendedSaver(self.h5saver, self._extended_shape)
|
|
227
|
+
|
|
228
|
+
def add_data(self, where: Union[Node, str], data: DataToExport, indexes: Tuple[int],
|
|
229
|
+
distribution=DataDistribution['uniform']):
|
|
230
|
+
self._datatoexport_saver.add_data(where, data, indexes=indexes, distribution=distribution)
|
|
231
|
+
|
|
232
|
+
def add_nav_axes(self, where: Union[Node, str], axes: List[Axis]):
|
|
233
|
+
self._datatoexport_saver.add_nav_axes(where, axes)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class ActuatorSaver(ModuleSaver):
|
|
237
|
+
"""Implementation of the ModuleSaver class dedicated to DAQ_Move modules
|
|
238
|
+
|
|
239
|
+
Parameters
|
|
240
|
+
----------
|
|
241
|
+
h5saver
|
|
242
|
+
module
|
|
243
|
+
"""
|
|
244
|
+
group_type = GroupType['actuator']
|
|
245
|
+
|
|
246
|
+
def __init__(self, module: DAQ_Move):
|
|
247
|
+
self._axis_saver = None
|
|
248
|
+
self._module_group: GROUP = None
|
|
249
|
+
self._module: DAQ_Move = module
|
|
250
|
+
self._h5saver = None
|
|
251
|
+
|
|
252
|
+
def update_after_h5changed(self):
|
|
253
|
+
self._axis_saver = AxisSaverLoader(self.h5saver)
|
|
254
|
+
|
|
255
|
+
def _add_module(self, where: Union[Node, str] = None, metadata={}):
|
|
256
|
+
if where is None:
|
|
257
|
+
where = self._h5saver.raw_group
|
|
258
|
+
|
|
259
|
+
settings_xml = ET.Element('All_settings')
|
|
260
|
+
settings_xml.append(ioxml.walk_parameters_to_xml(param=self._module.settings))
|
|
261
|
+
|
|
262
|
+
return self._h5saver.add_act_group(where, title=self._module.title, settings_as_xml=ET.tostring(settings_xml),
|
|
263
|
+
metadata=metadata)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class ScanSaver(ModuleSaver):
|
|
267
|
+
"""Implementation of the ModuleSaver class dedicated to DAQScan module
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
h5saver
|
|
272
|
+
module
|
|
273
|
+
"""
|
|
274
|
+
group_type = GroupType['scan']
|
|
275
|
+
|
|
276
|
+
def __init__(self, module):
|
|
277
|
+
self._module_group: GROUP = None
|
|
278
|
+
self._module: 'DAQScan' = module
|
|
279
|
+
self._h5saver = None
|
|
280
|
+
|
|
281
|
+
def update_after_h5changed(self):
|
|
282
|
+
for module in self._module.modules_manager.modules_all:
|
|
283
|
+
if hasattr(module, 'module_and_data_saver'):
|
|
284
|
+
module.module_and_data_saver.h5saver = self.h5saver
|
|
285
|
+
|
|
286
|
+
def get_set_node(self, where: Union[Node, str] = None, new=False) -> GROUP:
|
|
287
|
+
"""Get the last group scan node
|
|
288
|
+
|
|
289
|
+
Get the last Scan Group or create one
|
|
290
|
+
get the last Scan Group if:
|
|
291
|
+
* there is one already created
|
|
292
|
+
* new is False
|
|
293
|
+
|
|
294
|
+
Parameters
|
|
295
|
+
----------
|
|
296
|
+
where: Union[Node, str]
|
|
297
|
+
the path of a given node or the node itself
|
|
298
|
+
new: bool
|
|
299
|
+
|
|
300
|
+
Returns
|
|
301
|
+
-------
|
|
302
|
+
GROUP: the GROUP associated with this module
|
|
303
|
+
"""
|
|
304
|
+
self._module_group = self.get_last_node(where)
|
|
305
|
+
new = new or (self._module_group is None)
|
|
306
|
+
if new:
|
|
307
|
+
self._module_group = self._add_module(where)
|
|
308
|
+
for module in self._module.modules_manager.modules:
|
|
309
|
+
module.module_and_data_saver.main_module = False
|
|
310
|
+
module.module_and_data_saver.get_set_node(self._module_group)
|
|
311
|
+
return self._module_group
|
|
312
|
+
|
|
313
|
+
def _add_module(self, where: Union[Node, str] = None, metadata={}) -> Node:
|
|
314
|
+
"""
|
|
315
|
+
|
|
316
|
+
Parameters
|
|
317
|
+
----------
|
|
318
|
+
where: Union[Node, str]
|
|
319
|
+
the path of a given node or the node itself
|
|
320
|
+
metadata: dict
|
|
321
|
+
|
|
322
|
+
Returns
|
|
323
|
+
-------
|
|
324
|
+
|
|
325
|
+
"""
|
|
326
|
+
if where is None:
|
|
327
|
+
where = self._h5saver.raw_group
|
|
328
|
+
|
|
329
|
+
settings_xml = ET.Element('All_settings', type='group')
|
|
330
|
+
settings_xml.append(ioxml.walk_parameters_to_xml(param=self._module.settings))
|
|
331
|
+
if self.main_module:
|
|
332
|
+
saver_xml = ET.SubElement(settings_xml, 'H5Saver', type='group')
|
|
333
|
+
saver_xml.append(ioxml.walk_parameters_to_xml(param=self._h5saver.settings))
|
|
334
|
+
|
|
335
|
+
return self._h5saver.add_scan_group(where, title=self._module.title,
|
|
336
|
+
settings_as_xml=ET.tostring(settings_xml),
|
|
337
|
+
metadata=metadata)
|
|
338
|
+
|
|
339
|
+
def add_nav_axes(self, axes: List[Axis]):
|
|
340
|
+
for detector in self._module.modules_manager.detectors:
|
|
341
|
+
detector.module_and_data_saver.add_nav_axes(self._module_group, axes)
|
|
342
|
+
|
|
343
|
+
def add_data(self, indexes: Tuple[int] = None, distribution=DataDistribution['uniform']):
|
|
344
|
+
for detector in self._module.modules_manager.detectors:
|
|
345
|
+
try:
|
|
346
|
+
detector.insert_data(indexes, where=self._module_group, distribution=distribution)
|
|
347
|
+
except Exception as e:
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
|