在python的lmfit中使用Voigt profile拟合数据-巨大错误



我正在尝试将一些RIXS数据与Voigt配置文件(Python中的lmfit)相匹配,并且我以以下方式定义了Voigt配置文件:


def gfunction_norm(x, pos, gwid):
gauss= (1/(gwid*(np.sqrt(2*np.pi))))*(np.exp((-1.0/2)*((((x-pos)/gwid))**2)))
return (gauss-gauss.min())/(gauss.max()-gauss.min())
def lfunction_norm(x,pos,lwid):
lorentz=(0.15915*lwid)/((x-pos)**2+0.25*lwid**2)
return (lorentz-lorentz.min())/(lorentz.max()-lorentz.min())

def voigt(x, pos, gwid, lwid, int):
step=0.005
x2=np.arange(pos-7,pos+7+step,step)
voigt3=np.convolve(gfunction_norm(x2, pos, gwid), lfunction_norm(x2, pos, lwid), mode='same')   
norm=(voigt3-voigt3.min())/(voigt3.max()-voigt3.min()) 
y=np.interp(energy, x2, norm)
return y * int

我使用了这个定义,而不是Python中流行的Voigt配置文件定义:

def voigt(x, alpha, cen, gamma): 
sigma=alpha/np.sqrt(2*np.log(2))
return np.real(wofz((x-cen+1j*gamma)/sigma/np.sqrt(2)))/(sigma*2.51)

因为它让我更清楚地看到峰值的强度等

现在,我有几个9-10个峰的光谱,我正试图用Voigt谱来拟合它们(精确地按照我定义它的方式)。

现在,我有几个问题:

  1. 你认为我的Voigt定义是OK的吗?用卷积代替近似的第二种定义有什么优点?

  2. 由于我的适合度,有时我得到疯狂的大标准差。例如,以下是其中一个峰值的最佳拟合参数:

int8:    0.00986265 +/- 0.00113104 (11.47%) (init = 0.05)
pos8:   -2.57960013 +/- 0.00790640 (0.31%) (init = -2.6)
gwid8:   0.06613237 +/- 0.02558441 (38.69%) (init = 0.1)
lwid8:   1.0909e-04 +/- 1.48706395 (1363160.91%) (init = 0.001)

(强度、位置、高斯宽度和洛伦兹宽度)。这个输出是否意味着这个峰值应该是纯高斯的?

  1. 我注意到,当最佳拟合参数非常小时,通常会发生较大的误差。这是否与lmfit中默认使用的Levenberg-Marquardt算法有关?我应该注意到,即使我使用Voigt配置文件的其他定义(而不仅仅是洛伦兹宽度),有时也会遇到同样的问题。这是代码的一部分(它是一个更大的代码的一部分,它是一个for循环,这意味着我使用相同的初始值多个相似的光谱):
model = Model(final)
result = model.fit(spectra[:,nb_spectra], params, x=energy)
print(result.fit_report())

"final"是我之前定义的许多voigt配置文件的总和。

谢谢!

这似乎是Lmfit的重复或后续,产生了巨大的不确定性-请每个主题使用SO个问题。

你觉得我的Voigt定义没问题吗?用卷积代替近似的第二种定义有什么优点?

你为什么说第二个定义是近似的?从某种意义上说,所有的浮点计算都是近似的,但是scipy.special.wofz中的Faddeeva函数是Voigt剖面的解析解。自己做卷积可能会慢一点,也是一个近似值(在机器精度级别)。

由于您正在使用Lmfit,我建议使用它的VoigtModel,这将使您的工作更轻松:它使用scipy.special.wofz和参数名称,使切换到其他配置文件(例如,GaussianModel)变得容易。

你没有给出一个非常完整的代码示例(作为参考,一个最小的,实际代码的工作版本或多或少期望在SO和强烈推荐),但它可能看起来像

from lmfit.models import VoigtModel
model = VoigtModel(prefix='p1_') + VoigtModel(prefix='p2_') + ...

由于我的适合,有时我得到疯狂的大标准偏差。例如,这些是一个的最佳拟合参数峰:

int8:    0.00986265 +/- 0.00113104 (11.47%) (init = 0.05)
pos8:   -2.57960013 +/- 0.00790640 (0.31%) (init = -2.6)
gwid8:   0.06613237 +/- 0.02558441 (38.69%) (init = 0.1)
lwid8:   1.0909e-04 +/- 1.48706395 (1363160.91%) (init = 0.001) 

(强度、位置、高斯宽度和洛伦兹宽度)。这个输出是否意味着这个峰值应该是纯高斯的?

首先,这可能不是一个"疯狂的大"标准偏差,它取决于数据和拟合的其余部分。也许int8的值非常非常小,并且与其他峰值严重重叠——它可能与其他变量高度相关。但是,这很可能意味着峰值更像高斯。

由于您正在分析x射线散射数据,因此使用Voigt函数可能部分符合以下想法(断言,假设,期望?),即材料响应将给出高斯分布,而仪器(包括x射线源)将给出洛伦兹展宽。这表明不同峰的洛伦兹宽度可能是相同的,或者可能被参数化为入射和散射波长或q值的简单函数。也就是说,您可能能够(并且可能更好)约束洛伦兹宽度的值(我认为您的lwidlmfit.models.VoigtModel中的gamma)都是相同的。

相关内容

  • 没有找到相关文章

最新更新