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,528 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
from microEye.hardware.cams.camera_panel import Camera_Panel
|
|
5
|
+
from microEye.hardware.cams.dummy.dummy_panel import Dummy_Panel
|
|
6
|
+
from microEye.hardware.cams.micam import miDummy
|
|
7
|
+
from microEye.hardware.cams.thorlabs.thorlabs import CMD, thorlabs_camera
|
|
8
|
+
from microEye.hardware.cams.thorlabs.thorlabs_panel import Thorlabs_Panel
|
|
9
|
+
from microEye.hardware.pycromanager.devices import PycroCamera, PycroCore
|
|
10
|
+
from microEye.hardware.pycromanager.widgets import PycroPanel
|
|
11
|
+
from microEye.qt import QtGui, QtWidgets, Signal
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from pyueye import ueye
|
|
15
|
+
|
|
16
|
+
from microEye.hardware.cams.ueye.ueye_camera import IDS_Camera
|
|
17
|
+
from microEye.hardware.cams.ueye.ueye_panel import IDS_Panel
|
|
18
|
+
except Exception:
|
|
19
|
+
ueye = None
|
|
20
|
+
IDS_Camera = None
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
import vimba as vb
|
|
24
|
+
|
|
25
|
+
from microEye.hardware.cams.vimba.vimba_cam import get_camera_list, vimba_cam
|
|
26
|
+
from microEye.hardware.cams.vimba.vimba_panel import Vimba_Panel
|
|
27
|
+
except Exception:
|
|
28
|
+
vb = None
|
|
29
|
+
|
|
30
|
+
def get_camera_list():
|
|
31
|
+
return []
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CameraList(QtWidgets.QWidget):
|
|
35
|
+
'''
|
|
36
|
+
A widget for displaying and managing a list of cameras.
|
|
37
|
+
'''
|
|
38
|
+
|
|
39
|
+
cameraAdded = Signal(Camera_Panel, bool)
|
|
40
|
+
cameraRemoved = Signal(Camera_Panel, bool)
|
|
41
|
+
|
|
42
|
+
CAMERAS = {'uEye': [], 'Vimba': [], 'UC480': [], 'miDummy': [], 'PycroCore': []}
|
|
43
|
+
|
|
44
|
+
def __init__(self, parent: typing.Optional['QtWidgets.QWidget'] = None):
|
|
45
|
+
'''
|
|
46
|
+
Initialize the camera list widget.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
parent : typing.Optional[QtWidgets.QWidget], optional
|
|
51
|
+
The parent widget of this camera list widget.
|
|
52
|
+
'''
|
|
53
|
+
super().__init__(parent=parent)
|
|
54
|
+
|
|
55
|
+
self.cam_list = None
|
|
56
|
+
self.item_model = QtGui.QStandardItemModel()
|
|
57
|
+
self.cached_autofocusCam = None
|
|
58
|
+
|
|
59
|
+
# Layout
|
|
60
|
+
self.InitLayout()
|
|
61
|
+
|
|
62
|
+
def InitLayout(self):
|
|
63
|
+
'''
|
|
64
|
+
Initialize the layout of the widget.
|
|
65
|
+
'''
|
|
66
|
+
|
|
67
|
+
# main layout
|
|
68
|
+
self.mainLayout = QtWidgets.QVBoxLayout()
|
|
69
|
+
|
|
70
|
+
self.cam_table = QtWidgets.QTableView()
|
|
71
|
+
self.cam_table.setModel(self.item_model)
|
|
72
|
+
self.cam_table.clearSelection()
|
|
73
|
+
self.cam_table.horizontalHeader().setStretchLastSection(True)
|
|
74
|
+
self.cam_table.horizontalHeader().setSectionResizeMode(
|
|
75
|
+
QtWidgets.QHeaderView.ResizeMode.ResizeToContents
|
|
76
|
+
)
|
|
77
|
+
self.cam_table.setSelectionBehavior(
|
|
78
|
+
QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows
|
|
79
|
+
)
|
|
80
|
+
self.cam_table.setSelectionMode(
|
|
81
|
+
QtWidgets.QAbstractItemView.SelectionMode.SingleSelection
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
self.HL_buttons = QtWidgets.QHBoxLayout()
|
|
85
|
+
|
|
86
|
+
self.add_cam = QtWidgets.QPushButton(
|
|
87
|
+
'Add Camera', clicked=lambda: self.add_camera_clicked()
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
self.remove_cam = QtWidgets.QPushButton(
|
|
91
|
+
'Remove Camera', clicked=lambda: self.remove_camera_clicked()
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
self.refresh = QtWidgets.QPushButton(
|
|
95
|
+
'Refresh List', clicked=lambda: self.refresh_list()
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
self.HL_buttons.addWidget(self.add_cam)
|
|
99
|
+
self.HL_buttons.addWidget(self.remove_cam)
|
|
100
|
+
self.HL_buttons.addWidget(self.refresh)
|
|
101
|
+
|
|
102
|
+
self.mainLayout.addWidget(self.cam_table)
|
|
103
|
+
self.mainLayout.addLayout(self.HL_buttons)
|
|
104
|
+
|
|
105
|
+
self.setLayout(self.mainLayout)
|
|
106
|
+
|
|
107
|
+
self.refresh_list()
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def autofocusCam(self) -> typing.Union[Camera_Panel, None]:
|
|
111
|
+
'''
|
|
112
|
+
Get the autofocus camera panel.
|
|
113
|
+
|
|
114
|
+
Returns
|
|
115
|
+
-------
|
|
116
|
+
Camera_Panel | None
|
|
117
|
+
The autofocus camera panel, or None if no autofocus camera is available.
|
|
118
|
+
'''
|
|
119
|
+
if self.cached_autofocusCam is None:
|
|
120
|
+
self.cached_autofocusCam = next(
|
|
121
|
+
(
|
|
122
|
+
cam['Panel']
|
|
123
|
+
for _, cam_list in CameraList.CAMERAS.items()
|
|
124
|
+
for cam in cam_list
|
|
125
|
+
if cam['IR']
|
|
126
|
+
),
|
|
127
|
+
None,
|
|
128
|
+
)
|
|
129
|
+
return self.cached_autofocusCam
|
|
130
|
+
|
|
131
|
+
def add_camera_clicked(self):
|
|
132
|
+
'''
|
|
133
|
+
Add a camera when the "Add Camera" button is clicked.
|
|
134
|
+
'''
|
|
135
|
+
if len(self.cam_table.selectedIndexes()) > 0:
|
|
136
|
+
cam = self.cam_list[self.cam_table.currentIndex().row()]
|
|
137
|
+
|
|
138
|
+
# create a dialog with radio buttons
|
|
139
|
+
dialog, ok = QtWidgets.QInputDialog.getItem(
|
|
140
|
+
self,
|
|
141
|
+
'Add Camera',
|
|
142
|
+
'Choose camera type:',
|
|
143
|
+
('Acquisition', 'Autofocus IR'),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if ok and dialog is not None:
|
|
147
|
+
if dialog == 'Acquisition':
|
|
148
|
+
panel = self.add_camera(cam)
|
|
149
|
+
if panel:
|
|
150
|
+
self.cameraAdded.emit(panel, False)
|
|
151
|
+
elif dialog == 'Autofocus IR':
|
|
152
|
+
if self.autofocusCam is None:
|
|
153
|
+
panel = self.add_camera(cam, True)
|
|
154
|
+
if panel:
|
|
155
|
+
self.cameraAdded.emit(panel, True)
|
|
156
|
+
else:
|
|
157
|
+
self._display_warning_message(
|
|
158
|
+
'Autofocus IR camera has already been added!'
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
self.refresh_list()
|
|
162
|
+
else:
|
|
163
|
+
self._display_warning_message('Please select a device.')
|
|
164
|
+
|
|
165
|
+
def add_camera(self, cam, mini=False):
|
|
166
|
+
'''
|
|
167
|
+
Add a camera.
|
|
168
|
+
|
|
169
|
+
Parameters
|
|
170
|
+
----------
|
|
171
|
+
cam : dict
|
|
172
|
+
The camera information dictionary.
|
|
173
|
+
mini : bool, optional
|
|
174
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
Camera_Panel | None
|
|
179
|
+
The camera panel, or None if the camera could not be added.
|
|
180
|
+
'''
|
|
181
|
+
if cam['InUse'] == 0:
|
|
182
|
+
driver = cam['Driver']
|
|
183
|
+
if driver == 'uEye':
|
|
184
|
+
return self._add_ids_camera(cam, cam['Camera ID'], mini)
|
|
185
|
+
elif driver == 'UC480':
|
|
186
|
+
return self._add_thorlabs_camera(cam, cam['Camera ID'], mini)
|
|
187
|
+
elif driver == 'Vimba':
|
|
188
|
+
return self._add_vimba_camera(cam, cam['Camera ID'], mini)
|
|
189
|
+
elif driver == 'miDummy':
|
|
190
|
+
return self._add_dummy_camera(cam, mini)
|
|
191
|
+
elif driver == 'PycroCore':
|
|
192
|
+
return self._add_pycro_camera(cam, cam['Device ID'], mini)
|
|
193
|
+
else:
|
|
194
|
+
self._display_warning_message(f'Unsupported camera driver: {driver}')
|
|
195
|
+
else:
|
|
196
|
+
self._display_warning_message('Device is in use or already added.')
|
|
197
|
+
|
|
198
|
+
def _add_ids_camera(self, cam, camera_id, mini):
|
|
199
|
+
'''
|
|
200
|
+
Add an IDS camera.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
cam : dict
|
|
205
|
+
The camera information dictionary.
|
|
206
|
+
camera_id : int
|
|
207
|
+
The camera ID.
|
|
208
|
+
mini : bool
|
|
209
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
210
|
+
|
|
211
|
+
Returns
|
|
212
|
+
-------
|
|
213
|
+
Camera_Panel | None
|
|
214
|
+
The camera panel, or None if the camera could not be added.
|
|
215
|
+
'''
|
|
216
|
+
ids_cam = IDS_Camera(camera_id)
|
|
217
|
+
ids_cam.initialize()
|
|
218
|
+
ids_panel = IDS_Panel(ids_cam, mini, self.get_cam_title(cam))
|
|
219
|
+
CameraList.CAMERAS['uEye'].append(
|
|
220
|
+
{'Camera': ids_cam, 'Panel': ids_panel, 'IR': mini}
|
|
221
|
+
)
|
|
222
|
+
return ids_panel
|
|
223
|
+
|
|
224
|
+
def _add_thorlabs_camera(self, cam, camera_id, mini):
|
|
225
|
+
'''
|
|
226
|
+
Add a Thorlabs camera.
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
cam : dict
|
|
231
|
+
The camera information dictionary.
|
|
232
|
+
camera_id : int
|
|
233
|
+
The camera ID.
|
|
234
|
+
mini : bool
|
|
235
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
Camera_Panel | None
|
|
240
|
+
The camera panel, or None if the camera could not be added.
|
|
241
|
+
'''
|
|
242
|
+
thor_cam = thorlabs_camera(camera_id)
|
|
243
|
+
n_ret = thor_cam.initialize()
|
|
244
|
+
if n_ret == CMD.IS_SUCCESS:
|
|
245
|
+
thor_panel = Thorlabs_Panel(thor_cam, mini, self.get_cam_title(cam))
|
|
246
|
+
CameraList.CAMERAS['UC480'].append(
|
|
247
|
+
{'Camera': thor_cam, 'Panel': thor_panel, 'IR': mini}
|
|
248
|
+
)
|
|
249
|
+
return thor_panel
|
|
250
|
+
else:
|
|
251
|
+
self._display_warning_message('Thorlabs camera initialization failed.')
|
|
252
|
+
|
|
253
|
+
def _add_vimba_camera(self, cam, camera_id, mini):
|
|
254
|
+
'''
|
|
255
|
+
Add a Vimba camera.
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
cam : dict
|
|
260
|
+
The camera information dictionary.
|
|
261
|
+
camera_id : int
|
|
262
|
+
The camera ID.
|
|
263
|
+
mini : bool
|
|
264
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
Camera_Panel | None
|
|
269
|
+
The camera panel, or None if the camera could not be added.
|
|
270
|
+
'''
|
|
271
|
+
v_cam = vimba_cam(camera_id)
|
|
272
|
+
v_panel = Vimba_Panel(v_cam, mini, self.get_cam_title(cam))
|
|
273
|
+
CameraList.CAMERAS['Vimba'].append(
|
|
274
|
+
{'Camera': v_cam, 'Panel': v_panel, 'IR': mini}
|
|
275
|
+
)
|
|
276
|
+
return v_panel
|
|
277
|
+
|
|
278
|
+
def _add_dummy_camera(self, cam, mini):
|
|
279
|
+
'''
|
|
280
|
+
Add a dummy camera.
|
|
281
|
+
|
|
282
|
+
Parameters
|
|
283
|
+
----------
|
|
284
|
+
cam : dict
|
|
285
|
+
The camera information dictionary.
|
|
286
|
+
mini : bool
|
|
287
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
288
|
+
|
|
289
|
+
Returns
|
|
290
|
+
-------
|
|
291
|
+
Camera_Panel | None
|
|
292
|
+
The camera panel, or None if the camera could not be added.
|
|
293
|
+
'''
|
|
294
|
+
dummy_panel = Dummy_Panel(mini, self.get_cam_title(cam))
|
|
295
|
+
CameraList.CAMERAS['miDummy'].append(
|
|
296
|
+
{'Camera': dummy_panel.cam, 'Panel': dummy_panel, 'IR': mini}
|
|
297
|
+
)
|
|
298
|
+
return dummy_panel
|
|
299
|
+
|
|
300
|
+
def _add_pycro_camera(self, cam, camera_id, mini):
|
|
301
|
+
'''
|
|
302
|
+
Add a PycroManager camera.
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
cam : dict
|
|
307
|
+
The camera information dictionary.
|
|
308
|
+
camera_id : int
|
|
309
|
+
The camera ID / Label.
|
|
310
|
+
mini : bool
|
|
311
|
+
True to add a mini camera panel, False to add a full camera panel.
|
|
312
|
+
|
|
313
|
+
Returns
|
|
314
|
+
-------
|
|
315
|
+
Camera_Panel | None
|
|
316
|
+
The camera panel, or None if the camera could not be added.
|
|
317
|
+
'''
|
|
318
|
+
pycro_cam = PycroCamera(
|
|
319
|
+
cam['Camera ID'], port=int(cam['Device ID'].split('-')[0])
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
pycro_pan = PycroPanel(pycro_cam, mini, self.get_cam_title(cam))
|
|
323
|
+
CameraList.CAMERAS['PycroCore'].append(
|
|
324
|
+
{'Camera': pycro_cam, 'Panel': pycro_pan, 'IR': mini}
|
|
325
|
+
)
|
|
326
|
+
return pycro_pan
|
|
327
|
+
|
|
328
|
+
def _display_warning_message(self, message):
|
|
329
|
+
'''
|
|
330
|
+
Display a warning message.
|
|
331
|
+
|
|
332
|
+
Parameters
|
|
333
|
+
----------
|
|
334
|
+
message : str
|
|
335
|
+
The warning message to display.
|
|
336
|
+
'''
|
|
337
|
+
QtWidgets.QMessageBox.warning(
|
|
338
|
+
self, 'Warning', message, QtWidgets.QMessageBox.StandardButton.Ok
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
def get_cam_title(self, cam: dict):
|
|
342
|
+
'''
|
|
343
|
+
Get the camera title.
|
|
344
|
+
|
|
345
|
+
Parameters
|
|
346
|
+
----------
|
|
347
|
+
cam : dict
|
|
348
|
+
The camera information dictionary.
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
str
|
|
353
|
+
The camera title.
|
|
354
|
+
'''
|
|
355
|
+
return f"{cam['Driver']} | {cam['Model']}"
|
|
356
|
+
|
|
357
|
+
def remove_camera_clicked(self):
|
|
358
|
+
'''
|
|
359
|
+
Remove a camera when the "Remove Camera" button is clicked.
|
|
360
|
+
'''
|
|
361
|
+
if len(self.cam_table.selectedIndexes()) > 0:
|
|
362
|
+
cam = self.cam_list[self.cam_table.currentIndex().row()]
|
|
363
|
+
|
|
364
|
+
# Display a confirmation dialog
|
|
365
|
+
confirm = QtWidgets.QMessageBox.question(
|
|
366
|
+
self,
|
|
367
|
+
'Confirmation',
|
|
368
|
+
f'Do you want to remove this camera {self.get_cam_title(cam)}?',
|
|
369
|
+
QtWidgets.QMessageBox.StandardButton.Yes
|
|
370
|
+
| QtWidgets.QMessageBox.StandardButton.No,
|
|
371
|
+
QtWidgets.QMessageBox.StandardButton.No,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
if confirm == QtWidgets.QMessageBox.StandardButton.Yes:
|
|
375
|
+
self.remove_camera(cam)
|
|
376
|
+
|
|
377
|
+
self.refresh_list()
|
|
378
|
+
else:
|
|
379
|
+
self._display_warning_message('Please select a device.')
|
|
380
|
+
|
|
381
|
+
def remove_camera(self, cam):
|
|
382
|
+
'''
|
|
383
|
+
Remove a camera.
|
|
384
|
+
|
|
385
|
+
Parameters
|
|
386
|
+
----------
|
|
387
|
+
cam : dict
|
|
388
|
+
The camera information dictionary.
|
|
389
|
+
'''
|
|
390
|
+
cams: list[dict] = CameraList.CAMERAS.get(cam['Driver'], [])
|
|
391
|
+
if cams:
|
|
392
|
+
for item in cams:
|
|
393
|
+
pan: Camera_Panel = item['Panel']
|
|
394
|
+
if pan.title() == self.get_cam_title(cam):
|
|
395
|
+
if pan.cam.acquisition:
|
|
396
|
+
self._display_warning_message(
|
|
397
|
+
'Please stop acquisition before removing!'
|
|
398
|
+
)
|
|
399
|
+
else:
|
|
400
|
+
if isinstance(pan.cam, (IDS_Camera, thorlabs_camera)):
|
|
401
|
+
pan.cam.free_memory()
|
|
402
|
+
pan.cam.dispose()
|
|
403
|
+
if isinstance(item['Camera'], miDummy):
|
|
404
|
+
miDummy.instances.remove(item['Camera'])
|
|
405
|
+
|
|
406
|
+
pan._dispose_cam = True
|
|
407
|
+
if pan.acq_job is not None:
|
|
408
|
+
pan.acq_job.stop_threads = True
|
|
409
|
+
|
|
410
|
+
cams.remove(item)
|
|
411
|
+
if item['IR']:
|
|
412
|
+
pan.setParent(None)
|
|
413
|
+
else:
|
|
414
|
+
pan.close()
|
|
415
|
+
pan.setParent(None)
|
|
416
|
+
self.cameraRemoved.emit(pan, item['IR'])
|
|
417
|
+
return
|
|
418
|
+
else:
|
|
419
|
+
self._display_warning_message('Device/Panel not found!')
|
|
420
|
+
|
|
421
|
+
def removeAllCameras(self):
|
|
422
|
+
'''
|
|
423
|
+
Remove all cameras.
|
|
424
|
+
Stops any active acquisitions and properly disposes of camera resources.
|
|
425
|
+
'''
|
|
426
|
+
for _, camera_list in self.CAMERAS.items():
|
|
427
|
+
# Create a copy of the list since we'll be modifying it during iteration
|
|
428
|
+
for camera_info in camera_list[:]:
|
|
429
|
+
panel: Camera_Panel = camera_info['Panel']
|
|
430
|
+
|
|
431
|
+
# Stop acquisition if running
|
|
432
|
+
if panel.cam.acquisition:
|
|
433
|
+
panel.stop()
|
|
434
|
+
|
|
435
|
+
# Clean up based on camera type
|
|
436
|
+
if isinstance(panel.cam, (IDS_Camera, thorlabs_camera)):
|
|
437
|
+
panel.cam.free_memory()
|
|
438
|
+
panel.cam.dispose()
|
|
439
|
+
|
|
440
|
+
# Remove dummy camera instances
|
|
441
|
+
if isinstance(camera_info['Camera'], miDummy):
|
|
442
|
+
miDummy.instances.remove(camera_info['Camera'])
|
|
443
|
+
|
|
444
|
+
# Stop any acquisition jobs
|
|
445
|
+
if panel.acq_job is not None:
|
|
446
|
+
panel.acq_job.stop_threads = True
|
|
447
|
+
|
|
448
|
+
# Remove from parent and clean up panel
|
|
449
|
+
panel._dispose_cam = True
|
|
450
|
+
if camera_info['IR']:
|
|
451
|
+
panel.setParent(None)
|
|
452
|
+
else:
|
|
453
|
+
panel.close()
|
|
454
|
+
panel.setParent(None)
|
|
455
|
+
|
|
456
|
+
# Remove from camera list
|
|
457
|
+
camera_list.remove(camera_info)
|
|
458
|
+
|
|
459
|
+
def refresh_list(self):
|
|
460
|
+
'''
|
|
461
|
+
Refresh the camera list.
|
|
462
|
+
'''
|
|
463
|
+
self.cam_list = []
|
|
464
|
+
|
|
465
|
+
# Add miDummy to the list
|
|
466
|
+
self.cam_list += miDummy.get_camera_list()
|
|
467
|
+
|
|
468
|
+
if ueye is not None:
|
|
469
|
+
self.cam_list += IDS_Camera.get_camera_list()
|
|
470
|
+
|
|
471
|
+
if os.path.exists(thorlabs_camera.uc480_file):
|
|
472
|
+
self.cam_list += thorlabs_camera.get_camera_list()
|
|
473
|
+
|
|
474
|
+
if vb is not None:
|
|
475
|
+
self.cam_list += get_camera_list()
|
|
476
|
+
|
|
477
|
+
if hasattr(PycroCore, 'get_camera_list'):
|
|
478
|
+
self.cam_list += PycroCore.get_camera_list()
|
|
479
|
+
|
|
480
|
+
if self.cam_list is None:
|
|
481
|
+
self.cam_list = []
|
|
482
|
+
print('No cameras connected.')
|
|
483
|
+
|
|
484
|
+
self.item_model = QtGui.QStandardItemModel(len(self.cam_list), 8)
|
|
485
|
+
|
|
486
|
+
self.item_model.setHorizontalHeaderLabels(
|
|
487
|
+
[
|
|
488
|
+
'In Use',
|
|
489
|
+
'Camera ID',
|
|
490
|
+
'Device ID',
|
|
491
|
+
'Model',
|
|
492
|
+
'Serial',
|
|
493
|
+
'Status',
|
|
494
|
+
'Sensor ID',
|
|
495
|
+
'Driver',
|
|
496
|
+
]
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
for i in range(len(self.cam_list)):
|
|
500
|
+
self.item_model.setItem(
|
|
501
|
+
i, 0, QtGui.QStandardItem(str(self.cam_list[i]['InUse']))
|
|
502
|
+
)
|
|
503
|
+
self.item_model.setItem(
|
|
504
|
+
i, 1, QtGui.QStandardItem(str(self.cam_list[i]['Camera ID']))
|
|
505
|
+
)
|
|
506
|
+
self.item_model.setItem(
|
|
507
|
+
i, 2, QtGui.QStandardItem(str(self.cam_list[i]['Device ID']))
|
|
508
|
+
)
|
|
509
|
+
self.item_model.setItem(
|
|
510
|
+
i, 3, QtGui.QStandardItem(self.cam_list[i]['Model'])
|
|
511
|
+
)
|
|
512
|
+
self.item_model.setItem(
|
|
513
|
+
i, 4, QtGui.QStandardItem(self.cam_list[i]['Serial'])
|
|
514
|
+
)
|
|
515
|
+
self.item_model.setItem(
|
|
516
|
+
i, 5, QtGui.QStandardItem(str(self.cam_list[i]['Status']))
|
|
517
|
+
)
|
|
518
|
+
self.item_model.setItem(
|
|
519
|
+
i, 6, QtGui.QStandardItem(str(self.cam_list[i]['Sensor ID']))
|
|
520
|
+
)
|
|
521
|
+
self.item_model.setItem(
|
|
522
|
+
i, 7, QtGui.QStandardItem(str(self.cam_list[i]['Driver']))
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
self.cam_table.setModel(self.item_model)
|
|
526
|
+
|
|
527
|
+
# Update the cached_autofocusCam value
|
|
528
|
+
self.cached_autofocusCam = None
|