#ifndef _FITTER_H_
#define _FITTER_H_


/*
 * Base Class for Numerical Fitters  --  Draft 1
 *
 * To build the documentation, do
 *   doc++ fitter.h
 *
 * (C) 1997 Patrick Schemitz
 * KOrigin (C) 1997 Patrick Schemitz, Martin Häfner
 *
 */


#include <qlist.h>
#include <kconfig.h>
#include "column.h"


class QPopupMenu;


/** Abstract Base Class for Generic Fitters.
	
	This is as generic as possible, just an interface to (hopefully) *any*
	kind of fitter.

	The basic idea is the following. What do fitter have in common?

	They all take input data and create output data, in form of columns of
	numbers. This has been taken into account by providing the functions
	setInputColumns() and setOutputColumns().

	The number of columns they take as input and fill as output, however,
	varies, as does the meaning of the columns. In respect to this, the
	functions getInputColumnCount(), getOutputColumnCount(),
	getInputColumnName(), and getOutputColumnName() have been made
	pure virtual: each fitter must implement them for itself.

	Every fitter might offer some specific options, which can be queried
	in some dialogs as well as stored/retrieved to/from a config file.
	to offer this functionality, the pure virtual functions
	execOptionsDialog(), saveSettings(), and loadSettings() have been
	introducted.

	Finally, every fitter must actually *do* something, namely a fit.
	Therefore, a pure virtual function, fit() has been declared, and
	each fit must implement it.

	For an example for a fit, see the @ref LinearRegression fitter.

	@see LinearRegression
	@author Patrick Schemitz
*/

class Fitter
{
public:
  /** Default constructor.

	  Just initializes some pointers to zero.
  */
  Fitter ();

  /** Destructor - just to ensure that it is virtual.

	  Fitters are destroyed by deleting Fitter pointers. Since these
	  actually point to concrete (derived) fitters which may have their
	  own destructors, the destructor of the base class must be declared
	  virtual, even if it doesn't do anything.
  */
  virtual ~Fitter ();

  /** [pure virtual] Return the concrete fitter's name.

	  @return the fitters name for the "Fit" menu entry.
  */
  virtual const char* name () = 0;

  /** Pop up the fitter's options dialog box.

	  The (derived) concrete fitter must implement it's own Options
	  dialog, of course. That's why this is pure virtual.

	  @return Your implementation should just pass on the return code from QDialog::exec()
  */
  virtual int execOptionsDialog () = 0;

  /** [pure virtual] Returns the number of columns a fitter takes for input.

	  A linear regression fitter would take two columns, namely x and y,
	  for input.

	  @return Number of columns the fitter takes for input.
  */
  virtual int getInputColumnCount () = 0;

  /** [pure virtual] Returns the number of columns a fitter fills with its
	  output.

	  A linear regression fitter would fill one column, y_linear, as output.
	  Note that the caller has to create those columns! They are _not_
	  created by the Fitter!

	  @return Number of columns the fitter fills with output.
  */
  virtual int getOutputColumnCount () = 0;

  /** [pure virtual] Returns the symbolic name of the ith input column the
	  fitter takes.

	  For a linear regression fitter, this would be "X" for i=0 and "Y"
	  for i=1.

	  @return Name of the ith input column.
  */
  virtual const char* getInputColumnName (int i) = 0;

  /** [pure virtual] Returns the symbolic name of the ith output column the
	  fitter fills.

	  For a linear regression fitter, this would be "YLinear" for i=0.

	  @return Name of the ith output column.
  */
  virtual const char* getOutputColumnName (int i) = 0;

  /** [pure virtual] Defines what columns the fitter should take for input.

	  The array of columns passed to this function is taken as
	  input data for the fitter. For an interpretation of the ith
	  entry of the array, check the description returned by
	  getInputColumnName().

	  The caller is responsible for deleting the columns! Not the fit!

	  @param col_array the array of columns to be taken as input data.
	  @see #getInputColumnCount()
	  @see #getInputColumnName(int)
	  @see #setOutputColumns(DoubleColumn*)
  */
  void setInputColumns (Column* col_array);

  /** [pure virtual] Defines the columns to be filled by the fitter.

	  The columns passed to this functions will be taken as output
	  buffer, i.e. the fitter will fill them with the results of the
	  fit. A linear regression fitter would fill its single output
	  column with the fitted y values for the appropriate x (input)
	  value. However, a non-linear fitter would most likely also
	  fill a column with its own x values, since the input x values
	  might be too coarse to make sense with fitted y values. It is
	  important to understand that the columns in the output buffer
	  are not necessarily of the same length as the input columns. A
	  fitter might decide that it needs a finer x stepwidth and create
	  a grid with dx=0.01 whereas the input columns have dx=0.1. With
	  self-expanding columns, this is a plug to implement.

	  In analogy with setInputColumns(), the columns handed to this
	  function must already exist (though they might be empty). Their
	  meaning can be obtained by getOutputColumnName().

	  The caller is responsible for deleting the columns! Not the fit!

	  @param col_array the array of columns to be filled by the fitter.
	  @see #getOutputColumnCount()
	  @see #getOutputColumnName(int)
	  @see #setInputColumns(DoubleColumn*)
  */
  void setOutputColumns (Column* col_array);

