/* @file pmFPA.h
 * @brief Defines the focal plane hierarchy, along with functions for interacting with it
 *
 * @author George Gusciora, MHPCC
 * @author Paul Price, IfA
 * @author Eugene Magnier, IfA
 *
 * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
 * @date $Date: 2007-01-24 02:54:14 $
 * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
 */

#ifndef PM_FPA_H
#define PM_FPA_H

/// @addtogroup Camera Camera Layout
/// @{

#include <pslib.h>
#include "pmHDU.h"

#define FPA_ASTROM 1                    ///< Include astrometry information in the structures?

/// Focal plane array (the entirety of the camera)
///
/// The FPA is the top-level camera structure, and consists of one or more chips.  It also contains the
/// concepts metadata appropriate to this level, a summary of analysis tasks that have been performed, the
/// camera configuration information, any HDU that corresponds to this level for the file of interest, and
/// astrometric transformations.  The astrometric transformations encode how to transform from the tangent
/// plane to the sky, and back.
typedef struct
{
    #if FPA_ASTROM
    // Astrometric transformations
    psPlaneTransform *fromTPA;  ///< Transformation from tangent plane to focal plane, or NULL
    psPlaneTransform *toTPA;  ///< Transformation from focal plane to tangent plane, or NULL
    psProjection *toSky;         ///< Projection from tangent plane to sky, or NULL
    #endif
    // Information
    psMetadata *concepts;               ///< FPA-level concepts
    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
    psMetadata *analysis;               ///< FPA-level analysis metadata
    const psMetadata *camera;           ///< Camera configuration
    psArray *chips;                     ///< The component chips
    pmHDU *hdu;                         ///< FITS header data unit of interest, or NULL
}
pmFPA;

/// A chip (contiguous detector element)
///
/// The chip is the mid-level camera structure, being part of an FPA, and consisting of one or more cells
/// (e.g., a CCD).  It also contains the concepts metadata appropriate to this level, a summary of analysis
/// tasks that have been performed, status flags, any HDU that corresponds to this level for the file of
/// interest, and astrometric transformations.  The astrometric transformations provide transforms between the
/// chip and FPA coordinates and back.
typedef struct
{
    #if FPA_ASTROM
    // Astrometric transformations
    psPlaneTransform *toFPA;            ///< Transformation from chip to FPA coordinates, or NULL
    psPlaneTransform *fromFPA;          ///< Transformation from FPA to chip coordinates, or NULL
    #endif
    // Information
    psMetadata *concepts;               ///< Chip-level concepts
    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
    psMetadata *analysis;               ///< Chip-level analysis metadata
    psArray *cells;                     ///< The component cells
    pmFPA *parent;                      ///< Parent FPA
    bool process;                       ///< Do we bother about reading and working with this chip?
    bool file_exists;                   ///< Does the file for this chip exist (read case only)?
    bool data_exists;                   ///< Does the data for this chip exist (read case only)?
    pmHDU *hdu;                         ///< FITS header data unit of interest,
}
pmChip;

/// A cell (smallest logical unit)
///
/// A cell is the lowest-level camera structure, being part of a chip (e.g., an amplifier).  It may consist of
/// one or more readouts, which are individual reads of the cell.  It also contains the concepts metadata
/// appropriate to this level, the cell configuration information (for convenience) from the camera
/// configuration, a summary of analysis tasks that have been performed, status flags, and any HDU that
/// corresponds to this level for the file of interest

/** 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
{
    psMetadata *concepts;               ///< Cell-level concepts
    unsigned int conceptsRead;          ///< Which concepts have been read; see pmConceptsSource
    psMetadata *config;                 ///< Cell configuration information (from CELLS in the camera config)
    psMetadata *analysis;               ///< Cell-level analysis metadata
    psArray *readouts;                  ///< The component readouts
    pmChip *parent;                     ///< Parent chip
    bool process;                       ///< Do we bother about reading and working with this cell?
    bool file_exists;                   ///< Does the file for this cell exist (read case only)?
    bool data_exists;                   ///< Does the data for this cell exist (read case only)?
    pmHDU *hdu;                         ///< FITS header data unit of interest
}
pmCell;

/// A readout (individual read of a cell)
///
/// A readout corresponds to an individual read of a cell (e.g., a single image as part of a video sequence,
/// or one of multiple coadds).  It contains the actual pixels used in analysis (along with mask and weight
/// maps).  When reading from a FITS file, the images are subimages (from CELL.TRIMSEC) of the pixels read
/// from the appropriate HDU (at the FPA, chip or cell level).  The readout also contains a list of bias
/// sections (prescans or overscans, or otherwise), a summary of analysis tasks that have been performed,
/// status flags, and the offsets used for reading a FITS file incrementally.
typedef struct
{
    int col0;                           ///< Column offset; non-zero if reading in columns incrementally
    int row0;                           ///< Row offset; non-zero if reading in rows incrementally
    psImage *image;                     ///< Imaging area of readout (corresponds to CELL.TRIMSEC region)
    psImage *mask;                      ///< Mask of input image (corresponds to CELL.TRIMSEC region)
    psImage *weight;                    ///< Weight of input image (corresponds to CELL.TRIMSEC region)
    psList *bias;                       ///< List of bias (prescan/overscan) images
    psMetadata *analysis;               ///< Readout-level analysis metadata
    pmCell *parent;                     ///< Parent cell
    bool process;                       ///< Do we bother about reading and working with this readout?
    bool file_exists;                   ///< Does the file for this readout exist (read case only)?
    bool data_exists;                   ///< Does the data for this readout exist (read case only)?
}
pmReadout;

/// Free all readouts within a cell
void pmCellFreeReadouts(pmCell *cell    ///< Cell for which to free readouts
                       );

/// Free all cells within a chip
void pmChipFreeCells(pmChip *chip       ///< Chip for which to free cells
                    );

/// Free all data within a readout
void pmReadoutFreeData(pmReadout *readout ///< Readout for which to free data
                      );

/// Free all data within a cell (all readouts as well as metadata)
void pmCellFreeData(pmCell *cell        ///< Cell for which to free data
                   );

/// Free all data within a chip (all cells as well as metadata)
void pmChipFreeData(pmChip *chip        ///< Chip for which to free data
                   );

/// Free all data within an FPA (all chips as well as metadata)
void pmFPAFreeData(pmFPA *fpa           ///< FPA for which to free data
                  );

/// Allocate a readout associated with a cell
pmReadout *pmReadoutAlloc(pmCell *cell  ///< Parent cell, or NULL
                         );

/// Allocate a cell associated with a chip
///
/// The name is used to set CELL.NAME within the concepts.
pmCell *pmCellAlloc(pmChip *chip,       ///< Parent chip, or NULL
                    const char *name    ///< Name of cell, for CELL.NAME
                   );

/// Allocate a chip associated with an FPA
///
/// The name is used to set CHIP.NAME within the concepts
pmChip *pmChipAlloc(pmFPA *fpa,         ///< Parent FPA, or NULL
                    const char *name    ///< Name of chip, for CHIP.NAME
                   );

/// Allocate an FPA
pmFPA *pmFPAAlloc(const psMetadata *camera ///< Camera configuration (to store in FPA)
                 );


/// Check parent links within an FPA
///
/// Iterates through the FPA to verify that the "parent" links in the chip, cell and readout are set
/// correctly.  If there are any incorrect links, they are fixed, and the function returns false.
bool pmFPACheckParents(pmFPA *fpa       ///< FPA to check
                      );
/// @}
#endif // #ifndef PM_FPA_H
