/** @file  pmFPA.h
*
*  @brief This file defines the basic types the focal plane hierarchy.
*
*  @ingroup AstroImage
*
*  @author GLG, MHPCC
*
*  @version $Revision: 1.1.4.1 $ $Name: not supported by cvs2svn $
*  @date $Date: 2006-02-17 17:13:41 $
*
*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
*/

#ifndef PM_FPA_H
#define PM_FPA_H
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include "pslib.h"
#include "psDB.h"

/// @addtogroup AstroImage
/// @{

// XXX: Is this correct?  Must determine what p_pmHDU is.
// XXX: Create the p_pmHDU alloc/free.
typedef struct
{
    const char *extname;                // Extension name, if it corresponds to this level
    psMetadata *header;                 // The FITS header, if it corresponds to this level
    psArray *images;                    // The pixel data, if it corresponds to this level
    psArray *masks;                     // The mask data, if it corresponds to this level
    psArray *weights;                   // The weight data, if it corresponds to this level
}
p_pmHDU;

/** Focal plane data structure
 *
 *  A focal plane consists of one or more chips (according to the number of
 *  pieces of contiguous silicon). It contains metadata containers for the
 *  concepts and analysis, a link to the parent, and pointers to the FITS header,
 *  if that corresponds to this level (the FPA may be the PHU, but will not ever
 *  contain pixels). For astrometry, it contains a transformation from the focal
 *  plane to the tangent plane and the fixed pattern residuals. It is expected
 *  that the transformation will consist of two 4D polynomials (i.e. a function
 *  of two coordinates in position, the magnitude of the object, and the color of
 *  the object) in order to correct for optical distortions and the effects of
 *  the atmosphere; hence we think that it is prudent to include a reverse
 *  transformation which will be derived from numerically inverting the forward
 *  transformation.
 *
 */
typedef struct
{
    // Astrometric transformations
    psPlaneDistort* fromTangentPlane;   ///< Transformation from tangent plane to focal plane
    psPlaneDistort* toTangentPlane;     ///< Transformation from focal plane to tangent plane
    psProjection *projection;           ///< Projection from tangent plane to sky
    // Information
    psMetadata *concepts;               ///< Cache for PS concepts
    psMetadata *analysis;               ///< FPA-level analysis metadata
    const psMetadata *camera;           ///< Camera configuration
    psArray *chips;                     ///< The chips
    p_pmHDU *hdu;                       ///< FITS data
    psMetadata *phu;                    ///< Primary Header
}
pmFPA;

/** Chip data structure
 *
 *  A chip consists of one or more cells (according to the number of amplifiers
 *  on the device). The chip contains metadata containers for the concepts and
 *  analysis, a link to the parent, and pointers to the pointers to the various
 *  FITS data, if that corresponds to this level. For astrometry, in addition to
 *  the rough positioning information, it contains a coordinate transform from
 *  the chip to the focal plane. It is expected that this transform will consist
 *  of two second-order 2D polynomials; hence we think that it is prudent to
 *  include a reverse transformation which will be derived from numerically
 *  inverting the forward transformation. A boolean indicates whether the chip is
 *  of interest, allowing it to be excluded from analysis.
 *
 */
typedef struct
{
    // Offset specifying position on focal plane
    int col0;                           ///< Offset from the left of FPA.
    int row0;                           ///< Offset from the bottom of FPA.
    // Astrometric transformations
    psPlaneTransform* toFPA;            ///< Transformation from chip to FPA coordinates
    psPlaneTransform* fromFPA;          ///< Transformation from FPA to chip coordinates
    // Information
    psMetadata *concepts;               ///< Cache for PS concepts
    psMetadata *analysis;               ///< Chip-level analysis metadata
    psArray *cells;                     ///< The cells (referred to by name)
    pmFPA *parent;                      ///< Parent FPA
    bool process;                       ///< Do we bother about reading and working with this chip?
    bool exists;                        ///< Does the chip exist --- has it been read in?
    p_pmHDU *hdu;                       ///< FITS data
}
pmChip;

/** Cell data structure
 *
 *  A cell consists of one or more readouts.  It also contains a pointer to the
 *  cell's metadata, and its parent chip.  On the astrometry side, it also
 *  contains coordinate transforms from the cell to chip, from the cell to
 *  focal-plane, as well as a "quick and dirty" tranform from the cell to
 *  sky coordinates.
 *
 */
typedef struct
{
    // Offset specifying position on chip
    int col0;                           ///< Offset from the left of chip.
    int row0;                           ///< Offset from the bottom of chip.
    // Astrometric transformations
    psPlaneTransform* toChip;           ///< Transformations from cell to chip coordinates
    psPlaneTransform* toFPA;            ///< Transformations from cell to FPA coordinates
    psPlaneTransform* toSky;            ///< Transformations from cell to sky coordinates
    // Information
    psMetadata *concepts;               ///< Cache for PS concepts
    psMetadata *camera;                 ///< Camera Info
    psMetadata *analysis;               ///< Cell-level analysis metadata
    psArray *readouts;                  ///< The readouts (referred to by number)
    pmChip *parent;                     ///< Parent chip
    bool process;                       ///< Do we bother about reading and working with this cell?
    bool exists;                        ///< Does the cell exist --- has it been read in?
    p_pmHDU *hdu;                       ///< FITS data
}
pmCell;

