/* @file pmFPAHeader.h
 * @brief Functions read FITS headers for FPA components
 *
 * @author Paul Price, IfA
 * @author Eugene Magnier, IfA
 *
 * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
 * @date $Date: 2009-02-06 02:31:24 $
 * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
 */

#ifndef PM_FPA_MASK_WEIGHT_H
#define PM_FPA_MASK_WEIGHT_H

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

#if 0
/// Pixel mask values
typedef enum {
    PM_MASK_CLEAR    = 0x00,            ///< The pixel is not masked
    PM_MASK_BLANK    = 0x01,            ///< The pixel is blank or has no (valid) data
    PM_MASK_FLAT     = 0x02,            ///< The pixel is non-positive in the flat-field
    PM_MASK_DETECTOR = 0x02,            ///< The detector pixel is bad (e.g., bad column, charge trap)
    PM_MASK_SAT      = 0x04,            ///< The pixel is saturated in the image of interest
    PM_MASK_BAD      = 0x04,            ///< The pixel is low in the image of interest
    PM_MASK_RANGE    = 0x04,            ///< The pixel is out of range in the image of interest
    PM_MASK_CR       = 0x08,            ///< The pixel is probably a CR
    PM_MASK_SPARE1   = 0x10,            ///< Spare mask value
    PM_MASK_SPARE2   = 0x20,            ///< Spare mask value
    PM_MASK_SUSPECT  = 0x40,            ///< The pixel is suspected of being bad, but may not be
    PM_MASK_MARK     = 0x80,            ///< The pixel is marked as temporarily ignored
} pmMaskValue;
#define PM_MASK_MARK 0x80            ///< The pixel is marked as temporarily ignored
#define PM_MASK_SAT  0x04            ///< The pixel is saturated in the image of interest
#endif

/// Set a temporary readout mask using CELL.SATURATION and CELL.BAD
///
/// Identifies pixels that are saturated (>= CELL.SATURATION) or bad (<= CELL.BAD).  The mask that is produced
/// within the readout is temporary --- it is not added to the HDU.  This is intended for when the user is
/// iterating using pmReadoutReadNext, in which case the HDU can't be generated.
bool pmReadoutSetMask(pmReadout *readout, ///< Readout for which to set mask
                      psImageMaskType satMask, ///< Mask value to give saturated pixels
                      psImageMaskType badMask  ///< Mask value to give bad (low) pixels
    );


/// Set a temporary readout variance map using CELL.GAIN and CELL.READNOISE
///
/// Calculates variances for each pixel using photon statistics and the cell gain (CELL.GAIN) and read noise
/// (CELL.READNOISE).  The weight map that is produced within the readout is temporary --- it is not added to
/// the HDU.  This is intended for when the user is iterating using pmReadoutReadNext, in which case the HDU
/// can't be generated.
bool pmReadoutSetVariance(pmReadout *readout, ///< Readout for which to set variance
                          bool poisson    ///< Include poisson variance (in addition to read noise)?
    );

/// Generate a readout mask (suitable for output) using CELL.SATURATION and CELL.BAD
///
/// Identifies pixels that are saturated (>= CELL.SATURATION) or bad (<= CELL.BAD).  The mask that is produced
/// is suitable for output (complete with HDU entry).  This is intended for most operations.
bool pmReadoutGenerateMask(pmReadout *readout, ///< Readout for which to generate mask
                           psImageMaskType sat, ///< Mask value to give saturated pixels
                           psImageMaskType bad ///< Mask value to give bad (low) pixels
    );

/// Generate a variance map (suitable for output) using CELL.GAIN and CELL.READNOISE
///
/// Calculates variances for each pixel using photon statistics and the cell gain (CELL.GAIN) and read noise
/// (CELL.READNOISE).  The variance map that is produced within the readout is suitable for output (complete
/// with HDU entry).  This is intended for most operations.
bool pmReadoutGenerateVariance(pmReadout *readout, ///< Readout for which to generate variance
                               bool poisson    ///< Include poisson variance (in addition to read noise)?
    );

