/* @file  pmPSF.h
 *
 * This file contains typedefs for the Point-Spread Function and prototypes
 * for functions that calculate the PSF.
 *
 * @author EAM, IfA
 *
 * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
 * @date $Date: 2007-04-27 22:14:08 $
 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */

# ifndef PM_PSF_H
# define PM_PSF_H

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

typedef enum {
    PM_PSF_APTREND_ERROR = 0,
    PM_PSF_APTREND_NONE,
    PM_PSF_APTREND_CONSTANT,
    PM_PSF_APTREND_SKYBIAS,
    PM_PSF_APTREND_SKYSAT,
    PM_PSF_APTREND_XY_LIN,
    PM_PSF_APTREND_XY_QUAD,
    PM_PSF_APTREND_SKY_XY_LIN,
    PM_PSF_APTREND_SKYSAT_XY_LIN,
    PM_PSF_APTREND_ALL
} pmPSFApTrendOptions;

/** pmPSF data structure
 * 
 * It is useful to generate a model to define the point-spread-function which
 * describes the flux distribution for unresolved sources in an image. In
 * general, the PSF varies with position in the image. We allow any of the source
 * models defined for the pmModel to represent the PSF. For a given source model,
 * the 2D spatial variation of all of the source parameters, except the first
 * four PSF-independent parameters, are represented as polynomial, stored in a
 * psArray. The other elements of the structure define the quality of the PSF
 * determination.
 * 
 */
typedef struct
{
    pmModelType type;   ///< PSF Model in use
    psArray *params_NEW;   ///< Model parameters (psPolynomial2D)
    // XXXXX I am changing params: we will allocate elements for the
    // unfitted elements (So, Io, Xo, Yo) and leave them as NULL
    // I am using a new name to catch all refs to params with gcc
    psPolynomial1D *ChiTrend;	      ///< Chisq vs flux fit (correction for systematic errors)
    psPolynomial4D *ApTrend;		///< ApResid vs (x,y,rflux) (rflux = ten(0.4*mInst))
    float ApResid;			///< apMag - psfMag (for PSF stars)
    float dApResid;			///< scatter of ApResid
    float skyBias;			///< implied residual sky offset from ApResid fit
    float skySat;			///< roll-over of ApResid fit
    float chisq;			///< PSF goodness statistic (unused??)
    int nPSFstars;			///< number of stars used to measure PSF
    int nApResid;			///< number of stars used to measure ApResid
    bool poissonErrors;
    pmGrowthCurve *growth;		///< apMag vs Radius
    pmResiduals *residuals;		///< normalized residual image (no spatial variation)
}
pmPSF;

# define PM_PAR_E0 PM_PAR_SXX
# define PM_PAR_E1 PM_PAR_SYY
# define PM_PAR_E2 PM_PAR_SXY

/**
 * 
 * Allocator for the pmPSF structure.
 * 
 */
pmPSF *pmPSFAlloc(
    pmModelType type,     // type of model for PSF
    bool poissonErrors,
    psPolynomial2D *psfTrendMask
);

/**
 * 
 * This function constructs a pmModel instance based on the pmPSF description
 * of the PSF. The input is a pmModel with at least the values of the centroid
 * coordinates (possibly normalization if this is needed) defined. The values of
 * the PSF-dependent parameters are specified for the specific realization based
 * on the coordinates of the object.
 * 
 */
pmModel *pmModelFromPSF(
    pmModel *model,                     ///< Add comment
    pmPSF *psf                          ///< Add comment
);

bool pmPSFMaskApTrend (psPolynomial4D *trend, pmPSFApTrendOptions option);

pmPSFApTrendOptions pmPSFApTrendOptionFromName (char *name);

double pmPSF_SXYfromModel (psF32 *modelPar);
double pmPSF_SXYtoModel (psF32 *fittedPar);

bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore);
pmPSF *pmPSFBuildSimple (char *typeName, float sxx, float syy, float sxy, ...);

bool pmPSF_AxesToModel (psF32 *modelPar, psEllipseAxes axes);
psEllipseAxes pmPSF_ModelToAxes (psF32 *modelPar, double maxAR);
bool pmPSF_FitToModel (psF32 *fittedPar, float minMinorAxis);
psEllipsePol pmPSF_ModelToFit (psF32 *modelPar);

/// @}
# endif
