pymodaq 3.6.13__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.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.13.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 -686
- 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.13.dist-info/METADATA +0 -39
- pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.13.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.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
pymodaq/daq_utils/h5utils.py
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
# Standard imports
|
|
2
|
-
from collections import OrderedDict
|
|
3
|
-
from typing import List, Dict
|
|
4
|
-
|
|
5
|
-
# 3rd party imports
|
|
6
|
-
import numpy as np
|
|
7
|
-
|
|
8
|
-
# project imports
|
|
9
|
-
from pymodaq.daq_utils.h5backend import Node
|
|
10
|
-
from pymodaq.daq_utils.daq_utils import set_logger, get_module_name
|
|
11
|
-
from pymodaq.daq_utils.daq_utils import capitalize, Axis, NavAxis
|
|
12
|
-
|
|
13
|
-
logger = set_logger(get_module_name(__file__))
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Normally, this function does not rely on a H5Backend object so this is good
|
|
17
|
-
def find_scan_node(scan_node: Node):
|
|
18
|
-
"""
|
|
19
|
-
utility function to find the parent node of "scan" type, meaning some of its children (DAQ_scan case)
|
|
20
|
-
or co-nodes (daq_logger case) are navigation axes
|
|
21
|
-
Parameters
|
|
22
|
-
----------
|
|
23
|
-
scan_node: (pytables node)
|
|
24
|
-
data node from where this function look for its navigation axes if any
|
|
25
|
-
Returns
|
|
26
|
-
-------
|
|
27
|
-
node: the parent node of 'scan' type
|
|
28
|
-
list: the data nodes of type 'navigation_axis' corresponding to the initial data node
|
|
29
|
-
|
|
30
|
-
"""
|
|
31
|
-
try:
|
|
32
|
-
while True:
|
|
33
|
-
if scan_node.attrs['type'] == 'scan':
|
|
34
|
-
break
|
|
35
|
-
else:
|
|
36
|
-
scan_node = scan_node.parent_node
|
|
37
|
-
children = list(scan_node.children().values()) # for data saved using daq_scan
|
|
38
|
-
# How is it any different from list(scan_node.parent_node.children().values()) ???
|
|
39
|
-
children.extend([scan_node.parent_node.children()[child] for child in
|
|
40
|
-
scan_node.parent_node.children_name()]) # for data saved using the daq_logger
|
|
41
|
-
nav_children = []
|
|
42
|
-
for child in children:
|
|
43
|
-
if 'type' in child.attrs.attrs_name:
|
|
44
|
-
if child.attrs['type'] == 'navigation_axis':
|
|
45
|
-
nav_children.append(child)
|
|
46
|
-
return scan_node, nav_children
|
|
47
|
-
except Exception:
|
|
48
|
-
return None, []
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def get_h5_attributes(self, node_path):
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
node = self.get_node(node_path)
|
|
56
|
-
attrs_names = node.attrs.attrs_name
|
|
57
|
-
attr_dict = OrderedDict([])
|
|
58
|
-
for attr in attrs_names:
|
|
59
|
-
# if attr!='settings':
|
|
60
|
-
attr_dict[attr] = node.attrs[attr]
|
|
61
|
-
|
|
62
|
-
settings = None
|
|
63
|
-
scan_settings = None
|
|
64
|
-
if 'settings' in attrs_names:
|
|
65
|
-
if node.attrs['settings'] != '':
|
|
66
|
-
settings = node.attrs['settings']
|
|
67
|
-
|
|
68
|
-
if 'scan_settings' in attrs_names:
|
|
69
|
-
if node.attrs['scan_settings'] != '':
|
|
70
|
-
scan_settings = node.attrs['scan_settings']
|
|
71
|
-
pixmaps = []
|
|
72
|
-
for attr in attrs_names:
|
|
73
|
-
if 'pixmap' in attr:
|
|
74
|
-
pixmaps.append(node.attrs[attr])
|
|
75
|
-
|
|
76
|
-
return attr_dict, settings, scan_settings, pixmaps
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
# This is a get_h5_data rewritten to remove dependency on a H5Backend object
|
|
80
|
-
def get_h5_data_from_node(node: Node) -> (np.ndarray, Dict[str, Axis], List[Axis], bool):
|
|
81
|
-
"""Check if there exist a data in the node, and if yes get the relevant axes.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
is_spread = False
|
|
85
|
-
# checks If the node contains an array. Effectively, if the node is a 'CARRAY', 'EARRAY' etc.
|
|
86
|
-
# if that's not the case we return some empty data
|
|
87
|
-
if 'ARRAY' not in node.attrs['CLASS']:
|
|
88
|
-
logger.warning(f'node {node} does not host a dataset.')
|
|
89
|
-
return np.array([]), [], [], is_spread
|
|
90
|
-
|
|
91
|
-
# Otherwise Axis node is an ARRAY subclass which implements read() and has a GROUP parent node
|
|
92
|
-
data = node.read()
|
|
93
|
-
nav_axes = []
|
|
94
|
-
axes = dict([])
|
|
95
|
-
if isinstance(data, np.ndarray):
|
|
96
|
-
data = np.squeeze(data)
|
|
97
|
-
if 'Bkg' in node.parent_node.children_name() and node.name != 'Bkg':
|
|
98
|
-
parent_group = node.parent_node # This should be a group object if I get how this works
|
|
99
|
-
# Then the parent node should have a children method which alllows to get the background.
|
|
100
|
-
bkg_node = parent_group.children()['Bkg']
|
|
101
|
-
bkg = np.squeeze(bkg_node.read())
|
|
102
|
-
# bkg = np.squeeze(self.get_node(node.parent_node.path, 'Bkg').read())
|
|
103
|
-
try:
|
|
104
|
-
data = data - bkg
|
|
105
|
-
except ValueError:
|
|
106
|
-
logger.warning(f'Could not substract bkg from data node {node} as their shape are '
|
|
107
|
-
f'incoherent {bkg.shape} and {data.shape}')
|
|
108
|
-
if 'type' in node.attrs.attrs_name:
|
|
109
|
-
if 'data' in node.attrs['type'] or 'channel' in node.attrs['type'].lower():
|
|
110
|
-
# parent_path = node.parent_node.path
|
|
111
|
-
children_names = node.parent_node.children_name()
|
|
112
|
-
|
|
113
|
-
if 'data_dimension' not in node.attrs.attrs_name: # for backcompatibility
|
|
114
|
-
data_dim = node.attrs['data_type']
|
|
115
|
-
else:
|
|
116
|
-
data_dim = node.attrs['data_dimension']
|
|
117
|
-
if 'scan_subtype' in node.attrs.attrs_name:
|
|
118
|
-
if node.attrs['scan_subtype'].lower() == 'adaptive':
|
|
119
|
-
is_spread = True
|
|
120
|
-
tmp_axes = ['x_axis', 'y_axis']
|
|
121
|
-
for ax in tmp_axes:
|
|
122
|
-
if capitalize(ax) in children_names:
|
|
123
|
-
# Following the same logic as before we should be able to apply this
|
|
124
|
-
axis_node = node.parent_node.children()[capitalize(ax)]
|
|
125
|
-
# axis_node = self.get_node(parent_path + '/{:s}'.format(capitalize(ax)))
|
|
126
|
-
axes[ax] = Axis(data=axis_node.read())
|
|
127
|
-
if 'units' in axis_node.attrs.attrs_name:
|
|
128
|
-
axes[ax]['units'] = axis_node.attrs['units']
|
|
129
|
-
if 'label' in axis_node.attrs.attrs_name:
|
|
130
|
-
axes[ax]['label'] = axis_node.attrs['label']
|
|
131
|
-
else:
|
|
132
|
-
axes[ax] = Axis()
|
|
133
|
-
|
|
134
|
-
if data_dim == 'ND': # check for navigation axis
|
|
135
|
-
tmp_nav_axes = ['y_axis', 'x_axis', ]
|
|
136
|
-
nav_axes = []
|
|
137
|
-
for ind_ax, ax in enumerate(tmp_nav_axes):
|
|
138
|
-
if 'Nav_{:s}'.format(ax) in children_names:
|
|
139
|
-
nav_axes.append(ind_ax)
|
|
140
|
-
axis_node = node.parent_node.children()[f"Nav_{ax}"]
|
|
141
|
-
# axis_node = self.get_node(parent_path + '/Nav_{:s}'.format(ax))
|
|
142
|
-
if is_spread:
|
|
143
|
-
axes['nav_{:s}'.format(ax)] = Axis(data=axis_node.read())
|
|
144
|
-
else:
|
|
145
|
-
axes['nav_{:s}'.format(ax)] = Axis(data=np.unique(axis_node.read()))
|
|
146
|
-
if axes['nav_{:s}'.format(ax)]['data'].shape[0] != data.shape[ind_ax]:
|
|
147
|
-
# could happen in case of linear back to start type of scan
|
|
148
|
-
tmp_ax = []
|
|
149
|
-
for ix in axes['nav_{:s}'.format(ax)]['data']:
|
|
150
|
-
tmp_ax.extend([ix, ix])
|
|
151
|
-
axes['nav_{:s}'.format(ax)] = Axis(data=np.array(tmp_ax))
|
|
152
|
-
|
|
153
|
-
if 'units' in axis_node.attrs.attrs_name:
|
|
154
|
-
axes['nav_{:s}'.format(ax)]['units'] = axis_node.attrs['units']
|
|
155
|
-
if 'label' in axis_node.attrs.attrs_name:
|
|
156
|
-
axes['nav_{:s}'.format(ax)]['label'] = axis_node.attrs['label']
|
|
157
|
-
|
|
158
|
-
if 'scan_type' in node.attrs.attrs_name:
|
|
159
|
-
scan_type = node.attrs['scan_type'].lower()
|
|
160
|
-
# if scan_type == 'scan1d' or scan_type == 'scan2d':
|
|
161
|
-
scan_node, nav_children = find_scan_node(node)
|
|
162
|
-
nav_axes = []
|
|
163
|
-
if scan_type == 'tabular' or is_spread:
|
|
164
|
-
datas = []
|
|
165
|
-
labels = []
|
|
166
|
-
all_units = []
|
|
167
|
-
npts = 2 # Just in case nav_children is empty
|
|
168
|
-
for axis_node in nav_children:
|
|
169
|
-
npts = axis_node.attrs['shape'][0]
|
|
170
|
-
datas.append(axis_node.read())
|
|
171
|
-
labels.append(axis_node.attrs['label'])
|
|
172
|
-
all_units.append(axis_node.attrs['units'])
|
|
173
|
-
|
|
174
|
-
nav_axes.append(0)
|
|
175
|
-
axes['nav_x_axis'] = NavAxis(
|
|
176
|
-
data=np.linspace(0, npts - 1, npts),
|
|
177
|
-
nav_index=nav_axes[-1], units='', label='Scan index', labels=labels,
|
|
178
|
-
datas=datas, all_units=all_units)
|
|
179
|
-
else:
|
|
180
|
-
for axis_node in nav_children:
|
|
181
|
-
nav_axes.append(axis_node.attrs['nav_index'])
|
|
182
|
-
if is_spread:
|
|
183
|
-
axes[f'nav_{nav_axes[-1]:02d}'] = NavAxis(data=axis_node.read(),
|
|
184
|
-
nav_index=nav_axes[-1])
|
|
185
|
-
else:
|
|
186
|
-
axes[f'nav_{nav_axes[-1]:02d}'] = NavAxis(data=np.unique(axis_node.read()),
|
|
187
|
-
nav_index=nav_axes[-1])
|
|
188
|
-
if nav_axes[-1] < len(data.shape):
|
|
189
|
-
if axes[f'nav_{nav_axes[-1]:02d}']['data'].shape[0] != data.shape[nav_axes[-1]]:
|
|
190
|
-
# could happen in case of linear back to start type of scan
|
|
191
|
-
tmp_ax = []
|
|
192
|
-
for ix in axes[f'nav_{nav_axes[-1]:02d}']['data']:
|
|
193
|
-
tmp_ax.extend([ix, ix])
|
|
194
|
-
axes[f'nav_{nav_axes[-1]:02d}'] = NavAxis(data=np.array(tmp_ax),
|
|
195
|
-
nav_index=nav_axes[-1])
|
|
196
|
-
|
|
197
|
-
if 'units' in axis_node.attrs.attrs_name:
|
|
198
|
-
axes[f'nav_{nav_axes[-1]:02d}']['units'] = axis_node.attrs[
|
|
199
|
-
'units']
|
|
200
|
-
if 'label' in axis_node.attrs.attrs_name:
|
|
201
|
-
axes[f'nav_{nav_axes[-1]:02d}']['label'] = axis_node.attrs[
|
|
202
|
-
'label']
|
|
203
|
-
elif 'axis' in node.attrs['type']:
|
|
204
|
-
axis_node = node
|
|
205
|
-
axes['y_axis'] = Axis(data=axis_node.read()) # Axis node should be CARRAY which implements read()
|
|
206
|
-
if 'units' in axis_node.attrs.attrs_name:
|
|
207
|
-
axes['y_axis']['units'] = axis_node.attrs['units']
|
|
208
|
-
if 'label' in axis_node.attrs.attrs_name:
|
|
209
|
-
axes['y_axis']['label'] = axis_node.attrs['label']
|
|
210
|
-
axes['x_axis'] = Axis(
|
|
211
|
-
data=np.linspace(0, axis_node.attrs['shape'][0] - 1, axis_node.attrs['shape'][0]),
|
|
212
|
-
units='pxls',
|
|
213
|
-
label='')
|
|
214
|
-
return data, axes, nav_axes, is_spread
|
|
215
|
-
|
|
216
|
-
elif isinstance(data, list):
|
|
217
|
-
data = np.array(data)
|
|
218
|
-
return data, dict([]), [], is_spread
|
|
219
|
-
|
|
220
|
-
def extract_axis(ax: Axis) -> np.ndarray:
|
|
221
|
-
"""Extract the unique values in a PyMoDAQ axis object in an order-preserving way"""
|
|
222
|
-
axis_data = ax.data
|
|
223
|
-
_, idx = np.unique(axis_data, return_index=True)
|
|
224
|
-
|
|
225
|
-
unique_ax = axis_data[np.sort(idx)]
|
|
226
|
-
|
|
227
|
-
return unique_ax
|
|
228
|
-
|
|
229
|
-
def verify_axis_data_uniformity(axis_data: np.ndarray, tol: float = 1e-6) -> (float, float):
|
|
230
|
-
"""Try fitting the axis data with an affine function. Return offset,slope if the
|
|
231
|
-
result is within tolerances, otherwise return None, None"""
|
|
232
|
-
slope = None
|
|
233
|
-
offset = None
|
|
234
|
-
|
|
235
|
-
index = np.arange(len(axis_data))
|
|
236
|
-
res, residuals, rank, singular_values, rcond = np.polyfit(x=index, y=axis_data, deg=1, full=True) # noqa
|
|
237
|
-
if residuals[0] < tol:
|
|
238
|
-
slope = res[0]
|
|
239
|
-
offset = res[1]
|
|
240
|
-
|
|
241
|
-
return offset, slope
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import pymodaq.daq_utils.messenger
|
|
2
|
-
from multipledispatch import dispatch
|
|
3
|
-
from qtpy import QtGui, QtWidgets, QtCore
|
|
4
|
-
|
|
5
|
-
from qtpy.QtWidgets import QAction
|
|
6
|
-
|
|
7
|
-
from pymodaq.resources.QtDesigner_Ressources import QtDesigner_ressources_rc
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class QAction(QAction):
|
|
12
|
-
"""
|
|
13
|
-
QAction subclass to mimic signals as pushbuttons. Done to be sure of backcompatibility when I moved from
|
|
14
|
-
pushbuttons to QAction
|
|
15
|
-
"""
|
|
16
|
-
def __init__(self, *args, **kwargs):
|
|
17
|
-
super().__init__(*args, **kwargs)
|
|
18
|
-
|
|
19
|
-
def click(self):
|
|
20
|
-
pymodaq.daq_utils.messenger.deprecation_msg("click for PyMoDAQ's QAction is deprecated, use *trigger*",
|
|
21
|
-
stacklevel=3)
|
|
22
|
-
self.trigger()
|
|
23
|
-
|
|
24
|
-
@property
|
|
25
|
-
def clicked(self):
|
|
26
|
-
pymodaq.daq_utils.messenger.deprecation_msg("clicked for PyMoDAQ's QAction is deprecated, use *trigger*",
|
|
27
|
-
stacklevel=3)
|
|
28
|
-
return self.triggered
|
|
29
|
-
|
|
30
|
-
def connect_to(self, slot):
|
|
31
|
-
self.triggered.connect(slot)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def addaction(name='', icon_name='', tip='', checkable=False, slot=None, toolbar=None, menu=None):
|
|
35
|
-
"""Create a new action and add it eventually to a toolbar and a menu
|
|
36
|
-
Parameters
|
|
37
|
-
----------
|
|
38
|
-
name: (str) Displayed name if should be displayed (for instance in menus)
|
|
39
|
-
icon_name: (str) png file name to produce the icon
|
|
40
|
-
tip: (str) a tooltip to be displayed when hovering above the action
|
|
41
|
-
checkable: (bool) set the checkable state of the action
|
|
42
|
-
slot: (callable) Method or function that will be called when the action is triggered
|
|
43
|
-
toolbar: (QToolBar) a toolbar where action should be added.
|
|
44
|
-
menu: (QMenu) a menu where action should be added.
|
|
45
|
-
"""
|
|
46
|
-
if icon_name != '':
|
|
47
|
-
icon = QtGui.QIcon()
|
|
48
|
-
if Path(icon_name).is_file():
|
|
49
|
-
icon.addPixmap(QtGui.QPixmap(icon_name), QtGui.QIcon.Normal,
|
|
50
|
-
QtGui.QIcon.Off)
|
|
51
|
-
else:
|
|
52
|
-
icon.addPixmap(QtGui.QPixmap(f":/icons/Icon_Library/{icon_name}.png"), QtGui.QIcon.Normal,
|
|
53
|
-
QtGui.QIcon.Off)
|
|
54
|
-
action = QAction(icon, name, None)
|
|
55
|
-
else:
|
|
56
|
-
action = QAction(name)
|
|
57
|
-
|
|
58
|
-
if slot is not None:
|
|
59
|
-
action.connect_to(slot)
|
|
60
|
-
action.setCheckable(checkable)
|
|
61
|
-
action.setToolTip(tip)
|
|
62
|
-
if toolbar is not None:
|
|
63
|
-
toolbar.addAction(action)
|
|
64
|
-
if menu is not None:
|
|
65
|
-
menu.addAction(action)
|
|
66
|
-
return action
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class ActionManager:
|
|
70
|
-
"""MixIn Class to be used by all UserInterface to manage their QActions and the action they are connected to"""
|
|
71
|
-
def __init__(self, toolbar=None, menu=None):
|
|
72
|
-
self._actions = dict([])
|
|
73
|
-
self._toolbar = toolbar
|
|
74
|
-
self._menu = menu
|
|
75
|
-
|
|
76
|
-
#self.setup_actions()
|
|
77
|
-
|
|
78
|
-
def setup_actions(self):
|
|
79
|
-
"""
|
|
80
|
-
self.add_action('Quit', 'close2', "Quit program")
|
|
81
|
-
self.add_action('Grab', 'camera', "Grab from camera", checkable=True)
|
|
82
|
-
self.add_action('Load', 'Open', "Load target file (.h5, .png, .jpg) or data from camera", checkable=False)
|
|
83
|
-
self.add_action('Save', 'SaveAs', "Save current data", checkable=False)
|
|
84
|
-
|
|
85
|
-
See Also
|
|
86
|
-
--------
|
|
87
|
-
ActionManager.add_action
|
|
88
|
-
"""
|
|
89
|
-
raise NotImplementedError(f'You have to define actions here in the following form:'
|
|
90
|
-
f'{self.setup_actions.__doc__}')
|
|
91
|
-
|
|
92
|
-
def add_action(self, short_name='', name='', icon_name='', tip='', checkable=False, toolbar=None, menu=None):
|
|
93
|
-
"""Create a new action and add it to toolbar and menu
|
|
94
|
-
Parameters
|
|
95
|
-
----------
|
|
96
|
-
short_name: (str) the name as referenced in the dict self.actions
|
|
97
|
-
name: (str) Displayed name if should be displayed in
|
|
98
|
-
icon_name: (str) png file name to produce the icon
|
|
99
|
-
tip: (str) a tooltip to be displayed when hovering above the action
|
|
100
|
-
checkable: (bool) set the checkable state of the action
|
|
101
|
-
toolbar: (QToolBar) a toolbar where action should be added. Actions can also be added later see *affect_to*
|
|
102
|
-
menu: (QMenu) a menu where action should be added. Actions can also be added later see *affect_to*
|
|
103
|
-
|
|
104
|
-
See Also
|
|
105
|
-
--------
|
|
106
|
-
affect_to: method to affect an action to a toolbar or manu
|
|
107
|
-
pymodaq.resources.QtDesigner_Ressources.Icon_Library: resource for icons png
|
|
108
|
-
pymodaq.daq_utils.managers.action_manager.add_action: base method used here
|
|
109
|
-
"""
|
|
110
|
-
if toolbar is None:
|
|
111
|
-
toolbar = self._toolbar
|
|
112
|
-
if menu is None:
|
|
113
|
-
menu = self._menu
|
|
114
|
-
self._actions[short_name] = addaction(name, icon_name, tip, checkable=checkable, toolbar=toolbar, menu=menu)
|
|
115
|
-
|
|
116
|
-
def set_toolbar(self, toolbar):
|
|
117
|
-
"""
|
|
118
|
-
affect a toolbar to self
|
|
119
|
-
Parameters
|
|
120
|
-
----------
|
|
121
|
-
toolbar: (QtWidgets.QToolBar)
|
|
122
|
-
|
|
123
|
-
"""
|
|
124
|
-
self._toolbar = toolbar
|
|
125
|
-
|
|
126
|
-
def set_menu(self, menu):
|
|
127
|
-
"""
|
|
128
|
-
affect a menu to self
|
|
129
|
-
Parameters
|
|
130
|
-
----------
|
|
131
|
-
menu: (QtWidgets.QMenu)
|
|
132
|
-
|
|
133
|
-
"""
|
|
134
|
-
self._menu = menu
|
|
135
|
-
|
|
136
|
-
def set_action_text(self, action_name, text: str):
|
|
137
|
-
self.get_action(action_name).setText(text)
|
|
138
|
-
|
|
139
|
-
def get_action(self, name):
|
|
140
|
-
if self.has_action(name):
|
|
141
|
-
return self._actions[name]
|
|
142
|
-
else:
|
|
143
|
-
raise KeyError(f'The action with name: {name} is not referenced'
|
|
144
|
-
f' in the view actions: {self._actions.keys()}')
|
|
145
|
-
|
|
146
|
-
def has_action(self, action_name):
|
|
147
|
-
return action_name in self._actions
|
|
148
|
-
|
|
149
|
-
@property
|
|
150
|
-
def toolbar(self):
|
|
151
|
-
return self._toolbar
|
|
152
|
-
|
|
153
|
-
@property
|
|
154
|
-
def menu(self):
|
|
155
|
-
return self._menu
|
|
156
|
-
|
|
157
|
-
def affect_to(self, action_name, obj):
|
|
158
|
-
if isinstance(obj, QtWidgets.QToolBar) or isinstance(obj, QtWidgets.QMenu):
|
|
159
|
-
obj.addAction(self._actions[action_name])
|
|
160
|
-
|
|
161
|
-
def connect_action(self, name, slot, connect=True):
|
|
162
|
-
"""
|
|
163
|
-
Connect (or disconnect) the action referenced by name to the given slot
|
|
164
|
-
Parameters
|
|
165
|
-
----------
|
|
166
|
-
name: (str) key of the action as referenced in the self._actions dict
|
|
167
|
-
slot: (method) a method/function
|
|
168
|
-
connect: (bool) if True connect the trigegr signal of the action to the defined slot else disconnect it
|
|
169
|
-
"""
|
|
170
|
-
if name in self._actions:
|
|
171
|
-
if connect:
|
|
172
|
-
self._actions[name].triggered.connect(slot)
|
|
173
|
-
else:
|
|
174
|
-
try:
|
|
175
|
-
self._actions[name].triggered.disconnect()
|
|
176
|
-
except (TypeError,) as e:
|
|
177
|
-
pass # the action was not connected
|
|
178
|
-
else:
|
|
179
|
-
raise KeyError(f'The action with name: {name} is not referenced'
|
|
180
|
-
f' in the view actions: {self._actions.keys()}')
|
|
181
|
-
|
|
182
|
-
@dispatch(str)
|
|
183
|
-
def is_action_visible(self, action_name: str):
|
|
184
|
-
if action_name in self._actions:
|
|
185
|
-
return self._actions[action_name].isVisible()
|
|
186
|
-
else:
|
|
187
|
-
raise KeyError(f'The action with name: {action_name} is not referenced'
|
|
188
|
-
f' in the actions list: {self._actions}')
|
|
189
|
-
|
|
190
|
-
@dispatch(list)
|
|
191
|
-
def is_action_visible(self, actions_name: list):
|
|
192
|
-
isvisible = False
|
|
193
|
-
for action_name in actions_name:
|
|
194
|
-
isvisible = isvisible and self.is_action_visible(action_name)
|
|
195
|
-
return isvisible
|
|
196
|
-
|
|
197
|
-
@dispatch(str)
|
|
198
|
-
def is_action_checked(self, action_name: str):
|
|
199
|
-
if action_name in self._actions:
|
|
200
|
-
return self._actions[action_name].isChecked()
|
|
201
|
-
else:
|
|
202
|
-
raise KeyError(f'The action with name: {action_name} is not referenced'
|
|
203
|
-
f' in the actions list: {self._actions}')
|
|
204
|
-
|
|
205
|
-
@dispatch(list)
|
|
206
|
-
def is_action_checked(self, actions_name: list):
|
|
207
|
-
ischecked = False
|
|
208
|
-
for action_name in actions_name:
|
|
209
|
-
ischecked = ischecked and self.is_action_checked(action_name)
|
|
210
|
-
return ischecked
|
|
211
|
-
|
|
212
|
-
@dispatch(str, bool)
|
|
213
|
-
def set_action_visible(self, action_name: str, visible=True):
|
|
214
|
-
if action_name in self._actions:
|
|
215
|
-
self._actions[action_name].setVisible(visible)
|
|
216
|
-
else:
|
|
217
|
-
raise KeyError(f'The action with name: {action_name} is not referenced'
|
|
218
|
-
f' in the actions list: {self._actions}')
|
|
219
|
-
|
|
220
|
-
@dispatch(list, bool)
|
|
221
|
-
def set_action_visible(self, actions_name: list, visible=True):
|
|
222
|
-
for action_name in actions_name:
|
|
223
|
-
self.set_action_visible(action_name, visible)
|
|
224
|
-
|
|
225
|
-
@dispatch(str, bool)
|
|
226
|
-
def set_action_checked(self, action_name: str, checked=True):
|
|
227
|
-
if action_name in self._actions:
|
|
228
|
-
self._actions[action_name].setChecked(checked)
|
|
229
|
-
else:
|
|
230
|
-
raise KeyError(f'The action with name: {action_name} is not referenced'
|
|
231
|
-
f' in the actions list: {self._actions}')
|
|
232
|
-
|
|
233
|
-
@dispatch(list, bool)
|
|
234
|
-
def set_action_checked(self, actions_name: list, checked=True):
|
|
235
|
-
for action_name in actions_name:
|
|
236
|
-
self.set_action_checked(action_name, checked)
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
from pyqtgraph.parametertree import Parameter, ParameterTree
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class ParameterManager:
|
|
5
|
-
params = []
|
|
6
|
-
|
|
7
|
-
def __init__(self):
|
|
8
|
-
self.settings = Parameter.create(name='settings', type='group', children=self.params) # create a Parameter
|
|
9
|
-
# object containing the settings defined in the preamble
|
|
10
|
-
# # create a settings tree to be shown eventually in a dock
|
|
11
|
-
self.settings_tree = ParameterTree()
|
|
12
|
-
self.settings_tree.setParameters(self.settings, showTop=False) # load the tree with this parameter object
|
|
13
|
-
self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)
|
|
14
|
-
|
|
15
|
-
def parameter_tree_changed(self, param, changes):
|
|
16
|
-
for param, change, data in changes:
|
|
17
|
-
if change == 'childAdded':
|
|
18
|
-
self.child_added(param)
|
|
19
|
-
|
|
20
|
-
elif change == 'value':
|
|
21
|
-
self.value_changed(param)
|
|
22
|
-
|
|
23
|
-
elif change == 'parent':
|
|
24
|
-
self.param_deleted(param)
|
|
25
|
-
|
|
26
|
-
def value_changed(self, param):
|
|
27
|
-
"""Non mandatory method to be subclassed for actions to perform when one of the param's value in self.settings is changed
|
|
28
|
-
|
|
29
|
-
For instance:
|
|
30
|
-
if param.name() == 'do_something':
|
|
31
|
-
if param.value():
|
|
32
|
-
print('Do something')
|
|
33
|
-
self.settings.child('main_settings', 'something_done').setValue(False)
|
|
34
|
-
|
|
35
|
-
Parameters
|
|
36
|
-
----------
|
|
37
|
-
param: (Parameter) the parameter whose value just changed
|
|
38
|
-
"""
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
def child_added(self, param):
|
|
42
|
-
"""Non mandatory method to be subclassed for actions to perform when a param has been added in self.settings
|
|
43
|
-
|
|
44
|
-
Parameters
|
|
45
|
-
----------
|
|
46
|
-
param: (Parameter) the parameter that has been deleted
|
|
47
|
-
"""
|
|
48
|
-
pass
|
|
49
|
-
|
|
50
|
-
def param_deleted(self, param):
|
|
51
|
-
"""Non mandatory method to be subclassed for actions to perform when one of the param in self.settings has been deleted
|
|
52
|
-
|
|
53
|
-
Parameters
|
|
54
|
-
----------
|
|
55
|
-
param: (Parameter) the parameter that has been deleted
|
|
56
|
-
"""
|
|
57
|
-
pass
|