Note
Click here to download the full example code
Fit Using Inequality ConstraintΒΆ
Sometimes specifying boundaries using min
and max
are not sufficient,
and more complicated (inequality) constraints are needed. In the example below
the center of the Lorentzian peak is constrained to be between 0-5 away from
the center of the Gaussian peak.
See also: https://lmfit.github.io/lmfit-py/constraints.html#using-inequality-constraints
import matplotlib.pyplot as plt
import numpy as np
from lmfit import Minimizer, Parameters, report_fit
from lmfit.lineshapes import gaussian, lorentzian
def residual(pars, x, data):
model = (gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) +
lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']))
return model - data
Generate the simulated data using a Gaussian and Lorentzian line shape:
Create the fitting parameters and set an inequality constraint for cen_l
.
First, we add a new fitting parameter peak_split
, which can take values
between 0 and 5. Afterwards, we constrain the value for cen_l
using the
expression to be 'peak_split+cen_g'
:
pfit = Parameters()
pfit.add(name='amp_g', value=10)
pfit.add(name='amp_l', value=10)
pfit.add(name='cen_g', value=5)
pfit.add(name='peak_split', value=2.5, min=0, max=5, vary=True)
pfit.add(name='cen_l', expr='peak_split+cen_g')
pfit.add(name='wid_g', value=1)
pfit.add(name='wid_l', expr='wid_g')
mini = Minimizer(residual, pfit, fcn_args=(x, data))
out = mini.leastsq()
best_fit = data + out.residual
Performing a fit, here using the leastsq
algorithm, gives the following
fitting results:
report_fit(out.params)
Out:
[[Variables]]
amp_g: 21.2722837 +/- 0.05138760 (0.24%) (init = 10)
amp_l: 9.46504191 +/- 0.05445416 (0.58%) (init = 10)
cen_g: 6.10496394 +/- 0.00334614 (0.05%) (init = 5)
peak_split: 3.52163535 +/- 0.01004618 (0.29%) (init = 2.5)
cen_l: 9.62659929 +/- 0.01066173 (0.11%) == 'peak_split+cen_g'
wid_g: 1.21434950 +/- 0.00327315 (0.27%) (init = 1)
wid_l: 1.21434950 +/- 0.00327315 (0.27%) == 'wid_g'
[[Correlations]] (unreported correlations are < 0.100)
C(amp_g, wid_g) = 0.620
C(amp_g, peak_split) = 0.380
C(peak_split, wid_g) = 0.344
C(amp_g, amp_l) = -0.295
C(amp_l, cen_g) = -0.276
C(amp_g, cen_g) = 0.194
C(amp_l, wid_g) = -0.165
C(cen_g, wid_g) = 0.155
and figure:
Out:
/Users/Newville/Codes/lmfit-py/examples/example_fit_with_inequality.py:61: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
plt.show()
Total running time of the script: ( 0 minutes 0.094 seconds)