microeye 2.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- microEye/__init__.py +47 -0
- microEye/_version.py +2 -0
- microEye/analysis/__init__.py +1 -0
- microEye/analysis/checklist_dialog.py +143 -0
- microEye/analysis/cmosMaps.py +228 -0
- microEye/analysis/filters/__init__.py +9 -0
- microEye/analysis/filters/base.py +21 -0
- microEye/analysis/filters/spatial.py +338 -0
- microEye/analysis/filters/temporal.py +76 -0
- microEye/analysis/fitting/__init__.py +0 -0
- microEye/analysis/fitting/fit.py +680 -0
- microEye/analysis/fitting/nena.py +375 -0
- microEye/analysis/fitting/phasor_fit.py +90 -0
- microEye/analysis/fitting/processing.py +317 -0
- microEye/analysis/fitting/psf/__init__.py +6 -0
- microEye/analysis/fitting/psf/extract.py +1129 -0
- microEye/analysis/fitting/psf/rubost_mean.py +150 -0
- microEye/analysis/fitting/psf/spline.py +167 -0
- microEye/analysis/fitting/psf/stats/__init__.py +12 -0
- microEye/analysis/fitting/psf/stats/core.py +295 -0
- microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
- microEye/analysis/fitting/psf/stats/io.py +104 -0
- microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
- microEye/analysis/fitting/psf/temp.py +147 -0
- microEye/analysis/fitting/psf/test.py +47 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
- microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
- microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
- microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
- microEye/analysis/fitting/results.py +917 -0
- microEye/analysis/fitting/results_stats.py +251 -0
- microEye/analysis/fitting/tardis.py +209 -0
- microEye/analysis/multi_viewer.py +568 -0
- microEye/analysis/processing/__init__.py +1 -0
- microEye/analysis/processing/frc.py +120 -0
- microEye/analysis/rendering/__init__.py +3 -0
- microEye/analysis/rendering/base.py +452 -0
- microEye/analysis/rendering/cloud.py +215 -0
- microEye/analysis/rendering/core.py +47 -0
- microEye/analysis/rendering/volumetric.py +198 -0
- microEye/analysis/tools/__init__.py +0 -0
- microEye/analysis/tools/kymograms.py +1079 -0
- microEye/analysis/tools/roi_selectors.py +556 -0
- microEye/analysis/utils/__init__.py +3 -0
- microEye/analysis/utils/coordinates.py +18 -0
- microEye/analysis/utils/images.py +68 -0
- microEye/analysis/utils/windows.py +19 -0
- microEye/analysis/viewer/__init__.py +3 -0
- microEye/analysis/viewer/image_options_widget.py +615 -0
- microEye/analysis/viewer/images.py +1225 -0
- microEye/analysis/viewer/layers_widget.py +415 -0
- microEye/analysis/viewer/localizations.py +1304 -0
- microEye/analysis/viewer/psf.py +1003 -0
- microEye/analysis/viewer/volume.py +456 -0
- microEye/hardware/__init__.py +3 -0
- microEye/hardware/cams/__init__.py +29 -0
- microEye/hardware/cams/camera_calibration.py +99 -0
- microEye/hardware/cams/camera_list.py +528 -0
- microEye/hardware/cams/camera_options.py +694 -0
- microEye/hardware/cams/camera_panel.py +941 -0
- microEye/hardware/cams/dummy/__init__.py +1 -0
- microEye/hardware/cams/dummy/dummy_panel.py +759 -0
- microEye/hardware/cams/jobs.py +497 -0
- microEye/hardware/cams/line_profiler.py +99 -0
- microEye/hardware/cams/linescan/IR_Cam.py +474 -0
- microEye/hardware/cams/linescan/__init__.py +1 -0
- microEye/hardware/cams/micam.py +524 -0
- microEye/hardware/cams/pco/__init__.py +58 -0
- microEye/hardware/cams/pco/enums.py +382 -0
- microEye/hardware/cams/pco/pco_cam.py +761 -0
- microEye/hardware/cams/pco/pco_panel.py +477 -0
- microEye/hardware/cams/shortcuts.py +312 -0
- microEye/hardware/cams/thorlabs/__init__.py +1 -0
- microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
- microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
- microEye/hardware/cams/ueye/__init__.py +1 -0
- microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
- microEye/hardware/cams/ueye/ueye_panel.py +861 -0
- microEye/hardware/cams/vimba/__init__.py +1 -0
- microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
- microEye/hardware/cams/vimba/vimba_panel.py +813 -0
- microEye/hardware/device.py +60 -0
- microEye/hardware/lasers/__init__.py +13 -0
- microEye/hardware/lasers/io_matchbox.py +791 -0
- microEye/hardware/lasers/io_params.py +85 -0
- microEye/hardware/lasers/io_single_laser.py +742 -0
- microEye/hardware/lasers/laser_relay.py +594 -0
- microEye/hardware/mieye/__init__.py +1 -0
- microEye/hardware/mieye/acquisition_manager.py +467 -0
- microEye/hardware/mieye/devices_manager.py +533 -0
- microEye/hardware/mieye/miEye.py +659 -0
- microEye/hardware/misc/__init__.py +0 -0
- microEye/hardware/misc/acquisition_view.py +71 -0
- microEye/hardware/misc/reglo.py +761 -0
- microEye/hardware/misc/temp.py +188 -0
- microEye/hardware/port_config.py +59 -0
- microEye/hardware/protocols/__init__.py +2 -0
- microEye/hardware/protocols/actions.py +402 -0
- microEye/hardware/protocols/actions_items.py +703 -0
- microEye/hardware/protocols/designer.py +244 -0
- microEye/hardware/protocols/scene_manager.py +191 -0
- microEye/hardware/protocols/serialization.py +97 -0
- microEye/hardware/pycromanager/__init__.py +16 -0
- microEye/hardware/pycromanager/core.py +1433 -0
- microEye/hardware/pycromanager/devices.py +461 -0
- microEye/hardware/pycromanager/enums.py +107 -0
- microEye/hardware/pycromanager/headless.py +153 -0
- microEye/hardware/pycromanager/utils.py +34 -0
- microEye/hardware/pycromanager/widgets/__init__.py +5 -0
- microEye/hardware/pycromanager/widgets/bridges.py +407 -0
- microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
- microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
- microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
- microEye/hardware/stages/__init__.py +18 -0
- microEye/hardware/stages/elliptec/__init__.py +5 -0
- microEye/hardware/stages/elliptec/baseDevice.py +314 -0
- microEye/hardware/stages/elliptec/device.py +384 -0
- microEye/hardware/stages/elliptec/deviceID.py +212 -0
- microEye/hardware/stages/elliptec/devicePort.py +379 -0
- microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
- microEye/hardware/stages/elliptec/devicesView.py +706 -0
- microEye/hardware/stages/elliptec/ellDevices.py +134 -0
- microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
- microEye/hardware/stages/elliptec/motorInfo.py +153 -0
- microEye/hardware/stages/elliptec/stage.py +62 -0
- microEye/hardware/stages/elliptec/test.py +139 -0
- microEye/hardware/stages/kinesis/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
- microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
- microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
- microEye/hardware/stages/kinesis/kinesis.py +776 -0
- microEye/hardware/stages/piezo_concept.py +607 -0
- microEye/hardware/stages/stabilizer.py +785 -0
- microEye/hardware/stages/stage.py +89 -0
- microEye/hardware/widgets/__init__.py +10 -0
- microEye/hardware/widgets/controller.py +246 -0
- microEye/hardware/widgets/devices.py +133 -0
- microEye/hardware/widgets/focusWidget.py +264 -0
- microEye/hardware/widgets/qlist_slider.py +113 -0
- microEye/hardware/widgets/scan_acquisition.py +424 -0
- microEye/icons/1024.png +0 -0
- microEye/icons/128.png +0 -0
- microEye/icons/16.png +0 -0
- microEye/icons/24.png +0 -0
- microEye/icons/256.png +0 -0
- microEye/icons/32.png +0 -0
- microEye/icons/48.png +0 -0
- microEye/icons/512.png +0 -0
- microEye/icons/64.png +0 -0
- microEye/icons/__init__.py +0 -0
- microEye/icons/close.svg +88 -0
- microEye/icons/mieye.png +0 -0
- microEye/icons/min.svg +83 -0
- microEye/icons/viewer.png +0 -0
- microEye/launcher.py +42 -0
- microEye/qt.py +181 -0
- microEye/utils/__init__.py +2 -0
- microEye/utils/enum_encoder.py +10 -0
- microEye/utils/expandable_groupbox.py +93 -0
- microEye/utils/gui_helper.py +457 -0
- microEye/utils/hid/__init__.py +8 -0
- microEye/utils/hid/controller.py +153 -0
- microEye/utils/hid/device.py +63 -0
- microEye/utils/hid/enums.py +140 -0
- microEye/utils/hid/utils.py +58 -0
- microEye/utils/labelled_slider.py +134 -0
- microEye/utils/metadata.py +599 -0
- microEye/utils/metadata_tree.py +718 -0
- microEye/utils/micro_launcher.py +245 -0
- microEye/utils/parameter_tree.py +325 -0
- microEye/utils/pyscripting.py +444 -0
- microEye/utils/retry_exec.py +35 -0
- microEye/utils/start_gui.py +112 -0
- microEye/utils/thread_worker.py +115 -0
- microEye/utils/uImage.py +1512 -0
- microeye-2.3.2.dist-info/METADATA +401 -0
- microeye-2.3.2.dist-info/RECORD +190 -0
- microeye-2.3.2.dist-info/WHEEL +5 -0
- microeye-2.3.2.dist-info/entry_points.txt +2 -0
- microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
- microeye-2.3.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import numba as nb
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numba import cuda
|
|
7
|
+
from scipy import ndimage
|
|
8
|
+
|
|
9
|
+
from microEye.analysis.fitting.pyfit3Dcspline import CPU
|
|
10
|
+
from microEye.analysis.fitting.pyfit3Dcspline.constants import *
|
|
11
|
+
|
|
12
|
+
if cuda.is_available():
|
|
13
|
+
from microEye.analysis.fitting.pyfit3Dcspline import GPU
|
|
14
|
+
|
|
15
|
+
def GPUmleFit_LM(
|
|
16
|
+
data: np.ndarray,
|
|
17
|
+
fittype: int,
|
|
18
|
+
PSFparam: np.ndarray,
|
|
19
|
+
varim: np.ndarray,
|
|
20
|
+
initZ: float,
|
|
21
|
+
iterations: int = 30,
|
|
22
|
+
):
|
|
23
|
+
'''
|
|
24
|
+
GPU Fit
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
data : np.ndarray
|
|
29
|
+
image stack in shape (roi_index, roi_size)
|
|
30
|
+
fittype : int
|
|
31
|
+
fitting mode:
|
|
32
|
+
|
|
33
|
+
1. fix PSF.
|
|
34
|
+
2. free PSF.
|
|
35
|
+
3. Gauss fit z. (SMAP developers suppressed this)
|
|
36
|
+
4. fit PSFx, PSFy elliptical.
|
|
37
|
+
5. cspline.
|
|
38
|
+
|
|
39
|
+
PSFparam : np.ndarray
|
|
40
|
+
paramters for fitters:
|
|
41
|
+
|
|
42
|
+
1. fix PSF: PSFxy sigma.
|
|
43
|
+
2. free PSF: start PSFxy.
|
|
44
|
+
3. Gauss fit z parameters:
|
|
45
|
+
PSFx, Ax, Ay, Bx, By, gamma, d, PSFy.
|
|
46
|
+
|
|
47
|
+
4. fit PSFx, PSFy elliptical: start PSFx, PSFy.
|
|
48
|
+
5. cspline: cspline coefficients.
|
|
49
|
+
varim : np.ndarray
|
|
50
|
+
Variance map for CMOS, if None then EMCCD, default is None.
|
|
51
|
+
initZ : float
|
|
52
|
+
z start parameter.
|
|
53
|
+
unit: distance of stack calibration, center-based.
|
|
54
|
+
iterations : int
|
|
55
|
+
number of fit iterations (if None default=30)
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
Parameters : np.ndarray
|
|
60
|
+
fitting results in shape (roi_index, column) for each fit mode:
|
|
61
|
+
|
|
62
|
+
1. x, y, I, bg, iteration.
|
|
63
|
+
2. x, y, I, bg, sigma, iteration.
|
|
64
|
+
3. ???
|
|
65
|
+
4. x, y, I, bg, sigmax, sigmay, iteration.
|
|
66
|
+
5. x, y, I, bg, z, iteration.
|
|
67
|
+
CRLBs : np.ndarray
|
|
68
|
+
Cramer-Rao Lower Bounds for fitting results
|
|
69
|
+
in shape (roi_index, column).
|
|
70
|
+
LogLikelihood : np.ndarray
|
|
71
|
+
Log Likelihood in shape (roi_index).
|
|
72
|
+
'''
|
|
73
|
+
blockx = 0
|
|
74
|
+
threadx = 0
|
|
75
|
+
PSFSigma = 1
|
|
76
|
+
startParameters = 0
|
|
77
|
+
d_data = None
|
|
78
|
+
Ndim = Nfitraw = sz = cameratype = 0 # default cameratype 0 EMCCD
|
|
79
|
+
noParameters = 0
|
|
80
|
+
|
|
81
|
+
# CMOS
|
|
82
|
+
d_varim = None
|
|
83
|
+
|
|
84
|
+
# Spline
|
|
85
|
+
spline_xsize = spline_ysize = spline_zsize = 0
|
|
86
|
+
coeff = d_coeff = 0
|
|
87
|
+
# d_Parameters = d_CRLBs = d_LogLikelihood = 0
|
|
88
|
+
BlockSize = BSZ # for no shared scenario, we don't care!
|
|
89
|
+
|
|
90
|
+
# fun with timing
|
|
91
|
+
freq = 0
|
|
92
|
+
togpu = 0
|
|
93
|
+
fit = 0
|
|
94
|
+
fromgpu = 0
|
|
95
|
+
cleanup = 0
|
|
96
|
+
start = stop = 0
|
|
97
|
+
start = time.perf_counter_ns()
|
|
98
|
+
# QueryPerformanceFrequency(&freq)
|
|
99
|
+
# QueryPerformanceCounter(&start)
|
|
100
|
+
|
|
101
|
+
# input checks
|
|
102
|
+
sz = math.sqrt(data.shape[1])
|
|
103
|
+
Nfitraw = data.shape[0]
|
|
104
|
+
|
|
105
|
+
# if fittype == 1: # fixed sigma
|
|
106
|
+
# pass
|
|
107
|
+
# elif fittype == 2: # free sigma
|
|
108
|
+
# pass
|
|
109
|
+
if fittype == 4: # fixed sigmax and sigmay
|
|
110
|
+
PSFSigma = float(PSFparam[0])
|
|
111
|
+
elif fittype == 5: # spline fit
|
|
112
|
+
coeff = PSFparam.flatten()
|
|
113
|
+
spline_xsize = PSFparam.shape[1]
|
|
114
|
+
spline_ysize = PSFparam.shape[2]
|
|
115
|
+
spline_zsize = PSFparam.shape[3]
|
|
116
|
+
|
|
117
|
+
# EMCCD = 0, sCMOS = 1
|
|
118
|
+
cameratype = 0 if varim is None else 1
|
|
119
|
+
|
|
120
|
+
# query GPUs
|
|
121
|
+
assert cuda.is_available(), 'No GPU is available.'
|
|
122
|
+
deviceCount = len(cuda.gpus)
|
|
123
|
+
|
|
124
|
+
# check if we are allocating more memory than the card has
|
|
125
|
+
availableMemory = cuda.current_context().get_memory_info()[0]
|
|
126
|
+
requiredMemory = 0
|
|
127
|
+
float_size = 4 # in bytes
|
|
128
|
+
|
|
129
|
+
if fittype == 1: # fixed sigma
|
|
130
|
+
requiredMemory += (2 * NV_P + 2) * Nfitraw * float_size
|
|
131
|
+
elif fittype == 2: # free sigma
|
|
132
|
+
requiredMemory += (2 * NV_PS + 2) * Nfitraw * float_size
|
|
133
|
+
elif fittype == 4: # fixed sigmax and sigmay
|
|
134
|
+
requiredMemory += (2 * NV_PS2 + 2) * Nfitraw * float_size
|
|
135
|
+
elif fittype == 5: # spline fit
|
|
136
|
+
requiredMemory += (2 * NV_PS + 2) * Nfitraw * float_size
|
|
137
|
+
requiredMemory += (
|
|
138
|
+
spline_xsize * spline_ysize * spline_zsize * 64 * float_size
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if cameratype == 0: # EMCCD
|
|
142
|
+
requiredMemory += sz * sz * Nfitraw * float_size
|
|
143
|
+
elif cameratype == 1: # sCMOS
|
|
144
|
+
requiredMemory += 2 * sz * sz * Nfitraw * float_size
|
|
145
|
+
|
|
146
|
+
assert requiredMemory < 0.9 * availableMemory, (
|
|
147
|
+
f'Trying to allocation {requiredMemory / (1024 * 1024):.3f}MB.',
|
|
148
|
+
f'GPU only has {availableMemory / (1024 * 1024):.0f}MB.\n'
|
|
149
|
+
+ 'Please break your fitting into multiple smaller runs.\n',
|
|
150
|
+
)
|
|
151
|
+
print(
|
|
152
|
+
f'Allocating {100 * requiredMemory / availableMemory:.3e}% out of',
|
|
153
|
+
f'available GPU memory {availableMemory / (1024 * 1024):.0f}MB.',
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# copy data to device
|
|
157
|
+
d_data = cuda.to_device(data.flatten().astype(np.float32))
|
|
158
|
+
|
|
159
|
+
# CMOS
|
|
160
|
+
if cameratype == 1:
|
|
161
|
+
d_varim = cuda.to_device(varim.flatten().astype(np.float32))
|
|
162
|
+
|
|
163
|
+
if fittype == 5:
|
|
164
|
+
d_coeff = cuda.to_device(coeff.flatten().astype(np.float32))
|
|
165
|
+
|
|
166
|
+
# create output for parameters and CRLBs
|
|
167
|
+
if fittype == 1: # (x,y,bg,I)
|
|
168
|
+
d_Parameters = cuda.to_device(np.zeros((NV_P + 1) * Nfitraw, np.float32))
|
|
169
|
+
d_CRLBs = cuda.to_device(np.zeros(NV_P * Nfitraw, np.float32))
|
|
170
|
+
elif fittype == 2: # (x,y,bg,I,Sigma)
|
|
171
|
+
d_Parameters = cuda.to_device(np.zeros((NV_PS + 1) * Nfitraw, np.float32))
|
|
172
|
+
d_CRLBs = cuda.to_device(np.zeros(NV_PS * Nfitraw, np.float32))
|
|
173
|
+
elif fittype == 4: # (x,y,bg,I,Sx,Sy)
|
|
174
|
+
d_Parameters = cuda.to_device(np.zeros((NV_PS2 + 1) * Nfitraw, np.float32))
|
|
175
|
+
d_CRLBs = cuda.to_device(np.zeros(NV_PS2 * Nfitraw, np.float32))
|
|
176
|
+
elif fittype == 5: # (x,y,bg,I,z)
|
|
177
|
+
d_Parameters = cuda.to_device(np.zeros((NV_PS + 1) * Nfitraw, np.float32))
|
|
178
|
+
d_CRLBs = cuda.to_device(np.zeros(NV_PS * Nfitraw, np.float32))
|
|
179
|
+
|
|
180
|
+
d_LogLikelihood = cuda.to_device(np.zeros(Nfitraw, np.float32))
|
|
181
|
+
|
|
182
|
+
# print(
|
|
183
|
+
# d_data.nbytes +
|
|
184
|
+
# (d_varim.nbytes if d_varim is not None else 0) +
|
|
185
|
+
# (d_coeff.nbytes if fittype == 5 else 0) +
|
|
186
|
+
# d_Parameters.nbytes +
|
|
187
|
+
# d_CRLBs.nbytes +
|
|
188
|
+
# d_LogLikelihood.nbytes,
|
|
189
|
+
# requiredMemory
|
|
190
|
+
# )
|
|
191
|
+
|
|
192
|
+
stop = time.perf_counter_ns()
|
|
193
|
+
togpu = stop - start
|
|
194
|
+
print(f'Data copied to GPU in {togpu/1e9:.6f}s.\n')
|
|
195
|
+
start = time.perf_counter_ns()
|
|
196
|
+
|
|
197
|
+
# setup kernel
|
|
198
|
+
blockx = math.ceil(Nfitraw / BlockSize)
|
|
199
|
+
threadx = BlockSize
|
|
200
|
+
|
|
201
|
+
if fittype == 1: # fit x,y,bg,I
|
|
202
|
+
if cameratype == 0:
|
|
203
|
+
GPU.kernel_MLEFit_LM_EMCCD[blockx, threadx](
|
|
204
|
+
d_data,
|
|
205
|
+
PSFSigma,
|
|
206
|
+
int(sz),
|
|
207
|
+
iterations,
|
|
208
|
+
d_Parameters,
|
|
209
|
+
d_CRLBs,
|
|
210
|
+
d_LogLikelihood,
|
|
211
|
+
Nfitraw,
|
|
212
|
+
)
|
|
213
|
+
elif cameratype == 1:
|
|
214
|
+
GPU.kernel_MLEFit_LM_sCMOS[blockx, threadx](
|
|
215
|
+
d_data,
|
|
216
|
+
PSFSigma,
|
|
217
|
+
int(sz),
|
|
218
|
+
iterations,
|
|
219
|
+
d_Parameters,
|
|
220
|
+
d_CRLBs,
|
|
221
|
+
d_LogLikelihood,
|
|
222
|
+
int(Nfitraw),
|
|
223
|
+
d_varim,
|
|
224
|
+
)
|
|
225
|
+
elif fittype == 2: # fit x,y,bg,I,sigma
|
|
226
|
+
if cameratype == 0:
|
|
227
|
+
GPU.kernel_MLEFit_LM_Sigma_EMCCD[blockx, threadx](
|
|
228
|
+
d_data,
|
|
229
|
+
PSFSigma,
|
|
230
|
+
int(sz),
|
|
231
|
+
iterations,
|
|
232
|
+
d_Parameters,
|
|
233
|
+
d_CRLBs,
|
|
234
|
+
d_LogLikelihood,
|
|
235
|
+
int(Nfitraw),
|
|
236
|
+
)
|
|
237
|
+
elif cameratype == 1:
|
|
238
|
+
GPU.kernel_MLEFit_LM_Sigma_sCMOS[blockx, threadx](
|
|
239
|
+
d_data,
|
|
240
|
+
PSFSigma,
|
|
241
|
+
int(sz),
|
|
242
|
+
iterations,
|
|
243
|
+
d_Parameters,
|
|
244
|
+
d_CRLBs,
|
|
245
|
+
d_LogLikelihood,
|
|
246
|
+
int(Nfitraw),
|
|
247
|
+
d_varim,
|
|
248
|
+
)
|
|
249
|
+
elif fittype == 4: # fit x,y,bg,I,sigmax,sigmay
|
|
250
|
+
if cameratype == 0:
|
|
251
|
+
GPU.kernel_MLEFit_LM_sigmaxy_EMCCD[blockx, threadx](
|
|
252
|
+
d_data,
|
|
253
|
+
PSFSigma,
|
|
254
|
+
int(sz),
|
|
255
|
+
iterations,
|
|
256
|
+
d_Parameters,
|
|
257
|
+
d_CRLBs,
|
|
258
|
+
d_LogLikelihood,
|
|
259
|
+
int(Nfitraw),
|
|
260
|
+
)
|
|
261
|
+
elif cameratype == 1:
|
|
262
|
+
GPU.kernel_MLEFit_LM_sigmaxy_sCMOS[blockx, threadx](
|
|
263
|
+
d_data,
|
|
264
|
+
PSFSigma,
|
|
265
|
+
int(sz),
|
|
266
|
+
iterations,
|
|
267
|
+
d_Parameters,
|
|
268
|
+
d_CRLBs,
|
|
269
|
+
d_LogLikelihood,
|
|
270
|
+
int(Nfitraw),
|
|
271
|
+
d_varim,
|
|
272
|
+
)
|
|
273
|
+
elif fittype == 5: # fit x,y,bg,I,z
|
|
274
|
+
if initZ < 0:
|
|
275
|
+
initZ = spline_zsize / 2.0
|
|
276
|
+
|
|
277
|
+
if cameratype == 0:
|
|
278
|
+
GPU.kernel_splineMLEFit_z_EMCCD[blockx, threadx](
|
|
279
|
+
d_data,
|
|
280
|
+
d_coeff,
|
|
281
|
+
spline_xsize,
|
|
282
|
+
spline_ysize,
|
|
283
|
+
spline_zsize,
|
|
284
|
+
int(sz),
|
|
285
|
+
iterations,
|
|
286
|
+
d_Parameters,
|
|
287
|
+
d_CRLBs,
|
|
288
|
+
d_LogLikelihood,
|
|
289
|
+
initZ,
|
|
290
|
+
int(Nfitraw),
|
|
291
|
+
)
|
|
292
|
+
elif cameratype == 1:
|
|
293
|
+
GPU.kernel_splineMLEFit_z_sCMOS[blockx, threadx](
|
|
294
|
+
d_data,
|
|
295
|
+
d_coeff,
|
|
296
|
+
spline_xsize,
|
|
297
|
+
spline_ysize,
|
|
298
|
+
spline_zsize,
|
|
299
|
+
int(sz),
|
|
300
|
+
iterations,
|
|
301
|
+
d_Parameters,
|
|
302
|
+
d_CRLBs,
|
|
303
|
+
d_LogLikelihood,
|
|
304
|
+
initZ,
|
|
305
|
+
int(Nfitraw),
|
|
306
|
+
d_varim,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
cuda.synchronize()
|
|
310
|
+
|
|
311
|
+
stop = time.perf_counter_ns()
|
|
312
|
+
fit = stop - start
|
|
313
|
+
print(f'Fitted {Nfitraw:d} localizations in {fit/1e9:6f}s.\n')
|
|
314
|
+
start = time.perf_counter_ns()
|
|
315
|
+
|
|
316
|
+
# copy to matlab output
|
|
317
|
+
if fittype == 1: # (x,y,bg,I)
|
|
318
|
+
Parameters = d_Parameters.copy_to_host()
|
|
319
|
+
CRLBs = d_CRLBs.copy_to_host()
|
|
320
|
+
elif fittype == 2: # (x,y,bg,I,Sigma)
|
|
321
|
+
Parameters = d_Parameters.copy_to_host()
|
|
322
|
+
CRLBs = d_CRLBs.copy_to_host()
|
|
323
|
+
elif fittype == 4: # (x,y,bg,I,Sx,Sy)
|
|
324
|
+
Parameters = d_Parameters.copy_to_host()
|
|
325
|
+
CRLBs = d_CRLBs.copy_to_host()
|
|
326
|
+
elif fittype == 5: # (x,y,bg,I,z)
|
|
327
|
+
Parameters = d_Parameters.copy_to_host()
|
|
328
|
+
CRLBs = d_CRLBs.copy_to_host()
|
|
329
|
+
|
|
330
|
+
LogLikelihood = d_LogLikelihood.copy_to_host()
|
|
331
|
+
|
|
332
|
+
stop = time.perf_counter_ns()
|
|
333
|
+
fromgpu = stop - start
|
|
334
|
+
print(f'Data copied to Host in {fromgpu/1e9:.6f}s.\n')
|
|
335
|
+
start = time.perf_counter_ns()
|
|
336
|
+
|
|
337
|
+
# cleanup
|
|
338
|
+
# cuda.current_context().reset()
|
|
339
|
+
|
|
340
|
+
# cuda.close()
|
|
341
|
+
|
|
342
|
+
stop = time.perf_counter_ns()
|
|
343
|
+
|
|
344
|
+
# reshape output for parameters and CRLBs
|
|
345
|
+
if fittype == 1: # (x,y,bg,I)
|
|
346
|
+
Parameters = Parameters.reshape((-1, (NV_P + 1)))
|
|
347
|
+
CRLBs = CRLBs.reshape((-1, NV_P))
|
|
348
|
+
elif fittype == 2: # (x,y,bg,I,Sigma)
|
|
349
|
+
Parameters = Parameters.reshape((-1, (NV_PS + 1)))
|
|
350
|
+
CRLBs = CRLBs.reshape((-1, NV_PS))
|
|
351
|
+
elif fittype == 4: # (x,y,bg,I,Sx,Sy)
|
|
352
|
+
Parameters = Parameters.reshape((-1, (NV_PS2 + 1)))
|
|
353
|
+
CRLBs = CRLBs.reshape((-1, NV_PS2))
|
|
354
|
+
elif fittype == 5: # (x,y,bg,I,z)
|
|
355
|
+
Parameters = Parameters.reshape((-1, (NV_PS + 1)))
|
|
356
|
+
CRLBs = CRLBs.reshape((-1, NV_PS))
|
|
357
|
+
|
|
358
|
+
return Parameters, CRLBs, LogLikelihood
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def CPUmleFit_LM(
|
|
362
|
+
data: np.ndarray,
|
|
363
|
+
fittype: int,
|
|
364
|
+
PSFparam: np.ndarray,
|
|
365
|
+
varim: np.ndarray,
|
|
366
|
+
initZ: float,
|
|
367
|
+
iterations: int = 60,
|
|
368
|
+
):
|
|
369
|
+
'''
|
|
370
|
+
CPU Fit
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
data : np.ndarray
|
|
375
|
+
image stack in shape (roi_index, roi_size)
|
|
376
|
+
fittype : int
|
|
377
|
+
fitting mode:
|
|
378
|
+
|
|
379
|
+
1. fix PSF.
|
|
380
|
+
2. free PSF.
|
|
381
|
+
3. Gauss fit z. (SMAP developers suppressed this)
|
|
382
|
+
4. fit PSFx, PSFy elliptical.
|
|
383
|
+
5. cspline.
|
|
384
|
+
|
|
385
|
+
PSFparam : np.ndarray
|
|
386
|
+
paramters for fitters:
|
|
387
|
+
|
|
388
|
+
1. fix PSF: PSFxy sigma.
|
|
389
|
+
2. free PSF: start PSFxy.
|
|
390
|
+
3. Gauss fit z: parameters: PSFx, Ax, Ay, Bx, By, gamma, d, PSFy.
|
|
391
|
+
4. fit PSFx, PSFy elliptical: start PSFx, PSFy.
|
|
392
|
+
5. cspline: cspline coefficients.
|
|
393
|
+
varim : np.ndarray
|
|
394
|
+
Variance map for CMOS, if None then EMCCD, default is None.
|
|
395
|
+
initZ : float
|
|
396
|
+
z start parameter. unit: distance of stack calibration, center based.
|
|
397
|
+
iterations : int
|
|
398
|
+
number of fit iterations (default=30)
|
|
399
|
+
|
|
400
|
+
Returns
|
|
401
|
+
-------
|
|
402
|
+
Parameters : np.ndarray
|
|
403
|
+
fitting results in shape (roi_index, column) for each fit mode:
|
|
404
|
+
|
|
405
|
+
1. x, y, I, bg, iteration.
|
|
406
|
+
2. x, y, I, bg, sigma, iteration.
|
|
407
|
+
3. ???
|
|
408
|
+
4. x, y, I, bg, sigmax, sigmay, iteration.
|
|
409
|
+
5. x, y, I, bg, z, iteration.
|
|
410
|
+
CRLBs : np.ndarray
|
|
411
|
+
Cramer-Rao Lower Bounds for fitting results
|
|
412
|
+
in shape (roi_index, column).
|
|
413
|
+
LogLikelihood : np.ndarray
|
|
414
|
+
Log Likelihood in shape (roi_index).
|
|
415
|
+
'''
|
|
416
|
+
PSFSigma = 1
|
|
417
|
+
cameratype = 0 # default cameratype 0 EMCCD
|
|
418
|
+
noParameters = 0
|
|
419
|
+
|
|
420
|
+
# Spline
|
|
421
|
+
spline_xsize = spline_ysize = spline_zsize = 0
|
|
422
|
+
coeff = 0
|
|
423
|
+
|
|
424
|
+
# fun with timing
|
|
425
|
+
freq = 0
|
|
426
|
+
togpu = 0
|
|
427
|
+
fit = 0
|
|
428
|
+
fromgpu = 0
|
|
429
|
+
cleanup = 0
|
|
430
|
+
start = stop = 0
|
|
431
|
+
start = time.perf_counter_ns()
|
|
432
|
+
# QueryPerformanceFrequency(&freq)
|
|
433
|
+
# QueryPerformanceCounter(&start)
|
|
434
|
+
|
|
435
|
+
# input checks
|
|
436
|
+
sz = math.sqrt(data.shape[1])
|
|
437
|
+
Nfitraw = data.shape[0]
|
|
438
|
+
|
|
439
|
+
if fittype == 1: # fixed sigma
|
|
440
|
+
PSFSigma = float(PSFparam[0])
|
|
441
|
+
elif fittype == 2: # free sigma
|
|
442
|
+
PSFSigma = float(PSFparam[0])
|
|
443
|
+
elif fittype == 4: # fixed sigmax and sigmay
|
|
444
|
+
PSFSigma = float(PSFparam[0])
|
|
445
|
+
elif fittype == 5: # spline fit
|
|
446
|
+
coeff = PSFparam.flatten()
|
|
447
|
+
spline_xsize = PSFparam.shape[1]
|
|
448
|
+
spline_ysize = PSFparam.shape[2]
|
|
449
|
+
spline_zsize = PSFparam.shape[3]
|
|
450
|
+
|
|
451
|
+
# EMCCD = 0, sCMOS = 1
|
|
452
|
+
cameratype = 0 if varim is None else 1
|
|
453
|
+
|
|
454
|
+
# create output for parameters and CRLBs
|
|
455
|
+
if fittype == 1: # (x,y,bg,I)
|
|
456
|
+
Parameters = np.zeros((Nfitraw, (NV_P + 1)), np.float32)
|
|
457
|
+
CRLBs = np.zeros((Nfitraw, NV_P), np.float32)
|
|
458
|
+
elif fittype == 2: # (x,y,bg,I,Sigma)
|
|
459
|
+
Parameters = np.zeros((Nfitraw, (NV_PS + 1)), np.float32)
|
|
460
|
+
CRLBs = np.zeros((Nfitraw, NV_PS), np.float32)
|
|
461
|
+
elif fittype == 4: # (x,y,bg,I,Sx,Sy)
|
|
462
|
+
Parameters = np.zeros((Nfitraw, (NV_PS2 + 1)), np.float32)
|
|
463
|
+
CRLBs = np.zeros((Nfitraw, NV_PS2), np.float32)
|
|
464
|
+
elif fittype == 5: # (x,y,bg,I,z)
|
|
465
|
+
Parameters = np.zeros((Nfitraw, (NV_PS + 1)), np.float32)
|
|
466
|
+
CRLBs = np.zeros((Nfitraw, NV_PS), np.float32)
|
|
467
|
+
|
|
468
|
+
LogLikelihood = np.zeros(Nfitraw, np.float32)
|
|
469
|
+
|
|
470
|
+
stop = time.perf_counter_ns()
|
|
471
|
+
togpu = stop - start
|
|
472
|
+
start = time.perf_counter_ns()
|
|
473
|
+
|
|
474
|
+
# if fittype == 1: # fit x,y,bg,I
|
|
475
|
+
# for ii in range(Nfitraw):
|
|
476
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = \
|
|
477
|
+
# CPU.kernel_MLEFit_LM(
|
|
478
|
+
# data[ii, :], PSFSigma, int(sz), iterations,
|
|
479
|
+
# varim if varim is None else varim[ii, :])
|
|
480
|
+
# elif fittype == 2: # fit x,y,bg,I,sigma
|
|
481
|
+
# for ii in range(Nfitraw):
|
|
482
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = \
|
|
483
|
+
# CPU.kernel_MLEFit_LM_Sigma(
|
|
484
|
+
# data[ii, :], PSFSigma, int(sz), iterations,
|
|
485
|
+
# varim if varim is None else varim[ii, :])
|
|
486
|
+
# elif fittype == 4: # fit x,y,bg,I,sigmax,sigmay
|
|
487
|
+
# for ii in range(Nfitraw):
|
|
488
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = \
|
|
489
|
+
# CPU.kernel_MLEFit_LM_sigmaxy(
|
|
490
|
+
# data[ii, :], PSFSigma, int(sz), iterations,
|
|
491
|
+
# varim if varim is None else varim[ii, :])
|
|
492
|
+
if fittype == 5: # fit x,y,bg,I,z
|
|
493
|
+
if initZ < 0:
|
|
494
|
+
initZ = spline_zsize / 2.0
|
|
495
|
+
|
|
496
|
+
CPU_parallel_fit_3D_scpline(
|
|
497
|
+
data,
|
|
498
|
+
varim,
|
|
499
|
+
coeff,
|
|
500
|
+
spline_xsize,
|
|
501
|
+
spline_ysize,
|
|
502
|
+
spline_zsize,
|
|
503
|
+
sz,
|
|
504
|
+
Nfitraw,
|
|
505
|
+
initZ,
|
|
506
|
+
iterations,
|
|
507
|
+
Parameters,
|
|
508
|
+
CRLBs,
|
|
509
|
+
LogLikelihood,
|
|
510
|
+
)
|
|
511
|
+
else:
|
|
512
|
+
CPU_parallel_fit_2D(
|
|
513
|
+
data,
|
|
514
|
+
fittype,
|
|
515
|
+
PSFSigma,
|
|
516
|
+
varim,
|
|
517
|
+
sz,
|
|
518
|
+
Nfitraw,
|
|
519
|
+
initZ,
|
|
520
|
+
iterations,
|
|
521
|
+
Parameters,
|
|
522
|
+
CRLBs,
|
|
523
|
+
LogLikelihood,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
stop = time.perf_counter_ns()
|
|
527
|
+
fit = stop - start
|
|
528
|
+
start = time.perf_counter_ns()
|
|
529
|
+
|
|
530
|
+
stop = time.perf_counter_ns()
|
|
531
|
+
fromgpu = stop - start
|
|
532
|
+
start = time.perf_counter_ns()
|
|
533
|
+
|
|
534
|
+
# cleanup
|
|
535
|
+
stop = time.perf_counter_ns()
|
|
536
|
+
|
|
537
|
+
return Parameters, CRLBs, LogLikelihood
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def init_numba_CPU():
|
|
541
|
+
n = 21
|
|
542
|
+
sigma = 4
|
|
543
|
+
x = np.arange(n, dtype=np.float32)
|
|
544
|
+
y = 100 * np.exp(-((x - n / 2) ** 2) / (2 * sigma**2))
|
|
545
|
+
y = np.tile(y, n).reshape((n, n))
|
|
546
|
+
z = (y * y.T).flatten().astype(np.float32)
|
|
547
|
+
z = z[np.newaxis, ...]
|
|
548
|
+
|
|
549
|
+
varim = np.ones(z.shape, dtype=np.float32)
|
|
550
|
+
LogLikelihood = np.zeros((1, 1), dtype=np.float32)
|
|
551
|
+
# varim=None
|
|
552
|
+
Parameters = np.zeros((1, (NV_P + 1)), np.float32)
|
|
553
|
+
CRLBs = np.zeros((1, NV_P), np.float32)
|
|
554
|
+
CPU_parallel_fit_2D(z, 1, 1.5, None, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
555
|
+
Parameters = np.zeros((1, (NV_PS + 1)), np.float32)
|
|
556
|
+
CRLBs = np.zeros((1, NV_PS), np.float32)
|
|
557
|
+
CPU_parallel_fit_2D(z, 2, 1.5, None, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
558
|
+
Parameters = np.zeros((1, (NV_PS2 + 1)), np.float32)
|
|
559
|
+
CRLBs = np.zeros((1, NV_PS2), np.float32)
|
|
560
|
+
CPU_parallel_fit_2D(z, 4, 1.5, None, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
561
|
+
Parameters = np.zeros((1, (NV_PS + 1)), np.float32)
|
|
562
|
+
CRLBs = np.zeros((1, NV_PS), np.float32)
|
|
563
|
+
CPU_parallel_fit_3D_scpline(
|
|
564
|
+
z,
|
|
565
|
+
varim,
|
|
566
|
+
np.ones((64, 4, 4, 4), dtype=np.float32).flatten(),
|
|
567
|
+
4,
|
|
568
|
+
4,
|
|
569
|
+
4,
|
|
570
|
+
int(n),
|
|
571
|
+
1,
|
|
572
|
+
0,
|
|
573
|
+
30,
|
|
574
|
+
Parameters,
|
|
575
|
+
CRLBs,
|
|
576
|
+
LogLikelihood,
|
|
577
|
+
)
|
|
578
|
+
# varim not None
|
|
579
|
+
Parameters = np.zeros((1, (NV_P + 1)), np.float32)
|
|
580
|
+
CRLBs = np.zeros((1, NV_P), np.float32)
|
|
581
|
+
CPU_parallel_fit_2D(z, 1, 1.5, varim, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
582
|
+
Parameters = np.zeros((1, (NV_PS + 1)), np.float32)
|
|
583
|
+
CRLBs = np.zeros((1, NV_PS), np.float32)
|
|
584
|
+
CPU_parallel_fit_2D(z, 2, 1.5, varim, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
585
|
+
Parameters = np.zeros((1, (NV_PS2 + 1)), np.float32)
|
|
586
|
+
CRLBs = np.zeros((1, NV_PS2), np.float32)
|
|
587
|
+
CPU_parallel_fit_2D(z, 4, 1.5, varim, n, 1, 0, 1, Parameters, CRLBs, LogLikelihood)
|
|
588
|
+
Parameters = np.zeros((1, (NV_PS + 1)), np.float32)
|
|
589
|
+
CRLBs = np.zeros((1, NV_PS), np.float32)
|
|
590
|
+
CPU_parallel_fit_3D_scpline(
|
|
591
|
+
z,
|
|
592
|
+
varim,
|
|
593
|
+
np.ones((64, 4, 4, 4), dtype=np.float32).flatten(),
|
|
594
|
+
4,
|
|
595
|
+
4,
|
|
596
|
+
4,
|
|
597
|
+
int(n),
|
|
598
|
+
1,
|
|
599
|
+
0,
|
|
600
|
+
30,
|
|
601
|
+
Parameters,
|
|
602
|
+
CRLBs,
|
|
603
|
+
LogLikelihood,
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
@nb.njit
|
|
608
|
+
def fit_single_iteration(data, PSFSigma, sz, iterations, varim, fittype):
|
|
609
|
+
ll = np.float64(np.nan)
|
|
610
|
+
|
|
611
|
+
try:
|
|
612
|
+
if fittype == 1:
|
|
613
|
+
result, crb, ll = CPU.kernel_MLEFit_LM(
|
|
614
|
+
data, PSFSigma, int(sz), iterations, varim
|
|
615
|
+
)
|
|
616
|
+
elif fittype == 2:
|
|
617
|
+
result, crb, ll = CPU.kernel_MLEFit_LM_Sigma(
|
|
618
|
+
data, PSFSigma, int(sz), iterations, varim
|
|
619
|
+
)
|
|
620
|
+
elif fittype == 4:
|
|
621
|
+
result, crb, ll = CPU.kernel_MLEFit_LM_sigmaxy(
|
|
622
|
+
data, PSFSigma, int(sz), iterations, varim
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
return result, crb, ll
|
|
626
|
+
except Exception:
|
|
627
|
+
if fittype == 1:
|
|
628
|
+
result = np.zeros(NV_P + 1, dtype=np.float32)
|
|
629
|
+
crb = np.zeros(NV_P, dtype=np.float32)
|
|
630
|
+
elif fittype == 2:
|
|
631
|
+
result = np.zeros(NV_PS + 1, dtype=np.float32)
|
|
632
|
+
crb = np.zeros(NV_PS, dtype=np.float32)
|
|
633
|
+
elif fittype == 4:
|
|
634
|
+
result = np.zeros(NV_PS2 + 1, dtype=np.float32)
|
|
635
|
+
crb = np.zeros(NV_PS2, dtype=np.float32)
|
|
636
|
+
|
|
637
|
+
return result, crb, ll
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
@nb.njit(parallel=True, cache=True)
|
|
641
|
+
def CPU_parallel_fit_2D(
|
|
642
|
+
data,
|
|
643
|
+
fittype,
|
|
644
|
+
PSFSigma,
|
|
645
|
+
varim,
|
|
646
|
+
sz,
|
|
647
|
+
Nfitraw,
|
|
648
|
+
initZ,
|
|
649
|
+
iterations,
|
|
650
|
+
Parameters,
|
|
651
|
+
CRLBs,
|
|
652
|
+
LogLikelihood,
|
|
653
|
+
):
|
|
654
|
+
for ii in nb.prange(Nfitraw):
|
|
655
|
+
varim_ii = None if varim is None else varim[ii, :]
|
|
656
|
+
Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = fit_single_iteration(
|
|
657
|
+
data[ii, :], PSFSigma, sz, iterations, varim_ii, fittype
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
return Parameters, CRLBs, LogLikelihood
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
# @nb.njit(parallel=True, cache=True)
|
|
664
|
+
# def CPU_parallel_fit_2D(
|
|
665
|
+
# data,
|
|
666
|
+
# fittype,
|
|
667
|
+
# PSFSigma,
|
|
668
|
+
# varim,
|
|
669
|
+
# sz,
|
|
670
|
+
# Nfitraw,
|
|
671
|
+
# initZ,
|
|
672
|
+
# iterations,
|
|
673
|
+
# Parameters,
|
|
674
|
+
# CRLBs,
|
|
675
|
+
# LogLikelihood,
|
|
676
|
+
# ):
|
|
677
|
+
# if fittype == 1: # fit x,y,bg,I
|
|
678
|
+
# for ii in nb.prange(Nfitraw):
|
|
679
|
+
# try:
|
|
680
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = (
|
|
681
|
+
# CPU.kernel_MLEFit_LM(
|
|
682
|
+
# data[ii, :],
|
|
683
|
+
# PSFSigma,
|
|
684
|
+
# int(sz),
|
|
685
|
+
# iterations,
|
|
686
|
+
# None if varim is None else varim[ii, :],
|
|
687
|
+
# )
|
|
688
|
+
# )
|
|
689
|
+
# except Exception:
|
|
690
|
+
# Parameters[ii, :] = -1
|
|
691
|
+
# CRLBs[ii, :] = -1
|
|
692
|
+
# LogLikelihood[ii] = -1
|
|
693
|
+
# elif fittype == 2: # fit x,y,bg,I,sigma
|
|
694
|
+
# for ii in nb.prange(Nfitraw):
|
|
695
|
+
# try:
|
|
696
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = (
|
|
697
|
+
# CPU.kernel_MLEFit_LM_Sigma(
|
|
698
|
+
# data[ii, :],
|
|
699
|
+
# PSFSigma,
|
|
700
|
+
# int(sz),
|
|
701
|
+
# iterations,
|
|
702
|
+
# None if varim is None else varim[ii, :],
|
|
703
|
+
# )
|
|
704
|
+
# )
|
|
705
|
+
# except Exception:
|
|
706
|
+
# Parameters[ii, :] = -1
|
|
707
|
+
# CRLBs[ii, :] = -1
|
|
708
|
+
# LogLikelihood[ii] = -1
|
|
709
|
+
# elif fittype == 4: # fit x,y,bg,I,sigmax,sigmay
|
|
710
|
+
# for ii in nb.prange(Nfitraw):
|
|
711
|
+
# try:
|
|
712
|
+
# Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = (
|
|
713
|
+
# CPU.kernel_MLEFit_LM_sigmaxy(
|
|
714
|
+
# data[ii, :],
|
|
715
|
+
# PSFSigma,
|
|
716
|
+
# int(sz),
|
|
717
|
+
# iterations,
|
|
718
|
+
# None if varim is None else varim[ii, :],
|
|
719
|
+
# )
|
|
720
|
+
# )
|
|
721
|
+
# except Exception:
|
|
722
|
+
# Parameters[ii, :] = -1
|
|
723
|
+
# CRLBs[ii, :] = -1
|
|
724
|
+
# LogLikelihood[ii] = -1
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
@nb.njit(parallel=True, cache=True)
|
|
728
|
+
def CPU_parallel_fit_3D_scpline(
|
|
729
|
+
data,
|
|
730
|
+
varim,
|
|
731
|
+
coeff,
|
|
732
|
+
spline_xsize,
|
|
733
|
+
spline_ysize,
|
|
734
|
+
spline_zsize,
|
|
735
|
+
sz,
|
|
736
|
+
Nfitraw,
|
|
737
|
+
initZ,
|
|
738
|
+
iterations,
|
|
739
|
+
Parameters,
|
|
740
|
+
CRLBs,
|
|
741
|
+
LogLikelihood,
|
|
742
|
+
):
|
|
743
|
+
for ii in nb.prange(Nfitraw):
|
|
744
|
+
try:
|
|
745
|
+
Parameters[ii, :], CRLBs[ii, :], LogLikelihood[ii] = (
|
|
746
|
+
CPU.kernel_splineMLEFit_z(
|
|
747
|
+
data[ii, :],
|
|
748
|
+
coeff,
|
|
749
|
+
spline_xsize,
|
|
750
|
+
spline_ysize,
|
|
751
|
+
spline_zsize,
|
|
752
|
+
int(sz),
|
|
753
|
+
iterations,
|
|
754
|
+
initZ,
|
|
755
|
+
None if varim is None else varim[ii, :],
|
|
756
|
+
)
|
|
757
|
+
)
|
|
758
|
+
except Exception:
|
|
759
|
+
Parameters[ii, :] = -1
|
|
760
|
+
CRLBs[ii, :] = -1
|
|
761
|
+
LogLikelihood[ii] = -1
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
@nb.njit(cache=True)
|
|
765
|
+
def get_roi_list(image: np.ndarray, points: np.ndarray, roi_size=7):
|
|
766
|
+
'''
|
|
767
|
+
Gets the roi list of specific size around the supplied (x, y) points
|
|
768
|
+
|
|
769
|
+
Parameters
|
|
770
|
+
----------
|
|
771
|
+
image : np.ndarray
|
|
772
|
+
The single channel image
|
|
773
|
+
points : np.ndarray
|
|
774
|
+
The points list of preliminary detection
|
|
775
|
+
roi_size : int, optional
|
|
776
|
+
roi size, by default 7
|
|
777
|
+
|
|
778
|
+
Returns
|
|
779
|
+
-------
|
|
780
|
+
tuple[np.ndarray, np.ndarray]
|
|
781
|
+
roi_list array of shape (nRoi, roi_size**2),
|
|
782
|
+
coord_list of roi top left corner
|
|
783
|
+
'''
|
|
784
|
+
if len(points) < 1:
|
|
785
|
+
return None
|
|
786
|
+
|
|
787
|
+
assert len(image.shape) == 2, 'image should be a 2D ndarray!'
|
|
788
|
+
|
|
789
|
+
roi_list = np.zeros((points.shape[0], roi_size**2), np.float32)
|
|
790
|
+
coord_list = np.zeros_like(points)
|
|
791
|
+
|
|
792
|
+
for r in nb.prange(points.shape[0]):
|
|
793
|
+
x, y = points[r, :]
|
|
794
|
+
idx = int(x - roi_size // 2)
|
|
795
|
+
idy = int(y - roi_size // 2)
|
|
796
|
+
if idx < 0:
|
|
797
|
+
idx = 0
|
|
798
|
+
if idy < 0:
|
|
799
|
+
idy = 0
|
|
800
|
+
if idx + roi_size > image.shape[1]:
|
|
801
|
+
idx = image.shape[1] - roi_size
|
|
802
|
+
if idy + roi_size > image.shape[0]:
|
|
803
|
+
idy = image.shape[0] - roi_size
|
|
804
|
+
coord_list[r, :] = [idx, idy]
|
|
805
|
+
roi_list[r, :] = image[idy : idy + roi_size, idx : idx + roi_size].flatten()
|
|
806
|
+
|
|
807
|
+
return roi_list, coord_list
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
@nb.njit(cache=True)
|
|
811
|
+
def get_roi_list_CMOS(
|
|
812
|
+
image: np.ndarray, varim: np.ndarray, points: np.ndarray, roi_size=7
|
|
813
|
+
):
|
|
814
|
+
'''
|
|
815
|
+
Gets the roi list of specific size around the supplied (x, y) points
|
|
816
|
+
|
|
817
|
+
Parameters
|
|
818
|
+
----------
|
|
819
|
+
image : np.ndarray
|
|
820
|
+
The single channel image
|
|
821
|
+
varim : np.ndarray
|
|
822
|
+
The CMOS pixel variance map
|
|
823
|
+
points : np.ndarray
|
|
824
|
+
The points list of preliminary detection
|
|
825
|
+
roi_size : int, optional
|
|
826
|
+
roi size, by default 7
|
|
827
|
+
|
|
828
|
+
Returns
|
|
829
|
+
-------
|
|
830
|
+
tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
831
|
+
roi_list array of shape (nRoi, roi_size**2),
|
|
832
|
+
coord_list of roi top left corner
|
|
833
|
+
'''
|
|
834
|
+
if len(points) < 1:
|
|
835
|
+
return None
|
|
836
|
+
|
|
837
|
+
assert len(image.shape) == 2, 'image should be a 2D ndarray!'
|
|
838
|
+
|
|
839
|
+
assert image.shape == varim.shape, 'image & varim must have equal shape!'
|
|
840
|
+
|
|
841
|
+
roi_list = np.zeros((2, points.shape[0], roi_size**2), np.float32)
|
|
842
|
+
coord_list = np.zeros_like(points)
|
|
843
|
+
|
|
844
|
+
for r in nb.prange(points.shape[0]):
|
|
845
|
+
x, y = points[r, :]
|
|
846
|
+
idx = int(x - roi_size // 2)
|
|
847
|
+
idy = int(y - roi_size // 2)
|
|
848
|
+
if idx < 0:
|
|
849
|
+
idx = 0
|
|
850
|
+
if idy < 0:
|
|
851
|
+
idy = 0
|
|
852
|
+
if idx + roi_size > image.shape[1]:
|
|
853
|
+
idx = image.shape[1] - roi_size
|
|
854
|
+
if idy + roi_size > image.shape[0]:
|
|
855
|
+
idy = image.shape[0] - roi_size
|
|
856
|
+
coord_list[r, :] = [idx, idy]
|
|
857
|
+
roi_list[0, r, :] = image[idy : idy + roi_size, idx : idx + roi_size].flatten()
|
|
858
|
+
roi_list[1, r, :] = varim[idy : idy + roi_size, idx : idx + roi_size].flatten()
|
|
859
|
+
|
|
860
|
+
return roi_list[0], roi_list[1], coord_list
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def psf2cspline_np(psf):
|
|
864
|
+
# calculate A
|
|
865
|
+
A = np.zeros((64, 64))
|
|
866
|
+
for i in range(1, 5):
|
|
867
|
+
dx = (i - 1) / 3
|
|
868
|
+
for j in range(1, 5):
|
|
869
|
+
dy = (j - 1) / 3
|
|
870
|
+
for k in range(1, 5):
|
|
871
|
+
dz = (k - 1) / 3
|
|
872
|
+
for ll in range(1, 5):
|
|
873
|
+
for m in range(1, 5):
|
|
874
|
+
for n in range(1, 5):
|
|
875
|
+
A[
|
|
876
|
+
(i - 1) * 16 + (j - 1) * 4 + k - 1,
|
|
877
|
+
(ll - 1) * 16 + (m - 1) * 4 + n - 1,
|
|
878
|
+
] = dx ** (ll - 1) * dy ** (m - 1) * dz ** (n - 1)
|
|
879
|
+
|
|
880
|
+
# upsample psf with factor of 3
|
|
881
|
+
psf_up = ndimage.zoom(psf, 3.0, mode='grid-constant', grid_mode=True)[
|
|
882
|
+
1:-1, 1:-1, 1:-1
|
|
883
|
+
]
|
|
884
|
+
A = np.float32(A)
|
|
885
|
+
coeff = calsplinecoeff(A, psf, psf_up)
|
|
886
|
+
return coeff
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
def calsplinecoeff(A, psf, psf_up):
|
|
890
|
+
# calculate cspline coefficients
|
|
891
|
+
coeff = np.zeros((64, psf.shape[0] - 1, psf.shape[1] - 1, psf.shape[2] - 1))
|
|
892
|
+
for i in range(coeff.shape[1]):
|
|
893
|
+
for j in range(coeff.shape[2]):
|
|
894
|
+
for k in range(coeff.shape[3]):
|
|
895
|
+
temp = psf_up[
|
|
896
|
+
i * 3 : 3 * (i + 1) + 1,
|
|
897
|
+
j * 3 : 3 * (j + 1) + 1,
|
|
898
|
+
k * 3 : 3 * (k + 1) + 1,
|
|
899
|
+
]
|
|
900
|
+
x = np.linalg.solve(A, temp.flatten())
|
|
901
|
+
coeff[:, i, j, k] = x
|
|
902
|
+
|
|
903
|
+
return coeff
|