FittingMixin

class Stoner.analysis.fitting.FittingMixin[source]

Bases: object

A mixin calss for Stoner.Core.DataFile to provide additional curve_fiotting methods.

Methods Summary

annotate_fit(model[, x, y, z, text_only])

Annotate a plot with some information about a fit.

curve_fit(func[, xcol, ycol, sigma])

General curve fitting function passed through from scipy.

differential_evolution(model[, xcol, ycol, ...])

Fit model to the data using a differential evolution algorithm.

lmfit(model[, xcol, ycol, p0, sigma])

Wrap the lmfit module fitting.

odr(model[, xcol, ycol])

Wrap the scipy.odr orthogonal distance regression fitting.

polyfit([xcol, ycol, polynomial_order, ...])

Pass through to numpy.polyfit.

Methods Documentation

annotate_fit(model, x=None, y=None, z=None, text_only=False, **kargs)[source]

Annotate a plot with some information about a fit.

Parameters:

mode (callable or lmfit.Model) – The function/model used to describe the fit to be annotated.

Keyword Parameters:
x (float):

x coordinate of the label

y (float):

y coordinate of the label

z (float):

z co-ordinbate of the label if the current axes are 3D

prefix (str):

The prefix placed ahead of the model parameters in the metadata.

text_only (bool):

If False (default), add the text to the plot and return the current object, otherwise, return just the text and don’t add to a plot.

prefix(str):

If given overridges the prefix from the model to determine a prefix to the parameter names in the metadata

Returns:

(Datam, str) – A copy of the current Data instance if text_only is False, otherwise returns the text.

If prefix is not given, then the first prefix in the metadata lmfit.prefix is used if present, otherwise a prefix is generated from the model.prefix attribute. If x and y are not specified then they are set to be 0.75 * maximum x and y limit of the plot.

curve_fit(func, xcol=None, ycol=None, sigma=None, **kargs)[source]

General curve fitting function passed through from scipy.

Parameters:
  • func (callable, lmfit.Model, odr.Model) – The fitting function with the form def f(x,*p) where p is a list of fitting parameters

  • xcol (index, Iterable) – The index of the x-column data to fit. If list or other iterable sends a tuple of x columns to func for N-d fitting.

  • ycol (index, list of indices or array) – The index of the y-column data to fit. If an array, then should be 1D and the same length as the data. If ycol is a list of indices then the columns are iterated over in turn, fitting occurring for each one. In this case the return value is a list of what would be returned for a single column fit.

Keyword Arguments:
  • p0 (list, tuple, array or callable) – A vector of initial parameter values to try. See notes below.

  • sigma (index) – The index of the column with the y-error bars

  • bounds (callable) – A callable object that evaluates true if a row is to be included. Should be of the form f(x,y)

  • result (bool) – Determines whether the fitted data should be added into the DataFile object. If result is True then the last column will be used. If result is a string or an integer then it is used as a column index. Default to None for not adding fitted data

  • replace (bool) – Inidcatesa whether the fitted data replaces existing data or is inserted as a new column (default False)

  • header (string or None) – If this is a string then it is used as the name of the fitted data. (default None)

  • absolute_sigma (bool) – If False, sigma denotes relative weights of the data points. The default True means that the sigma parameter is the reciprocal of the absolute standard deviation.

  • output (str, default "fit") – Specify what to return.

Returns:

(various)

The return value is determined by the output parameter. Options are:
  • ”fit” (tuple of popt,pcov) Optimal values of the fitting parameters p, and the

    variance-co-variance matrix for the fitting parameters.

  • ”row” just a one dimensional numpy array of the fit parameters interleaved with their

    uncertainties

  • ”full” a tuple of (popt,pcov,dictionary of optional outputs, message, return code, row).

  • ”data” a copy of the Stoner.Core.DataFile object with fit recorded in the

    metadata and optionally as a new column.

Note

If the columns are not specified (or set to None) then the X and Y data are taken using the Stoner.Core.DataFile.setas attribute.

The fitting function should have prototype y=f(x,p[0],p[1],p[2]…) The x-column and y-column can be anything that Stoner.Core.DataFile.find_col() can use as an index but typucally either strings to be matched against column headings or integers. The initial parameter values and weightings default to None which corresponds to all parameters starting at 1 and all points equally weighted. The bounds function has format b(x, y-vec) and rewturns true if the point is to be used in the fit and false if not.

