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
pymodaq/daq_scan.py DELETED
@@ -1,2160 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
-
4
- """Automated scanning module functionalities for PyMoDAQ
5
-
6
- Contains all objects related to the DAQ_Scan module, to do automated scans, saving data...
7
- """
8
-
9
- import sys
10
- from collections import OrderedDict
11
- import numpy as np
12
- from pathlib import Path
13
- import os
14
-
15
- import pymodaq.daq_utils.gui_utils.dock
16
- import pymodaq.daq_utils.gui_utils.file_io
17
- import pymodaq.daq_utils.gui_utils.utils
18
- import pymodaq.daq_utils.gui_utils.widgets.spinbox
19
- import pymodaq.daq_utils.messenger
20
- from pymodaq.daq_utils.config import Config, get_set_preset_path
21
- from pymodaq.daq_utils.managers.action_manager import QAction
22
- import pymodaq.daq_utils.parameter.ioxml
23
-
24
- from pyqtgraph.parametertree import Parameter, ParameterTree
25
- from qtpy import QtWidgets, QtCore, QtGui
26
- from qtpy.QtCore import QObject, Slot, QThread, Signal, QDateTime, QDate, QTime
27
- from pymodaq.daq_utils import exceptions
28
- from pymodaq.daq_utils.plotting.data_viewers.viewer2D import Viewer2D
29
- from pymodaq.daq_utils.plotting.data_viewers.viewer1D import Viewer1D
30
- from pymodaq.daq_utils.plotting.data_viewers.viewer1Dbasic import Viewer1DBasic
31
- from pymodaq.daq_utils.plotting.navigator import Navigator
32
- from pymodaq.daq_utils.scanner import Scanner, adaptive, adaptive_losses
33
- from pymodaq.daq_utils.managers.batchscan_manager import BatchScanner
34
- from pymodaq.daq_utils.managers.modules_manager import ModulesManager
35
- from pymodaq.daq_utils.gui_utils.widgets import QLED
36
- from pymodaq.daq_utils.messenger import messagebox
37
-
38
- from pymodaq.daq_utils import daq_utils as utils
39
- from pymodaq.daq_utils import gui_utils as gutils
40
- from pymodaq.daq_utils.h5modules import H5Saver
41
-
42
- config = Config()
43
- logger = utils.set_logger(utils.get_module_name(__file__))
44
-
45
-
46
- class DAQ_Scan(QObject):
47
- """
48
- Main class initializing a DAQ_Scan module with its dashboard and scanning control panel
49
- """
50
- command_DAQ_signal = Signal(list)
51
- status_signal = Signal(str)
52
- live_data_1D_signal = Signal(list)
53
-
54
- params = [
55
- {'title': 'Time Flow:', 'name': 'time_flow', 'type': 'group', 'expanded': False, 'children': [
56
- {'title': 'Wait time step (ms)', 'name': 'wait_time', 'type': 'int', 'value': 0,
57
- 'tip': 'Wait time in ms after each step of acquisition (move and grab)'},
58
- {'title': 'Wait time between (ms)', 'name': 'wait_time_between', 'type': 'int',
59
- 'value': 0,
60
- 'tip': 'Wait time in ms between move and grab processes'},
61
- {'title': 'Timeout (ms)', 'name': 'timeout', 'type': 'int', 'value': 10000},
62
- ]},
63
- {'title': 'Scan options', 'name': 'scan_options', 'type': 'group', 'children': [
64
- {'title': 'Naverage:', 'name': 'scan_average', 'type': 'int', 'value': 1, 'min': 1},
65
- {'title': 'Plot from:', 'name': 'plot_from', 'type': 'list'},
66
- {'title': 'Sort 1D scan data:', 'name': 'sort_scan1D', 'type': 'bool', 'value': False},]},
67
- ]
68
-
69
- def __init__(self, dockarea=None, dashboard=None, show_popup=True):
70
- """
71
-
72
- Parameters
73
- ----------
74
- dockarea: (dockarea) instance of the modified pyqtgraph Dockarea
75
- dashboard: (DashBoard) instance of the pymodaq dashboard
76
- """
77
-
78
- logger.info('Initializing DAQ_Scan')
79
- super().__init__()
80
- self.dockarea = dockarea
81
- self.dashboard = dashboard
82
- if dashboard is None:
83
- raise Exception('No valid dashboard initialized')
84
- self.mainwindow = self.dockarea.parent()
85
-
86
- self.show_popup = show_popup # used to deactivate popups when testing with pytest
87
- self.wait_time = 1000
88
- self.navigator = None
89
- self.scan_x_axis = None
90
- self.scan_y_axis = None
91
- self.scan_data_1D = np.array([])
92
- self.scan_data_1D_average = np.array([])
93
- self.scan_data_2D = []
94
- self.scan_data_2D_average = []
95
- self.curvilinear_values = []
96
- self.ind_scan = 0
97
- self.ind_average = 0
98
- self.scan_positions = []
99
- self.scan_data_2D_to_save = []
100
- self.scan_data_1D_to_save = []
101
- self.plot_1D_ini = False
102
- self.plot_2D_ini = False
103
-
104
- self.scan_thread = None
105
- self.modules_manager = ModulesManager(self.dashboard.detector_modules, self.dashboard.actuators_modules)
106
-
107
- self.h5saver = H5Saver()
108
- self.h5saver.settings.child(('do_save')).hide()
109
- self.h5saver.settings.child(('custom_name')).hide()
110
- self.h5saver.new_file_sig.connect(self.create_new_file)
111
- self.h5arrays = OrderedDict([])
112
-
113
- self.scanner = Scanner(actuators=self.modules_manager.actuators, adaptive_losses=adaptive_losses)
114
- self.scan_parameters = None
115
-
116
- self.batcher = None
117
- self.batch_started = False
118
- self.ind_batch = 0
119
-
120
-
121
- self.modules_manager.actuators_changed[list].connect(self.update_actuators)
122
- self.modules_manager.detectors_changed[list].connect(self.update_plot_det_items)
123
-
124
- self.setupUI()
125
- self.setup_modules(self.dashboard.title)
126
- self.set_config()
127
- self.scanner.set_config()
128
-
129
- logger.info('DAQ_Scan Initialized')
130
-
131
- ################
132
- # CONFIG/SETUP UI / EXIT
133
-
134
- def set_config(self):
135
- self.settings.child('time_flow', 'wait_time').setValue(config['scan']['timeflow']['wait_time'])
136
- self.settings.child('time_flow', 'wait_time_between').setValue(config['scan']['timeflow']['wait_time'])
137
- self.settings.child('time_flow', 'timeout').setValue(config['scan']['timeflow']['timeout'])
138
-
139
- self.settings.child('scan_options', 'scan_average').setValue(config['scan']['Naverage'])
140
- self.settings.child('scan_options', 'sort_scan1D').setValue(config['scan']['sort1D'])
141
-
142
- def setup_modules(self, filename):
143
- """
144
-
145
- """
146
- try:
147
-
148
- ######################################################################
149
- # set scan selector
150
- items = OrderedDict()
151
- if self.navigator is not None:
152
- items["Navigator"] = dict(viewers=[self.navigator.viewer], names=["Navigator"])
153
- for det in self.modules_manager.detectors_all:
154
- if len([view for view in det.ui.viewers if view.viewer_type == 'Data2D']) != 0:
155
- items[det.title] = dict(viewers=[view for view in det.ui.viewers if view.viewer_type == 'Data2D'],
156
- names=[view.title for view in det.ui.viewers if
157
- view.viewer_type == 'Data2D'], )
158
- items["DAQ_Scan"] = dict(viewers=[self.ui.scan2D_graph], names=["DAQ_Scan"])
159
-
160
- if self.navigator is not None:
161
- items = OrderedDict(Navigator=dict(viewers=[self.navigator.viewer], names=["Navigator"]))
162
- items.update(self.scanner.scan_selector.viewers_items)
163
-
164
- self.scanner.viewers_items = items
165
-
166
- self.scanner.scan_selector.widget.setVisible(False)
167
- self.scanner.scan_selector.settings.child('scan_options', 'scan_type').hide()
168
-
169
- self.scanner.scan_selector.widget.setVisible(False)
170
- self.scanner.scan_selector.show_scan_selector(visible=False)
171
-
172
- # setting moves and det in tree
173
- preset_items_det = [mod for ind, mod in enumerate(self.modules_manager.detectors_all) if ind == 0]
174
- self.settings.child('scan_options', 'plot_from').setLimits([mod.title for mod in preset_items_det])
175
- if preset_items_det != []:
176
- self.settings.child('scan_options', 'plot_from').setValue(preset_items_det[0].title)
177
-
178
- self.show_average_dock(False)
179
-
180
- self.ui.scan_dock.setEnabled(True)
181
- self.file_menu.setEnabled(True)
182
- self.settings_menu.setEnabled(True)
183
- self.create_new_file(True)
184
-
185
- except Exception as e:
186
- logger.exception(str(e))
187
- # self.update_status(getLineInfo()+str(e), self.wait_time, log_type='log')
188
-
189
- def create_average_dock(self):
190
- self.ui.average_dock = pymodaq.daq_utils.gui_utils.dock.Dock("Averaging")
191
- average_tab = QtWidgets.QTabWidget()
192
- average1D_widget = QtWidgets.QWidget()
193
- average2D_widget = QtWidgets.QWidget()
194
-
195
- # %% init the 1D viewer
196
- self.ui.average1D_graph = Viewer1D(average1D_widget)
197
-
198
- # %% init the 2D viewer
199
- self.ui.average2D_graph = Viewer2D(average2D_widget)
200
-
201
- average_tab.addTab(average1D_widget, '1D plot Average')
202
- average_tab.addTab(average2D_widget, '2D plot Average')
203
-
204
- self.ui.average_dock.addWidget(average_tab)
205
- self.dockarea.addDock(self.ui.average_dock, 'right', self.ui.scan_dock)
206
-
207
- self.ui.average_dock.setVisible(False)
208
-
209
- def create_menu(self):
210
- """
211
- """
212
- # %% create Settings menu
213
-
214
- menubar = QtWidgets.QMenuBar()
215
- menubar.setMaximumHeight(30)
216
- self.ui.verticalLayout.insertWidget(0, menubar)
217
-
218
- self.file_menu = menubar.addMenu('File')
219
- load_action = self.file_menu.addAction('Load file')
220
- load_action.triggered.connect(self.load_file)
221
- self.file_menu.addSeparator()
222
- save_action = self.file_menu.addAction('Save file as')
223
- save_action.triggered.connect(self.save_file)
224
- show_action = self.file_menu.addAction('Show file content')
225
- show_action.triggered.connect(self.show_file_content)
226
-
227
- self.settings_menu = menubar.addMenu('Settings')
228
- action_navigator = self.settings_menu.addAction('Show Navigator')
229
- action_navigator.triggered.connect(self.show_navigator)
230
- action_batcher = self.settings_menu.addAction('Show Batch Scanner')
231
- action_batcher.triggered.connect(lambda: self.show_batcher(menubar))
232
-
233
- def quit_fun(self):
234
- """
235
- Quit the current instance of DAQ_scan and close on cascade move and detector modules.
236
-
237
- See Also
238
- --------
239
- quit_fun
240
- """
241
- try:
242
- self.h5saver.close_file()
243
- self.ui.average_dock.close()
244
- self.ui.scan_dock.close()
245
- self.dockarea.close()
246
-
247
- except Exception as e:
248
- logger.exception(str(e))
249
-
250
- def setupUI(self):
251
- self.ui = QObject()
252
- widgetsettings = QtWidgets.QWidget()
253
- self.ui.verticalLayout = QtWidgets.QVBoxLayout()
254
- widgetsettings.setLayout(self.ui.verticalLayout)
255
- self.ui.StatusBarLayout = QtWidgets.QHBoxLayout()
256
- self.ui.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
257
-
258
- self.ui.verticalLayout.addWidget(self.ui.splitter)
259
- self.ui.verticalLayout.addLayout(self.ui.StatusBarLayout)
260
-
261
- self.ui.horizontalLayout = QtWidgets.QHBoxLayout()
262
- sett_widget = QtWidgets.QWidget()
263
- self.ui.settings_layout = QtWidgets.QVBoxLayout()
264
- sett_widget.setLayout(self.ui.settings_layout)
265
- self.ui.horizontalLayout.addWidget(sett_widget)
266
-
267
- # ###########################BUTTONS##################
268
- widget_buttons = QtWidgets.QWidget()
269
- self.ui.horizontalLayout_2 = QtWidgets.QHBoxLayout()
270
- widget_buttons.setLayout(self.ui.horizontalLayout_2)
271
-
272
- iconquit = QtGui.QIcon()
273
- iconquit.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/close2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
274
- self.ui.quit_pb = QtWidgets.QPushButton(iconquit, 'Quit')
275
-
276
- iconstart = QtGui.QIcon()
277
- iconstart.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/run2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
278
- self.ui.start_scan_pb = QtWidgets.QPushButton(iconstart, '')
279
- self.ui.start_scan_pb.setToolTip('Start Scan')
280
-
281
- iconstop = QtGui.QIcon()
282
- iconstop.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/stop.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
283
- self.ui.stop_scan_pb = QtWidgets.QPushButton(iconstop, '')
284
- self.ui.stop_scan_pb.setToolTip('Stop Scan (or skip current one if Batch scan running)')
285
-
286
- self.ui.set_scan_pb = QtWidgets.QPushButton('Set Scan')
287
- self.ui.set_scan_pb.setToolTip('Process the scanner settings and prepare the modules for coming scan')
288
- self.ui.set_ini_positions_pb = QtWidgets.QPushButton('Init Positions')
289
- self.ui.set_ini_positions_pb.setToolTip(
290
- 'Set Move Modules to their initial position as defined in the current scan')
291
-
292
- iconstartbatch = QtGui.QIcon()
293
- iconstartbatch.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/run_all.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
294
- self.ui.start_batch_pb = QtWidgets.QPushButton(iconstartbatch, '')
295
- self.ui.start_batch_pb.setToolTip('Start the batch of scans defined in the batch manager')
296
- self.ui.start_batch_pb.setVisible(False)
297
-
298
- self.ui.horizontalLayout_2.addWidget(self.ui.quit_pb)
299
- self.ui.horizontalLayout_2.addStretch()
300
- self.ui.horizontalLayout_2.addWidget(self.ui.set_scan_pb)
301
- self.ui.horizontalLayout_2.addWidget(self.ui.set_ini_positions_pb)
302
- self.ui.horizontalLayout_2.addWidget(self.ui.start_batch_pb)
303
- self.ui.horizontalLayout_2.addWidget(self.ui.start_scan_pb)
304
- self.ui.horizontalLayout_2.addWidget(self.ui.stop_scan_pb)
305
-
306
- self.ui.settings_layout.addWidget(widget_buttons)
307
- self.ui.splitter.addWidget(sett_widget)
308
-
309
- # ##################TAB########################################
310
- self.ui.tabWidget = QtWidgets.QTabWidget()
311
-
312
- self.ui.tab_plot1D = QtWidgets.QWidget()
313
- self.ui.scan1D_layout = QtWidgets.QVBoxLayout()
314
- self.ui.tab_plot1D.setLayout(self.ui.scan1D_layout)
315
-
316
- self.ui.tab_plot2D = QtWidgets.QWidget()
317
- self.ui.scan2D_layout = QtWidgets.QVBoxLayout()
318
- self.ui.tab_plot2D.setLayout(self.ui.scan2D_layout)
319
-
320
- self.ui.tab_navigator = QtWidgets.QWidget()
321
- self.ui.navigator_layout = QtWidgets.QVBoxLayout()
322
- self.ui.tab_navigator.setLayout(self.ui.navigator_layout)
323
-
324
- self.ui.tabWidget.addTab(self.ui.tab_plot1D, "")
325
- self.ui.tabWidget.addTab(self.ui.tab_plot2D, "")
326
- self.ui.tabWidget.addTab(self.ui.tab_navigator, "")
327
- self.ui.tabWidget.setTabText(self.ui.tabWidget.indexOf(self.ui.tab_plot1D), '1D plot')
328
- self.ui.tabWidget.setTabText(self.ui.tabWidget.indexOf(self.ui.tab_plot2D), '2D plot')
329
- self.ui.tabWidget.setTabText(self.ui.tabWidget.indexOf(self.ui.tab_navigator), 'Navigator')
330
-
331
- self.ui.splitter.addWidget(self.ui.tabWidget)
332
- ##################################################################
333
-
334
- # %% create scan dock and make it a floating window
335
- self.ui.scan_dock = pymodaq.daq_utils.gui_utils.dock.Dock("Scan", size=(1, 1), autoOrientation=False) # give this dock the minimum possible size
336
- self.ui.scan_dock.setOrientation('vertical')
337
- self.ui.scan_dock.addWidget(widgetsettings)
338
-
339
- self.dockarea.addDock(self.ui.scan_dock, 'left')
340
- #self.ui.scan_dock.float()
341
-
342
- # %% init the 1D viewer
343
- self.ui.scan1D_graph_widget = QtWidgets.QSplitter(orientation=QtCore.Qt.Vertical)
344
- self.ui.scan1D_layout.addWidget(self.ui.scan1D_graph_widget)
345
-
346
- scan1D_widget = QtWidgets.QWidget()
347
- self.ui.scan1D_graph = Viewer1D(scan1D_widget)
348
- self.ui.scan1D_graph_widget.addWidget(scan1D_widget)
349
-
350
- # this subgraph is used to display axes values when performing scans as a function of multiple axes, and so
351
- # impossible to plot in usual 1D or 2D graphs
352
- scan1D_subgraph_widget = QtWidgets.QWidget()
353
- self.ui.scan1D_subgraph = Viewer1DBasic(scan1D_subgraph_widget)
354
- self.ui.scan1D_graph_widget.addWidget(scan1D_subgraph_widget)
355
- self.ui.scan1D_subgraph.show(False)
356
-
357
- # %% init the 2D viewer
358
- self.ui.scan2D_graph_widget = QtWidgets.QSplitter(orientation=QtCore.Qt.Vertical)
359
- self.ui.scan2D_layout.addWidget(self.ui.scan2D_graph_widget)
360
-
361
- scan2D_graph_widget = QtWidgets.QWidget()
362
- self.ui.scan2D_graph = Viewer2D(scan2D_graph_widget)
363
- self.ui.scan2D_graph_widget.addWidget(scan2D_graph_widget)
364
-
365
- # this subgraph is used to display axes values when performing scans as a function of multiple axes, and so
366
- # impossible to plot in usual 1D or 2D graphs
367
- scan2D_subgraph_widget = QtWidgets.QWidget()
368
- self.ui.scan2D_subgraph = Viewer1DBasic(scan2D_subgraph_widget)
369
- self.ui.scan2D_graph_widget.addWidget(scan2D_subgraph_widget)
370
- self.ui.scan2D_subgraph.show(False)
371
-
372
- self.ui.scan2D_graph.set_action_checked('histo', False)
373
- self.ui.scan2D_graph.set_action_visible(['flip_ud', 'flip_lr', 'rotate'], False)
374
- #self.ui.scan2D_graph.histogrammer.show_hide_histogram(False, [False for ind in range(3)])
375
-
376
-
377
- self.move_to_crosshair_action = QAction(
378
- QtGui.QIcon(QtGui.QPixmap(':/icons/Icon_Library/move_contour.png')),"Move at doubleClicked")
379
- self.move_to_crosshair_action.setCheckable(True)
380
- self.ui.move_to_crosshair_cb = self.move_to_crosshair_action
381
-
382
- self.ui.scan2D_graph.toolbar.addAction(self.move_to_crosshair_action)
383
- self.ui.scan2D_graph.sig_double_clicked.connect(self.move_to_crosshair)
384
-
385
- # %% init and set the status bar
386
- self.ui.statusbar = QtWidgets.QStatusBar(self.dockarea)
387
- self.ui.statusbar.setMaximumHeight(25)
388
- self.ui.StatusBarLayout.addWidget(self.ui.statusbar)
389
- self.ui.status_message = QtWidgets.QLabel('Initializing')
390
- self.ui.statusbar.addPermanentWidget(self.ui.status_message)
391
- self.ui.N_scan_steps_sb = pymodaq.daq_utils.gui_utils.widgets.spinbox.QSpinBox_ro()
392
- self.ui.N_scan_steps_sb.setToolTip('Total number of steps')
393
- self.ui.indice_scan_sb = pymodaq.daq_utils.gui_utils.widgets.spinbox.QSpinBox_ro()
394
- self.ui.indice_scan_sb.setToolTip('Current step value')
395
- self.ui.indice_average_sb = pymodaq.daq_utils.gui_utils.widgets.spinbox.QSpinBox_ro()
396
- self.ui.indice_average_sb.setToolTip('Current average value')
397
- self.ui.scan_done_LED = QLED()
398
- self.ui.scan_done_LED.setToolTip('Scan done state')
399
- self.ui.statusbar.addPermanentWidget(self.ui.N_scan_steps_sb)
400
- self.ui.statusbar.addPermanentWidget(self.ui.indice_scan_sb)
401
- self.ui.statusbar.addPermanentWidget(self.ui.indice_average_sb)
402
- self.ui.indice_average_sb.setVisible(False)
403
- self.ui.statusbar.addPermanentWidget(self.ui.scan_done_LED)
404
-
405
- self.plot_colors = utils.plot_colors
406
- self.ui.splitter.setSizes([500, 1200])
407
-
408
- self.ui.scan_done_LED.set_as_false()
409
- self.ui.scan_done_LED.clickable = False
410
-
411
- # displaying the settings
412
- widget_settings = QtWidgets.QWidget()
413
- settings_layout = QtWidgets.QGridLayout()
414
- widget_settings.setLayout(settings_layout)
415
- self.ui.settings_layout.addWidget(widget_settings)
416
-
417
- self.settings_tree = ParameterTree()
418
- self.settings_tree.setMinimumWidth(300)
419
-
420
- settings_layout.addWidget(self.modules_manager.settings_tree, 0, 0, 1, 1)
421
- self.ui.toolbox = QtWidgets.QToolBox()
422
- settings_layout.addWidget(self.ui.toolbox, 0, 1, 1, 1)
423
-
424
- self.ui.toolbox.addItem(self.settings_tree, 'General Settings')
425
- self.ui.toolbox.addItem(self.h5saver.settings_tree, 'Save Settings')
426
- self.ui.toolbox.addItem(self.scanner.settings_tree, 'Scanner Settings')
427
- self.ui.toolbox.setCurrentIndex(2)
428
-
429
- self.h5saver.settings_tree.setMinimumWidth(300)
430
- self.settings = Parameter.create(name='Settings', type='group', children=self.params)
431
-
432
- self.settings_tree.setParameters(self.settings, showTop=False)
433
- self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)
434
-
435
- # params about dataset attributes and scan attibutes
436
- date = QDateTime(QDate.currentDate(), QTime.currentTime())
437
- params_dataset = [{'title': 'Dataset information', 'name': 'dataset_info', 'type': 'group', 'children': [
438
- {'title': 'Author:', 'name': 'author', 'type': 'str', 'value': config['user']['name']},
439
- {'title': 'Date/time:', 'name': 'date_time', 'type': 'date_time', 'value': date},
440
- {'title': 'Sample:', 'name': 'sample', 'type': 'str', 'value': ''},
441
- {'title': 'Experiment type:', 'name': 'experiment_type', 'type': 'str', 'value': ''},
442
- {'title': 'Description:', 'name': 'description', 'type': 'text', 'value': ''}]}]
443
-
444
- params_scan = [{'title': 'Scan information', 'name': 'scan_info', 'type': 'group', 'children': [
445
- {'title': 'Author:', 'name': 'author', 'type': 'str', 'value': config['user']['name']},
446
- {'title': 'Date/time:', 'name': 'date_time', 'type': 'date_time', 'value': date},
447
- {'title': 'Scan type:', 'name': 'scan_type', 'type': 'list', 'value': 'Scan1D',
448
- 'limits': ['Scan1D', 'Scan2D']},
449
- {'title': 'Scan name:', 'name': 'scan_name', 'type': 'str', 'value': '', 'readonly': True},
450
- {'title': 'Description:', 'name': 'description', 'type': 'text', 'value': ''},
451
- ]}]
452
-
453
- self.dataset_attributes = Parameter.create(name='Attributes', type='group', children=params_dataset)
454
- self.scan_attributes = Parameter.create(name='Attributes', type='group', children=params_scan)
455
-
456
- # creating the Average dock plots
457
- self.create_average_dock()
458
-
459
- # creating the menubar
460
- self.create_menu()
461
-
462
- # connecting
463
- self.ui.set_scan_pb.clicked.connect(self.set_scan)
464
- self.ui.quit_pb.clicked.connect(self.quit_fun)
465
-
466
- self.ui.start_scan_pb.clicked.connect(self.start_scan)
467
- self.ui.start_batch_pb.clicked.connect(self.start_scan_batch)
468
- self.ui.stop_scan_pb.clicked.connect(self.stop_scan)
469
- self.ui.set_ini_positions_pb.clicked.connect(self.set_ini_positions)
470
-
471
- self.ui.tabWidget.removeTab(2)
472
-
473
- ###################
474
- # external modules
475
-
476
- def show_batcher(self, menubar):
477
- self.batcher = BatchScanner(self.dockarea, self.modules_manager.actuators_name,
478
- self.modules_manager.detectors_name)
479
- self.batcher.create_menu(menubar)
480
- self.batcher.setupUI()
481
- self.ui.start_batch_pb.setVisible(True)
482
-
483
- def start_scan_batch(self):
484
- self.batch_started = True
485
- self.ind_batch = 0
486
- self.loop_scan_batch()
487
-
488
- def loop_scan_batch(self):
489
- if self.ind_batch >= len(self.batcher.scans_names):
490
- self.stop_scan()
491
- return
492
- self.scanner = self.batcher.scans[self.batcher.scans_names[self.ind_batch]]
493
- actuators, detectors = self.batcher.get_act_dets()
494
- self.set_scan_batch(actuators[self.batcher.scans_names[self.ind_batch]],
495
- detectors[self.batcher.scans_names[self.ind_batch]])
496
- self.start_scan()
497
-
498
- def set_scan_batch(self, actuators, detectors):
499
- self.modules_manager.selected_detectors_name = detectors
500
- self.modules_manager.selected_actuators_name = actuators
501
- QtWidgets.QApplication.processEvents()
502
-
503
- def show_file_attributes(self, type_info='dataset'):
504
- """
505
- Switch the type_info value.
506
-
507
- In case of :
508
- * *scan* : Set parameters showing top false
509
- * *dataset* : Set parameters showing top false
510
- * *managers* : Set parameters showing top false. Add the save/cancel buttons to the accept/reject dialog (to save managers parameters in a xml file).
511
-
512
- Finally, in case of accepted managers type info, save the managers parameters in a xml file.
513
-
514
- =============== =========== ====================================
515
- **Parameters** **Type** **Description**
516
- *type_info* string The file type information between
517
- * scan
518
- * dataset
519
- * managers
520
- =============== =========== ====================================
521
-
522
- See Also
523
- --------
524
- custom_tree.parameter_to_xml_file, create_menu
525
- """
526
- if self.show_popup:
527
- dialog = QtWidgets.QDialog()
528
- vlayout = QtWidgets.QVBoxLayout()
529
- tree = ParameterTree()
530
- tree.setMinimumWidth(400)
531
- tree.setMinimumHeight(500)
532
- if type_info == 'scan':
533
- tree.setParameters(self.scan_attributes, showTop=False)
534
- elif type_info == 'dataset':
535
- tree.setParameters(self.dataset_attributes, showTop=False)
536
-
537
- vlayout.addWidget(tree)
538
- dialog.setLayout(vlayout)
539
- buttonBox = QtWidgets.QDialogButtonBox(parent=dialog)
540
- buttonBox.addButton('Cancel', buttonBox.RejectRole)
541
- buttonBox.addButton('Apply', buttonBox.AcceptRole)
542
- buttonBox.rejected.connect(dialog.reject)
543
- buttonBox.accepted.connect(dialog.accept)
544
-
545
- vlayout.addWidget(buttonBox)
546
- dialog.setWindowTitle('Fill in information about this {}'.format(type_info))
547
- res = dialog.exec()
548
- else:
549
- res = True
550
- return res
551
-
552
- def show_file_content(self):
553
- try:
554
- self.h5saver.init_file(addhoc_file_path=self.h5saver.settings.child(('current_h5_file')).value())
555
- self.h5saver.show_file_content()
556
- except Exception as e:
557
- logger.exception(str(e))
558
-
559
- def show_navigator(self):
560
- if self.navigator is None:
561
- # loading navigator
562
-
563
- widgnav = QtWidgets.QWidget()
564
- self.navigator = Navigator(widgnav)
565
-
566
- self.navigator.log_signal[str].connect(self.dashboard.add_status)
567
- self.navigator.settings.child('settings', 'Load h5').hide()
568
- self.navigator.loadaction.setVisible(False)
569
-
570
- self.ui.navigator_layout.addWidget(widgnav)
571
- self.navigator.sig_double_clicked.connect(self.move_at)
572
-
573
- self.scanner.scan_selector.remove_scan_selector()
574
- items = OrderedDict(Navigator=dict(viewers=[self.navigator.viewer], names=["Navigator"]))
575
- items.update(self.scanner.scan_selector.viewers_items)
576
- self.scanner.viewers_items = items
577
-
578
- self.ui.tabWidget.setCurrentIndex(self.ui.tabWidget.addTab(self.ui.tab_navigator, 'Navigator'))
579
- self.set_scan() # to load current scans into the navigator
580
-
581
- ################
582
- # LOADING SAVING
583
-
584
- def load_file(self):
585
- self.h5saver.load_file(self.h5saver.h5_file_path)
586
-
587
- def save_scan(self):
588
- """
589
- save live data and adds metadata to write that the scan is done
590
- """
591
- try:
592
- scan_type = self.scanner.scan_parameters.scan_type
593
- isadaptive = self.scanner.scan_parameters.scan_subtype == 'Adaptive'
594
- self.ui.scan2D_graph.show_roi_target(False)
595
-
596
- self.h5saver.current_scan_group.attrs['scan_done'] = True
597
- self.h5saver.init_file(addhoc_file_path=self.h5saver.settings.child(('current_h5_file')).value())
598
- # create Live scan node (may be empty if no possible live data could be plotted) but mandatory for
599
- # incrementing scan index, otherwise current scan is overwritten
600
- if scan_type == 'Scan1D' or \
601
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 1) or \
602
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes > 2) or \
603
- scan_type == 'Tabular':
604
- live_group = self.h5saver.add_live_scan_group(self.h5saver.current_scan_group, '1D', title='',
605
- settings_as_xml='', metadata=dict([]))
606
- else: # scan_type == 'Scan2D' or\
607
- # (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 2):
608
- live_group = self.h5saver.add_live_scan_group(self.h5saver.current_scan_group, '2D', title='',
609
- settings_as_xml='', metadata=dict([]))
610
-
611
- # save scan1D
612
- if len(self.scan_data_1D) != 0:
613
-
614
- if self.settings.child('scan_options', 'scan_average').value() <= 1:
615
- datas = OrderedDict([])
616
- for ind in range(self.scan_data_1D.shape[1]):
617
- datas['Scan_Data_{:03d}'.format(ind)] = OrderedDict([])
618
- datas['Scan_Data_{:03d}'.format(ind)]['data'] = self.scan_data_1D[:, ind]
619
- if len(self.scan_data_1D[:, 0]) > 1: # means data are 1D (so save corresponding axis)
620
- if scan_type == 'Scan1D' or \
621
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 1):
622
- datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = utils.Axis(
623
- data=self.scan_x_axis,
624
- units=self.modules_manager.actuators[0].settings.child(
625
- 'move_settings', 'units').value(),
626
- label=self.modules_manager.actuators[0].title)
627
- else:
628
- datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = utils.Axis(data=self.scan_x_axis,
629
- units='',
630
- label='Scan indexes')
631
-
632
- for ind_channel, channel in enumerate(datas): # list of OrderedDict
633
- channel_group = self.h5saver.add_CH_group(live_group, title=channel)
634
- self.h5saver.add_data_live_scan(channel_group, datas['Scan_Data_{:03d}'.format(ind_channel)],
635
- scan_type='scan1D',
636
- scan_subtype=self.scanner.scan_parameters.scan_subtype)
637
-
638
- else:
639
- averaged_datas = OrderedDict([])
640
- for ind in range(self.scan_data_1D.shape[1]):
641
- averaged_datas['Scan_Data_{:03d}'.format(ind)] = OrderedDict([])
642
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['data'] = self.scan_data_1D_average[:, ind]
643
- if scan_type == 'Scan1D' or \
644
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 1):
645
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = utils.Axis(
646
- data=self.scan_x_axis,
647
- units=self.modules_manager.actuators[0].settings.child(
648
- 'move_settings', 'units').value(),
649
- label=self.modules_manager.actuators[0].title)
650
- else:
651
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = utils.Axis(
652
- data=self.scan_x_axis, units='', label='Scan indexes')
653
-
654
- for ind_channel, channel in enumerate(averaged_datas): # list of OrderedDict
655
- channel_group = self.h5saver.add_CH_group(live_group, title=channel)
656
- self.h5saver.add_data_live_scan(channel_group,
657
- averaged_datas['Scan_Data_{:03d}'.format(ind_channel)],
658
- scan_type='scan1D',
659
- scan_subtype=self.scanner.scan_parameters.scan_subtype)
660
-
661
- if self.settings.child('scan_options', 'scan_average').value() > 1:
662
- string = pymodaq.daq_utils.gui_utils.utils.widget_to_png_to_bytes(self.ui.average1D_graph.parent)
663
- else:
664
- string = pymodaq.daq_utils.gui_utils.utils.widget_to_png_to_bytes(self.ui.scan1D_graph.parent)
665
- live_group.attrs['pixmap1D'] = string
666
-
667
- elif self.scan_data_2D != []: #if live data is saved as 1D not needed to save as 2D
668
-
669
- if len(self.modules_manager.actuators) == 1:
670
- scan_type = 'scan1D'
671
- elif len(self.modules_manager.actuators) == 2:
672
- scan_type = 'scan2D'
673
- if not isadaptive:
674
- if self.settings.child('scan_options', 'scan_average').value() <= 1:
675
- datas = OrderedDict([])
676
- for ind, data2D in enumerate(self.scan_data_2D):
677
- datas['Scan_Data_{:03d}'.format(ind)] = OrderedDict([])
678
- datas['Scan_Data_{:03d}'.format(ind)]['data'] = data2D.T
679
- datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = dict(
680
- data=self.ui.scan2D_graph.x_axis.axis_data(data2D.shape[1]),
681
- units=self.ui.scan2D_graph.x_axis.axis_units,
682
- label=self.ui.scan2D_graph.x_axis.axis_label)
683
- if scan_type == 'scan2D':
684
- datas['Scan_Data_{:03d}'.format(ind)]['y_axis'] = dict(
685
- data=self.ui.scan2D_graph.y_axis.axis_data(data2D.shape[0]),
686
- units=self.ui.scan2D_graph.y_axis.axis_units,
687
- label=self.ui.scan2D_graph.y_axis.axis_label)
688
-
689
- for ind_channel, channel in enumerate(datas): # list of OrderedDict
690
- channel_group = self.h5saver.add_CH_group(live_group, title=channel)
691
- self.h5saver.add_data_live_scan(channel_group,
692
- datas['Scan_Data_{:03d}'.format(ind_channel)],
693
- scan_type=scan_type,
694
- scan_subtype=self.scanner.scan_parameters.scan_subtype)
695
-
696
- else:
697
- averaged_datas = OrderedDict([])
698
- for ind, data2D in enumerate(self.scan_data_2D_average):
699
- averaged_datas['Scan_Data_{:03d}'.format(ind)] = OrderedDict([])
700
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['data'] = data2D.T
701
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['x_axis'] = dict(
702
- data=self.ui.scan2D_graph.x_axis.axis_data(data2D.shape[1]),
703
- units=self.ui.scan2D_graph.x_axis.axis_units,
704
- label=self.ui.scan2D_graph.x_axis.axis_label)
705
- if scan_type == 'scan2D':
706
- averaged_datas['Scan_Data_{:03d}'.format(ind)]['y_axis'] = dict(
707
- data=self.ui.scan2D_graph.y_axis.axis_data(data2D.shape[0]),
708
- units=self.ui.scan2D_graph.y_axis.axis_units,
709
- label=self.ui.scan2D_graph.y_axis.axis_label)
710
-
711
- for ind_channel, channel in enumerate(averaged_datas): # dict of OrderedDict
712
- channel_group = self.h5saver.add_CH_group(live_group, title=channel)
713
- self.h5saver.add_data_live_scan(channel_group, averaged_datas[
714
- 'Scan_Data_{:03d}'.format(ind_channel)],
715
- scan_type=scan_type, scan_subtype=self.scanner.scan_parameters.scan_subtype)
716
-
717
- else:
718
- channel_group = self.h5saver.add_CH_group(live_group, title='Scan_Data_000')
719
- self.h5saver.add_data_live_scan(channel_group, dict(data=self.scan_data_2D[:, 2],
720
- x_axis=self.scan_data_2D[:, 0],
721
- y_axis=self.scan_data_2D[:, 1]),
722
- scan_type=scan_type,
723
- scan_subtype=self.scanner.scan_parameters.scan_subtype)
724
-
725
- if self.settings.child('scan_options', 'scan_average').value() > 1:
726
- string = pymodaq.daq_utils.gui_utils.utils.widget_to_png_to_bytes(self.ui.average2D_graph.parent)
727
- else:
728
- string = pymodaq.daq_utils.gui_utils.utils.widget_to_png_to_bytes(self.ui.scan2D_graph.parent)
729
- live_group.attrs['pixmap2D'] = string
730
-
731
- if self.navigator is not None:
732
- self.navigator.update_2Dscans()
733
-
734
- except Exception as e:
735
- logger.exception(str(e))
736
-
737
- def save_file(self):
738
- if not os.path.isdir(self.h5saver.settings.child(('base_path')).value()):
739
- os.mkdir(self.h5saver.settings.child(('base_path')).value())
740
- filename = pymodaq.daq_utils.gui_utils.file_io.select_file(self.h5saver.settings.child(('base_path')).value(), save=True, ext='h5')
741
- self.h5saver.h5_file.copy_file(str(filename))
742
-
743
- def save_metadata(self, node, type_info='dataset_info'):
744
- """
745
- Switch the type_info value with :
746
- * *'dataset_info'* : Give the params attributes the dataset_attributes values
747
- * *'dataset'* : Give the params attributes the scan_attributes values
748
-
749
- |
750
- | Once done, course the params and add string casted date/time metadata as an element of attributes array.
751
- | Save the contents of given parameter object into a xml string unde the attributes settings.
752
-
753
- =============== =================== =========================================
754
- **Parameters** **Type** **Description**
755
- *node* pytables h5 node Root node to be treated
756
- *type_info* string File type info between :
757
- * 'dataset_info'
758
- * 'scan_info'
759
- =============== =================== =========================================
760
-
761
- See Also
762
- --------
763
- custom_tree.parameter_to_xml_string
764
- """
765
-
766
- attr = node.attrs
767
- if type_info == 'dataset_info':
768
- attr['type'] = 'dataset'
769
- params = self.dataset_attributes
770
- else:
771
- attr['type'] = 'scan'
772
- params = self.scan_attributes
773
- for child in params.child((type_info)).children():
774
- if type(child.value()) is QDateTime:
775
- attr[child.name()] = child.value().toString('dd/mm/yyyy HH:MM:ss')
776
- else:
777
- attr[child.name()] = child.value()
778
- if type_info == 'dataset_info':
779
- # save contents of given parameter object into an xml string under the attribute settings
780
- settings_str = b'<All_settings title="All Settings" type="group">' + \
781
- pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(params) + \
782
- pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(self.settings)
783
- # pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(
784
- # self.dashboard.preset_manager.preset_params) +\
785
- settings_str += b'</All_settings>'
786
- attr['settings'] = settings_str
787
-
788
- elif type_info == 'scan_info':
789
- settings_all = [pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(params),
790
- pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(self.settings),
791
- pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(self.h5saver.settings),
792
- pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(self.scanner.settings)]
793
-
794
- settings_str = b'<All_settings title="All Settings" type="group">'
795
- for set in settings_all:
796
- if len(settings_str + set) < 60000:
797
- # size limit for any object header (including all the other attributes) is 64kb
798
- settings_str += set
799
- else:
800
- break
801
- settings_str += b'</All_settings>'
802
- attr['settings'] = settings_str
803
-
804
- def create_new_file(self, new_file):
805
- self.h5saver.init_file(update_h5=new_file)
806
- res = self.update_file_settings(new_file)
807
- self.h5saver.current_scan_group.attrs['scan_done'] = False
808
- if new_file:
809
- self.ui.start_scan_pb.setEnabled(False)
810
- self.ui.stop_scan_pb.setEnabled(False)
811
- return res
812
-
813
- def update_file_settings(self, new_file=False):
814
- try:
815
- if self.h5saver.current_scan_group is None:
816
- new_file = True
817
-
818
- if new_file:
819
- self.set_metadata_about_dataset()
820
- self.save_metadata(self.h5saver.raw_group, 'dataset_info')
821
-
822
- if self.h5saver.current_scan_name is None:
823
- self.h5saver.add_scan_group()
824
- elif not self.h5saver.is_node_in_group(self.h5saver.raw_group, self.h5saver.current_scan_name):
825
- self.h5saver.add_scan_group()
826
-
827
- if self.navigator is not None:
828
- self.navigator.update_h5file(self.h5saver.h5_file)
829
- self.navigator.settings.child('settings', 'filepath').setValue(self.h5saver.h5_file.filename)
830
-
831
- # set attributes to the current group, such as scan_type....
832
- self.scan_attributes.child('scan_info', 'scan_type').setValue(
833
- self.scanner.settings.child('scan_type').value())
834
- self.scan_attributes.child('scan_info', 'scan_name').setValue(self.h5saver.current_scan_group.name)
835
- self.scan_attributes.child('scan_info', 'description').setValue(
836
- self.h5saver.current_scan_group.attrs['description'])
837
- res = self.set_metadata_about_current_scan()
838
- self.save_metadata(self.h5saver.current_scan_group, 'scan_info')
839
- return res
840
-
841
- except Exception as e:
842
- logger.exception(str(e))
843
-
844
- # PROCESS MODIFICATIONS
845
-
846
- @Slot(list)
847
- def update_actuators(self, actuators):
848
- self.scanner.actuators = actuators
849
-
850
- def move_to_crosshair(self, posx=None, posy=None):
851
- """
852
- Compute the scaled position from the given x/y position and send the command_DAQ signal with computed values as attributes.
853
-
854
-
855
- =============== =========== ==============================
856
- **Parameters** **Type** **Description**
857
- *posx* float the original x position
858
- *posy* float the original y position
859
- =============== =========== ==============================
860
-
861
- See Also
862
- --------
863
- update_status
864
- """
865
- try:
866
- if self.ui.move_to_crosshair_cb.isChecked():
867
- if "2D" in self.scanner.settings.child('scan_type').value():
868
- if len(self.modules_manager.actuators) == 2 and posx is not None and posy is not None:
869
- posx_real = posx * self.ui.scan2D_graph.x_axis.axis_scaling +\
870
- self.ui.scan2D_graph.x_axis.axis_offset
871
- posy_real = posy * self.ui.scan2D_graph.y_axis.axis_scaling +\
872
- self.ui.scan2D_graph.y_axis.axis_offset
873
- self.move_at(posx_real, posy_real)
874
- else:
875
- self.update_status("not valid configuration, check number of stages and scan2D option",
876
- log_type='log')
877
- except Exception as e:
878
- logger.exception(str(e))
879
- # self.update_status(getLineInfo()+ str(e),log_type='log')
880
-
881
- def move_at(self, posx_real, posy_real):
882
- self.command_DAQ_signal.emit(["move_stages", [posx_real, posy_real]])
883
-
884
- def parameter_tree_changed(self, param, changes):
885
- """
886
- Check for changes in the given (parameter,change,information) tuple list.
887
- In case of value changed, update the DAQscan_settings tree consequently.
888
-
889
- =============== ============================================ ==============================
890
- **Parameters** **Type** **Description**
891
- *param* instance of pyqtgraph parameter the parameter to be checked
892
- *changes* (parameter,change,information) tuple list the current changes state
893
- =============== ============================================ ==============================
894
- """
895
- for param, change, data in changes:
896
- path = self.settings.childPath(param)
897
- if path is not None:
898
- childName = '.'.join(path)
899
- else:
900
- childName = param.name()
901
- if change == 'childAdded':
902
- pass
903
-
904
- elif change == 'value':
905
- if param.name() == 'scan_average':
906
- self.show_average_dock(param.value() > 1)
907
-
908
- elif change == 'parent':
909
- pass
910
-
911
- def update_plot_det_items(self, dets):
912
- """
913
- """
914
- self.settings.child('scan_options', 'plot_from').setOpts(limits=dets)
915
-
916
- def update_status(self, txt, wait_time=0, log_type=None):
917
- """
918
- Show the txt message in the status bar with a delay of wait_time ms.
919
-
920
- =============== =========== =======================
921
- **Parameters** **Type** **Description**
922
- *txt* string The message to show
923
- *wait_time* int the delay of showing
924
- *log_type* string the type of the log
925
- =============== =========== =======================
926
- """
927
- self.ui.statusbar.showMessage(txt, wait_time)
928
- self.status_signal.emit(txt)
929
- logger.info(txt)
930
-
931
- @Slot(list)
932
- def thread_status(self, status): # general function to get datas/infos from all threads back to the main
933
- """
934
- | General function to get datas/infos from all threads back to the main.
935
- |
936
-
937
- Switch the status with :
938
- * *"Update status"* : Update the status bar with the status attribute txt message
939
- * *"Update_scan_index"* : Set the value of the User Interface - indice_scan_sb attribute.
940
- * *"Scan_done"* : Save the scan and init the positions
941
- * *"Timeout"* : Set the "Timeout occured" in the User Interface-log message
942
-
943
- See Also
944
- --------
945
- update_status, save_scan, set_ini_positions
946
- """
947
- if status[0] == "Update_Status":
948
- self.update_status(status[1], wait_time=self.wait_time)
949
-
950
- elif status[0] == "Update_scan_index":
951
- # status[1] = [ind_scan,ind_average]
952
- self.ind_scan = status[1][0]
953
- self.ui.indice_scan_sb.setValue(status[1][0])
954
- self.ind_average = status[1][1]
955
- self.ui.indice_average_sb.setValue(status[1][1])
956
-
957
- elif status[0] == "Scan_done":
958
- self.ui.scan_done_LED.set_as_true()
959
- self.save_scan()
960
- if not self.batch_started:
961
- if not self.dashboard.overshoot:
962
- self.set_ini_positions()
963
- self.ui.set_scan_pb.setEnabled(True)
964
- self.ui.set_ini_positions_pb.setEnabled(True)
965
- self.ui.start_scan_pb.setEnabled(True)
966
-
967
- # reactivate module controls usiong remote_control
968
- if hasattr(self.dashboard, 'remote_manager'):
969
- remote_manager = getattr(self.dashboard, 'remote_manager')
970
- remote_manager.activate_all(True)
971
- else:
972
- self.ind_batch += 1
973
- self.loop_scan_batch()
974
-
975
- elif status[0] == "Timeout":
976
- self.ui.status_message.setText('Timeout occurred')
977
-
978
- ############
979
- # PLOTTING
980
-
981
- def show_average_dock(self, show=True):
982
- self.ui.average_dock.setVisible(show)
983
- self.ui.indice_average_sb.setVisible(show)
984
- if show:
985
- self.ui.average_dock.setStretch(100, 100)
986
-
987
- @Slot(OrderedDict)
988
- def update_scan_GUI(self, datas):
989
- """
990
- Update the graph in the Graphic Interface from the given datas switching 0D/1D/2D consequently.
991
-
992
- =============== =============================== ===========================
993
- **Parameters** **Type** **Description**
994
- *datas* double precision float array the data values to update
995
- =============== =============================== ===========================
996
-
997
- See Also
998
- --------
999
- update_2D_graph, update_1D_graph, update_status
1000
- """
1001
-
1002
- self.scan_positions.append(self.modules_manager.order_positions(datas['positions']))
1003
- scan_type = utils.capitalize(self.scanner.scan_parameters.scan_type)
1004
-
1005
- display_as_sequence = (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes > 2) or \
1006
- (scan_type == 'Tabular' and not self.scanner.scan_parameters.Naxes == 1)
1007
-
1008
- tabular2D = scan_type == 'Tabular' and self.scanner.scan_parameters.Naxes == 2
1009
- isadaptive = self.scanner.scan_parameters.scan_subtype == 'Adaptive'
1010
- if 'curvilinear' in datas:
1011
- self.curvilinear_values.append(datas['curvilinear'])
1012
-
1013
- if self.bkg_container is None:
1014
- det_name = self.settings.child('scan_options', 'plot_from').value()
1015
- det_mod = self.modules_manager.get_mod_from_name(det_name)
1016
- if det_mod.bkg is not None and det_mod.is_bkg:
1017
- self.bkg_container = OrderedDict([])
1018
- det_mod.process_data(det_mod.bkg, self.bkg_container)
1019
-
1020
- try:
1021
- if scan_type == 'Scan1D' or \
1022
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 1) or \
1023
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes > 2) or \
1024
- (scan_type == 'Tabular' and self.scanner.scan_parameters.Naxes == 1) or \
1025
- (scan_type == 'Tabular' and self.scanner.scan_parameters.Naxes > 2):
1026
-
1027
- if 'data0D' in datas['datas'].keys():
1028
- if not (datas['datas']['data0D'] is None or datas['datas']['data0D'] == OrderedDict()):
1029
- if self.bkg_container is None:
1030
- bkg = None
1031
- else:
1032
- bkg = self.bkg_container['data0D']
1033
- self.update_1D_graph(datas['datas']['data0D'], display_as_sequence=display_as_sequence,
1034
- isadaptive=isadaptive, bkg=bkg)
1035
- else:
1036
- self.scan_data_1D = []
1037
- if 'data1D' in datas['datas'].keys():
1038
- if not (datas['datas']['data1D'] is None or datas['datas']['data1D'] == OrderedDict()):
1039
- if self.bkg_container is None:
1040
- bkg = None
1041
- else:
1042
- bkg = self.bkg_container['data1D']
1043
- self.update_2D_graph(datas['datas']['data1D'], display_as_sequence=display_as_sequence,
1044
- isadaptive=isadaptive, bkg=bkg)
1045
- # else:
1046
- # self.scan_data_2D = []
1047
-
1048
- if scan_type == 'Scan2D' or \
1049
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 2) or \
1050
- tabular2D:
1051
- # means 2D cartography type scan
1052
-
1053
- if 'data0D' in datas['datas'].keys():
1054
- if not (datas['datas']['data0D'] is None or datas['datas']['data0D'] == OrderedDict()):
1055
- if self.bkg_container is None:
1056
- bkg = None
1057
- else:
1058
- bkg = self.bkg_container['data0D']
1059
- self.update_2D_graph(datas['datas']['data0D'], display_as_sequence=display_as_sequence,
1060
- isadaptive=isadaptive or tabular2D, bkg=bkg)
1061
- else:
1062
- self.scan_data_2D = []
1063
-
1064
- except Exception as e:
1065
- logger.exception(str(e))
1066
-
1067
- def update_1D_graph(self, datas, display_as_sequence=False, isadaptive=False, bkg=None):
1068
- """
1069
- Update the 1D graphic window in the Graphic Interface with the given datas.
1070
-
1071
- Depending of scan type :
1072
- * *'Linear back to start'* scan :
1073
- * Calibrate axis positions between graph and scan
1074
- * Update scan datas from the given datas values
1075
- * Set data on item attribute
1076
- * *'linear'* or else scan :
1077
- * Calibrate axis positions between graph and scan
1078
- * Update scan datas from the given datas values
1079
-
1080
- =============== ============================== =====================================
1081
- **Parameters** **Type** **Description**
1082
- *datas* Double precision float array The datas to be showed in the graph
1083
- =============== ============================== =====================================
1084
-
1085
- See Also
1086
- --------
1087
- update_status
1088
- """
1089
- try:
1090
- scan_type = self.scanner.scan_parameters.scan_type
1091
- # self.scan_y_axis = np.array([])
1092
- if not self.plot_1D_ini: # init the datas
1093
- self.plot_1D_ini = True
1094
- self.ui.scan1D_subgraph.show(display_as_sequence)
1095
- if isadaptive:
1096
- self.scan_data_1D = np.expand_dims(np.array([datas[key]['data'] for key in datas]), 0)
1097
- else:
1098
- if not display_as_sequence:
1099
- if self.scanner.scan_parameters.scan_subtype == 'Linear back to start':
1100
- self.scan_x_axis = np.array(self.scanner.scan_parameters.positions[0::2, 0])
1101
- else:
1102
- self.scan_x_axis = np.array(self.scanner.scan_parameters.positions[:, 0])
1103
-
1104
- else:
1105
- self.scan_x_axis = np.linspace(0, len(self.scanner.scan_parameters.positions) - 1,
1106
- len(self.scanner.scan_parameters.positions))
1107
- self.ui.scan1D_subgraph.show_data(
1108
- [positions for positions in self.scanner.scan_parameters.positions.T])
1109
- self.ui.scan1D_subgraph.update_labels(self.scanner.actuators)
1110
- self.ui.scan1D_subgraph.set_axis_label(axis_settings=dict(orientation='bottom',
1111
- label='Scan index', units=''))
1112
-
1113
- self.scan_data_1D = np.zeros((self.scanner.scan_parameters.Nsteps, len(datas))) * np.nan
1114
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1115
- self.scan_data_1D_average = np.zeros((self.scanner.scan_parameters.Nsteps, len(datas)))
1116
-
1117
- self.ui.scan1D_graph.set_axis_label(axis_settings=dict(orientation='left',
1118
- label=self.settings.child('scan_options',
1119
- 'plot_from').value(),
1120
- units=''))
1121
-
1122
- if display_as_sequence:
1123
- self.ui.scan1D_subgraph.show_data(
1124
- [positions for positions in np.array(self.scan_positions).T])
1125
- self.ui.scan1D_subgraph.update_labels(self.scanner.actuators)
1126
- self.ui.scan1D_subgraph.set_axis_label(axis_settings=dict(orientation='bottom',
1127
- label='Scan index', units=''))
1128
-
1129
- # to test random mode:
1130
- # self.scan_data_1D[self.ind_scan, :] =np.random.rand((1))* np.array([np.exp(-(self.scan_x_axis[self.ind_scan]-50)**2/20**2),np.exp(-(self.scan_x_axis[self.ind_scan]-50)**6/10**6)]) # np.array(list(datas.values()))
1131
- # self.scan_data_1D[self.ind_scan, :] = np.array(list(datas.values()))
1132
-
1133
- if isadaptive:
1134
- if self.ind_scan != 0:
1135
-
1136
- self.scan_data_1D = np.vstack((self.scan_data_1D, np.array([
1137
- self.get_data_live_bkg(datas, key, bkg) for key in datas])))
1138
-
1139
- if not display_as_sequence:
1140
- self.scan_x_axis = np.array(self.scan_positions)
1141
- else:
1142
- if isadaptive:
1143
- self.scan_x_axis = np.array(self.curvilinear_values)
1144
- else:
1145
- self.scan_x_axis = np.linspace(0, len(self.scan_positions) - 1,
1146
- len(self.scan_positions))
1147
- else:
1148
- if self.scanner.scan_parameters.scan_subtype == 'Linear back to start':
1149
- if not utils.odd_even(self.ind_scan):
1150
-
1151
- self.scan_data_1D[int(self.ind_scan / 2), :] = \
1152
- np.array([self.get_data_live_bkg(datas, key, bkg) for key in datas])
1153
-
1154
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1155
- self.scan_data_1D_average[self.ind_scan, :] = \
1156
- (self.ind_average * self.scan_data_1D_average[
1157
- int(self.ind_scan / 2), :] + self.scan_data_1D[
1158
- int(self.ind_scan / 2), :]) / (self.ind_average + 1)
1159
-
1160
- else:
1161
- self.scan_data_1D[self.ind_scan, :] = \
1162
- np.squeeze(np.array([self.get_data_live_bkg(datas, key, bkg) for key in datas]))
1163
-
1164
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1165
- self.scan_data_1D_average[self.ind_scan, :] = \
1166
- (self.ind_average * self.scan_data_1D_average[self.ind_scan, :] + self.scan_data_1D[
1167
- self.ind_scan, :]) / (self.ind_average + 1)
1168
-
1169
- data_to_plot = list(self.scan_data_1D.T)
1170
- if self.settings.child('scan_options', 'sort_scan1D').value():
1171
- x_axis_to_plot, indices = np.unique(self.scan_x_axis, return_index=True)
1172
- data_to_plot = [data[indices] for data in data_to_plot]
1173
- else:
1174
- x_axis_to_plot = np.squeeze(self.scan_x_axis)
1175
-
1176
- if not display_as_sequence:
1177
- x_axis = utils.Axis(data=x_axis_to_plot,
1178
- label=self.modules_manager.actuators[0].title,
1179
- units=self.modules_manager.actuators[0].settings.child('move_settings',
1180
- 'units').value())
1181
- else:
1182
- if isadaptive:
1183
- x_axis = utils.Axis(data=x_axis_to_plot, label='Curvilinear value', units='')
1184
- else:
1185
- x_axis = utils.Axis(data=x_axis_to_plot, label='Scan index', units='')
1186
-
1187
- #self.ui.scan1D_graph.x_axis = x_axis
1188
- self.ui.scan1D_graph.show_data(data_to_plot, x_axis=x_axis)
1189
- self.live_data_1D_signal.emit([x_axis, data_to_plot])
1190
-
1191
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1192
- data_averaged_sorted = list(self.scan_data_1D_average.T)
1193
- if self.settings.child('scan_options', 'sort_scan1D').value():
1194
- data_averaged_sorted = [data[indices] for data in data_averaged_sorted]
1195
- self.ui.average1D_graph.show_data(data_averaged_sorted, x_axis=x_axis)
1196
-
1197
- except Exception as e:
1198
- logger.exception(str(e))
1199
-
1200
- def get_data_live_bkg(self, datas, key, bkg):
1201
- bkg_flag = False
1202
- if bkg is not None:
1203
- if key in bkg:
1204
- bkg_flag = True
1205
- if bkg_flag:
1206
- data = datas[key]['data'] - bkg[key]['data']
1207
- else:
1208
- data = datas[key]['data']
1209
- return data
1210
-
1211
- def update_2D_graph(self, datas, display_as_sequence=False, isadaptive=False, bkg=None):
1212
- """
1213
- Update the 2D graphic window in the Graphic Interface with the given datas (if not none).
1214
-
1215
- Depending on scan type :
1216
- * *2D scan* :
1217
- * Calibrate the axis positions between graphic and scan
1218
- * Update scan datas with the given datas values.
1219
- * Set an image with the updated scan data
1220
- * *1D scan* :
1221
- * Calibrate the axis positions between graphic and scan
1222
- * Update scan datas with the given datas values.
1223
- * Concatenate 1D vectors to make a 2D image
1224
- * Set an image with the updated scan data
1225
-
1226
- =============== =============================== ===========================
1227
- **Parameters** **Type** **Description**
1228
- *datas* double precision float array the data values to update
1229
- =============== =============================== ===========================
1230
-
1231
- See Also
1232
- --------
1233
- update_status
1234
- """
1235
- try:
1236
- scan_type = self.scanner.scan_parameters.scan_type
1237
- if scan_type == 'Scan2D' or \
1238
- (scan_type == 'Sequential' and self.scanner.scan_parameters.Naxes == 2) or \
1239
- (scan_type == 'Tabular' and self.scanner.scan_parameters.Naxes == 2):
1240
-
1241
- if not self.plot_2D_ini: # init the data
1242
- # self.ui.scan1D_subgraph.show(False)
1243
- self.plot_2D_ini = True
1244
- self.ui.scan2D_graph.show_roi_target(not isadaptive)
1245
- if isadaptive:
1246
- self.scan_x_axis2D = np.array(self.scan_positions)[:, 0]
1247
- self.scan_y_axis = np.array(self.scan_positions)[:, 1]
1248
- key = list(datas.keys())[0]
1249
- if bkg is not None:
1250
- self.scan_data_2D = \
1251
- np.hstack((self.scan_positions[-1], datas[key]['data'] - bkg[key]['data']))
1252
- else:
1253
- self.scan_data_2D = \
1254
- np.hstack((self.scan_positions[-1], datas[key]['data']))
1255
- else:
1256
-
1257
- self.scan_x_axis2D = self.scanner.scan_parameters.axes_unique[0]
1258
- self.scan_y_axis = self.scanner.scan_parameters.axes_unique[1]
1259
- self.scan_data_2D = [np.zeros((len(self.scan_y_axis),
1260
- len(self.scan_x_axis2D)))
1261
- for ind in range(min((3, len(datas))))]
1262
- self.ui.scan2D_graph.x_axis = utils.Axis(data=self.scan_x_axis2D,
1263
- units=self.modules_manager.actuators[0].settings.child(
1264
- 'move_settings', 'units').value(),
1265
- label=self.modules_manager.actuators[0].title)
1266
- self.ui.scan2D_graph.y_axis = utils.Axis(data=self.scan_y_axis,
1267
- units=self.modules_manager.actuators[1].settings.child(
1268
- 'move_settings', 'units').value(),
1269
-
1270
- label=self.modules_manager.actuators[1].title)
1271
- size = (self.scanner.scan_parameters.steps[0] / self.ui.scan2D_graph.x_axis.axis_scaling,
1272
- self.scanner.scan_parameters.steps[1] / self.ui.scan2D_graph.y_axis.axis_scaling)
1273
- self.ui.scan2D_graph.move_scale_roi_target(size=size)
1274
-
1275
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1276
- self.ui.average2D_graph.x_axis = utils.Axis(data=self.scan_x_axis2D,
1277
- units=self.modules_manager.actuators[0].settings.child(
1278
- 'move_settings', 'units').value(),
1279
- label=self.modules_manager.actuators[0].title)
1280
- self.ui.average2D_graph.y_axis = utils.Axis(data=self.scan_y_axis,
1281
- units=self.modules_manager.actuators[1].settings.child(
1282
- 'move_settings', 'units').value(),
1283
- label=self.modules_manager.actuators[1].title)
1284
- self.scan_data_2D_average = [np.zeros((len(self.scanner.scan_parameters.axis_2D_2),
1285
- len(self.scanner.scan_parameters.axis_2D_1)))
1286
- for ind in range(min((3, len(datas))))]
1287
-
1288
- if not isadaptive:
1289
- ind_pos_axis_1 = self.scanner.scan_parameters.axes_indexes[self.ind_scan, 0]
1290
- ind_pos_axis_2 = self.scanner.scan_parameters.axes_indexes[self.ind_scan, 1]
1291
- self.ui.scan2D_graph.move_scale_roi_target(pos=(ind_pos_axis_1, ind_pos_axis_2))
1292
- for ind_plot in range(min((3, len(datas)))):
1293
- keys = list(datas.keys())
1294
-
1295
- self.scan_data_2D[ind_plot][ind_pos_axis_2, ind_pos_axis_1] = \
1296
- self.get_data_live_bkg(datas, keys[ind_plot], bkg)
1297
-
1298
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1299
- self.scan_data_2D_average[ind_plot][ind_pos_axis_2, ind_pos_axis_1] = \
1300
- (self.ind_average * self.scan_data_2D_average[ind_plot][
1301
- ind_pos_axis_2, ind_pos_axis_1] + datas[
1302
- keys[ind_plot]]['data']) / (self.ind_average + 1)
1303
- self.ui.scan2D_graph.show_data(utils.DataFromPlugins(dim='Data2D', data=self.scan_data_2D))
1304
-
1305
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1306
- self.ui.average2D_graph.setImage(*self.scan_data_2D_average)
1307
-
1308
- else:
1309
- if self.ind_scan != 0:
1310
- key = list(datas.keys())[0]
1311
-
1312
- self.scan_data_2D = np.vstack((self.scan_data_2D,
1313
- np.hstack((self.scan_positions[-1],
1314
- self.get_data_live_bkg(datas, key, bkg)))))
1315
-
1316
- if len(self.scan_data_2D) > 3: # at least 3 point to make a triangulation image
1317
- self.ui.scan2D_graph.setImage(data_spread=self.scan_data_2D)
1318
-
1319
- else: # scan 1D with concatenation of vectors making a 2D image
1320
- if not self.plot_2D_ini: # init the data
1321
- self.plot_2D_ini = True
1322
- if display_as_sequence:
1323
- self.ui.scan2D_subgraph.show(True)
1324
- self.ui.scan2D_subgraph.show_data(
1325
- [positions for positions in self.scanner.scan_parameters.positions.T])
1326
- self.ui.scan2D_subgraph.update_labels(self.scanner.actuators)
1327
-
1328
- data = datas[list(datas.keys())[0]]
1329
- Ny = len(data[list(data.keys())[0]])
1330
-
1331
- self.scan_y_axis = np.array([])
1332
-
1333
- Nx = len(self.scanner.scan_parameters.positions)
1334
- if not display_as_sequence:
1335
-
1336
- if self.scanner.scan_parameters.scan_subtype == 'Linear back to start':
1337
- self.scan_x_axis2D = np.array(self.scanner.scan_parameters.positions[0::2, 0])
1338
- else:
1339
- self.scan_x_axis2D = np.array(self.scanner.scan_parameters.positions[:, 0])
1340
-
1341
- x_axis = utils.Axis(data=self.scan_x_axis2D,
1342
- label=self.modules_manager.actuators[0].title,
1343
- units=self.modules_manager.actuators[0].settings.child('move_settings',
1344
- 'units').value())
1345
-
1346
- else:
1347
- x_axis = utils.Axis(data=self.scan_x_axis2D,
1348
- label='Scan index',
1349
- units='')
1350
- self.scan_x_axis2D = np.linspace(0, Nx - 1, Nx)
1351
-
1352
- self.ui.scan2D_graph.x_axis = x_axis
1353
- self.ui.scan2D_subgraph.x_axis = x_axis
1354
-
1355
- det_names = [det.title for det in self.modules_manager.detectors_all]
1356
- ind_plot_det = det_names.index(self.settings.child('scan_options', 'plot_from').value())
1357
- if 'x_axis' in data.keys():
1358
- self.scan_y_axis = data['x_axis']['data']
1359
- label = data['x_axis']['label']
1360
- units = data['x_axis']['units']
1361
- else:
1362
- self.scan_y_axis = np.linspace(0, Ny - 1, Ny)
1363
- label = 'pixels'
1364
- units = 'index'
1365
-
1366
- if self.modules_manager.detectors_all[ind_plot_det].ui.viewers[0].viewer_type == 'Data1D':
1367
- if label == '':
1368
- label = self.modules_manager.detectors_all[ind_plot_det].ui.viewers[0].axis_settings['label']
1369
- if units == '':
1370
- units = self.modules_manager.detectors_all[ind_plot_det].ui.viewers[0].axis_settings['units']
1371
-
1372
- self.ui.scan2D_graph.y_axis =\
1373
- utils.Axis(data=self.scan_y_axis,
1374
- units=units,
1375
- label=f'{self.modules_manager.detectors_all[ind_plot_det].title} {label}')
1376
- self.scan_data_2D = []
1377
- self.scan_data_2D_average = []
1378
- for ind, key in enumerate(datas):
1379
- if ind >= 3:
1380
- break
1381
- self.scan_data_2D.append(np.zeros([datas[key]['data'].shape[0]] + [Nx]))
1382
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1383
- self.scan_data_2D_average.append(np.zeros([datas[key]['data'].shape[0]] + [Nx]))
1384
-
1385
- if self.scanner.scan_parameters.scan_subtype == 'Linear back to start':
1386
- if not utils.odd_even(self.ind_scan):
1387
- for ind_plot, key in enumerate(datas.keys()):
1388
-
1389
- self.scan_data_2D[ind_plot][:, int(self.ind_scan / 2)] = \
1390
- self.get_data_live_bkg(datas, key, bkg)
1391
-
1392
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1393
- self.scan_data_2D_average[ind_plot][:, int(self.ind_scan / 2)] = \
1394
- (self.ind_average * self.scan_data_2D_average[ind_plot][
1395
- :, int(self.ind_scan / 2)] + datas[key]['data']) / (self.ind_average + 1)
1396
-
1397
- else:
1398
- if not display_as_sequence:
1399
- ind_pos_axis = self.scanner.scan_parameters.axes_indexes[self.ind_scan, 0]
1400
- else:
1401
- ind_pos_axis = self.ind_scan
1402
-
1403
- for ind_plot, key in enumerate(datas.keys()):
1404
- if ind_plot >= 3:
1405
- break
1406
- self.scan_data_2D[ind_plot][:, ind_pos_axis] = self.get_data_live_bkg(datas, key, bkg)
1407
-
1408
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1409
- self.scan_data_2D_average[ind_plot][:, self.ind_scan] = \
1410
- (self.ind_average * self.scan_data_2D_average[ind_plot][:, ind_pos_axis] + datas[key][
1411
- 'data']) \
1412
- / (self.ind_average + 1)
1413
-
1414
- self.ui.scan2D_graph.setImage(*self.scan_data_2D)
1415
- if self.settings.child('scan_options', 'scan_average').value() > 1:
1416
- self.ui.average2D_graph.setImage(*self.scan_data_2D_average)
1417
-
1418
- except Exception as e:
1419
- logger.exception(str(e))
1420
-
1421
- #################
1422
- # SCAN FLOW
1423
-
1424
- def set_scan(self, scan=None):
1425
- """
1426
- Sets the current scan given the selected settings. Makes some checks, increments the h5 file scans.
1427
- In case the dialog is cancelled, return False and aborts the scan
1428
- """
1429
- try:
1430
- # set the filename and path
1431
- res = self.create_new_file(False)
1432
- if not res:
1433
- return
1434
-
1435
- # reinit these objects
1436
- self.scan_data_1D = []
1437
- self.scan_data_1D_average = []
1438
- self.scan_data_2D = []
1439
- self.scan_data_2D_average = []
1440
-
1441
- scan_params = self.scanner.set_scan()
1442
- if scan_params.scan_info.positions is None:
1443
- messagebox(text=f"An error occurred when establishing the scan steps. Actual settings "
1444
- f"gives approximately {int(scan_params.Nsteps)} steps."
1445
- f" Please check the steps number "
1446
- f"limit in the config file ({config['scan']['steps_limit']}) or modify"
1447
- f" your scan settings.")
1448
-
1449
- if len(self.modules_manager.actuators) != self.scanner.scan_parameters.Naxes:
1450
- messagebox(text="There are not enough or too much selected move modules for this scan")
1451
- return
1452
-
1453
- if self.scanner.scan_parameters.scan_subtype == 'Adaptive':
1454
- if len(self.modules_manager.get_selected_probed_data('0D')) == 0:
1455
- messagebox(text="In adaptive mode, you have to pick a 0D signal from which the algorithm will"
1456
- " determine the next positions to scan, see 'probe_data' in the modules selector"
1457
- " panel")
1458
- return
1459
-
1460
- self.ui.N_scan_steps_sb.setValue(self.scanner.scan_parameters.Nsteps)
1461
-
1462
- # check if the modules are initialized
1463
- for module in self.modules_manager.actuators:
1464
- if not module.initialized_state:
1465
- raise exceptions.DAQ_ScanException('module ' + module.title + " is not initialized")
1466
-
1467
- for module in self.modules_manager.detectors:
1468
- if not module.initialized_state:
1469
- raise exceptions.DAQ_ScanException('module ' + module.title + " is not initialized")
1470
-
1471
- self.ui.start_scan_pb.setEnabled(True)
1472
- self.ui.stop_scan_pb.setEnabled(True)
1473
-
1474
- return True
1475
-
1476
- except Exception as e:
1477
- logger.exception(str(e))
1478
- self.ui.start_scan_pb.setEnabled(False)
1479
- self.ui.stop_scan_pb.setEnabled(False)
1480
-
1481
- def set_metadata_about_current_scan(self):
1482
- """
1483
- Set the date/time and author values of the scan_info child of the scan_attributes tree.
1484
- Show the 'scan' file attributes.
1485
-
1486
- See Also
1487
- --------
1488
- show_file_attributes
1489
- """
1490
- date = QDateTime(QDate.currentDate(), QTime.currentTime())
1491
- self.scan_attributes.child('scan_info', 'date_time').setValue(date)
1492
- self.scan_attributes.child('scan_info', 'author').setValue(
1493
- self.dataset_attributes.child('dataset_info', 'author').value())
1494
- if not self.batch_started:
1495
- res = self.show_file_attributes('scan')
1496
- else:
1497
- res = True
1498
- return res
1499
-
1500
- def set_metadata_about_dataset(self):
1501
- """
1502
- Set the date value of the data_set_info-date_time child of the data_set_attributes tree.
1503
- Show the 'dataset' file attributes.
1504
-
1505
- See Also
1506
- --------
1507
- show_file_attributes
1508
- """
1509
- date = QDateTime(QDate.currentDate(), QTime.currentTime())
1510
- self.dataset_attributes.child('dataset_info', 'date_time').setValue(date)
1511
- res = self.show_file_attributes('dataset')
1512
- return res
1513
-
1514
- def start_scan(self):
1515
- """
1516
- Start an acquisition calling the set_scan function.
1517
- Emit the command_DAQ signal "start_acquisition".
1518
-
1519
- See Also
1520
- --------
1521
- set_scan
1522
- """
1523
- self.ui.status_message.setText('Starting acquisition')
1524
- self.dashboard.overshoot = False
1525
- self.plot_2D_ini = False
1526
- self.plot_1D_ini = False
1527
- self.bkg_container = None
1528
- self.scan_positions = []
1529
- self.curvilinear_values = []
1530
- res = self.set_scan()
1531
- if res:
1532
-
1533
- # deactivate module controls usiong remote_control
1534
- if hasattr(self.dashboard, 'remote_manager'):
1535
- remote_manager = getattr(self.dashboard, 'remote_manager')
1536
- remote_manager.activate_all(False)
1537
-
1538
- # save settings from move modules
1539
- move_modules_names = [mod.title for mod in self.modules_manager.actuators]
1540
- for ind_move, move_name in enumerate(move_modules_names):
1541
- move_group_name = 'Move{:03d}'.format(ind_move)
1542
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group, move_group_name):
1543
- self.h5saver.add_move_group(self.h5saver.current_scan_group, title='',
1544
- settings_as_xml=pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(
1545
- self.modules_manager.actuators[ind_move].settings),
1546
- metadata=dict(name=move_name))
1547
-
1548
- # save settings from detector modules
1549
- detector_modules_names = [mod.title for mod in self.modules_manager.detectors]
1550
- for ind_det, det_name in enumerate(detector_modules_names):
1551
- det_group_name = 'Detector{:03d}'.format(ind_det)
1552
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group, det_group_name):
1553
- settings_str = pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(
1554
- self.modules_manager.detectors[ind_det].settings)
1555
- try:
1556
- if 'Data0D' not in [viewer.viewer_type for viewer in
1557
- self.modules_manager.detectors[
1558
- ind_det].ui.viewers]: # no roi_settings in viewer0D
1559
- settings_str = b'<All_settings title="All Settings" type="group">' + settings_str
1560
- for ind_viewer, viewer in enumerate(self.modules_manager.detectors[ind_det].ui.viewers):
1561
- if hasattr(viewer, 'roi_manager'):
1562
- settings_str += '<Viewer{:0d}_ROI_settings title="ROI Settings" type="group">'.format(
1563
- ind_viewer).encode()
1564
- settings_str += pymodaq.daq_utils.parameter.ioxml.parameter_to_xml_string(
1565
- viewer.roi_manager.settings) + '</Viewer{:0d}_ROI_settings>'.format(
1566
- ind_viewer).encode()
1567
- settings_str += b'</All_settings>'
1568
- except Exception as e:
1569
- logger.exception(str(e))
1570
-
1571
- self.h5saver.add_det_group(self.h5saver.current_scan_group,
1572
- settings_as_xml=settings_str, metadata=dict(name=det_name))
1573
-
1574
- # mandatory to deal with multithreads
1575
- if self.scan_thread is not None:
1576
- self.command_DAQ_signal.disconnect()
1577
- if self.scan_thread.isRunning():
1578
- self.scan_thread.terminate()
1579
- while not self.scan_thread.isFinished():
1580
- QThread.msleep(100)
1581
- self.scan_thread = None
1582
-
1583
- self.scan_thread = QThread()
1584
-
1585
- scan_acquisition = DAQ_Scan_Acquisition(self.settings, self.scanner.settings, self.h5saver.settings,
1586
- self.modules_manager, self.scanner.scan_parameters)
1587
- if config['scan']['scan_in_thread']:
1588
- scan_acquisition.moveToThread(self.scan_thread)
1589
- self.command_DAQ_signal[list].connect(scan_acquisition.queue_command)
1590
- scan_acquisition.scan_data_tmp[OrderedDict].connect(self.update_scan_GUI)
1591
- scan_acquisition.status_sig[list].connect(self.thread_status)
1592
-
1593
- self.scan_thread.scan_acquisition = scan_acquisition
1594
- self.scan_thread.start()
1595
-
1596
- self.ui.set_scan_pb.setEnabled(False)
1597
- self.ui.set_ini_positions_pb.setEnabled(False)
1598
- self.ui.start_scan_pb.setEnabled(False)
1599
- QtWidgets.QApplication.processEvents()
1600
- self.ui.scan_done_LED.set_as_false()
1601
-
1602
- self.command_DAQ_signal.emit(["start_acquisition"])
1603
- self.ui.status_message.setText('Running acquisition')
1604
- logger.info('Running acquisition')
1605
-
1606
- def set_ini_positions(self):
1607
- """
1608
- Send the command_DAQ signal with "set_ini_positions" list item as an attribute.
1609
- """
1610
- self.command_DAQ_signal.emit(["set_ini_positions"])
1611
-
1612
- def stop_scan(self):
1613
- """
1614
- Emit the command_DAQ signal "stop_acquisiion".
1615
-
1616
- See Also
1617
- --------
1618
- set_ini_positions
1619
- """
1620
- self.ui.status_message.setText('Stoping acquisition')
1621
- self.command_DAQ_signal.emit(["stop_acquisition"])
1622
-
1623
- if not self.dashboard.overshoot:
1624
- self.set_ini_positions() # do not set ini position again in case overshoot fired
1625
- status = 'Data Acquisition has been stopped by user'
1626
- else:
1627
- status = 'Data Acquisition has been stopped due to overshoot'
1628
-
1629
- self.update_status(status, log_type='log')
1630
- self.ui.status_message.setText('')
1631
-
1632
- self.ui.set_scan_pb.setEnabled(True)
1633
- self.ui.set_ini_positions_pb.setEnabled(True)
1634
- self.ui.start_scan_pb.setEnabled(True)
1635
-
1636
- def do_scan(self, start_scan=True):
1637
- """Public method to start the scan programmatically"""
1638
- if start_scan:
1639
- if not self.ui.start_scan_pb.isEnabled():
1640
- self.ui.set_scan_pb.click()
1641
- QtWidgets.QApplication.processEvents()
1642
- self.ui.start_scan_pb.click()
1643
- else:
1644
- self.ui.stop_scan_pb.click()
1645
-
1646
-
1647
- class DAQ_Scan_Acquisition(QObject):
1648
- """
1649
- =========================== ========================================
1650
-
1651
- =========================== ========================================
1652
-
1653
- """
1654
- scan_data_tmp = Signal(OrderedDict)
1655
- status_sig = Signal(list)
1656
-
1657
- def __init__(self, settings=None, scan_settings=None, h5saver=None, modules_manager=None, scan_parameters=None):
1658
-
1659
- """
1660
- DAQ_Scan_Acquisition deal with the acquisition part of daq_scan, that is transferring commands to modules,
1661
- getting back data, saviong and letting know th UI about the scan status
1662
-
1663
- """
1664
-
1665
- super().__init__()
1666
-
1667
- self.stop_scan_flag = False
1668
- self.settings = settings
1669
- self.scan_settings = scan_settings
1670
- self.Naverage = self.settings.child('scan_options', 'scan_average').value()
1671
- self.ind_average = 0
1672
- self.ind_scan = 0
1673
- self.scan_parameters = scan_parameters
1674
- self.isadaptive = self.scan_parameters.scan_subtype == 'Adaptive'
1675
- self.curvilinear_array = None
1676
- self.modules_manager = modules_manager
1677
- self.modules_manager.timeout_signal.connect(self.timeout)
1678
- self.timeout_scan_flag = False
1679
-
1680
- self.curvilinear = None # used for adaptive/Tabular scan mode
1681
-
1682
- self.scan_x_axis = None
1683
- self.scan_x_axis2D = None
1684
- self.scan_y_axis = None
1685
- self.scan_z_axis = None
1686
- self.scan_x_axis_unique = None
1687
- self.scan_y_axis_unique = None
1688
- self.scan_z_axis_unique = None
1689
- self.scan_shape = None
1690
-
1691
- self.scan_read_positions = []
1692
- self.scan_read_datas = []
1693
- self.move_done_flag = False
1694
- self.det_done_flag = False
1695
-
1696
- self.det_done_datas = OrderedDict()
1697
-
1698
- self.h5saver = H5Saver()
1699
- self.h5saver.settings.restoreState(h5saver.saveState())
1700
- self.h5saver.init_file(addhoc_file_path=self.h5saver.settings.child(('current_h5_file')).value())
1701
-
1702
- self.h5_det_groups = []
1703
- self.h5_move_groups = []
1704
- self.channel_arrays = OrderedDict([])
1705
-
1706
- # save settings from move modules
1707
- for ind_move in range(self.modules_manager.Nactuators):
1708
- move_group_name = 'Move{:03d}'.format(ind_move)
1709
- self.h5_move_groups.append(self.h5saver.get_node(self.h5saver.current_scan_group, move_group_name))
1710
-
1711
- # save settings from detector modules
1712
- for ind_det in range(self.modules_manager.Ndetectors):
1713
- det_group_name = 'Detector{:03d}'.format(ind_det)
1714
- self.h5_det_groups.append(self.h5saver.get_node(self.h5saver.current_scan_group, det_group_name))
1715
-
1716
- @Slot(list)
1717
- def queue_command(self, command):
1718
- """
1719
- Treat the queue of commands from the current command to act, between :
1720
- * *start_acquisition*
1721
- * *stop_acquisition*
1722
- * *set_ini_position*
1723
- * *move_stages*
1724
-
1725
- =============== ============== =========================
1726
- **Parameters** **Type** **Description**
1727
- command string list the command string list
1728
- =============== ============== =========================
1729
-
1730
- See Also
1731
- --------
1732
- start_acquisition, set_ini_positions, move_stages
1733
- """
1734
- if command[0] == "start_acquisition":
1735
- self.start_acquisition()
1736
-
1737
- elif command[0] == "stop_acquisition":
1738
- self.stop_scan_flag = True
1739
-
1740
- elif command[0] == "set_ini_positions":
1741
- self.set_ini_positions()
1742
-
1743
- elif command[0] == "move_stages":
1744
- self.modules_manager.move_actuators(command[1])
1745
-
1746
- def set_ini_positions(self):
1747
- """
1748
- | Set the positions from the scan_move attribute.
1749
- |
1750
- | Move all activated modules to specified positions.
1751
- | Check the module corresponding to the name assigned in pos.
1752
-
1753
- See Also
1754
- --------
1755
- DAQ_Move_main.daq_move.move_Abs
1756
- """
1757
- try:
1758
- if self.scan_parameters.scan_subtype != 'Adaptive':
1759
- self.modules_manager.move_actuators(list(self.scan_parameters.positions[0]))
1760
-
1761
- except Exception as e:
1762
- logger.exception(str(e))
1763
-
1764
- def init_data(self):
1765
- self.channel_arrays = OrderedDict([])
1766
- for ind_det, det_name in enumerate(self.modules_manager.get_names(self.modules_manager.detectors)):
1767
- datas = self.modules_manager.det_done_datas[det_name]
1768
- det_group = self.h5_det_groups[ind_det]
1769
- self.channel_arrays[det_name] = OrderedDict([])
1770
- data_types = ['data0D', 'data1D']
1771
- if self.h5saver.settings.child(('save_2D')).value():
1772
- data_types.extend(['data2D', 'dataND'])
1773
-
1774
- det_mod = self.modules_manager.get_mod_from_name(det_name)
1775
- if det_mod.bkg is not None and det_mod.is_bkg:
1776
- bkg_container = OrderedDict([])
1777
- det_mod.process_data(det_mod.bkg, bkg_container)
1778
-
1779
- for data_type in data_types:
1780
- if data_type in datas.keys():
1781
- if datas[data_type] is not None:
1782
- if len(datas[data_type]) != 0:
1783
- data_raw_roi = [datas[data_type][key]['source'] for key in datas[data_type]]
1784
- if not (self.h5saver.settings.child(
1785
- ('save_raw_only')).value() and 'raw' not in data_raw_roi):
1786
- if not self.h5saver.is_node_in_group(det_group, data_type):
1787
- self.channel_arrays[det_name][data_type] = OrderedDict([])
1788
- data_group = self.h5saver.add_data_group(det_group, data_type)
1789
- for ind_channel, channel in enumerate(datas[data_type]): # list of OrderedDict
1790
- if not (
1791
- self.h5saver.settings.child(
1792
- 'save_raw_only').value() and datas[
1793
- data_type][channel]['source'] != 'raw'):
1794
- channel_group = self.h5saver.add_CH_group(data_group, title=channel)
1795
- self.channel_arrays[det_name][data_type]['parent'] = channel_group
1796
- data_tmp = datas[data_type][channel]
1797
-
1798
- if det_mod.bkg is not None and det_mod.is_bkg:
1799
- if channel in bkg_container[data_type]:
1800
- data_tmp['bkg'] = bkg_container[data_type][channel]['data']
1801
- if data_tmp['bkg'].shape == (): # in case one get a numpy.float64 object
1802
- data_tmp['bkg'] = np.array([data_tmp['bkg']])
1803
-
1804
- self.channel_arrays[det_name][data_type][channel] = \
1805
- self.h5saver.add_data(channel_group,
1806
- data_tmp,
1807
- scan_type=self.scan_parameters.scan_type,
1808
- scan_subtype=self.scan_parameters.scan_subtype,
1809
- scan_shape=self.scan_shape, init=True,
1810
- add_scan_dim=True,
1811
- enlargeable=self.isadaptive)
1812
- pass
1813
-
1814
- def start_acquisition(self):
1815
- try:
1816
-
1817
- self.modules_manager.connect_actuators()
1818
- self.modules_manager.connect_detectors()
1819
-
1820
- self.scan_read_positions = []
1821
- self.scan_read_datas = []
1822
- self.stop_scan_flag = False
1823
- Naxes = self.scan_parameters.Naxes
1824
- scan_type = self.scan_parameters.scan_type
1825
- self.navigation_axes = []
1826
-
1827
- if scan_type == 'Scan1D' or scan_type == 'Scan2D':
1828
- """creates the X_axis and Y_axis valid only for 1D or 2D scans """
1829
- if self.isadaptive:
1830
- self.scan_x_axis = np.array([0.0, ])
1831
- self.scan_x_axis_unique = np.array([0.0, ])
1832
- else:
1833
- self.scan_x_axis = self.scan_parameters.positions[:, 0]
1834
- self.scan_x_axis_unique = self.scan_parameters.axes_unique[0]
1835
-
1836
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group, 'scan_x_axis'):
1837
- x_axis_meta = dict(
1838
- units=self.modules_manager.actuators[0].settings.child('move_settings', 'units').value(),
1839
- label=self.modules_manager.get_names(self.modules_manager.actuators)[0],
1840
- nav_index=0)
1841
-
1842
- self.navigation_axes.append(self.h5saver.add_navigation_axis(self.scan_x_axis,
1843
- self.h5saver.current_scan_group,
1844
- axis='x_axis',
1845
- metadata=x_axis_meta,
1846
- enlargeable=self.isadaptive))
1847
-
1848
- if not self.isadaptive:
1849
- if self.scan_parameters.scan_subtype == 'Linear back to start':
1850
- self.scan_shape = [len(self.scan_x_axis)]
1851
- else:
1852
- self.scan_shape = [len(self.scan_x_axis_unique)]
1853
- else:
1854
- self.scan_shape = [0]
1855
-
1856
- if scan_type == 'Scan2D': # "means scan 2D"
1857
- if self.isadaptive:
1858
- self.scan_y_axis = np.array([0.0, ])
1859
- self.scan_y_axis_unique = np.array([0.0, ])
1860
- else:
1861
- self.scan_y_axis = self.scan_parameters.positions[:, 1]
1862
- self.scan_y_axis_unique = self.scan_parameters.axes_unique[1]
1863
-
1864
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group, 'scan_y_axis'):
1865
- y_axis_meta = dict(
1866
- units=self.modules_manager.actuators[1].settings.child('move_settings', 'units').value(),
1867
- label=self.modules_manager.get_names(self.modules_manager.actuators)[1],
1868
- nav_index=1)
1869
- self.navigation_axes.append(self.h5saver.add_navigation_axis(self.scan_y_axis,
1870
- self.h5saver.current_scan_group,
1871
- axis='y_axis',
1872
- metadata=y_axis_meta,
1873
- enlargeable=self.isadaptive))
1874
- if not self.isadaptive:
1875
- self.scan_shape.append(len(self.scan_y_axis_unique))
1876
- else:
1877
- self.scan_shape.append(0)
1878
-
1879
- elif scan_type == 'Sequential':
1880
- """Creates axes labelled by the index within the sequence"""
1881
- self.scan_shape = [len(ax) for ax in self.scan_parameters.axes_unique]
1882
- for ind in range(Naxes):
1883
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group,
1884
- 'scan_{:02d}_axis'.format(ind)):
1885
- axis_meta = dict(
1886
- units=self.modules_manager.actuators[ind].settings.child('move_settings', 'units').value(),
1887
- label=self.modules_manager.get_names(self.modules_manager.actuators)[ind],
1888
- nav_index=ind)
1889
- self.navigation_axes.append(
1890
- self.h5saver.add_navigation_axis(self.scan_parameters.axes_unique[ind],
1891
- self.h5saver.current_scan_group,
1892
- axis=f'{ind:02d}_axis', metadata=axis_meta))
1893
-
1894
- elif scan_type == 'Tabular':
1895
- """Creates axes labelled by the index within the sequence"""
1896
- if not self.isadaptive:
1897
- self.scan_shape = [self.scan_parameters.Nsteps, ]
1898
- nav_axes = [self.scan_parameters.positions[:, ind] for ind in range(Naxes)]
1899
- else:
1900
- self.scan_shape = [0, Naxes]
1901
- nav_axes = [np.array([0.0, ]) for ind in range(Naxes)]
1902
-
1903
- for ind in range(Naxes):
1904
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group,
1905
- 'scan_{:02d}_axis'.format(ind)):
1906
- axis_meta = dict(
1907
- units=self.modules_manager.actuators[ind].settings.child('move_settings', 'units').value(),
1908
- label=self.modules_manager.get_names(self.modules_manager.actuators)[ind],
1909
- nav_index=ind)
1910
- self.navigation_axes.append(self.h5saver.add_navigation_axis(nav_axes[ind],
1911
- self.h5saver.current_scan_group,
1912
- axis=f'{ind:02d}_axis',
1913
- metadata=axis_meta,
1914
- enlargeable=self.isadaptive))
1915
-
1916
- if self.isadaptive:
1917
- if not self.h5saver.is_node_in_group(self.h5saver.current_scan_group, 'Curvilinear_axis'):
1918
- axis_meta = dict(units='',
1919
- label='Curvilinear coordinate',
1920
- nav_index=-1)
1921
- self.curvilinear_array = self.h5saver.add_navigation_axis(np.array([0.0, ]),
1922
- self.h5saver.current_scan_group,
1923
- axis='curvilinear_axis',
1924
- metadata=axis_meta,
1925
- enlargeable=self.isadaptive)
1926
-
1927
- if self.Naverage > 1:
1928
- self.scan_shape.append(self.Naverage)
1929
-
1930
- if self.isadaptive:
1931
- """
1932
- adaptive_losses = dict(
1933
- loss1D=['default', 'curvature', 'uniform'],
1934
- loss2D=['default', 'resolution', 'uniform', 'triangle'])
1935
- """
1936
- if self.scan_parameters.scan_type == 'Scan1D' or self.scan_parameters.scan_type == 'Tabular':
1937
- if self.scan_parameters.adaptive_loss == 'curvature':
1938
- loss = adaptive.learner.learner1D.curvature_loss_function()
1939
- elif self.scan_parameters.adaptive_loss == 'uniform':
1940
- loss = adaptive.learner.learner1D.uniform_loss
1941
- else:
1942
- loss = adaptive.learner.learner1D.default_loss
1943
- if self.scan_parameters.scan_type == 'Scan1D':
1944
- bounds = [self.scan_parameters.starts[0], self.scan_parameters.stops[0]]
1945
- else:
1946
- length = 0.
1947
- for vec in self.scan_parameters.vectors:
1948
- length += vec.norm()
1949
- bounds = [0., length]
1950
-
1951
- learner = adaptive.learner.learner1D.Learner1D(None, bounds=bounds,
1952
- loss_per_interval=loss)
1953
-
1954
- elif self.scan_parameters.scan_type == 'Scan2D':
1955
- if self.scan_parameters.adaptive_loss == 'resolution':
1956
- loss = adaptive.learner.learner2D.resolution_loss_function(
1957
- min_distance=self.scan_parameters.steps[0] / 100,
1958
- max_distance=self.scan_parameters.steps[1] / 100)
1959
- elif self.scan_parameters.adaptive_loss == 'uniform':
1960
- loss = adaptive.learner.learner2D.uniform_loss
1961
- elif self.scan_parameters.adaptive_loss == 'triangle':
1962
- loss = adaptive.learner.learner2D.triangle_loss
1963
- else:
1964
- loss = adaptive.learner.learner2D.default_loss
1965
-
1966
- learner = adaptive.learner.learner2D.Learner2D(None,
1967
- bounds=[b for b in zip(self.scan_parameters.starts,
1968
- self.scan_parameters.stops)],
1969
- loss_per_triangle=loss)
1970
-
1971
- else:
1972
- logger.warning('Adaptive for more than 2 axis is not currently done (sequential adaptive)')
1973
- return
1974
-
1975
- self.status_sig.emit(["Update_Status", "Acquisition has started", 'log'])
1976
-
1977
- self.timeout_scan_flag = False
1978
- for ind_average in range(self.Naverage):
1979
- self.ind_average = ind_average
1980
- self.ind_scan = -1
1981
- while True:
1982
- self.ind_scan += 1
1983
- if not self.isadaptive:
1984
- if self.ind_scan >= len(self.scan_parameters.positions):
1985
- break
1986
- positions = self.scan_parameters.positions[self.ind_scan] # get positions
1987
- else:
1988
- positions = learner.ask(1)[0][-1] # next point to probe
1989
- if self.scan_parameters.scan_type == 'Tabular': # translate normalized curvilinear position to real coordinates
1990
- self.curvilinear = positions
1991
- length = 0.
1992
- for v in self.scan_parameters.vectors:
1993
- length += v.norm()
1994
- if length >= self.curvilinear:
1995
- vec = v
1996
- frac_curvilinear = (self.curvilinear - (length - v.norm())) / v.norm()
1997
- break
1998
-
1999
- position = (vec.vectorize() * frac_curvilinear).translate_to(vec.p1()).p2()
2000
- positions = [position.x(), position.y()]
2001
-
2002
- self.status_sig.emit(["Update_scan_index", [self.ind_scan, ind_average]])
2003
-
2004
- if self.stop_scan_flag or self.timeout_scan_flag:
2005
- break
2006
-
2007
- #move motors of modules and wait for move completion
2008
- positions = self.modules_manager.order_positions(self.modules_manager.move_actuators(positions))
2009
-
2010
- QThread.msleep(self.settings.child('time_flow', 'wait_time_between').value())
2011
-
2012
- #grab datas and wait for grab completion
2013
- self.det_done(self.modules_manager.grab_datas(positions=positions), positions)
2014
-
2015
- if self.isadaptive:
2016
- det_channel = self.modules_manager.get_selected_probed_data()
2017
- det, channel = det_channel[0].split('/')
2018
- if self.scan_parameters.scan_type == 'Tabular':
2019
- self.curvilinear_array.append(np.array([self.curvilinear]))
2020
- new_positions = self.curvilinear
2021
- elif self.scan_parameters.scan_type == 'Scan1D':
2022
- new_positions = positions[0]
2023
- else:
2024
- new_positions = positions[:]
2025
-
2026
- learner.tell(new_positions, self.modules_manager.det_done_datas[det]['data0D'][channel]['data'])
2027
-
2028
- # daq_scan wait time
2029
- QThread.msleep(self.settings.child('time_flow', 'wait_time').value())
2030
-
2031
- self.h5saver.h5_file.flush()
2032
- self.modules_manager.connect_actuators(False)
2033
- self.modules_manager.connect_detectors(False)
2034
-
2035
- self.status_sig.emit(["Update_Status", "Acquisition has finished", 'log'])
2036
- self.status_sig.emit(["Scan_done"])
2037
-
2038
- except Exception as e:
2039
- logger.exception(str(e))
2040
- # self.status_sig.emit(["Update_Status", getLineInfo() + str(e), 'log'])
2041
-
2042
- def wait_for_det_done(self):
2043
- self.timeout_scan_flag = False
2044
- self.timer.start(self.settings.child('time_flow', 'timeout').value())
2045
- while not (self.det_done_flag or self.timeout_scan_flag):
2046
- # wait for grab done signals to end
2047
- QtWidgets.QApplication.processEvents()
2048
-
2049
- def det_done(self, det_done_datas, positions=[]):
2050
- """
2051
- | Initialize 0D/1D/2D datas from given data parameter.
2052
- | Update h5_file group and array.
2053
- | Save 0D/1D/2D... datas.
2054
- Parameters
2055
- ----------
2056
- det_done_datas: (OrderedDict) on the form OrderedDict
2057
- (det0=OrderedDict(data0D=None, data1D=None, data2D=None, dataND=None),
2058
- det1=OrderedDict(data0D=None, data1D=None, data2D=None, dataND=None),...)
2059
- """
2060
- try:
2061
- self.scan_read_datas = det_done_datas[
2062
- self.settings.child('scan_options', 'plot_from').value()].copy()
2063
-
2064
- if self.ind_scan == 0 and self.ind_average == 0: # first occurence=> initialize the channels
2065
- self.init_data()
2066
-
2067
- if not self.isadaptive:
2068
- if self.scan_parameters.scan_type == 'Tabular':
2069
- indexes = np.array([self.ind_scan])
2070
- else:
2071
- indexes = self.scan_parameters.axes_indexes[self.ind_scan]
2072
-
2073
- if self.Naverage > 1:
2074
- indexes = list(indexes)
2075
- indexes.append(self.ind_average)
2076
-
2077
- indexes = tuple(indexes)
2078
-
2079
- if self.isadaptive:
2080
- for ind_ax, nav_axis in enumerate(self.navigation_axes):
2081
- nav_axis.append(np.array(positions[ind_ax]))
2082
-
2083
- for ind_det, det_name in enumerate(self.modules_manager.get_names(self.modules_manager.detectors)):
2084
- datas = det_done_datas[det_name]
2085
-
2086
- data_types = ['data0D', 'data1D']
2087
- if self.h5saver.settings.child(('save_2D')).value():
2088
- data_types.extend(['data2D', 'dataND'])
2089
-
2090
- for data_type in data_types:
2091
- if data_type in datas.keys():
2092
- if datas[data_type] is not None:
2093
- if len(datas[data_type]) != 0:
2094
- for ind_channel, channel in enumerate(datas[data_type]):
2095
- if not (self.h5saver.settings.child(
2096
- 'save_raw_only').value() and datas[data_type][channel]['source'] != 'raw'):
2097
- if not self.isadaptive:
2098
- self.channel_arrays[
2099
- det_name][data_type][channel].__setitem__(
2100
- indexes, value=det_done_datas[det_name][data_type][channel]['data'])
2101
- else:
2102
- data = det_done_datas[det_name][data_type][channel]['data']
2103
- if isinstance(data, float) or isinstance(data, int):
2104
- data = np.array([data])
2105
- self.channel_arrays[det_name][data_type][channel].append(data)
2106
-
2107
- self.det_done_flag = True
2108
-
2109
- self.scan_data_tmp.emit(OrderedDict(positions=self.modules_manager.move_done_positions,
2110
- datas=self.scan_read_datas,
2111
- curvilinear=self.curvilinear))
2112
- except Exception as e:
2113
- logger.exception(str(e))
2114
- # self.status_sig.emit(["Update_Status", getLineInfo() + str(e), 'log'])
2115
-
2116
- def timeout(self):
2117
- """
2118
- Send the status signal *'Time out during acquisition'*.
2119
- """
2120
- self.timeout_scan_flag = True
2121
- self.status_sig.emit(["Update_Status", "Timeout during acquisition", 'log'])
2122
- self.status_sig.emit(["Timeout"])
2123
-
2124
-
2125
- def main(init_qt=True):
2126
- if init_qt: # used for the test suite
2127
- app = QtWidgets.QApplication(sys.argv)
2128
- if config['style']['darkstyle']:
2129
- import qdarkstyle
2130
- app.setStyleSheet(qdarkstyle.load_stylesheet())
2131
-
2132
- from pymodaq.dashboard import DashBoard
2133
-
2134
- win = QtWidgets.QMainWindow()
2135
- area = pymodaq.daq_utils.gui_utils.dock.DockArea()
2136
- win.setCentralWidget(area)
2137
- win.resize(1000, 500)
2138
- win.setWindowTitle('PyMoDAQ Dashboard')
2139
-
2140
- dashboard = DashBoard(area)
2141
- daq_scan = None
2142
- file = Path(get_set_preset_path()).joinpath(f"{config('presets', 'default_preset_for_scan')}.xml")
2143
- if file.exists():
2144
- dashboard.set_preset_mode(file)
2145
- daq_scan = dashboard.load_scan_module()
2146
- else:
2147
- msgBox = QtWidgets.QMessageBox()
2148
- msgBox.setText(f"The default file specified in the configuration file does not exists!\n"
2149
- f"{file}\n"
2150
- f"Impossible to load the DAQ_Scan Module")
2151
- msgBox.setStandardButtons(msgBox.Ok)
2152
- ret = msgBox.exec()
2153
-
2154
- if init_qt:
2155
- sys.exit(app.exec_())
2156
- return dashboard, daq_scan, win
2157
-
2158
-
2159
- if __name__ == '__main__':
2160
- main()