Least-squares fitting with the Fitter Class¶
Note: This module is still a work-in-progress and the usage of these classes and/or functions may change in the future.
The follow is an example of how to use the Fitter
class, which is an interface to the non-linear least-squares minimization routine scipy.optimize.leastsq
, with some features based on lmfit.minimize
.
Defining the problem¶
Fitter
requires you to pass a residuals
function, rather than the function to which you desire to fit your data. This gives more flexibility because the form of the residuals can be defined by the user, rather than being confined to the standard formula for residuals:
Assuming you already have your function
prepared, defining the residuals function is trivial. For the sake of this example we will assume that function
is the one dimensional functions.gaussian
:
from neutronpy.functions import gaussian
def residuals(params, data):
x, y, err = data
return (y - gaussian(params, x)) / err
Notice that I did not square the residuals function. This is because Fitter
will square the residuals as part of the Least-squares fitting.
Initializing¶
Once the problem is defined, we can initialize our object using Fitter
:
>>> from neutronpy import Fitter
>>> fitobj = Fitter(residuals=residuals, data=(x, y, err))
Initial parameters and Constraints¶
The parameters and constraints will obviously depend on the specific problem. Initial parameters can be defined as a list; in this example we will define a single gaussian peak with no background:
>>> params = [0, 0, 1, 0, 0.1]
Defining constraints is slightly more complicated however. It is possible to define whether the parameter is fixed, its limits, its step size, and its sidedness, for each parameter. Like the parameters, constraints, i.e. parinfo
is defined as a list, but with either dictionaries or None
for each parameter. For example, let us fix the background terms:
>>> fitobj.parinfo = [{'fixed': True}, {'fixed': 1}, {'fixed': 0}, {'fixed': False}, None]
The above illustrates equivalent ways to either fix (the first two list members), or leave unfixed (the last three list members) the parameters.
Fitting¶
To fit the function we simply call Fitter.fit
with our initial parameters:
>>> fitobj.fit(params0=params)
Results¶
Results of the fit are stored in fitobj.params
. \(\chi^2\) is stored in fitobj.chi2_min
, and the parameter errors are stored in fitobj.xerror
.