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,759 @@
1
+ import logging
2
+ import time
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.micam import miDummy
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
+ import vimba as vb
22
+ except Exception:
23
+ vb = None
24
+
25
+
26
+ class DummyParams(Enum):
27
+ FREERUN = 'Acquisition.Freerun'
28
+ STOP = 'Acquisition.Stop'
29
+ LOAD = 'Acquisition Settings.Load Config'
30
+ SAVE = 'Acquisition Settings.Save Config'
31
+ GAIN = 'Acquisition Settings.Gain'
32
+ OFFSET = 'Acquisition Settings.Offset'
33
+ HEIGHT = 'Acquisition Settings.Height'
34
+ WIDTH = 'Acquisition Settings.Width'
35
+ BINNING_HORIZONTAL = 'Acquisition Settings.Binning Horizontal'
36
+ BINNING_VERTICAL = 'Acquisition Settings.Binning Vertical'
37
+ BIT_DEPTH = 'Acquisition Settings.Bit Depth'
38
+ FULL_WELL_CAPACITY = 'Acquisition Settings.Full Well Capacity'
39
+ QUANTUM_EFFICIENCY = 'Acquisition Settings.Quantum Efficiency'
40
+ DARK_CURRENT = 'Acquisition Settings.Dark Current'
41
+ READOUT_NOISE = 'Acquisition Settings.Readout Noise'
42
+ NOISE_BASELINE = 'Acquisition Settings.Noise Baseline'
43
+ FLUX = 'Acquisition Settings.Flux'
44
+ PATTERN_TYPE = 'Acquisition Settings.Pattern Type'
45
+ PATTERN_OFFSET = 'Acquisition Settings.Pattern Offset'
46
+ PATTERN_SINUSOIDAL = 'Acquisition Settings.Sinusoidal Pattern'
47
+ SINUSOIDAL_FREQUENCY = 'Acquisition Settings.Sinusoidal Pattern.Frequency'
48
+ SINUSOIDAL_PHASE = 'Acquisition Settings.Sinusoidal Pattern.Phase'
49
+ SINUSOIDAL_AMPLITUDE = 'Acquisition Settings.Sinusoidal Pattern.Amplitude'
50
+ SINUSOIDAL_DIRECTION = 'Acquisition Settings.Sinusoidal Pattern.Direction'
51
+
52
+ DRIFT_SIM = 'Acquisition Settings.Drift Simulation'
53
+ DRIFT_SPEED = DRIFT_SIM + '.Speed [pixel/frames]'
54
+ DRIFT_PERIOD = DRIFT_SIM + '.Period [frames]'
55
+ DRIFT_MOMENTUM = DRIFT_SIM + '.Momentum Coefficient'
56
+ DRIFT_RANDOM_WALK = DRIFT_SIM + '.Random Walk Coefficient'
57
+ DRIFT_VIBRATION = DRIFT_SIM + '.Vibration Amplitude'
58
+ DRIFT_SIGMA_X = DRIFT_SIM + r'.$\sigma_x$ [pixels]'
59
+ DRIFT_SIGMA_Y = DRIFT_SIM + r'.$\sigma_y$ [pixels]'
60
+ DRIFT_AMPLITUDE = DRIFT_SIM + '.Amplitude'
61
+
62
+ SM = 'Acquisition Settings.Single Molecule Sim'
63
+ SM_INTENSITY = SM + '.Intensity [photons/loc]'
64
+ SM_DENSITY = SM + '.Density [loc/um]'
65
+ SM_WAVELENGTH = SM + '.Wavelength [nm]'
66
+ SM_PIXEL_SIZE = SM + '.Projected Pixel Size [nm]'
67
+ SM_NA = SM + '.Objective NA'
68
+
69
+ def __str__(self):
70
+ '''
71
+ Return the last part of the enum value (Param name).
72
+ '''
73
+ return self.value.split('.')[-1]
74
+
75
+ def get_path(self):
76
+ '''
77
+ Return the full parameter path.
78
+ '''
79
+ return self.value.split('.')
80
+
81
+
82
+ class Dummy_Panel(Camera_Panel):
83
+ '''
84
+ A Qt Widget for a dummy camera
85
+ | Inherits Camera_Panel
86
+ '''
87
+
88
+ PARAMS = DummyParams
89
+
90
+ def __init__(self, mini=False, *args, **kwargs):
91
+ '''
92
+ Initializes a new Dummy_Panel Qt widget.
93
+
94
+ Inherits Camera_Panel.
95
+
96
+ Parameters
97
+ ----------
98
+ mini : bool, optional
99
+ Flag indicating if this is a mini camera panel, by default False.
100
+
101
+ Other Parameters
102
+ ---------------
103
+ *args
104
+ Arguments to pass to the Camera_Panel constructor.
105
+
106
+ **kwargs
107
+ Keyword arguments to pass to the Camera_Panel constructor.
108
+ '''
109
+ super().__init__(miDummy(), mini, *args, **kwargs)
110
+
111
+ self.OME_tab.set_param_value(MetaParams.CHANNEL_NAME, self._cam.name)
112
+ self.OME_tab.set_param_value(MetaParams.DET_MANUFACTURER, 'MicroEye')
113
+ self.OME_tab.set_param_value(MetaParams.DET_MODEL, 'Dummy')
114
+ self.OME_tab.set_param_value(MetaParams.DET_SERIAL, '123456789')
115
+ self.OME_tab.set_param_value(MetaParams.DET_TYPE, 'CMOS')
116
+
117
+ # exposure init
118
+ exposure = self.camera_options.get_param(CamParams.EXPOSURE)
119
+ exposure.setLimits((self._cam.exposure_range[0], self._cam.exposure_range[1]))
120
+ exposure.setOpts(
121
+ step=self._cam.exposure_increment, suffix=self._cam.exposure_unit
122
+ )
123
+ exposure.setValue(self._cam.exposure_current)
124
+ exposure.sigValueChanged.connect(self.exposure_spin_changed)
125
+
126
+ HEIGHT = {
127
+ 'name': str(DummyParams.HEIGHT),
128
+ 'type': 'int',
129
+ 'value': 512,
130
+ 'limits': [0, 4096],
131
+ }
132
+ WIDTH = {
133
+ 'name': str(DummyParams.WIDTH),
134
+ 'type': 'int',
135
+ 'value': 512,
136
+ 'limits': [0, 4096],
137
+ }
138
+ BINNING_HORIZONTAL = {
139
+ 'name': str(DummyParams.BINNING_HORIZONTAL),
140
+ 'type': 'int',
141
+ 'value': 1,
142
+ 'limits': [0, 10],
143
+ }
144
+ BINNING_VERTICAL = {
145
+ 'name': str(DummyParams.BINNING_VERTICAL),
146
+ 'type': 'int',
147
+ 'value': 1,
148
+ 'limits': [0, 10],
149
+ }
150
+ BIT_DEPTH = {
151
+ 'name': str(DummyParams.BIT_DEPTH),
152
+ 'type': 'list',
153
+ 'limits': [8, 10, 12, 16],
154
+ 'value': 12,
155
+ }
156
+ GAIN = {'name': str(DummyParams.GAIN), 'type': 'float', 'value': 2.23}
157
+ FULL_WELL_CAPACITY = {
158
+ 'name': str(DummyParams.FULL_WELL_CAPACITY),
159
+ 'type': 'int',
160
+ 'value': 9200,
161
+ 'suffix': 'e-',
162
+ }
163
+ QUANTUM_EFFICIENCY = {
164
+ 'name': str(DummyParams.QUANTUM_EFFICIENCY),
165
+ 'type': 'float',
166
+ 'value': 0.8,
167
+ 'limits': [0, 1],
168
+ }
169
+ DARK_CURRENT = {
170
+ 'name': str(DummyParams.DARK_CURRENT),
171
+ 'type': 'float',
172
+ 'value': 0.0001,
173
+ 'suffix': ' e-/s',
174
+ }
175
+ READOUT_NOISE = {
176
+ 'name': str(DummyParams.READOUT_NOISE),
177
+ 'type': 'float',
178
+ 'value': 2.1,
179
+ 'suffix': ' e-',
180
+ }
181
+ NOISE_BASELINE = {
182
+ 'name': str(DummyParams.NOISE_BASELINE),
183
+ 'type': 'float',
184
+ 'value': 5.0,
185
+ 'limits': [0, 2**16],
186
+ 'suffix': ' ADU',
187
+ }
188
+ FLUX = {
189
+ 'name': str(DummyParams.FLUX),
190
+ 'type': 'float',
191
+ 'value': 0,
192
+ 'suffix': ' e-/p/s',
193
+ }
194
+ PATTERN_TYPE = {
195
+ 'name': str(DummyParams.PATTERN_TYPE),
196
+ 'type': 'list',
197
+ 'limits': [
198
+ 'Constant Flux',
199
+ 'Sinusoidal',
200
+ 'Gaussian',
201
+ 'Single Molecule Sim',
202
+ ],
203
+ 'value': 'Sinusoidal',
204
+ }
205
+ PATTERN_OFFSET = {
206
+ 'name': str(DummyParams.PATTERN_OFFSET),
207
+ 'type': 'float',
208
+ 'value': 0.0,
209
+ 'suffix': ' e-',
210
+ }
211
+ PATTERN_SINUSOIDAL = {
212
+ 'name': str(DummyParams.PATTERN_SINUSOIDAL),
213
+ 'type': 'group',
214
+ 'expanded': False,
215
+ 'children': [
216
+ {
217
+ 'name': str(DummyParams.SINUSOIDAL_FREQUENCY),
218
+ 'type': 'float',
219
+ 'value': 0.01,
220
+ 'suffix': ' Hz',
221
+ },
222
+ {
223
+ 'name': str(DummyParams.SINUSOIDAL_PHASE),
224
+ 'type': 'float',
225
+ 'value': 0.0,
226
+ 'suffix': ' deg',
227
+ },
228
+ {
229
+ 'name': str(DummyParams.SINUSOIDAL_AMPLITUDE),
230
+ 'type': 'float',
231
+ 'value': 0.1e5,
232
+ 'suffix': ' e-/p/s',
233
+ },
234
+ {
235
+ 'name': str(DummyParams.SINUSOIDAL_DIRECTION),
236
+ 'type': 'list',
237
+ 'limits': ['d', 'h', 'v', 'r'],
238
+ 'value': 'd',
239
+ },
240
+ ],
241
+ }
242
+ SM_SIM = {
243
+ 'name': str(DummyParams.SM),
244
+ 'type': 'group',
245
+ 'expanded': False,
246
+ 'children': [
247
+ {
248
+ 'name': str(DummyParams.SM_INTENSITY),
249
+ 'type': 'float',
250
+ 'value': 5000,
251
+ 'decimals': 6,
252
+ },
253
+ {
254
+ 'name': str(DummyParams.SM_DENSITY),
255
+ 'type': 'float',
256
+ 'value': 0.5,
257
+ 'decimals': 6,
258
+ },
259
+ {
260
+ 'name': str(DummyParams.SM_PIXEL_SIZE),
261
+ 'type': 'float',
262
+ 'value': 114.17,
263
+ 'decimals': 6,
264
+ },
265
+ {
266
+ 'name': str(DummyParams.SM_WAVELENGTH),
267
+ 'type': 'float',
268
+ 'value': 650,
269
+ 'decimals': 6,
270
+ },
271
+ {
272
+ 'name': str(DummyParams.SM_NA),
273
+ 'type': 'float',
274
+ 'value': 1.49,
275
+ 'decimals': 6,
276
+ },
277
+ ],
278
+ }
279
+
280
+ # drift simulation
281
+ DRIFT_SIM = {
282
+ 'name': str(DummyParams.DRIFT_SIM),
283
+ 'type': 'group',
284
+ 'expanded': False,
285
+ 'children': [
286
+ {
287
+ 'name': str(DummyParams.DRIFT_SPEED),
288
+ 'type': 'float',
289
+ 'value': 0.1,
290
+ },
291
+ {
292
+ 'name': str(DummyParams.DRIFT_PERIOD),
293
+ 'type': 'int',
294
+ 'value': 90,
295
+ },
296
+ {
297
+ 'name': str(DummyParams.DRIFT_MOMENTUM),
298
+ 'type': 'float',
299
+ 'value': 0.8,
300
+ 'limits': [0, 1],
301
+ },
302
+ {
303
+ 'name': str(DummyParams.DRIFT_RANDOM_WALK),
304
+ 'type': 'float',
305
+ 'value': 0.80,
306
+ },
307
+ {
308
+ 'name': str(DummyParams.DRIFT_VIBRATION),
309
+ 'type': 'float',
310
+ 'value': 0.1,
311
+ },
312
+ {
313
+ 'name': str(DummyParams.DRIFT_SIGMA_X),
314
+ 'type': 'float',
315
+ 'value': 5,
316
+ },
317
+ {
318
+ 'name': str(DummyParams.DRIFT_SIGMA_Y),
319
+ 'type': 'float',
320
+ 'value': 20,
321
+ },
322
+ {
323
+ 'name': str(DummyParams.DRIFT_AMPLITUDE),
324
+ 'type': 'float',
325
+ 'value': 5000,
326
+ }
327
+ ],
328
+ }
329
+
330
+ # add parameters
331
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, HEIGHT)
332
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, WIDTH)
333
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, BINNING_HORIZONTAL)
334
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, BINNING_VERTICAL)
335
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, BIT_DEPTH)
336
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, GAIN)
337
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, FULL_WELL_CAPACITY)
338
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, QUANTUM_EFFICIENCY)
339
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, DARK_CURRENT)
340
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, READOUT_NOISE)
341
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, NOISE_BASELINE)
342
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, FLUX)
343
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, PATTERN_TYPE)
344
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, PATTERN_OFFSET)
345
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, PATTERN_SINUSOIDAL)
346
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, DRIFT_SIM)
347
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, SM_SIM)
348
+
349
+ # update params
350
+ self.camera_options.paramsChanged.connect(self.update_cam)
351
+
352
+ # start freerun mode button
353
+ freerun = self.get_event_action(DummyParams.FREERUN)
354
+ self.camera_options.add_param_child(CamParams.ACQUISITION, freerun)
355
+ self.camera_options.get_param(DummyParams.FREERUN).sigActivated.connect(
356
+ self.start_free_run
357
+ )
358
+
359
+ # stop acquisition button
360
+ stop = {'name': str(DummyParams.STOP), 'type': 'action'}
361
+ self.camera_options.add_param_child(CamParams.ACQUISITION, stop)
362
+ self.camera_options.get_param(DummyParams.STOP).sigActivated.connect(self.stop)
363
+
364
+ # config buttons
365
+ load = {'name': str(DummyParams.LOAD), 'type': 'action'}
366
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, load)
367
+ self.camera_options.get_param(DummyParams.LOAD).sigActivated.connect(
368
+ self.load_config
369
+ )
370
+
371
+ save = {'name': str(DummyParams.SAVE), 'type': 'action'}
372
+ self.camera_options.add_param_child(CamParams.ACQ_SETTINGS, save)
373
+ self.camera_options.get_param(DummyParams.SAVE).sigActivated.connect(
374
+ self.save_config
375
+ )
376
+
377
+ # ROI
378
+ self.camera_options.set_roi_limits(
379
+ (0, self.cam.getWidth()),
380
+ (0, self.cam.getHeight()),
381
+ (32, self.cam.getWidth()),
382
+ (32, self.cam.getHeight()),
383
+ )
384
+
385
+ @property
386
+ def cam(self):
387
+ '''The miDummy property.
388
+
389
+ Returns
390
+ -------
391
+ miDummy
392
+ the cam property value
393
+ '''
394
+ return self._cam
395
+
396
+ @cam.setter
397
+ def cam(self, cam: miDummy):
398
+ '''The miDummy property.
399
+
400
+ Parameters
401
+ ----------
402
+ cam : miDummy
403
+ the miDummy to set as panel camera.
404
+ '''
405
+ self._cam = cam
406
+
407
+ def update_cam(self, param, param_value):
408
+ '''Update the camera parameters.'''
409
+ path = self.camera_options.param_tree.childPath(param)
410
+
411
+ try:
412
+ param_name = DummyParams('.'.join(path))
413
+ except ValueError:
414
+ return
415
+
416
+ if param_name == DummyParams.HEIGHT:
417
+ self._cam.height = param_value
418
+ elif param_name == DummyParams.WIDTH:
419
+ self._cam.width = param_value
420
+ elif param_name == DummyParams.BINNING_HORIZONTAL:
421
+ self._cam.binning_horizontal = param_value
422
+ elif param_name == DummyParams.BINNING_VERTICAL:
423
+ self._cam.binning_vertical = param_value
424
+ elif param_name == DummyParams.BIT_DEPTH:
425
+ self._cam.bit_depth = param_value
426
+ elif param_name == DummyParams.GAIN:
427
+ self._cam.gain = param_value
428
+ elif param_name == DummyParams.FULL_WELL_CAPACITY:
429
+ self._cam.full_well_capacity = param_value
430
+ elif param_name == DummyParams.QUANTUM_EFFICIENCY:
431
+ self._cam.quantum_efficiency = param_value
432
+ elif param_name == DummyParams.DARK_CURRENT:
433
+ self._cam.dark_current = param_value
434
+ elif param_name == DummyParams.READOUT_NOISE:
435
+ self._cam.readout_noise = param_value
436
+ elif param_name == DummyParams.NOISE_BASELINE:
437
+ self._cam.noise_baseline = param_value
438
+ elif param_name == DummyParams.FLUX:
439
+ self._cam.flux = param_value
440
+ elif param_name == DummyParams.PATTERN_TYPE:
441
+ self._cam.pattern_type = param_value
442
+ elif param_name == DummyParams.PATTERN_OFFSET:
443
+ self._cam.pattern_offset = param_value
444
+
445
+ elif param_name == DummyParams.SINUSOIDAL_AMPLITUDE:
446
+ self._cam.sinusoidal_amplitude = param_value
447
+ elif param_name == DummyParams.SINUSOIDAL_FREQUENCY:
448
+ self._cam.sinusoidal_frequency = param_value
449
+ elif param_name == DummyParams.SINUSOIDAL_PHASE:
450
+ self._cam.sinusoidal_phase = param_value
451
+ elif param_name == DummyParams.SINUSOIDAL_DIRECTION:
452
+ self._cam.sinusoidal_direction = param_value
453
+
454
+ elif param_name == DummyParams.SM_INTENSITY:
455
+ self._cam.sm_intensity = param_value
456
+ elif param_name == DummyParams.SM_DENSITY:
457
+ self._cam.sm_density = param_value
458
+ elif param_name == DummyParams.SM_PIXEL_SIZE:
459
+ self._cam.sm_pixel_size = param_value
460
+ elif param_name == DummyParams.SM_WAVELENGTH:
461
+ self._cam.sm_wavelength = param_value
462
+ elif param_name == DummyParams.SM_NA:
463
+ self._cam.sm_na = param_value
464
+
465
+ elif param_name == DummyParams.DRIFT_SPEED:
466
+ self._cam.drift_speed = param_value
467
+ elif param_name == DummyParams.DRIFT_PERIOD:
468
+ self._cam.drift_period = param_value
469
+ elif param_name == DummyParams.DRIFT_MOMENTUM:
470
+ self._cam.drift_momentum = param_value
471
+ elif param_name == DummyParams.DRIFT_RANDOM_WALK:
472
+ self._cam.drift_random_walk_factor = param_value
473
+ elif param_name == DummyParams.DRIFT_VIBRATION:
474
+ self._cam.drift_vibration_amplitude = param_value
475
+ elif param_name == DummyParams.DRIFT_SIGMA_X:
476
+ self._cam.drift_sigma_x = param_value
477
+ elif param_name == DummyParams.DRIFT_SIGMA_Y:
478
+ self._cam.drift_sigma_y = param_value
479
+ elif param_name == DummyParams.DRIFT_AMPLITUDE:
480
+ self._cam.drift_amplitude = param_value
481
+
482
+ def set_ROI(self):
483
+ '''Sets the ROI for the slected miDummy'''
484
+ if self.cam.acquisition:
485
+ QtWidgets.QMessageBox.warning(
486
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
487
+ )
488
+ return # if acquisition is already going on
489
+
490
+ self.cam.set_roi(*self.camera_options.get_roi_info(False))
491
+
492
+ def reset_ROI(self):
493
+ '''Resets the ROI for the slected miDummy'''
494
+ if self.cam.acquisition:
495
+ QtWidgets.QMessageBox.warning(
496
+ self, 'Warning', 'Cannot reset ROI while acquiring images!'
497
+ )
498
+ return # if acquisition is already going on
499
+
500
+ self.cam.reset_roi()
501
+
502
+ self.camera_options.set_roi_info(
503
+ 0, 0, int(self.cam.width), int(self.cam.height)
504
+ )
505
+
506
+ def center_ROI(self):
507
+ '''Sets the ROI for the slected miDummy'''
508
+ if self.cam.acquisition:
509
+ QtWidgets.QMessageBox.warning(
510
+ self, 'Warning', 'Cannot center ROI while acquiring images!'
511
+ )
512
+ return # if acquisition is already going on
513
+
514
+ x, y, width, height = self.camera_options.get_roi_info(False)
515
+ x = (int(self.cam.width) - width) // 2
516
+ y = (int(self.cam.height) - height) // 2
517
+
518
+ self.cam.set_roi(x, y, width, height)
519
+
520
+ self.camera_options.set_roi_info(x, y, width, height)
521
+
522
+ def select_ROI(self):
523
+ '''
524
+ Opens a dialog to select a ROI from the last image.
525
+ '''
526
+ if self.cam.acquisition:
527
+ QtWidgets.QMessageBox.warning(
528
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
529
+ )
530
+ return # if acquisition is already going on
531
+
532
+ if self.acq_job is not None:
533
+ try:
534
+
535
+ def work_func(**kwargs):
536
+ try:
537
+ image = uImage(self.acq_job.frame.image)
538
+
539
+ image.equalizeLUT(nLUT=True)
540
+
541
+ scale_factor = get_scaling_factor(image.height, image.width)
542
+
543
+ selector = MultiRectangularROISelector.get_selector(
544
+ image._view, scale_factor, max_rois=1
545
+ )
546
+ # if old_rois:
547
+ # selector.rois = old_rois
548
+
549
+ rois = selector.select_rectangular_rois()
550
+
551
+ rois = convert_rois_to_pos_size(rois)
552
+
553
+ if len(rois) > 0:
554
+ return rois[0]
555
+ else:
556
+ return None
557
+ except Exception:
558
+ traceback.print_exc()
559
+ return None
560
+
561
+ def done(result: list):
562
+ if result is not None:
563
+ # x, y, w, h = result
564
+ self.camera_options.set_roi_info(*result)
565
+
566
+ self.worker = QThreadWorker(work_func)
567
+ self.worker.signals.result.connect(done)
568
+ # Execute
569
+ self._threadpool.start(self.worker)
570
+ except Exception:
571
+ traceback.print_exc()
572
+
573
+ def select_ROIs(self):
574
+ '''
575
+ Opens a dialog to select multiple ROIs from the last image.
576
+ '''
577
+ if self.cam.acquisition:
578
+ QtWidgets.QMessageBox.warning(
579
+ self, 'Warning', 'Cannot set ROI while acquiring images!'
580
+ )
581
+ return # if acquisition is already going on
582
+
583
+ if self.acq_job is not None:
584
+ try:
585
+
586
+ def work_func(**kwargs):
587
+ try:
588
+ image = uImage(self.acq_job.frame.image)
589
+
590
+ image.equalizeLUT(nLUT=True)
591
+
592
+ scale_factor = get_scaling_factor(image.height, image.width)
593
+
594
+ selector = MultiRectangularROISelector.get_selector(
595
+ image._view, scale_factor, max_rois=4, one_size=True
596
+ )
597
+
598
+ old_rois = self.camera_options.get_export_rois()
599
+
600
+ if len(old_rois) > 0:
601
+ old_rois = convert_pos_size_to_rois(old_rois)
602
+ selector.rois = old_rois
603
+
604
+ rois = selector.select_rectangular_rois()
605
+
606
+ rois = convert_rois_to_pos_size(rois)
607
+
608
+ if len(rois) > 0:
609
+ return rois
610
+ else:
611
+ return None
612
+ except Exception:
613
+ traceback.print_exc()
614
+ return None
615
+
616
+ def done(results: list[list]):
617
+ if results is not None:
618
+ rois_param = self.camera_options.get_param(
619
+ CamParams.EXPORTED_ROIS
620
+ )
621
+ rois_param.clearChildren()
622
+ for x, y, w, h in results:
623
+ self.camera_options.add_param_child(
624
+ CamParams.EXPORTED_ROIS,
625
+ {
626
+ 'name': 'ROI 1',
627
+ 'type': 'str',
628
+ 'readonly': True,
629
+ 'removable': True,
630
+ 'value': f'{x}, {y}, {w}, {h}',
631
+ },
632
+ )
633
+
634
+ self.worker = QThreadWorker(work_func)
635
+ self.worker.signals.result.connect(done)
636
+ # Execute
637
+ self._threadpool.start(self.worker)
638
+ except Exception:
639
+ traceback.print_exc()
640
+
641
+ def exposure_spin_changed(self, param, value: float):
642
+ '''
643
+ Slot for changed exposure
644
+
645
+ Parameters
646
+ ----------
647
+ Value : double
648
+ selected exposure in milliseconds
649
+ '''
650
+ self._cam.exposure = value
651
+
652
+ self.refresh_exposure()
653
+
654
+ self.OME_tab.set_param_value(
655
+ MetaParams.EXPOSURE, float(self._cam.exposure_current)
656
+ )
657
+
658
+ def refresh_exposure(self):
659
+ self.camera_options.set_param_value(
660
+ CamParams.EXPOSURE, self._cam.exposure_current, self.exposure_spin_changed
661
+ )
662
+
663
+ def cam_capture(self, *args, **kwargs):
664
+ '''Capture function executed by the capture worker.
665
+
666
+ Sends software trigger signals and transfers the
667
+ acquired frame to the display processing stack.
668
+
669
+ Parameters
670
+ ----------
671
+ cam : miDummy
672
+ the miDummy used to acquire frames.
673
+ '''
674
+ try:
675
+ # Continuous image capture
676
+ while self.acq_job.frames_captured < self.acq_job.frames or self.mini:
677
+ cycle_time = time.perf_counter_ns()
678
+
679
+ self._buffer.put(
680
+ self._cam.get_dummy_image_from_pattern(
681
+ self.acq_job.frames_captured / 100
682
+ ).tobytes()
683
+ )
684
+ # add sensor temperature to the stack
685
+ self._temps.put(self.cam.get_temperature())
686
+ self.acq_job.frames_captured += 1
687
+
688
+ diff = (
689
+ int(self._cam.exposure * 1000)
690
+ - (time.perf_counter_ns() - cycle_time) // 1000
691
+ )
692
+ if diff > 0:
693
+ QtCore.QThread.usleep(diff)
694
+ else:
695
+ QtCore.QThread.usleep(100) # sleep 100us
696
+
697
+ if self.acq_job.stop_threads:
698
+ break # in case stop threads is initiated
699
+
700
+ self.acq_job.stop_threads = True
701
+ logging.debug('Stop')
702
+ except Exception:
703
+ traceback.print_exc()
704
+ finally:
705
+ # reset flags and release resources
706
+ self._cam.acquisition = False
707
+ QtCore.QThreadPool.globalInstance().releaseThread()
708
+ return QDateTime.currentDateTime()
709
+
710
+ def getCaptureArgs(self) -> list:
711
+ '''User specific arguments to be passed to the parallelized
712
+ Camera_Panel.cam_capture function.
713
+
714
+ Returns
715
+ -------
716
+ list
717
+ list of args to be passed in order to
718
+ Camera_Panel.cam_capture function.
719
+
720
+ Raises
721
+ ------
722
+ NotImplementedError
723
+ Has to be implemented by the use in child class.
724
+ '''
725
+ args = []
726
+ return args
727
+
728
+ def save_config(self):
729
+ filename, _ = getSaveFileName(self, 'Save config', filter='XML Files (*.xml);;')
730
+
731
+ if len(filename) > 0:
732
+ with self.cam.cam:
733
+ self.cam.cam.save_settings(filename, vb.PersistType.All)
734
+
735
+ QtWidgets.QMessageBox.information(self, 'Info', 'Config saved.')
736
+ else:
737
+ QtWidgets.QMessageBox.warning(self, 'Warning', 'Config not saved.')
738
+
739
+ def load_config(self):
740
+ filename, _ = getOpenFileName(self, 'Load config', filter='XML Files (*.xml);;')
741
+
742
+ if len(filename) > 0:
743
+ with self.cam.cam:
744
+ self.cam.default()
745
+
746
+ # Load camera settings from file.
747
+ self.cam.cam.load_settings(filename, vb.PersistType.All)
748
+
749
+ w, h, x, y = self.cam.get_roi()
750
+
751
+ self.camera_options.set_roi_info(int(x), int(y), int(w), int(h))
752
+
753
+ self.cam_trigger_mode_cbox.setCurrentText(self.cam.get_trigger_mode())
754
+
755
+ self.camera_options.set_param_value(
756
+ CamParams.EXPOSURE, self.cam.get_exposure()
757
+ )
758
+ else:
759
+ QtWidgets.QMessageBox.warning(self, 'Warning', 'No file selected.')