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.

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.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.13.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 -686
  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.13.dist-info/METADATA +0 -39
  205. pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.13.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.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -1,71 +0,0 @@
1
- class DAQ_ScanException(Exception):
2
- """Raised when an error occur within the DAQ_Scan"""
3
- pass
4
-
5
-
6
- class ScannerException(Exception):
7
- """Raised when there is an error related to the Scanner class (see pymodaq.da_utils.scanner)"""
8
- pass
9
-
10
-
11
- class DetectorError(Exception):
12
- pass
13
-
14
-
15
- class ActuatorError(Exception):
16
- pass
17
-
18
-
19
- class ViewerError(Exception):
20
- pass
21
-
22
-
23
- class DataSourceError(Exception):
24
- pass
25
-
26
-
27
- class InvalidExport(Exception):
28
- pass
29
-
30
-
31
- class InvalidGroupType(Exception):
32
- pass
33
-
34
-
35
- class InvalidSave(Exception):
36
- pass
37
-
38
-
39
- class InvalidGroupDataType(Exception):
40
- pass
41
-
42
-
43
- class InvalidDataType(Exception):
44
- pass
45
-
46
-
47
- class InvalidDataDimension(Exception):
48
- pass
49
-
50
-
51
- class InvalidScanType(Exception):
52
- pass
53
-
54
-
55
- class ExpectedError(Exception):
56
- """Raised in the tests made for pymodaq plugins"""
57
- pass
58
-
59
-
60
- class Expected_1(ExpectedError):
61
- """Expected error 1 for pymodaq tests"""
62
- pass
63
-
64
-
65
- class Expected_2(ExpectedError):
66
- """Expected error 2 for pymodaq tests"""
67
- pass
68
-
69
-
70
- class Expected_3(ExpectedError):
71
- """Expected error 3 for pymodaq tests"""
@@ -1,103 +0,0 @@
1
- from qtpy.QtCore import QObject, QLocale
2
- from pymodaq.daq_utils.gui_utils.dock import DockArea
3
- from pymodaq.daq_utils.managers.action_manager import ActionManager
4
- from pymodaq.daq_utils.managers.parameter_manager import ParameterManager
5
- from pymodaq.daq_utils.managers.modules_manager import ModulesManager
6
- from pyqtgraph.dockarea import DockArea
7
- from qtpy import QtCore, QtWidgets
8
-
9
-
10
- class CustomApp(QObject, ActionManager, ParameterManager):
11
- """
12
- Implements the MixIns ActionManager and ParameterManager methods and attributes, you have to subclass it and make
13
- concrete implementation of a given number of methods:
14
-
15
- * setup_actions: mandatory, see ActionManager
16
- * value_changed: non mandatory, see ParameterManager
17
- * child_added: non mandatory, see ParameterManager
18
- * param_deleted: non mandatory, see ParameterManager
19
- * setup_docks: mandatory
20
- * setup_menu: non mandatory
21
- * connect_things: mandatory
22
- """
23
- # custom signal that will be fired sometimes. Could be connected to an external object method or an internal method
24
- log_signal = QtCore.Signal(str)
25
-
26
- # list of dicts enabling the settings tree on the user interface
27
- params = []
28
-
29
- def __init__(self, dockarea: DockArea, dashboard=None):
30
- QObject.__init__(self)
31
- ActionManager.__init__(self)
32
- ParameterManager.__init__(self)
33
- QLocale.setDefault(QLocale(QLocale.English, QLocale.UnitedStates))
34
-
35
- if not isinstance(dockarea, DockArea):
36
- raise Exception('no valid parent container, expected a DockArea')
37
-
38
- self.dockarea = dockarea
39
- self.mainwindow = dockarea.parent()
40
- self.dashboard = dashboard
41
-
42
- self.docks = dict([])
43
- self.statusbar = None
44
- self._toolbar = QtWidgets.QToolBar()
45
-
46
- if self.mainwindow is not None:
47
- self.mainwindow.addToolBar(self._toolbar)
48
- self.statusbar = self.mainwindow.statusBar()
49
-
50
- self.set_toolbar(self._toolbar)
51
-
52
- def setup_ui(self):
53
- self.setup_docks()
54
-
55
- self.setup_actions() # see ActionManager MixIn class
56
-
57
- self.setup_menu()
58
-
59
- self.connect_things()
60
-
61
- def setup_docks(self):
62
- """
63
- Mandatory method to be subclassed to setup the docks layout
64
- for instance:
65
-
66
- self.docks['ADock'] = gutils.Dock('ADock name)
67
- self.dockarea.addDock(self.docks['ADock"])
68
- self.docks['AnotherDock'] = gutils.Dock('AnotherDock name)
69
- self.dockarea.addDock(self.docks['AnotherDock"], 'bottom', self.docks['ADock"])
70
-
71
- See Also
72
- ########
73
- pyqtgraph.dockarea.Dock
74
- """
75
- raise NotImplementedError
76
-
77
- def setup_menu(self):
78
- """
79
- Non mandatory method to be subclassed in order to create a menubar
80
- create menu for actions contained into the self._actions, for instance:
81
-
82
- For instance:
83
-
84
- file_menu = self._menubar.addMenu('File')
85
- self.affect_to('load', file_menu)
86
- self.affect_to('save', file_menu)
87
-
88
- file_menu.addSeparator()
89
- self.affect_to('quit', file_menu)
90
-
91
- See Also
92
- --------
93
- pymodaq.daq_utils.managers.action_manager.ActionManager
94
- """
95
- pass
96
-
97
- def connect_things(self):
98
- raise NotImplementedError
99
-
100
- @property
101
- def modules_manager(self) -> ModulesManager:
102
- if self.dashboard is not None:
103
- return self.dashboard.modules_manager
@@ -1,75 +0,0 @@
1
- from pathlib import Path
2
-
3
- from pymodaq.daq_utils.config import Config
4
- from qtpy import QtWidgets
5
-
6
- config = Config()
7
-
8
-
9
- def select_file(start_path=config('data_saving', 'h5file', 'save_path'), save=True, ext=None, filter=None):
10
- """Save or open a file with Qt5 file dialog, to be used within an Qt5 loop.
11
-
12
- Usage::
13
-
14
- from pymodaq.daq_utils.daq_utils import select_file
15
- select_file(start_path="C:\\test.h5",save=True,ext='h5')
16
-
17
- =============== ======================================= ===========================================================================
18
- **Parameters** **Type** **Description**
19
-
20
- *start_path* Path object or str or None, optional the path Qt5 will open in te dialog
21
- *save* bool, optional * if True, a savefile dialog will open in order to set a savefilename
22
- * if False, a openfile dialog will open in order to open an existing file
23
- *ext* str, optional the extension of the file to be saved or opened
24
- =============== ======================================= ===========================================================================
25
-
26
- Returns
27
- -------
28
- Path object
29
- the Path object pointing to the file
30
-
31
- Examples
32
- --------
33
-
34
-
35
-
36
- """
37
- if ext is None:
38
- ext = '.h5'
39
-
40
- if filter is None:
41
- if not save:
42
- if not isinstance(ext, list):
43
- ext = [ext]
44
- filter = "Data files ("
45
- for ext_tmp in ext:
46
- filter += '*.' + ext_tmp + " "
47
- filter += ")"
48
-
49
- if start_path is not None:
50
- if not isinstance(start_path, str):
51
- start_path = str(start_path)
52
- if save:
53
- # fname = QtWidgets.QFileDialog.getSaveFileName(None, 'Enter a .' + ext + ' file name', start_path,
54
- # ext + " file (*." + ext + ")")
55
- fname = QtWidgets.QFileDialog.getSaveFileName(None, 'Enter a file name', start_path,
56
- filter)
57
- else:
58
- fname = QtWidgets.QFileDialog.getOpenFileName(None, 'Select a file name', start_path, filter)
59
-
60
- fname = fname[0]
61
- if fname != '': # execute if the user didn't cancel the file selection
62
- fname = Path(fname)
63
- # if save:
64
- # parent = fname.parent
65
- # filename = fname.stem
66
- # fname = parent.joinpath(filename + "." + ext) # forcing the right extension on the filename
67
- return fname # fname is a Path object
68
-
69
-
70
- if __name__ == '__main__':
71
- import sys
72
- app = QtWidgets.QApplication(sys.argv)
73
- file = select_file(save=True, filter="Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)")
74
- print(file)
75
- sys.exit(app.exec_())
@@ -1,9 +0,0 @@
1
- from qtpy import QtWidgets
2
-
3
-
4
- class QSpinBox_ro(QtWidgets.QSpinBox):
5
- def __init__(self, **kwargs):
6
- super().__init__()
7
- self.setMaximum(100000)
8
- self.setReadOnly(True)
9
- self.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
@@ -1,115 +0,0 @@
1
- # Standard imports
2
-
3
- # 3rd party imports
4
- import numpy as np
5
- import hyperspy.api_nogui as hs
6
-
7
- # project imports
8
- from pymodaq.daq_utils.h5backend import Node
9
- from pymodaq.daq_utils.h5utils import get_h5_data_from_node, extract_axis, verify_axis_data_uniformity
10
- from pymodaq.daq_utils.h5exporters import ExporterFactory, H5Exporter
11
- from pymodaq.daq_utils.daq_utils import set_logger, get_module_name
12
-
13
- # This is needed to log
14
- logger = set_logger(get_module_name(__file__))
15
-
16
-
17
- @ExporterFactory.register_exporter()
18
- class H5hspyExporter(H5Exporter):
19
- """ Exporter object for saving nodes as hspy files"""
20
-
21
- FORMAT_DESCRIPTION = "Hyperspy file format"
22
- FORMAT_EXTENSION = "hspy"
23
-
24
- def _export_data(self, node: Node, filename) -> None:
25
- """Exporting a .h5 node as a hyperspy object"""
26
-
27
- # first verify if the node type is compatible with export. Only data nodes are.
28
- nodetype = node.attrs['type']
29
- if nodetype == 'data':
30
- # If yes we can use this function (the same for plotting in h5browser) to extract information
31
- data, axes, nav_axes, is_spread = get_h5_data_from_node(node)
32
- data = data.reshape(data.shape, order='F')
33
- logger.debug(f"extracted data of shape {data.shape}")
34
- logger.debug(f"extracted axes: {axes}")
35
-
36
- # get_h5_data_from_node will return sometimes empty axes that we must yeet.
37
- axes_keys_to_remove = []
38
- for key, ax in axes.items():
39
- if ax['data'] is None:
40
- logger.warning(f'Dropping axis {key} due to empty data')
41
- axes_keys_to_remove.append(key)
42
- for key in axes_keys_to_remove:
43
- del axes[key]
44
-
45
- else:
46
- # Else just raise an error.
47
- raise NotImplementedError(f"hspy export not supported for nodes of type {nodetype}'. "
48
- f"Export from the data node instead.")
49
-
50
- # Verify that this is not an adaptive scan. If it is we throw and say it is not supported.
51
- if is_spread:
52
- raise NotImplementedError(f"hspy export not supported for adaptive scan data.")
53
-
54
- # Then we build the hyperspy axes objects.
55
- hyperspy_axes = []
56
- for key, ax in axes.items():
57
- logger.info(f"Extracting axis {ax['label']}.")
58
- unique_ax = extract_axis(ax)
59
- try:
60
- indexv = data.shape.index(len(unique_ax))
61
- logger.info(f"{ax['label']}, size {len(unique_ax)}, data index: {indexv}")
62
- except ValueError:
63
- raise ValueError(f"Signal axis of length {len(unique_ax)} does not match any "
64
- f"dimension in data of shape {data.shape} ")
65
- is_nav = key.startswith('nav')
66
- hyperspy_axes.append(self.build_hyperspy_axis(unique_ax, data_idx=indexv, label=ax['label'],
67
- unit=ax['units'], navigate=is_nav))
68
-
69
- ordered_axes = sorted(hyperspy_axes, key=lambda d: d['index_in_array'])
70
- for ax in ordered_axes:
71
- del ax['index_in_array']
72
- # Then we build the hyperspy object. First we must know its dimensionality
73
- # from the number of signal axes.
74
- dim = len(axes) - len(nav_axes)
75
- if dim == 1:
76
- # Then signal1D
77
- sig = hs.signals.Signal1D(data=data, original_metadata={}, axes=ordered_axes)
78
- elif dim == 2:
79
- # Then signal2D
80
- sig = hs.signals.Signal2D(data=data, original_metadata={}, axes=ordered_axes)
81
- else:
82
- # Then basesignal
83
- sig = hs.signals.BaseSignal(data=data, original_metadata={}, axes=ordered_axes)
84
-
85
- # Finally save
86
- sig.save(filename)
87
-
88
- def build_hyperspy_axis(self, ax_data: np.ndarray, data_idx: int,
89
- label: str, unit: str, navigate: bool) -> dict:
90
- """Build an axis based on the input data. Choose between a UniformDataAxis or
91
- DataAxis object based on a quick linearity check of the input data."""
92
- offset, scale = verify_axis_data_uniformity(ax_data)
93
- if offset is not None:
94
- axis_dict = {'_type': 'UniformDataAxis',
95
- 'index_in_array': data_idx,
96
- 'name': label,
97
- 'units': unit,
98
- 'navigate': navigate,
99
- 'size': len(ax_data),
100
- 'scale': scale,
101
- 'offset': offset}
102
- else:
103
- axis_dict = {'_type': 'DataAxis',
104
- 'index_in_array': data_idx,
105
- 'name': label,
106
- 'units': unit,
107
- 'navigate': navigate,
108
- 'size': len(ax_data),
109
- 'axis': ax_data}
110
-
111
- return axis_dict
112
-
113
- def build_hyperspy_original_metadata(self, node: Node):
114
- """Build original metadata dictionary"""
115
- pass
@@ -1,242 +0,0 @@
1
- # Standard imports
2
- from abc import ABCMeta, abstractmethod
3
- from typing import Callable
4
-
5
- # 3rd party imports
6
- import numpy as np
7
-
8
- # project imports
9
- from pymodaq.daq_utils.h5backend import H5Backend, Node
10
- from pymodaq.daq_utils.daq_utils import set_logger, get_module_name
11
-
12
- logger = set_logger(get_module_name(__file__))
13
-
14
-
15
- class ExporterFactory:
16
- """The factory class for creating executors"""
17
-
18
- exporters_registry = {}
19
- file_filters = {}
20
-
21
- @classmethod
22
- def register_exporter(cls) -> Callable:
23
- """Class decorator method to register exporter class to the internal registry. Must be used as
24
- decorator above the definition of an H5Exporter class. H5Exporter must implement specific class
25
- attributes and methods, see definition: h5node_exporter.H5Exporter
26
-
27
- See h5node_exporter.H5txtExporter and h5node_exporter.H5txtExporter for usage examples.
28
-
29
- returns:
30
- the exporter class
31
- """
32
-
33
- def inner_wrapper(wrapped_class) -> Callable:
34
- extension = wrapped_class.FORMAT_EXTENSION
35
- # Warn if overriding existing exporter
36
- if extension in cls.exporters_registry:
37
- logger.warning(f"Exporter for the .{extension} format already exists and will be replaced")
38
-
39
- # Register extension
40
- cls.exporters_registry[extension] = wrapped_class
41
- cls.file_filters[extension] = wrapped_class.FORMAT_DESCRIPTION
42
- # Return wrapped_class
43
- return wrapped_class
44
-
45
- # Return decorated function
46
- return inner_wrapper
47
-
48
- @classmethod
49
- def create_exporter(cls, extension: str):
50
- """Factory command to create the exporter object.
51
-
52
- This method gets the appropriate executor class from the registry
53
- and instantiates it.
54
-
55
- Args:
56
- extension (str): the extension of the file that will be exported
57
-
58
- returns:
59
- an instance of the executor created
60
- """
61
- if extension not in cls.exporters_registry:
62
- raise ValueError(f".{extension} is not a supported file format.")
63
-
64
- exporter_class = cls.exporters_registry[extension]
65
-
66
- exporter = exporter_class()
67
-
68
- return exporter
69
-
70
- @classmethod
71
- def get_file_filters(cls):
72
- """Create the file filters string"""
73
- tmplist = [f"{v} (*.{k})" for k, v in cls.file_filters.items()]
74
- return ";;".join(tmplist)
75
-
76
-
77
- class H5Exporter(metaclass=ABCMeta):
78
- """Base class for an exporter. """
79
-
80
- # This is to define an abstract class attribute
81
- @classmethod
82
- @property
83
- @abstractmethod
84
- def FORMAT_DESCRIPTION(cls):
85
- """str: file format description as a short text. eg: text file"""
86
- raise NotImplementedError
87
-
88
- @classmethod
89
- @property
90
- @abstractmethod
91
- def FORMAT_EXTENSION(cls):
92
- """str: File format extension. eg: txt"""
93
- raise NotImplementedError
94
-
95
- def __init__(self):
96
- """Abstract Exporter Constructor"""
97
- pass
98
-
99
- @abstractmethod
100
- def _export_data(self, node: Node, filename: str) -> None:
101
- """Abstract method to save a .h5 node to a file"""
102
- pass
103
-
104
-
105
- @ExporterFactory.register_exporter()
106
- class H5h5Exporter(H5Exporter):
107
- """ Exporter object for saving nodes as single h5 files"""
108
-
109
- FORMAT_DESCRIPTION = "Single node h5 file"
110
- FORMAT_EXTENSION = "h5"
111
-
112
- def _export_data(self, node: Node, filename: str) -> None:
113
- """Export an h5 node"""
114
- # This should allow to get the base file object
115
- if node.backend == 'tables':
116
- basefile = node.node._v_file
117
- basefile.copy_file(dstfilename=str(filename), overwrite=False)
118
- else:
119
- import h5py
120
- with h5py.File(filename, 'w') as f_dest:
121
- node.node.h5file.copy(self.h5file, f_dest)
122
-
123
- # basefile = node.get_file()
124
- # basefile.copy_file(dstfilename=str(filename), overwrite=False)
125
-
126
- new_file = H5Backend(backend="tables")
127
- new_file.open_file(str(filename), 'a')
128
-
129
- new_file.h5file.move_node(self.get_node_path(node), newparent=new_file.h5file.get_node('/'))
130
- new_file.h5file.remove_node('/Raw_datas', recursive=True)
131
- new_file.close_file()
132
-
133
-
134
- @ExporterFactory.register_exporter()
135
- class H5txtExporter(H5Exporter):
136
- """ Exporter object for saving nodes as txt files"""
137
-
138
- FORMAT_DESCRIPTION = "Text files"
139
- FORMAT_EXTENSION = "txt"
140
-
141
- def _export_data(self, node: Node, filename: str) -> None:
142
- """Export the node as a .txt file format"""
143
- if 'ARRAY' in node.attrs['CLASS']:
144
- data = node.read()
145
- if not isinstance(data, np.ndarray):
146
- # in case one has a list of same objects (array of strings for instance, logger or other)
147
- data = np.array(data)
148
- np.savetxt(filename, data, '%s', '\t')
149
- else:
150
- np.savetxt(filename, data, '%.6e', '\t')
151
- elif 'GROUP' in node.attrs['CLASS']:
152
- data_tot = []
153
- header = []
154
- dtypes = []
155
- fmts = []
156
- for subnode_name, subnode in node.children().items():
157
- if 'ARRAY' in subnode.attrs['CLASS']:
158
- if len(subnode.attrs['shape']) == 1:
159
- data = subnode.read()
160
- if not isinstance(data, np.ndarray):
161
- # in case one has a list of same objects (array of strings for instance, logger or other)
162
- data = np.array(data)
163
- data_tot.append(data)
164
- dtypes.append((subnode_name, data.dtype))
165
- header.append(subnode_name)
166
- if data.dtype.char == 'U':
167
- fmt = '%s' # for strings
168
- elif data.dtype.char == 'l':
169
- fmt = '%d' # for integers
170
- else:
171
- fmt = '%.6f' # for decimal numbers
172
- fmts.append(fmt)
173
-
174
- data_trans = np.array(list(zip(*data_tot)), dtype=dtypes)
175
- np.savetxt(filename, data_trans, fmts, '\t', header='#' + '\t'.join(header))
176
-
177
-
178
- @ExporterFactory.register_exporter()
179
- class H5asciiExporter(H5Exporter):
180
- """ Exporter object for saving nodes as txt files"""
181
-
182
- FORMAT_DESCRIPTION = "Ascii file"
183
- FORMAT_EXTENSION = "ascii"
184
-
185
- def _export_data(self, node: Node, filename: str) -> None:
186
- if 'ARRAY' in node.attrs['CLASS']:
187
- data = node.read()
188
- if not isinstance(data, np.ndarray):
189
- # in case one has a list of same objects (array of strings for instance, logger or other)
190
- data = np.array(data)
191
- np.savetxt(filename,
192
- data.T if len(data.shape) > 1 else [data],
193
- '%s', '\t')
194
- else:
195
- np.savetxt(filename,
196
- data.T if len(data.shape) > 1 else [data],
197
- '%.6e', '\t')
198
-
199
- elif 'GROUP' in node.attrs['CLASS']:
200
- data_tot = []
201
- header = []
202
- dtypes = []
203
- fmts = []
204
- for subnode_name, subnode in node.children().items():
205
- if 'ARRAY' in subnode.attrs['CLASS']:
206
- if len(subnode.attrs['shape']) == 1:
207
- data = subnode.read()
208
- if not isinstance(data, np.ndarray):
209
- # in case one has a list of same objects (array of strings for instance, logger or other)
210
- data = np.array(data)
211
- data_tot.append(data)
212
- dtypes.append((subnode_name, data.dtype))
213
- header.append(subnode_name)
214
- if data.dtype.char == 'U':
215
- fmt = '%s' # for strings
216
- elif data.dtype.char == 'l':
217
- fmt = '%d' # for integers
218
- else:
219
- fmt = '%.6f' # for decimal numbers
220
- fmts.append(fmt)
221
-
222
- data_trans = np.array(list(zip(*data_tot)), dtype=dtypes)
223
-
224
- np.savetxt(filename, data_trans, fmts, '\t', header='#' + '\t'.join(header))
225
-
226
-
227
- @ExporterFactory.register_exporter()
228
- class H5npyExporter(H5Exporter):
229
- """ Exporter object for saving nodes as npy files"""
230
-
231
- FORMAT_DESCRIPTION = "Binary NumPy format"
232
- FORMAT_EXTENSION = "npy"
233
-
234
- def _export_data(self, node: Node, filename: str) -> None:
235
- """Export the node as a numpy binary file format"""
236
- # String __contain__ method will evaluate to True for CARRAY,EARRAY,VLARRAY,stringARRAY
237
- if 'ARRAY' in node.attrs['CLASS']:
238
- data = node.read()
239
- if not isinstance(data, np.ndarray):
240
- data = np.array(data)
241
-
242
- np.save(filename, data)