Index: /trunk/doc/pslib/psLibSDRS.tex
===================================================================
--- /trunk/doc/pslib/psLibSDRS.tex	(revision 308)
+++ /trunk/doc/pslib/psLibSDRS.tex	(revision 309)
@@ -1,3 +1,3 @@
-%%% $Id: psLibSDRS.tex,v 1.11 2004-03-24 03:42:51 price Exp $
+%%% $Id: psLibSDRS.tex,v 1.12 2004-03-27 02:11:28 eugene Exp $
 \documentclass[panstarrs]{panstarrs}
 %\documentclass[panstarrs]{panstarrs}
@@ -708,5 +708,45 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\section{Data Containers}
+\subsection{Miscellaneous Utilities}
+
+\begin{verbatim}
+#define PS_STRING(S) #S                 // converts argument S to string
+    
+/// Prints an error message and aborts
+void psAbort(const char *name,          ///< Category of code that caused the abort
+             const char *fmt,           ///< Format
+             ...                        ///< Extra arguments to use format
+             );
+
+/// Prints an error message and doesn't abort
+void psError(const char *name,          ///< Category of code that caused the abort
+             const char *fmt,           ///< Format
+             ...                        ///< Extra arguments to use format
+    );
+
+/// Allocates and returns a copy of a string
+char *psStringCopy(const char *str      ///< string to copy
+    );
+
+/// Allocates nChar and returns a copy of the string or segment
+char *psStringNCopy(const char *str,    ///< string to copy
+                    int nChar           //!< Number of characters (including \0 )
+    );
+\end{verbatim}
+
+\code{psAbort} shall call \code{psMsgLog} with a level of \code{PS_LOG_ABORT},
+and then call \code{abort}.
+\code{psError} shall call \code{psMsgLog} with a level of \code{PS_LOG_ERROR},
+and then return.
+In cases of doubt, a good choice for
+\code{name} is \code{__func__}.
+
+\code{psStringCopy} shall allocate and return a copy of the input string.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{Basic Data Collections}
 
 We require general data containers, so that associated values (e.g.\
@@ -719,5 +759,170 @@
 \end{itemize}
 
-\subsection{The Pan-STARRS \texttt{psDlist} doubly-linked list type}
+\subsection{Simple Array types}
+
+\subsubsection{Arrays of Simple Types}
+
+Any \PS{} datatype \code{psType} may be associated with an array type
+\code{psTypeArray}:
+\begin{verbatim}
+typedef struct {
+  int size;
+  int n;
+  psType *arr;
+} psTypeArray;
+\end{verbatim}
+with associated constructors and a destructor:
+\begin{verbatim}
+psTypeArray *psTypeAlloc(int n, int size);
+psTypeArray *psTypeRealloc(psTypeArray *arr, int n);
+void psTypeFree(psTypeArray *arr);  
+\end{verbatim}
+
+The argument \code{n} is the dimension of the array; \code{size}
+is the number of elements allocated ($s \ge n$).
+
+This type and functions may be declared and defined using two macros,
+\code{PS_DECLARE_ARRAY_TYPE(psType)} and
+\code{PS_CREATE_ARRAY_TYPE(psType)}.  The former defines the
+\code{typedef} and declares the prototypes (and is thus suitable for
+use in a header file); the latter generates the code for the three
+functions \code{psType(Alloc|Realloc|Free)} (and should thus appear in
+exactly one source file for a given type).
+
+The \code{psType} should be a single word (e.g. \code{psXY}); in particular,
+there is no requirement to support a pointer type (\eg{} \code{psXY *});
+see next section.
+
+\subsubsection{Arrays of Pointer Types}
+
+The data type created with \code{PS_CREATE_ARRAY_TYPE} (\code{psType})
+contains an array of \code{psType}s not
+pointers to \code{psType}s; this means that the individual elements are
+not allocated using \code{psTypeAlloc}, are not correctly initialized,
+and shouldn't be individually deleted with \code{psTypeFree};
+
+If you wish to use arrays of pointers, use the macros
+\code{PS_DECLARE_ARRAY_PTR_TYPE(psType)} and
+\code{PS_CREATE_ARRAY_PTR_TYPE(psType)}. These
+create types \code{typedef psType *psTypePtr} and \code{psTypePtrArray}:
+\begin{verbatim}
+typedef struct {
+  int size;
+  int n;
+  psTypePtr *arr;
+} psTypePtrArray;
+\end{verbatim}
+with associated constructors and a destructor:
+\begin{verbatim}
+psTypePtrArray *psTypePtrAlloc(int n, int size);
+psTypePtrArray *psTypePtrRealloc(psTypePtrArray *arr, int n);
+void psTypePtrArrayFree(psTypePtrArray *arr);  
+\end{verbatim}
+
+These constructors create arrays of \code{psType *} and call
+\code{psTypeAlloc} and \code{psTypeFree} to allocate and free the
+elements. As for the simple arrays, The former defines the typedef and
+declares the prototypes (and is thus suitable for use in a header
+file) and the latter generates the code for the three functions
+\code{psType(Alloc|Realloc|Free)} (and should thus appear in exactly one
+source file for a given type).
+
+The objects pointed to by these types have had their \code{refCounter}s
+incremented (see \ref{secMemRefcounter}); to remove an element from the array you
+need to say something like:
+\begin{verbatim}
+  psTypePtrArray *pt = psTypePtrArrayAlloc(10, 10);
+  psType *xy = psMemDecrRefCounter(pt->arr[0]);
+  pt->arr[0] = NULL;
+\end{verbatim}
+
+\subsubsection{Arrays of \texttt{void *}}
+\hlabel{secArrayVoidPtr}
+
+Arrays of \code{void *} are different, as they need an explicitly-specified
+destructor.
+
+We require a type \code{psVoidPtrArray} that behaves in all respects
+as if it had been created with:
+\begin{verbatim}
+typedef void *psVoidPtr;
+PS_DECLARE_ARRAY_TYPE(psVoidPtr);
+PS_CREATE_ARRAY_TYPE(psVoidPtr);
+\end{verbatim}
+except that its destructor is specified as:
+\begin{verbatim}
+void psVoidPtrArrayFree(psVoidPtrArray *arr,      // array to destroy
+                       void (*elemFree)(void *)); // destructor for array data
+\end{verbatim}
+
+The routine \code{psVoidPtrArrayFree} assumes that all pointers
+had their reference counters incremented
+when they were inserted onto the array.\footnote{%
+  \eg{} \code{va->arr[i] = psMemIncrRefCounter(ptr);}}
+
+If \code{psVoidPtrArrayFree}'s argument \code{elemFree} is NULL, the
+list should be deleted, but not the elements on it (although their
+\code{refcounter}'s should be decremented).
+
+\subsubsection{Examples of Array Types}
+
+The following is a complete C program that illustrates the use of
+\code{array}s.
+\begin{verbatim}
+#include "psLib.h"
+
+typedef struct {
+    int x, y;
+} psXY;
+
+psXY *psXYAlloc(void)
+{
+    return psAlloc(sizeof(psXY));
+}
+
+void psXYFree(psXY *xy)
+{
+    psFree(xy);
+}
+
+PS_DECLARE_ARRAY_TYPE(psXY);
+PS_CREATE_ARRAY_TYPE(psXY);
+
+PS_DECLARE_ARRAY_PTR_TYPE(psXY);
+PS_CREATE_ARRAY_PTR_TYPE(psXY);
+
+int main(void)
+{
+    psXYArray *t = psXYArrayAlloc(10, 15);
+    psXYPtrArray *pt = psXYPtrArrayAlloc(10, 10);
+
+    for (int i = 0; i < t->n; i++) {
+        t->arr[i].x = i;
+        pt->arr[i]->y = 10*i;
+    }
+
+    t = psXYArrayRealloc(t, 5);
+    t = psXYArrayRealloc(t, 8);
+
+    for (int i = 0; i < t->n; i++) {
+        printf("%d %d  ", t->arr[i].x, pt->arr[i]->y);
+    }
+    printf("\n");
+    
+    psXYArrayFree(t);
+
+    psXY *xy = psMemDecrRefCounter(pt->arr[0]);
+    pt->arr[0] = NULL;
+    psXYFree(xy);    
+    
+    psXYPtrArrayFree(pt);
+
+    psMemCheckLeaks(0, NULL, stderr);
+
+    return 0;
+}
+\end{verbatim}
+
+\subsection{Doubly-linked lists}
 \hlabel{psDlist}
 
@@ -843,169 +1048,4 @@
 \code{psDlist}).
 
-\subsection{The \PS{} Array types}
-
-\subsubsection{Arrays of Simple Types}
-
-Any \PS{} datatype \code{psType} may be associated with an array type
-\code{psTypeArray}:
-\begin{verbatim}
-typedef struct {
-  int size;
-  int n;
-  psType *arr;
-} psTypeArray;
-\end{verbatim}
-with associated constructors and a destructor:
-\begin{verbatim}
-psTypeArray *psTypeAlloc(int n, int size);
-psTypeArray *psTypeRealloc(psTypeArray *arr, int n);
-void psTypeFree(psTypeArray *arr);  
-\end{verbatim}
-
-The argument \code{n} is the dimension of the array; \code{size}
-is the number of elements allocated ($s \ge n$).
-
-This type and functions may be declared and defined using two macros,
-\code{PS_DECLARE_ARRAY_TYPE(psType)} and
-\code{PS_CREATE_ARRAY_TYPE(psType)}.  The former defines the
-\code{typedef} and declares the prototypes (and is thus suitable for
-use in a header file); the latter generates the code for the three
-functions \code{psType(Alloc|Realloc|Free)} (and should thus appear in
-exactly one source file for a given type).
-
-The \code{psType} should be a single word (e.g. \code{psXY}); in particular,
-there is no requirement to support a pointer type (\eg{} \code{psXY *});
-see next section.
-
-\subsubsection{Arrays of Pointer Types}
-
-The data type created with \code{PS_CREATE_ARRAY_TYPE} (\code{psType})
-contains an array of \code{psType}s not
-pointers to \code{psType}s; this means that the individual elements are
-not allocated using \code{psTypeAlloc}, are not correctly initialized,
-and shouldn't be individually deleted with \code{psTypeFree};
-
-If you wish to use arrays of pointers, use the macros
-\code{PS_DECLARE_ARRAY_PTR_TYPE(psType)} and
-\code{PS_CREATE_ARRAY_PTR_TYPE(psType)}. These
-create types \code{typedef psType *psTypePtr} and \code{psTypePtrArray}:
-\begin{verbatim}
-typedef struct {
-  int size;
-  int n;
-  psTypePtr *arr;
-} psTypePtrArray;
-\end{verbatim}
-with associated constructors and a destructor:
-\begin{verbatim}
-psTypePtrArray *psTypePtrAlloc(int n, int size);
-psTypePtrArray *psTypePtrRealloc(psTypePtrArray *arr, int n);
-void psTypePtrArrayFree(psTypePtrArray *arr);  
-\end{verbatim}
-
-These constructors create arrays of \code{psType *} and call
-\code{psTypeAlloc} and \code{psTypeFree} to allocate and free the
-elements. As for the simple arrays, The former defines the typedef and
-declares the prototypes (and is thus suitable for use in a header
-file) and the latter generates the code for the three functions
-\code{psType(Alloc|Realloc|Free)} (and should thus appear in exactly one
-source file for a given type).
-
-The objects pointed to by these types have had their \code{refCounter}s
-incremented (see \ref{secMemRefcounter}); to remove an element from the array you
-need to say something like:
-\begin{verbatim}
-  psTypePtrArray *pt = psTypePtrArrayAlloc(10, 10);
-  psType *xy = psMemDecrRefCounter(pt->arr[0]);
-  pt->arr[0] = NULL;
-\end{verbatim}
-
-\subsubsection{Arrays of \texttt{void *}}
-\hlabel{secArrayVoidPtr}
-
-Arrays of \code{void *} are different, as they need an explicitly-specified
-destructor.
-
-We require a type \code{psVoidPtrArray} that behaves in all respects
-as if it had been created with:
-\begin{verbatim}
-typedef void *psVoidPtr;
-PS_DECLARE_ARRAY_TYPE(psVoidPtr);
-PS_CREATE_ARRAY_TYPE(psVoidPtr);
-\end{verbatim}
-except that its destructor is specified as:
-\begin{verbatim}
-void psVoidPtrArrayFree(psVoidPtrArray *arr,      // array to destroy
-                       void (*elemFree)(void *)); // destructor for array data
-\end{verbatim}
-
-The routine \code{psVoidPtrArrayFree} assumes that all pointers
-had their reference counters incremented
-when they were inserted onto the array.\footnote{%
-  \eg{} \code{va->arr[i] = psMemIncrRefCounter(ptr);}}
-
-If \code{psVoidPtrArrayFree}'s argument \code{elemFree} is NULL, the
-list should be deleted, but not the elements on it (although their
-\code{refcounter}'s should be decremented).
-
-\subsubsection{Examples of Array Types}
-
-The following is a complete C program that illustrates the use of
-\code{array}s.
-\begin{verbatim}
-#include "psLib.h"
-
-typedef struct {
-    int x, y;
-} psXY;
-
-psXY *psXYAlloc(void)
-{
-    return psAlloc(sizeof(psXY));
-}
-
-void psXYFree(psXY *xy)
-{
-    psFree(xy);
-}
-
-PS_DECLARE_ARRAY_TYPE(psXY);
-PS_CREATE_ARRAY_TYPE(psXY);
-
-PS_DECLARE_ARRAY_PTR_TYPE(psXY);
-PS_CREATE_ARRAY_PTR_TYPE(psXY);
-
-int main(void)
-{
-    psXYArray *t = psXYArrayAlloc(10, 15);
-    psXYPtrArray *pt = psXYPtrArrayAlloc(10, 10);
-
-    for (int i = 0; i < t->n; i++) {
-        t->arr[i].x = i;
-        pt->arr[i]->y = 10*i;
-    }
-
-    t = psXYArrayRealloc(t, 5);
-    t = psXYArrayRealloc(t, 8);
-
-    for (int i = 0; i < t->n; i++) {
-        printf("%d %d  ", t->arr[i].x, pt->arr[i]->y);
-    }
-    printf("\n");
-    
-    psXYArrayFree(t);
-
-    psXY *xy = psMemDecrRefCounter(pt->arr[0]);
-    pt->arr[0] = NULL;
-    psXYFree(xy);    
-    
-    psXYPtrArrayFree(pt);
-
-    psMemCheckLeaks(0, NULL, stderr);
-
-    return 0;
-}
-\end{verbatim}
-
 \subsection{Hash Tables}
 \hlabel{psHash}
@@ -1069,48 +1109,10 @@
 key from the table, and returns the \code{data}; if the key's invalid it returns NULL.
 
-\subsection{Miscellaneous Utilities}
-
-\begin{verbatim}
-#define PS_STRING(S) #S                 // converts argument S to string
-    
-/// Prints an error message and aborts
-void psAbort(const char *name,          ///< Category of code that caused the abort
-             const char *fmt,           ///< Format
-             ...                        ///< Extra arguments to use format
-             );
-
-/// Prints an error message and doesn't abort
-void psError(const char *name,          ///< Category of code that caused the abort
-             const char *fmt,           ///< Format
-             ...                        ///< Extra arguments to use format
-    );
-
-/// Allocates and returns a copy of a string
-char *psStringCopy(const char *str      ///< string to copy
-    );
-
-/// Allocates nChar and returns a copy of the string or segment
-char *psStringNCopy(const char *str,    ///< string to copy
-                    int nChar           //!< Number of characters (including \0 )
-    );
-\end{verbatim}
-
-\code{psAbort} shall call \code{psMsgLog} with a level of \code{PS_LOG_ABORT},
-and then call \code{abort}.
-\code{psError} shall call \code{psMsgLog} with a level of \code{PS_LOG_ERROR},
-and then return.
-In cases of doubt, a good choice for
-\code{name} is \code{__func__}.
-
-\code{psStringCopy} shall allocate and return a copy of the input string.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 \section{Data manipulation}
 
-We require general data manipulation functions, which will act upon
-data (in particular, arrays/vectors).  We require the following capabilities:
+There are a number of data concepts which can be naturally represented
+in C as structures.  We require a variety of basic data manipulation
+functions which will act upon data (in particular, arrays/vectors).
+We require the following capabilities:
 \begin{itemize}
 \item Bit masks;
@@ -1186,85 +1188,4 @@
     );
 \end{verbatim}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\subsection{Vector and Image Arithmetic}
-
-We will need to be able to perform various operations on vectors and
-images, e.g.\ dividing one image by another, subtracting a vector
-from an image, etc.  Both binary operations and unary operations are
-required.
-
-\begin{verbatim}
-/** Perform a binary operation on two data items (psImage, psVector, psScalar).
-*/
-psType *
-psBinaryOp (void *out,                  ///< destination (may be NULL)
-            void *in1,                  ///< first input
-            char *operator,             ///< operator
-            void *in2                   ///< second input
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Perform a binary operation on two data items (psImage, psVector, psScalar).
-*/
-psType *
-psUnaryOp (void *out,                   ///< destination (may be NULL)
-           void *in,                    ///< input
-           char *operator,              ///< operator
-    );
-\end{verbatim}
-
-Note that these functions should return the appropriate type (i.e.,
-the \code{psType} return type refers to \code{psVector} and
-\code{psImage} and \code{psScalar}).  It is expected that the
-implementation of these functions will employ pre-processor macros to
-perform the onerous task of creating the loops.
-
-It is desirable to use the same functions for both vectors and
-images, so inputs are \code{void*}; this necessitates that vectors
-and images each have a type element at a pre-determined and constant
-location in the \code{struct}.  It is further desirable to allow
-scalar values to be used within these functions, which requires the
-following additions:
-
-\begin{verbatim}
-/** create a psType-ed structure from a constant value. */
-p_ps_Scalar *
-psScalar (double value);
-\end{verbatim}
-
-\begin{verbatim}
-/** create a psType-ed structure from a specified type  */
-p_ps_Scalar *
-psScalarType (char *mode,               ///< type description 
-              ...                       ///< value (or values) of specified types
-);
-\end{verbatim}
-
-\begin{verbatim}
-/** private structure used to pass constant values into the math operators. */
-typedef struct {
-    psType type;                        ///< data type information
-    union {                            
-        int i;                          ///< integer value entry
-        float f;                        ///< float value entry
-        double d;                       ///< double value entry
-        complex float c;                ///< complex value entry
-    } val;
-} p_psScalar;
-\end{verbatim}
-
-This allows one to write the following to take the sine of the square
-of all pixels in an image:
-\begin{verbatim}
-psImage A,B;
-
-B = psBinaryOp (NULL, A, "^", psScalar(2));
-(void) psUnaryOp(B, B, "sin");
-\end{verbatim}
-
-Note that the \code{psUnaryOp} is performed on \code{B} in-place.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1546,5 +1467,5 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\subsection{General functions}
+\subsection{Analytical functions}
 
 We require two types of general functions which will be used in fitting:
@@ -1637,5 +1558,5 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\subsection{Minimisation and fitting routines}
+\subsection{Minimization and fitting routines}
 
 We require a general minimisation routine, a routine that will
@@ -1678,26 +1599,5 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\section{Astronomy-Specific Functions}
-
-Some basic, relatively simple astronomy-specific functions are
-required which will serve as the foundation for building the Phase $N$
-modules.  These functions are not expected to cover every forseeable
-function, but will serve as the building blocks of more complicated
-processing functions.
-
-We require functions covering each of the following areas:
-\begin{itemize}
-\item Astrometry;
-\item Dates and times;
-\item Image handling;
-\item Metadata;
-\item Detector and sky positions;
-\item Astronomical objects; and
-\item Photometry.
-\end{itemize}
-These are each dealt with below.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Image handling}
+\subsection{Simple Images}
 
 The most important data product produced by the telescope is an image.
@@ -2118,535 +2018,283 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-\subsection{Astrometry}
-
-Astrometry is a basic functionality required for the IPP that will be
-used repeatedly, both for low-precision (roughly where is my favourite
-object?) and high-precision (what is the proper motion of this star?).
-As such, it must be flexible, yet robust.  Accordingly, we will wrap
-the StarLink Astronomy Libraries (SLALib), which has already been
-developed.
-
-\subsubsection{Terminology}
-
-Some brief review of terminology would be useful so that previous
-definitions do not influence the understanding of this document.
-
-A ``readout'' is a read of the detector.
-
-A ``cell'' is defined as the smallest element of the detector readout;
-usually associated with an amplifier.  Correspondingly, each cell has
-its own overscan region.  There may be multiple readouts in a cell if
-the cell was used to provide fast guiding.
-
-A ``chip'' is defined as a contiguous piece of silicon, and consists
-of a group of cells.
-
-A ``focal plane'' is defined as a mosaic of chips, and consists of a
-group of chips.
-
-For example, take a mosaic camera consisting of eight $2k\times 4k$
-CCDs, each of which is read out through two amplifiers.  Then there
-would be sixteen cells in total, each of which is presumably $2k\times
-2k$.  There would be eight chips, each consisting of two cells, and
-the focal plane consists of these eight chips.
-
-As another example, consider an observation by PS1.  The focal plane
-would consist of 60 chips, each of which consist of 64 cells (or less;
-a few cells may be dead).  Some cells (those containing guide stars
-for the orthogonal transfer) will contain multiple readouts.
-
-\subsubsection{Coordinate frames}
-\label{sec:coordinateFrames}
-
-There are five coordinate frames that we need to worry about for the
-purposes of astrometry:
+\subsection{Vector and Image Arithmetic}
+
+We will need to be able to perform various operations on vectors and
+images, e.g.\ dividing one image by another, subtracting a vector
+from an image, etc.  Both binary operations and unary operations are
+required.
+
+\begin{verbatim}
+/** Perform a binary operation on two data items (psImage, psVector, psScalar).
+*/
+psType *
+psBinaryOp (void *out,                  ///< destination (may be NULL)
+            void *in1,                  ///< first input
+            char *operator,             ///< operator
+            void *in2                   ///< second input
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Perform a binary operation on two data items (psImage, psVector, psScalar).
+*/
+psType *
+psUnaryOp (void *out,                   ///< destination (may be NULL)
+           void *in,                    ///< input
+           char *operator,              ///< operator
+    );
+\end{verbatim}
+
+Note that these functions should return the appropriate type (i.e.,
+the \code{psType} return type refers to \code{psVector} and
+\code{psImage} and \code{psScalar}).  It is expected that the
+implementation of these functions will employ pre-processor macros to
+perform the onerous task of creating the loops.
+
+It is desirable to use the same functions for both vectors and
+images, so inputs are \code{void*}; this necessitates that vectors
+and images each have a type element at a pre-determined and constant
+location in the \code{struct}.  It is further desirable to allow
+scalar values to be used within these functions, which requires the
+following additions:
+
+\begin{verbatim}
+/** create a psType-ed structure from a constant value. */
+p_ps_Scalar *
+psScalar (double value);
+\end{verbatim}
+
+\begin{verbatim}
+/** create a psType-ed structure from a specified type  */
+p_ps_Scalar *
+psScalarType (char *mode,               ///< type description 
+              ...                       ///< value (or values) of specified types
+);
+\end{verbatim}
+
+\begin{verbatim}
+/** private structure used to pass constant values into the math operators. */
+typedef struct {
+    psType type;                        ///< data type information
+    union {                            
+        int i;                          ///< integer value entry
+        float f;                        ///< float value entry
+        double d;                       ///< double value entry
+        complex float c;                ///< complex value entry
+    } val;
+} p_psScalar;
+\end{verbatim}
+
+This allows one to write the following to take the sine of the square
+of all pixels in an image:
+\begin{verbatim}
+psImage A,B;
+
+B = psBinaryOp (NULL, A, "^", psScalar(2));
+(void) psUnaryOp(B, B, "sin");
+\end{verbatim}
+
+Note that the \code{psUnaryOp} is performed on \code{B} in-place.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{Astronomy-Specific Functions}
+
+Some basic, relatively simple astronomy-specific functions are
+required which will serve as the foundation for building the Phase $N$
+modules.  These functions are not expected to cover every forseeable
+function, but will serve as the building blocks of more complicated
+processing functions.
+
+We require functions covering each of the following areas:
 \begin{itemize}
-\item Cell: $(x,y)$ in pixels --- raw coordinates;
-\item Chip: $(X,Y)$ in pixels --- the location on the silicon;
-\item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;
-\item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and
-\item Sky: (RA,Dec) --- ICRS.
+\item Astrometry;
+\item Dates and times;
+\item Image handling;
+\item Metadata;
+\item Detector and sky positions;
+\item Astronomical objects; and
+\item Photometry.
 \end{itemize}
-
-The following steps are required to convert from the cell coordinates to
-the sky:
-\begin{itemize}
-\item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;
-\item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;
-\item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =
-h(p,q,m,c)$, where $m$ and $c$ are the magnitude and colour of the
-object, respectively; and
-\item TP $\longleftrightarrow$ Sky: SLALib transformation using a
-transform pre-computed for each pointing.
-\end{itemize}
-
-Note that the transformation between the Focal Plane and the Tangent
-Plane is a four-dimensional polynomial, in order to account for any
-possible dependencies in the astrometry on the stellar magnitude and
-colour; the former serves as a check for charge transfer
-inefficiencies, while the latter will correct chromatic refraction,
-both through the atmosphere and the corrector lenses.
-
-\textbf{[If the magnitude terms serve to check CTI, then shouldn't we
-put them in the cell $\leftrightarrow$ chip section?]}
-
-We require structures to contain each of the above transformations as
-well as the pixel data.
-
-\subsubsection{A Readout}
-
-A readout is the result of a single read of a cell (or a portion
-thereof).  It contains a pointer to the pixel data, a separate pointer
-to the overscan pixels, and additional pointers to the objects found
-in the readout, and the readout metadata.  It also contains the offset
-from the lower-left corner of the chip, in the case that the CCD was
-windowed.
-
-\begin{verbatim}
-/** a Readout: a collection of pixels */
-typedef struct {
-    int x0, y0;                         //!< Offset from the lower-left corner
-    psImage *image;                     ///< imaging area of cell 
-    psDlist *objects;                   ///< objects derived from cell
-    psImage *overscan;                  ///< bias region (subimage) of cell
-    psMetaDataSet *md;                  //!< Readout-level metadata
-} psReadout;
-\end{verbatim}    
-
-
-\subsubsection{A Cell}
-
-A cell consists of one or more readouts (usually only one except in the
-case that the cell has been used for fast guiding).  It also contains
-a pointer to the cell metadata, and a pointer to its parent chip.  On
-the astrometry side, it also contains coordinate transforms from the
-cell to the chip and, as a convenience, from the cell to the focal
-plane.  It is expected that these transforms will consist of two
-first-order 2D polynomials, simply specifying a translation, rotation
-and magnification; hence they are easily inverted, and there is no
-need to add reverse transformations.  We also add an additional
-transformation, which is intended to provide a ``quick and dirty''
-transform from the cell coordinates to the sky; this transformation
-not guaranteed to be as precise as the ``standard'' transformation of
-Cell $\rightarrow$ Chip $\rightarrow$ Focal Plane $\rightarrow$
-Tangent Plane $\rightarrow$ Sky, but will be faster.
-
-\begin{verbatim}
-/** a Cell: a collection of readouts.
+These are each dealt with below.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\subsection{Dates and times}
+
+\textbf{[May be deferred.]}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\subsection{Detector and sky positions}
+
+Both detector and sky positions will be used extensively in the IPP.
+Since these both contain two coordinates with their associated errors,
+we bundle these into a single generic structure, \code{psCoord},
+containing \code{union}s to handle the semantic differences.
+
+\begin{verbatim}
+/** A point in 2-D space, with errors.
+ */
+typedef union {
+    struct {
+        double x;                       //!< x position
+        double y;                       //!< y position
+        double xErr;                    //!< Error in x position
+        double yErr;                    //!< Error in y position
+    } xy;
+    struct {
+        double r;                       //!< RA
+        double d;                       //!< Dec
+        double rErr;                    //!< Error in RA
+        double dErr;                    //!< Error in Dec
+    } rd;
+} psCoord;
+\end{verbatim}
+
+\subsubsection{Transformations}
+
+We specify two types of transforms between coordinate systems.  The
+first consists simply of two 2D polynomials to transform both
+components; this will be used to apply the coordinate transformations
+between Cells, Chips and the Focal Plane.  The second consists of two
+4D polynomials; this will be used to apply position-, colour- and
+magnitude-dependent distortions between the Focal Plane and the
+Tangent Plane.
+
+\begin{verbatim}
+/** A polynomial transformation between coordinate frames.  This may be a linear relationship, or may
+ *  represent a higher-order transformation.
  */
 typedef struct {
-    int nReadouts;                      ///< number of readouts in this cell realization; each may have its own
-                                        ///< image, objects and overscan.
-    struct psReadout *readouts;         //!< Readouts from the cell
-    psMetaDataSet *md;                  ///< Cell-level metadata
-
-    psCoordXform *cellToChip;           ///< Transformations from cell coordinates to chip coordinates
-    psCoordXform *cellToFPA;            ///< Transformations from cell coordinates to FPA coordinates
-    psCoordXform *cellToSky;            ///< Quick and Dirty transformations from cell coordinates to sky
-
-    struct psChip  *parentChip;         ///< chip which contains this cell
-} psCell;
-\end{verbatim}
-
-
-\subsubsection{A Chip}
-
-A chip consists of one or more cells (according to the number of
-amplifiers on the CCD).  It contains a pointer to the chip metadata,
-and a pointer to the parent focal plane.  For astrometry, it contains
-a coordinate transform from the chip to the focal plane.  It is
-expected that this transforms will consist of two second-order 2D
-polynomials; hence we expect that it is prudent to include a reverse
-transformation which will be derived from numerically inverting the
-forward transformation.
-
-\begin{verbatim}
-/** a Chip: a collection of cells.  Not all valid cells in a chip need to be listed in an
- *  instance of psChip.
+    psDPolynomial2D *x;
+    psDPolynomial2D *y;
+} psCoordXform;
+\end{verbatim}
+
+\begin{verbatim}
+/** The optical distortion terms.  The lowest two terms are the x and y axis of the target system.  The higher
+ *  two terms represent magnitude and color terms.
  */
 typedef struct {
-    int nCells;                         ///< Number of Cells assigned
-    psCell *cells;                      ///< Cells in the Chip
-
-    psMetaDataSet *md;                  ///< Chip-level metadata
-    psCoordXform *chipToFPA;            ///< Transformations from chip coordinates to FPA coordinates
-    psCoordXform *FPAtoChip;            //!< Transformations from FPA coordinates to chip
-
-    struct psFPA *parentFPA;            ///< FPA which contains this chip
-} psChip;
-\end{verbatim}
-
-\subsubsection{A Focal Plane}
-
-A focal plane consists of one or more chips (according to the number
-of pieces of contiguous silicon).  It contains pointers to the focal
-plane metadata and the exposure information.  For astrometry, it
-contains a transformation from the focal plane to the tangent plane
-and the fixed pattern residuals.  It is expected that the
-transformation will consist of two 4D polynomials (i.e.\ a function of
-two coordinates in position, the magnitude of the object, and the
-colour of the object) in order to correct for optical distortions and
-the effects of the atmosphere; hence we expect that it is prudent to
-include a reverse transformation which will be derived from
-numerically inverting the forward transformation.  Since colours are
-involved in the transformation, it is necessary to specify the colour
-the transformation is defined for.  We also include some values to
-characterise the quality of the transformation: the root mean square
-deviation for the x and y transformation fits, and the $\chi^2$ for
-the transformation fit.
-
-\begin{verbatim}
-/** a Focal plane array: a collection of chips.  Not all chips in a camera need to be listed in an instance of
- *  psFPA.
- */
-typedef struct {
-    int nChips;                         ///< Number of Cells assigned
-    int nAlloc;                         ///< Number of Cells available
-    psChip *chips;                      ///< Chips in the Focal Plane Array
-
-    psMetaDataSet *md;                  ///< FPA-level metadata 
-    psDistortion *TPtoFP;               ///< Transformation term from 
-    psDistortion *FPtoTP;               ///< Transformation term from 
-    psFixedPattern *pattern;            //!< Fixed pattern residual offsets
-    psExposure *exp;                    ///< information about this exposure
-    psPhotSystem colorPlus, colorMinus; ///< Colour reference
-    float rmsX, rmsY;                   //!< Dispersion in astrometric solution
-    float chi2;                         //!< chi^2 of astrometric solution
-} psFPA;
-\end{verbatim}
-
-
-\subsubsection{SLALib information}
-
-SLALib requires several elements to perform the transformations
-between the tangent plane and the sky.  Pre-computing these quantities
-for each exposure means that subsequent transformations are faster.
-For historical reasons, this structure is known colloquially as
-``Wallace's Grommit''.
-
-\begin{verbatim}
-/** Information needed (by SLALib) to convert Apparent to Observed Position */
-typedef struct {
-    double latitude;                    ///< geodetic latitude (radians)
-    double sinLat, cosLat;              ///< sine and cosine of geodetic latitude
-    double abberationMag;               ///< magnitude of diurnal aberration vector
-    double height;                      ///< height (HM)
-    double temperature;                 ///< ambient temperature (TDK)
-    double pressure;                    ///< pressure (PMB)
-    double humidity;                    ///< relative humidity (RH)
-    double wavelength;                  ///< wavelength (WL)
-    double lapseRate;                   ///< lapse rate (TLR)
-    double refractA, refractB;          ///< refraction constants A and B (radians)
-    double longitudeOffset;             ///< longitude + eqn of equinoxes + ``sidereal UT'' (radians)
-    double siderealTime;                ///< local apparent sidereal time (radians)
-} psGrommit;
-\end{verbatim}
-
-
-\subsubsection{Exposure information}
-
-We need several quantities from the telescope in order to make a
-first guess at the astrometric solution.  From these quantities,
-further quantities can be derived and stored for later use.
-
-\begin{verbatim}
-/** Exposure information from the telescope */
-typedef struct {
-    // Telescope longitude, latitude and height are stored separately, since they don't change with pointing
-    double ra, dec;                     //!< Telescope boresight
-    double ha;                          //!< Hour angle
-    double zd;                          //!< Zenith distance
-    double az;                          //!< Azimuth
-    double lst;                         //!< Local Sidereal Time
-    float mjd;                          //!< MJD of observation
-    float rotAngle;                     //!< Rotator position angle
-    float temp;                         //!< Air temperature, for estimating refraction
-    float pressure;                     //!< Air pressure, for calculating refraction
-    float humidity;                     //!< Relative humidity, for calculating refraction
-    float exptime;                      //!< Exposure time
-    /* Derived quantities */
-    float posAngle;                     //!< Position angle
-    float parallactic;                  //!< Parallactic angle
-    float airmass;                      //!< Airmass, calculated from zenith distance
-    float pf;                           //!< Parallactic factor
-    char *cameraName;                   ///< name of camera which provided exposure
-    char *telescopeName;                ///< name of telescope which provided exposure
-    psGrommit *grommit;                 //!< Data needed to convert from the sky to the tangent plane
-} psExposure;
-\end{verbatim}
-
-
-\subsubsection{Fixed Pattern}
-
-The fixed pattern is a correction to the general astrometric solution
-formed by summing the residuals from many observations.  The intent is
-to correct for higher-order distortions in the camera system on a
-coarse grid (larger than individual pixels, but smaller than a single
-cell).  Hence, in addition to the offsets, we need to specify the size
-and scale of the grid in $x$ and $y$, as well as the origin of the
-grid.
-
-\begin{verbatim}
-/** The fixed pattern residual offsets.  These are specified via a coarse grid of x and y offsets. */
-typedef struct {
-    int nX, nY;                         //!< Number of elements in x and y
-    double x0, y0;                      //!< Position of the lower-left corner of the grid on the focal plane
-    double xScale, yScale;              //!< Scale of the grid
-    double **x, **y;                    //!< The grid of offsets in x and y
-} psFixedPattern;
-\end{verbatim}
-
-
-\subsubsection{Constructors and Destructors}
-
-Each of the above structures needs an appropriate constructor and
-destructor.  Other than \code{psExposure}, which contains significant
-non-pointer types, the constructors should not take any arguments, and
-the destructors should only take the structure to be destroyed.
-The constructor for \code{psExposure} is specified below.
-
-\begin{verbatim}
-/** Constructor */
-psExposure *
-psExposureAlloc(double ra, double dec,  //!< Telescope boresight
-                double ha,              //!< Hour angle
-                double zd,              //!< Zenith distance
-                double az,              //!< Azimuth
-                double lst,             //!< Local Sidereal Time
-                float mjd,              //!< MJD
-                float rotAngle,         //!< Rotator position angle
-                float temp,             //!< Temperature
-                float pressure,         //!< Pressure
-                float humidity,         //!< Relative humidity
-                float exptime           //!< Exposure time
-                );
-\end{verbatim}
-
-
-\subsubsection{Finding}
-
-We require functions to return the structure containing given
-coordinates.  For example, we want the chip that corresponds to the
-focal plane coordinates $(p,q) = (-1.234,+5.678)$.  These routines
-handle the one-to-many problem --- i.e., for one given focal plane
-coordinate, there are many chips that this coordinate may be
-correspond to; these functions will select the correct one.
-
-
-\begin{verbatim}
-/** returns Chip in FPA which contains the given FPA coordinate */
-psChip *
-psChipInFPA (psChip *out,               //!< Chip to return, or NULL
-             const psFPA *fpa,          ///< FPA description
-             const psCoord *coord       ///< coordinate in FPA
-             );
-\end{verbatim}
-
-\begin{verbatim}
-/** returns Cell in Chip which contains the given chip coordinate */
-psCell *
-psCellInChip(psCell *out,               //!< Cell to return, or NULL
-             const psChip *chip,        ///< chip description
-             const psCoord *coord       ///< coordinate in chip
-             );
-\end{verbatim}
-
-Usually we will want to go directly from the FPA to the Cell, so we
-also specify the following function, which performs the above two
-functions in order.
-
-\begin{verbatim}
-/** Return the cell in FPA which contains the given FPA coordinates */
-psCell *
-psCellInFPA(psCell *out,                //!< Cell to return, or NULL
-            const psFPA *fpa,           //!< FPA description
-            const psCoord *coord        //!< Coordinate in FPA
-            );
-\end{verbatim}
-
-
-
-\subsubsection{Conversion Functions}
-
-We require functions to convert between the various coordinate frames
-(Section~\ref{sec:coordinateFrames}).  The heirarchy of the coordinate
-frames and the transformations between each are shown in
-Figure~\ref{fig:coco}.  The functions that employ the transformations
-are shown in Figure~\ref{fig:cocoFunc}.  In addition to
-transformations between each adjoining coordinate frame in the
-heirarchy, we also require higher-level functions to convert between
-the Cell and Sky coordinate frames; these will simply perform the
-intermediate steps.
-
-\begin{figure}
-\psfig{file=coordinateFrames.ps,height=7in,angle=-90}
-\caption{The coordinate systems in the \PS{} IPP, and the relation
-between each by transformations contained in the appropriate
-structures.}
-\label{fig:coco}
-\end{figure}
-
-\begin{figure}
-\psfig{file=coordinateConv.ps,height=7in,angle=-90}
-\caption{Conversion between coordinate systems by PSLib.}
-\label{fig:cocoFunc}
-\end{figure}
-
-The function prototypes are:
-
-\begin{verbatim}
-/** Convert (RA,Dec) to cell and cell coordinates */
+    psDPolynomial4D *x;
+    psDPolynomial4D *y;
+} psDistortion;
+\end{verbatim}
+
+We require corresponding functions to apply the transformations:
+
+\begin{verbatim}
+/** apply the coordinate transformation to the given coordinate */
+psCoord *psCoordXformApply (psCoord *out, //!< Output coordinates, or NULL
+                            const psCoordXform *frame, ///< coordinate transformation
+                            const psCoord *coords ///< input coordiate
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** apply the optical distortion to the given coordinate, magnitude, color */
+psCoord *psDistortionApply (psCoord *out, //!< Output coordinates, or NULL
+                            const psdistortion *pattern, ///< optical distortion pattern
+                            const psCoord *coords, ///< input coordinate
+                            float mag,  ///< magnitude of object
+                            float color ///< color of object
+    );
+\end{verbatim}
+
+
+\subsubsection{Offsets}
+
+We require a function to calculate the offset between two positions on
+the sky, as well as a function to apply an offset to a position.
+
+\begin{verbatim}
+/** Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical */
 psCoord *
-psCoordSkyToCell(psCoord *out,          //!< Coordinates to return, or NULL
-                 psCell *cell,          //!< Cell to return
-                 const psFPA *fpa       //!< FPA description
-                 );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert cell and cell coordinate to (RA,Dec) */
+psGetOffset(const psCoord *restrict position1, //!< Position 1
+            const psCoord *restrict position2, //!< Position 2
+            const char *type            //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Apply an offset to a position */
 psCoord *
-psCoordCellToSky(psCoord *out,          //!< Coordinates to return, or NULL
-                 const psCell *cell,    //!< Cell to get coordinates for
-                 const psCoord *coord   //!< cell coordinates to transform
-                 );
-\end{verbatim}
-
-\begin{verbatim}
-/** Quick and dirty cell to (RA,Dec) --- employs cellToSky transformation */
+psApplyOffset(const psCoord *restrict position, //!< Position
+              const psCoord *restrict offset, //!< Offset
+              const char *type          //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
+    );
+\end{verbatim}
+
+
+\subsubsection{Positions of Major SS Objects}
+
+We require the ability to calculate the position of major Solar System
+objects, as well as Lunar phase.
+
+\begin{verbatim}
+/** Get Sun Position */
 psCoord *
-psCoordCellToSkyQuick(psCoord *out,     //!< Coordinates to return, or NULL
-                      const psCell *cell, //!< Cell description
-                      const psCoord *coord //!< cell coordinates to transform
-                      );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert (RA,Dec) to tangent plane coords */
+psGetSunPos(float mjd                   //!< MJD to get position for
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Get Moon position */
 psCoord *
-psCoordSkyToTP(psCoord *out,            //!< Coordinates to return, or NULL
-               const psExposure *exp,   //!< Exposure description
-               const psCoord *coord     //!< input Sky coordinate
-               );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert tangent plane coords to focal plane coordinates */
+psGetMoonPos(float mjd,                 //!< MJD to get position for
+             double latitude,           //!< Latitude for apparent position
+             double longitude           //!< Longitude for apparent position
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Get Moon phase */
+float
+psGetMoonPhase(float mjd                //!< MJD to get phase for
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Get Planet positions */
 psCoord *
-psCoordTPtoFPA(psCoord *out,            //!< Coordinates to return, or NULL
-               const psFPA *fpa,        //!< FPA description
-               const psCoord *coord     //!< input TP coordinate
-               );
-\end{verbatim}
-
-\begin{verbatim}
-/** converts the specified FPA coord to the coord on the given Chip */
+psGetSolarSystemPos(const char *solarSystemObject, //!< Named S.S. object
+                    float mjd           //!< MJD to get position for
+    );
+\end{verbatim}
+
+\subsubsection{Celestial Coordinate Conversions}
+
+We need to be able to convert between ICRS, Galactic and Ecliptic
+coordinates.
+
+\begin{verbatim}
+/** Convert ICRS to Ecliptic */
 psCoord *
-psCoordFPAtoChip (psCoord *out,         //!< Coordinates to return, or NULL
-                  const psChip *chip,   ///< Chip of interest
-                  const psCoord *coord  ///< input FPA coordinate
-                  ); 
-\end{verbatim}
-
-\begin{verbatim}
-/** converts the specified Chip coord to the coord on the given Cell */
+psCoordinatesItoE(const psCoord *restrict coordinates //!< ICRS coordinates to convert
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert Ecliptic to ICRS */
 psCoord *
-psCoordChiptoCell (psCoord *out,        //!< Coordinates to return, or NULL
-                   const psCell *cell,  ///< Cell of interest
-                   const psCoord *coord ///< input Chip coordinate
-                   );
-\end{verbatim}
-
-\begin{verbatim}
-/** converts the specified Cell coord to the coord on the parent Chip */
+psCoordinatesEtoI(const psCoord *restrict coordinates //!< Ecliptic coordinates to convert
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert ICRS to Galactic */
 psCoord *
-psCoordCelltoChip (psCoord *out,        //!< Coordinates to return, or NULL
-                   const psCell *cell,  ///< Cell description
-                   const psCoord *coord ///< input Cell coordinate
-                   );
-\end{verbatim}
-
-\begin{verbatim}
-/** converts the specified Chip coord to the coord on the parent FPA */
+psCoordinatesItoG(const psCoord *restrict coordinates //!< ICRS coordinates to convert
+    );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert Galactic to ICRS */
 psCoord *
-psCoordChiptoFPA (psCoord *out,         //!< Coordinates to return, or NULL
-                  const psChip *chip,   ///< Chip description
-                  const psCoord *coord  ///< input Chip coordinate
-                  );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert focal plane coords to tangent plane coordinates */
-psCoord *
-psCoordFPAToTP(psCoord *out,            //!< Coordinates to return, or NULL
-               const psFPA *fpa,        //!< FPA description
-               const psCoord *coord     //!< input FPA coordinate
-               );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert tangent plane coords to (RA,Dec) */
-psCoord *
-psCoordTPtoSky(psCoord *out,            //!< Coordinates to return, or NULL
-               const psExposure *exp,   //!< Exposure description
-               const psCoord *coord     //!< input TP coordinate
-               );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert Cell coords to FPA coordinates */
-psCoord *
-psCoordCellToFPA(psCoord *out,          //!< Coordinates to return, or NULL
-                 const psCell *cell,    //!< Cell description
-                 const psCoord *coord   //!< Input cell coordinates
-                 );
-\end{verbatim}
-
-\subsubsection{Additional functions}
-
-We require additional functions to perform general functions which
-will be useful for astrometry.  Given coordinates on the sky, we
-need to get the airmass, the parallactic angle, and an estimate of
-the atmospheric refraction.
-
-\begin{verbatim}
-/** Get the airmass for a given position and sidereal time */
-float
-psGetAirmass(const psCoord *coord,      //!< Position on the sky
-             double siderealTime,       //!< Sidereal time
-             float height               //!< Height above sea level
-             );
-\end{verbatim}
-
-\begin{verbatim}
-/** Get the parallactic angle for a given position and sidereal time */
-float
-psGetParallactic(const psCoord *coord,  //!< Position on the sky
-                 double siderealTime    //!< Sidereal time
-                 );
-\end{verbatim}
-
-\begin{verbatim}
-/** Estimate atmospheric refraction, along the parallactic */
-float
-psGetRefraction(float colour,           //!< Colour of object
-                psPhotSystem colorPlus, ///< Colour reference
-                psPhotSystem colorMinus, ///< Colour reference
-                const psExposure *exp   //!< Telescope pointing information, for airmass, temp and pressure
-                );
-\end{verbatim}
-
-\begin{verbatim}
-/** Calculate the parallax factor */
-double
-psGetParallaxFactor(const psExposure *exp //!< Exposure details
-    );
-\end{verbatim}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\subsection{Dates and times}
-
-\textbf{[May be deferred.]}
+psCoordinatesGtoI(const psCoord *restrict coordinates //!< Galactic coordinates to convert
+    );
+\end{verbatim}
+
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2866,181 +2514,534 @@
 \end{verbatim}
 
-\subsection{Detector and sky positions}
-
-Both detector and sky positions will be used extensively in the IPP.
-Since these both contain two coordinates with their associated errors,
-we bundle these into a single generic structure, \code{psCoord},
-containing \code{union}s to handle the semantic differences.
-
-\begin{verbatim}
-/** A point in 2-D space, with errors.
- */
-typedef union {
-    struct {
-        double x;                       //!< x position
-        double y;                       //!< y position
-        double xErr;                    //!< Error in x position
-        double yErr;                    //!< Error in y position
-    } xy;
-    struct {
-        double r;                       //!< RA
-        double d;                       //!< Dec
-        double rErr;                    //!< Error in RA
-        double dErr;                    //!< Error in Dec
-    } rd;
-} psCoord;
-\end{verbatim}
-
-\subsubsection{Transformations}
-
-We specify two types of transforms between coordinate systems.  The
-first consists simply of two 2D polynomials to transform both
-components; this will be used to apply the coordinate transformations
-between Cells, Chips and the Focal Plane.  The second consists of two
-4D polynomials; this will be used to apply position-, colour- and
-magnitude-dependent distortions between the Focal Plane and the
-Tangent Plane.
-
-\begin{verbatim}
-/** A polynomial transformation between coordinate frames.  This may be a linear relationship, or may
- *  represent a higher-order transformation.
+\subsection{Astronomy Images}
+
+\subsubsection{Terminology}
+
+Some brief review of terminology would be useful so that previous
+definitions do not influence the understanding of this document.
+
+A ``readout'' is a read of the detector.
+
+A ``cell'' is defined as the smallest element of the detector readout;
+usually associated with an amplifier.  Correspondingly, each cell has
+its own overscan region.  There may be multiple readouts in a cell if
+the cell was used to provide fast guiding.
+
+A ``chip'' is defined as a contiguous piece of silicon, and consists
+of a group of cells.
+
+A ``focal plane'' is defined as a mosaic of chips, and consists of a
+group of chips.
+
+For example, take a mosaic camera consisting of eight $2k\times 4k$
+CCDs, each of which is read out through two amplifiers.  Then there
+would be sixteen cells in total, each of which is presumably $2k\times
+2k$.  There would be eight chips, each consisting of two cells, and
+the focal plane consists of these eight chips.
+
+As another example, consider an observation by PS1.  The focal plane
+would consist of 60 chips, each of which consist of 64 cells (or less;
+a few cells may be dead).  Some cells (those containing guide stars
+for the orthogonal transfer) will contain multiple readouts.
+
+\subsubsection{A Readout}
+
+A readout is the result of a single read of a cell (or a portion
+thereof).  It contains a pointer to the pixel data, a separate pointer
+to the overscan pixels, and additional pointers to the objects found
+in the readout, and the readout metadata.  It also contains the offset
+from the lower-left corner of the chip, in the case that the CCD was
+windowed.
+
+\begin{verbatim}
+/** a Readout: a collection of pixels */
+typedef struct {
+    int x0, y0;                         //!< Offset from the lower-left corner
+    psImage *image;                     ///< imaging area of cell 
+    psDlist *objects;                   ///< objects derived from cell
+    psImage *overscan;                  ///< bias region (subimage) of cell
+    psMetaDataSet *md;                  //!< Readout-level metadata
+} psReadout;
+\end{verbatim}    
+
+
+\subsubsection{A Cell}
+
+A cell consists of one or more readouts (usually only one except in the
+case that the cell has been used for fast guiding).  It also contains
+a pointer to the cell metadata, and a pointer to its parent chip.  On
+the astrometry side, it also contains coordinate transforms from the
+cell to the chip and, as a convenience, from the cell to the focal
+plane.  It is expected that these transforms will consist of two
+first-order 2D polynomials, simply specifying a translation, rotation
+and magnification; hence they are easily inverted, and there is no
+need to add reverse transformations.  We also add an additional
+transformation, which is intended to provide a ``quick and dirty''
+transform from the cell coordinates to the sky; this transformation
+not guaranteed to be as precise as the ``standard'' transformation of
+Cell $\rightarrow$ Chip $\rightarrow$ Focal Plane $\rightarrow$
+Tangent Plane $\rightarrow$ Sky, but will be faster.
+
+\begin{verbatim}
+/** a Cell: a collection of readouts.
  */
 typedef struct {
-    psDPolynomial2D *x;
-    psDPolynomial2D *y;
-} psCoordXform;
-\end{verbatim}
-
-\begin{verbatim}
-/** The optical distortion terms.  The lowest two terms are the x and y axis of the target system.  The higher
- *  two terms represent magnitude and color terms.
+    int nReadouts;                      ///< number of readouts in this cell realization; each may have its own
+                                        ///< image, objects and overscan.
+    struct psReadout *readouts;         //!< Readouts from the cell
+    psMetaDataSet *md;                  ///< Cell-level metadata
+
+    psCoordXform *cellToChip;           ///< Transformations from cell coordinates to chip coordinates
+    psCoordXform *cellToFPA;            ///< Transformations from cell coordinates to FPA coordinates
+    psCoordXform *cellToSky;            ///< Quick and Dirty transformations from cell coordinates to sky
+
+    struct psChip  *parentChip;         ///< chip which contains this cell
+} psCell;
+\end{verbatim}
+
+
+\subsubsection{A Chip}
+
+A chip consists of one or more cells (according to the number of
+amplifiers on the CCD).  It contains a pointer to the chip metadata,
+and a pointer to the parent focal plane.  For astrometry, it contains
+a coordinate transform from the chip to the focal plane.  It is
+expected that this transforms will consist of two second-order 2D
+polynomials; hence we expect that it is prudent to include a reverse
+transformation which will be derived from numerically inverting the
+forward transformation.
+
+\begin{verbatim}
+/** a Chip: a collection of cells.  Not all valid cells in a chip need to be listed in an
+ *  instance of psChip.
  */
 typedef struct {
-    psDPolynomial4D *x;
-    psDPolynomial4D *y;
-} psDistortion;
-\end{verbatim}
-
-We require corresponding functions to apply the transformations:
-
-\begin{verbatim}
-/** apply the coordinate transformation to the given coordinate */
-psCoord *psCoordXformApply (psCoord *out, //!< Output coordinates, or NULL
-                            const psCoordXform *frame, ///< coordinate transformation
-                            const psCoord *coords ///< input coordiate
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** apply the optical distortion to the given coordinate, magnitude, color */
-psCoord *psDistortionApply (psCoord *out, //!< Output coordinates, or NULL
-                            const psdistortion *pattern, ///< optical distortion pattern
-                            const psCoord *coords, ///< input coordinate
-                            float mag,  ///< magnitude of object
-                            float color ///< color of object
-    );
-\end{verbatim}
-
-
-\subsubsection{Offsets}
-
-We require a function to calculate the offset between two positions on
-the sky, as well as a function to apply an offset to a position.
-
-\begin{verbatim}
-/** Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical */
+    int nCells;                         ///< Number of Cells assigned
+    psCell *cells;                      ///< Cells in the Chip
+
+    psMetaDataSet *md;                  ///< Chip-level metadata
+    psCoordXform *chipToFPA;            ///< Transformations from chip coordinates to FPA coordinates
+    psCoordXform *FPAtoChip;            //!< Transformations from FPA coordinates to chip
+
+    struct psFPA *parentFPA;            ///< FPA which contains this chip
+} psChip;
+\end{verbatim}
+
+\subsubsection{A Focal Plane}
+
+A focal plane consists of one or more chips (according to the number
+of pieces of contiguous silicon).  It contains pointers to the focal
+plane metadata and the exposure information.  For astrometry, it
+contains a transformation from the focal plane to the tangent plane
+and the fixed pattern residuals.  It is expected that the
+transformation will consist of two 4D polynomials (i.e.\ a function of
+two coordinates in position, the magnitude of the object, and the
+colour of the object) in order to correct for optical distortions and
+the effects of the atmosphere; hence we expect that it is prudent to
+include a reverse transformation which will be derived from
+numerically inverting the forward transformation.  Since colours are
+involved in the transformation, it is necessary to specify the colour
+the transformation is defined for.  We also include some values to
+characterise the quality of the transformation: the root mean square
+deviation for the x and y transformation fits, and the $\chi^2$ for
+the transformation fit.
+
+\begin{verbatim}
+/** a Focal plane array: a collection of chips.  Not all chips in a camera need to be listed in an instance of
+ *  psFPA.
+ */
+typedef struct {
+    int nChips;                         ///< Number of Cells assigned
+    int nAlloc;                         ///< Number of Cells available
+    psChip *chips;                      ///< Chips in the Focal Plane Array
+
+    psMetaDataSet *md;                  ///< FPA-level metadata 
+    psDistortion *TPtoFP;               ///< Transformation term from 
+    psDistortion *FPtoTP;               ///< Transformation term from 
+    psFixedPattern *pattern;            //!< Fixed pattern residual offsets
+    psExposure *exp;                    ///< information about this exposure
+    psPhotSystem colorPlus, colorMinus; ///< Colour reference
+    float rmsX, rmsY;                   //!< Dispersion in astrometric solution
+    float chi2;                         //!< chi^2 of astrometric solution
+} psFPA;
+\end{verbatim}
+
+
+\subsubsection{Exposure information}
+
+We need several quantities from the telescope in order to make a
+first guess at the astrometric solution.  From these quantities,
+further quantities can be derived and stored for later use.
+
+\begin{verbatim}
+/** Exposure information from the telescope */
+typedef struct {
+    // Telescope longitude, latitude and height are stored separately, since they don't change with pointing
+    double ra, dec;                     //!< Telescope boresight
+    double ha;                          //!< Hour angle
+    double zd;                          //!< Zenith distance
+    double az;                          //!< Azimuth
+    double lst;                         //!< Local Sidereal Time
+    float mjd;                          //!< MJD of observation
+    float rotAngle;                     //!< Rotator position angle
+    float temp;                         //!< Air temperature, for estimating refraction
+    float pressure;                     //!< Air pressure, for calculating refraction
+    float humidity;                     //!< Relative humidity, for calculating refraction
+    float exptime;                      //!< Exposure time
+    /* Derived quantities */
+    float posAngle;                     //!< Position angle
+    float parallactic;                  //!< Parallactic angle
+    float airmass;                      //!< Airmass, calculated from zenith distance
+    float pf;                           //!< Parallactic factor
+    char *cameraName;                   ///< name of camera which provided exposure
+    char *telescopeName;                ///< name of telescope which provided exposure
+    psGrommit *grommit;                 //!< Data needed to convert from the sky to the tangent plane
+} psExposure;
+\end{verbatim}
+
+
+\subsubsection{Constructors and Destructors}
+
+Each of the above structures needs an appropriate constructor and
+destructor.  Other than \code{psExposure}, which contains significant
+non-pointer types, the constructors should not take any arguments, and
+the destructors should only take the structure to be destroyed.
+The constructor for \code{psExposure} is specified below.
+
+\begin{verbatim}
+/** Constructor */
+psExposure *
+psExposureAlloc(double ra, double dec,  //!< Telescope boresight
+                double ha,              //!< Hour angle
+                double zd,              //!< Zenith distance
+                double az,              //!< Azimuth
+                double lst,             //!< Local Sidereal Time
+                float mjd,              //!< MJD
+                float rotAngle,         //!< Rotator position angle
+                float temp,             //!< Temperature
+                float pressure,         //!< Pressure
+                float humidity,         //!< Relative humidity
+                float exptime           //!< Exposure time
+                );
+\end{verbatim}
+
+
+\subsection{Astrometry}
+
+Astrometry is a basic functionality required for the IPP that will be
+used repeatedly, both for low-precision (roughly where is my favourite
+object?) and high-precision (what is the proper motion of this star?).
+As such, it must be flexible, yet robust.  Accordingly, we will wrap
+the StarLink Astronomy Libraries (SLALib), which has already been
+developed.
+
+\subsubsection{Coordinate frames}
+\label{sec:coordinateFrames}
+
+There are five coordinate frames that we need to worry about for the
+purposes of astrometry:
+\begin{itemize}
+\item Cell: $(x,y)$ in pixels --- raw coordinates;
+\item Chip: $(X,Y)$ in pixels --- the location on the silicon;
+\item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;
+\item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and
+\item Sky: (RA,Dec) --- ICRS.
+\end{itemize}
+
+The following steps are required to convert from the cell coordinates to
+the sky:
+\begin{itemize}
+\item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;
+\item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;
+\item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =
+h(p,q,m,c)$, where $m$ and $c$ are the magnitude and colour of the
+object, respectively; and
+\item TP $\longleftrightarrow$ Sky: SLALib transformation using a
+transform pre-computed for each pointing.
+\end{itemize}
+
+Note that the transformation between the Focal Plane and the Tangent
+Plane is a four-dimensional polynomial, in order to account for any
+possible dependencies in the astrometry on the stellar magnitude and
+colour; the former serves as a check for charge transfer
+inefficiencies, while the latter will correct chromatic refraction,
+both through the atmosphere and the corrector lenses.
+
+\textbf{[If the magnitude terms serve to check CTI, then shouldn't we
+put them in the cell $\leftrightarrow$ chip section?]}
+
+We require structures to contain each of the above transformations as
+well as the pixel data.
+
+\subsubsection{SLALib information}
+
+SLALib requires several elements to perform the transformations
+between the tangent plane and the sky.  Pre-computing these quantities
+for each exposure means that subsequent transformations are faster.
+For historical reasons, this structure is known colloquially as
+``Wallace's Grommit''.
+
+\begin{verbatim}
+/** Information needed (by SLALib) to convert Apparent to Observed Position */
+typedef struct {
+    double latitude;                    ///< geodetic latitude (radians)
+    double sinLat, cosLat;              ///< sine and cosine of geodetic latitude
+    double abberationMag;               ///< magnitude of diurnal aberration vector
+    double height;                      ///< height (HM)
+    double temperature;                 ///< ambient temperature (TDK)
+    double pressure;                    ///< pressure (PMB)
+    double humidity;                    ///< relative humidity (RH)
+    double wavelength;                  ///< wavelength (WL)
+    double lapseRate;                   ///< lapse rate (TLR)
+    double refractA, refractB;          ///< refraction constants A and B (radians)
+    double longitudeOffset;             ///< longitude + eqn of equinoxes + ``sidereal UT'' (radians)
+    double siderealTime;                ///< local apparent sidereal time (radians)
+} psGrommit;
+\end{verbatim}
+
+
+\subsubsection{Fixed Pattern}
+
+The fixed pattern is a correction to the general astrometric solution
+formed by summing the residuals from many observations.  The intent is
+to correct for higher-order distortions in the camera system on a
+coarse grid (larger than individual pixels, but smaller than a single
+cell).  Hence, in addition to the offsets, we need to specify the size
+and scale of the grid in $x$ and $y$, as well as the origin of the
+grid.
+
+\begin{verbatim}
+/** The fixed pattern residual offsets.  These are specified via a coarse grid of x and y offsets. */
+typedef struct {
+    int nX, nY;                         //!< Number of elements in x and y
+    double x0, y0;                      //!< Position of the lower-left corner of the grid on the focal plane
+    double xScale, yScale;              //!< Scale of the grid
+    double **x, **y;                    //!< The grid of offsets in x and y
+} psFixedPattern;
+\end{verbatim}
+
+
+\subsubsection{Finding}
+
+We require functions to return the structure containing given
+coordinates.  For example, we want the chip that corresponds to the
+focal plane coordinates $(p,q) = (-1.234,+5.678)$.  These routines
+handle the one-to-many problem --- i.e., for one given focal plane
+coordinate, there are many chips that this coordinate may be
+correspond to; these functions will select the correct one.
+
+
+\begin{verbatim}
+/** returns Chip in FPA which contains the given FPA coordinate */
+psChip *
+psChipInFPA (psChip *out,               //!< Chip to return, or NULL
+             const psFPA *fpa,          ///< FPA description
+             const psCoord *coord       ///< coordinate in FPA
+             );
+\end{verbatim}
+
+\begin{verbatim}
+/** returns Cell in Chip which contains the given chip coordinate */
+psCell *
+psCellInChip(psCell *out,               //!< Cell to return, or NULL
+             const psChip *chip,        ///< chip description
+             const psCoord *coord       ///< coordinate in chip
+             );
+\end{verbatim}
+
+Usually we will want to go directly from the FPA to the Cell, so we
+also specify the following function, which performs the above two
+functions in order.
+
+\begin{verbatim}
+/** Return the cell in FPA which contains the given FPA coordinates */
+psCell *
+psCellInFPA(psCell *out,                //!< Cell to return, or NULL
+            const psFPA *fpa,           //!< FPA description
+            const psCoord *coord        //!< Coordinate in FPA
+            );
+\end{verbatim}
+
+
+
+\subsubsection{Conversion Functions}
+
+We require functions to convert between the various coordinate frames
+(Section~\ref{sec:coordinateFrames}).  The heirarchy of the coordinate
+frames and the transformations between each are shown in
+Figure~\ref{fig:coco}.  The functions that employ the transformations
+are shown in Figure~\ref{fig:cocoFunc}.  In addition to
+transformations between each adjoining coordinate frame in the
+heirarchy, we also require higher-level functions to convert between
+the Cell and Sky coordinate frames; these will simply perform the
+intermediate steps.
+
+\begin{figure}
+\psfig{file=coordinateFrames.ps,height=7in,angle=-90}
+\caption{The coordinate systems in the \PS{} IPP, and the relation
+between each by transformations contained in the appropriate
+structures.}
+\label{fig:coco}
+\end{figure}
+
+\begin{figure}
+\psfig{file=coordinateConv.ps,height=7in,angle=-90}
+\caption{Conversion between coordinate systems by PSLib.}
+\label{fig:cocoFunc}
+\end{figure}
+
+The function prototypes are:
+
+\begin{verbatim}
+/** Convert (RA,Dec) to cell and cell coordinates */
 psCoord *
-psGetOffset(const psCoord *restrict position1, //!< Position 1
-            const psCoord *restrict position2, //!< Position 2
-            const char *type            //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Apply an offset to a position */
+psCoordSkyToCell(psCoord *out,          //!< Coordinates to return, or NULL
+                 psCell *cell,          //!< Cell to return
+                 const psFPA *fpa       //!< FPA description
+                 );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert cell and cell coordinate to (RA,Dec) */
 psCoord *
-psApplyOffset(const psCoord *restrict position, //!< Position
-              const psCoord *restrict offset, //!< Offset
-              const char *type          //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
-    );
-\end{verbatim}
-
-
-\subsubsection{Positions of Major SS Objects}
-
-We require the ability to calculate the position of major Solar System
-objects, as well as Lunar phase.
-
-\begin{verbatim}
-/** Get Sun Position */
+psCoordCellToSky(psCoord *out,          //!< Coordinates to return, or NULL
+                 const psCell *cell,    //!< Cell to get coordinates for
+                 const psCoord *coord   //!< cell coordinates to transform
+                 );
+\end{verbatim}
+
+\begin{verbatim}
+/** Quick and dirty cell to (RA,Dec) --- employs cellToSky transformation */
 psCoord *
-psGetSunPos(float mjd                   //!< MJD to get position for
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Get Moon position */
+psCoordCellToSkyQuick(psCoord *out,     //!< Coordinates to return, or NULL
+                      const psCell *cell, //!< Cell description
+                      const psCoord *coord //!< cell coordinates to transform
+                      );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert (RA,Dec) to tangent plane coords */
 psCoord *
-psGetMoonPos(float mjd,                 //!< MJD to get position for
-             double latitude,           //!< Latitude for apparent position
-             double longitude           //!< Longitude for apparent position
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Get Moon phase */
+psCoordSkyToTP(psCoord *out,            //!< Coordinates to return, or NULL
+               const psExposure *exp,   //!< Exposure description
+               const psCoord *coord     //!< input Sky coordinate
+               );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert tangent plane coords to focal plane coordinates */
+psCoord *
+psCoordTPtoFPA(psCoord *out,            //!< Coordinates to return, or NULL
+               const psFPA *fpa,        //!< FPA description
+               const psCoord *coord     //!< input TP coordinate
+               );
+\end{verbatim}
+
+\begin{verbatim}
+/** converts the specified FPA coord to the coord on the given Chip */
+psCoord *
+psCoordFPAtoChip (psCoord *out,         //!< Coordinates to return, or NULL
+                  const psChip *chip,   ///< Chip of interest
+                  const psCoord *coord  ///< input FPA coordinate
+                  ); 
+\end{verbatim}
+
+\begin{verbatim}
+/** converts the specified Chip coord to the coord on the given Cell */
+psCoord *
+psCoordChiptoCell (psCoord *out,        //!< Coordinates to return, or NULL
+                   const psCell *cell,  ///< Cell of interest
+                   const psCoord *coord ///< input Chip coordinate
+                   );
+\end{verbatim}
+
+\begin{verbatim}
+/** converts the specified Cell coord to the coord on the parent Chip */
+psCoord *
+psCoordCelltoChip (psCoord *out,        //!< Coordinates to return, or NULL
+                   const psCell *cell,  ///< Cell description
+                   const psCoord *coord ///< input Cell coordinate
+                   );
+\end{verbatim}
+
+\begin{verbatim}
+/** converts the specified Chip coord to the coord on the parent FPA */
+psCoord *
+psCoordChiptoFPA (psCoord *out,         //!< Coordinates to return, or NULL
+                  const psChip *chip,   ///< Chip description
+                  const psCoord *coord  ///< input Chip coordinate
+                  );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert focal plane coords to tangent plane coordinates */
+psCoord *
+psCoordFPAToTP(psCoord *out,            //!< Coordinates to return, or NULL
+               const psFPA *fpa,        //!< FPA description
+               const psCoord *coord     //!< input FPA coordinate
+               );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert tangent plane coords to (RA,Dec) */
+psCoord *
+psCoordTPtoSky(psCoord *out,            //!< Coordinates to return, or NULL
+               const psExposure *exp,   //!< Exposure description
+               const psCoord *coord     //!< input TP coordinate
+               );
+\end{verbatim}
+
+\begin{verbatim}
+/** Convert Cell coords to FPA coordinates */
+psCoord *
+psCoordCellToFPA(psCoord *out,          //!< Coordinates to return, or NULL
+                 const psCell *cell,    //!< Cell description
+                 const psCoord *coord   //!< Input cell coordinates
+                 );
+\end{verbatim}
+
+\subsubsection{Additional functions}
+
+We require additional functions to perform general functions which
+will be useful for astrometry.  Given coordinates on the sky, we
+need to get the airmass, the parallactic angle, and an estimate of
+the atmospheric refraction.
+
+\begin{verbatim}
+/** Get the airmass for a given position and sidereal time */
 float
-psGetMoonPhase(float mjd                //!< MJD to get phase for
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Get Planet positions */
-psCoord *
-psGetSolarSystemPos(const char *solarSystemObject, //!< Named S.S. object
-                    float mjd           //!< MJD to get position for
-    );
-\end{verbatim}
-
-\subsubsection{Celestial Coordinate Conversions}
-
-We need to be able to convert between ICRS, Galactic and Ecliptic
-coordinates.
-
-\begin{verbatim}
-/** Convert ICRS to Ecliptic */
-psCoord *
-psCoordinatesItoE(const psCoord *restrict coordinates //!< ICRS coordinates to convert
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert Ecliptic to ICRS */
-psCoord *
-psCoordinatesEtoI(const psCoord *restrict coordinates //!< Ecliptic coordinates to convert
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert ICRS to Galactic */
-psCoord *
-psCoordinatesItoG(const psCoord *restrict coordinates //!< ICRS coordinates to convert
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Convert Galactic to ICRS */
-psCoord *
-psCoordinatesGtoI(const psCoord *restrict coordinates //!< Galactic coordinates to convert
-    );
-\end{verbatim}
-
+psGetAirmass(const psCoord *coord,      //!< Position on the sky
+             double siderealTime,       //!< Sidereal time
+             float height               //!< Height above sea level
+             );
+\end{verbatim}
+
+\begin{verbatim}
+/** Get the parallactic angle for a given position and sidereal time */
+float
+psGetParallactic(const psCoord *coord,  //!< Position on the sky
+                 double siderealTime    //!< Sidereal time
+                 );
+\end{verbatim}
+
+\begin{verbatim}
+/** Estimate atmospheric refraction, along the parallactic */
+float
+psGetRefraction(float colour,           //!< Colour of object
+                psPhotSystem colorPlus, ///< Colour reference
+                psPhotSystem colorMinus, ///< Colour reference
+                const psExposure *exp   //!< Telescope pointing information, for airmass, temp and pressure
+                );
+\end{verbatim}
+
+\begin{verbatim}
+/** Calculate the parallax factor */
+double
+psGetParallaxFactor(const psExposure *exp //!< Exposure details
+    );
+\end{verbatim}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\subsection{Astronomical objects}
-
-\textbf{[Deferred.]}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 \subsection{Photometry}
 
@@ -3113,4 +3114,10 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+\subsection{Astronomical objects}
+
+\textbf{[Deferred.]}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 \appendix
 
@@ -3129,4 +3136,7 @@
 \input{psAstroGroup.tex}
 
+\section{API Summary: all structures}
+\input{psStructures.tex}
+
 \bibliographystyle{plain} \bibliography{panstarrs}
 
