@@ -6,66 +6,110 @@ using Noise
66using CUDA
77
88# simulate a gaussian blob with Poisson noise and fit it with a Gaussian function
9- sz = (7 ,7 ) # (1600, 1600)
10- many_fits = true
9+ sz = (9 , 9 ) # (1600, 1600)
10+ many_off = true
11+ many_int = true
12+ many_bg = true
13+ many_sig = true
14+
1115use_cuda = false
12- N = 1_000
13- hyperplanes = many_fits ? rand (Float32, (1 , N)) : 0
14- hp_zeros = many_fits ? zeros (Float32, (1 , N)) : 0
16+ DType = Float32
17+ N = 10_000
18+ hp_off = many_off ? 2 .* rand (DType, (1 , N)) : 0
19+ hp_sig = many_sig ? zeros (DType, (1 , N)) : 0
20+ hp_int = many_int ? 1 .+ rand (DType, (1 , N)) : 1
1521
16- off = [3.2f0 , 3.5f0 ] .+ hyperplanes
17- sigma = [1.4f0 , 1.1f0 ] .+ hp_zeros
18- hyperplanes = many_fits ? rand (Float32, (1 , N)) : 0
19- intensity = [50f0 ] .* (1 .+ hyperplanes)
20- vec_true = ComponentVector (;bg= 10.0f0 .+ hp_zeros, intensity= intensity, off = off, args = sigma)
21- vec_true = Float64 .(vec_true)
22+ off = [5.2 , 4.5 ] .+ hp_off
23+ sigma = [1.4 , 1.1 ] .+ hp_sig
24+ intensity = [50 ] .* hp_int
25+ bg = many_bg ? 10.2 .+ zeros (DType, (1 , N)) : 10.2
26+ vec_true = DType .(ComponentVector (;bg= bg, intensity= intensity, off = off, args = sigma))
2227
28+ # create the perfect spots:
2329pdat = gaussian_vec (sz, vec_true)
24- dat = Float32 .(poisson (Float64 .(pdat)))
30+ dat = DType .(poisson (Float64 .(pdat)))
31+
32+ startvals = DType .(ComponentVector (gauss_start (dat, 0.2 , length (sz))));
33+ sum (abs2 .(collect (startvals. off) .- vec_true. off))
2534
2635pdat = (use_cuda) ? CuArray (pdat) : pdat
2736dat = (use_cuda) ? CuArray (dat) : dat
28-
29- qdat = copy (pdat)
30- qdat .= qdat[:,:,1 ]
31- # now prepare the fitting:
32- # myfg! = get_fg!(pdat, gaussian_raw, length(sz); loss=loss_anscombe_pos, bg=7f0);
33- myfg! = get_fg! (qdat, gaussian_raw, length (sz); loss= loss_gaussian);
34- shyperplanes = many_fits ? zeros (Float32, (1 , size (dat)[end ])) : 0
35- soff = [4.0f0 , 4.0f0 ] .+ shyperplanes
36- bg = [0.5f0 ] .+ shyperplanes
37- intensity = [45f0 ] .+ shyperplanes
38- sigma = [3.0f0 , 2.0f0 ] .+ shyperplanes
3937if (use_cuda)
40- bg = CuArray ([bg])
41- intensity = CuArray (intensity)
42- soff = CuArray (soff)
43- sigma = CuArray (sigma)
38+ startvals = ComponentVector (;bg= CuArray (startvals. bg), intensity= CuArray (startvals. intensity), off = CuArray (startvals. off), args = CuArray (startvals. args))
4439end
45- startvals = ComponentVector (;bg= bg, intensity= intensity, off = soff, args = sigma)
46- startvals = Float64 .(startvals)
47- opt = Optim. Options (iterations = 50 ); #
48- odo = OnceDifferentiable (Optim. NLSolversBase. only_fg! (myfg!), startvals);
40+
41+ # @vt pdat gaussian_vec(sz, startvals)
42+ # qdat = copy(pdat)
43+ # qdat .= qdat[:,:,1]
44+ # now prepare the fitting:
45+ # myfg! = get_fg!(dat, gaussian_raw, length(sz); loss=loss_anscombe_pos, bg=0.1f0);
46+ # myfg! = get_fg!(dat, gaussian_raw, length(sz); loss=loss_gaussian);
47+ myfg! = get_fg! (dat, gaussian_raw, length (sz); loss= loss_poisson_pos);
48+ # hp_off2 = many_off ? zeros(DType, (1, size(dat)[end])) : 0
49+ # soff = [4.0, 4.0] .+ hp_off2
50+ # bg = [0.5] .+ shyperplanes
51+ # intensity = [45.0] .+ hp_int
52+ # sigma = [3.0, 2.0] .+ hp_sig
53+ # if (use_cuda)
54+ # bg = CuArray([bg])
55+ # intensity = CuArray(intensity)
56+ # soff = CuArray(soff)
57+ # sigma = CuArray(sigma)
58+ # end
59+ # startvals = DType.(ComponentVector(;bg=bg, intensity=intensity, off = soff, args = sigma))
60+ opt = Optim. Options (iterations = 1500 ); #
4961
5062if (false )
5163 G = copy (startvals)
5264 myfg! (1 , G, startvals)
5365
54- myfg2! = get_fg! (pdat[:,:,1 ], gaussian_raw, length (sz); loss= loss_anscombe_pos, bg= 7f0 );
66+ myfg2! = get_fg! (pdat[:,:,1 ], gaussian_raw, length (sz); loss= loss_anscombe_pos, bg= 0.1f0 );
5567 sv = ComponentVector {Float32} (bg= startvals. bg[1 ], intensity= startvals. intensity[1 ], off = startvals. off[:,1 ], args = startvals. args[:,1 ])
5668 G2 = copy (sv)
5769 myfg2! (1 , G2, sv)
5870 G2
5971end
6072
6173# and perform the fit
62- @time reso = Optim. optimize (odo, startvals, Optim. LBFGS (), opt);
74+ svb = copy (startvals)
75+ # svb.args = svb.args .* 1.2f0
76+ odo = OnceDifferentiable (Optim. NLSolversBase. only_fg! (myfg!), svb);
77+ @time reso = Optim. optimize (odo, svb, Optim. LBFGS (), opt);
78+ # 14 sec, CUDA: 2.5 sec
6379# 2 sec, 5k fits/s (44.25 k allocations: 1.546 GiB, 7.35% gc time)
6480# with intensity variations: 26.833106 seconds (532.47 k allocations: 20.251 GiB, 5.99% gc time)
6581# in Cuda:
6682reso. f_calls # 61 # 1766 für 10_000 fits, 155, 2.2 sec for 10_000 fits with all entries being vectors
6783reso. minimum #
68- @vt pdat gaussian_vec (sz, startvals) gaussian_vec (sz, reso. minimizer)
84+ @vt pdat dat (gaussian_vec (sz, startvals).- dat) (gaussian_vec (sz, reso. minimizer).- dat)
85+
86+ success = sum (abs .(collect (startvals. off) .- vec_true. off), dims= 1 ) .< 0.5
87+ success = success .&& sum (abs .(collect (reso. minimizer. off) .- vec_true. off), dims= 1 ) .< 0.5
88+ sum (.! success)
89+ # findfirst(.!success)
90+ @vt collect (dat)[:,:,.! success[:]] collect (pdat)[:,:,.! success[:]] collect (gaussian_vec (sz, startvals))[:,:,.! success[:]] collect (gaussian_vec (sz, reso. minimizer))[:,:,.! success[:]]
91+
92+ ff = findfirst (.! success)[2 ]
93+ sv = ComponentVector (off= startvals. off[:,ff], bg = startvals. bg[:,ff], intensity= startvals. intensity[:,ff], args = startvals. args[:,ff])
94+ sdat = dat[:,:,ff]
95+ afg! = get_fg! (sdat, gaussian_raw, length (sz); loss= loss_gaussian); # loss_poisson_pos
96+ odo = OnceDifferentiable (Optim. NLSolversBase. only_fg! (afg!), sv);
97+ @time reso = Optim. optimize (odo, sv, Optim. LBFGS (), opt);
98+ @vt sdat gaussian_vec (sz, sv) gaussian_vec (sz, reso. minimizer)
99+
100+ trueoff = vec_true. off[:,collect (success[:])]
101+ startoff = collect (startvals. off[:,success[:]])
102+ minoff = collect (reso. minimizer. off[:,success[:]])
103+ sum (abs2 .(startoff .- trueoff), dims= 2 ) # 0 failed, 68.29712, 42.612137
104+ sum (abs2 .(minoff .- trueoff), dims= 2 ) # 21 failed, 57.92457, 33.990776 # Anscombe: 5 failed, 58.806953, 34.21795
105+ @vt abs .(startoff .- trueoff) abs .(minoff .- trueoff)
106+
107+ sum (abs2 .(collect (startvals. intensity) .- vec_true. intensity))
108+ sum (abs2 .(collect (reso. minimizer. intensity) .- vec_true. intensity))
109+ sum (abs2 .(collect (startvals. bg) .- vec_true. bg))
110+ sum (abs2 .(collect (reso. minimizer. bg) .- vec_true. bg))
111+ sum (abs2 .(collect (startvals. args) .- vec_true. args), dims= 2 )
112+ sum (abs2 .(collect (reso. minimizer. args) .- vec_true. args), dims= 2 )
69113
70114odo = OnceDifferentiable (Optim. NLSolversBase. only_fg! (myfg!), startvals);
71115if isa (dat, CuArray)
97141# 5 ms (39192 allocations: 4.35 MiB)
98142
99143# @btime Optim.optimize($loss, $off_start, $sigma_start, LBFGS(); autodiff = :forward); # 1.000 ms (10001 allocations: 1.53 MiB)
144+
145+ # here is the LsqFit example from https://github.com/JuliaNLSolvers/LsqFit.jl
146+ using LsqFit
147+
148+ x = collect (range (0 , stop= 200 , length= 201 ))
149+ y = collect (range (0 , stop= 200 , length= 201 ))
150+
151+ xy = hcat (x, y)
152+
153+ function twoD_Gaussian (xy, p)
154+ amplitude, xo, yo, sigma_x, sigma_y, theta, offset = p
155+ a = (cos (theta)^ 2 )/ (2 * sigma_x^ 2 ) + (sin (theta)^ 2 )/ (2 * sigma_y^ 2 )
156+ b = - (sin (2 * theta))/ (4 * sigma_x^ 2 ) + (sin (2 * theta))/ (4 * sigma_y^ 2 )
157+ c = (sin (theta)^ 2 )/ (2 * sigma_x^ 2 ) + (cos (theta)^ 2 )/ (2 * sigma_y^ 2 )
158+
159+ # creating linear meshgrid from xy
160+ x = xy[:, 1 ]
161+ y = xy[:, 2 ]
162+ g = offset .+ amplitude .* exp .( - (a.* ((x .- xo). ^ 2 ) + 2 .* b .* (x .- xo) .* (y .- yo) + c * ((y .- yo). ^ 2 )))
163+ return g[:]
164+ end
165+
166+ p0 = Float64 .([3 , 100 , 100 , 20 , 40 , 0 , 10 ])
167+ data = twoD_Gaussian (xy, p0)
168+
169+ # Noisy data
170+ data_noisy = data + 0.2 * randn (size (data))
171+
172+ fit = LsqFit. curve_fit (twoD_Gaussian, xy, data_noisy, p0)
0 commit comments