pymodaq 3.6.13__py3-none-any.whl → 4.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +13 -6
- pymodaq/control_modules/__init__.py +0 -7
- pymodaq/control_modules/daq_move.py +965 -2
- pymodaq/control_modules/daq_move_ui.py +319 -0
- pymodaq/control_modules/daq_viewer.py +1573 -3
- pymodaq/control_modules/daq_viewer_ui.py +393 -0
- pymodaq/control_modules/mocks.py +51 -0
- pymodaq/control_modules/move_utility_classes.py +709 -8
- pymodaq/control_modules/utils.py +256 -0
- pymodaq/control_modules/viewer_utility_classes.py +663 -6
- pymodaq/daq_utils.py +89 -0
- pymodaq/dashboard.py +91 -72
- pymodaq/examples/custom_app.py +12 -11
- pymodaq/examples/custom_viewer.py +10 -10
- pymodaq/examples/function_plotter.py +16 -13
- pymodaq/examples/nonlinearscanner.py +8 -6
- pymodaq/examples/parameter_ex.py +7 -7
- pymodaq/examples/preset_MockCamera.xml +1 -0
- pymodaq/extensions/__init__.py +16 -0
- pymodaq/extensions/console.py +76 -0
- pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
- pymodaq/extensions/daq_scan.py +1339 -0
- pymodaq/extensions/daq_scan_ui.py +240 -0
- pymodaq/extensions/h5browser.py +23 -0
- pymodaq/{pid → extensions/pid}/__init__.py +4 -2
- pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
- pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
- pymodaq/{pid → extensions/pid}/utils.py +52 -6
- pymodaq/extensions/utils.py +40 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
- pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
- pymodaq/post_treatment/load_and_plot.py +219 -0
- pymodaq/post_treatment/process_to_scalar.py +263 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
- pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +32 -13
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
- pymodaq/utils/__init__.py +0 -29
- pymodaq/utils/abstract/__init__.py +48 -0
- pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
- pymodaq/utils/array_manipulation.py +379 -8
- pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
- pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
- pymodaq/utils/config.py +448 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +828 -8
- pymodaq/utils/data.py +1873 -7
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
- pymodaq/{daq_utils → utils}/enums.py +12 -7
- pymodaq/utils/exceptions.py +37 -0
- pymodaq/utils/factory.py +82 -0
- pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
- pymodaq/utils/gui_utils/custom_app.py +129 -0
- pymodaq/utils/gui_utils/file_io.py +66 -0
- pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
- pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
- pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
- pymodaq/utils/gui_utils/widgets/label.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
- pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
- pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
- pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
- pymodaq/utils/h5modules/__init__.py +1 -0
- pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
- pymodaq/utils/h5modules/browsing.py +683 -0
- pymodaq/utils/h5modules/data_saving.py +839 -0
- pymodaq/utils/h5modules/h5logging.py +110 -0
- pymodaq/utils/h5modules/module_saving.py +350 -0
- pymodaq/utils/h5modules/saving.py +914 -0
- pymodaq/utils/h5modules/utils.py +85 -0
- pymodaq/utils/logger.py +64 -6
- pymodaq/utils/managers/action_manager.py +460 -0
- pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
- pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
- pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
- pymodaq/utils/managers/parameter_manager.py +110 -0
- pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
- pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
- pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
- pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
- pymodaq/utils/math_utils.py +546 -10
- pymodaq/{daq_utils → utils}/messenger.py +5 -1
- pymodaq/utils/parameter/__init__.py +2 -15
- pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
- pymodaq/utils/parameter/utils.py +206 -11
- pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
- pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
- pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
- pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
- pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
- pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
- pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
- pymodaq/utils/plotting/navigator.py +355 -0
- pymodaq/utils/plotting/scan_selector.py +480 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
- pymodaq/utils/plotting/utils/filter.py +538 -0
- pymodaq/utils/plotting/utils/lineout.py +224 -0
- pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
- pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
- pymodaq/utils/plotting/widgets.py +76 -0
- pymodaq/utils/scanner/__init__.py +10 -0
- pymodaq/utils/scanner/scan_factory.py +204 -0
- pymodaq/utils/scanner/scanner.py +271 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
- pymodaq/utils/scanner/scanners/sequential.py +192 -0
- pymodaq/utils/scanner/scanners/tabular.py +294 -0
- pymodaq/utils/scanner/utils.py +83 -0
- pymodaq/utils/slicing.py +47 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +51 -0
- pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
- pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
- pymodaq/utils/units.py +216 -0
- pymodaq-4.0.1.dist-info/METADATA +159 -0
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
- pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
- pymodaq/daq_move/daq_move_gui.py +0 -279
- pymodaq/daq_move/daq_move_gui.ui +0 -534
- pymodaq/daq_move/daq_move_main.py +0 -1042
- pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
- pymodaq/daq_move/utility_classes.py +0 -686
- pymodaq/daq_scan.py +0 -2160
- pymodaq/daq_utils/array_manipulation.py +0 -386
- pymodaq/daq_utils/config.py +0 -273
- pymodaq/daq_utils/conftests.py +0 -7
- pymodaq/daq_utils/custom_parameter_tree.py +0 -9
- pymodaq/daq_utils/daq_enums.py +0 -133
- pymodaq/daq_utils/daq_utils.py +0 -1402
- pymodaq/daq_utils/exceptions.py +0 -71
- pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
- pymodaq/daq_utils/gui_utils/file_io.py +0 -75
- pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
- pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
- pymodaq/daq_utils/h5exporters.py +0 -242
- pymodaq/daq_utils/h5modules.py +0 -1559
- pymodaq/daq_utils/h5utils.py +0 -241
- pymodaq/daq_utils/managers/action_manager.py +0 -236
- pymodaq/daq_utils/managers/parameter_manager.py +0 -57
- pymodaq/daq_utils/math_utils.py +0 -705
- pymodaq/daq_utils/parameter/__init__.py +0 -1
- pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
- pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
- pymodaq/daq_utils/parameter/utils.py +0 -136
- pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
- pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
- pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
- pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
- pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
- pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
- pymodaq/daq_utils/plotting/items/__init__.py +0 -0
- pymodaq/daq_utils/plotting/navigator.py +0 -500
- pymodaq/daq_utils/plotting/scan_selector.py +0 -289
- pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
- pymodaq/daq_utils/plotting/utils/filter.py +0 -236
- pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
- pymodaq/daq_utils/scanner.py +0 -1289
- pymodaq/daq_utils/tree_layout/__init__.py +0 -0
- pymodaq/daq_viewer/__init__.py +0 -0
- pymodaq/daq_viewer/daq_gui_settings.py +0 -237
- pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
- pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
- pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
- pymodaq/daq_viewer/utility_classes.py +0 -673
- pymodaq/examples/logger_image/__init__.py +0 -0
- pymodaq/examples/logger_image/logger_displayer.py +0 -121
- pymodaq/examples/logger_image/setup.svg +0 -3119
- pymodaq/examples/logger_image/setup_svg.py +0 -114
- pymodaq/h5browser.py +0 -39
- pymodaq/utils/scanner.py +0 -15
- pymodaq-3.6.13.dist-info/METADATA +0 -39
- pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.13.dist-info/top_level.txt +0 -1
- /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
- /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
- /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
- /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
- /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
- /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
- /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
- /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
- {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
pymodaq/daq_utils/scanner.py
DELETED
|
@@ -1,1289 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from collections import OrderedDict
|
|
3
|
-
import numpy as np
|
|
4
|
-
from pymodaq.daq_utils.config import Config
|
|
5
|
-
from qtpy import QtWidgets, QtCore
|
|
6
|
-
from qtpy.QtCore import QObject, Signal, Slot
|
|
7
|
-
|
|
8
|
-
from pymodaq.daq_utils.parameter import ioxml
|
|
9
|
-
|
|
10
|
-
from pymodaq.daq_utils.daq_utils import linspace_step, odd_even, greater2n
|
|
11
|
-
from pymodaq.daq_utils.plotting.scan_selector import ScanSelector
|
|
12
|
-
import pymodaq.daq_utils.daq_utils as utils
|
|
13
|
-
import pymodaq.daq_utils.gui_utils as gutils
|
|
14
|
-
from pymodaq.daq_utils.parameter import utils as putils
|
|
15
|
-
from pymodaq.daq_utils import math_utils as mutils
|
|
16
|
-
from pymodaq.daq_utils.plotting.utils.plot_utils import QVector
|
|
17
|
-
from pyqtgraph.parametertree import Parameter, ParameterTree
|
|
18
|
-
import pymodaq.daq_utils.parameter.pymodaq_ptypes as pymodaq_types # to be placed after importing Parameter
|
|
19
|
-
|
|
20
|
-
from pymodaq.daq_utils.exceptions import ScannerException
|
|
21
|
-
|
|
22
|
-
logger = utils.set_logger(utils.get_module_name(__file__))
|
|
23
|
-
config = Config()
|
|
24
|
-
|
|
25
|
-
SCAN_TYPES = ['Scan1D', 'Scan2D', 'Sequential', 'Tabular']
|
|
26
|
-
SCAN_SUBTYPES = dict(Scan1D=dict(subpath=('scan1D_settings', 'scan1D_type'),
|
|
27
|
-
limits=['Linear', 'Adaptive', 'Linear back to start', 'Random']),
|
|
28
|
-
Scan2D=dict(subpath=('scan2D_settings', 'scan2D_type'),
|
|
29
|
-
limits=['Spiral', 'Linear', 'Adaptive', 'Back&Forth', 'Random']),
|
|
30
|
-
Sequential=dict(subpath=('seq_settings', 'scanseq_type'),
|
|
31
|
-
limits=['Linear']),
|
|
32
|
-
Tabular=dict(subpath=('tabular_settings', 'tabular_subtype'),
|
|
33
|
-
limits=['Linear', 'Adaptive']))
|
|
34
|
-
|
|
35
|
-
try:
|
|
36
|
-
import adaptive
|
|
37
|
-
from adaptive.learner import learner1D
|
|
38
|
-
from adaptive.learner import learner2D
|
|
39
|
-
adaptive_losses = dict(
|
|
40
|
-
loss1D=['default', 'curvature', 'uniform'],
|
|
41
|
-
loss2D=['default', 'resolution', 'uniform', 'triangle'])
|
|
42
|
-
|
|
43
|
-
except Exception:
|
|
44
|
-
SCAN_SUBTYPES['Scan1D']['limits'].pop(SCAN_SUBTYPES['Scan1D']['limits'].index('Adaptive'))
|
|
45
|
-
SCAN_SUBTYPES['Scan2D']['limits'].pop(SCAN_SUBTYPES['Scan2D']['limits'].index('Adaptive'))
|
|
46
|
-
SCAN_SUBTYPES['Tabular']['limits'].pop(SCAN_SUBTYPES['Tabular']['limits'].index('Adaptive'))
|
|
47
|
-
adaptive_losses = None
|
|
48
|
-
adaptive = None
|
|
49
|
-
logger.info('adaptive module is not present, no adaptive scan possible')
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class ScanInfo:
|
|
53
|
-
def __init__(self, Nsteps=0, positions=None, axes_indexes=None, axes_unique=None, **kwargs):
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
Parameters
|
|
57
|
-
----------
|
|
58
|
-
Nsteps: (int) Number of steps of the scan
|
|
59
|
-
positions: (ndarray) multidimensional array of Nsteps 0th dimension length where each element is the position
|
|
60
|
-
positions_indexes: (ndarray) multidimensional array of Nsteps 0th dimension length where each element is the index
|
|
61
|
-
of the corresponding positions within the axis_unique
|
|
62
|
-
axes_unique: (list of ndarray) list of sorted (and with unique values) 1D arrays of unique positions of each defined axes
|
|
63
|
-
"""
|
|
64
|
-
self.Nsteps = Nsteps
|
|
65
|
-
self.positions = positions
|
|
66
|
-
self.axes_indexes = axes_indexes
|
|
67
|
-
self.axes_unique = axes_unique
|
|
68
|
-
for k in kwargs:
|
|
69
|
-
setattr(self, k, kwargs[k])
|
|
70
|
-
|
|
71
|
-
def __repr__(self):
|
|
72
|
-
if self.positions is not None:
|
|
73
|
-
return f'[ScanInfo with {self.Nsteps} positions of shape {self.positions.shape})'
|
|
74
|
-
else:
|
|
75
|
-
return '[ScanInfo with position is None)'
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class ScanParameters:
|
|
79
|
-
"""
|
|
80
|
-
Utility class to define and store information about scans to be done
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
def __init__(self, Naxes=1, scan_type='Scan1D', scan_subtype='Linear', starts=None, stops=None, steps=None,
|
|
84
|
-
positions=None, adaptive_loss=None):
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
Parameters
|
|
88
|
-
----------
|
|
89
|
-
Naxes: (int) number of axes used to do the scan
|
|
90
|
-
scan_type: (str) one value of the SCAN_TYPES list items
|
|
91
|
-
scan_subtype: (str) ne value of the SCAN_SUBTYPES dict items for the scan_type key
|
|
92
|
-
starts: (list of floats) list of starts position of each axis
|
|
93
|
-
stops: (list of floats) list of stops position of each axis
|
|
94
|
-
steps: (list of floats) list of steps position of each axis
|
|
95
|
-
positions: (ndarray) containing the positions already calculated from some method. If not None, this is used to
|
|
96
|
-
define the scan_info (otherwise one use the starts, stops and steps)
|
|
97
|
-
|
|
98
|
-
See Also
|
|
99
|
-
--------
|
|
100
|
-
daq_utils.plotting.scan_selector
|
|
101
|
-
"""
|
|
102
|
-
self.Naxes = Naxes
|
|
103
|
-
if scan_type not in SCAN_TYPES:
|
|
104
|
-
raise ValueError(
|
|
105
|
-
f'Chosen scan_type value ({scan_type}) is not possible. Should be among : {str(SCAN_TYPES)}')
|
|
106
|
-
if scan_subtype not in SCAN_SUBTYPES[scan_type]['limits']:
|
|
107
|
-
raise ValueError(
|
|
108
|
-
f'Chosen scan_subtype value ({scan_subtype}) is not possible. Should be among'
|
|
109
|
-
f' : {str(SCAN_SUBTYPES[scan_type]["limits"])}')
|
|
110
|
-
self.scan_type = scan_type
|
|
111
|
-
self.scan_subtype = scan_subtype
|
|
112
|
-
self.adaptive_loss = adaptive_loss
|
|
113
|
-
self.vectors = None
|
|
114
|
-
|
|
115
|
-
# if positions is not None:
|
|
116
|
-
# self.starts = np.min(positions, axis=0)
|
|
117
|
-
# self.stops = np.max(positions, axis=0)
|
|
118
|
-
# else:
|
|
119
|
-
self.starts = starts
|
|
120
|
-
self.stops = stops
|
|
121
|
-
|
|
122
|
-
self.steps = steps
|
|
123
|
-
|
|
124
|
-
self.scan_info = ScanInfo(Nsteps=0, positions=positions, adaptive_loss=adaptive_loss)
|
|
125
|
-
|
|
126
|
-
self.set_scan()
|
|
127
|
-
|
|
128
|
-
def __getattr__(self, item):
|
|
129
|
-
if item == 'Nsteps':
|
|
130
|
-
return self.scan_info.Nsteps
|
|
131
|
-
elif item == 'positions':
|
|
132
|
-
return self.scan_info.positions
|
|
133
|
-
elif item == 'axes_indexes':
|
|
134
|
-
return self.scan_info.axes_indexes
|
|
135
|
-
elif item == 'axes_unique':
|
|
136
|
-
return self.scan_info.axes_unique
|
|
137
|
-
else:
|
|
138
|
-
if hasattr(self.scan_info, item):
|
|
139
|
-
return getattr(self.scan_info, item)
|
|
140
|
-
else:
|
|
141
|
-
raise ValueError(f'no attribute named {item}')
|
|
142
|
-
|
|
143
|
-
def get_info_from_positions(self, positions):
|
|
144
|
-
if positions is not None:
|
|
145
|
-
if len(positions.shape) == 1:
|
|
146
|
-
positions = np.expand_dims(positions, 1)
|
|
147
|
-
axes_unique = []
|
|
148
|
-
for ax in positions.T:
|
|
149
|
-
axes_unique.append(np.unique(ax))
|
|
150
|
-
axes_indexes = np.zeros_like(positions, dtype=int)
|
|
151
|
-
for ind in range(positions.shape[0]):
|
|
152
|
-
for ind_pos, pos in enumerate(positions[ind]):
|
|
153
|
-
axes_indexes[ind, ind_pos] = mutils.find_index(axes_unique[ind_pos], pos)[0][0]
|
|
154
|
-
|
|
155
|
-
return ScanInfo(Nsteps=positions.shape[0], axes_unique=axes_unique,
|
|
156
|
-
axes_indexes=axes_indexes, positions=positions, adaptive_loss=self.adaptive_loss)
|
|
157
|
-
else:
|
|
158
|
-
return ScanInfo()
|
|
159
|
-
|
|
160
|
-
def set_scan(self):
|
|
161
|
-
steps_limit = config('scan', 'steps_limit')
|
|
162
|
-
Nsteps = self.evaluate_Nsteps()
|
|
163
|
-
if Nsteps > steps_limit:
|
|
164
|
-
self.scan_info = ScanInfo(Nsteps=Nsteps)
|
|
165
|
-
return self.scan_info
|
|
166
|
-
|
|
167
|
-
if self.scan_type == "Scan1D":
|
|
168
|
-
if self.positions is not None:
|
|
169
|
-
positions = self.positions
|
|
170
|
-
else:
|
|
171
|
-
positions = mutils.linspace_step(self.starts[0], self.stops[0], self.steps[0])
|
|
172
|
-
|
|
173
|
-
if self.scan_subtype == "Linear":
|
|
174
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
175
|
-
|
|
176
|
-
elif self.scan_subtype == 'Linear back to start':
|
|
177
|
-
positions = np.insert(positions, range(1, len(positions) + 1), positions[0], axis=0)
|
|
178
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
179
|
-
|
|
180
|
-
elif self.scan_subtype == 'Random':
|
|
181
|
-
np.random.shuffle(positions)
|
|
182
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
183
|
-
|
|
184
|
-
elif self.scan_subtype == 'Adaptive':
|
|
185
|
-
# return an "empty" ScanInfo as positions will be "set" during the scan
|
|
186
|
-
self.scan_info = ScanInfo(Nsteps=0, positions=np.array([0, 1]), axes_unique=[np.array([])],
|
|
187
|
-
axes_indexes=np.array([]), adaptive_loss=self.adaptive_loss)
|
|
188
|
-
|
|
189
|
-
else: # pragma: no cover
|
|
190
|
-
raise ScannerException(f'The chosen scan_subtype: {str(self.scan_subtype)} is not known')
|
|
191
|
-
|
|
192
|
-
elif self.scan_type == "Scan2D":
|
|
193
|
-
if self.scan_subtype != 'Adaptive':
|
|
194
|
-
if np.abs((self.stops[0]-self.starts[0]) / self.steps[0]) > steps_limit:
|
|
195
|
-
return ScanInfo()
|
|
196
|
-
|
|
197
|
-
if self.scan_subtype == 'Spiral':
|
|
198
|
-
positions = set_scan_spiral(self.starts, self.stops, self.steps)
|
|
199
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
200
|
-
|
|
201
|
-
elif self.scan_subtype == 'Back&Forth':
|
|
202
|
-
positions = set_scan_linear(self.starts, self.stops, self.steps, back_and_force=True)
|
|
203
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
204
|
-
|
|
205
|
-
elif self.scan_subtype == 'Linear':
|
|
206
|
-
positions = set_scan_linear(self.starts, self.stops, self.steps, back_and_force=False)
|
|
207
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
208
|
-
|
|
209
|
-
elif self.scan_subtype == 'Random':
|
|
210
|
-
positions = set_scan_random(self.starts, self.stops, self.steps)
|
|
211
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
212
|
-
|
|
213
|
-
elif self.scan_subtype == 'Adaptive':
|
|
214
|
-
# return an "empty" ScanInfo as positions will be "set" during the scan
|
|
215
|
-
self.scan_info = ScanInfo(Nsteps=0, positions=np.zeros([0, 2]), axes_unique=[np.array([])],
|
|
216
|
-
axes_indexes=np.array([]), adaptive_loss=self.adaptive_loss)
|
|
217
|
-
else:
|
|
218
|
-
raise ScannerException(f'The chosen scan_subtype: {str(self.scan_subtype)} is not known')
|
|
219
|
-
|
|
220
|
-
elif self.scan_type == "Sequential":
|
|
221
|
-
if self.scan_subtype == 'Linear':
|
|
222
|
-
positions = set_scan_sequential(self.starts, self.stops, self.steps)
|
|
223
|
-
self.scan_info = self.get_info_from_positions(positions)
|
|
224
|
-
else:
|
|
225
|
-
raise ScannerException(f'The chosen scan_subtype: {str(self.scan_subtype)} is not known')
|
|
226
|
-
|
|
227
|
-
elif self.scan_type == 'Tabular':
|
|
228
|
-
if self.scan_subtype == 'Linear':
|
|
229
|
-
if self.positions is not None:
|
|
230
|
-
self.starts = np.min(self.positions, axis=0)
|
|
231
|
-
self.stops = np.max(self.positions, axis=0)
|
|
232
|
-
self.scan_info = self.get_info_from_positions(self.positions)
|
|
233
|
-
elif self.scan_subtype == 'Adaptive':
|
|
234
|
-
# return an "empty" ScanInfo as positions will be "set" during the scan
|
|
235
|
-
# but adds some usefull info such as total length and list of vectors
|
|
236
|
-
self.vectors = []
|
|
237
|
-
length = 0.
|
|
238
|
-
|
|
239
|
-
for ind in range(len(self.starts)):
|
|
240
|
-
self.vectors.append(QVector(self.starts[ind][0], self.starts[ind][1],
|
|
241
|
-
self.stops[ind][0], self.stops[ind][1]))
|
|
242
|
-
length += self.vectors[-1].norm()
|
|
243
|
-
|
|
244
|
-
self.scan_info = ScanInfo(Nsteps=0, positions=np.zeros([0, self.Naxes]), axes_unique=[np.array([])],
|
|
245
|
-
axes_indexes=np.array([]), vectors=self.vectors, length=length,
|
|
246
|
-
adaptive_loss=self.adaptive_loss)
|
|
247
|
-
else:
|
|
248
|
-
raise ScannerException(f'The chosen scan_subtype: {str(self.scan_subtype)} is not known')
|
|
249
|
-
return self.scan_info
|
|
250
|
-
|
|
251
|
-
def evaluate_Nsteps(self):
|
|
252
|
-
Nsteps = 1
|
|
253
|
-
if self.starts is not None:
|
|
254
|
-
for ind in range(len(self.starts)):
|
|
255
|
-
if self.scan_subtype == 'Adaptive':
|
|
256
|
-
Nsteps = 1
|
|
257
|
-
elif self.scan_subtype != 'Spiral':
|
|
258
|
-
Nsteps *= np.abs((self.stops[ind] - self.starts[ind]) / self.steps[ind])+1
|
|
259
|
-
else:
|
|
260
|
-
Nsteps *= np.abs(2 * (self.stops[ind] / self.steps[ind]) + 1)
|
|
261
|
-
return Nsteps
|
|
262
|
-
|
|
263
|
-
def __repr__(self):
|
|
264
|
-
if self.vectors is not None:
|
|
265
|
-
bounds = f'bounds as vectors: {self.vectors} and curvilinear step: {self.steps}'
|
|
266
|
-
else:
|
|
267
|
-
bounds = f' bounds (starts/stops/steps): {self.starts}/{self.stops}/{self.steps})'
|
|
268
|
-
|
|
269
|
-
if self.scan_subtype != 'Adaptive':
|
|
270
|
-
return f'[{self.scan_type}/{self.scan_subtype}] scanner with {self.scan_info.Nsteps} positions and ' + bounds
|
|
271
|
-
else:
|
|
272
|
-
return f'[{self.scan_type}/{self.scan_subtype}] scanner with unknown (yet) positions to reach and ' + bounds
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
class Scanner(QObject):
|
|
276
|
-
scan_params_signal = Signal(ScanParameters)
|
|
277
|
-
|
|
278
|
-
params = [#{'title': 'Scanner settings', 'name': 'scan_options', 'type': 'group', 'children': [
|
|
279
|
-
{'title': 'Calculate positions:', 'name': 'calculate_positions', 'type': 'action'},
|
|
280
|
-
{'title': 'N steps:', 'name': 'Nsteps', 'type': 'int', 'value': 0, 'readonly': True},
|
|
281
|
-
|
|
282
|
-
{'title': 'Scan type:', 'name': 'scan_type', 'type': 'list', 'limits': SCAN_TYPES,
|
|
283
|
-
'value': config('scan', 'default')},
|
|
284
|
-
{'title': 'Scan1D settings', 'name': 'scan1D_settings', 'type': 'group', 'children': [
|
|
285
|
-
{'title': 'Scan subtype:', 'name': 'scan1D_type', 'type': 'list',
|
|
286
|
-
'limits': SCAN_SUBTYPES['Scan1D']['limits'], 'value': config('scan', 'scan1D', 'type'),
|
|
287
|
-
'tip': 'For adaptive, an algo will '
|
|
288
|
-
'determine the positions to check within the scan bounds. The defined step will be set as the'
|
|
289
|
-
'biggest feature size the algo should reach.'},
|
|
290
|
-
{'title': 'Loss type', 'name': 'scan1D_loss', 'type': 'list',
|
|
291
|
-
'limits': [], 'tip': 'Type of loss used by the algo. to determine next points'},
|
|
292
|
-
{'title': 'Start:', 'name': 'start_1D', 'type': 'float', 'value': config('scan', 'scan1D', 'start')},
|
|
293
|
-
{'title': 'stop:', 'name': 'stop_1D', 'type': 'float', 'value': config('scan', 'scan1D', 'stop')},
|
|
294
|
-
{'title': 'Step:', 'name': 'step_1D', 'type': 'float', 'value': config('scan', 'scan1D', 'step')}
|
|
295
|
-
]},
|
|
296
|
-
{'title': 'Scan2D settings', 'name': 'scan2D_settings', 'type': 'group', 'visible': False, 'children': [
|
|
297
|
-
{'title': 'Scan subtype:', 'name': 'scan2D_type', 'type': 'list',
|
|
298
|
-
'limits': SCAN_SUBTYPES['Scan2D']['limits'], 'value': config('scan', 'scan2D', 'type'),
|
|
299
|
-
'tip': 'For adaptive, an algo will '
|
|
300
|
-
'determine the positions to check within the scan bounds. The defined step will be set as the'
|
|
301
|
-
'biggest feature size the algo should reach.'},
|
|
302
|
-
{'title': 'Loss type', 'name': 'scan2D_loss', 'type': 'list',
|
|
303
|
-
'limits': [], 'tip': 'Type of loss used by the algo. to determine next points'},
|
|
304
|
-
{'title': 'Selection:', 'name': 'scan2D_selection', 'type': 'list', 'limits': ['Manual', 'FromROI']},
|
|
305
|
-
{'title': 'From module:', 'name': 'scan2D_roi_module', 'type': 'list', 'limits': [], 'visible': False},
|
|
306
|
-
{'title': 'Start Ax1:', 'name': 'start_2d_axis1', 'type': 'float',
|
|
307
|
-
'value': config('scan', 'scan2D', 'start1'), 'visible': True},
|
|
308
|
-
{'title': 'Start Ax2:', 'name': 'start_2d_axis2', 'type': 'float',
|
|
309
|
-
'value': config('scan', 'scan2D', 'start2'), 'visible': True},
|
|
310
|
-
{'title': 'Step Ax1:', 'name': 'step_2d_axis1', 'type': 'float',
|
|
311
|
-
'value': config('scan', 'scan2D', 'step1'), 'visible': True},
|
|
312
|
-
{'title': 'Step Ax2:', 'name': 'step_2d_axis2', 'type': 'float',
|
|
313
|
-
'value': config('scan', 'scan2D', 'step2'), 'visible': True},
|
|
314
|
-
{'title': 'Npts/axis', 'name': 'npts_by_axis', 'type': 'int', 'min': 1,
|
|
315
|
-
'value': config('scan', 'scan2D', 'npts'),
|
|
316
|
-
'visible': True},
|
|
317
|
-
{'title': 'Stop Ax1:', 'name': 'stop_2d_axis1', 'type': 'float',
|
|
318
|
-
'value': config('scan', 'scan2D', 'stop1'), 'visible': True,
|
|
319
|
-
'readonly': True, },
|
|
320
|
-
{'title': 'Stop Ax2:', 'name': 'stop_2d_axis2', 'type': 'float',
|
|
321
|
-
'value': config('scan', 'scan2D', 'stop2'), 'visible': True,
|
|
322
|
-
'readonly': True, },
|
|
323
|
-
|
|
324
|
-
]},
|
|
325
|
-
{'title': 'Sequential settings', 'name': 'seq_settings', 'type': 'group', 'visible': False, 'children': [
|
|
326
|
-
{'title': 'Scan subtype:', 'name': 'scanseq_type', 'type': 'list',
|
|
327
|
-
'limits': SCAN_SUBTYPES['Sequential']['limits'], 'value': SCAN_SUBTYPES['Sequential']['limits'][0], },
|
|
328
|
-
{'title': 'Sequences', 'name': 'seq_table', 'type': 'table_view',
|
|
329
|
-
'delegate': gutils.SpinBoxDelegate},
|
|
330
|
-
]},
|
|
331
|
-
{'title': 'Tabular settings', 'name': 'tabular_settings', 'type': 'group', 'visible': False, 'children': [
|
|
332
|
-
{'title': 'Scan subtype:', 'name': 'tabular_subtype', 'type': 'list',
|
|
333
|
-
'limits': SCAN_SUBTYPES['Tabular']['limits'], 'value': config('scan', 'tabular', 'type'),
|
|
334
|
-
'tip': 'For adaptive, an algo will '
|
|
335
|
-
'determine the positions to check within the scan bounds. The defined step will be set as the'
|
|
336
|
-
'biggest feature size the algo should reach.'},
|
|
337
|
-
{'title': 'Loss type', 'name': 'tabular_loss', 'type': 'list',
|
|
338
|
-
'limits': [], 'tip': 'Type of loss used by the algo. to determine next points'},
|
|
339
|
-
{'title': 'Selection:', 'name': 'tabular_selection', 'type': 'list',
|
|
340
|
-
'limits': ['Manual', 'Polylines']},
|
|
341
|
-
{'title': 'From module:', 'name': 'tabular_roi_module', 'type': 'list', 'limits': [],
|
|
342
|
-
'visible': False},
|
|
343
|
-
{'title': 'Curvilinear Step:', 'name': 'tabular_step', 'type': 'float',
|
|
344
|
-
'value': config('scan', 'tabular', 'curvilinear')},
|
|
345
|
-
{'title': 'Positions', 'name': 'tabular_table', 'type': 'table_view',
|
|
346
|
-
'delegate': gutils.SpinBoxDelegate, 'menu': True},
|
|
347
|
-
]},
|
|
348
|
-
{'title': 'Load settings', 'name': 'load_xml', 'type': 'action'},
|
|
349
|
-
{'title': 'Save settings', 'name': 'save_xml', 'type': 'action'},
|
|
350
|
-
]#}]
|
|
351
|
-
|
|
352
|
-
def __init__(self, scanner_items=OrderedDict([]), scan_type='Scan1D', actuators=[], adaptive_losses=None):
|
|
353
|
-
"""
|
|
354
|
-
|
|
355
|
-
Parameters
|
|
356
|
-
----------
|
|
357
|
-
scanner_items: (items used by ScanSelector for chosing scan area or linear traces)
|
|
358
|
-
scan_type: type of scan selector
|
|
359
|
-
actuators: list of actuators names
|
|
360
|
-
"""
|
|
361
|
-
super().__init__()
|
|
362
|
-
|
|
363
|
-
self.settings_tree = None
|
|
364
|
-
self.setupUI()
|
|
365
|
-
|
|
366
|
-
self.scan_selector = ScanSelector(scanner_items, scan_type)
|
|
367
|
-
self.settings.child('scan_type').setValue(scan_type)
|
|
368
|
-
# self.scan_selector.settings.child('scan_options', 'scan_type').hide()
|
|
369
|
-
self.scan_selector.scan_select_signal.connect(self.update_scan_2D_positions)
|
|
370
|
-
self.scan_selector.scan_select_signal.connect(lambda: self.update_tabular_positions())
|
|
371
|
-
|
|
372
|
-
self.settings.child('tabular_settings', 'tabular_roi_module').setOpts(
|
|
373
|
-
limits=self.scan_selector.sources_names)
|
|
374
|
-
self.settings.child('scan2D_settings', 'scan2D_roi_module').setOpts(
|
|
375
|
-
limits=self.scan_selector.sources_names)
|
|
376
|
-
self.table_model = None
|
|
377
|
-
|
|
378
|
-
if adaptive_losses is not None:
|
|
379
|
-
if 'loss1D' in adaptive_losses:
|
|
380
|
-
self.settings.child('scan1D_settings', 'scan1D_loss').setOpts(
|
|
381
|
-
limits=adaptive_losses['loss1D'], visible=False)
|
|
382
|
-
if 'loss1D' in adaptive_losses:
|
|
383
|
-
self.settings.child('tabular_settings', 'tabular_loss').setOpts(
|
|
384
|
-
limits=adaptive_losses['loss1D'], visible=False)
|
|
385
|
-
if 'loss2D' in adaptive_losses:
|
|
386
|
-
self.settings.child('scan2D_settings', 'scan2D_loss').setOpts(
|
|
387
|
-
limits=adaptive_losses['loss2D'], visible=False)
|
|
388
|
-
|
|
389
|
-
self.actuators = actuators
|
|
390
|
-
# if actuators != []:
|
|
391
|
-
# self.actuators = actuators
|
|
392
|
-
# else:
|
|
393
|
-
# stypes = SCAN_TYPES[:]
|
|
394
|
-
# stypes.pop(stypes.index('Sequential'))
|
|
395
|
-
# self.settings.child('scan_type').setLimits(stypes)
|
|
396
|
-
# self.settings.child('scan_type').setValue(stypes[0])
|
|
397
|
-
|
|
398
|
-
self.scan_selector.widget.setVisible(False)
|
|
399
|
-
self.scan_selector.show_scan_selector(visible=False)
|
|
400
|
-
self.settings.child('load_xml').sigActivated.connect(self.load_xml)
|
|
401
|
-
self.settings.child('save_xml').sigActivated.connect(self.save_xml)
|
|
402
|
-
|
|
403
|
-
self.set_scan()
|
|
404
|
-
self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)
|
|
405
|
-
|
|
406
|
-
def load_xml(self):
|
|
407
|
-
fname = gutils.select_file(start_path=None, save=False, ext='xml')
|
|
408
|
-
if fname is not None and fname != '':
|
|
409
|
-
par = ioxml.XML_file_to_parameter(fname)
|
|
410
|
-
self.settings.restoreState(Parameter.create(name='settings', type='group', children=par).saveState())
|
|
411
|
-
self.update_model()
|
|
412
|
-
scan_type = self.settings.child('scan_type').value()
|
|
413
|
-
if scan_type == 'Sequential':
|
|
414
|
-
self.table_model = self.settings.child('seq_settings', 'seq_table').value()
|
|
415
|
-
elif scan_type == 'Tabular':
|
|
416
|
-
self.table_model = self.settings.child('tabular_settings', 'tabular_table').value()
|
|
417
|
-
self.set_scan()
|
|
418
|
-
|
|
419
|
-
def save_xml(self):
|
|
420
|
-
"""
|
|
421
|
-
"""
|
|
422
|
-
fname = gutils.select_file(start_path=None, save=True, ext='xml')
|
|
423
|
-
if fname is not None and fname != '':
|
|
424
|
-
ioxml.parameter_to_xml_file(self.settings, fname)
|
|
425
|
-
|
|
426
|
-
def set_config(self):
|
|
427
|
-
scan_type = config['scan']['default']
|
|
428
|
-
self.settings.child('scan_type').setValue(scan_type)
|
|
429
|
-
|
|
430
|
-
self.settings.child('scan1D_settings', 'scan1D_type').setValue(config('scan', 'scan1D', 'type'))
|
|
431
|
-
self.settings.child('scan1D_settings', 'start_1D').setValue(config('scan', 'scan1D', 'start'))
|
|
432
|
-
self.settings.child('scan1D_settings', 'stop_1D').setValue(config('scan', 'scan1D', 'stop'))
|
|
433
|
-
self.settings.child('scan1D_settings', 'step_1D').setValue(config('scan', 'scan1D', 'step'))
|
|
434
|
-
|
|
435
|
-
self.settings.child('scan2D_settings', 'scan2D_type').setValue(config('scan', 'scan2D', 'type'))
|
|
436
|
-
self.settings.child('scan2D_settings', 'start_2d_axis1').setValue(
|
|
437
|
-
config('scan', 'scan2D', 'start1'))
|
|
438
|
-
self.settings.child('scan2D_settings', 'start_2d_axis2').setValue(
|
|
439
|
-
config('scan', 'scan2D', 'start2'))
|
|
440
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').setValue(
|
|
441
|
-
config('scan', 'scan2D', 'step1'))
|
|
442
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').setValue(
|
|
443
|
-
config('scan', 'scan2D', 'step2'))
|
|
444
|
-
self.settings.child('scan2D_settings', 'npts_by_axis').setValue(
|
|
445
|
-
config('scan', 'scan2D', 'npts'))
|
|
446
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis1').setValue(
|
|
447
|
-
config('scan', 'scan2D', 'stop1'))
|
|
448
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis2').setValue(
|
|
449
|
-
config('scan', 'scan2D', 'stop2'))
|
|
450
|
-
|
|
451
|
-
self.settings.child('tabular_settings', 'tabular_subtype').setValue(
|
|
452
|
-
config('scan', 'tabular', 'type'))
|
|
453
|
-
self.settings.child('tabular_settings', 'tabular_step').setValue(
|
|
454
|
-
config('scan', 'tabular', 'curvilinear'))
|
|
455
|
-
|
|
456
|
-
@property
|
|
457
|
-
def actuators(self):
|
|
458
|
-
"""
|
|
459
|
-
Returns as a list the name of the actuators selected to describe the actual scan
|
|
460
|
-
"""
|
|
461
|
-
return self._actuators
|
|
462
|
-
|
|
463
|
-
@actuators.setter
|
|
464
|
-
def actuators(self, act_list):
|
|
465
|
-
self._actuators = act_list
|
|
466
|
-
if len(act_list) >= 1:
|
|
467
|
-
tip = f'Ax1 corresponds to the {act_list[0]} actuator'
|
|
468
|
-
self.settings.child('scan2D_settings', 'start_2d_axis1').setOpts(tip=tip)
|
|
469
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis1').setOpts(tip=tip)
|
|
470
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').setOpts(tip=tip)
|
|
471
|
-
if len(act_list) >= 2:
|
|
472
|
-
tip = f'Ax2 corresponds to the {act_list[1]} actuator'
|
|
473
|
-
self.settings.child('scan2D_settings', 'start_2d_axis2').setOpts(tip=tip)
|
|
474
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis2').setOpts(tip=tip)
|
|
475
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').setOpts(tip=tip)
|
|
476
|
-
|
|
477
|
-
self.update_model()
|
|
478
|
-
|
|
479
|
-
def update_model(self, init_data=None):
|
|
480
|
-
try:
|
|
481
|
-
scan_type = self.settings.child('scan_type').value()
|
|
482
|
-
if scan_type == 'Sequential':
|
|
483
|
-
if init_data is None:
|
|
484
|
-
if self.table_model is not None:
|
|
485
|
-
init_data = []
|
|
486
|
-
names = [row[0] for row in self.table_model.get_data_all()]
|
|
487
|
-
for name in self._actuators:
|
|
488
|
-
if name in names:
|
|
489
|
-
ind_row = names.index(name)
|
|
490
|
-
init_data.append(self.table_model.get_data_all()[ind_row])
|
|
491
|
-
else:
|
|
492
|
-
init_data.append([name, 0., 1., 0.1])
|
|
493
|
-
else:
|
|
494
|
-
init_data = [[name, 0., 1., 0.1] for name in self._actuators]
|
|
495
|
-
self.table_model = TableModelSequential(init_data, )
|
|
496
|
-
self.table_view = putils.get_widget_from_tree(self.settings_tree, pymodaq_types.TableViewCustom)[0]
|
|
497
|
-
self.settings.child('seq_settings', 'seq_table').setValue(self.table_model)
|
|
498
|
-
elif scan_type == 'Tabular':
|
|
499
|
-
if init_data is None:
|
|
500
|
-
init_data = [[0. for name in self._actuators]]
|
|
501
|
-
|
|
502
|
-
self.table_model = TableModelTabular(init_data, [name for name in self._actuators])
|
|
503
|
-
self.table_view = putils.get_widget_from_tree(self.settings_tree, pymodaq_types.TableViewCustom)[1]
|
|
504
|
-
self.settings.child('tabular_settings', 'tabular_table').setValue(self.table_model)
|
|
505
|
-
except Exception as e:
|
|
506
|
-
logger.exception(str(e))
|
|
507
|
-
|
|
508
|
-
if scan_type == 'Sequential' or scan_type == 'Tabular':
|
|
509
|
-
self.table_view.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
|
510
|
-
self.table_view.horizontalHeader().setStretchLastSection(True)
|
|
511
|
-
self.table_view.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
|
|
512
|
-
self.table_view.setSelectionMode(QtWidgets.QTableView.SingleSelection)
|
|
513
|
-
styledItemDelegate = QtWidgets.QStyledItemDelegate()
|
|
514
|
-
styledItemDelegate.setItemEditorFactory(gutils.SpinBoxDelegate())
|
|
515
|
-
self.table_view.setItemDelegate(styledItemDelegate)
|
|
516
|
-
|
|
517
|
-
self.table_view.setDragEnabled(True)
|
|
518
|
-
self.table_view.setDropIndicatorShown(True)
|
|
519
|
-
self.table_view.setAcceptDrops(True)
|
|
520
|
-
self.table_view.viewport().setAcceptDrops(True)
|
|
521
|
-
self.table_view.setDefaultDropAction(QtCore.Qt.MoveAction)
|
|
522
|
-
self.table_view.setDragDropMode(QtWidgets.QTableView.InternalMove)
|
|
523
|
-
self.table_view.setDragDropOverwriteMode(False)
|
|
524
|
-
|
|
525
|
-
if scan_type == 'Tabular':
|
|
526
|
-
self.table_view.add_data_signal[int].connect(self.table_model.add_data)
|
|
527
|
-
self.table_view.remove_row_signal[int].connect(self.table_model.remove_data)
|
|
528
|
-
self.table_view.load_data_signal.connect(self.table_model.load_txt)
|
|
529
|
-
self.table_view.save_data_signal.connect(self.table_model.save_txt)
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
@property
|
|
533
|
-
def viewers_items(self):
|
|
534
|
-
return self.scan_selector.viewers_items
|
|
535
|
-
|
|
536
|
-
@viewers_items.setter
|
|
537
|
-
def viewers_items(self, items):
|
|
538
|
-
self.scan_selector.remove_scan_selector()
|
|
539
|
-
self.scan_selector.viewers_items = items
|
|
540
|
-
self.settings.child('tabular_settings', 'tabular_roi_module').setOpts(
|
|
541
|
-
limits=self.scan_selector.sources_names)
|
|
542
|
-
self.settings.child('scan2D_settings', 'scan2D_roi_module').setOpts(
|
|
543
|
-
limits=self.scan_selector.sources_names)
|
|
544
|
-
|
|
545
|
-
def set_scan_type_and_subtypes(self, scan_type: str, scan_subtype=None):
|
|
546
|
-
"""Convenience function to qzt the main scan type"""
|
|
547
|
-
if scan_type in SCAN_TYPES:
|
|
548
|
-
self.settings.child('scan_type').setValue(scan_type)
|
|
549
|
-
|
|
550
|
-
if scan_subtype is not None:
|
|
551
|
-
if scan_subtype in SCAN_SUBTYPES[scan_type]['limits']:
|
|
552
|
-
self.settings.child(*SCAN_SUBTYPES[scan_type]['subpath']).setValue(scan_subtype)
|
|
553
|
-
|
|
554
|
-
def parameter_tree_changed(self, param, changes):
|
|
555
|
-
"""
|
|
556
|
-
|
|
557
|
-
"""
|
|
558
|
-
for param, change, data in changes:
|
|
559
|
-
path = self.settings.childPath(param)
|
|
560
|
-
if path is not None:
|
|
561
|
-
childName = '.'.join(path)
|
|
562
|
-
else:
|
|
563
|
-
childName = param.name()
|
|
564
|
-
if change == 'childAdded':
|
|
565
|
-
pass
|
|
566
|
-
|
|
567
|
-
elif change == 'value':
|
|
568
|
-
if param.name() == 'scan_type':
|
|
569
|
-
|
|
570
|
-
if data == 'Scan1D':
|
|
571
|
-
self.settings.child('scan1D_settings').show()
|
|
572
|
-
self.settings.child('scan2D_settings').hide()
|
|
573
|
-
self.settings.child('seq_settings').hide()
|
|
574
|
-
self.settings.child('tabular_settings').hide()
|
|
575
|
-
self.settings_tree.setMaximumHeight(500)
|
|
576
|
-
|
|
577
|
-
elif data == 'Scan2D':
|
|
578
|
-
self.settings.child('scan1D_settings').hide()
|
|
579
|
-
self.settings.child('scan2D_settings').show()
|
|
580
|
-
self.settings.child('seq_settings').hide()
|
|
581
|
-
self.settings.child('tabular_settings').hide()
|
|
582
|
-
self.settings_tree.setMaximumHeight(500)
|
|
583
|
-
self.scan_selector.settings.child('scan_options', 'scan_type').setValue(data)
|
|
584
|
-
if self.settings.child('scan2D_settings',
|
|
585
|
-
'scan2D_selection').value() == 'Manual':
|
|
586
|
-
self.scan_selector.show_scan_selector(visible=False)
|
|
587
|
-
else:
|
|
588
|
-
self.scan_selector.show_scan_selector(visible=True)
|
|
589
|
-
self.update_scan_2D_positions()
|
|
590
|
-
self.update_scan2D_type(param)
|
|
591
|
-
|
|
592
|
-
elif data == 'Sequential':
|
|
593
|
-
self.settings.child('scan1D_settings').hide()
|
|
594
|
-
self.settings.child('scan2D_settings').hide()
|
|
595
|
-
self.settings.child('seq_settings').show()
|
|
596
|
-
self.settings.child('tabular_settings').hide()
|
|
597
|
-
self.update_model()
|
|
598
|
-
self.settings_tree.setMaximumHeight(600)
|
|
599
|
-
|
|
600
|
-
elif data == 'Tabular':
|
|
601
|
-
self.settings.child('scan1D_settings').hide()
|
|
602
|
-
self.settings.child('scan2D_settings').hide()
|
|
603
|
-
self.settings.child('seq_settings').hide()
|
|
604
|
-
self.settings.child('tabular_settings').show()
|
|
605
|
-
self.settings.child('tabular_settings', 'tabular_step').hide()
|
|
606
|
-
|
|
607
|
-
self.update_tabular_positions()
|
|
608
|
-
self.settings_tree.setMaximumHeight(600)
|
|
609
|
-
self.scan_selector.settings.child('scan_options', 'scan_type').setValue(data)
|
|
610
|
-
if self.settings.child('tabular_settings',
|
|
611
|
-
'tabular_selection').value() == 'Manual':
|
|
612
|
-
self.scan_selector.show_scan_selector(visible=False)
|
|
613
|
-
else:
|
|
614
|
-
self.scan_selector.show_scan_selector(visible=True)
|
|
615
|
-
|
|
616
|
-
elif param.name() == 'scan1D_type':
|
|
617
|
-
status = 'adaptive' in param.value().lower()
|
|
618
|
-
self.settings.child('scan1D_settings', 'scan1D_loss').show(status)
|
|
619
|
-
|
|
620
|
-
elif param.name() == 'tabular_subtype':
|
|
621
|
-
isadaptive = 'adaptive' in self.settings.child('tabular_settings',
|
|
622
|
-
'tabular_subtype').value().lower()
|
|
623
|
-
ismanual = self.settings.child('tabular_settings',
|
|
624
|
-
'tabular_selection').value() == 'Manual'
|
|
625
|
-
self.settings.child('tabular_settings', 'tabular_loss').show(isadaptive)
|
|
626
|
-
self.settings.child('tabular_settings',
|
|
627
|
-
'tabular_step').show(not isadaptive and not ismanual)
|
|
628
|
-
self.update_tabular_positions()
|
|
629
|
-
|
|
630
|
-
elif param.name() == 'tabular_roi_module' or param.name() == 'scan2D_roi_module':
|
|
631
|
-
self.scan_selector.settings.child('scan_options', 'sources').setValue(param.value())
|
|
632
|
-
|
|
633
|
-
elif param.name() == 'tabular_selection':
|
|
634
|
-
isadaptive = 'adaptive' in self.settings.child('tabular_settings',
|
|
635
|
-
'tabular_subtype').value().lower()
|
|
636
|
-
ismanual = self.settings.child('tabular_settings',
|
|
637
|
-
'tabular_selection').value() == 'Manual'
|
|
638
|
-
self.settings.child('tabular_settings',
|
|
639
|
-
'tabular_step').show(not isadaptive and not ismanual)
|
|
640
|
-
if data == 'Polylines':
|
|
641
|
-
self.settings.child('tabular_settings', 'tabular_roi_module').show()
|
|
642
|
-
self.scan_selector.show_scan_selector(visible=True)
|
|
643
|
-
else:
|
|
644
|
-
self.settings.child('tabular_settings', 'tabular_roi_module').hide()
|
|
645
|
-
self.scan_selector.show_scan_selector(visible=False)
|
|
646
|
-
self.update_tabular_positions()
|
|
647
|
-
|
|
648
|
-
elif param.name() == 'tabular_step':
|
|
649
|
-
self.update_tabular_positions()
|
|
650
|
-
self.set_scan()
|
|
651
|
-
|
|
652
|
-
elif param.name() == 'scan2D_selection':
|
|
653
|
-
if param.value() == 'Manual':
|
|
654
|
-
self.scan_selector.show_scan_selector(visible=False)
|
|
655
|
-
self.settings.child('scan2D_settings', 'scan2D_roi_module').hide()
|
|
656
|
-
else:
|
|
657
|
-
self.scan_selector.show_scan_selector(visible=True)
|
|
658
|
-
self.settings.child('scan2D_settings', 'scan2D_roi_module').show()
|
|
659
|
-
|
|
660
|
-
self.update_scan2D_type(param)
|
|
661
|
-
|
|
662
|
-
elif param.name() in putils.iter_children(self.settings.child('scan2D_settings'), []):
|
|
663
|
-
self.update_scan2D_type(param)
|
|
664
|
-
self.set_scan()
|
|
665
|
-
|
|
666
|
-
elif param.name() == 'Nsteps':
|
|
667
|
-
pass # just do nothing (otherwise set_scan will be fired, see below)
|
|
668
|
-
|
|
669
|
-
else:
|
|
670
|
-
try:
|
|
671
|
-
self.set_scan()
|
|
672
|
-
except Exception as e:
|
|
673
|
-
logger.error(f'Invalid call to setScan ({str(e)})')
|
|
674
|
-
|
|
675
|
-
elif change == 'parent':
|
|
676
|
-
pass
|
|
677
|
-
|
|
678
|
-
def setupUI(self):
|
|
679
|
-
# layout = QtWidgets.QHBoxLayout()
|
|
680
|
-
# layout.setSpacing(0)
|
|
681
|
-
# self.parent.setLayout(layout)
|
|
682
|
-
self.settings_tree = ParameterTree()
|
|
683
|
-
self.settings = Parameter.create(name='Scanner_Settings', title='Scanner Settings', type='group',
|
|
684
|
-
children=self.params)
|
|
685
|
-
self.settings_tree.setParameters(self.settings, showTop=False)
|
|
686
|
-
self.settings_tree.setMaximumHeight(500)
|
|
687
|
-
|
|
688
|
-
self.settings.child('calculate_positions').sigActivated.connect(self.set_scan)
|
|
689
|
-
# layout.addWidget(self.settings_tree)
|
|
690
|
-
|
|
691
|
-
def set_scan(self):
|
|
692
|
-
scan_type = self.settings.child('scan_type').value()
|
|
693
|
-
|
|
694
|
-
if scan_type == "Scan1D":
|
|
695
|
-
start = self.settings.child('scan1D_settings', 'start_1D').value()
|
|
696
|
-
stop = self.settings.child('scan1D_settings', 'stop_1D').value()
|
|
697
|
-
step = self.settings.child('scan1D_settings', 'step_1D').value()
|
|
698
|
-
self.scan_parameters = ScanParameters(Naxes=1, scan_type="Scan1D",
|
|
699
|
-
scan_subtype=self.settings.child('scan1D_settings',
|
|
700
|
-
'scan1D_type').value(),
|
|
701
|
-
starts=[start], stops=[stop], steps=[step],
|
|
702
|
-
adaptive_loss=self.settings.child('scan1D_settings',
|
|
703
|
-
'scan1D_loss').value())
|
|
704
|
-
|
|
705
|
-
elif scan_type == "Scan2D":
|
|
706
|
-
starts = [self.settings.child('scan2D_settings', 'start_2d_axis1').value(),
|
|
707
|
-
self.settings.child('scan2D_settings', 'start_2d_axis2').value()]
|
|
708
|
-
stops = [self.settings.child('scan2D_settings', 'stop_2d_axis1').value(),
|
|
709
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis2').value()]
|
|
710
|
-
steps = [self.settings.child('scan2D_settings', 'step_2d_axis1').value(),
|
|
711
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').value()]
|
|
712
|
-
self.scan_parameters = ScanParameters(Naxes=2, scan_type="Scan2D",
|
|
713
|
-
scan_subtype=self.settings.child('scan2D_settings',
|
|
714
|
-
'scan2D_type').value(),
|
|
715
|
-
starts=starts, stops=stops, steps=steps,
|
|
716
|
-
adaptive_loss=self.settings.child('scan2D_settings',
|
|
717
|
-
'scan2D_loss').value())
|
|
718
|
-
|
|
719
|
-
elif scan_type == "Sequential":
|
|
720
|
-
starts = [self.table_model.get_data(ind, 1) for ind in range(self.table_model.rowCount(None))]
|
|
721
|
-
stops = [self.table_model.get_data(ind, 2) for ind in range(self.table_model.rowCount(None))]
|
|
722
|
-
steps = [self.table_model.get_data(ind, 3) for ind in range(self.table_model.rowCount(None))]
|
|
723
|
-
self.scan_parameters = ScanParameters(Naxes=len(starts), scan_type="Sequential",
|
|
724
|
-
scan_subtype=self.settings.child('seq_settings',
|
|
725
|
-
'scanseq_type').value(),
|
|
726
|
-
starts=starts, stops=stops, steps=steps)
|
|
727
|
-
|
|
728
|
-
elif scan_type == 'Tabular':
|
|
729
|
-
positions = np.array(self.table_model.get_data_all())
|
|
730
|
-
Naxes = positions.shape[1]
|
|
731
|
-
if self.settings.child('tabular_settings', 'tabular_subtype').value() == 'Adaptive':
|
|
732
|
-
starts = positions[:-1]
|
|
733
|
-
stops = positions[1:]
|
|
734
|
-
steps = [self.settings.child('tabular_settings', 'tabular_step').value()]
|
|
735
|
-
positions = None
|
|
736
|
-
else:
|
|
737
|
-
starts = None
|
|
738
|
-
stops = None
|
|
739
|
-
steps = None
|
|
740
|
-
|
|
741
|
-
self.scan_parameters = ScanParameters(Naxes=Naxes, scan_type="Tabular",
|
|
742
|
-
scan_subtype=self.settings.child('tabular_settings',
|
|
743
|
-
'tabular_subtype').value(),
|
|
744
|
-
starts=starts, stops=stops, steps=steps, positions=positions,
|
|
745
|
-
adaptive_loss=self.settings.child('tabular_settings',
|
|
746
|
-
'tabular_loss').value())
|
|
747
|
-
|
|
748
|
-
self.settings.child('Nsteps').setValue(self.scan_parameters.Nsteps)
|
|
749
|
-
self.scan_params_signal.emit(self.scan_parameters)
|
|
750
|
-
return self.scan_parameters
|
|
751
|
-
|
|
752
|
-
def update_tabular_positions(self, positions=None):
|
|
753
|
-
try:
|
|
754
|
-
if self.settings.child('scan_type').value() == 'Tabular':
|
|
755
|
-
if positions is None:
|
|
756
|
-
if self.settings.child('tabular_settings',
|
|
757
|
-
'tabular_selection').value() == 'Polylines': # from ROI
|
|
758
|
-
viewer = self.scan_selector.scan_selector_source
|
|
759
|
-
|
|
760
|
-
if self.settings.child('tabular_settings', 'tabular_subtype').value() == 'Linear':
|
|
761
|
-
positions = self.scan_selector.scan_selector.getArrayIndexes(
|
|
762
|
-
spacing=self.settings.child('tabular_settings', 'tabular_step').value())
|
|
763
|
-
elif self.settings.child('tabular_settings',
|
|
764
|
-
'tabular_subtype').value() == 'Adaptive':
|
|
765
|
-
positions = self.scan_selector.scan_selector.get_vertex()
|
|
766
|
-
|
|
767
|
-
steps_x, steps_y = zip(*positions)
|
|
768
|
-
steps_x, steps_y = viewer.scale_axis(np.array(steps_x), np.array(steps_y))
|
|
769
|
-
positions = np.transpose(np.array([steps_x, steps_y]))
|
|
770
|
-
self.update_model(init_data=positions)
|
|
771
|
-
else:
|
|
772
|
-
self.update_model()
|
|
773
|
-
elif isinstance(positions, np.ndarray):
|
|
774
|
-
self.update_model(init_data=positions)
|
|
775
|
-
else:
|
|
776
|
-
pass
|
|
777
|
-
else:
|
|
778
|
-
self.update_model()
|
|
779
|
-
except Exception as e:
|
|
780
|
-
logger.exception(str(e))
|
|
781
|
-
|
|
782
|
-
def update_scan_2D_positions(self):
|
|
783
|
-
try:
|
|
784
|
-
viewer = self.scan_selector.scan_selector_source
|
|
785
|
-
pos_dl = self.scan_selector.scan_selector.pos()
|
|
786
|
-
pos_ur = self.scan_selector.scan_selector.pos() + self.scan_selector.scan_selector.size()
|
|
787
|
-
pos_dl_scaled = viewer.scale_axis(pos_dl[0], pos_dl[1])
|
|
788
|
-
pos_ur_scaled = viewer.scale_axis(pos_ur[0], pos_ur[1])
|
|
789
|
-
|
|
790
|
-
if self.settings.child('scan2D_settings', 'scan2D_type').value() == 'Spiral':
|
|
791
|
-
self.settings.child('scan2D_settings', 'start_2d_axis1').setValue(
|
|
792
|
-
np.mean((pos_dl_scaled[0], pos_ur_scaled[0])))
|
|
793
|
-
self.settings.child('scan2D_settings', 'start_2d_axis2').setValue(
|
|
794
|
-
np.mean((pos_dl_scaled[1], pos_ur_scaled[1])))
|
|
795
|
-
|
|
796
|
-
nsteps = 2 * np.min((np.abs((pos_ur_scaled[0] - pos_dl_scaled[0]) / 2) / self.settings.child(
|
|
797
|
-
'scan2D_settings', 'step_2d_axis1').value(), np.abs(
|
|
798
|
-
(pos_ur_scaled[1] - pos_dl_scaled[1]) / 2) / self.settings.child(
|
|
799
|
-
'scan2D_settings', 'step_2d_axis2').value()))
|
|
800
|
-
|
|
801
|
-
self.settings.child('scan2D_settings', 'npts_by_axis').setValue(nsteps)
|
|
802
|
-
|
|
803
|
-
else:
|
|
804
|
-
self.settings.child('scan2D_settings', 'start_2d_axis1').setValue(pos_dl_scaled[0])
|
|
805
|
-
self.settings.child('scan2D_settings', 'start_2d_axis2').setValue(pos_dl_scaled[1])
|
|
806
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis1').setValue(pos_ur_scaled[0])
|
|
807
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis2').setValue(pos_ur_scaled[1])
|
|
808
|
-
|
|
809
|
-
except Exception as e:
|
|
810
|
-
raise ScannerException(str(e))
|
|
811
|
-
|
|
812
|
-
def update_scan2D_type(self, param):
|
|
813
|
-
"""
|
|
814
|
-
Update the scan type from the given parameter.
|
|
815
|
-
|
|
816
|
-
=============== ================================= ========================
|
|
817
|
-
**Parameters** **Type** **Description**
|
|
818
|
-
*param* instance of pyqtgraph parameter the parameter to treat
|
|
819
|
-
=============== ================================= ========================
|
|
820
|
-
|
|
821
|
-
See Also
|
|
822
|
-
--------
|
|
823
|
-
update_status
|
|
824
|
-
"""
|
|
825
|
-
try:
|
|
826
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').show()
|
|
827
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').show()
|
|
828
|
-
scan_subtype = self.settings.child('scan2D_settings', 'scan2D_type').value()
|
|
829
|
-
self.settings.child('scan2D_settings', 'scan2D_loss').show(scan_subtype == 'Adaptive')
|
|
830
|
-
if scan_subtype == 'Adaptive':
|
|
831
|
-
if self.settings.child('scan2D_settings', 'scan2D_loss').value() == 'resolution':
|
|
832
|
-
title = 'Minimal feature (%):'
|
|
833
|
-
if self.settings.child('scan2D_settings', 'step_2d_axis1').opts['title'] != title:
|
|
834
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').setValue(1)
|
|
835
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').setValue(100)
|
|
836
|
-
|
|
837
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').setOpts(
|
|
838
|
-
limits=[0, 100], title=title, visible=True,
|
|
839
|
-
tip='Features smaller than this will not be probed first. In percent of maximal scanned area'
|
|
840
|
-
' length',
|
|
841
|
-
)
|
|
842
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').setOpts(
|
|
843
|
-
limits=[0, 100], title='Maximal feature (%):', visible=True,
|
|
844
|
-
tip='Features bigger than this will be probed first. In percent of maximal scanned area length',
|
|
845
|
-
)
|
|
846
|
-
|
|
847
|
-
else:
|
|
848
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').hide()
|
|
849
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').hide()
|
|
850
|
-
else:
|
|
851
|
-
self.settings.child('scan2D_settings',
|
|
852
|
-
'step_2d_axis1').setOpts(title='Step Ax1:',
|
|
853
|
-
tip='Step size for ax1 in actuator units')
|
|
854
|
-
self.settings.child('scan2D_settings',
|
|
855
|
-
'step_2d_axis2').setOpts(title='Step Ax2:',
|
|
856
|
-
tip='Step size for ax2 in actuator units')
|
|
857
|
-
|
|
858
|
-
if scan_subtype == 'Spiral':
|
|
859
|
-
self.settings.child('scan2D_settings',
|
|
860
|
-
'start_2d_axis1').setOpts(title='Center Ax1')
|
|
861
|
-
self.settings.child('scan2D_settings',
|
|
862
|
-
'start_2d_axis2').setOpts(title='Center Ax2')
|
|
863
|
-
|
|
864
|
-
self.settings.child('scan2D_settings',
|
|
865
|
-
'stop_2d_axis1').setOpts(title='Rmax Ax1', readonly=True,
|
|
866
|
-
tip='Read only for Spiral scan type, set the step and Npts/axis')
|
|
867
|
-
self.settings.child('scan2D_settings',
|
|
868
|
-
'stop_2d_axis2').setOpts(title='Rmax Ax2', readonly=True,
|
|
869
|
-
tip='Read only for Spiral scan type, set the step and Npts/axis')
|
|
870
|
-
self.settings.child('scan2D_settings',
|
|
871
|
-
'npts_by_axis').show()
|
|
872
|
-
|
|
873
|
-
# do some checks and set stops values
|
|
874
|
-
self.settings.sigTreeStateChanged.disconnect()
|
|
875
|
-
if param.name() == 'step_2d_axis1':
|
|
876
|
-
if param.value() < 0:
|
|
877
|
-
param.setValue(-param.value())
|
|
878
|
-
|
|
879
|
-
if param.name() == 'step_2d_axis2':
|
|
880
|
-
if param.value() < 0:
|
|
881
|
-
param.setValue(-param.value())
|
|
882
|
-
|
|
883
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis1').setValue(
|
|
884
|
-
np.rint(self.settings.child(
|
|
885
|
-
'scan2D_settings', 'npts_by_axis').value() / 2) * np.abs(
|
|
886
|
-
self.settings.child('scan2D_settings', 'step_2d_axis1').value()))
|
|
887
|
-
|
|
888
|
-
self.settings.child('scan2D_settings', 'stop_2d_axis2').setValue(
|
|
889
|
-
np.rint(self.settings.child(
|
|
890
|
-
'scan2D_settings', 'npts_by_axis').value() / 2) * np.abs(
|
|
891
|
-
self.settings.child('scan2D_settings', 'step_2d_axis2').value()))
|
|
892
|
-
QtWidgets.QApplication.processEvents()
|
|
893
|
-
self.settings.sigTreeStateChanged.connect(self.parameter_tree_changed)
|
|
894
|
-
else:
|
|
895
|
-
self.settings.child('scan2D_settings',
|
|
896
|
-
'start_2d_axis1').setOpts(title='Start Ax1')
|
|
897
|
-
self.settings.child('scan2D_settings',
|
|
898
|
-
'start_2d_axis2').setOpts(title='Start Ax2')
|
|
899
|
-
|
|
900
|
-
self.settings.child('scan2D_settings',
|
|
901
|
-
'stop_2d_axis1').setOpts(title='Stop Ax1', readonly=False,
|
|
902
|
-
tip='Set the stop positions')
|
|
903
|
-
self.settings.child('scan2D_settings',
|
|
904
|
-
'stop_2d_axis2').setOpts(title='StopAx2', readonly=False,
|
|
905
|
-
tip='Set the stop positions')
|
|
906
|
-
self.settings.child('scan2D_settings', 'npts_by_axis').hide()
|
|
907
|
-
except Exception as e:
|
|
908
|
-
raise ScannerException(str(e))
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
class TableModelTabular(gutils.TableModel):
|
|
912
|
-
def __init__(self, data, axes_name=None, **kwargs):
|
|
913
|
-
if axes_name is None:
|
|
914
|
-
if 'header' in kwargs: # when saved as XML the header will be saved and restored here
|
|
915
|
-
axes_name = [h for h in kwargs['header']]
|
|
916
|
-
kwargs.pop('header')
|
|
917
|
-
else:
|
|
918
|
-
raise Exception('Invalid header')
|
|
919
|
-
|
|
920
|
-
header = [name for name in axes_name]
|
|
921
|
-
editable = [True for name in axes_name]
|
|
922
|
-
super().__init__(data, header, editable=editable, **kwargs)
|
|
923
|
-
|
|
924
|
-
@Slot(int)
|
|
925
|
-
def add_data(self, row, data=None):
|
|
926
|
-
if data is not None:
|
|
927
|
-
self.insert_data(row, [float(d) for d in data])
|
|
928
|
-
else:
|
|
929
|
-
self.insert_data(row, [0. for name in self.header])
|
|
930
|
-
|
|
931
|
-
@Slot(int)
|
|
932
|
-
def remove_data(self, row):
|
|
933
|
-
self.remove_row(row)
|
|
934
|
-
|
|
935
|
-
def load_txt(self):
|
|
936
|
-
fname = gutils.select_file(start_path=None, save=False, ext='*')
|
|
937
|
-
if fname is not None and fname != '':
|
|
938
|
-
while self.rowCount(self.index(-1, -1)) > 0:
|
|
939
|
-
self.remove_row(0)
|
|
940
|
-
|
|
941
|
-
data = np.loadtxt(fname)
|
|
942
|
-
if len(data.shape) == 1:
|
|
943
|
-
data = data.reshape((data.size, 1))
|
|
944
|
-
self.set_data_all(data)
|
|
945
|
-
|
|
946
|
-
def save_txt(self):
|
|
947
|
-
fname = gutils.select_file(start_path=None, save=True, ext='dat')
|
|
948
|
-
if fname is not None and fname != '':
|
|
949
|
-
np.savetxt(fname, self.get_data_all(), delimiter='\t')
|
|
950
|
-
|
|
951
|
-
def __repr__(self):
|
|
952
|
-
return f'{self.__class__.__name__} from module {self.__class__.__module__}'
|
|
953
|
-
|
|
954
|
-
def validate_data(self, row, col, value):
|
|
955
|
-
"""
|
|
956
|
-
make sure the values and signs of the start, stop and step values are "correct"
|
|
957
|
-
Parameters
|
|
958
|
-
----------
|
|
959
|
-
row: (int) row within the table that is to be changed
|
|
960
|
-
col: (int) col within the table that is to be changed
|
|
961
|
-
value: (float) new value for the value defined by row and col
|
|
962
|
-
|
|
963
|
-
Returns
|
|
964
|
-
-------
|
|
965
|
-
bool: True is the new value is fine (change some other values if needed) otherwise False
|
|
966
|
-
"""
|
|
967
|
-
|
|
968
|
-
return True
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
class TableModelSequential(gutils.TableModel):
|
|
972
|
-
def __init__(self, data, **kwargs):
|
|
973
|
-
header = ['Actuator', 'Start', 'Stop', 'Step']
|
|
974
|
-
if 'header' in kwargs:
|
|
975
|
-
header = kwargs.pop('header')
|
|
976
|
-
editable = [False, True, True, True]
|
|
977
|
-
if 'editable' in kwargs:
|
|
978
|
-
editable = kwargs.pop('editable')
|
|
979
|
-
super().__init__(data, header, editable=editable, **kwargs)
|
|
980
|
-
|
|
981
|
-
def __repr__(self):
|
|
982
|
-
return f'{self.__class__.__name__} from module {self.__class__.__module__}'
|
|
983
|
-
|
|
984
|
-
def validate_data(self, row, col, value):
|
|
985
|
-
"""
|
|
986
|
-
make sure the values and signs of the start, stop and step values are "correct"
|
|
987
|
-
Parameters
|
|
988
|
-
----------
|
|
989
|
-
row: (int) row within the table that is to be changed
|
|
990
|
-
col: (int) col within the table that is to be changed
|
|
991
|
-
value: (float) new value for the value defined by row and col
|
|
992
|
-
|
|
993
|
-
Returns
|
|
994
|
-
-------
|
|
995
|
-
bool: True is the new value is fine (change some other values if needed) otherwise False
|
|
996
|
-
"""
|
|
997
|
-
start = self.data(self.index(row, 1), QtCore.Qt.DisplayRole)
|
|
998
|
-
stop = self.data(self.index(row, 2), QtCore.Qt.DisplayRole)
|
|
999
|
-
step = self.data(self.index(row, 3), QtCore.Qt.DisplayRole)
|
|
1000
|
-
isstep = False
|
|
1001
|
-
if col == 1: # the start
|
|
1002
|
-
start = value
|
|
1003
|
-
elif col == 2: # the stop
|
|
1004
|
-
stop = value
|
|
1005
|
-
elif col == 3: # the step
|
|
1006
|
-
isstep = True
|
|
1007
|
-
step = value
|
|
1008
|
-
|
|
1009
|
-
if np.abs(step) < 1e-12 or start == stop:
|
|
1010
|
-
return False
|
|
1011
|
-
if np.sign(stop - start) != np.sign(step):
|
|
1012
|
-
if isstep:
|
|
1013
|
-
self._data[row][2] = -stop
|
|
1014
|
-
else:
|
|
1015
|
-
self._data[row][3] = -step
|
|
1016
|
-
return True
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
def set_scan_linear(starts, stops, steps, back_and_force=False, oversteps=10000):
|
|
1020
|
-
"""
|
|
1021
|
-
Set a linear scan
|
|
1022
|
-
Parameters
|
|
1023
|
-
----------
|
|
1024
|
-
starts
|
|
1025
|
-
stops
|
|
1026
|
-
steps
|
|
1027
|
-
back_and_force: (bool) if True insert between two steps a position back to start (to be used as a reference in the scan analysis)
|
|
1028
|
-
oversteps: (int) maximum number of calculated steps (stops the steps calculation if over the first power of 2 greater than oversteps)
|
|
1029
|
-
|
|
1030
|
-
Returns
|
|
1031
|
-
-------
|
|
1032
|
-
positions (ndarray)
|
|
1033
|
-
|
|
1034
|
-
See Also
|
|
1035
|
-
--------
|
|
1036
|
-
ScanParameters
|
|
1037
|
-
"""
|
|
1038
|
-
starts = np.array(starts)
|
|
1039
|
-
stops = np.array(stops)
|
|
1040
|
-
steps = np.array(steps)
|
|
1041
|
-
|
|
1042
|
-
if np.any(np.abs(steps) < 1e-12) or \
|
|
1043
|
-
np.any(np.sign(stops - starts) != np.sign(steps)) or \
|
|
1044
|
-
np.any(starts == stops):
|
|
1045
|
-
return np.array([starts])
|
|
1046
|
-
|
|
1047
|
-
else:
|
|
1048
|
-
axis_1_unique = linspace_step(starts[0], stops[0], steps[0])
|
|
1049
|
-
len1 = len(axis_1_unique)
|
|
1050
|
-
|
|
1051
|
-
axis_2_unique = linspace_step(starts[1], stops[1], steps[1])
|
|
1052
|
-
len2 = len(axis_2_unique)
|
|
1053
|
-
# if number of steps is over oversteps, reduce both axis in the same ratio
|
|
1054
|
-
if len1 * len2 > oversteps:
|
|
1055
|
-
axis_1_unique = axis_1_unique[:int(np.ceil(np.sqrt(oversteps * len1 / len2)))]
|
|
1056
|
-
axis_2_unique = axis_2_unique[:int(np.ceil(np.sqrt(oversteps * len2 / len1)))]
|
|
1057
|
-
|
|
1058
|
-
positions = []
|
|
1059
|
-
for ind_x, pos1 in enumerate(axis_1_unique):
|
|
1060
|
-
if back_and_force:
|
|
1061
|
-
for ind_y, pos2 in enumerate(axis_2_unique):
|
|
1062
|
-
if not odd_even(ind_x):
|
|
1063
|
-
positions.append([pos1, pos2])
|
|
1064
|
-
else:
|
|
1065
|
-
positions.append([pos1, axis_2_unique[len(axis_2_unique) - ind_y - 1]])
|
|
1066
|
-
else:
|
|
1067
|
-
for ind_y, pos2 in enumerate(axis_2_unique):
|
|
1068
|
-
positions.append([pos1, pos2])
|
|
1069
|
-
|
|
1070
|
-
return np.array(positions)
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
def set_scan_random(starts, stops, steps, oversteps=10000):
|
|
1074
|
-
"""
|
|
1075
|
-
|
|
1076
|
-
Parameters
|
|
1077
|
-
----------
|
|
1078
|
-
starts
|
|
1079
|
-
stops
|
|
1080
|
-
steps
|
|
1081
|
-
oversteps
|
|
1082
|
-
|
|
1083
|
-
Returns
|
|
1084
|
-
-------
|
|
1085
|
-
|
|
1086
|
-
"""
|
|
1087
|
-
|
|
1088
|
-
positions = set_scan_linear(starts, stops, steps, back_and_force=False, oversteps=oversteps)
|
|
1089
|
-
np.random.shuffle(positions)
|
|
1090
|
-
return positions
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
def set_scan_spiral(starts, rmaxs, rsteps, nsteps=None, oversteps=10000):
|
|
1094
|
-
"""Calculate the positions to describe a spiral type scan, starting from a center position and spiraling out from it
|
|
1095
|
-
|
|
1096
|
-
Parameters
|
|
1097
|
-
----------
|
|
1098
|
-
starts: (sequence like) containing the center positions of the scan
|
|
1099
|
-
rmaxs: (sequence like) containing the maximum radius (ellipse axes) in each direction
|
|
1100
|
-
rsteps: (sequence like) containing the step size for each axis
|
|
1101
|
-
nsteps: (int) If not None, this is used together with rsteps to calculate rmaxs
|
|
1102
|
-
oversteps: (int) maximum number of calculated steps (stops the steps calculation if over the first power of 2 greater than oversteps)
|
|
1103
|
-
|
|
1104
|
-
Returns
|
|
1105
|
-
-------
|
|
1106
|
-
ndarray of all positions for each axis
|
|
1107
|
-
|
|
1108
|
-
See Also
|
|
1109
|
-
--------
|
|
1110
|
-
ScanParameters
|
|
1111
|
-
"""
|
|
1112
|
-
if np.isscalar(rmaxs):
|
|
1113
|
-
rmaxs = np.ones(starts.shape) * rmaxs
|
|
1114
|
-
else:
|
|
1115
|
-
rmaxs = np.array(rmaxs)
|
|
1116
|
-
if np.isscalar(rsteps):
|
|
1117
|
-
rsteps = np.ones(starts.shape) * rsteps
|
|
1118
|
-
else:
|
|
1119
|
-
rsteps = np.array(rsteps)
|
|
1120
|
-
|
|
1121
|
-
starts = np.array(starts)
|
|
1122
|
-
|
|
1123
|
-
if nsteps is not None:
|
|
1124
|
-
rmaxs = np.rint(nsteps / 2) * rsteps
|
|
1125
|
-
|
|
1126
|
-
if np.any(np.array(rmaxs) == 0) or np.any(np.abs(rmaxs) < 1e-12) or np.any(np.abs(rsteps) < 1e-12):
|
|
1127
|
-
positions = np.array([starts])
|
|
1128
|
-
return positions
|
|
1129
|
-
|
|
1130
|
-
ind = 0
|
|
1131
|
-
flag = True
|
|
1132
|
-
oversteps = greater2n(oversteps) # make sure the position matrix is still a square
|
|
1133
|
-
|
|
1134
|
-
Nlin = np.trunc(rmaxs / rsteps)
|
|
1135
|
-
if not np.all(Nlin == Nlin[0]):
|
|
1136
|
-
raise ScannerException(f'For Spiral 2D scans both axis should have same length, here: {Nlin.shape}')
|
|
1137
|
-
else:
|
|
1138
|
-
Nlin = Nlin[0]
|
|
1139
|
-
|
|
1140
|
-
axis_1_indexes = [0]
|
|
1141
|
-
axis_2_indexes = [0]
|
|
1142
|
-
while flag:
|
|
1143
|
-
if odd_even(ind):
|
|
1144
|
-
step = 1
|
|
1145
|
-
else:
|
|
1146
|
-
step = -1
|
|
1147
|
-
if flag:
|
|
1148
|
-
|
|
1149
|
-
for ind_step in range(ind):
|
|
1150
|
-
axis_1_indexes.append(axis_1_indexes[-1] + step)
|
|
1151
|
-
axis_2_indexes.append(axis_2_indexes[-1])
|
|
1152
|
-
if len(axis_1_indexes) >= (2 * Nlin + 1) ** 2 or len(axis_1_indexes) >= oversteps:
|
|
1153
|
-
flag = False
|
|
1154
|
-
break
|
|
1155
|
-
if flag:
|
|
1156
|
-
for ind_step in range(ind):
|
|
1157
|
-
|
|
1158
|
-
axis_1_indexes.append(axis_1_indexes[-1])
|
|
1159
|
-
axis_2_indexes.append(axis_2_indexes[-1] + step)
|
|
1160
|
-
if len(axis_1_indexes) >= (2 * Nlin + 1) ** 2 or len(axis_1_indexes) >= oversteps:
|
|
1161
|
-
flag = False
|
|
1162
|
-
break
|
|
1163
|
-
ind += 1
|
|
1164
|
-
|
|
1165
|
-
positions = []
|
|
1166
|
-
for ind in range(len(axis_1_indexes)):
|
|
1167
|
-
positions.append(np.array([axis_1_indexes[ind] * rsteps[0] + starts[0],
|
|
1168
|
-
axis_2_indexes[ind] * rsteps[1] + starts[1]]))
|
|
1169
|
-
|
|
1170
|
-
return np.array(positions)
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
def pos_above_stops(positions, steps, stops):
|
|
1174
|
-
state = []
|
|
1175
|
-
for pos, step, stop in zip(positions, steps, stops):
|
|
1176
|
-
if step >= 0:
|
|
1177
|
-
state.append(pos > stop)
|
|
1178
|
-
else:
|
|
1179
|
-
state.append(pos < stop)
|
|
1180
|
-
return state
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
def set_scan_sequential(starts, stops, steps):
|
|
1184
|
-
"""
|
|
1185
|
-
Create a list of positions (one for each actuator == one for each element in starts list) that are sequential
|
|
1186
|
-
Parameters
|
|
1187
|
-
----------
|
|
1188
|
-
starts: (sequence like)
|
|
1189
|
-
list of starts of all selected actuators
|
|
1190
|
-
stops: (sequence like)
|
|
1191
|
-
list of stops of all selected actuators
|
|
1192
|
-
steps: (sequence like)
|
|
1193
|
-
|
|
1194
|
-
Returns
|
|
1195
|
-
-------
|
|
1196
|
-
positions: (ndarray)
|
|
1197
|
-
"""
|
|
1198
|
-
|
|
1199
|
-
all_positions = [starts[:]]
|
|
1200
|
-
positions = starts[:]
|
|
1201
|
-
state = pos_above_stops(positions, steps, stops)
|
|
1202
|
-
while not state[0]:
|
|
1203
|
-
if not np.any(np.array(state)):
|
|
1204
|
-
positions[-1] += steps[-1]
|
|
1205
|
-
|
|
1206
|
-
else:
|
|
1207
|
-
indexes_true = np.where(np.array(state))
|
|
1208
|
-
positions[indexes_true[-1][0]] = starts[indexes_true[-1][0]]
|
|
1209
|
-
positions[indexes_true[-1][0] - 1] += steps[indexes_true[-1][0] - 1]
|
|
1210
|
-
|
|
1211
|
-
state = pos_above_stops(positions, steps, stops)
|
|
1212
|
-
if not np.any(np.array(state)):
|
|
1213
|
-
all_positions.append(positions[:])
|
|
1214
|
-
|
|
1215
|
-
return np.array(all_positions)
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
if __name__ == '__main__':
|
|
1219
|
-
app = QtWidgets.QApplication(sys.argv)
|
|
1220
|
-
from qtpy.QtCore import QThread
|
|
1221
|
-
from pymodaq.daq_utils.gui_utils import DockArea
|
|
1222
|
-
from pyqtgraph.dockarea import Dock
|
|
1223
|
-
from pymodaq.daq_utils.plotting.data_viewers.viewer2D import Viewer2D
|
|
1224
|
-
from pymodaq.daq_utils.plotting.navigator import Navigator
|
|
1225
|
-
from pymodaq.daq_viewer.daq_viewer_main import DAQ_Viewer
|
|
1226
|
-
|
|
1227
|
-
class UI:
|
|
1228
|
-
def __init__(self):
|
|
1229
|
-
pass
|
|
1230
|
-
|
|
1231
|
-
class FakeDaqScan:
|
|
1232
|
-
def __init__(self, area):
|
|
1233
|
-
self.area = area
|
|
1234
|
-
self.detector_modules = None
|
|
1235
|
-
self.ui = UI()
|
|
1236
|
-
self.dock = Dock('2D scan', size=(500, 300), closable=False)
|
|
1237
|
-
|
|
1238
|
-
form = QtWidgets.QWidget()
|
|
1239
|
-
self.ui.scan2D_graph = Viewer2D(form)
|
|
1240
|
-
self.dock.addWidget(form)
|
|
1241
|
-
self.area.addDock(self.dock)
|
|
1242
|
-
|
|
1243
|
-
def get_scan_params(param):
|
|
1244
|
-
print(param)
|
|
1245
|
-
print(param.scan_info.positions)
|
|
1246
|
-
|
|
1247
|
-
#
|
|
1248
|
-
# ####simple sequential scan test
|
|
1249
|
-
# prog = Scanner(actuators=['Xaxis', 'Yaxis', 'Theta Axis'])
|
|
1250
|
-
# prog.settings_tree.show()
|
|
1251
|
-
# #prog.actuators = ['xxx', 'yyy']
|
|
1252
|
-
# prog.scan_params_signal.connect(get_scan_params)
|
|
1253
|
-
|
|
1254
|
-
win = QtWidgets.QMainWindow()
|
|
1255
|
-
area = DockArea()
|
|
1256
|
-
|
|
1257
|
-
win.setCentralWidget(area)
|
|
1258
|
-
win.resize(1000, 500)
|
|
1259
|
-
win.setWindowTitle('pymodaq main')
|
|
1260
|
-
fake = FakeDaqScan(area)
|
|
1261
|
-
|
|
1262
|
-
prog = DAQ_Viewer(area, title="Testing", DAQ_type='DAQ2D', parent_scan=fake)
|
|
1263
|
-
prog.ui.IniDet_pb.click()
|
|
1264
|
-
QThread.msleep(1000)
|
|
1265
|
-
QtWidgets.QApplication.processEvents()
|
|
1266
|
-
prog2 = Navigator()
|
|
1267
|
-
widgnav = QtWidgets.QWidget()
|
|
1268
|
-
prog2 = Navigator(widgnav)
|
|
1269
|
-
nav_dock = Dock('Navigator')
|
|
1270
|
-
nav_dock.addWidget(widgnav)
|
|
1271
|
-
area.addDock(nav_dock)
|
|
1272
|
-
QThread.msleep(1000)
|
|
1273
|
-
QtWidgets.QApplication.processEvents()
|
|
1274
|
-
|
|
1275
|
-
fake.detector_modules = [prog, prog2]
|
|
1276
|
-
items = OrderedDict()
|
|
1277
|
-
items[prog.title] = dict(viewers=[view for view in prog.ui.viewers],
|
|
1278
|
-
names=[view.title for view in prog.ui.viewers],
|
|
1279
|
-
)
|
|
1280
|
-
items['Navigator'] = dict(viewers=[prog2.viewer],
|
|
1281
|
-
names=['Navigator'])
|
|
1282
|
-
items["DaqScan"] = dict(viewers=[fake.ui.scan2D_graph],
|
|
1283
|
-
names=["DaqScan"])
|
|
1284
|
-
|
|
1285
|
-
prog = Scanner(items, actuators=['Xaxis', 'Yaxis'])
|
|
1286
|
-
prog.settings_tree.show()
|
|
1287
|
-
prog.scan_params_signal.connect(get_scan_params)
|
|
1288
|
-
win.show()
|
|
1289
|
-
sys.exit(app.exec_())
|