python中lmfit库的多峰曲线拟合

python中lmfit库的多峰曲线拟合,python,python-3.x,curve-fitting,data-fitting,lmfit,Python,Python 3.x,Curve Fitting,Data Fitting,Lmfit,第一列是x值,第二列是y值,第三列是y-error。我想拟合数据。我遵循的示例来自,我的代码是- import matplotlib.pyplot as plt import numpy as np from lmfit.models import ExponentialModel, GaussianModel file='sample-data.txt' dat = np.loadtxt(file) x = dat[:, 0] y = dat[:, 1] exp_mod = Exp

第一列是x值,第二列是y值,第三列是y-error。我想拟合数据。我遵循的示例来自,我的代码是-

import matplotlib.pyplot as plt
import numpy as np

from lmfit.models import ExponentialModel, GaussianModel


file='sample-data.txt'
dat = np.loadtxt(file)
x = dat[:, 0]
y = dat[:, 1]



exp_mod = ExponentialModel(prefix='exp_')
pars = exp_mod.guess(y, x=x)

gauss1 = GaussianModel(prefix='g1_')
pars.update(gauss1.make_params())

pars['g1_center'].set(value=105000, min=75000, max=125000)
pars['g1_sigma'].set(value=150000, min=30000)
pars['g1_amplitude'].set(value=2000000, min=100000)

gauss2 = GaussianModel(prefix='g2_')
pars.update(gauss2.make_params())

pars['g2_center'].set(value=155000, min=125000, max=175000)
pars['g2_sigma'].set(value=150000, min=30000)
pars['g2_amplitude'].set(value=2000000, min=100000)

mod = gauss1 + gauss2 + exp_mod

init = mod.eval(pars, x=x)
out = mod.fit(y, pars, x=x)

print(out.fit_report(min_correl=0.5))

fig, axes = plt.subplots(1, 2, figsize=(12.8, 4.8))
axes[0].plot(x, y, 'b')
axes[0].plot(x, init, 'k--', label='initial fit')
axes[0].plot(x, out.best_fit, 'r-', label='best fit')
axes[0].legend(loc='best')

comps = out.eval_components(x=x)
axes[1].plot(x, y, 'b')
axes[1].plot(x, comps['g1_'], 'g--', label='Gaussian component 1')
axes[1].plot(x, comps['g2_'], 'm--', label='Gaussian component 2')
axes[1].plot(x, comps['exp_'], 'k--', label='Exponential component')
axes[1].legend(loc='best')

plt.show()
该代码给出了以下曲线图(拟合不起作用)-

我期待着这样的事情-

  • 有人能帮我把数据拟合到绘图中吗
  • 在该值中,手动定义了中心、σ和振幅的最小值、最大值。有没有办法从数据文件中获取/计算这些值
  • 更新

    我试着在评论中使用@mikuszefski的建议。但它也能像图中显示的那样拾取所有的小峰值(噪音)。

    有没有办法只为较大的峰值选择值?

    您确实必须(“必须”、“必须”、“在任何情况下都必须”、“绝对”)为所有参数提供合理、有限和合理的初始值

    当你说

    pars['g1_center'].set(value=105000, min=75000, max=125000)
    pars['g1_sigma'].set(value=150000, min=30000)
    pars['g1_amplitude'].set(value=2000000, min=100000)
    
    gauss2 = GaussianModel(prefix='g2_')
    pars.update(gauss2.make_params())
    
    pars['g2_center'].set(value=155000, min=125000, max=175000)
    pars['g2_sigma'].set(value=150000, min=30000)
    pars['g2_amplitude'].set(value=2000000, min=100000)
    
    您(字面意思是“字面意思”)告诉程序高斯#1应该以105000的中心值开始,并且在任何情况下都不能超过[75000,125000]

    您提供的数据和曲线图显示,您感兴趣的两个峰值出现在
    x
    值约为1.4和1.5

    所以,中心的值约为1,您告诉它该值约为10^5,不能低于75000。在这些限制条件下,这是最合适的。程序运行没有错误或问题,你得到了你想要的东西

    同样,对于非线性最小二乘问题和曲线拟合,初始值总是很重要的。在任何情况下,它们都是无关紧要的

    也就是说,使用mikuszefski建议的峰值查找算法是一个不错的选择


    旁白:边界应主要用于约束逻辑/物理。例如,可以合理地说振幅应该是正的。一般来说,高斯(或者,可能是你的数据)并没有内在的要求质心值74999是非感官的。因此,不要从这样的界限开始。开始时不要限制,尽可能简单。只有在需要的时候才添加这种复杂性。

    尝试使用pythons获取起始参数。@mikuszefski,谢谢你的建议。但是发现_峰值也会拾取噪声值(参见更新)。是否有办法仅获取较大峰值的值?请尝试使用
    高度
    和/或
    阈值
    kwarg。谢谢你的解释。现在的问题是,我必须处理另外50个类似的数据集,每个数据集可能有不同的中心/峰值。为每一个提供这些值需要很长时间。有没有办法让代码从数据集中理解这些值?当你说“需要很长时间”时,你的意思是“与得到明显没有意义的结果相比”?因为,不,可能不会。质心的猜测不需要很好,只需要“在范围内”。如果你有两个明显重叠的峰(嗯…),你可能需要注意保持它们分开。但是,从“峰值查找可以自动进行吗?”,上面的评论已经暗示了如何做到这一点:查看
    scipy.signal.find\u peaks
    和/或
    scipy.signal.find\u peaks\u cwt