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
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib import import_module
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
here = Path(__file__).parent.joinpath('scanners')
|
|
5
|
+
for path in here.iterdir():
|
|
6
|
+
if path.is_file():
|
|
7
|
+
import_module(f'.{path.stem}', 'pymodaq.utils.scanner.scanners')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .scanner import Scanner # import this one after the scanners because they have to first be registered
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 05/12/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from abc import ABCMeta, abstractmethod
|
|
10
|
+
from typing import Callable, Union, List, Tuple, TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
from pymodaq.utils.managers.parameter_manager import ParameterManager, Parameter
|
|
16
|
+
from pymodaq.utils.factory import ObjectFactory
|
|
17
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
18
|
+
from pymodaq.utils.data import Axis, DataDistribution
|
|
19
|
+
from pymodaq.utils.abstract import abstract_attribute
|
|
20
|
+
from pymodaq.utils import math_utils as mutils
|
|
21
|
+
from pymodaq.utils import config as configmod
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from pymodaq.control_modules.daq_move import DAQ_Move
|
|
25
|
+
from pymodaq.utils.plotting.scan_selector import Selector
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
logger = set_logger(get_module_name(__file__))
|
|
29
|
+
config = configmod.Config()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ScanParameterManager(ParameterManager):
|
|
33
|
+
settings_name = 'scanner_settings'
|
|
34
|
+
|
|
35
|
+
def __init__(self):
|
|
36
|
+
super().__init__()
|
|
37
|
+
self.settings_tree.header().setVisible(False)
|
|
38
|
+
self.settings_tree.setMinimumHeight(150)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ScannerBase(ScanParameterManager, metaclass=ABCMeta):
|
|
42
|
+
"""Abstract class for all Scanners
|
|
43
|
+
|
|
44
|
+
Attributes
|
|
45
|
+
----------
|
|
46
|
+
params: List[dict]
|
|
47
|
+
list specifying the scanner set of parameters to properly configure all the scan steps
|
|
48
|
+
positions: np.ndarray
|
|
49
|
+
ndarray of all positions. First dimension is number of actuators, second is positions of a given actuator at
|
|
50
|
+
each step
|
|
51
|
+
axes_unique: List[np.ndarray]
|
|
52
|
+
list of ndarrays representing unique values of steps for each actuator in the scan
|
|
53
|
+
axes_indexes: np.ndarray
|
|
54
|
+
ndarray of indexes from axes_unique for each value in positions
|
|
55
|
+
n_steps: int
|
|
56
|
+
Number of scan steps. Equal to the second dimension of positions
|
|
57
|
+
n_axes: int
|
|
58
|
+
Number of actuators/scan axes. Equal to the first dimension of positions
|
|
59
|
+
"""
|
|
60
|
+
params: List[dict] = abstract_attribute()
|
|
61
|
+
axes_unique: List[np.ndarray] = abstract_attribute()
|
|
62
|
+
axes_indexes: np.ndarray = abstract_attribute()
|
|
63
|
+
n_steps: int = abstract_attribute()
|
|
64
|
+
n_axes: int = abstract_attribute()
|
|
65
|
+
distribution: DataDistribution = abstract_attribute()
|
|
66
|
+
|
|
67
|
+
def __init__(self, actuators: List[DAQ_Move] = None):
|
|
68
|
+
super().__init__()
|
|
69
|
+
self.positions: np.ndarray = None
|
|
70
|
+
self.n_steps = 1
|
|
71
|
+
self._actuators: List[DAQ_Move] = None
|
|
72
|
+
|
|
73
|
+
self.actuators = actuators
|
|
74
|
+
|
|
75
|
+
self.set_settings_titles()
|
|
76
|
+
|
|
77
|
+
if self.check_steps():
|
|
78
|
+
self.set_scan()
|
|
79
|
+
|
|
80
|
+
def set_settings_titles(self):
|
|
81
|
+
"""Update the settings accordingly with the selected actuators"""
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def actuators(self):
|
|
86
|
+
return self._actuators
|
|
87
|
+
|
|
88
|
+
@actuators.setter
|
|
89
|
+
def actuators(self, actuators_name: List[DAQ_Move]):
|
|
90
|
+
self._actuators = actuators_name
|
|
91
|
+
|
|
92
|
+
def check_steps(self):
|
|
93
|
+
steps_limit = config('scan', 'steps_limit')
|
|
94
|
+
n_steps = self.evaluate_steps()
|
|
95
|
+
return n_steps <= steps_limit
|
|
96
|
+
|
|
97
|
+
def __call__(self, **kwargs):
|
|
98
|
+
return self(**kwargs)
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
def set_scan(self):
|
|
102
|
+
"""To be reimplemented. Calculations of all mandatory attributes from the settings"""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
@abstractmethod
|
|
106
|
+
def get_nav_axes(self) -> List[Axis]:
|
|
107
|
+
"""To be reimplemented. Calculations of all navigation axes from attributes"""
|
|
108
|
+
...
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def get_scan_shape(self) -> Tuple[int]:
|
|
112
|
+
"""To be reimplemented. Calculations of all the final shape of the scan"""
|
|
113
|
+
...
|
|
114
|
+
|
|
115
|
+
@abstractmethod
|
|
116
|
+
def get_indexes_from_scan_index(self, scan_index: int) -> Tuple[int]:
|
|
117
|
+
"""To be reimplemented. Calculations of indexes within the scan"""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def get_info_from_positions(self, positions: np.ndarray):
|
|
121
|
+
"""Set mandatory attributes from a ndarray of positions"""
|
|
122
|
+
if positions is not None:
|
|
123
|
+
if len(positions.shape) == 1:
|
|
124
|
+
positions = np.expand_dims(positions, 1)
|
|
125
|
+
axes_unique = []
|
|
126
|
+
for ax in positions.T:
|
|
127
|
+
axes_unique.append(np.unique(ax))
|
|
128
|
+
axes_indexes = np.zeros_like(positions, dtype=int)
|
|
129
|
+
for ind in range(positions.shape[0]):
|
|
130
|
+
for ind_pos, pos in enumerate(positions[ind]):
|
|
131
|
+
axes_indexes[ind, ind_pos] = mutils.find_index(axes_unique[ind_pos], pos)[0][0]
|
|
132
|
+
|
|
133
|
+
self.n_axes = len(axes_unique)
|
|
134
|
+
self.axes_unique = axes_unique
|
|
135
|
+
self.axes_indexes = axes_indexes
|
|
136
|
+
self.positions = positions
|
|
137
|
+
self.n_steps = positions.shape[0]
|
|
138
|
+
|
|
139
|
+
@abstractmethod
|
|
140
|
+
def evaluate_steps(self):
|
|
141
|
+
"""To be reimplemented. Quick evaluation of the current numbers of scan steps from the settings
|
|
142
|
+
"""
|
|
143
|
+
...
|
|
144
|
+
|
|
145
|
+
def update_model(self):
|
|
146
|
+
"""Method to reimplement and use for scanners using table_view types Parameters to set and apply the underlying
|
|
147
|
+
model
|
|
148
|
+
|
|
149
|
+
See Also
|
|
150
|
+
--------
|
|
151
|
+
SequentialScanner, TabularScanner, pymodaq.utils.parameter.pymodaq_ptypes.tableview
|
|
152
|
+
"""
|
|
153
|
+
...
|
|
154
|
+
|
|
155
|
+
def value_changed(self, param):
|
|
156
|
+
self.evaluate_steps()
|
|
157
|
+
|
|
158
|
+
@abstractmethod
|
|
159
|
+
def update_from_scan_selector(self, scan_selector: Selector):
|
|
160
|
+
"""To be reimplemented. Process the Selector object to set the Scanner settings
|
|
161
|
+
|
|
162
|
+
See Also
|
|
163
|
+
--------
|
|
164
|
+
Selector, ScanSelector
|
|
165
|
+
"""
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class ScannerFactory(ObjectFactory):
|
|
170
|
+
"""Factory class registering and storing Scanners"""
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def register(cls, key: str, sub_key: str = '') -> Callable:
|
|
174
|
+
def inner_wrapper(wrapped_class: Union[Callable]) -> Callable:
|
|
175
|
+
if cls.__name__ not in cls._builders:
|
|
176
|
+
cls._builders[cls.__name__] = {}
|
|
177
|
+
if key not in cls._builders[cls.__name__]:
|
|
178
|
+
cls._builders[cls.__name__][key] = {}
|
|
179
|
+
if sub_key not in cls._builders[cls.__name__][key]:
|
|
180
|
+
cls._builders[cls.__name__][key][sub_key] = wrapped_class
|
|
181
|
+
else:
|
|
182
|
+
logger.warning(f'The {cls.__name__}/{key}/{sub_key} builder is already registered. Replacing it')
|
|
183
|
+
return wrapped_class
|
|
184
|
+
|
|
185
|
+
return inner_wrapper
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def create(cls, key, sub_key, **kwargs) -> ScannerBase:
|
|
189
|
+
builder = cls._builders[cls.__name__].get(key).get(sub_key)
|
|
190
|
+
if not builder:
|
|
191
|
+
raise ValueError(key)
|
|
192
|
+
return builder(**kwargs)
|
|
193
|
+
|
|
194
|
+
def get(self, scan_type, scan_sub_type, **kwargs):
|
|
195
|
+
return self.create(scan_type, scan_sub_type, **kwargs)
|
|
196
|
+
|
|
197
|
+
def scan_types(self) -> List[str]:
|
|
198
|
+
"""Returns the list of scan types, main identifier of a given scanner"""
|
|
199
|
+
return sorted(list(self.builders[self.__class__.__name__].keys()))
|
|
200
|
+
|
|
201
|
+
def scan_sub_types(self, scan_type: str) -> List[str]:
|
|
202
|
+
"""Returns the list of scan subtypes, second identifier of a given scanner of type scan_type"""
|
|
203
|
+
return list(self.builders[self.__class__.__name__][scan_type].keys())
|
|
204
|
+
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Tuple, List, TYPE_CHECKING
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from qtpy import QtWidgets, QtCore
|
|
7
|
+
from qtpy.QtCore import QObject, Signal, Slot
|
|
8
|
+
|
|
9
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
10
|
+
from pymodaq.utils.config import Config
|
|
11
|
+
from pymodaq.utils.scanner.scan_factory import ScannerFactory, ScannerBase
|
|
12
|
+
from pymodaq.utils.managers.parameter_manager import ParameterManager, Parameter
|
|
13
|
+
import pymodaq.utils.daq_utils as utils
|
|
14
|
+
from pymodaq.utils.scanner.utils import ScanInfo
|
|
15
|
+
from pymodaq.utils.plotting.scan_selector import Selector
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from pymodaq.control_modules.daq_move import DAQ_Move
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
logger = set_logger(get_module_name(__file__))
|
|
22
|
+
config = Config()
|
|
23
|
+
scanner_factory = ScannerFactory()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Scanner(QObject, ParameterManager):
|
|
27
|
+
"""Main Object to define a PyMoDAQ scan and create a UI to set it
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
parent_widget: QtWidgets.QWidget
|
|
32
|
+
scanner_items: list of GraphicItems
|
|
33
|
+
used by ScanSelector for chosing scan area or linear traces
|
|
34
|
+
actuators: List[DAQ_Move]
|
|
35
|
+
list actuators names
|
|
36
|
+
|
|
37
|
+
See Also
|
|
38
|
+
--------
|
|
39
|
+
ScanSelector, ScannerBase, TableModelSequential, TableModelTabular, pymodaq_types.TableViewCustom
|
|
40
|
+
"""
|
|
41
|
+
scanner_updated_signal = Signal()
|
|
42
|
+
settings_name = 'scanner'
|
|
43
|
+
|
|
44
|
+
params = [
|
|
45
|
+
{'title': 'Calculate positions:', 'name': 'calculate_positions', 'type': 'action'},
|
|
46
|
+
{'title': 'N steps:', 'name': 'n_steps', 'type': 'int', 'value': 0, 'readonly': True},
|
|
47
|
+
{'title': 'Scan type:', 'name': 'scan_type', 'type': 'list', 'limits': scanner_factory.scan_types()},
|
|
48
|
+
{'title': 'Scan subtype:', 'name': 'scan_sub_type', 'type': 'list',
|
|
49
|
+
'limits': scanner_factory.scan_sub_types(scanner_factory.scan_types()[0])},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
def __init__(self, parent_widget: QtWidgets.QWidget = None, scanner_items=OrderedDict([]),
|
|
53
|
+
actuators: List[DAQ_Move] = []):
|
|
54
|
+
QObject.__init__(self)
|
|
55
|
+
ParameterManager.__init__(self)
|
|
56
|
+
if parent_widget is None:
|
|
57
|
+
parent_widget = QtWidgets.QWidget()
|
|
58
|
+
self.parent_widget = parent_widget
|
|
59
|
+
self._scanner_settings_widget = None
|
|
60
|
+
|
|
61
|
+
self.connect_things()
|
|
62
|
+
self._scanner: ScannerBase = None
|
|
63
|
+
|
|
64
|
+
self.setup_ui()
|
|
65
|
+
self.actuators = actuators
|
|
66
|
+
self.settings.child('n_steps').setValue(self._scanner.evaluate_steps())
|
|
67
|
+
|
|
68
|
+
def setup_ui(self):
|
|
69
|
+
self.parent_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
70
|
+
self.parent_widget.layout().setContentsMargins(0, 0, 0, 0)
|
|
71
|
+
self.parent_widget.layout().addWidget(self.settings_tree)
|
|
72
|
+
self._scanner_settings_widget = QtWidgets.QWidget()
|
|
73
|
+
self._scanner_settings_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
74
|
+
self._scanner_settings_widget.layout().setContentsMargins(0, 0, 0, 0)
|
|
75
|
+
self.parent_widget.layout().addWidget(self._scanner_settings_widget)
|
|
76
|
+
self.settings_tree.setMinimumHeight(110)
|
|
77
|
+
self.settings_tree.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
|
78
|
+
|
|
79
|
+
def set_scanner(self):
|
|
80
|
+
try:
|
|
81
|
+
self._scanner: ScannerBase = scanner_factory.get(self.settings['scan_type'],
|
|
82
|
+
self.settings['scan_sub_type'], actuators=self.actuators)
|
|
83
|
+
|
|
84
|
+
while True:
|
|
85
|
+
child = self._scanner_settings_widget.layout().takeAt(0)
|
|
86
|
+
if not child:
|
|
87
|
+
break
|
|
88
|
+
child.widget().deleteLater()
|
|
89
|
+
QtWidgets.QApplication.processEvents()
|
|
90
|
+
|
|
91
|
+
self._scanner_settings_widget.layout().addWidget(self._scanner.settings_tree)
|
|
92
|
+
self._scanner.settings.sigTreeStateChanged.connect(self._update_steps)
|
|
93
|
+
|
|
94
|
+
except ValueError:
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
def get_scanner_sub_settings(self):
|
|
98
|
+
"""Get the current ScannerBase implementation's settings"""
|
|
99
|
+
return self._scanner.settings
|
|
100
|
+
|
|
101
|
+
def value_changed(self, param: Parameter):
|
|
102
|
+
if param.name() == 'scan_type':
|
|
103
|
+
self.settings.child('scan_sub_type').setOpts(
|
|
104
|
+
limits=scanner_factory.scan_sub_types(param.value()))
|
|
105
|
+
if param.name() in ['scan_type', 'scan_sub_type']:
|
|
106
|
+
self.set_scanner()
|
|
107
|
+
|
|
108
|
+
self.settings.child('n_steps').setValue(self._scanner.evaluate_steps())
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def actuators(self):
|
|
112
|
+
"""list of str: Returns as a list the name of the selected actuators to describe the actual scan"""
|
|
113
|
+
return self._actuators
|
|
114
|
+
|
|
115
|
+
@actuators.setter
|
|
116
|
+
def actuators(self, act_list):
|
|
117
|
+
self._actuators = act_list
|
|
118
|
+
self.set_scanner()
|
|
119
|
+
|
|
120
|
+
def set_scan_type_and_subtypes(self, scan_type: str, scan_subtype: str):
|
|
121
|
+
"""Convenience function to set the main scan type
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
scan_type: str
|
|
126
|
+
one of registered Scanner main identifier
|
|
127
|
+
scan_subtype: list of str or None
|
|
128
|
+
one of registered Scanner second identifier for a given main identifier
|
|
129
|
+
|
|
130
|
+
See Also
|
|
131
|
+
--------
|
|
132
|
+
ScannerFactory
|
|
133
|
+
"""
|
|
134
|
+
if scan_type in scanner_factory.scan_types():
|
|
135
|
+
self.settings.child('scan_type').setValue(scan_type)
|
|
136
|
+
|
|
137
|
+
if scan_subtype is not None:
|
|
138
|
+
if scan_subtype in scanner_factory.scan_sub_types(scan_type):
|
|
139
|
+
self.settings.child('scan_sub_type').setValue(scan_subtype)
|
|
140
|
+
|
|
141
|
+
def set_scan_from_settings(self, settings: Parameter, scanner_settings: Parameter):
|
|
142
|
+
|
|
143
|
+
self.set_scan_type_and_subtypes(settings['scan_type'],
|
|
144
|
+
settings['scan_sub_type'])
|
|
145
|
+
self.settings.restoreState(settings.saveState())
|
|
146
|
+
self._scanner.settings.restoreState(scanner_settings.saveState())
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def scan_type(self) -> str:
|
|
150
|
+
return self.settings['scan_type']
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def scan_sub_type(self) -> str:
|
|
154
|
+
return self.settings['scan_sub_type']
|
|
155
|
+
|
|
156
|
+
def connect_things(self):
|
|
157
|
+
self.settings.child('calculate_positions').sigActivated.connect(self.set_scan)
|
|
158
|
+
|
|
159
|
+
def get_scan_info(self) -> ScanInfo:
|
|
160
|
+
"""Get a summary of the configured scan as a ScanInfo object"""
|
|
161
|
+
return ScanInfo(self._scanner.n_steps, positions=self._scanner.positions,
|
|
162
|
+
axes_indexes=self._scanner.axes_indexes, axes_unique=self._scanner.axes_unique,
|
|
163
|
+
selected_actuators=[act.title for act in self.actuators])
|
|
164
|
+
|
|
165
|
+
def get_nav_axes(self):
|
|
166
|
+
return self._scanner.get_nav_axes()
|
|
167
|
+
|
|
168
|
+
def get_scan_shape(self):
|
|
169
|
+
return self._scanner.get_scan_shape()
|
|
170
|
+
|
|
171
|
+
def get_indexes_from_scan_index(self, scan_index: int) -> Tuple[int]:
|
|
172
|
+
"""To be reimplemented. Calculations of indexes within the scan"""
|
|
173
|
+
return self._scanner.get_indexes_from_scan_index(scan_index)
|
|
174
|
+
|
|
175
|
+
def _update_steps(self):
|
|
176
|
+
self.settings.child('n_steps').setValue(self.n_steps)
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def n_steps(self):
|
|
180
|
+
return self._scanner.evaluate_steps()
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def n_axes(self):
|
|
184
|
+
return self._scanner.n_axes
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def positions(self):
|
|
188
|
+
return self._scanner.positions
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def axes_indexes(self):
|
|
192
|
+
return self._scanner.axes_indexes
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def axes_unique(self):
|
|
196
|
+
return self._scanner.axes_unique
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def distribution(self):
|
|
200
|
+
return self._scanner.distribution
|
|
201
|
+
|
|
202
|
+
def set_scan(self):
|
|
203
|
+
"""Process the settings options to calculate the scan positions
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
bool: True if the processed number of steps if **higher** than the configured number of steps
|
|
208
|
+
"""
|
|
209
|
+
oversteps = config('scan', 'steps_limit')
|
|
210
|
+
if self._scanner.evaluate_steps() > oversteps:
|
|
211
|
+
return True
|
|
212
|
+
self._scanner.set_scan()
|
|
213
|
+
self.settings.child('n_steps').setValue(self.n_steps)
|
|
214
|
+
self.scanner_updated_signal.emit()
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
def update_from_scan_selector(self, scan_selector: Selector):
|
|
218
|
+
self._scanner.update_from_scan_selector(scan_selector)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def main():
|
|
222
|
+
from pymodaq.utils.parameter import ParameterTree
|
|
223
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
224
|
+
|
|
225
|
+
class MoveMock:
|
|
226
|
+
def __init__(self, ind: int = 0):
|
|
227
|
+
self.title = f'act_{ind}'
|
|
228
|
+
self.units = f'units_{ind}'
|
|
229
|
+
|
|
230
|
+
actuators = [MoveMock(ind) for ind in range(3)]
|
|
231
|
+
|
|
232
|
+
params = [{'title': 'Actuators', 'name': 'actuators', 'type': 'itemselect',
|
|
233
|
+
'value': dict(all_items=[act.title for act in actuators], selected=[])},
|
|
234
|
+
{'title': 'Set Scan', 'name': 'set_scan', 'type': 'action'},
|
|
235
|
+
]
|
|
236
|
+
settings = Parameter.create(name='settings', type='group', children=params)
|
|
237
|
+
settings_tree = ParameterTree()
|
|
238
|
+
settings_tree.setParameters(settings)
|
|
239
|
+
|
|
240
|
+
widget_main = QtWidgets.QWidget()
|
|
241
|
+
widget_main.setLayout(QtWidgets.QVBoxLayout())
|
|
242
|
+
widget_scanner = QtWidgets.QWidget()
|
|
243
|
+
widget_main.layout().addWidget(settings_tree)
|
|
244
|
+
widget_main.layout().addWidget(widget_scanner)
|
|
245
|
+
scanner = Scanner(widget_scanner, actuators=actuators)
|
|
246
|
+
|
|
247
|
+
def update_actuators(param):
|
|
248
|
+
scanner.actuators = [utils.find_objects_in_list_from_attr_name_val(actuators, 'title', act_str,
|
|
249
|
+
return_first=True)[0]
|
|
250
|
+
for act_str in param.value()['selected']]
|
|
251
|
+
|
|
252
|
+
def print_info():
|
|
253
|
+
print('info:')
|
|
254
|
+
print(scanner.get_scan_info())
|
|
255
|
+
print('positions:')
|
|
256
|
+
print(scanner.positions)
|
|
257
|
+
print('nav:')
|
|
258
|
+
print(scanner.get_nav_axes())
|
|
259
|
+
|
|
260
|
+
settings.child('actuators').sigValueChanged.connect(update_actuators)
|
|
261
|
+
settings.child('set_scan').sigActivated.connect(scanner.set_scan)
|
|
262
|
+
scanner.scanner_updated_signal.connect(print_info)
|
|
263
|
+
widget_main.show()
|
|
264
|
+
sys.exit(app.exec_())
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
if __name__ == '__main__':
|
|
268
|
+
import sys
|
|
269
|
+
from qtpy import QtWidgets
|
|
270
|
+
main()
|
|
271
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 05/12/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
from typing import List, Tuple
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from pymodaq.utils.data import Axis, DataDistribution
|
|
11
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
12
|
+
from pymodaq.utils import math_utils as mutils
|
|
13
|
+
from pymodaq.utils import config as configmod
|
|
14
|
+
from pymodaq.utils.plotting.scan_selector import Selector
|
|
15
|
+
|
|
16
|
+
from ..scan_factory import ScannerFactory, ScannerBase, ScanParameterManager
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
logger = set_logger(get_module_name(__file__))
|
|
20
|
+
config = configmod.Config()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@ScannerFactory.register('Scan1D', 'Linear')
|
|
24
|
+
class Scan1DLinear(ScannerBase):
|
|
25
|
+
params = [
|
|
26
|
+
{'title': 'Start:', 'name': 'start', 'type': 'float', 'value': config('scan', 'scan1D', 'start')},
|
|
27
|
+
{'title': 'Stop:', 'name': 'stop', 'type': 'float', 'value': config('scan', 'scan1D', 'stop')},
|
|
28
|
+
{'title': 'Step:', 'name': 'step', 'type': 'float', 'value': config('scan', 'scan1D', 'step')}
|
|
29
|
+
]
|
|
30
|
+
n_axes = 1
|
|
31
|
+
distribution = DataDistribution['uniform']
|
|
32
|
+
|
|
33
|
+
def __init__(self, actuators: List = None, **_ignored):
|
|
34
|
+
ScannerBase.__init__(self, actuators=actuators)
|
|
35
|
+
|
|
36
|
+
def set_scan(self):
|
|
37
|
+
self.positions = mutils.linspace_step(self.settings['start'], self.settings['stop'],
|
|
38
|
+
self.settings['step'])
|
|
39
|
+
self.get_info_from_positions(self.positions)
|
|
40
|
+
|
|
41
|
+
def set_settings_titles(self):
|
|
42
|
+
if len(self.actuators) == 1:
|
|
43
|
+
self.settings.child('start').setOpts(title=f'{self.actuators[0].title} start:')
|
|
44
|
+
self.settings.child('stop').setOpts(title=f'{self.actuators[0].title} stop:')
|
|
45
|
+
self.settings.child('step').setOpts(title=f'{self.actuators[0].title} step:')
|
|
46
|
+
|
|
47
|
+
def evaluate_steps(self) -> int:
|
|
48
|
+
n_steps = int(np.abs((self.settings['stop'] - self.settings['start']) / self.settings['step']) + 1)
|
|
49
|
+
return n_steps
|
|
50
|
+
|
|
51
|
+
def get_nav_axes(self) -> List[Axis]:
|
|
52
|
+
return [Axis(label=f'{self.actuators[0].title}',
|
|
53
|
+
units=f'{self.actuators[0].units}',
|
|
54
|
+
data=np.squeeze(self.positions))]
|
|
55
|
+
|
|
56
|
+
def get_scan_shape(self) -> Tuple[int]:
|
|
57
|
+
return len(self.positions),
|
|
58
|
+
|
|
59
|
+
def get_indexes_from_scan_index(self, scan_index: int) -> Tuple[int]:
|
|
60
|
+
"""To be reimplemented. Calculations of indexes within the scan"""
|
|
61
|
+
return tuple(self.axes_indexes[scan_index])
|
|
62
|
+
|
|
63
|
+
def update_from_scan_selector(self, scan_selector: Selector):
|
|
64
|
+
coordinates = scan_selector.get_coordinates()
|
|
65
|
+
if coordinates.shape == (2, 2) or coordinates.shape == (2, 1):
|
|
66
|
+
self.settings.child('start').setValue(coordinates[0, 0])
|
|
67
|
+
self.settings.child('stop').setValue(coordinates[1, 0])
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@ScannerFactory.register('Scan1D', 'Random')
|
|
71
|
+
class Scan1DRandom(Scan1DLinear):
|
|
72
|
+
def __init__(self, actuators: List = None, **_ignored):
|
|
73
|
+
super().__init__(actuators=actuators)
|
|
74
|
+
|
|
75
|
+
def set_scan(self):
|
|
76
|
+
self.positions = mutils.linspace_step(self.settings['start'], self.settings['stop'],
|
|
77
|
+
self.settings['step'])
|
|
78
|
+
np.random.shuffle(self.positions)
|
|
79
|
+
self.get_info_from_positions(self.positions)
|
|
80
|
+
self.set_settings_titles()
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
import adaptive
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@ScannerFactory.register('Scan1D', 'Adaptive')
|
|
87
|
+
class Scan1DAdaptive(Scan1DLinear):
|
|
88
|
+
params = [
|
|
89
|
+
{'title': 'Loss type', 'name': 'scan_loss', 'type': 'list',
|
|
90
|
+
'limits': ['default', 'curvature', 'uniform'], 'tip': 'Type of loss used by the algo. to determine next points'},
|
|
91
|
+
{'title': 'Start:', 'name': 'start', 'type': 'float', 'value': config('scan', 'scan1D', 'start')},
|
|
92
|
+
{'title': 'Stop:', 'name': 'stop', 'type': 'float', 'value': config('scan', 'scan1D', 'stop')},
|
|
93
|
+
]
|
|
94
|
+
distribution = DataDistribution['spread']
|
|
95
|
+
|
|
96
|
+
def __init__(self, actuators: List = None, **_ignored):
|
|
97
|
+
super().__init__(actuators=actuators)
|
|
98
|
+
|
|
99
|
+
def set_scan(self):
|
|
100
|
+
self.axes_unique = [np.array([])]
|
|
101
|
+
self.axes_indexes = np.array([], dtype=int)
|
|
102
|
+
self.positions = np.array([self.settings['start'], self.settings['stop']])
|
|
103
|
+
|
|
104
|
+
def evaluate_steps(self) -> int:
|
|
105
|
+
return 1
|
|
106
|
+
|
|
107
|
+
def get_nav_axes(self) -> List[Axis]:
|
|
108
|
+
return [Axis(label=f'{self.actuators[0].mod_name} axis',
|
|
109
|
+
units=f'{self.actuators[0].units}',
|
|
110
|
+
data=self.positions[0])]
|
|
111
|
+
|
|
112
|
+
def get_scan_shape(self) -> Tuple[int]:
|
|
113
|
+
return len(self.positions),
|
|
114
|
+
|
|
115
|
+
except ModuleNotFoundError:
|
|
116
|
+
logger.info('adaptive module is not present, no adaptive scan possible')
|
|
117
|
+
|