/** Readout data structure.
 *
 *  A readout is the result of a single read of a cell (or a portion thereof).
 *  It contains the offset from the lower-left corner of the chip, in the case
 *  that the CCD was windowed, as well as the binning factors and parity (if the
 *  binning value is negative, then the parity is reversed). It also contains the
 *  pixel data, metadata containers for the concepts and analysis, and a link to
 *  the parent.
 *
 */
typedef struct
{
    // Position on the cell
    // XXX: These may be removed in the future; use parent->concepts instead?
    int col0;                           ///< Offset from the left of chip.
    int row0;                           ///< Offset from the bottom of chip.
    int colBins;                        ///< Amount of binning in x-dimension
    int rowBins;                        ///< Amount of binning in y-dimension
    // Information
    psImage *image;                     ///< Imaging area of readout
    psImage *mask;                      ///< Mask of input image
    psImage *weight;                    ///< Weight of input image
    psList *bias;                       ///< Overscan images
    psMetadata *analysis;               ///< Readout-level analysis metadata
    pmCell *parent;                     ///< Parent cell
}
pmReadout;

void pmCellFreeReadouts(pmCell *cell);
void pmChipFreeCells(pmChip *chip);

/** Allocates a pmReadout
 *
 *  The constructor shall make an empty pmReadout. If the parent cell is not
 *  NULL, the parent link is made and the readout shall be placed in the
 *  parents array of readouts. The metadata containers shall be allocated. All
 *  other pointers in the structure shall be initialized to NULL.
 *
 *  @return pmReadout*    newly allocated pmReadout with all internal pointers set to NULL
 */
pmReadout *pmReadoutAlloc(
    pmCell *cell                        ///< Parent cell
);

/** Allocates a pmCell
 *
 *  The constructor shall make an empty pmCell. If the parent chip is not NULL,
 *  the parent link is made and the cell shall be placed in the parents array of
 *  cells. The readouts array shall be allocated with a zero size, and the
 *  metadata containers constructed. All other pointers in the structure shall be
 *  initialized to NULL.
 *
 *  @return pmCell*    newly allocated pmCell
 */
pmCell *pmCellAlloc(
    pmChip *chip,       ///< Parent chip
    psMetadata *cameraData, ///< Camera data
    const char *name    ///< Name of cell
);

/** Allocates a pmChip
 *
 *  The constructor shall make an empty pmChip. If the parent fpa is not NULL,
 *  the parent link is made and the chip shall be placed in the parent's array
 *  of chips. The cells array shall be allocated with a zero size, and the
 *  metadata containers constructed. All other pointers in the structure shall be
 *  initialized to NULL.
 *
 *  @return pmChip*    newly allocated pmChip
 */
pmChip *pmChipAlloc(
    pmFPA *fpa,                         ///< FPA to which the chip belongs
    const char *name                    ///< Name of chip
);

/** Allocates a pmFPA
 *
 *  The constructor shall make an empty pmFPA. The chips array shall be
 *  allocated with a zero size, the camera and db pointers set to the values
 *  provided, and the concepts metadata constructed. All other pointers in the
 *  structure shall be initialized to NULL.
 *
 */
pmFPA *pmFPAAlloc(
    const psMetadata *camera            ///< Camera configuration
);

/** Allocates a p_pmHDU
 *
 * XXX: More detailed description
 *
 * @return p_pmHDU*    newly allocated p_pmHDU
 */
p_pmHDU *p_pmHDUAlloc(const char *extname // Extension name
                     );


/** Verify parent links.
 *
 *  This function checks the validity of the parent links in the FPA hierarchy.
 *  If a parent link is not set (or not set correctly), it is corrected, and the
 *  function shall return false. If all the parent pointers were correct, the
 *  function shall return true.
 *
 */
bool pmFPACheckParents(
    pmFPA *fpa
);



/** FUNC DESC
 *
 *
 *
 *
 */



/**
 *
 * pmFPASelectChip shall set valid to true for the specified chip number
 * (chipNum), and all other chips shall have valid set to false. In the event
 * that the specified chip number does not exist within the fpa, the function
 * shall return false.
 *
 */
bool pmFPASelectChip(
    pmFPA *fpa,
    int chipNum
);

bool pmChipSelectCell(pmChip *chip,
                      int cellNum
                     );

/**
 *
 * pmFPAExcludeChip shall set valid to false only for the specified chip
 * number (chipNum). In the event that the specified chip number does not exist
 * within the fpa, the function shall generate a warning, and perform no action.
 * The function shall return the number of chips within the fpa that have valid
 * set to true.
 *
 */
int pmFPAExcludeChip(
    pmFPA *fpa,
    int chipNum
);

int pmChipExcludeCell(pmChip *chip,
                      int cellNum
                     );

// Set the weights and masks within a cell, based on the gain and RN
bool pmCellSetWeights(pmCell *cell // Cell for which to set weights
                     );



#endif // #ifndef PM_FPA_H
