/** @file  pmSource.h
 *
 *  @author EAM, IfA; GLG, MHPCC
 *
 *  @version $Revision: 1.1.2.4 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2006-04-19 06:31:55 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 *
 */

# ifndef PM_SOURCE_H
# define PM_SOURCE_H

/**
 * In the object analysis process, we will use specific mask values to mark the
 * image pixels. The following structure defines the relevant mask values.
 *
 * XXX: This is probably a bad solution: we will want to set mask values
 * outside of the PSPHOT code.  Perhaps we can set up a registered set of mask
 * values with specific meanings that other functions can add to or define?
 */

/*
typedef enum {
    PM_SOURCE_MASK_CLEAR     = 0x00,
    PM_SOURCE_MASK_INVALID   = 0x01,
    PM_SOURCE_MASK_SATURATED = 0x02,
    PM_SOURCE_MASK_MARKED    = 0x08,
} psphotMaskValues;
*/

/** pmSourceType enumeration
 *
 * A given source may be identified as most-likely to be one of several source
 * types. The pmSource entry pmSourceType defines the current best-guess for this
 * source.
 *
 * XXX: The values given below are currently illustrative and will require
 * some modification as the source classification code is developed. (TBD)
 *
 */
typedef enum {
    PM_SOURCE_TYPE_UNKNOWN,  ///< a cosmic-ray
    PM_SOURCE_TYPE_DEFECT,  ///< a cosmic-ray
    PM_SOURCE_TYPE_SATURATED,  ///< random saturated pixels
    PM_SOURCE_TYPE_STAR,  ///< a good-quality star
    PM_SOURCE_TYPE_EXTENDED,  ///< an extended object (eg, galaxy)
} pmSourceType;

typedef enum {
    PM_SOURCE_MODE_DEFAULT    = 0x0000, ///<
    PM_SOURCE_MODE_PSFMODEL   = 0x0001, ///<
    PM_SOURCE_MODE_EXTMODEL   = 0x0002, ///<
    PM_SOURCE_MODE_SUBTRACTED = 0x0004, ///<
    PM_SOURCE_MODE_FITTED     = 0x0008, ///<
    PM_SOURCE_MODE_FAIL       = 0x0010, ///<
    PM_SOURCE_MODE_POOR       = 0x0020, ///<
    PM_SOURCE_MODE_PAIR       = 0x0040, ///<
    PM_SOURCE_MODE_PSFSTAR    = 0x0080, ///<
    PM_SOURCE_MODE_SATSTAR    = 0x0100, ///<
    PM_SOURCE_MODE_BLEND      = 0x0200, ///<
    PM_SOURCE_MODE_LINEAR     = 0x0400, ///<
    PM_SOURCE_MODE_TEMPSUB    = 0x0800, ///< XXX get me a better name!
} pmSourceMode;

/** pmSource data structure
 *
 *  This source has the capacity for several types of measurements. The
 *  simplest measurement of a source is the location and flux of the peak pixel
 *  associated with the source:
 *
 */
typedef struct
{
    pmPeak *peak;   ///< Description of peak pixel.
    psImage *pixels;   ///< Rectangular region including object pixels.
    psImage *weight;   ///< Image variance.
    psImage *mask;   ///< Mask which marks pixels associated with objects.
    pmMoments *moments;   ///< Basic moments measure for the object.
    pmModel *modelPSF;   ///< PSF Model fit (parameters and type)
    pmModel *modelEXT;   ///< EXT (floating) Model fit (parameters and type).
    pmSourceType type;   ///< Best identification of object.
    pmSourceMode mode;   ///< Best identification of object.
    psArray *blends;
    float psfMag;
    float extMag;
    float errMag;
    float apMag;
    float pixWeight;   // model-weighted coverage of valid pixels
    psRegion region;   // area on image covered by selected pixels
}
pmSource;

/** pmPSFClump data structure
 *
 * A collection of object moment measurements can be used to determine
 * approximate object classes. The key to this analysis is the location and
 * statistics (in the second-moment plane,
 *
 */
typedef struct
{
    float X;
    float dX;
    float Y;
    float dY;
}
pmPSFClump;


/** pmSourceAlloc()
 *
 */
pmSource  *pmSourceAlloc();