The absolute_sigma keyword determines whether the returned covariance matrix pcov is based on estimated errors in the data, and is not affected by the overall magnitude of the values in sigma. Only the relative magnitudes of the sigma values matter. If True, sigma describes one standard deviation errors of the input data points. The estimated covariance in pcov is based on these values.

The starting vector p0 can be either a list, tuple or array, or a callable that will produce a list, tuple or array. IF callable, it should take the form:

def p0_func(ydata,x=xdata):

and return a list of parameter values that is in the same order as the model function. If p0 is not given and a lmfit.Model or scipy.odr.Model is supplied as the model function, then the model’s estimates of the starting values will be used instead.

differential_evolution(model, xcol=None, ycol=None, p0=None, sigma=None, **kargs)[source]

Fit model to the data using a differential evolution algorithm.

Parameters:
  • model (lmfit.Model) – An instance of an lmfit.Model that represents the model to be fitted to the data

  • xcol (index or None) – Columns to be used for the x data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas x column

  • ycol (index or None) – Columns to be used for the y data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas y column

Keyword Arguments:
  • p0 (list, tuple, array or callable) – A vector of initial parameter values to try. See the notes in Stoner.Data.curve_fit() for more details.

  • sigma (index) – The index of the column with the y-error bars

  • bounds (callable) – A callable object that evaluates true if a row is to be included. Should be of the form f(x,y)

  • result (bool) – Determines whether the fitted data should be added into the DataFile object. If result is True then the last column will be used. If result is a string or an integer then it is used as a column index. Default to None for not adding fitted data

  • replace (bool) – Inidcatesa whether the fitted data replaces existing data or is inserted as a new column (default False)

  • header (string or None) – If this is a string then it is used as the name of the fitted data. (default None)

  • scale_covar (bool) – whether to automatically scale covariance matrix (leastsq only)

  • output (str, default "fit") – Specify what to return.

Returns:

( various )

The return value is determined by the output parameter. Options are
  • ”fit” just the lmfit.model.ModelFit instance that contains all relevant

    information about the fit.

  • ”row” just a one dimensional numpy array of the fit parameters interleaved with their

    uncertainties

  • ”full” a tuple of the fit instance and the row.

  • ”data” a copy of the Stoner.Core.DataFile object with the fit recorded in the

    emtadata and optionally as a column of data.

This function is essentially a wrapper around the scipy.optimize.differential_evolution() function that presents the same interface as the other Stoner package curve fitting functions. The parent function, however, does not provide the variance-covariance matrix to estimate the fitting errors. To work around this, this function does the initial fit with the differential evolution, but then uses that to give a starting vector to a call to scipy.optimize.curve_fit() to calculate the covariance matrix.

Example

"""Simple use of lmfit to fit data."""
from numpy import linspace, exp, random

from Stoner import Data

random.seed(12345)  # Ensure consistent random numbers!
# Make some data
x = linspace(0, 10.0, 101)
y = 2 + 4 * exp(-x / 1.7) + random.normal(scale=0.2, size=101)

d = Data(x, y, column_headers=["Time", "Signal"], setas="xy")

func = lambda x, A, B, C: A + B * exp(-x / C)


# Do the fitting and plot the result
fit = d.differential_evolution(
    func,
    result=True,
    header="Fit",
    A=1,
    B=1,
    C=1,
    prefix="Model",
    residuals=True,
)

# Reset labels
d.labels = []

# Make nice two panel plot layout
ax = d.subplot2grid((3, 1), (2, 0))
d.setas = "x..y"
d.plot(fmt="g+")
d.title = ""

ax = d.subplot2grid((3, 1), (0, 0), rowspan=2)
d.setas = "xyy"
d.plot(fmt=["r.", "b-"])
d.xticklabels = [[]]
d.xlabel = ""

# Annotate plot with fitting parameters
d.annotate_fit(func, prefix="Model", x=0.7, y=0.3, fontdict={"size": "x-small"})
text = r"$y=A+Be^{-x/C}$" + "\n\n"
d.text(7.2, 3.9, text, fontdict={"size": "x-small"})
d.title = "Differential Evolution  Fit"

(png, hires.png, pdf)

