#include <CFit.h> class CFit : public CNamedItem { public: struct Point { double x; double y; int operator==(const Point& rhs) const; int operator!=(const Point& rhs) const; }; typedef std::vector<Point> PointArray; typedef PointArray::iterator PointIterator; typedef std::pair<std::string, double> FitParameter; typedef std::vector<FitParameter> FitParameterList; typedef FitParameterList::iterator FitParameterIterator; typedef enum { Accepting, Performed } FitState; //!< State of the fit. void AddPoint (Point p) ; PointIterator begin () ; PointIterator end () ; size_t size () ; FitState GetState () const ; virtual CFit* clone() = 0; virtual void Perform () = 0 ; virtual double operator() (double x) =0 ; virtual FitParameterList GetParameters () =0 ; virtual std::string Type() const = 0; protected: void SetFitState(FitState state) ; };
SpecTcl has an extensible fitting program. Fits can be created and updated based on the current data. SpecTcl also interacts with the display program to display any fits on appropriate spectra, if that display program is capable of that.
The core of the fitting subsystem is the CFit
abstract base class. Each object that performs a fit must be a
concrete class derived from CFit
Fits are stateful objects. There are two states a fit can
be in. The Accepting state means that the
fit has had at least one point added without a call to
Perform
. In this state the fit parameters
cannot be retrieved. Once Perform
is called,
the fit is in the Performed state and the fit
parameters can be extracted from the object.
Note that since CFit
is a
CNamedItem
, it inherits a constructor
that have name and id as parameters.
The class defines a few contained data types. By contained, we mean a data type that is defined inside the class definition. Contained data type names must be resolved in the scope of the class. E.g. PointArray a; will cause a compiler error but CFit::PointArray a; will not.
Point
a data point.
The Point
struct represents a point
of data that needs to be fitted. For spectrum fits, each
point is a channel coordinate (x
)
and the counts in that channel (y
).
At present, SpecTcl fits are restricted to 1-d data sets.
x
The X coordinate of the point. Normally this represents a channel number in the spectrum being fitted.
y
The Y coordinate of the point. Normally this is the
number of points in the channel selected by
x
.
const int operator==(const Point& rhs);
Returns non zero (1) if
the x
and
y
fields of the
Point
referred to by
rhs
are equal to that of this
object.
const int operator!=(const Point& rhs);
Inverse of operator==
.
Point
PointArray objects maintain the set of points gathered for a fit.
Support iteration in the container that defines PointArray. Using iterators rather than indexing allows software to be written independent of the actual underlying container that is PointArray.
Fit parameters are a bit tricky. Each fit type will have its own set of parameters. Thus a fit parameter is defined not just by its value but by its meaning in the context of the fit type.
typedef std::pair<std::string, double> FitParameter represents a single fit parameter. The first part of the pair is a name that identifies the meaning of the parameter. The second part of the pair is the value itself. For example, for a linear fit, the first item of the pair might be the string slope and the second part the fitted slope.
Most fits have more than one parameter. Therefore: typedef std::vector<FitParameter> FitParameterList is a container of fit parameters.
In order to allow the container type to change later;
FitParameterList instances should not be indexed.
Instead, use iterators defined by
typedef FitParameterList::iterator FitParameterIterator.
FitParameterList instances have the standard
iterator support methods begin
and end
to support this.
Fit objects are stateful. They distinguish between accepting points and having fit those points. The fit state is captured by FitState which is an enumerated type with the following values:
The fit is in the process of accepting points.
If it has sufficient points;
Perform
can be invoked.
In this state, the fit is not able to deliver fit parameters.
The fit has been performed and can deliver
parameters. This is the state right after a call
to Perform
and before the
fit is invalidated by adding more points.
void AddPoint (Point p);
Adds a point to the internal list of points. This places the object in the Accepting state, if it's not already in that state.
PointIterator begin();
,
PointIterator end();
,
size_t size();
These three methods support iteration over the internal
PointArray. Iteration is supported in the
same sense as for C++ container types. At present,
the iterator returned is a pointer like object that
points to a Point
struct.
begin
returns an iterator that
'points' to the beginning of the
PointArray. end
returns an iterator pointing just off the end of the
PointArray. size
returns the number of points in that container.
const FitState GetState ();
Returns the current fit state. This has been previously described.
virtual = 0 CFit* clone();
Pure virtual method that is supposed to dynamically create a copy of this object. If the object supports copy construction, this is like a virtual copy constructor and can be implemented like this:
CFit* CMyFitType::clone() { return new CMyFitType(*this); }
virtual = 0 void Perform();
Performs the fit with the set of points that have been added to the object. An exception should be thrown if there are not sufficient points to determine the fit.
If the fit is successfully performed, this method
should invoke SetFitState
to set the new fit state to Performed.
virtual =0 double operator() (double x);
If the fit is not in the Performed
state this method should throw an exception. If the
fit has been performed, this method should return the
value of the fit function evaluated at
x
.
virtual =0 FitParameterList GetParameters();
If the fit is not in the Performed state this should throw an exception. Otherwise it should return the fit specific list of fit parameters. Note that one of them should always be (regardless of fit type) chisquare, the Chi Square goodness of fit.
virtual const = 0; std::string Type();
Returns a textual fit type. This should be
a string descriptive of the fit; e.g.
gaussian is returned by
CGaussianFit
.
protected void SetFitState(FitState state);
Allows concrete subclasses to set the fit state.
In all cases, this should be used by
Perform
to set the state to
Performed once the fit is actually
computed.