Builtin Fitting Models in the models
module¶
Lmfit provides several builtin fitting models in the models
module.
These predefined models each subclass from the Model
class of the
previous chapter and wrap relatively wellknown functional forms, such as
Gaussians, Lorentzian, and Exponentials that are used in a wide range of
scientific domains. In fact, all the models are based on simple, plain
Python functions defined in the lineshapes
module. In addition to
wrapping a function into a Model
, these models also provide a
guess()
method that is intended to give a reasonable
set of starting values from a data array that closely approximates the
data to be fit.
As shown in the previous chapter, a key feature of the Model
class
is that models can easily be combined to give a composite
CompositeModel
. Thus, while some of the models listed here may
seem pretty trivial (notably, ConstantModel
and LinearModel
),
the main point of having these is to be able to use them in composite models. For
example, a Lorentzian plus a linear background might be represented as:
>>> from lmfit.models import LinearModel, LorentzianModel
>>> peak = LorentzianModel()
>>> background = LinearModel()
>>> model = peak + background
All the models listed below are one dimensional, with an independent
variable named x
. Many of these models represent a function with a
distinct peak, and so share common features. To maintain uniformity,
common parameter names are used whenever possible. Thus, most models have
a parameter called amplitude
that represents the overall height (or
area of) a peak or function, a center
parameter that represents a peak
centroid position, and a sigma
parameter that gives a characteristic
width. Many peak shapes also have a parameter fwhm
(constrained by
sigma
) giving the full width at half maximum and a parameter height
(constrained by sigma
and amplitude
) to give the maximum peak
height.
After a list of builtin models, a few examples of their use are given.
Peaklike models¶
There are many peaklike models available. These include
GaussianModel
, LorentzianModel
, VoigtModel
and
some less commonly used variations. The guess()
methods for all of these make a fairly crude guess for the value of
amplitude
, but also set a lower bound of 0 on the value of sigma
.
GaussianModel
¶

class
GaussianModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Gaussian or normal distribution lineshape (see https://en.wikipedia.org/wiki/Normal_distribution), with three Parameters:
amplitude
,center
, andsigma
. In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma) = \frac{A}{\sigma\sqrt{2\pi}} e^{[{{(x\mu)^2}/{{2\sigma}^2}}]}\]where the parameter
amplitude
corresponds to \(A\),center
to \(\mu\), andsigma
to \(\sigma\). The full width at half maximum is \(2\sigma\sqrt{2\ln{2}}\), approximately \(2.3548\sigma\).Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
LorentzianModel
¶

class
LorentzianModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Lorentzian or CauchyLorentz distribution function (see https://en.wikipedia.org/wiki/Cauchy_distribution), with three Parameters:
amplitude
,center
, andsigma
. In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma) = \frac{A}{\pi} \big[\frac{\sigma}{(x  \mu)^2 + \sigma^2}\big]\]where the parameter
amplitude
corresponds to \(A\),center
to \(\mu\), andsigma
to \(\sigma\). The full width at half maximum is \(2\sigma\).Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
VoigtModel
¶

