microeye 2.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. microEye/__init__.py +47 -0
  2. microEye/_version.py +2 -0
  3. microEye/analysis/__init__.py +1 -0
  4. microEye/analysis/checklist_dialog.py +143 -0
  5. microEye/analysis/cmosMaps.py +228 -0
  6. microEye/analysis/filters/__init__.py +9 -0
  7. microEye/analysis/filters/base.py +21 -0
  8. microEye/analysis/filters/spatial.py +338 -0
  9. microEye/analysis/filters/temporal.py +76 -0
  10. microEye/analysis/fitting/__init__.py +0 -0
  11. microEye/analysis/fitting/fit.py +680 -0
  12. microEye/analysis/fitting/nena.py +375 -0
  13. microEye/analysis/fitting/phasor_fit.py +90 -0
  14. microEye/analysis/fitting/processing.py +317 -0
  15. microEye/analysis/fitting/psf/__init__.py +6 -0
  16. microEye/analysis/fitting/psf/extract.py +1129 -0
  17. microEye/analysis/fitting/psf/rubost_mean.py +150 -0
  18. microEye/analysis/fitting/psf/spline.py +167 -0
  19. microEye/analysis/fitting/psf/stats/__init__.py +12 -0
  20. microEye/analysis/fitting/psf/stats/core.py +295 -0
  21. microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
  22. microEye/analysis/fitting/psf/stats/io.py +104 -0
  23. microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
  24. microEye/analysis/fitting/psf/temp.py +147 -0
  25. microEye/analysis/fitting/psf/test.py +47 -0
  26. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
  27. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
  28. microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
  29. microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
  30. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
  31. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
  32. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
  33. microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
  34. microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
  35. microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
  36. microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
  37. microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
  38. microEye/analysis/fitting/results.py +917 -0
  39. microEye/analysis/fitting/results_stats.py +251 -0
  40. microEye/analysis/fitting/tardis.py +209 -0
  41. microEye/analysis/multi_viewer.py +568 -0
  42. microEye/analysis/processing/__init__.py +1 -0
  43. microEye/analysis/processing/frc.py +120 -0
  44. microEye/analysis/rendering/__init__.py +3 -0
  45. microEye/analysis/rendering/base.py +452 -0
  46. microEye/analysis/rendering/cloud.py +215 -0
  47. microEye/analysis/rendering/core.py +47 -0
  48. microEye/analysis/rendering/volumetric.py +198 -0
  49. microEye/analysis/tools/__init__.py +0 -0
  50. microEye/analysis/tools/kymograms.py +1079 -0
  51. microEye/analysis/tools/roi_selectors.py +556 -0
  52. microEye/analysis/utils/__init__.py +3 -0
  53. microEye/analysis/utils/coordinates.py +18 -0
  54. microEye/analysis/utils/images.py +68 -0
  55. microEye/analysis/utils/windows.py +19 -0
  56. microEye/analysis/viewer/__init__.py +3 -0
  57. microEye/analysis/viewer/image_options_widget.py +615 -0
  58. microEye/analysis/viewer/images.py +1225 -0
  59. microEye/analysis/viewer/layers_widget.py +415 -0
  60. microEye/analysis/viewer/localizations.py +1304 -0
  61. microEye/analysis/viewer/psf.py +1003 -0
  62. microEye/analysis/viewer/volume.py +456 -0
  63. microEye/hardware/__init__.py +3 -0
  64. microEye/hardware/cams/__init__.py +29 -0
  65. microEye/hardware/cams/camera_calibration.py +99 -0
  66. microEye/hardware/cams/camera_list.py +528 -0
  67. microEye/hardware/cams/camera_options.py +694 -0
  68. microEye/hardware/cams/camera_panel.py +941 -0
  69. microEye/hardware/cams/dummy/__init__.py +1 -0
  70. microEye/hardware/cams/dummy/dummy_panel.py +759 -0
  71. microEye/hardware/cams/jobs.py +497 -0
  72. microEye/hardware/cams/line_profiler.py +99 -0
  73. microEye/hardware/cams/linescan/IR_Cam.py +474 -0
  74. microEye/hardware/cams/linescan/__init__.py +1 -0
  75. microEye/hardware/cams/micam.py +524 -0
  76. microEye/hardware/cams/pco/__init__.py +58 -0
  77. microEye/hardware/cams/pco/enums.py +382 -0
  78. microEye/hardware/cams/pco/pco_cam.py +761 -0
  79. microEye/hardware/cams/pco/pco_panel.py +477 -0
  80. microEye/hardware/cams/shortcuts.py +312 -0
  81. microEye/hardware/cams/thorlabs/__init__.py +1 -0
  82. microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
  83. microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
  84. microEye/hardware/cams/ueye/__init__.py +1 -0
  85. microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
  86. microEye/hardware/cams/ueye/ueye_panel.py +861 -0
  87. microEye/hardware/cams/vimba/__init__.py +1 -0
  88. microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
  89. microEye/hardware/cams/vimba/vimba_panel.py +813 -0
  90. microEye/hardware/device.py +60 -0
  91. microEye/hardware/lasers/__init__.py +13 -0
  92. microEye/hardware/lasers/io_matchbox.py +791 -0
  93. microEye/hardware/lasers/io_params.py +85 -0
  94. microEye/hardware/lasers/io_single_laser.py +742 -0
  95. microEye/hardware/lasers/laser_relay.py +594 -0
  96. microEye/hardware/mieye/__init__.py +1 -0
  97. microEye/hardware/mieye/acquisition_manager.py +467 -0
  98. microEye/hardware/mieye/devices_manager.py +533 -0
  99. microEye/hardware/mieye/miEye.py +659 -0
  100. microEye/hardware/misc/__init__.py +0 -0
  101. microEye/hardware/misc/acquisition_view.py +71 -0
  102. microEye/hardware/misc/reglo.py +761 -0
  103. microEye/hardware/misc/temp.py +188 -0
  104. microEye/hardware/port_config.py +59 -0
  105. microEye/hardware/protocols/__init__.py +2 -0
  106. microEye/hardware/protocols/actions.py +402 -0
  107. microEye/hardware/protocols/actions_items.py +703 -0
  108. microEye/hardware/protocols/designer.py +244 -0
  109. microEye/hardware/protocols/scene_manager.py +191 -0
  110. microEye/hardware/protocols/serialization.py +97 -0
  111. microEye/hardware/pycromanager/__init__.py +16 -0
  112. microEye/hardware/pycromanager/core.py +1433 -0
  113. microEye/hardware/pycromanager/devices.py +461 -0
  114. microEye/hardware/pycromanager/enums.py +107 -0
  115. microEye/hardware/pycromanager/headless.py +153 -0
  116. microEye/hardware/pycromanager/utils.py +34 -0
  117. microEye/hardware/pycromanager/widgets/__init__.py +5 -0
  118. microEye/hardware/pycromanager/widgets/bridges.py +407 -0
  119. microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
  120. microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
  121. microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
  122. microEye/hardware/stages/__init__.py +18 -0
  123. microEye/hardware/stages/elliptec/__init__.py +5 -0
  124. microEye/hardware/stages/elliptec/baseDevice.py +314 -0
  125. microEye/hardware/stages/elliptec/device.py +384 -0
  126. microEye/hardware/stages/elliptec/deviceID.py +212 -0
  127. microEye/hardware/stages/elliptec/devicePort.py +379 -0
  128. microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
  129. microEye/hardware/stages/elliptec/devicesView.py +706 -0
  130. microEye/hardware/stages/elliptec/ellDevices.py +134 -0
  131. microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
  132. microEye/hardware/stages/elliptec/motorInfo.py +153 -0
  133. microEye/hardware/stages/elliptec/stage.py +62 -0
  134. microEye/hardware/stages/elliptec/test.py +139 -0
  135. microEye/hardware/stages/kinesis/__init__.py +1 -0
  136. microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
  137. microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
  138. microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
  139. microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
  140. microEye/hardware/stages/kinesis/kinesis.py +776 -0
  141. microEye/hardware/stages/piezo_concept.py +607 -0
  142. microEye/hardware/stages/stabilizer.py +785 -0
  143. microEye/hardware/stages/stage.py +89 -0
  144. microEye/hardware/widgets/__init__.py +10 -0
  145. microEye/hardware/widgets/controller.py +246 -0
  146. microEye/hardware/widgets/devices.py +133 -0
  147. microEye/hardware/widgets/focusWidget.py +264 -0
  148. microEye/hardware/widgets/qlist_slider.py +113 -0
  149. microEye/hardware/widgets/scan_acquisition.py +424 -0
  150. microEye/icons/1024.png +0 -0
  151. microEye/icons/128.png +0 -0
  152. microEye/icons/16.png +0 -0
  153. microEye/icons/24.png +0 -0
  154. microEye/icons/256.png +0 -0
  155. microEye/icons/32.png +0 -0
  156. microEye/icons/48.png +0 -0
  157. microEye/icons/512.png +0 -0
  158. microEye/icons/64.png +0 -0
  159. microEye/icons/__init__.py +0 -0
  160. microEye/icons/close.svg +88 -0
  161. microEye/icons/mieye.png +0 -0
  162. microEye/icons/min.svg +83 -0
  163. microEye/icons/viewer.png +0 -0
  164. microEye/launcher.py +42 -0
  165. microEye/qt.py +181 -0
  166. microEye/utils/__init__.py +2 -0
  167. microEye/utils/enum_encoder.py +10 -0
  168. microEye/utils/expandable_groupbox.py +93 -0
  169. microEye/utils/gui_helper.py +457 -0
  170. microEye/utils/hid/__init__.py +8 -0
  171. microEye/utils/hid/controller.py +153 -0
  172. microEye/utils/hid/device.py +63 -0
  173. microEye/utils/hid/enums.py +140 -0
  174. microEye/utils/hid/utils.py +58 -0
  175. microEye/utils/labelled_slider.py +134 -0
  176. microEye/utils/metadata.py +599 -0
  177. microEye/utils/metadata_tree.py +718 -0
  178. microEye/utils/micro_launcher.py +245 -0
  179. microEye/utils/parameter_tree.py +325 -0
  180. microEye/utils/pyscripting.py +444 -0
  181. microEye/utils/retry_exec.py +35 -0
  182. microEye/utils/start_gui.py +112 -0
  183. microEye/utils/thread_worker.py +115 -0
  184. microEye/utils/uImage.py +1512 -0
  185. microeye-2.3.2.dist-info/METADATA +401 -0
  186. microeye-2.3.2.dist-info/RECORD +190 -0
  187. microeye-2.3.2.dist-info/WHEEL +5 -0
  188. microeye-2.3.2.dist-info/entry_points.txt +2 -0
  189. microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
  190. microeye-2.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,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