/** @file  pmObjects.h
 *
 *  This file will ...
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.7.2.1 $ $Name: rel5_1 $
 *  @date $Date: 2005/04/06 19:34:06 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 *
 */

#if !defined(PM_OBJECTS_H)
#define PM_OBJECTS_H

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include<stdio.h>
#include<math.h>
#include "pslib.h"

typedef enum {
    PM_PEAK_LONE,           ///< Isolated peak.
    PM_PEAK_EDGE,           ///< Peak on edge.
    PM_PEAK_FLAT,           ///< Peak has equal-value neighbors.
    PM_PEAK_UNDEF           ///< Undefined.
} psPeakType;

typedef struct
{
    psS32 x;                ///< X-coordinate of peak pixel.
    psS32 y;                ///< Y-coordinate of peak pixel.
    psF32 counts;           ///< Value of peak pixel (above sky?).
    psPeakType class;       ///< Description of peak.
}
psPeak;

typedef struct
{
    psF32 x;                ///< X-coord of centroid.
    psF32 y;                ///< Y-coord of centroid.
    psF32 Sx;               ///< x-second moment.
    psF32 Sy;               ///< y-second moment.
    psF32 Sxy;              ///< xy cross moment.
    psF32 Sum;              ///< Pixel sum above sky (background).
    psF32 Peak;             ///< Peak counts above sky.
    psF32 Sky;              ///< Sky level (background).
    psS32 nPixels;          ///< Number of pixels used.
}
psMoments;

typedef enum {
    PS_MODEL_GAUSS,			///< Regular 2-D Gaussian
    PS_MODEL_PGAUSS,  ///< Psuedo 2-D Gaussian
    PS_MODEL_TWIST_GAUSS, ///< 2-D Twisted Gaussian
    PS_MODEL_WAUSS,  ///< 2-D Waussian
    PS_MODEL_SERSIC,  ///< Sersic
    PS_MODEL_SERSIC_CORE, ///< Sersic Core
    PS_MODEL_UNDEFINED  ///< Undefined
} psModelType;

// XXX: It will be better if params, and dparams, were psVectors.
typedef struct
{
    psModelType type;       ///< Model to be used.
    psVector *params;       ///< Paramater values.
    psVector *dparams;      ///< Parameter errors.
    psF32 chisq;            ///< Fit chi-squared.
    psS32 nDOF;             ///< number of degrees of freedom
    psS32 nIter;            ///< number of iterations to reach min
}
psModel;

// XXX: What is this enum?
typedef enum {
    PS_SOURCE_PSFSTAR,
    PS_SOURCE_GALAXY,
    PS_SOURCE_DEFECT,
    PS_SOURCE_SATURATED,
    PS_SOURCE_SATSTAR,
    PS_SOURCE_FAINTSTAR,
    PS_SOURCE_BRIGHTSTAR,
    PS_SOURCE_OTHER
} psSourceType;

typedef struct
{
    psPeak *peak;           ///< Description of peak pixel.
    psImage *pixels;        ///< Rectangular region including object pixels.
    psImage *mask;          ///< Mask which marks pixels associated with objects.
    psMoments *moments;     ///< Basic moments measure for the object.
    psModel *models;        ///< Model parameters and type.
    psSourceType type;      ///< Best identification of object.
}
psSource;

psPeak *pmPeakAlloc(psS32 x,  ///< Row-coordinate in image space
                    psS32 y,  ///< Col-coordinate in image space
                    psF32 counts, ///< The value of the peak pixel
                    psPeakType class ///< The type of peak pixel
                   );

psMoments *pmMomentsAlloc();
psModel *pmModelAlloc(psModelType type);
psSource *pmSourceAlloc();

/******************************************************************************
pmFindVectorPeaks(vector, threshold): Find all local peaks in the given vector
above the given threshold.  Returns a vector of type PS_TYPE_U32 containing
the location (x value) of all peaks.
 *****************************************************************************/
psVector *pmFindVectorPeaks(const psVector *vector, ///< The input vector (psF32)
                            psF32 threshold  ///< Threshold above which to find a peak
                           );

/******************************************************************************
pmFindImagePeaks(image, threshold): Find all local peaks in the given psImage
above the given threshold.  Returns a psList containing the location (x/y
value) of all peaks.
 *****************************************************************************/
psArray *pmFindImagePeaks(const psImage *image, ///< The input image where peaks will be found (psF32)
                         psF32 threshold ///< Threshold above which to find a peak
                        );

/******************************************************************************
psCullPeaks(peaks, maxValue, valid): eliminate peaks from the psList that have
a peak value above the given maximum, or fall outside the valid region.
 
XXX: Do we free the psList elements of those culled peaks?
 *****************************************************************************/
psList *pmCullPeaks(psList *peaks,  ///< The psList of peaks to be culled
                    psF32 maxValue,  ///< Cull peaks above this value
                    const psRegion *valid ///< Cull peaks otside this psRegion
                   );

