IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 3564


Ignore:
Timestamp:
Mar 30, 2005, 11:14:48 AM (21 years ago)
Author:
eugene
Message:

serious reorg for release 13

Location:
trunk/doc/pslib
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/pslib/ChangeLogADD.tex

    r3438 r3564  
    11
    2 \subsection{Changes from version 06 to version 07}
     2\subsection{Changes from version 06 (7 September 2004) to version 07 (24 November 2004)}
    33
    44\begin{itemize}
     
    1212\end{itemize}
    1313
    14 \subsection{Changes from version 07 to version 08}
     14\subsection{Changes from version 07 (24 November 2004) to version 08 (8 January 2005)}
    1515
    1616\begin{itemize}
     
    2020\end{itemize}
    2121
    22 \subsection{Changes from version 08 to version 09}
     22\subsection{Changes from version 08 (8 January 2005) to version 09 (14 February 2005)}
    2323
    2424\begin{itemize}
     
    2727  \code{PS_RESAMPLE_LAGRANGE}.
    2828\item Added section on FITS WCS.
     29\end{itemize}
     30
     31\subsection{Changes from version 09 (14 February 2005) to version 10 (29 March 2005}
     32
     33\begin{itemize}
    2934\item Changes to the Time section:
    3035\begin{itemize}
     
    3641\item Verbatim Fortran code for UT1 interpolation
    3742\end{itemize}
     43
     44\item section reorganization:
     45\begin{itemize}
     46\item renamed Astronomical Image Manipulations to Image Manipulations
     47\item moved Image Manipulations to own subsection before Astronomy Utilities
     48\item promoted all PSLib subsections to sections
    3849\end{itemize}
     50
     51\end{itemize}
  • trunk/doc/pslib/ChangeLogSDRS.tex

    r3537 r3564  
    1 %%% $Id: ChangeLogSDRS.tex,v 1.77 2005-03-29 03:42:16 price Exp $
     1%%% $Id: ChangeLogSDRS.tex,v 1.78 2005-03-30 21:14:48 eugene Exp $
    22
    33\subsection{Changes from version 00 to version 01}
     
    464464\end{itemize}
    465465
    466 \subsection{Changes from Revision 12 (9 February 2005) to Revision 13 (Present)}
     466\subsection{Changes from Revision 12 (9 February 2005) to Revision 13 (30 March 2005)}
    467467
    468468\begin{itemize}
     
    481481  from a file.
    482482\item \code{psMetadataAddV} changed to use \code{va_list} parameter (bug 312).
    483 \item Added \code{psPixels} structure, \code{psPixelsToMask},
    484   \code{psMaskToPixels}, \code{psPixelsConcatenate} and
    485   \code{psPixelsTransform}.
     483
    486484\item Modified \code{psImageTransform} in preparation for image combination.
     485
     486\item Added \code{psPixels} structure and related functions
    487487\item Added \code{psPlaneTransformDeriv}.
    488488\item Added \code{psImageGrowMask}.
     489\item Added Earth Orientation Calculations Section
     490
    489491\item Changes to the Time section:
    490492\begin{itemize}
     
    508510\item Adding logical operations (and, or) to \code{psBinaryOp}.
    509511\end{itemize}
     512
     513\item Substantial reorganization:
     514\begin{itemize}
     515\item Moved Metadata, Database, and XML sections to new section
     516\item Re-named Detector \& Sky Coordinates to Linear \& Spherical Coordinates
     517\item Moved Exposure and Observatory information out of 'Astronomical Images'
     518\item Moved Celestial Coordinate Systems out of 'Detector \& Sky Coordinates'
     519\item Added Atmospheric Effects section, incorporating psGrommit and airmass functions from other sections)
     520\item Moved Fixed Pattern out of Astronomical Images
     521\end{itemize}
     522\end{itemize}
  • trunk/doc/pslib/psLibADD.tex

    r3448 r3564  
    1 %%% $Id: psLibADD.tex,v 1.69 2005-03-18 20:40:14 jhoblitt Exp $
     1%%% $Id: psLibADD.tex,v 1.70 2005-03-30 21:14:48 eugene Exp $
    22\documentclass[panstarrs]{panstarrs}
    33
     
    1414\project{Pan-STARRS Image Processing Pipeline}
    1515\organization{Institute for Astronomy}
    16 \version{09}
     16\version{10}
    1717\docnumber{PSDC-430-006}
     18
     19\setcounter{tocdepth}{5} % lowest level to be included in toc
    1820
    1921\newcommand\citealt{}
     
    313301 & 2004 May 21 & Added section on 2D Chebyshev fitting, then removed. \\ \hline
    323402 & 2004 Jun 22 & modified stats specification \\ \hline
    33 03--05 & ??? & ??? \\ \hline
    34 06 & 2004 Sep 7 & Frozen for PSLib-2 \\ \hline
     3503 & 2004 Jul 13 & \\ \hline
     3604 & 2004 Aug 16 & \\ \hline
     3705 & 2004 Sep 01 & \\ \hline
     3806 & 2004 Sep 07 & Frozen for PSLib-2 \\ \hline
    353907 & 2004 Nov 24 & Frozen for Cycle 4 \\ \hline
    364008 & 2005 Jan 21 & Draft for Cycle 5 \\ \hline
    374109 & 2005 Feb 14 & Frozen for Cycle 5 \\ \hline
     4210 & 2005 Mar 21 & Draft for Cycle 6 \\ \hline
    3843\RevisionsEnd
    3944
     
    6974\pagenumbering{arabic}
    7075
    71 \section{Pan-STARRS Library PSLib}
    72 
    73 \subsection{Math Utilities}
    74 
    75 \subsubsection{Sorting}
     76% \section{Pan-STARRS Library PSLib}
     77
     78\section{PSLib Math Utilities}
     79
     80\subsection{Sorting}
    7681
    7782A variety of sorting algorithms exist, with a wide range in speed for
     
    103108\code{in.arr[out->arr[0]]} to \code{in.arr[out->arr[in.n - 1]]}.
    104109
    105 \subsubsection{Smoothing: Boxcar and Gaussian}
     110\subsection{Smoothing: Boxcar and Gaussian}
    106111\label{smooth}
    107112
     
    135140\end{equation}
    136141
    137 \subsubsection{Statistics}
     142\subsection{Statistics}
    138143
    139144The general statistics function \code{psStats} performs a variety of
     
    148153sample and robust estimators.
    149154
    150 \paragraph{Sample Statistics}
     155\subsubsection{Sample Statistics}
    151156
    152157We define the following statistical terms, assuming there is a set of
    153158data elements $x_i$ with (standard) errors $\sigma_i$.
    154159
    155 \subparagraph{Mean}
     160\paragraph{Mean}
    156161
    157162The simple mean is defined as:
     
    160165\end{equation}
    161166
    162 \subparagraph{Weighted Mean}
     167\paragraph{Weighted Mean}
    163168
    164169The weighted mean is defined as:
     
    170175standard definition of the mean.
    171176
    172 \subparagraph{Median}
     177\paragraph{Median}
    173178
    174179The median is defined as the value for which 50\% of the data values
     
    181186calculating the sample median.
    182187
    183 \subparagraph{Upper and Lower Quartiles}
     188\paragraph{Upper and Lower Quartiles}
    184189
    185190The upper and lower quartiles ($U_{\frac{1}{4}}$ and
     
    196201the sample quartiles.
    197202
    198 \subparagraph{Standard Deviation}
     203\paragraph{Standard Deviation}
    199204
    200205The standard deviation of the sample is given by:
     
    218223
    219224
    220 \paragraph{Clipped Statistics}
     225\subsubsection{Clipped Statistics}
    221226
    222227The clipped statistics are used to determine the mean and standard
     
    255260\bar{x}| > k \sigma_i$.
    256261
    257 \paragraph{Robust Statistics}
     262\subsubsection{Robust Statistics}
    258263
    259264The robust version of the statistics provides estimators of basic
     
    312317quartiles are estimated in the same manner as above.
    313318
    314 \paragraph{Histograms}
     319\subsubsection{Histograms}
    315320
    316321When calculating histograms in the presence of known errors in the
     
    342347Note that the total adds to one --- the number of values added.
    343348
    344 \subsubsection{Matrix Operations}
     349\subsection{Matrix Operations}
    345350
    346351In this section, we define the linear algebra operations performed on
     
    361366\code{gsl_linalg_LU_decomp}.
    362367
    363 \paragraph{LU Decomposition}
     368\subsubsection{LU Decomposition}
    364369\label{LUdecomp}
    365370
     
    402407\end{equation}
    403408
    404 \paragraph{Calculate a matrix determinant}
     409\subsubsection{Calculate a matrix determinant}
    405410
    406411The determinant $D$ of a matrix $a_{ij}$ is calculated from the
     
    418423shall be used.
    419424
    420 \paragraph{Solving a Linear Equation}
     425\subsubsection{Solving a Linear Equation}
    421426
    422427The LU decomposition of a matrix may be used to solve the
     
    438443\end{eqnarray}
    439444
    440 \paragraph{Invert a matrix}
     445\subsubsection{Invert a matrix}
    441446
    442447Inversion of a matrix using the LU decomposition is performed by
     
    447452operation shall be implemented using the GSL function \code{gsl_linalg_LU_invert}.
    448453
    449 \paragraph{Perform matrix addition, subtraction and multiplication}
     454\subsubsection{Perform matrix addition, subtraction and multiplication}
    450455
    451456Matrix binary arithmetic operations differ from image binary
     
    471476\times$.
    472477
    473 \paragraph{Transpose a matrix}
     478\subsubsection{Transpose a matrix}
    474479
    475480The transpose of a matrix is simply the reorganization of the matrix
     
    484489where $M_{ij}$ is the matrix to be transposed.
    485490
    486 \paragraph{Convert a matrix to a vector}
     491\subsubsection{Convert a matrix to a vector}
    487492
    488493Matrix-to-vector conversion is only defined for a matrix that has a
     
    493498matrix is converted to a \code{PS_DIMEN_TRANV}-type vector.
    494499
    495 \subsubsection{Fitting}
    496 
    497 \paragraph{Chi-squared}
     500\subsection{Fitting}
     501
     502\subsubsection{Chi-squared}
    498503\label{chisq}
    499504
     
    506511\end{equation}
    507512
    508 \paragraph{General Polynomial Fitting}
     513\subsubsection{General Polynomial Fitting}
    509514
    510515Given a set of data values $y_i$ with errors $\sigma_i$, related to
     
    531536(section~\ref{LUdecomp}).
    532537
    533 \subsubsection{Non-linear Minimization}
    534 
    535 \paragraph{Levenberg-Marquardt Method}
     538\subsection{Non-linear Minimization}
     539
     540\subsubsection{Levenberg-Marquardt Method}
    536541
    537542In the Levenberg-Marquardt Method (LMM; see NR \S 15.5), we make a
     
    612617
    613618
    614 \paragraph{Powell's method}
     619\subsubsection{Powell's method}
    615620
    616621Powell's method is a type of ``Direction Set'' methods in
     
    621626manner until the advances along the vectors are smaller than some
    622627pre-defined tolerance.  Such direction set methods, including Powell's
    623 Quadratically Convergent method are discussed in NR\S10.5.
     628Quadratically Convergent method are discussed in NR \S 10.5.
    624629
    625630We will use for our algorithm the modified version of Powell's
     
    665670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    666671
    667 \subsubsection{Polynomials}
     672\subsection{Polynomials}
    668673\label{sec:polynomials}
    669674
     
    703708$-1 < x < 1$.
    704709
    705 \paragraph{Multi-dimensional polynomials}
     710\subsubsection{Multi-dimensional polynomials}
    706711
    707712Multi-dimensional polynomials shall be composed of multiplications of
     
    711716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    712717
    713 \subsubsection{(Fast) Fourier Transforms}
     718\subsection{(Fast) Fourier Transforms}
    714719
    715720(Fast) Fourier Transforms (FFTs) shall be implemented using the
     
    717722library}.
    718723
    719 \paragraph{FFTW Plans}
     724\subsubsection{FFTW Plans}
    720725
    721726FFTW requires the user to create a ``plan'' for each transform size,
     
    733738initialisation of the PSLib FFT functions and saved at the conclusion.
    734739
    735 \paragraph{Function mapping}
     740\subsubsection{Function mapping}
    736741
    737742The forward and reverse transforms call the corresponding
     
    750755place to avoid the need to pad the input array to hold the output.
    751756
    752 \paragraph{More Complicated Functions}
     757\subsubsection{More Complicated Functions}
    753758
    754759\code{psFFTCrossCorrelate()} and \code{psFFTConvolve()} both involve
     
    772777caller, and choose to normalise by $1/N^2$.
    773778
     779\subsection{Image Manipulations}
     780
     781\subsubsection{Interpolation}
     782
     783Interpolation is needed in various image manipulation operations,
     784including rotation and resampling.  We have specified a function to
     785perform the interpolation using one of several possible interpolation
     786methods, defined below.  It is important in the discussions that
     787follow to remember that a pixel with column,row if $i,j$ has
     788coordinate at the center of $i+0.5,j+0.5$ and corners with coordinates
     789from $i,j$ to $i+1,j+1$.  Thus, the interpolation of a coordinate
     790$x,y$ = 5.0,4.0 is a value midway between the four pixels with
     791column,row of (5,4), (5,5), (6,4), (6,5). 
     792
     793\paragraph{Nearest Pixel Interpolation ({\tt PS\_INTERPOLATE\_FLAT})}
     794
     795In this interpolation, the value of the closest pixel is returned.
     796This is equivalent to pixel duplication or replication.
     797
     798\paragraph{Bilinear Interpolation ({\tt PS\_INTERPOLATE\_BILINEAR})}
     799
     800In this interpolation, the value at the coordinate is calculated using
     801linear interpolation in two dimensions from the four nearest neighbor
     802pixels.  The bilinear interpolation value at a coordinate $x,y$
     803depends on the four nearest neighbor pixels and the fractional
     804distance $fx,fy$ of the given coordinates from the centers of those
     805four pixels.  Consider four neighboring pixels at column,row of $i,j$,
     806$i+1,j$, $i,j+1$, and $i+1,j+1$ with pixel values $V_{0,0}$,
     807$V_{1,0}$, $V_{0,1}$, $V_{1,1}$.  The value at $x,y$ is given by:
     808\[ V = (V_{0,0}(1 - f_x) + V_{1,0}f_x)(1 - f_y) + (V_{0,1}(1-f_x) + V_{1,1}f_x)f_y \]
     809This expression is more efficiently evaluated by factoring and
     810calculating the expresion as:
     811\[ r_x = V_{0,0} + (V_{1,0} - V_{0,0})f_x \]
     812\[ V = r_x + (V_{0,1} + (V_{1,1} - V_{0,1})f_x - r_x)f_y \]
     813
     814Note that the values of $f_x$ and $f_y$ require some care.  Given a
     815coordinate $x,y$, the value of $f_x$ is calculated as $f_x - 0.5 -
     816int(f_x - 0.5)$.  For example, when interpolating the value at
     817(5.8.5.2), the relevant neighbor pixels are (5,4), (6,4), (5,5), (6,5)
     818and the fractional coordinate values $f_x, f_y = 0.3, 0.7$.  The
     819resulting coordinate would be contained within the pixel at column,row
     820(5,5).
     821
     822\paragraph{Sinc Interpolation ({\tt PS\_INTERPOLATE\_LANCZOS[234]})}
     823
     824Because it would be slow to specify the size of the kernel
     825dynamically, we specify three hard-coded kernel sizes: 4, 6 and 8
     826pixels in each dimension (a kernel of size 2 pixels in each dimension
     827is handled by the bilinear interpolation).  These correspond to the
     828options \code{PS_INTERPOLATE_LANCZOS2}, \code{PS_INTERPOLATE_LANCZOS3} and
     829\code{PS_INTERPOLATE_LANCZOS4}, respectively.
     830
     831Given a position on the input image, $(x_0,y_0)$, a kernel is derived
     832according to pixels local to the position:
     833\begin{equation}
     834  h(x,y) = {\rm sinc}(\pi \delta x) {\rm sinc}(\pi \delta x / N) \rm{sinc}(\pi \delta y) \rm{sinc}(\pi \delta y / N)
     835\end{equation}
     836where
     837\begin{eqnarray}
     838  \delta x & = & x - x_0 \\
     839  \delta y & = & y - y_0 \\
     840  {\rm sinc}(z) & = & \sin(z)/z
     841\end{eqnarray}
     842and $N$ corresponds to the choice of kernel size.  For $N = 2$, the
     843kernel size is 4 pixels in each dimension (i.e., $-2 < \delta x \le
     8442$).  For $N = 3$, the kernel size is 6 pixels in each dimension
     845(i.e., $-3 < \delta x \le 3$).  For $N = 4$, the kernel size is 8
     846pixels in each dimension (i.e., $-4 < \delta x \le 4$).
     847
     848The interpolated value at the given position, $(x_0,y_0)$, is then
     849simply the dot product of the kernel and the fluxes:
     850\begin{equation}
     851  f(x_0,y_0) = \sum_R f(x,y) h(x,y)
     852\end{equation}
     853where $R$ is the region defined by the kernel size, and $f(x,y)$ is
     854the flux at the pixel position.
     855
     856For further information, see the
     857\href{http://terapix.iap.fr/IMG/pdf/swarp.pdf}{SWarp manual}.
     858
     859\subsubsection{Image Cuts and Slices}
     860
     861Several functions specify operations which manipulate a collection of
     862pixels to return a statistic on the pixel collection.  In the simplest
     863case, these are trivial to define: if the boundaries of the region of
     864interest are specified along integral pixel coordinates, then the
     865pixels used to measure the statistic are always an exact integer.
     866This is the case for the function \code{psImageSlice} which requires a
     867starting coordinate which is an integer and a width in both dimensions
     868which is an integer.  For the case of the functions \code{psImageCut}
     869and \code{psImageRadialCut}, the situation is a bit more subtle.  In
     870both of these cases, the region is unlikely to contain only whole
     871pixels and some choices must be made.
     872
     873One posibility which we reject is to identify the fractional pixels
     874which are overlapped by the region of interest and add that fraction
     875of the pixel's flux when calculating the statistic of interest.  This
     876is computationally intensive, and not necessarily well defined for all
     877statistics. 
     878
     879In PSLib, we instead identify the pixels overlapped by the region, use
     880the complete set of pixel values, treating all pixels equally, and
     881renormalize as needed.  To perform this, the region of interest is
     882laid on top of the image pixels.  Any pixels which overlap the region
     883are identified as part of the input sample.  The statistic (ie, sample
     884mean, robust mode, etc), is then calculated on this collection of
     885pixels.  If the output statistic is an average value, the measured
     886value is reported.  If the output statistic is a sum value (sum of
     887counts, sum of pixels), then the value is renormalized by the ratio of
     888pixels used in the calculation to the pixel area of the region of
     889interest.  For example, if the sum within a radial aperture is
     890requested, the circle of the specified radius and center is placed on
     891the pixel grid.  Any pixels which touch the circle are then placed in
     892a list to be analysed.  The statistic of interest is the measured for
     893this collection of pixels.  In the case of a circular aperture which
     894is centered at the coordinate (2,2) and has a radius of 2, the number
     895of pixels which are touched by the circle is 16, while the total pixel
     896area of the circle is 12.57 square pixels.  In this case, the pixel
     897sum is renormalized by the ratio (12.57/16.00).
     898
     899\paragraph{Radial Cuts}
     900
     901Consider an image with pixels $x_i,y_i$ and a reference coordinate
     902$x_c, y_c$.  We want to construct a radial cut by measuring statistics
     903for pixels in a sequence of radial annulii $r_s < r < r_e$.  For each
     904annulus, we need to select the pixels which fall within this annulus.
     905The coordinates of the center of pixel $i,j$ are $i+0.5,j+0.5$.  A
     906given pixel has a distance from the reference coordinate of $dX = x_c
     907- i - 0.5, dY = y_c - j - 0.5$.  The pixels to be used for a given
     908radial annulus are all of those pixels for which $r_s < \sqrt{dX^2 +
     909  dY^2} < r_e$.  This is more efficiently calculated by comparing the
     910square of the radii and distances.  All pixels which satisfy the above
     911condition are included in a specific annular radius.  All average
     912quantities are calculated directly from the pixel ensemble
     913statistics. 
     914
     915\paragraph{Arbitrary Linear Cuts}
     916
     917Select the pixels which lie along a line following steps of 1 pixel
     918length:
     919
     920\begin{verbatim}
     921
     922  dX = xe - xs;
     923  dY = ye - ys;
     924  L = hypot (dX, dY);
     925  dX = dX / L;
     926  dY = dY / L;
     927
     928  REALLOCATE (xvec[0].elements, float, MAX (L, 1));
     929  REALLOCATE (yvec[0].elements, float, MAX (L, 1));
     930  xvec[0].Nelements = L;
     931  yvec[0].Nelements = L;
     932
     933  V = (float *)buf[0].matrix.buffer;
     934  for (i = 0; i < L; i++) {
     935    xi = xs + i*dX - 0.5;
     936    yi = ys + i*dY - 0.5;
     937    xvec[0].elements[i] = i;
     938    yvec[0].elements[i] = V[xi + Nx*yi];
     939  }
     940\end{verbatim}
     941
     942\subsubsection{Image Rotation}
     943
     944Image rotation can be performed in two possible ways under different
     945circumstances, identified in the following discussion.
     946
     947In the simplest case, the rotation angle is an integer multiple of 90
     948degrees ($\pi/2$ rad).  In these cases, the input and output pixels
     949have a one-to-one mapping.  If the input image has dimensions of $N_x,
     950N_y$, then the output image will have dimensions of either $N_x, N_y$
     951(for even multiples of 90 degrees) or $N_y, N_x$ (for odd multiples).
     952
     953If the angle of the rotation is not a multiple of 90, then the output
     954pixels necessarily result from the interpolation of several input
     955pixels.  In this case, for an input image of dimensions $N_x, N_y$ and
     956rotation angle $\theta$, the output image has dimensions $Lx = |N_x
     957\cos \theta| + |N_y \sin \theta|$ and $Ly = |N_x \sin \theta| + |N_y
     958\cos \theta|$, each dimension rounded up to the nearest integer as
     959needed.  Every pixel in the output image is in general derived from an
     960interpolation over 4 neighboring pixels.  The coordinate of a pixel in
     961the output image ($i,j$) corresponds to a fractional pixel coordinate
     962($x,y$) in the input image according to:
     963\[ x = (i - i_o)*\cos\theta + (j - j_o)*\sin\theta \]
     964\[ y = (i_o - i)*\sin\theta + (j - j_o)*\cos\theta \]
     965where the offset coordinate ($i_o,j_o$) depends on the sign of the
     966sine of the angle $\theta$.  If the sign of that sine is positive, the
     967offset coordinate is ($N_y\sin\theta$,0), otherwise it is
     968(0,$-N_x\sin\theta$).
     969
    774970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    775971
    776 \subsection{Astronomy Utilities}
     972\pagebreak
     973\section{PSLib Astronomy Utilities}
    777974
    778975Most of the astronomy utilities will be implemented through wrapping
     
    782979the next release}
    783980
    784 \subsubsection{Time}
     981\subsection{Time}
    785982
    786983Correct time representation is \emph{critical} in astronomical software.  PSLib
     
    799996``1970-01-01T00:00:00Z'' UTC.
    800997
    801 \paragraph{Coordinated Universal Time (UTC)}
     998\subsubsection{Coordinated Universal Time (UTC)}
    802999
    8031000Coordinated Univeral Time (UTC) is defined by the International
     
    8291026timezone is forbidden.}
    8301027
    831 \paragraph{International Atomic Time (TAI)}
     1028\subsubsection{International Atomic Time (TAI)}
    8321029
    8331030International Atomic Time or Temps Atomique International (TAI) is a system of
     
    8451042seconds since the UNIX epoch of ``1970-01-01T00:00:00Z''.
    8461043
    847 \paragraph{Leap-seconds}
     1044\subsubsection{Leap-seconds}
    8481045
    8491046Leap seconds keep UTC within 0.9s of UT1.  The offset between TAI and
     
    8831080This data is available from: \code{ftp://maia.usno.navy.mil/ser7/tai-utc.dat}
    8841081
    885 \paragraph{Gregorian dates to seconds}
     1082\subsubsection{Gregorian dates to seconds}
    8861083
    8871084The Perl code below, based on an algorithm described in the book ``Calendrical
     
    10031200\end{verbatim}
    10041201Outputs year, month, day as \code{$y, $m, $d}.
     1202%$
    10051203
    10061204\emph{The above code was taken [and slightly altered] from
     
    10111209
    10121210
    1013 \paragraph{Universal Time (UT1)}
     1211\subsubsection{Universal Time (UT1)}
    10141212\label{sec:ut1}
    10151213
     
    10541252IERS publications references above, and should be interpolated in the same way.
    10551253
    1056 \paragraph{Julian Date and Modified Julian Date}
     1254\subsubsection{Julian Date and Modified Julian Date}
    10571255
    10581256The follow definitions of Julian Date (JD) and Modified Julian Date (MJD) was
     
    10621260http://www.iers.org/iers/earth/resolutions/UAI\_b1.html}.
    10631261
    1064 \subparagraph{Julian Date}
     1262\paragraph{Julian Date}
    10651263
    10661264\begin{verbatim}
     
    10891287\end{verbatim}
    10901288
    1091 \subparagraph{Modified Julian Date}
     1289\paragraph{Modified Julian Date}
    10921290
    10931291\begin{verbatim}
     
    10971295\end{verbatim}
    10981296
    1099 \subparagraph{JD and MJD conversion}
     1297\paragraph{JD and MJD conversion}
    11001298
    11011299Conversion between \code{psTime} values and MJD and JD are determined
     
    11151313\end{equation}
    11161314
    1117 \paragraph{Terrestrial Time (TT)}
     1315\subsubsection{Terrestrial Time (TT)}
    11181316
    11191317Terrestrial Time (TT) is defined as a fixed offset from TAI.
     
    11231321\end{equation}
    11241322
    1125 \paragraph{TT as Julian Centuries since J2000.0}
     1323\subsubsection{TT as Julian Centuries since J2000.0}
    11261324
    11271325The algorithm for calulating GMST requires TT formated in Julian centruies
     
    11311329\end{equation}
    11321330
    1133 \paragraph{UT1 as Julian Centuries since J2000.0}
     1331\subsubsection{UT1 as Julian Centuries since J2000.0}
    11341332
    11351333The algorithm for calulating GMST requires UT1 be formated in Julian centuries
     
    11401338\end{equation}
    11411339
    1142 \paragraph{Greenwich Mean Sidereal Time (GMST)}
     1340\subsubsection{Local Mean Sidereal Time (LMST)}
     1341
     1342Local Mean Sidereal Time (LMST) is Greenwich Mean Sideral Time (GMST) plus the
     1343observer's location in East longitude. Calculating LMST requires the input of
     1344Universal Time (UT1), Terrestrial Dynamical Time (TT) and a longitude (measured
     1345East of Greenwich).
     1346
     1347\begin{equation}
     1348LMST = GMST00(t_u, t) + longitude
     1349\end{equation}
     1350
     1351Gives $LMST$ in seconds.
     1352
     1353\subsubsection{Greenwich Mean Sidereal Time (GMST)}
    11431354
    11441355Greenwich Mean Sidereal Time (GMST) is caclulated from UT1 and TT.  This
     
    11591370Gives $GMST00$ in seconds.
    11601371
    1161 
    1162 \paragraph{Longitude}
     1372\subsubsection{Longitude}
    11631373
    11641374Longitudes are often expressed in the form of decimal degrees while the
     
    11691379\end{equation}
    11701380
    1171 \paragraph{Local Mean Sidereal Time (LMST)}
    1172 
    1173 Local Mean Sidereal Time (LMST) is Greenwich Mean Sideral Time (GMST) plus the
    1174 observer's location in East longitude. Calculating LMST requires the input of
    1175 Universal Time (UT1), Terrestrial Dynamical Time (TT) and a longitude (measured
    1176 East of Greenwich).
    1177 
    1178 \begin{equation}
    1179 LMST = GMST00(t_u, t) + longitude
    1180 \end{equation}
    1181 
    1182 Gives $LMST$ in seconds.
    1183 
    1184 \paragraph{Polar Motion}
     1381\subsubsection{Polar Motion}
     1382\tbd{move this to Earth Motion section}
    11851383
    11861384The polar coordinates, $x_p$ and $y_p$, required for the transformation from
     
    11901388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    11911389
    1192 \subsubsection{Astronomical Image Manipulations}
    1193 
    1194 \paragraph{Interpolation}
    1195 
    1196 Interpolation is needed in various image manipulation operations,
    1197 including rotation and resampling.  We have specified a function to
    1198 perform the interpolation using one of several possible interpolation
    1199 methods, defined below.  It is important in the discussions that
    1200 follow to remember that a pixel with column,row if $i,j$ has
    1201 coordinate at the center of $i+0.5,j+0.5$ and corners with coordinates
    1202 from $i,j$ to $i+1,j+1$.  Thus, the interpolation of a coordinate
    1203 $x,y$ = 5.0,4.0 is a value midway between the four pixels with
    1204 column,row of (5,4), (5,5), (6,4), (6,5). 
    1205 
    1206 \subparagraph{Nearest Pixel Interpolation ({\tt PS\_INTERPOLATE\_FLAT})}
    1207 
    1208 In this interpolation, the value of the closest pixel is returned.
    1209 This is equivalent to pixel duplication or replication.
    1210 
    1211 \subparagraph{Bilinear Interpolation ({\tt PS\_INTERPOLATE\_BILINEAR})}
    1212 
    1213 In this interpolation, the value at the coordinate is calculated using
    1214 linear interpolation in two dimensions from the four nearest neighbor
    1215 pixels.  The bilinear interpolation value at a coordinate $x,y$
    1216 depends on the four nearest neighbor pixels and the fractional
    1217 distance $fx,fy$ of the given coordinates from the centers of those
    1218 four pixels.  Consider four neighboring pixels at column,row of $i,j$,
    1219 $i+1,j$, $i,j+1$, and $i+1,j+1$ with pixel values $V_{0,0}$,
    1220 $V_{1,0}$, $V_{0,1}$, $V_{1,1}$.  The value at $x,y$ is given by:
    1221 \[ V = (V_{0,0}(1 - f_x) + V_{1,0}f_x)(1 - f_y) + (V_{0,1}(1-f_x) + V_{1,1}f_x)f_y \]
    1222 This expression is more efficiently evaluated by factoring and
    1223 calculating the expresion as:
    1224 \[ r_x = V_{0,0} + (V_{1,0} - V_{0,0})f_x \]
    1225 \[ V = r_x + (V_{0,1} + (V_{1,1} - V_{0,1})f_x - r_x)f_y \]
    1226 
    1227 Note that the values of $f_x$ and $f_y$ require some care.  Given a
    1228 coordinate $x,y$, the value of $f_x$ is calculated as $f_x - 0.5 -
    1229 int(f_x - 0.5)$.  For example, when interpolating the value at
    1230 (5.8.5.2), the relevant neighbor pixels are (5,4), (6,4), (5,5), (6,5)
    1231 and the fractional coordinate values $f_x, f_y = 0.3, 0.7$.  The
    1232 resulting coordinate would be contained within the pixel at column,row
    1233 (5,5).
    1234 
    1235 \subparagraph{Sinc Interpolation ({\tt PS\_INTERPOLATE\_LANCZOS[234]})}
    1236 
    1237 Because it would be slow to specify the size of the kernel
    1238 dynamically, we specify three hard-coded kernel sizes: 4, 6 and 8
    1239 pixels in each dimension (a kernel of size 2 pixels in each dimension
    1240 is handled by the bilinear interpolation).  These correspond to the
    1241 options \code{PS_INTERPOLATE_LANCZOS2}, \code{PS_INTERPOLATE_LANCZOS3} and
    1242 \code{PS_INTERPOLATE_LANCZOS4}, respectively.
    1243 
    1244 Given a position on the input image, $(x_0,y_0)$, a kernel is derived
    1245 according to pixels local to the position:
    1246 \begin{equation}
    1247   h(x,y) = {\rm sinc}(\pi \delta x) {\rm sinc}(\pi \delta x / N) \rm{sinc}(\pi \delta y) \rm{sinc}(\pi \delta y / N)
    1248 \end{equation}
    1249 where
    1250 \begin{eqnarray}
    1251   \delta x & = & x - x_0 \\
    1252   \delta y & = & y - y_0 \\
    1253   {\rm sinc}(z) & = & \sin(z)/z
    1254 \end{eqnarray}
    1255 and $N$ corresponds to the choice of kernel size.  For $N = 2$, the
    1256 kernel size is 4 pixels in each dimension (i.e., $-2 < \delta x \le
    1257 2$).  For $N = 3$, the kernel size is 6 pixels in each dimension
    1258 (i.e., $-3 < \delta x \le 3$).  For $N = 4$, the kernel size is 8
    1259 pixels in each dimension (i.e., $-4 < \delta x \le 4$).
    1260 
    1261 The interpolated value at the given position, $(x_0,y_0)$, is then
    1262 simply the dot product of the kernel and the fluxes:
    1263 \begin{equation}
    1264   f(x_0,y_0) = \sum_R f(x,y) h(x,y)
    1265 \end{equation}
    1266 where $R$ is the region defined by the kernel size, and $f(x,y)$ is
    1267 the flux at the pixel position.
    1268 
    1269 For further information, see the
    1270 \href{http://terapix.iap.fr/IMG/pdf/swarp.pdf}{SWarp manual}.
    1271 
    1272 \paragraph{Image Cuts and Slices}
    1273 
    1274 Several functions specify operations which manipulate a collection of
    1275 pixels to return a statistic on the pixel collection.  In the simplest
    1276 case, these are trivial to define: if the boundaries of the region of
    1277 interest are specified along integral pixel coordinates, then the
    1278 pixels used to measure the statistic are always an exact integer.
    1279 This is the case for the function \code{psImageSlice} which requires a
    1280 starting coordinate which is an integer and a width in both dimensions
    1281 which is an integer.  For the case of the functions \code{psImageCut}
    1282 and \code{psImageRadialCut}, the situation is a bit more subtle.  In
    1283 both of these cases, the region is unlikely to contain only whole
    1284 pixels and some choices must be made.
    1285 
    1286 One posibility which we reject is to identify the fractional pixels
    1287 which are overlapped by the region of interest and add that fraction
    1288 of the pixel's flux when calculating the statistic of interest.  This
    1289 is computationally intensive, and not necessarily well defined for all
    1290 statistics. 
    1291 
    1292 In PSLib, we instead identify the pixels overlapped by the region, use
    1293 the complete set of pixel values, treating all pixels equally, and
    1294 renormalize as needed.  To perform this, the region of interest is
    1295 laid on top of the image pixels.  Any pixels which overlap the region
    1296 are identified as part of the input sample.  The statistic (ie, sample
    1297 mean, robust mode, etc), is then calculated on this collection of
    1298 pixels.  If the output statistic is an average value, the measured
    1299 value is reported.  If the output statistic is a sum value (sum of
    1300 counts, sum of pixels), then the value is renormalized by the ratio of
    1301 pixels used in the calculation to the pixel area of the region of
    1302 interest.  For example, if the sum within a radial aperture is
    1303 requested, the circle of the specified radius and center is placed on
    1304 the pixel grid.  Any pixels which touch the circle are then placed in
    1305 a list to be analysed.  The statistic of interest is the measured for
    1306 this collection of pixels.  In the case of a circular aperture which
    1307 is centered at the coordinate (2,2) and has a radius of 2, the number
    1308 of pixels which are touched by the circle is 16, while the total pixel
    1309 area of the circle is 12.57 square pixels.  In this case, the pixel
    1310 sum is renormalized by the ratio (12.57/16.00).
    1311 
    1312 \subparagraph{Radial Cuts}
    1313 
    1314 Consider an image with pixels $x_i,y_i$ and a reference coordinate
    1315 $x_c, y_c$.  We want to construct a radial cut by measuring statistics
    1316 for pixels in a sequence of radial annulii $r_s < r < r_e$.  For each
    1317 annulus, we need to select the pixels which fall within this annulus.
    1318 The coordinates of the center of pixel $i,j$ are $i+0.5,j+0.5$.  A
    1319 given pixel has a distance from the reference coordinate of $dX = x_c
    1320 - i - 0.5, dY = y_c - j - 0.5$.  The pixels to be used for a given
    1321 radial annulus are all of those pixels for which $r_s < \sqrt{dX^2 +
    1322   dY^2} < r_e$.  This is more efficiently calculated by comparing the
    1323 square of the radii and distances.  All pixels which satisfy the above
    1324 condition are included in a specific annular radius.  All average
    1325 quantities are calculated directly from the pixel ensemble
    1326 statistics. 
    1327 
    1328 \subparagraph{Arbitrary Linear Cuts}
    1329 
    1330 Select the pixels which lie along a line following steps of 1 pixel
    1331 length:
     1390\subsection{2D transformations}
     1391
     1392In PSLib, we implement 2-dimensional transformations using
     1393\code{psPlaneTransform}, which contains a matrix of polynomial
     1394coefficients for each dimension.  Since we are using these to model
     1395the real world, where, for example, a particular point on the detector
     1396maps to a particular point on the sky, we consider only
     1397transformations that are ``one-to-one''.  This makes it possible to
     1398speak of inverse transformations, and of combining multiple
     1399transformations.
     1400
     1401Given a transformation, $f(x,y)$, the inverse transformation,
     1402$g(x,y)$, is that for which $g(f(x,y)) = (x,y)$ for $(x,y)$ over the
     1403range of interest (not necessarily the entire set of real numbers).
     1404
     1405Given two transformations, $f(x,y)$ and $g(x,y)$, the combined
     1406transformation is the transformation, $h(x,y) = g(f(x,y))$ for $(x,y)$
     1407over the range of interest (not necessarily the entire set of real
     1408numbers).
     1409
     1410Both of these operations are straightforward if the transformation is
     1411linear.  If the function $(u,v) = f(x,y)$ is:
     1412\begin{eqnarray}
     1413u & = & a + bx + cy \\
     1414v & = & d + ex + fy
     1415\end{eqnarray}
     1416then the inverse transformation $(x,y) = g(u,v)$ is:
     1417\begin{eqnarray}
     1418x & = & (-fa+cd)/\Delta + fu/\Delta - cv/\Delta \\
     1419y & = & (ae-bd)/\Delta - eu/\Delta + bv/\Delta
     1420\end{eqnarray}
     1421where $\Delta = bf - ce$ is the matrix determinant.  Given two
     1422functions $f_i(x,y)$ for $i=1,2$:
     1423\begin{eqnarray}
     1424u & = & a_i + b_i x + c_i y \\
     1425v & = & d_i + e_i x + f_i y
     1426\end{eqnarray}
     1427then the combined transformation, $(u,v) = f_2(f_1(x,y))$ is:
     1428\begin{eqnarray}
     1429u & = & (a_2 + b_2 a_1 + c_2 d_1) + (b_2 b_1 + c_2 e_1) x + (b_2 c_1 + c_2 f_1) y \\
     1430v & = & (d_2 + e_2 a_1 + f_2 d_1) + (e_2 b_1 + f_2 e_1) x + (e_2 c_1 + f_2 f_1) y
     1431\end{eqnarray}
     1432
     1433When the transformations are not linear, the inverse and combined
     1434transformations can be estimated by sampling a grid over the region of
     1435interest, calculating the transformation (or double transformation)
     1436for each sample, and using this information to derive the best fit
     1437transformation that produces the inverse or combined transformation.
     1438The inverse transformation should be of the same order as that of the
     1439forward transformation, while the combined transformation should be of
     1440the higher order of the two component transformations.
     1441
     1442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     1443
     1444\subsection{Spherical Rotations with Quaternions}
     1445
     1446\subsubsection{Quaternion Construction}
     1447
     1448The following describes the algorithms needed to implement 3-D
     1449rotations in terms of quaternions. A quaternion is an ordered set of
     1450four numbers, $\bar{q} = (q_0, q_1, q_2, q_3)$. A rotation of angle
     1451$\theta$ about the axis defined by the unit vector $(v_x, v_y, v_z)$
     1452has quaternion components:
     1453\begin{eqnarray}
     1454q_0 & = & v_x sin(\theta/2), \\
     1455q_1 & = & v_y sin(\theta/2), \\
     1456q_2 & = & v_z sin(\theta/2), and \\
     1457q_3 & = & cos(\theta/2). \\
     1458\end{eqnarray}
     1459Note that the sine and cosine are taken of the half angle of the
     1460rotation.  Note also that this implies that the quaternion components
     1461are normalized such that $|\bar{q}| \def q_0^2 + q_1^2 + q_2^2 + q_3^2
     1462= 1$.
     1463
     1464The 3-vector representation of the angle of the pole is determined
     1465from the coordinate of the pole ($\alpha_p, \delta_p$) by:
     1466\begin{eqnarray}
     1467v_x & = & \cos \delta_p \cos \alpha_p \\
     1468v_y & = & \cos \delta_p \sin \alpha_p \\
     1469v_x & = & \sin \delta_p \\
     1470\end{eqnarray}
     1471
     1472\subsubsection{Combining Two Rotations}
     1473
     1474Given two quaternions $\bar{p1}$ and $\bar{p2}$, there is a third
     1475quaternion, $\bar{p}$, which represents the result of first applying
     1476$\bar{p1}$, and then $\bar{p2}$. The components of $\bar{p}$ are given
     1477by:
    13321478
    13331479\begin{verbatim}
    1334 
    1335   dX = xe - xs;
    1336   dY = ye - ys;
    1337   L = hypot (dX, dY);
    1338   dX = dX / L;
    1339   dY = dY / L;
    1340 
    1341   REALLOCATE (xvec[0].elements, float, MAX (L, 1));
    1342   REALLOCATE (yvec[0].elements, float, MAX (L, 1));
    1343   xvec[0].Nelements = L;
    1344   yvec[0].Nelements = L;
    1345 
    1346   V = (float *)buf[0].matrix.buffer;
    1347   for (i = 0; i < L; i++) {
    1348     xi = xs + i*dX - 0.5;
    1349     yi = ys + i*dY - 0.5;
    1350     xvec[0].elements[i] = i;
    1351     yvec[0].elements[i] = V[xi + Nx*yi];
    1352   }
     1480p_0 & = &  p2_3 p1_0 + p2_2 p1_1 - p2_1 p1_2 + p2_0 p1_3 \\
     1481p_1 & = & -p2_2 p1_0 + p2_3 p1_1 + p2_0 p1_2 + p2_1 p1_3 \\
     1482p_2 & = &  p2_1 p1_0 - p2_0 p1_1 + p2_3 p1_2 + p2_2 p1_3 \\
     1483p_3 & = & -p2_0 p1_0 - p2_1 p1_1 - p2_2 p1_2 + p2_3 p1_3 \\
    13531484\end{verbatim}
    13541485
    1355 \paragraph{Image Rotation}
    1356 
    1357 Image rotation can be performed in two possible ways under different
    1358 circumstances, identified in the following discussion.
    1359 
    1360 In the simplest case, the rotation angle is an integer multiple of 90
    1361 degrees ($\pi/2$ rad).  In these cases, the input and output pixels
    1362 have a one-to-one mapping.  If the input image has dimensions of $N_x,
    1363 N_y$, then the output image will have dimensions of either $N_x, N_y$
    1364 (for even multiples of 90 degrees) or $N_y, N_x$ (for odd multiples).
    1365 
    1366 If the angle of the rotation is not a multiple of 90, then the output
    1367 pixels necessarily result from the interpolation of several input
    1368 pixels.  In this case, for an input image of dimensions $N_x, N_y$ and
    1369 rotation angle $\theta$, the output image has dimensions $Lx = |N_x
    1370 \cos \theta| + |N_y \sin \theta|$ and $Ly = |N_x \sin \theta| + |N_y
    1371 \cos \theta|$, each dimension rounded up to the nearest integer as
    1372 needed.  Every pixel in the output image is in general derived from an
    1373 interpolation over 4 neighboring pixels.  The coordinate of a pixel in
    1374 the output image ($i,j$) corresponds to a fractional pixel coordinate
    1375 ($x,y$) in the input image according to:
    1376 \[ x = (i - i_o)*\cos\theta + (j - j_o)*\sin\theta \]
    1377 \[ y = (i_o - i)*\sin\theta + (j - j_o)*\cos\theta \]
    1378 where the offset coordinate ($i_o,j_o$) depends on the sign of the
    1379 sine of the angle $\theta$.  If the sign of that sine is positive, the
    1380 offset coordinate is ($N_y\sin\theta$,0), otherwise it is
    1381 (0,$-N_x\sin\theta$).
    1382 
    1383 \subsubsection{Celestial Coordinate Conversions}
     1486\subsubsection{Rotating a Vector}
     1487
     1488You may rotate a unit vector by first constructing a quaternion
     1489$\bar{p2}$, whose first three components are the components of the
     1490unit vector, and whose fourth component is zero. To rotate this vector
     1491by a quaternion $\bar{p1}$, you apply the formula above for combining
     1492two quaternions. The rotated vector is found in the first three
     1493components of the resulting quaternion, $\bar{p}$.
     1494
     1495\subsubsection{Rotation Matrix}
     1496
     1497The rotation matrix representation of a rotation may be derived
     1498directly from the quaternion representation.  The following formulae
     1499convert a quaternion to a rotation matrix:
     1500
     1501\begin{eqnarray}
     1502    rot_{x,x} & = &  q_0 q_0 - q_1 q_1 - q_2 q_2 + q_3 q_3 \\
     1503    rot_{y,y} & = & -q_0 q_0 + q_1 q_1 - q_2 q_2 + q_3 q_3 \\
     1504    rot_{z,z} & = & -q_0 q_0 - q_1 q_1 + q_2 q_2 + q_3 q_3 \\
     1505
     1506    rot_{x,y} & = & 2 (q_0 q_1 + q_2 q_3) \\
     1507    rot_{y,x} & = & 2 (q_0 q_1 - q_2 q_3) \\
     1508
     1509    rot_{x,z} & = & 2 (q_0 q_2 - q_1 q_3) \\
     1510    rot_{z,x} & = & 2 (q_0 q_2 + q_1 q_3) \\
     1511
     1512    rot_{y,z} & = & 2 (q_1 q_2 + q_0 q_3) \\
     1513    rot_{z,y} & = & 2 (q_1 q_2 - q_0 q_3) \\
     1514\end{eqnarray}
     1515
     1516\subsubsection{Conversion to Other Representations}
     1517
     1518You may convert a rotation matrix, m, to a quaternion, p, with the following
     1519code:
     1520
     1521\begin{verbatim}
     1522double diag_sum[3];
     1523int maxi;
     1524double recip;
     1525
     1526diag_sum[0]=1+m[0][0]-m[1][1]-m[2][2];
     1527diag_sum[1]=1-m[0][0]+m[1][1]-m[2][2];
     1528diag_sum[2]=1-m[0][0]-m[1][1]+m[2][2];
     1529diag_sum[3]=1+m[0][0]+m[1][1]+m[2][2];
     1530
     1531
     1532maxi=0;
     1533for(i=1;i<4;++i) {
     1534    if(diag_sum[i]>diag_sum[maxi]) maxi=i;
     1535}
     1536
     1537
     1538p[maxi]=0.5*sqrt(diag_sum[maxi]);
     1539recip=1./(4.*p[maxi]);
     1540
     1541if(maxi==0) {
     1542    p[1]=recip*(m[0][1]+m[1][0]);
     1543    p[2]=recip*(m[2][0]+m[0][2]);
     1544    p[3]=recip*(m[1][2]-m[2][1]);
     1545
     1546} else if(maxi==1) {
     1547    p[0]=recip*(m[0][1]+m[1][0]);
     1548    p[2]=recip*(m[1][2]+m[2][1]);
     1549    p[3]=recip*(m[2][0]-m[0][2]);
     1550
     1551} else if(maxi==2) {
     1552    p[0]=recip*(m[2][0]+m[0][2]);
     1553    p[1]=recip*(m[1][2]+m[2][1]);
     1554    p[3]=recip*(m[0][1]-m[1][0]);
     1555
     1556} else if(maxi==3) {
     1557    p[0]=recip*(m[1][2]-m[2][1]);
     1558    p[1]=recip*(m[2][0]-m[0][2]);
     1559    p[2]=recip*(m[0][1]-m[1][0]);
     1560}
     1561\end{verbatim}
     1562
     1563\subsection{Celestial Coordinate Conversions}
    13841564
    13851565Changes between spherical coordinate systems (ie, Ecliptic, Galactic,
     
    14261606the forward transformation.
    14271607
    1428 \paragraph{Galactic to ICRS}
     1608\subsubsection{Galactic to ICRS}
    14291609
    14301610The appropriate values, from the Hipparcos and Tycho Catalogues are:
     
    14351615\end{eqnarray}
    14361616
    1437 \paragraph{Ecliptic to ICRS}
     1617\subsubsection{Ecliptic to ICRS}
    14381618
    14391619The appropriate values, from Zombeck, are:
     
    14451625where $T$ is the time in Julian centuries since 1900.
    14461626
    1447 \paragraph{Precession}
     1627\subsubsection{Precession}
    14481628
    14491629The appropriate values, from Elixir, are:
     
    14571637
    14581638
    1459 \paragraph{Suggested test cases}
     1639\subsubsection{Suggested test cases}
    14601640
    14611641$(\alpha,\delta) = (0^\circ,0^\circ)$ transforms to Galactic
     
    14791659
    14801660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1481 \subsubsection{2D transformations}
    1482 
    1483 In PSLib, we implement 2-dimensional transformations using
    1484 \code{psPlaneTransform}, which contains a matrix of polynomial
    1485 coefficients for each dimension.  Since we are using these to model
    1486 the real world, where, for example, a particular point on the detector
    1487 maps to a particular point on the sky, we consider only
    1488 transformations that are ``one-to-one''.  This makes it possible to
    1489 speak of inverse transformations, and of combining multiple
    1490 transformations.
    1491 
    1492 Given a transformation, $f(x,y)$, the inverse transformation,
    1493 $g(x,y)$, is that for which $g(f(x,y)) = (x,y)$ for $(x,y)$ over the
    1494 range of interest (not necessarily the entire set of real numbers).
    1495 
    1496 Given two transformations, $f(x,y)$ and $g(x,y)$, the combined
    1497 transformation is the transformation, $h(x,y) = g(f(x,y))$ for $(x,y)$
    1498 over the range of interest (not necessarily the entire set of real
    1499 numbers).
    1500 
    1501 Both of these operations are straightforward if the transformation is
    1502 linear.  If the function $(u,v) = f(x,y)$ is:
    1503 \begin{eqnarray}
    1504 u & = & a + bx + cy \\
    1505 v & = & d + ex + fy
    1506 \end{eqnarray}
    1507 then the inverse transformation $(x,y) = g(u,v)$ is:
    1508 \begin{eqnarray}
    1509 x & = & (-fa+cd)/\Delta + fu/\Delta - cv/\Delta \\
    1510 y & = & (ae-bd)/\Delta - eu/\Delta + bv/\Delta
    1511 \end{eqnarray}
    1512 where $\Delta = bf - ce$ is the matrix determinant.  Given two
    1513 functions $f_i(x,y)$ for $i=1,2$:
    1514 \begin{eqnarray}
    1515 u & = & a_i + b_i x + c_i y \\
    1516 v & = & d_i + e_i x + f_i y
    1517 \end{eqnarray}
    1518 then the combined transformation, $(u,v) = f_2(f_1(x,y))$ is:
    1519 \begin{eqnarray}
    1520 u & = & (a_2 + b_2 a_1 + c_2 d_1) + (b_2 b_1 + c_2 e_1) x + (b_2 c_1 + c_2 f_1) y \\
    1521 v & = & (d_2 + e_2 a_1 + f_2 d_1) + (e_2 b_1 + f_2 e_1) x + (e_2 c_1 + f_2 f_1) y
    1522 \end{eqnarray}
    1523 
    1524 When the transformations are not linear, the inverse and combined
    1525 transformations can be estimated by sampling a grid over the region of
    1526 interest, calculating the transformation (or double transformation)
    1527 for each sample, and using this information to derive the best fit
    1528 transformation that produces the inverse or combined transformation.
    1529 The inverse transformation should be of the same order as that of the
    1530 forward transformation, while the combined transformation should be of
    1531 the higher order of the two component transformations.
    1532 
    1533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1534 
    1535 \subsubsection{Projections}
    1536 
    1537 We implement three types of projections: {\em zenithal}, {\em
    1538 cylindrical} and {\em pseudocylindrical}, each requiring slightly
    1539 different handling.  Our representations are based on the treatment of
    1540 projections presented by
    1541 \href{http://www.cv.nrao.edu/fits/documents/wcs/wcs.all.ps}{Greisen \&
    1542 Calabretta (1995, ADASS, 4, 233)}.  In all of these projections, we
    1543 are converting from a spherical coordinate $\alpha,\delta$ to a linear
    1544 (2-D) coordinate $x_p,y_p$.  The projection is defined by the
    1545 projection type, the projection center ($\alpha_p, \delta_p$) and the
    1546 the plate scales in the $x_p$ and $y_p$ directions ($\rho_x,\rho_y$).
    1547 
    1548 In the structure, \code{psProjection}, the projection type is defined
    1549 by the element \code{type}, the projection center $\alpha_p,\delta_p$
    1550 is defined by the elements \code{R,D}, and the plate scales,
    1551 $\rho_x,\rho_y$, are defined by the elements \code{Xs,Ys}.  The plate
    1552 scales are applied independently to the $x$ and $y$ coordinates to
    1553 convert them to the corresponding linear units (ie, pixels):
    1554 %
    1555 \begin{eqnarray}
    1556 x_p & = & \rho_x x \\
    1557 y_p & = & \rho_y y \\
    1558 \end{eqnarray}
    1559 %
    1560 In the discussions below, we ignore this last step (or first step,
    1561 depending on the direction of the conversion).
    1562 
    1563 \paragraph{Zenithal Projections}
    1564 
    1565 The {\em zenithal} projections are defined relative to a set of
    1566 spherical coordinates with pole at the center of the projection
    1567 ($\alpha_p, \delta_p$), and which thus represents a coordinate system
    1568 rotated relative to the coordinate system of $\alpha, \delta$.  In
    1569 this spherical coordinate system, the coordinate of longitude is
    1570 labeled $\phi$, and has domain of $-\pi < \phi \le \pi$, while the
    1571 latitude, measured from the pole, is labeled $\theta$ and has domain
    1572 $0 \le \theta \le \pi$.  The coordinate frame of $\phi,\theta$ is
    1573 defined so that $\phi_p$, the longitude of the target system pole, is
    1574 0.0.
    1575 
    1576 For an arbitrary projection center, it is necessary to convert the
    1577 spherical coordinates to be projected ($\alpha,\delta$) to the
    1578 projection spherical coordinate system coordinates ($\phi, \theta$).
    1579 In practice, we construct the following useful trigonometric
    1580 relationships between $\phi$ and $\theta$ which may be employed in the
    1581 equations of $x,y$ below:
    1582 %
    1583 \begin{eqnarray}
    1584 \sin \theta           & = & \sin \delta \sin \delta_p + \cos \delta \cos \delta_p \cos (\alpha - \alpha_p) \\
    1585 \cos \theta \cos \phi & = & \sin \delta \cos \delta_p - \cos \delta \sin \delta_p \cos (\alpha - \alpha_p) \\
    1586 \cos \theta \sin \phi & = & - \cos \delta \sin (\alpha - \alpha_p)
    1587 \end{eqnarray}
    1588 %
    1589 For the inverse transformations, the equivalent relationships are:
    1590 %
    1591 \begin{eqnarray}
    1592 \sin \delta                          & = & \sin \theta \sin \delta_p + \cos \theta \cos \delta_p \cos \phi \\
    1593 \cos \delta \cos (\alpha - \alpha_p) & = & \sin \theta \cos \delta_p - \cos \theta \sin \delta_p \cos \phi \\
    1594 \cos \delta \sin (\alpha - \alpha_p) & = & - \cos \theta \sin \phi
    1595 \end{eqnarray}
    1596 %
    1597 For zenithal projections, the linear coordinates are related to
    1598 $\phi,\theta$ by:
    1599 %
    1600 \begin{eqnarray}
    1601 x & = & R_\theta \sin \phi \\
    1602 y & = & -R_\theta \cos \phi
    1603 \end{eqnarray}
    1604 %
    1605 and the inverse:
    1606 %
    1607 \begin{eqnarray}
    1608 R_\theta & = & \sqrt{x^2 + y^2} \\
    1609 \phi     & = & {\rm atan} (-y,x)
    1610 \end{eqnarray}
    1611 %
    1612 The coordinates $x,y$ above are defined to be in angular units (ie,
    1613 radians). 
    1614 
    1615 From these relationships, we can calculate $\alpha, \delta$ as:
    1616 %
    1617 \begin{eqnarray}
    1618 \alpha - \alpha_p & = & \arctan (\sin \alpha, \cos \alpha) \\
    1619 \delta            & = & \arcsin (\sin \delta) \\
    1620 \end{eqnarray}
    1621 %
    1622 Note that if $(x,y) = (0,0)$, then $\alpha = \alpha_p, \delta = \delta_p$.
    1623 
    1624 \subparagraph{Gnomonic}
    1625 
    1626 The Gnomonic projection (``TAN'') is a zenithal projection with
    1627 $R_\theta = \cot \theta$.  The resulting relationships for $(x,y)$ and
    1628 for $\sin \theta, \cos \theta$ are:
    1629 
    1630 \begin{eqnarray}
    1631 x           & = & \frac{\cos \theta \sin \phi}{\sin \theta} \\
    1632 y           & = & \frac{-\cos \theta \cos \phi}{\sin \theta} \\
    1633 \sin \theta & = & \zeta / \sqrt{1 + \zeta^2} \\
    1634 \cos \theta & = & 1 / \sqrt{1 + \zeta^2} \\
    1635 \end{eqnarray}
    1636 
    1637 where $\zeta = 1 / R_\theta$.
    1638 
    1639 \subparagraph{Orthographic}
    1640 
    1641 The Orthographic projection (``SIN'') is a zenithal projection with
    1642 $R_\theta = \cos \theta$.  The resulting relationships for $(x,y)$ and
    1643 for $\sin \theta, \cos \theta$ are:
    1644 
    1645 \begin{eqnarray}
    1646 x           & = & \cos \theta \sin \phi \\
    1647 y           & = & -\cos \theta \cos \phi \\
    1648 \sin \theta & = & \sqrt{1 - R_\theta^2} \\
    1649 \cos \theta & = & R_\theta \\
    1650 \end{eqnarray}
    1651 
    1652 \paragraph{Cylindrical and Pseudocylindrical Projections}
    1653 
    1654 The {\em cylindrical} and {\em pseudocylindrical} projections are
    1655 defined relative to a set of cylindrical coordinates whose pole is
    1656 coincident with the pole of the spherical coordinates.  These
    1657 projections are particularly used for full-sky representations, and
    1658 are only defined for projection centers with $\delta_p = 0$.  In this
    1659 spherical coordinate system, the coordinate of longitude is labeled
    1660 $\phi$, and has domain of $-\pi < \phi \le \pi$, while the latitude,
    1661 measured from the pole, is labeled $\theta$ and has domain $0 \le
    1662 \theta \le \pi$.  The projection center longitude, $\alpha_p$
    1663 corresponds to $\phi = 0$, thus the value of $\phi$ is determined as
    1664 $\alpha - \alpha_p$ for all such projections.
    1665 
    1666 \subparagraph{Cartesian}
    1667 
    1668 The Cartesian projection (``CAR'') is a very simple cylindrical
    1669 projection with the following relationships between $x,y$ and
    1670 $\phi,\theta$:
    1671 
    1672 \begin{eqnarray}
    1673 x & = & \phi \\
    1674 y & = & \theta
    1675 \end{eqnarray}
    1676 
    1677 \subparagraph{Mercator}
    1678 
    1679 The Mercator projection (``MER'') is a cylindrical projection.
    1680 
    1681 \begin{eqnarray}
    1682 x & = & \phi \\
    1683 y & = & \ln \left( \tan (\pi/4 + \theta/2) \right) \\
    1684 {\rm and}\hspace{1cm} \theta & = & 2 \arctan \left( e^y \right) - \pi/2
    1685 \end{eqnarray}
    1686 
    1687 \subparagraph{Hammer-Aitoff}
    1688 
    1689 The Hammer-Aitoff projection(``AIT'') is a pseudocylindrical projection, and is defined:
    1690 
    1691 \begin{eqnarray}
    1692 x & = & 2 \zeta \cos \theta \sin \frac{\phi}{2} \\
    1693 y & = & \zeta \sin \theta \\
    1694 {\rm where}\hspace{1cm} \zeta^{-1} & \equiv & \sqrt{\frac{1}{2}\left(1 + \cos \theta \cos \frac{\phi}{2} \right)}
    1695 \end{eqnarray}
    1696 
    1697 And in reverse:
    1698 
    1699 \begin{eqnarray}
    1700 \phi & = & 2 {\rm \arctan} (2z^2 - 1, x z) \\
    1701 \theta & = & \arcsin (yz) \\
    1702 {\rm where}\hspace{1cm} z & \equiv & \sqrt{1 - (x/2)^2 - y^2}
    1703 \end{eqnarray}
    1704 
    1705 \subparagraph{Parabolic}
    1706 
    1707 The Parabolic projection (``PAR'') is a pseudocylindrical projection, and is defined:
    1708 
    1709 \begin{eqnarray}
    1710 x & = & \phi \left( 2 \cos \frac{2 \theta}{3} - 1 \right) \\
    1711 y & = & \pi \sin \frac{\theta}{3} \\
    1712 \end{eqnarray}
    1713 
    1714 And in reverse:
    1715 
    1716 \begin{eqnarray}
    1717 \theta & = & 3 \sin^{-1} \rho \\
    1718 \phi   & = & \frac{x}{1 - 4\rho^2} \\
    1719 {\rm where}\hspace{1cm} \rho & \equiv & y/\pi \\
    1720 \end{eqnarray}
    1721 
    1722 \subsubsection{Offset}
    1723 
    1724 Coordinate offsets can be either spherical offsets or linear offsets.
    1725 
    1726 A spherical offset is performed by adding the components of the
    1727 offset, after unit conversion, to the given position.  The resulting
    1728 coordinates must be wrapped to within the allowed range ($-\pi$ to
    1729 $\pi$, 0 to $2\pi$).
    1730 
    1731 A linear offset is defined to be a linear offset in a tangent
    1732 projection centered on the starting coordinate with $y$ axis aligned
    1733 with the local direction or increasing Declination.  This projection
    1734 is undefined only for the coordinates exactly at the north and south
    1735 poles, in which case the orientation is defined to have the $y$ axis
    1736 parallel to the line of RA = 0.0.  The scale of the projection is 1.0
    1737 (ie, 1 'pixel' is 1 radian) and the given offsets must the scaled
    1738 based on the given offset units. 
    1739 
    1740 Pseudo-code to implement the above for an offset:
    1741 
    1742 \begin{verbatim}
    1743 psSphere *psSphereSetOffset (psSphere pos, psSphere offset) {
    1744 
    1745   psPlane lin;
    1746   psSphere new;
    1747   psProjection proj;
    1748 
    1749   proj.R = pos->r;
    1750   proj.D = pos->d;
    1751   proj.X = 0;
    1752   proj.Y = 0;
    1753   proj.type = PS_PROJ_TAN;
    1754 
    1755   lin.x = offset.r;
    1756   lin.y = offset.d;
    1757 
    1758   new = psDeproject (&lin, &proj);
    1759   return (new);
    1760 }
    1761 \end{verbatim}
    1762 
    1763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1764 
    1765 \subsubsection{Tangent Plane to Sky}
     1661
     1662\subsection{Tangent Plane to Sky}
    17661663
    17671664\tbd{we will replace the SLALIB version of AOPPA with a new function}
     
    17981695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    17991696
    1800 \subsubsection{The One-to-Many Problem with Mosaic Cameras}
     1697\subsection{Sky to Tangent Plane (II)}
     1698
     1699This section describes the transformation between celestial coordinates
     1700(R.A., Dec.) and local terrestrial coordinates (Az, Alt). This transformation
     1701is broken down into a number of steps as described below.
     1702
     1703\paragraph{Reference Implementations}
     1704
     1705There are two reference implementatins for the code to account for the
     1706motion of the Earth in space. The first are the sample routines
     1707provided by the IERS to accompany chaper 5 of IERS Bulletin 32.  This
     1708document and the code can be downloaded from
     1709http://maia.usno.navy.mil/conv2003.html .  The second reference
     1710implementation is the SOFA software package managed by the IAU and
     1711available at http://www.iau-sofa.rl.ac.uk Only the 2003-04-29 version
     1712of SOFA should be used.  The IERS code requires a few of the rotation
     1713matrix utility routines from SOFA.
     1714
     1715Both implementations are in FORTRAN 77. The SOFA code has a more
     1716complex implementation of precession-nutation for backward
     1717compatibility with the pre 2003-01-01 conventions.  The IERS code
     1718includes some tricks to achieve greater precision in the fundamental
     1719arguments of nutation, which the SOFA code omits.  Therefore, the main
     1720reference for psLib should be the IERS code.  Note that the IERS code
     1721calculates the transform from terrestrial to celestial coordinates,
     1722while the SOFA code calculates its inverse.
     1723
     1724\subsubsection{Coordinate Systems}
     1725
     1726\begin{figure}
     1727\psfig{file=transforms.ps}
     1728\caption{Coordinates systems and the transformations between them}
     1729
     1730\end{figure}
     1731Figure X shows the transformation steps and intermediate coordinate systems
     1732between celestial and local terrestrial coordinate systems. The intermediate
     1733coordinate systems are defined below.
     1734
     1735\paragraph{ICRS}
     1736The official IAU-sanctioned celestial coordinate system is the
     1737International Celestial Reference System (ICRS). It is defined in terms of
     1738a number of radio sources whose positions have been measured using VLBI.
     1739It can be tied to the optical through the Hipparcos catalog. The ICRS has its
     1740origin at the solar system barycenter.
     1741
     1742\paragraph{GCRS}
     1743The Geocentric Celestial Reference System (GCRS) corresponds to the ICRS, but
     1744has its origin at the center of the Earth. The differences between the two
     1745systems are due to the velocity of the Earth (aberration), the position of
     1746the Earth (parallax), and general relativistic bending of light rays.
     1747There is no net rotation between the ICRS and the GCRS.
     1748
     1749\paragraph{ITRS}
     1750The International Terrestrial Reference System (ITRS) is a coordinate
     1751system which is fixed with respect to the Earth's crust.
     1752
     1753\paragraph{Intermediate Coordinate Systems - CIP, CEO, TEO}
     1754The transform between the GCRS and ITRS is conventionally
     1755decomposed into three parts in order to isolate the relatively rapid rotation
     1756of the Earth from the movement of the Earth's rotational axis in the GCRS
     1757and ITRS. All three sub-transforms are rigid rotations.
     1758
     1759This decomposition results in two intermediate coordinate systems. Both of
     1760these share the same pole, known as the Celestial Intermediate Pole (CIP).
     1761The CIP is defined by its motion in the GCRS to match the Tisserand
     1762mean axis of the Earth (Seidelmann 1982, Celesial Mechanics 27, 78-106),
     1763excluding motions with periods less than or equal
     1764to two days. The CIP approximates the angular momentum vector of the
     1765rotating Earth.
     1766
     1767The X axes of the intermediate coordinate systems are known as the
     1768Celestial and Terrestrial Ephemeris Origins. (CEO and TEO). Both are defined
     1769to be non-rotating origins. A non-rotating origin is a point on the equator
     1770whose instantaneous motion is always orthogonal to the equator
     1771(Kaplan 2003 IAU XXV Joint Discussion 16
     1772\footnote{http://aa.usno.navy.mil/kaplan/NROs\%5BJD16proc\%5D.pdf}).
     1773Thus the CEO is defined by its position in the GCRS at some epoch and by the
     1774motion of the CIP in the GCRS since that date. Similarly the TEO is
     1775defined by its position in the ITRS at some epoch and the motion of the
     1776CIP in the ITRS since that date.
     1777
     1778\subsubsection{ICRS - GCRS}
     1779
     1780The transformation between barycentric (ICRS) and geocentric (GCRS) coordinates
     1781involves two components. These are
     1782the general relativistic deflection of light rays by the Sun's gravity, and
     1783aberration, due to the orbital motion
     1784of the Earth.
     1785
     1786\paragraph{Gravitational Deflection}
     1787
     1788The Sun's gravity bends the path of light rays which pass near it.
     1789To first order, a light ray is deflected by an angle of $4GM/c^2r_0$ radians,
     1790where $G$ is the gravitational constant,
     1791$M$ is the mass of the Sun,
     1792$c$ is the speed of light, and
     1793$r_0$ is the point of closest approach to the light ray to the Sun.
     1794To the same order this is equal to the impact parameter - i.e. the point
     1795of closest approach if the light ray were not deflected. Note that
     1796$r_0/d = \tan(\theta)$, where $d$ is the distance from the Earth
     1797to the Sun, and $\theta$
     1798is the angular separation of the star from the center of the Sun.
     1799
     1800There is a maximum deflection of 1.75 arc seconds if we set
     1801$r_0$ to the radius of the sun.
     1802Since the Sun bends light rays toward it, a star appears shifted away from the sun in the sky.
     1803
     1804\paragraph{Aberration}
     1805
     1806Aberration is the apparent change in direction of a ray of light in the
     1807reference frame of a moving observer. Traditionally the aberration
     1808calculation has been done with a linear expansion of the full
     1809relativistic expression, often neglecting all but the linear term in
     1810$v/c$, since the relativistic terms are on the order of a miliarcsecond.
     1811However, the full relativistic expression poses no challenge for modern
     1812computers, so psLib will use the following procedure to calculate aberration.
     1813
     1814Suppose an observer has a velocity $\beta\hat{\beta}$, with respect to
     1815the Solar System barycenter, where $\beta$ is in units of the speed of
     1816light, and $\hat{\beta}$ is a unit vector. Suppose also that the unit vector
     1817$\hat{r}$ points toward a star in the barycenter frame of reference
     1818(i.e. the ``actual'' position).
     1819and $\hat{r}'$ gives the direction of the star in the observer's frame,
     1820(i.e. the apparent position).
     1821
     1822First, decompose $\hat{r}$ into components parallel and perpendicular to
     1823$\hat{\beta}$ by calculating
     1824$\mu = \hat{r}\cdot\hat{\beta}$ and
     1825$\vec{r}_\perp = \hat{r} - \mu \hat{\beta}$.
     1826
     1827Next, use the following expression for relativistic beaming, modified
     1828slightly from equation 4.8b of Rybicki and Lightman:
     1829\begin{equation}
     1830\mu' = \mu + \beta \frac{\mu^2 - 1}{1 - \beta\mu}
     1831\end{equation}
     1832where $\mu' = \hat{r}' \cdot \hat{\beta}$.
     1833
     1834Now, the component of $\hat{r}'$ perpendicular to $\hat{\beta}$
     1835(i.e. $\vec{r}_\perp'$) must point
     1836in the same direction as $\vec{r}_\perp$, but will have a different magnitude
     1837because $\hat{r}'$ is a unit vector. In other words,
     1838$\vec{r}_\perp' = a\vec{r}_\perp$, for some scalar $a$. So the next step is
     1839to calculate $a = \sqrt{(1-\mu'^2)/\vec{r}_\perp}$.
     1840
     1841Finally, reassemble the components of
     1842$\hat{r}' = \mu'\hat{\beta} + a \vec{r_\perp}$.
     1843
     1844
     1845\subsubsection{GCRS - ITRS}
     1846The transformation between geocentric celestial coordinates and terrestrial
     1847coordinates is a solid body rotation due to the motion of the Earth is space.
     1848This is conventionally broken down into three components to isolate the
     1849relatively rapid rotation of the Earth from the motion of its rotational axis.
     1850
     1851This section is largely a summary of
     1852Chapter 5 of IERS Technical Note 32 \footnote{http://maia.usno.navy.mil/conv2003.html}
     1853(hereafter IERS32),
     1854which is a description of the implementation of the Resoltions of the
     1855XXIVth General Assembly of the IAU, available from the same URL as above.
     1856These two documents describe a set of conventions which have been in effect
     1857since 2003-01-01. The conventions in effect before that date will not be
     1858implemented by psLib.
     1859
     1860
     1861\paragraph{Precession/Nutation}
     1862
     1863The transform between the GCRS and the CIP/CEO coordinate systems is described
     1864by the IAU 2000A precession-nutation model, which is accurate to the
     18650.2 mas level.
     1866For higher accuracy the user must apply corrections to the model, which are tabulated by the IERS.
     1867
     1868
     1869
     1870The IAU 2000A precession-nutation model may be calculated in the following
     1871way. First calculate the time $t$ as the number of Julian centuries since
     18722000-01-01T12:00:00 TT.
     1873
     1874Next calculate the fundamental arguments of nutation using equations (40)
     1875and (41) of IERS32, reproduced below:
     1876\begin{eqnarray}
     1877F_1\equiv l\quad  =~&\ Mean\ Anomaly\ of\ the\ Moon \cr
     1878 =~& 134.96340251^\circ + 1717915923.2178'' t
     1879 + 31.8792'' t^2 + 0.051635'' t^3 - 0.00024470'' t^4,\cr
     1880F_2\equiv l'\quad =~&\ Mean\ Anomaly\ of\ the\ Sun\cr
     1881=~& 357.52910918^\circ + 129596581.0481'' t
     1882- 0.5532'' t^2 + 0.000136'' t^3 - 0.00001149'' t^4,\cr
     1883F_3\equiv F\quad  =~& L - \Omega\cr
     1884=~& 93.27209062^\circ + 1739527262.8478'' t - 12.7512'' t^2
     1885- 0.001037'' t^3 + 0.00000417'' t^4,\cr
     1886F_4\equiv D\quad  =~&\ Mean\ Elongation\ of\ the\ Moon\ from\ the\ Sun\cr
     1887=~& 297.85019547^\circ + 1602961601.2090'' t - 6.3706'' t^2
     1888+ 0.006593'' t^3 - 0.00003169'' t^4,\cr
     1889F_5\equiv\Omega\quad  =~&\ Mean\ Longitude\ of\ the\ Ascending\ Node\ of\
     1890the\ Moon\cr
     1891=~& 125.04455501^\circ - 6962890.5431'' t + 7.4722'' t^2 + 0.007702'' t^3 - 0.00005939'' t^4 \cr
     1892F_6\ \equiv l_{Me}\quad    =~& 4.402 608 842 + 2608.7903 141 574\times t,\cr
     1893F_7\ \equiv l_{Ve}\quad    =~& 3.176 146 697 + 1021.3285 546 211 \times t,\cr
     1894F_8\ \equiv l_{E\ }\quad   =~& 1.753 470 314 + 628.3075 849 991 \times t,\cr
     1895F_9\equiv l_{Ma}\quad    =~& 6.203 480 913 + 334.0612 426 700 \times t,\cr
     1896F_{10}\equiv l_{Ju}\quad =~& 0.599 546 497 + 52.9690 962 641 \times t,\cr
     1897F_{11}\equiv l_{Sa}\quad =~& 0.874 016 757 + 21.3299 104 960 \times t,\cr
     1898F_{12}\equiv l_{Ur}\quad =~& 5.481 293 872 +  7.4781 598 567 \times t,\cr
     1899F_{13}\equiv l_{Ne}\quad =~& 5.311 886 287 +  3.8133 035 638 \times t,\cr
     1900F_{14}\equiv p_{a\ }\quad =~& 0.024 381 750 \times t + 0.000 005 386 91 \times t^2.
     1901\end{eqnarray}
     1902
     1903Next calculate the quantities $X$, $Y$, and $s$, using expressions of the form:
     1904
     1905\begin{equation}
     1906     \sum_{j} p_j t^j + \sum_{j}\sum_{i}[
     1907     (a_{{\rm s},j})_i t^j \sin ({\rm \scriptstyle {ARG_{i,j}}})
     1908   + (a_{{\rm c},j})_i t^j \cos ({\rm \scriptstyle {ARG_{i,j}}})]
     1909   ,
     1910\end{equation}
     1911
     1912where the $\rm \scriptstyle{ARG_{i,j}} = \sum_{k} w_{i,j,k} F_k$ represent linear
     1913combinations of the fundamental arguments of nutation.
     1914
     1915The constants $p_j$, $w_{i,j,k}$, $(a_{{\rm s},j})_i$, and $(a_{{\rm c},j})_i$
     1916are given in the ASCII files:
     1917tab5.2a.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2a.txt} (for $X$),
     1918tab5.2b.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2b.txt} (for $Y$), and
     1919tab5.2c.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2c.txt} (for $s+XY/2$).
     1920Note that the expansion is given for $s+XY/2$, since this series converges
     1921more rapidly than the one for $s$ alone.
     1922
     1923Each file contains a human-readable header, which includes the polynomial
     1924coeficients, $p_j$ under the heading ``Polynomial part''. The data part of the
     1925file lists the remaining constants, with rows cycling first through $i$, and
     1926then through $j$. There is a separate heading each time $j$ increments.
     1927Each row contains the following columns:
     1928
     1929\begin{itemize}
     1930\item col 1 - A running index of rows in the table.
     1931\item col 2 - The sine coeficients, $(a_{{\rm s},j})_i$
     1932\item col 3 - The cosine coeficients, $(a_{{\rm c},j})_i$
     1933\item cols 4 - 17 The weighting factors for the fundamental arguments of
     1934                  nutation, $w_{i,j,k}$.
     1935\end{itemize}
     1936
     1937
     1938A FORTRAN reference implementation for the precession/nutation model is available from the IERS
     1939\footnote{http://maia.usno.navy.mil/conv2000/chapter5/XYS2000A.f}.
     1940The psLib results should agree with the reference implementation to within
     1941the limits of numerical precision.
     1942
     1943Next, corrections to $X$, and $Y$ may be obtained from the IERS as part of
     1944Bulletin A, or B. It is recommended to use the values published daily in
     1945http://maia.usno.navy.mil/ser7/finals2000A.daily, which has the format
     1946described by http://maia.usno.navy.mil/ser7/readme.finals2000A. The
     1947quantities of interest are labeled dX and dY. Note that UT1$-$UTC and the
     1948polar motion values are obtained from this same table.
     1949
     1950By convention, nutation terms with periods of less
     1951than two days
     1952are accounted for by the corresponding polar motion. So it is sufficient to
     1953interpolate the corrections tabulated daily by the IERS, and take the result as
     1954instantaneous values.
     1955
     1956The final step is to use $X$, $Y$, and $s$ to calculate the rotation
     1957matrix from the CIP/CEO system to the GCRS using IERS32 equation (10),
     1958reproduced below:
     1959
     1960\begin{equation}
     1961\begin{pmatrix}1-aX^2& -aXY& X\cr -aXY& 1-aY^2& Y\cr -X& -Y&
     19621-a(X^2+Y^2)\cr
     1963\end{pmatrix} \cdot R_3(s),
     1964\end{equation}
     1965where $R_3$ denotes a rotation about the Z axis,
     1966$a = 1/(1+\sqrt{1 - X^2 + Y^2})$,
     1967and $X$ and $Y$ are expressed in radians.
     1968A FORTRAN reference implementation for this calculation is given
     1969by the IERS \footnote{http://maia.usno.navy.mil/conv2000/chapter5/BPN2000.f}.
     1970
     1971Note that above we gave the expression for the transform toward celestial
     1972coordinates (upward in figure X), in order to match the IERS reference code.
     1973The inverse transform may be found by inverting the resulting rotation.
     1974
     1975\paragraph{Rotation of the Earth}
     1976
     1977The transform from the CIP/CEO to CIP/TEO coordinate systems is a
     1978rotation about the CIP (i.e. the Z axis) by an angle known as the
     1979``Earth Rotation Angle''.
     1980By definition the Earth Rotation Angle is given by
     1981equation (13) of IERS32, reproduced below:
     1982\begin{equation}
     1983\theta(T_u)=2\pi(0.7790572732640 + 1.00273781191135448T_u),
     1984\end{equation}
     1985where $T_u$ is the Julian UT1 date minus 2451545.0 .
     1986
     1987\paragraph{Polar Motion}
     1988
     1989The motion of the CIP in the ITRS is known as ``polar motion''. Similarly to
     1990precession/nutation, the instantaneous position of the CIP in the
     1991ITRS is specified by the quantites $x_p$, and $y_p$, and a third quantity,
     1992$s'$, gives the position of the TEO with respect to the ITRS.
     1993The values of $x_p$ and $y_p$ are published daily by the IERS in
     1994http://maia.usno.navy.mil/ser7/finals2000A.daily, which has the format
     1995described by http://maia.usno.navy.mil/ser7/readme.finals2000A.
     1996The UT1$-$UTC, and the precession/nutation corrections (discussed elsewhere
     1997in this document) come from this same source.
     1998
     1999The polar motion coordinates should be interpolated using a third order
     2000polynomial, as described in
     2001IERS Gazette \#13 \footnote{http://maia.usno.navy.mil/iers-gaz13},
     2002which gives a
     2003FORTRAN reference implementation of the correct procedure.
     2004
     2005\tbd{reference to interpolation in this doc?}
     2006
     2007The values published by the IERS are smoothed to remove noise and
     2008variations on the timescale of a day or less. There are two sources of
     2009short timescale variations - tidal effects on the order of 0.1 milliarcseconds,
     2010and short period nutation terms on the order of 15 microarcseconds.
     2011Both of these effects may be modeled and added to the interpolated values
     2012for higher accuracy.
     2013
     2014The tidal effects should be included using the FORTRAN reference implementation
     2015of the Ray tidal model given in IERS Gazette \#13. This code should be
     2016mimiced to machine accuracy by psLib.
     2017
     2018By definition of the CIP, nutation terms with periods less than 2 days are
     2019not included in the IAU 2000A precession/nutation model.
     2020So these motions
     2021must be compensated for by their equivalent polar motions. These may
     2022be calculated using a form similar to that of the precession/nutation $X$,
     2023and $Y$. The constants to use are given in Table 5.1 of IERS32.
     2024Note that only the terms with periods less than 2 days should be used.
     2025
     2026The quantity $s'$ may be approximated with microarcsecond accuracy over this
     2027century by $s' = -4.7 \times 10^{-5} t$ in arcseconds. There is no need
     2028to apply short timescale corrections to $s'$.
     2029
     2030The transform from the ITRS to the CIP/TEO frame can be constructed by
     2031first rotating about the X axis by $y_p$, then rotating about the X axis by
     2032$x_p$, and finally rotating about the Z axis by $s'$.
     2033The IERS reference implementation for this is given in the subroutine
     2034POM2000 \footnote{http://maia.usno.navy.mil/conv2000/chapter5/POM2000.f}.
     2035Note that we describe the transform toward celestial coordinates (upward in
     2036figure X), in order to match the reference implementation.
     2037
     2038\subsubsection{ITRS - Alt/Az}
     2039
     2040\paragraph{Orientation of the Observer}
     2041
     2042An observer's astronomical longitude and latitude give the orientation of
     2043the local vertical with respect to the ITRS. Note that these coordinates
     2044can be approximated by the geographic longitude and latitude of the observatory,
     2045but their exact values must be calibrated from observation of stars
     2046with known coordinates in the ICRS.
     2047
     2048The transform from the ITRS to Az/Alt in the absence of atmospheric refraction
     2049is first a rotation about the Z axis by the observer's astronomical longitude,
     2050and then a rotation about the Y axis of 90 degrees minus the observer's
     2051astronomical latitude, followed by a rotation about the Z axis of 180 degrees
     2052so that North is zero azimuth.
     2053
     2054\paragraph{Atmospheric Refraction}
     2055
     2056\tbd{add in summary of Ken's paper}
     2057
     2058\subsection{Projections}
     2059
     2060We implement three types of projections: {\em zenithal}, {\em
     2061cylindrical} and {\em pseudocylindrical}, each requiring slightly
     2062different handling.  Our representations are based on the treatment of
     2063projections presented by
     2064\href{http://www.cv.nrao.edu/fits/documents/wcs/wcs.all.ps}{Greisen \&
     2065Calabretta (1995, ADASS, 4, 233)}.  In all of these projections, we
     2066are converting from a spherical coordinate $\alpha,\delta$ to a linear
     2067(2-D) coordinate $x_p,y_p$.  The projection is defined by the
     2068projection type, the projection center ($\alpha_p, \delta_p$) and the
     2069the plate scales in the $x_p$ and $y_p$ directions ($\rho_x,\rho_y$).
     2070
     2071In the structure, \code{psProjection}, the projection type is defined
     2072by the element \code{type}, the projection center $\alpha_p,\delta_p$
     2073is defined by the elements \code{R,D}, and the plate scales,
     2074$\rho_x,\rho_y$, are defined by the elements \code{Xs,Ys}.  The plate
     2075scales are applied independently to the $x$ and $y$ coordinates to
     2076convert them to the corresponding linear units (ie, pixels):
     2077%
     2078\begin{eqnarray}
     2079x_p & = & \rho_x x \\
     2080y_p & = & \rho_y y \\
     2081\end{eqnarray}
     2082%
     2083In the discussions below, we ignore this last step (or first step,
     2084depending on the direction of the conversion).
     2085
     2086\subsubsection{Zenithal Projections}
     2087
     2088The {\em zenithal} projections are defined relative to a set of
     2089spherical coordinates with pole at the center of the projection
     2090($\alpha_p, \delta_p$), and which thus represents a coordinate system
     2091rotated relative to the coordinate system of $\alpha, \delta$.  In
     2092this spherical coordinate system, the coordinate of longitude is
     2093labeled $\phi$, and has domain of $-\pi < \phi \le \pi$, while the
     2094latitude, measured from the pole, is labeled $\theta$ and has domain
     2095$0 \le \theta \le \pi$.  The coordinate frame of $\phi,\theta$ is
     2096defined so that $\phi_p$, the longitude of the target system pole, is
     20970.0.
     2098
     2099For an arbitrary projection center, it is necessary to convert the
     2100spherical coordinates to be projected ($\alpha,\delta$) to the
     2101projection spherical coordinate system coordinates ($\phi, \theta$).
     2102In practice, we construct the following useful trigonometric
     2103relationships between $\phi$ and $\theta$ which may be employed in the
     2104equations of $x,y$ below:
     2105%
     2106\begin{eqnarray}
     2107\sin \theta           & = & \sin \delta \sin \delta_p + \cos \delta \cos \delta_p \cos (\alpha - \alpha_p) \\
     2108\cos \theta \cos \phi & = & \sin \delta \cos \delta_p - \cos \delta \sin \delta_p \cos (\alpha - \alpha_p) \\
     2109\cos \theta \sin \phi & = & - \cos \delta \sin (\alpha - \alpha_p)
     2110\end{eqnarray}
     2111%
     2112For the inverse transformations, the equivalent relationships are:
     2113%
     2114\begin{eqnarray}
     2115\sin \delta                          & = & \sin \theta \sin \delta_p + \cos \theta \cos \delta_p \cos \phi \\
     2116\cos \delta \cos (\alpha - \alpha_p) & = & \sin \theta \cos \delta_p - \cos \theta \sin \delta_p \cos \phi \\
     2117\cos \delta \sin (\alpha - \alpha_p) & = & - \cos \theta \sin \phi
     2118\end{eqnarray}
     2119%
     2120For zenithal projections, the linear coordinates are related to
     2121$\phi,\theta$ by:
     2122%
     2123\begin{eqnarray}
     2124x & = & R_\theta \sin \phi \\
     2125y & = & -R_\theta \cos \phi
     2126\end{eqnarray}
     2127%
     2128and the inverse:
     2129%
     2130\begin{eqnarray}
     2131R_\theta & = & \sqrt{x^2 + y^2} \\
     2132\phi     & = & {\rm atan} (-y,x)
     2133\end{eqnarray}
     2134%
     2135The coordinates $x,y$ above are defined to be in angular units (ie,
     2136radians). 
     2137
     2138From these relationships, we can calculate $\alpha, \delta$ as:
     2139%
     2140\begin{eqnarray}
     2141\alpha - \alpha_p & = & \arctan (\sin \alpha, \cos \alpha) \\
     2142\delta            & = & \arcsin (\sin \delta) \\
     2143\end{eqnarray}
     2144%
     2145Note that if $(x,y) = (0,0)$, then $\alpha = \alpha_p, \delta = \delta_p$.
     2146
     2147\paragraph{Gnomonic}
     2148
     2149The Gnomonic projection (``TAN'') is a zenithal projection with
     2150$R_\theta = \cot \theta$.  The resulting relationships for $(x,y)$ and
     2151for $\sin \theta, \cos \theta$ are:
     2152
     2153\begin{eqnarray}
     2154x           & = & \frac{\cos \theta \sin \phi}{\sin \theta} \\
     2155y           & = & \frac{-\cos \theta \cos \phi}{\sin \theta} \\
     2156\sin \theta & = & \zeta / \sqrt{1 + \zeta^2} \\
     2157\cos \theta & = & 1 / \sqrt{1 + \zeta^2} \\
     2158\end{eqnarray}
     2159
     2160where $\zeta = 1 / R_\theta$.
     2161
     2162\paragraph{Orthographic}
     2163
     2164The Orthographic projection (``SIN'') is a zenithal projection with
     2165$R_\theta = \cos \theta$.  The resulting relationships for $(x,y)$ and
     2166for $\sin \theta, \cos \theta$ are:
     2167
     2168\begin{eqnarray}
     2169x           & = & \cos \theta \sin \phi \\
     2170y           & = & -\cos \theta \cos \phi \\
     2171\sin \theta & = & \sqrt{1 - R_\theta^2} \\
     2172\cos \theta & = & R_\theta \\
     2173\end{eqnarray}
     2174
     2175\subsubsection{Cylindrical and Pseudocylindrical Projections}
     2176
     2177The {\em cylindrical} and {\em pseudocylindrical} projections are
     2178defined relative to a set of cylindrical coordinates whose pole is
     2179coincident with the pole of the spherical coordinates.  These
     2180projections are particularly used for full-sky representations, and
     2181are only defined for projection centers with $\delta_p = 0$.  In this
     2182spherical coordinate system, the coordinate of longitude is labeled
     2183$\phi$, and has domain of $-\pi < \phi \le \pi$, while the latitude,
     2184measured from the pole, is labeled $\theta$ and has domain $0 \le
     2185\theta \le \pi$.  The projection center longitude, $\alpha_p$
     2186corresponds to $\phi = 0$, thus the value of $\phi$ is determined as
     2187$\alpha - \alpha_p$ for all such projections.
     2188
     2189\paragraph{Cartesian}
     2190
     2191The Cartesian projection (``CAR'') is a very simple cylindrical
     2192projection with the following relationships between $x,y$ and
     2193$\phi,\theta$:
     2194
     2195\begin{eqnarray}
     2196x & = & \phi \\
     2197y & = & \theta
     2198\end{eqnarray}
     2199
     2200\paragraph{Mercator}
     2201
     2202The Mercator projection (``MER'') is a cylindrical projection.
     2203
     2204\begin{eqnarray}
     2205x & = & \phi \\
     2206y & = & \ln \left( \tan (\pi/4 + \theta/2) \right) \\
     2207{\rm and}\hspace{1cm} \theta & = & 2 \arctan \left( e^y \right) - \pi/2
     2208\end{eqnarray}
     2209
     2210\paragraph{Hammer-Aitoff}
     2211
     2212The Hammer-Aitoff projection(``AIT'') is a pseudocylindrical projection, and is defined:
     2213
     2214\begin{eqnarray}
     2215x & = & 2 \zeta \cos \theta \sin \frac{\phi}{2} \\
     2216y & = & \zeta \sin \theta \\
     2217{\rm where}\hspace{1cm} \zeta^{-1} & \equiv & \sqrt{\frac{1}{2}\left(1 + \cos \theta \cos \frac{\phi}{2} \right)}
     2218\end{eqnarray}
     2219
     2220And in reverse:
     2221
     2222\begin{eqnarray}
     2223\phi & = & 2 {\rm \arctan} (2z^2 - 1, x z) \\
     2224\theta & = & \arcsin (yz) \\
     2225{\rm where}\hspace{1cm} z & \equiv & \sqrt{1 - (x/2)^2 - y^2}
     2226\end{eqnarray}
     2227
     2228\paragraph{Parabolic}
     2229
     2230The Parabolic projection (``PAR'') is a pseudocylindrical projection, and is defined:
     2231
     2232\begin{eqnarray}
     2233x & = & \phi \left( 2 \cos \frac{2 \theta}{3} - 1 \right) \\
     2234y & = & \pi \sin \frac{\theta}{3} \\
     2235\end{eqnarray}
     2236
     2237And in reverse:
     2238
     2239\begin{eqnarray}
     2240\theta & = & 3 \sin^{-1} \rho \\
     2241\phi   & = & \frac{x}{1 - 4\rho^2} \\
     2242{\rm where}\hspace{1cm} \rho & \equiv & y/\pi \\
     2243\end{eqnarray}
     2244
     2245\subsection{Offset}
     2246
     2247Coordinate offsets can be either spherical offsets or linear offsets.
     2248
     2249A spherical offset is performed by adding the components of the
     2250offset, after unit conversion, to the given position.  The resulting
     2251coordinates must be wrapped to within the allowed range ($-\pi$ to
     2252$\pi$, 0 to $2\pi$).
     2253
     2254A linear offset is defined to be a linear offset in a tangent
     2255projection centered on the starting coordinate with $y$ axis aligned
     2256with the local direction or increasing Declination.  This projection
     2257is undefined only for the coordinates exactly at the north and south
     2258poles, in which case the orientation is defined to have the $y$ axis
     2259parallel to the line of RA = 0.0.  The scale of the projection is 1.0
     2260(ie, 1 'pixel' is 1 radian) and the given offsets must the scaled
     2261based on the given offset units. 
     2262
     2263Pseudo-code to implement the above for an offset:
     2264
     2265\begin{verbatim}
     2266psSphere *psSphereSetOffset (psSphere pos, psSphere offset) {
     2267
     2268  psPlane lin;
     2269  psSphere new;
     2270  psProjection proj;
     2271
     2272  proj.R = pos->r;
     2273  proj.D = pos->d;
     2274  proj.X = 0;
     2275  proj.Y = 0;
     2276  proj.type = PS_PROJ_TAN;
     2277
     2278  lin.x = offset.r;
     2279  lin.y = offset.d;
     2280
     2281  new = psDeproject (&lin, &proj);
     2282  return (new);
     2283}
     2284\end{verbatim}
     2285
     2286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     2287
     2288\subsection{The One-to-Many Problem with Mosaic Cameras}
    18012289
    18022290The \PS{} focal plane consists of several chips, so we will often want
     
    18202308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    18212309
    1822 \subsubsection{General Astronomy Functions}
     2310\subsection{General Astronomy Functions}
    18232311
    18242312\tbd{we will provide a new airmass function}
     
    18542342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    18552343
    1856 \subsubsection{Positions of Major Solar System Objects}
     2344\subsection{Positions of Major Solar System Objects}
    18572345
    18582346\tbd{ephemerides code to replace this}
     
    18692357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    18702358
    1871 \subsection{Missing and Todo}
    1872 
    1873 \tbd{define sunrise, sunset, sun position}
    1874 
    1875 \tbd{define moonrise, moonset, moon position, moon phase}
    1876 
    1877 \tbd{define planet functions}
    1878 
    1879 \tbd{clean up FITS I/O issues}
    1880 
    1881 \tbd{define Brent's method \& minimization bracketing}
    1882 
     2359\pagebreak
    18832360\section{Pan-STARRS Modules}
    18842361
     
    22252702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    22262703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     2704
     2705\section{Missing and Todo}
     2706
     2707\tbd{define sunrise, sunset, sun position}
     2708
     2709\tbd{define moonrise, moonset, moon position, moon phase}
     2710
     2711\tbd{define planet functions}
     2712
     2713\tbd{clean up FITS I/O issues}
     2714
     2715\tbd{define Brent's method \& minimization bracketing}
     2716
    22272717\appendix
    22282718\section{Change Log}
     
    22302720
    22312721\end{document}
    2232 
    2233 
    2234 \section{Modules}
    2235 
    2236 \subsection{Image Processing Modules}
    2237 \subsubsection{debias}
    2238 \subsubsection{mask}
    2239 \subsubsection{trim}
    2240 \subsubsection{flatten}
    2241 \subsubsection{sky/fringe subtract}
    2242 \subsubsection{warp}
    2243 \subsubsection{stack}
    2244 \subsubsection{difference}
    2245 \subsubsection{kernel convolution}
    2246 \subsubsection{special stack}
    2247 
    2248 \subsection{Object Detection Modules}
    2249 \subsubsection{find peaks}
    2250 \subsubsection{background }
    2251 \subsubsection{aperture photometry}
    2252 \subsubsection{get shape}
    2253 
    2254 \subsection{Miscellaneous Modules}
    2255 
    2256 \section{Analysis Stages}
    2257 \subsection{Phase 1}
    2258 \subsection{Phase 2}
    2259 \subsection{Phase 3}
    2260 \subsection{Phase 4}
    2261 \subsection{Cal 1}
    2262 \subsection{Cal 2}
    2263 \subsection{Cal 3}
    2264 \subsection{Astrom Ref}
    2265 \subsection{Photom Ref}
    2266 
    2267 \section{Architectual Components}
    2268 
  • trunk/doc/pslib/psLibSDRS.tex

    r3537 r3564  
    1 %%% $Id: psLibSDRS.tex,v 1.191 2005-03-29 03:42:21 price Exp $
     1%%% $Id: psLibSDRS.tex,v 1.192 2005-03-30 21:14:48 eugene Exp $
    22\documentclass[panstarrs,spec]{panstarrs}
    33
     
    1111\project{Pan-STARRS Image Processing Pipeline}
    1212\organization{Institute for Astronomy}
    13 \version{12}
     13\version{13}
    1414\docnumber{PSDC-430-007}
    1515
     16% \setcounter{tocdepth}{5} % lowest level to be included in toc
    1617\setlength{\topsep}{-2pt}
    1718 
     
    137138\href{heasarc.gsfc.nasa.gov/docs/software/fitsio}{\tt heasarc.gsfc.nasa.gov/docs/software/fitsio}
    138139
    139 \item \tbd{SLALIB support is likely to be dropped} Many of the
    140 astronomy routines will wrap the StarLink Positional Astronomy
    141 libraries (SLALib):
     140\item the StarLink Positional Astronomy libraries (SLALib) are a
     141  useful reference:
    142142
    143143\href{star-www.rl.ac.uk/star/docs/sun67.htx/sun67.html}{\tt
     
    183183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    184184
     185\pagebreak
    185186\section{System Utilities}
    186187
     
    11931194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    11941195
     1196\pagebreak
    11951197\section{Basic Data Types and Collections}
    11961198
     
    18941896%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    18951897
     1898\pagebreak
    18961899\section{Data manipulation}
    18971900
     
    30283031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    30293032
     3033\subsection{Image Pixel Lists}
     3034
     3035Usually an image mask is the best way to carry information about what
     3036pixels mean what.  However, in the case where the number of pixels in
     3037which we are interested is limited, it is more efficient to simply
     3038carry a list of pixels.  An example of this is in the image
     3039combination code, where we want to perform an operation on a
     3040relatively small fraction of pixels, and it is inefficient to go
     3041through an entire mask image checking each pixel.
     3042
     3043\begin{verbatim}
     3044typedef struct {
     3045    psVector *x;                        // x coordinate
     3046    psVector *y;                        // y coordinate
     3047} psPixels;
     3048\end{verbatim}
     3049
     3050Of course, the size of each of the vectors should match.  In the event
     3051that they do not match, any function which detects the problem shall
     3052generate a warning and use the size of the shorter of the vectors as
     3053the size.  The order in which the pixels are kept is not considered
     3054important.
     3055
     3056\begin{verbatim}
     3057psImage *psPixelsToMask(psImage *out, const psPixels *pixels, const psRegion *region, unsigned int maskVal);
     3058psPixels *psMaskToPixels(psPixels *out, const psImage *mask, unsigned int maskVal);
     3059\end{verbatim}
     3060
     3061\code{psPixelsToMask} shall return an image of type U8 with the
     3062\code{pixels} lying within the specified \code{region} set to the
     3063\code{maskVal}.  The \code{out} image shall be modified if supplied,
     3064or allocated and returned if \code{NULL}.  The size of the output
     3065image shall be \code{region->x1 - region->x0} by \code{region->y1 -
     3066region->y0}, with \code{out->x0 = region->x0} and \code{out->y0 =
     3067region->y0}.  In the event that either of \code{pixels} or
     3068\code{region} are \code{NULL}, the function shall generate an error
     3069and return \code{NULL}.
     3070
     3071\code{psMaskToPixels} shall return a \code{psPixels} consisting of the
     3072coordinates in the \code{mask} that match the \code{maskVal}.  The
     3073\code{out} pixel list shall be modified if supplied, or allocated and
     3074returned if \code{NULL}.  In hte event that \code{mask} is
     3075\code{NULL}, the function shall generate an error and return
     3076\code{NULL}.
     3077
     3078\begin{verbatim}
     3079psPixels *psPixelsConcatenate(psPixels *out, const psPixels *pixels);
     3080\end{verbatim}
     3081
     3082\code{psPixelsConcatenate} shall concatenate \code{pixels} onto
     3083\code{out}.  In the event that \code{out} is \code{NULL}, a new
     3084\code{psPixels} shall be allocated, and the contents of \code{pixels}
     3085simply copied in.  If \code{pixels} is \code{NULL}, the function shall
     3086generate an error and return \code{NULL}.  The function shall take
     3087care to ensure that there are no duplicate pixels in \code{out} (since
     3088the order in which the pixels are stored is not important, the values
     3089may be sorted, allowing the use of a faster algorithm than a linear
     3090scan).
     3091
     3092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     3093
     3094\subsection{Image Regions}
     3095
     3096In many places, we need to refer to a rectangular area.  We define a
     3097structure to represent a rectangle:
     3098\begin{verbatim}
     3099typedef struct {
     3100  float x0;
     3101  float x1;
     3102  float y0;
     3103  float y1;
     3104} psRegion;
     3105psRegion *psRegionAlloc (float x0, float x1, float y0, float y1);
     3106\end{verbatim}
     3107
     3108\begin{verbatim}
     3109psRegion *psRegionFromString (char *region);
     3110\end{verbatim}
     3111This function converts the IRAF description of a region in the form
     3112\code{[x0:x1,y0:y1]}, used for header entries such as \code{BIASSEC},
     3113into the corresponding \code{psRegion} structure.
     3114
    30303115\subsection{Vector and Image Arithmetic}
    30313116\label{sec:arithmetic}
     
    34433528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    34443529
     3530\pagebreak
     3531\section{Rich Data Structures and I/O}
     3532
     3533\subsection{Metadata}
     3534\label{sec:metadata}
     3535
     3536\subsubsection{Conceptual Overview}
     3537
     3538Within PSLib, we provide a data structure to carry metadata and
     3539mechanisms to manipulate the metadata.  Metadata is a general concept
     3540that requires some discussion.  In any data analysis task, the
     3541ensemble of all possible data may be divided into two or three
     3542classes: there is the specific data of interest, there is data which
     3543is related or critical but not the primary data of interest, and there
     3544is all of the other data which may or may not be interesting.  For
     3545example, consider a simple 2D image obtained of a galaxy from a CCD
     3546camera on a telescope.  If you want to study the galaxy, the specific
     3547data of interest is the collection of pixels.  There are a variety of
     3548other pieces of data which are closely related and crucial to
     3549understanding the data in those pixels, such as the dimensions of the
     3550image, the coordinate system, the time of the image, the exposure
     3551time, and so forth.  Other data may be known which may be less
     3552critical to understanding the image, but which may be interesting or
     3553desired at a later date.  For example, the observer who took the
     3554image, the filter manufacturer, the humidity at the telescope, etc.
     3555
     3556Formally, all of the related data which describe the principal data of
     3557interest are metadata.  Note that which piece is the metadata and
     3558which is the data may depend on the context.  If you are examining the
     3559pixels in an image, the coordinate and flux of an object may be part
     3560of the metadata.  However, if you are analyzing a collection of
     3561objects extracted from an image, you may consider then pixel data
     3562simply part of the metadata associated with the list of objects. 
     3563
     3564There are various ways to handle metadata vs data within a programming
     3565environment.  In C, it is convenient to use structures to group
     3566associated data together.  One possibility is to define the metadata
     3567as part of the associated data structure.  For example, the image data
     3568structure would have elements for all possible associated measurement.
     3569This approach is both cumbersome (because of the large number metadata
     3570types), impractical (because the full range of necessary metadata is
     3571difficult to know in advance) and inflexible (because any change in
     3572the collection of metadata requires addition of new structure elements
     3573and recompilation). 
     3574
     3575An alternative is to place the metadata in a generic container and use
     3576lookup mechanisms to extract the appropriate metadata when needed.  An
     3577example of this is would be a text-based FITS header for an image read
     3578into a flat text buffer.  In this implementation, metadata lookup
     3579functions could return the current value of, for example, NAXIS1 (the
     3580number of columns of the image) by scanning through the header buffer.
     3581This method has the benefits of flexibility and simplicity of
     3582programming interface, but it has the disadvantage that all metadata
     3583is accessed though this lookup mechanism.  This may make the code less
     3584readable and it may slow down the access. 
     3585
     3586PSLib implements an intermediate solution to this problem.  We specify
     3587a flexible, generic metadata container and access methods.  Data types
     3588which require association with a general collection of metadata should
     3589include an entry of this metadata type.  However, a subset of metadata
     3590concepts which are basic and frequently required may be placed in the
     3591coded structure elements.  This approach allows the code to refer to
     3592the basic metadata concepts as part of the data structure (ie,
     3593\code{image.nx}), but also allows us to provide access to any
     3594arbitrary metadata which may be generated.  As a practical matter, the
     3595choice of which entries are only in the metadata and which are part of
     3596the explicit structure elements is rather subjective.  Any data
     3597elements which are frequently used should be put in the structure;
     3598those which are only infrequently needed should be left in the generic
     3599metadata.
     3600
     3601There are some points of caution which must be noted.  Any
     3602manipulation of the data should be reflected in the metadata where
     3603appropriate.  This is always an issue of concern.  For example,
     3604consider an image of dimensions \code{nx, ny}.  If a function extracts
     3605a subraster, it must change the values of \code{nx, ny} to match the
     3606new dimensions.  What should it do to the corresponding metadata?
     3607Clearly, it should change the corresponding value which defines
     3608\code{nX, nY}.  However, it is not quite so simple: there may be other
     3609metadata values which depend on those values.  These must also be
     3610changed appropriately.  What if the metadata element points to a
     3611copy of the metadata which may be shared by other representations of
     3612the image?  These must be treated differently because the change would
     3613invalidate those other references.  Care must be taken, therefore,
     3614when writing functions which operate on the data to consider all of
     3615the relevant metadata entries which must also be updated.
     3616
     3617A related issue is the definition of metadata names.  Entries in a
     3618structure have the advantage of being hardwired: every instance of
     3619that structure will have the same name for the same entry.  This is
     3620not necessarily the case with a more flexible metadata container.  The
     3621image exposure time is a notorious example in astronomy.  Different
     3622observatories use different header keywords (ie, metadata names) for
     3623the same concept of the exposure time (\code{EXPTIME},
     3624\code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc).  Any system
     3625which operates on these metadata needs to address the issue of
     3626identifying these names.  This issue seems like an argument for
     3627hardwiring metadata in the structure, but in fact it does not present
     3628such a strong case.  If the metadata are hardwired, some function will
     3629still have to know how to interpret the various names to populate the
     3630structure.  The concept can still be localized with generic metadata
     3631containers by including abstract metadata names within the code which
     3632are tied to the various implementations-specific metadata names.
     3633
     3634\subsubsection{Metadata Representation}
     3635
     3636\begin{figure}
     3637\psfig{file=Metadata,width=6.5in}
     3638\caption{Metadata Structures\label{fig:metadata}}
     3639\end{figure}
     3640
     3641This section addresses the question of how \PS{} metadata should be
     3642represented in memory, not how it should be represented on disk.
     3643
     3644We define an item of metadata with the following structure:
     3645\filbreak
     3646\begin{verbatim}
     3647typedef struct {
     3648    int id;                             ///< unique ID for this item
     3649    char *name;                         ///< Name of item
     3650    psMetadataType type;                ///< type of this item
     3651    psElemType ptype;                   ///< primitive data type
     3652    const union {
     3653        psS32 S32;                      ///< integer data
     3654        psF32 F32;                      ///< floating-point data
     3655        psF64 F64;                      ///< double-precision data
     3656        void *V;                        ///< other type
     3657        psList *list;                   ///< psList entry
     3658        psMetadata *md;                 ///< psMetadata entry
     3659    } data;                             ///< value of metadata
     3660    char *comment;                      ///< optional comment ("", not NULL)
     3661} psMetadataItem;
     3662\end{verbatim}
     3663
     3664The \code{id} is a unique identifier for this item of metadata;
     3665experience shows that such tags are useful.  The entry \code{name}
     3666specifies the name of the metadata item.  The value of the metadata is
     3667given by the union \code{data}, and may be of type \code{psS32},
     3668\code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at
     3669by the \code{void} pointer \code{V}.  A character string comment
     3670associated with this metadata item may be stored in the element
     3671\code{comment}. The \code{type} entry specifies how to interpret the
     3672type of the data being represented, given by the enumerated type
     3673\code{psMetadataType}:
     3674%
     3675\filbreak
     3676\begin{verbatim}
     3677typedef enum {                          ///< type of item.data is:
     3678    PS_META_PRIMITIVE,                  ///< primitive type: use item.ptype
     3679    PS_META_LIST,                       ///< psList; use item.data.list (used for non-unique data)
     3680    PS_META_META,                       ///< psMetadata: use item.data.list
     3681    PS_META_STR,                        ///< string (item.data.V)
     3682    PS_META_MATH,                       ///< psScalar, psVector, psImage (item.data.V)
     3683    PS_META_JPEG,                       ///< JPEG (item.data)
     3684    PS_META_PNG,                        ///< PNG (item.data)
     3685    PS_META_ASTROM,                     ///< astrometric coefficients (item.data)
     3686    PS_META_UNKNOWN,                    ///< other (item.data)
     3687    PS_META_NTYPE                       ///< Number of types; must be last
     3688} psMetadataType;
     3689\end{verbatim}
     3690If the data is a PSLib primitive data value, the primitive data type
     3691is given by the value of \code{ptype}.
     3692
     3693A collection of metadata is represented by the \code{psMetadata} structure:
     3694\begin{verbatim}
     3695typedef struct {
     3696    psList *list;                       ///< list of psMetadataItem
     3697    psHash *table;                      ///< hash table of the same metadata
     3698} psMetadata;
     3699\end{verbatim}
     3700The type \code{psMetadata} is a container class for metadata. Note
     3701that there are in fact \emph{two} representations of the metadata
     3702(each \code{psMetadataItem} appears on both).  The first
     3703representation employs a doubly-linked list that allows the order of
     3704the metadata to be preserved (e.g., if FITS headers are read in a
     3705particular order, they should be written in the same order).  The
     3706second representation employs a hash table which allows fast look-up
     3707given a specific metadata keyword.
     3708
     3709Certain metadata names (such as the FITS keywords \code{COMMENT} and
     3710\code{HISTORY} in a FITS header) may be repeated with different
     3711values.  In such a case, the \code{psMetadata.list} structure contains
     3712the entries in their original sequence with duplicate keys.  The
     3713\code{psMetadata.hash} entries, which are required to have unique
     3714keys, would have a single entry with the keyword of the repeated key,
     3715with the value of \code{psMetadataType} set to \code{PS_META_LIST},
     3716and the \code{psMetadataItem.data} element pointing to a \code{psList}
     3717containing the actual entries.  If \code{psMetadataItemAlloc} is
     3718called with the type set to \code{PS_META_LIST}, such a repeated key
     3719is created.  If the data value passed to \code{psMetadataItemAlloc}
     3720(the quantity in ellipsis) is \code{NULL}, then an empty
     3721\code{psMetadataItem} with the given keyword is created to hold future
     3722entries of that keyword.
     3723
     3724The \code{psMetadataAdd} routine is required to check that all
     3725metadata names are unique unless the type is already qualified as
     3726\code{PS_META_LIST}; in this case the data are added to the
     3727corresponding \code{psMetadataItem.data} list.
     3728
     3729\subsubsection{Metadata APIs}
     3730
     3731The allocator for \code{psMetadataItem} returns a full
     3732\code{psMetadataItem} ready for insertion into the \code{psMetadata}.
     3733The \code{name} entry specifies the name to use for this metadata
     3734item, and may include \code{sprintf}-type formating codes.  The
     3735\code{comment} entry is a fixed string which is used for the comment
     3736associated with this metadata item.  The metadata data and the
     3737arguments to the \code{name} formatting codes are passed, in that
     3738order (metadata pointer first), to \code{psMetadataItemAlloc} as
     3739arguments following the comment string.  The data must be a pointer
     3740for any data types which are stored in the element \code{data.void},
     3741while other data types are passed as numeric values.  The argument
     3742list must be interpreted appropriately by the \code{va_list} operators
     3743in the function.
     3744\begin{verbatim}
     3745psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...);
     3746psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list);
     3747\end{verbatim}
     3748
     3749The constructor for the collection of metadata, \code{psMetadata},
     3750simply returns an empty metadata container (employing the constructors
     3751for the doubly-linked list and hash table).  The destructor needs to
     3752free each of the \code{psMetadataItem}s using \code{psMetadataItemFree}.
     3753\begin{verbatim}
     3754psMetadata *psMetadataAlloc(void);
     3755\end{verbatim}
     3756
     3757Items may be added to the metadata in one of two ways --- firstly, an
     3758item may be added by appending a \code{psMetadataItem} which has
     3759already been created; and secondly by directly providing the data to
     3760be appended.  In both cases, the return value defines the success
     3761(\code{true}) or failure of the operation.  The second function,
     3762\code{psMetadataAdd} takes a pointer or value which is interpreted by
     3763the function using variadic argument interpretation.  The third
     3764version is the \code{va_list} version of the second function.  All
     3765three functions take a parameter, \code{location}, which specifies
     3766where in the list to place the element, following the conventions for
     3767the \code{psList}.  The entry \code{mode} for \code{psMetadataAddItem}
     3768is a bit mask constructed by OR-ing the allowed option flags (eg,
     3769\code{PS_META_REPLACE}) which specifies minor variations on the
     3770behavior.  The \code{format} entry, which specifies both the metadata
     3771type and the optional flags, is constructed by bit-wise OR-ing the
     3772appropriate \code{psMetadataType} and allowed option option flags.
     3773Care should be taken not to leak memory when appending an item for
     3774which the key already exists in the metadata (and is not
     3775\code{PS_META_LIST}).
     3776%
     3777\begin{verbatim}
     3778bool psMetadataAddItem(psMetadata *md, psMetadataItem *item, int location, int mode);
     3779bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...);
     3780bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment,
     3781                    va_list list);
     3782\end{verbatim}
     3783
     3784The functions above take option flags which modify the behavior when
     3785metadata items are added to the metadata list.  These flags must be
     3786bit-exclusive of those used above for the \code{psMetadataTypes}.  The
     3787flags have the following meanings:
     3788
     3789\code{PS_META_DEFAULT}: This is the zero bit mask, to allow the
     3790default behavior for \code{psMetadataAddItem} above.  If this is OR-ed
     3791with a \code{psMetadataType}, the result is as if no OR-ing took
     3792place.
     3793
     3794\code{PS_META_REPLACE}: If the given metadata item exists in the
     3795metadata list, and is not of type \code{PS_META_LIST} or
     3796\code{PS_META_META} (ie, not a container type), then this entry is
     3797allowed to replace the existing entry.  If this mode bit is not set, a
     3798duplicate (non-container-type) entry is an error.
     3799
     3800\begin{verbatim}
     3801typedef enum {                          ///< option flags for psMetadata functions
     3802    PS_META_DEFAULT,                    ///< default behavior (0x0000) for use in mode above
     3803    PS_META_REPLACE,                    ///< allow entry to be replaced
     3804} psMetadataFlags;
     3805\end{verbatim}
     3806
     3807An example of code to use these metadata APIs to generate the
     3808structure seen in Figure~\ref{fig:metadata} is given below.
     3809
     3810\begin{verbatim}
     3811md = psMetadataAlloc();
     3812
     3813psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE",   PS_META_BOOL, "basic fits",            TRUE);
     3814psMetadataAdd(md, PS_LIST_TAIL, "BLANK",    PS_META_S32,  "invalid pixel data",    -32768);
     3815psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR,  "observing date UT", "   2004-6-16");
     3816psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_LIST, "head of comment block", NULL);
     3817psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "DATA");
     3818psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "PARAMS");
     3819psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME",  PS_META_F32,  "exposure time (sec)",   1.05);
     3820psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "FOO");
     3821
     3822cell = psMetadataAlloc();
     3823psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME",  PS_META_STR,  "",                    "CCD00");
     3824psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR,  "",                    "BSEC-00");
     3825psMetadataAdd(cell, PS_LIST_TAIL, "CHIP",     PS_META_STR,  "",                    "CHIP.00");
     3826psMetadataAdd(md,   PS_LIST_TAIL, "CELL.00",  PS_META_META, "",                    cell);
     3827
     3828cell = psMetadataAlloc();
     3829psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME",  PS_META_STR,  "",                    "CCD01");
     3830psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR,  "",                    "BSEC-01");
     3831psMetadataAdd(cell, PS_LIST_TAIL, "CHIP",     PS_META_STR,  "",                    "CHIP.01");
     3832psMetadataAdd(md,   PS_LIST_TAIL, "CELL.01",  PS_META_META, "",                    cell);
     3833\end{verbatim}
     3834
     3835The following code shows how to use the APIs to replace one of these values:
     3836\begin{verbatim}
     3837psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME",  PS_META_F32 | PS_REPLACE,  "new exposure time (sec)",   2.05);
     3838\end{verbatim}
     3839
     3840Items may be removed from the metadata by specifying a key or a
     3841location in the list.  If the value of \code{name} is \code{NULL}, the
     3842value of \code{location} is used.  If the value of \code{name} is not
     3843\code{NULL}, then \code{location} must be set to
     3844\code{PS_LIST_UNKNOWN}.  If the key matches a metadata item, the item
     3845is removed from the metadata and \code{true} is returned; otherwise,
     3846\code{false} is returned.  If the key is not unique, then \emph{all}
     3847items corresponding to the key are removed, and \code{true} is
     3848returned.
     3849%
     3850\begin{verbatim}
     3851bool psMetadataRemove(psMetadata *md, int location, const char *key);
     3852\end{verbatim}
     3853
     3854Items may be found within the metadata by providing a key.  In the
     3855event that the key is non-unique, the first item is returned.
     3856\begin{verbatim}
     3857psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key);
     3858\end{verbatim}
     3859
     3860Several utility functions are provided for simple cases.  These
     3861functions perform the effort of casting the data to the appropriate
     3862type.  The numerical functions shall return 0.0 if their key is not
     3863found.  If the pointer value of \code{status} is not \code{NULL}, it
     3864is set to reflect the success or failure of the lookup.
     3865\begin{verbatim}
     3866void *psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key);
     3867psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key);
     3868psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key);
     3869\end{verbatim}
     3870
     3871Items may be retrieved from the metadata by their entry position.  The
     3872value of which specifies the desired entry in the fashion of
     3873\code{psList}.
     3874\begin{verbatim}
     3875psMetadataItem *psMetadataGet(const psMetadata *md, int location);
     3876\end{verbatim}
     3877
     3878The metadata list component may be iterated over by using a
     3879\code{psListIterator} in a fashion equivalent to the usage for
     3880\code{psList}.  The iterator may be set to a location in the
     3881\code{psMetadata} list, and the user may get the previous or next item
     3882in the list relative to that location.  \code{psMetadataGetNext} has
     3883the ability to match the key using a POSIX regex, e.g., if the user
     3884only wants to iterate through \code{IPP.machines.sky} and doesn't want
     3885to bother with \code{IPP.machines.detector}.  The iterator should
     3886iterate over every item in the metadata list, even those that are
     3887contained in a \code{PS_META_LIST}.  The value \code{iterator}
     3888specifies the iterator to be used.  In setting the iterator, the
     3889position of the iterator is defined by \code{location}, which follows
     3890the conventions of the \code{psList} iterators.
     3891\begin{verbatim}
     3892psListIterator *psMetadataIteratorAlloc(psMetadata *md, int location, bool mutable);
     3893bool psMetadataIteratorSet(psListIterator *iterator, int location);
     3894psMetadataItem *psMetadataGetAndIncrement(psListIterator *iterator, const char *regex);
     3895psMetadataItem *psMetadataGetAndDecrement(psListIterator *iterator, const char *regex);
     3896\end{verbatim}
     3897
     3898Metadata items may be printed to an open file descriptor based on a
     3899provided format.  The format string is an sprintf format statement
     3900with exactly one \% formatting command.  If the metadata item type is
     3901a numeric type, this formatting command must also be numeric, and type
     3902conversion performed to the value to match the format type.  If the
     3903metadata item type is a string, the formatting command must also be
     3904for a string (\%s type of command).  If the metadata type is any other
     3905data type, printing is not allowed.
     3906\begin{verbatim}
     3907bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *md);
     3908\end{verbatim}
     3909
     3910\subsubsection{Configuration files}
     3911\label{sec:configspec}
     3912
     3913It will be necessary for the \PS{} system, in order to load
     3914pre-defined settings, to parse a configuration file into a
     3915\code{psMetadata} structure.  This shall be performed by the
     3916function \code{psMetadataParseConfig}, as described below.
     3917
     3918\begin{verbatim}
     3919psMetadata *psMetadataParseConfig(psMetadata *md, int *nFail, const char *filename, bool overwrite);
     3920\end{verbatim}
     3921
     3922Given a metadata container, \code{md}, and the name of a configuration
     3923file, \code{filename}, \code{psMetadataParseConfig} shall parse the
     3924configuration file, placing the contained key/type/value/comment quads
     3925into the metadata, and returning a pointer to the metadata structure.
     3926The number of lines that failed to parse is returned in \code{nFail}.
     3927Multiple specifications of a key that haven't been declared (see
     3928below) are overwritten if and only if \code{overwrite} is \code{true}.
     3929If the metadata container is \code{NULL}, it shall be allocated. 
     3930
     3931On error, the function shall return \code{NULL}.
     3932
     3933The configuration file shall consist of plain text with
     3934key/type/value/comment quads on separate lines.  Blank lines,
     3935including those consisting solely of whitespace (both spaces and
     3936tabs), shall be ignored, as shall lines that commence with the comment
     3937character (a hash mark, \code{#}), either immediately at the start of
     3938the line, or preceded by whitespace.  The key/type/value/comment quads
     3939shall all lie on a single line, separated by whitespace.
     3940
     3941The key shall be first, possibly preceded on the line by whitespace
     3942which should not form part of the key.
     3943
     3944Next, to assist the casting of the value, shall be a string
     3945identifying the type of the value, which shall correspond to one of
     3946the simple types supported in \code{psMetadata}:
     3947\code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to abbreviate
     3948\code{STRING}.
     3949
     3950\tbd{May, in the future, require more types, including U8,S16,C64,
     3951which will also necessitate updating the definition of psMetadata.}
     3952
     3953The value shall follow the type: strings may consist of multiple
     3954words, and shall have all leading and trailing whitespace removed;
     3955booleans shall simply be either \code{T} or \code{F}.
     3956
     3957Following the value may be an optional comment, preceded by a comment
     3958character (a hash mark, \code{#}), which in the case of a string
     3959value, serves to mark the end of the value, and for other types serves
     3960to identify the comment to the reader.  Only one comment character may
     3961be present on any single line (i.e., neither strings nor comments are
     3962permitted to contain the comment character).  The comment may consist
     3963of multiple words, and shall have leading and trailing whitespace
     3964removed.
     3965
     3966One wrinkle is the specification of vectors.  Keys for which the value
     3967is to be parsed as a vector shall be preceded immediately by a
     3968``vector symbol'', which we choose to be the ``at'' sign, \code{@}.
     3969In this case, the type shall be interpreted as the type for the
     3970vector, which may be any of the signed or unsigned integer or floating
     3971point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not
     3972the complex floating point types; and the value shall consist of
     3973multiple numbers, separated either by a comma or whitespace.  These
     3974values shall populate a \code{psVector} of the appropriate type in the
     3975order in which they appear in the configuration file.
     3976
     3977\tbd{May add complex types, likely to be specified with values such as
     3978  1.23+4.56i in the future.}
     3979
     3980An additional hurdle is the specification of keys that may be
     3981non-unique (such as the \code{COMMENT} keyword in a FITS header).
     3982These keys shall be specified in the configuration file as non-unique
     3983by specifying the key at the start of the line (possibly preceded by
     3984whitespace) and specifying the type as a ``multiple symbol'', which we
     3985choose to be an asterisk, \code{*}.  No other data may be provided on
     3986this line, though a comment, preceeded by the comment marker, is
     3987valid.  A warning shall be produced when a key which has not been
     3988specified to be non-unique is repeated; in this case, the former value
     3989shall be overwritten if \code{overwrite} is \code{true}, otherwise the
     3990line shall be ignored and counted as one that could not be parsed.
     3991
     3992If a line does not conform to the rules laid out here, a warning shall
     3993be generated, it shall be ignored and counted as a line that could not
     3994be parsed.  The total number of lines that were not able to be parsed
     3995(including those that were ignored because \code{overwrite} is
     3996\code{false}, and any other parsing problems, but not including blank
     3997lines and comment lines) shall be returned by the function in the
     3998argument \code{nFail}.
     3999
     4000Here are some examples of lines of a valid configuration file:
     4001\filbreak
     4002\begin{verbatim}
     4003Double     F64     1.23456789      # This is a comment
     4004Float    F32 0.98765 # This is a comment too
     4005String  STR This is the string that forms the value #comment
     4006
     4007 # This is a comment line and is to be ignored
     4008boolean     BOOL    T # The value of `boolean' is `true'
     4009
     4010@primes U8  2,3 5 7,11,13 17 #   These are prime numbers
     4011
     4012comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique
     4013comment STR This
     4014comment STR     is
     4015comment STR       a
     4016comment STR        non-unique
     4017comment STR                  key
     4018Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored
     4019\end{verbatim}
     4020
     4021Of course, a real configuration file should look much nicer to humans
     4022than the above example, but PSLib must be able to parse such ugly
     4023files.
     4024
     4025We extend \code{psMetadataParseConfig} to allow a modest tree
     4026structure by defining a reserved keyword \code{TYPE}.  Any line in the
     4027config file which starts with the word \code{TYPE} shall be
     4028interpretted as defining a new valid type.  The defined type name
     4029follows the word \code{TYPE}, and is in turn followed by an arbitrary
     4030number of words.  These words are to be interpreted as the names of an
     4031embedded \code{psMetadata} entry, where the values are given on any
     4032line which (following the \code{TYPE} definition) employs the new type
     4033name.  For example, a new type may be defined as:
     4034\begin{verbatim}
     4035TYPE      CELL   EXTNAME   BIASSEC  CHIP
     4036CELL.00   CELL   CCD00     BSEC-00  CHIP.00
     4037CELL.01   CELL   CCD01     BSEC-01  CHIP.00
     4038\end{verbatim}
     4039
     4040When \code{psMetadataParseConfig} encounters the \code{TYPE} line, it
     4041should construct a \code{psMetadata} container and fill it with
     4042\code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP},
     4043with type \code{PS_META_STR}, but data allocated.  When it next
     4044encounters an entry of type \code{CELL}, it should then use the given
     4045name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy
     4046the \code{psMetadata} data onto the \code{psMetadataItem.data.md}
     4047entry, filling in the values from the rest of the line (\code{CCD00,
     4048BSEC-00, CHIP.00}).  This hierarchical structure is illustrated in
     4049Figure~\ref{fig:metadata}.
     4050
     4051We further extend \code{psMetadataParseConfig} to allow the definition
     4052of a \code{psMetadata} entry using a sequence of successive lines to
     4053define the values of the \code{psMetadataItem} entries.  The initial
     4054line defines the new \code{psMetadata} entry and its name.  The
     4055following lines have the same format as the other metadata config file
     4056entries.  The sequence is terminated with a line with a single word
     4057\code{END}.  For example, a metadata entry may be defined as:
     4058\begin{verbatim}
     4059CELL      METADATA
     4060 EXTNAME   STR   CCD00
     4061 BIASSEC   STR   BSEC-00
     4062 CHIP      STR   CHIP.00
     4063 NCELL     S32   24
     4064END
     4065\end{verbatim}
     4066
     4067A series of test inputs is contained in
     4068\S\ref{sec:configtest}.
     4069
     4070\subsection{XML Functions}
     4071
     4072Within Pan-STARRS, we will use XML documents as a transport mechanism
     4073to carry data between programs and between IPP and other subsystems.
     4074Configuration information may be stored as well as XML documents, in
     4075addition to the text format discussed in the discussion on Metadata.
     4076XML is an extremely variable document format, and it is not currently
     4077the intention of PSLib to provide a complete PSLib version of XML
     4078operations.  Rather, a limited number of operations are defined to
     4079convert specific data structures to an appropriate XML document.  To
     4080maximize the simplicity of the XML APIs, we will use the convention
     4081that a single XML document to be parsed by PSLib shall contain only a
     4082single data structure.  Each of the XML APIs therefore take as input a
     4083reference to a complete XML document and return a PSLib data
     4084structure, or take a PSLib data structure and return a complete XML
     4085document.
     4086
     4087We start by defining a PSLib wrapper type which is a pointer to an XML
     4088document in memory.  We wrap the \code{libxml2} version of an XML
     4089document pointer for now:
     4090\begin{verbatim}
     4091typedef xmlDocPtr psXMLDoc;
     4092void psXMLDocFree(psXMLDoc *doc);
     4093\end{verbatim}
     4094
     4095The next pair of functions convert a \code{psMetadata} data structure
     4096to a complete \code{psXMLDoc} (in memory) and vice versa:
     4097\begin{verbatim}
     4098psXMLDoc *psMetadataToXMLDoc(const psMetadata *metadata);
     4099psMetadata *psXMLDocToMetadata(const psXMLDoc *doc);
     4100\end{verbatim}
     4101
     4102The next pair of functions loads the data in a named file into a
     4103complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc}
     4104to a named file:
     4105\begin{verbatim}
     4106psXMLDoc *psXMLParseFile(const char *filename);
     4107int psXMLDocToFile(const psXMLDoc *doc, const char *filename);
     4108\end{verbatim}
     4109
     4110The next pair of functions accepts a block of memory and parses it
     4111into a complete \code{psXMLDoc} (also in memory), and vice versa:
     4112\begin{verbatim}
     4113psXMLDoc *psXMLParseMemory(const char *buffer, const int size);
     4114int psXMLDocToMemory(const psXMLDoc *doc, char *buffer);
     4115\end{verbatim}
     4116
     4117The next pair of functions read from and write to a file descriptor.
     4118The first converts the imcoming data to a complete \code{psXMLDoc}
     4119(also in memory), the second writes the \code{psXMLDoc} to the file
     4120descriptor:
     4121\begin{verbatim}
     4122psXMLDoc *psXMLParseFD(int fd);
     4123int psXMLDocToFD(const psXMLDoc *doc, int fd);
     4124\end{verbatim}
     4125
     4126\subsection{Database Functions}
     4127
     4128Many of the applications that PSLib will be used for will require
     4129access to a simple relational database.  PSLib includes generic
     4130database-independent interface mechanisms as part of its API set.  The
     4131most important aspect of PSLib's database support is to abstract as
     4132much database specific complexity as is feasible.  As almost all RDBMS
     4133provide at least a simple transactional model, commit and rollback
     4134support should be provided.
     4135
     4136Currently, only support for MySQL 4.1.x is required but other backends
     4137may be added as options in the future.  As a particular example which
     4138has implications for the database interaction model, support for
     4139SQLite may be required in the future.  Currently, the choice of
     4140backend database interface may be made as a compile option.  Details
     4141of the specified APIs in the discussion below refer to the relevant
     4142MySQL functions.
     4143
     4144Database errors must be trapped and placed onto the psError stack.
     4145The complete error message should be retrieved with the database's
     4146error function.
     4147
     4148\subsubsection{Managing the Database Connection}
     4149
     4150We specify a database handle which carries the information about the
     4151database connection:
     4152
     4153\begin{verbatim}
     4154    typedef struct {
     4155        MYSQL *mysql;
     4156    } psDB;
     4157\end{verbatim}
     4158
     4159The following collection of functions provides basic database functionality:
     4160
     4161\begin{verbatim}
     4162    // wraps mysql_init() & mysql_real_connect()
     4163    psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname);
     4164
     4165    // wraps mysql_close()
     4166    void psDBCleanup(psDB *dbh);
     4167
     4168    // wraps mysql_create_db()
     4169    bool psDBCreate(psDB *dbh, const char *dbname);
     4170
     4171    // wraps mysql_select_db()
     4172    bool psDBChange(psDB *dbh, const char *dbname);
     4173
     4174    // wraps mysql_drop_db()
     4175    bool psDBDrop(psDB *dbh, const char *dbname);
     4176\end{verbatim}
     4177
     4178For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and
     4179\code{mysql_real_connect()} in order to initialize a psDB structure and
     4180establish a database connection.  A null pointer should be returned on
     4181failure.
     4182
     4183When implementing support for SQLite, or other DB which is purely
     4184file-based, the \code{host}, \code{user}, and \code{passwd} arguments
     4185would be ignored while \code{dbname} would specify the path to the
     4186SQLite db file.
     4187
     4188\subsubsection{Interacting with Database Tables}
     4189
     4190The functions in this section perform high level interactions with the
     4191database tables.  All of them should behave ``atomically'' with
     4192respect to the state of the database.  Specifically, all interactions
     4193with the database should be done as a part of a transaction that is
     4194rolled-back on failure and committed only after all queries used by
     4195the API have been run.  In general, this API set attempts to treat a
     4196database table as a 2D matrix where columns can be represented by a
     4197\code{psVector} and rows as a \code{psMetadata} type.  A
     4198\code{psMetadata} collection is also used to define the columns of a
     4199table and as part of the query restrictions.
     4200
     4201\begin{verbatim}
     4202    bool psDBCreateTable(psDB *dbh, const char *tableName, psMetadata *md);
     4203\end{verbatim}
     4204
     4205This function generates and executes the SQL needed to create a table
     4206named \code{tableName}, with the column names and datatypes as
     4207described in \code{md}.  Each data item in the \code{psMetadata}
     4208collection represents a single table field.  The name of the field is
     4209given by the name of the \code{psMetadataItem} and the data type is
     4210give by the \code{psMetadataItem.type} and \code{psMetadataItem.ptype}
     4211entries.  A lookup table should be used to convert from PSLib types
     4212into MySQL compatible SQL data types.  For example, a
     4213\code{PS_META_STR} would map to an SQL99 varchar.  If the value of
     4214\code{type} is \code{PS_META_STR} then the \code{psMetadataItem.data}
     4215element is set to a string with the length for the field written as a
     4216text string.  The value of the \code{psMetadataItem.data} element is
     4217unused for the \code{PS_META_PRIMITIVE} types.  Other metadata types
     4218beyond \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed
     4219in a table definition metadata collection.
     4220
     4221Database indexes can be specified setting the \code{comment} field to
     4222``\code{Primary Key}'' or ``\code{Key}''.  Comment are otherwise
     4223ignored.
     4224
     4225\begin{verbatim}
     4226    bool psDBDropTable(psDB *dbh, const char *tableName);
     4227\end{verbatim}
     4228
     4229This function deletes the specified table.
     4230
     4231\begin{verbatim}
     4232    psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, const psU64 limit);
     4233    psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType pType, const psU64 limit);
     4234\end{verbatim}
     4235
     4236These functions generates and executes the SQL needed to select an entire
     4237column from a table or up to \code{limit} rows from it.  If \code{limit} is 0,
     4238the entire range is returned.  The database response is processed and a
     4239\code{psArray} of strings is returned.  The Num version of the function returns
     4240the data in a \code{psVector}, data cast to \code{pType}.  It returns an error
     4241(NULL) if the requested field is not a numerical type.
     4242
     4243\begin{verbatim}
     4244    psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, const psU64 limit);
     4245\end{verbatim}
     4246
     4247This function returns rows from the specified table which match
     4248the restrictions given by \code{where}.  The restrictions are
     4249specified as field / value pairs.  The \code{psMetadata} collection
     4250where must consist of valid database fields, though the database query
     4251checking functions may be used to validate the fields as part of the
     4252query.  If \code{where} is \code{NULL}, then there are no restrictions
     4253on the rows selected.  The selected rows are returned as a
     4254\code{psArray} of \code{psMetadata} values, one per row.
     4255
     4256\begin{verbatim}
     4257    bool psDBInsertOneRow(psDB *dbh, const char *tableName, psMetadata *row);
     4258\end{verbatim}
     4259
     4260Insert the data from \code{row} into \code{tableName}.  It should be noted in
     4261the API reference that if fields are specified in \code{row} that do not exist
     4262in \code{tablename}, the insert will fail.
     4263
     4264\begin{verbatim}
     4265    bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet);
     4266\end{verbatim}
     4267
     4268Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once
     4269and is atomic for the complete set of rows.
     4270
     4271\begin{verbatim}
     4272    psArray *psDBDumpRows(psDB *dbh, const char *tableName);
     4273\end{verbatim}
     4274
     4275Fetch all rows as an psArray of psMetadata.
     4276
     4277\begin{verbatim}
     4278    psMetadata *psDBDumpCols(psDB *dbh, const char *tableName);
     4279\end{verbatim}
     4280
     4281Fetch all columns, as either a psVector or a psArray depnding on whether or not
     4282the column is numeric, and return them in a psMetadata structure where
     4283psMetadataItem.name contains the column's name.
     4284
     4285\begin{verbatim}
     4286    psS64 psDBUpdateRows(psDB *dbh, const char *tableName, psMetadata *where, psMetadata *values);
     4287\end{verbatim}
     4288
     4289Update the columns contained in \code{values} in the row(s) that have a field
     4290with the value indicated by \code{where} (note that this is only allows very
     4291limited use of SQL99's ``where'' semantics).  The number of rows modified is
     4292returned.  A negative value is return to indicate an error. If there are
     4293multiple psMetadataItems in \code{where} then each item should be considered as
     4294an additional constraint.  e.g.  ``where foo = x and where bar = y''
     4295
     4296\begin{verbatim}
     4297    psS64 psDBDeleteRows(psDB *dbh, const char *tableName, psMetadata *where);
     4298\end{verbatim}
     4299
     4300Delete the rows that are matched by \code{where} using the same semantics for
     4301\code{where} as in psDBUpdateRow().  A negative value is returned to indicate an
     4302error.
     4303
     4304\subsection{FITS I/O Functions}
     4305
     4306We need a variety of I/O functions between the disk and certain of our
     4307PSLib data structures.  We need the ability to access FITS headers,
     4308images and tables (both ASCII and Binary).  We define here the FITS
     4309I/O functions, all of which are currently specified as wrappers to
     4310functions within CFITSIO.  CFITSIO provides a wide range of utilities
     4311which we do not feel are particularly appropriate as part of a generic
     4312I/O library, such as assumptions about names which change the data
     4313interpretation, etc.  We are defining our calls to avoid the hidden
     4314'features'.  The CFITSIO functions which are wrapped should in general
     4315be the most basic versions.
     4316
     4317\begin{verbatim}
     4318typedef struct {
     4319    fitsfile fd;
     4320} psFits;
     4321\end{verbatim}
     4322We begin by defining a datatype to wrap the CFITSIO \code{fitsfile}
     4323structure.  This is necessary to allow repeated access to the data in
     4324a file without multiple open commands (which are expensive).
     4325
     4326\subsubsection{FITS File Manipulations}
     4327
     4328\begin{verbatim}
     4329psFits *psFitsAlloc(const char *filename);
     4330\end{verbatim}
     4331
     4332Opens a FITS file at positions the pointer to the PHU.
     4333
     4334\begin{verbatim}
     4335bool psFitsMoveExtName(psFits *fits, const char *extname);
     4336\end{verbatim}
     4337
     4338Positions the pointer to the beginning of the specified
     4339\code{extname}.  If the \code{extname} does not exist, the function
     4340shall fail. 
     4341
     4342\begin{verbatim}
     4343bool psFitsMoveExtNum(psFits* fits, int extnum, bool relative);
     4344\end{verbatim}
     4345
     4346Moves the pointer to the beginning of the specified HDU number.  If
     4347\code{relative} is TRUE, \code{extnum} represents the number of HDUs
     4348relative to the current HDU.  The PHU is entry number 0, while the
     4349extended data segments start at number 1.
     4350
     4351\begin{verbatim}
     4352int psFitsGetExtNum(psFits* fits);
     4353\end{verbatim}
     4354
     4355Returns the current HDU number (i.e., file position). 
     4356
     4357\begin{verbatim}
     4358int psFitsGetSize(psFits* fits);
     4359\end{verbatim}
     4360
     4361Returns the number of HDUs in the file.
     4362
     4363\begin{verbatim}
     4364psFitsType psFitsGetExtType(psFits* fits);
     4365\end{verbatim}
     4366
     4367Gets the current HDU's type (table or image).
     4368
     4369\subsubsection{FITS Header I/O Functions}
     4370
     4371\begin{verbatim}
     4372psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits);
     4373\end{verbatim}
     4374Read header data into a \code{psMetadata} structure.  The data is read
     4375from the current HDU pointed at by the \code{psFits *fits} entry.  If
     4376\code{out} is \code{NULL}, a new psMetadata is created.
     4377
     4378\begin{verbatim}
     4379psMetadata *psFitsReadHeaderSet (psFits *fits);
     4380\end{verbatim}
     4381Load a complete set of headers from the \code{psFits} file pointer.
     4382This function loads the headers from all extensions into a
     4383\code{psMetadata} collection, each entry of which is a pointer to a
     4384\code{psMetadata} structure containing the header data.  The metadata
     4385entry names are the \code{EXTNAME} values for each header (with the
     4386value of \code{PHU} for the primary header unit).  At the start of the
     4387operation, the file pointer is rewound to the beginning of the file.
     4388At the end, it is positioned where it started when the function was
     4389called.
     4390
     4391\begin{verbatim}
     4392bool psFitsWriteHeader(psMetadata *output, const psFits *fits);
     4393\end{verbatim}
     4394Write metadata into the header of a FITS image file.  The header is
     4395written at the current HDU.
     4396
     4397\subsubsection{FITS Image I/O Functions}
     4398
     4399\begin{verbatim}
     4400psImage *psFitsReadImage(psImage *output, psFits *fits, psRegion region, int z);
     4401\end{verbatim}
     4402Read an image or subimage from the \code{psFits} file pointer.  This
     4403function is a wrapper to the CFITSIO library function.  The input
     4404parameters allow a full image or a subimage to be read.  The region to
     4405be read is specified by \code{region}.  A negative value for either of
     4406\code{region.x1} or \code{region.y1} specifies the size of the region
     4407to be read counting down from the end of the array. 
     4408
     4409If the native image is a cube, the value of z specifies the requested
     4410slice of the image.  This function must call \code{psError} and return
     4411\code{NULL} if any of the specified parameters are out of range for
     4412the data in the image file, or if the image on disk is zero- or
     4413one-dimensional.  This function need only read images of the native
     4414FITS image types (\code{psU8}, \code{psS16}, \code{psS32},
     4415\code{psF32}, \code{psF64}).  The user is expected to convert the data
     4416type as needed with \code{psImageCopy}.
     4417 
     4418\begin{verbatim}
     4419bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z);
     4420\end{verbatim}
     4421\tbd{we have discussed this as the alternate name}
     4422Write an image section to the open \code{psFits} file pointer.  This
     4423operation may write a portion of an image over the existing bytes of
     4424an existing image.  Care must be taken to interpret \code{region},
     4425which specified the output pixels to be written / over-written.  If
     4426the combination of \code{region} and the size of \code{psImage *input}
     4427implies writing pixels outside the existing data area of the image,
     4428the function shall return an error (ie, if \code{region.x0 + image.nx
     4429>= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >=
     4430NAXIS3}).  This function will only write images of the native FITS
     4431image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32},
     4432\code{psF64}).  The user is expected to convert the data type as
     4433needed with \code{psImageCopy}.  The return value must be 0 for a
     4434successful operation and 1 for an error.
     4435
     4436\begin{verbatim}
     4437bool psFitsWriteImage(psFits *fits, psMetadata *header, const psImage *input, int depth);
     4438\end{verbatim}
     4439Create a new image based on the dimensions specified for the image and
     4440the requested depth.  The header and image data segments are written
     4441in the file at the current position of the \code{psFits} pointer.
     4442This function will only write images of the native FITS image types
     4443(\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}).
     4444The user is expected to convert the data type as needed with
     4445\code{psImageCopy}.  The return value must be 0 for a successful
     4446operation and 1 for an error.
     4447
     4448\subsubsection{FITS Table I/O Functions}
     4449
     4450\begin{verbatim}
     4451psMetadata *psFitsReadTableRow (psFits *fits, int row);
     4452\end{verbatim}
     4453This function reads a single row of the table in the extension pointed
     4454at by the \code{psFits} file pointer.  The row number to be read is
     4455given by \code{row}.  The result is returned as a \code{psMetadata}
     4456collection with elements of the apporpriate types and keys
     4457corresponding to the table column names.  The function must apply the
     4458needed byte-swapping on the data in the row based on the description
     4459of the table data in the table header.  \tbr{we may need to be more
     4460flexible here: if we call this function repeatedly, it would be more
     4461efficient to pass the corresponding header or keep it somewhere (and
     4462the file pointer location, for that matter).}
     4463
     4464\begin{verbatim}
     4465void *psFitsReadTableRowRaw (int *nBytes, psFits *fits, int row);
     4466\end{verbatim}
     4467This function reads a single row of the table in the extension pointed
     4468at by the \code{psFits} file pointer.  The row number to be read is
     4469given by \code{row}.  The result is returned as collection of
     4470\code{nBytes} bytes allocated by the function.  The function must
     4471apply the needed byte-swapping on the data in the row based on the
     4472description of the table data in the table header.  \tbr{we may need
     4473to be more flexible here: if we call this function repeatedly, it
     4474would be more efficient to pass the corresponding header or keep it
     4475somewhere (and the file pointer location, for that matter).}
     4476
     4477\begin{verbatim}
     4478psArray *psFitsReadTableColumn (psFits *fits, char *colname);
     4479\end{verbatim}
     4480This function reads a single column of the table in the extension
     4481pointed at by the \code{psFits} file pointer.  The column is specified
     4482by the FITS table column key given by \code{row}.  The result is
     4483returned as a \code{psArray}, with the data from one row of the table
     4484column per array element.
     4485
     4486\begin{verbatim}
     4487psVector *psFitsReadTableColumnNum (psFits *fits, char *colname);
     4488\end{verbatim}
     4489This function reads a single column of the table in the extension
     4490pointed at by the \code{psFits} file pointer.  The column is specified
     4491by the FITS table column key given by \code{row} and must be of a
     4492numeric data type.  The result is returned as a \code{psVector} of the
     4493appropriate data type, with the data from one row of the table column
     4494per array element.
     4495
     4496\begin{verbatim}
     4497psArray *psFitsReadTableRaw (int *nBytes, psFits *fits);
     4498\end{verbatim}
     4499This function reads the entire data block from a table into the a
     4500\code{psArray}, with one element of the array per row.  The number of
     4501bytes per row is returned in \code{nBytes}.  The function must apply
     4502the needed byte-swapping on the data in each row based on the
     4503description of the table data in the table header.
     4504
     4505\begin{verbatim}
     4506psArray *psFitsReadTable (psFits *fits);
     4507\end{verbatim}
     4508This function reads the entire data block from a table into the a
     4509\code{psArray}, with one element of the array per row.  Each row is
     4510stored as a \code{psMetadata} collection as described above for
     4511\code{psFitsReadTableRow}.
     4512
     4513\begin{verbatim}
     4514bool psFitsWriteTable(psFits* fits, psMetadata *header, psArray* table);
     4515\end{verbatim}
     4516Accepts a \code{psArray} of \code{psMetadata} and writes it to the
     4517current HDU.  If the current HDU is not a table type, this will fail
     4518and return FALSE.
     4519
     4520\begin{verbatim}
     4521bool psFitsUpdateTable(psFits* fits, psMetadata *header, psMetadata* data, int row);
     4522\end{verbatim}
     4523Writes the \code{psMetadata} data to a FITS table at the specified row
     4524in the current HDU.  If the current HDU is not a table type, this will
     4525fail and return FALSE. 
     4526
     4527\pagebreak
    34454528\section{Astronomy-Specific Functions}
    34464529
     
    34574540\begin{itemize}
    34584541\item Dates and times
    3459 \item Metadata
    34604542\item Detector and sky positions
    3461 \item Astronomy Image
     4543\item Astronomical Image Containers
    34624544\item Astrometry
    34634545\item Photometry
     
    34874569
    34884570typedef enum {
    3489     PS_IERS_A,                      ///< IERS Bulliten A
    3490     PS_IERS_B,                      ///< IERS Bulliten B
    3491 } psTimeBulliten;
     4571    PS_IERS_A,                      ///< IERS Bulletin A
     4572    PS_IERS_B,                      ///< IERS Bulletin B
     4573} psTimeBulletin;
    34924574
    34934575typedef struct {
    34944576    psS64            sec;           ///< seconds, negative values represent dates before 1970
    3495     psU32            nsec;          ///< nanseconds
     4577    psU32            nsec;          ///< nanoseconds
    34964578    bool             leapsecond;    ///< if time falls on a UTC leapsecond
    34974579    psTimeType       type;          ///< type of time
     
    35234605This function may be used to convert between the various \code{psTimeType} time
    35244606representations.  The \code{time} is modified and returned.  Conversion between
    3525 all of the \emph{SI} length second systems should be implimented as first
     4607all of the \emph{SI} length second systems should be implimented by first
    35264608converting to TAI and then to the destination system.  UT1 is a special case
    35274609for conversion as it uses variable length secounds.  Conversation to UT1, via
    35284610TAI, is allowed but conversion \emph{from} UT1 is currently forbidden.
    35294611
    3530 To convert to Local Mean Sidereal Time, it is necessary to provide the local
    3531 longitude (specified in radians, positive East of Greenwich) as well:
     4612The following function converts to Local Mean Sidereal Time.  It is
     4613necessary to provide the local longitude (specified in radians,
     4614positive East of Greenwich) as well:
    35324615
    35334616\begin{verbatim}
     
    35354618\end{verbatim}
    35364619
    3537 The function may accept any of the \code{psTimeType} types with \emph{SI}
    3538 length seconds.  The \code{time} is modified and returned.  Note that this
    3539 function must supply the value $UT1-UTC$, which is available externally (see
    3540 \code{psTimeGetUT1Delta()}) and should use the UT1 values interpolated from
    3541 IERS bulliten B.  The following utility function encapsulates the PSLib
    3542 mechanism to extract the value of $UT1-UTC$:
    3543 
    3544 \begin{verbatim}
    3545 double psTimeGetUT1Delta(const psTime *time, psTimeBulliten bulliten);
    3546 psSphere *psTimeGetPoleCoords(const psTime *time, psTimeBulliten bulliten);
    3547 \end{verbatim}
    3548 
    3549 Leap seconds are added to UTC in order to keep it within $0.9s$ of UT1 (which
    3550 is defined relative to the Earth's rotation, and hence is useful for
    3551 astronomical purposes).
     4620The function may accept any of the \code{psTimeType} types with
     4621\emph{SI} length seconds.  The \code{time} is modified and returned.
     4622Note that this function requires the value $UT1-UTC$ (see
     4623\code{psTimeGetUT1Delta()}) and should use the UT1 values interpolated
     4624from IERS bulletin B. 
     4625
     4626The following utility function encapsulates the PSLib mechanism to
     4627extract the value of $UT1-UTC$ from the IERS Time Tables:
     4628
     4629\begin{verbatim}
     4630double psTimeGetUT1Delta(const psTime *time, psTimeBulletin bulletin);
     4631\end{verbatim}
     4632
     4633The following function provides tidal corrections to UT1-UTC, using
     4634the Ray model of Simon et al (REF).
     4635\begin{verbatim}
     4636psTime *psTime_TideUT1Corr(const psTime *time);
     4637\end{verbatim}
     4638
     4639Leap seconds are added to UTC in order to keep it within $0.9s$ of UT1
     4640(which is defined relative to the Earth's rotation, and hence is
     4641useful for astronomical purposes).  The following function calculates
     4642the absolute number of leap seconds different between two times.
    35524643
    35534644\begin{verbatim}
     
    35554646\end{verbatim}
    35564647
    3557 This function calculates the absolute number of leap seconds different between
    3558 two times.
     4648The following function accepts \code{PS_TIME_UTC} objects and
     4649determines if the time is potentaly a leapsecond, returning
     4650\code{TRUE} if so.
    35594651
    35604652\begin{verbatim}
    35614653bool psTimeIsLeapSecond(const psTime *utc);
    35624654\end{verbatim}
    3563 
    3564 This function only accepts \code{PS_TIME_UTC} objects and determines if the
    3565 time is potentaly a leapsecond.
    35664655
    35674656\subsubsection{External Date and Time Formats}
     
    35814670\end{verbatim}
    35824671
    3583 The \code{psTimeToISO()} function will convertion \code{PS_TIME_UTC} objects
    3584 with the \code{leapsecond} flag set to represent the number of seconds as
    3585 ``:60''.
     4672The \code{psTimeToISO()} function converts \code{PS_TIME_UTC} objects
     4673with the \code{leapsecond} flag set to represent the number of seconds
     4674as ``:60''.
    35864675
    35874676\subsubsection{Date and Time Parsing}
     
    36224711\code{psS64} (the type of \code{psTime.sec}).
    36234712
    3624 Note that in both these functions, when handling UTC, that the difference
    3625 between two times is not inclusive of leap seconds.  For example, if we add 30
    3626 seconds to 1998-12-31T23:59:45Z, the result is 1999-01-01T00:00:14Z, since a
    3627 leap second was introduced at 1999-01-01T00:00:00Z.
    3628 
    3629 Time math may only be done on the of \code{psTime} objects of the same type,
    3630 and in the case of UT1, the functions shall internally convert the
    3631 \code{psTime} inputs to TAI before performing the math; this is in order that
    3632 leap seconds are accounted for.
    3633 
    3634 The type of the time returned by \code{psTimeMath} shall be the same as that of
    3635 the input \code{time}.
    3636 
     4713Note that in both these functions the difference between two times is
     4714the elapsed number of seconds, inclusing leap seconds.  For example,
     4715if we add 30 seconds to 1998-12-31T23:59:45Z, the result is
     47161999-01-01T00:00:14Z, since a leap second was introduced at
     47171999-01-01T00:00:00Z.
     4718
     4719Time math may only be done on \code{psTime} objects of the same type,
     4720and except in the case of UT1, the functions shall internally convert
     4721the \code{psTime} inputs to TAI before performing the math; this
     4722ensures that leap seconds are correctly counted.
     4723
     4724The type of the time returned by \code{psTimeMath} shall be the same
     4725as that of the input \code{time}.
    36374726
    36384727\subsubsection{Time Tables}
     
    36454734
    36464735\begin{itemize}
    3647 \item IERS Bulliten A \& B (1 year ago $\rightarrow$ now + $\sim$3 months)
     4736\item IERS Bulletin A \& B (1 year ago $\rightarrow$ now + $\sim$3 months)
    36484737\begin{itemize}
    36494738\item \code{ftp://maia.usno.navy.mil/ser7/finals.daily}
    36504739\end{itemize}
    36514740
    3652 \item IERS Bulliten A \& B (1973-1-2 $\rightarrow$ now + $\sim$1 year)
     4741\item IERS Bulletin A \& B (1973-1-2 $\rightarrow$ now + $\sim$1 year)
    36534742\begin{itemize}
    36544743\item \code{ftp://maia.usno.navy.mil/ser7/finals.all}
     
    36734762format of these files shall be simple, for speed in reading.  Each line shall
    36744763contain the date in MJD and the following values from both the A \& B IERS
    3675 bullitens: $x_p$ (in arcseconds), $y_p$ (in arcseconds) and $\Delta$UT (in
     4764bulletins: $x_p$ (in arcseconds), $y_p$ (in arcseconds) and $\Delta$UT (in
    36764765seconds).  This format must be readable by \code{psLookupTableRead}.  For
    36774766example:
     
    37564845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    37574846
    3758 \subsection{Regions}
    3759 
    3760 In many places, we need to refer to a rectangular area.  We define a
    3761 structure to represent a rectangle:
    3762 \begin{verbatim}
    3763 typedef struct {
    3764   float x0;
    3765   float x1;
    3766   float y0;
    3767   float y1;
    3768 } psRegion;
    3769 psRegion *psRegionAlloc (float x0, float x1, float y0, float y1);
    3770 \end{verbatim}
    3771 
    3772 \begin{verbatim}
    3773 psRegion *psRegionFromString (char *region);
    3774 \end{verbatim}
    3775 This function converts the IRAF description of a region in the form
    3776 \code{[x0:x1,y0:y1]}, used for header entries such as \code{BIASSEC},
    3777 into the corresponding \code{psRegion} structure.
    3778 
    3779 \subsection{Metadata}
    3780 \label{sec:metadata}
    3781 
    3782 \subsubsection{Conceptual Overview}
    3783 
    3784 Within PSLib, we provide a data structure to carry metadata and
    3785 mechanisms to manipulate the metadata.  Metadata is a general concept
    3786 that requires some discussion.  In any data analysis task, the
    3787 ensemble of all possible data may be divided into two or three
    3788 classes: there is the specific data of interest, there is data which
    3789 is related or critical but not the primary data of interest, and there
    3790 is all of the other data which may or may not be interesting.  For
    3791 example, consider a simple 2D image obtained of a galaxy from a CCD
    3792 camera on a telescope.  If you want to study the galaxy, the specific
    3793 data of interest is the collection of pixels.  There are a variety of
    3794 other pieces of data which are closely related and crucial to
    3795 understanding the data in those pixels, such as the dimensions of the
    3796 image, the coordinate system, the time of the image, the exposure
    3797 time, and so forth.  Other data may be known which may be less
    3798 critical to understanding the image, but which may be interesting or
    3799 desired at a later date.  For example, the observer who took the
    3800 image, the filter manufacturer, the humidity at the telescope, etc.
    3801 
    3802 Formally, all of the related data which describe the principal data of
    3803 interest are metadata.  Note that which piece is the metadata and
    3804 which is the data may depend on the context.  If you are examining the
    3805 pixels in an image, the coordinate and flux of an object may be part
    3806 of the metadata.  However, if you are analyzing a collection of
    3807 objects extracted from an image, you may consider then pixel data
    3808 simply part of the metadata associated with the list of objects. 
    3809 
    3810 There are various ways to handle metadata vs data within a programming
    3811 environment.  In C, it is convenient to use structures to group
    3812 associated data together.  One possibility is to define the metadata
    3813 as part of the associated data structure.  For example, the image data
    3814 structure would have elements for all possible associated measurement.
    3815 This approach is both cumbersome (because of the large number metadata
    3816 types), impractical (because the full range of necessary metadata is
    3817 difficult to know in advance) and inflexible (because any change in
    3818 the collection of metadata requires addition of new structure elements
    3819 and recompilation). 
    3820 
    3821 An alternative is to place the metadata in a generic container and use
    3822 lookup mechanisms to extract the appropriate metadata when needed.  An
    3823 example of this is would be a text-based FITS header for an image read
    3824 into a flat text buffer.  In this implementation, metadata lookup
    3825 functions could return the current value of, for example, NAXIS1 (the
    3826 number of columns of the image) by scanning through the header buffer.
    3827 This method has the benefits of flexibility and simplicity of
    3828 programming interface, but it has the disadvantage that all metadata
    3829 is accessed though this lookup mechanism.  This may make the code less
    3830 readable and it may slow down the access. 
    3831 
    3832 PSLib implements an intermediate solution to this problem.  We specify
    3833 a flexible, generic metadata container and access methods.  Data types
    3834 which require association with a general collection of metadata should
    3835 include an entry of this metadata type.  However, a subset of metadata
    3836 concepts which are basic and frequently required may be placed in the
    3837 coded structure elements.  This approach allows the code to refer to
    3838 the basic metadata concepts as part of the data structure (ie,
    3839 \code{image.nx}), but also allows us to provide access to any
    3840 arbitrary metadata which may be generated.  As a practical matter, the
    3841 choice of which entries are only in the metadata and which are part of
    3842 the explicit structure elements is rather subjective.  Any data
    3843 elements which are frequently used should be put in the structure;
    3844 those which are only infrequently needed should be left in the generic
    3845 metadata.
    3846 
    3847 There are some points of caution which must be noted.  Any
    3848 manipulation of the data should be reflected in the metadata where
    3849 appropriate.  This is always an issue of concern.  For example,
    3850 consider an image of dimensions \code{nx, ny}.  If a function extracts
    3851 a subraster, it must change the values of \code{nx, ny} to match the
    3852 new dimensions.  What should it do to the corresponding metadata?
    3853 Clearly, it should change the corresponding value which defines
    3854 \code{nX, nY}.  However, it is not quite so simple: there may be other
    3855 metadata values which depend on those values.  These must also be
    3856 changed appropriately.  What if the metadata element points to a
    3857 copy of the metadata which may be shared by other representations of
    3858 the image?  These must be treated differently because the change would
    3859 invalidate those other references.  Care must be taken, therefore,
    3860 when writing functions which operate on the data to consider all of
    3861 the relevant metadata entries which must also be updated.
    3862 
    3863 A related issue is the definition of metadata names.  Entries in a
    3864 structure have the advantage of being hardwired: every instance of
    3865 that structure will have the same name for the same entry.  This is
    3866 not necessarily the case with a more flexible metadata container.  The
    3867 image exposure time is a notorious example in astronomy.  Different
    3868 observatories use different header keywords (ie, metadata names) for
    3869 the same concept of the exposure time (\code{EXPTIME},
    3870 \code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc).  Any system
    3871 which operates on these metadata needs to address the issue of
    3872 identifying these names.  This issue seems like an argument for
    3873 hardwiring metadata in the structure, but in fact it does not present
    3874 such a strong case.  If the metadata are hardwired, some function will
    3875 still have to know how to interpret the various names to populate the
    3876 structure.  The concept can still be localized with generic metadata
    3877 containers by including abstract metadata names within the code which
    3878 are tied to the various implementations-specific metadata names.
    3879 
    3880 \subsubsection{Metadata Representation}
    3881 
    3882 \begin{figure}
    3883 \psfig{file=Metadata,width=6.5in}
    3884 \caption{Metadata Structures\label{fig:metadata}}
    3885 \end{figure}
    3886 
    3887 This section addresses the question of how \PS{} metadata should be
    3888 represented in memory, not how it should be represented on disk.
    3889 
    3890 We define an item of metadata with the following structure:
    3891 \filbreak
    3892 \begin{verbatim}
    3893 typedef struct {
    3894     int id;                             ///< unique ID for this item
    3895     char *name;                         ///< Name of item
    3896     psMetadataType type;                ///< type of this item
    3897     psElemType ptype;                   ///< primitive data type
    3898     const union {
    3899         psS32 S32;                      ///< integer data
    3900         psF32 F32;                      ///< floating-point data
    3901         psF64 F64;                      ///< double-precision data
    3902         void *V;                        ///< other type
    3903         psList *list;                   ///< psList entry
    3904         psMetadata *md;                 ///< psMetadata entry
    3905     } data;                             ///< value of metadata
    3906     char *comment;                      ///< optional comment ("", not NULL)
    3907 } psMetadataItem;
    3908 \end{verbatim}
    3909 
    3910 The \code{id} is a unique identifier for this item of metadata;
    3911 experience shows that such tags are useful.  The entry \code{name}
    3912 specifies the name of the metadata item.  The value of the metadata is
    3913 given by the union \code{data}, and may be of type \code{psS32},
    3914 \code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at
    3915 by the \code{void} pointer \code{V}.  A character string comment
    3916 associated with this metadata item may be stored in the element
    3917 \code{comment}. The \code{type} entry specifies how to interpret the
    3918 type of the data being represented, given by the enumerated type
    3919 \code{psMetadataType}:
    3920 %
    3921 \filbreak
    3922 \begin{verbatim}
    3923 typedef enum {                          ///< type of item.data is:
    3924     PS_META_PRIMITIVE,                  ///< primitive type: use item.ptype
    3925     PS_META_LIST,                       ///< psList; use item.data.list (used for non-unique data)
    3926     PS_META_META,                       ///< psMetadata: use item.data.list
    3927     PS_META_STR,                        ///< string (item.data.V)
    3928     PS_META_MATH,                       ///< psScalar, psVector, psImage (item.data.V)
    3929     PS_META_JPEG,                       ///< JPEG (item.data)
    3930     PS_META_PNG,                        ///< PNG (item.data)
    3931     PS_META_ASTROM,                     ///< astrometric coefficients (item.data)
    3932     PS_META_UNKNOWN,                    ///< other (item.data)
    3933     PS_META_NTYPE                       ///< Number of types; must be last
    3934 } psMetadataType;
    3935 \end{verbatim}
    3936 If the data is a PSLib primitive data value, the primitive data type
    3937 is given by the value of \code{ptype}.
    3938 
    3939 A collection of metadata is represented by the \code{psMetadata} structure:
    3940 \begin{verbatim}
    3941 typedef struct {
    3942     psList *list;                       ///< list of psMetadataItem
    3943     psHash *table;                      ///< hash table of the same metadata
    3944 } psMetadata;
    3945 \end{verbatim}
    3946 The type \code{psMetadata} is a container class for metadata. Note
    3947 that there are in fact \emph{two} representations of the metadata
    3948 (each \code{psMetadataItem} appears on both).  The first
    3949 representation employs a doubly-linked list that allows the order of
    3950 the metadata to be preserved (e.g., if FITS headers are read in a
    3951 particular order, they should be written in the same order).  The
    3952 second representation employs a hash table which allows fast look-up
    3953 given a specific metadata keyword.
    3954 
    3955 Certain metadata names (such as the FITS keywords \code{COMMENT} and
    3956 \code{HISTORY} in a FITS header) may be repeated with different
    3957 values.  In such a case, the \code{psMetadata.list} structure contains
    3958 the entries in their original sequence with duplicate keys.  The
    3959 \code{psMetadata.hash} entries, which are required to have unique
    3960 keys, would have a single entry with the keyword of the repeated key,
    3961 with the value of \code{psMetadataType} set to \code{PS_META_LIST},
    3962 and the \code{psMetadataItem.data} element pointing to a \code{psList}
    3963 containing the actual entries.  If \code{psMetadataItemAlloc} is
    3964 called with the type set to \code{PS_META_LIST}, such a repeated key
    3965 is created.  If the data value passed to \code{psMetadataItemAlloc}
    3966 (the quantity in ellipsis) is \code{NULL}, then an empty
    3967 \code{psMetadataItem} with the given keyword is created to hold future
    3968 entries of that keyword.
    3969 
    3970 The \code{psMetadataAdd} routine is required to check that all
    3971 metadata names are unique unless the type is already qualified as
    3972 \code{PS_META_LIST}; in this case the data are added to the
    3973 corresponding \code{psMetadataItem.data} list.
    3974 
    3975 \subsubsection{Metadata APIs}
    3976 
    3977 The allocator for \code{psMetadataItem} returns a full
    3978 \code{psMetadataItem} ready for insertion into the \code{psMetadata}.
    3979 The \code{name} entry specifies the name to use for this metadata
    3980 item, and may include \code{sprintf}-type formating codes.  The
    3981 \code{comment} entry is a fixed string which is used for the comment
    3982 associated with this metadata item.  The metadata data and the
    3983 arguments to the \code{name} formatting codes are passed, in that
    3984 order (metadata pointer first), to \code{psMetadataItemAlloc} as
    3985 arguments following the comment string.  The data must be a pointer
    3986 for any data types which are stored in the element \code{data.void},
    3987 while other data types are passed as numeric values.  The argument
    3988 list must be interpreted appropriately by the \code{va_list} operators
    3989 in the function.
    3990 \begin{verbatim}
    3991 psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...);
    3992 psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list);
    3993 \end{verbatim}
    3994 
    3995 The constructor for the collection of metadata, \code{psMetadata},
    3996 simply returns an empty metadata container (employing the constructors
    3997 for the doubly-linked list and hash table).  The destructor needs to
    3998 free each of the \code{psMetadataItem}s using \code{psMetadataItemFree}.
    3999 \begin{verbatim}
    4000 psMetadata *psMetadataAlloc(void);
    4001 \end{verbatim}
    4002 
    4003 Items may be added to the metadata in one of two ways --- firstly, an
    4004 item may be added by appending a \code{psMetadataItem} which has
    4005 already been created; and secondly by directly providing the data to
    4006 be appended.  In both cases, the return value defines the success
    4007 (\code{true}) or failure of the operation.  The second function,
    4008 \code{psMetadataAdd} takes a pointer or value which is interpreted by
    4009 the function using variadic argument interpretation.  The third
    4010 version is the \code{va_list} version of the second function.  All
    4011 three functions take a parameter, \code{location}, which specifies
    4012 where in the list to place the element, following the conventions for
    4013 the \code{psList}.  The entry \code{mode} for \code{psMetadataAddItem}
    4014 is a bit mask constructed by OR-ing the allowed option flags (eg,
    4015 \code{PS_META_REPLACE}) which specifies minor variations on the
    4016 behavior.  The \code{format} entry, which specifies both the metadata
    4017 type and the optional flags, is constructed by bit-wise OR-ing the
    4018 appropriate \code{psMetadataType} and allowed option option flags.
    4019 Care should be taken not to leak memory when appending an item for
    4020 which the key already exists in the metadata (and is not
    4021 \code{PS_META_LIST}).
    4022 %
    4023 \begin{verbatim}
    4024 bool psMetadataAddItem(psMetadata *md, psMetadataItem *item, int location, int mode);
    4025 bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...);
    4026 bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment,
    4027                     va_list list);
    4028 \end{verbatim}
    4029 
    4030 The functions above take option flags which modify the behavior when
    4031 metadata items are added to the metadata list.  These flags must be
    4032 bit-exclusive of those used above for the \code{psMetadataTypes}.  The
    4033 flags have the following meanings:
    4034 
    4035 \code{PS_META_DEFAULT}: This is the zero bit mask, to allow the
    4036 default behavior for \code{psMetadataAddItem} above.  If this is OR-ed
    4037 with a \code{psMetadataType}, the result is as if no OR-ing took
    4038 place.
    4039 
    4040 \code{PS_META_REPLACE}: If the given metadata item exists in the
    4041 metadata list, and is not of type \code{PS_META_LIST} or
    4042 \code{PS_META_META} (ie, not a container type), then this entry is
    4043 allowed to replace the existing entry.  If this mode bit is not set, a
    4044 duplicate (non-container-type) entry is an error.
    4045 
    4046 \begin{verbatim}
    4047 typedef enum {                          ///< option flags for psMetadata functions
    4048     PS_META_DEFAULT,                    ///< default behavior (0x0000) for use in mode above
    4049     PS_META_REPLACE,                    ///< allow entry to be replaced
    4050 } psMetadataFlags;
    4051 \end{verbatim}
    4052 
    4053 An example of code to use these metadata APIs to generate the
    4054 structure seen in Figure~\ref{fig:metadata} is given below.
    4055 
    4056 \begin{verbatim}
    4057 md = psMetadataAlloc();
    4058 
    4059 psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE",   PS_META_BOOL, "basic fits",            TRUE);
    4060 psMetadataAdd(md, PS_LIST_TAIL, "BLANK",    PS_META_S32,  "invalid pixel data",    -32768);
    4061 psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR,  "observing date UT", "   2004-6-16");
    4062 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_LIST, "head of comment block", NULL);
    4063 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "DATA");
    4064 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "PARAMS");
    4065 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME",  PS_META_F32,  "exposure time (sec)",   1.05);
    4066 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT",  PS_META_STR,  "",                      "FOO");
    4067 
    4068 cell = psMetadataAlloc();
    4069 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME",  PS_META_STR,  "",                    "CCD00");
    4070 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR,  "",                    "BSEC-00");
    4071 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP",     PS_META_STR,  "",                    "CHIP.00");
    4072 psMetadataAdd(md,   PS_LIST_TAIL, "CELL.00",  PS_META_META, "",                    cell);
    4073 
    4074 cell = psMetadataAlloc();
    4075 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME",  PS_META_STR,  "",                    "CCD01");
    4076 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR,  "",                    "BSEC-01");
    4077 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP",     PS_META_STR,  "",                    "CHIP.01");
    4078 psMetadataAdd(md,   PS_LIST_TAIL, "CELL.01",  PS_META_META, "",                    cell);
    4079 \end{verbatim}
    4080 
    4081 The following code shows how to use the APIs to replace one of these values:
    4082 \begin{verbatim}
    4083 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME",  PS_META_F32 | PS_REPLACE,  "new exposure time (sec)",   2.05);
    4084 \end{verbatim}
    4085 
    4086 Items may be removed from the metadata by specifying a key or a
    4087 location in the list.  If the value of \code{name} is \code{NULL}, the
    4088 value of \code{location} is used.  If the value of \code{name} is not
    4089 \code{NULL}, then \code{location} must be set to
    4090 \code{PS_LIST_UNKNOWN}.  If the key matches a metadata item, the item
    4091 is removed from the metadata and \code{true} is returned; otherwise,
    4092 \code{false} is returned.  If the key is not unique, then \emph{all}
    4093 items corresponding to the key are removed, and \code{true} is
    4094 returned.
    4095 %
    4096 \begin{verbatim}
    4097 bool psMetadataRemove(psMetadata *md, int location, const char *key);
    4098 \end{verbatim}
    4099 
    4100 Items may be found within the metadata by providing a key.  In the
    4101 event that the key is non-unique, the first item is returned.
    4102 \begin{verbatim}
    4103 psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key);
    4104 \end{verbatim}
    4105 
    4106 Several utility functions are provided for simple cases.  These
    4107 functions perform the effort of casting the data to the appropriate
    4108 type.  The numerical functions shall return 0.0 if their key is not
    4109 found.  If the pointer value of \code{status} is not \code{NULL}, it
    4110 is set to reflect the success or failure of the lookup.
    4111 \begin{verbatim}
    4112 void *psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key);
    4113 psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key);
    4114 psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key);
    4115 \end{verbatim}
    4116 
    4117 Items may be retrieved from the metadata by their entry position.  The
    4118 value of which specifies the desired entry in the fashion of
    4119 \code{psList}.
    4120 \begin{verbatim}
    4121 psMetadataItem *psMetadataGet(const psMetadata *md, int location);
    4122 \end{verbatim}
    4123 
    4124 The metadata list component may be iterated over by using a
    4125 \code{psListIterator} in a fashion equivalent to the usage for
    4126 \code{psList}.  The iterator may be set to a location in the
    4127 \code{psMetadata} list, and the user may get the previous or next item
    4128 in the list relative to that location.  \code{psMetadataGetNext} has
    4129 the ability to match the key using a POSIX regex, e.g., if the user
    4130 only wants to iterate through \code{IPP.machines.sky} and doesn't want
    4131 to bother with \code{IPP.machines.detector}.  The iterator should
    4132 iterate over every item in the metadata list, even those that are
    4133 contained in a \code{PS_META_LIST}.  The value \code{iterator}
    4134 specifies the iterator to be used.  In setting the iterator, the
    4135 position of the iterator is defined by \code{location}, which follows
    4136 the conventions of the \code{psList} iterators.
    4137 \begin{verbatim}
    4138 psListIterator *psMetadataIteratorAlloc(psMetadata *md, int location, bool mutable);
    4139 bool psMetadataIteratorSet(psListIterator *iterator, int location);
    4140 psMetadataItem *psMetadataGetAndIncrement(psListIterator *iterator, const char *regex);
    4141 psMetadataItem *psMetadataGetAndDecrement(psListIterator *iterator, const char *regex);
    4142 \end{verbatim}
    4143 
    4144 Metadata items may be printed to an open file descriptor based on a
    4145 provided format.  The format string is an sprintf format statement
    4146 with exactly one \% formatting command.  If the metadata item type is
    4147 a numeric type, this formatting command must also be numeric, and type
    4148 conversion performed to the value to match the format type.  If the
    4149 metadata item type is a string, the formatting command must also be
    4150 for a string (\%s type of command).  If the metadata type is any other
    4151 data type, printing is not allowed.
    4152 \begin{verbatim}
    4153 bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *md);
    4154 \end{verbatim}
    4155 
    4156 \subsubsection{Configuration files}
    4157 \label{sec:configspec}
    4158 
    4159 It will be necessary for the \PS{} system, in order to load
    4160 pre-defined settings, to parse a configuration file into a
    4161 \code{psMetadata} structure.  This shall be performed by the
    4162 function \code{psMetadataParseConfig}, as described below.
    4163 
    4164 \begin{verbatim}
    4165 psMetadata *psMetadataParseConfig(psMetadata *md, int *nFail, const char *filename, bool overwrite);
    4166 \end{verbatim}
    4167 
    4168 Given a metadata container, \code{md}, and the name of a configuration
    4169 file, \code{filename}, \code{psMetadataParseConfig} shall parse the
    4170 configuration file, placing the contained key/type/value/comment quads
    4171 into the metadata, and returning a pointer to the metadata structure.
    4172 The number of lines that failed to parse is returned in \code{nFail}.
    4173 Multiple specifications of a key that haven't been declared (see
    4174 below) are overwritten if and only if \code{overwrite} is \code{true}.
    4175 If the metadata container is \code{NULL}, it shall be allocated. 
    4176 
    4177 On error, the function shall return \code{NULL}.
    4178 
    4179 The configuration file shall consist of plain text with
    4180 key/type/value/comment quads on separate lines.  Blank lines,
    4181 including those consisting solely of whitespace (both spaces and
    4182 tabs), shall be ignored, as shall lines that commence with the comment
    4183 character (a hash mark, \code{#}), either immediately at the start of
    4184 the line, or preceded by whitespace.  The key/type/value/comment quads
    4185 shall all lie on a single line, separated by whitespace.
    4186 
    4187 The key shall be first, possibly preceded on the line by whitespace
    4188 which should not form part of the key.
    4189 
    4190 Next, to assist the casting of the value, shall be a string
    4191 identifying the type of the value, which shall correspond to one of
    4192 the simple types supported in \code{psMetadata}:
    4193 \code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to abbreviate
    4194 \code{STRING}.
    4195 
    4196 \tbd{May, in the future, require more types, including U8,S16,C64,
    4197 which will also necessitate updating the definition of psMetadata.}
    4198 
    4199 The value shall follow the type: strings may consist of multiple
    4200 words, and shall have all leading and trailing whitespace removed;
    4201 booleans shall simply be either \code{T} or \code{F}.
    4202 
    4203 Following the value may be an optional comment, preceded by a comment
    4204 character (a hash mark, \code{#}), which in the case of a string
    4205 value, serves to mark the end of the value, and for other types serves
    4206 to identify the comment to the reader.  Only one comment character may
    4207 be present on any single line (i.e., neither strings nor comments are
    4208 permitted to contain the comment character).  The comment may consist
    4209 of multiple words, and shall have leading and trailing whitespace
    4210 removed.
    4211 
    4212 One wrinkle is the specification of vectors.  Keys for which the value
    4213 is to be parsed as a vector shall be preceded immediately by a
    4214 ``vector symbol'', which we choose to be the ``at'' sign, \code{@}.
    4215 In this case, the type shall be interpreted as the type for the
    4216 vector, which may be any of the signed or unsigned integer or floating
    4217 point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not
    4218 the complex floating point types; and the value shall consist of
    4219 multiple numbers, separated either by a comma or whitespace.  These
    4220 values shall populate a \code{psVector} of the appropriate type in the
    4221 order in which they appear in the configuration file.
    4222 
    4223 \tbd{May add complex types, likely to be specified with values such as
    4224   1.23+4.56i in the future.}
    4225 
    4226 An additional hurdle is the specification of keys that may be
    4227 non-unique (such as the \code{COMMENT} keyword in a FITS header).
    4228 These keys shall be specified in the configuration file as non-unique
    4229 by specifying the key at the start of the line (possibly preceded by
    4230 whitespace) and specifying the type as a ``multiple symbol'', which we
    4231 choose to be an asterisk, \code{*}.  No other data may be provided on
    4232 this line, though a comment, preceeded by the comment marker, is
    4233 valid.  A warning shall be produced when a key which has not been
    4234 specified to be non-unique is repeated; in this case, the former value
    4235 shall be overwritten if \code{overwrite} is \code{true}, otherwise the
    4236 line shall be ignored and counted as one that could not be parsed.
    4237 
    4238 If a line does not conform to the rules laid out here, a warning shall
    4239 be generated, it shall be ignored and counted as a line that could not
    4240 be parsed.  The total number of lines that were not able to be parsed
    4241 (including those that were ignored because \code{overwrite} is
    4242 \code{false}, and any other parsing problems, but not including blank
    4243 lines and comment lines) shall be returned by the function in the
    4244 argument \code{nFail}.
    4245 
    4246 Here are some examples of lines of a valid configuration file:
    4247 \filbreak
    4248 \begin{verbatim}
    4249 Double     F64     1.23456789      # This is a comment
    4250 Float    F32 0.98765 # This is a comment too
    4251 String  STR This is the string that forms the value #comment
    4252 
    4253  # This is a comment line and is to be ignored
    4254 boolean     BOOL    T # The value of `boolean' is `true'
    4255 
    4256 @primes U8  2,3 5 7,11,13 17 #   These are prime numbers
    4257 
    4258 comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique
    4259 comment STR This
    4260 comment STR     is
    4261 comment STR       a
    4262 comment STR        non-unique
    4263 comment STR                  key
    4264 Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored
    4265 \end{verbatim}
    4266 
    4267 Of course, a real configuration file should look much nicer to humans
    4268 than the above example, but PSLib must be able to parse such ugly
    4269 files.
    4270 
    4271 We extend \code{psMetadataParseConfig} to allow a modest tree
    4272 structure by defining a reserved keyword \code{TYPE}.  Any line in the
    4273 config file which starts with the word \code{TYPE} shall be
    4274 interpretted as defining a new valid type.  The defined type name
    4275 follows the word \code{TYPE}, and is in turn followed by an arbitrary
    4276 number of words.  These words are to be interpreted as the names of an
    4277 embedded \code{psMetadata} entry, where the values are given on any
    4278 line which (following the \code{TYPE} definition) employs the new type
    4279 name.  For example, a new type may be defined as:
    4280 \begin{verbatim}
    4281 TYPE      CELL   EXTNAME   BIASSEC  CHIP
    4282 CELL.00   CELL   CCD00     BSEC-00  CHIP.00
    4283 CELL.01   CELL   CCD01     BSEC-01  CHIP.00
    4284 \end{verbatim}
    4285 
    4286 When \code{psMetadataParseConfig} encounters the \code{TYPE} line, it
    4287 should construct a \code{psMetadata} container and fill it with
    4288 \code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP},
    4289 with type \code{PS_META_STR}, but data allocated.  When it next
    4290 encounters an entry of type \code{CELL}, it should then use the given
    4291 name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy
    4292 the \code{psMetadata} data onto the \code{psMetadataItem.data.md}
    4293 entry, filling in the values from the rest of the line (\code{CCD00,
    4294 BSEC-00, CHIP.00}).  This hierarchical structure is illustrated in
    4295 Figure~\ref{fig:metadata}.
    4296 
    4297 We further extend \code{psMetadataParseConfig} to allow the definition
    4298 of a \code{psMetadata} entry using a sequence of successive lines to
    4299 define the values of the \code{psMetadataItem} entries.  The initial
    4300 line defines the new \code{psMetadata} entry and its name.  The
    4301 following lines have the same format as the other metadata config file
    4302 entries.  The sequence is terminated with a line with a single word
    4303 \code{END}.  For example, a metadata entry may be defined as:
    4304 \begin{verbatim}
    4305 CELL      METADATA
    4306  EXTNAME   STR   CCD00
    4307  BIASSEC   STR   BSEC-00
    4308  CHIP      STR   CHIP.00
    4309  NCELL     S32   24
    4310 END
    4311 \end{verbatim}
    4312 
    4313 A series of test inputs is contained in
    4314 \S\ref{sec:configtest}.
    4315 
    4316 \subsection{XML Functions}
    4317 
    4318 Within Pan-STARRS, we will use XML documents as a transport mechanism
    4319 to carry data between programs and between IPP and other subsystems.
    4320 Configuration information may be stored as well as XML documents, in
    4321 addition to the text format discussed in the discussion on Metadata.
    4322 XML is an extremely variable document format, and it is not currently
    4323 the intention of PSLib to provide a complete PSLib version of XML
    4324 operations.  Rather, a limited number of operations are defined to
    4325 convert specific data structures to an appropriate XML document.  To
    4326 maximize the simplicity of the XML APIs, we will use the convention
    4327 that a single XML document to be parsed by PSLib shall contain only a
    4328 single data structure.  Each of the XML APIs therefore take as input a
    4329 reference to a complete XML document and return a PSLib data
    4330 structure, or take a PSLib data structure and return a complete XML
    4331 document.
    4332 
    4333 We start by defining a PSLib wrapper type which is a pointer to an XML
    4334 document in memory.  We wrap the \code{libxml2} version of an XML
    4335 document pointer for now:
    4336 \begin{verbatim}
    4337 typedef xmlDocPtr psXMLDoc;
    4338 void psXMLDocFree(psXMLDoc *doc);
    4339 \end{verbatim}
    4340 
    4341 The next pair of functions convert a \code{psMetadata} data structure
    4342 to a complete \code{psXMLDoc} (in memory) and vice versa:
    4343 \begin{verbatim}
    4344 psXMLDoc *psMetadataToXMLDoc(const psMetadata *metadata);
    4345 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc);
    4346 \end{verbatim}
    4347 
    4348 The next pair of functions loads the data in a named file into a
    4349 complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc}
    4350 to a named file:
    4351 \begin{verbatim}
    4352 psXMLDoc *psXMLParseFile(const char *filename);
    4353 int psXMLDocToFile(const psXMLDoc *doc, const char *filename);
    4354 \end{verbatim}
    4355 
    4356 The next pair of functions accepts a block of memory and parses it
    4357 into a complete \code{psXMLDoc} (also in memory), and vice versa:
    4358 \begin{verbatim}
    4359 psXMLDoc *psXMLParseMemory(const char *buffer, const int size);
    4360 int psXMLDocToMemory(const psXMLDoc *doc, char *buffer);
    4361 \end{verbatim}
    4362 
    4363 The next pair of functions read from and write to a file descriptor.
    4364 The first converts the imcoming data to a complete \code{psXMLDoc}
    4365 (also in memory), the second writes the \code{psXMLDoc} to the file
    4366 descriptor:
    4367 \begin{verbatim}
    4368 psXMLDoc *psXMLParseFD(int fd);
    4369 int psXMLDocToFD(const psXMLDoc *doc, int fd);
    4370 \end{verbatim}
    4371 
    4372 \subsection{Database Functions}
    4373 
    4374 Many of the applications that PSLib will be used for will require
    4375 access to a simple relational database.  PSLib includes generic
    4376 database-independent interface mechanisms as part of its API set.  The
    4377 most important aspect of PSLib's database support is to abstract as
    4378 much database specific complexity as is feasible.  As almost all RDBMS
    4379 provide at least a simple transactional model, commit and rollback
    4380 support should be provided.
    4381 
    4382 Currently, only support for MySQL 4.1.x is required but other backends
    4383 may be added as options in the future.  As a particular example which
    4384 has implications for the database interaction model, support for
    4385 SQLite may be required in the future.  Currently, the choice of
    4386 backend database interface may be made as a compile option.  Details
    4387 of the specified APIs in the discussion below refer to the relevant
    4388 MySQL functions.
    4389 
    4390 Database errors must be trapped and placed onto the psError stack.
    4391 The complete error message should be retrieved with the database's
    4392 error function.
    4393 
    4394 \subsubsection{Managing the Database Connection}
    4395 
    4396 We specify a database handle which carries the information about the
    4397 database connection:
    4398 
    4399 \begin{verbatim}
    4400     typedef struct {
    4401         MYSQL *mysql;
    4402     } psDB;
    4403 \end{verbatim}
    4404 
    4405 The following collection of functions provides basic database functionality:
    4406 
    4407 \begin{verbatim}
    4408     // wraps mysql_init() & mysql_real_connect()
    4409     psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname);
    4410 
    4411     // wraps mysql_close()
    4412     void psDBCleanup(psDB *dbh);
    4413 
    4414     // wraps mysql_create_db()
    4415     bool psDBCreate(psDB *dbh, const char *dbname);
    4416 
    4417     // wraps mysql_select_db()
    4418     bool psDBChange(psDB *dbh, const char *dbname);
    4419 
    4420     // wraps mysql_drop_db()
    4421     bool psDBDrop(psDB *dbh, const char *dbname);
    4422 \end{verbatim}
    4423 
    4424 For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and
    4425 \code{mysql_real_connect()} in order to initialize a psDB structure and
    4426 establish a database connection.  A null pointer should be returned on
    4427 failure.
    4428 
    4429 When implementing support for SQLite, or other DB which is purely
    4430 file-based, the \code{host}, \code{user}, and \code{passwd} arguments
    4431 would be ignored while \code{dbname} would specify the path to the
    4432 SQLite db file.
    4433 
    4434 \subsubsection{Interacting with Database Tables}
    4435 
    4436 The functions in this section perform high level interactions with the
    4437 database tables.  All of them should behave ``atomically'' with
    4438 respect to the state of the database.  Specifically, all interactions
    4439 with the database should be done as a part of a transaction that is
    4440 rolled-back on failure and committed only after all queries used by
    4441 the API have been run.  In general, this API set attempts to treat a
    4442 database table as a 2D matrix where columns can be represented by a
    4443 \code{psVector} and rows as a \code{psMetadata} type.  A
    4444 \code{psMetadata} collection is also used to define the columns of a
    4445 table and as part of the query restrictions.
    4446 
    4447 \begin{verbatim}
    4448     bool psDBCreateTable(psDB *dbh, const char *tableName, psMetadata *md);
    4449 \end{verbatim}
    4450 
    4451 This function generates and executes the SQL needed to create a table
    4452 named \code{tableName}, with the column names and datatypes as
    4453 described in \code{md}.  Each data item in the \code{psMetadata}
    4454 collection represents a single table field.  The name of the field is
    4455 given by the name of the \code{psMetadataItem} and the data type is
    4456 give by the \code{psMetadataItem.type} and \code{psMetadataItem.ptype}
    4457 entries.  A lookup table should be used to convert from PSLib types
    4458 into MySQL compatible SQL data types.  For example, a
    4459 \code{PS_META_STR} would map to an SQL99 varchar.  If the value of
    4460 \code{type} is \code{PS_META_STR} then the \code{psMetadataItem.data}
    4461 element is set to a string with the length for the field written as a
    4462 text string.  The value of the \code{psMetadataItem.data} element is
    4463 unused for the \code{PS_META_PRIMITIVE} types.  Other metadata types
    4464 beyond \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed
    4465 in a table definition metadata collection.
    4466 
    4467 Database indexes can be specified setting the \code{comment} field to
    4468 ``\code{Primary Key}'' or ``\code{Key}''.  Comment are otherwise
    4469 ignored.
    4470 
    4471 \begin{verbatim}
    4472     bool psDBDropTable(psDB *dbh, const char *tableName);
    4473 \end{verbatim}
    4474 
    4475 This function deletes the specified table.
    4476 
    4477 \begin{verbatim}
    4478     psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, const psU64 limit);
    4479     psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType pType, const psU64 limit);
    4480 \end{verbatim}
    4481 
    4482 These functions generates and executes the SQL needed to select an entire
    4483 column from a table or up to \code{limit} rows from it.  If \code{limit} is 0,
    4484 the entire range is returned.  The database response is processed and a
    4485 \code{psArray} of strings is returned.  The Num version of the function returns
    4486 the data in a \code{psVector}, data cast to \code{pType}.  It returns an error
    4487 (NULL) if the requested field is not a numerical type.
    4488 
    4489 \begin{verbatim}
    4490     psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, const psU64 limit);
    4491 \end{verbatim}
    4492 
    4493 This function returns rows from the specified table which match
    4494 the restrictions given by \code{where}.  The restrictions are
    4495 specified as field / value pairs.  The \code{psMetadata} collection
    4496 where must consist of valid database fields, though the database query
    4497 checking functions may be used to validate the fields as part of the
    4498 query.  If \code{where} is \code{NULL}, then there are no restrictions
    4499 on the rows selected.  The selected rows are returned as a
    4500 \code{psArray} of \code{psMetadata} values, one per row.
    4501 
    4502 \begin{verbatim}
    4503     bool psDBInsertOneRow(psDB *dbh, const char *tableName, psMetadata *row);
    4504 \end{verbatim}
    4505 
    4506 Insert the data from \code{row} into \code{tableName}.  It should be noted in
    4507 the API reference that if fields are specified in \code{row} that do not exist
    4508 in \code{tablename}, the insert will fail.
    4509 
    4510 \begin{verbatim}
    4511     bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet);
    4512 \end{verbatim}
    4513 
    4514 Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once
    4515 and is atomic for the complete set of rows.
    4516 
    4517 \begin{verbatim}
    4518     psArray *psDBDumpRows(psDB *dbh, const char *tableName);
    4519 \end{verbatim}
    4520 
    4521 Fetch all rows as an psArray of psMetadata.
    4522 
    4523 \begin{verbatim}
    4524     psMetadata *psDBDumpCols(psDB *dbh, const char *tableName);
    4525 \end{verbatim}
    4526 
    4527 Fetch all columns, as either a psVector or a psArray depnding on whether or not
    4528 the column is numeric, and return them in a psMetadata structure where
    4529 psMetadataItem.name contains the column's name.
    4530 
    4531 \begin{verbatim}
    4532     psS64 psDBUpdateRows(psDB *dbh, const char *tableName, psMetadata *where, psMetadata *values);
    4533 \end{verbatim}
    4534 
    4535 Update the columns contained in \code{values} in the row(s) that have a field
    4536 with the value indicated by \code{where} (note that this is only allows very
    4537 limited use of SQL99's ``where'' semantics).  The number of rows modified is
    4538 returned.  A negative value is return to indicate an error. If there are
    4539 multiple psMetadataItems in \code{where} then each item should be considered as
    4540 an additional constraint.  e.g.  ``where foo = x and where bar = y''
    4541 
    4542 \begin{verbatim}
    4543     psS64 psDBDeleteRows(psDB *dbh, const char *tableName, psMetadata *where);
    4544 \end{verbatim}
    4545 
    4546 Delete the rows that are matched by \code{where} using the same semantics for
    4547 \code{where} as in psDBUpdateRow().  A negative value is returned to indicate an
    4548 error.
    4549 
    4550 \subsection{FITS I/O Functions}
    4551 
    4552 We need a variety of I/O functions between the disk and certain of our
    4553 PSLib data structures.  We need the ability to access FITS headers,
    4554 images and tables (both ASCII and Binary).  We define here the FITS
    4555 I/O functions, all of which are currently specified as wrappers to
    4556 functions within CFITSIO.  CFITSIO provides a wide range of utilities
    4557 which we do not feel are particularly appropriate as part of a generic
    4558 I/O library, such as assumptions about names which change the data
    4559 interpretation, etc.  We are defining our calls to avoid the hidden
    4560 'features'.  The CFITSIO functions which are wrapped should in general
    4561 be the most basic versions.
    4562 
    4563 \begin{verbatim}
    4564 typedef struct {
    4565     fitsfile fd;
    4566 } psFits;
    4567 \end{verbatim}
    4568 We begin by defining a datatype to wrap the CFITSIO \code{fitsfile}
    4569 structure.  This is necessary to allow repeated access to the data in
    4570 a file without multiple open commands (which are expensive).
    4571 
    4572 \subsubsection{FITS File Manipulations}
    4573 
    4574 \begin{verbatim}
    4575 psFits *psFitsAlloc(const char *filename);
    4576 \end{verbatim}
    4577 
    4578 Opens a FITS file at positions the pointer to the PHU.
    4579 
    4580 \begin{verbatim}
    4581 bool psFitsMoveExtName(psFits *fits, const char *extname);
    4582 \end{verbatim}
    4583 
    4584 Positions the pointer to the beginning of the specified
    4585 \code{extname}.  If the \code{extname} does not exist, the function
    4586 shall fail. 
    4587 
    4588 \begin{verbatim}
    4589 bool psFitsMoveExtNum(psFits* fits, int extnum, bool relative);
    4590 \end{verbatim}
    4591 
    4592 Moves the pointer to the beginning of the specified HDU number.  If
    4593 \code{relative} is TRUE, \code{extnum} represents the number of HDUs
    4594 relative to the current HDU.  The PHU is entry number 0, while the
    4595 extended data segments start at number 1.
    4596 
    4597 \begin{verbatim}
    4598 int psFitsGetExtNum(psFits* fits);
    4599 \end{verbatim}
    4600 
    4601 Returns the current HDU number (i.e., file position). 
    4602 
    4603 \begin{verbatim}
    4604 int psFitsGetSize(psFits* fits);
    4605 \end{verbatim}
    4606 
    4607 Returns the number of HDUs in the file.
    4608 
    4609 \begin{verbatim}
    4610 psFitsType psFitsGetExtType(psFits* fits);
    4611 \end{verbatim}
    4612 
    4613 Gets the current HDU's type (table or image).
    4614 
    4615 \subsubsection{FITS Header I/O Functions}
    4616 
    4617 \begin{verbatim}
    4618 psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits);
    4619 \end{verbatim}
    4620 Read header data into a \code{psMetadata} structure.  The data is read
    4621 from the current HDU pointed at by the \code{psFits *fits} entry.  If
    4622 \code{out} is \code{NULL}, a new psMetadata is created.
    4623 
    4624 \begin{verbatim}
    4625 psMetadata *psFitsReadHeaderSet (psFits *fits);
    4626 \end{verbatim}
    4627 Load a complete set of headers from the \code{psFits} file pointer.
    4628 This function loads the headers from all extensions into a
    4629 \code{psMetadata} collection, each entry of which is a pointer to a
    4630 \code{psMetadata} structure containing the header data.  The metadata
    4631 entry names are the \code{EXTNAME} values for each header (with the
    4632 value of \code{PHU} for the primary header unit).  At the start of the
    4633 operation, the file pointer is rewound to the beginning of the file.
    4634 At the end, it is positioned where it started when the function was
    4635 called.
    4636 
    4637 \begin{verbatim}
    4638 bool psFitsWriteHeader(psMetadata *output, const psFits *fits);
    4639 \end{verbatim}
    4640 Write metadata into the header of a FITS image file.  The header is
    4641 written at the current HDU.
    4642 
    4643 \subsubsection{FITS Image I/O Functions}
    4644 
    4645 \begin{verbatim}
    4646 psImage *psFitsReadImage(psImage *output, psFits *fits, psRegion region, int z);
    4647 \end{verbatim}
    4648 Read an image or subimage from the \code{psFits} file pointer.  This
    4649 function is a wrapper to the CFITSIO library function.  The input
    4650 parameters allow a full image or a subimage to be read.  The region to
    4651 be read is specified by \code{region}.  A negative value for either of
    4652 \code{region.x1} or \code{region.y1} specifies the size of the region
    4653 to be read counting down from the end of the array. 
    4654 
    4655 If the native image is a cube, the value of z specifies the requested
    4656 slice of the image.  This function must call \code{psError} and return
    4657 \code{NULL} if any of the specified parameters are out of range for
    4658 the data in the image file, or if the image on disk is zero- or
    4659 one-dimensional.  This function need only read images of the native
    4660 FITS image types (\code{psU8}, \code{psS16}, \code{psS32},
    4661 \code{psF32}, \code{psF64}).  The user is expected to convert the data
    4662 type as needed with \code{psImageCopy}.
    4663  
    4664 \begin{verbatim}
    4665 bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z);
    4666 \end{verbatim}
    4667 \tbd{we have discussed this as the alternate name}
    4668 Write an image section to the open \code{psFits} file pointer.  This
    4669 operation may write a portion of an image over the existing bytes of
    4670 an existing image.  Care must be taken to interpret \code{region},
    4671 which specified the output pixels to be written / over-written.  If
    4672 the combination of \code{region} and the size of \code{psImage *input}
    4673 implies writing pixels outside the existing data area of the image,
    4674 the function shall return an error (ie, if \code{region.x0 + image.nx
    4675 >= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >=
    4676 NAXIS3}).  This function will only write images of the native FITS
    4677 image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32},
    4678 \code{psF64}).  The user is expected to convert the data type as
    4679 needed with \code{psImageCopy}.  The return value must be 0 for a
    4680 successful operation and 1 for an error.
    4681 
    4682 \begin{verbatim}
    4683 bool psFitsWriteImage(psFits *fits, psMetadata *header, const psImage *input, int depth);
    4684 \end{verbatim}
    4685 Create a new image based on the dimensions specified for the image and
    4686 the requested depth.  The header and image data segments are written
    4687 in the file at the current position of the \code{psFits} pointer.
    4688 This function will only write images of the native FITS image types
    4689 (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}).
    4690 The user is expected to convert the data type as needed with
    4691 \code{psImageCopy}.  The return value must be 0 for a successful
    4692 operation and 1 for an error.
    4693 
    4694 \subsubsection{FITS Table I/O Functions}
    4695 
    4696 \begin{verbatim}
    4697 psMetadata *psFitsReadTableRow (psFits *fits, int row);
    4698 \end{verbatim}
    4699 This function reads a single row of the table in the extension pointed
    4700 at by the \code{psFits} file pointer.  The row number to be read is
    4701 given by \code{row}.  The result is returned as a \code{psMetadata}
    4702 collection with elements of the apporpriate types and keys
    4703 corresponding to the table column names.  The function must apply the
    4704 needed byte-swapping on the data in the row based on the description
    4705 of the table data in the table header.  \tbr{we may need to be more
    4706 flexible here: if we call this function repeatedly, it would be more
    4707 efficient to pass the corresponding header or keep it somewhere (and
    4708 the file pointer location, for that matter).}
    4709 
    4710 \begin{verbatim}
    4711 void *psFitsReadTableRowRaw (int *nBytes, psFits *fits, int row);
    4712 \end{verbatim}
    4713 This function reads a single row of the table in the extension pointed
    4714 at by the \code{psFits} file pointer.  The row number to be read is
    4715 given by \code{row}.  The result is returned as collection of
    4716 \code{nBytes} bytes allocated by the function.  The function must
    4717 apply the needed byte-swapping on the data in the row based on the
    4718 description of the table data in the table header.  \tbr{we may need
    4719 to be more flexible here: if we call this function repeatedly, it
    4720 would be more efficient to pass the corresponding header or keep it
    4721 somewhere (and the file pointer location, for that matter).}
    4722 
    4723 \begin{verbatim}
    4724 psArray *psFitsReadTableColumn (psFits *fits, char *colname);
    4725 \end{verbatim}
    4726 This function reads a single column of the table in the extension
    4727 pointed at by the \code{psFits} file pointer.  The column is specified
    4728 by the FITS table column key given by \code{row}.  The result is
    4729 returned as a \code{psArray}, with the data from one row of the table
    4730 column per array element.
    4731 
    4732 \begin{verbatim}
    4733 psVector *psFitsReadTableColumnNum (psFits *fits, char *colname);
    4734 \end{verbatim}
    4735 This function reads a single column of the table in the extension
    4736 pointed at by the \code{psFits} file pointer.  The column is specified
    4737 by the FITS table column key given by \code{row} and must be of a
    4738 numeric data type.  The result is returned as a \code{psVector} of the
    4739 appropriate data type, with the data from one row of the table column
    4740 per array element.
    4741 
    4742 \begin{verbatim}
    4743 psArray *psFitsReadTableRaw (int *nBytes, psFits *fits);
    4744 \end{verbatim}
    4745 This function reads the entire data block from a table into the a
    4746 \code{psArray}, with one element of the array per row.  The number of
    4747 bytes per row is returned in \code{nBytes}.  The function must apply
    4748 the needed byte-swapping on the data in each row based on the
    4749 description of the table data in the table header.
    4750 
    4751 \begin{verbatim}
    4752 psArray *psFitsReadTable (psFits *fits);
    4753 \end{verbatim}
    4754 This function reads the entire data block from a table into the a
    4755 \code{psArray}, with one element of the array per row.  Each row is
    4756 stored as a \code{psMetadata} collection as described above for
    4757 \code{psFitsReadTableRow}.
    4758 
    4759 \begin{verbatim}
    4760 bool psFitsWriteTable(psFits* fits, psMetadata *header, psArray* table);
    4761 \end{verbatim}
    4762 Accepts a \code{psArray} of \code{psMetadata} and writes it to the
    4763 current HDU.  If the current HDU is not a table type, this will fail
    4764 and return FALSE.
    4765 
    4766 \begin{verbatim}
    4767 bool psFitsUpdateTable(psFits* fits, psMetadata *header, psMetadata* data, int row);
    4768 \end{verbatim}
    4769 Writes the \code{psMetadata} data to a FITS table at the specified row
    4770 in the current HDU.  If the current HDU is not a table type, this will
    4771 fail and return FALSE. 
    4772 
    4773 \subsection{Detector and Sky Coordinates}
     4847\subsection{Linear and Spherical Coordinates}
    47744848
    47754849Both detector and sky positions will be used extensively in the IPP.
    47764850The first are linear coordinates which conform to Euclidean geometry
    4777 while the second are angular coordinates for which additional care
    4778 must often be taken.  We put these into two structures, \code{psPlane}
    4779 and \code{psSphere}, respectively.  Partitioning these two will enable
    4780 error-checking.
     4851while the second are angular coordinates which define a position on
     4852the sphere of the sky.  We put these into two structures,
     4853\code{psPlane} and \code{psSphere}, respectively.  Partitioning these
     4854two will enable error-checking.  An alternative representation for
     4855angular positions is the 3-D unit vector.  These are used in
     4856particular as part of spherical rotation calculations.  We define
     4857\code{psCube} to represent such an element.
    47814858%
    47824859\begin{verbatim}
     
    47944871    double dErr;                        ///< Error in Dec
    47954872} psSphere;
     4873
     4874typedef struct {
     4875    double x;                           ///< cos (DEC) cos (RA)
     4876    double y;                           ///< cos (DEC) sin (RA)
     4877    double z;                           ///< sin (DEC)
     4878    double xErr;                        ///< Error in x
     4879    double yErr;                        ///< Error in y
     4880    double zErr;                        ///< Error in z
     4881} psCube;
    47964882\end{verbatim}
    47974883
     
    48184904Constructors for these are straight-forward:
    48194905\begin{verbatim}
    4820 psPlane *psPlaneAlloc(void);
     4906psPlane  *psPlaneAlloc(void);
    48214907psSphere *psSphereAlloc(void);
     4908psCube   *psCubeAlloc(void);
    48224909\end{verbatim}
    48234910Initialization of the structures is not necessary.
     
    49855072\code{NULL}, the function shall generate an error and return
    49865073\code{NULL}.
    4987 
    4988 
    4989 \subsubsection{Celestial Coordinate Conversions}
    4990 
    4991 We need to be able to convert between ICRS, Galactic and Ecliptic
    4992 coordinates, and potentially between arbitrary spherical coordinate
    4993 systems.  All of these basic spherical transformations represent
    4994 rotations of the spherical coordinate reference.  We specify a general
    4995 transformation function which takes a structure,
    4996 \code{psSphereTransform}, defining the transformation between two
    4997 spherical coordinate systems (the structure contains the sines and
    4998 cosines of the angles involved so as to minimize computation time for
    4999 repeated transformations).  We also define a function to generate
    5000 \code{psSphereTransform}, based on the three angles
    5001 describing the location of the pole and the relative equatorial
    5002 rotations of the two systems.  We also specify special functions to
    5003 return the \code{psSphereTransform} for transformations
    5004 between standard coordinate systems.
    5005 
    5006 \begin{verbatim}
    5007 typedef struct {
    5008     double cosDeltaP;                 ///< Cosine of target pole latitude in the source system
    5009     double sinDeltaP;                 ///< Sine of target pole latitude in the source system
    5010     double alphaP;                    ///< Longitude of the target system pole in the source system
    5011     double phiP;                      ///< Longitude of the ascending node in the target system
    5012 } psSphereTransform;
    5013 \end{verbatim}
    5014 
    5015 The constructor is defined as follows:
    5016 \begin{verbatim}
    5017 psSphereTransform *psSphereTransformAlloc(double alphaP, double deltaP, double phiP);
    5018 \end{verbatim}
    5019 where \code{alphaP} and \code{deltaP} define the coordinates in the
    5020 input system of the north pole in the output system and \code{phiP}
    5021 defines the longitude in the input system of the equatorial
    5022 intersection between the two systems (e.g, the first point of Ares).
    5023 The constructor must calculate the sines and cosines above.
    5024 
    5025 Spherical coordinates may be transformed by providing the
    5026 transformation and the coordinate in the input system to
    5027 \code{psSphereTransform}:
    5028 \begin{verbatim}
    5029 psSphere *psSphereTransformApply(psSphere *out,
    5030                                  const psSphereTransform *transform,
    5031                                  const psSphere *coord);
    5032 \end{verbatim}
    5033 
    5034 The following functions simply return the appropriate
    5035 \code{psSphereTransform} to convert between predefined spherical
    5036 coordinate systems (i.e., ICRS, Ecliptic and Galactic).  These are
    5037 constructors as well as the above \code{psSphereTransformAlloc}.
    5038 %
    5039 \begin{verbatim}
    5040 psSphereTransform *psSphereTransformICRSToEcliptic(psTime *time);
    5041 psSphereTransform *psSphereTransformEclipticToICRS(psTime *time);
    5042 psSphereTransform *psSphereTransformICRSToGalactic(void);
    5043 psSphereTransform *psSphereTransformGalacticToICRS(void);
    5044 \end{verbatim}
    5045 
    5046 We also require the ability to precess coordinates from one equinox to
    5047 another.
    5048 
    5049 \begin{verbatim}
    5050 psSphere *psSpherePrecess(psSphere *coords, const psTime *fromTime, const psTime *toTime);
    5051 \end{verbatim}
    5052 
    5053 Given coordinates, \code{coords}, with equinox for \code{fromTime},
    5054 the coordinates are precessed to equinox for \code{toTime}.  The
    5055 \code{coords} are modified in-place.  Equinoxes shall be Julian
    5056 equinoxes (as opposed to Bessellian).
    5057 
    5058 \subsubsection{Projections}
    5059 
    5060 We require functions to convert between spherical and linear
    5061 coordinate systems based on a variety of projections.  The required
    5062 projections include:
    5063 \begin{itemize}
    5064 \item TAN
    5065 \item SIN
    5066 \item AIT
    5067 \item PAR
    5068 \end{itemize}
    5069 
    5070 We specify the following structure \code{psProjection} to define the
    5071 parameters of the projection:
    5072 \begin{verbatim}
    5073 typedef struct {
    5074     double R, D;                         ///< coordinates of projection center
    5075     double Xs, Ys;                       ///< plate-scale in X and Y directions
    5076     psProjectionType type;               ///< projection type
    5077 } psProjection;
    5078 \end{verbatim}
    5079 
    5080 The projection type is defined by the following enumerated type \code{psProjectionType}:
    5081 \begin{verbatim}
    5082 typedef enum {                          ///< type of val is:
    5083     PS_PROJ_TAN,                        ///< Tangent projection
    5084     PS_PROJ_SIN,                        ///< Sine projection
    5085     PS_PROJ_AIT,                        ///< Aitoff projection
    5086     PS_PROJ_PAR,                        ///< Par projection
    5087     PS_PROJ_NTYPE                       ///< Number of types; must be last
    5088 } psProjectionType;
    5089 \end{verbatim}
    5090 
    5091 The constructor is straight-forward:
    5092 \begin{verbatim}
    5093 psProjection *psProjectionAlloc(double R, double D, double Xs, double Ys, psProjectionType type);
    5094 \end{verbatim}
    5095 
    5096 The following functions will project and deproject (respectively)
    5097 spherical coordinates:
    5098 
    5099 \begin{verbatim}
    5100 psPlane  *psProject(const psSphere *coord, const psProjection *projection);
    5101 psSphere *psDeproject(const psPlane *coord, const psProjection *projection);
    5102 \end{verbatim}
    5103 
    5104 \subsubsection{Offsets}
    5105 We require a function to calculate the offset between two positions on
    5106 the sky, as well as a function to apply an offset to a position.  The
    5107 first determines the offset (RA,Dec) on the sky between two positions.
    5108 The second applies the given offset to the coordinate.  Both an offset
    5109 mode and an offset unit may be defined.  The mode may be either
    5110 \code{PS_SPHERICAL}, in which case the specified offset corresponds to
    5111 an offset in angles, or it may be \code{PS_LINEAR}, in which case the
    5112 offset corresponds to a linear offset in a local projection.  The
    5113 offset unit may be in one of \code{PS_ARCSEC}, \code{PS_ARCMIN},
    5114 \code{PS_DEGREE}, and \code{PS_RADIAN}, which specifies the units of
    5115 the offset only.
    5116 
    5117 \begin{verbatim}
    5118 psSphere *psSphereGetOffset(const psSphere *position1,
    5119                             const psSphere *position2,
    5120                             psSphereOffsetMode mode,
    5121                             psSphereOffsetUnit unit);
    5122 
    5123 psSphere *psSphereSetOffset(const psSphere *position,
    5124                             const psSphere *offset,
    5125                             psSphereOffsetMode mode,
    5126                             psSphereOffsetUnit unit);
    5127 
    5128 typedef enum {
    5129     PS_SPHERICAL;                       ///< Offset on a sphere
    5130     PS_LINEAR;                          ///< Linear offset
    5131 } psSphereOffsetMode;
    5132 
    5133 typedef enum {
    5134     PS_ARCSEC;                          ///< Arcseconds
    5135     PS_ARCMIN;                          ///< Arcminutes
    5136     PS_DEGREE;                          ///< Degrees
    5137     PS_RADIAN;                          ///< Radians
    5138 } psSphereOffsetUnit;
    5139 \end{verbatim}
    5140 Note that these should propagate the errors appropriately.
    5141 
    5142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5143 
    5144 %%% Astronomical Images and Astrometry
    5145 \include{psLibSDRS_Astrom}
    5146 
    5147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5148 
    5149 \subsection{Pixel Lists}
    5150 
    5151 Usually an image mask is the best way to carry information about what
    5152 pixels mean what.  However, in the case where the number of pixels in
    5153 which we are interested is limited, it is more efficient to simply
    5154 carry a list of pixels.  An example of this is in the image
    5155 combination code, where we want to perform an operation on a
    5156 relatively small fraction of pixels, and it is inefficient to go
    5157 through an entire mask image checking each pixel.
    5158 
    5159 \begin{verbatim}
    5160 typedef struct {
    5161     psVector *x;                        // x coordinate
    5162     psVector *y;                        // y coordinate
    5163 } psPixels;
    5164 \end{verbatim}
    5165 
    5166 Of course, the size of each of the vectors should match.  In the event
    5167 that they do not match, any function which detects the problem shall
    5168 generate a warning and use the size of the shorter of the vectors as
    5169 the size.  The order in which the pixels are kept is not considered
    5170 important.
    5171 
    5172 \begin{verbatim}
    5173 psImage *psPixelsToMask(psImage *out, const psPixels *pixels, const psRegion *region, unsigned int maskVal);
    5174 psPixels *psMaskToPixels(psPixels *out, const psImage *mask, unsigned int maskVal);
    5175 \end{verbatim}
    5176 
    5177 \code{psPixelsToMask} shall return an image of type U8 with the
    5178 \code{pixels} lying within the specified \code{region} set to the
    5179 \code{maskVal}.  The \code{out} image shall be modified if supplied,
    5180 or allocated and returned if \code{NULL}.  The size of the output
    5181 image shall be \code{region->x1 - region->x0} by \code{region->y1 -
    5182 region->y0}, with \code{out->x0 = region->x0} and \code{out->y0 =
    5183 region->y0}.  In the event that either of \code{pixels} or
    5184 \code{region} are \code{NULL}, the function shall generate an error
    5185 and return \code{NULL}.
    5186 
    5187 \code{psMaskToPixels} shall return a \code{psPixels} consisting of the
    5188 coordinates in the \code{mask} that match the \code{maskVal}.  The
    5189 \code{out} pixel list shall be modified if supplied, or allocated and
    5190 returned if \code{NULL}.  In hte event that \code{mask} is
    5191 \code{NULL}, the function shall generate an error and return
    5192 \code{NULL}.
    5193 
    5194 \begin{verbatim}
    5195 psPixels *psPixelsConcatenate(psPixels *out, const psPixels *pixels);
    5196 \end{verbatim}
    5197 
    5198 \code{psPixelsConcatenate} shall concatenate \code{pixels} onto
    5199 \code{out}.  In the event that \code{out} is \code{NULL}, a new
    5200 \code{psPixels} shall be allocated, and the contents of \code{pixels}
    5201 simply copied in.  If \code{pixels} is \code{NULL}, the function shall
    5202 generate an error and return \code{NULL}.  The function shall take
    5203 care to ensure that there are no duplicate pixels in \code{out} (since
    5204 the order in which the pixels are stored is not important, the values
    5205 may be sorted, allowing the use of a faster algorithm than a linear
    5206 scan).
    52075074
    52085075\begin{verbatim}
     
    52285095and return \code{NULL}.
    52295096
    5230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     5097\subsubsection{Spherical Rotations}
     5098
     5099Spherical rotations represent coordinate transformation in 3-D, as
     5100well as the effects of precession and nutation.  We need spherical
     5101rotatations to convert between ICRS, Galactic and Ecliptic
     5102coordinates, and to determine Alt-Az coordinates for sources.  All of
     5103these basic spherical transformations represent rotations of the
     5104spherical coordinate reference.  We specify a general transformation
     5105function which takes a structure, \code{psSphereRot}, defining the
     5106transformation between two spherical coordinate systems.  The
     5107structure contains the elements of a quaternion to represent the
     5108spherical rotational.  We define two allocators for
     5109\code{psSphereRot}, one which defines the rotation in terms of the
     5110coordinate of the pole and the rotation about that pole.  The other
     5111defines the rotation from the elements of the quaternion.  We also
     5112specify functions to manipulate \code{psSphereRot} in several useful
     5113way.
     5114
     5115\begin{verbatim}
     5116typedef struct {
     5117    double q0;
     5118    double q1;
     5119    double q2;
     5120    double q3;
     5121} psSphereRot;
     5122\end{verbatim}
     5123
     5124The constructor is defined as follows:
     5125\begin{verbatim}
     5126psSphereRot *psSphereRotAlloc(double alphaP, double deltaP, double phiP);
     5127\end{verbatim}
     5128where \code{alphaP} and \code{deltaP} define the coordinates in the
     5129input system of the axis of rotation (the north pole of the output
     5130system), while \code{phiP} defines the rotation about that pole.  This
     5131last angle is also equal to 270\degree - $\phi_a$, where $\phi_a$ is
     5132the longitude in the output system of the ascending node (equatorial
     5133intersection between the two systems, e.g, the first point of Ares).
     5134
     5135The \code{psSphereRot} may also be constructed by supplying the
     5136elements of the quaternion to the following function:
     5137\begin{verbatim}
     5138psSphereRot *psSphereRotQuat(double q0, double q1, double q2, double q3);
     5139\end{verbatim}
     5140This function normalizes the quaternion, so the input elements need
     5141not be normalized.
     5142
     5143Spherical coordinates may be transformed by providing the
     5144transformation and the coordinate in the input system to
     5145\code{psSphereRot}.  The output pointer may be optionally supplied, or
     5146if \code{NULL}, is allocated by the function.
     5147
     5148\begin{verbatim}
     5149psSphere *psSphereRotApply(psSphere *out, const psSphereRot *transform, const psSphere *coord);
     5150\end{verbatim}
     5151
     5152The following function combines two rotations, to produce a single
     5153rotation which is the equivallent of applying the first rotation and
     5154then the second.  The output rotation may be supplied, or will be
     5155allocated if \code{NULL}.
     5156
     5157\begin{verbatim}
     5158psSphereRot *psSphereRotCombine(psSphereRot *out, psSphereRot *rot1, psSphereRot *rot2)
     5159\end{verbatim}
     5160
     5161The following function changes the given rotation to its inverse:
     5162
     5163\begin{verbatim}
     5164psSphereRot *psSphereRotInvert(psSphereRot *rot)
     5165\end{verbatim}
     5166
     5167The 3-vector representation of the angles (\code{psCube}) is needed to
     5168implement these functions, and is useful in other circumstances as
     5169well.  Two utility functions are provided to convert between the
     5170angular and 3-vector representations:
     5171\begin{verbatim}
     5172psSphere *psCubeToSphere(psCube *cube);
     5173psCube *psSphereToCube(psSphere *sphere);
     5174\end{verbatim}
     5175
     5176\subsubsection{Offsets}
     5177We require a function to calculate the offset between two positions on
     5178the sky, as well as a function to apply an offset to a position.  The
     5179first determines the offset (RA,Dec) on the sky between two positions.
     5180The second applies the given offset to the coordinate.  Both an offset
     5181mode and an offset unit may be defined.  The mode may be either
     5182\code{PS_SPHERICAL}, in which case the specified offset corresponds to
     5183an offset in angles, or it may be \code{PS_LINEAR}, in which case the
     5184offset corresponds to a linear offset in a local projection.  The
     5185offset unit may be in one of \code{PS_ARCSEC}, \code{PS_ARCMIN},
     5186\code{PS_DEGREE}, and \code{PS_RADIAN}, which specifies the units of
     5187the offset only.
     5188
     5189\begin{verbatim}
     5190psSphere *psSphereGetOffset(const psSphere *position1,
     5191                            const psSphere *position2,
     5192                            psSphereOffsetMode mode,
     5193                            psSphereOffsetUnit unit);
     5194
     5195psSphere *psSphereSetOffset(const psSphere *position,
     5196                            const psSphere *offset,
     5197                            psSphereOffsetMode mode,
     5198                            psSphereOffsetUnit unit);
     5199
     5200typedef enum {
     5201    PS_SPHERICAL;                       ///< Offset on a sphere
     5202    PS_LINEAR;                          ///< Linear offset
     5203} psSphereOffsetMode;
     5204
     5205typedef enum {
     5206    PS_ARCSEC;                          ///< Arcseconds
     5207    PS_ARCMIN;                          ///< Arcminutes
     5208    PS_DEGREE;                          ///< Degrees
     5209    PS_RADIAN;                          ///< Radians
     5210} psSphereOffsetUnit;
     5211\end{verbatim}
     5212Note that these should propagate the errors appropriately.
     5213
     5214\subsection{Celestial Coordinate Systems}
     5215
     5216The following functions simply return the appropriate
     5217\code{psSphereRot} to convert between predefined spherical
     5218coordinate systems (i.e., ICRS, Ecliptic and Galactic).  These are
     5219constructors as well as the above \code{psSphereRotAlloc}.
     5220%
     5221\begin{verbatim}
     5222psSphereRot *psSphereRotICRSToEcliptic(psTime *time);
     5223psSphereRot *psSphereRotEclipticToICRS(psTime *time);
     5224psSphereRot *psSphereRotICRSToGalactic(void);
     5225psSphereRot *psSphereRotGalacticToICRS(void);
     5226\end{verbatim}
     5227
     5228\subsection{Earth Orientation Calculations}
     5229
     5230One of the critical sets of calculations in astronomy is the sequence
     5231of steps needed to convert between the celestial coordinates of an
     5232object and the observed coordinates of the object.  This problem is
     5233best divided into two major components: transformation between the
     5234celestial sphere and coordinates relative to the surface of the solid
     5235earth, excluding the effects of the atmosphere, and compensation for
     5236the effects of the atmosphere.  In this section, we address the first
     5237of these two transformations: the Earth Orientation Calculations.
     5238
     5239The Earth Orientation Calculations are further subdivided into several
     5240steps, illustrated in Figure~\ref{CoordinateSystems} .  Celestial
     5241coordinates are defined in the International Celestial Reference
     5242System (ICRS), which has the solar barycenter as its reference
     5243position and velocity.  The next coordinate system is the Geocentric
     5244Celestial Reference System (GCRS), which uses the earth barycenter as
     5245a reference.  The transformation between these two includes the
     5246abberation due to the Earth's velocity, the parallax of the object,
     5247which depends on both the Earth's position and the distance to the
     5248object of interest, and the general relativistic correction for the
     5249bending of light as it approaches the Earth.
     5250
     5251The next set of transformations compenstate for the 3-D rotation of
     5252the Earth on various timescales, including the effects of precession,
     5253nutation, and simple solid-body rotation.  These calculations can be
     5254performed using different amounts of information for higher levels of
     5255precision.  Since the Earth's rotation is constantly affected by
     5256stochastic processes (weather, earthquakes, etc), these conversions
     5257are constantly modified by observations reported by authoratative
     5258sources such as the US Naval Observatory.  The target of this
     5259transformation is the International Terrestrial Reference System
     5260(ITRS), which is fixed with respect to the Earth's crust.  This
     5261transformation is subdivided into slow precesion and nutation
     5262(yielding the coordinate system CIP/CEO), followed by the Earth's
     5263rotation (yielding the coordinate system CIP/TEO), and finally
     5264corrections for the short-period motion of the Earth's pole. 
     5265
     5266\subsubsection{Transformation from ICRS to GCRS}
     5267
     5268\tbd{we need a function to construct the direction and speed elements
     5269  given the time}.
     5270
     5271\tbd{supply the velocity as an un-normalized 3 vector?}
     5272
     5273\paragraph{Aberration}
     5274The following function calculates the \code{apparent} position of a
     5275star, given its \code{actual} position and the velocity vector of the
     5276observer, represented as a speed and a direction:
     5277\begin{verbatim}
     5278psAberration(psSphere *apparent, psSphere *actual, psSphere direction, double speed);
     5279\end{verbatim}
     5280The \code{actual} and \code{apparent} positions are represented as
     5281\code{psSphere} entries, as is the \code{direction} of motion.  The
     5282speed in that direction is given in units of the speed of light.
     5283
     5284\paragraph{Gravitational Deflection}
     5285
     5286\paragraph{Parallax}
     5287
     5288\begin{verbatim}
     5289double psEOC_ParallaxFactor(psSphere *coords, psTime *time);
     5290\end{verbatim}
     5291Calculate the parallax factor for the given position and time.
     5292
     5293\subsubsection{Transformation from GCRS to ITRS}
     5294
     5295\paragraph{Precession/Nutation}
     5296
     5297The following routine calculates the components of the rotation
     5298between the CEO and GCRS frames, $X$, $Y$, and $s$, using to the
     5299IAU2000A precession \& nutation model:
     5300%
     5301\begin{verbatim}
     5302psSphere *psEOC_PrecessionModel(double *s, const psTime *time)
     5303\end{verbatim}
     5304%
     5305The input to this function is the desired \code{time}, which may be
     5306represented in any format other than UT1.  This routine must give
     5307results identical to the IERS XYS2000A subroutine within the limits of
     5308machine accuracy.
     5309
     5310The following function provides interpolated corrections to $X$ and
     5311$Y$ from the tables provided by the IERS, just as it does for UT1 and
     5312polar motion. 
     5313
     5314\begin{verbatim}
     5315psSphere *psEOC_GetPolarCorr(const psTime *time, psTimeBulletin bulletin);
     5316\end{verbatim}
     5317
     5318The polar correction is applied to the $X$ and $Y$ elements of the
     5319rotation to provide higher accuracy.  The spherical rotation term is
     5320generated by providing the three elements of the rotation to the
     5321following function:
     5322\begin{verbatim}
     5323psSphereRot *psSphereRot_CEOtoGCRS(double s, const psSphere *pole)
     5324\end{verbatim}
     5325The retulting \code{psSphereRot} may be used to determine the rotation
     5326from CIP/CEO to GCRS.  This function must give results identical to
     5327the IERS BPN2000, within the limits of machine accuracy.
     5328
     5329\paragraph{Earth Rotation}
     5330
     5331The following routine calculates the rotation of the Earth about the CIP:
     5332\begin{verbatim}
     5333psSphereRot *psSphereRot_TEOtoCEO(const psTime *time)
     5334\end{verbatim}
     5335The IERS code to create the comparable rotation is embedded in
     5336T2C2000, with the Earth Rotation Angle calculated by ERA2000.
     5337
     5338\paragraph{Polar Motion}
     5339
     5340The following function provides interpolated values of the polar
     5341motion components, $x_p$ and $y_p$, extracted from the IERS tables. 
     5342\begin{verbatim}
     5343psSphere *psEOC_GetPoleCoords(const psTime *time, psTimeBulletin bulletin);
     5344\end{verbatim}
     5345
     5346The following function provides tidal corrections to the polar motion
     5347components, $x_p$ and $y_p$, using the Ray model of Simon et al (see
     5348ADD).
     5349\begin{verbatim}
     5350psSphere *psEOC_TidePolarCorr(const psTime *time);
     5351\end{verbatim}
     5352
     5353The following function provides the additional corrections due to nutation
     5354terms with periods less than or equal to two days:
     5355\begin{verbatim}
     5356psSphere *psEOC_NutationCorr(psTime *time);
     5357\end{verbatim}
     5358
     5359The following function should generate the \code{psSphereRot} transform from
     5360ITRS to CIP/TEO:
     5361\begin{verbatim}
     5362psSphereRot *psSphereRot_ITRStoTEO(psSphere pole, psTime *time);
     5363\end{verbatim}
     5364The time argument should be used to internally calculate $s'$.
     5365This function should give identical results to the IERS POM2000 subroutine.
     5366
     5367\subsubsection{Earth Orientation Wrappers}
     5368
     5369The following function generates the complete spherical rotation to
     5370account for precession between two times.  If \code{NULL} is provided
     5371for either time, it is assumed to have the reference equinox value of
     5372J2000.
     5373\begin{verbatim}
     5374psSphere *psSpherePrecess(const psTime *fromTime, const psTime *toTime, psPrecessMethod mode);
     5375\end{verbatim}
     5376The mode argument is used to specify the level of detail used in the
     5377calculation.
     5378
     5379\begin{verbatim}
     5380typedef enum {
     5381  PS_PRECESS_ROUGH,
     5382  PS_PRECESS_COMPLETE,
     5383  PS_PRECESS_IAU2000A,
     5384} psPrecessMethod;
     5385\end{verbatim}
     5386
     5387\subsection{Atmospheric Effects}
     5388
     5389\tbd{The ATM effects components should be deferred until we clean up
     5390  the refraction definitions}
     5391
     5392A-priori astrometric transformations between the telescope orientation
     5393(Alt/Az) and the predicted stellar coordinates above the atmosphere
     5394(DEC/HA) requires several pieces of information describing the current
     5395environmental conditions.  These quantities are consistent across an
     5396image, and may vary only slowly with time.  Pre-computing these
     5397quantities for exposures means that subsequent transformations are
     5398faster.  The structure below carries the environmental data of interest.
     5399For historical reasons, this structure is known colloquially as ``the
     5400Grommit''.
     5401
     5402\tbd{this structure needs to be modified to correspond to what we
     5403  actually need to carry around for the atmosphere functions}
     5404
     5405\tbd{provide a single Grommit to carry around all EOC + ATM
     5406  pre-calculated entries and a separate structure for ATM effect?}
     5407
     5408\begin{verbatim}
     5409typedef struct {
     5410    const double latitude;              ///< geodetic latitude (radians)
     5411    const double longitude;             ///< longitude + ... (radians)
     5412    const double height;                ///< height (HM)
     5413    const double abberationMag;         ///< magnitude of diurnal aberration vector
     5414    const double temperature;           ///< ambient temperature (TDK)
     5415    const double pressure;              ///< pressure (PMB)
     5416    const double humidity;              ///< relative humidity (RH)
     5417    const double wavelength;            ///< wavelength (WL)
     5418    const double lapseRate;             ///< lapse rate (TLR)
     5419    const double refractA, refractB;    ///< refraction constants A and B (radians)
     5420    const double siderealTime;          ///< local apparent sidereal time (radians)
     5421} psGrommit;
     5422\end{verbatim}
     5423
     5424The \code{psGrommit} is calculated from telescope information for the
     5425particular exposure, \code{exp}:
     5426\begin{verbatim}
     5427psGrommit *psGrommitAlloc(const psExposure *exp);
     5428\end{verbatim}
     5429
     5430\tbd{these functions probably need to take the ATM structure}
     5431
     5432We require additional functions to perform general functions which
     5433will be useful for astrometry.  Given coordinates on the sky, we
     5434need to get the airmass, the parallactic angle, and an estimate of
     5435the atmospheric refraction.
     5436
     5437\begin{verbatim}
     5438float psGetAirmass(const psSphere *coord, psTime *lst, float height);
     5439\end{verbatim}
     5440which returns the airmass for a given position and local sidereal time
     5441(\code{lst}).
     5442
     5443\begin{verbatim}
     5444float psGetParallactic(const psSphere *coord, double siderealTime);
     5445\end{verbatim}
     5446which returns the parallactic angle for a given position and sidereal time.
     5447
     5448\begin{verbatim}
     5449float psGetRefraction(float colour,            ///< Colour of object
     5450                      psPhotSystem colorPlus,  ///< Colour reference
     5451                      psPhotSystem colorMinus, ///< Colour reference
     5452                      const psExposure *exp);  ///< Telescope pointing information
     5453\end{verbatim}
     5454which provides an estimate of the atmospheric refraction, along the parallactic angle.
     5455
     5456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     5457
     5458\subsection{Fixed Pattern}
     5459
     5460The fixed pattern is a correction to the general astrometric solution
     5461formed by summing the residuals from many observations.  The intent is
     5462to correct for higher-order distortions in the camera system on a
     5463coarse grid (larger than individual pixels, but smaller than a single
     5464cell).  Hence, in addition to the offsets, we need to specify the size
     5465and scale of the grid in $x$ and $y$, as well as the origin of the
     5466grid.
     5467
     5468\begin{verbatim}
     5469typedef struct {
     5470    int nX, nY;                         ///< Number of elements in x and y
     5471    double x0, y0;                      ///< Position of 0,0 corner on focal plane
     5472    double xScale, yScale;              ///< Scale of the grid
     5473    double **x, **y;                    ///< The grid of offsets in x and y
     5474} psFixedPattern;
     5475\end{verbatim}
     5476
     5477The constructor for \code{psFixedPattern} shall be:
     5478\begin{verbatim}
     5479psFixedPattern *psFixedPatternAlloc(double x0,        double y0,
     5480                                    double xScale,    double yScale,
     5481                                    const psImage *x, const psImage *y);
     5482\end{verbatim}
     5483Here, \code{x0}, \code{y0}, \code{xScale} and \code{yScale} have the
     5484same meaning as in the \code{psFixedPattern} structure.  Note that the
     5485values of the fixed pattern offsets are specified as images, the
     5486values from which need to be copied into the \code{double **x} and
     5487\code{double **y} of \code{psFixedPattern}, and that the number of
     5488elements may be derived from the size of the images.
     5489
     5490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
     5491
     5492\subsection{Projections}
     5493
     5494We require functions to convert between spherical and linear
     5495coordinate systems based on a variety of projections.  The required
     5496projections include:
     5497\begin{itemize}
     5498\item TAN
     5499\item SIN
     5500\item AIT
     5501\item PAR
     5502\end{itemize}
     5503
     5504We specify the following structure \code{psProjection} to define the
     5505parameters of the projection:
     5506\begin{verbatim}
     5507typedef struct {
     5508    double R, D;                         ///< coordinates of projection center
     5509    double Xs, Ys;                       ///< plate-scale in X and Y directions
     5510    psProjectionType type;               ///< projection type
     5511} psProjection;
     5512\end{verbatim}
     5513
     5514The projection type is defined by the following enumerated type \code{psProjectionType}:
     5515\begin{verbatim}
     5516typedef enum {                          ///< type of val is:
     5517    PS_PROJ_TAN,                        ///< Tangent projection
     5518    PS_PROJ_SIN,                        ///< Sine projection
     5519    PS_PROJ_AIT,                        ///< Aitoff projection
     5520    PS_PROJ_PAR,                        ///< Par projection
     5521    PS_PROJ_NTYPE                       ///< Number of types; must be last
     5522} psProjectionType;
     5523\end{verbatim}
     5524
     5525The constructor is straight-forward:
     5526\begin{verbatim}
     5527psProjection *psProjectionAlloc(double R, double D, double Xs, double Ys, psProjectionType type);
     5528\end{verbatim}
     5529
     5530The following functions will project and deproject (respectively)
     5531spherical coordinates:
     5532
     5533\begin{verbatim}
     5534psPlane  *psProject(const psSphere *coord, const psProjection *projection);
     5535psSphere *psDeproject(const psPlane *coord, const psProjection *projection);
     5536\end{verbatim}
     5537
     5538%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
    52315539
    52325540\subsection{Photometry}
     
    52985606M_{\rm pM} - pA, M_{\rm sP} - M_{\rm sM} - sA)$.
    52995607
    5300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     5608%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     5609
     5610%%% Astronomical Images and Astrometry
     5611\include{psLibSDRS_Astrom}
    53015612
    53025613\subsection{Astronomical objects}
     
    53295640\appendix
    53305641
     5642\pagebreak
    53315643\section{Configuration File Test Inputs}
    53325644\label{sec:configtest}
  • trunk/doc/pslib/psLibSDRS_Astrom.tex

    r3181 r3564  
    270270\code{TRUE} if they are all correctly assigned, otherwise \code{FALSE}.
    271271
    272 \subsubsection{Coordinate Transformations}
     272\subsubsection{Detector Coordinate Transformations}
    273273
    274274\begin{figure}
     
    322322\end{verbatim}
    323323
    324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    325 
    326 % add psExposure to metadata?
    327 % add grommit to metadata?
    328 % add photsystem data to metadata?
    329 % add statistics to metadata?
    330 
    331 \subsubsection{Observatory data}
     324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     325
     326\subsection{Astrometry}
     327
     328Astrometry is a basic functionality required for the IPP that will be
     329used repeatedly, both for low-precision (roughly where is my favorite
     330object?) and high-precision (what is the proper motion of this star?).
     331As such, it must be flexible, yet robust.
     332
     333\subsubsection{Coordinate frames}
     334\label{sec:coordinateFrames}
     335
     336There are five coordinate frames that we need to worry about for the
     337purposes of astrometry:
     338\begin{itemize}
     339\item Cell: $(x,y)$ in pixels --- raw coordinates;
     340\item Chip: $(X,Y)$ in pixels --- the location on the silicon;
     341\item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;
     342\item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and
     343\item Sky: (RA,Dec) --- ICRS.
     344\end{itemize}
     345
     346The following steps are required to convert from the cell coordinates to
     347the sky:
     348\begin{itemize}
     349\item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;
     350\item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;
     351\item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =
     352h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the
     353object, respectively; and
     354\item TP $\longleftrightarrow$ Sky:  transformation to the sky using
     355pre-computed coefficients for each pointing.
     356\end{itemize}
     357
     358Note that the transformation between the Focal Plane and the Tangent
     359Plane is a four-dimensional polynomial, in order to account for any
     360possible dependencies in the astrometry on the stellar magnitude and
     361color; the former serves as a check for charge transfer
     362inefficiencies, while the latter will correct chromatic refraction,
     363both through the atmosphere and the corrector lenses.
     364
     365We require structures to contain each of the above transformations as
     366well as the pixel data.
     367
     368\subsubsection{Position Finding}
     369
     370We require functions to return the structure containing given
     371coordinates.  For example, we want the chip that corresponds to the
     372focal plane coordinates $(p,q) = (-1.234,+5.678)$.  These routines
     373handle the one-to-many problem --- i.e., for one given focal plane
     374coordinate, there are many chips that this coordinate may be
     375correspond to; these functions will select the correct one.
     376%
     377\begin{verbatim}
     378psCell *psCellInFPA (const psPlane *coord, const psFPA *fpa);
     379psChip *psChipInFPA (const psPlane *coord, const psFPA *fpa);
     380psCell *psCellInChip(const psPlane *coord, const psChip *chip);
     381\end{verbatim}
     382
     383\subsubsection{Conversion Functions}
     384
     385We require functions to convert between the various coordinate frames
     386(Section~\ref{sec:coordinateFrames}).  The hierarchy of the coordinate
     387frames and the transformations between each are shown in
     388Figure~\ref{fig:coco}.  The functions that employ the transformations
     389are shown in Figure~\ref{fig:cocoFunc}.  In addition to
     390transformations between each adjoining coordinate frame in the
     391hierarchy, we also require higher-level functions to convert between
     392the Cell and Sky coordinate frames; these will simply perform the
     393intermediate steps.
     394
     395\begin{figure}
     396\psfig{file=coordinateFrames,height=7in,angle=-90}
     397\caption{The coordinate systems in the \PS{} IPP, and the relation
     398between each by transformations contained in the appropriate
     399structures.}
     400\label{fig:coco}
     401\end{figure}
     402
     403\begin{figure}
     404\psfig{file=coordinateConv,height=7in,angle=-90}
     405\caption{Conversion between coordinate systems by PSLib.}
     406\label{fig:cocoFunc}
     407\end{figure}
     408
     409We specify the following functions to convert between coordinates in
     410one type of frame to another type of frame.  The first group consist
     411of unambiguous transformations: from the coordinates in a low-level
     412frame to the coordinates in the containing higher-level frame, of
     413which only one exists.  In all of these functions, the output
     414coordinate structure may be \code{NULL} or may be supplied by the
     415calling function.  In the former case, the structure must be
     416allocated; in the latter case, the supplied structure must be used.
     417
     418\begin{verbatim}
     419psPlane *psCoordCellToChip (psPlane *out, const psPlane *in, const psCell *cell);
     420% astrometry comes from cell (no need for parent)
     421\end{verbatim}
     422which converts coordindates \code{in} on the specified \code{cell} to
     423the coordinates on the parent chip.
     424
     425\begin{verbatim}
     426psPlane *psCoordChipToFPA (psPlane *out, const psPlane *in, const psChip *chip);
     427% astrometry comes from chip (no need for parent)
     428\end{verbatim}
     429which converts the coordinates \code{in} on the specified \code{chip}
     430to the coordinates on the parent FPA.
     431
     432\begin{verbatim}
     433psPlane *psCoordFPAToTP(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);
     434% astrometry comes from FPA (no need for parent)
     435\end{verbatim}
     436which converts coordinates \code{in} on the specified focal plane
     437\code{fpa} to tangent plane coordinates, applying the appropriate
     438distortion terms.  The \code{color} and magnitude (\code{mag}) of the
     439source is necessary in order to perform the distortion between the
     440focal plane and the tangent plane.
     441
     442\begin{verbatim}
     443psSphere *psCoordTPToSky(psSphere *out, const psPlane *in, const psGrommit *grommit);
     444\end{verbatim}
     445which converts the tangent plane coordinates \code{in} to (RA,Dec) on
     446the sky, based on the environmental information specified by
     447\code{grommit}.
     448
     449% astrometry comes from cell
     450\begin{verbatim}
     451psPlane *psCoordCellToFPA(psPlane *out, const psPlane *in, const psCell *cell);
     452\end{verbatim}
     453which performs the single-step conversion between Cell coordinates
     454\code{in} and FPA coordinates.
     455
     456% astrometry comes from cell,chip,fpa (PARENT IS NEEDED HERE)
     457\begin{verbatim}
     458psSphere *psCoordCellToSky(psSphere *out, const psPlane *in, float color, float mag, const psCell *cell);
     459\end{verbatim}
     460which converts coordinates on the specified cell to (RA,Dec).  This
     461transformation must be performed using the intermediate stage
     462transformations of Cell to Chip, Chip to FPA, FPA to Tangent Plane,
     463Tangent Plane to Sky.  The information needed for each of these
     464transformations is available in the \code{.parent} elements of
     465\code{psCell} and \code{psChip}, and the \code{psFPA.exposure}
     466element.  The \code{color} and magnitude (\code{mag}) of the source is
     467necessary in order to perform the distortion between the focal plane
     468and the tangent plane.
     469
     470% astrometry comes from cell (no need for parent)
     471\begin{verbatim}
     472psSphere *psCoordCellToSkyQuick(psSphere *out, const psPlane *in, const psCell *cell);
     473\end{verbatim}
     474which uses the 'quick-and-dirty' transformation to convert coordinates
     475on the specified cell to (RA,Dec).  This transformation should use the
     476locally linear transformation specified by the element
     477\code{psCell.toTP}.  Although the accuracy of this transformation
     478is lower than the complete transformation above, the calculation is
     479substantially faster as it only involves linear transformations.
     480
     481The following functions convert from high-level frames to the
     482coordinates of contained lower-level frames. 
     483
     484\begin{verbatim}
     485psPlane *psCoordSkyToTP(psPlane *out, const psSphere *in, const psGrommit *grommit);
     486\end{verbatim}
     487which converts (RA,Dec) coordinates \code{in} to tangent plane coords
     488based on the enviromental information supplied by \code{grommit}.
     489
     490\begin{verbatim}
     491psPlane *psCoordTPToFPA(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);
     492\end{verbatim}
     493which converts the tangent plane coordinates \code{in} to focal plane
     494coordinates.  The \code{color} and magnitude (\code{mag}) of the
     495source is necessary in order to perform the distortion between the
     496focal plane and the tangent plane.
     497
     498\begin{verbatim}
     499psPlane *psCoordFPAToChip (psPlane *out, const psPlane *in, const psChip *chip);
     500\end{verbatim}
     501which converts the specified FPA coordinates \code{in} to the
     502coordinates on the given Chip.  The specified chip need not contain
     503the input coordinate.  To find the chip which contains a particular
     504coordinate, the function \code{psChipInFPA}, defined above, should be
     505used.
     506
     507\begin{verbatim}
     508psPlane *psCoordChipToCell (psPlane *out, const psPlane *in, const psCell *cell);
     509\end{verbatim}
     510which converts the specified Chip coordinate \code{in} to the
     511coordinate on the given Cell.  The specified Cell need not contain the
     512input coordinate.  To find the cell which contains a particular
     513coordinate, the function \code{psCellInChip}, defined above, should be
     514used.
     515
     516\begin{verbatim}
     517psPlane *psCoordSkyToCell(psPlane *out, const psSphere *in, float color, float mag, psCell *cell);
     518\end{verbatim}
     519which directly converts (RA,Dec) \code{in} to coordinates on the
     520specified cell.  The specified cell need not contain the input
     521coordinates.  The \code{color} and magnitude (\code{mag}) of the
     522source is necessary in order to perform the distortion between the
     523focal plane and the tangent plane.
     524
     525\begin{verbatim}
     526psPlane *psCoordSkyToCellQuick(psPlane *out, const psSphere *in, psCell *cell);
     527\end{verbatim}
     528which directly converts (RA,Dec) \code{in} to coordinates on the
     529specified cell.  The specified cell need not contain the input
     530coordinates.  This transformation should use the locally linear
     531transformation specified by the element \code{psCell.toTP}.
     532Although the accuracy of this transformation is lower than the
     533complete transformation above, the calculation is substantially faster
     534as it only involves linear transformations.
     535
     536%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     537
     538\subsection{Astrometry and World Coordinate System}
     539
     540The FITS World Coordinate System (WCS) headers are commonly employed
     541with astronomical images in order to relate pixels to celestial (or
     542otherwise) coordinates.  Since it is a FITS standard, we must be able
     543to read and write from WCS into our internal format.  For the time
     544being, we will consider only celestial WCS (i.e., no spectral
     545wavelength calibrations, etc).  Because WCS does not support the
     546multiple layers that we have built for \PS{}, we will use a simple
     547internal representation: a transformation, which handles any
     548distortions (i.e., goes directly from the coordinate frame of the
     549image to the tangent plane); and the projection.
     550
     551\begin{verbatim}
     552bool psAstrometryReadWCS(psPlaneTransform **transform, // Output transformation
     553                         psProjection **projection, // Output projection
     554                         psMetadata *header // Input FITS header
     555                         );
     556bool psAstrometryWriteWCS(psMetadata *header, // Output FITS header
     557                          psPlaneTransform *transform, // Input transformation
     558                          psProjection *projection, // Input projection
     559                          double color, // Mean color to use
     560                          double magnitude, // Mean magnitude to use
     561                          );
     562bool psAstrometrySimplify(psPlaneTransform **transform, // Output transformation
     563                          psProjection **projection, // Output projection
     564                          psCell *cell // Cell for which to generate transform and projection
     565                          );
     566\end{verbatim}                 
     567
     568\code{pmReadAstrometry} shall parse the specified FITS \code{header},
     569returning new instances of the \code{transform} and \code{projection}
     570that represent the WCS.  The function shall return \code{true} if it
     571was able to successfully generate the outputs; otherwise it shall
     572return \code{false}.
     573
     574\code{pmWriteAstrometry} shall add WCS keywords to the supplied FITS
     575\code{header} that implement the given \code{transform} and
     576\code{projection}.  The function shall return \code{true} if it was
     577able to successfully generate the output; otherwise it shall return
     578\code{false}.
     579
     580\code{pmSimplifyAstrometry} shall take a \code{cell} and simplify the
     581internal astrometric representation (\code{cell->toFPA} or equivalent,
     582\code{cell->parent->parent->toTangentPlane} and
     583\code{cell->parent->parent->grommit}) to a single \code{transform} and
     584\code{projection}.  This allows the subsequent use of
     585\code{pmWriteAstrometry} in the case that we have only the
     586multi-layered \PS{} internal astrometric representation.  The function
     587shall return \code{true} if it was able to successfully generate the
     588output; otherwise it shall return \code{false}.
     589
     590\subsection{Observatory data}
    332591
    333592We need a container for the observatory data that doesn't change per
     
    350609\end{verbatim}
    351610
    352 \subsubsection{Exposure information}
     611\subsection{Exposure information}
    353612
    354613We need several quantities from the telescope in order to make a
     
    388647\end{verbatim}
    389648
    390 \subsubsection{Environmental Information}
    391 
    392 A-priori astrometric transformations between the tangent plane and the
    393 sky require several pieces of information describing the current
    394 environmental conditions.  These quantities are consistent from image
    395 to image, and may vary only slowly with time.  Pre-computing these
    396 quantities for exposures means that subsequent transformations are
    397 faster.  The structure below carries the environment data of interest.
    398 For historical reasons, this structure is known colloquially as ``the
    399 Grommit''.
    400 
    401 \begin{verbatim}
    402 typedef struct {
    403     const double latitude;              ///< geodetic latitude (radians)
    404     const double sinLat, cosLat;        ///< sine and cosine of geodetic latitude
    405     const double abberationMag;         ///< magnitude of diurnal aberration vector
    406     const double height;                ///< height (HM)
    407     const double temperature;           ///< ambient temperature (TDK)
    408     const double pressure;              ///< pressure (PMB)
    409     const double humidity;              ///< relative humidity (RH)
    410     const double wavelength;            ///< wavelength (WL)
    411     const double lapseRate;             ///< lapse rate (TLR)
    412     const double refractA, refractB;    ///< refraction constants A and B (radians)
    413     const double longitudeOffset;       ///< longitude + ... (radians)
    414     const double siderealTime;          ///< local apparent sidereal time (radians)
    415 } psGrommit;
    416 \end{verbatim}
    417 
    418 The \code{psGrommit} is calculated from telescope information for the
    419 particular exposure, \code{exp}:
    420 \begin{verbatim}
    421 psGrommit *psGrommitAlloc(const psExposure *exp);
    422 \end{verbatim}
    423 
    424 \subsubsection{Fixed Pattern}
    425 
    426 The fixed pattern is a correction to the general astrometric solution
    427 formed by summing the residuals from many observations.  The intent is
    428 to correct for higher-order distortions in the camera system on a
    429 coarse grid (larger than individual pixels, but smaller than a single
    430 cell).  Hence, in addition to the offsets, we need to specify the size
    431 and scale of the grid in $x$ and $y$, as well as the origin of the
    432 grid.
    433 
    434 \begin{verbatim}
    435 typedef struct {
    436     int nX, nY;                         ///< Number of elements in x and y
    437     double x0, y0;                      ///< Position of 0,0 corner on focal plane
    438     double xScale, yScale;              ///< Scale of the grid
    439     double **x, **y;                    ///< The grid of offsets in x and y
    440 } psFixedPattern;
    441 \end{verbatim}
    442 
    443 The constructor for \code{psFixedPattern} shall be:
    444 \begin{verbatim}
    445 psFixedPattern *psFixedPatternAlloc(double x0,        double y0,
    446                                     double xScale,    double yScale,
    447                                     const psImage *x, const psImage *y);
    448 \end{verbatim}
    449 Here, \code{x0}, \code{y0}, \code{xScale} and \code{yScale} have the
    450 same meaning as in the \code{psFixedPattern} structure.  Note that the
    451 values of the fixed pattern offsets are specified as images, the
    452 values from which need to be copied into the \code{double **x} and
    453 \code{double **y} of \code{psFixedPattern}, and that the number of
    454 elements may be derived from the size of the images.
    455 
    456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    457 
    458 \subsection{Astrometry}
    459 
    460 Astrometry is a basic functionality required for the IPP that will be
    461 used repeatedly, both for low-precision (roughly where is my favorite
    462 object?) and high-precision (what is the proper motion of this star?).
    463 As such, it must be flexible, yet robust.  Accordingly, we will wrap
    464 the StarLink Astronomy Libraries (SLALib), which has already been
    465 developed.  \tbd{SLAlib functions will be replaced in the next
    466 release}.
    467 
    468 \subsubsection{Coordinate frames}
    469 \label{sec:coordinateFrames}
    470 
    471 There are five coordinate frames that we need to worry about for the
    472 purposes of astrometry:
    473 \begin{itemize}
    474 \item Cell: $(x,y)$ in pixels --- raw coordinates;
    475 \item Chip: $(X,Y)$ in pixels --- the location on the silicon;
    476 \item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;
    477 \item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and
    478 \item Sky: (RA,Dec) --- ICRS.
    479 \end{itemize}
    480 
    481 The following steps are required to convert from the cell coordinates to
    482 the sky:
    483 \begin{itemize}
    484 \item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;
    485 \item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;
    486 \item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =
    487 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the
    488 object, respectively; and
    489 \item TP $\longleftrightarrow$ Sky:  transformation to the sky using
    490 pre-computed coefficients for each pointing.
    491 \end{itemize}
    492 
    493 Note that the transformation between the Focal Plane and the Tangent
    494 Plane is a four-dimensional polynomial, in order to account for any
    495 possible dependencies in the astrometry on the stellar magnitude and
    496 color; the former serves as a check for charge transfer
    497 inefficiencies, while the latter will correct chromatic refraction,
    498 both through the atmosphere and the corrector lenses.
    499 
    500 We require structures to contain each of the above transformations as
    501 well as the pixel data.
    502 
    503 \subsubsection{Position Finding}
    504 
    505 We require functions to return the structure containing given
    506 coordinates.  For example, we want the chip that corresponds to the
    507 focal plane coordinates $(p,q) = (-1.234,+5.678)$.  These routines
    508 handle the one-to-many problem --- i.e., for one given focal plane
    509 coordinate, there are many chips that this coordinate may be
    510 correspond to; these functions will select the correct one.
    511 %
    512 \begin{verbatim}
    513 psCell *psCellInFPA (const psPlane *coord, const psFPA *fpa);
    514 psChip *psChipInFPA (const psPlane *coord, const psFPA *fpa);
    515 psCell *psCellInChip(const psPlane *coord, const psChip *chip);
    516 \end{verbatim}
    517 
    518 \subsubsection{Conversion Functions}
    519 
    520 We require functions to convert between the various coordinate frames
    521 (Section~\ref{sec:coordinateFrames}).  The hierarchy of the coordinate
    522 frames and the transformations between each are shown in
    523 Figure~\ref{fig:coco}.  The functions that employ the transformations
    524 are shown in Figure~\ref{fig:cocoFunc}.  In addition to
    525 transformations between each adjoining coordinate frame in the
    526 hierarchy, we also require higher-level functions to convert between
    527 the Cell and Sky coordinate frames; these will simply perform the
    528 intermediate steps.
    529 
    530 \begin{figure}
    531 \psfig{file=coordinateFrames,height=7in,angle=-90}
    532 \caption{The coordinate systems in the \PS{} IPP, and the relation
    533 between each by transformations contained in the appropriate
    534 structures.}
    535 \label{fig:coco}
    536 \end{figure}
    537 
    538 \begin{figure}
    539 \psfig{file=coordinateConv,height=7in,angle=-90}
    540 \caption{Conversion between coordinate systems by PSLib.}
    541 \label{fig:cocoFunc}
    542 \end{figure}
    543 
    544 We specify the following functions to convert between coordinates in
    545 one type of frame to another type of frame.  The first group consist
    546 of unambiguous transformations: from the coordinates in a low-level
    547 frame to the coordinates in the containing higher-level frame, of
    548 which only one exists.  In all of these functions, the output
    549 coordinate structure may be \code{NULL} or may be supplied by the
    550 calling function.  In the former case, the structure must be
    551 allocated; in the latter case, the supplied structure must be used.
    552 
    553 \begin{verbatim}
    554 psPlane *psCoordCellToChip (psPlane *out, const psPlane *in, const psCell *cell);
    555 % astrometry comes from cell (no need for parent)
    556 \end{verbatim}
    557 which converts coordindates \code{in} on the specified \code{cell} to
    558 the coordinates on the parent chip.
    559 
    560 \begin{verbatim}
    561 psPlane *psCoordChipToFPA (psPlane *out, const psPlane *in, const psChip *chip);
    562 % astrometry comes from chip (no need for parent)
    563 \end{verbatim}
    564 which converts the coordinates \code{in} on the specified \code{chip}
    565 to the coordinates on the parent FPA.
    566 
    567 \begin{verbatim}
    568 psPlane *psCoordFPAToTP(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);
    569 % astrometry comes from FPA (no need for parent)
    570 \end{verbatim}
    571 which converts coordinates \code{in} on the specified focal plane
    572 \code{fpa} to tangent plane coordinates, applying the appropriate
    573 distortion terms.  The \code{color} and magnitude (\code{mag}) of the
    574 source is necessary in order to perform the distortion between the
    575 focal plane and the tangent plane.
    576 
    577 \begin{verbatim}
    578 psSphere *psCoordTPToSky(psSphere *out, const psPlane *in, const psGrommit *grommit);
    579 \end{verbatim}
    580 which converts the tangent plane coordinates \code{in} to (RA,Dec) on
    581 the sky, based on the environmental information specified by
    582 \code{grommit}.
    583 
    584 \begin{verbatim}
    585 psPlane *psCoordCellToFPA(psPlane *out, const psPlane *in, const psCell *cell);
    586 % astrometry comes from cell
    587 \end{verbatim}
    588 which performs the single-step conversion between Cell coordinates
    589 \code{in} and FPA coordinates.
    590 
    591 \begin{verbatim}
    592 psSphere *psCoordCellToSky(psSphere *out, const psPlane *in, float color, float mag, const psCell *cell);
    593 % astrometry comes from cell,chip,fpa (PARENT IS NEEDED HERE)
    594 \end{verbatim}
    595 which converts coordinates on the specified cell to (RA,Dec).  This
    596 transformation must be performed using the intermediate stage
    597 transformations of Cell to Chip, Chip to FPA, FPA to Tangent Plane,
    598 Tangent Plane to Sky.  The information needed for each of these
    599 transformations is available in the \code{.parent} elements of
    600 \code{psCell} and \code{psChip}, and the \code{psFPA.exposure}
    601 element.  The \code{color} and magnitude (\code{mag}) of the source is
    602 necessary in order to perform the distortion between the focal plane
    603 and the tangent plane.
    604 
    605 \begin{verbatim}
    606 psSphere *psCoordCellToSkyQuick(psSphere *out, const psPlane *in, const psCell *cell);
    607 % astrometry comes from cell (no need for parent)
    608 \end{verbatim}
    609 which uses the 'quick-and-dirty' transformation to convert coordinates
    610 on the specified cell to (RA,Dec).  This transformation should use the
    611 locally linear transformation specified by the element
    612 \code{psCell.toTP}.  Although the accuracy of this transformation
    613 is lower than the complete transformation above, the calculation is
    614 substantially faster as it only involves linear transformations.
    615 
    616 The following functions convert from high-level frames to the
    617 coordinates of contained lower-level frames. 
    618 
    619 \begin{verbatim}
    620 psPlane *psCoordSkyToTP(psPlane *out, const psSphere *in, const psGrommit *grommit);
    621 \end{verbatim}
    622 which converts (RA,Dec) coordinates \code{in} to tangent plane coords
    623 based on the enviromental information supplied by \code{grommit}.
    624 
    625 \begin{verbatim}
    626 psPlane *psCoordTPToFPA(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);
    627 \end{verbatim}
    628 which converts the tangent plane coordinates \code{in} to focal plane
    629 coordinates.  The \code{color} and magnitude (\code{mag}) of the
    630 source is necessary in order to perform the distortion between the
    631 focal plane and the tangent plane.
    632 
    633 \begin{verbatim}
    634 psPlane *psCoordFPAToChip (psPlane *out, const psPlane *in, const psChip *chip);
    635 \end{verbatim}
    636 which converts the specified FPA coordinates \code{in} to the
    637 coordinates on the given Chip.  The specified chip need not contain
    638 the input coordinate.  To find the chip which contains a particular
    639 coordinate, the function \code{psChipInFPA}, defined above, should be
    640 used.
    641 
    642 \begin{verbatim}
    643 psPlane *psCoordChipToCell (psPlane *out, const psPlane *in, const psCell *cell);
    644 \end{verbatim}
    645 which converts the specified Chip coordinate \code{in} to the
    646 coordinate on the given Cell.  The specified Cell need not contain the
    647 input coordinate.  To find the cell which contains a particular
    648 coordinate, the function \code{psCellInChip}, defined above, should be
    649 used.
    650 
    651 \begin{verbatim}
    652 psPlane *psCoordSkyToCell(psPlane *out, const psSphere *in, float color, float mag, psCell *cell);
    653 \end{verbatim}
    654 which directly converts (RA,Dec) \code{in} to coordinates on the
    655 specified cell.  The specified cell need not contain the input
    656 coordinates.  The \code{color} and magnitude (\code{mag}) of the
    657 source is necessary in order to perform the distortion between the
    658 focal plane and the tangent plane.
    659 
    660 \begin{verbatim}
    661 psPlane *psCoordSkyToCellQuick(psPlane *out, const psSphere *in, psCell *cell);
    662 \end{verbatim}
    663 which directly converts (RA,Dec) \code{in} to coordinates on the
    664 specified cell.  The specified cell need not contain the input
    665 coordinates.  This transformation should use the locally linear
    666 transformation specified by the element \code{psCell.toTP}.
    667 Although the accuracy of this transformation is lower than the
    668 complete transformation above, the calculation is substantially faster
    669 as it only involves linear transformations.
    670 
    671 \subsubsection{Additional functions}
    672 
    673 We require additional functions to perform general functions which
    674 will be useful for astrometry.  Given coordinates on the sky, we
    675 need to get the airmass, the parallactic angle, and an estimate of
    676 the atmospheric refraction.
    677 
    678 \begin{verbatim}
    679 float psGetAirmass(const psSphere *coord, psTime *lst, float height);
    680 \end{verbatim}
    681 which returns the airmass for a given position and local sidereal time
    682 (\code{lst}).
    683 
    684 \begin{verbatim}
    685 float psGetParallactic(const psSphere *coord, double siderealTime);
    686 \end{verbatim}
    687 which returns the parallactic angle for a given position and sidereal time.
    688 
    689 \begin{verbatim}
    690 float psGetRefraction(float colour,            ///< Colour of object
    691                       psPhotSystem colorPlus,  ///< Colour reference
    692                       psPhotSystem colorMinus, ///< Colour reference
    693                       const psExposure *exp);  ///< Telescope pointing information
    694 \end{verbatim}
    695 which provides an estimate of the atmospheric refraction, along the parallactic angle.
    696 
    697 \begin{verbatim}
    698 double psGetParallaxFactor(const psExposure *exp)
    699 \end{verbatim}
    700 Calculate the parallax factor for the given exposure.  \tbd{Why do we need this?}.
    701 
    702 
    703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    704 
    705 \subsection{Astrometry and World Coordinate System}
    706 
    707 The FITS World Coordinate System (WCS) headers are commonly employed
    708 with astronomical images in order to relate pixels to celestial (or
    709 otherwise) coordinates.  Since it is a FITS standard, we must be able
    710 to read and write from WCS into our internal format.  For the time
    711 being, we will consider only celestial WCS (i.e., no spectral
    712 wavelength calibrations, etc).  Because WCS does not support the
    713 multiple layers that we have built for \PS{}, we will use a simple
    714 internal representation: a transformation, which handles any
    715 distortions (i.e., goes directly from the coordinate frame of the
    716 image to the tangent plane); and the projection.
    717 
    718 \begin{verbatim}
    719 bool psAstrometryReadWCS(psPlaneTransform **transform, // Output transformation
    720                          psProjection **projection, // Output projection
    721                          psMetadata *header // Input FITS header
    722                          );
    723 bool psAstrometryWriteWCS(psMetadata *header, // Output FITS header
    724                           psPlaneTransform *transform, // Input transformation
    725                           psProjection *projection, // Input projection
    726                           double color, // Mean color to use
    727                           double magnitude, // Mean magnitude to use
    728                           );
    729 bool psAstrometrySimplify(psPlaneTransform **transform, // Output transformation
    730                           psProjection **projection, // Output projection
    731                           psCell *cell // Cell for which to generate transform and projection
    732                           );
    733 \end{verbatim}                 
    734 
    735 \code{pmReadAstrometry} shall parse the specified FITS \code{header},
    736 returning new instances of the \code{transform} and \code{projection}
    737 that represent the WCS.  The function shall return \code{true} if it
    738 was able to successfully generate the outputs; otherwise it shall
    739 return \code{false}.
    740 
    741 \code{pmWriteAstrometry} shall add WCS keywords to the supplied FITS
    742 \code{header} that implement the given \code{transform} and
    743 \code{projection}.  The function shall return \code{true} if it was
    744 able to successfully generate the output; otherwise it shall return
    745 \code{false}.
    746 
    747 \code{pmSimplifyAstrometry} shall take a \code{cell} and simplify the
    748 internal astrometric representation (\code{cell->toFPA} or equivalent,
    749 \code{cell->parent->parent->toTangentPlane} and
    750 \code{cell->parent->parent->grommit}) to a single \code{transform} and
    751 \code{projection}.  This allows the subsequent use of
    752 \code{pmWriteAstrometry} in the case that we have only the
    753 multi-layered \PS{} internal astrometric representation.  The function
    754 shall return \code{true} if it was able to successfully generate the
    755 output; otherwise it shall return \code{false}.
    756 
Note: See TracChangeset for help on using the changeset viewer.