/** pmSourceDefinePixels()
 *
 * Define psImage subarrays for the source located at coordinates x,y on the
 * image set defined by readout. The pixels defined by this operation consist of
 * a square window (of full width 2Radius+1) centered on the pixel which contains
 * the given coordinate, in the frame of the readout. The window is defined to
 * have limits which are valid within the boundary of the readout image, thus if
 * the radius would fall outside the image pixels, the subimage is truncated to
 * only consist of valid pixels. If readout->mask or readout->weight are not
 * NULL, matching subimages are defined for those images as well. This function
 * fails if no valid pixels can be defined (x or y less than Radius, for
 * example). This function should be used to define a region of interest around a
 * source, including both source and sky pixels.
 *
 */
bool pmSourceDefinePixels(
    pmSource *mySource,                 ///< source to be re-defined
    const pmReadout *readout,  ///< base the source on this readout
    psF32 x,                            ///< center coords of source
    psF32 y,                            ///< center coords of source
    psF32 Radius                        ///< size of box on source
);

bool pmSourceRedefinePixels (
    pmSource *mySource,   ///< source to be re-defined
    const pmReadout *readout,   ///< base the source on this readout
    psF32 x,     ///< center coords of source
    psF32 y,      ///< center coords of source
    psF32 Radius   ///< size of box on source
);

/** pmSourcePSFClump()
 *
 * We use the source moments to make an initial, approximate source
 * classification, and as part of the information needed to build a PSF model for
 * the image. As long as the PSF shape does not vary excessively across the
 * image, the sources which are represented by a PSF (the start) will have very
 * similar second moments. The function pmSourcePSFClump searches a collection of
 * sources with measured moments for a group with moments which are all very
 * similar. The function returns a pmPSFClump structure, representing the
 * centroid and size of the clump in the sigma_x, sigma_y second-moment plane.
 *
 * The goal is to identify and characterize the stellar clump within the
 * sigma_x, sigma_y second-moment plane.  To do this, an image is constructed to
 * represent this plane.  The units of sigma_x and sigma_y are in image pixels. A
 * pixel in this analysis image represents 0.1 pixels in the input image. The
 * dimensions of the image need only be 10 pixels. The peak pixel in this image
 * (above a threshold of half of the image maximum) is found. The coordinates of
 * this peak pixel represent the 2D mode of the sigma_x, sigma_y distribution.
 * The sources with sigma_x, sigma_y within 0.2 pixels of this value are then
 *  * used to calculate the median and standard deviation of the sigma_x, sigma_y
 * values. These resulting values are returned via the pmPSFClump structure.
 *
 * The return value indicates the success (TRUE) of the operation.
 *
 * XXX: Limit the S/N of the candidate sources (part of Metadata)? (TBD).
 * XXX: Save the clump parameters on the Metadata (TBD)
 *
 */
pmPSFClump pmSourcePSFClump(
    psArray *source,   ///< The input pmSource
    psMetadata *metadata  ///< Contains classification parameters
);


/** pmSourceRoughClass()
 *
 * Based on the specified data values, make a guess at the source
 * classification. The sources are provides as a psArray of pmSource entries.
 * Definable parameters needed to make the classification are provided to the
 * routine with the psMetadata structure. The rules (in SDRS) refer to values which
 * can be extracted from the metadata using the given keywords. Except as noted,
 * the data type for these parameters are psF32.
 *
 */
bool pmSourceRoughClass(
    psArray *source,   ///< The input pmSource
    psMetadata *metadata,  ///< Contains classification parameters
    pmPSFClump clump   ///< Statistics about the PSF clump
);


/** pmSourceMoments()
 *
 * Measure source moments for the given source, using the value of
 * source.moments.sky provided as the local background value and the peak
 * coordinates as the initial source location. The resulting moment values are
 * applied to the source.moments entry, and the source is returned. The moments
 * are measured within the given circular radius of the source.peak coordinates.
 * The return value indicates the success (TRUE) of the operation.
 *
 */
bool pmSourceMoments(
    pmSource *source,   ///< The input pmSource for which moments will be computed
    float radius   ///< Use a circle of pixels around the peak
);


// select the model used for this source
pmModel *pmSourceSelectModel (pmSource *source);

# endif /* PM_SOURCE_H */
