/* @file  pmModelGroup.h
 *
 * The object model function types are desined to allow for the flexible addition of new object
 * models. Every object model, with parameters represented by pmModel, has an associated set of
 * functions which provide necessary support operations. A set of abstract functions allow the
 * programmer to select the approriate function or property for a specific named object model.
 *
 * Every model instance belongs to a class of models, defined by the value of
 * the pmModelType type entry. Various functions need access to information about
 * each of the models. Some of this information varies from model to model, and
 * may depend on the current parameter values or other data quantities. In order
 * to keep the code from requiring the information about each model to be coded
 * into the low-level fitting routines, we define a collection of functions which
 * allow us to abstract this type of model-dependent information. These generic
 * functions take the model type and return the corresponding function pointer
 * for the specified model. Each model is defined by creating this collection of
 * specific functions, and placing them in a single file for each model. We
 * define the following structure to carry the collection of information about
 * the models.
 *
 * @author EAM, IfA
 *
 * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
 * @date $Date: 2007-11-10 01:09:20 $
 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */

# ifndef PM_MODEL_GROUP_H
# define PM_MODEL_GROUP_H

/// @addtogroup Objects Object Detection / Analysis Functions
/// @{

//  This function is the model chi-square minimization function for this model.
typedef psMinimizeLMChi2Func pmModelFunc;

//  This function sets the parameter limits for this model.
typedef psMinimizeLMLimitFunc pmModelLimits;

// This function returns the integrated flux for the given model parameters.
typedef psF64 (*pmModelFlux)(const psVector *params);

// This function returns the radius at which the given model and parameters
// achieves the given flux.
typedef psF64 (*pmModelRadius)(const psVector *params, double flux);

//  This function provides the model guess parameters based on the details of
//  the given source.
typedef bool (*pmModelGuessFunc)(pmModel *model, pmSource *source);

//  This function constructs the PSF model for the given source based on the
//  supplied psf and the EXT model for the object.
typedef bool (*pmModelFromPSFFunc)(pmModel *modelPSF, pmModel *modelEXT, pmPSF *psf);

//  This function sets the model parameters based on the PSF for a given coordinate and central
//  intensity
typedef bool (*pmModelParamsFromPSF)(pmModel *model, pmPSF *psf, float Xo, float Yo, float Io);

//  This function returns the success / failure status of the given model fit
typedef bool (*pmModelFitStatusFunc)(pmModel *model);

typedef struct
{
    char *name;
    int nParams;
    pmModelFunc          modelFunc;
    pmModelFlux          modelFlux;
    pmModelRadius        modelRadius;
    pmModelLimits        modelLimits;
    pmModelGuessFunc     modelGuessFunc;
    pmModelFromPSFFunc   modelFromPSFFunc;
    pmModelParamsFromPSF modelParamsFromPSF;
    pmModelFitStatusFunc modelFitStatusFunc;
}
pmModelGroup;

// allocate a pmModelGroup to hold nModels entries
pmModelGroup *pmModelGroupAlloc (int nModels);

bool psMemCheckModelGroup(psPtr ptr);

// initialize the internal (static) model group with the default models
bool pmModelGroupInit (void);

// free the internal (static) model group
void pmModelGroupCleanup (void);

// add a new model to the internal (static) model group
void pmModelGroupAdd (pmModelGroup *model);

/* This function returns the number of parameters used by the listed function.
 */
int pmModelParameterCount(
    pmModelType type                    ///< Add comment.
);


/* This function returns the user-space model names for the specified model type.
 */
char *pmModelGetType(
    pmModelType type                    ///< Add comment.
);


/**
 * 
 * This function returns the internal model type code for the user-space model names.
 * 
 */
pmModelType pmModelSetType(
    char *name                          ///< Add comment.
);

/**
 * 
 *  Each of the function types above has a corresponding function which returns
 *  the function given the model type:
 * 
 */

/**
 * 
 * pmModelFunc is the function used to determine the value of the model at a
 * specific coordinate, and is the one used by psMinimizeLMChi2.
 * 
 */
pmModelFunc          pmModelFunc_GetFunction (pmModelType type);


/**
 * 
 * pmModelFlux returns the total integrated flux for the given input parameters.
 * 
 */
pmModelFlux          pmModelFlux_GetFunction (pmModelType type);


/**
 * 
 * pmModelRadius returns the scaling radius at which the flux of the model
 * matches the specified flux. This presumes that the model is a function of an
 * elliptical contour.
 * 
 */
pmModelRadius        pmModelRadius_GetFunction (pmModelType type);


/**
 * 
 * pmModelLimits sets the parameter limit vectors for the function.
 * 
 */
pmModelLimits        pmModelLimits_GetFunction (pmModelType type);


/**
 * 
 * pmModelGuessFunc generates an initial guess for the model based on the
 * provided source statistics (moments and pixel values as needed).
 * 
 */
pmModelGuessFunc     pmModelGuessFunc_GetFunction (pmModelType type);


/**
 * 
 * pmModelFromPSFFunc takes as input a representation of the psf and a value
 * for the model and fills in the PSF parameters of the model. The input
 * primarily relies upon the centroid coordinates of the input model, though the
 * normalization may potentially be used.
 * 
 */
pmModelFromPSFFunc   pmModelFromPSFFunc_GetFunction (pmModelType type);


/**
 * 
 * pmModelFitStatusFunc returns a true or false values based on the success or
 * failure of a model fit.  The success is determined by quantities such as the
 * chisq or the signal-to-noise.
 * 
 */
pmModelFitStatusFunc pmModelFitStatusFunc_GetFunction (pmModelType type);


/** pmSourceModelGuess()
 *
 * Convert available data to an initial guess for the given model. This
 * function allocates a pmModel entry for the pmSource structure based on the
 * provided model selection. The method of defining the model parameter guesses
 * are specified for each model below. The guess values are placed in the model
 * parameters. The function returns TRUE on success or FALSE on failure.
 *
 */
pmModel *pmSourceModelGuess(
    pmSource *source,   ///< The input pmSource
    pmModelType model   ///< The type of model to be created.
);

/// @}
# endif /* PM_MODEL_GROUP_H */