../_images/diffev1.png
lmfit(model, xcol=None, ycol=None, p0=None, sigma=None, **kargs)[source]

Wrap the lmfit module fitting.

Parameters:
  • model (lmfit.Model) – An instance of an lmfit.Model that represents the model to be fitted to the data

  • xcol (index or None) – Columns to be used for the x data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas x column

  • ycol (index or None) – Columns to be used for the y data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas y column

Keyword Arguments:
  • p0 (list, tuple, array or callable) – A vector of initial parameter values to try. See the notes in Stoner.Data.curve_fit() for more details.

  • sigma (index) – The index of the column with the y-error bars

  • bounds (callable) – A callable object that evaluates true if a row is to be included. Should be of the form f(x,y)

  • result (bool) – Determines whether the fitted data should be added into the DataFile object. If result is True then the last column will be used. If result is a string or an integer then it is used as a column index. Default to None for not adding fitted data

  • replace (bool) – Inidcatesa whether the fitted data replaces existing data or is inserted as a new column (default False)

  • header (string or None) – If this is a string then it is used as the name of the fitted data. (default None)

  • scale_covar (bool) – whether to automatically scale covariance matrix (leastsq only)

  • output (str, default "fit") – Specify what to return.

Returns:

( various )

The return value is determined by the output parameter. Options are
  • ”fit” just the lmfit.model.ModelFit instance that contains all relevant

    information about the fit.

  • ”row” just a one dimensional numpy array of the fit parameters interleaved with their

    uncertainties

  • ”full” a tuple of the fit instance and the row.

  • ”data” a copy of the Stoner.Core.DataFile object with the fit recorded in the

    emtadata and optionally as a column of data.

Note

If p0 is fed a 2D array, then it assumed that you want to calculate \(\chi^2\) for different starting parameters with some variables fixed. In this mode, fitting is carried out repeatedly with each row representing one attempt with different values of the parameters. In this mode the return value is a 2D array whose rows correspond to the inputs to the rows of p0, the columns are the fitted values of the parameters with an additional column for \(\chi^2\).

Example

"""Simple use of lmfit to fit data."""
from numpy import linspace, exp, random

from Stoner import Data

random.seed(12345)  # Ensure Consistent Random numbers
# Make some data
x = linspace(0, 10.0, 101)
y = 2 + 4 * exp(-x / 1.7) + random.normal(scale=0.2, size=101)

d = Data(x, y, column_headers=["Time", "Signal"], setas="xy")

# Do the fitting and plot the result
func = lambda x, A, B, C: A + B * exp(-x / C)
fit = d.lmfit(
    func,
    result=True,
    header="Fit",
    A=1,
    B=1,
    C=1,
    residuals=True,
    output="report",
)

# Reset labels
d.labels = []

# Make nice two panel plot layout
ax = d.subplot2grid((3, 1), (2, 0))
d.setas = "x..y"
d.plot(fmt="g+")
d.title = ""

ax = d.subplot2grid((3, 1), (0, 0), rowspan=2)
d.setas = "xyy"
d.plot(fmt=["ro", "b-"])
d.xticklabels = [[]]
d.xlabel = ""

# Annotate plot with fitting parameters
d.annotate_fit(func, prefix="Model", x=7.2, y=3, fontdict={"size": "x-small"})
text = r"$y=A+Be^{-x/C}$" + "\n\n"
d.text(7.2, 3.9, text, fontdict={"size": "x-small"})
d.title = "Levenberg-Marquardt Fit"

(png, hires.png, pdf)

../_images/lmfit2.png
odr(model, xcol=None, ycol=None, **kargs)[source]

Wrap the scipy.odr orthogonal distance regression fitting.

Parameters:
  • model (scipy.odr.Model, lmfit.models.Model or callable) – The model that describes the data. See below for more details.

  • xcol (index or None) – Columns to be used for the x data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas x column

  • ycol (index or None) – Columns to be used for the y data for the fitting. If not givem defaults to the Stoner.Core.DataFile.setas y column