  /** [pure virtual] The actual fitting function.

	  This is the core of the fitter. In here, the actual fitting algorithm
	  is implemented. Or, as a matter of fact, the derived concrete fitter
	  must implement it here. Please do _not_ do any dialogs here! This
	  function might get called as a thread of its own later. (Currently,
	  it blocks the program.)
  */
  virtual bool fit () = 0;

  /** [pure virtual] Save fitter-specific settings to the configuration file.

	  If your fitter has some specific settings, your implementation of
	  this function's got the chance to store them in Korigins config
	  file. A neuronal net fitter might save the (maximum) number of
	  nodes; an iterative fitter might save some epsilons.
	  Of course, the implementation of this function must match
	  loadSettings().

	  @param conf pointer to Korigins KConfig instance.
	  @see #loadSettings()
	*/
  virtual void saveSettings (KConfig* conf) = 0;

  /** [pure virtual] Load fitter-specific settings from the configuration
	  file.

	  If your fitter has some specific settings, your implementation of
	  this function's got the chance to restore them from Korigins config
	  file. A neuronal net fitter might load the (maximum) number of
	  nodes; an iterative fitter might retrieve some epsilons.
	  Of course, the implementation of this function must match
	  saveSettings().

	  @param conf pointer to Korigins KConfig instance.
	  @see #saveSettings()
	*/
  virtual void loadSettings (KConfig* conf) = 0;

  /** Main menu entry for the Fitters.

	  This function builds the main menu entry "Fit".

	  @see #getFitterOptionsMenu()
  */
  static QPopupMenu* getFitterMenu ();

  /** Options menu entry for the Fitters.

	  This function builds the menu entry "Options|Fitter".

	  @see #getFitterMenu()
  */
  static QPopupMenu* getFitterOptionsMenu ();

protected:

  /** Input data for the fitter.

	  This array, filled by the caller and used by the fitter,
	  contains the input data for the fit. The implementation of
	  fit() will read it. Note that it must be deleted by the caller,
	  not by the destructor.

	  @see #setInputColumns()
	  @see #fit()
  */
  Column* inputColumns;

  /** Output buffer for the fitter.

	  This array, provided by the caller, is filled during the
	  fit(). Note that it must be deleted by the caller, not by
	  the destructor!

	  @see #setOutputColumns()
	  @see #fit()
  */
  Column* outputColumns;

private:
  /** Copy constructor is locked.
	  Fitters should not be copied, so I've locked away the copy
	  constructor.
  */
  Fitter (const Fitter&);

  /** Assignment operator is locked.
	  Fitters should not be copied, so I've locked away the assignment
	  operator.
  */
  Fitter& operator= (const Fitter&);
};


/** Type for the Fitter list.

	This is just a template instatiation of Qt's QList for
	a list of Fitters. Intelligent as the QList is, it actually
	stores a list of pointers, which is exactly what we want here,
	since class Fitter is abstract, so it cannot be instantiated.

	@see Fitters()
*/
typedef QList<Fitter> FitterList;

/** The list of all fitters.

	The FitterList returned by this function contains a list of all
	fitters linked to Korigin. The list is filled by using the
	REGISTER_FITTER macro in your concrete fitter module.

	The fitter list is implemented in a Singleton pattern, because if I
	had it implemented as a global variable, I'ld have run into trouble
	with the initialization order of global instances -- which is
	undefined in the C++ standard. Actually, I had it implemented this
	way initially, but then the order files were linked together was
	important. (Took me quite a bit of time to figure out why.)

	@see FitterList
	@see REGISTER_FITTER
	@return list of all fitters.
*/
FitterList& Fitters ();


/** For internal use only!

	This is an auxillary class. Needed because Qt only allows to connect
	to instances but not to global functions. I had to put this in the
	header because I need to run the moc on it. (And a separate header
	for one method is ridiculous.)

	@author Patrick Schemitz
*/

class FitHelper : public QObject
{
  Q_OBJECT
public slots:
  /// Slot for the Options||Fitter menu entry.
  void execFitterOptions(int i);
};


/** Registers *your* fitter in the fitter list.

	Use this macro in the .cc file of your fitter module to register
	your new concrete fitter to Korigin. If you forget to do so, your
	fitter will not be accessible from Korigin.

	Usage:

	class MyFitter : public Fitter { ... };
	REGISTER_FITTER(MyFitter);

	(Don't forget the semicolon after REGISTER_FITTER!)

	@see Fitters
	@see FitterList
*/
#define REGISTER_FITTER(type)                  \
                                               \
  class Registrator##type {                    \
  public:                                      \
    Registrator##type () {                     \
      Fitters().append(new type);              \
    }                                          \
  };                                           \
                                               \
  static Registrator##type _register##type


#endif

Documentation generated by mh@jeff_clever on Thu Feb 5 14:15:25 MET 1998