将高斯拟合到 python 中的吸收线

Fitting gaussian to absorbtion line in python

我正在尝试对我的数据进行高斯拟合,这些数据是在非常窄的光谱 window 中获取的。我们得到了大约 2 个连续体点,然后大约有 10-11 个点是直线的一部分。我想应该还是可以拟合的,但是每次曲线拟合都失败,我也不知道为什么。

当 运行 我得到 RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 800.

代码和数据:

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

x = np.arange(13)
xx = np.arange(130)/13.
y = np.array([19699.959 , 21679.445 , 21143.195 , 20602.875 , 16246.769 ,
        11635.25  ,  8602.465 ,  7035.493 ,  6697.0337,  6510.092 ,
        7717.772 , 12270.446 , 16807.81  ])
# weighted arithmetic mean (corrected - check the section below)
mean = sum(x * y) / sum(y)
sigma = np.sqrt(sum(y * (x - mean)**2) / sum(y))

def Gauss(x, a, x0, sigma):
    return a * np.exp(-(x - x0)**2 / (2 * sigma**2))


popt,pcov = curve_fit(Gauss, x, y, p0=[max(y), mean, sigma])

plt.plot(x, y, 'b+:', label='data')
plt.plot(xx, Gauss(xx, *popt), 'r-', label='fit')

plt.legend()
plt.show()

正如错误所说,寻找最优值的过程没有收敛。如果你真的认为你拥有的东西可以用高斯曲线拟合,那么这通常意味着你的起点不好。

你如何给出起点可能是个问题,特别是你如何提供 sigma,因为在位置 11、12 和 13 你有可能是另一个信号的开始。无论如何,这不是这次最大的问题,而是您忘记为高斯函数添加偏移量

#             ----> new parameter in signature
#             |
def Gauss(x, y0, a, x0, sigma):
    return y0 + a * np.exp(-(x - x0)**2 / (2 * sigma**2))
#           |
#           -------> adding and offset

然后,你可以决定如何提供一个偏移量的起点,但是从目测来看,我确实设置了5000

popt, pcov = curve_fit(Gauss, x, y, p0=[5000, max(y), mean, sigma])

这样做,我就健康了。但是,由于最后三个数据点,这不是一个很好的数据。

如果避免这些值,拟合度会显着提高。

编辑:

正如评论中指出的那样,高斯分布以 8 为中心向下看(愚蠢的我,这是一条吸收线)。

在这种情况下,偏移量应位于最大值 ~22000 左右,然后振幅参数应为负值 ~ -(max(y)-min(y)) ~ -16000。

另外,最好将xx改成如下

xx = np.linspace(0, 13, 100)

xx = np.arange(0, 13, 0.05)

哪个会给

并检查 popt 你基本上得到了我 mentioned/estimated 的值,只需查看 ~(2180, -16000, 8) 和 2.7 的西格玛,这是我唯一没有的对如何估算有一个直接的感觉。

我的猜测是,您实际上应该拟合高斯和 Cauchy/Lorentz 线形或更好的 Voigt lineshape 的混合,以考虑实验范围的扩大。