nscl_logo_small.gif (2463 bytes)

Extending SpecTcl's fitting subsystem

HH00706_.jpg (6530 bytes)
Programmer's guide

Background

The SpecTcl fit subsystem is extensible. This means that it is possible for users to add custom fit types to the program. This section describes enough of the structure of the SpecTcl fitting subsystem to give you a basic understanding of the steps needed to add a new fit type. The second section of this page describes the step-by-step procedure for adding a new fit type to SpecTcl.

The SpecTcl Fit command is based on several interacting classes. The ones which matter to you are:

How to create a new fit type

The steps you must follow to create a new fit type are to:

  1. Write a new fit class that implements the new fit type.
  2. Write a new fit creator class that creates an instance (object) of the class on behalf of the factory.
  3. Register your fit creator with the fit factory so that it knows when to ask it to create a fit object.
  4. Incorporate all your new code into your tailored SpecTcl and build it.

The CFit class:

The part of the CFit abstract base class interface you need to be concerned with is shown below:

class CFit : public  CNamedItem     
{
  // Public data types.
public:
  struct Point {                // A point for the fit.

    double x;
    double y;
  };
  typedef std::vector PointArray; // Point array is a std::vector of points.
  typedef PointArray::iterator PointIterator;

  typedef std::pair FitParameter;
  typedef std::vector FitParameterList;
  typedef FitParameterList::iterator FitParameterIterator;

  typedef enum {
    Accepting,
    Performed
  } FitState;                   //!< State of the fit.
public:
  CFit (std::string name, int id = 0);          // Constructor.
  
protected:
  void SetFitState(FitState state);

// Class operations:

public:
  
  

  void AddPoint (Point p)   ; 
  void ClearPoints();
  PointIterator begin ()   ; 
  PointIterator end ()   ; 
  size_t size ()   ; 
  FitState GetState ()  const ; 

 
  
 
  // Pure virtual functions must be implemented by
  // subclasses.

  virtual CFit* clone() = 0;
  virtual   void Perform ()   = 0 ; 
  virtual  double operator() (double x)  =0 ; 
  virtual  FitParameterList GetParameters () =0  ; 
  virtual  std::string Type() const  = 0;
  virtual  std::string makeTclFitScript() = 0;
 
};
Note that the entire class definition is in <CFit.h>.

Your job will be to implement the pure virtual members of this class:
clone This member function should return a new fit object that is a functional copy of *this. In general, if you have implemented a copy constructor, this can be implemented as:
return new CMyFitType(*this);
where you must substitute your own fit type for the CMyFitType class above.
Perform Perform the fit. The fit points can be gotten by iterating through them using begin(), and end(). Once successfully performed, SetFitState must be called to set the fit state to CFit::Performed.
operator() Is expected to return the value of the fit evaluated at its parameter. If the fit has not yet been performed, this should throw an error. Note that FitState can be called to determine if the fit has been performed.
GetParameters Should return the list of parameter name value pairs for the fit. If the fit has not yet been performed, this shouldthrow an errror.
Type Must return a string that is the same as the fit type (e.g. the gaussian fit returns "gaussian").
makeTclFitScript This function must return a Tcl script named fitline that takes a single parameter and returns the height of the fit at that channel.

The CFitCreator class

Fit creator objects are used by the fit factory to generate the correct type of fit object. In order to add a fit type you will need to create your fit class, and a class that is subclassed from CFitCreator that creates a new object of your fit type.

The fit creator class has the following key interfaces:

class CFitCreator      
{
public:
  
  virtual   CFit* operator() (std::string name, int id=0)   = 0 ; 
  virtual   std::string DescribeFit()  = 0;
};

Your fit creator subclass must implement the pure virtual functions as follows:
operator() Create and return a new fit of the type you are implementing. Usually this is done as follows:
return new CMyFit(name id) ;
where you must substitute the name of your fit type for CMyFit.
DescribeFit Should return a string that describes the fit type that this creator creates e.g. "gaussianl - Gaussian fit on a linear background".

Registering your fit creator

Once you have written the classes descdribed above, you must make your fit type known to the fit factory. This is done by associating your fit creator with a fit type keyword. To do this, in your MySpecTclApp.cpp file, in some function such as AddCommands, add a call to CFitCreator::AddFitType e.g:

    CFitCreator::AddFitType(string("myfitform"), new CMyFitCreator());

Last Modified: October 23, 2006
by: fox@nscl.msu.edu Copyright NSCL 1999, All rights reserved