2017-10-11 131 views
0

我正在尝试使用LMFIT库进行多洛伦兹拟合,但它不工作,我甚至明白我所做的是完全错误的语法,但我没有任何新的想法。使用LMFIT为DataSet拟合多峰函数

我的问题是这样的:我有一个很长的光谱,有多组 峰,但是这些组中峰的数目并不是恒定的,所以有时候我只会有1个峰,但有时我可能有8个峰 甚至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) 

我已经开始试图让一个返回 多洛伦兹的通用功能,但我在如何使这项工作挣扎......

我m也发送x,y数组的数据。

DataSet for x and y

This is what the DataSet of x and y looks like.

回答

1

您应该能够利用内置的模型,并使用前缀作为manual描述。此外,最近有关于mailinglist上非常类似的话题的讨论。

你可以做一些事情,如下所示。它不适合最后一个峰值,但你可能会用起始值等来摆弄一下。此外,由于您的基线并不完全平坦,所以当您使用LinearModel代替ConstantModel时可能会有所改善,但我没有尝试过。

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() 
+0

非常感谢。 如果好奇,我使用peakutils.baseline模块在该区间中创建平均基线。它使n阶多项式拟合基线(通常我使用n = 2)。 –