scipy.integrate Pseudo-Voigt函数,积分变为0

时间:2016-06-06 12:04:52

标签: python numpy scipy data-fitting integrate

我正在使用Scipy,Numpy和Matplotlib编写一个脚本,用于在Python中将峰形拟合到光谱数据。它可以同时适应多个峰值。峰值轮廓(现在)是Pseudo-Voigt,它是高斯(aka Normal)和Lorentzian(aka Cauchy)分布的线性组合。

我有一个选项开关,我可以让软件优化高斯和洛伦兹的贡献或将其设置为固定值(其中0 =纯高斯和1 =纯洛伦兹)。按预期工作,绘制拟合的峰值看起来像预期的那样。当我尝试使用scipy.integrate计算峰的积分时,问题就开始了。

到目前为止,我尝试了scipy.integrate.quad,scipy.integrate.quadrature,scipy.integrate.fixed_quad和scipy.integrate.romberg。当峰值为纯高斯时,积分变为类似1.73476E-34(并非总是相同的数字),即使对于明显具有比非纯高斯相邻的峰值更大的区域的峰值,但返回有序的有限积分10到1000.这是相关部分的样子:

# Function defining the peak functions for plotting and integration
# WavNr: Wave number, the x-axis over which shall be integrated
# Pos: Peak center position
# Amp: Amplitude of the peak
# GammaL: Gamma parameter of the Lorentzian distribution
# FracL: Fraction of Lorentzian distribution
def PseudoVoigtFunction(WavNr, Pos, Amp, GammaL, FracL):
    SigmaG = GammaL / np.sqrt(2*np.log(2)) # Calculate the sigma parameter  for the Gaussian distribution from GammaL (coupled in Pseudo-Voigt)
    LorentzPart = Amp * (GammaL**2 / ((WavNr - Pos)**2 + GammaL**2)) # Lorentzian distribution
    GaussPart = Amp * np.exp( -((WavNr - Pos)/SigmaG)**2) # Gaussian distribution
    Fit = FracL * LorentzPart + (1 - FracL) * GaussPart # Linear combination of the two parts (or distributions)
    return Fit

这是由情节函数通过:

调用的
Fit = PseudoVoigtFunction(WavNr, Pos, Amp, GammaL, FracL)

工作正常。它也由集成商通过以下方式调用:

PeakArea, PeakAreaError = integrate.quad(PseudoVoigtFunction, -np.inf, np.inf, args=(Pos, Amp, GammaL, FracL))

或scipy.integrate提供的任何其他变体,都具有相同的结果,如果FracL = 0,则PeakArea =(几乎)0。

我确定问题只是因为我太愚蠢而无法弄清楚scipy.integrate如何使用比我能找到的示例更复杂的功能。希望有人看到我不知道的明显错误。两天搜索stackoverflow和Scipy Docs并重新排列和完全重写我的代码让我无处可去。我怀疑scipy.integrate中的args在某种程度上与问题有关,但对于我能找到的所有内容,它们似乎都是正确排列的。

提前致谢, OS

1 个答案:

答案 0 :(得分:0)

我确信你知道,间隔(-inf,inf)非常大。 :)高斯衰减非常快,所以除了峰值附近的区间,高斯在数值上与0无法区分。我怀疑quad根本没有看到你的峰值。

一个简单的解决方法是将积分分成两个区间,( - inf,pos)和(pos,inf)。 (你的函数关于Pos是对称的,所以你真的只需要两倍的积分(-inf,pos)。)

这是一个例子。我不知道这些参数值是否接近您使用的典型值,但它们说明了这一点。

In [259]: pos = 1500.0

In [260]: amp = 4.0

In [261]: gammal = 0.5

In [262]: fracl = 0  # Pure Gaussian

quad认为积分是0:

In [263]: quad(PseudoVoigtFunction, -np.inf, np.inf, args=(pos, amp, gammal, fracl))
Out[263]: (0.0, 0.0)

相反,整合(-inf,pos)和(pos,inf):

In [264]: quad(PseudoVoigtFunction, -np.inf, pos, args=(pos, amp, gammal, fracl))
Out[264]: (1.5053836955785238, 3.616268258191726e-11)

In [265]: quad(PseudoVoigtFunction, pos, np.inf, args=(pos, amp, gammal, fracl))
Out[265]: (1.5053836955785238, 3.616268258191726e-11)

因此(-inf,inf)的积分大约为3.010767。