IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 24, 2006, 3:48:17 PM (20 years ago)
Author:
Paul Price
Message:

Major changes to bring spec up to date with code, mainly for stuff written by PAP.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/modules/ModulesSDRS.tex

    r9713 r9744  
    1 %%% $Id: ModulesSDRS.tex,v 1.79 2006-10-21 04:27:38 price Exp $
     1%%% $Id: ModulesSDRS.tex,v 1.80 2006-10-25 01:48:17 price Exp $
    22\documentclass[panstarrs,spec]{panstarrs}
    33
     
    627627image detrending steps are:
    628628\begin{itemize}
    629 \item Subtract bias;
     629\item Subtract overscan, bias and dark;
    630630\item Correct for non-linearity;
     631\item Shutter correction;
    631632\item Flat-field;
    632633\item Mask bad pixels;
     634\item Fringe subtraction;
    633635\item Subtract the background;
    634636\item Mask cosmic rays;
     
    636638\end{itemize}
    637639
     640We also include here some of the (more complicated) functions for
     641generating the image detrend calibrations (fringes, flat-field
     642normalisation), and determining the suitable calibrations from the
     643detrend database.
     644
    638645\subsection{Bias subtraction}
    639646\label{sec:bias}
     
    641648The bias subtraction module provides a facility to correct detector
    642649images for the electronic pedestal introduced by the readout
    643 electronics.
    644 
    645 Given an input image and various other parameters,
    646 \code{pmSubtractBias} shall subtract the bias from the image:
    647 
    648 \begin{prototype}
    649 pmReadout *pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
    650                           psRegion imageRegion, psList *overscanRegions,
    651                           const pmReadout *bias, const pmReadout *dark);
    652 \end{prototype}
    653 
    654 Three types of bias correction may optionally be performed on the
    655 input image, \code{in}.  The first is the subtraction of an overscan.
    656 Multiple overscan regions may be specified and fit as a function of
    657 row (or column).  The second is the subtraction of a full-frame bias
    658 image.  The third is the subtraction of a suitably scaled full-frame
    659 dark image.
    660 
    661 The input image, \code{in}, shall have the bias subtracted in-place.
    662 The input image may be of type U16, S32, or F32.  The region of the
    663 input image that shall have the overscan or full-frame subtractions
    664 applied is specified by \code{imageRegion}.
    665 
    666 Overscan subtraction is performed if \code{overscanOpts} is
    667 non-\code{NULL} (see \S\ref{sec:overscan}).  \code{overscanRegions}
    668 shall be a list of \code{psRegion}s that specify the regions that
    669 comprise the overscans.
    670 
    671 A \code{bias} frame shall be subtracted pixel-by-pixel from the input
    672 image if \code{bias} is non-NULL.  If \code{dark} is non-\code{NULL},
    673 then the dark image, scaled by the ratio of dark times (from
    674 \code{CELL.DARKTIME}) shall be subtracted pixel-by-pixel from the
    675 input image.  The full-frame subtractions (both bias and dark) should
    676 only be performed on the image region specified by
    677 \code{CELL.TRIMSEC}.  Note that the input image, \code{in}, and the
    678 \code{bias} and \code{dark} frames need not be the same size, but the
    679 function shall use the offsets in the image (\code{in->x0} and
    680 \code{in->y0}) to determine the appropriate offsets to obtain the
    681 correct pixel on the \code{bias}.  In the event that the \code{bias}
    682 image is too small (i.e., pixels on the input image refer to pixels
    683 outside the range of the \code{bias} image), the function shall
    684 generate an error.  Any pixels masked in the \code{bias} or
    685 \code{dark} shall also be masked in the output.  The bias and dark
    686 images may be copied to the same type as the input image if required.
     650electronics.  The pedestal is measured from one or more of the
     651overscan, bias frame and dark frames.
     652
     653The following function subtracts the overscan, bias and/or dark from
     654the input readout.  The overscan is taken from the \code{bias} member
     655of the input \code{pmReadout}, and can be turned off by supplying a
     656\code{NULL} value for \code{overscanOpts}.  A bias image is subtracted
     657if \code{bias} is non-\code{NULL}, and a dark frame is scaled (by
     658\code{CELL.DARKTIME}) and subtracted if \code{dark} is
     659non-\code{NULL}.
     660\begin{prototype}
     661bool pmSubtractBias(pmReadout *in,      ///< Input readout, to be overscan/bias/dark corrected
     662                    pmOverscanOptions *overscanOpts, ///< Options for overscan subtraction, or NULL
     663                    const pmReadout *bias, ///< Bias image to subtract, or NULL
     664                    const pmReadout *dark ///< Dark image to scale and subtract, or NULL
     665                   );
     666\end{prototype}
    687667
    688668
     
    696676typedef struct {
    697677    // Inputs
    698     bool single;                // Reduce all overscan regions to a single value?
    699     bool scanRows;              // Scan direction was rows? (otherwise columns)
    700     pmFit fitType;              // Type of fit to overscan
    701     unsigned int order;         // Order of polynomial, or number of spline pieces
    702     psStats *stat;              // Statistic to use when reducing the minor direction
     678    bool single;                ///< Reduce all overscan regions to a single value?
     679    pmFit fitType;              ///< Type of fit to overscan
     680    unsigned int order;         ///< Order of polynomial, or number of spline pieces
     681    psStats *stat;              ///< Statistic to use when reducing the minor direction
    703682    // Outputs
    704     psPolynomial1D *poly;       // Result of polynomial fit
    705     psSpline1D *spline;         // Result of spline fit
     683    psPolynomial1D *poly;       ///< Result of polynomial fit
     684    psSpline1D *spline;         ///< Result of spline fit
    706685} pmOverscanOptions;
    707686\end{datatype}
    708687
    709 The mode in which the overscan is subtracted is specified by the
    710 \code{single} boolean.  If \code{single} is \code{true}, then the
    711 entire overscan region is reduced to a single value using the
    712 \code{stat}.  If \code{single} is \code{false}, the overscan shall be
    713 reduced along the dimension specified by \code{scanRows} (rows if
    714 \code{scanRows} is true; otherwise columns).
    715 
    716 If the overscan is not defined for each row/column,
    717 \code{pmSubtractBias} shall generate an error if \code{fitType} is
    718 \code{PM_FIT_NONE}; otherwise, the function shall shall generate a
    719 warning and the undefined values shall be interpolated using the
    720 provided functional form.
    721 
    722 The statistic to use in combining multiple pixels in the
    723 prescan/overscan regions is specified by \code{stat}.  \code{stat} is
    724 of type \code{psStats} instead of simply \code{psStatsOptions} so that
    725 clipping levels may be specified, if desired.  In the event that
    726 multiple options are specified by \code{stats}, a warning shall be
    727 generated, and the option with the highest priority shall be used,
    728 according to the following priority order: \code{PS_STAT_SAMPLE_MEAN},
    729 \code{PS_STAT_SAMPLE_MEDIAN}, \code{PS_STAT_CLIPPED_MEAN},
    730 \code{PS_STAT_ROBUST_MEAN}, \code{PS_STAT_ROBUST_MEDIAN},
    731 \code{PS_STAT_ROBUST_MODE}.
    732 
    733 \code{fitType} is an enumerated type which specifies the type of fit
    734 to employed on the overscan vector:
     688The overscan subtraction may be performed by reducing all overscan
     689regions to a single value (e.g., if there is no structure); or the
     690overscan may be fit perpendicular to the read direction (usually the
     691columns) with a particular functional form; or a single value may be
     692subtracted for each read/scan without fitting (if the structure defies
     693characterisation).  In any case, statistics are required to reduce
     694multiple values to a single value (either for the scan, or for the
     695entire overscan regions).
     696
     697The \code{fitType} is an enumerated type which specifies the type of
     698fit to employed on the overscan vector:
    735699\begin{datatype}
    736700typedef enum {
     
    748712allocated and updated with the results of the fit.
    749713
    750 The allocator for a \code{pmOverscanOptions} shall be:
    751 \begin{prototype}
    752 pmOverscanOptions *pmOverscanOptionsAlloc(bool single, bool scanRows,
    753                                           pmFit fitType, unsigned int order,
    754                                           psStats *stat);
     714The allocator for a \code{pmOverscanOptions} is:
     715\begin{prototype}
     716pmOverscanOptions *pmOverscanOptionsAlloc(bool single, ///< Reduce all overscan regions to a single value?
     717        pmFit fitType, ///< Type of fit to overscan
     718        unsigned int order, ///< Order of polynomial, or number of splines
     719        psStats *stat ///< Statistic to use
     720                                         );
    755721\end{prototype}
    756722
     
    762728since either (or both) might be used to specify the correction.
    763729
    764 These operations act only on the region of the readout specified by
    765 \code{CELL.TRIMSEC}.
    766 
    767 The first, \code{pmNonLinearityPolynomial} shall correct the input
    768 image for non-linearity by replacing the flux in each pixel of the
    769 input image, \code{in}, with the result of the specified polynomial,
    770 \code{coeff}, acting on the flux.  The API shall be the following:
    771 
    772 \begin{prototype}
    773 pmReadout *pmNonLinearityPolynomial(pmReadout *in, const psPolynomial1D *coeff);
    774 \end{prototype}
    775 
    776 The polynomial coefficients, \code{coeff}, will be supplied by the
    777 caller, likely from the image metadata.
    778 
    779 The second function, \code{pmNonLinearityLookup} shall correct
    780 the input image for non-linearity by using a lookup table.  The API
    781 shall be the following:
    782 
    783 \begin{prototype}
    784 pmReadout *pmNonLinearityLookup(pmReadout *in, const char *filename);
    785 \end{prototype}
    786 
    787 For each pixel in the input image, the function shall replace the flux
    788 with the corresponding value from the supplied lookup table, specified
    789 by the \code{filename}.  The lookup table file shall consist of two
    790 columns of data, the first being the original flux value and the
    791 second being the replaced flux value.  The file shall be in a format
    792 suitable for reading by \code{psLookupTableRead}.
    793 
    794 Both \code{pmNonLinearityPolynomial} and \code{pmNonLinearityLookup}
    795 shall modify the input image in-place.  The input image may be of
    796 type U16, S32, or F32.
     730The first, \code{pmNonLinearityPolynomial}, applies a polynomial to
     731the flux of each pixel in the input image to determine the corrected
     732flux.  The second function, \code{pmNonLinearityLookup} performs
     733linear interpolation on the table (specified by two vectors) to
     734determine the corrected flux.
     735
     736\begin{prototype}
     737pmReadout *pmNonLinearityPolynomial(pmReadout *in, ///< Input image, to correct
     738                                    const psPolynomial1D *coeff ///< Polynomial for non-linearity correction
     739                                   );
     740pmReadout *pmNonLinearityLookup(pmReadout *in, ///< Input image, to correct
     741                                const psVector *inFlux, ///< Table column with input fluxes
     742                                const psVector *outFlux ///< Table column with output fluxes
     743                               );
     744\end{prototype}
     745
    797746
    798747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    799748
     749\subsection{Shutter correction}
     750
     751A mechanical shutter may not yield uniform exposure times as a
     752function of position on the detector.  The typical error consists of a
     753constant exposure-time offset relative to the requested value,
     754i.e. the exposure time is $T_o + \delta T(x,y)$.  The exposure error,
     755$\delta T$, may be measured with the following scheme.  Obtain a set
     756of exposures with different exposures times taken of the same
     757flat-field source; the source must be spatially stable between the
     758exposures, but need not have a stable amplitude.  For an illuminating
     759flux of intensity $F(x,y) = F_o f(x,y)$, the signal recorded by any
     760pixel in the detector is given by: $S(t,x,y) = F_o(t) f(x,y) (T_o +
     761\delta T(x,y))$ where $F_o$ is the $F_o(t)$ is the (variable) overall
     762intensity of the illuminating source and $f(x,y)$ is the spatial
     763illumination patter times the flat-field response.  Choose a reference
     764location in the image (e.g., the detector center) and divide by the
     765value of that region (i.e., mean or median):
     766
     767\begin{eqnarray}
     768s(t,x,y) & = & S(t,x,y) / S(t,0,0) \\
     769s(t,x,y) & = & F_o(t) f(x,y) (T_o + \delta T(x,y)) / F_o(t) f(0,0) (T_o + \delta T(0,0)) \\
     770s(t,x,y) & = & f(x,y) (T_o + \delta T(x,y)) / f(0,0) (T_o + \delta T(0,0)) \\
     771\end{eqnarray}
     772
     773We can absorb the term $f(0,0)$ into $f(x,y)$, as we have no
     774motivation for the scale of $f(x,y)$.  For any single pixel, over the
     775set of exposures, we thus need to solve for $\delta T(x,y)$, $\delta
     776T(0,0)$, and $f'(x,y)$ in the equation:
     777
     778\begin{equation}
     779s(t,x,y) = f'(x,y) (T_o + dT(x,y)) / (T_o + \delta T(0,0))
     780\end{equation}
     781
     782We avoid directly fitting these values, as the process would be a
     783non-linear least-squares problem for every pixel in the image, and
     784thus very time consuming.  There are linear options which may be used
     785instead.  First, as $T_o$ goes to a large value, $s$ approaches the
     786value of $f'(x,y)$.  Next, as $T_o$ goes to a very small value, $s$
     787approaches the value of $f'(x,y) \delta T(x,y)/ \delta T(0,0)$.
     788Finally, when s has the value of $f'(x,y)*(1 + \delta T(x,y)/ \delta
     789T(0,0))/2$, then $T_o$ has the value of $\delta T(0,0)$.  With data
     790points covering a reasonable dynamic range, we can solve for these
     791three values by interpolation and/or extrapolation.
     792
     793To take the strategy one step further, we could use the above recipe
     794to obtain a guess for the three parameters and then apply non-linear
     795fitting to solve more accurately for the parameters.  If we limit this
     796operation to a handful of positions in the image (user defined, but
     797the obvious choice would be positions near the center, edges, and
     798corners), then we may determine a good value for $\delta T(0,0)$.
     799Since there is only one $\delta T(0,0)$ for the image, we can apply
     800the resulting measurement to the rest of the pixels in the image.  If
     801$\delta T(0,0)$ is not a free parameter, then the fitting process is
     802linear in terms of $\delta T(x,y)$ and $f'(x,y)$.
     803
     804\subsubsection{Components to creating a shutter correction}
     805
     806We define a shutter correction, applicable for a single pixel (or region):
     807\begin{datatype}
     808typedef struct {
     809    double scale;                       ///< The normalisation for an exposure, A(k)
     810    double offset;                      ///< The time offset, dTk
     811    double offref;                      ///< The reference time offset, dTo
     812} pmShutterCorrection;
     813\end{datatype}
     814
     815The allocator is:
     816\begin{prototype}
     817pmShutterCorrection *pmShutterCorrectionAlloc();
     818\end{prototype}
     819
     820
     821The following function provides a guess for the shutter correction,
     822based on plot of counts vs exposure time.  It should be used before
     823doing the full non-linear fit, to get parameters close to the true.
     824The function assumes the \code{exptime} vector is sorted (ascending
     825order; longest is last) prior to input.
     826\begin{prototype}
     827pmShutterCorrection *pmShutterCorrectionGuess(const psVector *exptime, ///< Exposure times for each exposure
     828        const psVector *counts ///< Counts for each exposure
     829                                             );
     830\end{prototype}
     831
     832A full non-linear fit may then be performed to the counts as a
     833function of exposure time.  The main purpose is to solve for the
     834reference time offset, so that future fits may be performed using
     835linear fitting with the reference time offset fixed.
     836\begin{prototype}
     837pmShutterCorrection *pmShutterCorrectionFullFit(const psVector *exptime, ///< Exposure times for each exposure
     838        const psVector *counts, ///< Counts for each exposure
     839        const psVector *cntError, ///< Error in the counts
     840        const pmShutterCorrection *guess ///< Initial guess
     841                                               );
     842\end{prototype}
     843
     844With the reference time offset fixed to a known value, a (much faster)
     845linear fit can be performed at each pixel to generate the shutter
     846correction.  This function performs the fit with iterative clipping,
     847if \code{nIter} $> 1$.
     848\begin{prototype}
     849pmShutterCorrection *pmShutterCorrectionLinFit(const psVector *exptime, ///< Exposure times for each exposure
     850        const psVector *counts, ///< Counts for each exposure
     851        const psVector *cntError, ///< Error in the counts
     852        const psVector *mask, ///< Mask for each exposure
     853        float offref, ///< Reference time offset
     854        int nIter, ///< Number of iterations
     855        float rej, ///< Rejection threshold (sigma)
     856        psMaskType maskVal ///< Mask value
     857                                              );
     858\end{prototype}
     859
     860\subsubsection{Creating a shutter correction}
     861
     862The above steps are all performed using the following function.  Given
     863an array of images with known exposure times, this function measures
     864the shutter correction (our principal concern is for the time offset,
     865rather than the normalisation) by measuring the reference time offset
     866using the full non-linear fit for a small number of representative
     867regions (middle and corners), and then using that to perform a linear
     868fit to each pixel.
     869\begin{prototype}
     870psImage *pmShutterCorrectionMeasure(const psVector *exptimes, ///< Exposure times
     871                                    const psArray *images, ///< Input images
     872                                    const psArray *weights, ///< Weight images
     873                                    const psArray *masks, ///< Mask images
     874                                    unsigned int size, ///< Size of samples for statistics for non-linear fit
     875                                    psStatsOptions meanStat, ///< Statistic to use for mean
     876                                    psStatsOptions stdevStat, ///< Statistic to use for stdev
     877                                    int nIter, ///< Number of iterations
     878                                    float rej, ///< Rejection threshold (sigma)
     879                                    psMaskType maskVal ///< Mask value
     880                                   );
     881\end{prototype}
     882
     883\subsubsection{Applying a shutter correction}
     884
     885Given a shutter correction (a measurement of $\delta T$ for each
     886pixel), the following function applies this correction to an input
     887image.
     888\begin{prototype}
     889bool pmShutterCorrectionApply(pmReadout *readout, ///< Readout to which to apply shutter correction
     890                              const pmReadout *shutter ///< Shutter correction readout, with dT for each pixel
     891                             );
     892\end{prototype}
     893
     894
     895%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     896
    800897\subsection{Flat-fielding}
    801898
    802 Given an input image and a flat-field image, \code{pmFlatField} shall
    803 divide the input image by the flat-field image and return it in place,
    804 updating the mask contained within the input image as appropriate.
    805 The API shall be the following:
    806 \begin{prototype}
    807 bool pmFlatField(pmReadout *in, const pmReadout *flat);
    808 \end{prototype}
    809 
    810 Note that the input image, \code{in}, and the flat-field image,
    811 \code{flat}, need not be the same size, since the input image may
    812 already have been trimmed (following overscan subtraction), but the
    813 function shall use the offsets of the readout (\code{in->col0,
    814 in->row0}) and the image subarray (\code{in->image->x0,
    815 in->image->y0}) to determine the appropriate offsets to obtain the
    816 correct detector pixels in the flat-field image.  Note that the image
    817 offset is relative to its parent, so this offset must be followed to
    818 the top level image which is not a child of another image and the
    819 offsets summed.  The detector pixel coordinates of pixel \code{x,y} in
    820 a top-level image are thus \code{x + in->image->x0 + in->col0, y +
    821 in->image->y0 + in->row0}. In the event that the \code{flat} image is
    822 too small (i.e., pixels on the input image refer to pixels outside the
    823 range of the \code{flat} image), the function shall generate an error.
    824 
    825 Pixels which are negative or zero in the \code{flat} shall be masked
    826 in the input image with the value \code{PM_MASK_FLAT} (see
    827 \S\ref{sec:maskValues}).  Negative pixels in the \code{flat} may be
    828 set to zero so that they are treated identically to zeroes.  Any
    829 pixels masked in the \code{flat} shall be masked with corresponding
    830 values in the \code{output}.
    831 
    832 The function shall not normalize the \code{flat}; this responsibility
    833 is left to the caller.  This function is basically equivalent to a
    834 divide (with \code{psImageOp}), but with care for the region that is
    835 divided, checking for zero and negative pixels, and copying of the
    836 mask from the \code{flat} to the output.
    837 
    838 The images in the input and flat-field readouts must both be of type
    839 F32.
    840 
    841 This operation acts only on the region of the readout specified by
    842 \code{CELL.TRIMSEC}.
     899
     900The following function applies the flat-field calibration to the input
     901readout.  The relative offsets between the input and flat images is
     902determined from the readout row0,col0 and the CELL.X0 and CELL.Y0
     903concepts.  Normalisation of the flat is left as the responsibility of
     904the caller.  Non-positive pixels in the flat are masked, if there is a
     905mask present in the input readout.
     906\begin{prototype}
     907bool pmFlatField(pmReadout *in,         ///< Readout with input image
     908                 const pmReadout *flat  ///< Readout with flat image
     909                );
     910\end{prototype}
    843911
    844912%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    846914\subsection{Masking}
    847915
    848 \subsubsection{Mask values}
    849 \label{sec:maskValues}
    850 
    851 We define several mask values for use in the detrend processing:
     916The following function applies a mask readout to an input (science) readout.
     917
     918Pixels marked as bad (according to the supplied mask value) within the
     919mask are marked as bad within the input image's mask.  If
     920\code{maskVal} is non-zero, all pixels in the mask have any of the
     921same bits sets as \code{maskVal} shall have the corresponding bits
     922raised.  If \code{maskVal} is zero, any zero pixels in the mask are
     923OR-ed with \code{PM_MASK_BAD}.  Position offsets (such as due to
     924trimming) between the input and mask are applied so that the same
     925pixels are referred to.  The science readout must already have a
     926supplied mask element (use e.g. \code{pmReadoutSetMask}).
     927\begin{prototype}
     928bool pmMaskBadPixels(pmReadout *input,  ///< Input science image
     929                     const pmReadout *mask, ///< Mask image to apply
     930                     psMaskType maskVal ///< Mask value to apply
     931                    );
     932\end{prototype}
     933
     934\tbd{Masks for the charge traps need to be grown by the extent of the
     935OT convolution kernel.  For other pixel types, orthogonal transfer of
     936the flux in this pixel will not (necessarily) affect the flux in
     937neighbouring pixels.}
     938
     939
     940\subsection{Fringes}
     941
     942Some images contain a signal caused by thin-film interference in the
     943device due to strong emission lines.  The resulting instrumental
     944effect consists of a pattern (the ``fringe pattern'') of bright and
     945dark bands corresponding to the constructive and destructive
     946interference of the emission lines.  In the case that a single
     947emission line causes the line structure, the resulting pattern can be
     948described by two independent parameters: First, the amplitude of the
     949emission line determines the overall amplitude of the pattern.
     950Second, the three-dimensional surface structure of the device
     951determines the shape of the pattern.  In a typical situation, the
     952device is illuminated by multiple emission lines, as well as a
     953continuum spectral source, which contributes to the overall light
     954detected by the device without following the fringe pattern.  The
     955relative intensities of the continuum background and the fringe
     956pattern depend on the device structure (thickness) and on the ratio of
     957the continuum and line emission fluxes.
     958
     959A simple approach to the fringe pattern is to subtract a master fringe
     960frame scaled by the amplitude of the fringe pattern.  The amplitude of
     961the fringe pattern is used both in the process of constructing the
     962master image and in scaling the master image when it is applied to
     963science image.  This is the method currently in use at CFHT and it
     964usually performs well.  However, the fringe signal can vary as the
     965emission lines in the atmosphere change, and the above method breaks
     966down unless different fringe images corresponding to different
     967atmospheric conditions are constructed. 
     968
     969An alternative technique is to use multiple master fringe images at
     970the same time, each representing different atmospheric conditions.
     971The observed fringe frame can be considered as a linear combination of
     972different fringe patterns, depending on the relative strengths of the
     973lines active in creating each of the fringe masters.  It is not
     974critical that the fringe master images represent completely orthogonal
     975fringe patterns, they need only sample sufficiently different
     976conditions to provide a handle on the underlying fringe signals. 
     977
     978We define a method of measuring the fringe pattern which is robust in
     979the presence of stars and which is fast.  We implement a varient on
     980the method used at CFHT in which the fringe pattern is mapped by a
     981series of points distributed across the image.  At CFHT, manual effort
     982is used to carefully define point pairs which correspond to peaks and
     983valleys of the fringe pattern.  We implement a different approach in
     984which the fringe points are randomly chosen across the image.  At each
     985point in the image, the median flux is measured in a box of specified
     986size.  A low-frequency spatial filter is then applied to these
     987measurements.  The resulting array of points and fluxes then
     988represents the strength of the fringe pattern on that image.  The
     989comparison between any two fringe images is then just a linear fit
     990between these fringe statistics vectors, as follows:
     991\[
     992S_i = C_0 + C_1 F_i
     993\]
     994where $S_i$ is the fringe statistic on the science image and $F_i$ is
     995the fringe statistic on the reference fringe image.  Extending this
     996logic to any number of reference fringe images results in the
     997following relationship:
     998\[
     999S_i = C_0 + \sum_j C_j F_j
     1000\]
     1001
     1002In order to correct a single science image, the collection of fringe
     1003statistics ($S_i$) are used to measure the coefficients $C_0$, $C_j$.
     1004The linear combination of the reference fringe images is then used to
     1005build a master image which is subtracted from the science image.  The
     1006following structures and functions implement the above concepts.
     1007
     1008
     1009\subsubsection{Fringe regions}
     1010
     1011Fringes are measured within a box of size \code{dX,dY}.  A large scale
     1012smoothing is performed by subtracting the background within large
     1013divisions of the image.  The coordinates of the fringe points and the
     1014mask are originally set to \code{NULL}, which means that they will be
     1015generated when required.
     1016
    8521017\begin{datatype}
    853 /** Mask values */
    854 typedef enum {
    855     PM_MASK_TRAP       = 0x0001,        ///< The pixel is a charge trap
    856     PM_MASK_BADCOL     = 0x0002,        ///< The pixel is a bad column
    857     PM_MASK_SAT        = 0x0004,        ///< The pixel is saturated
    858     PM_MASK_FLAT       = 0x0008         ///< The pixel is non-positive in the flat-field
    859 } pmMaskValue;
     1018typedef struct {
     1019    psU32 nRequested;                   // Number of fringe points selected
     1020    psU32 nAccepted;                    // Number of fringe points not masked
     1021    psU32 dX;                           // Median box half-width
     1022    psU32 dY;                           // Median box half-height
     1023    psU32 nX;                           // Number of large-scale smoothing divisions in x (col)
     1024    psU32 nY;                           // Number of large-scale smoothing divisions in y (row)
     1025    psVector *x;                        // Fringe point coordinates (col), or NULL
     1026    psVector *y;                        // Fringe point coordinates (row), or NULL
     1027    psVector *mask;                     // Fringe point on/off mask, or NULL
     1028} pmFringeRegions;
    8601029\end{datatype}
    8611030
    862 Of these, masks for the charge traps need to be grown by the extent of
    863 the OT convolution kernel.  For other pixel types, orthogonal transfer
    864 of the flux in this pixel will not (necessarily) affect the flux in
    865 neighbouring pixels.
    866 
    867 \subsubsection{Bad pixels}
    868 
    869 Given an input image, \code{in}, a bad pixel \code{mask}, a
    870 corresponding value in the bad pixel mask to mask in the input image,
    871 \code{maskVal}, a saturation level, and a growing radius,
    872 \code{pmMaskBadPixels} shall mask in the input image those
    873 pixels in the bad pixel mask that match the value to mask.  The API
    874 shall be the following:
    875 \begin{prototype}
    876 pmReadout *pmMaskBadPixels(pmReadout *in, const pmReadout *mask, unsigned int maskVal,
    877                            float sat, unsigned int growVal, int grow);
    878 \end{prototype}
    879 
    880 Note that the input image, \code{in}, is modified in-place.  All
    881 pixels in the \code{mask} which satisfy the \code{maskVal} shall have
    882 their corresponding pixels masked in the input image, \code{in}.  All
    883 pixels which satisfy the \code{growVal} shall have their corresponding
    884 pixels, along with all pixels within the \code{grow} radius masked.
    885 Pixels which have flux greater than \code{sat} shall also be masked,
    886 and grown by a single pixel (in addition to the \code{grow} done on
    887 the \code{growVal}).
    888 
    889 \tbd{In the future, may change {\tt grow} to a convolution kernel}.
    890 
    891 Note that the input image, \code{in}, and the \code{mask} need not be
    892 the same size, since the input image may already have been trimmed
    893 (following overscan subtraction), but the function shall use the
    894 offsets in the image (\code{in->x0} and \code{in->y0}) to determine
    895 the appropriate offsets to obtain the correct pixel on the mask.  In
    896 the event that the \code{mask} image is too small (i.e., pixels on the
    897 input image correspond to pixels outside the range of the \code{mask}
    898 image), the function shall generate an error.
    899 
    900 The input image may be of type U16, S32 or F32.  The mask image
    901 must be of type U8.
    902 
    903 This operation acts only on the region of the readout specified by
    904 \code{CELL.TRIMSEC}.
     1031The allocator is:
     1032\begin{prototype}
     1033pmFringeRegions *pmFringeRegionsAlloc (int nPts, ///< Number of fringe points to create
     1034                                       int dX, ///< Half-width of fringe boxes
     1035                                       int dY, ///< Half-height of fringe boxes
     1036                                       int nX, ///< Smoothing scale in x
     1037                                       int nY ///< Smoothing scale in y
     1038                                      );
     1039\end{prototype}
     1040
     1041The following function generates fringe points randomly over an image.
     1042No effort is made to avoid masked regions (indeed, the function knows
     1043nothing about masks).  If the random number generator is \code{NULL},
     1044then a new one will be used.
     1045\begin{prototype}
     1046bool pmFringeRegionsCreatePoints(pmFringeRegions *fringe, ///< Fringe regions to generate
     1047                                 const psImage *image, ///< Image for the regions (defines the size)
     1048                                 psRandom *random ///< Random number generator, or NULL
     1049                                );
     1050\end{prototype}
     1051
     1052Fringe regions may be written to and read from FITS files with the following functions.
     1053
     1054\code{pmFringeRegionsWriteFits} writes fringe regions to a FITS file,
     1055with the given extension name.  The header is supplemented with scalar
     1056values \code{dX}, \code{dY}, \code{nX} and \code{nY} (as
     1057\code{PSFRNGDX}, \code{PSFRNGDY}, \code{PSFRNGNX}, \code{PSFRNGNY})
     1058from the fringe regions, while the fringe coordinates and mask are
     1059written as a FITS table (as \code{x}, \code{y}, \code{mask}).
     1060
     1061\code{pmFringeRegionsReadFits} reads fringe regions from a FITS file,
     1062at the given extension name.  The scalars are retrieved from the
     1063header, while the table provides the fringe coordinates and mask.
     1064
     1065\begin{prototype}
     1066bool pmFringeRegionsWriteFits(psFits *fits, ///< Output FITS file
     1067                              psMetadata *header, ///< Additional headers to write, or NULL
     1068                              const pmFringeRegions *regions, ///< Regions to write
     1069                              const char *extname ///< Extension name, or NULL
     1070                             );
     1071pmFringeRegions *pmFringeRegionsReadFits(psMetadata *header, ///< Header to read, or NULL
     1072        const psFits *fits, ///< Input FITS file
     1073        const char *extname ///< Extension name, or NULL
     1074                                        );
     1075\end{prototype}
     1076
     1077\subsubsection{Fringe Statistics}
     1078
     1079Fringe measurements for a particular image are contained in the
     1080following structure, which contains the median and standard deviation
     1081for each of the fringe regions.
     1082\begin{datatype}
     1083typedef struct {
     1084    pmFringeRegions *regions;           ///< Fringe regions
     1085    psVector *f;                        ///< Fringe point median
     1086    psVector *df;                       ///< Fringe point stdev
     1087} pmFringeStats;
     1088\end{datatype}
     1089
     1090The allocator is:
     1091\begin{prototype}
     1092pmFringeStats *pmFringeStatsAlloc(pmFringeRegions *regions // The fringe regions which will be measured
     1093                                 );
     1094\end{prototype}
     1095
     1096The following function measures the fringe statistics (median and
     1097standard deviation) at each of the fringe regions for an image
     1098(supplied within a readout).  If the fringe regions are undefined,
     1099they are generated.
     1100\begin{prototype}
     1101pmFringeStats *pmFringeStatsMeasure(pmFringeRegions *fringe, ///< Fringe regions at which to measure
     1102                                    const pmReadout *readout, ///< Readout for which to measure
     1103                                    psMaskType maskVal ///< Mask value for image
     1104                                   );
     1105\end{prototype}
     1106
     1107Like the fringe regions, the fringe statistics may be written to and
     1108read from a FITS file, allowing rapid re-generation of the fringe
     1109measurements for the calibration files.
     1110
     1111\code{pmFringeStatsWriteFits} writes the fringe statistics for an
     1112image to a FITS table, with the given extension name.  The median and
     1113standard deviation measurements are written as a FITS table (as
     1114\code{f} and \code{df}).
     1115
     1116\code{pmFringeStatsReadFits} reads the fringe stats from a FITS table,
     1117at the given extension name.  It is assumed that the fringe
     1118measurements correspond to the regions provided.
     1119
     1120\begin{prototype}
     1121bool pmFringeStatsWriteFits(psFits *fits, ///< FITS file to which to write
     1122                            psMetadata *header, ///< Additional headers to write, or NULL
     1123                            const pmFringeStats *fringe, ///< Fringe statistics to be written
     1124                            const char *extname ///< Extension name for table
     1125                           );
     1126pmFringeStats *pmFringeStatsReadFits(psMetadata *header, ///< Header to read, or NULL
     1127                                     const psFits *fits, ///< FITS file from which to read
     1128                                     const char *extname, ///< Extension name to read
     1129                                     pmFringeRegions *regions ///< Corresponding regions
     1130                                    );
     1131\end{prototype}
     1132
     1133Since each readout of each chip must be measured separately (so as to
     1134avoid any gaps between the cells, as in the case for GPC), while the
     1135fit must be performed with all the readouts belonging to a chip (in
     1136order to get a secure measurement of the fringe amplitudes), we
     1137provide the following function, which concatenates the fringe stats
     1138for several readouts into a single fringe stats.  The function
     1139generates a new \code{pmFringeStats} from concatenating those in the
     1140array.  The corresponding \code{pmFringeRegions} is also generated.
     1141\begin{prototype}
     1142pmFringeStats *pmFringeStatsConcatenate(const psArray *fringes, ///< Array of pmFringeStats for the readouts
     1143                                        const psVector *x0, ///< Offset in x for the readout
     1144                                        const psVector *y0 ///< Offset in y for the readout
     1145                                       );
     1146\end{prototype}
     1147
     1148
     1149\subsubsection{Fringe scales}
     1150
     1151The following structure contains the fringe solution --- the
     1152coefficients of the linear system of library fringe images that best
     1153fit the science image.
     1154
     1155\begin{datatype}
     1156typedef struct {
     1157    int nFringeFrames;                  ///< Number of fringe frames
     1158    psVector *coeff;                    ///< Fringe coefficients; size = nFringeFrames
     1159    psVector *coeffErr;                 ///< Error in fringe coefficients; size = nFringeFrames
     1160} pmFringeScale;
     1161\end{datatype}
     1162
     1163The corresponding allocator is:
     1164\begin{prototype}
     1165pmFringeScale *pmFringeScaleAlloc(int nFringeFrames ///< Number of fringe frames
     1166                                 );
     1167\end{prototype}
     1168
     1169The following function measures the fringe scales for the library
     1170fringe images, solving the linear system that best fits the fringe
     1171measurements made on the science image.  Given a fringe measurement
     1172for a science image, and an array of template fringe measurements, the
     1173function measures the contribution of each of the templates to the
     1174input.  Rejection is performed on the fringe regions, to weed out
     1175stars etc.
     1176\begin{prototype}
     1177pmFringeScale *pmFringeScaleMeasure(pmFringeStats *science, ///< Fringe measurements from science image
     1178                                    psArray *fringes, ///< Array of fringe measurements from templates
     1179                                    float rej, ///< Rejection threshold (in standard deviations)
     1180                                    unsigned int nIter, ///< Maximum number of iterations
     1181                                    float keepFrac ///< Minimum fraction of regions to keep
     1182                                   );
     1183\end{prototype}
     1184
     1185
     1186\subsubsection{Fringe correction}
     1187
     1188The following function solves for and applies the fringe correction.
     1189It is a wrapper around each of the fringe correction components to
     1190measure the fringe points, solve for the fringe correction, and apply
     1191the fringe correction.  The input fringe images are modified (scaled
     1192by the solution coefficients in order to correct the science image).
     1193The function returns the summed fringe image, and corrects the input
     1194science image.
     1195
     1196\begin{prototype}
     1197psImage *pmFringeCorrect(pmReadout *in, ///< Input science image
     1198                         pmFringeRegions *fringes, ///< The fringe regions used
     1199                         psArray *fringeImages, ///< Fringe template images to use in correction
     1200                         psArray *fringeStats, ///< Fringe stats (for templates) to use in correction
     1201                         psMaskType maskVal, ///< Value to mask for science image
     1202                         float rej,     ///< Rejection threshold, for pmFringeScaleMeasure
     1203                         unsigned int nIter, ///< Maximum number of iterations, for pmFringeScaleMeasure
     1204                         float keepFrac ///< Minimum fraction of regions to keep, for pmFringeScaleMeasure
     1205                        );
     1206\end{prototype}
     1207
     1208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    9051209
    9061210\subsection{Subtract sky}
    9071211
    908 \tbd{This may be deferred.}
     1212\tbd{This has been deferred.}
    9091213
    9101214Given an input image, a polynomial or spline specifying the order of a
     
    9621266
    9631267\subsection{Paper Trail}
     1268
     1269\tbd{This is not implemented yet.}
    9641270
    9651271The elements of the focal plane hierarchy each contain an
     
    10981404will have the same noise characteristics.
    10991405
    1100 \begin{datatype}
    1101 typedef struct {
    1102     psStats *stats;                     // Statistics to use in combining pixels
    1103     unsigned int maskVal,               // Mask pixels where mask & maskVal == 1
    1104     float fracHigh;                     // Fraction of high pixels to throw
    1105     float fracLow;                      // Fraction of low pixels to throw
    1106     int nKeep;                          // Number of pixels to be sure to keep
    1107 } pmCombineParams;
    1108 \end{datatype}
    1109 
    1110 \begin{prototype}
    1111 psImage *
    1112 pmReadoutCombine(psImage *output,       // Output image, or NULL
    1113                  const psList *inputs,  // List of input readouts
    1114                  pmCombineParams *params, // Combination parameters
    1115                  const psVector *zero,  // Offsets to apply for each image
    1116                  const psVector *scale, // Scales to apply for each image
    1117                  bool applyZeroScale,   // Are zero and scale for application, or only noise properties?
    1118                  float gain,            // Gain in e/ADU
    1119                  float readnoise        // Read noise in e
    1120                  );
    1121 \end{prototype}
    1122 
    1123 \code{pmReadoutCombine} combines input images pixel by pixel --- for
    1124 each pixel of the output image, a stack of contributing input pixels
    1125 is formed and combined.  Several of its input parameters are lists or
    1126 vectors, and if these are not all of the same length (or \code{NULL}),
    1127 the module shall generate an error and return \code{NULL}.
    1128 
    1129 If the provided \code{output} is \code{NULL}, then the module shall
    1130 allocate a new image of sufficient size for the input images.  If the
    1131 \code{output} image is non-\code{NULL} and is not of sufficient size
    1132 for the combined image, the module shall generate an error and return
    1133 \code{NULL}.
    1134 
    1135 If the \code{inputs} is \code{NULL}, the module shall generate an
    1136 error and return \code{NULL}.  Otherwise, the \code{inputs} shall be a
    1137 list of \code{pmReadout}s.  The images contained within the
    1138 \code{pmReadout}s need not all be of the same size, but the module
    1139 shall take into account the offsets (\code{col0,row0}) from the corner
    1140 of the detector when comparing pixels, so that it is the same
    1141 \textit{physical} pixels that are combined.
    1142 
    1143 The parameters used in the combination, including how the pixels are
    1144 to be combined, and how the rejection is performed is contained within
    1145 the \code{params}, which may not be \code{NULL} (otherwise the module
    1146 shall generate an error and return \code{NULL}).  We choose to use
    1147 this structure instead of supplying the values separately in order to
    1148 keep down the number of parameters to \code{pmReadoutCombine}; the
    1149 \code{pmCombineParams} may be recycled for subsequent calls to
    1150 \code{pmReadoutCombine} since the values are not dependent upon the
    1151 choice of inputs, but merely specify how the combination is to be
    1152 performed.
    1153 
    1154 The particular statistic specified by \code{stats} shall be used to
    1155 combine each stack of pixels from the input images.  Only one of the
    1156 statistics choices may be specified, otherwise the module shall
    1157 generate an error and return \code{NULL}.
    1158 
    1159 If the \code{maskVal} is non-zero, then pixels in the \code{mask} of
    1160 each \code{pmReadout} in the \code{inputs} which satisfy the
    1161 \code{maskVal} shall not have the corresponding pixels placed in the
    1162 stack for combination.
     1406The following structure specifies how the combination of a stack of
     1407pixels is performed.  The particular statistic specified by
     1408\code{combine} is used to combine each stack of pixels from the input
     1409images.  If the \code{combine} specifies clipped fitting, the
     1410\code{iter} and \code{rej} members provide the number of iterations
     1411and the rejection threshold for clipping.
     1412
     1413The \code{maskVal} specifies mask values for pixels to be
     1414masked out of the combination.
    11631415
    11641416After masking, but before performing the combination, the highest
     
    11681420rejection is performed.
    11691421
    1170 If the \code{zero} vector is non-\code{NULL} and \code{applyZeroScale}
    1171 is \code{true}, then the appropriate values shall be added to the
    1172 \code{inputs} before rejection is performed.  If \code{zero} is
    1173 non-\code{NULL} and \code{applyZeroScale} is false, then the values
    1174 shall only be used in calculating the Poisson variances.
    1175 
    1176 If the \code{scale} vector is non-\code{NULL} and
    1177 \code{applyZeroScale} is \code{true}, then the appropriate values
    1178 shall multiply the \code{inputs} before rejection is performed.  If
    1179 \code{scale} is non-\code{NULL} and \code{applyZeroScale} is false,
    1180 then the values shall only be used in calculating the Poisson
    1181 variances.
    1182 
    1183 The purpose of \code{applyZeroScale} is to allow combination of fringe
    1184 frames, where the frames have been deliberately sky-subtracted and
    1185 rescaled (to get the fringes amplitudes running from -1 to 1), which
    1186 actions should not be undone when combining, but yet it is desirable
    1187 to provide the \code{zero} and \code{scale} values so that the correct
    1188 noise properties are used in the combination.
    1189 
    1190 If the \code{gain} and \code{readnoise} are positive and non-negative
    1191 (respectively), then these shall be used to provide weights for the
    1192 combination using Poisson statistics ($\sigma_i$ below).
    1193 
    1194 In summary, pixels corresponding to the same physical pixel are
    1195 combined, having values $x_i \pm \sigma_i$.  In the case that
    1196 \code{applyZeroScale} is \code{true}, then:
    1197 \begin{eqnarray}
    1198 x_i & = & s_i f_i + z_i \\
    1199 \sigma_i & = & [g x_i + r^2]^{1/2} / g
    1200 \end{eqnarray}
    1201 Where $f_i$ is the value of the pixel in image $i$, $s_i$ is the scale
    1202 applied to image $i$, $z_i$ is the zero offset applied to image $i$,
    1203 $g$ is the gain, and $r$ is the read noise.  If scales are not
    1204 provided, they are set to unity; if zero offsets are not provided,
    1205 they are set to zero.
    1206 
    1207 If \code{applyZeroScale} is \code{false}, then the values are:
    1208 \begin{eqnarray}
    1209 x_i & = & f_i \\
    1210 \sigma_i & = & [g (s_i f_i + z_i) + r^2]^{1/2} / g
    1211 \end{eqnarray}
    1212 where the same symbols are used as above.
    1213 
    1214 The \code{inputs, zero} and \code{scale} may be of U16, S32 and F32
    1215 types, and must all be of the same type.  The \code{output} shall be
    1216 of the same type.
    1217 
    1218 \subsection{Fringe Amplitude}
    1219 
    1220 Some images contain a signal caused by thin-film interference in the
    1221 device due to strong emission lines.  The resulting instrumental
    1222 effect consists of a pattern (the ``fringe pattern'') of bright and
    1223 dark bands corresponding to the constructive and destructive
    1224 interference of the emission lines.  In the case that a single
    1225 emission line causes the line structure, the resulting pattern can be
    1226 described by two independent parameters: First, the amplitude of the
    1227 emission line determines the overall amplitude of the pattern.
    1228 Second, the three-dimensional surface structure of the device
    1229 determines the shape of the pattern.  In a typical situation, the
    1230 device is illuminated by multiple emission lines, as well as a
    1231 continuum spectral source, which contributes to the overall light
    1232 detected by the device without following the fringe pattern.  The
    1233 relative intensities of the continuum background and the fringe
    1234 pattern depend on the device structure (thickness) and on the ratio of
    1235 the continuum and line emission fluxes.
    1236 
    1237 A simple approach to the fringe pattern is to subtract a master fringe
    1238 frame scaled by the amplitude of the fringe pattern.  The amplitude of
    1239 the fringe pattern is used both in the process of constructing the
    1240 master image and in scaling the master image when it is applied to
    1241 science image.  This is the method currently in use at CFHT and it
    1242 usually performs well.  However, the fringe signal can vary as the
    1243 emission lines in the atmosphere change, and the above method breaks
    1244 down unless different fringe images corresponding to different
    1245 atmospheric conditions are constructed. 
    1246 
    1247 An alternative technique is to use multiple master fringe images at
    1248 the same time, each representing different atmospheric conditions.
    1249 The observed fringe frame can be considered as a linear combination of
    1250 different fringe patterns, depending on the relative strengths of the
    1251 lines active in creating each of the fringe masters.  It is not
    1252 critical that the fringe master images represent completely orthogonal
    1253 fringe patterns, they need only sample sufficiently different
    1254 conditions to provide a handle on the underlying fringe signals. 
    1255 
    1256 We define a method of measuring the fringe pattern which is robust in
    1257 the presence of stars and which is fast.  We implement a varient on
    1258 the method used at CFHT in which the fringe pattern is mapped by a
    1259 series of points distributed across the image.  At CFHT, manual effort
    1260 is used to carefully define point pairs which correspond to peaks and
    1261 valleys of the fringe pattern.  We implement a different approach in
    1262 which the fringe points are randomly chosen across the image.  At each
    1263 point in the image, the median flux is measured in a box of specified
    1264 size.  A low-frequency spatial filter is then applied to these
    1265 measurements.  The resulting array of points and fluxes then
    1266 represents the strength of the fringe pattern on that image.  The
    1267 comparison between any two fringe images is then just a linear fit
    1268 between these fringe statistics vectors, as follows:
    1269 \[
    1270 S_i = C_0 + C_1 F_i
    1271 \]
    1272 where $S_i$ is the fringe statistic on the science image and $F_i$ is
    1273 the fringe statistic on the reference fringe image.  Extending this
    1274 logic to any number of reference fringe images results in the
    1275 following relationship:
    1276 \[
    1277 S_i = C_0 + \sum_j C_j F_j
    1278 \]
    1279 
    1280 In order to correct a single science image, the collection of fringe
    1281 statistics ($S_i$) are used to measure the coefficients $C_0$, $C_j$.
    1282 The linear combination of the reference fringe images is then used to
    1283 build a master image which is subtracted from the science image.  The
    1284 following structures and functions implement the above concepts.
    1285 
    1286 The \code{pmFringeStats} structure represents the fringe statistics
    1287 for a given image. 
    12881422\begin{datatype}
    12891423typedef struct {
    1290     psU32 nRequested;   // number of fringe points selected
    1291     psU32 nAccepted;    // number of fringe points not masked
    1292     psU32 dX;           // median box half-width
    1293     psU32 dY;           // median box half-height
    1294     psU32 nX;           // large-scale smoothing in x (col)
    1295     psU32 nY;           // large-scale smoothing in y (row)
    1296     psVector x;         // fringe point coordinates (col)
    1297     psVector y;         // fringe point coordinates (row)
    1298     psVector f;         // fringe point median
    1299     psVector df;        // fringe point stdev
    1300     psVector mask;      // fringe point on/off mask
    1301 } pmFringeStats;
     1424    psStatsOptions combine;             ///< Statistic to use when performing the combination
     1425    psMaskType maskVal;                 ///< Mask value
     1426    int nKeep;                          ///< Mimimum number of pixels to keep
     1427    float fracHigh;                     ///< Fraction of high pixels to immediately throw
     1428    float fracLow;                      ///< Fraction of low pixels to immediately throw
     1429    int iter;                           ///< Number of iterations for clipping (for CLIPPED_MEAN only)
     1430    float rej;                          ///< Rejection threshould for clipping (for CLIPPED_MEAN only)
     1431} pmCombineParams;
    13021432\end{datatype}
    13031433
    1304 The \code{pmFringeStats} structure is allocated with the following
    1305 function:
    1306 \begin{prototype}
    1307 pmFringeStats *pmFringeStatsAlloc (
    1308     int nPts,     // number of points to create
    1309     int dX,     // half-width of fringe boxes
    1310     int dY,     // half-height of fringe boxes
    1311     int nX,     // smoothing scale in x
    1312     int nY    // smoothing scale in y
    1313 );
    1314 \end{prototype}
    1315 
    1316 A set of fringe points appropriate to the dimensions of a specific
    1317 image are created with the following function:
    1318 \begin{prototype}
    1319 bool pmFringeStatsCreatePoints (pmFringeStats *fringe, psImage *image);
    1320 \end{prototype}
    1321 
    1322 In general, \code{pmFringeStatsCreatePoints} should only be needed
    1323 when a new chip and filter are first use for analysis.  Multiple
    1324 fringe images with the same chip and filter need to be examined with
    1325 the same fringe points in order for the statistical comparison to be
    1326 meaningful.  The constructed fringe points should be saved and loaded
    1327 as a FITS table using the following function:
    1328 \begin{prototype}
    1329 bool pmFringeStatsWriteFits (psFits *fits, pmFringeStats *fringe);
    1330 bool pmFringeStatsReadFits (psFits *fits, pmFringeStats *fringe);
    1331 \end{prototype}
    1332 
    1333 In order to measure the fringe statistics for a given image, the
    1334 following function is defined:
    1335 \begin{prototype}
    1336 bool pmFringeStatsMeasure(pmFringeStats *fringe, pmReadout *readout)
    1337 \end{prototype}
    1338 This function measures the robust median at each of the fringe points
    1339 and saves the median values in \code{fringe->f} and the scatter in
    1340 \code{fringe->df}.
    1341  
    1342 Given the fringe statistics for a science image, and the fringe
    1343 statistics for a set of reference fringe images, the following
    1344 function can be used to measure the scaling coefficients of the
    1345 reference fringe frames which best fit the science image fringe
    1346 pattern:
    1347 \begin{prototype}
    1348 pmFringeScale *pmFringeScaleMeasure (pmFringeStats *science, psArray *fringes)
    1349 \end{prototype}
    1350 
    1351 Given a science image, a set of master fringe images, and a the set of
    1352 fringe statistics for the reference fringe images, the following
    1353 function can be used to correct the science image for the fringe pattern:
    1354 \begin{prototype}
    1355 psImage *pmFringeCorrect(psImage *out, psMetadata *info, psImage *science, psArray *fringeImage, psArray *fringeStats);
    1356 \end{prototype}
     1434The allocator is:
     1435\begin{prototype}
     1436pmCombineParams *pmCombineParamsAlloc(psStatsOptions statsOptions ///< Statistic to use for combination
     1437                                     );
     1438\end{prototype}
     1439
     1440The combination is performed by the following function:
     1441\begin{prototype}
     1442bool pmReadoutCombine(pmReadout *output,///< Output readout; altered and returned
     1443                      const psArray *inputs,  ///< Array of input readouts (F32 image and weight, U8 mask)
     1444                      const psVector *zero, ///< Zero corrections to subtract from input, or NULL
     1445                      const psVector *scale, ///< Scale corrections to divide into input, or NULL
     1446                      const pmCombineParams *params ///< Combination parameters
     1447                     );
     1448\end{prototype}
     1449
     1450\code{pmReadoutCombine} combines input images pixel by pixel --- for
     1451each pixel of the output image, a stack of contributing input pixels
     1452is formed and combined, using the mask and weights if supplied in the
     1453input readouts.
     1454
     1455The \code{output} readout is extended in size, if necessary, to
     1456contain the input pixels.
     1457
     1458The \code{inputs} array contains the \code{pmReadout}s to be combined.
     1459The images contained within the \code{pmReadout}s need not all be of
     1460the same size, but the module will take into account the offsets from
     1461the corner of the detector when comparing pixels, so that it is the
     1462same \textit{physical} pixels that are combined.
     1463
     1464If the \code{zero} vector is non-\code{NULL} then the appropriate
     1465values are subtracted from the \code{inputs} before rejection is
     1466performed.  If the \code{scale} vector is non-\code{NULL}, then the
     1467appropriate values multiply the \code{inputs} before rejection is
     1468performed.
     1469
    13571470
    13581471\subsection{Flat-field Re-Normalization}
     
    14251538to modify the flux levels on the master flat-field images.
    14261539
    1427 We define the following function to perform the analysis discussed
    1428 above:
    1429 \begin{prototype}
    1430 bool pmFlatNormalization (psVector *sourceFlux, psVector *chipGains, psArray *fluxLevels);
    1431 \end{prototype}
    1432 The input array \code{fluxLevels} consists of $N_i$ vectors, one per
    1433 mosaic image.  Each vector consists of $N_j$ elements, each a
    1434 measurement of the input flat-field image flux levels.  All of these
    1435 vectors must be constructed with the same number of elements, or the
    1436 function will return an error.  If a chip is missing from a particular
    1437 image, that element should be set to \code{NaN}.  The vector
    1438 \code{chipGains} supplies initial guesses for the chip gains.  If the
    1439 vector contains the values 0.0 or \code{NaN} for any of the elements,
    1440 the gain is set to the mean of the valid values.  If the vector length
    1441 does not match the number of chips, an warning is raised, all chip
    1442 gain guesses will be set to 1.0, and the vector length modified to
    1443 match the number of chips defined by the supplied \code{fluxLevels}.
    1444 The \code{sourceFlux} input vector must be allocated (not
    1445 \code{NULL}), but the routine will set the vector length to the number
    1446 of source images regardless of the initial state of the vector.  All
    1447 vectors used by this function must be of type \code{PS_DATA_F64}.
     1540The following function solves this system.  The matrix of background
     1541measurements ($M_{i,j}$) contains the background for the flat fields
     1542used in the combination, as a function of exposure (rows) and chip
     1543(columns).  The exposure fluxes and chip gains are modified upon
     1544return with the solved values.  The function returns true if the
     1545solution converged.  An initial guess for the chip gains might be
     1546helpful, but is not necessary.
     1547\begin{prototype}
     1548bool pmFlatNormalize(psVector **expFluxesPtr, ///< Flux in each exposure, or NULL; modified
     1549                     psVector **chipGainsPtr, ///< Initial guess of the chip gains or NULL; modified
     1550                     const psImage *bgMatrix ///< Background measurements: rows are exposures, cols are chips
     1551                    );
     1552\end{prototype}
     1553
    14481554
    14491555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    14501556
    14511557\section{Objects on Images}
     1558
     1559\tbd{EAM to update, if necessary.}
    14521560
    14531561\subsection{Overview}
     
    24652573\section{Image Combination}
    24662574
     2575\tbd{PAP to code and update.}
     2576
    24672577The image combination for \PS{} will employ an iterative approach, in
    24682578order to identify cosmic rays.  The first pass involves transforming
     
    26652775\section{Image Subtraction}
    26662776
     2777\tbd{PAP to code and update.}
     2778
    26672779Image subtraction is arguably the best method of identifying faint
    26682780variable sources in images with different point-spread functions.  It
     
    31203232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    31213233
    3122 \section{Example Camera Configuration Files}
    3123 
    3124 \tbd{Some of these don't exactly match the specifications of this
    3125 document yet, because they have been changed from the prototype, but
    3126 it is hoped that they will be useful.  Questions are welcome.}
    3127 
    3128 \subsection{MegaCam Raw}
    3129 
    3130 \begin{verbatim}
    3131 # The raw MegaCam data comes off the telescope with each of the chips stored in extensions of a MEF file.
    3132 
    3133 # How to identify this type
    3134 RULE    METADATA
    3135         TELESCOP        STR     CFHT 3.6m
    3136         DETECTOR        STR     MegaCam
    3137         EXTEND          BOOL    T
    3138         NEXTEND         S32     72
    3139 END
    3140 
    3141 # How to read this data
    3142 PHU             STR     FPA     # The FITS file represents an entire FPA
    3143 EXTENSIONS      STR     CELL    # The extensions represent cells
    3144 
    3145 # What's in the FITS file?
    3146 CONTENTS        METADATA
    3147         # Extension name, chip name:type
    3148         amp00   STR     ccd00:left
    3149         amp01   STR     ccd00:right
    3150         amp02   STR     ccd01:left
    3151         amp03   STR     ccd01:right
    3152         amp04   STR     ccd02:left
    3153         amp05   STR     ccd02:right
    3154         amp06   STR     ccd03:left
    3155         amp07   STR     ccd03:right
    3156         amp08   STR     ccd04:left
    3157         amp09   STR     ccd04:right
    3158         amp10   STR     ccd05:left
    3159         amp11   STR     ccd05:right
    3160         amp12   STR     ccd06:left
    3161         amp13   STR     ccd06:right
    3162         amp14   STR     ccd07:left
    3163         amp15   STR     ccd07:right
    3164         amp16   STR     ccd08:left
    3165         amp17   STR     ccd08:right
    3166         amp18   STR     ccd09:left
    3167         amp19   STR     ccd09:right
    3168         amp20   STR     ccd10:left
    3169         amp21   STR     ccd10:right
    3170         amp22   STR     ccd11:left
    3171         amp23   STR     ccd11:right
    3172         amp24   STR     ccd12:left
    3173         amp25   STR     ccd12:right
    3174         amp26   STR     ccd13:left
    3175         amp27   STR     ccd13:right
    3176         amp28   STR     ccd14:left
    3177         amp29   STR     ccd14:right
    3178         amp30   STR     ccd15:left
    3179         amp31   STR     ccd15:right
    3180         amp32   STR     ccd16:left
    3181         amp33   STR     ccd16:right
    3182         amp34   STR     ccd17:left
    3183         amp35   STR     ccd17:right
    3184         amp36   STR     ccd18:left
    3185         amp37   STR     ccd18:right
    3186         amp38   STR     ccd19:left
    3187         amp39   STR     ccd19:right
    3188         amp40   STR     ccd20:left
    3189         amp41   STR     ccd20:right
    3190         amp42   STR     ccd21:left
    3191         amp43   STR     ccd21:right
    3192         amp44   STR     ccd22:left
    3193         amp45   STR     ccd22:right
    3194         amp46   STR     ccd23:left
    3195         amp47   STR     ccd23:right
    3196         amp48   STR     ccd24:left
    3197         amp49   STR     ccd24:right
    3198         amp50   STR     ccd25:left
    3199         amp51   STR     ccd25:right
    3200         amp52   STR     ccd26:left
    3201         amp53   STR     ccd26:right
    3202         amp54   STR     ccd27:left
    3203         amp55   STR     ccd27:right
    3204         amp56   STR     ccd28:left
    3205         amp57   STR     ccd28:right
    3206         amp58   STR     ccd29:left
    3207         amp59   STR     ccd29:right
    3208         amp60   STR     ccd30:left
    3209         amp61   STR     ccd30:right
    3210         amp62   STR     ccd31:left
    3211         amp63   STR     ccd31:right
    3212         amp64   STR     ccd32:left
    3213         amp65   STR     ccd32:right
    3214         amp66   STR     ccd33:left
    3215         amp67   STR     ccd33:right
    3216         amp68   STR     ccd34:left
    3217         amp69   STR     ccd34:right
    3218         amp70   STR     ccd35:left
    3219         amp71   STR     ccd35:right
    3220 END
    3221 
    3222 # Specify the cell data
    3223 CELLS   METADATA
    3224         left    METADATA        # Left amplifier
    3225                 CELL.BIASSEC    STR     HEADER:BIASSEC
    3226                 CELL.TRIMSEC    STR     HEADER:DATASEC
    3227                 CELL.XPARITY    S32     1       # We could have specified this as a DEFAULT, but this works
    3228         END
    3229         right   METADATA        # Right amplifier
    3230                 CELL.BIASSEC    STR     HEADER:BIASSEC
    3231                 CELL.TRIMSEC    STR     HEADER:DATASEC
    3232                 CELL.XPARITY    S32     -1      # This cell is read out in the opposite direction
    3233         END
    3234 END
    3235 
    3236 # How to translate PS concepts into FITS headers
    3237 TRANSLATION     METADATA
    3238         FPA.NAME        STR     EXPNUM
    3239         FPA.AIRMASS     STR     AIRMASS
    3240         FPA.FILTER      STR     FILTER
    3241         FPA.POSANGLE    STR     ROTANGLE
    3242         FPA.RA          STR     RA
    3243         FPA.DEC         STR     DEC
    3244         FPA.RADECSYS    STR     RADECSYS
    3245         FPA.MJD         STR     MJD-OBS
    3246         CELL.EXPOSURE   STR     EXPTIME
    3247         CELL.DARKTIME   STR     DARKTIME
    3248         CELL.XBIN       STR     CCDBIN1
    3249         CELL.YBIN       STR     CCDBIN2
    3250         CELL.GAIN       STR     GAIN
    3251         CELL.READNOISE  STR     RDNOISE
    3252         CELL.SATURATION STR     SATURATE
    3253 END
    3254 
    3255 # Default PS concepts that may be specified by value
    3256 DEFAULTS        METADATA
    3257         CELL.BAD                S32     0
    3258         CELL.YPARITY_DEPEND     STR     CHIP.NAME
    3259         CELL.YPARITY    METADATA
    3260                 ccd00   S32     -1
    3261                 ccd01   S32     -1
    3262                 ccd02   S32     -1
    3263                 ccd03   S32     -1
    3264                 ccd04   S32     -1
    3265                 ccd05   S32     -1
    3266                 ccd06   S32     -1
    3267                 ccd07   S32     -1
    3268                 ccd08   S32     -1
    3269                 ccd09   S32     -1
    3270                 ccd10   S32     -1
    3271                 ccd11   S32     -1
    3272                 ccd12   S32     -1
    3273                 ccd13   S32     -1
    3274                 ccd14   S32     -1
    3275                 ccd15   S32     -1
    3276                 ccd16   S32     -1
    3277                 ccd17   S32     -1
    3278                 ccd18   S32     1
    3279                 ccd19   S32     1
    3280                 ccd20   S32     1
    3281                 ccd21   S32     1
    3282                 ccd22   S32     1
    3283                 ccd23   S32     1
    3284                 ccd24   S32     1
    3285                 ccd25   S32     1
    3286                 ccd26   S32     1
    3287                 ccd27   S32     1
    3288                 ccd28   S32     1
    3289                 ccd29   S32     1
    3290                 ccd30   S32     1
    3291                 ccd31   S32     1
    3292                 ccd32   S32     1
    3293                 ccd33   S32     1
    3294                 ccd34   S32     1
    3295                 ccd35   S32     1
    3296         END
    3297 END
    3298 
    3299 # How to translate PS concepts into database lookups
    3300 DATABASE        METADATA
    3301         TYPE            dbEntry         TABLE           COLUMN          GIVENDBCOL      GIVENPS
    3302 #       CELL.GAIN       dbEntry         Camera          gain            chipId,cellId   CHIP.NAME,CELL.NAME
    3303 #       CELL.READNOISE  dbEntry         Camera          readNoise       chipId,cellId   CHIP.NAME,CELL.NAME
    3304 
    3305 # A database entry refers to a particular column (COLUMN) in a
    3306 # particular table (TABLE), given certain PS concepts (GIVENPS) that
    3307 # match certain database columns (GIVENDBCOL).
    3308 
    3309 END
    3310 \end{verbatim}
    3311 
    3312 \subsection{MegaCam Splice}
    3313 
    3314 \begin{verbatim}
    3315 # The spliced MecaCam data is stored in single extensions for each chip
    3316 
    3317 # How to recognise this type
    3318 RULE    METADATA
    3319         TELESCOP        STR     CFHT 3.6m
    3320         DETECTOR        STR     MegaCam
    3321         EXTEND          BOOL    T
    3322         NEXTEND         S32     36
    3323 END
    3324 
    3325 # How to read this data
    3326 PHU             STR     FPA     # The FITS file represents an entire FPA
    3327 EXTENSIONS      STR     CHIP    # The extensions represent chips
    3328 
    3329 # What's in the FITS file?
    3330 CONTENTS        METADATA
    3331         # Extension name, components
    3332         ccd00           STR     left right
    3333         ccd01           STR     left right
    3334         ccd02           STR     left right
    3335         ccd03           STR     left right
    3336         ccd04           STR     left right
    3337         ccd05           STR     left right
    3338         ccd06           STR     left right
    3339         ccd07           STR     left right
    3340         ccd08           STR     left right
    3341         ccd09           STR     left right
    3342         ccd10           STR     left right
    3343         ccd11           STR     left right
    3344         ccd12           STR     left right
    3345         ccd13           STR     left right
    3346         ccd14           STR     left right
    3347         ccd15           STR     left right
    3348         ccd16           STR     left right
    3349         ccd17           STR     left right
    3350         ccd18           STR     left right
    3351         ccd19           STR     left right
    3352         ccd20           STR     left right
    3353         ccd21           STR     left right
    3354         ccd22           STR     left right
    3355         ccd23           STR     left right
    3356         ccd24           STR     left right
    3357         ccd25           STR     left right
    3358         ccd26           STR     left right
    3359         ccd27           STR     left right
    3360         ccd28           STR     left right
    3361         ccd29           STR     left right
    3362         ccd30           STR     left right
    3363         ccd31           STR     left right
    3364         ccd32           STR     left right
    3365         ccd33           STR     left right
    3366         ccd34           STR     left right
    3367         ccd35           STR     left right
    3368 END
    3369 
    3370 # Specify the cells
    3371 CELLS           METADATA
    3372         left            METADATA
    3373                 CELL.BIASSEC    STR     HEADER:BSECA
    3374                 CELL.TRIMSEC    STR     HEADER:TSECA
    3375         END
    3376 
    3377         right           METADATA
    3378                 CELL.BIASSEC    STR     HEADER:BSECB
    3379                 CELL.TRIMSEC    STR     HEADER:TSECB
    3380         END
    3381 END
    3382 
    3383 # How to translate PS concepts into FITS headers
    3384 TRANSLATION     METADATA
    3385         FPA.NAME        STR     EXPNUM
    3386         FPA.AIRMASS     STR     AIRMASS
    3387         FPA.FILTER      STR     FILTER
    3388         FPA.POSANGLE    STR     ROTANGLE
    3389         FPA.RA          STR     RA
    3390         FPA.DEC         STR     DEC
    3391         FPA.RADECSYS    STR     RADECSYS
    3392         FPA.MJD         STR     MJD-OBS
    3393         CELL.EXPOSURE   STR     EXPTIME
    3394         CELL.DARKTIME   STR     DARKTIME
    3395         CELL.XBIN       STR     CCDBIN1
    3396         CELL.YBIN       STR     CCDBIN2
    3397         CELL.GAIN       STR     GAIN
    3398         CELL.READNOISE  STR     RDNOISE
    3399         CELL.SATURATION STR     SATURATE
    3400 END
    3401 
    3402 # Default PS concepts that may be specified by value
    3403 DEFAULTS        METADATA
    3404         CELL.BAD                S32     0
    3405         CELL.XPARITY            S32     1
    3406         CELL.YPARITY            S32     1
    3407 END
    3408 
    3409 
    3410 # How to translate PS concepts into database lookups
    3411 DATABASE        METADATA
    3412         TYPE            dbEntry         TABLE           COLUMN          GIVENDBCOL      GIVENPS
    3413 #       CELL.GAIN       dbEntry         Camera          gain            chipId,cellId   CHIP.NAME,CELL.NAME
    3414 #       CELL.READNOISE  dbEntry         Camera          readNoise       chipId,cellId   CHIP.NAME,CELL.NAME
    3415 
    3416 # A database entry refers to a particular column (COLUMN) in a
    3417 # particular table (TABLE), given certain PS concepts (GIVENPS) that
    3418 # match certain database columns (GIVENDBCOL).
    3419 
    3420 END             
    3421 \end{verbatim}
    3422 
    3423 \subsection{LRIS Blue}
    3424 
    3425 \begin{verbatim}
    3426 # The Low Resolution Imager and Spectrograph (LRIS) blue side
    3427 
    3428 # We have no choice but to hard-code the various regions, because Keck
    3429 # only stores them as:
    3430 # WINDOW  = '1,0,0,2048,4096'
    3431 # PREPIX  =                   51
    3432 # POSTPIX =                   80
    3433 # BINNING = '1,1     '
    3434 # AMPPSIZE= '[1:1024,1:4096]'
    3435 
    3436 # I don't know how we would get the IPP to react to changes in the
    3437 # windowing on the fly --- we have no mechanism for setting the region
    3438 # sizes on the basis of the above keywords.  Therefore, we hard-code
    3439 # the regions and assert on our assumptions in the RULE.
    3440 
    3441 
    3442 # How to identify this type
    3443 RULE    METADATA
    3444         TELESCOP        STR     Keck I
    3445         INSTRUME        STR     LRISBLUE
    3446         AMPLIST         STR     1,4,0,0
    3447         WINDOW          STR     1,0,0,2048,4096
    3448         PREPIX          S32     51
    3449         POSTPIX         S32     80
    3450         BINNING         STR     1,1
    3451         AMPPSIZE        STR     [1:1024,1:4096]
    3452         NAXIS1          S32     4620
    3453         NAXIS2          S32     4096
    3454 END
    3455 
    3456 # How to read this data
    3457 PHU             STR     FPA     # The FITS file represents an entire FPA
    3458 EXTENSIONS      STR     NONE    # There are no extensions
    3459 
    3460 # What's in the FITS file?
    3461 CONTENTS        METADATA
    3462         LeftChip        STR     amp1 amp2
    3463         RightChip       STR     amp3 amp4
    3464 END
    3465 
    3466 # Specify the cell data
    3467 CELLS   METADATA
    3468         amp1            METADATA
    3469                 CELL.BIASSEC    STR     VALUE:[1:51,1:4096];[4301:4380,1:4096]
    3470                 CELL.TRIMSEC    STR     VALUE:[205:1228,1:4096]
    3471                 CELL.GAIN       STR     VALUE:1.2
    3472                 CELL.READNOISE  STR     VALUE:5.6
    3473         END
    3474 
    3475         amp2    METADATA
    3476                 CELL.BIASSEC    STR     VALUE:[52:102,1:4096];[4381:4460,1:4096]
    3477                 CELL.TRIMSEC    STR     VALUE:[1229:2252,1:4096]
    3478                 CELL.GAIN       STR     VALUE:1.3
    3479                 CELL.READNOISE  STR     VALUE:6.7
    3480         END
    3481 
    3482         amp3            METADATA
    3483                 CELL.BIASSEC    STR     VALUE:[103:153,1:4096];[4461:4540,1:4096]
    3484                 CELL.TRIMSEC    STR     VALUE:[2253:3276,1:4096]
    3485                 CELL.GAIN       STR     VALUE:1.4
    3486                 CELL.READNOISE  STR     VALUE:7.8
    3487         END
    3488 
    3489         amp4    METADATA
    3490                 CELL.BIASSEC    STR     VALUE:[154:204,1:4096];[4541:4620,1:4096]
    3491                 CELL.TRIMSEC    STR     VALUE:[3277:4300,1:4096]
    3492                 CELL.GAIN       STR     VALUE:1.5
    3493                 CELL.READNOISE  STR     VALUE:8.9
    3494         END
    3495 END
    3496 
    3497 # How to translate PS concepts into FITS headers
    3498 TRANSLATION     METADATA
    3499         FPA.AIRMASS     STR     AIRMASS
    3500         FPA.FILTER      STR     BLUFILT
    3501         FPA.POSANGLE    STR     ROTPOSN
    3502         FPA.RA          STR     RA
    3503         FPA.DEC         STR     DEC
    3504         CELL.EXPOSURE   STR     EXPOSURE
    3505         CELL.DARKTIME   STR     EXPOSURE        // No special darktime header; use exposure time
    3506         CELL.DATE       STR     DATE            // NOTE: There are TWO keywords called "DATE" (creation, exp)!
    3507         CELL.TIME       STR     UT
    3508 END
    3509 
    3510 # Default PS concepts that may be specified by value
    3511 DEFAULTS        METADATA
    3512         FPA.RADECSYS    STR     ICRS
    3513 END
    3514 \end{verbatim}
    3515 
    3516 \subsection{LRIS Red}
    3517 
    3518 \begin{verbatim}
    3519 # The Low Resolution Imager and Spectrograph (LRIS) red side
    3520 
    3521 # We have no choice but to hard-code the various regions, because Keck
    3522 # only stores them as:
    3523 # WINDOW  = '0,0,0,2048,2048'
    3524 # PREPIX  =                   20
    3525 # POSTPIX =                   80
    3526 # BINNING = '1,1     '
    3527 # AMPPSIZE= '[1:1024,1:4096]'
    3528 
    3529 # I don't know how we would get the IPP to react to changes in the
    3530 # windowing on the fly --- we have no mechanism for setting the region
    3531 # sizes on the basis of the above keywords.  Therefore, we hard-code
    3532 # the regions and assert on our assumptions in the RULE.
    3533 
    3534 
    3535 # How to identify this type
    3536 RULE    METADATA
    3537         TELESCOP        STR     Keck I
    3538         INSTRUME        STR     LRIS
    3539         AMPLIST         STR     2,1,0,0
    3540         WINDOW          STR     0,0,0,2048,2048
    3541         PREPIX          S32     20
    3542         POSTPIX         S32     80
    3543         BINNING         STR     1, 1
    3544         CCDPSIZE        STR     [1:2048,1:2048]
    3545         NAXIS1          S32     2248
    3546         NAXIS2          S32     2048
    3547         IMTYPE          STR     TWOAMPTOP
    3548 END
    3549 
    3550 # How to read this data
    3551 PHU             STR     CHIP    # The FITS file represents a single chip
    3552 EXTENSIONS      STR     NONE    # There are no extensions
    3553 
    3554 # What's in the FITS file?
    3555 CONTENTS        STR     LeftSide RightSide
    3556 
    3557 # Specify the cell data
    3558 CELLS   METADATA
    3559         LeftSide        METADATA
    3560                 CELL.BIASSEC    STR     VALUE:[1:20,1:2048];[2089:2168,1:2048]
    3561                 CELL.TRIMSEC    STR     VALUE:[41:1064,1:2048]
    3562                 CELL.GAIN       STR     VALUE:1.2
    3563                 CELL.READNOISE  STR     VALUE:5.6
    3564         END
    3565 
    3566         RightSide       METADATA
    3567                 CELL.BIASSEC    STR     VALUE:[21:40,1:2048];[2169:2248,1:2048]
    3568                 CELL.TRIMSEC    STR     VALUE:[1065:2088,1:2048]
    3569                 CELL.GAIN       STR     VALUE:1.3
    3570                 CELL.READNOISE  STR     VALUE:6.5
    3571         END
    3572 END
    3573 
    3574 # How to translate PS concepts into FITS headers
    3575 TRANSLATION     METADATA
    3576         FPA.AIRMASS     STR     AIRMASS
    3577         FPA.FILTER      STR     FILTER
    3578         FPA.POSANGLE    STR     POSANG
    3579         FPA.RA          STR     OBJ-RA
    3580         FPA.DEC         STR     OBJ-DEC
    3581         CELL.EXPOSURE   STR     EXPTIME
    3582         CELL.DARKTIME   STR     DARKTIME
    3583         CELL.DATE       STR     DATE-OBS
    3584         CELL.TIME       STR     TIME-OBS
    3585 END
    3586 
    3587 # Default PS concepts that may be specified by value
    3588 DEFAULTS        METADATA
    3589         FPA.RADECSYS    STR     ICRS
    3590 END
    3591 \end{verbatim}
    3592 
    3593 \subsection{GPC OTA}
    3594 
    3595 \begin{verbatim}
    3596 # The raw GPC data comes off the telescope with each of the chips stored in separate files
    3597 
    3598 # How to identify this type
    3599 RULE    METADATA
    3600 #       TELESCOP        STR     PS1
    3601 #       DETECTOR        STR     GPC1
    3602         EXTEND          BOOL    T
    3603         NEXTEND         S32     64
    3604         NAMPS           S32     64
    3605 END
    3606 
    3607 # How to read this data
    3608 PHU             STR     CHIP    # The FITS file represents a single chip
    3609 EXTENSIONS      STR     CELL    # The extensions represent cells
    3610 
    3611 # What's in the FITS file?
    3612 CONTENTS        METADATA
    3613         # Extension name, type
    3614         xy00    STR     pitch10u
    3615         xy01    STR     pitch10u
    3616         xy02    STR     pitch10u
    3617         xy03    STR     pitch10u
    3618         xy04    STR     pitch10u
    3619         xy05    STR     pitch10u
    3620         xy06    STR     pitch10u
    3621         xy07    STR     pitch10u
    3622         xy10    STR     pitch10u
    3623         xy11    STR     pitch10u
    3624         xy12    STR     pitch10u
    3625         xy13    STR     pitch10u
    3626         xy14    STR     pitch10u
    3627         xy15    STR     pitch10u
    3628         xy16    STR     pitch10u
    3629         xy17    STR     pitch10u
    3630         xy20    STR     pitch10u
    3631         xy21    STR     pitch10u
    3632         xy22    STR     pitch10u
    3633         xy23    STR     pitch10u
    3634         xy24    STR     pitch10u
    3635         xy25    STR     pitch10u
    3636         xy26    STR     pitch10u
    3637         xy27    STR     pitch10u
    3638         xy30    STR     pitch10u
    3639         xy31    STR     pitch10u
    3640         xy32    STR     pitch10u
    3641         xy33    STR     pitch10u
    3642         xy34    STR     pitch10u
    3643         xy35    STR     pitch10u
    3644         xy36    STR     pitch10u
    3645         xy37    STR     pitch10u
    3646         xy40    STR     pitch10u
    3647         xy41    STR     pitch10u
    3648         xy42    STR     pitch10u
    3649         xy43    STR     pitch10u
    3650         xy44    STR     pitch10u
    3651         xy45    STR     pitch10u
    3652         xy46    STR     pitch10u
    3653         xy47    STR     pitch10u
    3654         xy50    STR     pitch10u
    3655         xy51    STR     pitch10u
    3656         xy52    STR     pitch10u
    3657         xy53    STR     pitch10u
    3658         xy54    STR     pitch10u
    3659         xy55    STR     pitch10u
    3660         xy56    STR     pitch10u
    3661         xy57    STR     pitch10u
    3662         xy60    STR     pitch10u
    3663         xy61    STR     pitch10u
    3664         xy62    STR     pitch10u
    3665         xy63    STR     pitch10u
    3666         xy64    STR     pitch10u
    3667         xy65    STR     pitch10u
    3668         xy66    STR     pitch10u
    3669         xy67    STR     pitch10u
    3670         xy70    STR     pitch10u
    3671         xy71    STR     pitch10u
    3672         xy72    STR     pitch10u
    3673         xy73    STR     pitch10u
    3674         xy74    STR     pitch10u
    3675         xy75    STR     pitch10u
    3676         xy76    STR     pitch10u
    3677         xy77    STR     pitch10u
    3678 END
    3679 
    3680 # Specify the cell data
    3681 CELLS   METADATA
    3682         pitch10u        METADATA
    3683                 CELL.BIASSEC    STR     VALUE:[575:606,1:594]
    3684                 CELL.TRIMSEC    STR     VALUE:[1:574,1:594]
    3685         #       CELL.BIASSEC    STR     HEADER:BIASSEC
    3686         #       CELL.TRIMSEC    STR     HEADER:DATASEC
    3687         END
    3688 
    3689         # This is just in here for fun
    3690         pitch12u        METADATA
    3691                 CELL.BIASSEC    STR     VALUE:[1:10,1:512];[523:574,1:512]
    3692                 CELL.TRIMSEC    STR     VALUE:[11:522,1:512]
    3693         #       CELL.BIASSEC    STR     HEADER:BIASSEC
    3694         #       CELL.TRIMSEC    STR     HEADER:TRIMSEC
    3695         END
    3696 END
    3697 
    3698 
    3699 # How to translate PS concepts into FITS headers
    3700 TRANSLATION     METADATA
    3701         CELL.BIN        STR     CCDSUM
    3702         CELL.SATURATION STR     SATURATE
    3703 END
    3704 
    3705 # Default PS concepts that may be specified by value
    3706 DEFAULTS        METADATA
    3707         FPA.AIRMASS     F32     0.0
    3708         FPA.FILTER      STR     NONE
    3709         FPA.POSANGLE    F32     0.0
    3710         FPA.RA          STR     0:0:0
    3711         FPA.DEC         STR     0:0:0
    3712         FPA.RADECSYS    STR     ICRS
    3713         FPA.NAME        S32     0
    3714         FPA.MJD         F32     12345.6789
    3715         CELL.EXPOSURE   F32     0.0
    3716         CELL.DARKTIME   F32     0.0
    3717         CELL.GAIN       F32     1.0
    3718         CELL.READNOISE  F32     0.0
    3719         CELL.BAD        S32     0
    3720         CELL.BIN        S32     1
    3721         CELL.XPARITY    S32     1
    3722         CELL.YPARITY    S32     1
    3723 END
    3724 
    3725 # How to translate PS concepts into database lookups
    3726 DATABASE        METADATA
    3727         TYPE            dbEntry         TABLE           COLUMN          GIVENDBCOL      GIVENPS
    3728         CELL.GAIN       dbEntry         Camera          gain            chipId,cellId   CHIP,CELL
    3729         CELL.READNOISE  dbEntry         Camera          readNoise       chipId,cellId   CHIP,CELL
    3730 
    3731 # A database entry refers to a particular column (COLUMN) in a
    3732 # particular table (TABLE), given certain PS concepts (GIVENPS) that
    3733 # match certain database columns (GIVENDBCOL).
    3734 
    3735 END
    3736 \end{verbatim}
    3737 
    3738 
    3739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    3740 
    37413234\section{Revision Change Log}
    37423235\input{ChangeLogSDRS.tex}
Note: See TracChangeset for help on using the changeset viewer.