microeye 2.3.2__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.
- microEye/__init__.py +47 -0
- microEye/_version.py +2 -0
- microEye/analysis/__init__.py +1 -0
- microEye/analysis/checklist_dialog.py +143 -0
- microEye/analysis/cmosMaps.py +228 -0
- microEye/analysis/filters/__init__.py +9 -0
- microEye/analysis/filters/base.py +21 -0
- microEye/analysis/filters/spatial.py +338 -0
- microEye/analysis/filters/temporal.py +76 -0
- microEye/analysis/fitting/__init__.py +0 -0
- microEye/analysis/fitting/fit.py +680 -0
- microEye/analysis/fitting/nena.py +375 -0
- microEye/analysis/fitting/phasor_fit.py +90 -0
- microEye/analysis/fitting/processing.py +317 -0
- microEye/analysis/fitting/psf/__init__.py +6 -0
- microEye/analysis/fitting/psf/extract.py +1129 -0
- microEye/analysis/fitting/psf/rubost_mean.py +150 -0
- microEye/analysis/fitting/psf/spline.py +167 -0
- microEye/analysis/fitting/psf/stats/__init__.py +12 -0
- microEye/analysis/fitting/psf/stats/core.py +295 -0
- microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
- microEye/analysis/fitting/psf/stats/io.py +104 -0
- microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
- microEye/analysis/fitting/psf/temp.py +147 -0
- microEye/analysis/fitting/psf/test.py +47 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
- microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
- microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
- microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
- microEye/analysis/fitting/results.py +917 -0
- microEye/analysis/fitting/results_stats.py +251 -0
- microEye/analysis/fitting/tardis.py +209 -0
- microEye/analysis/multi_viewer.py +568 -0
- microEye/analysis/processing/__init__.py +1 -0
- microEye/analysis/processing/frc.py +120 -0
- microEye/analysis/rendering/__init__.py +3 -0
- microEye/analysis/rendering/base.py +452 -0
- microEye/analysis/rendering/cloud.py +215 -0
- microEye/analysis/rendering/core.py +47 -0
- microEye/analysis/rendering/volumetric.py +198 -0
- microEye/analysis/tools/__init__.py +0 -0
- microEye/analysis/tools/kymograms.py +1079 -0
- microEye/analysis/tools/roi_selectors.py +556 -0
- microEye/analysis/utils/__init__.py +3 -0
- microEye/analysis/utils/coordinates.py +18 -0
- microEye/analysis/utils/images.py +68 -0
- microEye/analysis/utils/windows.py +19 -0
- microEye/analysis/viewer/__init__.py +3 -0
- microEye/analysis/viewer/image_options_widget.py +615 -0
- microEye/analysis/viewer/images.py +1225 -0
- microEye/analysis/viewer/layers_widget.py +415 -0
- microEye/analysis/viewer/localizations.py +1304 -0
- microEye/analysis/viewer/psf.py +1003 -0
- microEye/analysis/viewer/volume.py +456 -0
- microEye/hardware/__init__.py +3 -0
- microEye/hardware/cams/__init__.py +29 -0
- microEye/hardware/cams/camera_calibration.py +99 -0
- microEye/hardware/cams/camera_list.py +528 -0
- microEye/hardware/cams/camera_options.py +694 -0
- microEye/hardware/cams/camera_panel.py +941 -0
- microEye/hardware/cams/dummy/__init__.py +1 -0
- microEye/hardware/cams/dummy/dummy_panel.py +759 -0
- microEye/hardware/cams/jobs.py +497 -0
- microEye/hardware/cams/line_profiler.py +99 -0
- microEye/hardware/cams/linescan/IR_Cam.py +474 -0
- microEye/hardware/cams/linescan/__init__.py +1 -0
- microEye/hardware/cams/micam.py +524 -0
- microEye/hardware/cams/pco/__init__.py +58 -0
- microEye/hardware/cams/pco/enums.py +382 -0
- microEye/hardware/cams/pco/pco_cam.py +761 -0
- microEye/hardware/cams/pco/pco_panel.py +477 -0
- microEye/hardware/cams/shortcuts.py +312 -0
- microEye/hardware/cams/thorlabs/__init__.py +1 -0
- microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
- microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
- microEye/hardware/cams/ueye/__init__.py +1 -0
- microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
- microEye/hardware/cams/ueye/ueye_panel.py +861 -0
- microEye/hardware/cams/vimba/__init__.py +1 -0
- microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
- microEye/hardware/cams/vimba/vimba_panel.py +813 -0
- microEye/hardware/device.py +60 -0
- microEye/hardware/lasers/__init__.py +13 -0
- microEye/hardware/lasers/io_matchbox.py +791 -0
- microEye/hardware/lasers/io_params.py +85 -0
- microEye/hardware/lasers/io_single_laser.py +742 -0
- microEye/hardware/lasers/laser_relay.py +594 -0
- microEye/hardware/mieye/__init__.py +1 -0
- microEye/hardware/mieye/acquisition_manager.py +467 -0
- microEye/hardware/mieye/devices_manager.py +533 -0
- microEye/hardware/mieye/miEye.py +659 -0
- microEye/hardware/misc/__init__.py +0 -0
- microEye/hardware/misc/acquisition_view.py +71 -0
- microEye/hardware/misc/reglo.py +761 -0
- microEye/hardware/misc/temp.py +188 -0
- microEye/hardware/port_config.py +59 -0
- microEye/hardware/protocols/__init__.py +2 -0
- microEye/hardware/protocols/actions.py +402 -0
- microEye/hardware/protocols/actions_items.py +703 -0
- microEye/hardware/protocols/designer.py +244 -0
- microEye/hardware/protocols/scene_manager.py +191 -0
- microEye/hardware/protocols/serialization.py +97 -0
- microEye/hardware/pycromanager/__init__.py +16 -0
- microEye/hardware/pycromanager/core.py +1433 -0
- microEye/hardware/pycromanager/devices.py +461 -0
- microEye/hardware/pycromanager/enums.py +107 -0
- microEye/hardware/pycromanager/headless.py +153 -0
- microEye/hardware/pycromanager/utils.py +34 -0
- microEye/hardware/pycromanager/widgets/__init__.py +5 -0
- microEye/hardware/pycromanager/widgets/bridges.py +407 -0
- microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
- microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
- microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
- microEye/hardware/stages/__init__.py +18 -0
- microEye/hardware/stages/elliptec/__init__.py +5 -0
- microEye/hardware/stages/elliptec/baseDevice.py +314 -0
- microEye/hardware/stages/elliptec/device.py +384 -0
- microEye/hardware/stages/elliptec/deviceID.py +212 -0
- microEye/hardware/stages/elliptec/devicePort.py +379 -0
- microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
- microEye/hardware/stages/elliptec/devicesView.py +706 -0
- microEye/hardware/stages/elliptec/ellDevices.py +134 -0
- microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
- microEye/hardware/stages/elliptec/motorInfo.py +153 -0
- microEye/hardware/stages/elliptec/stage.py +62 -0
- microEye/hardware/stages/elliptec/test.py +139 -0
- microEye/hardware/stages/kinesis/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
- microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
- microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
- microEye/hardware/stages/kinesis/kinesis.py +776 -0
- microEye/hardware/stages/piezo_concept.py +607 -0
- microEye/hardware/stages/stabilizer.py +785 -0
- microEye/hardware/stages/stage.py +89 -0
- microEye/hardware/widgets/__init__.py +10 -0
- microEye/hardware/widgets/controller.py +246 -0
- microEye/hardware/widgets/devices.py +133 -0
- microEye/hardware/widgets/focusWidget.py +264 -0
- microEye/hardware/widgets/qlist_slider.py +113 -0
- microEye/hardware/widgets/scan_acquisition.py +424 -0
- microEye/icons/1024.png +0 -0
- microEye/icons/128.png +0 -0
- microEye/icons/16.png +0 -0
- microEye/icons/24.png +0 -0
- microEye/icons/256.png +0 -0
- microEye/icons/32.png +0 -0
- microEye/icons/48.png +0 -0
- microEye/icons/512.png +0 -0
- microEye/icons/64.png +0 -0
- microEye/icons/__init__.py +0 -0
- microEye/icons/close.svg +88 -0
- microEye/icons/mieye.png +0 -0
- microEye/icons/min.svg +83 -0
- microEye/icons/viewer.png +0 -0
- microEye/launcher.py +42 -0
- microEye/qt.py +181 -0
- microEye/utils/__init__.py +2 -0
- microEye/utils/enum_encoder.py +10 -0
- microEye/utils/expandable_groupbox.py +93 -0
- microEye/utils/gui_helper.py +457 -0
- microEye/utils/hid/__init__.py +8 -0
- microEye/utils/hid/controller.py +153 -0
- microEye/utils/hid/device.py +63 -0
- microEye/utils/hid/enums.py +140 -0
- microEye/utils/hid/utils.py +58 -0
- microEye/utils/labelled_slider.py +134 -0
- microEye/utils/metadata.py +599 -0
- microEye/utils/metadata_tree.py +718 -0
- microEye/utils/micro_launcher.py +245 -0
- microEye/utils/parameter_tree.py +325 -0
- microEye/utils/pyscripting.py +444 -0
- microEye/utils/retry_exec.py +35 -0
- microEye/utils/start_gui.py +112 -0
- microEye/utils/thread_worker.py +115 -0
- microEye/utils/uImage.py +1512 -0
- microeye-2.3.2.dist-info/METADATA +401 -0
- microeye-2.3.2.dist-info/RECORD +190 -0
- microeye-2.3.2.dist-info/WHEEL +5 -0
- microeye-2.3.2.dist-info/entry_points.txt +2 -0
- microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
- microeye-2.3.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Optional, Union, overload
|
|
4
|
+
|
|
5
|
+
from pyqtgraph.parametertree import Parameter
|
|
6
|
+
|
|
7
|
+
from microEye.hardware.stages.stabilizer import FocusStabilizer
|
|
8
|
+
from microEye.hardware.stages.stage import stage
|
|
9
|
+
from microEye.qt import QtCore, QtSerialPort, QtWidgets, Signal
|
|
10
|
+
from microEye.utils import Tree
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StageParams(Enum):
|
|
14
|
+
'''
|
|
15
|
+
Enum class defining Stage parameters.
|
|
16
|
+
'''
|
|
17
|
+
|
|
18
|
+
MODEL = 'Model'
|
|
19
|
+
|
|
20
|
+
HOME = 'Home'
|
|
21
|
+
REFRESH = 'Refresh'
|
|
22
|
+
JUMP_P = 'Jump +'
|
|
23
|
+
JUMP_N = 'Jump -'
|
|
24
|
+
STEP_P = 'Step +'
|
|
25
|
+
STEP_N = 'Step -'
|
|
26
|
+
|
|
27
|
+
SERIAL_PORT = 'Serial Port'
|
|
28
|
+
PORT = 'Serial Port.Port'
|
|
29
|
+
BAUDRATE = 'Serial Port.Baudrate'
|
|
30
|
+
SET_PORT = 'Serial Port.Set Config'
|
|
31
|
+
OPEN = 'Serial Port.Connect'
|
|
32
|
+
CLOSE = 'Serial Port.Disconnect'
|
|
33
|
+
PORT_STATE = 'Serial Port.State'
|
|
34
|
+
|
|
35
|
+
OPTIONS = 'Options'
|
|
36
|
+
STEP = 'Options.Step Size [nm]'
|
|
37
|
+
JUMP = 'Options.Jump Size [um]'
|
|
38
|
+
|
|
39
|
+
READINGS = 'Readings'
|
|
40
|
+
Z_POSITION = 'Readings.Z Position [um]'
|
|
41
|
+
|
|
42
|
+
INFO = 'Info'
|
|
43
|
+
|
|
44
|
+
REMOVE = 'Remove Device'
|
|
45
|
+
|
|
46
|
+
def __str__(self):
|
|
47
|
+
'''
|
|
48
|
+
Return the last part of the enum value (Param name).
|
|
49
|
+
'''
|
|
50
|
+
return self.value.split('.')[-1]
|
|
51
|
+
|
|
52
|
+
def get_path(self):
|
|
53
|
+
'''
|
|
54
|
+
Return the full parameter path.
|
|
55
|
+
'''
|
|
56
|
+
return self.value.split('.')
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PzFocSignals(QtCore.QObject):
|
|
60
|
+
positionChanged = Signal(float)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class PzFoc:
|
|
64
|
+
'''PiezoConcept FOC 1-axis stage adapter.'''
|
|
65
|
+
|
|
66
|
+
def __init__(self, max_um: int = 100):
|
|
67
|
+
'''
|
|
68
|
+
Initializes a PiezoConcept FOC 1-axis stage adapter.
|
|
69
|
+
'''
|
|
70
|
+
self.signals = PzFocSignals()
|
|
71
|
+
|
|
72
|
+
self.ZPosition = 50000
|
|
73
|
+
self.LastCmd = ''
|
|
74
|
+
self.Received = ''
|
|
75
|
+
|
|
76
|
+
self.max_um = max_um
|
|
77
|
+
|
|
78
|
+
self.serial = QtSerialPort.QSerialPort(None, readyRead=self.rx_piezo)
|
|
79
|
+
self.serial.setBaudRate(115200)
|
|
80
|
+
self.serial.setPortName('COM5')
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def max_nm(self) -> int:
|
|
84
|
+
'''Maximum stage position in nanometers.'''
|
|
85
|
+
return self.max_um * 1000
|
|
86
|
+
|
|
87
|
+
def isOpen(self):
|
|
88
|
+
'''Returns True if connected.'''
|
|
89
|
+
return self.serial.isOpen()
|
|
90
|
+
|
|
91
|
+
def open(self):
|
|
92
|
+
'''Opens the serial port.'''
|
|
93
|
+
if not self.isOpen():
|
|
94
|
+
self.serial.open(QtCore.QIODevice.OpenModeFlag.ReadWrite)
|
|
95
|
+
|
|
96
|
+
def close(self):
|
|
97
|
+
'''Closes the supplied serial port.'''
|
|
98
|
+
if self.isOpen():
|
|
99
|
+
self.serial.close()
|
|
100
|
+
|
|
101
|
+
def setPortName(self, name: str):
|
|
102
|
+
'''Sets the serial port name.'''
|
|
103
|
+
if not self.isOpen():
|
|
104
|
+
self.serial.setPortName(name)
|
|
105
|
+
|
|
106
|
+
def setBaudRate(self, baudRate: int):
|
|
107
|
+
'''Sets the serial port baudrate.'''
|
|
108
|
+
if not self.isOpen():
|
|
109
|
+
self.serial.setBaudRate(baudRate)
|
|
110
|
+
|
|
111
|
+
def write(self, value):
|
|
112
|
+
'''
|
|
113
|
+
Writes data to the serial port.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
data : QByteArray | bytes | bytearray
|
|
118
|
+
The data to be written to the serial port.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
int
|
|
123
|
+
The number of bytes written to the serial port, or a negative value
|
|
124
|
+
if an error occurs.
|
|
125
|
+
|
|
126
|
+
Raises
|
|
127
|
+
------
|
|
128
|
+
IOError
|
|
129
|
+
If the serial port is not open.
|
|
130
|
+
'''
|
|
131
|
+
return self.serial.write(value)
|
|
132
|
+
|
|
133
|
+
def GETZ(self):
|
|
134
|
+
'''Gets the current stage position along the Z axis.'''
|
|
135
|
+
if self.isOpen():
|
|
136
|
+
self.write(b'GET_Z\n')
|
|
137
|
+
self.LastCmd = 'GETZ'
|
|
138
|
+
|
|
139
|
+
def HOME(self):
|
|
140
|
+
'''Centers the stage position along the Z axis.'''
|
|
141
|
+
if self.isOpen():
|
|
142
|
+
self.ZPosition = self.max_nm // 2
|
|
143
|
+
self.write(f'MOVEZ {self.max_um // 2}u\n'.encode())
|
|
144
|
+
self.LastCmd = 'MOVEZ'
|
|
145
|
+
|
|
146
|
+
def ABSOLUTE(self, pos: int):
|
|
147
|
+
'''
|
|
148
|
+
Moves the stage to an absolute position.
|
|
149
|
+
'''
|
|
150
|
+
if self.isOpen():
|
|
151
|
+
self.ZPosition = min(max(pos, 0), self.max_nm)
|
|
152
|
+
self.write(f'MOVEZ {pos}u\n'.encode())
|
|
153
|
+
self.LastCmd = 'MOVEZ'
|
|
154
|
+
|
|
155
|
+
def REFRESH(self):
|
|
156
|
+
'''Refresh the stage position
|
|
157
|
+
to the set value in case of discrepancy.
|
|
158
|
+
'''
|
|
159
|
+
if self.isOpen():
|
|
160
|
+
self.write(('MOVEZ ' + str(self.ZPosition) + 'n\n').encode('utf-8'))
|
|
161
|
+
self.LastCmd = 'MOVEZ'
|
|
162
|
+
|
|
163
|
+
def UP(self, step: int):
|
|
164
|
+
'''
|
|
165
|
+
Moves the stage up by a specified number of steps.
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
step : int
|
|
170
|
+
The number of steps to move up in nanometers.
|
|
171
|
+
|
|
172
|
+
Raises
|
|
173
|
+
------
|
|
174
|
+
IOError
|
|
175
|
+
If the serial port is not open or an error occurs while writing.
|
|
176
|
+
'''
|
|
177
|
+
if self.isOpen():
|
|
178
|
+
self.ZPosition = min(max(self.ZPosition + step, 0), self.max_nm)
|
|
179
|
+
self.write(('MOVEZ ' + str(self.ZPosition) + 'n\n').encode('utf-8'))
|
|
180
|
+
self.LastCmd = 'MOVEZ'
|
|
181
|
+
|
|
182
|
+
def DOWN(self, step: int):
|
|
183
|
+
'''
|
|
184
|
+
Moves the stage down by a specified number of steps.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
step : int
|
|
189
|
+
The number of steps to move down in nanometers.
|
|
190
|
+
|
|
191
|
+
Raises
|
|
192
|
+
------
|
|
193
|
+
IOError
|
|
194
|
+
If the serial port is not open or an error occurs while writing.
|
|
195
|
+
'''
|
|
196
|
+
if self.isOpen():
|
|
197
|
+
self.ZPosition = min(max(self.ZPosition - step, 0), self.max_nm)
|
|
198
|
+
self.write(('MOVEZ ' + str(self.ZPosition) + 'n\n').encode('utf-8'))
|
|
199
|
+
self.LastCmd = 'MOVEZ'
|
|
200
|
+
|
|
201
|
+
def rx_piezo(self):
|
|
202
|
+
'''
|
|
203
|
+
Reads data from the serial port and processes it.
|
|
204
|
+
|
|
205
|
+
This method is called automatically when new data is available in the
|
|
206
|
+
serial port input buffer. It reads the data, parses the response, and
|
|
207
|
+
updates the appropriate attributes of the `PzFoc` object as needed.
|
|
208
|
+
|
|
209
|
+
Raises
|
|
210
|
+
------
|
|
211
|
+
IOError
|
|
212
|
+
If the serial port is not open, or an error occurs while reading.
|
|
213
|
+
'''
|
|
214
|
+
self.Received = str(self.serial.readAll(), encoding='utf8')
|
|
215
|
+
if self.LastCmd != 'GETZ':
|
|
216
|
+
self.GETZ()
|
|
217
|
+
else:
|
|
218
|
+
match = re.search(r' *(\d+\.\d+).*um.*', self.Received)
|
|
219
|
+
if match:
|
|
220
|
+
self.ZPosition = int(float(match.group(1)) * 1000)
|
|
221
|
+
self.signals.positionChanged.emit(float(match.group(1)))
|
|
222
|
+
|
|
223
|
+
def getQWidget(self):
|
|
224
|
+
'''Generates a PzFocView with stage controls.'''
|
|
225
|
+
return PzFocView(stage=self)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class PzFocView(Tree):
|
|
229
|
+
PARAMS = StageParams
|
|
230
|
+
removed = Signal(object)
|
|
231
|
+
|
|
232
|
+
def __init__(
|
|
233
|
+
self, parent: Optional['QtWidgets.QWidget'] = None, stage: PzFoc = None
|
|
234
|
+
):
|
|
235
|
+
'''
|
|
236
|
+
Initialize the PzFocView instance.
|
|
237
|
+
|
|
238
|
+
This method initializes the `PzFocView` instance, sets up the stage signals,
|
|
239
|
+
creates the parameter tree, and sets up the GUI elements.
|
|
240
|
+
|
|
241
|
+
Parameters
|
|
242
|
+
----------
|
|
243
|
+
parent : Optional[QWidget]
|
|
244
|
+
The parent widget.
|
|
245
|
+
stage : Optional[`PzFoc`]
|
|
246
|
+
The stage to be controlled by the GUI. If None, a new stage instance is
|
|
247
|
+
created.
|
|
248
|
+
'''
|
|
249
|
+
self.stage = stage if stage else PzFoc()
|
|
250
|
+
|
|
251
|
+
super().__init__(parent=parent)
|
|
252
|
+
|
|
253
|
+
def create_parameters(self):
|
|
254
|
+
'''
|
|
255
|
+
Create the parameter tree structure.
|
|
256
|
+
|
|
257
|
+
This method creates and sets up the parameter tree structure for the
|
|
258
|
+
`PzFocView` class.
|
|
259
|
+
'''
|
|
260
|
+
params = [
|
|
261
|
+
{
|
|
262
|
+
'name': str(StageParams.MODEL),
|
|
263
|
+
'type': 'str',
|
|
264
|
+
'value': 'PiezoConcept FOC 1-axis',
|
|
265
|
+
'readonly': True,
|
|
266
|
+
},
|
|
267
|
+
{'name': str(StageParams.HOME), 'type': 'action'},
|
|
268
|
+
{'name': str(StageParams.REFRESH), 'type': 'action'},
|
|
269
|
+
{'name': str(StageParams.JUMP_P), 'type': 'action'},
|
|
270
|
+
{'name': str(StageParams.STEP_P), 'type': 'action'},
|
|
271
|
+
{'name': str(StageParams.STEP_N), 'type': 'action'},
|
|
272
|
+
{'name': str(StageParams.JUMP_N), 'type': 'action'},
|
|
273
|
+
{
|
|
274
|
+
'name': str(StageParams.SERIAL_PORT),
|
|
275
|
+
'type': 'group',
|
|
276
|
+
'expanded': False,
|
|
277
|
+
'children': [
|
|
278
|
+
{
|
|
279
|
+
'name': str(StageParams.PORT),
|
|
280
|
+
'type': 'list',
|
|
281
|
+
'limits': [
|
|
282
|
+
info.portName()
|
|
283
|
+
for info in QtSerialPort.QSerialPortInfo.availablePorts()
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
'name': str(StageParams.BAUDRATE),
|
|
288
|
+
'type': 'list',
|
|
289
|
+
'value': 115200,
|
|
290
|
+
'limits': [
|
|
291
|
+
bd
|
|
292
|
+
for bd in QtSerialPort.QSerialPortInfo.standardBaudRates()
|
|
293
|
+
],
|
|
294
|
+
},
|
|
295
|
+
{'name': str(StageParams.SET_PORT), 'type': 'action'},
|
|
296
|
+
{'name': str(StageParams.OPEN), 'type': 'action'},
|
|
297
|
+
{'name': str(StageParams.CLOSE), 'type': 'action'},
|
|
298
|
+
{
|
|
299
|
+
'name': str(StageParams.PORT_STATE),
|
|
300
|
+
'type': 'str',
|
|
301
|
+
'value': 'closed',
|
|
302
|
+
'readonly': True,
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
'name': str(StageParams.READINGS),
|
|
308
|
+
'type': 'group',
|
|
309
|
+
'children': [
|
|
310
|
+
{
|
|
311
|
+
'name': str(StageParams.Z_POSITION),
|
|
312
|
+
'type': 'float',
|
|
313
|
+
'value': 0.0,
|
|
314
|
+
'readonly': True,
|
|
315
|
+
'decimals': 6,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
'name': str(StageParams.OPTIONS),
|
|
321
|
+
'type': 'group',
|
|
322
|
+
'children': [
|
|
323
|
+
{
|
|
324
|
+
'name': str(StageParams.STEP),
|
|
325
|
+
'type': 'int',
|
|
326
|
+
'value': 100,
|
|
327
|
+
'limits': [1, 1000],
|
|
328
|
+
'step': 5,
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
'name': str(StageParams.JUMP),
|
|
332
|
+
'type': 'int',
|
|
333
|
+
'value': 1,
|
|
334
|
+
'limits': [1, 100],
|
|
335
|
+
'step': 5,
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
},
|
|
339
|
+
{'name': str(StageParams.REMOVE), 'type': 'action'},
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
self.param_tree = Parameter.create(name='', type='group', children=params)
|
|
343
|
+
self.param_tree.sigTreeStateChanged.connect(self.change)
|
|
344
|
+
self.header().setSectionResizeMode(
|
|
345
|
+
QtWidgets.QHeaderView.ResizeMode.ResizeToContents
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
def remove_widget(self):
|
|
349
|
+
'''
|
|
350
|
+
Remove the widget from the parent layout.
|
|
351
|
+
|
|
352
|
+
This method removes the widget from the parent layout and deletes it.
|
|
353
|
+
'''
|
|
354
|
+
if self.parent() and not self.stage.isOpen():
|
|
355
|
+
self.parent().removeWidget(self)
|
|
356
|
+
self.removed.emit(self)
|
|
357
|
+
self.deleteLater()
|
|
358
|
+
else:
|
|
359
|
+
print(f'Disconnect FOC stage before removing!')
|
|
360
|
+
|
|
361
|
+
def __str__(self):
|
|
362
|
+
return f'Piezo Concept FOC Stage ({self.stage.serial.portName()})'
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
class PzFocController:
|
|
366
|
+
def __init__(self, stage: PzFoc = None, view: PzFocView = None):
|
|
367
|
+
'''
|
|
368
|
+
Initialize the PzFocController class.
|
|
369
|
+
|
|
370
|
+
This class controls the interaction between the PzFoc stage
|
|
371
|
+
and the PzFocView widget.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
stage: pz_foc
|
|
376
|
+
The stage to be controlled.
|
|
377
|
+
Default is a new PzFoc instance.
|
|
378
|
+
view: FOC_View
|
|
379
|
+
The GUI/view for the stage.
|
|
380
|
+
Default is a new PzFocView instance with the stage as an argument.
|
|
381
|
+
'''
|
|
382
|
+
self.stage = stage if stage else PzFoc()
|
|
383
|
+
self.view = view if view else PzFocView(stage=self.stage)
|
|
384
|
+
|
|
385
|
+
self.view.get_param(StageParams.JUMP_P).sigActivated.connect(
|
|
386
|
+
lambda: self.moveStage(
|
|
387
|
+
True, self.view.get_param_value(StageParams.JUMP) * 1000, True
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
self.view.get_param(StageParams.JUMP_N).sigActivated.connect(
|
|
391
|
+
lambda: self.moveStage(
|
|
392
|
+
False, self.view.get_param_value(StageParams.JUMP) * 1000, True
|
|
393
|
+
)
|
|
394
|
+
)
|
|
395
|
+
self.view.get_param(StageParams.STEP_P).sigActivated.connect(
|
|
396
|
+
lambda: self.moveStage(
|
|
397
|
+
True, self.view.get_param_value(StageParams.STEP), True
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
self.view.get_param(StageParams.STEP_N).sigActivated.connect(
|
|
401
|
+
lambda: self.moveStage(
|
|
402
|
+
False, self.view.get_param_value(StageParams.STEP), True
|
|
403
|
+
)
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
self.view.get_param(StageParams.SET_PORT).sigActivated.connect(self.set_config)
|
|
407
|
+
self.view.get_param(StageParams.OPEN).sigActivated.connect(
|
|
408
|
+
lambda: self.stage.open()
|
|
409
|
+
)
|
|
410
|
+
self.view.get_param(StageParams.CLOSE).sigActivated.connect(
|
|
411
|
+
lambda: self.stage.close()
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
self.view.get_param(StageParams.HOME).sigActivated.connect(self.stage.HOME)
|
|
415
|
+
self.view.get_param(StageParams.REFRESH).sigActivated.connect(
|
|
416
|
+
self.stage.REFRESH
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
self.stage.signals.positionChanged.connect(
|
|
420
|
+
lambda value: self.set_param_value(StageParams.Z_POSITION, value)
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def set_config(self):
|
|
424
|
+
'''Sets the serial port configuration.
|
|
425
|
+
|
|
426
|
+
This method sets the serial port configuration based on the current
|
|
427
|
+
settings in the parameter tree.
|
|
428
|
+
'''
|
|
429
|
+
if not self.stage.isOpen():
|
|
430
|
+
self.stage.setPortName(self.view.get_param_value(StageParams.PORT))
|
|
431
|
+
self.stage.setBaudRate(self.view.get_param_value(StageParams.BAUDRATE))
|
|
432
|
+
|
|
433
|
+
def setPortName(self, value: str):
|
|
434
|
+
'''
|
|
435
|
+
Set the name of the serial port.
|
|
436
|
+
|
|
437
|
+
Parameters
|
|
438
|
+
----------
|
|
439
|
+
value : str
|
|
440
|
+
The name of the serial port.
|
|
441
|
+
'''
|
|
442
|
+
self.stage.serial.setPortName(value)
|
|
443
|
+
self.view.set_param_value(StageParams.PORT, value)
|
|
444
|
+
|
|
445
|
+
def setBaudRate(self, value: int):
|
|
446
|
+
'''
|
|
447
|
+
Set the baud rate of the serial port.
|
|
448
|
+
|
|
449
|
+
Parameters
|
|
450
|
+
----------
|
|
451
|
+
value : int
|
|
452
|
+
The baud rate of the serial port.
|
|
453
|
+
'''
|
|
454
|
+
self.stage.serial.setBaudRate(value)
|
|
455
|
+
self.view.set_param_value(StageParams.BAUDRATE, value)
|
|
456
|
+
|
|
457
|
+
def connect(self):
|
|
458
|
+
'''
|
|
459
|
+
Opens the stage serial port.
|
|
460
|
+
'''
|
|
461
|
+
self.stage.open()
|
|
462
|
+
|
|
463
|
+
def disconnect(self):
|
|
464
|
+
'''
|
|
465
|
+
Closes the stage serial port.
|
|
466
|
+
'''
|
|
467
|
+
self.stage.close()
|
|
468
|
+
|
|
469
|
+
def isOpen(self):
|
|
470
|
+
'''
|
|
471
|
+
Check if the stage is open.
|
|
472
|
+
|
|
473
|
+
Returns
|
|
474
|
+
-------
|
|
475
|
+
bool
|
|
476
|
+
True if the stage is open, False otherwise.
|
|
477
|
+
'''
|
|
478
|
+
return self.stage.isOpen()
|
|
479
|
+
|
|
480
|
+
def getStep(self):
|
|
481
|
+
'''
|
|
482
|
+
Get the current step size.
|
|
483
|
+
|
|
484
|
+
Returns
|
|
485
|
+
-------
|
|
486
|
+
float
|
|
487
|
+
The current step size.
|
|
488
|
+
'''
|
|
489
|
+
return self.view.get_param_value(StageParams.STEP)
|
|
490
|
+
|
|
491
|
+
def setStep(self, value: float, incerement: bool = False):
|
|
492
|
+
'''
|
|
493
|
+
Set the step size.
|
|
494
|
+
|
|
495
|
+
Parameters
|
|
496
|
+
----------
|
|
497
|
+
value : float
|
|
498
|
+
The new step size value.
|
|
499
|
+
incerement : bool, optional
|
|
500
|
+
If True, increment the current step size value by the given value, otherwise
|
|
501
|
+
set the step size to the given value.
|
|
502
|
+
'''
|
|
503
|
+
if incerement:
|
|
504
|
+
step = self.view.get_param_value(StageParams.STEP)
|
|
505
|
+
self.view.set_param_value(StageParams.STEP, step + value)
|
|
506
|
+
else:
|
|
507
|
+
self.view.set_param_value(StageParams.STEP, value)
|
|
508
|
+
|
|
509
|
+
def moveAbsolute(self, pos: int):
|
|
510
|
+
'''
|
|
511
|
+
Move the stage to an absolute position.
|
|
512
|
+
|
|
513
|
+
Parameters
|
|
514
|
+
----------
|
|
515
|
+
pos : int
|
|
516
|
+
The absolute position to move to in nanometers.
|
|
517
|
+
'''
|
|
518
|
+
focusStabilizer = FocusStabilizer.instance()
|
|
519
|
+
if focusStabilizer is not None and focusStabilizer.isFocusStabilized():
|
|
520
|
+
return
|
|
521
|
+
|
|
522
|
+
self.stage.ABSOLUTE(pos)
|
|
523
|
+
|
|
524
|
+
def moveStage(self, dir: bool, step_arg: Union[int, bool], interface: bool = False):
|
|
525
|
+
'''
|
|
526
|
+
Move the stage in a specified direction by a specified
|
|
527
|
+
number of steps in nanometers. Optional boolean argument
|
|
528
|
+
to specify jump or step move. If FocusStabilizer is stabilizing
|
|
529
|
+
and use calibration is set to True, moves the center pixel value
|
|
530
|
+
instead of the Z position when `interface` is True.
|
|
531
|
+
|
|
532
|
+
Parameters
|
|
533
|
+
----------
|
|
534
|
+
dir: bool
|
|
535
|
+
Direction of the movement. If True, moves the stage up, else moves it down.
|
|
536
|
+
step_arg: Union[int, bool]
|
|
537
|
+
Number of steps to move in the specified direction.
|
|
538
|
+
If provided as a `bool`:
|
|
539
|
+
- `True`: Moves the stage by the value of the JUMP parameter.
|
|
540
|
+
- `False`: Moves the stage by the value of the STEP parameter.
|
|
541
|
+
interface : bool, optional
|
|
542
|
+
If True, moves the center pixel value instead of the Z position
|
|
543
|
+
when FocusStabilizer is stabilizing and use calibration is set to True.
|
|
544
|
+
'''
|
|
545
|
+
if isinstance(step_arg, bool):
|
|
546
|
+
if step_arg:
|
|
547
|
+
step_arg = 1000 * self.view.get_param_value(StageParams.JUMP)
|
|
548
|
+
else:
|
|
549
|
+
step_arg = self.view.get_param_value(StageParams.STEP)
|
|
550
|
+
|
|
551
|
+
focusStabilizer = FocusStabilizer.instance()
|
|
552
|
+
if (
|
|
553
|
+
focusStabilizer is not None
|
|
554
|
+
and focusStabilizer.isFocusStabilized()
|
|
555
|
+
and focusStabilizer.useCal()
|
|
556
|
+
and interface
|
|
557
|
+
):
|
|
558
|
+
sign = 1 if dir else -1
|
|
559
|
+
focusStabilizer.setPeakPosition(
|
|
560
|
+
focusStabilizer.pixelCalCoeff() * step_arg * sign, True
|
|
561
|
+
)
|
|
562
|
+
else:
|
|
563
|
+
self.stage.UP(step_arg) if dir else self.stage.DOWN(step_arg)
|
|
564
|
+
|
|
565
|
+
def updatePortState(self):
|
|
566
|
+
'''
|
|
567
|
+
Update the port state in the parameter tree.
|
|
568
|
+
|
|
569
|
+
This method updates the port state in the parameter tree
|
|
570
|
+
to reflect the current state of the serial port.
|
|
571
|
+
'''
|
|
572
|
+
self.view.set_param_value(
|
|
573
|
+
StageParams.PORT_STATE, 'open' if self.isOpen() else 'closed'
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
def refreshPorts(self):
|
|
577
|
+
"""
|
|
578
|
+
Refreshes the available serial ports list in the GUI.
|
|
579
|
+
|
|
580
|
+
This method updates the list of available serial ports in the GUI by fetching
|
|
581
|
+
the current list of available ports and setting it as the options for the
|
|
582
|
+
'QSerial Port' parameter in the parameter tree.
|
|
583
|
+
"""
|
|
584
|
+
if not self.isOpen():
|
|
585
|
+
self.view.get_param(StageParams.PORT).setLimits(
|
|
586
|
+
[
|
|
587
|
+
info.portName()
|
|
588
|
+
for info in QtSerialPort.QSerialPortInfo.availablePorts()
|
|
589
|
+
]
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
def get_config(self) -> dict:
|
|
593
|
+
'''Get the current configuration of the stage.'''
|
|
594
|
+
return {
|
|
595
|
+
'port': self.stage.serial.portName(),
|
|
596
|
+
'baudrate': self.stage.serial.baudRate(),
|
|
597
|
+
'max_um': self.stage.max_um,
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
def load_config(self, config: dict) -> None:
|
|
601
|
+
'''Load the configuration of the stage from a dictionary.'''
|
|
602
|
+
self.stage.setPortName(config.get('port', 'COM5'))
|
|
603
|
+
self.stage.setBaudRate(config.get('baudrate', 115200))
|
|
604
|
+
self.stage.max_um = config.get('max_um', 100)
|
|
605
|
+
|
|
606
|
+
def __str__(self):
|
|
607
|
+
return 'Piezo Concept FOC Stage Controller'
|