Keyword Arguments:
  • p0 (list, tuple, array or callable) – A vector of initial parameter values to try. See the notes to Stoner.Data.curve_fit() for more details.

  • sigma_x (index) – The index of the column with the x-error bars

  • sigma_y (index) – The index of the column with the x-error bars

  • bounds (callable) – A callable object that evaluates true if a row is to be included. Should be of the form f(x,y)

  • result (bool) – Determines whether the fitted data should be added into the DataFile object. If result is True then the last column will be used. If result is a string or an integer then it is used as a column index. Default to None for not adding fitted data

  • replace (bool) – Inidcatesa whether the fitted data replaces existing data or is inserted as a new column (default False)

  • header (string or None) – If this is a string then it is used as the name of the fitted data. (default None)

  • output (str, default "fit") – Specify what to return.

Returns:

( various )

The return value is determined by the output parameter. Options are
  • ”fit” just the scipy.odr.Output instance (default)

  • ”row” just a one dimensional numpy array of the fit parameters interleaved with their

    uncertainties

  • ”full” a tuple of the fit instance and the row.

  • ”data” a copy of the Stoner.Core.DataFile object with the fit recorded in the

    emtadata and optionally

    as a column of data.

Notes

The function tries to make use of whatever model you give it. Specifically, it accepts:

  • A subclass or an instance of scipy.odr.Model : this is the native model type for the underlying scipy odr package.

  • A subclass or instance of an lmfit.models.Model: the Stoner.analysis.fitting.models package has a number of useful prebuilt lmfit models that can be used directly by this function.

  • A callable function which should have a signature f(x,parameter1,parameter2…) and not the scip.odr standard f(beta,x)

This function is designed to be as compatible as possible with AnalysisMixin.curve_fit() and

AnalysisMixin.lmfit() to facilitate easy of switching between them.

See also

Example

"""Simple use of lmfit to fit data."""
from numpy import linspace, exp, random

from Stoner import Data
from Stoner.plot.utils import errorfill

random.seed(12345)  # Ensure consistent random numbers!

# Make some data
x = linspace(0, 10.0, 101)
y = 2 + 4 * exp(-x / 1.7) + random.normal(scale=0.2, size=101)
x += +random.normal(scale=0.1, size=101)

d = Data(x, y, column_headers=["Time", "Signal"], setas="xy")

func = lambda x, A, B, C: A + B * exp(-x / C)

# Do the fitting and plot the result
fit = d.odr(
    func,
    result=True,
    header="Fit",
    A=1,
    B=1,
    C=1,
    prefix="Model",
    residuals=True,
)

# Reset labels
d.labels = []

# Make nice two panel plot layout
ax = d.subplot2grid((3, 1), (2, 0))
d.setas = "x..y"
d.plot(fmt="g+")
d.title = ""

# Plot up the data
ax = d.subplot2grid((3, 1), (0, 0), rowspan=2)
d.setas = "xy"
d.plot(fmt="ro")

d.setas = "x.y"
d.plot(plotter=errorfill, yerr=0.2, color="orange")
d.plot(plotter=errorfill, xerr=0.1, color="orange", label=None)
d.xticklabels = [[]]
d.xlabel = ""

# Annotate plot with fitting parameters
d.annotate_fit(func, prefix="Model", x=0.7, y=0.3, fontdict={"size": "x-small"})
text = r"$y=A+Be^{-x/C}$" + "\n\n"
d.text(7.2, 3.9, text, fontdict={"size": "x-small"})
d.title = "Orthogonal Distance Regression  Fit"

(png, hires.png, pdf)

../_images/odrfit1.png
polyfit(xcol=None, ycol=None, polynomial_order=2, bounds=<function FittingMixin.<lambda>>, result=None, replace=False, header=None)[source]

Pass through to numpy.polyfit.

Parameters:
  • xcol (index) – Index to the column in the data with the X data in it

  • ycol (index) – Index to the column int he data with the Y data in it

  • polynomial_order (int) – Order of polynomial to fit (default 2)

  • bounds (callable) – A function that evaluates True if the current row should be included in the fit

  • result (index or None) – Add the fitted data to the current data object in a new column (default don’t add)

  • replace (bool) – Overwrite or insert new data if result is not None (default False)

  • header (string or None) – Name of column_header of replacement data. Default is construct a string from the y column headser and polynomial order.

Returns:

(numpy.poly) – The best fit polynomial as a numpy.poly object.

Note

If the x or y columns are not specified (or are None) the the setas attribute is used instead.

This method is deprecated and may be removed in a future version in favour of the more general

curve_fit