class
VoigtModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Voigt distribution function (see https://en.wikipedia.org/wiki/Voigt_profile), with four Parameters:
amplitude
,center
,sigma
, andgamma
. By default,gamma
is constrained to have a value equal tosigma
, though it can be varied independently. In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively. The definition for the Voigt function used here is\[f(x; A, \mu, \sigma, \gamma) = \frac{A \textrm{Re}[w(z)]}{\sigma\sqrt{2 \pi}}\]where
\begin{eqnarray*} z &=& \frac{x\mu +i\gamma}{\sigma\sqrt{2}} \\ w(z) &=& e^{z^2}{\operatorname{erfc}}(iz) \end{eqnarray*}and
erfc()
is the complementary error function. As above,amplitude
corresponds to \(A\),center
to \(\mu\), andsigma
to \(\sigma\). The parametergamma
corresponds to \(\gamma\). Ifgamma
is kept at the default value (constrained tosigma
), the full width at half maximum is approximately \(3.6013\sigma\).Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
PseudoVoigtModel
¶

class
PseudoVoigtModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a pseudoVoigt distribution function (see https://en.wikipedia.org/wiki/Voigt_profile#PseudoVoigt_Approximation), which is a weighted sum of a Gaussian and Lorentzian distribution function that share values for
amplitude
(\(A\)),center
(\(\mu\)) and full width at half maximumfwhm
(and so have constrained values ofsigma
(\(\sigma\)) andheight
(maximum peak height). A parameterfraction
(\(\alpha\)) controls the relative weight of the Gaussian and Lorentzian components, giving the full definition of\[f(x; A, \mu, \sigma, \alpha) = \frac{(1\alpha)A}{\sigma_g\sqrt{2\pi}} e^{[{{(x\mu)^2}/{{2\sigma_g}^2}}]} + \frac{\alpha A}{\pi} \big[\frac{\sigma}{(x  \mu)^2 + \sigma^2}\big]\]where \(\sigma_g = {\sigma}/{\sqrt{2\ln{2}}}\) so that the full width at half maximum of each component and of the sum is \(2\sigma\). The
guess()
function always sets the starting value forfraction
at 0.5.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
MoffatModel
¶

class
MoffatModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on the Moffat distribution function (see https://en.wikipedia.org/wiki/Moffat_distribution), with four Parameters:
amplitude
(\(A\)),center
(\(\mu\)), a width parametersigma
(\(\sigma\)) and an exponentbeta
(\(\beta\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, \beta) = A \big[(\frac{x\mu}{\sigma})^2+1\big]^{\beta}\]the full width have maximum is \(2\sigma\sqrt{2^{1/\beta}1}\). The
guess()
function always sets the starting value forbeta
to 1.Note that for (\(\beta=1\)) the Moffat has a Lorentzian shape.
Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Pearson7Model
¶

class
Pearson7Model
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Pearson VII distribution (see https://en.wikipedia.org/wiki/Pearson_distribution#The_Pearson_type_VII_distribution), with four parameters:
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andexponent
(\(m\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, m) = \frac{A}{\sigma{\beta(m\frac{1}{2}, \frac{1}{2})}} \bigl[1 + \frac{(x\mu)^2}{\sigma^2} \bigr]^{m}\]where \(\beta\) is the beta function (see scipy.special.beta) The
guess()
function always gives a starting value forexponent
of 1.5. In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
StudentsTModel
¶

class
StudentsTModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Student’s t distribution function (see https://en.wikipedia.org/wiki/Student%27s_tdistribution), with three Parameters:
amplitude
(\(A\)),center
(\(\mu\)) andsigma
(\(\sigma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma) = \frac{A \Gamma(\frac{\sigma+1}{2})} {\sqrt{\sigma\pi}\,\Gamma(\frac{\sigma}{2})} \Bigl[1+\frac{(x\mu)^2}{\sigma}\Bigr]^{\frac{\sigma+1}{2}}\]where \(\Gamma(x)\) is the gamma function.
Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
BreitWignerModel
¶

class
BreitWignerModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a BreitWignerFano function (see https://en.wikipedia.org/wiki/Fano_resonance), with four Parameters:
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andq
(\(q\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, q) = \frac{A (q\sigma/2 + x  \mu)^2}{(\sigma/2)^2 + (x  \mu)^2}\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
LognormalModel
¶

class
LognormalModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on the Lognormal distribution function (see https://en.wikipedia.org/wiki/Lognormal), with three Parameters
amplitude
(\(A\)),center
(\(\mu\)) andsigma
(\(\sigma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma) = \frac{A}{\sigma\sqrt{2\pi}}\frac{e^{(\ln(x)  \mu)^2/ 2\sigma^2}}{x}\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
DampedOcsillatorModel
¶

class
DampedOscillatorModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on the Damped Harmonic Oscillator Amplitude (see https://en.wikipedia.org/wiki/Harmonic_oscillator#Amplitude_part), with three Parameters:
amplitude
(\(A\)),center
(\(\mu\)) andsigma
(\(\sigma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma) = \frac{A}{\sqrt{ [1  (x/\mu)^2]^2 + (2\sigma x/\mu)^2}}\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
DampedHarmonicOcsillatorModel
¶

class
DampedHarmonicOscillatorModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a variation of the Damped Harmonic Oscillator (see https://en.wikipedia.org/wiki/Harmonic_oscillator), following the definition given in DAVE/PAN (see https://www.ncnr.nist.gov/dave/) with four Parameters:
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andgamma
(\(\gamma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, \gamma) = \frac{A\sigma}{\pi [1  \exp(x/\gamma)]} \Big[ \frac{1}{(x\mu)^2 + \sigma^2}  \frac{1}{(x+\mu)^2 + \sigma^2} \Big]\]where \(\gamma=kT\) k is the Boltzmann constant in \(evK^1\) and T is the temperature in \(K\).
Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
ExponentialGaussianModel
¶

class
ExponentialGaussianModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model of an Exponentially modified Gaussian distribution (see https://en.wikipedia.org/wiki/Exponentially_modified_Gaussian_distribution) with four Parameters
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andgamma
(\(\gamma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, \gamma) = \frac{A\gamma}{2} \exp\bigl[\gamma({\mu  x + \gamma\sigma^2/2})\bigr] {\operatorname{erfc}}\Bigl(\frac{\mu + \gamma\sigma^2  x}{\sqrt{2}\sigma}\Bigr)\]where
erfc()
is the complementary error function.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
SkewedGaussianModel
¶

class
SkewedGaussianModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A variation of the Exponential Gaussian, this uses a skewed normal distribution (see https://en.wikipedia.org/wiki/Skew_normal_distribution), with Parameters
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andgamma
(\(\gamma\)). In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, respectively.\[f(x; A, \mu, \sigma, \gamma) = \frac{A}{\sigma\sqrt{2\pi}} e^{[{{(x\mu)^2}/{{2\sigma}^2}}]} \Bigl\{ 1 + {\operatorname{erf}}\bigl[ \frac{{\gamma}(x\mu)}{\sigma\sqrt{2}} \bigr] \Bigr\}\]where
erf()
is the error function.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
SkewedVoigtModel
¶

class
SkewedVoigtModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶  A variation of the Skewed Gaussian, this applies the same skewing
 to a Voigt distribution (see
https://en.wikipedia.org/wiki/Voigt_distribution). It has Parameters
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andgamma
(\(\gamma\)), as usual for a Voigt distribution, and add a Parameterskew
. In addition, parametersfwhm
andheight
are included as constraints to report full width at half maximum and maximum peak height, of the Voigt distribution, respectively.
\[f(x; A, \mu, \sigma, \gamma, \rm{skew}) = {\rm{Voigt}}(x; A, \mu, \sigma, \gamma) \Bigl\{ 1 + {\operatorname{erf}}\bigl[ \frac{{\rm{skew}}(x\mu)}{\sigma\sqrt{2}} \bigr] \Bigr\}\]where
erf()
is the error function.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
DonaichModel
¶

class
DonaichModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model of an Doniach Sunjic asymmetric lineshape (see https://www.casaxps.com/help_manual/line_shapes.htm), used in photoemission, with four Parameters
amplitude
(\(A\)),center
(\(\mu\)),sigma
(\(\sigma\)), andgamma
(\(\gamma\)). In addition, parameterheight
is included as a constraint.\[f(x; A, \mu, \sigma, \gamma) = \frac{A}{\sigma^{1\gamma}} \frac{\cos\bigl[\pi\gamma/2 + (1\gamma) \arctan{((x  \mu)}/\sigma)\bigr]} {\bigr[1 + (x\mu)/\sigma\bigl]^{(1\gamma)/2}}\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Linear and Polynomial Models¶
These models correspond to polynomials of some degree. Of course, lmfit is a very inefficient way to do linear regression (see numpy.polyfit or scipy.stats.linregress), but these models may be useful as one of many components of a composite model.
ConstantModel
¶

class
ConstantModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ Constant model, with a single Parameter:
c
.Note that this is ‘constant’ in the sense of having no dependence on the independent variable
x
, not in the sense of being nonvarying. To be clear,c
will be a Parameter that will be varied in the fit (by default, of course).Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
LinearModel
¶

class
LinearModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ Linear model, with two Parameters
intercept
andslope
.Defined as:
\[f(x; m, b) = m x + b\]with
slope
for \(m\) andintercept
for \(b\).Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
QuadraticModel
¶

class
QuadraticModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A quadratic model, with three Parameters
a
,b
, andc
.Defined as:
\[f(x; a, b, c) = a x^2 + b x + c\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
PolynomialModel
¶

class
PolynomialModel
(degree, independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A polynomial model with up to 7 Parameters, specfied by
degree
.\[f(x; c_0, c_1, \ldots, c_7) = \sum_{i=0, 7} c_i x^i\]with parameters
c0
,c1
, …,c7
. The supplieddegree
will specify how many of these are actual variable parameters. This uses numpy.polyval for its calculation of the polynomial.Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Steplike models¶
Two models represent steplike functions, and share many characteristics.
StepModel
¶

class
StepModel
(independent_vars=['x'], prefix='', nan_policy='raise', form='linear', **kwargs)¶ A model based on a Step function, with three Parameters:
amplitude
(\(A\)),center
(\(\mu\)) andsigma
(\(\sigma\)).There are four choices for
form
:linear
(the default)atan
orarctan
for an arctangent functionerf
for an error functionlogistic
for a logistic function (see https://en.wikipedia.org/wiki/Logistic_function)
The step function starts with a value 0, and ends with a value of \(A\) rising to \(A/2\) at \(\mu\), with \(\sigma\) setting the characteristic width. The functional forms are defined as:
\begin{eqnarray*} & f(x; A, \mu, \sigma, {\mathrm{form={}'linear{}'}}) & = A \min{[1, \max{(0, \alpha)}]} \\ & f(x; A, \mu, \sigma, {\mathrm{form={}'arctan{}'}}) & = A [1/2 + \arctan{(\alpha)}/{\pi}] \\ & f(x; A, \mu, \sigma, {\mathrm{form={}'erf{}'}}) & = A [1 + {\operatorname{erf}}(\alpha)]/2 \\ & f(x; A, \mu, \sigma, {\mathrm{form={}'logistic{}'}})& = A [1  \frac{1}{1 + e^{\alpha}} ] \end{eqnarray*}where \(\alpha = (x  \mu)/{\sigma}\).
Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
RectangleModel
¶

class
RectangleModel
(independent_vars=['x'], prefix='', nan_policy='raise', form='linear', **kwargs)¶ A model based on a Stepup and Stepdown function, with five Parameters:
amplitude
(\(A\)),center1
(\(\mu_1\)),center2
(\(\mu_2\)), sigma1` (\(\sigma_1\)) andsigma2
(\(\sigma_2\)).There are four choices for
form
, which is used for both the Step up and the Step down:linear
(the default)atan
orarctan
for an arctangent functionerf
for an error functionlogistic
for a logistic function (see https://en.wikipedia.org/wiki/Logistic_function)
The function starts with a value 0, transitions to a value of \(A\), taking the value \(A/2\) at \(\mu_1\), with \(\sigma_1\) setting the characteristic width. The function then transitions again to the value \(A/2\) at \(\mu_2\), with \(\sigma_2\) setting the characteristic width. The functional forms are defined as:
\begin{eqnarray*} &f(x; A, \mu, \sigma, {\mathrm{form={}'linear{}'}}) &= A \{ \min{[1, \max{(0, \alpha_1)}]} + \min{[1, \max{(0, \alpha_2)}]} \} \\ &f(x; A, \mu, \sigma, {\mathrm{form={}'arctan{}'}}) &= A [\arctan{(\alpha_1)} + \arctan{(\alpha_2)}]/{\pi} \\ &f(x; A, \mu, \sigma, {\mathrm{form={}'erf{}'}}) &= A [{\operatorname{erf}}(\alpha_1) + {\operatorname{erf}}(\alpha_2)]/2 \\ &f(x; A, \mu, \sigma, {\mathrm{form={}'logistic{}'}}) &= A [1  \frac{1}{1 + e^{\alpha_1}}  \frac{1}{1 + e^{\alpha_2}} ] \end{eqnarray*}where \(\alpha_1 = (x  \mu_1)/{\sigma_1}\) and \(\alpha_2 = (x  \mu_2)/{\sigma_2}\).
Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Exponential and Power law models¶
ExponentialModel
¶

class
ExponentialModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on an exponential decay function (see https://en.wikipedia.org/wiki/Exponential_decay) with two Parameters:
amplitude
(\(A\)), anddecay
(\(\tau\)), in:\[f(x; A, \tau) = A e^{x/\tau}\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
PowerLawModel
¶

class
PowerLawModel
(independent_vars=['x'], prefix='', nan_policy='raise', **kwargs)¶ A model based on a Power Law (see https://en.wikipedia.org/wiki/Power_law), with two Parameters:
amplitude
(\(A\)), andexponent
(\(k\)), in:\[f(x; A, k) = A x^k\]Parameters:  independent_vars (['x']) – Arguments to func that are independent variables.
 prefix (str, optional) – String to prepend to parameter names, needed to add two Models that have parameter names in common.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kwargs (optional) – Keyword arguments to pass to
Model
.
Notes
1. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
2. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Userdefined Models¶
As shown in the previous chapter (Modeling Data and Curve Fitting), it is fairly straightforward to build fitting models from parametrized Python functions. The number of model classes listed so far in the present chapter should make it clear that this process is not too difficult. Still, it is sometimes desirable to build models from a usersupplied function. This may be especially true if modelbuilding is builtin to some larger library or application for fitting in which the user may not be able to easily build and use a new model from Python code.
The ExpressionModel
allows a model to be built from a
usersupplied expression. This uses the asteval module also used for
mathematical constraints as discussed in Using Mathematical Constraints.
ExpressionModel
¶

class
ExpressionModel
(expr, independent_vars=None, init_script=None, nan_policy='raise', **kws)¶ Generate a model from usersupplied expression.
Parameters:  expr (str) – Mathematical expression for model.
 independent_vars (list of str or None, optional) – Variable names to use as independent variables.
 init_script (str or None, optional) – Initial script to run in asteval interpreter.
 nan_policy (str, optional) – How to handle NaN and missing values in data. Must be one of: ‘raise’ (default), ‘propagate’, or ‘omit’. See Notes below.
 missing (str, optional) – Synonym for ‘nan_policy’ for backward compatibility.
 **kws (optional) – Keyword arguments to pass to
Model
.
Notes
 each instance of ExpressionModel will create and using its own version of an asteval interpreter.
 prefix is not supported for ExpressionModel.
3. nan_policy sets what to do when a NaN or missing value is seen in the data. Should be one of:
 ‘raise’ : Raise a ValueError (default)
 ‘propagate’ : do nothing
 ‘omit’ : (was ‘drop’) drop missing data
4. The missing argument is deprecated in lmfit 0.9.8 and will be removed in a later version. Use nan_policy instead, as it is consistent with the Minimizer class.
Since the point of this model is that an arbitrary expression will be
supplied, the determination of what are the parameter names for the model
happens when the model is created. To do this, the expression is parsed,
and all symbol names are found. Names that are already known (there are
over 500 function and value names in the asteval namespace, including most
Python builtins, more than 200 functions inherited from NumPy, and more
than 20 common lineshapes defined in the lineshapes
module) are not
converted to parameters. Unrecognized names are expected to be names of either
parameters or independent variables. If independent_vars is the
default value of None, and if the expression contains a variable named
x, that will be used as the independent variable. Otherwise,
independent_vars must be given.
For example, if one creates an ExpressionModel
as:
>>> mod = ExpressionModel('off + amp * exp(x/x0) * sin(x*phase)')
The name exp will be recognized as the exponent function, so the model will be interpreted to have parameters named off, amp, x0 and phase. In addition, x will be assumed to be the sole independent variable. In general, there is no obvious way to set default parameter values or parameter hints for bounds, so this will have to be handled explicitly.
To evaluate this model, you might do the following:
>>> x = numpy.linspace(0, 10, 501)
>>> params = mod.make_params(off=0.25, amp=1.0, x0=2.0, phase=0.04)
>>> y = mod.eval(params, x=x)
While many custom models can be built with a single line expression (especially since the names of the lineshapes like gaussian, lorentzian and so on, as well as many NumPy functions, are available), more complex models will inevitably require multiple line functions. You can include such Python code with the init_script argument. The text of this script is evaluated when the model is initialized (and before the actual expression is parsed), so that you can define functions to be used in your expression.
As a probably unphysical example, to make a model that is the derivative of a Gaussian function times the logarithm of a Lorentzian function you may could to define this in a script:
>>> script = """
def mycurve(x, amp, cen, sig):
loren = lorentzian(x, amplitude=amp, center=cen, sigma=sig)
gauss = gaussian(x, amplitude=amp, center=cen, sigma=sig)
return log(loren) * gradient(gauss) / gradient(x)
"""
and then use this with ExpressionModel
as:
>>> mod = ExpressionModel('mycurve(x, height, mid, wid)',
init_script=script,
independent_vars=['x'])
As above, this will interpret the parameter names to be height, mid, and wid, and build a model that can be used to fit data.
Example 1: Fit Peak data to Gaussian, Lorentzian, and Voigt profiles¶
Here, we will fit data to three similar line shapes, in order to decide which
might be the better model. We will start with a Gaussian profile, as in
the previous chapter, but use the builtin GaussianModel
instead
of writing one ourselves. This is a slightly different version from the
one in previous example in that the parameter names are different, and have
builtin default values. We will simply use:
from numpy import loadtxt
from lmfit.models import GaussianModel
data = loadtxt('test_peak.dat')
x = data[:, 0]
y = data[:, 1]
mod = GaussianModel()
pars = mod.guess(y, x=x)
out = mod.fit(y, pars, x=x)
print(out.fit_report(min_correl=0.25))
which prints out the results:
[[Model]]
Model(gaussian)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 27
# data points = 401
# variables = 3
chisquare = 29.9943157
reduced chisquare = 0.07536260
Akaike info crit = 1033.77437
Bayesian info crit = 1021.79248
[[Variables]]
sigma: 1.23218359 +/ 0.00737496 (0.60%) (init = 1.35)
amplitude: 30.3135620 +/ 0.15712686 (0.52%) (init = 43.62238)
center: 9.24277047 +/ 0.00737496 (0.08%) (init = 9.25)
fwhm: 2.90157056 +/ 0.01736670 (0.60%) == '2.3548200*sigma'
height: 9.81457817 +/ 0.05087283 (0.52%) == '0.3989423*amplitude/max(1.e15, sigma)'
[[Correlations]] (unreported correlations are < 0.250)
C(sigma, amplitude) = 0.577
We see a few interesting differences from the results of the previous
chapter. First, the parameter names are longer. Second, there are fwhm
and height
parameters, to give the full width at half maximum and
maximum peak height. And third, the automated initial guesses are pretty
good. A plot of the fit:
shows a decent match to the data – the fit worked with no explicit setting
of initial parameter values. Looking more closely, the fit is not perfect,
especially in the tails of the peak, suggesting that a different peak
shape, with longer tails, should be used. Perhaps a Lorentzian would be
better? To do this, we simply replace GaussianModel
with
LorentzianModel
to get a LorentzianModel
:
from lmfit.models import LorentzianModel
mod = LorentzianModel()
with the rest of the script as above. Perhaps predictably, the first thing we try gives results that are worse:
[[Model]]
Model(lorentzian)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 23
# data points = 401
# variables = 3
chisquare = 53.7535387
reduced chisquare = 0.13505914
Akaike info crit = 799.830322
Bayesian info crit = 787.848438
[[Variables]]
sigma: 1.15483925 +/ 0.01315659 (1.14%) (init = 1.35)
center: 9.24438944 +/ 0.00927619 (0.10%) (init = 9.25)
amplitude: 38.9727645 +/ 0.31386183 (0.81%) (init = 54.52798)
fwhm: 2.30967850 +/ 0.02631318 (1.14%) == '2.0000000*sigma'
height: 10.7421156 +/ 0.08633945 (0.80%) == '0.3183099*amplitude/max(1.e15, sigma)'
[[Correlations]] (unreported correlations are < 0.250)
C(sigma, amplitude) = 0.709
with the plot shown on the right in the figure above. The tails are now
too big, and the value for \(\chi^2\) almost doubled. A Voigt model
does a better job. Using VoigtModel
, this is as simple as using:
from lmfit.models import VoigtModel
mod = VoigtModel()
with all the rest of the script as above. This gives:
[[Model]]
Model(voigt)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 23
# data points = 401
# variables = 3
chisquare = 14.5448627
reduced chisquare = 0.03654488
Akaike info crit = 1324.00615
Bayesian info crit = 1312.02427
[[Variables]]
center: 9.24411150 +/ 0.00505482 (0.05%) (init = 9.25)
sigma: 0.73015627 +/ 0.00368460 (0.50%) (init = 0.8775)
amplitude: 35.7554146 +/ 0.13861321 (0.39%) (init = 65.43358)
gamma: 0.73015627 +/ 0.00368460 (0.50%) == 'sigma'
fwhm: 2.62951907 +/ 0.01326940 (0.50%) == '3.6013100*sigma'
height: 10.2203969 +/ 0.03009415 (0.29%) == 'amplitude*wofz((1j*gamma)/(sigma*sqrt(2))).real/(sigma*sqrt(2*pi))'
[[Correlations]] (unreported correlations are < 0.250)
C(sigma, amplitude) = 0.651
which has a much better value for \(\chi^2\) and the other goodnessoffit measures, and an obviously better match to the data as seen in the figure below (left).
Can we do better? The Voigt function has a \(\gamma\) parameter
(gamma
) that can be distinct from sigma
. The default behavior used
above constrains gamma
to have exactly the same value as sigma
. If
we allow these to vary separately, does the fit improve? To do this, we
have to change the gamma
parameter from a constrained expression and
give it a starting value using something like:
mod = VoigtModel()
pars = mod.guess(y, x=x)
pars['gamma'].set(value=0.7, vary=True, expr='')
which gives:
[[Model]]
Model(voigt)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 23
# data points = 401
# variables = 4
chisquare = 10.9301767
reduced chisquare = 0.02753193
Akaike info crit = 1436.57602
Bayesian info crit = 1420.60017
[[Variables]]
sigma: 0.89518909 +/ 0.01415450 (1.58%) (init = 0.8775)
amplitude: 34.1914737 +/ 0.17946860 (0.52%) (init = 65.43358)
center: 9.24374847 +/ 0.00441903 (0.05%) (init = 9.25)
gamma: 0.52540199 +/ 0.01857955 (3.54%) (init = 0.7)
fwhm: 3.22385342 +/ 0.05097475 (1.58%) == '3.6013100*sigma'
height: 10.0872204 +/ 0.03482129 (0.35%) == 'amplitude*wofz((1j*gamma)/(sigma*sqrt(2))).real/(sigma*sqrt(2*pi))'
[[Correlations]] (unreported correlations are < 0.250)
C(sigma, gamma) = 0.928
C(amplitude, gamma) = 0.821
C(sigma, amplitude) = 0.651
and the fit shown on the right above.
Comparing the two fits with the Voigt function, we see that \(\chi^2\)
is definitely improved with a separately varying gamma
parameter. In
addition, the two values for gamma
and sigma
differ significantly
– well outside the estimated uncertainties. More compelling, reduced
\(\chi^2\) is improved even though a fourth variable has been added to
the fit. In the simplest statistical sense, this suggests that gamma
is a significant variable in the model. In addition, we can use both the
Akaike or Bayesian Information Criteria (see
Akaike and Bayesian Information Criteria) to assess how likely the model with
variable gamma
is to explain the data than the model with gamma
fixed to the value of sigma
. According to theory,
\(\exp((\rm{AIC1}\rm{AIC0})/2)\) gives the probability that a model with
AIC1 is more likely than a model with AIC0. For the two models here, with
AIC values of 1436 and 1324 (Note: if we had more carefully set the value
for weights
based on the noise in the data, these values might be
positive, but there difference would be roughly the same), this says that
the model with gamma
fixed to sigma
has a probability less than 5.e25
of being the better model.
Example 2: Fit data to a Composite Model with predefined models¶
Here, we repeat the point made at the end of the last chapter that
instances of Model
class can be added together to make a
composite model. By using the large number of builtin models available,
it is therefore very simple to build models that contain multiple peaks and
various backgrounds. An example of a simple fit to a noisy step function
plus a constant:
#!/usr/bin/env python
# <examples/doc_builtinmodels_stepmodel.py>
import matplotlib.pyplot as plt
import numpy as np
from lmfit.models import LinearModel, StepModel
x = np.linspace(0, 10, 201)
y = np.ones_like(x)
y[:48] = 0.0
y[48:77] = np.arange(7748)/(77.048)
np.random.seed(0)
y = 110.2 * (y + 9e3*np.random.randn(len(x))) + 12.0 + 2.22*x
step_mod = StepModel(form='erf', prefix='step_')
line_mod = LinearModel(prefix='line_')
pars = line_mod.make_params(intercept=y.min(), slope=0)
pars += step_mod.guess(y, x=x, center=2.5)
mod = step_mod + line_mod
out = mod.fit(y, pars, x=x)
print(out.fit_report())
plt.plot(x, y, 'b')
plt.plot(x, out.init_fit, 'k')
plt.plot(x, out.best_fit, 'r')
plt.show()
# <end examples/doc_builtinmodels_stepmodel.py>
After constructing steplike data, we first create a StepModel
telling it to use the erf
form (see details above), and a
ConstantModel
. We set initial values, in one case using the data
and guess()
method for the initial step function paramaters, and
make_params()
arguments for the linear component.
After making a composite model, we run fit()
and report the
results, which gives:
[[Model]]
(Model(step, prefix='step_', form='erf') + Model(linear, prefix='line_'))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 49
# data points = 201
# variables = 5
chisquare = 593.709622
reduced chisquare = 3.02913072
Akaike info crit = 227.700173
Bayesian info crit = 244.216698
[[Variables]]
line_intercept: 12.0964833 +/ 0.27606235 (2.28%) (init = 11.58574)
line_slope: 1.87164655 +/ 0.09318714 (4.98%) (init = 0)
step_sigma: 0.67392841 +/ 0.01091168 (1.62%) (init = 1.428571)
step_center: 3.13494792 +/ 0.00516615 (0.16%) (init = 2.5)
step_amplitude: 112.858376 +/ 0.65392949 (0.58%) (init = 134.7378)
[[Correlations]] (unreported correlations are < 0.100)
C(line_slope, step_amplitude) = 0.879
C(step_sigma, step_amplitude) = 0.564
C(line_slope, step_sigma) = 0.457
C(line_intercept, step_center) = 0.427
C(line_intercept, line_slope) = 0.309
C(line_slope, step_center) = 0.234
C(line_intercept, step_sigma) = 0.137
C(line_intercept, step_amplitude) = 0.117
C(step_center, step_amplitude) = 0.109
with a plot of
Example 3: Fitting Multiple Peaks – and using Prefixes¶
As shown above, many of the models have similar parameter names. For
composite models, this could lead to a problem of having parameters for
different parts of the model having the same name. To overcome this, each
Model
can have a prefix
attribute (normally set to a blank
string) that will be put at the beginning of each parameter name. To
illustrate, we fit one of the classic datasets from the NIST StRD suite
involving a decaying exponential and two gaussians.
#!/usr/bin/env python
# <examples/doc_builtinmodels_nistgauss.py>
import matplotlib.pyplot as plt
import numpy as np
from lmfit.models import ExponentialModel, GaussianModel
dat = np.loadtxt('NIST_Gauss2.dat')
x = dat[:, 1]
y = dat[:, 0]
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(105, min=75, max=125)
pars['g1_sigma'].set(15, min=3)
pars['g1_amplitude'].set(2000, min=10)
gauss2 = GaussianModel(prefix='g2_')
pars.update(gauss2.make_params())
pars['g2_center'].set(155, min=125, max=175)
pars['g2_sigma'].set(15, min=3)
pars['g2_amplitude'].set(2000, min=10)
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))
plot_components = False
plt.plot(x, y, 'b')
plt.plot(x, init, 'k')
plt.plot(x, out.best_fit, 'r')
if plot_components:
comps = out.eval_components(x=x)
plt.plot(x, comps['g1_'], 'b')
plt.plot(x, comps['g2_'], 'b')
plt.plot(x, comps['exp_'], 'k')
plt.show()
# <end examples/doc_builtinmodels_nistgauss.py>
where we give a separate prefix to each model (they all have an
amplitude
parameter). The prefix
values are attached transparently
to the models.
Note that the calls to make_param()
used the bare name, without the
prefix. We could have used the prefixes, but because we used the
individual model gauss1
and gauss2
, there was no need.
Note also in the example here that we explicitly set bounds on many of the parameter values.
The fit results printed out are:
[[Model]]
((Model(gaussian, prefix='g1_') + Model(gaussian, prefix='g2_')) + Model(exponential, prefix='exp_'))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 48
# data points = 250
# variables = 8
chisquare = 1247.52821
reduced chisquare = 5.15507524
Akaike info crit = 417.864631
Bayesian info crit = 446.036318
[[Variables]]
exp_decay: 90.9508860 +/ 1.10310509 (1.21%) (init = 93.24905)
exp_amplitude: 99.0183283 +/ 0.53748735 (0.54%) (init = 162.2102)
g1_center: 107.030954 +/ 0.15006786 (0.14%) (init = 105)
g1_sigma: 16.6725753 +/ 0.16048161 (0.96%) (init = 15)
g1_amplitude: 4257.77319 +/ 42.3833645 (1.00%) (init = 2000)
g1_fwhm: 39.2609138 +/ 0.37790530 (0.96%) == '2.3548200*g1_sigma'
g1_height: 101.880231 +/ 0.59217100 (0.58%) == '0.3989423*g1_amplitude/max(1.e15, g1_sigma)'
g2_center: 153.270101 +/ 0.19466743 (0.13%) (init = 155)
g2_sigma: 13.8069484 +/ 0.18679415 (1.35%) (init = 15)
g2_amplitude: 2493.41771 +/ 36.1694731 (1.45%) (init = 2000)
g2_fwhm: 32.5128783 +/ 0.43986659 (1.35%) == '2.3548200*g2_sigma'
g2_height: 72.0455934 +/ 0.61722094 (0.86%) == '0.3989423*g2_amplitude/max(1.e15, g2_sigma)'
[[Correlations]] (unreported correlations are < 0.500)
C(g1_sigma, g1_amplitude) = 0.824
C(g2_sigma, g2_amplitude) = 0.815
C(exp_decay, exp_amplitude) = 0.695
C(g1_sigma, g2_center) = 0.684
C(g1_center, g2_amplitude) = 0.669
C(g1_center, g2_sigma) = 0.652
C(g1_amplitude, g2_center) = 0.648
C(g1_center, g2_center) = 0.621
C(g1_center, g1_sigma) = 0.507
C(exp_decay, g1_amplitude) = 0.507
We get a very good fit to this problem (described at the NIST site as of average difficulty, but the tests there are generally deliberately challenging) by applying reasonable initial guesses and putting modest but explicit bounds on the parameter values. This fit is shown on the left:
One final point on setting initial values. From looking at the data
itself, we can see the two Gaussian peaks are reasonably well separated but
do overlap. Furthermore, we can tell that the initial guess for the
decaying exponential component was poorly estimated because we used the
full data range. We can simplify the initial parameter values by using
this, and by defining an index_of()
function to limit the data range.
That is, with:
def index_of(arrval, value):
"""Return index of array *at or below* value."""
if value < min(arrval):
return 0
return max(np.where(arrval <= value)[0])
ix1 = index_of(x, 75)
ix2 = index_of(x, 135)
ix3 = index_of(x, 175)
exp_mod.guess(y[:ix1], x=x[:ix1])
gauss1.guess(y[ix1:ix2], x=x[ix1:ix2])
gauss2.guess(y[ix2:ix3], x=x[ix2:ix3])
we can get a better initial estimate. The fit converges to the same answer, giving to identical values (to the precision printed out in the report), but in few steps, and without any bounds on parameters at all:
[[Model]]
((Model(gaussian, prefix='g1_') + Model(gaussian, prefix='g2_')) + Model(exponential, prefix='exp_'))
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 39
# data points = 250
# variables = 8
chisquare = 1247.52821
reduced chisquare = 5.15507524
Akaike info crit = 417.864631
Bayesian info crit = 446.036318
[[Variables]]
exp_decay: 90.9508890 +/ 1.10310483 (1.21%) (init = 111.1985)
exp_amplitude: 99.0183270 +/ 0.53748905 (0.54%) (init = 94.53724)
g1_sigma: 16.6725765 +/ 0.16048227 (0.96%) (init = 14.5)
g1_amplitude: 4257.77343 +/ 42.3836432 (1.00%) (init = 3189.648)
g1_center: 107.030956 +/ 0.15006873 (0.14%) (init = 106.5)
g1_fwhm: 39.2609166 +/ 0.37790686 (0.96%) == '2.3548200*g1_sigma'
g1_height: 101.880230 +/ 0.59217233 (0.58%) == '0.3989423*g1_amplitude/max(1.e15, g1_sigma)'
g2_sigma: 13.8069461 +/ 0.18679534 (1.35%) (init = 15)
g2_amplitude: 2493.41733 +/ 36.1696911 (1.45%) (init = 2818.337)
g2_center: 153.270101 +/ 0.19466905 (0.13%) (init = 150)
g2_fwhm: 32.5128728 +/ 0.43986940 (1.35%) == '2.3548200*g2_sigma'
g2_height: 72.0455948 +/ 0.61722329 (0.86%) == '0.3989423*g2_amplitude/max(1.e15, g2_sigma)'
[[Correlations]] (unreported correlations are < 0.500)
C(g1_sigma, g1_amplitude) = 0.824
C(g2_sigma, g2_amplitude) = 0.815
C(exp_decay, exp_amplitude) = 0.695
C(g1_sigma, g2_center) = 0.684
C(g1_center, g2_amplitude) = 0.669
C(g1_center, g2_sigma) = 0.652
C(g1_amplitude, g2_center) = 0.648
C(g1_center, g2_center) = 0.621
C(g1_sigma, g1_center) = 0.507
C(exp_decay, g1_amplitude) = 0.507
This script is in the file doc_builtinmodels_nistgauss2.py
in the examples folder,
and the fit result shown on the right above shows an improved initial
estimate of the data.