pymodaq 3.6.13__py3-none-any.whl → 4.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +13 -6
- pymodaq/control_modules/__init__.py +0 -7
- pymodaq/control_modules/daq_move.py +965 -2
- pymodaq/control_modules/daq_move_ui.py +319 -0
- pymodaq/control_modules/daq_viewer.py +1573 -3
- pymodaq/control_modules/daq_viewer_ui.py +393 -0
- pymodaq/control_modules/mocks.py +51 -0
- pymodaq/control_modules/move_utility_classes.py +709 -8
- pymodaq/control_modules/utils.py +256 -0
- pymodaq/control_modules/viewer_utility_classes.py +663 -6
- pymodaq/daq_utils.py +89 -0
- pymodaq/dashboard.py +91 -72
- pymodaq/examples/custom_app.py +12 -11
- pymodaq/examples/custom_viewer.py +10 -10
- pymodaq/examples/function_plotter.py +16 -13
- pymodaq/examples/nonlinearscanner.py +8 -6
- pymodaq/examples/parameter_ex.py +7 -7
- pymodaq/examples/preset_MockCamera.xml +1 -0
- pymodaq/extensions/__init__.py +16 -0
- pymodaq/extensions/console.py +76 -0
- pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
- pymodaq/extensions/daq_scan.py +1339 -0
- pymodaq/extensions/daq_scan_ui.py +240 -0
- pymodaq/extensions/h5browser.py +23 -0
- pymodaq/{pid → extensions/pid}/__init__.py +4 -2
- pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
- pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
- pymodaq/{pid → extensions/pid}/utils.py +52 -6
- pymodaq/extensions/utils.py +40 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
- pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
- pymodaq/post_treatment/load_and_plot.py +219 -0
- pymodaq/post_treatment/process_to_scalar.py +263 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
- pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +32 -13
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
- pymodaq/utils/__init__.py +0 -29
- pymodaq/utils/abstract/__init__.py +48 -0
- pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
- pymodaq/utils/array_manipulation.py +379 -8
- pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
- pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
- pymodaq/utils/config.py +448 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +828 -8
- pymodaq/utils/data.py +1873 -7
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
- pymodaq/{daq_utils → utils}/enums.py +12 -7
- pymodaq/utils/exceptions.py +37 -0
- pymodaq/utils/factory.py +82 -0
- pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
- pymodaq/utils/gui_utils/custom_app.py +129 -0
- pymodaq/utils/gui_utils/file_io.py +66 -0
- pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
- pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
- pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
- pymodaq/utils/gui_utils/widgets/label.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
- pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
- pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
- pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
- pymodaq/utils/h5modules/__init__.py +1 -0
- pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
- pymodaq/utils/h5modules/browsing.py +683 -0
- pymodaq/utils/h5modules/data_saving.py +839 -0
- pymodaq/utils/h5modules/h5logging.py +110 -0
- pymodaq/utils/h5modules/module_saving.py +350 -0
- pymodaq/utils/h5modules/saving.py +914 -0
- pymodaq/utils/h5modules/utils.py +85 -0
- pymodaq/utils/logger.py +64 -6
- pymodaq/utils/managers/action_manager.py +460 -0
- pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
- pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
- pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
- pymodaq/utils/managers/parameter_manager.py +110 -0
- pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
- pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
- pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
- pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
- pymodaq/utils/math_utils.py +546 -10
- pymodaq/{daq_utils → utils}/messenger.py +5 -1
- pymodaq/utils/parameter/__init__.py +2 -15
- pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
- pymodaq/utils/parameter/utils.py +206 -11
- pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
- pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
- pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
- pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
- pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
- pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
- pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
- pymodaq/utils/plotting/navigator.py +355 -0
- pymodaq/utils/plotting/scan_selector.py +480 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
- pymodaq/utils/plotting/utils/filter.py +538 -0
- pymodaq/utils/plotting/utils/lineout.py +224 -0
- pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
- pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
- pymodaq/utils/plotting/widgets.py +76 -0
- pymodaq/utils/scanner/__init__.py +10 -0
- pymodaq/utils/scanner/scan_factory.py +204 -0
- pymodaq/utils/scanner/scanner.py +271 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
- pymodaq/utils/scanner/scanners/sequential.py +192 -0
- pymodaq/utils/scanner/scanners/tabular.py +294 -0
- pymodaq/utils/scanner/utils.py +83 -0
- pymodaq/utils/slicing.py +47 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +51 -0
- pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
- pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
- pymodaq/utils/units.py +216 -0
- pymodaq-4.0.1.dist-info/METADATA +159 -0
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
- pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
- pymodaq/daq_move/daq_move_gui.py +0 -279
- pymodaq/daq_move/daq_move_gui.ui +0 -534
- pymodaq/daq_move/daq_move_main.py +0 -1042
- pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
- pymodaq/daq_move/utility_classes.py +0 -686
- pymodaq/daq_scan.py +0 -2160
- pymodaq/daq_utils/array_manipulation.py +0 -386
- pymodaq/daq_utils/config.py +0 -273
- pymodaq/daq_utils/conftests.py +0 -7
- pymodaq/daq_utils/custom_parameter_tree.py +0 -9
- pymodaq/daq_utils/daq_enums.py +0 -133
- pymodaq/daq_utils/daq_utils.py +0 -1402
- pymodaq/daq_utils/exceptions.py +0 -71
- pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
- pymodaq/daq_utils/gui_utils/file_io.py +0 -75
- pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
- pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
- pymodaq/daq_utils/h5exporters.py +0 -242
- pymodaq/daq_utils/h5modules.py +0 -1559
- pymodaq/daq_utils/h5utils.py +0 -241
- pymodaq/daq_utils/managers/action_manager.py +0 -236
- pymodaq/daq_utils/managers/parameter_manager.py +0 -57
- pymodaq/daq_utils/math_utils.py +0 -705
- pymodaq/daq_utils/parameter/__init__.py +0 -1
- pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
- pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
- pymodaq/daq_utils/parameter/utils.py +0 -136
- pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
- pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
- pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
- pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
- pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
- pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
- pymodaq/daq_utils/plotting/items/__init__.py +0 -0
- pymodaq/daq_utils/plotting/navigator.py +0 -500
- pymodaq/daq_utils/plotting/scan_selector.py +0 -289
- pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
- pymodaq/daq_utils/plotting/utils/filter.py +0 -236
- pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
- pymodaq/daq_utils/scanner.py +0 -1289
- pymodaq/daq_utils/tree_layout/__init__.py +0 -0
- pymodaq/daq_viewer/__init__.py +0 -0
- pymodaq/daq_viewer/daq_gui_settings.py +0 -237
- pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
- pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
- pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
- pymodaq/daq_viewer/utility_classes.py +0 -673
- pymodaq/examples/logger_image/__init__.py +0 -0
- pymodaq/examples/logger_image/logger_displayer.py +0 -121
- pymodaq/examples/logger_image/setup.svg +0 -3119
- pymodaq/examples/logger_image/setup_svg.py +0 -114
- pymodaq/h5browser.py +0 -39
- pymodaq/utils/scanner.py +0 -15
- pymodaq-3.6.13.dist-info/METADATA +0 -39
- pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.13.dist-info/top_level.txt +0 -1
- /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
- /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
- /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
- /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
- /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
- /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
- /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
- /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
pymodaq/daq_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()
|