简体   繁体   English

高斯的2D拟合将不起作用

[英]2d fit of gaussian will not work

I am trying to fit a 2d data set. 我正在尝试拟合2D数据集。 I can plot it without any problem at all but when I try to fit it I always get the same error message that I do not understand: 我可以完全没有问题地绘制它,但是当我尝试拟合它时,总是会收到我不理解的错误消息:

def twod_Gaussian(x,y,Amp,x0,y0,sigma_x,sigma_y,Offset):
    return Amp*np.exp(-((x-x0)/(2*sigma_x**2)+(y-y0)/(2*sigma_y**2)))+Offset

# get data
filename = '20180503-1455-43_confocal_xy_data.dat'
data = np.genfromtxt(filename, comments='#')
values = open(filename)
val = values.readlines(500)
res = float(val[11][-4:-1])
values.close()
x = [float(i) for i in data[:, 0]]
y = [float(i) for i in data[:, 1]]
count_rate = [float(i) for i in data[:, 3]]



#reshape data
xmax = max(x)
xmin = min(x)
ymax = max(y)
ymin = min(y)
cmax = max(count_rate)
cmin = min(count_rate)
np.percentile(count_rate, 99)
resX = (xmax-xmin)/res
rexY = (ymax-ymin)/res
res2 = len(x)/res
xx = np.array(x).reshape((int(res2), int(res)))
yy = np.array(y).reshape((int(res2), int(res)))



#plot data
count_matrix = np.array(count_rate).reshape((int(res2), int(res)))
fig = plt.figure()
ax = fig.gca(projection='3d')
CS = ax.plot_surface((xx)/1e-6, (yy)/1e-6, count_matrix, cmap='plasma')
plt.ticklabel_format(style='plain', axis='both', scilimits=(0, 0))
ax.set_xlabel(r'X position ($\mathrm{\mu}$m)')
ax.set_ylabel(r'Y position ($\mathrm{\mu}$m)')
fig.colorbar(CS, ax=ax, extend='max', format='%.0e')
plt.show()

#initial guess and trying to fit it
p0=(98e-06,81.5e-06,50000,0.5e-06,0.5e-06,20000)
popt, pcov = curve_fit(twod_Gaussian, x, y, count_rate, p0)

I always get the error message 我总是收到错误消息

ValueError: sigma has incorrect shape. ValueError: sigma形状不正确。

If I change the last line to 如果我将最后一行更改为

popt, pcov = curve_fit(twod_Gaussian, (x, y), count_rate, p0)

I get as error message: 我收到错误消息:

twod_Gaussian() missing 1 required positional argument: 'Offset'

I dont have any idea why the shape should be wrong? 我不知道为什么形状应该是错误的?

First, I believe the problem is that your model function definition has an extra argument because you are using two separate arguments for your two dimensions ( x and y ), instead of the one argument for the independent variable that curve_fit requires. 首先,我认为问题在于模型函数定义有一个额外的参数,因为您对两个维度( xy )使用了两个单独的参数,而不是curve_fit所需的自变量使用了一个参数。 Changing your model function to be 将模型功能更改为

def twod_Gaussian(xy, Amp,x0,y0,sigma_x,sigma_y,Offset):
    x, y = xy
    return Amp*np.exp(-((x-x0)/(2*sigma_x**2)+(y-y0)/(2*sigma_y**2)))+Offset

and then calling curve_fit with 然后调用curve_fit

xy = x, y
popt, pcov = curve_fit(twod_Gaussian, xy, count_rate, p0)

should do what you want. 应该做你想做的。

Second, you might also consider using lmfit ( https://lmfit.github.io/lmfit-py ). 其次,您还可以考虑使用lmfithttps://lmfit.github.io/lmfit-py )。 This library has a slightly higher level interface to curve-fitting, still wrapped around the scipy.optimize solvers. 该库具有稍高一点的曲线拟合接口,仍然围绕scipy.optimize求解器。 For example, it treats parameters as first-class, named objects, and easily supports placing bounds and constraints on parameters outside of the model function. 例如,它将参数视为一流的命名对象,并轻松支持在模型函数之外的参数上放置边界和约束。 For your case, it also supports defining multiple independent variables for a fitting function, not forcing you to assume that only the first argument of the model function is the independent variable, and all others are meant to be variables in the fit. 对于您的情况,它还支持为拟合函数定义多个自变量,而不是强迫您假定仅模型函数的第一个参数是自变量,而所有其他参数都应是拟合中的变量。 With lmfit your problem would look approximately like (I didn't run this because I don't have your data): 使用lmfit时,您的问题大致类似于(我没有运行它,因为我没有您的数据):

from lmfit import Model
def twod_Gaussian(x, y, Amp,x0,y0,sigma_x,sigma_y,Offset):
    return Amp*np.exp(-((x-x0)/(2*sigma_x**2)+(y-y0)/(2*sigma_y**2)))+Offset

# turn your model function into a Model, specifying independent variables
g2model = Model(twod_Gaussian, independent_vars=['x', 'y'])

# create Parameters object -- ordered dict of *named parameters, 
# giving initial values here:
params = g2model.make_params(Amp=98e-6, x0=81e-6, y0=50000., sigma_x=5e-7, sigma_y=5e-7, Offset=20000)

# Note that using names is *way* better than using an ordered list. 
# for example, you may have mixed up the order and really meant:
params = g2model.make_params(x0=98e-6, y0=81e-6, Amp=50000., sigma_x=5e-7, sigma_y=5e-7, Offset=20000)

# you can place bounds on parameters, perhaps as
params['sigma_x'].min = 0
params['sigma_y'].min = 0

# do fit, passing independent vars explicitly
result = g2model.fit(count_rate, params, x=x, y=y)

# print out full report of statistics, best-fit values and stderrs:
print(result.fit_report())

# array of best-fit data == result.best_fit

There are lots more features, described in the docs. 有更多功能,如文档所述。

Finally, to make a 2-D Gaussian with your function, y should be a row-wise array ( x is column-wise). 最后,要使用函数创建二维高斯, y应该是行数组( x是列数组)。 Otherwise your twod_Gaussian() will return a 1-d array of the same length as x and y . 否则,您的twod_Gaussian()将返回与xy长度相同的一维数组。 So, I think you want to add 所以,我想你想补充

y = np.vstack(y)

just after your creation of y from your data array. data数组创建y之后。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM