I have some 2D data, specifically scanned X-ray films. These have measurements of overlapping point source exposures. Example of data: https://i.stack.imgur.com/oawlU.png
I want to find the peak positions, by fitting a sum of 2D gaussians to the data. I've tried several other methods with some success, including a "star search" method that locates the global maximum, fits a Gaussian and subtracts it. Looping this finds all of the peaks reasonably well, but it's unstable and not very accurate. I would like to use the star search output as a first guess for a fit, but I'm having trouble, implementing scipy.optimize.curve_fit
.
I've made a function twoD_envelope
that creates the 2D envelope of all the Gaussians found from the star search. This produces this output: https://i.stack.imgur.com/4KnpG.png
I was under the impression that I could use this to as an initial guess in curve_fit
, however I get the following TypeError
:
TypeError: twoD_envelope() takes 4 positional arguments but 358802 were given
358802 is 1 more than size of the data, which is a huge clue, but I can't work out what the problem is! I'm a physicist with "pragmatic" coding knowledge, so any input is very much appreciated.
The code is below.
def twoD_envelope(npoints, xls, yls, pars):
envl = copy.copy(sq_image)
envl[:] = 0
for n in range(0,npoints):
height, cx, cy, width_x, width_y = pars[n]
FWHM = 0.5*(width_x+width_y)
g=makeGaussian(shape(sq_image)[0],fwhm=FWHM,center=[cx+xls[n],cy+yls[n]])
envl = envl + g
return envl.ravel()
# Create x and y indices
x = np.linspace(0, np.size(sq_image[0]), np.size(sq_image[0])+1)
y = np.linspace(0, np.size(sq_image[1]), np.size(sq_image[1])+1)
x, y = np.meshgrid(x, y)
coords = [x,y]
data = sq_image
initial_guess = twoD_envelope(9,xls,yls,pars)
pars_opt, pars_cov = opt.curve_fit(twoD_envelope, coords, data, p0=initial_guess)
(sq_image
is the data, an ndarray
with shape (599,599)
)
(pars, xls, yxl
= lists of Gaussian fit parameters from star search)
(makeGaussian
is a function defined elsewhere)