使用LMFIT将多峰函数拟合到数据集 [英] Fitting a multi-peak function to a DataSet using LMFIT
问题描述
我正在尝试使用LMFIT库进行多洛伦兹拟合, 但它不起作用,我什至理解我的语法 完全是错误的,但是我没有任何新想法.
I'm trying to make a multi-lorentzian fitting using the LMFIT library, but it's not working and I even understand that the syntax of what I made is completelly wrong, but I don't have any new ideas.
我的问题是:我的光谱很长,有多套 峰,但是在这些组中峰的数量不是恒定的,因此 有时我只有1个高峰,但有时我可能有8个高峰 甚至20.
My problem is this: I have a very long spectra with multiple sets of peaks, but the number of peaks is not constant in these sets, so sometimes I will have just 1 peak, but sometimes I might have 8 or even 20.
#function definition:
def Lorentzian(x, amp, cen, wid, n):
f = 0
for i in range( int(n) ):
"lorentzian function: wid = half-width at half-max"
f += (amp[i]/(1 + ((x-cen[i])/wid[i])**2))
return f
#library import and model definition:
import lmfit as lf
lmodel = lf.Model(Lorentzian)
#The initial parameters for the model:
peaks_in_interval = np.array([2378, 2493, 2525, 2630, 2769])
number_of_peaks = len(peaks_in_interval)
amplitude = width = np.zeros( number_of_peaks ) + 1
center = x[peaks_in_interval]
params = lmodel.make_params(x = x, amp = amplitude, cen = center, wid = width, n = number_of_peaks)
#This is the line that doesn't work:
result = lmodel.fit( y, params, x = x )
我已经开始尝试创建一个通用函数,该函数返回一个 多洛伦兹式的,但我在如何使该作品中苦苦挣扎...
I've started trying to make a generic function that returns a multi-Lorentzian, but I'm struggling in how to make that work...
我也在发送x,y数组的数据.
I'm also sending the data for x, y arrays.
推荐答案
您应该能够使用内置模型和前缀,如邮件列表中最近有一个关于非常相似主题的讨论. .
You should be able to make use of the built-in models and using prefixes as described in the manual. In addition, there was a recent discussion about a very similar topic on the mailinglist.
您可以执行以下操作.它还不能很好地适应最后一个峰值,但是您可能可以在起始值等方面进行一些调整.而且,由于您的基线并不完全平坦,使用LinearModel
而不是ConstantModel
可能会有所改善,但是我没有尝试过.
You can do something as shown below. It doesn't fit the last peak very well yet, but you can probably fiddle around a bit with the starting values and such. Moreover, since your baseline isn't completely flat it might improve when you use a LinearModel
insteadd of a ConstantModel
, but I haven't tried.
from lmfit.models import LorentzianModel, ConstantModel
import numpy as np
import matplotlib.pyplot as plt
x, y = np.loadtxt('Peaks.txt', unpack=True)
peaks_in_interval = np.array([43, 159, 191, 296, 435, 544])
number_of_peaks = len(peaks_in_interval)
amplitude = y[peaks_in_interval] / 5
width = np.zeros(number_of_peaks) + 0.1
center = x[peaks_in_interval]
def make_model(num):
pref = "f{0}_".format(num)
model = LorentzianModel(prefix = pref)
model.set_param_hint(pref+'amplitude', value=amplitude[num], min=0, max=5*amplitude[num])
model.set_param_hint(pref+'center', value=center[num], min=center[num]-0.5, max=center[num]+0.5)
model.set_param_hint(pref+'sigma', value=width[num], min=0, max=2)
return model
mod = None
for i in range(len(peaks_in_interval)):
this_mod = make_model(i)
if mod is None:
mod = this_mod
else:
mod = mod + this_mod
offset = ConstantModel()
offset.set_param_hint('c', value=np.average(y[-75:]))
mod = mod + offset
out=mod.fit(y, x=x, method='nelder')
plt.interactive(True)
print(out.fit_report())
plt.plot(x, y)
plt.plot(x, out.best_fit, label='best fit')
plt.plot(x, out.init_fit, 'r--', label='fit with initial values')
plt.show()
这篇关于使用LMFIT将多峰函数拟合到数据集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!