CurveFitting.py

Add custom curves to the list of builtins that's available when you right-click a figure and choose "Curve fitting".

Fitting is done by nonlinear least-squares regression. You can provide an analytic derivative or let it do numerical derivatives.

fitters

a dictionary mapping curve name to the implementing class. The implementing class should be a subclass of NLFitter. An instance of this class is created when the user chooses the curve type.

class NLFitter:

__init__( self )

Don't forget to call this from your subclass's constructor

initParams( self, nParamToFit, param_0, param_1, ... )

nParamToFit      only this many params will be fit; the rest can be used as outputs; e.g. curve area in GaussFit.py
param_i      a tuple: (name, initial_val, min_val, max_val)

Subclasses must call this in their constructor.

initComponent( self, param )

param      a qubtree.Node containing one child per parameter.

Override in your subclass to set appropriate param values for a new component. See GaussFit.py for an example.

getEqn( self )

Override in your subclass to provide a string representation of the curve to the user.

setParamsFromData( self )

Override in your subclass to provide appropriate param values for the data in self.X and self.Y.
Change the param vals in self.params (a
qubtree.Node).

func( self, paramvals, x )

paramvals      a list of param vals for one component, in the order passed to initParams()
x      the x value at which to evaluate the function

You must override in your subclass. Calculates the function value of one component at x.

deriv( self, paramvals, x )

paramvals      a list of param vals for one component, in the order passed to initParams()
x      the x value at which to evaluate the derivatives

You must override in your subclass. Calculates the derivative of one component at x, w.r.t. each param. Returns a list in the same order as paramvals.

onFitDone( self )

Called by fit(), just before it returns. Override in your subclass if you want to do any post-processing; e.g. to determine the fraction of area under each component.

promptOptions( self )

Displays a dialog box with curve-specific options. Override in your subclass if you've got your own options.

fit( self, maxIter, precision )

maxIter      stop looking after this many iterations
precision      stop looking when the residuals are less than this

Uses
func and deriv to find the best param values, then calls onFitDone. You probably don't want to override this one.

setNumComponents( self, n )

Change the number of components to fit. Any added components will be initialized using initComponent.

Certain pathological curves, e.g. linear regression, must override this to prevent an invalid number of curves from being set. The rest of y'all can leave it be.

getNumComponents( self )

Returns the number of components to fit.

getParamList( self, component_i )

Converts one component's parameters from the qubtree at self.params[ component_i ] into a list of values.

updateParamLists( self )

Makes sure the lists returned by getParamList() are up to date.
(for speed, they are stored and ordinarily not recomputed.)

useData( self, dataset )

dataset      a qubtree.Node with children "X" and "Y"
Gives the fitter a data series to fit, then calls
setParamsFromData.

getCurves( self, curves )

Fills the qub tree curves with children named "Component".
The first "Component" is the sum of the rest, so there are getNumComponents() + 1 of them.
Each "Component" has data of length len(self.X).

If the "Component"s already exist, they will be re-used. Typically, consumers in the GUI re-use the same curves tree each time the params change.