/// Generate mask and variance map for a readout
///
/// Calls pmReadoutGenerateMask and pmReadoutGenerateVariance for the readout
bool pmReadoutGenerateMaskVariance(pmReadout *readout, ///< Readout for which to generate mask and variance
                                   psImageMaskType sat, ///< Mask value to give saturated pixels
                                   psImageMaskType bad, ///< Mask value to give bad (low) pixels
                                   bool poisson ///< Include poisson variance (in addition to read noise)?
    );

/// Generate mask and variance maps for all readouts within a cell
///
/// Calls pmReadoutGenerateMaskVariance for each readout within the cell.
bool pmCellGenerateMaskVariance(pmCell *cell, ///< Cell for which to generate mask and variance
                                psImageMaskType sat, ///< Mask value to give saturated pixels
                                psImageMaskType bad, ///< Mask value to give bad (low) pixels
                                bool poisson ///< Include poisson variance (in addition to read noise)?
    );

/// Renormalise the variance map to match the actual pixel variance
///
/// The variance map is adjusted so that the mean matches the actual pixel variance in the image
bool pmReadoutVarianceRenormPixels(
    const pmReadout *readout,           ///< Readout to normalise
    psImageMaskType maskVal,                 ///< Value to mask
    psStatsOptions meanStat,            ///< Statistic to measure the mean (of the variance map)
    psStatsOptions stdevStat,           ///< Statistic to measure the stdev (of the image)
    psRandom *rng                       ///< Random number generator
    );

/// Renormalise the variance map to match the actual photometry variance
///
/// The variance map is adjusted so that the actual significance of fake sources matches the
/// guestimated significance
bool pmReadoutVarianceRenormPhot(
    const pmReadout *readout,           ///< Readout to normalise
    psImageMaskType maskVal,            ///< Value to mask
    int num,                            ///< Number of instances to measure over the image
    float width,                        ///< Photometry width
    psStatsOptions meanStat,            ///< Statistic to measure the mean
    psStatsOptions stdevStat,           ///< Statistic to measure the stdev
    psRandom *rng                       ///< Random number generator
    );

/// Renormalise the variance map to match the actual variance
///
/// The variance in the image is measured in patches, and the variance map is adjusted so that the mean for
/// that patch corresponds.
bool pmReadoutVarianceRenorm(const pmReadout *readout, // Readout to normalise
                             psImageMaskType maskVal, // Value to mask
                             psStatsOptions meanStat, // Statistic to measure the mean (of the variance map)
                             psStatsOptions stdevStat, // Statistic to measure the stdev (of the image)
                             int width,   // Width of patch (pixels)
                             psRandom *rng // Random number generator (for sub-sampling images)
    );

/// Explicitly mask non-finite pixels
///
/// Since unmasked non-finite pixels can occur (e.g., by out-of-range in quantisation), it is sometimes
/// necessary to mask them explicitly.  Non-finite pixels in the image or variance have their mask OR-ed with
/// the provided value.
bool pmReadoutMaskNonfinite(pmReadout *readout, ///< Readout to mask
                            psImageMaskType maskVal ///< Mask value to give non-finite pixels
    );

/// Apply a mask to the image and variance map
///
/// Unfortunately, image subtraction may result in a bi-modal image in masked areas, which can upset image
/// statistics (very important for quantising images so that a product can be written out!).  This function
/// sets masked areas to NAN in the image and variance.
bool pmReadoutMaskApply(pmReadout *readout, ///< Readout to mask
                        psImageMaskType maskVal ///< Mask value for which to apply mask
    );

/// Interpolate over bad pixels
///
/// Scan the mask image for bad pixels, and interpolate over them using the nominated options
bool pmReadoutInterpolateBadPixels(pmReadout *readout, ///< Readout to work on
                                   psImageMaskType maskVal, ///< Value to mask
                                   psImageInterpolateMode mode, ///< Interpolation mode
                                   float poorFrac, ///< Maximum bad fraction of kernel for "poor" status
                                   psImageMaskType maskPoor, ///< Mask value to give poor pixels
                                   psImageMaskType maskBad ///< Mask value to give bad pixels
    );

/// @}
#endif
