pymodaq 5.1.6__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.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -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 +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
+
<Project Type="Project" LVVersion="16008000">
|
|
3
|
+
<Item Name="My Computer" Type="My Computer">
|
|
4
|
+
<Property Name="server.app.propertiesEnabled" Type="Bool">true</Property>
|
|
5
|
+
<Property Name="server.control.propertiesEnabled" Type="Bool">true</Property>
|
|
6
|
+
<Property Name="server.tcp.enabled" Type="Bool">false</Property>
|
|
7
|
+
<Property Name="server.tcp.port" Type="Int">0</Property>
|
|
8
|
+
<Property Name="server.tcp.serviceName" Type="Str">My Computer/VI Server</Property>
|
|
9
|
+
<Property Name="server.tcp.serviceName.default" Type="Str">My Computer/VI Server</Property>
|
|
10
|
+
<Property Name="server.vi.callsEnabled" Type="Bool">true</Property>
|
|
11
|
+
<Property Name="server.vi.propertiesEnabled" Type="Bool">true</Property>
|
|
12
|
+
<Property Name="specify.custom.address" Type="Bool">false</Property>
|
|
13
|
+
<Item Name="controls" Type="Folder">
|
|
14
|
+
<Item Name="client_state.ctl" Type="VI" URL="../client_state.ctl"/>
|
|
15
|
+
<Item Name="cmd_types.ctl" Type="VI" URL="../cmd_types.ctl"/>
|
|
16
|
+
</Item>
|
|
17
|
+
<Item Name="subvis" Type="Folder">
|
|
18
|
+
<Item Name="DAQ_TCP_read_cmd.vi" Type="VI" URL="../DAQ_TCP_read_cmd.vi"/>
|
|
19
|
+
<Item Name="DAQ_TCP_read_float.vi" Type="VI" URL="../DAQ_TCP_read_float.vi"/>
|
|
20
|
+
<Item Name="DAQ_TCP_read_int.vi" Type="VI" URL="../DAQ_TCP_read_int.vi"/>
|
|
21
|
+
<Item Name="DAQ_TCP_send_data.vi" Type="VI" URL="../DAQ_TCP_send_data.vi"/>
|
|
22
|
+
<Item Name="DAQ_TCP_send_int.vi" Type="VI" URL="../DAQ_TCP_send_int.vi"/>
|
|
23
|
+
<Item Name="DAQ_TCP_send_scalar.vi" Type="VI" URL="../DAQ_TCP_send_scalar.vi"/>
|
|
24
|
+
<Item Name="DAQ_TCP_send_string.vi" Type="VI" URL="../DAQ_TCP_send_string.vi"/>
|
|
25
|
+
<Item Name="DAQ_TCP_Server_1Dgaussian.vi" Type="VI" URL="../DAQ_TCP_Server_1Dgaussian.vi"/>
|
|
26
|
+
<Item Name="DAQ_TCP_Server_2Dgaussian.vi" Type="VI" URL="../DAQ_TCP_Server_2Dgaussian.vi"/>
|
|
27
|
+
</Item>
|
|
28
|
+
<Item Name="DAQ_TCP_Client.vi" Type="VI" URL="../DAQ_TCP_Client.vi"/>
|
|
29
|
+
<Item Name="Dependencies" Type="Dependencies"/>
|
|
30
|
+
<Item Name="Build Specifications" Type="Build"/>
|
|
31
|
+
</Item>
|
|
32
|
+
</Project>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 27/06/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from qtpy import QtWidgets
|
|
10
|
+
from qtpy.QtCore import Slot, QDate, QThread, QTimer
|
|
11
|
+
|
|
12
|
+
from pymodaq.utils import data as data_mod
|
|
13
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
14
|
+
from pymodaq_gui.utils.custom_app import CustomApp
|
|
15
|
+
from pymodaq_gui.utils.dock import DockArea, Dock
|
|
16
|
+
from pymodaq_data.data import DataRaw, Axis
|
|
17
|
+
from pymodaq_utils.config import Config
|
|
18
|
+
|
|
19
|
+
from pymodaq_gui.plotting.data_viewers.viewer1D import Viewer1D
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
config = Config()
|
|
23
|
+
logger = set_logger(get_module_name(__file__))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class FunctionPlotter(CustomApp):
|
|
27
|
+
|
|
28
|
+
# list of dicts enabling the settings tree on the user interface
|
|
29
|
+
params = [
|
|
30
|
+
{'title': 'Save base path:', 'name': 'base_path', 'type': 'browsepath',
|
|
31
|
+
'value': config('data_saving', 'h5file', 'save_path')},
|
|
32
|
+
{'title': 'File name:', 'name': 'target_filename', 'type': 'str', 'value': "", 'readonly': True},
|
|
33
|
+
{'title': 'Date:', 'name': 'date', 'type': 'date', 'value': QDate.currentDate()},
|
|
34
|
+
|
|
35
|
+
{'title': 'Functions:', 'name': 'functions', 'type': 'list',
|
|
36
|
+
'limits': ['exp(-(x/5)**2)', 'sin(x)', 'arctan(x)']},
|
|
37
|
+
{'title': 'Function:', 'name': 'function', 'type': 'str', 'value': 'sinc(x)'},
|
|
38
|
+
{'title': 'Add function:', 'label': 'Add!', 'name': 'add_function', 'type': 'bool_push', 'value': False},
|
|
39
|
+
{'title': 'Plot refresh (ms):', 'name': 'plot_refresh', 'type': 'int', 'value': 2000},
|
|
40
|
+
{'title': 'Xaxis:', 'name': 'xaxis', 'type': 'group', 'children': [
|
|
41
|
+
{'title': 'Npts:', 'name': 'npoints', 'type': 'int', 'value': 200},
|
|
42
|
+
{'title': 'Xstart:', 'name': 'xstart', 'type': 'float', 'value': -10},
|
|
43
|
+
{'title': 'Xstop:', 'name': 'xstop', 'type': 'int', 'value': 10},
|
|
44
|
+
]}
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
def __init__(self, dockarea):
|
|
48
|
+
super().__init__(dockarea)
|
|
49
|
+
|
|
50
|
+
# init the object parameters
|
|
51
|
+
self.raw_data = []
|
|
52
|
+
self.setup_ui() # will trigger:
|
|
53
|
+
# self.setup_docks()
|
|
54
|
+
# self.setup_actions() # see ActionManager MixIn class
|
|
55
|
+
# self.setup_menu()
|
|
56
|
+
# self.connect_things()
|
|
57
|
+
self.timer = QTimer()
|
|
58
|
+
self.timer.setInterval(self.settings['plot_refresh'])
|
|
59
|
+
self.timer.timeout.connect(self.plot_timer)
|
|
60
|
+
|
|
61
|
+
self.ind_plot = 0
|
|
62
|
+
|
|
63
|
+
def setup_docks(self):
|
|
64
|
+
"""
|
|
65
|
+
subclass method from CustomApp
|
|
66
|
+
"""
|
|
67
|
+
logger.debug('setting docks')
|
|
68
|
+
self.dock_settings = Dock('Settings', size=(350, 350))
|
|
69
|
+
self.dockarea.addDock(self.dock_settings, 'left')
|
|
70
|
+
self.dock_settings.addWidget(self.settings_tree, 10)
|
|
71
|
+
# settings_tree is an inherited property of the ParameterManager base class
|
|
72
|
+
|
|
73
|
+
# create a dock containing a viewer object
|
|
74
|
+
dock_viewer = Dock('Viewer dock', size=(350, 350))
|
|
75
|
+
self.dockarea.addDock(dock_viewer, 'right', self.dock_settings) # add this dock to the right of the settings one
|
|
76
|
+
viewer_widget = QtWidgets.QWidget()
|
|
77
|
+
self.viewer = Viewer1D(viewer_widget)
|
|
78
|
+
dock_viewer.addWidget(viewer_widget)
|
|
79
|
+
|
|
80
|
+
logger.debug('docks are set')
|
|
81
|
+
|
|
82
|
+
def setup_actions(self):
|
|
83
|
+
"""
|
|
84
|
+
subclass method from ActionManager
|
|
85
|
+
"""
|
|
86
|
+
logger.debug('setting actions')
|
|
87
|
+
self.add_action('quit', 'Quit', 'close2', "Quit program", toolbar=self.toolbar)
|
|
88
|
+
# toolbar is an inherited property of the ActionManager base class
|
|
89
|
+
|
|
90
|
+
self.add_action('show', 'Show/hide', 'read2', "Show Hide Viewer", checkable=True, toolbar=self.toolbar)
|
|
91
|
+
self.add_action('plot', 'Plot', 'snap', "Plot", checkable=False, toolbar=self.toolbar)
|
|
92
|
+
self.add_action('plot_seq', 'Plot Sequence', 'camera', "Plot functions", checkable=True, toolbar=self.toolbar)
|
|
93
|
+
self.add_action('save', 'Save', 'SaveAs', "Save current function", checkable=False, toolbar=self.toolbar)
|
|
94
|
+
logger.debug('actions set')
|
|
95
|
+
|
|
96
|
+
def connect_things(self):
|
|
97
|
+
self.connect_action('quit', self.quit)
|
|
98
|
+
self.connect_action('plot', self.plot)
|
|
99
|
+
|
|
100
|
+
self.connect_action('plot_seq', self.plot_all)
|
|
101
|
+
|
|
102
|
+
def quit(self):
|
|
103
|
+
self.mainwindow.close()
|
|
104
|
+
|
|
105
|
+
def plot(self):
|
|
106
|
+
function_str = self.settings['functions']
|
|
107
|
+
x = np.linspace(self.settings['xaxis', 'xstart'], self.settings['xaxis', 'xstop'],
|
|
108
|
+
self.settings['xaxis', 'npoints'])
|
|
109
|
+
|
|
110
|
+
function_vals = eval(f'np.{function_str}')
|
|
111
|
+
|
|
112
|
+
self.viewer.show_data(DataRaw(name=function_str,
|
|
113
|
+
data=[function_vals],
|
|
114
|
+
labels=[function_str],
|
|
115
|
+
axes=[
|
|
116
|
+
data_mod.Axis(
|
|
117
|
+
data=x, label='An axis', units='arb. units')],
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def value_changed(self, param):
|
|
122
|
+
if param.name() == 'add_function':
|
|
123
|
+
function_list = [self.settings['function']]
|
|
124
|
+
old_functions = self.functions
|
|
125
|
+
function_list.extend(old_functions)
|
|
126
|
+
function_list = list(np.unique(function_list))
|
|
127
|
+
self.settings.child('functions').setLimits(function_list)
|
|
128
|
+
param.setValue(False)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def functions(self):
|
|
132
|
+
return self.settings.child('functions').opts['limits']
|
|
133
|
+
|
|
134
|
+
def plot_timer(self):
|
|
135
|
+
self.settings.child('functions').setValue(self.functions[self.ind_plot % len(self.functions)])
|
|
136
|
+
self.plot()
|
|
137
|
+
self.ind_plot += 1
|
|
138
|
+
|
|
139
|
+
def plot_all(self):
|
|
140
|
+
if self.is_action_checked('plot_seq'):
|
|
141
|
+
self.timer.start()
|
|
142
|
+
else:
|
|
143
|
+
self.timer.stop()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def main():
|
|
147
|
+
import sys
|
|
148
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
149
|
+
mainwindow = QtWidgets.QMainWindow()
|
|
150
|
+
dockarea = DockArea()
|
|
151
|
+
mainwindow.setCentralWidget(dockarea)
|
|
152
|
+
|
|
153
|
+
prog = FunctionPlotter(dockarea)
|
|
154
|
+
|
|
155
|
+
mainwindow.show()
|
|
156
|
+
sys.exit(app.exec_())
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if __name__ == '__main__':
|
|
160
|
+
main()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
5
|
+
from pymodaq.utils.gui_utils.custom_app import CustomApp
|
|
6
|
+
from pymodaq.utils.gui_utils.dock import DockArea, Dock
|
|
7
|
+
from pymodaq.utils.config import Config, get_set_preset_path
|
|
8
|
+
from qtpy import QtWidgets
|
|
9
|
+
from qtpy.QtCore import Signal, QLocale
|
|
10
|
+
|
|
11
|
+
from pymodaq.utils import gui_utils as gutils
|
|
12
|
+
from pymodaq.utils import daq_utils as utils
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
config = Config()
|
|
16
|
+
logger = set_logger(get_module_name(__file__))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NonLinearScanner(CustomApp):
|
|
20
|
+
|
|
21
|
+
positions_signal = Signal(np.ndarray)
|
|
22
|
+
|
|
23
|
+
# list of dicts enabling the settings tree on the user interface
|
|
24
|
+
params = [
|
|
25
|
+
{'title': 'Init Position:', 'name': 'ini_pos', 'type': 'float', 'value': 0, },
|
|
26
|
+
{'title': 'Saturation pos:', 'name': 'satu_pos', 'type': 'float', 'value': 5, },
|
|
27
|
+
{'title': 'Start scan:', 'name': 'start_scan', 'type': 'float', 'value': 4, },
|
|
28
|
+
{'title': 'Stop Scan:', 'name': 'stop_scan', 'type': 'float', 'value': 3, },
|
|
29
|
+
{'title': 'Step Scan:', 'name': 'step_scan', 'type': 'float', 'value': -0.05, },
|
|
30
|
+
{'title': 'Apply', 'name': 'apply', 'type': 'action',},
|
|
31
|
+
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
def __init__(self, dockarea):
|
|
35
|
+
|
|
36
|
+
super().__init__(dockarea)
|
|
37
|
+
self.setup_ui()
|
|
38
|
+
|
|
39
|
+
def setup_actions(self):
|
|
40
|
+
'''
|
|
41
|
+
subclass method from ActionManager
|
|
42
|
+
'''
|
|
43
|
+
logger.debug('setting actions')
|
|
44
|
+
|
|
45
|
+
logger.debug('actions set')
|
|
46
|
+
|
|
47
|
+
def setup_docks(self):
|
|
48
|
+
'''
|
|
49
|
+
subclass method from CustomApp
|
|
50
|
+
'''
|
|
51
|
+
logger.debug('setting docks')
|
|
52
|
+
self.dock_settings = Dock('Settings', size=(350, 350))
|
|
53
|
+
self.dockarea.addDock(self.dock_settings, 'left')
|
|
54
|
+
self.dock_settings.addWidget(self.settings_tree, 10)
|
|
55
|
+
logger.debug('docks are set')
|
|
56
|
+
|
|
57
|
+
def connect_things(self):
|
|
58
|
+
'''
|
|
59
|
+
subclass method from CustomApp
|
|
60
|
+
'''
|
|
61
|
+
logger.debug('connecting things')
|
|
62
|
+
self.settings.child('apply').sigActivated.connect(self.emit_positions)
|
|
63
|
+
logger.debug('connecting done')
|
|
64
|
+
|
|
65
|
+
def setup_menu(self):
|
|
66
|
+
'''
|
|
67
|
+
subclass method from CustomApp
|
|
68
|
+
'''
|
|
69
|
+
logger.debug('settings menu')
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
logger.debug('menu set')
|
|
73
|
+
|
|
74
|
+
def value_changed(self, param):
|
|
75
|
+
logger.debug(f'calling value_changed with param {param.name()}')
|
|
76
|
+
|
|
77
|
+
logger.debug(f'Value change applied')
|
|
78
|
+
|
|
79
|
+
def update_positions(self):
|
|
80
|
+
xini = self.settings.child('ini_pos').value()
|
|
81
|
+
sat = self.settings.child('satu_pos').value()
|
|
82
|
+
start = self.settings.child('start_scan').value()
|
|
83
|
+
stop = self.settings.child('stop_scan').value()
|
|
84
|
+
step = self.settings.child('step_scan').value()
|
|
85
|
+
|
|
86
|
+
return np.concatenate((np.array([xini, sat]), utils.linspace_step(start, stop, step), np.array([xini])))
|
|
87
|
+
|
|
88
|
+
def emit_positions(self):
|
|
89
|
+
self.positions_signal.emit(np.transpose(np.array([self.update_positions()])))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def main():
|
|
93
|
+
import sys
|
|
94
|
+
from pathlib import Path
|
|
95
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
96
|
+
|
|
97
|
+
from pymodaq.dashboard import DashBoard
|
|
98
|
+
|
|
99
|
+
win = QtWidgets.QMainWindow()
|
|
100
|
+
area = DockArea()
|
|
101
|
+
win.setCentralWidget(area)
|
|
102
|
+
win.resize(1000, 500)
|
|
103
|
+
win.setWindowTitle('PyMoDAQ Dashboard')
|
|
104
|
+
|
|
105
|
+
dash = DashBoard(area)
|
|
106
|
+
file = Path(get_set_preset_path()).joinpath(f"{config('presets', 'default_preset_for_scan')}.xml")
|
|
107
|
+
if file.exists():
|
|
108
|
+
dash.set_preset_mode(file)
|
|
109
|
+
dash.load_scan_module()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
mainwindow = QtWidgets.QMainWindow()
|
|
113
|
+
dockarea = DockArea()
|
|
114
|
+
mainwindow.setCentralWidget(dockarea)
|
|
115
|
+
|
|
116
|
+
prog = NonLinearScanner(dockarea)
|
|
117
|
+
|
|
118
|
+
QtWidgets.QApplication.processEvents()
|
|
119
|
+
prog.positions_signal.connect(dash.scan_module.scanner.update_tabular_positions)
|
|
120
|
+
|
|
121
|
+
mainwindow.show()
|
|
122
|
+
sys.exit(app.exec_())
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == '__main__':
|
|
126
|
+
main()
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example how to create an actuator or detector module, which does not require Qt, nor any GUI functionality.
|
|
3
|
+
|
|
4
|
+
You can connect to this qtless module with a PyMoDAQ LECODirector module (the detector or actuator version, both are preinstalled),
|
|
5
|
+
as if it were any pymodaq module.
|
|
6
|
+
|
|
7
|
+
This example works best with an Actuator Director Module as it has fake movements, but does not return any detector value.
|
|
8
|
+
In this example, the name is "qt_less" (defined in the final if clause), which you have to give as the "actor" argument to the Director module.
|
|
9
|
+
|
|
10
|
+
Add any code in the methods defined below, for example instrument access and execute the file.
|
|
11
|
+
For remote control, you need to start a Coordinator, as described for remote control via LECO.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from time import sleep
|
|
16
|
+
from typing import cast, List, Optional
|
|
17
|
+
|
|
18
|
+
from pyleco.utils.listener import Listener
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from pymodaq_data.data import DataWithAxes
|
|
22
|
+
from pymodaq_utils.serialize.factory import SerializableFactory
|
|
23
|
+
|
|
24
|
+
class QtLessModule:
|
|
25
|
+
"""Some module doing things without Qt.
|
|
26
|
+
|
|
27
|
+
You can run an instance of this class anywhere in your LECO network.
|
|
28
|
+
Then you can control this instance with a PyMoDAQ LECODirectorModule (in mock modules) as if it were a PyMoDAQ module.
|
|
29
|
+
|
|
30
|
+
Just add any logic you wish to the methods below.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, name: str, host: str = "localhost", **kwargs) -> None:
|
|
34
|
+
super().__init__()
|
|
35
|
+
self.listener = Listener(name=name, host=host, timeout=1, **kwargs)
|
|
36
|
+
self._fake_position = 0
|
|
37
|
+
self.start_listen()
|
|
38
|
+
self._stored = []
|
|
39
|
+
# register DataWithAxes for deserialization
|
|
40
|
+
cls = DataWithAxes
|
|
41
|
+
SerializableFactory().register_from_type(cls, cls.serialize, cls.deserialize)
|
|
42
|
+
|
|
43
|
+
def start_listen(self) -> None:
|
|
44
|
+
"""Start to listen on incoming commands."""
|
|
45
|
+
self.listener.start_listen()
|
|
46
|
+
self.communicator = self.listener.get_communicator()
|
|
47
|
+
self.register_rpc_methods()
|
|
48
|
+
|
|
49
|
+
def register_rpc_methods(self) -> None:
|
|
50
|
+
"""Make the following methods available via LECO."""
|
|
51
|
+
register_rpc_method = self.communicator.register_rpc_method
|
|
52
|
+
register_rpc_method(self.set_info)
|
|
53
|
+
register_rpc_method(self.send_data)
|
|
54
|
+
# binary methods can accept additionally binary payload, like serialized pymodaq objects.
|
|
55
|
+
self.listener.register_binary_rpc_method(self.move_abs, accept_binary_input=True)
|
|
56
|
+
self.listener.register_binary_rpc_method(self.move_rel, accept_binary_input=True)
|
|
57
|
+
register_rpc_method(self.move_home)
|
|
58
|
+
register_rpc_method(self.get_actuator_value)
|
|
59
|
+
register_rpc_method(self.stop_motion)
|
|
60
|
+
register_rpc_method(self.set_remote_name)
|
|
61
|
+
|
|
62
|
+
def stop_listen(self) -> None:
|
|
63
|
+
"""Stop to listen on incoming commands."""
|
|
64
|
+
self.listener.stop_listen()
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def extract_pymodaq_object(
|
|
68
|
+
value: Optional[float], additional_payload: Optional[List[bytes]]
|
|
69
|
+
):
|
|
70
|
+
if value is None and additional_payload:
|
|
71
|
+
res = cast(DataWithAxes, SerializableFactory().get_apply_deserializer(additional_payload[0]))
|
|
72
|
+
else:
|
|
73
|
+
res = value
|
|
74
|
+
return res
|
|
75
|
+
|
|
76
|
+
# methods for being remote controlled
|
|
77
|
+
# these methods are executed and cannot talk to the controlling module directly.
|
|
78
|
+
# if you need to send a response (for example with a value) you have to store the information and
|
|
79
|
+
# send it after these methods have been executed.
|
|
80
|
+
def set_remote_name(self, name: str) -> None:
|
|
81
|
+
"""Define what the name of the remote for answers is."""
|
|
82
|
+
self.remote_name = name
|
|
83
|
+
|
|
84
|
+
# generic commands
|
|
85
|
+
def set_info(self, path: List[str], param_dict_str: str) -> None:
|
|
86
|
+
print("set_info", path, param_dict_str)
|
|
87
|
+
|
|
88
|
+
# detector commands
|
|
89
|
+
def send_data(self, grabber_type: str = "") -> None:
|
|
90
|
+
print("send_data")
|
|
91
|
+
|
|
92
|
+
# actuator commands
|
|
93
|
+
def move_abs(
|
|
94
|
+
self,
|
|
95
|
+
position: Optional[float],
|
|
96
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Move to an absolute position.
|
|
99
|
+
|
|
100
|
+
:param position: Deprecated, should be None and content transferred binary.
|
|
101
|
+
:param additional_payload: binary frames containing the position as PyMoDAQ `DataActuator`.
|
|
102
|
+
"""
|
|
103
|
+
pos = self.extract_pymodaq_object(position, additional_payload)
|
|
104
|
+
print("move_abs", pos)
|
|
105
|
+
self._fake_position = float(pos)
|
|
106
|
+
|
|
107
|
+
def move_rel(
|
|
108
|
+
self,
|
|
109
|
+
position: Optional[float],
|
|
110
|
+
additional_payload: Optional[List[bytes]] = None,
|
|
111
|
+
) -> None:
|
|
112
|
+
"""Move by a relative position.
|
|
113
|
+
|
|
114
|
+
:param position: Deprecated, should be None and content transferred binary.
|
|
115
|
+
:param additional_payload: binary frames containing the position as PyMoDAQ `DataActuator`.
|
|
116
|
+
"""
|
|
117
|
+
pos = self.extract_pymodaq_object(position, additional_payload)
|
|
118
|
+
print("move_rel", pos)
|
|
119
|
+
self._fake_position += float(pos)
|
|
120
|
+
|
|
121
|
+
def move_home(self) -> None:
|
|
122
|
+
self._fake_position = 0
|
|
123
|
+
print("move_home")
|
|
124
|
+
|
|
125
|
+
def get_actuator_value(self) -> None:
|
|
126
|
+
"""Request that the actuator value is sent later on."""
|
|
127
|
+
# according to DAQ_Move, this supersedes "check_position"
|
|
128
|
+
print("get_actuator_value")
|
|
129
|
+
# send the actuator position after this method has finished execution.
|
|
130
|
+
# this method sends the result to the controlling control module.
|
|
131
|
+
self.send_later(
|
|
132
|
+
receiver=self.remote_name,
|
|
133
|
+
method="set_position",
|
|
134
|
+
position=self._fake_position,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def stop_motion(self,) -> None:
|
|
138
|
+
# not implemented in DAQ_Move!
|
|
139
|
+
print("stop_motion")
|
|
140
|
+
|
|
141
|
+
# end of methods for being remote controlled
|
|
142
|
+
|
|
143
|
+
def send_later(self, receiver, method, **kwargs):
|
|
144
|
+
"""Store information to send it later."""
|
|
145
|
+
self._stored.append((receiver, method, kwargs))
|
|
146
|
+
|
|
147
|
+
def send_stored(self):
|
|
148
|
+
"""Send messages stored for later sending."""
|
|
149
|
+
while self._stored:
|
|
150
|
+
receiver, method, kwargs = self._stored.pop()
|
|
151
|
+
self.communicator.ask_rpc(receiver=receiver, method=method, **kwargs)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
print("listening endlessly as 'qt_less'")
|
|
156
|
+
log = logging.getLogger()
|
|
157
|
+
log.addHandler(logging.StreamHandler())
|
|
158
|
+
# log.setLevel(logging.DEBUG)
|
|
159
|
+
m = QtLessModule("qt_less")
|
|
160
|
+
try:
|
|
161
|
+
while True:
|
|
162
|
+
sleep(0.1)
|
|
163
|
+
m.send_stored()
|
|
164
|
+
except KeyboardInterrupt:
|
|
165
|
+
m.stop_listen()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Minimal example of a TCP client connecting to a TCP server instrument class plugin (type 0D) and
|
|
3
|
+
sending to it 0D data in a row representing a sinus.
|
|
4
|
+
|
|
5
|
+
To execute all this:
|
|
6
|
+
|
|
7
|
+
* start a Daq_Viewer from the console, select DAQ0D and TCP_Server, set the IP to localhost, then init
|
|
8
|
+
* execute this script
|
|
9
|
+
|
|
10
|
+
You should see the TCP server printing the sinus in its 0D data viewer
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
from pymodaq.utils.tcp_ip.tcp_server_client import TCPClientTemplate
|
|
18
|
+
from pymodaq_data.data import DataToExport, DataRaw
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TCPClient(TCPClientTemplate):
|
|
22
|
+
def __init__(self):
|
|
23
|
+
super().__init__(ipaddress="localhost", port=6341, client_type="GRABBER")
|
|
24
|
+
|
|
25
|
+
def post_init(self, extra_commands=[]):
|
|
26
|
+
self.socket.check_sended_with_serializer(self.client_type)
|
|
27
|
+
|
|
28
|
+
def send_data(self, data: DataToExport):
|
|
29
|
+
# first send 'Done' and then send the length of the list
|
|
30
|
+
if not isinstance(data, DataToExport):
|
|
31
|
+
raise TypeError(f'should send a DataToExport object')
|
|
32
|
+
if self.socket is not None:
|
|
33
|
+
self.socket.check_sended_with_serializer('Done')
|
|
34
|
+
self.socket.check_sended_with_serializer(data)
|
|
35
|
+
|
|
36
|
+
def ready_to_read(self):
|
|
37
|
+
message = self._deserializer.string_deserialization()
|
|
38
|
+
self.get_data(message)
|
|
39
|
+
|
|
40
|
+
def get_data(self, message: str):
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
message
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
if self.socket is not None:
|
|
52
|
+
|
|
53
|
+
if message == 'set_info':
|
|
54
|
+
path = self._deserializer.list_deserialization()
|
|
55
|
+
param_xml = self._deserializer.string_deserialization()
|
|
56
|
+
print(param_xml)
|
|
57
|
+
|
|
58
|
+
elif message == 'move_abs' or message == 'move_rel':
|
|
59
|
+
position = self._deserializer.dwa_deserialization()
|
|
60
|
+
print(f'Position is {position}')
|
|
61
|
+
|
|
62
|
+
else:
|
|
63
|
+
print(message)
|
|
64
|
+
|
|
65
|
+
def data_ready(self, data: DataToExport):
|
|
66
|
+
self.send_data(data)
|
|
67
|
+
|
|
68
|
+
def ready_to_write(self):
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
def ready_with_error(self):
|
|
72
|
+
self.connected = False
|
|
73
|
+
|
|
74
|
+
def process_error_in_polling(self, e: Exception):
|
|
75
|
+
print(e)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == '__main__':
|
|
80
|
+
from threading import Thread
|
|
81
|
+
from time import sleep
|
|
82
|
+
|
|
83
|
+
tcpclient = TCPClient()
|
|
84
|
+
t = Thread(target=tcpclient.init_connection)
|
|
85
|
+
|
|
86
|
+
t.start()
|
|
87
|
+
sleep(1)
|
|
88
|
+
sinus = np.sin(np.linspace(0, 2 * np.pi, 10))
|
|
89
|
+
|
|
90
|
+
for ind in range(10):
|
|
91
|
+
dwa = DataRaw('mydata', data=[np.array([sinus[ind]])], plot=True)
|
|
92
|
+
tcpclient.data_ready(dwa.as_dte())
|
|
93
|
+
|
|
94
|
+
tcpclient.close()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 25/10/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
from .utils import get_extensions
|
|
8
|
+
from .pid.utils import get_models
|
|
9
|
+
|
|
10
|
+
from .console import QtConsole
|
|
11
|
+
from .daq_scan import DAQScan
|
|
12
|
+
from .daq_logger.daq_logger import DAQ_Logger
|
|
13
|
+
from .pid.pid_controller import DAQ_PID
|
|
14
|
+
from .h5browser import H5Browser #backcompat but should be loaded from pymodaq_gui!
|
|
15
|
+
|
|
16
|
+
from .bayesian.bayesian_optimization import BayesianOptimization
|
|
17
|
+
from .bayesian.utils import OptimizerModelDefault
|
|
18
|
+
|
|
19
|
+
from .adaptive.adaptive_optimization import AdaptiveOptimisation
|
|
20
|
+
|
|
21
|
+
from .data_mixer.data_mixer import DataMixer
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|