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.

Files changed (233) hide show
  1. pymodaq/__init__.py +13 -6
  2. pymodaq/control_modules/__init__.py +0 -7
  3. pymodaq/control_modules/daq_move.py +965 -2
  4. pymodaq/control_modules/daq_move_ui.py +319 -0
  5. pymodaq/control_modules/daq_viewer.py +1573 -3
  6. pymodaq/control_modules/daq_viewer_ui.py +393 -0
  7. pymodaq/control_modules/mocks.py +51 -0
  8. pymodaq/control_modules/move_utility_classes.py +709 -8
  9. pymodaq/control_modules/utils.py +256 -0
  10. pymodaq/control_modules/viewer_utility_classes.py +663 -6
  11. pymodaq/daq_utils.py +89 -0
  12. pymodaq/dashboard.py +91 -72
  13. pymodaq/examples/custom_app.py +12 -11
  14. pymodaq/examples/custom_viewer.py +10 -10
  15. pymodaq/examples/function_plotter.py +16 -13
  16. pymodaq/examples/nonlinearscanner.py +8 -6
  17. pymodaq/examples/parameter_ex.py +7 -7
  18. pymodaq/examples/preset_MockCamera.xml +1 -0
  19. pymodaq/extensions/__init__.py +16 -0
  20. pymodaq/extensions/console.py +76 -0
  21. pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
  22. pymodaq/extensions/daq_scan.py +1339 -0
  23. pymodaq/extensions/daq_scan_ui.py +240 -0
  24. pymodaq/extensions/h5browser.py +23 -0
  25. pymodaq/{pid → extensions/pid}/__init__.py +4 -2
  26. pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
  27. pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
  28. pymodaq/{pid → extensions/pid}/utils.py +52 -6
  29. pymodaq/extensions/utils.py +40 -0
  30. pymodaq/post_treatment/__init__.py +6 -0
  31. pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
  32. pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
  33. pymodaq/post_treatment/load_and_plot.py +219 -0
  34. pymodaq/post_treatment/process_to_scalar.py +263 -0
  35. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  36. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  37. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
  38. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
  39. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
  40. pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
  41. pymodaq/resources/VERSION +1 -1
  42. pymodaq/resources/config_template.toml +32 -13
  43. pymodaq/resources/preset_default.xml +1 -1
  44. pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
  45. pymodaq/utils/__init__.py +0 -29
  46. pymodaq/utils/abstract/__init__.py +48 -0
  47. pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
  48. pymodaq/utils/array_manipulation.py +379 -8
  49. pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
  50. pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
  51. pymodaq/utils/config.py +448 -0
  52. pymodaq/utils/conftests.py +5 -0
  53. pymodaq/utils/daq_utils.py +828 -8
  54. pymodaq/utils/data.py +1873 -7
  55. pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
  56. pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
  57. pymodaq/{daq_utils → utils}/enums.py +12 -7
  58. pymodaq/utils/exceptions.py +37 -0
  59. pymodaq/utils/factory.py +82 -0
  60. pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
  61. pymodaq/utils/gui_utils/custom_app.py +129 -0
  62. pymodaq/utils/gui_utils/file_io.py +66 -0
  63. pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
  64. pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
  65. pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
  66. pymodaq/utils/gui_utils/widgets/label.py +24 -0
  67. pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
  68. pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
  69. pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
  70. pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
  71. pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
  72. pymodaq/utils/h5modules/__init__.py +1 -0
  73. pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
  74. pymodaq/utils/h5modules/browsing.py +683 -0
  75. pymodaq/utils/h5modules/data_saving.py +839 -0
  76. pymodaq/utils/h5modules/h5logging.py +110 -0
  77. pymodaq/utils/h5modules/module_saving.py +350 -0
  78. pymodaq/utils/h5modules/saving.py +914 -0
  79. pymodaq/utils/h5modules/utils.py +85 -0
  80. pymodaq/utils/logger.py +64 -6
  81. pymodaq/utils/managers/action_manager.py +460 -0
  82. pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
  83. pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
  84. pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
  85. pymodaq/utils/managers/parameter_manager.py +110 -0
  86. pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
  87. pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
  88. pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
  89. pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
  90. pymodaq/utils/math_utils.py +546 -10
  91. pymodaq/{daq_utils → utils}/messenger.py +5 -1
  92. pymodaq/utils/parameter/__init__.py +2 -15
  93. pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
  94. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
  95. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
  96. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
  97. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
  98. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
  99. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
  100. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
  101. pymodaq/utils/parameter/utils.py +206 -11
  102. pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
  103. pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
  104. pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
  105. pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
  106. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
  107. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
  108. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
  109. pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
  110. pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
  111. pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
  112. pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
  113. pymodaq/utils/plotting/navigator.py +355 -0
  114. pymodaq/utils/plotting/scan_selector.py +480 -0
  115. pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
  116. pymodaq/utils/plotting/utils/filter.py +538 -0
  117. pymodaq/utils/plotting/utils/lineout.py +224 -0
  118. pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
  119. pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
  120. pymodaq/utils/plotting/widgets.py +76 -0
  121. pymodaq/utils/scanner/__init__.py +10 -0
  122. pymodaq/utils/scanner/scan_factory.py +204 -0
  123. pymodaq/utils/scanner/scanner.py +271 -0
  124. pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
  125. pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
  126. pymodaq/utils/scanner/scanners/sequential.py +192 -0
  127. pymodaq/utils/scanner/scanners/tabular.py +294 -0
  128. pymodaq/utils/scanner/utils.py +83 -0
  129. pymodaq/utils/slicing.py +47 -0
  130. pymodaq/utils/svg/__init__.py +6 -0
  131. pymodaq/utils/svg/svg_renderer.py +20 -0
  132. pymodaq/utils/svg/svg_view.py +35 -0
  133. pymodaq/utils/svg/svg_viewer2D.py +51 -0
  134. pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
  135. pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
  136. pymodaq/utils/units.py +216 -0
  137. pymodaq-4.0.1.dist-info/METADATA +159 -0
  138. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
  140. pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
  141. pymodaq/daq_move/daq_move_gui.py +0 -279
  142. pymodaq/daq_move/daq_move_gui.ui +0 -534
  143. pymodaq/daq_move/daq_move_main.py +0 -1042
  144. pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
  145. pymodaq/daq_move/utility_classes.py +0 -671
  146. pymodaq/daq_scan.py +0 -2160
  147. pymodaq/daq_utils/array_manipulation.py +0 -386
  148. pymodaq/daq_utils/config.py +0 -273
  149. pymodaq/daq_utils/conftests.py +0 -7
  150. pymodaq/daq_utils/custom_parameter_tree.py +0 -9
  151. pymodaq/daq_utils/daq_enums.py +0 -133
  152. pymodaq/daq_utils/daq_utils.py +0 -1402
  153. pymodaq/daq_utils/exceptions.py +0 -71
  154. pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
  155. pymodaq/daq_utils/gui_utils/file_io.py +0 -75
  156. pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
  157. pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
  158. pymodaq/daq_utils/h5exporters.py +0 -242
  159. pymodaq/daq_utils/h5modules.py +0 -1559
  160. pymodaq/daq_utils/h5utils.py +0 -241
  161. pymodaq/daq_utils/managers/action_manager.py +0 -236
  162. pymodaq/daq_utils/managers/parameter_manager.py +0 -57
  163. pymodaq/daq_utils/math_utils.py +0 -705
  164. pymodaq/daq_utils/parameter/__init__.py +0 -1
  165. pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
  166. pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
  167. pymodaq/daq_utils/parameter/utils.py +0 -136
  168. pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
  169. pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
  170. pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
  171. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
  172. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
  173. pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
  174. pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
  175. pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
  176. pymodaq/daq_utils/plotting/items/__init__.py +0 -0
  177. pymodaq/daq_utils/plotting/navigator.py +0 -500
  178. pymodaq/daq_utils/plotting/scan_selector.py +0 -289
  179. pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
  180. pymodaq/daq_utils/plotting/utils/filter.py +0 -236
  181. pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
  182. pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
  183. pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
  184. pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
  185. pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
  186. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
  187. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
  188. pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
  189. pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
  190. pymodaq/daq_utils/scanner.py +0 -1289
  191. pymodaq/daq_utils/tree_layout/__init__.py +0 -0
  192. pymodaq/daq_viewer/__init__.py +0 -0
  193. pymodaq/daq_viewer/daq_gui_settings.py +0 -237
  194. pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
  195. pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
  196. pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
  197. pymodaq/daq_viewer/utility_classes.py +0 -673
  198. pymodaq/examples/logger_image/__init__.py +0 -0
  199. pymodaq/examples/logger_image/logger_displayer.py +0 -121
  200. pymodaq/examples/logger_image/setup.svg +0 -3119
  201. pymodaq/examples/logger_image/setup_svg.py +0 -114
  202. pymodaq/h5browser.py +0 -39
  203. pymodaq/utils/scanner.py +0 -15
  204. pymodaq-3.6.12.dist-info/METADATA +0 -39
  205. pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.12.dist-info/top_level.txt +0 -1
  207. /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
  208. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
  209. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
  210. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
  211. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
  212. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
  213. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
  214. /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
  215. /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
  216. /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
  217. /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
  218. /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
  219. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
  220. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
  221. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
  222. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
  223. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
  224. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
  225. /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
  226. /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
  227. /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
  228. /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
  229. /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
  230. /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
  231. /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
  232. /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
  233. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -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