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,533 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
import weakref
|
|
3
|
+
from enum import Enum, auto
|
|
4
|
+
from typing import Any, Union
|
|
5
|
+
|
|
6
|
+
from microEye.hardware.cams import *
|
|
7
|
+
from microEye.hardware.lasers import *
|
|
8
|
+
from microEye.hardware.protocols import WeakObjects
|
|
9
|
+
from microEye.hardware.pycromanager.devices import PycroCore
|
|
10
|
+
from microEye.hardware.pycromanager.headless import HeadlessInstance, HeadlessManager
|
|
11
|
+
from microEye.hardware.stages import *
|
|
12
|
+
from microEye.hardware.widgets import focusWidget
|
|
13
|
+
from microEye.qt import QtCore, QtWidgets, Signal
|
|
14
|
+
from microEye.utils.hid import Buttons, dz_hybrid, hidController
|
|
15
|
+
from microEye.utils.retry_exec import retry_exec
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DEVICES(Enum):
|
|
19
|
+
CAM_LIST = auto()
|
|
20
|
+
CAMERA = auto()
|
|
21
|
+
ELLIPTEC = auto()
|
|
22
|
+
FocusStabilizer = auto()
|
|
23
|
+
HID_CONTROLLER = auto()
|
|
24
|
+
IR_CAM = auto()
|
|
25
|
+
LASER = auto()
|
|
26
|
+
LASER_RELAY = auto()
|
|
27
|
+
XY_STAGE = auto()
|
|
28
|
+
Z_STAGE = auto()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class DeviceManager(QtCore.QObject):
|
|
32
|
+
widgetAdded = Signal(DEVICES, QtWidgets.QWidget)
|
|
33
|
+
widgetRemoved = Signal(DEVICES, QtWidgets.QWidget)
|
|
34
|
+
|
|
35
|
+
WIDGETS = weakref.WeakValueDictionary()
|
|
36
|
+
CONTROLLERS = weakref.WeakValueDictionary()
|
|
37
|
+
|
|
38
|
+
def __new__(cls, *args, **kwargs):
|
|
39
|
+
# If the single instance doesn't exist, create a new one
|
|
40
|
+
if not hasattr(cls, '_singleton') or cls._singleton is None:
|
|
41
|
+
cls._singleton = super().__new__(cls, *args)
|
|
42
|
+
# Return the single instance
|
|
43
|
+
return cls._singleton
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def instance(cls):
|
|
47
|
+
if not hasattr(cls, '_singleton') or cls._singleton is None:
|
|
48
|
+
return DeviceManager()
|
|
49
|
+
|
|
50
|
+
return cls._singleton
|
|
51
|
+
|
|
52
|
+
def __init__(self):
|
|
53
|
+
if not hasattr(self, '_initialized'):
|
|
54
|
+
super().__init__()
|
|
55
|
+
self.cameras = []
|
|
56
|
+
self.stages = []
|
|
57
|
+
self.lasers: list[Union[SingleMatchBox, CombinerLaserWidget]] = []
|
|
58
|
+
|
|
59
|
+
self._initialized = True
|
|
60
|
+
|
|
61
|
+
def init_devices(self):
|
|
62
|
+
self._init_cameras_list()
|
|
63
|
+
self._init_ir_cam()
|
|
64
|
+
self._init_laser_relay()
|
|
65
|
+
self._init_z_stage()
|
|
66
|
+
self._init_xy_stage()
|
|
67
|
+
self._init_elliptec_devices()
|
|
68
|
+
self._init_hid_controller()
|
|
69
|
+
self._init_focus_stabilizer()
|
|
70
|
+
|
|
71
|
+
def _init_cameras_list(self):
|
|
72
|
+
self.camList = CameraList()
|
|
73
|
+
self.camList.cameraAdded.connect(self._add_camera)
|
|
74
|
+
self.camList.cameraRemoved.connect(self._remove_camera)
|
|
75
|
+
|
|
76
|
+
self.widgetAdded.emit(DEVICES.CAM_LIST, self.camList)
|
|
77
|
+
|
|
78
|
+
def _init_ir_cam(self):
|
|
79
|
+
self.ir_array_detector = None
|
|
80
|
+
|
|
81
|
+
def _init_laser_relay(self):
|
|
82
|
+
self.laser_relay = LaserRelayController()
|
|
83
|
+
self.laser_relay.sendCommandActivated.connect(
|
|
84
|
+
lambda: self.laser_relay.sendCommand(self.laser_relay_settings())
|
|
85
|
+
)
|
|
86
|
+
DeviceManager.WIDGETS[DEVICES.LASER_RELAY] = self.laser_relay.view
|
|
87
|
+
WeakObjects.addObject(self.laser_relay)
|
|
88
|
+
self.widgetAdded.emit(DEVICES.LASER_RELAY, self.laser_relay.view)
|
|
89
|
+
|
|
90
|
+
def _init_elliptec_devices(self):
|
|
91
|
+
self._add_elliptec_devices()
|
|
92
|
+
|
|
93
|
+
def _add_elliptec_devices(self):
|
|
94
|
+
self.elliptec = ELLDevices()
|
|
95
|
+
self.elliptecView = ElliptecView(elleptic=self.elliptec)
|
|
96
|
+
DeviceManager.WIDGETS[DEVICES.ELLIPTEC] = self.elliptecView
|
|
97
|
+
WeakObjects.addObject(self.elliptecView)
|
|
98
|
+
self.widgetAdded.emit(DEVICES.ELLIPTEC, self.elliptecView)
|
|
99
|
+
|
|
100
|
+
def _init_z_stage(self):
|
|
101
|
+
self.stage: PzFocController = None
|
|
102
|
+
|
|
103
|
+
self._set_z_stage('FOC100')
|
|
104
|
+
|
|
105
|
+
def _init_xy_stage(self):
|
|
106
|
+
self.stage_xy = KinesisXY()
|
|
107
|
+
view = self.stage_xy.getViewWidget()
|
|
108
|
+
DeviceManager.WIDGETS[DEVICES.XY_STAGE] = view
|
|
109
|
+
WeakObjects.addObject(view)
|
|
110
|
+
self.widgetAdded.emit(DEVICES.XY_STAGE, view)
|
|
111
|
+
|
|
112
|
+
def _init_hid_controller(self):
|
|
113
|
+
self.hid_controller = hidController()
|
|
114
|
+
self.hid_controller.reportEvent.connect(self.hid_report)
|
|
115
|
+
# self.hid_controller.reportRStickPosition.connect(self.hid_RStick_report)
|
|
116
|
+
# self.hid_controller.reportLStickPosition.connect(self.hid_LStick_report)
|
|
117
|
+
self.hid_controller_toggle = False
|
|
118
|
+
|
|
119
|
+
self.widgetAdded.emit(DEVICES.HID_CONTROLLER, self.hid_controller)
|
|
120
|
+
|
|
121
|
+
def _init_focus_stabilizer(self):
|
|
122
|
+
FocusStabilizer.instance().moveStage.connect(self.moveStage)
|
|
123
|
+
FocusStabilizer.instance().startWorker()
|
|
124
|
+
|
|
125
|
+
self.focus = focusWidget()
|
|
126
|
+
DeviceManager.WIDGETS[DEVICES.FocusStabilizer] = self.focus
|
|
127
|
+
WeakObjects.addObject(self.focus)
|
|
128
|
+
|
|
129
|
+
self.widgetAdded.emit(DEVICES.FocusStabilizer, self.focus)
|
|
130
|
+
|
|
131
|
+
def moveStage(self, dir: bool, steps: int):
|
|
132
|
+
if isinstance(self.stage, PzFocController):
|
|
133
|
+
self.stage.moveStage(dir, steps)
|
|
134
|
+
|
|
135
|
+
def moveStageXY(self, x: float, y: float):
|
|
136
|
+
if isinstance(self.stage_xy, KinesisXY):
|
|
137
|
+
self.stage_xy.move_relative(x, y)
|
|
138
|
+
|
|
139
|
+
def stopRequest(self, axis):
|
|
140
|
+
if axis in ['x', 'y', 'xy']:
|
|
141
|
+
self.stage_xy.stop()
|
|
142
|
+
|
|
143
|
+
def homeRequest(self, axis):
|
|
144
|
+
if axis == 'z':
|
|
145
|
+
self.stage.stage.HOME()
|
|
146
|
+
|
|
147
|
+
def toggleLock(self, axis):
|
|
148
|
+
if axis == 'z':
|
|
149
|
+
widget: focusWidget = DeviceManager.WIDGETS.get(DEVICES.FocusStabilizer)
|
|
150
|
+
if widget:
|
|
151
|
+
widget.focusStabilizerView.toggleFocusStabilization()
|
|
152
|
+
|
|
153
|
+
def moveRequest(self, axis, direction, step, relative=True):
|
|
154
|
+
"""
|
|
155
|
+
Move the stage in the specified direction and step size.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
axis : str
|
|
160
|
+
The axis to move ('x', 'y', or 'z').
|
|
161
|
+
direction : bool
|
|
162
|
+
The direction to move (True for positive, False for negative).
|
|
163
|
+
step : int
|
|
164
|
+
The step size for the movement.
|
|
165
|
+
relative : bool, optional
|
|
166
|
+
Whether to move relative to the current position (default is True).
|
|
167
|
+
"""
|
|
168
|
+
if axis in ['x', 'y']:
|
|
169
|
+
dist = direction * step
|
|
170
|
+
args = [dist, 0] if axis == 'x' else [0, dist]
|
|
171
|
+
if relative:
|
|
172
|
+
self.stage_xy.move_relative(*args)
|
|
173
|
+
else:
|
|
174
|
+
self.stage_xy.move_absolute(*args)
|
|
175
|
+
else:
|
|
176
|
+
if relative:
|
|
177
|
+
self.stage.moveStage(
|
|
178
|
+
direction > 0, step, interface=True
|
|
179
|
+
) if self.stage else None
|
|
180
|
+
else:
|
|
181
|
+
self.stage.moveAbsolute(step)
|
|
182
|
+
|
|
183
|
+
def hid_report(self, reportedEvent: Buttons):
|
|
184
|
+
self._handle_z_stage_events(reportedEvent)
|
|
185
|
+
self._handle_xy_stage_events(reportedEvent)
|
|
186
|
+
|
|
187
|
+
def _handle_z_stage_events(self, reportedEvent: Buttons):
|
|
188
|
+
if isinstance(self.stage, PzFocController):
|
|
189
|
+
if reportedEvent == Buttons.X:
|
|
190
|
+
self.stage.moveStage(True, True, True)
|
|
191
|
+
elif reportedEvent == Buttons.B:
|
|
192
|
+
self.stage.moveStage(False, True, True)
|
|
193
|
+
elif reportedEvent == Buttons.Y:
|
|
194
|
+
self.stage.moveStage(True, False, True)
|
|
195
|
+
elif reportedEvent == Buttons.A:
|
|
196
|
+
self.stage.moveStage(False, False, True)
|
|
197
|
+
elif reportedEvent == Buttons.Options:
|
|
198
|
+
self.stage.stage.HOME()
|
|
199
|
+
elif reportedEvent == Buttons.R3:
|
|
200
|
+
self.hid_controller_toggle = not self.hid_controller_toggle
|
|
201
|
+
|
|
202
|
+
def _handle_xy_stage_events(self, reportedEvent: Buttons):
|
|
203
|
+
kinesisView: KinesisView = DeviceManager.WIDGETS[DEVICES.XY_STAGE]
|
|
204
|
+
|
|
205
|
+
if reportedEvent == Buttons.LEFT:
|
|
206
|
+
kinesisView.move(True, self.hid_controller_toggle, False)
|
|
207
|
+
elif reportedEvent == Buttons.RIGHT:
|
|
208
|
+
kinesisView.move(True, self.hid_controller_toggle, True)
|
|
209
|
+
elif reportedEvent == Buttons.UP:
|
|
210
|
+
kinesisView.move(False, self.hid_controller_toggle, True)
|
|
211
|
+
elif reportedEvent == Buttons.DOWN:
|
|
212
|
+
kinesisView.move(False, self.hid_controller_toggle, False)
|
|
213
|
+
elif reportedEvent == Buttons.R1:
|
|
214
|
+
pass
|
|
215
|
+
# kinesisView.center()
|
|
216
|
+
elif reportedEvent == Buttons.L1:
|
|
217
|
+
kinesisView.stop()
|
|
218
|
+
elif reportedEvent == Buttons.L3:
|
|
219
|
+
self._toggle_xy_step_or_jump(kinesisView)
|
|
220
|
+
|
|
221
|
+
def _toggle_xy_step_or_jump(self, kinesisView: KinesisView):
|
|
222
|
+
self.hid_controller_toggle = not self.hid_controller_toggle
|
|
223
|
+
kinesisView.updateControls(self.hid_controller_toggle)
|
|
224
|
+
|
|
225
|
+
def hid_LStick_report(self, x, y):
|
|
226
|
+
diff_x = x - 128
|
|
227
|
+
diff_y = y - 127
|
|
228
|
+
deadzone = 16
|
|
229
|
+
res = dz_hybrid([diff_x, diff_y], deadzone)
|
|
230
|
+
diff = res[1]
|
|
231
|
+
|
|
232
|
+
kinesisView: KinesisView = DeviceManager.WIDGETS[DEVICES.XY_STAGE]
|
|
233
|
+
|
|
234
|
+
self._update_step_or_jump_spin(kinesisView, diff)
|
|
235
|
+
|
|
236
|
+
if abs(diff) > 0:
|
|
237
|
+
if self.hid_controller_toggle:
|
|
238
|
+
val = 0.0001 * diff
|
|
239
|
+
val += kinesisView.getJump()
|
|
240
|
+
kinesisView.setJump(val)
|
|
241
|
+
else:
|
|
242
|
+
val = 0.0001 * diff
|
|
243
|
+
val += kinesisView.getStep()
|
|
244
|
+
kinesisView.setStep(val)
|
|
245
|
+
else:
|
|
246
|
+
if self.hid_controller_toggle:
|
|
247
|
+
val = kinesisView.getJump()
|
|
248
|
+
val -= val % 0.0005
|
|
249
|
+
kinesisView.setJump(val)
|
|
250
|
+
else:
|
|
251
|
+
val = kinesisView.getJump()
|
|
252
|
+
val -= val % 0.0005
|
|
253
|
+
kinesisView.setJump(val)
|
|
254
|
+
|
|
255
|
+
def _update_step_or_jump_spin(self, kinesisView: KinesisView, diff):
|
|
256
|
+
current_value = (
|
|
257
|
+
kinesisView.getJump()
|
|
258
|
+
if self.hid_controller_toggle
|
|
259
|
+
else kinesisView.getStep()
|
|
260
|
+
)
|
|
261
|
+
if abs(diff) > 0:
|
|
262
|
+
new_value = current_value + 0.0001 * diff
|
|
263
|
+
else:
|
|
264
|
+
new_value = current_value - (current_value % 0.0005)
|
|
265
|
+
if self.hid_controller_toggle:
|
|
266
|
+
kinesisView.setJump(new_value)
|
|
267
|
+
else:
|
|
268
|
+
kinesisView.setStep(new_value)
|
|
269
|
+
|
|
270
|
+
def hid_RStick_report(self, x, y):
|
|
271
|
+
diff_x = x - 128
|
|
272
|
+
diff_y = y - 127
|
|
273
|
+
deadzone = 16
|
|
274
|
+
res = dz_hybrid([diff_x, diff_y], deadzone)
|
|
275
|
+
diff = res[1]
|
|
276
|
+
|
|
277
|
+
if self.hid_controller_toggle:
|
|
278
|
+
self._handle_focus_stabilization(diff)
|
|
279
|
+
else:
|
|
280
|
+
self._handle_z_stage_step(diff)
|
|
281
|
+
|
|
282
|
+
def _handle_focus_stabilization(self, diff):
|
|
283
|
+
if FocusStabilizer.instance().isFocusStabilized():
|
|
284
|
+
value = 1e-3 * diff
|
|
285
|
+
FocusStabilizer.instance().setPeakPosition(value, True)
|
|
286
|
+
|
|
287
|
+
def _handle_z_stage_step(self, diff):
|
|
288
|
+
if abs(diff) > 0 and abs(diff) < 100:
|
|
289
|
+
value = 0.25 * diff
|
|
290
|
+
self.stage.setStep(value, True)
|
|
291
|
+
else:
|
|
292
|
+
value = self.stage.getStep()
|
|
293
|
+
value -= value % 5
|
|
294
|
+
self.stage.setStep(value)
|
|
295
|
+
|
|
296
|
+
# gui + hardware
|
|
297
|
+
|
|
298
|
+
def _add_laser(self, laser: str):
|
|
299
|
+
if (
|
|
300
|
+
'IO MatchBox' in laser and 'Combiner' in laser
|
|
301
|
+
) or CombinerLaserWidget.__name__ in laser:
|
|
302
|
+
widget = CombinerLaserWidget()
|
|
303
|
+
elif (
|
|
304
|
+
'IO MatchBox' in laser and 'Single' in laser
|
|
305
|
+
) or SingleMatchBox.__name__ in laser:
|
|
306
|
+
widget = SingleMatchBox()
|
|
307
|
+
else:
|
|
308
|
+
raise ValueError(f'Unknown laser type: {laser}')
|
|
309
|
+
|
|
310
|
+
self.lasers.append(widget)
|
|
311
|
+
WeakObjects.addObject(widget)
|
|
312
|
+
|
|
313
|
+
widget.removed.connect(lambda: self._laser_removed(widget))
|
|
314
|
+
|
|
315
|
+
self.widgetAdded.emit(DEVICES.LASER, widget)
|
|
316
|
+
|
|
317
|
+
return widget
|
|
318
|
+
|
|
319
|
+
def _laser_removed(self, widget: QtWidgets.QWidget):
|
|
320
|
+
WeakObjects.removeObject(widget)
|
|
321
|
+
if widget in self.lasers:
|
|
322
|
+
self.lasers.remove(widget)
|
|
323
|
+
self.widgetRemoved.emit(DEVICES.LASER, widget)
|
|
324
|
+
|
|
325
|
+
def _add_camera(self, widget: Camera_Panel, ir: bool):
|
|
326
|
+
if ir:
|
|
327
|
+
widget._frames = FocusStabilizer.instance().buffer
|
|
328
|
+
|
|
329
|
+
self.widgetAdded.emit(DEVICES.IR_CAM, widget)
|
|
330
|
+
|
|
331
|
+
else:
|
|
332
|
+
widget.setWindowTitle(widget.title())
|
|
333
|
+
widget.show()
|
|
334
|
+
|
|
335
|
+
WeakObjects.addObject(widget)
|
|
336
|
+
|
|
337
|
+
def _remove_camera(self, widget: QtWidgets.QWidget, ir: bool):
|
|
338
|
+
WeakObjects.removeObject(widget)
|
|
339
|
+
if ir:
|
|
340
|
+
self.widgetRemoved.emit(DEVICES.IR_CAM, widget)
|
|
341
|
+
|
|
342
|
+
def _set_ir_array_detector(self, value: str):
|
|
343
|
+
if self.camList.autofocusCam:
|
|
344
|
+
title = self.camList.autofocusCam.title()
|
|
345
|
+
QtWidgets.QMessageBox.warning(
|
|
346
|
+
self,
|
|
347
|
+
'Warning',
|
|
348
|
+
f'Please remove {title}.',
|
|
349
|
+
QtWidgets.QMessageBox.StandardButton.Ok,
|
|
350
|
+
)
|
|
351
|
+
return
|
|
352
|
+
|
|
353
|
+
if self.ir_array_detector and self.ir_array_detector.isOpen:
|
|
354
|
+
QtWidgets.QMessageBox.warning(
|
|
355
|
+
self,
|
|
356
|
+
'Warning',
|
|
357
|
+
f'Please disconnect {self.ir_array_detector.name}.',
|
|
358
|
+
QtWidgets.QMessageBox.StandardButton.Ok,
|
|
359
|
+
)
|
|
360
|
+
return
|
|
361
|
+
|
|
362
|
+
if 'TSL1401' in value:
|
|
363
|
+
self.ir_array_detector = ParallaxLineScanner(
|
|
364
|
+
FocusStabilizer.instance().buffer
|
|
365
|
+
)
|
|
366
|
+
widget = self.ir_array_detector.getQWidget()
|
|
367
|
+
self.widgetAdded.emit(DEVICES.IR_CAM, widget)
|
|
368
|
+
DeviceManager.WIDGETS[DEVICES.IR_CAM] = widget
|
|
369
|
+
elif 'Demo Line Scanner' in value:
|
|
370
|
+
self.ir_array_detector = DemoLineScanner(FocusStabilizer.instance().buffer)
|
|
371
|
+
widget = self.ir_array_detector.getQWidget()
|
|
372
|
+
self.widgetAdded.emit(DEVICES.IR_CAM, widget)
|
|
373
|
+
DeviceManager.WIDGETS[DEVICES.IR_CAM] = widget
|
|
374
|
+
|
|
375
|
+
def _remove_ir_array_detector(self):
|
|
376
|
+
if self.ir_array_detector.isOpen:
|
|
377
|
+
QtWidgets.QMessageBox.warning(
|
|
378
|
+
self,
|
|
379
|
+
'Warning',
|
|
380
|
+
f'Please disconnect {self.ir_array_detector.name}.',
|
|
381
|
+
QtWidgets.QMessageBox.StandardButton.Ok,
|
|
382
|
+
)
|
|
383
|
+
return
|
|
384
|
+
|
|
385
|
+
self.widgetRemoved.emit(DEVICES.IR_CAM, DeviceManager.WIDGETS[DEVICES.IR_CAM])
|
|
386
|
+
self.ir_array_detector = None
|
|
387
|
+
|
|
388
|
+
def _set_z_stage(self, value: str):
|
|
389
|
+
if self.stage and self.stage.isOpen():
|
|
390
|
+
QtWidgets.QMessageBox.warning(
|
|
391
|
+
None,
|
|
392
|
+
'Warning',
|
|
393
|
+
f'Please disconnect {self.stage}.',
|
|
394
|
+
QtWidgets.QMessageBox.StandardButton.Ok,
|
|
395
|
+
)
|
|
396
|
+
return
|
|
397
|
+
|
|
398
|
+
if self.stage:
|
|
399
|
+
self.stage.view.remove_widget()
|
|
400
|
+
|
|
401
|
+
if 'FOC100' in value:
|
|
402
|
+
self.stage = PzFocController()
|
|
403
|
+
self.stage.view.removed.connect(self._remove_z_stage)
|
|
404
|
+
DeviceManager.WIDGETS[DEVICES.Z_STAGE] = self.stage.view
|
|
405
|
+
WeakObjects.addObject(self.stage.view)
|
|
406
|
+
self.widgetAdded.emit(DEVICES.Z_STAGE, self.stage.view)
|
|
407
|
+
|
|
408
|
+
def _remove_z_stage(self, panel: QtWidgets.QWidget):
|
|
409
|
+
DeviceManager.WIDGETS[DEVICES.Z_STAGE] = None
|
|
410
|
+
WeakObjects.removeObject(panel)
|
|
411
|
+
self.widgetRemoved.emit(DEVICES.Z_STAGE, panel)
|
|
412
|
+
|
|
413
|
+
def laser_relay_settings(self):
|
|
414
|
+
'''Returns the RelayBox setting command.
|
|
415
|
+
|
|
416
|
+
Returns
|
|
417
|
+
-------
|
|
418
|
+
str
|
|
419
|
+
the RelayBox setting command.
|
|
420
|
+
'''
|
|
421
|
+
config = ''
|
|
422
|
+
for panel in self.lasers:
|
|
423
|
+
config += panel.GetRelayState()
|
|
424
|
+
return self.laser_relay.getCommand(config)
|
|
425
|
+
|
|
426
|
+
def _get_laser_configs(self) -> dict:
|
|
427
|
+
'''
|
|
428
|
+
Returns the laser configurations.
|
|
429
|
+
|
|
430
|
+
Returns
|
|
431
|
+
-------
|
|
432
|
+
list
|
|
433
|
+
list of laser configurations.
|
|
434
|
+
'''
|
|
435
|
+
configs = []
|
|
436
|
+
for panel in self.lasers:
|
|
437
|
+
configs.append(panel.get_config())
|
|
438
|
+
|
|
439
|
+
return configs
|
|
440
|
+
|
|
441
|
+
def get_config(self) -> dict:
|
|
442
|
+
config = {
|
|
443
|
+
'LaserRelay': self.laser_relay.get_config(),
|
|
444
|
+
'Elliptec': self.elliptec.get_config(),
|
|
445
|
+
'Stage Z': self.stage.get_config(),
|
|
446
|
+
'Stage XY': self.stage_xy.get_config(),
|
|
447
|
+
'FocusStabilizer': self.focus.get_config(),
|
|
448
|
+
'Pycromanager': {
|
|
449
|
+
'core_instances': list(PycroCore._instances.keys()),
|
|
450
|
+
'headless_instances': HeadlessManager()._instances,
|
|
451
|
+
},
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
config['Lasers'] = self._get_laser_configs()
|
|
455
|
+
|
|
456
|
+
return config
|
|
457
|
+
|
|
458
|
+
def load_config(self, config: dict):
|
|
459
|
+
self.laser_relay.load_config(config.get('LaserRelay', {}))
|
|
460
|
+
self.elliptec.load_config(config.get('Elliptec', {}))
|
|
461
|
+
self.stage.load_config(
|
|
462
|
+
config.get('PiezoStage', {})
|
|
463
|
+
if 'PiezoStage' in config
|
|
464
|
+
else config.get('Stage Z', {})
|
|
465
|
+
)
|
|
466
|
+
self.stage_xy.load_config(config.get('Stage XY', {}))
|
|
467
|
+
self.focus.load_config(config.get('FocusStabilizer', {}))
|
|
468
|
+
|
|
469
|
+
while len(self.lasers) > 0:
|
|
470
|
+
panel = self.lasers.pop()
|
|
471
|
+
panel.Laser.CloseCOM()
|
|
472
|
+
panel.remove_widget()
|
|
473
|
+
|
|
474
|
+
for laser in config.get('Lasers', []):
|
|
475
|
+
laser_widget = self._add_laser(laser.get('class'))
|
|
476
|
+
laser_widget.load_config(laser)
|
|
477
|
+
|
|
478
|
+
try:
|
|
479
|
+
pycro_config: dict = config.get('Pycromanager', {})
|
|
480
|
+
|
|
481
|
+
core_instances: list[int] = pycro_config.get('core_instances', [])
|
|
482
|
+
for port in core_instances:
|
|
483
|
+
PycroCore.instance(int(port))
|
|
484
|
+
|
|
485
|
+
headless_instances: dict[int, dict] = pycro_config.get(
|
|
486
|
+
'headless_instances', {}
|
|
487
|
+
)
|
|
488
|
+
for _, instance in headless_instances.items():
|
|
489
|
+
HeadlessManager().start_instance(HeadlessInstance(**instance))
|
|
490
|
+
except Exception:
|
|
491
|
+
traceback.print_exc()
|
|
492
|
+
|
|
493
|
+
def auto_connect(self):
|
|
494
|
+
funcs = [
|
|
495
|
+
self.laser_relay.connect,
|
|
496
|
+
self.elliptecView.open,
|
|
497
|
+
self.stage.connect,
|
|
498
|
+
self.stage_xy.open,
|
|
499
|
+
]
|
|
500
|
+
|
|
501
|
+
for panel in self.lasers:
|
|
502
|
+
funcs.append(panel.laser_connect)
|
|
503
|
+
|
|
504
|
+
for func in funcs:
|
|
505
|
+
retry_exec(func)
|
|
506
|
+
|
|
507
|
+
def shutdown(self, exit=True):
|
|
508
|
+
'''Disconnects all devices and exits the application.'''
|
|
509
|
+
|
|
510
|
+
if self.camList.autofocusCam:
|
|
511
|
+
self.camList.autofocusCam.stop()
|
|
512
|
+
|
|
513
|
+
funcs = [
|
|
514
|
+
self.camList.removeAllCameras,
|
|
515
|
+
self.laser_relay.disconnect,
|
|
516
|
+
self.elliptecView.close,
|
|
517
|
+
self.stage.disconnect,
|
|
518
|
+
self.stage_xy.close,
|
|
519
|
+
]
|
|
520
|
+
|
|
521
|
+
for panel in self.lasers:
|
|
522
|
+
funcs.append(panel.Laser.CloseCOM)
|
|
523
|
+
|
|
524
|
+
for func in funcs:
|
|
525
|
+
retry_exec(func)
|
|
526
|
+
|
|
527
|
+
print('All devices disconnected!')
|
|
528
|
+
if not exit:
|
|
529
|
+
return
|
|
530
|
+
|
|
531
|
+
import sys
|
|
532
|
+
|
|
533
|
+
sys.exit(0)
|