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.
Files changed (190) hide show
  1. microEye/__init__.py +47 -0
  2. microEye/_version.py +2 -0
  3. microEye/analysis/__init__.py +1 -0
  4. microEye/analysis/checklist_dialog.py +143 -0
  5. microEye/analysis/cmosMaps.py +228 -0
  6. microEye/analysis/filters/__init__.py +9 -0
  7. microEye/analysis/filters/base.py +21 -0
  8. microEye/analysis/filters/spatial.py +338 -0
  9. microEye/analysis/filters/temporal.py +76 -0
  10. microEye/analysis/fitting/__init__.py +0 -0
  11. microEye/analysis/fitting/fit.py +680 -0
  12. microEye/analysis/fitting/nena.py +375 -0
  13. microEye/analysis/fitting/phasor_fit.py +90 -0
  14. microEye/analysis/fitting/processing.py +317 -0
  15. microEye/analysis/fitting/psf/__init__.py +6 -0
  16. microEye/analysis/fitting/psf/extract.py +1129 -0
  17. microEye/analysis/fitting/psf/rubost_mean.py +150 -0
  18. microEye/analysis/fitting/psf/spline.py +167 -0
  19. microEye/analysis/fitting/psf/stats/__init__.py +12 -0
  20. microEye/analysis/fitting/psf/stats/core.py +295 -0
  21. microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
  22. microEye/analysis/fitting/psf/stats/io.py +104 -0
  23. microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
  24. microEye/analysis/fitting/psf/temp.py +147 -0
  25. microEye/analysis/fitting/psf/test.py +47 -0
  26. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
  27. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
  28. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
  29. microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
  30. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
  31. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
  32. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
  33. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
  34. microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
  35. microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
  36. microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
  37. microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
  38. microEye/analysis/fitting/results.py +917 -0
  39. microEye/analysis/fitting/results_stats.py +251 -0
  40. microEye/analysis/fitting/tardis.py +209 -0
  41. microEye/analysis/multi_viewer.py +568 -0
  42. microEye/analysis/processing/__init__.py +1 -0
  43. microEye/analysis/processing/frc.py +120 -0
  44. microEye/analysis/rendering/__init__.py +3 -0
  45. microEye/analysis/rendering/base.py +452 -0
  46. microEye/analysis/rendering/cloud.py +215 -0
  47. microEye/analysis/rendering/core.py +47 -0
  48. microEye/analysis/rendering/volumetric.py +198 -0
  49. microEye/analysis/tools/__init__.py +0 -0
  50. microEye/analysis/tools/kymograms.py +1079 -0
  51. microEye/analysis/tools/roi_selectors.py +556 -0
  52. microEye/analysis/utils/__init__.py +3 -0
  53. microEye/analysis/utils/coordinates.py +18 -0
  54. microEye/analysis/utils/images.py +68 -0
  55. microEye/analysis/utils/windows.py +19 -0
  56. microEye/analysis/viewer/__init__.py +3 -0
  57. microEye/analysis/viewer/image_options_widget.py +615 -0
  58. microEye/analysis/viewer/images.py +1225 -0
  59. microEye/analysis/viewer/layers_widget.py +415 -0
  60. microEye/analysis/viewer/localizations.py +1304 -0
  61. microEye/analysis/viewer/psf.py +1003 -0
  62. microEye/analysis/viewer/volume.py +456 -0
  63. microEye/hardware/__init__.py +3 -0
  64. microEye/hardware/cams/__init__.py +29 -0
  65. microEye/hardware/cams/camera_calibration.py +99 -0
  66. microEye/hardware/cams/camera_list.py +528 -0
  67. microEye/hardware/cams/camera_options.py +694 -0
  68. microEye/hardware/cams/camera_panel.py +941 -0
  69. microEye/hardware/cams/dummy/__init__.py +1 -0
  70. microEye/hardware/cams/dummy/dummy_panel.py +759 -0
  71. microEye/hardware/cams/jobs.py +497 -0
  72. microEye/hardware/cams/line_profiler.py +99 -0
  73. microEye/hardware/cams/linescan/IR_Cam.py +474 -0
  74. microEye/hardware/cams/linescan/__init__.py +1 -0
  75. microEye/hardware/cams/micam.py +524 -0
  76. microEye/hardware/cams/pco/__init__.py +58 -0
  77. microEye/hardware/cams/pco/enums.py +382 -0
  78. microEye/hardware/cams/pco/pco_cam.py +761 -0
  79. microEye/hardware/cams/pco/pco_panel.py +477 -0
  80. microEye/hardware/cams/shortcuts.py +312 -0
  81. microEye/hardware/cams/thorlabs/__init__.py +1 -0
  82. microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
  83. microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
  84. microEye/hardware/cams/ueye/__init__.py +1 -0
  85. microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
  86. microEye/hardware/cams/ueye/ueye_panel.py +861 -0
  87. microEye/hardware/cams/vimba/__init__.py +1 -0
  88. microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
  89. microEye/hardware/cams/vimba/vimba_panel.py +813 -0
  90. microEye/hardware/device.py +60 -0
  91. microEye/hardware/lasers/__init__.py +13 -0
  92. microEye/hardware/lasers/io_matchbox.py +791 -0
  93. microEye/hardware/lasers/io_params.py +85 -0
  94. microEye/hardware/lasers/io_single_laser.py +742 -0
  95. microEye/hardware/lasers/laser_relay.py +594 -0
  96. microEye/hardware/mieye/__init__.py +1 -0
  97. microEye/hardware/mieye/acquisition_manager.py +467 -0
  98. microEye/hardware/mieye/devices_manager.py +533 -0
  99. microEye/hardware/mieye/miEye.py +659 -0
  100. microEye/hardware/misc/__init__.py +0 -0
  101. microEye/hardware/misc/acquisition_view.py +71 -0
  102. microEye/hardware/misc/reglo.py +761 -0
  103. microEye/hardware/misc/temp.py +188 -0
  104. microEye/hardware/port_config.py +59 -0
  105. microEye/hardware/protocols/__init__.py +2 -0
  106. microEye/hardware/protocols/actions.py +402 -0
  107. microEye/hardware/protocols/actions_items.py +703 -0
  108. microEye/hardware/protocols/designer.py +244 -0
  109. microEye/hardware/protocols/scene_manager.py +191 -0
  110. microEye/hardware/protocols/serialization.py +97 -0
  111. microEye/hardware/pycromanager/__init__.py +16 -0
  112. microEye/hardware/pycromanager/core.py +1433 -0
  113. microEye/hardware/pycromanager/devices.py +461 -0
  114. microEye/hardware/pycromanager/enums.py +107 -0
  115. microEye/hardware/pycromanager/headless.py +153 -0
  116. microEye/hardware/pycromanager/utils.py +34 -0
  117. microEye/hardware/pycromanager/widgets/__init__.py +5 -0
  118. microEye/hardware/pycromanager/widgets/bridges.py +407 -0
  119. microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
  120. microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
  121. microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
  122. microEye/hardware/stages/__init__.py +18 -0
  123. microEye/hardware/stages/elliptec/__init__.py +5 -0
  124. microEye/hardware/stages/elliptec/baseDevice.py +314 -0
  125. microEye/hardware/stages/elliptec/device.py +384 -0
  126. microEye/hardware/stages/elliptec/deviceID.py +212 -0
  127. microEye/hardware/stages/elliptec/devicePort.py +379 -0
  128. microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
  129. microEye/hardware/stages/elliptec/devicesView.py +706 -0
  130. microEye/hardware/stages/elliptec/ellDevices.py +134 -0
  131. microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
  132. microEye/hardware/stages/elliptec/motorInfo.py +153 -0
  133. microEye/hardware/stages/elliptec/stage.py +62 -0
  134. microEye/hardware/stages/elliptec/test.py +139 -0
  135. microEye/hardware/stages/kinesis/__init__.py +1 -0
  136. microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
  137. microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
  138. microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
  139. microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
  140. microEye/hardware/stages/kinesis/kinesis.py +776 -0
  141. microEye/hardware/stages/piezo_concept.py +607 -0
  142. microEye/hardware/stages/stabilizer.py +785 -0
  143. microEye/hardware/stages/stage.py +89 -0
  144. microEye/hardware/widgets/__init__.py +10 -0
  145. microEye/hardware/widgets/controller.py +246 -0
  146. microEye/hardware/widgets/devices.py +133 -0
  147. microEye/hardware/widgets/focusWidget.py +264 -0
  148. microEye/hardware/widgets/qlist_slider.py +113 -0
  149. microEye/hardware/widgets/scan_acquisition.py +424 -0
  150. microEye/icons/1024.png +0 -0
  151. microEye/icons/128.png +0 -0
  152. microEye/icons/16.png +0 -0
  153. microEye/icons/24.png +0 -0
  154. microEye/icons/256.png +0 -0
  155. microEye/icons/32.png +0 -0
  156. microEye/icons/48.png +0 -0
  157. microEye/icons/512.png +0 -0
  158. microEye/icons/64.png +0 -0
  159. microEye/icons/__init__.py +0 -0
  160. microEye/icons/close.svg +88 -0
  161. microEye/icons/mieye.png +0 -0
  162. microEye/icons/min.svg +83 -0
  163. microEye/icons/viewer.png +0 -0
  164. microEye/launcher.py +42 -0
  165. microEye/qt.py +181 -0
  166. microEye/utils/__init__.py +2 -0
  167. microEye/utils/enum_encoder.py +10 -0
  168. microEye/utils/expandable_groupbox.py +93 -0
  169. microEye/utils/gui_helper.py +457 -0
  170. microEye/utils/hid/__init__.py +8 -0
  171. microEye/utils/hid/controller.py +153 -0
  172. microEye/utils/hid/device.py +63 -0
  173. microEye/utils/hid/enums.py +140 -0
  174. microEye/utils/hid/utils.py +58 -0
  175. microEye/utils/labelled_slider.py +134 -0
  176. microEye/utils/metadata.py +599 -0
  177. microEye/utils/metadata_tree.py +718 -0
  178. microEye/utils/micro_launcher.py +245 -0
  179. microEye/utils/parameter_tree.py +325 -0
  180. microEye/utils/pyscripting.py +444 -0
  181. microEye/utils/retry_exec.py +35 -0
  182. microEye/utils/start_gui.py +112 -0
  183. microEye/utils/thread_worker.py +115 -0
  184. microEye/utils/uImage.py +1512 -0
  185. microeye-2.3.2.dist-info/METADATA +401 -0
  186. microeye-2.3.2.dist-info/RECORD +190 -0
  187. microeye-2.3.2.dist-info/WHEEL +5 -0
  188. microeye-2.3.2.dist-info/entry_points.txt +2 -0
  189. microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
  190. microeye-2.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,861 @@
