本文介绍了将高斯拟合到python中的吸收线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将高斯拟合为我的数据,该数据是在非常狭窄的光谱窗口中拍摄的。我们得到了大约2个连续体点,然后得到大约10-11个连续体点。我认为应该仍然可以拟合它,但是每次曲线拟合都会失败,而且我不确定为什么。

I am trying to fit a gaussian to my data which is taken in a pretty narrow spectral window. We got about 2 points of continuum and then about 10-11 that are part of the line. It should still be possible to fit it I think, but the curve fit is failing each time, and I am not sure why.

运行时,我得到 RuntimeError:找不到最佳参数:对函数的调用次数已达到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()


推荐答案

如错误所述,找到最佳值的过程并不收敛。如果您真的认为自己所拥有的可以拟合高斯曲线,那么通常这意味着您有一个不好的起点。

As the error says, the procedure to find the optimal values doesn't converge. If you really think that what you have can be fitted with a Gaussian curve, then this in general means you have a bad starting point.

您如何给出起点这一点可能是一个问题,特别是在位置11、12和13处您可能提供另一个信号的情况下,如何提供sigma。无论如何,这不是最大的问题,但是您忘记为高斯函数添加偏移量了

How you're giving the starting point could have been an issue, particularly with how you provide sigma given that at positions 11, 12 and 13 you have what could be the onset of another signal. Anyhow, that's not the biggest issue this time, but the fact that you forgot to add an offset to the gaussian function

#             ----> 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

Then, you can decide how to provide a starting point for the offset, but by eye, I did set 5000

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

这样做,我很合适。但是,由于最后三个数据点,它并不是一个很好的数据点。

Doing that, I get a fit. But, due to the last three data points, it's not a very nice one.

如果避免使用这些值,则适合

If you avoid those values, the fit improves significantly.

如评论中所示,高斯中心位于向下看的大约8点(对不起,这是一条吸收线)。

As indicated in the comments, the Gaussian is centered at about 8 looking downwards (silly me, it was an absorption line).

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

In such a case, the offset should be located at about the maximum ~22000 and then the parameter for the amplitude should be negative ~ -(max(y)-min(y)) ~ -16000.

此外,最好将 xx 更改为如下

And as an addition, better change xx to be as follows

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

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

哪个会给

并检查 popt ,您基本上得到了这些值我只是通过查看σ为2.7的图〜(2180,-16000,8)来提及/估计的,这是我对如何估计没有立即感觉的唯一答案。

and checking popt you get basically the values I mentioned/estimated by just looking at the plot ~(2180, -16000, 8) with a sigma of 2.7 which was the only one I don't have an immediate feeling on how to estimate.

我的猜测是,您实际上应该拟合高斯和柯西/洛伦兹线条的混合体,甚至更好地是,以说明实验性拓宽。

My guess is that you should actually be fitting a mixture of Gauss and a Cauchy/Lorentz lineshape or even better a Voigt lineshape, to account for experimental broadening.

这篇关于将高斯拟合到python中的吸收线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 00:31