如何在 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)
这将使更改背景模型变得更加容易。
我有一个不对称峰,我想使用带有 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)
这将使更改背景模型变得更加容易。