/** @file  pmPSF.h
 *
 * This file contains typedefs for the Point-Spread Function and prototypes
 * for functions that calculate the PSF.
 *
 *  @author EAM, IfA
 *
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 *
 */

# ifndef PM_PSF_H
# define PM_PSF_H

/** 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;   ///< Model parameters (psPolynomial2D)
    psPolynomial1D *ChiTrend;  ///< Chisq vs flux fit (correction for systematic errors)
    psPolynomial4D *ApTrend;  ///< ApResid vs (x,y,rflux) (rflux = ten(0.4*mInst))
    //pmGrowthCurve *growth;  ///< apMag vs Radius // move to end as gdb is confused by it here
    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
}
pmPSF;

typedef enum {
    PM_PSF_NONE,
    PM_PSF_CONSTANT,
    PM_PSF_SKYBIAS,
    PM_PSF_SKYSAT,
    PM_PSF_XY_LIN,
    PM_PSF_XY_QUAD,
    PM_PSF_SKY_XY_LIN,
    PM_PSF_SKYSAT_XY_LIN,
    PM_PSF_ALL
} pmPSF_ApTrendOptions;

/**
 * 
 * Allocator for the pmPSF structure.
 * 
 */
pmPSF *pmPSFAlloc(
    pmModelType type,   // type of model for PSF
    bool poissonErrors   ///< use poissonian errors or not?
);


/**
 * 
 * This function takes a collection of pmModel fitted models from across a
 * single image and builds a pmPSF representation of the PSF. The input array of
 * model fits may consist of entries to be ignored (noted by a non-zero mask
 * entry). The analysis of the models fits a 2D polynomial for each parameter to
 * the collection of model parameters as a function of position (and
 * normalization?). In this process, some of the input models may be marked as
 * outliers and excluded from the fit. These elements will be marked with a
 * specific mask value (1 == PSFTRY_MASK_OUTLIER).
 * 
 */
bool pmPSFFromModels(
    pmPSF *psf,                         ///< Add comment
    psArray *models,                    ///< Add comment
    psVector *mask                      ///< Add comment
);


/**
 * 
 * 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 pmPSF_MaskApTrend (psPolynomial4D *trend, pmPSF_ApTrendOptions option);

# endif
