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,338 @@
1
+ import math
2
+ from enum import Enum
3
+
4
+ import cv2
5
+ import numpy as np
6
+ from scipy import signal
7
+ from scipy.fftpack import fft2, fftshift, ifft2, ifftshift
8
+
9
+ from microEye.analysis.filters.base import AbstractFilter
10
+
11
+
12
+ class PassFilter(AbstractFilter):
13
+ def run(self, image: np.ndarray) -> np.ndarray:
14
+ return image
15
+
16
+ def get_metadata(self):
17
+ '''Return metadata about the Pass filter.'''
18
+ return {
19
+ 'name': 'Pass Filter'
20
+ }
21
+
22
+ class DoG_Filter(AbstractFilter):
23
+ def __init__(self, sigma: float = 1, factor: float = 2.5) -> None:
24
+ '''Difference of Gauss init
25
+
26
+ Parameters
27
+ ----------
28
+ sigma : float, optional
29
+ sigma_min, by default 1
30
+ factor : float, optional
31
+ factor = sigma_max/sigma_min, by default 2.5
32
+ '''
33
+ self.set_params(sigma, factor)
34
+
35
+ def set_params(self, sigma: float, factor: float):
36
+ '''Set filter parameters.
37
+
38
+ Parameters
39
+ ----------
40
+ sigma : float
41
+ sigma_min
42
+ factor : float
43
+ factor = sigma_max/sigma_min
44
+ '''
45
+ self._show_filter = False
46
+ self.sigma = sigma
47
+ self.factor = factor
48
+ self.rsize = max(math.ceil(6 * self.sigma + 1), 3)
49
+ self.dog = DoG_Filter.gaussian_kernel(
50
+ self.rsize, self.sigma
51
+ ) - DoG_Filter.gaussian_kernel(self.rsize, max(1, self.factor * self.sigma))
52
+
53
+ def gaussian_kernel(dim, sigma):
54
+ x = cv2.getGaussianKernel(dim, sigma)
55
+ kernel = x.dot(x.T)
56
+ return kernel
57
+
58
+ def run(self, image: np.ndarray) -> np.ndarray:
59
+ rows, cols = image.shape
60
+ nrows = cv2.getOptimalDFTSize(rows)
61
+ ncols = cv2.getOptimalDFTSize(cols)
62
+ pad_rows = nrows - rows
63
+ pad_cols = ncols - cols
64
+
65
+ # Ensure that pad_cols[1] and pad_rows[1] are at least 1
66
+ pad_rows = (pad_rows // 2, max(1, pad_rows - pad_rows // 2))
67
+ pad_cols = (pad_cols // 2, max(1, pad_cols - pad_cols // 2))
68
+
69
+ nimg = np.pad(image, (pad_rows, pad_cols), mode='reflect')
70
+
71
+ res = cv2.normalize(
72
+ signal.convolve2d(nimg, np.rot90(self.dog), mode='same')[
73
+ pad_rows[0] : -pad_rows[1], pad_cols[0] : -pad_cols[1]
74
+ ],
75
+ None,
76
+ 0,
77
+ 255,
78
+ cv2.NORM_MINMAX,
79
+ cv2.CV_8U,
80
+ )
81
+ return res
82
+
83
+ def get_metadata(self):
84
+ '''Return metadata about the Difference of Gaussians filter.'''
85
+ return {
86
+ 'name': 'Difference of Gaussains Filter',
87
+ 'sigma': self.sigma,
88
+ 'factor': self.factor,
89
+ }
90
+
91
+
92
+ class GaussFilter(AbstractFilter):
93
+ def __init__(self, sigma=1) -> None:
94
+ '''Gaussian filter initialization.'''
95
+ self.set_sigma(sigma)
96
+
97
+ def set_sigma(self, sigma):
98
+ '''Set the sigma parameter for the Gaussian filter.'''
99
+ self.sigma = 1
100
+ self.gauss = GaussFilter.gaussian_kernel(
101
+ max(3, math.ceil(3 * sigma + 1)), sigma
102
+ )
103
+
104
+ def gaussian_kernel(dim, sigma):
105
+ x = cv2.getGaussianKernel(dim, sigma)
106
+ kernel = x.dot(x.T)
107
+ return kernel
108
+
109
+ def run(self, image: np.ndarray) -> np.ndarray:
110
+ return signal.convolve2d(image, np.rot90(self.gauss), mode='same')
111
+
112
+
113
+ class BANDPASS_TYPES(Enum):
114
+ Gaussian = 1
115
+ Butterworth = 2
116
+ Ideal = 3
117
+
118
+ @classmethod
119
+ def from_string(cls, s: str):
120
+ for column in cls:
121
+ if column.name.lower() == s.lower() or s.lower() in column.name.lower():
122
+ return column
123
+ raise ValueError(f'{cls.__name__} has no value matching "{s}"')
124
+
125
+ @classmethod
126
+ def values(cls):
127
+ return [column.name for column in cls]
128
+
129
+
130
+ class BandpassFilter(AbstractFilter):
131
+ def __init__(
132
+ self, center=40.0, width=90.0, filter_type=BANDPASS_TYPES.Gaussian, show=False
133
+ ) -> None:
134
+ '''Bandpass filter initialization.'''
135
+ self._radial_coordinates = None
136
+ self._filter = None
137
+ self._center = center
138
+ self._width = width
139
+ self._type = filter_type
140
+ self._show_filter = show
141
+ self._refresh = True
142
+
143
+ def radial_coordinates(self, shape):
144
+ '''Generates a 2D array with radial cordinates
145
+ with according to the first two axis of the
146
+ supplied shape tuple
147
+
148
+ Returns
149
+ -------
150
+ R, Rsq
151
+ Radius 2d matrix (R) and radius squared matrix (Rsq)
152
+ '''
153
+ y_len = np.arange(-shape[0] // 2, shape[0] // 2)
154
+ x_len = np.arange(-shape[1] // 2, shape[1] // 2)
155
+
156
+ X, Y = np.meshgrid(x_len, y_len)
157
+
158
+ Rsq = X**2 + Y**2
159
+
160
+ self._radial_coordinates = (np.sqrt(Rsq), Rsq)
161
+
162
+ return self._radial_coordinates
163
+
164
+ def ideal_bandpass_filter(self, shape, cutoff, cuton):
165
+ '''Generates an ideal bandpass filter of shape
166
+
167
+ Params
168
+ -------
169
+ shape
170
+ the shape of filter matrix
171
+ cutoff
172
+ the cutoff frequency (low)
173
+ cuton
174
+ the cuton frequency (high)
175
+
176
+ Returns
177
+ -------
178
+ filter (np.ndarray)
179
+ the filter in fourier space
180
+ '''
181
+
182
+ cir_filter = np.zeros((shape[0], shape[1]), dtype=np.float32)
183
+ cir_center = (shape[1] // 2, shape[0] // 2)
184
+ cir_filter = cv2.circle(cir_filter, cir_center, cuton, 1, -1)
185
+ cir_filter = cv2.circle(cir_filter, cir_center, cutoff, 0, -1)
186
+ return cir_filter
187
+
188
+ def gauss_bandpass_filter(self, shape, center, width):
189
+ '''Generates a Gaussian bandpass filter of shape
190
+
191
+ Params
192
+ -------
193
+ shape
194
+ the shape of filter matrix
195
+ center
196
+ the center frequency
197
+ width
198
+ the filter bandwidth
199
+
200
+ Returns
201
+ -------
202
+ filter (np.ndarray)
203
+ the filter in fourier space
204
+ '''
205
+ if self._radial_coordinates is None:
206
+ R, Rsq = self.radial_coordinates(shape)
207
+ elif self._radial_coordinates[0].shape != shape[:2]:
208
+ R, Rsq = self.radial_coordinates(shape)
209
+ else:
210
+ R, Rsq = self._radial_coordinates
211
+
212
+ with np.errstate(divide='ignore', invalid='ignore'):
213
+ filter = np.exp(-(((Rsq - center**2) / (R * width)) ** 2))
214
+ filter[filter == np.inf] = 0
215
+
216
+ a, b = np.unravel_index(R.argmin(), R.shape)
217
+
218
+ filter[a, b] = 1
219
+
220
+ return filter
221
+
222
+ def butterworth_bandpass_filter(self, shape, center, width):
223
+ '''Generates a Gaussian bandpass filter of shape
224
+
225
+ Params
226
+ -------
227
+ shape
228
+ the shape of filter matrix
229
+ center
230
+ the center frequency
231
+ width
232
+ the filter bandwidth
233
+
234
+ Returns
235
+ -------
236
+ filter (np.ndarray)
237
+ the filter in fourier space
238
+ '''
239
+ if self._radial_coordinates is None:
240
+ R, Rsq = self.radial_coordinates(shape)
241
+ elif self._radial_coordinates[0].shape != shape[:2]:
242
+ R, Rsq = self.radial_coordinates(shape)
243
+ else:
244
+ R, Rsq = self._radial_coordinates
245
+
246
+ with np.errstate(divide='ignore', invalid='ignore'):
247
+ filter = 1 - (1 / (1 + ((R * width) / (Rsq - center**2)) ** 10))
248
+ filter[filter == np.inf] = 0
249
+
250
+ a, b = np.unravel_index(R.argmin(), R.shape)
251
+
252
+ filter[a, b] = 1
253
+
254
+ return filter
255
+
256
+ def run(self, image: np.ndarray):
257
+ '''Applies an FFT bandpass filter to the 2D image.
258
+
259
+ Params
260
+ -------
261
+ image (np.ndarray)
262
+ the image to be filtered.
263
+ '''
264
+
265
+ # time = QDateTime.currentDateTime()
266
+
267
+ rows, cols = image.shape
268
+ nrows = cv2.getOptimalDFTSize(rows)
269
+ ncols = cv2.getOptimalDFTSize(cols)
270
+ pad_rows = nrows - rows
271
+ pad_cols = ncols - cols
272
+
273
+ # Ensure that pad_cols[1] and pad_rows[1] are at least 1
274
+ pad_rows = (pad_rows // 2, max(1, pad_rows - pad_rows // 2))
275
+ pad_cols = (pad_cols // 2, max(1, pad_cols - pad_cols // 2))
276
+
277
+ nimg = np.pad(image, (pad_rows, pad_cols), mode='reflect')
278
+ # nimg = np.zeros((nrows, ncols))
279
+ # nimg[:rows, :cols] = image
280
+
281
+ ft = fftshift(cv2.dft(np.float64(nimg), flags=cv2.DFT_COMPLEX_OUTPUT))
282
+
283
+ filter = np.ones(ft.shape[:2])
284
+
285
+ refresh = self._refresh
286
+
287
+ if self._filter is None:
288
+ refresh = True
289
+ elif self._filter.shape != ft.shape[:2]:
290
+ refresh = True
291
+
292
+ if refresh:
293
+ if self._type == BANDPASS_TYPES.Gaussian.name:
294
+ filter = self.gauss_bandpass_filter(ft.shape, self._center, self._width)
295
+ elif self._type == BANDPASS_TYPES.Butterworth.name:
296
+ filter = self.butterworth_bandpass_filter(
297
+ ft.shape, self._center, self._width
298
+ )
299
+ else:
300
+ cutoff = int(max(0, self._center - self._width // 2))
301
+ cuton = int(self._center + self._width // 2)
302
+ filter = self.ideal_bandpass_filter(ft.shape, cutoff, cuton)
303
+
304
+ self._filter = filter
305
+ else:
306
+ filter = self._filter
307
+
308
+ if self._show_filter:
309
+ cv2.namedWindow('BandpassFilter', cv2.WINDOW_NORMAL)
310
+ cv2.imshow('BandpassFilter', (filter * 255).astype(np.uint8))
311
+
312
+ img = np.zeros(nimg.shape, dtype=np.uint8)
313
+ ft[:, :, 0] *= filter
314
+ ft[:, :, 1] *= filter
315
+ idft = cv2.idft(ifftshift(ft))
316
+ idft = cv2.magnitude(idft[:, :, 0], idft[:, :, 1])
317
+ cv2.normalize(idft, img, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
318
+
319
+ # exex = time.msecsTo(QDateTime.currentDateTime())
320
+ return img[pad_rows[0] : -pad_rows[1], pad_cols[0] : -pad_cols[1]]
321
+
322
+ def set_params(
323
+ self, center: float, width: float, filter_type: BANDPASS_TYPES, show: bool
324
+ ):
325
+ self._center = center
326
+ self._width = width
327
+ self._type = filter_type
328
+ self._show_filter = show
329
+
330
+ def get_metadata(self):
331
+ '''Return metadata about the Bandpass Fourier Filter.'''
332
+ return {
333
+ 'name': 'Fourier Bandpass Filter',
334
+ 'type': self._type,
335
+ 'band center': self._center,
336
+ 'band width': self._width,
337
+ 'show filter': self._show_filter,
338
+ }
@@ -0,0 +1,76 @@
1
+ import dask.array
2
+ import numpy as np
3
+
4
+ from microEye.analysis.filters.base import AbstractFilter
5
+ from microEye.utils.uImage import ZarrImageSequence
6
+
7
+
8
+ class TemporalMedianFilter(AbstractFilter):
9
+
10
+ def __init__(self, window=3) -> None:
11
+ super().__init__()
12
+
13
+ self._temporal_window = window
14
+ self._frames = None
15
+ self._median = None
16
+
17
+ def getFrames(
18
+ self, index,
19
+ dataHandler: ZarrImageSequence, c_slice=0, z_slice=0):
20
+ if self._temporal_window < 2:
21
+ self._frames = None
22
+ self._median = None
23
+ self._start = None
24
+ return
25
+
26
+ maximum = dataHandler.shapeTCZYX()[0]
27
+ step = 0
28
+ if self._temporal_window % 2:
29
+ step = self._temporal_window // 2
30
+ else:
31
+ step = (self._temporal_window // 2) - 1
32
+
33
+ self._start = max(
34
+ 0,
35
+ min(
36
+ index - step,
37
+ maximum - self._temporal_window))
38
+
39
+
40
+ data_slice = slice(
41
+ max(self._start, 0),
42
+ min(self._start + self._temporal_window, maximum),
43
+ 1
44
+ )
45
+ return dask.array.from_array(
46
+ dataHandler.getSlice(data_slice, c_slice, z_slice))
47
+
48
+ def run(self, image: np.ndarray, frames: np.ndarray, roiInfo=None):
49
+ if frames is not None:
50
+ if roiInfo is None:
51
+ median = np.array(
52
+ dask.array.median(frames, axis=0))
53
+
54
+ img = image - median
55
+ else:
56
+ origin = roiInfo[0] # ROI (x,y)
57
+ dim = roiInfo[1] # ROI (w,h)
58
+ median = np.array(
59
+ dask.array.median(frames[
60
+ :,
61
+ int(origin[1]):int(origin[1] + dim[1]),
62
+ int(origin[0]):int(origin[0] + dim[0])
63
+ ], axis=0))
64
+
65
+ img = image.astype(np.float64)
66
+ img[
67
+ int(origin[1]):int(origin[1] + dim[1]),
68
+ int(origin[0]):int(origin[0] + dim[0])] -= median
69
+
70
+ img[img < 0] = 0
71
+ # max_val = np.iinfo(image.dtype).max
72
+ # img *= 10 # 0.9 * max_val / img.max()
73
+ return img.astype(image.dtype)
74
+ else:
75
+ return image
76
+
File without changes