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,1396 @@
|
|
|
1
|
+
|
|
2
|
+
import numba as nb
|
|
3
|
+
from numba import cuda
|
|
4
|
+
|
|
5
|
+
from microEye.analysis.fitting.pyfit3Dcspline.constants import *
|
|
6
|
+
from microEye.analysis.fitting.pyfit3Dcspline.GPU.GPUfunctions import *
|
|
7
|
+
from microEye.analysis.fitting.pyfit3Dcspline.GPU.GPUsplineLib import *
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@cuda.jit
|
|
11
|
+
def kernel_MLEFit_LM_EMCCD(
|
|
12
|
+
d_data, PSFSigma, sz, iterations, d_Parameters, d_CRLBs,
|
|
13
|
+
d_LogLikelihood, Nfits):
|
|
14
|
+
'''
|
|
15
|
+
brief basic MLE fitting kernel. No additional parameters are computed.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
d_data : _type_
|
|
20
|
+
d_data array of subregions to fit copied to GPU
|
|
21
|
+
PSFSigma : _type_
|
|
22
|
+
PSFSigma sigma of the point spread function
|
|
23
|
+
sz : _type_
|
|
24
|
+
sz nxn size of the subregion to fit
|
|
25
|
+
iterations : _type_
|
|
26
|
+
iterations number of iterations for solution to converge
|
|
27
|
+
d_Parameters : _type_
|
|
28
|
+
d_Parameters array of fitting parameters to return for each subregion
|
|
29
|
+
d_CRLBs : _type_
|
|
30
|
+
d_CRLBs array of Cramer-Rao lower bound estimates to return for
|
|
31
|
+
each subregion
|
|
32
|
+
d_LogLikelihood : _type_
|
|
33
|
+
d_LogLikelihood array of loglikelihood estimates to return for
|
|
34
|
+
each subregion
|
|
35
|
+
Nfits : _type_
|
|
36
|
+
Nfits number of subregions to fit
|
|
37
|
+
'''
|
|
38
|
+
NV = NV_P
|
|
39
|
+
NV_NV = NV_P_squared
|
|
40
|
+
M = cuda.local.array(NV_NV, nb.float32)
|
|
41
|
+
|
|
42
|
+
Diag = cuda.local.array(NV, nb.float32)
|
|
43
|
+
Minv = cuda.local.array(NV_NV, nb.float32)
|
|
44
|
+
|
|
45
|
+
tx = cuda.threadIdx.x
|
|
46
|
+
bx = cuda.blockIdx.x
|
|
47
|
+
BlockSize = cuda.blockDim.x
|
|
48
|
+
|
|
49
|
+
model = 0
|
|
50
|
+
data = 0
|
|
51
|
+
Div = 0
|
|
52
|
+
|
|
53
|
+
newTheta = cuda.local.array(NV, nb.float32)
|
|
54
|
+
oldTheta = cuda.local.array(NV, nb.float32)
|
|
55
|
+
newLambda = INIT_LAMBDA
|
|
56
|
+
oldLambda = INIT_LAMBDA
|
|
57
|
+
mu = 0
|
|
58
|
+
|
|
59
|
+
newUpdate = cuda.local.array(NV, nb.float32)
|
|
60
|
+
oldUpdate = cuda.local.array(NV, nb.float32)
|
|
61
|
+
newDudt = cuda.local.array(NV, nb.float32)
|
|
62
|
+
for i in range(NV):
|
|
63
|
+
newUpdate[i] = 1e13
|
|
64
|
+
oldUpdate[i] = 1e13
|
|
65
|
+
newDudt[i] = 0
|
|
66
|
+
maxJump = cuda.local.array(4, nb.float32)
|
|
67
|
+
maxJump[0] = 1.0
|
|
68
|
+
maxJump[1] = 1.0
|
|
69
|
+
maxJump[2] = 100.0
|
|
70
|
+
maxJump[3] = 20.0
|
|
71
|
+
|
|
72
|
+
newErr = 1e12
|
|
73
|
+
oldErr = 1e13
|
|
74
|
+
|
|
75
|
+
jacobian = cuda.local.array(NV, nb.float32)
|
|
76
|
+
hessian = cuda.local.array(NV_NV, nb.float32)
|
|
77
|
+
t1 = 0
|
|
78
|
+
t2 = 0
|
|
79
|
+
|
|
80
|
+
Nmax = 0
|
|
81
|
+
errFlag = 0
|
|
82
|
+
L = cuda.local.array(NV_NV, nb.float32)
|
|
83
|
+
U = cuda.local.array(NV_NV, nb.float32)
|
|
84
|
+
|
|
85
|
+
# Prevent read/write past end of array
|
|
86
|
+
if ((bx*BlockSize+tx) >= Nfits):
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
for ii in range(NV_NV):
|
|
90
|
+
M[ii] = 0
|
|
91
|
+
Minv[ii] = 0
|
|
92
|
+
hessian[ii] = 0
|
|
93
|
+
L[ii] = 0
|
|
94
|
+
U[ii] = 0
|
|
95
|
+
|
|
96
|
+
# Requires Checking
|
|
97
|
+
idx = sz*sz*bx*BlockSize + sz*sz*tx
|
|
98
|
+
s_data = d_data[idx:idx + sz*sz]
|
|
99
|
+
|
|
100
|
+
# initial values
|
|
101
|
+
newTheta[0], newTheta[1] = kernel_CenterofMass2D(sz, s_data)
|
|
102
|
+
Nmax, newTheta[3] = kernel_GaussFMaxMin2D(sz, PSFSigma, s_data)
|
|
103
|
+
newTheta[2] = max(0.0, (Nmax-newTheta[3])*2*pi*PSFSigma*PSFSigma)
|
|
104
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
105
|
+
|
|
106
|
+
maxJump[2] = max(newTheta[2], maxJump[2])
|
|
107
|
+
|
|
108
|
+
maxJump[3] = max(newTheta[3], maxJump[3])
|
|
109
|
+
|
|
110
|
+
for ii in range(NV):
|
|
111
|
+
oldTheta[ii] = newTheta[ii]
|
|
112
|
+
jacobian[ii] = 0
|
|
113
|
+
|
|
114
|
+
# updateFitValues
|
|
115
|
+
newErr = 0
|
|
116
|
+
for ii in range(sz):
|
|
117
|
+
for jj in range(sz):
|
|
118
|
+
newDudt, model = kernel_DerivativeGauss2D(
|
|
119
|
+
ii, jj, PSFSigma, newTheta, newDudt)
|
|
120
|
+
data = s_data[sz*jj+ii]
|
|
121
|
+
|
|
122
|
+
if (data > 0):
|
|
123
|
+
newErr = newErr + 2*((model-data)-data*math.log(model/data))
|
|
124
|
+
else:
|
|
125
|
+
newErr = newErr + 2*model
|
|
126
|
+
data = 0
|
|
127
|
+
|
|
128
|
+
t1 = 1 - data/model
|
|
129
|
+
for ll in range(NV):
|
|
130
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
131
|
+
|
|
132
|
+
t2 = data/math.pow(model, 2)
|
|
133
|
+
for ll in range(NV):
|
|
134
|
+
for mm in range(ll, NV, 1):
|
|
135
|
+
hessian[ll*NV + mm] += t2 * newDudt[ll] * newDudt[mm]
|
|
136
|
+
hessian[mm*NV + ll] = hessian[ll*NV + mm]
|
|
137
|
+
|
|
138
|
+
for kk in range(iterations): # main iterative loop # noqa: B007
|
|
139
|
+
if(abs((newErr-oldErr)/newErr) < TOLERANCE):
|
|
140
|
+
break # CONVERGED
|
|
141
|
+
else:
|
|
142
|
+
if(newErr > ACCEPTANCE * oldErr):
|
|
143
|
+
# copy Fitdata
|
|
144
|
+
|
|
145
|
+
for i in range(NV):
|
|
146
|
+
newTheta[i] = oldTheta[i]
|
|
147
|
+
newUpdate[i] = oldUpdate[i]
|
|
148
|
+
newLambda = oldLambda
|
|
149
|
+
newErr = oldErr
|
|
150
|
+
mu = max((1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
151
|
+
newLambda = SCALE_UP * newLambda
|
|
152
|
+
elif(newErr < oldErr and errFlag == 0):
|
|
153
|
+
newLambda = SCALE_DOWN * newLambda
|
|
154
|
+
mu = 1 + newLambda
|
|
155
|
+
|
|
156
|
+
for i in range(NV):
|
|
157
|
+
hessian[i*NV + i] = hessian[i*NV + i] * mu
|
|
158
|
+
|
|
159
|
+
for ii in range(NV_NV):
|
|
160
|
+
L[ii] = 0
|
|
161
|
+
U[ii] = 0
|
|
162
|
+
|
|
163
|
+
errFlag = kernel_cholesky(hessian, NV, L, U)
|
|
164
|
+
if (errFlag == 0):
|
|
165
|
+
for i in range(NV):
|
|
166
|
+
oldTheta[i] = newTheta[i]
|
|
167
|
+
oldUpdate[i] = newUpdate[i]
|
|
168
|
+
oldLambda = newLambda
|
|
169
|
+
oldErr = newErr
|
|
170
|
+
|
|
171
|
+
kernel_luEvaluate(L, U, jacobian, NV, newUpdate)
|
|
172
|
+
|
|
173
|
+
# updateFitParameters
|
|
174
|
+
for ll in range(NV):
|
|
175
|
+
if (newUpdate[ll]/oldUpdate[ll] < -0.5):
|
|
176
|
+
maxJump[ll] = maxJump[ll] * 0.5
|
|
177
|
+
|
|
178
|
+
newUpdate[ll] = (
|
|
179
|
+
newUpdate[ll] /
|
|
180
|
+
(1+math.fabs(newUpdate[ll]/maxJump[ll])))
|
|
181
|
+
newTheta[ll] = newTheta[ll] - newUpdate[ll]
|
|
182
|
+
|
|
183
|
+
# restrict range
|
|
184
|
+
newTheta[0] = max(newTheta[0], (float(sz)-1)/2-sz/4.0)
|
|
185
|
+
newTheta[0] = min(newTheta[0], (float(sz)-1)/2+sz/4.0)
|
|
186
|
+
newTheta[1] = max(newTheta[1], (float(sz)-1)/2-sz/4.0)
|
|
187
|
+
newTheta[1] = min(newTheta[1], (float(sz)-1)/2+sz/4.0)
|
|
188
|
+
newTheta[2] = max(newTheta[2], 1.0)
|
|
189
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
190
|
+
|
|
191
|
+
newErr = 0
|
|
192
|
+
for hh in range(NV):
|
|
193
|
+
jacobian[hh] = 0
|
|
194
|
+
for hh in range(NV_NV):
|
|
195
|
+
hessian[hh] = 0
|
|
196
|
+
for ii in range(sz):
|
|
197
|
+
for jj in range(sz):
|
|
198
|
+
# calculating derivatives
|
|
199
|
+
newDudt, model = kernel_DerivativeGauss2D(
|
|
200
|
+
ii, jj, PSFSigma, newTheta, newDudt)
|
|
201
|
+
data = s_data[sz*jj+ii]
|
|
202
|
+
|
|
203
|
+
if (data > 0):
|
|
204
|
+
newErr = newErr + \
|
|
205
|
+
2*((model-data)-data*math.log(model/data))
|
|
206
|
+
else:
|
|
207
|
+
newErr = newErr + 2 * model
|
|
208
|
+
data = 0
|
|
209
|
+
|
|
210
|
+
t1 = 1 - data/model
|
|
211
|
+
for ll in range(NV):
|
|
212
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
213
|
+
|
|
214
|
+
t2 = data/math.pow(model, 2)
|
|
215
|
+
for ll in range(NV):
|
|
216
|
+
for mm in range(ll, NV, 1):
|
|
217
|
+
hessian[ll*NV+mm] += \
|
|
218
|
+
t2 * newDudt[ll] * newDudt[mm]
|
|
219
|
+
hessian[mm*NV+ll] = hessian[ll*NV+mm]
|
|
220
|
+
else:
|
|
221
|
+
mu = max(
|
|
222
|
+
(1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
223
|
+
newLambda = SCALE_UP * newLambda
|
|
224
|
+
|
|
225
|
+
# output iteration
|
|
226
|
+
d_Parameters[(NV + 1)*(1+BlockSize*bx+tx) - 1] = kk
|
|
227
|
+
# Calculating the CRLB and LogLikelihood
|
|
228
|
+
Div = 0.0
|
|
229
|
+
for ii in range(sz):
|
|
230
|
+
for jj in range(sz):
|
|
231
|
+
newDudt, model = kernel_DerivativeGauss2D(
|
|
232
|
+
ii, jj, PSFSigma, newTheta, newDudt)
|
|
233
|
+
data = s_data[sz*jj+ii]
|
|
234
|
+
|
|
235
|
+
# Building the Fisher Information Matrix
|
|
236
|
+
for kk in range(NV):
|
|
237
|
+
for ll in range(kk, NV, 1):
|
|
238
|
+
M[kk*NV+ll] += newDudt[ll] * newDudt[kk] / model
|
|
239
|
+
M[ll*NV+kk] = M[kk*NV+ll]
|
|
240
|
+
|
|
241
|
+
# LogLikelyhood
|
|
242
|
+
if (model > 0):
|
|
243
|
+
if (data > 0):
|
|
244
|
+
Div += \
|
|
245
|
+
data*math.log(model) - \
|
|
246
|
+
model-data*math.log(data) + data
|
|
247
|
+
else:
|
|
248
|
+
Div += - model
|
|
249
|
+
|
|
250
|
+
# Matrix inverse (CRLB=F^-1) and output assigments
|
|
251
|
+
kernel_MatInvN(M, Minv, Diag, NV)
|
|
252
|
+
# Write to global arrays
|
|
253
|
+
for kk in range(NV):
|
|
254
|
+
d_Parameters[kk + (NV + 1)*(BlockSize*bx+tx)] = newTheta[kk]
|
|
255
|
+
d_CRLBs[kk + NV*(BlockSize*bx+tx)] = Diag[kk]
|
|
256
|
+
d_LogLikelihood[BlockSize*bx+tx] = Div
|
|
257
|
+
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@cuda.jit
|
|
262
|
+
def kernel_MLEFit_LM_Sigma_EMCCD(
|
|
263
|
+
d_data, PSFSigma, sz, iterations, d_Parameters,
|
|
264
|
+
d_CRLBs, d_LogLikelihood, Nfits):
|
|
265
|
+
'''
|
|
266
|
+
basic MLE fitting kernel. No additional parameters are computed.
|
|
267
|
+
|
|
268
|
+
Parameters
|
|
269
|
+
----------
|
|
270
|
+
d_data : float[]
|
|
271
|
+
d_data array of subregions to fit copied to GPU
|
|
272
|
+
PSFSigma : float
|
|
273
|
+
PSFSigma sigma of the point spread function
|
|
274
|
+
sz : int
|
|
275
|
+
sz nxn size of the subregion to fit
|
|
276
|
+
iterations : int
|
|
277
|
+
iterations number of iterations for solution to converge
|
|
278
|
+
d_Parameters : float[]
|
|
279
|
+
d_Parameters array of fitting parameters to return for each subregion
|
|
280
|
+
d_CRLBs : float[]
|
|
281
|
+
d_CRLBs array of Cramer-Rao lower bound estimates to return for
|
|
282
|
+
each subregion
|
|
283
|
+
d_LogLikelihood : float[]
|
|
284
|
+
d_LogLikelihood array of loglikelihood estimates to return for
|
|
285
|
+
each subregion
|
|
286
|
+
Nfits : int
|
|
287
|
+
Nfits number of subregions to fit
|
|
288
|
+
'''
|
|
289
|
+
NV = NV_PS
|
|
290
|
+
NV_NV = NV_PS_squared
|
|
291
|
+
|
|
292
|
+
M = cuda.local.array(NV_NV, nb.float32)
|
|
293
|
+
Diag = cuda.local.array(NV, nb.float32)
|
|
294
|
+
Minv = cuda.local.array(NV_NV, nb.float32)
|
|
295
|
+
|
|
296
|
+
tx = cuda.threadIdx.x
|
|
297
|
+
bx = cuda.blockIdx.x
|
|
298
|
+
BlockSize = cuda.blockDim.x
|
|
299
|
+
|
|
300
|
+
model = 0
|
|
301
|
+
data = 0
|
|
302
|
+
Div = 0
|
|
303
|
+
|
|
304
|
+
newTheta = cuda.local.array(NV, nb.float32)
|
|
305
|
+
oldTheta = cuda.local.array(NV, nb.float32)
|
|
306
|
+
newLambda = INIT_LAMBDA
|
|
307
|
+
oldLambda = INIT_LAMBDA
|
|
308
|
+
mu = 0
|
|
309
|
+
|
|
310
|
+
newUpdate = cuda.local.array(NV, nb.float32)
|
|
311
|
+
oldUpdate = cuda.local.array(NV, nb.float32)
|
|
312
|
+
newDudt = cuda.local.array(NV, nb.float32)
|
|
313
|
+
for i in range(NV):
|
|
314
|
+
newUpdate[i] = 1e13
|
|
315
|
+
oldUpdate[i] = 1e13
|
|
316
|
+
newDudt[i] = 0
|
|
317
|
+
maxJump = cuda.local.array(NV, nb.float32)
|
|
318
|
+
maxJump[0] = 1.0
|
|
319
|
+
maxJump[1] = 1.0
|
|
320
|
+
maxJump[2] = 100.0
|
|
321
|
+
maxJump[3] = 20.0
|
|
322
|
+
maxJump[4] = 0.5
|
|
323
|
+
|
|
324
|
+
newErr = 1e12
|
|
325
|
+
oldErr = 1e13
|
|
326
|
+
|
|
327
|
+
jacobian = cuda.local.array(NV, nb.float32)
|
|
328
|
+
hessian = cuda.local.array(NV_NV, nb.float32)
|
|
329
|
+
t1 = 0
|
|
330
|
+
t2 = 0
|
|
331
|
+
|
|
332
|
+
Nmax = 0
|
|
333
|
+
errFlag = 0
|
|
334
|
+
L = cuda.local.array(NV_NV, nb.float32)
|
|
335
|
+
U = cuda.local.array(NV_NV, nb.float32)
|
|
336
|
+
|
|
337
|
+
# Prevent read/write past end of array
|
|
338
|
+
if ((bx*BlockSize+tx) >= Nfits):
|
|
339
|
+
return
|
|
340
|
+
|
|
341
|
+
for ii in range(NV_NV):
|
|
342
|
+
M[ii] = 0
|
|
343
|
+
Minv[ii] = 0
|
|
344
|
+
hessian[ii] = 0
|
|
345
|
+
L[ii] = 0
|
|
346
|
+
U[ii] = 0
|
|
347
|
+
|
|
348
|
+
# Requires Checking
|
|
349
|
+
idx = sz*sz*bx*BlockSize + sz*sz*tx
|
|
350
|
+
s_data = d_data[idx:idx + sz*sz]
|
|
351
|
+
|
|
352
|
+
# initial values
|
|
353
|
+
newTheta[0], newTheta[1] = kernel_CenterofMass2D(sz, s_data)
|
|
354
|
+
Nmax, newTheta[3] = kernel_GaussFMaxMin2D(sz, PSFSigma, s_data)
|
|
355
|
+
newTheta[2] = max(0.0, (Nmax-newTheta[3])*2*pi*PSFSigma*PSFSigma)
|
|
356
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
357
|
+
newTheta[4] = PSFSigma
|
|
358
|
+
|
|
359
|
+
maxJump[2] = max(newTheta[2], maxJump[2])
|
|
360
|
+
|
|
361
|
+
maxJump[3] = max(newTheta[3], maxJump[3])
|
|
362
|
+
|
|
363
|
+
for ii in range(NV):
|
|
364
|
+
oldTheta[ii] = newTheta[ii]
|
|
365
|
+
jacobian[ii] = 0
|
|
366
|
+
|
|
367
|
+
# updateFitValues
|
|
368
|
+
newErr = 0
|
|
369
|
+
for ii in range(sz):
|
|
370
|
+
for jj in range(sz):
|
|
371
|
+
newDudt, model = kernel_DerivativeGauss2D_sigma(
|
|
372
|
+
ii, jj, newTheta, newDudt)
|
|
373
|
+
data = s_data[sz*jj+ii]
|
|
374
|
+
|
|
375
|
+
if (data > 0):
|
|
376
|
+
newErr = newErr + 2*((model-data)-data*math.log(model/data))
|
|
377
|
+
else:
|
|
378
|
+
newErr = newErr + 2*model
|
|
379
|
+
data = 0
|
|
380
|
+
|
|
381
|
+
t1 = 1 - data/model
|
|
382
|
+
for ll in range(NV):
|
|
383
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
384
|
+
|
|
385
|
+
t2 = data/math.pow(model, 2)
|
|
386
|
+
for ll in range(NV):
|
|
387
|
+
for mm in range(ll, NV, 1):
|
|
388
|
+
hessian[ll*NV + mm] += t2 * newDudt[ll] * newDudt[mm]
|
|
389
|
+
hessian[mm*NV + ll] = hessian[ll*NV + mm]
|
|
390
|
+
|
|
391
|
+
for kk in range(iterations): # main iterative loop # noqa: B007
|
|
392
|
+
if(abs((newErr-oldErr)/newErr) < TOLERANCE):
|
|
393
|
+
break # CONVERGED
|
|
394
|
+
else:
|
|
395
|
+
if(newErr > ACCEPTANCE * oldErr):
|
|
396
|
+
# copy Fitdata
|
|
397
|
+
|
|
398
|
+
for i in range(NV):
|
|
399
|
+
newTheta[i] = oldTheta[i]
|
|
400
|
+
newUpdate[i] = oldUpdate[i]
|
|
401
|
+
newLambda = oldLambda
|
|
402
|
+
newErr = oldErr
|
|
403
|
+
mu = max((1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
404
|
+
newLambda = SCALE_UP * newLambda
|
|
405
|
+
elif(newErr < oldErr and errFlag == 0):
|
|
406
|
+
newLambda = SCALE_DOWN * newLambda
|
|
407
|
+
mu = 1 + newLambda
|
|
408
|
+
|
|
409
|
+
for i in range(NV):
|
|
410
|
+
hessian[i*NV + i] = hessian[i*NV + i] * mu
|
|
411
|
+
|
|
412
|
+
for ii in range(NV_NV):
|
|
413
|
+
L[ii] = 0
|
|
414
|
+
U[ii] = 0
|
|
415
|
+
|
|
416
|
+
errFlag = kernel_cholesky(hessian, NV, L, U)
|
|
417
|
+
if (errFlag == 0):
|
|
418
|
+
for i in range(NV):
|
|
419
|
+
oldTheta[i] = newTheta[i]
|
|
420
|
+
oldUpdate[i] = newUpdate[i]
|
|
421
|
+
oldLambda = newLambda
|
|
422
|
+
oldErr = newErr
|
|
423
|
+
|
|
424
|
+
newUpdate = kernel_luEvaluate(L, U, jacobian, NV, newUpdate)
|
|
425
|
+
|
|
426
|
+
# updateFitParameters
|
|
427
|
+
for ll in range(NV):
|
|
428
|
+
if (newUpdate[ll]/oldUpdate[ll] < -0.5):
|
|
429
|
+
maxJump[ll] = maxJump[ll] * 0.5
|
|
430
|
+
|
|
431
|
+
newUpdate[ll] = (
|
|
432
|
+
newUpdate[ll] /
|
|
433
|
+
(1+math.fabs(newUpdate[ll]/maxJump[ll])))
|
|
434
|
+
newTheta[ll] = newTheta[ll] - newUpdate[ll]
|
|
435
|
+
# restrict range
|
|
436
|
+
newTheta[0] = max(newTheta[0], (float(sz)-1)/2-sz/4.0)
|
|
437
|
+
newTheta[0] = min(newTheta[0], (float(sz)-1)/2+sz/4.0)
|
|
438
|
+
newTheta[1] = max(newTheta[1], (float(sz)-1)/2-sz/4.0)
|
|
439
|
+
newTheta[1] = min(newTheta[1], (float(sz)-1)/2+sz/4.0)
|
|
440
|
+
newTheta[2] = max(newTheta[2], 1.0)
|
|
441
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
442
|
+
newTheta[4] = max(newTheta[4], 0.5)
|
|
443
|
+
newTheta[4] = min(newTheta[4], sz/2.0)
|
|
444
|
+
|
|
445
|
+
newErr = 0
|
|
446
|
+
for hh in range(NV):
|
|
447
|
+
jacobian[hh] = 0
|
|
448
|
+
for hh in range(NV_NV):
|
|
449
|
+
hessian[hh] = 0
|
|
450
|
+
for ii in range(sz):
|
|
451
|
+
for jj in range(sz):
|
|
452
|
+
# calculating derivatives
|
|
453
|
+
newDudt, model = kernel_DerivativeGauss2D_sigma(
|
|
454
|
+
ii, jj, newTheta, newDudt)
|
|
455
|
+
data = s_data[sz*jj+ii]
|
|
456
|
+
|
|
457
|
+
if (data > 0):
|
|
458
|
+
newErr = newErr + \
|
|
459
|
+
2*((model-data)-data*math.log(model/data))
|
|
460
|
+
else:
|
|
461
|
+
newErr = newErr + 2 * model
|
|
462
|
+
data = 0
|
|
463
|
+
|
|
464
|
+
t1 = 1 - data/model
|
|
465
|
+
for ll in range(NV):
|
|
466
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
467
|
+
|
|
468
|
+
t2 = data/math.pow(model, 2)
|
|
469
|
+
for ll in range(NV):
|
|
470
|
+
for mm in range(ll, NV, 1):
|
|
471
|
+
hessian[ll*NV+mm] += \
|
|
472
|
+
t2 * newDudt[ll] * newDudt[mm]
|
|
473
|
+
hessian[mm*NV+ll] = hessian[ll*NV+mm]
|
|
474
|
+
else:
|
|
475
|
+
mu = max(
|
|
476
|
+
(1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
477
|
+
newLambda = SCALE_UP * newLambda
|
|
478
|
+
|
|
479
|
+
# output iteration
|
|
480
|
+
d_Parameters[(NV + 1)*(1+BlockSize*bx+tx) - 1] = kk
|
|
481
|
+
|
|
482
|
+
# Calculating the CRLB and LogLikelihood
|
|
483
|
+
Div = 0.0
|
|
484
|
+
for ii in range(sz):
|
|
485
|
+
for jj in range(sz):
|
|
486
|
+
newDudt, model = kernel_DerivativeGauss2D_sigma(
|
|
487
|
+
ii, jj, newTheta, newDudt)
|
|
488
|
+
data = s_data[sz*jj+ii]
|
|
489
|
+
|
|
490
|
+
# Building the Fisher Information Matrix
|
|
491
|
+
for kk in range(NV):
|
|
492
|
+
for ll in range(kk, NV, 1):
|
|
493
|
+
M[kk*NV+ll] += newDudt[ll] * newDudt[kk] / model
|
|
494
|
+
M[ll*NV+kk] = M[kk*NV+ll]
|
|
495
|
+
|
|
496
|
+
# LogLikelyhood
|
|
497
|
+
if (model > 0):
|
|
498
|
+
if (data > 0):
|
|
499
|
+
Div += \
|
|
500
|
+
data*math.log(model) - \
|
|
501
|
+
model-data*math.log(data) + data
|
|
502
|
+
else:
|
|
503
|
+
Div += - model
|
|
504
|
+
|
|
505
|
+
# Matrix inverse (CRLB=F^-1) and output assigments
|
|
506
|
+
kernel_MatInvN(M, Minv, Diag, NV)
|
|
507
|
+
# Write to global arrays
|
|
508
|
+
for kk in range(NV):
|
|
509
|
+
d_Parameters[kk + (NV + 1)*(BlockSize*bx+tx)] = newTheta[kk]
|
|
510
|
+
d_CRLBs[kk + NV*(BlockSize*bx+tx)] = Diag[kk]
|
|
511
|
+
d_LogLikelihood[BlockSize*bx+tx] = Div
|
|
512
|
+
|
|
513
|
+
return
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
@cuda.jit
|
|
517
|
+
def kernel_MLEFit_LM_z_EMCCD(
|
|
518
|
+
d_data, PSFSigma_x, Ax, Ay, Bx, By, gamma, d,
|
|
519
|
+
PSFSigma_y, sz, iterations, d_Parameters, d_CRLBs,
|
|
520
|
+
d_LogLikelihood, Nfits):
|
|
521
|
+
'''
|
|
522
|
+
basic MLE fitting kernel. No additional parameters are computed.
|
|
523
|
+
|
|
524
|
+
Parameters
|
|
525
|
+
----------
|
|
526
|
+
d_data : float[]
|
|
527
|
+
array of subregions to fit copied to GPU
|
|
528
|
+
PSFSigma_x : float
|
|
529
|
+
sigma of the point spread function on the x axis
|
|
530
|
+
Ax : float
|
|
531
|
+
???
|
|
532
|
+
Ay : float
|
|
533
|
+
???
|
|
534
|
+
Bx : float
|
|
535
|
+
???
|
|
536
|
+
By : float
|
|
537
|
+
???
|
|
538
|
+
gamma : float
|
|
539
|
+
???
|
|
540
|
+
d : float
|
|
541
|
+
???
|
|
542
|
+
PSFSigma_y : float
|
|
543
|
+
sigma of the point spread function on the y axis
|
|
544
|
+
sz : int
|
|
545
|
+
nxn size of the subregion to fit
|
|
546
|
+
iterations : int
|
|
547
|
+
number of iterations for solution to converge
|
|
548
|
+
d_Parameters : float[]
|
|
549
|
+
array of fitting parameters to return for each subregion
|
|
550
|
+
d_CRLBs : float[]
|
|
551
|
+
array of Cramer-Rao lower bound estimates to return for each subregion
|
|
552
|
+
d_LogLikelihood : float[]
|
|
553
|
+
array of loglikelihood estimates to return for each subregion
|
|
554
|
+
Nfits : int
|
|
555
|
+
number of subregions to fit
|
|
556
|
+
'''
|
|
557
|
+
NV = NV_PS
|
|
558
|
+
NV_NV = NV_PS_squared
|
|
559
|
+
|
|
560
|
+
M = cuda.local.array(NV_NV, nb.float32)
|
|
561
|
+
Diag = cuda.local.array(NV, nb.float32)
|
|
562
|
+
Minv = cuda.local.array(NV_NV, nb.float32)
|
|
563
|
+
|
|
564
|
+
tx = cuda.threadIdx.x
|
|
565
|
+
bx = cuda.blockIdx.x
|
|
566
|
+
BlockSize = cuda.blockDim.x
|
|
567
|
+
|
|
568
|
+
model = 0
|
|
569
|
+
data = 0
|
|
570
|
+
Div = 0
|
|
571
|
+
PSFy = PSFx = 0
|
|
572
|
+
|
|
573
|
+
newTheta = cuda.local.array(NV, nb.float32)
|
|
574
|
+
oldTheta = cuda.local.array(NV, nb.float32)
|
|
575
|
+
newLambda = INIT_LAMBDA
|
|
576
|
+
oldLambda = INIT_LAMBDA
|
|
577
|
+
mu = 0
|
|
578
|
+
|
|
579
|
+
newUpdate = cuda.local.array(NV, nb.float32)
|
|
580
|
+
oldUpdate = cuda.local.array(NV, nb.float32)
|
|
581
|
+
newDudt = cuda.local.array(NV, nb.float32)
|
|
582
|
+
for i in range(NV):
|
|
583
|
+
newUpdate[i] = 1e13
|
|
584
|
+
oldUpdate[i] = 1e13
|
|
585
|
+
newDudt[i] = 0
|
|
586
|
+
maxJump = cuda.local.array(NV, nb.float32)
|
|
587
|
+
maxJump[0] = 1.0
|
|
588
|
+
maxJump[1] = 1.0
|
|
589
|
+
maxJump[2] = 100.0
|
|
590
|
+
maxJump[3] = 20.0
|
|
591
|
+
maxJump[4] = 2
|
|
592
|
+
|
|
593
|
+
newErr = 1e12
|
|
594
|
+
oldErr = 1e13
|
|
595
|
+
|
|
596
|
+
jacobian = cuda.local.array(NV, nb.float32)
|
|
597
|
+
hessian = cuda.local.array(NV_NV, nb.float32)
|
|
598
|
+
t1 = 0
|
|
599
|
+
t2 = 0
|
|
600
|
+
|
|
601
|
+
Nmax = 0
|
|
602
|
+
errFlag = 0
|
|
603
|
+
L = cuda.local.array(NV_NV, nb.float32)
|
|
604
|
+
U = cuda.local.array(NV_NV, nb.float32)
|
|
605
|
+
|
|
606
|
+
# Prevent read/write past end of array
|
|
607
|
+
if ((bx*BlockSize+tx) >= Nfits):
|
|
608
|
+
return
|
|
609
|
+
|
|
610
|
+
for ii in range(NV_NV):
|
|
611
|
+
M[ii] = 0
|
|
612
|
+
Minv[ii] = 0
|
|
613
|
+
hessian[ii] = 0
|
|
614
|
+
L[ii] = 0
|
|
615
|
+
U[ii] = 0
|
|
616
|
+
|
|
617
|
+
# Requires Checking
|
|
618
|
+
idx = sz*sz*bx*BlockSize + sz*sz*tx
|
|
619
|
+
s_data = d_data[idx:idx + sz*sz]
|
|
620
|
+
|
|
621
|
+
# initial values
|
|
622
|
+
newTheta[0], newTheta[1] = kernel_CenterofMass2D(
|
|
623
|
+
sz, s_data)
|
|
624
|
+
Nmax, newTheta[3] = kernel_GaussFMaxMin2D(
|
|
625
|
+
sz, PSFSigma_x, s_data)
|
|
626
|
+
newTheta[2] = max(
|
|
627
|
+
0.0,
|
|
628
|
+
(Nmax-newTheta[3])*2*pi*PSFSigma_x*PSFSigma_y*math.sqrt(2.0))
|
|
629
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
630
|
+
newTheta[4] = 0
|
|
631
|
+
|
|
632
|
+
maxJump[2] = max(newTheta[2], maxJump[2])
|
|
633
|
+
|
|
634
|
+
maxJump[3] = max(newTheta[3], maxJump[3])
|
|
635
|
+
|
|
636
|
+
for ii in range(NV):
|
|
637
|
+
oldTheta[ii] = newTheta[ii]
|
|
638
|
+
jacobian[ii] = 0
|
|
639
|
+
|
|
640
|
+
# updateFitValues
|
|
641
|
+
newErr = 0
|
|
642
|
+
for ii in range(sz):
|
|
643
|
+
for jj in range(sz):
|
|
644
|
+
PSFx, PSFy, newDudt, _, model = kernel_DerivativeIntGauss2Dz(
|
|
645
|
+
ii, jj, newTheta, PSFSigma_x, PSFSigma_y,
|
|
646
|
+
Ax, Ay, Bx, By, gamma, d, newDudt, None, False)
|
|
647
|
+
data = s_data[sz*jj+ii]
|
|
648
|
+
|
|
649
|
+
if (data > 0):
|
|
650
|
+
newErr = newErr + 2*((model-data)-data*math.log(model/data))
|
|
651
|
+
else:
|
|
652
|
+
newErr = newErr + 2*model
|
|
653
|
+
data = 0
|
|
654
|
+
|
|
655
|
+
t1 = 1 - data/model
|
|
656
|
+
for ll in range(NV):
|
|
657
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
658
|
+
|
|
659
|
+
t2 = data/math.pow(model, 2)
|
|
660
|
+
for ll in range(NV):
|
|
661
|
+
for mm in range(ll, NV, 1):
|
|
662
|
+
hessian[ll*NV + mm] += t2 * newDudt[ll] * newDudt[mm]
|
|
663
|
+
hessian[mm*NV + ll] = hessian[ll*NV + mm]
|
|
664
|
+
|
|
665
|
+
for kk in range(iterations): # main iterative loop # noqa: B007
|
|
666
|
+
if(abs((newErr-oldErr)/newErr) < TOLERANCE):
|
|
667
|
+
break # CONVERGED
|
|
668
|
+
else:
|
|
669
|
+
if(newErr > ACCEPTANCE * oldErr):
|
|
670
|
+
# copy Fitdata
|
|
671
|
+
|
|
672
|
+
for i in range(NV):
|
|
673
|
+
newTheta[i] = oldTheta[i]
|
|
674
|
+
newUpdate[i] = oldUpdate[i]
|
|
675
|
+
newLambda = oldLambda
|
|
676
|
+
newErr = oldErr
|
|
677
|
+
mu = max((1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
678
|
+
newLambda = SCALE_UP * newLambda
|
|
679
|
+
elif(newErr < oldErr and errFlag == 0):
|
|
680
|
+
newLambda = SCALE_DOWN * newLambda
|
|
681
|
+
mu = 1 + newLambda
|
|
682
|
+
|
|
683
|
+
for i in range(NV):
|
|
684
|
+
hessian[i*NV + i] = hessian[i*NV + i] * mu
|
|
685
|
+
|
|
686
|
+
for ii in range(NV_NV):
|
|
687
|
+
L[ii] = 0
|
|
688
|
+
U[ii] = 0
|
|
689
|
+
|
|
690
|
+
errFlag = kernel_cholesky(hessian, NV, L, U)
|
|
691
|
+
if (errFlag == 0):
|
|
692
|
+
for i in range(NV):
|
|
693
|
+
oldTheta[i] = newTheta[i]
|
|
694
|
+
oldUpdate[i] = newUpdate[i]
|
|
695
|
+
oldLambda = newLambda
|
|
696
|
+
oldErr = newErr
|
|
697
|
+
|
|
698
|
+
newUpdate = kernel_luEvaluate(L, U, jacobian, NV, newUpdate)
|
|
699
|
+
|
|
700
|
+
# updateFitParameters
|
|
701
|
+
for ll in range(NV):
|
|
702
|
+
if (newUpdate[ll]/oldUpdate[ll] < -0.5):
|
|
703
|
+
maxJump[ll] = maxJump[ll] * 0.5
|
|
704
|
+
|
|
705
|
+
newUpdate[ll] = (
|
|
706
|
+
newUpdate[ll] /
|
|
707
|
+
(1+math.fabs(newUpdate[ll]/maxJump[ll])))
|
|
708
|
+
newTheta[ll] = newTheta[ll] - newUpdate[ll]
|
|
709
|
+
# restrict range
|
|
710
|
+
newTheta[0] = max(newTheta[0], (float(sz)-1)/2-sz/4.0)
|
|
711
|
+
newTheta[0] = min(newTheta[0], (float(sz)-1)/2+sz/4.0)
|
|
712
|
+
newTheta[1] = max(newTheta[1], (float(sz)-1)/2-sz/4.0)
|
|
713
|
+
newTheta[1] = min(newTheta[1], (float(sz)-1)/2+sz/4.0)
|
|
714
|
+
newTheta[2] = max(newTheta[2], 1.0)
|
|
715
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
716
|
+
|
|
717
|
+
newErr = 0
|
|
718
|
+
for hh in range(NV):
|
|
719
|
+
jacobian[hh] = 0
|
|
720
|
+
for hh in range(NV_NV):
|
|
721
|
+
hessian[hh] = 0
|
|
722
|
+
for ii in range(sz):
|
|
723
|
+
for jj in range(sz):
|
|
724
|
+
# calculating derivatives
|
|
725
|
+
PSFx, PSFy, newDudt, _, model = \
|
|
726
|
+
kernel_DerivativeIntGauss2Dz(
|
|
727
|
+
ii, jj, newTheta, PSFSigma_x, PSFSigma_y,
|
|
728
|
+
Ax, Ay, Bx, By, gamma, d, newDudt, None, False)
|
|
729
|
+
|
|
730
|
+
data = s_data[sz*jj+ii]
|
|
731
|
+
|
|
732
|
+
if (data > 0):
|
|
733
|
+
newErr = newErr + \
|
|
734
|
+
2*((model-data)-data*math.log(model/data))
|
|
735
|
+
else:
|
|
736
|
+
newErr = newErr + 2 * model
|
|
737
|
+
data = 0
|
|
738
|
+
|
|
739
|
+
t1 = 1 - data/model
|
|
740
|
+
for ll in range(NV):
|
|
741
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
742
|
+
|
|
743
|
+
t2 = data/math.pow(model, 2)
|
|
744
|
+
for ll in range(NV):
|
|
745
|
+
for mm in range(ll, NV, 1):
|
|
746
|
+
hessian[ll*NV+mm] += \
|
|
747
|
+
t2 * newDudt[ll] * newDudt[mm]
|
|
748
|
+
hessian[mm*NV+ll] = hessian[ll*NV+mm]
|
|
749
|
+
else:
|
|
750
|
+
mu = max(
|
|
751
|
+
(1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
752
|
+
newLambda = SCALE_UP * newLambda
|
|
753
|
+
|
|
754
|
+
# output iteration
|
|
755
|
+
d_Parameters[(NV + 1)*(1+BlockSize*bx+tx) - 1] = kk
|
|
756
|
+
|
|
757
|
+
# Calculating the CRLB and LogLikelihood
|
|
758
|
+
Div = 0.0
|
|
759
|
+
for ii in range(sz):
|
|
760
|
+
for jj in range(sz):
|
|
761
|
+
PSFx, PSFy, newDudt, _, model = kernel_DerivativeIntGauss2Dz(
|
|
762
|
+
ii, jj, newTheta, PSFSigma_x, PSFSigma_y,
|
|
763
|
+
Ax, Ay, Bx, By, gamma, d, newDudt, None, False)
|
|
764
|
+
data = s_data[sz*jj+ii]
|
|
765
|
+
|
|
766
|
+
# Building the Fisher Information Matrix
|
|
767
|
+
for kk in range(NV):
|
|
768
|
+
for ll in range(kk, NV, 1):
|
|
769
|
+
M[kk*NV+ll] += newDudt[ll] * newDudt[kk] / model
|
|
770
|
+
M[ll*NV+kk] = M[kk*NV+ll]
|
|
771
|
+
|
|
772
|
+
# LogLikelyhood
|
|
773
|
+
if (model > 0):
|
|
774
|
+
if (data > 0):
|
|
775
|
+
Div += \
|
|
776
|
+
data*math.log(model) - \
|
|
777
|
+
model-data*math.log(data) + data
|
|
778
|
+
else:
|
|
779
|
+
Div += - model
|
|
780
|
+
|
|
781
|
+
# Matrix inverse (CRLB=F^-1) and output assigments
|
|
782
|
+
kernel_MatInvN(M, Minv, Diag, NV)
|
|
783
|
+
# Write to global arrays
|
|
784
|
+
for kk in range(NV):
|
|
785
|
+
d_Parameters[kk + (NV + 1)*(BlockSize*bx+tx)] = newTheta[kk]
|
|
786
|
+
d_CRLBs[kk + NV*(BlockSize*bx+tx)] = Diag[kk]
|
|
787
|
+
d_LogLikelihood[BlockSize*bx+tx] = Div
|
|
788
|
+
|
|
789
|
+
return
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
@cuda.jit
|
|
793
|
+
def kernel_MLEFit_LM_sigmaxy_EMCCD(
|
|
794
|
+
d_data, PSFSigma, sz, iterations, d_Parameters,
|
|
795
|
+
d_CRLBs, d_LogLikelihood, Nfits):
|
|
796
|
+
'''
|
|
797
|
+
basic MLE fitting kernel. No additional parameters are computed.
|
|
798
|
+
|
|
799
|
+
Parameters
|
|
800
|
+
----------
|
|
801
|
+
d_data : float[]
|
|
802
|
+
array of subregions to fit copied to GPU
|
|
803
|
+
PSFSigma : float
|
|
804
|
+
sigma of the point spread function
|
|
805
|
+
sz : int
|
|
806
|
+
nxn size of the subregion to fit
|
|
807
|
+
iterations : int
|
|
808
|
+
number of iterations for solution to converge
|
|
809
|
+
d_Parameters : float[]
|
|
810
|
+
array of fitting parameters to return for each subregion
|
|
811
|
+
d_CRLBs : float[]
|
|
812
|
+
array of Cramer-Rao lower bound estimates to return for each subregion
|
|
813
|
+
d_LogLikelihood : float[]
|
|
814
|
+
array of loglikelihood estimates to return for each subregion
|
|
815
|
+
Nfits : int
|
|
816
|
+
number of subregions to fit
|
|
817
|
+
'''
|
|
818
|
+
NV = NV_PS2
|
|
819
|
+
NV_NV = NV_PS2_squared
|
|
820
|
+
|
|
821
|
+
M = cuda.local.array(NV_NV, nb.float32)
|
|
822
|
+
Diag = cuda.local.array(NV, nb.float32)
|
|
823
|
+
Minv = cuda.local.array(NV_NV, nb.float32)
|
|
824
|
+
|
|
825
|
+
tx = cuda.threadIdx.x
|
|
826
|
+
bx = cuda.blockIdx.x
|
|
827
|
+
BlockSize = cuda.blockDim.x
|
|
828
|
+
|
|
829
|
+
model = 0
|
|
830
|
+
data = 0
|
|
831
|
+
Div = 0
|
|
832
|
+
|
|
833
|
+
newTheta = cuda.local.array(NV, nb.float32)
|
|
834
|
+
oldTheta = cuda.local.array(NV, nb.float32)
|
|
835
|
+
newLambda = INIT_LAMBDA
|
|
836
|
+
oldLambda = INIT_LAMBDA
|
|
837
|
+
mu = 0
|
|
838
|
+
|
|
839
|
+
newUpdate = cuda.local.array(NV, nb.float32)
|
|
840
|
+
oldUpdate = cuda.local.array(NV, nb.float32)
|
|
841
|
+
newDudt = cuda.local.array(NV, nb.float32)
|
|
842
|
+
for i in range(NV):
|
|
843
|
+
newUpdate[i] = 1e13
|
|
844
|
+
oldUpdate[i] = 1e13
|
|
845
|
+
newDudt[i] = 0
|
|
846
|
+
maxJump = cuda.local.array(NV, nb.float32)
|
|
847
|
+
maxJump[0] = 1.0
|
|
848
|
+
maxJump[1] = 1.0
|
|
849
|
+
maxJump[2] = 100.0
|
|
850
|
+
maxJump[3] = 20.0
|
|
851
|
+
maxJump[4] = 0.5
|
|
852
|
+
maxJump[5] = 0.5
|
|
853
|
+
|
|
854
|
+
newErr = 1e12
|
|
855
|
+
oldErr = 1e13
|
|
856
|
+
|
|
857
|
+
jacobian = cuda.local.array(NV, nb.float32)
|
|
858
|
+
hessian = cuda.local.array(NV_NV, nb.float32)
|
|
859
|
+
t1 = 0.0
|
|
860
|
+
t2 = 0.0
|
|
861
|
+
|
|
862
|
+
Nmax = 0
|
|
863
|
+
errFlag = 0
|
|
864
|
+
L = cuda.local.array(NV_NV, nb.float32)
|
|
865
|
+
U = cuda.local.array(NV_NV, nb.float32)
|
|
866
|
+
|
|
867
|
+
# Prevent read/write past end of array
|
|
868
|
+
if ((bx*BlockSize+tx) >= Nfits):
|
|
869
|
+
return
|
|
870
|
+
|
|
871
|
+
for ii in range(NV_NV):
|
|
872
|
+
M[ii] = 0
|
|
873
|
+
Minv[ii] = 0
|
|
874
|
+
hessian[ii] = 0
|
|
875
|
+
L[ii] = 0
|
|
876
|
+
U[ii] = 0
|
|
877
|
+
|
|
878
|
+
# Requires Checking
|
|
879
|
+
idx = sz*sz*bx*BlockSize + sz*sz*tx
|
|
880
|
+
s_data = d_data[idx:idx + sz*sz]
|
|
881
|
+
|
|
882
|
+
# initial values
|
|
883
|
+
newTheta[0], newTheta[1] = kernel_CenterofMass2D(
|
|
884
|
+
sz, s_data)
|
|
885
|
+
Nmax, newTheta[3] = kernel_GaussFMaxMin2D(
|
|
886
|
+
sz, PSFSigma, s_data)
|
|
887
|
+
newTheta[2] = max(
|
|
888
|
+
0.0,
|
|
889
|
+
(Nmax-newTheta[3])*2*pi*PSFSigma*PSFSigma)
|
|
890
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
891
|
+
newTheta[4] = PSFSigma
|
|
892
|
+
newTheta[5] = PSFSigma
|
|
893
|
+
|
|
894
|
+
maxJump[2] = max(newTheta[2], maxJump[2])
|
|
895
|
+
|
|
896
|
+
maxJump[3] = max(newTheta[3], maxJump[3])
|
|
897
|
+
|
|
898
|
+
for ii in range(NV):
|
|
899
|
+
oldTheta[ii] = newTheta[ii]
|
|
900
|
+
jacobian[ii] = 0
|
|
901
|
+
|
|
902
|
+
# updateFitValues
|
|
903
|
+
newErr = 0
|
|
904
|
+
for ii in range(sz):
|
|
905
|
+
for jj in range(sz):
|
|
906
|
+
newDudt, model = kernel_DerivativeGauss2D_sigmaxy(
|
|
907
|
+
ii, jj, newTheta, newDudt)
|
|
908
|
+
data = s_data[sz*jj+ii]
|
|
909
|
+
|
|
910
|
+
if (data > 0):
|
|
911
|
+
newErr = newErr + 2*((model-data)-data*math.log(model/data))
|
|
912
|
+
else:
|
|
913
|
+
newErr = newErr + 2*model
|
|
914
|
+
data = 0
|
|
915
|
+
|
|
916
|
+
t1 = 1 - data/model
|
|
917
|
+
for ll in range(NV):
|
|
918
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
919
|
+
|
|
920
|
+
t2 = data/math.pow(model, 2)
|
|
921
|
+
for ll in range(NV):
|
|
922
|
+
for mm in range(ll, NV, 1):
|
|
923
|
+
hessian[ll*NV + mm] += t2 * newDudt[ll] * newDudt[mm]
|
|
924
|
+
hessian[mm*NV + ll] = hessian[ll*NV + mm]
|
|
925
|
+
|
|
926
|
+
for kk in range(iterations): # main iterative loop # noqa: B007
|
|
927
|
+
if(abs((newErr-oldErr)/newErr) < TOLERANCE):
|
|
928
|
+
break # CONVERGED
|
|
929
|
+
else:
|
|
930
|
+
if(newErr > ACCEPTANCE * oldErr):
|
|
931
|
+
# copy Fitdata
|
|
932
|
+
for i in range(NV):
|
|
933
|
+
newTheta[i] = oldTheta[i]
|
|
934
|
+
newUpdate[i] = oldUpdate[i]
|
|
935
|
+
newLambda = oldLambda
|
|
936
|
+
newErr = oldErr
|
|
937
|
+
mu = max((1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
938
|
+
newLambda = SCALE_UP * newLambda
|
|
939
|
+
elif(newErr < oldErr and errFlag == 0):
|
|
940
|
+
newLambda = SCALE_DOWN * newLambda
|
|
941
|
+
mu = 1 + newLambda
|
|
942
|
+
|
|
943
|
+
for i in range(NV):
|
|
944
|
+
hessian[i*NV + i] = hessian[i*NV + i] * mu
|
|
945
|
+
|
|
946
|
+
for ii in range(NV_NV):
|
|
947
|
+
L[ii] = 0
|
|
948
|
+
U[ii] = 0
|
|
949
|
+
|
|
950
|
+
errFlag = kernel_cholesky(hessian, NV, L, U)
|
|
951
|
+
if (errFlag == 0):
|
|
952
|
+
for i in range(NV):
|
|
953
|
+
oldTheta[i] = newTheta[i]
|
|
954
|
+
oldUpdate[i] = newUpdate[i]
|
|
955
|
+
oldLambda = newLambda
|
|
956
|
+
oldErr = newErr
|
|
957
|
+
|
|
958
|
+
newUpdate = kernel_luEvaluate(L, U, jacobian, NV, newUpdate)
|
|
959
|
+
|
|
960
|
+
# updateFitParameters
|
|
961
|
+
for ll in range(NV):
|
|
962
|
+
if (newUpdate[ll]/oldUpdate[ll] < -0.5):
|
|
963
|
+
maxJump[ll] = maxJump[ll] * 0.5
|
|
964
|
+
|
|
965
|
+
newUpdate[ll] = (
|
|
966
|
+
newUpdate[ll] /
|
|
967
|
+
(1+math.fabs(newUpdate[ll]/maxJump[ll])))
|
|
968
|
+
newTheta[ll] = newTheta[ll] - newUpdate[ll]
|
|
969
|
+
# restrict range
|
|
970
|
+
newTheta[0] = max(newTheta[0], (float(sz)-1)/2-sz/4.0)
|
|
971
|
+
newTheta[0] = min(newTheta[0], (float(sz)-1)/2+sz/4.0)
|
|
972
|
+
newTheta[1] = max(newTheta[1], (float(sz)-1)/2-sz/4.0)
|
|
973
|
+
newTheta[1] = min(newTheta[1], (float(sz)-1)/2+sz/4.0)
|
|
974
|
+
newTheta[2] = max(newTheta[2], 1.0)
|
|
975
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
976
|
+
newTheta[4] = max(newTheta[4], PSFSigma/10.0)
|
|
977
|
+
newTheta[5] = max(newTheta[5], PSFSigma/10.0)
|
|
978
|
+
|
|
979
|
+
newErr = 0
|
|
980
|
+
for hh in range(NV):
|
|
981
|
+
jacobian[hh] = 0
|
|
982
|
+
for hh in range(NV_NV):
|
|
983
|
+
hessian[hh] = 0
|
|
984
|
+
for ii in range(sz):
|
|
985
|
+
for jj in range(sz):
|
|
986
|
+
# calculating derivatives
|
|
987
|
+
newDudt, model = kernel_DerivativeGauss2D_sigmaxy(
|
|
988
|
+
ii, jj, newTheta, newDudt)
|
|
989
|
+
data = s_data[sz*jj+ii]
|
|
990
|
+
|
|
991
|
+
if (data > 0):
|
|
992
|
+
newErr = newErr + \
|
|
993
|
+
2*((model-data)-data*math.log(model/data))
|
|
994
|
+
else:
|
|
995
|
+
newErr = newErr + 2*model
|
|
996
|
+
data = 0
|
|
997
|
+
|
|
998
|
+
t1 = 1 - data/model
|
|
999
|
+
for ll in range(NV):
|
|
1000
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
1001
|
+
|
|
1002
|
+
t2 = data/math.pow(model, 2)
|
|
1003
|
+
for ll in range(NV):
|
|
1004
|
+
for mm in range(ll, NV, 1):
|
|
1005
|
+
hessian[ll*NV+mm] += \
|
|
1006
|
+
t2 * newDudt[ll] * newDudt[mm]
|
|
1007
|
+
hessian[mm*NV+ll] = hessian[ll*NV+mm]
|
|
1008
|
+
else:
|
|
1009
|
+
mu = max(
|
|
1010
|
+
(1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
1011
|
+
newLambda = SCALE_UP * newLambda
|
|
1012
|
+
|
|
1013
|
+
# output iteration
|
|
1014
|
+
d_Parameters[(NV + 1)*(1+BlockSize*bx+tx) - 1] = kk
|
|
1015
|
+
|
|
1016
|
+
# Calculating the CRLB and LogLikelihood
|
|
1017
|
+
Div = 0.0
|
|
1018
|
+
for ii in range(sz):
|
|
1019
|
+
for jj in range(sz):
|
|
1020
|
+
newDudt, model = kernel_DerivativeGauss2D_sigmaxy(
|
|
1021
|
+
ii, jj, newTheta, newDudt)
|
|
1022
|
+
data = s_data[sz*jj+ii]
|
|
1023
|
+
|
|
1024
|
+
# Building the Fisher Information Matrix
|
|
1025
|
+
for kk in range(NV):
|
|
1026
|
+
for ll in range(kk, NV, 1):
|
|
1027
|
+
M[kk*NV+ll] += newDudt[ll] * newDudt[kk] / model
|
|
1028
|
+
M[ll*NV+kk] = M[kk*NV+ll]
|
|
1029
|
+
|
|
1030
|
+
# LogLikelyhood
|
|
1031
|
+
if (model > 0):
|
|
1032
|
+
if (data > 0):
|
|
1033
|
+
Div += \
|
|
1034
|
+
data*math.log(model) - \
|
|
1035
|
+
model-data*math.log(data) + data
|
|
1036
|
+
else:
|
|
1037
|
+
Div += - model
|
|
1038
|
+
|
|
1039
|
+
# Matrix inverse (CRLB=F^-1) and output assigments
|
|
1040
|
+
kernel_MatInvN(M, Minv, Diag, NV)
|
|
1041
|
+
# Write to global arrays
|
|
1042
|
+
for kk in range(NV):
|
|
1043
|
+
d_Parameters[kk + (NV + 1)*(BlockSize*bx+tx)] = newTheta[kk]
|
|
1044
|
+
d_CRLBs[kk + NV*(BlockSize*bx+tx)] = Diag[kk]
|
|
1045
|
+
d_LogLikelihood[BlockSize*bx+tx] = Div
|
|
1046
|
+
|
|
1047
|
+
return
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
@cuda.jit
|
|
1051
|
+
def kernel_splineMLEFit_z_EMCCD(
|
|
1052
|
+
d_data, d_coeff, spline_xsize, spline_ysize, spline_zsize, sz,
|
|
1053
|
+
iterations, d_Parameters, d_CRLBs, d_LogLikelihood,
|
|
1054
|
+
initZ, Nfits):
|
|
1055
|
+
'''
|
|
1056
|
+
basic MLE fitting kernel. No additional parameters are computed.
|
|
1057
|
+
|
|
1058
|
+
Parameters
|
|
1059
|
+
----------
|
|
1060
|
+
d_data : float[]
|
|
1061
|
+
array of subregions to fit copied to GPU
|
|
1062
|
+
d_coeff : float[]
|
|
1063
|
+
array of spline coefficients of the PSF model
|
|
1064
|
+
spline_xsize : int
|
|
1065
|
+
x size of spline coefficients
|
|
1066
|
+
spline_ysize : int
|
|
1067
|
+
y size of spline coefficients
|
|
1068
|
+
spline_zsize : int
|
|
1069
|
+
z size of spline coefficients
|
|
1070
|
+
sz : int
|
|
1071
|
+
nxn size of the subregion to fit
|
|
1072
|
+
iterations : int
|
|
1073
|
+
number of iterations for solution to converge
|
|
1074
|
+
d_Parameters : float[]
|
|
1075
|
+
array of fitting parameters to return for each subregion
|
|
1076
|
+
d_CRLBs : float[]
|
|
1077
|
+
array of Cramer-Rao lower bound estimates to return for each subregion
|
|
1078
|
+
d_LogLikelihood : float[]
|
|
1079
|
+
array of loglikelihood estimates to return for each subregion
|
|
1080
|
+
initZ : float
|
|
1081
|
+
intial z position used for fitting
|
|
1082
|
+
Nfits : int
|
|
1083
|
+
number of subregions to fit
|
|
1084
|
+
'''
|
|
1085
|
+
NV = NV_PSP
|
|
1086
|
+
NV_NV = NV_PSP_squared
|
|
1087
|
+
|
|
1088
|
+
M = cuda.local.array(NV_NV, nb.float32)
|
|
1089
|
+
Diag = cuda.local.array(NV, nb.float32)
|
|
1090
|
+
Minv = cuda.local.array(NV_NV, nb.float32)
|
|
1091
|
+
|
|
1092
|
+
tx = cuda.threadIdx.x
|
|
1093
|
+
bx = cuda.blockIdx.x
|
|
1094
|
+
BlockSize = cuda.blockDim.x
|
|
1095
|
+
|
|
1096
|
+
xstart = ystart = zstart = 0
|
|
1097
|
+
|
|
1098
|
+
s_coeff = d_coeff
|
|
1099
|
+
|
|
1100
|
+
model = 0
|
|
1101
|
+
data = 0
|
|
1102
|
+
Div = 0
|
|
1103
|
+
|
|
1104
|
+
newTheta = cuda.local.array(NV, nb.float32)
|
|
1105
|
+
oldTheta = cuda.local.array(NV, nb.float32)
|
|
1106
|
+
newLambda = INIT_LAMBDA
|
|
1107
|
+
oldLambda = INIT_LAMBDA
|
|
1108
|
+
mu = 0
|
|
1109
|
+
|
|
1110
|
+
newUpdate = cuda.local.array(NV, nb.float32)
|
|
1111
|
+
oldUpdate = cuda.local.array(NV, nb.float32)
|
|
1112
|
+
newDudt = cuda.local.array(NV, nb.float32)
|
|
1113
|
+
for i in range(NV):
|
|
1114
|
+
newUpdate[i] = 1e13
|
|
1115
|
+
oldUpdate[i] = 1e13
|
|
1116
|
+
newDudt[i] = 0
|
|
1117
|
+
maxJump = cuda.local.array(NV, nb.float32)
|
|
1118
|
+
maxJump[0] = 1.0
|
|
1119
|
+
maxJump[1] = 1.0
|
|
1120
|
+
maxJump[2] = 100.0
|
|
1121
|
+
maxJump[3] = 20.0
|
|
1122
|
+
maxJump[4] = 2
|
|
1123
|
+
|
|
1124
|
+
newErr = 1e12
|
|
1125
|
+
oldErr = 1e13
|
|
1126
|
+
|
|
1127
|
+
off = 0.0
|
|
1128
|
+
jacobian = cuda.local.array(NV, nb.float32)
|
|
1129
|
+
hessian = cuda.local.array(NV_NV, nb.float32)
|
|
1130
|
+
t1 = 0.0
|
|
1131
|
+
t2 = 0.0
|
|
1132
|
+
|
|
1133
|
+
Nmax = 0
|
|
1134
|
+
errFlag = 0
|
|
1135
|
+
L = cuda.local.array(NV_NV, nb.float32)
|
|
1136
|
+
U = cuda.local.array(NV_NV, nb.float32)
|
|
1137
|
+
|
|
1138
|
+
xc = yc = zc = 0.0
|
|
1139
|
+
delta_f = cuda.local.array(64, nb.float32)
|
|
1140
|
+
delta_dxf = cuda.local.array(64, nb.float32)
|
|
1141
|
+
delta_dyf = cuda.local.array(64, nb.float32)
|
|
1142
|
+
delta_dzf = cuda.local.array(64, nb.float32)
|
|
1143
|
+
for ii in range(64):
|
|
1144
|
+
delta_f[ii] = 0
|
|
1145
|
+
delta_dxf[ii] = 0
|
|
1146
|
+
delta_dyf[ii] = 0
|
|
1147
|
+
delta_dzf[ii] = 0
|
|
1148
|
+
|
|
1149
|
+
# Prevent read/write past end of array
|
|
1150
|
+
if ((bx*BlockSize+tx) >= Nfits):
|
|
1151
|
+
return
|
|
1152
|
+
|
|
1153
|
+
for ii in range(NV_NV):
|
|
1154
|
+
M[ii] = 0
|
|
1155
|
+
Minv[ii] = 0
|
|
1156
|
+
hessian[ii] = 0
|
|
1157
|
+
L[ii] = 0
|
|
1158
|
+
U[ii] = 0
|
|
1159
|
+
|
|
1160
|
+
# Requires Checking
|
|
1161
|
+
idx = sz*sz*bx*BlockSize + sz*sz*tx
|
|
1162
|
+
s_data = d_data[idx:idx + sz*sz]
|
|
1163
|
+
|
|
1164
|
+
# initial values
|
|
1165
|
+
newTheta[0], newTheta[1] = kernel_CenterofMass2D(sz, s_data)
|
|
1166
|
+
Nmax, newTheta[3] = kernel_GaussFMaxMin2D(sz, 1.5, s_data)
|
|
1167
|
+
|
|
1168
|
+
# central pixel of spline model
|
|
1169
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
1170
|
+
newTheta[2] = \
|
|
1171
|
+
(Nmax-newTheta[3]) / d_coeff[
|
|
1172
|
+
int(spline_zsize/2) * (spline_xsize*spline_ysize) +
|
|
1173
|
+
int(spline_ysize/2) * spline_xsize +
|
|
1174
|
+
int(spline_xsize/2)] * 4
|
|
1175
|
+
|
|
1176
|
+
# newTheta[4]=float(spline_zsize)/2;
|
|
1177
|
+
newTheta[4] = initZ
|
|
1178
|
+
|
|
1179
|
+
maxJump[2] = max(newTheta[2], maxJump[2])
|
|
1180
|
+
maxJump[3] = max(newTheta[3], maxJump[3])
|
|
1181
|
+
maxJump[4] = max(spline_zsize/3.0, maxJump[4])
|
|
1182
|
+
|
|
1183
|
+
for ii in range(NV):
|
|
1184
|
+
oldTheta[ii] = newTheta[ii]
|
|
1185
|
+
jacobian[ii] = 0
|
|
1186
|
+
|
|
1187
|
+
# updateFitValues
|
|
1188
|
+
xc = -1.0*((newTheta[0]-float(sz)/2)+0.5)
|
|
1189
|
+
yc = -1.0*((newTheta[1]-float(sz)/2)+0.5)
|
|
1190
|
+
|
|
1191
|
+
off = math.floor((float(spline_xsize)+1.0-float(sz))/2)
|
|
1192
|
+
|
|
1193
|
+
xstart = math.floor(xc)
|
|
1194
|
+
xc = xc - xstart
|
|
1195
|
+
|
|
1196
|
+
ystart = math.floor(yc)
|
|
1197
|
+
yc = yc - ystart
|
|
1198
|
+
|
|
1199
|
+
# zstart = floor(newTheta[4]);
|
|
1200
|
+
zstart = math.floor(newTheta[4])
|
|
1201
|
+
zc = newTheta[4] - zstart
|
|
1202
|
+
|
|
1203
|
+
# updateFitValues
|
|
1204
|
+
newErr = 0
|
|
1205
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf = kernel_computeDelta3D(
|
|
1206
|
+
xc, yc, zc, delta_f, delta_dxf, delta_dyf, delta_dzf)
|
|
1207
|
+
|
|
1208
|
+
for ii in range(sz):
|
|
1209
|
+
for jj in range(sz):
|
|
1210
|
+
newDudt, model = kernel_DerivativeSpline(
|
|
1211
|
+
ii + xstart + off, jj + ystart + off, zstart,
|
|
1212
|
+
spline_xsize, spline_ysize, spline_zsize,
|
|
1213
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf,
|
|
1214
|
+
s_coeff, newTheta, newDudt)
|
|
1215
|
+
data = s_data[sz*jj+ii]
|
|
1216
|
+
|
|
1217
|
+
if (data > 0):
|
|
1218
|
+
newErr = newErr + 2*((model-data)-data*math.log(model/data))
|
|
1219
|
+
else:
|
|
1220
|
+
newErr = newErr + 2*model
|
|
1221
|
+
data = 0
|
|
1222
|
+
|
|
1223
|
+
t1 = 1 - data/model
|
|
1224
|
+
for ll in range(NV):
|
|
1225
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
1226
|
+
|
|
1227
|
+
t2 = data/math.pow(model, 2)
|
|
1228
|
+
for ll in range(NV):
|
|
1229
|
+
for mm in range(ll, NV, 1):
|
|
1230
|
+
hessian[ll*NV + mm] += t2 * newDudt[ll] * newDudt[mm]
|
|
1231
|
+
hessian[mm*NV + ll] = hessian[ll*NV + mm]
|
|
1232
|
+
|
|
1233
|
+
for kk in range(iterations): # main iterative loop # noqa: B007
|
|
1234
|
+
if(abs((newErr-oldErr)/newErr) < TOLERANCE):
|
|
1235
|
+
break # CONVERGED
|
|
1236
|
+
else:
|
|
1237
|
+
if(newErr > ACCEPTANCE * oldErr):
|
|
1238
|
+
# copy Fitdata
|
|
1239
|
+
for i in range(NV):
|
|
1240
|
+
newTheta[i] = oldTheta[i]
|
|
1241
|
+
newUpdate[i] = oldUpdate[i]
|
|
1242
|
+
newLambda = oldLambda
|
|
1243
|
+
newErr = oldErr
|
|
1244
|
+
mu = max((1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
1245
|
+
newLambda = SCALE_UP * newLambda
|
|
1246
|
+
elif(newErr < oldErr and errFlag == 0):
|
|
1247
|
+
newLambda = SCALE_DOWN * newLambda
|
|
1248
|
+
mu = 1 + newLambda
|
|
1249
|
+
|
|
1250
|
+
for i in range(NV):
|
|
1251
|
+
hessian[i*NV + i] = hessian[i*NV + i] * mu
|
|
1252
|
+
|
|
1253
|
+
for ii in range(NV_NV):
|
|
1254
|
+
L[ii] = 0
|
|
1255
|
+
U[ii] = 0
|
|
1256
|
+
|
|
1257
|
+
errFlag = kernel_cholesky(hessian, NV, L, U)
|
|
1258
|
+
|
|
1259
|
+
if (errFlag == 0):
|
|
1260
|
+
for i in range(NV):
|
|
1261
|
+
oldTheta[i] = newTheta[i]
|
|
1262
|
+
oldUpdate[i] = newUpdate[i]
|
|
1263
|
+
oldLambda = newLambda
|
|
1264
|
+
oldErr = newErr
|
|
1265
|
+
|
|
1266
|
+
newUpdate = kernel_luEvaluate(L, U, jacobian, NV, newUpdate)
|
|
1267
|
+
|
|
1268
|
+
# updateFitParameters
|
|
1269
|
+
for ll in range(NV):
|
|
1270
|
+
if (newUpdate[ll]/oldUpdate[ll] < -0.5):
|
|
1271
|
+
maxJump[ll] = maxJump[ll] * 0.5
|
|
1272
|
+
|
|
1273
|
+
newUpdate[ll] = (
|
|
1274
|
+
newUpdate[ll] /
|
|
1275
|
+
(1+math.fabs(newUpdate[ll]/maxJump[ll])))
|
|
1276
|
+
newTheta[ll] = newTheta[ll] - newUpdate[ll]
|
|
1277
|
+
# restrict range
|
|
1278
|
+
newTheta[0] = max(newTheta[0], (float(sz)-1)/2-sz/4.0)
|
|
1279
|
+
newTheta[0] = min(newTheta[0], (float(sz)-1)/2+sz/4.0)
|
|
1280
|
+
newTheta[1] = max(newTheta[1], (float(sz)-1)/2-sz/4.0)
|
|
1281
|
+
newTheta[1] = min(newTheta[1], (float(sz)-1)/2+sz/4.0)
|
|
1282
|
+
newTheta[2] = max(newTheta[2], 1.0)
|
|
1283
|
+
newTheta[3] = max(newTheta[3], 0.01)
|
|
1284
|
+
newTheta[4] = max(newTheta[4], 0.0)
|
|
1285
|
+
newTheta[4] = min(newTheta[4], float(spline_zsize))
|
|
1286
|
+
|
|
1287
|
+
# updateFitValues
|
|
1288
|
+
xc = -1.0*((newTheta[0]-float(sz)/2)+0.5)
|
|
1289
|
+
yc = -1.0*((newTheta[1]-float(sz)/2)+0.5)
|
|
1290
|
+
|
|
1291
|
+
xstart = math.floor(xc)
|
|
1292
|
+
xc = xc - xstart
|
|
1293
|
+
|
|
1294
|
+
ystart = math.floor(yc)
|
|
1295
|
+
yc = yc - ystart
|
|
1296
|
+
|
|
1297
|
+
zstart = math.floor(newTheta[4])
|
|
1298
|
+
zc = newTheta[4] - zstart
|
|
1299
|
+
|
|
1300
|
+
newErr = 0
|
|
1301
|
+
for hh in range(NV):
|
|
1302
|
+
jacobian[hh] = 0
|
|
1303
|
+
for hh in range(NV_NV):
|
|
1304
|
+
hessian[hh] = 0
|
|
1305
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf = \
|
|
1306
|
+
kernel_computeDelta3D(
|
|
1307
|
+
xc, yc, zc, delta_f, delta_dxf, delta_dyf, delta_dzf)
|
|
1308
|
+
|
|
1309
|
+
for ii in range(sz):
|
|
1310
|
+
for jj in range(sz):
|
|
1311
|
+
# calculating derivatives
|
|
1312
|
+
newDudt, model = kernel_DerivativeSpline(
|
|
1313
|
+
ii + xstart + off, jj + ystart + off, zstart,
|
|
1314
|
+
spline_xsize, spline_ysize, spline_zsize,
|
|
1315
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf,
|
|
1316
|
+
s_coeff, newTheta, newDudt)
|
|
1317
|
+
data = s_data[sz*jj+ii]
|
|
1318
|
+
|
|
1319
|
+
if (data > 0):
|
|
1320
|
+
newErr = newErr + \
|
|
1321
|
+
2*((model-data)-data*math.log(model/data))
|
|
1322
|
+
else:
|
|
1323
|
+
newErr = newErr + 2*model
|
|
1324
|
+
data = 0
|
|
1325
|
+
|
|
1326
|
+
t1 = 1 - data/model
|
|
1327
|
+
for ll in range(NV):
|
|
1328
|
+
jacobian[ll] += t1 * newDudt[ll]
|
|
1329
|
+
|
|
1330
|
+
t2 = data/math.pow(model, 2)
|
|
1331
|
+
for ll in range(NV):
|
|
1332
|
+
for mm in range(ll, NV, 1):
|
|
1333
|
+
hessian[ll*NV+mm] += \
|
|
1334
|
+
t2 * newDudt[ll] * newDudt[mm]
|
|
1335
|
+
hessian[mm*NV+ll] = hessian[ll*NV+mm]
|
|
1336
|
+
else:
|
|
1337
|
+
mu = max(
|
|
1338
|
+
(1 + newLambda*SCALE_UP)/(1 + newLambda), 1.3)
|
|
1339
|
+
newLambda = SCALE_UP * newLambda
|
|
1340
|
+
|
|
1341
|
+
# output iteration
|
|
1342
|
+
d_Parameters[(NV + 1)*(1+BlockSize*bx+tx) - 1] = kk
|
|
1343
|
+
|
|
1344
|
+
# Calculating the CRLB and LogLikelihood
|
|
1345
|
+
Div = 0.0
|
|
1346
|
+
|
|
1347
|
+
xc = -1.0*((newTheta[0]-float(sz)/2)+0.5)
|
|
1348
|
+
yc = -1.0*((newTheta[1]-float(sz)/2)+0.5)
|
|
1349
|
+
|
|
1350
|
+
# off = (float(spline_xsize)+1.0-2*float(sz))/2;
|
|
1351
|
+
|
|
1352
|
+
xstart = math.floor(xc)
|
|
1353
|
+
xc = xc - xstart
|
|
1354
|
+
|
|
1355
|
+
ystart = math.floor(yc)
|
|
1356
|
+
yc = yc - ystart
|
|
1357
|
+
|
|
1358
|
+
zstart = math.floor(newTheta[4])
|
|
1359
|
+
zc = newTheta[4] - zstart
|
|
1360
|
+
|
|
1361
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf = kernel_computeDelta3D(
|
|
1362
|
+
xc, yc, zc, delta_f, delta_dxf, delta_dyf, delta_dzf)
|
|
1363
|
+
|
|
1364
|
+
for ii in range(sz):
|
|
1365
|
+
for jj in range(sz):
|
|
1366
|
+
newDudt, model = kernel_DerivativeSpline(
|
|
1367
|
+
ii + xstart + off, jj + ystart + off, zstart,
|
|
1368
|
+
spline_xsize, spline_ysize, spline_zsize,
|
|
1369
|
+
delta_f, delta_dxf, delta_dyf, delta_dzf,
|
|
1370
|
+
s_coeff, newTheta, newDudt)
|
|
1371
|
+
data = s_data[sz*jj+ii]
|
|
1372
|
+
|
|
1373
|
+
# Building the Fisher Information Matrix
|
|
1374
|
+
for kk in range(NV):
|
|
1375
|
+
for ll in range(kk, NV, 1):
|
|
1376
|
+
M[kk*NV+ll] += newDudt[ll] * newDudt[kk] / model
|
|
1377
|
+
M[ll*NV+kk] = M[kk*NV+ll]
|
|
1378
|
+
|
|
1379
|
+
# LogLikelyhood
|
|
1380
|
+
if (model > 0):
|
|
1381
|
+
if (data > 0):
|
|
1382
|
+
Div += \
|
|
1383
|
+
data*math.log(model) - \
|
|
1384
|
+
model-data*math.log(data) + data
|
|
1385
|
+
else:
|
|
1386
|
+
Div += - model
|
|
1387
|
+
|
|
1388
|
+
# Matrix inverse (CRLB=F^-1) and output assigments
|
|
1389
|
+
kernel_MatInvN(M, Minv, Diag, NV)
|
|
1390
|
+
# Write to global arrays
|
|
1391
|
+
for kk in range(NV):
|
|
1392
|
+
d_Parameters[kk + (NV + 1)*(BlockSize*bx+tx)] = newTheta[kk]
|
|
1393
|
+
d_CRLBs[kk + NV*(BlockSize*bx+tx)] = Diag[kk]
|
|
1394
|
+
d_LogLikelihood[BlockSize*bx+tx] = Div
|
|
1395
|
+
|
|
1396
|
+
return
|