/******************************************************************************
psSource *pmSourceLocalSky(image, peak, innerRadius, outerRadius):
 
 *****************************************************************************/
psSource *pmSourceLocalSky(const psImage *image, ///< The input image (psF32)
                           const psPeak *peak,  ///< The peak for which the psSource struct is created.
                           psStatsOptions statsOptions, ///< The statistic used in calculating the background sky
                           psF32 innerRadius,  ///< The inner radius of the suqare annulus for calculating sky
                           psF32 outerRadius  ///< The outer radius of the suqare annulus for calculating sky
                          );

/******************************************************************************
 *****************************************************************************/
psSource *pmSourceMoments(psSource *source, ///< The input psSource for which moments will be computed
                          psF32 radius  ///< Use a circle of pixels around the peak
                         );

/******************************************************************************
pmSourceRoughClass(pmArray *source, psMetaDeta *metadata): make a guess at the
source classification.
 *****************************************************************************/
bool pmSourceRoughClass(psArray *source, ///< The input psSource
                        psMetadata *metadata ///< Contains classification parameters
                       );
/******************************************************************************
pmSourceSetPixelCircle(source, image, radius)
 *****************************************************************************/
bool pmSourceSetPixelCircle(psSource *source,  ///< The input psSource
                            const psImage *image, ///< The input image (psF32)
                            psF32 radius  ///< The radius of the circle
                           );

/******************************************************************************
 *****************************************************************************/
bool pmSourceModelGuess(psSource *source, ///< The input psSource
                        const psImage *image, ///< The input image (psF32)
                        psModelType model ///< The type of model to be created.
                       );

/******************************************************************************
 *****************************************************************************/
typedef enum {
    PS_CONTOUR_CRUDE,
} pmContourType;

psArray *pmSourceContour(psSource *source, ///< The input psSource
                         const psImage *image, ///< The input image (psF32) (this arg should be removed)
                         psF32 level,  ///< The level of the contour
                         pmContourType mode ///< Currently this must be PS_CONTOUR_CRUDE
                        );

/******************************************************************************
 *****************************************************************************/
bool pmSourceFitModel(psSource *source,  ///< The input psSource
                      const psImage *image ///< The input image (psF32)
                     );

/******************************************************************************
 *****************************************************************************/
bool pmSourceAddModel(psImage *image,  ///< The opuut image (psF32)
                      psSource *source,  ///< The input psSource
                      bool center  ///< A boolean flag that determines whether pixels are centered
                     );

/******************************************************************************
 *****************************************************************************/
bool pmSourceSubModel(psImage *image,  ///< The output image (psF32)
                      psSource *source,  ///< The input psSource
                      bool center  ///< A boolean flag that determines whether pixels are centered
                     );

/******************************************************************************
XXX: Why only *x argument?
XXX EAM: psMinimizeLMChi2Func returns psF64, not psF32
 *****************************************************************************/
psF64 pmMinLM_Gauss2D(psVector *deriv,  ///< A possibly-NULL structure for the output derivatives
                      psVector *params,  ///< A psVector which holds the parameters of this function
                      psVector *x  ///< A psVector which holds the row/col coordinate
                     );

/******************************************************************************
XXX: Why only *x argument?
 *****************************************************************************/
psF64 pmMinLM_PsuedoGauss2D(psVector *deriv, ///< A possibly-NULL structure for the output derivatives
                            psVector *params, ///< A psVector which holds the parameters of this function
                            psVector *x  ///< A psVector which holds the row/col coordinate
                           );

/******************************************************************************
 *****************************************************************************/
psF64 pmMinLM_Wauss2D(psVector *deriv,  ///< A possibly-NULL structure for the output derivatives
                      psVector *params,  ///< A psVector which holds the parameters of this function
                      psVector *x  ///< A psVector which holds the row/col coordinate
                     );

/******************************************************************************
 *****************************************************************************/
psF64 pmMinLM_TwistGauss2D(psVector *deriv, ///< A possibly-NULL structure for the output derivatives
                           psVector *params, ///< A psVector which holds the parameters of this function
                           psVector *x  ///< A psVector which holds the row/col coordinate
                          );

/******************************************************************************
 *****************************************************************************/
psF64 pmMinLM_Sersic(psVector *deriv,  ///< A possibly-NULL structure for the output derivatives
                     psVector *params,  ///< A psVector which holds the parameters of this function
                     psVector *x  ///< A psVector which holds the row/col coordinate
                    );

/******************************************************************************
 *****************************************************************************/
psF64 pmMinLM_SersicCore(psVector *deriv, ///< A possibly-NULL structure for the output derivatives
                         psVector *params, ///< A psVector which holds the parameters of this function
                         psVector *x  ///< A psVector which holds the row/col coordinate
                        );

/******************************************************************************
 *****************************************************************************/
psF64 pmMinLM_PsuedoSersic(psVector *deriv, ///< A possibly-NULL structure for the output derivatives
                           psVector *params, ///< A psVector which holds the parameters of this function
                           psVector *x  ///< A psVector which holds the row/col coordinate
                          );


#endif
