如何在 Python 中使用 Split Pearson 7 函数进行拟合?

How to do a fit with a Split Pearson 7 function in Python?

我有一个不对称峰,我想使用带有 lmfit 的拆分 Pearson 7 (SP7) 函数来拟合。 首先定义了SP7函数,然后我用lmfit重新调用了它,但最后出现了这个错误:ValueError: varargs '*p' is not supported。为什么?

def polynomial(x, *p):
    poly = Polynomial(p)
    y = poly(x)
    return y

def pearson7(x, *p):
    x0, IM, H, m = p
    y = IM / (1+4*(2**(1/m)-1)*(x-x0)**2/H**2)**m
    return y

def splitpearson7(x, *p):
    x0, IM, Hl, ml, Hr, mr = p
    pl = [x0, IM, Hl, ml]
    pr = [x0, IM, Hr, mr]
    y = pearson7(x, *pl)*np.heaviside(x-x0, 0.5) + pearson7(x, *pr)*np.heaviside(x0-x, 0.5)
    return y

def splitpearson7_backg(x, *p):
    """
    Split PearsonVII distribution with linear background (8 parameters)
    * background y = A + Bx
    """
    y = splitpearson7(x, *p[0:6]) + polynomial(x, *p[6:8])
    return y ```

first_params_fit=[0, np.max(y), 0.05, 0.5, 0.05, 0.5, 10, 0.3]
mod = Model(splitpearson7_backg)
pars = mod.make_params(first_params_fit)
result = mod.fit(y, pars, x=x)
print(result.fit_report()) ```
ValueError: varargs '*p' is not supported.

确实如此。

Why?

嗯,部分原因是它定义函数的方式很糟糕,部分原因是它打破了 lmfit.Model 的概念,无法确定 和名称 模型函数的参数。简而言之:可读性很重要。帮阅读您代码的人(包括未来的您)一个忙,编写可读代码。

你的 splitpearson7 函数参数的意义和顺序都丢失了。当然,顺序仍然很关键,但没有以任何方式描述。它甚至没有说有多少参数。相反,如果您使用

def splitpearson7(x, x0, IM, Hl, ml, Hr, mr):
    pl = [x0, IM, Hl, ml]
    pr = [x0, IM, Hr, mr]
    y = pearson7(x, *pl)*np.heaviside(x-x0, 0.5) + pearson7(x, *pr)*np.heaviside(x0-x, 0.5)
    return y

然后你可以用

创建一个lmfit.Model
 sp7_model = lmfit.Model(splitpearson7)

并命名参数:

 params = sp7_model.make_params(x0=0, IM=1, Hl=2, ml=3.3, Hr=2.1, mr=5)

事实上,您的 pearson7 函数也可以使用命名参数。或者,您可以使用 lmfit:

内置的版本
from lmfit.lineshapes import pearson7
def splitpearson7(x, center, amplitude, sigma_left, m_left, sigma_right, m_right):
      left = heaviside(x-center, 0.5)*pearson7(x, amplitude, center, sigma_left, m_left) 
      right = heaviside(center-x, 0.5)*pearson7(x, amplitude, center, sigma_right, m_right) 
      return left+right

另外,一般是"the lmfit Model way"不建有背景加功能的模型,而是做复合模型,如

from numpy import heaviside
from lmfit.lineshapes import pearson7
from lmfit.model import Model
from lmfit.models import PolynomialModel

def splitpearson7(x, center, amplitude, sigma_left, m_left, sigma_right, m_right):
    left = heaviside(x-center, 0.5)*pearson7(x, amplitude, center, sigma_left, m_left) 
    right = heaviside(center-x, 0.5)*pearson7(x, amplitude, center, sigma_right, m_right) 
    return left+right

# Note that PolynomialModel(2) will be quadratic with parameters 
# c0, c1, c2, and a form = c0 + c1*x + c2*x*x
mod = Model(splitpearson7) + PolynomialModel(2)
params = mod.make_params(center=0, amplitude=200, 
                         sigma_left=2, m_left=1, 
                         sigma_right=2.2, m_right=1.1, 
                         c0=10, c1=0, c2=0)

这将使更改背景模型变得更加容易。