1
+ import json
2
+ import logging
3
+ import traceback
4
+ from enum import Enum
5
+
6
+ from microEye.analysis.tools.roi_selectors import (
7
+ MultiRectangularROISelector,
8
+ convert_pos_size_to_rois,
9
+ convert_rois_to_pos_size,
10
+ )
11
+ from microEye.hardware.cams.camera_options import CamParams
12
+ from microEye.hardware.cams.camera_panel import Camera_Panel
13
+ from microEye.hardware.cams.ueye.ueye_camera import IDS_Camera
14
+ from microEye.qt import QDateTime, QtCore, QtWidgets, getOpenFileName, getSaveFileName
15
+ from microEye.utils.gui_helper import get_scaling_factor
16
+ from microEye.utils.metadata_tree import MetaParams
17
+ from microEye.utils.thread_worker import QThreadWorker
18
+ from microEye.utils.uImage import uImage
19
+
20
+ try:
21
+ from pyueye import ueye
22
+ except Exception:
23
+ ueye = None
24
+
25
+
26
+ class uEyeParams(Enum):
27
+ FREERUN = 'Acquisition.Start (Freerun)'
28
+ TRIGGERED = 'Acquisition.Start (Triggered)'
29
+ STOP = 'Acquisition.Stop'
30
+ PIXEL_CLOCK = 'Acquisition Settings.Pixel Clock (MHz)'
31
+ FRAMERATE = 'Acquisition Settings.Framerate Slider'
32
+ FRAME_AVERAGING = 'Acquisition Settings.Frame Averaging'
33
+ TRIGGER_MODE = 'Acquisition Settings.Trigger Mode'
34
+ FLASH_MODE = 'Acquisition Settings.Flash Mode'
35
+ FLASH_DURATION = 'Acquisition Settings.Flash Duration Slider'
36
+ FLASH_DELAY = 'Acquisition Settings.Flash Delay Slider'
37
+ LOAD = 'Acquisition Settings.Load'
38
+ SAVE = 'Acquisition Settings.Save'
39
+
40
+ def __str__(self):
41
+ '''
42
+ Return the last part of the enum value (Param name).
43
+ '''
44
+ return self.value.split('.')[-1]
45
+
46
+ def get_path(self):
47
+ '''
48
+ Return the full parameter path.
49
+ '''
50
+ return self.value.split('.')
51
+
52
+
53
+ class IDS_Panel(Camera_Panel):
54
+ '''
55
+ A Qt Widget for controlling an IDS Camera | Inherits Camera_Panel
56
+ '''
57
+ PARAMS = uEyeParams
58
+
59
+ def __init__(self, cam: IDS_Camera, mini=False, *args, **kwargs):
60
+ '''
61
+ Initializes a new IDS_Panel Qt widget.
62
+
63
+ Inherits Camera_Panel.
64
+
65
+ Parameters
66
+ ----------
67
+ cam : IDS_Camera
68
+ IDS Camera python adapter.
69
+
70
+ mini : bool, optional
71
+ Flag indicating if this is a mini camera panel, by default False.
72
+
73
+ Other Parameters
74
+ ---------------
75
+ *args
76
+ Arguments to pass to the Camera_Panel constructor.
77
+
78
+ **kwargs
79
+ Keyword arguments to pass to the Camera_Panel constructor.
80
+ '''
81
+ super().__init__(cam, mini, *args, **kwargs)
82
+
83
+ # flag true to close camera adapter and dispose it
84
+ self._dispose_cam = False
85
+
86
+ self.OME_tab.set_param_value(MetaParams.CHANNEL_NAME, self._cam.name)
87
+ self.OME_tab.set_param_value(MetaParams.DET_MANUFACTURER, 'IDS uEye')
88
+ self.OME_tab.set_param_value(
89
+ MetaParams.DET_MODEL, cam.sInfo.strSensorName.decode('utf-8')
90
+ )
91
+ self.OME_tab.set_param_value(
92
+ MetaParams.DET_SERIAL, cam.cInfo.SerNo.decode('utf-8')
93
+ )
94
+ self.OME_tab.set_param_value(MetaParams.DET_TYPE, 'CMOS')
95
+
96
+ # pixel clock label and combobox
97
+ pixel_clock = {
98
+ 'name': str(uEyeParams.PIXEL_CLOCK),
99
+ 'type': 'list',
100
+ 'limits': list(map(str, self._cam.pixel_clock_list[:])),
101
+ }
102
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, pixel_clock)
103
+ self.camera_options.get_param(uEyeParams.PIXEL_CLOCK).sigValueChanged.connect(
104
+ lambda: self.cam_pixel_cbox_changed(uEyeParams.PIXEL_CLOCK)
105
+ )
106
+
107
+ # framerate slider control
108
+ framerate = {
109
+ 'name': str(uEyeParams.FRAMERATE),
110
+ 'type': 'float',
111
+ 'value': int(self._cam.current_framerate.value),
112
+ 'dec': False,
113
+ 'decimals': 6,
114
+ 'step': self._cam.increment_framerate.value,
115
+ 'limits': [self._cam.min_framerate.value, self._cam.max_framerate.value],
116
+ 'suffix': 'Hz',
117
+ }
118
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, framerate)
119
+ self.camera_options.get_param(uEyeParams.FRAMERATE).sigValueChanged.connect(
120
+ self.cam_framerate_value_changed
121
+ )
122
+
123
+ # exposure text box
124
+ exposure = self.camera_options.get_param(CamParams.EXPOSURE)
125
+ exposure.setLimits(
126
+ (self._cam.exposure_range[0].value, self._cam.exposure_range[1].value)
127
+ )
128
+ exposure.setOpts(step=self._cam.exposure_range[2].value, suffix='ms')
129
+ exposure.setValue(self._cam.exposure_current.value)
130
+ exposure.sigValueChanged.connect(self.exposure_spin_changed)
131
+
132
+ # Averaging choice
133
+ averaging = {
134
+ 'name': str(uEyeParams.FRAME_AVERAGING),
135
+ 'type': 'int',
136
+ 'value': 1,
137
+ 'dec': False,
138
+ 'decimals': 6,
139
+ 'limits': [1, 512],
140
+ 'suffix': 'frame',
141
+ }
142
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, averaging)
143
+
144
+ # trigger mode combobox
145
+ trigger_mode = {
146
+ 'name': str(uEyeParams.TRIGGER_MODE),
147
+ 'type': 'list',
148
+ 'limits': list(IDS_Camera.TRIGGER_MODES.keys()),
149
+ }
150
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, trigger_mode)
151
+ self.camera_options.get_param(uEyeParams.TRIGGER_MODE).sigValueChanged.connect(
152
+ lambda: self.cam_trigger_cbox_changed(uEyeParams.TRIGGER_MODE)
153
+ )
154
+
155
+ # flash mode combobox
156
+ flash_mode = {
157
+ 'name': str(uEyeParams.FLASH_MODE),
158
+ 'type': 'list',
159
+ 'limits': list(IDS_Camera.FLASH_MODES.keys()),
160
+ 'enabled': not self.mini,
161
+ }
162
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, flash_mode)
163
+ self.camera_options.get_param(uEyeParams.FLASH_MODE).sigValueChanged.connect(
164
+ lambda: self.cam_flash_cbox_changed(uEyeParams.FLASH_MODE)
165
+ )
166
+
167
+ # flash duration slider
168
+ falsh_duration = {
169
+ 'name': str(uEyeParams.FLASH_DURATION),
170
+ 'type': 'int',
171
+ 'value': 0,
172
+ 'dec': False,
173
+ 'decimals': 6,
174
+ 'suffix': 'us',
175
+ 'enabled': not self.mini,
176
+ 'step': self._cam.flash_inc.u32Duration.value,
177
+ 'limits': [0, self._cam.flash_max.u32Duration.value],
178
+ }
179
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, falsh_duration)
180
+ self.camera_options.get_param(
181
+ uEyeParams.FLASH_DURATION
182
+ ).sigValueChanged.connect(self.cam_flash_duration_value_changed)
183
+
184
+ # flash delay
185
+ falsh_delay = {
186
+ 'name': str(uEyeParams.FLASH_DELAY),
187
+ 'type': 'int',
188
+ 'value': 0,
189
+ 'dec': False,
190
+ 'decimals': 6,
191
+ 'suffix': 'us',
192
+ 'enabled': not self.mini,
193
+ 'step': self._cam.flash_inc.s32Delay.value,
194
+ 'limits': [0, self._cam.flash_max.s32Delay.value],
195
+ }
196
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, falsh_delay)
197
+ self.camera_options.get_param(uEyeParams.FLASH_DELAY).sigValueChanged.connect(
198
+ self.cam_flash_delay_value_changed
199
+ )
200
+
201
+ # setting the highest pixel clock as default
202
+ self.camera_options.set_param_value(
203
+ uEyeParams.PIXEL_CLOCK, str(self._cam.pixel_clock_list[-1].value)
204
+ )
205
+
206
+ # start freerun mode
207
+ freerun = self.get_event_action(uEyeParams.FREERUN)
208
+ self.camera_options.add_param_child(CamParams.ACQUISITION, freerun)
209
+ self.camera_options.get_param(uEyeParams.FREERUN).sigActivated.connect(
210
+ self.start_free_run
211
+ )
212
+
213
+ # start trigger mode button
214
+ triggered = self.get_event_action(uEyeParams.TRIGGERED)
215
+ self.camera_options.add_param_child(CamParams.ACQUISITION, triggered)
216
+ self.camera_options.get_param(uEyeParams.TRIGGERED).sigActivated.connect(
217
+ self.start_software_triggered
218
+ )
219
+
220
+ # stop acquisition
221
+ stop = {'name': str(uEyeParams.STOP), 'type': 'action'}
222
+ self.camera_options.add_param_child(CamParams.ACQUISITION, stop)
223
+ self.camera_options.get_param(uEyeParams.STOP).sigActivated.connect(
224
+ lambda: self.stop()
225
+ )
226
+
227
+ # config buttons
228
+ load = {'name': str(uEyeParams.LOAD), 'type': 'action'}
229
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, load)
230
+ self.camera_options.get_param(uEyeParams.LOAD).sigActivated.connect(
231
+ lambda: self.load_config()
232
+ )
233
+
234
+ save = {'name': str(uEyeParams.SAVE), 'type': 'action'}
235
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, save)
236
+ self.camera_options.get_param(uEyeParams.SAVE).sigActivated.connect(
237
+ lambda: self.save_config()
238
+ )
239
+
240
+ # ROI
241
+ self.camera_options.set_roi_limits(
242
+ (0, self.cam.rectROI.s32Width.value),
243
+ (0, self.cam.rectROI.s32Height.value),
244
+ (32, self.cam.rectROI.s32Width.value),
245
+ (32, self.cam.rectROI.s32Height.value),
246
+ )
247
+
248
+ @property
249
+ def cam(self):
250
+ '''The IDS_Camera property.
251
+
252
+ Returns
253
+ -------
254
+ IDS_Camera
255
+ the cam property value
256
+ '''
257
+ return self._cam
258
+
259
+ @cam.setter
260
+ def cam(self, cam: IDS_Camera):
261
+ '''The IDS_Camera property.
262
+
263
+ Parameters
264
+ ----------
265
+ cam : IDS_Camera
266
+ the IDS_Camera to set as panel camera.
267
+ '''
268
+ self._cam = cam
269
+
270
+ def set_ROI(self):
271
+ '''Sets the ROI for the slected IDS_Camera'''
272
+ if self.cam.acquisition:
273
+ QtWidgets.QMessageBox.warning(
274
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
275
+ )
276
+ return # if acquisition is already going on
277
+
278
+ self.cam.set_roi(*self.camera_options.get_roi_info())
279
+
280
+ # setting the highest pixel clock as default
281
+ self.camera_options.set_param_value(
282
+ uEyeParams.PIXEL_CLOCK, str(self._cam.pixel_clock_list[0].value)
283
+ )
284
+ self.camera_options.set_param_value(
285
+ uEyeParams.PIXEL_CLOCK, str(self._cam.pixel_clock_list[-1].value)
286
+ )
287
+
288
+ self.camera_options.set_roi_info(
289
+ self.cam.set_rectROI.s32X.value,
290
+ self.cam.set_rectROI.s32Y.value,
291
+ self.cam.set_rectROI.s32Width.value,
292
+ self.cam.set_rectROI.s32Height.value,
293
+ )
294
+
295
+ def reset_ROI(self):
296
+ '''Resets the ROI for the slected IDS_Camera'''
297
+ if self.cam.acquisition:
298
+ QtWidgets.QMessageBox.warning(
299
+ self, 'Warning', 'Cannot reset ROI while acquiring images!'
300
+ )
301
+ return # if acquisition is already going on
302
+
303
+ self.cam.reset_roi()
304
+ self.camera_options.set_roi_info(
305
+ 0, 0, self.cam.width.value, self.cam.height.value
306
+ )
307
+
308
+ # setting the highest pixel clock as default
309
+ self.camera_options.set_param_value(
310
+ uEyeParams.PIXEL_CLOCK, str(self._cam.pixel_clock_list[0].value)
311
+ )
312
+ self.camera_options.set_param_value(
313
+ uEyeParams.PIXEL_CLOCK, str(self._cam.pixel_clock_list[-1].value)
314
+ )
315
+
316
+ def center_ROI(self):
317
+ '''Calculates the x, y values for a centered ROI'''
318
+ if self.cam.acquisition:
319
+ QtWidgets.QMessageBox.warning(
320
+ self, 'Warning', 'Cannot center ROI while acquiring images!'
321
+ )
322
+ return # if acquisition is already going on
323
+
324
+ _, _, w, h = self.camera_options.get_roi_info()
325
+ x = (self.cam.rectROI.s32Width.value - w) // 2
326
+ y = (self.cam.rectROI.s32Height.value - h) // 2
327
+
328
+ self.camera_options.set_roi_info(x, y, w, h)
329
+
330
+ self.set_ROI()
331
+
332
+ def select_ROI(self):
333
+ '''
334
+ Opens a dialog to select a ROI from the last image.
335
+ '''
336
+ if self.cam.acquisition:
337
+ QtWidgets.QMessageBox.warning(
338
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
339
+ )
340
+ return # if acquisition is already going on
341
+
342
+ if self.acq_job.frame is not None:
343
+ try:
344
+
345
+ def work_func(**kwargs):
346
+ try:
347
+ image = uImage(self.acq_job.frame.image)
348
+
349
+ image.equalizeLUT(nLUT=True)
350
+
351
+ scale_factor = get_scaling_factor(image.height, image.width)
352
+
353
+ selector = MultiRectangularROISelector.get_selector(
354
+ image._view, scale_factor, max_rois=1
355
+ )
356
+ # if old_rois:
357
+ # selector.rois = old_rois
358
+
359
+ rois = selector.select_rectangular_rois()
360
+
361
+ rois = convert_rois_to_pos_size(rois)
362
+
363
+ if len(rois) > 0:
364
+ return rois[0]
365
+ else:
366
+ return None
367
+ except Exception:
368
+ traceback.print_exc()
369
+ return None
370
+
371
+ def done(result: list):
372
+ if result is not None:
373
+ # x, y, w, h = result
374
+ self.camera_options.set_roi_info(*result)
375
+
376
+ self.worker = QThreadWorker(work_func)
377
+ self.worker.signals.result.connect(done)
378
+ # Execute
379
+ self._threadpool.start(self.worker)
380
+ except Exception:
381
+ traceback.print_exc()
382
+
383
+ def select_ROIs(self):
384
+ '''
385
+ Opens a dialog to select multiple ROIs from the last image.
386
+ '''
387
+ if self.cam.acquisition:
388
+ QtWidgets.QMessageBox.warning(
389
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
390
+ )
391
+ return # if acquisition is already going on
392
+
393
+ if self.acq_job is not None:
394
+ try:
395
+
396
+ def work_func(**kwargs):
397
+ try:
398
+ image = uImage(self.acq_job.frame.image)
399
+
400
+ image.equalizeLUT(nLUT=True)
401
+
402
+ scale_factor = get_scaling_factor(image.height, image.width)
403
+
404
+ selector = MultiRectangularROISelector.get_selector(
405
+ image._view, scale_factor, max_rois=4, one_size=True
406
+ )
407
+
408
+ old_rois = self.camera_options.get_export_rois()
409
+
410
+ if len(old_rois) > 0:
411
+ old_rois = convert_pos_size_to_rois(old_rois)
412
+ selector.rois = old_rois
413
+
414
+ rois = selector.select_rectangular_rois()
415
+
416
+ rois = convert_rois_to_pos_size(rois)
417
+
418
+ if len(rois) > 0:
419
+ return rois
420
+ else:
421
+ return None
422
+ except Exception:
423
+ traceback.print_exc()
424
+ return None
425
+
426
+ def done(results: list[list]):
427
+ if results is not None:
428
+ rois_param = self.camera_options.get_param(
429
+ CamParams.EXPORTED_ROIS
430
+ )
431
+ rois_param.clearChildren()
432
+ for x, y, w, h in results:
433
+ self.camera_options.add_param_child(
434
+ CamParams.EXPORTED_ROIS,
435
+ {
436
+ 'name': 'ROI 1',
437
+ 'type': 'str',
438
+ 'readonly': True,
439
+ 'removable': True,
440
+ 'value': f'{x}, {y}, {w}, {h}',
441
+ },
442
+ )
443
+
444
+ self.worker = QThreadWorker(work_func)
445
+ self.worker.signals.result.connect(done)
446
+ # Execute
447
+ self._threadpool.start(self.worker)
448
+ except Exception:
449
+ traceback.print_exc()
450
+
451
+ def cam_trigger_cbox_changed(self, param: uEyeParams):
452
+ '''
453
+ Slot for changed trigger mode
454
+
455
+ Parameters
456
+ ----------
457
+ param : uEyeParams
458
+ parameter path to index of selected trigger mode
459
+ from IDS_Camera.TRIGGER_MODES.
460
+ '''
461
+ value = self.camera_options.get_param_value(param)
462
+ self._cam.set_trigger_mode(IDS_Camera.TRIGGER_MODES[value])
463
+ self._cam.get_trigger_mode()
464
+
465
+ def cam_flash_cbox_changed(self, param: uEyeParams):
466
+ '''
467
+ Slot for changed flash mode
468
+
469
+ Parameters
470
+ ----------
471
+ param : uEyeParams
472
+ parameter path to index of selected flash mode from IDS_Camera.FLASH_MODES
473
+ '''
474
+ value = self.camera_options.get_param_value(param)
475
+ self._cam.set_flash_mode(IDS_Camera.FLASH_MODES[value])
476
+ self._cam.get_flash_mode(output=True)
477
+
478
+ def cam_pixel_cbox_changed(self, param: uEyeParams):
479
+ '''
480
+ Slot for changed pixel clock
481
+
482
+ Parameters
483
+ ----------
484
+ param : uEyeParams
485
+ parameter path Enum value pointing to pixel clock parameter in MHz
486
+ (note that only certain values are allowed by camera)
487
+ '''
488
+ value = self.camera_options.get_param_value(param)
489
+ self._cam.set_pixel_clock(int(value))
490
+ self._cam.get_pixel_clock_info(False)
491
+
492
+ self.refresh_framerate()
493
+
494
+ def cam_framerate_value_changed(self, param, value):
495
+ '''
496
+ Slot for changed framerate
497
+
498
+ Parameters
499
+ ----------
500
+ param : Parameter
501
+ frames per second parameter
502
+ Value : double
503
+ selected frames per second
504
+ '''
505
+ self._cam.set_framerate(value)
506
+ # self._cam.get_framerate(False)
507
+
508
+ self.camera_options.set_param_value(
509
+ uEyeParams.FRAMERATE,
510
+ self._cam.current_framerate.value,
511
+ self.cam_framerate_value_changed,
512
+ )
513
+
514
+ self.refresh_exposure()
515
+
516
+ def exposure_spin_changed(self, param, value: float):
517
+ '''
518
+ Slot for changed exposure
519
+
520
+ Parameters
521
+ ----------
522
+ param : Parameter
523
+ exposure parameter
524
+ Value : double
525
+ selected exposure in milliseconds
526
+ '''
527
+ self._cam.set_exposure(value)
528
+ self._cam.get_exposure(False)
529
+
530
+ self.camera_options.set_param_value(
531
+ CamParams.EXPOSURE,
532
+ self._cam.exposure_current.value,
533
+ self.exposure_spin_changed,
534
+ )
535
+
536
+ self.refresh_flash()
537
+
538
+ self.OME_tab.set_param_value(MetaParams.EXPOSURE, self._cam.exposure_current)
539
+ if self.master:
540
+ self.exposureChanged.emit()
541
+
542
+ def refresh_framerate(self):
543
+ self._cam.get_framerate_range(False)
544
+
545
+ framerate = self.camera_options.get_param(uEyeParams.FRAMERATE)
546
+ framerate.setLimits(
547
+ (self._cam.min_framerate.value, self._cam.max_framerate.value)
548
+ )
549
+ framerate.setOpts(step=self._cam.increment_framerate.value)
550
+
551
+ self.cam_framerate_value_changed(framerate, self._cam.max_framerate.value)
552
+
553
+ def refresh_exposure(self):
554
+ self._cam.get_exposure_range(False)
555
+
556
+ exposure = self.camera_options.get_param(CamParams.EXPOSURE)
557
+ exposure.setLimits(
558
+ (self._cam.exposure_range[0].value, self._cam.exposure_range[1].value)
559
+ )
560
+ exposure.setOpts(step=self._cam.exposure_range[2].value)
561
+ exposure.setValue(self.cam.exposure_range[1].value)
562
+
563
+ def refresh_flash(self):
564
+ self._cam.get_flash_range(False)
565
+
566
+ duration = self.camera_options.get_param(uEyeParams.FLASH_DURATION)
567
+ duration.setLimits((0, self._cam.flash_max.u32Duration.value))
568
+ duration.setOpts(step=self._cam.flash_inc.u32Duration.value)
569
+ duration.setValue(0)
570
+
571
+ delay = self.camera_options.get_param(uEyeParams.FLASH_DURATION)
572
+ delay.setLimits((0, self._cam.flash_max.s32Delay.value))
573
+ delay.setOpts(step=self._cam.flash_inc.s32Delay.value)
574
+ delay.setValue(0)
575
+
576
+ def cam_flash_duration_value_changed(self, param, value):
577
+ '''
578
+ Slot for changed flash duration
579
+
580
+ Parameters
581
+ ----------
582
+ param : Parameter
583
+ flash duration parameter
584
+ Value : double
585
+ selected flash duration in micro-seconds
586
+ '''
587
+ self._cam.set_flash_params(self._cam.flash_cur.s32Delay.value, value)
588
+ self._cam.get_flash_params()
589
+
590
+ self.camera_options.set_param_value(
591
+ uEyeParams.FLASH_DURATION,
592
+ self._cam.flash_cur.u32Duration.value,
593
+ self.cam_flash_duration_value_changed,
594
+ )
595
+
596
+ def cam_flash_delay_value_changed(self, param, value):
597
+ '''
598
+ Slot for changed flash delay
599
+
600
+ Parameters
601
+ ----------
602
+ param : Parameter
603
+ flash delay parameter
604
+ Value : double
605
+ selected flash delay in micro-seconds
606
+ '''
607
+ self._cam.set_flash_params(value, self._cam.flash_cur.u32Duration.value)
608
+
609
+ self.camera_options.set_param_value(
610
+ uEyeParams.FLASH_DELAY,
611
+ self._cam.flash_cur.s32Delay.value,
612
+ self.cam_flash_delay_value_changed,
613
+ )
614
+
615
+ def start_free_run(self, param=None, Prefix=''):
616
+ '''
617
+ Starts free run acquisition mode
618
+
619
+ Parameters
620
+ ----------
621
+ param : Parameter
622
+ the parameter that was activated.
623
+ Prefix : str
624
+ an extra prefix added to the image stack file name.
625
+ '''
626
+ nRet = 0
627
+ if self._cam.acquisition:
628
+ return # if acquisition is already going on
629
+
630
+ if not self._cam.memory_allocated:
631
+ self._cam.allocate_memory_buffer() # allocate memory
632
+
633
+ if not self._cam.capture_video:
634
+ self._cam.start_live_capture() # start live capture (freerun mode)
635
+
636
+ self._cam.refresh_info() # refresh adapter info
637
+
638
+ self._save_prefix = Prefix
639
+ self.acq_job = self.getAcquisitionJob()
640
+
641
+ self._cam.acquisition = True # set acquisition flag to true
642
+
643
+ # start both capture and display workers
644
+ self.start_all_workers()
645
+
646
+ def start_software_triggered(self, param=None, Prefix=''):
647
+ '''
648
+ Starts trigger acquisition mode
649
+
650
+ Parameters
651
+ ----------
652
+ param : Parameter
653
+ the parameter that was activated.
654
+ Prefix : str
655
+ an extra prefix added to the image stack file name.
656
+ '''
657
+
658
+ nRet = 0
659
+ if self._cam.acquisition:
660
+ return # if acquisition is already going on
661
+
662
+ if not self._cam.memory_allocated:
663
+ self._cam.allocate_memory_buffer() # allocate memory
664
+
665
+ self._cam.refresh_info() # refresh adapter info
666
+
667
+ self._save_prefix = Prefix
668
+ self.acq_job = self.getAcquisitionJob()
669
+
670
+ self._cam.acquisition = True # set acquisition flag to true
671
+
672
+ # start both capture and display workers
673
+ self.start_all_workers()
674
+
675
+ def cam_capture(self, *args, **kwargs):
676
+ '''Capture function executed by the capture worker.
677
+
678
+ Sends software trigger signals and transfers the
679
+ acquired frame to the display processing stack.
680
+
681
+ Parameters
682
+ ----------
683
+ nRet : int
684
+ return code from IDS_Camera, ueye.IS_SUCCESS = 0 to run.
685
+ cam : IDS_Camera
686
+ the IDS_Camera used to acquire frames.
687
+ '''
688
+ try:
689
+ nRet = ueye.IS_SUCCESS
690
+ time = QDateTime.currentDateTime()
691
+ # Continuous image capture
692
+ while nRet == ueye.IS_SUCCESS:
693
+ self.acq_job.capture_time = time.msecsTo(QDateTime.currentDateTime())
694
+ time = QDateTime.currentDateTime()
695
+
696
+ if not self._cam.capture_video:
697
+ ueye.is_FreezeVideo(self._cam.hCam, ueye.IS_WAIT)
698
+
699
+ nRet = self._cam.wait_for_next_image(500, not self.mini)
700
+ if nRet == ueye.IS_SUCCESS:
701
+ self._cam.get_pitch()
702
+ data = self._cam.get_data()
703
+
704
+ self._buffer.put(data.copy())
705
+ # add sensor temperature to the stack
706
+ self._temps.put(self._cam.get_temperature())
707
+ self.acq_job.frames_captured = self.acq_job.frames_captured + 1
708
+ if (
709
+ self.acq_job.frames_captured >= self.acq_job.frames
710
+ and not self.mini
711
+ ):
712
+ self.acq_job.c_event.set()
713
+ self.acq_job.stop_threads = True
714
+ logging.debug('Stop')
715
+ self._cam.unlock_buffer()
716
+
717
+ QtCore.QThread.usleep(100) # sleep 100us
718
+
719
+ if self.acq_job.stop_threads:
720
+ break # in case stop threads is initiated
721
+ except Exception:
722
+ traceback.print_exc()
723
+ finally:
724
+ # reset flags and release resources
725
+ self._cam.acquisition = False
726
+ if self._cam.capture_video:
727
+ self._cam.stop_live_capture()
728
+ self._cam.free_memory()
729
+ if self._dispose_cam:
730
+ self._cam.dispose()
731
+
732
+ self._threadpool.releaseThread()
733
+
734
+ def getCaptureArgs(self) -> list:
735
+ '''User specific arguments to be passed to the parallelized
736
+ Camera_Panel.cam_capture function.
737
+
738
+ Example
739
+ ------
740
+ check child panels (vimba, ueye or thorlabs)
741
+
742
+ Returns
743
+ -------
744
+ list
745
+ list of args to be passed in order to
746
+ Camera_Panel.cam_capture function.
747
+
748
+ Raises
749
+ ------
750
+ NotImplementedError
751
+ Has to be implemented by the use in child class.
752
+ '''
753
+ args = []
754
+ return args
755
+
756
+ def save_config(self):
757
+ filename, _ = getSaveFileName(
758
+ self, 'Save config', filter='JSON Files (*.json);;'
759
+ )
760
+
761
+ if len(filename) > 0:
762
+ config = {
763
+ 'model': self.cam.sInfo.strSensorName.decode('utf-8'),
764
+ 'serial': self.cam.cInfo.SerNo.decode('utf-8'),
765
+ 'clock speed': self.cam.pixel_clock.value,
766
+ 'trigger': self.camera_options.get_param_value(uEyeParams.TRIGGER_MODE),
767
+ 'flash mode': self.camera_options.get_param_value(
768
+ uEyeParams.FLASH_MODE
769
+ ),
770
+ 'framerate': self.cam.current_framerate.value,
771
+ 'exposure': self.cam.exposure_current.value,
772
+ 'flash duration': self.cam.flash_cur.u32Duration.value,
773
+ 'flash delay': self.cam.flash_cur.s32Delay.value,
774
+ 'ROI w': self.cam.set_rectROI.s32Width.value,
775
+ 'ROI h': self.cam.set_rectROI.s32Height.value,
776
+ 'ROI x': self.cam.set_rectROI.s32X.value,
777
+ 'ROI y': self.cam.set_rectROI.s32Y.value,
778
+ 'Zoom': self.camera_options.get_param_value(CamParams.RESIZE_DISPLAY),
779
+ }
780
+
781
+ with open(filename, 'w') as file:
782
+ json.dump(config, file)
783
+
784
+ QtWidgets.QMessageBox.information(self, 'Info', 'Config saved.')
785
+ else:
786
+ QtWidgets.QMessageBox.warning(self, 'Warning', 'Config not saved.')
787
+
788
+ def load_config(self):
789
+ filename, _ = getOpenFileName(
790
+ self, 'Load config', filter='JSON Files (*.json);;'
791
+ )
792
+
793
+ if len(filename) > 0:
794
+ config: dict = None
795
+ keys = [
796
+ 'model',
797
+ 'serial',
798
+ 'clock speed',
799
+ 'trigger',
800
+ 'flash mode',
801
+ 'framerate',
802
+ 'exposure',
803
+ 'flash duration',
804
+ 'flash delay',
805
+ 'ROI w',
806
+ 'ROI h',
807
+ 'ROI x',
808
+ 'ROI y',
809
+ 'Zoom',
810
+ ]
811
+ with open(filename) as file:
812
+ config = json.load(file)
813
+ if all(key in config for key in keys):
814
+ if self.cam.sInfo.strSensorName.decode('utf-8') == config['model']:
815
+ self.camera_options.set_roi_info(
816
+ int(config['ROI x']),
817
+ int(config['ROI y']),
818
+ int(config['ROI w']),
819
+ int(config['ROI h']),
820
+ )
821
+ self.set_ROI()
822
+
823
+ self.camera_options.set_param_value(
824
+ uEyeParams.PIXEL_CLOCK, str(config['clock speed'])
825
+ )
826
+ self.camera_options.set_param_value(
827
+ uEyeParams.TRIGGER_MODE, config['trigger']
828
+ )
829
+ self.camera_options.set_param_value(
830
+ uEyeParams.FLASH_DURATION, config['flash mode']
831
+ )
832
+
833
+ self.camera_options.set_param_value(
834
+ uEyeParams.FRAMERATE, config['framerate']
835
+ )
836
+
837
+ self.camera_options.set_param_value(
838
+ CamParams.EXPOSURE, config['exposure']
839
+ )
840
+
841
+ self.camera_options.set_param_value(
842
+ uEyeParams.FLASH_DURATION, config['flash duration']
843
+ )
844
+
845
+ self.camera_options.set_param_value(
846
+ uEyeParams.FLASH_DELAY, config['flash delay']
847
+ )
848
+
849
+ self.camera_options.set_param_value(
850
+ CamParams.RESIZE_DISPLAY, float(config['Zoom'])
851
+ )
852
+ else:
853
+ QtWidgets.QMessageBox.warning(
854
+ self, 'Warning', 'Camera model is different.'
855
+ )
856
+ else:
857
+ QtWidgets.QMessageBox.warning(
858
+ self, 'Warning', 'Wrong or corrupted config file.'
859
+ )
860
+ else:
861
+ QtWidgets.QMessageBox.warning(self, 'Warning', 'No file selected.')