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,467 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import threading
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
import cv2
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pyqtgraph as pg
|
|
8
|
+
import tabulate
|
|
9
|
+
import tifffile as tf
|
|
10
|
+
|
|
11
|
+
from microEye.hardware.cams import *
|
|
12
|
+
from microEye.hardware.mieye.devices_manager import DeviceManager
|
|
13
|
+
from microEye.hardware.protocols import WeakObjects
|
|
14
|
+
from microEye.hardware.stages import FocusStabilizer, KinesisView
|
|
15
|
+
from microEye.hardware.widgets import (
|
|
16
|
+
ScanAcquisitionWidget,
|
|
17
|
+
TiledImageSelector,
|
|
18
|
+
TileImage,
|
|
19
|
+
)
|
|
20
|
+
from microEye.qt import (
|
|
21
|
+
QtCore,
|
|
22
|
+
Signal,
|
|
23
|
+
)
|
|
24
|
+
from microEye.utils.thread_worker import QThreadWorker
|
|
25
|
+
from microEye.utils.uImage import uImage
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AcquisitionManager(QtCore.QObject):
|
|
29
|
+
acquisitionStarted = Signal()
|
|
30
|
+
acquisitionFinished = Signal(object)
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
super().__init__()
|
|
34
|
+
|
|
35
|
+
self.acquisitionWidget = ScanAcquisitionWidget()
|
|
36
|
+
WeakObjects.addObject(self.acquisitionWidget)
|
|
37
|
+
|
|
38
|
+
self._init_acquisition_signals()
|
|
39
|
+
|
|
40
|
+
self.lastTile = None
|
|
41
|
+
self.scan_worker = None
|
|
42
|
+
self._stop_scan = False
|
|
43
|
+
self._scanning = False
|
|
44
|
+
|
|
45
|
+
def _init_acquisition_signals(self):
|
|
46
|
+
self.acquisitionWidget.startAcquisitionXY.connect(self.start_scan_acquisitionXY)
|
|
47
|
+
self.acquisitionWidget.startAcquisitionZ.connect(self.start_scan_acquisitionZ)
|
|
48
|
+
self.acquisitionWidget.startCalibrationZ.connect(self.start_calibration_Z)
|
|
49
|
+
self.acquisitionWidget.stopAcquisitionXY.connect(self.stop_scan_acquisition)
|
|
50
|
+
self.acquisitionWidget.stopAcquisitionZ.connect(self.stop_scan_acquisition)
|
|
51
|
+
self.acquisitionWidget.openLastTileXY.connect(self.show_last_tile)
|
|
52
|
+
self.acquisitionWidget.directoryChanged.connect(self.update_directories)
|
|
53
|
+
self.acquisitionWidget.moveZ.connect(DeviceManager.instance().moveStage)
|
|
54
|
+
|
|
55
|
+
def result_scan_acquisition(self, data):
|
|
56
|
+
self._scanning = False
|
|
57
|
+
self.acquisitionWidget.setActionsStatus(True)
|
|
58
|
+
|
|
59
|
+
if data:
|
|
60
|
+
self.lastTile = TiledImageSelector(data)
|
|
61
|
+
self._connect_tile_position_signal(self.lastTile)
|
|
62
|
+
self.lastTile.show()
|
|
63
|
+
|
|
64
|
+
def _connect_tile_position_signal(self, tile: TiledImageSelector):
|
|
65
|
+
tile.positionSelected.connect(
|
|
66
|
+
lambda x, y: DeviceManager.instance().stage_xy.move_absolute(x, y)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def result_z_calibration(self, data):
|
|
70
|
+
self._scanning = False
|
|
71
|
+
self.acquisitionWidget.setActionsStatus(True)
|
|
72
|
+
|
|
73
|
+
if data is not None:
|
|
74
|
+
coeff = np.polyfit(data[:, 0], data[:, 1], 1)
|
|
75
|
+
FocusStabilizer.instance().setPixelCalCoeff(coeff[0])
|
|
76
|
+
plot_z_cal(data, coeff)
|
|
77
|
+
|
|
78
|
+
def result_scan_export(self, data: list[TileImage]):
|
|
79
|
+
self._scanning = False
|
|
80
|
+
self.acquisitionWidget.setActionsStatus(True)
|
|
81
|
+
|
|
82
|
+
if data:
|
|
83
|
+
self._export_tile_images(data)
|
|
84
|
+
|
|
85
|
+
def _export_tile_images(self, data: list[TileImage]):
|
|
86
|
+
directory = self.acquisitionWidget._directory
|
|
87
|
+
if len(directory) > 0:
|
|
88
|
+
index = self._get_next_index(directory)
|
|
89
|
+
path = os.path.join(directory, f'{index:03d}_XY/')
|
|
90
|
+
os.makedirs(path, exist_ok=True)
|
|
91
|
+
|
|
92
|
+
for idx, tile_img in enumerate(data):
|
|
93
|
+
filename = (
|
|
94
|
+
f'{idx:03d}_image_y{tile_img.index[0]:02d}'
|
|
95
|
+
+ f'_x{tile_img.index[1]:02d}.tif'
|
|
96
|
+
)
|
|
97
|
+
tf.imwrite(
|
|
98
|
+
os.path.join(path, filename),
|
|
99
|
+
tile_img.uImage.image,
|
|
100
|
+
photometric='minisblack',
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def _get_next_index(self, directory):
|
|
104
|
+
index = 0
|
|
105
|
+
while os.path.exists(os.path.join(directory, f'{index:03d}_XY/')):
|
|
106
|
+
index += 1
|
|
107
|
+
return index
|
|
108
|
+
|
|
109
|
+
def start_scan_acquisitionXY(self, params):
|
|
110
|
+
if not self._scanning:
|
|
111
|
+
self._stop_scan = False
|
|
112
|
+
self._scanning = True
|
|
113
|
+
|
|
114
|
+
self.scan_worker = QThreadWorker(
|
|
115
|
+
scanAcquisition,
|
|
116
|
+
[params[0], params[1]],
|
|
117
|
+
[params[2], params[3]],
|
|
118
|
+
params[4],
|
|
119
|
+
params[5],
|
|
120
|
+
)
|
|
121
|
+
self.scan_worker.signals.result.connect(self.result_scan_acquisition)
|
|
122
|
+
# Execute
|
|
123
|
+
QtCore.QThreadPool.globalInstance().start(self.scan_worker)
|
|
124
|
+
|
|
125
|
+
self.acquisitionWidget.setActionsStatus(False)
|
|
126
|
+
|
|
127
|
+
def start_scan_acquisitionZ(self, params):
|
|
128
|
+
if not self._scanning:
|
|
129
|
+
self._stop_scan = False
|
|
130
|
+
self._scanning = True
|
|
131
|
+
|
|
132
|
+
self.scan_worker = QThreadWorker(
|
|
133
|
+
z_stack_acquisition,
|
|
134
|
+
self,
|
|
135
|
+
params[0],
|
|
136
|
+
params[1],
|
|
137
|
+
params[2],
|
|
138
|
+
params[3],
|
|
139
|
+
params[4],
|
|
140
|
+
)
|
|
141
|
+
self.scan_worker.signals.result.connect(self.result_scan_acquisition)
|
|
142
|
+
# Execute
|
|
143
|
+
QtCore.QThreadPool.globalInstance().start(self.scan_worker)
|
|
144
|
+
|
|
145
|
+
self.acquisitionWidget.setActionsStatus(False)
|
|
146
|
+
|
|
147
|
+
def start_calibration_Z(self, params):
|
|
148
|
+
if not self._scanning:
|
|
149
|
+
self._stop_scan = False
|
|
150
|
+
self._scanning = True
|
|
151
|
+
|
|
152
|
+
self.scan_worker = QThreadWorker(
|
|
153
|
+
z_calibration,
|
|
154
|
+
self,
|
|
155
|
+
params[0],
|
|
156
|
+
params[1],
|
|
157
|
+
params[2],
|
|
158
|
+
params[3],
|
|
159
|
+
params[4],
|
|
160
|
+
)
|
|
161
|
+
self.scan_worker.signals.result.connect(self.result_z_calibration)
|
|
162
|
+
# Execute
|
|
163
|
+
QtCore.QThreadPool.globalInstance().start(self.scan_worker)
|
|
164
|
+
|
|
165
|
+
self.acquisitionWidget.setActionsStatus(False)
|
|
166
|
+
|
|
167
|
+
def stop_scan_acquisition(self):
|
|
168
|
+
self._stop_scan = True
|
|
169
|
+
if self.scan_worker:
|
|
170
|
+
self.scan_worker.stop()
|
|
171
|
+
|
|
172
|
+
def update_directories(self, value: str):
|
|
173
|
+
for _, cam_list in CameraList.CAMERAS.items():
|
|
174
|
+
for cam in cam_list:
|
|
175
|
+
panel: Camera_Panel = cam['Panel']
|
|
176
|
+
panel._directory = value
|
|
177
|
+
panel.camera_options.set_param_value(CamParams.SAVE_DIRECTORY, value)
|
|
178
|
+
|
|
179
|
+
def show_last_tile(self):
|
|
180
|
+
if self.lastTile is not None:
|
|
181
|
+
self.lastTile.show()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def scanAcquisition(steps, step_size, delay, average=1, **kwargs):
|
|
185
|
+
'''Scan Acquisition (works with Allied Vision Cams only)
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
steps : (int, int)
|
|
190
|
+
number of grid steps (x ,y)
|
|
191
|
+
step_size : (float, float)
|
|
192
|
+
step size in um (x ,y)
|
|
193
|
+
delay : float
|
|
194
|
+
delay in ms after moving before acquiring images
|
|
195
|
+
average : int
|
|
196
|
+
number of frames to average, default 1 (no averaging)
|
|
197
|
+
**kwargs : dict
|
|
198
|
+
additional arguments
|
|
199
|
+
- event : `threading.Event`
|
|
200
|
+
event to stop the acquisition
|
|
201
|
+
|
|
202
|
+
Returns
|
|
203
|
+
-------
|
|
204
|
+
list[TileImage]
|
|
205
|
+
result data list of TileImages
|
|
206
|
+
'''
|
|
207
|
+
try:
|
|
208
|
+
event: threading.Event = kwargs.get('event')
|
|
209
|
+
if event and event.is_set():
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
device_manager = DeviceManager.instance()
|
|
213
|
+
|
|
214
|
+
data = []
|
|
215
|
+
vimba_cams = [cam for cam in CameraList.CAMERAS['Vimba'] if not cam['IR']]
|
|
216
|
+
if device_manager.stage_xy.isOpen() and len(vimba_cams) > 0:
|
|
217
|
+
cam: vimba_cam = vimba_cams[0]['Camera']
|
|
218
|
+
for x in range(steps[0]):
|
|
219
|
+
device_manager.stage_xy.move_relative(
|
|
220
|
+
round(step_size[0] / 1000, 4), 0, False
|
|
221
|
+
)
|
|
222
|
+
for y in range(steps[1]):
|
|
223
|
+
if event and event.is_set():
|
|
224
|
+
return
|
|
225
|
+
|
|
226
|
+
if y > 0:
|
|
227
|
+
device_manager.stage_xy.move_relative(
|
|
228
|
+
0, ((-1) ** x) * round(step_size[1] / 1000, 4), False
|
|
229
|
+
)
|
|
230
|
+
frame = None
|
|
231
|
+
with cam.cam:
|
|
232
|
+
QtCore.QThread.msleep(delay)
|
|
233
|
+
if average > 1:
|
|
234
|
+
frames_avg = []
|
|
235
|
+
for _n in range(average):
|
|
236
|
+
frames_avg.append(
|
|
237
|
+
cam.cam.get_frame().as_numpy_ndarray()[..., 0]
|
|
238
|
+
)
|
|
239
|
+
frame = uImage(
|
|
240
|
+
np.array(frames_avg).mean(axis=0, dtype=np.uint16)
|
|
241
|
+
)
|
|
242
|
+
else:
|
|
243
|
+
frame = uImage(
|
|
244
|
+
cam.cam.get_frame().as_numpy_ndarray()[..., 0]
|
|
245
|
+
)
|
|
246
|
+
frame.equalizeLUT(None, True)
|
|
247
|
+
frame._view = cv2.resize(
|
|
248
|
+
frame._view,
|
|
249
|
+
(0, 0),
|
|
250
|
+
fx=0.5,
|
|
251
|
+
fy=0.5,
|
|
252
|
+
interpolation=cv2.INTER_NEAREST,
|
|
253
|
+
)
|
|
254
|
+
Y = (x % 2) * (steps[1] - 1) + ((-1) ** x) * y
|
|
255
|
+
data.append(
|
|
256
|
+
TileImage(frame, [Y, x], device_manager.stage_xy.position)
|
|
257
|
+
)
|
|
258
|
+
cv2.imshow(cam.name, frame._view)
|
|
259
|
+
cv2.waitKey(1)
|
|
260
|
+
|
|
261
|
+
# device_manager.stage_xy.update()
|
|
262
|
+
else:
|
|
263
|
+
return
|
|
264
|
+
except Exception:
|
|
265
|
+
traceback.print_exc()
|
|
266
|
+
finally:
|
|
267
|
+
try:
|
|
268
|
+
cv2.destroyAllWindows()
|
|
269
|
+
except Exception:
|
|
270
|
+
traceback.print_exc()
|
|
271
|
+
|
|
272
|
+
return data
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def z_stack_acquisition(
|
|
276
|
+
acquisition_manager: AcquisitionManager,
|
|
277
|
+
n,
|
|
278
|
+
step_size,
|
|
279
|
+
delay=100,
|
|
280
|
+
nFrames=1,
|
|
281
|
+
reverse=False,
|
|
282
|
+
**kwargs,
|
|
283
|
+
):
|
|
284
|
+
'''Z-Stack Acquisition (works with Allied Vision Cams only)
|
|
285
|
+
|
|
286
|
+
Parameters
|
|
287
|
+
----------
|
|
288
|
+
acq_manager : AcquisitionManager
|
|
289
|
+
acquisition manager instance
|
|
290
|
+
n : int
|
|
291
|
+
number of z-stacks
|
|
292
|
+
step_size : int
|
|
293
|
+
step size in nm along z-axis
|
|
294
|
+
delay : float
|
|
295
|
+
delay in ms after moving before acquiring images
|
|
296
|
+
nFrames : int
|
|
297
|
+
number of frames for each stack
|
|
298
|
+
reverse : bool
|
|
299
|
+
reverse the direction of the movement
|
|
300
|
+
**kwargs : dict
|
|
301
|
+
additional arguments
|
|
302
|
+
- event : `threading.Event`
|
|
303
|
+
event to stop the acquisition
|
|
304
|
+
'''
|
|
305
|
+
try:
|
|
306
|
+
event: threading.Event = kwargs.get('event')
|
|
307
|
+
if event and event.is_set():
|
|
308
|
+
return
|
|
309
|
+
|
|
310
|
+
device_manager = DeviceManager.instance()
|
|
311
|
+
|
|
312
|
+
data = []
|
|
313
|
+
peak = None
|
|
314
|
+
vimba_cams = [cam for cam in CameraList.CAMERAS['Vimba'] if not cam['IR']]
|
|
315
|
+
if device_manager.stage.isOpen() and len(vimba_cams) > 0 and nFrames > 0:
|
|
316
|
+
cam: miCamera = vimba_cams[0]['Camera']
|
|
317
|
+
cam_pan: Camera_Panel = vimba_cams[0]['Panel']
|
|
318
|
+
if cam.acquisition:
|
|
319
|
+
return
|
|
320
|
+
|
|
321
|
+
cam_pan.camera_options.set_param_value(CamParams.FRAMES, nFrames)
|
|
322
|
+
cam_pan.camera_options.set_param_value(CamParams.SAVE_DATA, True)
|
|
323
|
+
|
|
324
|
+
peak = FocusStabilizer.instance().getPeakPosition()
|
|
325
|
+
for x in range(n):
|
|
326
|
+
if x > 0:
|
|
327
|
+
if event and event.is_set():
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
if (
|
|
331
|
+
FocusStabilizer.instance().isFocusStabilized()
|
|
332
|
+
and FocusStabilizer.instance().useCal()
|
|
333
|
+
):
|
|
334
|
+
value = FocusStabilizer.instance().pixelCalCoeff() * step_size
|
|
335
|
+
if reverse:
|
|
336
|
+
value *= -1
|
|
337
|
+
FocusStabilizer.instance().setPeakPosition(value, True)
|
|
338
|
+
QtCore.QThread.msleep(delay)
|
|
339
|
+
else:
|
|
340
|
+
if FocusStabilizer.instance().isFocusStabilized():
|
|
341
|
+
FocusStabilizer.instance().toggleFocusStabilization(False)
|
|
342
|
+
acquisition_manager.acquisitionWidget.moveZ.emit(
|
|
343
|
+
reverse, step_size
|
|
344
|
+
)
|
|
345
|
+
QtCore.QThread.msleep(delay)
|
|
346
|
+
FocusStabilizer.instance().toggleFocusStabilization(True)
|
|
347
|
+
frame = None
|
|
348
|
+
prefix = f'Z_{x:04d}_'
|
|
349
|
+
|
|
350
|
+
cam_event = threading.Event()
|
|
351
|
+
|
|
352
|
+
cam_pan.asyncFreerun.emit(prefix, cam_event)
|
|
353
|
+
|
|
354
|
+
cam_event.wait()
|
|
355
|
+
QtCore.QThread.msleep(100)
|
|
356
|
+
else:
|
|
357
|
+
print('Z-scan failed!')
|
|
358
|
+
info = [
|
|
359
|
+
{
|
|
360
|
+
'Z-Stage Open': device_manager.stage.isOpen(),
|
|
361
|
+
'Camera Available': len(vimba_cams) > 0,
|
|
362
|
+
'Frames > 0': nFrames > 0,
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
print(tabulate.tabulate(info, headers='keys', tablefmt='rounded_grid'))
|
|
366
|
+
except Exception:
|
|
367
|
+
traceback.print_exc()
|
|
368
|
+
finally:
|
|
369
|
+
if peak:
|
|
370
|
+
FocusStabilizer.instance().setPeakPosition(peak)
|
|
371
|
+
return
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def z_calibration(
|
|
375
|
+
acquisition_manager: AcquisitionManager,
|
|
376
|
+
n,
|
|
377
|
+
step_size,
|
|
378
|
+
delay=100,
|
|
379
|
+
nFrames=50,
|
|
380
|
+
reverse=False,
|
|
381
|
+
**kwargs,
|
|
382
|
+
):
|
|
383
|
+
'''Z-Stack Acquisition (works with Allied Vision Cams only)
|
|
384
|
+
|
|
385
|
+
Parameters
|
|
386
|
+
----------
|
|
387
|
+
acq_manager : AcquisitionManager
|
|
388
|
+
acquisition manager instance
|
|
389
|
+
n : int
|
|
390
|
+
number of z-stacks
|
|
391
|
+
step_size : int
|
|
392
|
+
step size in nm along z-axis
|
|
393
|
+
delay : float
|
|
394
|
+
delay in ms per measurement
|
|
395
|
+
nFrames : int
|
|
396
|
+
number of frames used for each measurement
|
|
397
|
+
reverse : bool
|
|
398
|
+
reverse the direction of the movement
|
|
399
|
+
**kwargs : dict
|
|
400
|
+
additional arguments
|
|
401
|
+
- event : `threading.Event`
|
|
402
|
+
event to stop the acquisition
|
|
403
|
+
'''
|
|
404
|
+
positions = np.zeros((n, 2))
|
|
405
|
+
try:
|
|
406
|
+
event: threading.Event = kwargs.get('event')
|
|
407
|
+
if event and event.is_set():
|
|
408
|
+
return
|
|
409
|
+
|
|
410
|
+
device_manager = DeviceManager.instance()
|
|
411
|
+
|
|
412
|
+
data = []
|
|
413
|
+
if device_manager.stage.isOpen():
|
|
414
|
+
if FocusStabilizer.instance().isFocusStabilized():
|
|
415
|
+
FocusStabilizer.instance().toggleFocusStabilization(False)
|
|
416
|
+
for x in range(n):
|
|
417
|
+
if event and event.is_set():
|
|
418
|
+
return
|
|
419
|
+
|
|
420
|
+
if x > 0:
|
|
421
|
+
acquisition_manager.acquisitionWidget.moveZ.emit(reverse, step_size)
|
|
422
|
+
QtCore.QThread.msleep(delay * nFrames)
|
|
423
|
+
positions[x, 0] = x * step_size
|
|
424
|
+
positions[x, 1] = np.mean(
|
|
425
|
+
FocusStabilizer.instance().peak_positions[-nFrames:]
|
|
426
|
+
)
|
|
427
|
+
except Exception:
|
|
428
|
+
traceback.print_exc()
|
|
429
|
+
positions = None
|
|
430
|
+
return positions
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def plot_z_cal(data, coeff):
|
|
434
|
+
model = np.poly1d(coeff)
|
|
435
|
+
|
|
436
|
+
x = np.linspace(data[0, 0], data[-1, 0], 1001)
|
|
437
|
+
|
|
438
|
+
# plot results
|
|
439
|
+
plt = pg.plot()
|
|
440
|
+
|
|
441
|
+
plt.showGrid(x=True, y=True)
|
|
442
|
+
plt.addLegend()
|
|
443
|
+
|
|
444
|
+
# set properties of the label for y axis
|
|
445
|
+
plt.setLabel('left', 'Central Pixel', units='')
|
|
446
|
+
|
|
447
|
+
# set properties of the label for x axis
|
|
448
|
+
plt.setLabel('bottom', 'Z [nm]', units='')
|
|
449
|
+
|
|
450
|
+
plt.setWindowTitle(f'Slope: {coeff[0]} | Intercept {coeff[1]}')
|
|
451
|
+
|
|
452
|
+
# setting horizontal range
|
|
453
|
+
plt.setXRange(data[0, 0], data[-1, 0])
|
|
454
|
+
|
|
455
|
+
# setting vertical range
|
|
456
|
+
plt.setYRange(data[0, 1], data[-1, 1])
|
|
457
|
+
|
|
458
|
+
line1 = plt.plot(
|
|
459
|
+
data[:, 0],
|
|
460
|
+
data[:, 1],
|
|
461
|
+
pen='g',
|
|
462
|
+
symbol='x',
|
|
463
|
+
symbolPen='g',
|
|
464
|
+
symbolBrush=0.2,
|
|
465
|
+
name='Data',
|
|
466
|
+
)
|
|
467
|
+
line2 = plt.plot(x, model(x), pen='b', name='Fit')
|