pymodaq 3.6.12__py3-none-any.whl → 4.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- 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.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.12.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 -671
- 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.12.dist-info/METADATA +0 -39
- pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.12.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.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,7 +1,970 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""
|
|
3
|
-
Created the
|
|
3
|
+
Created the 29/07/2022
|
|
4
4
|
|
|
5
5
|
@author: Sebastien Weber
|
|
6
6
|
"""
|
|
7
|
-
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from qtpy.QtCore import QObject, Signal, QThread, Slot, Qt, QTimer
|
|
10
|
+
from qtpy import QtWidgets
|
|
11
|
+
|
|
12
|
+
from easydict import EasyDict as edict
|
|
13
|
+
|
|
14
|
+
from pymodaq.utils.logger import set_logger, get_module_name, get_module_name
|
|
15
|
+
from pymodaq.control_modules.utils import ControlModule
|
|
16
|
+
from pymodaq.utils.parameter import ioxml
|
|
17
|
+
from pymodaq.control_modules.daq_move_ui import DAQ_Move_UI, ThreadCommand
|
|
18
|
+
from pymodaq.utils.managers.parameter_manager import ParameterManager, Parameter
|
|
19
|
+
from pymodaq.control_modules.move_utility_classes import MoveCommand
|
|
20
|
+
from pymodaq.utils.tcp_server_client import TCPClient
|
|
21
|
+
from pymodaq.control_modules.move_utility_classes import params as daq_move_params
|
|
22
|
+
from pymodaq.utils import daq_utils as utils
|
|
23
|
+
from pymodaq.utils.parameter import utils as putils
|
|
24
|
+
from pymodaq.utils.gui_utils import get_splash_sc
|
|
25
|
+
from pymodaq.utils import config
|
|
26
|
+
from pymodaq.utils.exceptions import ActuatorError
|
|
27
|
+
from pymodaq.utils.messenger import deprecation_msg
|
|
28
|
+
from pymodaq.utils.h5modules import module_saving
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
local_path = config.get_set_local_dir()
|
|
32
|
+
sys.path.append(local_path)
|
|
33
|
+
logger = set_logger(get_module_name(__file__))
|
|
34
|
+
DAQ_Move_Actuators = utils.get_plugins('daq_move')
|
|
35
|
+
ACTUATOR_TYPES = [mov['name'] for mov in DAQ_Move_Actuators]
|
|
36
|
+
|
|
37
|
+
STATUS_WAIT_TIME = 1000
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DAQ_Move(ParameterManager, ControlModule):
|
|
41
|
+
""" Main PyMoDAQ class to drive actuators
|
|
42
|
+
|
|
43
|
+
Qt object and generic UI to drive actuators.
|
|
44
|
+
|
|
45
|
+
Attributes
|
|
46
|
+
----------
|
|
47
|
+
init_signal: Signal[bool]
|
|
48
|
+
This signal is emitted when the chosen actuator is correctly initialized
|
|
49
|
+
move_done_signal: Signal[str, float]
|
|
50
|
+
This signal is emitted when the chosen actuator finished its action. It gives the actuator's name and current
|
|
51
|
+
value
|
|
52
|
+
bounds_signal: Signal[bool]
|
|
53
|
+
This signal is emitted when the actuator reached defined limited boundaries.
|
|
54
|
+
|
|
55
|
+
See Also
|
|
56
|
+
--------
|
|
57
|
+
:class:`ControlModule`, :class:`ParameterManager`
|
|
58
|
+
"""
|
|
59
|
+
settings_name = 'daq_move_settings'
|
|
60
|
+
|
|
61
|
+
move_done_signal = Signal(str, float)
|
|
62
|
+
_current_value_signal = Signal(str, float)
|
|
63
|
+
# to be used in external program to make sure the move has been done,
|
|
64
|
+
# export the current position. str refer to the unique title given to the module
|
|
65
|
+
_update_settings_signal = Signal(edict)
|
|
66
|
+
bounds_signal = Signal(bool)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
params = daq_move_params
|
|
70
|
+
|
|
71
|
+
def __init__(self, parent=None, title="DAQ Move"):
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
parent: QWidget or None
|
|
77
|
+
parent: QWidget or None
|
|
78
|
+
if it is a valid QWidget, it will hold the user interface to drive it
|
|
79
|
+
title: str
|
|
80
|
+
The unique (should be unique) string identifier for the underlying actuator
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
self.logger = set_logger(f'{logger.name}.{title}')
|
|
84
|
+
self.logger.info(f'Initializing DAQ_Move: {title}')
|
|
85
|
+
|
|
86
|
+
QObject.__init__(self)
|
|
87
|
+
ParameterManager.__init__(self)
|
|
88
|
+
ControlModule.__init__(self)
|
|
89
|
+
|
|
90
|
+
self.parent = parent
|
|
91
|
+
if parent is not None:
|
|
92
|
+
self.ui = DAQ_Move_UI(parent, title)
|
|
93
|
+
else:
|
|
94
|
+
self.ui = None
|
|
95
|
+
|
|
96
|
+
if self.ui is not None:
|
|
97
|
+
self.ui.actuators = ACTUATOR_TYPES
|
|
98
|
+
self.ui.set_settings_tree(self.settings_tree)
|
|
99
|
+
self.ui.command_sig.connect(self.process_ui_cmds)
|
|
100
|
+
|
|
101
|
+
self.splash_sc = get_splash_sc()
|
|
102
|
+
self._title = title
|
|
103
|
+
if len(ACTUATOR_TYPES) > 0: # will be 0 if no valid plugins are installed
|
|
104
|
+
self.actuator = ACTUATOR_TYPES[0]
|
|
105
|
+
|
|
106
|
+
self.module_and_data_saver = module_saving.ActuatorSaver(self)
|
|
107
|
+
|
|
108
|
+
self._move_done_bool = True
|
|
109
|
+
|
|
110
|
+
self._current_value = 0.
|
|
111
|
+
self._target_value = 0.
|
|
112
|
+
self._relative_value = 0.
|
|
113
|
+
|
|
114
|
+
self._refresh_timer = QTimer()
|
|
115
|
+
self._refresh_timer.timeout.connect(self.get_actuator_value)
|
|
116
|
+
|
|
117
|
+
def process_ui_cmds(self, cmd: utils.ThreadCommand):
|
|
118
|
+
"""Process commands sent by actions done in the ui
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
cmd: ThreadCommand
|
|
123
|
+
Possible values are :
|
|
124
|
+
* init
|
|
125
|
+
* quit
|
|
126
|
+
* get_value
|
|
127
|
+
* loop_get_value
|
|
128
|
+
* find_home
|
|
129
|
+
* stop
|
|
130
|
+
* move_abs
|
|
131
|
+
* move_rel
|
|
132
|
+
* show_log
|
|
133
|
+
* actuator_changed
|
|
134
|
+
* rel_value
|
|
135
|
+
"""
|
|
136
|
+
if cmd.command == 'init':
|
|
137
|
+
self.init_hardware(cmd.attribute[0])
|
|
138
|
+
elif cmd.command == 'quit':
|
|
139
|
+
self.quit_fun()
|
|
140
|
+
elif cmd.command == 'get_value':
|
|
141
|
+
self.get_actuator_value()
|
|
142
|
+
elif cmd.command == 'loop_get_value':
|
|
143
|
+
self.get_continuous_actuator_value(cmd.attribute)
|
|
144
|
+
elif cmd.command == 'find_home':
|
|
145
|
+
self.move_home()
|
|
146
|
+
elif cmd.command == 'stop':
|
|
147
|
+
self.stop_motion()
|
|
148
|
+
elif cmd.command == 'move_abs':
|
|
149
|
+
self.move_abs(cmd.attribute)
|
|
150
|
+
elif cmd.command == 'move_rel':
|
|
151
|
+
self.move_rel(cmd.attribute)
|
|
152
|
+
elif cmd.command == 'show_log':
|
|
153
|
+
self.show_log()
|
|
154
|
+
elif cmd.command == 'actuator_changed':
|
|
155
|
+
self.actuator = cmd.attribute
|
|
156
|
+
elif cmd.command == 'rel_value':
|
|
157
|
+
self._relative_value = cmd.attribute
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def stop_motion(self):
|
|
161
|
+
"""Stop any motion
|
|
162
|
+
"""
|
|
163
|
+
try:
|
|
164
|
+
self.command_hardware.emit(ThreadCommand(command="stop_motion"))
|
|
165
|
+
except Exception as e:
|
|
166
|
+
self.logger.exception(str(e))
|
|
167
|
+
|
|
168
|
+
def move(self, move_command: MoveCommand):
|
|
169
|
+
"""Generic method to trigger the correct action on the actuator
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
move_command: MoveCommand
|
|
174
|
+
MoveCommand with move_type attribute either:
|
|
175
|
+
* 'abs': performs an absolute action
|
|
176
|
+
* 'rel': performs a relative action
|
|
177
|
+
* 'home': find the actuator's home
|
|
178
|
+
|
|
179
|
+
See Also
|
|
180
|
+
--------
|
|
181
|
+
:meth:`move_abs`, :meth:`move_rel`, :meth:`move_home`, :class:`..utility_classes.MoveCommand`
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
if move_command.move_type == 'abs':
|
|
185
|
+
self.move_abs(move_command.value)
|
|
186
|
+
elif move_command.move_type == 'rel':
|
|
187
|
+
self.move_rel(move_command.value)
|
|
188
|
+
elif move_command.move_type == 'home':
|
|
189
|
+
self.move_home(move_command.value)
|
|
190
|
+
|
|
191
|
+
def move_Abs(self, value, send_to_tcpip=False):
|
|
192
|
+
deprecation_msg(f'The method *move_Abs* should not be used anymore, use *move_abs*')
|
|
193
|
+
self.move_abs(value, send_to_tcpip=send_to_tcpip)
|
|
194
|
+
|
|
195
|
+
def move_abs(self, value, send_to_tcpip=False):
|
|
196
|
+
"""Move the connected hardware to the absolute value
|
|
197
|
+
|
|
198
|
+
Returns nothing but the move_done_signal will be send once the action is done
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
value: float
|
|
203
|
+
The value the actuator should reach
|
|
204
|
+
send_to_tcpip: bool
|
|
205
|
+
if True, this position is send through the TCP/IP communication canal
|
|
206
|
+
"""
|
|
207
|
+
try:
|
|
208
|
+
self._send_to_tcpip = send_to_tcpip
|
|
209
|
+
if not value == self._current_value:
|
|
210
|
+
if self.ui is not None:
|
|
211
|
+
self.ui.move_done = False
|
|
212
|
+
self._move_done_bool = False
|
|
213
|
+
self._target_value = value
|
|
214
|
+
self.update_status("Moving")
|
|
215
|
+
self.command_hardware.emit(ThreadCommand(command="reset_stop_motion"))
|
|
216
|
+
self.command_hardware.emit(ThreadCommand(command="move_abs", attribute=[value]))
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
self.logger.exception(str(e))
|
|
220
|
+
|
|
221
|
+
def move_Home(self, send_to_tcpip=False):
|
|
222
|
+
self.move_home(send_to_tcpip)
|
|
223
|
+
deprecation_msg(f'The method *move_Home* is deprecated, use *move_home*')
|
|
224
|
+
|
|
225
|
+
def move_home(self, send_to_tcpip=False):
|
|
226
|
+
"""Move the connected actuator to its home value (if any)
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
send_to_tcpip: bool
|
|
231
|
+
if True, this position is send through the TCP/IP communication canal
|
|
232
|
+
"""
|
|
233
|
+
self._send_to_tcpip = send_to_tcpip
|
|
234
|
+
try:
|
|
235
|
+
if self.ui is not None:
|
|
236
|
+
self.ui.move_done = False
|
|
237
|
+
self._move_done_bool = False
|
|
238
|
+
self.update_status("Moving")
|
|
239
|
+
self.command_hardware.emit(ThreadCommand(command="reset_stop_motion"))
|
|
240
|
+
self.command_hardware.emit(ThreadCommand(command="move_Home"))
|
|
241
|
+
|
|
242
|
+
except Exception as e:
|
|
243
|
+
self.logger.exception(str(e))
|
|
244
|
+
|
|
245
|
+
def move_Rel(self, rel_value, send_to_tcpip=False):
|
|
246
|
+
deprecation_msg(f'The method *move_Rel* should not be used anymore, use *move_rel*')
|
|
247
|
+
self.move_rel(rel_value, send_to_tcpip=send_to_tcpip)
|
|
248
|
+
|
|
249
|
+
def move_rel(self, rel_value, send_to_tcpip=False):
|
|
250
|
+
"""Move the connected hardware to the relative value
|
|
251
|
+
|
|
252
|
+
Returns nothing but the move_done_signal will be send once the action is done
|
|
253
|
+
|
|
254
|
+
Parameters
|
|
255
|
+
----------
|
|
256
|
+
value: float
|
|
257
|
+
The relative value the actuator should reach
|
|
258
|
+
send_to_tcpip: bool
|
|
259
|
+
if True, this position is send through the TCP/IP communication canal
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
self._send_to_tcpip = send_to_tcpip
|
|
264
|
+
if self.ui is not None:
|
|
265
|
+
self.ui.move_done = False
|
|
266
|
+
self._move_done_bool = False
|
|
267
|
+
self._target_value = self._current_value + rel_value
|
|
268
|
+
self.update_status("Moving")
|
|
269
|
+
self.command_hardware.emit(ThreadCommand(command="reset_stop_motion"))
|
|
270
|
+
self.command_hardware.emit(ThreadCommand(command="move_rel", attribute=[rel_value]))
|
|
271
|
+
|
|
272
|
+
except Exception as e:
|
|
273
|
+
self.logger.exception(str(e))
|
|
274
|
+
|
|
275
|
+
def move_Rel_p(self):
|
|
276
|
+
deprecation_msg(f'The method *move_Rel_p* should not be used anymore, use *move_rel_p*')
|
|
277
|
+
self.move_rel_p()
|
|
278
|
+
|
|
279
|
+
def move_Rel_m(self):
|
|
280
|
+
deprecation_msg(f'The method *move_Rel_m* should not be used anymore, use *move_rel_m*')
|
|
281
|
+
self.move_rel_m()
|
|
282
|
+
|
|
283
|
+
def move_rel_p(self):
|
|
284
|
+
self.move_rel(self._relative_value)
|
|
285
|
+
|
|
286
|
+
def move_rel_m(self):
|
|
287
|
+
self.move_rel(-self._relative_value)
|
|
288
|
+
|
|
289
|
+
def quit_fun(self):
|
|
290
|
+
"""Programmatic quitting of the current instance of DAQ_Move
|
|
291
|
+
|
|
292
|
+
Des-init the actuator then close the UI parent widget
|
|
293
|
+
"""
|
|
294
|
+
# insert anything that needs to be closed before leaving
|
|
295
|
+
|
|
296
|
+
if self._initialized_state:
|
|
297
|
+
self.init_hardware(False)
|
|
298
|
+
if self.ui is not None:
|
|
299
|
+
self.ui.get_action('quit').trigger()
|
|
300
|
+
self.quit_signal.emit()
|
|
301
|
+
|
|
302
|
+
def ini_stage_fun(self):
|
|
303
|
+
deprecation_msg(f'The function *ini_stage_fun* is deprecated, use init_hardware')
|
|
304
|
+
self.init_hardware(True)
|
|
305
|
+
|
|
306
|
+
def init_hardware_ui(self, do_init=True):
|
|
307
|
+
"""Programmatic actuator's Initialization
|
|
308
|
+
|
|
309
|
+
Programmatic way to simulate a click on the init button of the UI to initialize the communication with the
|
|
310
|
+
hardware
|
|
311
|
+
|
|
312
|
+
Parameters
|
|
313
|
+
----------
|
|
314
|
+
do_init: bool
|
|
315
|
+
if the init or des-init should be performed
|
|
316
|
+
"""
|
|
317
|
+
self.ui.do_init(do_init)
|
|
318
|
+
|
|
319
|
+
def init_hardware(self, do_init=True):
|
|
320
|
+
|
|
321
|
+
if not do_init:
|
|
322
|
+
try:
|
|
323
|
+
self.command_hardware.emit(ThreadCommand(command="close"))
|
|
324
|
+
if self.ui is not None:
|
|
325
|
+
self.ui.actuator_init = False
|
|
326
|
+
except Exception as e:
|
|
327
|
+
self.logger.exception(str(e))
|
|
328
|
+
else:
|
|
329
|
+
try:
|
|
330
|
+
hardware = DAQ_Move_Hardware(self._actuator_type, self._current_value, self._title)
|
|
331
|
+
self._hardware_thread = QThread()
|
|
332
|
+
hardware.moveToThread(self._hardware_thread)
|
|
333
|
+
|
|
334
|
+
self.command_hardware[ThreadCommand].connect(hardware.queue_command)
|
|
335
|
+
hardware.status_sig[ThreadCommand].connect(self.thread_status)
|
|
336
|
+
self._update_settings_signal[edict].connect(hardware.update_settings)
|
|
337
|
+
|
|
338
|
+
self._hardware_thread.hardware = hardware
|
|
339
|
+
self._hardware_thread.start()
|
|
340
|
+
self.command_hardware.emit(
|
|
341
|
+
ThreadCommand(command="ini_stage", attribute=[self.settings.child(('move_settings')).saveState(),
|
|
342
|
+
self.controller]))
|
|
343
|
+
except Exception as e:
|
|
344
|
+
self.logger.exception(str(e))
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def initialized_state(self):
|
|
348
|
+
"""bool: status of the actuator's initialization (init or not)"""
|
|
349
|
+
return self._initialized_state
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def move_done_bool(self):
|
|
353
|
+
"""bool: status of the actuator's action (done or not)"""
|
|
354
|
+
return self._move_done_bool
|
|
355
|
+
|
|
356
|
+
def value_changed(self, param):
|
|
357
|
+
if param.name() == 'connect_server':
|
|
358
|
+
if param.value():
|
|
359
|
+
self.connect_tcp_ip()
|
|
360
|
+
else:
|
|
361
|
+
self._command_tcpip.emit(ThreadCommand('quit', ))
|
|
362
|
+
|
|
363
|
+
elif param.name() == 'ip_address' or param.name == 'port':
|
|
364
|
+
self._command_tcpip.emit(
|
|
365
|
+
ThreadCommand('update_connection', dict(ipaddress=self.settings.child('main_settings', 'tcpip',
|
|
366
|
+
'ip_address').value(),
|
|
367
|
+
port=self.settings.child('main_settings', 'tcpip',
|
|
368
|
+
'port').value())))
|
|
369
|
+
elif param.name() == 'refresh_timeout':
|
|
370
|
+
self._refresh_timer.setInterval(param.value())
|
|
371
|
+
|
|
372
|
+
path = self.settings.childPath(param)
|
|
373
|
+
if path is not None:
|
|
374
|
+
if 'main_settings' not in path:
|
|
375
|
+
self._update_settings_signal.emit(edict(path=path, param=param, change='value'))
|
|
376
|
+
if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value():
|
|
377
|
+
self._command_tcpip.emit(ThreadCommand('send_info', dict(path=path, param=param)))
|
|
378
|
+
|
|
379
|
+
def param_deleted(self, param):
|
|
380
|
+
if param.name() not in putils.iter_children(self.settings.child('main_settings'), []):
|
|
381
|
+
self._update_settings_signal.emit(edict(path=['move_settings'], param=param, change='parent'))
|
|
382
|
+
|
|
383
|
+
def child_added(self, param, data):
|
|
384
|
+
path = self.settings.childPath(param)
|
|
385
|
+
if 'main_settings' not in path:
|
|
386
|
+
self._update_settings_signal.emit(edict(path=path, param=data[0].saveState(), change='childAdded'))
|
|
387
|
+
|
|
388
|
+
@Slot()
|
|
389
|
+
def raise_timeout(self):
|
|
390
|
+
"""Update status with "Timeout occurred" statement and change the timeout flag.
|
|
391
|
+
"""
|
|
392
|
+
self.update_status("Timeout occurred")
|
|
393
|
+
self.wait_position_flag = False
|
|
394
|
+
|
|
395
|
+
@Slot(ThreadCommand)
|
|
396
|
+
def thread_status(self, status): # general function to get datas/infos from all threads back to the main
|
|
397
|
+
"""
|
|
398
|
+
| General function to get datas/infos from all threads back to the main0
|
|
399
|
+
|
|
|
400
|
+
|
|
401
|
+
Interpret a command from the command given by the ThreadCommand status :
|
|
402
|
+
* In case of **'Update_status'** command, call the update_status method with status attribute as parameters
|
|
403
|
+
* In case of **'ini_stage'** command, initialise a Stage from status attribute
|
|
404
|
+
* In case of **'close'** command, close the launched stage thread
|
|
405
|
+
* In case of **'check_position'** command, set the current_value value from status attribute
|
|
406
|
+
* In case of **'move_done'** command, set the current_value value, make profile of move_done and send the move done signal with status attribute
|
|
407
|
+
* In case of **'Move_Not_Done'** command, set the current position value from the status attribute, make profile of Not_move_done and send the Thread Command "move_abs"
|
|
408
|
+
* In case of **'update_settings'** command, create child "Move Settings" from status attribute (if possible)
|
|
409
|
+
|
|
410
|
+
================ ================= ======================================================
|
|
411
|
+
**Parameters** **Type** **Description**
|
|
412
|
+
|
|
413
|
+
*status* ThreadCommand() instance of ThreadCommand containing two attribute :
|
|
414
|
+
|
|
415
|
+
* *command* str
|
|
416
|
+
* *attribute* list
|
|
417
|
+
|
|
418
|
+
================ ================= ======================================================
|
|
419
|
+
|
|
420
|
+
See Also
|
|
421
|
+
--------
|
|
422
|
+
update_status, set_enabled_move_buttons, get_actuator_value, DAQ_utils.ThreadCommand, parameter_tree_changed, raise_timeout
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
if status.command == "Update_Status":
|
|
426
|
+
if len(status.attribute) > 2:
|
|
427
|
+
self.update_status(status.attribute[0], log=status.attribute[1])
|
|
428
|
+
else:
|
|
429
|
+
self.update_status(status.attribute[0])
|
|
430
|
+
|
|
431
|
+
elif status.command == "ini_stage":
|
|
432
|
+
# status.attribute[0]=edict(initialized=bool,info="", controller=)
|
|
433
|
+
self.update_status("Stage initialized: {:} info: {:}".format(status.attribute[0]['initialized'],
|
|
434
|
+
status.attribute[0]['info']))
|
|
435
|
+
if status.attribute[0]['initialized']:
|
|
436
|
+
self.controller = status.attribute[0]['controller']
|
|
437
|
+
if self.ui is not None:
|
|
438
|
+
self.ui.actuator_init = True
|
|
439
|
+
self._initialized_state = True
|
|
440
|
+
else:
|
|
441
|
+
self._initialized_state = False
|
|
442
|
+
if self._initialized_state:
|
|
443
|
+
self.get_actuator_value()
|
|
444
|
+
self.init_signal.emit(self._initialized_state)
|
|
445
|
+
|
|
446
|
+
elif status.command == "close":
|
|
447
|
+
try:
|
|
448
|
+
self.update_status(status.attribute[0])
|
|
449
|
+
self._hardware_thread.exit()
|
|
450
|
+
self._hardware_thread.wait()
|
|
451
|
+
finished = self._hardware_thread.isFinished()
|
|
452
|
+
if finished:
|
|
453
|
+
pass
|
|
454
|
+
delattr(self, 'hardware_thread')
|
|
455
|
+
else:
|
|
456
|
+
self.update_status('thread is locked?!', STATUS_WAIT_TIME, 'log')
|
|
457
|
+
except Exception as e:
|
|
458
|
+
self.logger.exception(str(e))
|
|
459
|
+
self._initialized_state = False
|
|
460
|
+
self.init_signal.emit(self._initialized_state)
|
|
461
|
+
|
|
462
|
+
elif status.command == "get_actuator_value" or status.command == 'check_position':
|
|
463
|
+
if self.ui is not None:
|
|
464
|
+
self.ui.display_value(status.attribute[0])
|
|
465
|
+
self._current_value = status.attribute[0]
|
|
466
|
+
self._current_value_signal.emit(self.title, self._current_value)
|
|
467
|
+
if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value() and self._send_to_tcpip:
|
|
468
|
+
self._command_tcpip.emit(ThreadCommand('position_is', status.attribute))
|
|
469
|
+
|
|
470
|
+
elif status.command == "move_done":
|
|
471
|
+
if self.ui is not None:
|
|
472
|
+
self.ui.display_value(status.attribute[0])
|
|
473
|
+
self.ui.move_done = True
|
|
474
|
+
self._current_value = status.attribute[0]
|
|
475
|
+
self._move_done_bool = True
|
|
476
|
+
self.move_done_signal.emit(self._title, status.attribute[0])
|
|
477
|
+
if self.settings.child('main_settings', 'tcpip', 'tcp_connected').value() and self._send_to_tcpip:
|
|
478
|
+
self._command_tcpip.emit(ThreadCommand('move_done', status.attribute))
|
|
479
|
+
|
|
480
|
+
elif status.command == "Move_Not_Done":
|
|
481
|
+
if self.ui is not None:
|
|
482
|
+
self.ui.display_value(status.attribute[0])
|
|
483
|
+
self.ui.move_done = False
|
|
484
|
+
|
|
485
|
+
self._current_value = status.attribute[0]
|
|
486
|
+
self._move_done_bool = False
|
|
487
|
+
self.command_hardware.emit(ThreadCommand(command="move_abs", attribute=[self._target_value]))
|
|
488
|
+
|
|
489
|
+
elif status.command == 'update_main_settings':
|
|
490
|
+
# this is a way for the plugins to update main settings of the ui (solely values, limits and options)
|
|
491
|
+
try:
|
|
492
|
+
if status.attribute[2] == 'value':
|
|
493
|
+
self.settings.child('main_settings', *status.attribute[0]).setValue(status.attribute[1])
|
|
494
|
+
elif status.attribute[2] == 'limits':
|
|
495
|
+
self.settings.child('main_settings', *status.attribute[0]).setLimits(status.attribute[1])
|
|
496
|
+
elif status.attribute[2] == 'options':
|
|
497
|
+
self.settings.child('main_settings', *status.attribute[0]).setOpts(**status.attribute[1])
|
|
498
|
+
except Exception as e:
|
|
499
|
+
self.logger.exception(str(e))
|
|
500
|
+
|
|
501
|
+
elif status.command == 'update_settings':
|
|
502
|
+
# ThreadCommand(command='update_settings',attribute=[path,data,change]))
|
|
503
|
+
try:
|
|
504
|
+
self.settings.sigTreeStateChanged.disconnect(
|
|
505
|
+
self.parameter_tree_changed) # any changes on the settings will update accordingly the detector
|
|
506
|
+
except Exception:
|
|
507
|
+
pass
|
|
508
|
+
try:
|
|
509
|
+
if status.attribute[2] == 'value':
|
|
510
|
+
self.settings.child('move_settings', *status.attribute[0]).setValue(status.attribute[1])
|
|
511
|
+
elif status.attribute[2] == 'limits':
|
|
512
|
+
self.settings.child('move_settings', *status.attribute[0]).setLimits(status.attribute[1])
|
|
513
|
+
elif status.attribute[2] == 'options':
|
|
514
|
+
self.settings.child('move_settings', *status.attribute[0]).setOpts(**status.attribute[1])
|
|
515
|
+
elif status.attribute[2] == 'childAdded':
|
|
516
|
+
child = Parameter.create(name='tmp')
|
|
517
|
+
child.restoreState(status.attribute[1][0])
|
|
518
|
+
self.settings.child('move_settings', *status.attribute[0]).addChild(status.attribute[1][0])
|
|
519
|
+
|
|
520
|
+
except Exception as e:
|
|
521
|
+
self.logger.exception(str(e))
|
|
522
|
+
self.settings.sigTreeStateChanged.connect(
|
|
523
|
+
self.parameter_tree_changed) # any changes on the settings will update accordingly the detector
|
|
524
|
+
|
|
525
|
+
elif status.command == 'raise_timeout':
|
|
526
|
+
self.raise_timeout()
|
|
527
|
+
|
|
528
|
+
elif status.command == 'outofbounds':
|
|
529
|
+
self.bounds_signal.emit(True)
|
|
530
|
+
|
|
531
|
+
elif status.command == 'show_splash':
|
|
532
|
+
self.settings_tree.setEnabled(False)
|
|
533
|
+
self.splash_sc.show()
|
|
534
|
+
self.splash_sc.raise_()
|
|
535
|
+
self.splash_sc.showMessage(status.attribute[0], color=Qt.white)
|
|
536
|
+
|
|
537
|
+
elif status.command == 'close_splash':
|
|
538
|
+
self.splash_sc.close()
|
|
539
|
+
self.settings_tree.setEnabled(True)
|
|
540
|
+
|
|
541
|
+
elif status.command == 'set_allowed_values':
|
|
542
|
+
if self.ui is not None:
|
|
543
|
+
self.ui.set_spinbox_properties(**status.attribute)
|
|
544
|
+
|
|
545
|
+
def get_position(self):
|
|
546
|
+
deprecation_msg(f'This method is deprecated , please use `get_actuator_value`')
|
|
547
|
+
self.get_actuator_value()
|
|
548
|
+
|
|
549
|
+
def get_actuator_value(self):
|
|
550
|
+
"""Get the current actuator value via the "get_actuator_value" command send to the hardware
|
|
551
|
+
|
|
552
|
+
Returns nothing but the `move_done_signal` will be send once the action is done
|
|
553
|
+
"""
|
|
554
|
+
try:
|
|
555
|
+
self.command_hardware.emit(ThreadCommand(command="get_actuator_value"))
|
|
556
|
+
|
|
557
|
+
except Exception as e:
|
|
558
|
+
self.logger.exception(str(e))
|
|
559
|
+
|
|
560
|
+
def grab(self):
|
|
561
|
+
if self.ui is not None:
|
|
562
|
+
self.manage_ui_actions('refresh_value', 'setChecked', 'False')
|
|
563
|
+
self.get_continuous_actuator_value(False)
|
|
564
|
+
|
|
565
|
+
def stop_grab(self):
|
|
566
|
+
"""Stop value polling. Mandatory
|
|
567
|
+
|
|
568
|
+
First uncheck the ui action if ui is not None, then stop the polling
|
|
569
|
+
"""
|
|
570
|
+
if self.ui is not None:
|
|
571
|
+
self.manage_ui_actions('refresh_value', 'setChecked', 'False')
|
|
572
|
+
self.get_continuous_actuator_value(False)
|
|
573
|
+
|
|
574
|
+
def get_continuous_actuator_value(self, get_value=True):
|
|
575
|
+
"""Start the continuous getting of the actuator's value
|
|
576
|
+
|
|
577
|
+
Parameters
|
|
578
|
+
----------
|
|
579
|
+
get_value: bool
|
|
580
|
+
if True start the timer to periodically fetch the actuator's value, else stop it
|
|
581
|
+
|
|
582
|
+
Notes
|
|
583
|
+
-----
|
|
584
|
+
The current timer period is set by the refresh value *'refresh_timeout'* in the actuator main settings.
|
|
585
|
+
"""
|
|
586
|
+
if get_value:
|
|
587
|
+
self._refresh_timer.setInterval(self.settings['main_settings', 'refresh_timeout'])
|
|
588
|
+
self._refresh_timer.start()
|
|
589
|
+
else:
|
|
590
|
+
self._refresh_timer.stop()
|
|
591
|
+
|
|
592
|
+
@property
|
|
593
|
+
def actuator(self):
|
|
594
|
+
"""str: the selected actuator's type
|
|
595
|
+
|
|
596
|
+
Returns
|
|
597
|
+
-------
|
|
598
|
+
|
|
599
|
+
"""
|
|
600
|
+
return self._actuator_type
|
|
601
|
+
|
|
602
|
+
@actuator.setter
|
|
603
|
+
def actuator(self, act_type):
|
|
604
|
+
if act_type in ACTUATOR_TYPES:
|
|
605
|
+
self._actuator_type = act_type
|
|
606
|
+
if self.ui is not None:
|
|
607
|
+
self.ui.actuator = act_type
|
|
608
|
+
self.update_settings()
|
|
609
|
+
else:
|
|
610
|
+
raise ActuatorError(f'{act_type} is an invalid actuator, should be within {ACTUATOR_TYPES}')
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def units(self):
|
|
614
|
+
return self.settings['move_settings', 'units']
|
|
615
|
+
|
|
616
|
+
def update_settings(self):
|
|
617
|
+
|
|
618
|
+
self.settings.child('main_settings', 'move_type').setValue(self._actuator_type)
|
|
619
|
+
self.settings.child('main_settings', 'module_name').setValue(self._title)
|
|
620
|
+
try:
|
|
621
|
+
for child in self.settings.child('move_settings').children():
|
|
622
|
+
child.remove()
|
|
623
|
+
parent_module = utils.find_dict_in_list_from_key_val(DAQ_Move_Actuators, 'name', self._actuator_type)
|
|
624
|
+
class_ = getattr(getattr(parent_module['module'], 'daq_move_' + self._actuator_type),
|
|
625
|
+
'DAQ_Move_' + self._actuator_type)
|
|
626
|
+
params = getattr(class_, 'params')
|
|
627
|
+
move_params = Parameter.create(name='move_settings', type='group', children=params)
|
|
628
|
+
|
|
629
|
+
self.settings.child('move_settings').addChildren(move_params.children())
|
|
630
|
+
|
|
631
|
+
except Exception as e:
|
|
632
|
+
self.logger.exception(str(e))
|
|
633
|
+
|
|
634
|
+
def connect_tcp_ip(self):
|
|
635
|
+
if self.settings.child('main_settings', 'tcpip', 'connect_server').value():
|
|
636
|
+
self._tcpclient_thread = QThread()
|
|
637
|
+
|
|
638
|
+
tcpclient = TCPClient(self.settings.child('main_settings', 'tcpip', 'ip_address').value(),
|
|
639
|
+
self.settings.child('main_settings', 'tcpip', 'port').value(),
|
|
640
|
+
self.settings.child('move_settings'), client_type="ACTUATOR")
|
|
641
|
+
tcpclient.moveToThread(self._tcpclient_thread)
|
|
642
|
+
self._tcpclient_thread.tcpclient = tcpclient
|
|
643
|
+
tcpclient.cmd_signal.connect(self.process_tcpip_cmds)
|
|
644
|
+
|
|
645
|
+
self._command_tcpip[ThreadCommand].connect(tcpclient.queue_command)
|
|
646
|
+
|
|
647
|
+
self._tcpclient_thread.start()
|
|
648
|
+
tcpclient.init_connection()
|
|
649
|
+
|
|
650
|
+
@Slot(ThreadCommand)
|
|
651
|
+
def process_tcpip_cmds(self, status):
|
|
652
|
+
if 'move_abs' in status.command:
|
|
653
|
+
self.move_abs(status.attribute[0], send_to_tcpip=True)
|
|
654
|
+
|
|
655
|
+
elif 'move_rel' in status.command:
|
|
656
|
+
self.move_rel(status.attribute[0], send_to_tcpip=True)
|
|
657
|
+
|
|
658
|
+
elif 'move_home' in status.command:
|
|
659
|
+
self.move_home(send_to_tcpip=True)
|
|
660
|
+
|
|
661
|
+
elif 'check_position' in status.command:
|
|
662
|
+
deprecation_msg('check_position is deprecated, you should use get_actuator_value')
|
|
663
|
+
self._send_to_tcpip = True
|
|
664
|
+
self.command_hardware.emit(ThreadCommand('get_actuator_value', ))
|
|
665
|
+
|
|
666
|
+
elif 'get_actuator_value' in status.command:
|
|
667
|
+
self._send_to_tcpip = True
|
|
668
|
+
self.command_hardware.emit(ThreadCommand('get_actuator_value', ))
|
|
669
|
+
|
|
670
|
+
elif status.command == 'connected':
|
|
671
|
+
self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(True)
|
|
672
|
+
|
|
673
|
+
elif status.command == 'disconnected':
|
|
674
|
+
self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(False)
|
|
675
|
+
|
|
676
|
+
elif status.command == 'Update_Status':
|
|
677
|
+
self.thread_status(status)
|
|
678
|
+
|
|
679
|
+
elif status.command == 'set_info':
|
|
680
|
+
param_dict = ioxml.XML_string_to_parameter(status.attribute[1])[0]
|
|
681
|
+
param_tmp = Parameter.create(**param_dict)
|
|
682
|
+
param = self.settings.child('move_settings', *status.attribute[0][1:])
|
|
683
|
+
|
|
684
|
+
param.restoreState(param_tmp.saveState())
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class DAQ_Move_Hardware(QObject):
|
|
688
|
+
"""
|
|
689
|
+
================== ========================
|
|
690
|
+
**Attributes** **Type**
|
|
691
|
+
*status_sig* instance of Signal
|
|
692
|
+
*hardware* ???
|
|
693
|
+
*actuator_type* string
|
|
694
|
+
*current_position* float
|
|
695
|
+
*target_value* float
|
|
696
|
+
*hardware_adress* string
|
|
697
|
+
*axis_address* string
|
|
698
|
+
*motion_stoped* boolean
|
|
699
|
+
================== ========================
|
|
700
|
+
"""
|
|
701
|
+
status_sig = Signal(ThreadCommand)
|
|
702
|
+
|
|
703
|
+
def __init__(self, actuator_type, position, title='actuator'):
|
|
704
|
+
super().__init__()
|
|
705
|
+
self.logger = set_logger(f'{logger.name}.{title}.actuator')
|
|
706
|
+
self._title = title
|
|
707
|
+
self.hardware = None
|
|
708
|
+
self.actuator_type = actuator_type
|
|
709
|
+
self.current_position = position
|
|
710
|
+
self._target_value = 0
|
|
711
|
+
self.hardware_adress = None
|
|
712
|
+
self.axis_address = None
|
|
713
|
+
self.motion_stoped = False
|
|
714
|
+
|
|
715
|
+
def close(self):
|
|
716
|
+
"""
|
|
717
|
+
Uninitialize the stage closing the hardware.
|
|
718
|
+
|
|
719
|
+
"""
|
|
720
|
+
self.hardware.close()
|
|
721
|
+
|
|
722
|
+
return "Stage uninitialized"
|
|
723
|
+
|
|
724
|
+
def get_actuator_value(self):
|
|
725
|
+
"""Get the current position checking the hardware value.
|
|
726
|
+
"""
|
|
727
|
+
pos = self.hardware.get_actuator_value()
|
|
728
|
+
return pos
|
|
729
|
+
|
|
730
|
+
def check_position(self):
|
|
731
|
+
"""Get the current position checking the hardware position (deprecated)
|
|
732
|
+
"""
|
|
733
|
+
deprecation_msg('check_position is deprecated, use get_actuator_value')
|
|
734
|
+
pos = self.hardware.get_actuator_value()
|
|
735
|
+
return pos
|
|
736
|
+
|
|
737
|
+
def ini_stage(self, params_state=None, controller=None):
|
|
738
|
+
"""
|
|
739
|
+
Init a stage updating the hardware and sending an hardware move_done signal.
|
|
740
|
+
|
|
741
|
+
=============== =================================== ==========================================================================================================================
|
|
742
|
+
**Parameters** **Type** **Description**
|
|
743
|
+
|
|
744
|
+
*params_state* ordered dictionnary list The parameter state of the hardware class composed by a list representing the tree to keep a temporary save of the tree
|
|
745
|
+
|
|
746
|
+
*controller* one or many instance of DAQ_Move The controller id of the hardware
|
|
747
|
+
|
|
748
|
+
*stage* instance of DAQ_Move Defining axes and motors
|
|
749
|
+
=============== =================================== ==========================================================================================================================
|
|
750
|
+
|
|
751
|
+
See Also
|
|
752
|
+
--------
|
|
753
|
+
DAQ_utils.ThreadCommand, DAQ_Move
|
|
754
|
+
"""
|
|
755
|
+
|
|
756
|
+
status = edict(initialized=False, info="")
|
|
757
|
+
try:
|
|
758
|
+
parent_module = utils.find_dict_in_list_from_key_val(DAQ_Move_Actuators, 'name', self.actuator_type)
|
|
759
|
+
class_ = getattr(getattr(parent_module['module'], 'daq_move_' + self.actuator_type),
|
|
760
|
+
'DAQ_Move_' + self.actuator_type)
|
|
761
|
+
self.hardware = class_(self, params_state)
|
|
762
|
+
try:
|
|
763
|
+
infos = self.hardware.ini_stage(controller) # return edict(info="", controller=, stage=)
|
|
764
|
+
except Exception as e:
|
|
765
|
+
logger.exception('Hardware couldn\'t be initialized' + str(e))
|
|
766
|
+
infos = str(e), False
|
|
767
|
+
|
|
768
|
+
if isinstance(infos, edict): # following old plugin templating
|
|
769
|
+
status.update(infos)
|
|
770
|
+
deprecation_msg('Returns from init_stage should now be a string and a boolean,'
|
|
771
|
+
' see pymodaq_plugins_template', stacklevel=3)
|
|
772
|
+
else:
|
|
773
|
+
status.info = infos[0]
|
|
774
|
+
status.initialized = infos[1]
|
|
775
|
+
status.controller = self.hardware.controller
|
|
776
|
+
self.hardware.move_done_signal.connect(self.move_done)
|
|
777
|
+
|
|
778
|
+
return status
|
|
779
|
+
except Exception as e:
|
|
780
|
+
self.logger.exception(str(e))
|
|
781
|
+
return status
|
|
782
|
+
|
|
783
|
+
def move_abs(self, position, polling=True):
|
|
784
|
+
"""
|
|
785
|
+
Make the hardware absolute move from the given position.
|
|
786
|
+
|
|
787
|
+
=============== ========= =======================
|
|
788
|
+
**Parameters** **Type** **Description**
|
|
789
|
+
|
|
790
|
+
*position* float The absolute position
|
|
791
|
+
=============== ========= =======================
|
|
792
|
+
|
|
793
|
+
See Also
|
|
794
|
+
--------
|
|
795
|
+
move_Abs
|
|
796
|
+
"""
|
|
797
|
+
position = float(position) # because it may be a numpy float and could cause issues
|
|
798
|
+
# see https://github.com/pythonnet/pythonnet/issues/1833
|
|
799
|
+
self._target_value = position
|
|
800
|
+
self.hardware.move_is_done = False
|
|
801
|
+
self.hardware.ispolling = polling
|
|
802
|
+
pos = self.hardware.move_abs(position)
|
|
803
|
+
self.hardware.poll_moving()
|
|
804
|
+
|
|
805
|
+
def move_rel(self, rel_position, polling=True):
|
|
806
|
+
"""
|
|
807
|
+
Make the hardware relative move from the given relative position added to the current one.
|
|
808
|
+
|
|
809
|
+
================ ========= ======================
|
|
810
|
+
**Parameters** **Type** **Description**
|
|
811
|
+
|
|
812
|
+
*position* float The relative position
|
|
813
|
+
================ ========= ======================
|
|
814
|
+
|
|
815
|
+
See Also
|
|
816
|
+
--------
|
|
817
|
+
move_Rel
|
|
818
|
+
"""
|
|
819
|
+
rel_position = float(rel_position) # because it may be a numpy float and could cause issues
|
|
820
|
+
# see https://github.com/pythonnet/pythonnet/issues/1833
|
|
821
|
+
self.hardware.move_is_done = False
|
|
822
|
+
self._target_value = self.current_position + rel_position
|
|
823
|
+
self.hardware.ispolling = polling
|
|
824
|
+
pos = self.hardware.move_rel(rel_position)
|
|
825
|
+
self.hardware.poll_moving()
|
|
826
|
+
|
|
827
|
+
@Slot(float)
|
|
828
|
+
def Move_Stoped(self, pos):
|
|
829
|
+
"""
|
|
830
|
+
Send a "move_done" Thread Command with the given position as an attribute.
|
|
831
|
+
|
|
832
|
+
See Also
|
|
833
|
+
--------
|
|
834
|
+
DAQ_utils.ThreadCommand
|
|
835
|
+
"""
|
|
836
|
+
self.status_sig.emit(ThreadCommand("move_done", [pos]))
|
|
837
|
+
|
|
838
|
+
def move_home(self):
|
|
839
|
+
"""
|
|
840
|
+
Make the hardware move to the init position.
|
|
841
|
+
|
|
842
|
+
"""
|
|
843
|
+
self.hardware.move_is_done = False
|
|
844
|
+
self._target_value = 0
|
|
845
|
+
self.hardware.move_home()
|
|
846
|
+
|
|
847
|
+
@Slot(float)
|
|
848
|
+
def move_done(self, pos):
|
|
849
|
+
"""Send the move_done signal back to the main class
|
|
850
|
+
"""
|
|
851
|
+
self._current_value = pos
|
|
852
|
+
self.status_sig.emit(ThreadCommand(command="move_done", attribute=[pos]))
|
|
853
|
+
|
|
854
|
+
@Slot(ThreadCommand)
|
|
855
|
+
def queue_command(self, command: ThreadCommand):
|
|
856
|
+
"""Interpret command send by DAQ_Move class
|
|
857
|
+
* In case of **'ini_stage'** command, init a stage from command attribute.
|
|
858
|
+
* In case of **'close'** command, unitinalise the stage closing hardware and emitting the corresponding status signal
|
|
859
|
+
* In case of **'move_abs'** command, call the move_Abs method with position from command attribute
|
|
860
|
+
* In case of **'move_rel'** command, call the move_Rel method with the relative position from the command attribute.
|
|
861
|
+
* In case of **'move_home'** command, call the move_Home method
|
|
862
|
+
* In case of **'get_actuator_value'** command, get the current position from the check_position method
|
|
863
|
+
* In case of **'Stop_motion'** command, stop any motion via the stop_Motion method
|
|
864
|
+
* In case of **'reset_stop_motion'** command, set the motion_stopped attribute to false
|
|
865
|
+
|
|
866
|
+
Parameters
|
|
867
|
+
----------
|
|
868
|
+
command: ThreadCommand
|
|
869
|
+
Possible commands are:
|
|
870
|
+
* **'ini_stage'** command, init a stage from command attribute.
|
|
871
|
+
* **'close'** command, unitinalise the stage closing hardware and emitting the corresponding status signal
|
|
872
|
+
* **'move_abs'** command, call the move_abs method with position from command attribute
|
|
873
|
+
* **'move_rel'** command, call the move_rel method with the relative position from the command attribute.
|
|
874
|
+
* **'move_home'** command, call the move_home method
|
|
875
|
+
* **'get_actuator_value'** command, get the current position from the check_position method
|
|
876
|
+
* **'stop_motion'** command, stop any motion via the stop_Motion method
|
|
877
|
+
* **'reset_stop_motion'** command, set the motion_stopped attribute to false
|
|
878
|
+
"""
|
|
879
|
+
try:
|
|
880
|
+
if command.command == "ini_stage":
|
|
881
|
+
status = self.ini_stage(
|
|
882
|
+
*command.attribute) # return edict(initialized=bool,info="", controller=, stage=)
|
|
883
|
+
self.status_sig.emit(ThreadCommand(command=command.command, attribute=[status, 'log']))
|
|
884
|
+
|
|
885
|
+
elif command.command == "close":
|
|
886
|
+
status = self.close()
|
|
887
|
+
self.status_sig.emit(ThreadCommand(command=command.command, attribute=[status]))
|
|
888
|
+
|
|
889
|
+
elif command.command == "move_abs":
|
|
890
|
+
self.move_abs(*command.attribute)
|
|
891
|
+
|
|
892
|
+
elif command.command == "move_rel":
|
|
893
|
+
self.move_rel(*command.attribute)
|
|
894
|
+
|
|
895
|
+
elif command.command == "move_home":
|
|
896
|
+
self.move_home()
|
|
897
|
+
|
|
898
|
+
elif command.command == "get_actuator_value":
|
|
899
|
+
pos = self.get_actuator_value()
|
|
900
|
+
self.status_sig.emit(ThreadCommand('get_actuator_value', [pos]))
|
|
901
|
+
|
|
902
|
+
elif command.command == "stop_motion":
|
|
903
|
+
self.stop_motion()
|
|
904
|
+
|
|
905
|
+
elif command.command == "reset_stop_motion":
|
|
906
|
+
self.motion_stoped = False
|
|
907
|
+
|
|
908
|
+
else: # custom commands for particular plugins (see spectrometer module 'get_spectro_wl' for instance)
|
|
909
|
+
if hasattr(self.hardware, command.command):
|
|
910
|
+
cmd = getattr(self.hardware, command.command)
|
|
911
|
+
cmd(*command.attribute)
|
|
912
|
+
except Exception as e:
|
|
913
|
+
self.logger.exception(str(e))
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
def stop_motion(self):
|
|
917
|
+
"""
|
|
918
|
+
stop hardware motion with motion_stopped attribute updtaed to True and a status signal sended with an "update_status" Thread Command
|
|
919
|
+
|
|
920
|
+
See Also
|
|
921
|
+
--------
|
|
922
|
+
DAQ_utils.ThreadCommand, stop_motion
|
|
923
|
+
"""
|
|
924
|
+
self.status_sig.emit(ThreadCommand(command="Update_Status", attribute=["Motion stoping", 'log']))
|
|
925
|
+
self.motion_stoped = True
|
|
926
|
+
self.hardware.stop_motion()
|
|
927
|
+
self.hardware.poll_timer.stop()
|
|
928
|
+
|
|
929
|
+
@Slot(edict)
|
|
930
|
+
def update_settings(self, settings_parameter_dict):
|
|
931
|
+
"""
|
|
932
|
+
Update settings of hardware with dictionnary parameters in case of "Move_Settings" path, else update attribute with dictionnary parameters.
|
|
933
|
+
|
|
934
|
+
========================= =========== ======================================================
|
|
935
|
+
**Parameters** **Type** **Description**
|
|
936
|
+
|
|
937
|
+
*settings_parameter_dict* dictionnary Dictionnary containing the path and linked parameter
|
|
938
|
+
========================= =========== ======================================================
|
|
939
|
+
|
|
940
|
+
See Also
|
|
941
|
+
--------
|
|
942
|
+
update_settings
|
|
943
|
+
"""
|
|
944
|
+
# settings_parameter_dict = edict(path=path,param=param)
|
|
945
|
+
path = settings_parameter_dict['path']
|
|
946
|
+
param = settings_parameter_dict['param']
|
|
947
|
+
if path[0] == 'main_settings':
|
|
948
|
+
if hasattr(self, path[-1]):
|
|
949
|
+
setattr(self, path[-1], param.value())
|
|
950
|
+
|
|
951
|
+
elif path[0] == 'move_settings':
|
|
952
|
+
self.hardware.update_settings(settings_parameter_dict)
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
def main(init_qt=True):
|
|
956
|
+
if init_qt: # used for the test suite
|
|
957
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
958
|
+
|
|
959
|
+
widget = QtWidgets.QWidget()
|
|
960
|
+
prog = DAQ_Move(widget, title="test")
|
|
961
|
+
widget.show()
|
|
962
|
+
|
|
963
|
+
if init_qt:
|
|
964
|
+
sys.exit(app.exec_())
|
|
965
|
+
return prog, widget
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
if __name__ == '__main__':
|
|
969
|
+
main()
|
|
970
|
+
|