适合python中的数据的多个高斯

时间:2014-11-13 05:57:18

标签: python numpy scipy

我只是想知道是否有一种简单的方法可以实现高斯/洛伦兹拟合10个峰值并提取fwhm,并确定fwhm在x值上的位置。复杂的方法是分离峰值并拟合数据并提取fwhm。

数据为[https://drive.google.com/file/d/0B6sUnnbyNGuOT2RZb2UwYXU4dlE/view?usp=sharing]

任何建议都非常感谢。谢谢。

from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt('data.txt', delimiter=',')
x, y = data

plt.plot(x,y)
plt.show()

def func(x, *params):
    y = np.zeros_like(x)
    print len(params)
    for i in range(0, len(params), 3):
        ctr = params[i]
        amp = params[i+1]
        wid = params[i+2]
        y = y + amp * np.exp( -((x - ctr)/wid)**2)



guess = [0, 60000, 80, 1000, 60000, 80]
for i in range(12):
    guess += [60+80*i, 46000, 25]


popt, pcov = curve_fit(func, x, y, p0=guess)
print popt
fit = func(x, *popt)

plt.plot(x, y)
plt.plot(x, fit , 'r-')
plt.show()



Traceback (most recent call last):
File "C:\Users\test.py", line 33, in <module>
popt, pcov = curve_fit(func, x, y, p0=guess)
File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 533, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kw)
File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 368, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 19, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "C:\Python27\lib\site-packages\scipy\optimize\minpack.py", line 444, in    _ general_function
return function(xdata, *params) - ydata
TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'

3 个答案:

答案 0 :(得分:15)

这需要非线性拟合。一个很好的工具是scipy的curve_fit函数。

要使用curve_fit,我们需要一个模型函数,将其称为func,将x和我们的(猜测的)参数作为参数,并返回{{1}的相应值}。作为我们的模型,我们使用高斯的总和:

y

现在,让我们为我们的参数创建一个初始猜测。这个猜测从from scipy.optimize import curve_fit import numpy as np def func(x, *params): y = np.zeros_like(x) for i in range(0, len(params), 3): ctr = params[i] amp = params[i+1] wid = params[i+2] y = y + amp * np.exp( -((x - ctr)/wid)**2) return y x=0处的峰值开始,幅度为60,000,电子折叠宽度为80.然后,我们在x=1,000处添加候选峰值,幅度为46,000,宽度为25:

x=60, 140, 220, ...

现在,我们已准备好执行合适:

guess = [0, 60000, 80, 1000, 60000, 80]
for i in range(12):
    guess += [60+80*i, 46000, 25]

为了了解我们的表现如何,让我们将实际的popt, pcov = curve_fit(func, x, y, p0=guess) fit = func(x, *popt) 值(纯黑色曲线)和y(红色虚线曲线)绘制成fit

enter image description here

正如你所看到的,适合度相当不错。

完整的工作代码

x

答案 1 :(得分:0)

@ john1024的答案很好,但是需要手动过程才能生成初始猜测。这是一种自动开始猜测的简单方法。将john1024的相关3行代码替换为以下内容:

    import scipy.signal
    i_pk = scipy.signal.find_peaks_cwt(y, widths=range(3,len(x)//Npks))
    DX = (np.max(x)-np.min(x))/float(Npks) # starting guess for component width
    guess = np.ravel([[x[i], y[i], DX] for i in i_pk]) # starting guess for (x, amp, width) for each component

答案 2 :(得分:-1)

恕我直言,始终建议在此类问题中绘制残差(数据 - 模型)。您还需要查看拟合的 ChiSq。