IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 320


Ignore:
Timestamp:
Mar 31, 2004, 11:27:48 AM (22 years ago)
Author:
eugene
Message:

major revision of the text for sections on:
memory, logging, tracing

File:
1 edited

Legend:

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

    r314 r320  
    1 %%% $Id: psLibSDRS.tex,v 1.14 2004-03-30 05:40:01 price Exp $
     1%%% $Id: psLibSDRS.tex,v 1.15 2004-03-31 21:27:48 eugene Exp $
    22\documentclass[panstarrs]{panstarrs}
    33%\documentclass[panstarrs]{panstarrs}
    44
    55% basic document variables
    6 \title{Pan-STARRS IPP Library Design}
     6\title{Pan-STARRS IPP Library\\
     7Supplementary Design Requirements}
    78\author{Paul Price, Eugene Magnier, Robert Lupton}
    89\shorttitle{PSLib Design}
     
    2425% use \hline between each table row
    2526\RevisionsStart
    26 % version     Date         Description
    27 \theversion & 2003 Mar 11-- & Draft \\
     27% version  Date            Description
     28DR-1       & 2003 Mar 11 & Draft \\
     29\hline
     30DR-2       & 2003 Mar 29 & Reorganized, spell-checked \\
    2831\RevisionsEnd
    2932
    30 \pagebreak
     33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     34
     35\DocumentsInternal
     36PSCD-430-xxx  &   PS-1 Design Reference Mission \\
     37\hline
     38PSCD-430-004  &   Pan-STARRS IPP C Code Conventions \\
     39\hline
     40PSCD-430-005  &   Pan-STARRS IPP SRS \\
     41\hline
     42PSCD-430-006  &   Pan-STARRS IPP ADD \\
     43\hline
     44PSCD-430-007  &   Pan-STARRS IPP PSLib SDR \\
     45\hline
     46PSCD-430-008  &   Pan-STARRS IPP Architecture SDR \\
     47
     48\DocumentsExternal
     49Posix Standard & Open Group Based Specifications Issue 6, IEEE Std 1003.1, 2003 \\
     50\DocumentsEnd
     51
    3152\tableofcontents
    32 
    3353\pagebreak
    3454\pagenumbering{arabic}
    3555
    36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    39 
    40 \section{\PS{} Library (PSLib)}
    41 
    42 PSLib is a library of basic functions required for IPP (and MOPS)
    43 operations.  We expect that it will be, to a large extent, the major
    44 workhorse of the IPP.
    45 
    46 PSLib will consist of a variety of data structures and associated APIs
    47 to perform common functions.  It will provide low-level capabilities
    48 in each of the following areas:
     56%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     57
     58\section{Introduction}
     59
     60This document describes the Pan-STARRS Image Processing Pipeline (IPP)
     61Toolkit Library, PSLib.  Any large software project such as the IPP
     62benefits from the existence of a library of basic software functions
     63which can be used throughout the project to simplify programming
     64tasks.  Among the benefits are the ability to reuse code,
     65simplification of the testing process, streamlining of the code, and
     66the isolation and encapsulation of concepts which may be subject to
     67change.  The component functions of such a library should represent
     68well-defined, concise operations which can be coded with only a modest
     69number of lines.  PSLib is a library of basic functions required by
     70the IPP, but should include many programming concepts which may be useful
     71for other software projects, especially those which deal with
     72astronomical data handling tasks.
     73
     74PSLib consists of a collection of library function calls -- the
     75Application Programming Interfaces (APIs) -- and the associated data
     76structures.  The capabilities provided by PSLib are grouped into the
     77following areas:
     78%
    4979\begin{itemize}
    50 \item System utilities;
    51 \item Data containers;
    52 \item Data manipulation; and
    53 \item Astronomy-specific tasks.
     80\item System Utilities
     81\item Basic Data Collections
     82\item Data Manipulation
     83\item Astronomy-Specific Functions.
    5484\end{itemize}
    55 
    56 Below we sketch out approximately 200~APIs which specify the required
    57 capabilities.
    58 
    59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     85This list is sorted in a hierarchical order: the later entries depend
     86on the functions and data types of the earlier entries. 
     87
     88The installed base of code for PSLib consists of header files, the
     89binary library code, \code{libpslib.a} and the shared-library
     90equivalent, \code{libpslib.so}.  Assuming these components have been
     91installed into the library and search path, PSLib may be used within a
     92program by including the line \code{#include <pslib.h>} into the C
     93code and linking with \code{-lpslib}.
     94
     95This document describes the data structures and details the functions
     96calls. The specified data structures and functions follow the naming
     97conventions detailed in the IPP Code Conventions (PSDC-430-004).  In
     98particular, these coding conventions restrict the namespace used by
     99the library functions by requiring that all globally visible symbols
     100start with the two letters \code{ps}.  Further namespace organization
     101is achieved by encouraging functions to be named in the form
     102psNounVerbPhrase, where Noun is the data type of principle relevance
     103and VerbPhase describes the operation applied to that data type.  For
     104example, the function which copies an image (of type \code{psImage})
     105is called \code{psImageCopy()}.
     106
     107\tbd{discuss the use of external libraries (list them)}
     108
     109\tbd{discussion of thread safe?}
     110
     111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    62112
    63113\section{System Utilities}
     
    70120The \PS{} software system will need a level of memory management
    71121placed between the operating system (\code{malloc}/\code{free}) and
    72 the high level routines (e.g.\ \code{psMetaDataAlloc}).
    73 
    74 This layer is in addition to the possibility that specific heavily
    75 used data types may need their own special-purpose memory managers;
    76 but as we have specified that all user-level objects be allocated via
    77 \code{typeAlloc/typeFree} functions, we will easily be able to
    78 implement such functionality without impacting the facilities
    79 described here.
     122the high level routines (e.g.\ \code{psMetaDataAlloc}).  This layer is
     123in addition to the possibility that specific heavily used data types
     124may need their own special-purpose memory managers.  However, since we
     125require that all user-level objects be allocated via associated
     126\code{Alloc/Free} functions, we will easily be able to implement such
     127functionality without impacting the facilities described here.
    80128
    81129\subsubsection{Rationale}
     
    107155\item
    108156  While debugging complex scientific code, it is very useful to be
    109   able to trace a given data structure as it passed through the
     157  able to trace a given data structure as it passes through the
    110158  processing pipeline.
    111159
     
    115163\end{itemize}
    116164
    117 \subsubsection{A Minimal Specification}
    118 
    119 The previous section laid out a number of desiderata for a memory
    120 management system.  Rather than implement our own heap-manager at this
    121 stage of the project, we propose to put in place a sufficient set of
    122 data structures and APIs, but initially implement only a simple subset
    123 (e.g.\ that we not implement a multi-bucket memory manager that takes
    124 in 100Mb chunks from the system and performs sophisticated
    125 defragmentation and garbage collection).
    126 
    127 Subject to agreement with the IfA, some of the functions proposed
    128 here may be omitted from the initial implementation; in particular
    129 the routines \code{psMemCheckCorruption} and \code{psMemCheckLeaks}
    130 may be hard to build efficiently in a simple implementation based
    131 upon adding extra fields to allocation requests.
    132 
    133 \paragraph{Extra information to be saved by Memory Allocation Functions}
    134 
    135 It is required that a table of all allocated memory blocks be
    136 maintained by the \PS{} memory system.
    137 
    138 Each allocated block should preserve at least the information present
    139 in the following struct definition:
     165\subsubsection{Memory Management}
     166
     167In the following sections, we specify the API set, and define the
     168appropriate data structures, needed by the PSLib memory management
     169system in order to meet the requirements specified by the desiderata
     170listed above. 
     171
     172Within the PSLib memory management system, every allocated memory
     173block which is provided to the user is bounded by two additions memory
     174segments.  The segment preceeding the user-memory contains data
     175describing the allocated block, using the \code{psMemBlock} structure.
     176The final element of this structure is a \code{void} pointer called
     177\code{magic} and is assigned a special value, \code{PS_MEM_MAGIC}.
     178The segment following the user-memory block consists of a single
     179\code{void} pointer, and is also assigned the special value of
     180\code{PS_MEM_MAGIC}.
     181
     182In practice, these bounding memory blocks mean that when a user is
     183requests $N$ bytes of memory, the memory management system in fact
     184allocates \code{N + sizeof(psMemBlock) + sizeof(void)} bytes, starting
     185at a paricular address, \code{ADDR}.  It then fills in the first
     186\code{sizeof(psMemBlock)} bytes with the data of the \code{psMemBlock}
     187structure, and the last \code{sizeof(void)} bytes with the
     188\code{PS_MEM_MAGIC}.  It returns to the user the pointer corresponding
     189to the address \code{ADDR + sizeof(psMemBlock)}.  If the memory
     190management system reallocates a block of memory, it must also allocate
     191the additional space and fill in the boundary values.  If the memory
     192management system is give a specific pointer for some operation, it is
     193able to find the corresponding \code{psMemBlock} by simply subtracting
     194\code{sizeof(psMemBlock)} from the pointer address.
     195
     196The purpose of the two boundary markers is to catch corruption and to
     197act as an aid in low-level debugging.  In the first case, memory over-
     198and under-run errors are likely to overwrite the special values in
     199either the leading or trailing boundaries.  The typical situation is
     200one where the coder mis-counts the range and either fills the data
     201just before the start of the valid memory or just after the end of the
     202valid memory.  These actions will alter the boundary-post values and
     203can be detected by the memory management system.  In the second case,
     204hexidecimal dumps of large blocks of memory are easier to examine if
     205the value of \code{PS_MEM_MAGIC} is chosen to catch the eye.  A
     206traditional value for \code{PS_MEM_MAGIC} is \code{0xdeadbeef} which
     207is also easily recognized in a dump of the memory table. 
     208
     209The PSLib memory management system must maintain a private table of
     210the allocated memory blocks.  The table includes a list of pointers to
     211structures of type \code{psMemBlock}, defined as follows:
     212%
    140213\begin{verbatim}
    141214typedef struct {
    142     const void *magic0;                 //!< initialised to p_psMEMMAGIC
    143     const unsigned long id;             //!< a unique ID for this allocation
    144     const char *file;                   //!< set from __FILE__ in e.g. p_psAlloc
    145     const int lineno;                   //!< set from __LINE__ in e.g. p_psAlloc
    146     int refCounter;                     //!< how many times pointer is referenced
    147     const void *magic;                  //!< initialised to p_psMEMMAGIC
     215    const unsigned long id;             ///< a unique ID for this allocation
     216    const char *file;                   ///< set from __FILE__ in e.g. p_psAlloc
     217    const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
     218    int refCounter;                     ///< how many times pointer is referenced
     219    int state;                          ///< current state of memory block
     220    const void *magic;                  ///< initialised to PS_MEM_MAGIC
    148221} psMemBlock;
    149222\end{verbatim}
    150 
    151 The value of \code{P_PS_MEMMAGIC} shall be \code{(void *)0xdeadbeef}%
    152 \footnote{Why this choice? Tradition, and because it's easy to notice
    153   in a hex dump.}
    154 
    155 \paragraph{APIs for using Memory Allocation Functions}
    156 
    157 The types and function prototypes for the part of the memory API
    158 concerned with allocating and freeing memory are shown below.
    159 
    160 \begin{verbatim}
    161 /// Memory allocation. Underlying private function called by macro psAlloc.
    162 void *p_psAlloc(size_t size,            //!< Size required
    163                 const char *file,       //!< File of call
    164                 int lineno              //!< Line number of call
    165                 );
    166 
    167 /// Memory re-allocation.  Underlying private function called by macro psRealloc.
    168 void *p_psRealloc(void *ptr,            //!< Pointer to re-allocate
    169                   size_t size,          //!< Size required
    170                   const char *file,     //!< File of call
    171                   int lineno            //!< Line number of call
    172                   );
    173 
    174 /// Free memory.  Underlying private function called by macro psFree.
    175 void p_psFree(void *ptr,                //!< Pointer to free
    176               const char *file,         //!< File of call
    177               int lineno                //!< Line number of call
    178               );
    179 
    180 /// Memory allocation. psAlloc sends file and line number to p_psAlloc.
    181 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
    182 
    183 /// Memory re-allocation.  psRealloc sends file and line number to p_psRealloc.
    184 #define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__)
    185 
    186 /// Free memory.  psFree sends file and line number to p_psFree.
    187 #define psFree(size) p_psFree(size, __FILE__, __LINE__)
    188 \end{verbatim}
    189 
    190 N.b.
     223%
     224The first element in the structure is a sequential memory block ID.
     225The memory management system must maintain an internal memory block ID
     226counter from which a new ID may be supplied to each newly allocated
     227block of memory and saved in the element \code{id}.  This ID should
     228also be the key to the memory block in the memory block table.
     229
     230The two entries \code{file} and \code{lineno} are set to the line
     231number and file at which the memory was originally allocated.  This is
     232most easily implemented by the use of the C preprocessor macros
     233\code{__LINE__} and \code{__FILE__}.  For this reason, we specify
     234below that the basic memory managment functions be implemented as
     235preprocessor macros which wrap the intrinsic C level functions.
     236
     237The \code{psMemBlock} structure element \code{refCounter} is provided
     238so APIs may cleanly manage multiple references to the same block of
     239memory.  As discussed below, the basic free function, \code{psFree},
     240is specified to free the memory block only if the reference counter is
     241set to 1.  See the discussion of the \code{psDlist} and \code{psHash}
     242data containers for an example of the usage.  Usage of this feature is
     243strongly encouraged, but not enforced by the memory management system.
     244
     245The element \code{state} defines the state of the memory block.  In
     246order to trace double frees and other memory errors, the memory block
     247reference is not automatically deleted when the assocated memory is
     248deleted.  Valid states are \code{PS_MEM_FREE} and \code{PS_MEM_ALLOC}.
     249
     250\subsubsection{APIs for Allocation and Freeing}
     251
     252PSLib provides the following APIs to create and destroy memory blocks:
     253%
     254\begin{verbatim}
     255void *psAlloc(size_t size);
     256void *psRealloc(void *ptr, size_t size);
     257void *psFree(void *ptr);
     258\end{verbatim}
     259%
     260From the user's perspective, the functions \code{psAlloc},
     261\code{psRealloc}, and \code{psFree} have identical semantics to the
     262standard C library functions \code{malloc}, \code{realloc}, and
     263\code{free}.  In fact, these functions shall be implemented as C
     264preprocessor macros which call the following private functions:
     265%
     266\begin{verbatim}
     267void *p_psAlloc(size_t size, char *file, int line);
     268void *p_psRealloc(void *ptr, size_t size, char *file, int line);
     269void p_psFree(void *ptr, char *file, int line);
     270\end{verbatim}
     271%
     272In these function calls, \code{size} is the number of bytes required
     273to be allocated, \code{ptr} is the pointer to the allocated memory
     274block, \code{file} is the file containing the calling function (set by
     275\code{__FILE__}), and \code{line} is the calling function line number
     276in the source-code file (set by \code{__LINE__}).  Because the user
     277should only see the preprocessor versions (ie, \code{psAlloc}), we do
     278not distinguish between these two in the following discussion.
     279
     280In order to enforce the use of the PSLib versions, the header file
     281shall take steps to ensure that code calling the functions
     282\code{malloc}, \code{calloc}, \code{realloc}, or \code{free} will not
     283compile.  This may be achieved by defining preprocessor macros which
     284mask these functions with invalid statements (\eg{} \code{#define
     285malloc(S) for}).  In exceptional cases, such as the memory management
     286system itself, programmers may choose to override this prohibition by
     287defining the symbol \code{PS_ALLOW_MALLOC}.  Application code will
     288call \code{p_psAlloc,p_psRealloc,p_psFree} via the macros defined
     289above.
     290 
     291The functions \code{psAlloc} and \code{psRealloc} shall never return a
     292\code{NULL} pointer. If they are unable to provide the requested
     293memory they should attempt to obtain the desired memory by calling the
     294routine registered by \code{psMemExhaustedSetCB} (see subsubsection
     295\ref{secMemAdvanced}), and if still unsuccessful, call \code{psAbort()}.
     296
     297Note that we have not specified an equivalent of the \code{calloc}
     298function.  The \code{calloc} function provides two aspects which
     299\code{malloc} originally did not: aligned memory and inialization.
     300Neither of these are required: under POSIX, \code{malloc} is required
     301to be aligned.  Also, for all structures it is necessary to explicity
     302define the initialization independently since a byte value of 0 is
     303usually insufficient.
     304
     305\subsubsection{Callback Routines}
     306
     307The PSLib memory management system uses callback functions to handle
     308certain errors and trace conditions.  The callbacks are registered by
     309the programmer and called by the basic memory management functions if
     310needed.  The four callbacks currently defined are called in the
     311following situations:
     312%
    191313\begin{itemize}
    192 \item
    193   The functions \code{psAlloc}, \code{psRealloc}, and \code{psFree}
    194   are defined, and are required to be equivalent to \code{p_psAlloc},
    195   \code{p_psRealloc}, and \code{p_psFree} with the final two arguments
    196   \code{__FILE__} and \code{__LINE__}.
    197 
    198   In the descriptions that follow, I shall not distinguish between the
    199   functions with and without the \code{p_} prefix.
    200 
    201 \item
    202   Except as specified below, the functions \code{psAlloc},
    203   \code{psRealloc}, and \code{psFree} have identical semantics
    204   to the standard C library functins \code{malloc}, \code{realloc},
    205   and \code{free}.
    206  
    207 \item
    208   The header file (\file{psMemory.h}) shall take steps to ensure that
    209   code calling the functions \code{malloc}, \code{calloc},
    210   \code{realloc}, or \code{free} shall not compile (\eg{}
    211   \code{#define malloc(S) for}) unless the symbol
    212   \code{PS_ALLOC_MALLOC} is defined.
    213 
    214 \item
    215   In all cases, application code will call
    216   \CODE|p_{psAlloc,psRealloc,psFree}| via the macros defined above.
    217  
    218 \item
    219   The functions \code{psAlloc} and \code{psRealloc} shall never
    220   return a \code{NULL} pointer. If they are unable to provide
    221   the requested memory they should attempt to obtain the desired
    222   memory by calling the routine registered by \code{psMemExhaustedSetCB} (see
    223   subsubsection \ref{secMemAdvanced}), and if still unsuccessful,
    224   call \code{abort()}.
    225 
    226 \item
    227   The memory management routines shall maintain the field
    228   \code{psMemBlock.refcntr}. It should be set to \code{1}
    229   when a block is returned to the user. It is an error to
    230   attempt to free a block with \code{psMemBlock.refcntr != 1}
    231   (see subsubsection \ref{secMemRefcounter}).
    232  
    233 \item
    234   Where practical and efficient, the memory manager shall call the
    235   routine registered using the \code{psMemProblemSetCB} (see section
    236   \ref{secMemAdvanced}) whenever a corrupted block of memory is
    237   discovered. For example, doubly-freed blocks can be detected by
    238   checking \code{psMemBlock.refcntr}.
    239 
    240 \item
    241   There is no \code{psCalloc} function. Initialisation of data is
    242   almost always more complex than setting all bytes to 0.
    243   Correspondingly, the system call \code{calloc} should be disabled
    244   using the pre-processor.
     314\item when insufficient memory is available (\code{psMemExhaustedCB})
     315\item when a memory block is found to be corrupted (\code{psMemProblemCB})
     316\item when a specified memory ID is allocated (\code{psMemAllocateCB})
     317\item when a specified memory ID is freed (\code{psMemFreeCB})
    245318\end{itemize}
    246 
    247 \paragraph{APIs for Tracing and Debugging Memory}
     319%
     320The callback functions are defined in terms of specific callback
     321types, specified below.  The callbacks are set using functions with
     322names of the form \code{psCallbackSet}.  In all cases, the
     323`\code{Set}' routine takes a pointer to the desired callback
     324function and returns a pointer to the one that was previously
     325installed. If the function pointer is \code{NULL}, the default
     326callback function is reinstalled.  We discuss the use of each of the
     327four callbacks below.
     328
     329\subsubsubsection{\tt psMemExhaustedCB}
     330
     331If not enough memory is available to satisfy a request by
     332\code{psAlloc} or \code{psRealloc}, these functions attempt to find an
     333alternative solution by calling the \code{psMemExhaustedCB}, a
     334function which may be set by the programmer in appropriate
     335circumstances, rather than immediately fail.  The typical use of such
     336a feature may be when a program needs a large chunk of memory to do an
     337operation, but the exact size is not critical.  This feature gives the
     338programmer the opportunity to make a smaller request and try again,
     339limiting the size of the operating buffer.  This callback has the
     340following form:
     341%
     342\begin{verbatim}
     343typedef void *(*psMemExhaustedCB)(size_t size);
     344psMemExhaustedCB psMemExhaustedCBSet(psMemExhaustedCB func);
     345\end{verbatim}
     346%
     347The callback function is called with the attempted size and is
     348expected to return a pointer to the allocated memory or \code{NULL}.
     349Until the callback function is set with \code{psMemExhaustedCBSet},
     350the default callback function immediately returns \code{NULL}, in
     351which case \code{psAlloc} will call \code{psAbort}.
     352
     353\subsubsubsection{\tt psMemProblemCB}
     354
     355At various occasions, the memory manager can check the state of the
     356memory stack.  If any of these checks discover that the memory stack
     357is corrupted, the \code{psMemProblemCB} is called.  The callback
     358has the following form:
     359%
     360\begin{verbatim}
     361typedef void (*psMemProblemCB)(psMemBlock *ptr, char *file, int lineno);
     362psMemProblemCB psMemProblemCBSet(psMemProblemCB func);
     363\end{verbatim}
     364%
     365This callback may be used to report the error and other status
     366information.  No return value is accepted, and no specific operations
     367are expected.  The callback is for informational purposes only.  Where
     368practical and efficient, the memory manager shall call the routine
     369registered using the \code{psMemProblemCBSet} whenever a corrupted
     370block of memory is discovered.  For example, doubly-freed blocks can
     371be detected by checking \code{psMemBlock.refcntr}.
     372
     373\subsubsubsection{\tt psMemAllocateCB \& psMemFreeCB}
     374
     375Two private variables, \code{p_psMemAllocateID} and
     376\code{p_psMemFreeID}, can be used to trace the allocation and freeing
     377of specific memory blocks.  If the first (\code{p_psMemAllocateID}) is
     378set and a memory block with that ID is allocated, the corresponding
     379callback is called just before memory is returned to the calling
     380function.  If the second (\code{p_psMemFreeID}) is set and the memory
     381block with the ID is about to be freed, the corresponding callback is
     382called just before the memory block is freed.  These variables are
     383internal and private to the memory manager and should be set using the
     384following two functions:
     385%
     386\begin{verbatim}
     387long psMemAllocateCBSetID(long id);
     388long psMemFreeCBSetID(long id);
     389\end{verbatim}
     390%
     391The corresponding callback have the following form:
     392%
     393\begin{verbatim}
     394typedef long (*psMemAllocateCB)(const psMemBlock *ptr);
     395psMemAllocateCB psMemAllocateCBSet(psMemAllocateCB func);
     396typedef long (*psMemFreeCB)(const psMemBlock *ptr);
     397psMemFreeCB psMemFreeCBSet(psMemFreeCB func);
     398\end{verbatim}
     399%
     400The callback functions are called with a pointer to the corresponding
     401memory block.  The routines \code{psMemFreeIDSet} and
     402\code{psMemAllocateIDSet} accept the desired ID value and return the
     403old value to the user.  The return values of the handlers installed by
     404\code{psMemAllocateCBSet} and \code{psMemFreeCBSet} are used to
     405increment the values of \code{p_psMemAllocateID} and
     406\code{p_psMemFreeID} respectively.  For example, the return value
     407\code{0} implies that the value is unchanged; if the value is \code{2}
     408the callback will be called again when the memory ID counter has
     409increased by two.  This functionality may be useful to check, for
     410example, every 100th block allocated.  The function, \code{long
     411psMemGetId(void);} returns the next identification number to be
     412assigned to a memory block.  This function can be used to guide the
     413choice of ID set with the functions above.
     414
     415\subsubsection{Memory Tracing and Corruption Checks}
    248416\hlabel{secMemAdvanced}
    249417
    250 The types and function prototypes for this part of the memory API
    251 are shown below.
    252 
    253 \begin{verbatim}
    254 /// prototype of a basic callback used by memory functions
    255 typedef int (*psMemCallback)(const psMemBlock *ptr);
    256 
    257 /// prototype of a callback used in error conditions
    258 typedef void (*psMemProblemCallback)(const psMemBlock *ptr, const char *file, int lineno);
    259 
    260 /// prototype of a callback used when memory runs out
    261 typedef void *(*psMemExhaustedCallback)(size_t size);
    262 
    263 /// Set callback for problems
    264 psMemProblemCallback psMemProblemSetCB(psMemProblemCallback func //!< Function to run
    265                                        );
    266 
    267 /// Set callback for out-of-memory
    268 psMemExhaustedCallback psMemExhaustedSetCB(psMemExhaustedCallback func //!< Function to run
    269                                            );
    270 
    271 /// Set call back for when a particular memory block is allocated
    272 psMemCallback psMemAllocateSetCB(psMemCallback func //!< Function to run
    273                                  );
    274 
    275 /// Set call back for when a particular memory block is freed
    276 psMemCallback psMemFreeSetCB(psMemCallback func
    277                              );
    278 
    279 /// get next memory ID
    280 int psMemGetId(void);
    281 
    282 /// set p_psMemAllocateID to id
    283 long psMemSetAllocateID(long id         //!< ID to set
    284                         );
    285 
    286 /// set p_psMemFreeID to id
    287 long psMemSetFreeID(long id             //!< ID to set
    288                     );
    289 
    290 /// Check for memory leaks
    291 int psMemCheckLeaks(int id0,            //!< don't list blocks with id < id0
    292                     psMemBlock ***arr,  //!< pointer to array of pointers to leaked blocks, or NULL
    293                     FILE *fd            //!< print list of leaks to fd (or NULL)
    294                     );
    295 /// Check for memory corruption
    296 int psMemCheckCorruption(int abort_on_error //!< Abort on detecting corruption?
    297                          );
    298 \end{verbatim}
    299 
    300 \paragraph{Callback Routines}
    301 
    302 The four `\code{SetCB}' routines are:
    303 
    304 \begin{tabular}{ll|l}
    305 \textbf{type} &  \textbf{Name} & \textbf{Function of callback} \\
    306 \code{psMemProblemCallback} & \code{psMemProblemSetCB} &
    307 Called when a problem is detected with data being managed on the heap \\
    308 \code{psMemExhaustedCallback} & \code{psMemExhaustedSetCB} &
    309 Called when \code{psAlloc} is unable to satisfy a memory request. \\
    310 \code{psMemCallback} & \code{psMemAllocateSetCB} &
    311 Callback is called when the \code{psMemBlock} with a specified ID is
    312 allocated. \\
    313 \code{psMemCallback} & \code{psMemFreeSetCB} &
    314 Callback is called when the \code{psMemBlock} with a specified ID is
    315 freed. \\
    316 \end{tabular}
    317 
    318 N.b.
    319 \begin{itemize}
    320 \item
    321   In all cases, the `\code{SetCB}' routine takes a pointer to the
    322   desired callback function, and returns a pointer to the one that was
    323   previously installed. If the function pointer is \code{NULL}, the
    324   default callback function is reinstalled.
    325 
    326 \item
    327   The routine installed by \code{psMemExhaustedSetCB} should return
    328   a pointer to the desired memory or \code{NULL}; in the latter case
    329   \code{psAlloc} will call \code{abort()}
    330 
    331 \item
    332   \code{psMemGetId} returns the next identification number to be
    333   assigned to a \code{psMemBlock.id}.
    334 
    335 \item
    336   The handler specified by \code{psMemAllocateSetCB} is called just
    337   before the pointer with \code{psMemBlock.id} equal to
    338   \code{p_psMemAllocateID} is returned to the user. The variable
    339   \code{p_psMemAllocateID} should not be set directly in any
    340   delivered code, \code{psMemSetAllocateID} should be used instead.
    341 
    342 \item
    343   The handler specified by \code{psMemFreeSetCB} is called just
    344   before the pointer with \code{psMemBlock.id} equal to
    345   \code{p_psMemFreeID} is freed. The variable
    346   \code{p_psMemFreeID} should not be set directly in any delivered
    347   code, \code{psMemSetFreeID} should be used instead.
    348 
    349 \item
    350   The routines \code{psMemSetFreeID} and \code{psMemSetAllocateID}
    351   accept the desired ID value (see previous two items) and return
    352   the old value to the user.
    353 
    354 \item
    355   The return values of the handlers installed by \code{psMemAllocateSetCB}
    356   and \code{psMemFreeSetCB} are used to increment the values of
    357   \code{p_psMemAllocateID} and \code{p_psMemFreeID} respectively.
    358 
    359   For example, the return value \code{0} implies that the value is unchanged;
    360   if the value is \code{2} the callback will be called again when the
    361   memory ID counter has increased by two.
    362 \end{itemize}
    363 
    364 \paragraph{Memory Tracing and Corruption Routines}
    365 
     418The PSLib memory management system includes features to facilitate
     419tracing the memory allocation and freeing process and to debug memory
     420errors in the calling code.  The types and function prototypes for
     421this part of the memory API are shown below.
     422%
     423\begin{verbatim}
     424int psMemCheckLeaks(long id0, psMemBlock ***array, FILE *fd);
     425int psMemCheckCorruption(int abort_on_error);
     426\end{verbatim}
     427%
    366428The routine \code{psMemCheckLeaks} may be used to check for memory
    367429leaks. The return value is the number of blocks that have been
    368 allocated but not freed.
    369 
    370 Only blocks with \code{psMemBlock.id} greater than \code{id0}
    371 are checked; this allows the user to ignore blocks allocated
    372 by initialisation routines.
    373 
    374 If the argument \code{arr} is non-\code{NULL}, then upon entering
    375 the call \code{**arr} should be \code{NULL}. Upon return it is set
    376 to an array of \code{psMemBlock *} pointers, one for each block
     430allocated but not freed.  Only blocks with \code{psMemBlock.id}
     431greater than \code{id0} are checked; this allows the user to ignore
     432blocks allocated by initialization routines.
     433
     434If the argument \code{array} is non-\code{NULL}, then \code{**array}
     435is set to an array of \code{psMemBlock *} pointers when the function
     436returns.  These pointers represent the blocks which have been
    377437allocated but not freed.  It is the caller's responsibility to free
    378 this array with \code{psFree}.
     438this array with \code{psFree}. Also note that \code{**array} should be
     439\code{NULL} (or not point to allocated memory) upon entering the call
     440or the corresponding memory reference will be lost.
    379441
    380442If the argument \code{fd} is non\code{NULL}, a one-line summary
     
    384446The routine \code{psMemCheckCorruption} checks the entire heap for
    385447corruption, calling the routine registered with
    386 \code{psMemProblemSetCB} for each block detected as being corrupted.
     448\code{psMemProblemCBSet} for each block detected as being corrupted.
    387449The return value is the number of corrupted blocks detected. If the
    388 argument \code{abort_on_error} is true,
    389 \code{psMemCheckCorruption} shall call \code{abort()} as soon as
    390 memory corruption is detected.
    391 
    392 \paragraph{Reference Counting}
     450argument \code{abort_on_error} is true, \code{psMemCheckCorruption}
     451shall call \code{psAbort} as soon as memory corruption is detected.
     452
     453\subsubsection{Reference Counting}
    393454\hlabel{secMemRefcounter}
    394455
    395 The memory management routines include a field
    396 \code{psMemBlock.refcntr} which must equal \code{1} whenever
    397 a pointer is presented to \code{psFree}.
    398 
    399 The API for this field is:
    400 \begin{verbatim}
    401 /// Return reference counter
    402 int psMemGetRefCounter(void *vptr       //!< Pointer to get refCounter for
    403                        );
    404 
    405 /// Increment reference counter and return the pointer
    406 void *psMemIncrRefCounter(void *vptr    //!< Pointer to increment refCounter, and return
    407                           );
    408 
    409 /// Decrement reference counter and return the pointer
    410 void *psMemDecrRefCounter(void *vptr    //!< Pointer to decrement refCounter, and return
    411                           );
    412 \end{verbatim}
    413 
    414 The functions \code{psMemIncrRefCounter} and \code{psMemDecrRefCounter} shall
    415 return \code{NULL} if passed a \code{NULL} pointer.
    416 
    417 \subsubsubsection{Rationale}
    418 
    419 The \code{psMemBlock.refcounter} is clearly useful for detecting
    420 attempts to free memory that is already free.  A more complex
    421 application is for allowing pointers to complex data-objects (e.g.\
    422 images) to appear in more than one data structure simultaneously:
    423 
    424 \begin{verbatim}
    425 typedef struct {
    426     char *name;
    427     int value;
    428 } psSimple;
    429 
    430 psSimple *psSimpleAlloc(const char *name, int val)
    431 {
    432     psSimple *simp = psAlloc(sizeof(psSimple));
    433     simp->name = strcpy(psAlloc(strlen(name) + 1), name);
    434     simp->value = val;
    435 
    436     return simp;
    437 }
    438 
    439 void psSimpleFree(psSimple *simp)
    440 {
    441     if (simp == NULL) { return; }
    442 
    443     if (psMemGetRefCounter(simp) > 1) {
    444         (void)psMemDecrRefCounter(simp);
    445         return;
    446     }
    447 }
    448 \end{verbatim}
    449 
    450 
    451 Because of the use of the \code{refcounter} field, we can safely put items of
    452 this type onto many lists:
    453 \goodbreak
    454 \begin{verbatim}
    455 simp = psSimpleAlloc("RHL", 0);
    456 psDlistAppend(list1, psMemIncrRefCounter(simp));
    457 psDlistAppend(list2, psMemIncrRefCounter(simp));
    458 psSimpleFree(simp);
    459 \end{verbatim}
    460 
    461 (Note: in fact there is no need to explicitly increment the counter
    462 in this case, as the \code{psDlistAppend} (section \ref{psDlist})
    463 API specifies that it
    464 does it for you.)
     456As mentioned above, the memory management system provides the
     457\code{refCounter} element in \code{psMemBlock} to allow for the
     458management of multiple references to the same block of memory.
     459External APIs which make use of this structure must increment the
     460counter for every additional reference to an allocated memory block,
     461and decrement it when those references are removed.  The memory
     462management routines respect the use of the \code{refCounter} field:
     463\code{psFree} will not free a block for which \code{refCounter != 1},
     464and \code{psAlloc} will initialize the field to 1.  \tbd{should psFree
     465give an error if refCounter $>$ 1 or actually do the decrement?}
     466However, they do not (and cannot practically) enforce the use of the
     467counters; this is a requirement of external APIs which intend to use
     468the feature.
     469
     470Several APIs are provided to manage the reference counters.  These
     471APIs are:
     472%
     473\begin{verbatim}
     474int psMemGetRefCounter(void *vptr);
     475void *psMemIncrRefCounter(void *vptr);
     476void *psMemDecrRefCounter(void *vptr);
     477\end{verbatim}
     478%
     479The functions all take a pointer to the start of a user block of
     480memory.  The first simply returns the value of the reference counter.
     481The next two functions increment or decrement the reference counter,
     482returning the pointer which was passed in. These functions must
     483validate the memory pointer by determining the corresponding
     484\code{psMemBlock.id} and checking for consistency in the internal
     485memory block table (the table pointer for \code{psMemBlock.id} should
     486be in the valid range and should correspond to the address of the
     487\code{psMemBlock}).  For an example implementation of the
     488\code{refCounter} facilities, see the discussion of \code{psDlist}
     489
     490\tbd{REF}.
    465491
    466492\subsection{Tracing and Logging}
     
    468494This section defines the \PS{} Tracing and Logging APIs; the former
    469495refers to debug information that we wish to be able to turn on and off
    470 without recompiling (although it will \emph{not} be available in
    471 production code); the latter means information about the processing
    472 that must be collected and saved, even in the production system.
    473 
    474 We envision that we will make extensive use of \code{psTrace} throughout
    475 the \PS{} code.
     496without recompiling (it will \emph{not} be available in production
     497code); the latter means information about the processing that must be
     498collected and saved, even in the production system.  We envision that
     499we will make extensive use of \code{psTrace} throughout the \PS{}
     500code.
    476501
    477502\subsubsection{Tracing APIs}
    478503\hlabel{psTrace}
    479504
    480 \begin{verbatim}
    481 #if defined(PS_NTRACE)
    482 #  define psTrace(facil, level, ...) /* do nothing */
    483 #else
    484 #  define psTrace(facil, level, ...) \
    485           p_psTrace(facil, level, __VA_ARGS__)
    486 #endif
    487 
    488 /// Send a trace message
    489 void p_psTrace(const char *facil,       ///< facilty of interest
    490                int level,               ///< desired trace level
    491                ...                      ///< trace message arguments
    492     );
    493 
    494 /// Set trace level
    495 int psSetTraceLevel(const char *facil,  ///< facilty of interest
    496                     int level           ///< desired trace level
    497     );
    498 
    499 /// Get the trace level
    500 int psGetTraceLevel(const char *name    ///< facilty of interest
    501     );
    502 
    503 /// turn off all tracing, and free trace's allocated memory
    504 void psTraceReset(void);
    505 
    506 /// print trace levels
    507 void psPrintTraceLevels(void);
    508 \end{verbatim}
    509 
    510 \begin{itemize}
    511   \item
    512     Logging is provided by the function \code{psTrace},
    513     which is actually a macro.  When the macro \code{PS_NTRACE}
    514     is defined, all occurrences of \code{psTrace} shall
    515     be replaced by whitespace.
    516 
    517   \item
    518     The first argument to \code{psTrace} is a name of the form
    519     \code{aaa.bbb.ccc}. The second is an integer,
    520     \code{level}. The remaining arguments are a printf-style format
    521     and a (possibly empty) set of values for that formatting
    522     string. When this trace is active, \code{psTrace} shall generate
    523     the requested output on \code{stdout}, preceded by \code{level}
    524     spaces.
    525 
    526   \item
    527     The call \code{psSetTraceLevel(name, level)} shall set the trace
    528     level for \code{name} to \code{level}.
    529 
    530   \item
    531     The call \code{psGetTraceLevel(name)} shall return the level
    532     associated with \code{name}.  If \code{name} has not been
    533     associated with a level, the routine shall remove the \textit{last}
    534     element of \code{name} and attempt to look up its level; this
    535     procedure shall be applied recursively until the name is reduced
    536     to \code{""}; if this name has no level associated with
    537     it, then the value \code{0} shall be returned (see examples
    538     below).
    539 
    540     \item
    541       The call \code{psTrace(name, level, ...)}
    542       shall print the message if and only if
    543       \code{psGetTraceLevel(name)} returns a value greater than
    544       or equal to \code{level}.
    545 
    546     \item
    547       \code{psPrintTraceLevels} shall print a listing of all
    548       declared levels, displayed as a hierarchy with sub-components
    549       sorted within each component (see examples below).
    550 
    551       Note in particular that the root of the tree, the name \code{""}
    552       should print as \code{(root)}, and nodes which have not
    553       been assigned a value should list their level as \code{.}.
    554 
    555     \item
    556       All of the tracing facilities shall be SWIGed, with the exception
    557       of \code{p_psTrace}.
    558 
    559     \item
    560       There is no requirement that \code{psTrace} be usable from
    561       within the functions that implement the tracing or memory
    562       management systems.
    563 
    564     \item
    565       \code{psTraceReset} shall reset all tracing to the state that it
    566       had at program initiation, including freeing any memory that the
    567       tracing subsystem may have allocated.
    568 \end{itemize}
    569 
    570 \paragraph{Examples of the use of Tracing Facilities}
    571 
    572 For example, after the commands:
    573 \begin{verbatim}
    574     psSetTraceLevel("utils.dlist.add.head", 9);
    575     psSetTraceLevel("utils.dlist.add", 3);
    576     psSetTraceLevel("utils.dlist.remove", 4);
    577     psSetTraceLevel("coadd", 2);
    578     psSetTraceLevel("coadd.CR.remove.morphology", 5);
    579     psSetTraceLevel("utils.hash", 2);
    580     psSetTraceLevel("utils.dlist.add", 9);
    581     psSetTraceLevel("utils", 1);
    582 \end{verbatim}
    583 the command \code{psPrintTraceLevels()} should print:
    584 \begin{verbatim}
    585 (root)               0
    586  utils               1
    587   hash               2
    588   dlist              .
    589    remove            4
    590    add               9
    591     head             9
    592  coadd               2
    593   CR                 .
    594    remove            .
    595     morphology       5
    596 \end{verbatim}
    597 where \code{.} means that the trace level should be inherited from its parent.
    598 
    599 After this set of \code{psSetTraceLevel} commands, and if
    600 \code{PS_NTRACE} is not defined, the following commands
    601 \begin{verbatim}
    602     psTrace("utils.dlist.remove", 2, "Removing psDList key \"%s\"\n", "my_key");
    603     psTrace("utils", 2, "Initialising utilities library\n");
    604     psTrace("", 2, "This is turned on by trace component \"\"");
    605     psTrace("utils.dlist", 2, "Initialising psDList\n");
    606     psTrace("utils.dlist.remove", 4, "Removing psDList key \"%s\" (value: \"%d\")\n", "my_key", 12345);
    607     psTrace("utils.hash.remove", 4, "Removing hash key \"%s\" (value: \"%d\")\n", "my_key", 12345);
    608     psTrace("utils.dlist.add", 1, "Adding psDList key \"%s\"\n", "your_key");
    609     psTrace("utils.dlist.find", 2, "Looking up psDList key \"%s\"\n", "some_key");
    610     psTrace("coadd.CR.remove", 4, "Removing CRs\n");
    611     psTrace("coadd.CR.remove.morphology", 4, "CRs are not fuzzy\n");
    612 \end{verbatim}
    613 should produce this output:
    614 \begin{verbatim}
    615   Removing psDList key "my_key"
    616     Removing psDList key "my_key" (value: "12345")
    617  Adding psDList key "your_key"
    618     CRs are not fuzzy
    619 \end{verbatim}
    620 
    621 Note that
    622 \begin{description}
    623 \item
    624   \code{utils.dlist} messages are at level 1, inherited from \code{utils}, so the
    625   \code{Initialising utilities library}, \code{Initialising psDList}, and
    626   \code{Looking up psDList key} messages are \emph{not} printed (the traces are at level 2).
    627 
    628 \item
    629   \code{utils.dlist.remove} messages are at level 4, and are printed.
    630 
    631 \item
    632   \code{utils.hash} messages are at level 2, and are not printed (the traces are at level 4)
    633 
    634 \item
    635   \code{coadd.CR.remove} is at level 2 (inherited from \code{coadd}) so \code{Removing CRs}
    636   isn't printed.  \code{coadd.CR.remove.morphology} is at level 4, so \code{CRs are not fuzzy} is printed.
    637 \end{description}
     505A code-tracing facility should allow the programmer to place messages
     506in the code which, when called, will print some useful information
     507about the containing block of code.  Ideally, different messages may
     508be specified to have different levels (of severity or interest).  For
     509a given run of the program, the level of interest should be set to
     510provide more or less feedback, depending on the needs of the
     511programmer.  In a typical situation, low-level messages would be
     512placed generously throughout the code, indicating the flow of the
     513program.  Higher-level messages would be placed in a limited number of
     514special locations, such as the start of major code segments or where a
     515particularly unusual condition is met.  Top-level messages would be
     516placed in code triggered under serious error conditions.  A normal run
     517of the program would have the trace messages printed only for the
     518top-level.  If the user needs to dig deeper into the code, the trace
     519level should be set lower, and the more detailed messages could be
     520examined.  In a case of a real, poorly-understood problem with the
     521code, the trace threshold would be placed to the bottom and the
     522lowest-level step-by-step messages would be printed.
     523
     524The PSLib tracing facility provides the above functionality along with
     525the ability to assign different trace levels to different types of
     526messages.  Each trace message when placed in the code is assigned to
     527be part of a specific tracing 'facility', defined in more detail
     528below.  The trace level for that specific message is also set when the
     529message is placed.  Each facility may have its trace level set
     530independently.  Thus, it is possible to request detailed trace output
     531for one facility while minimizing the verbosity of the trace output
     532from the rest of the program. 
     533
     534The trace facilities consist of a hierarchy of names.  A trace
     535facility is defined by a string consisting of words separated by dots,
     536with a hierarchy equivalent to that of UNIX directory names.  The
     537top-level facility is simply \code{'.'} (one dot).  The next level
     538would be \code{'.A'}, followed by \code{.A.B}, and so on.  The
     539relationship is seen in two ways.  First, a facility inherits the
     540trace level of its parent unless specified.  Second, the hierarchy is
     541used to format the listing of the trace facilities.  The first of
     542these rules provides a mechanism to define the default trace levels
     543for any facility even if it has not been registered explicitly since
     544all named facilities are implicitly children of the top level facility
     545(\code{.}).  The second rule is simply an organizational technique to
     546make the listing of facility information clear.
     547
     548The API to place a trace message in the code, and simultaneously set
     549its trace level and facility, is:
     550%
     551\begin{verbatim}
     552void psTrace(char *facil, int myLevel,...);
     553\end{verbatim}
     554%
     555where the last argument is a printf-style formatting code and possible
     556arguments to that formatting statement, to be implemented using the
     557\code{vprintf} functions.  This command specifies the name of the
     558facility to which the message belongs (\code{facil}), the trace level
     559for this message in that facility (\code{myLevel}) and the message
     560itself.
     561
     562The trace level for any facility may be set at any time with the
     563following function:
     564%
     565\begin{verbatim}
     566int psSetTraceLevel(char *facil, int level);
     567\end{verbatim}
     568%
     569where \code{level} specifies the current trace level for the facility
     570named by \code{facil}.  The currently defined trace level for a given
     571facility is determined by the function:
     572%
     573\begin{verbatim}
     574int psGetTraceLevel(char *facil);
     575\end{verbatim}
     576%
     577which returns the trace level of the named facility following the
     578rules specified above.  A specified trace message (identified by
     579\code{psTrace}) shall be printed if and only if
     580\code{psGetTraceLevel(facil)} returns a value greater than or equal to
     581the value of \code{myLevel} for that message.
     582
     583PSLib includes a utility function for examining the current tracing
     584levels of all facilities: \code{void psPrintTraceLevels(void);}.  This
     585function will print the hierarchy of trace facilities along with the
     586current trace level for each facility.  For example, a particular
     587program may have a few facilities defined, along with their trace
     588levels.  A call to \code{psPrintTraceLevels} may produce a listing
     589which appears as:
     590\begin{verbatim}
     591.                    0
     592.debias              1
     593.flatten             1
     594.flatten.divide      2
     595.object.findpeak     1
     596.object.getsky       1
     597\end{verbatim}
     598
     599Considering the same program, the programmer might place a variety of
     600trace messages throughout the \code{flatten} portion of the code with
     601different types of messages, such as:
     602%
     603\begin{verbatim}
     604psTrace("flatten", 2, "starting flatten function\n");
     605psTrace("flatten", 0, "ERROR: flat-field image \%s is invalid\n", filename);
     606psTrace("flatten.divide", 2, "doing the divide\n");
     607psTrace("flatten.divide", 3, "trying the loop, i = \%d\n", i);
     608psTrace("flatten.divide", 1, "got an invalid pixel value (NaN) at \%d,\%d\n");
     609psTrace("flatten.divide", 2, "divide is done\n");
     610\end{verbatim}
     611%
     612Under the trace levels set above, if the code actually reached each of
     613these trace messages, the following messages would be printed:
     614%
     615\begin{verbatim}
     616ERROR: flat-field image foo.fits is invalid  (printed)
     617doing the divide                             (printed)
     618got an invalid pixel value (NaN) at 500,20   (printed)
     619divide is done                               (printed)
     620\end{verbatim}
     621%
     622while these two would not be printed because their facility level was
     623too low:
     624%
     625\begin{verbatim}
     626starting flatten function
     627trying the loop, i = 0   
     628trying the loop, i = 1   
     629trying the loop, i = 2   
     630...
     631\end{verbatim}
     632%
     633
     634The tracing facility should be made available, or not, on compilation.
     635If the C pre-processor macro \code{PS_NO_TRACE} is defined, all trace
     636code shall be replaced by empty space so that none of the code is
     637compiled.  This can be implemented via macro front-ends to private
     638versions of the user APIs.  In addition, a function \code{void
     639psTraceReset(void)} will set all trace levels to 0.
     640
     641\tbd{ability to send trace messages to output locations other than stdout?}
    638642
    639643\subsubsection{Message Logging}
    640644\hlabel{psLogMsg}
    641645
    642 \begin{verbatim}
    643 enum { PS_LOG_ABORT = 0, PS_LOG_ERROR, PS_LOG_WARN, PS_LOG_INFO }; //!< Status codes for log messages
    644 
    645 enum { PS_LOG_TO_STDERR, PS_LOG_TO_STDOUT }; //!< Destinations for log messages
    646 
    647 /// Logs a message
    648 void psLogMsg(const char *name, int level, const char *fmt, ...);
    649 
    650 /// Logs a message from varargs
    651 void p_psVLogMsg(const char *name, int level, const char *fmt, va_list ap);
    652 
    653 /// Sets the log destination
     646Message logging is similar in some respects to tracing.  Like trace
     647messages, log messages are placed in the code at various locations to
     648provide output describing the current state of the program.  Like
     649the PSLib trace facility, a good log facility should have the
     650capability of associating each message with an importance or severity
     651level, and at any point, the level for which messages are actually
     652printed should be set in a flexible manner.   Unlike trace messages,
     653however, log messages are always part of the code and are available in
     654the production version as well as in test versions. 
     655
     656The PSLib logging facility does not include the extensive facility
     657levels which are provided by the trace facility.  Less control over
     658the granularity is needed for the log messages than for the trace
     659messages. 
     660
     661A log message is placed in the code with the command:
     662%
     663\begin{verbatim}
     664void psLogMsg(char *name, int myLevel, char *fmt, ...);
     665void psVLogMsg(char *name, int myLevel, char *fmt, va_list ap);
     666\end{verbatim}
     667where \code{name} is a word to describe the source of the message,
     668\code{myLevel} is the severity level of this message, and \code{fmt}
     669is a printf-style formatting statement defining the actual message,
     670and is followed by the arguments to the formatting code.  The second
     671form, \code{psVLogMsg} is an equivalent command which takes a
     672\code{va_list} argument.
     673
     674A log message may have any level specified in the range 0-9, though
     675the first 4 levels are associated with symbolic names:
     676%
     677\begin{verbatim}
     678enum { PS_LOG_ABORT = 0, PS_LOG_ERROR, PS_LOG_WARN, PS_LOG_INFO };
     679\end{verbatim}
     680%
     681The default level is set to \code{PS_LOG_INFO}. 
     682
     683At any time, the program may set the current log level, the level
     684above which log messages are ignored, using the function:
     685%
     686\begin{verbatim}
     687int psSetLogLevel(int level);           
     688\end{verbatim}
     689%
     690A specific message invoked with \code{psLogMsg} is only printed if its
     691value of \code{myLevel} is less than the current value set by
     692\code{psSetLogLevel}. 
     693
     694Log messages are sent to the destination most recently set using:
     695%
     696\begin{verbatim}
    654697int psSetLogDestination(int dest);     
    655 
    656 /// Sets the log level
    657 int psSetLogLevel(int level);           
    658 
    659 /// sets the log format
     698\end{verbatim}
     699%
     700The only two values that are initially defined are
     701\code{PS_LOG_TO_STDERR} and \code{PS_LOG_TO_STDOUT} to write to
     702\code{stderr} and \code{stdout} respectively.  \tbd{define other
     703destinations? why not use file descriptors?, etc?}.
     704
     705The output format is controlled with the function:
     706%
     707\begin{verbatim}
    660708void psSetLogFormat(const char *fmt);   
    661709\end{verbatim}
    662 
    663 The function \code{psSetLogLevel} may be used to set the current
    664 level of logging; the previous value is returned.
    665 The default value is \code{PS_LOG_INFO}. Valid values are 0---9
    666 inclusive (note that only the first four are required to have
    667 symbolic names).
    668 
    669 A call to \code{psLogMsg(name, level, msg, ...)} shall generate
    670 a log message if \code{level} is less than or equal to the
    671 value most recently set using \code{psSetLogLevel}. The function
    672 \code{p_psLogMsg} is identical, except that it expects a
    673 final \code{va_list} argument.
    674 
    675 The format of the log message shall be of the form:
    676 \begin{verbatim}
    677 YYYY:MM:DD hh:mm:ssZ|hostname|l|name            |msg
    678 \end{verbatim}
    679 \code{YYYY}, \code{MM}, \code{DD}, \code{hh}, \code{mm}, and \code{ss}
    680 are the year, month (Jan == 1), day of the month, hours (0--23),
    681 minutes, and seconds when the log message was received.  Note that the
    682 timestamp is in ISO order, and that the timezone is GMT (hence the
    683 \code{Z}).
    684 
    685 The \code{hostname} is returned by \code{gethostname}, \code{l} is a
    686 letter associated with the level (\code{A}, \code{E}, \code{W}, and
    687 \code{I} for \code{PS_LOG_ABORT}, \code{PS_LOG_ERROR}, \code{PS_LOG_WARN},
    688 and \code{PS_LOG_INFO} respectively. Other levels are represented
    689 numerically (\code{5} etc.). The other two field, \code{name} and
    690 \code{msg} are arguments to \code{psLogMsg}; note that \code{name} has
    691 a fixed width of 15 characters. If \code{msg} doesn't end in a newline,
    692 a single newline is emitted to terminate the message.
    693 
    694 An example message is:
    695 \begin{verbatim}
    696 2004:02:24 20:14:18Z|alibaba.IfA.Hawaii.Edu|I|utils          |Hello World
    697 \end{verbatim}
    698 
    699 Log messages are sent to the destination most recently set using
    700 \code{psSetLogDestination}.  The only two values that are initially
    701 defined are \code{PS_LOG_TO_STDERR} and \code{PS_LOG_TO_STDOUT} to
    702 write to \code{stderr} and \code{stdout} respectively.
    703 
    704 The fields included in the log message may be controlled using \code{psSetLogFormat} which
    705 expects a string consisting of the letters \code{H} (host), \code{L} (level), \code{M} (message),
    706 \code{N} (name), and \code{T} (time).  The default is \code{THLNM}, as shown above.
    707 
    708 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     710%
     711which expects a string consisting of the letters \code{H} (host),
     712\code{L} (level), \code{M} (message), \code{N} (name), and \code{T}
     713(time).  The default is \code{THLNM}, which produces log messages in
     714the form:
     715\begin{verbatim}
     716YYYY:MM:DD hh:mm:ssZ | hostname | L | name            | msg
     717\end{verbatim}
     718where \code{YYYY}, \code{MM}, \code{DD}, \code{hh}, \code{mm}, and
     719\code{ss} are the year, month (Jan == 1), day of the month, hours
     720(0--23), minutes, and seconds when the log message was received.  Note
     721that the timestamp is in ISO order, and that the timezone is GMT
     722(hence the \code{Z}).  The \code{hostname} is returned by
     723\code{gethostname}, \code{L} is a letter associated with the level
     724(\code{A}, \code{E}, \code{W}, and \code{I} for \code{PS_LOG_ABORT},
     725\code{PS_LOG_ERROR}, \code{PS_LOG_WARN}, and \code{PS_LOG_INFO}
     726respectively. Other levels are represented numerically (\code{5}
     727etc.). The other two field, \code{name} and \code{msg} are the
     728arguments to \code{psLogMsg}; note that \code{name} has a fixed width
     729of 15 characters. If \code{msg} doesn't end in a newline, a single
     730newline is emitted to terminate the message.  An example message is:
     731%
     732\begin{verbatim}
     7332004:02:24 20:14:18Z | alibaba.IfA.Hawaii.Edu |I | utils          | Hello World
     734\end{verbatim}
     735%
     736The possible order of the format entries is fixed and not determined
     737by the order of the letters.  Selecting an output format with fewer
     738than the complete set of 5 entries simply removes those entries from
     739the output messages.
     740
     741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    709742
    710743\subsection{Miscellaneous Utilities}
    711744
    712 \begin{verbatim}
    713 #define PS_STRING(S) #S                 // converts argument S to string
    714    
    715 /// Prints an error message and aborts
    716 void psAbort(const char *name,          ///< Category of code that caused the abort
    717              const char *fmt,           ///< Format
    718              ...                        ///< Extra arguments to use format
    719              );
    720 
    721 /// Prints an error message and doesn't abort
    722 void psError(const char *name,          ///< Category of code that caused the abort
    723              const char *fmt,           ///< Format
    724              ...                        ///< Extra arguments to use format
    725     );
    726 
    727 /// Allocates and returns a copy of a string
    728 char *psStringCopy(const char *str      ///< string to copy
    729     );
    730 
    731 /// Allocates nChar and returns a copy of the string or segment
    732 char *psStringNCopy(const char *str,    ///< string to copy
    733                     int nChar           //!< Number of characters (including \0 )
    734     );
    735 \end{verbatim}
    736 
    737 \code{psAbort} shall call \code{psMsgLog} with a level of \code{PS_LOG_ABORT},
    738 and then call \code{abort}.
    739 \code{psError} shall call \code{psMsgLog} with a level of \code{PS_LOG_ERROR},
    740 and then return.
    741 In cases of doubt, a good choice for
    742 \code{name} is \code{__func__}.
    743 
    744 \code{psStringCopy} shall allocate and return a copy of the input string.
    745 
    746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     745We require a several very low-functions.  Two functions provide
     746conveniences tied to the logging facilities:
     747%
     748\begin{verbatim}
     749void psAbort(char *name, char *fmt,...);
     750void psError(char *name, char *fmt,...);
     751\end{verbatim}
     752%
     753The first function, \code{psAbort}, shall call \code{psMsgLog} with a
     754level of \code{PS_LOG_ABORT}, and then call \code{abort}.  The second
     755function, \code{psError}, shall call \code{psMsgLog} with a level of
     756\code{PS_LOG_ERROR}, and then return.  In cases of doubt, a good
     757choice for \code{name} is \code{__func__}. 
     758
     759A few useful string functions are also necessary:
     760%
     761\begin{verbatim}
     762PS_STRING(S);
     763char *psStringCopy(char *string);
     764char *psStringNCopy(char *string, int nChar);
     765\end{verbatim}
     766%
     767The first function simply converts the argument to a string
     768\tbd{explanation of usage and rational?}.  The second function,
     769\code{psStringCopy}, shall allocate a sufficient memory block and
     770return a copy of the input string.  Similarly, \code{psStringNCopy}
     771shall allocate exactly \code{nChar} bytes and copy as much of the
     772input string as possible into the resulting block without overrunning
     773the available space.  The last byte of the output string is required
     774to be \code{NULL}, as well as any additional bytes if \code{string} is
     775not long enough to fill the output string.
     776
     777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    749778
    750779\section{Basic Data Collections}
     
    933962/** Doubly-linked list element */
    934963typedef struct psDlistElem {
    935    struct psDlistElem *prev;            //!< previous link in list
    936    struct psDlistElem *next;            //!< next link in list
    937    void *data;                          //!< real data item
     964   struct psDlistElem *prev;            ///< previous link in list
     965   struct psDlistElem *next;            ///< next link in list
     966   void *data;                          ///< real data item
    938967} psDlistElem;
    939968
    940969/** Doubly-linked list */
    941970typedef struct {
    942    int n;                               //!< number of elements on list
    943    psDlistElem *head;                   //!< first element on list (may be NULL)
    944    psDlistElem *tail;                   //!< last element on list (may be NULL)
    945    psDlistElem *iter;                   //!< iteration cursor
     971   int n;                               ///< number of elements on list
     972   psDlistElem *head;                   ///< first element on list (may be NULL)
     973   psDlistElem *tail;                   ///< last element on list (may be NULL)
     974   psDlistElem *iter;                   ///< iteration cursor
    946975} psDlist;
    947976
    948977/** Special values of index into list */
    949978enum {
    950    PS_DLIST_HEAD = 0,                   //!< at head
    951    PS_DLIST_TAIL = -1,                  //!< at tail
    952    PS_DLIST_UNKNOWN = -2,               //!< unknown position
    953    PS_DLIST_PREV = -3,                  //!< previous element
    954    PS_DLIST_NEXT = -4                   //!< next element
     979   PS_DLIST_HEAD = 0,                   ///< at head
     980   PS_DLIST_TAIL = -1,                  ///< at tail
     981   PS_DLIST_UNKNOWN = -2,               ///< unknown position
     982   PS_DLIST_PREV = -3,                  ///< previous element
     983   PS_DLIST_NEXT = -4                   ///< next element
    955984};
    956985\end{verbatim}
     
    960989\begin{verbatim}
    961990/** Constructor */
    962 psDlist *psDlistAlloc(void *data        //!< initial data item; may be NULL
     991psDlist *psDlistAlloc(void *data        ///< initial data item; may be NULL
    963992                      );
    964993
    965994/** Destructor */
    966 void psDlistFree(psDlist *list,         //!< list to destroy
    967                 void (*elemFree)(void *) //!< destructor for data on list
     995void psDlistFree(psDlist *list,         ///< list to destroy
     996                void (*elemFree)(void *) ///< destructor for data on list
    968997                 );
    969998
     
    9711000
    9721001/** Add to list */
    973 psDlist *psDlistAdd(psDlist *list,      //!< list to add to (may be NULL)
    974                     void *data,         //!< data item to add
    975                     int where           //!< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
     1002psDlist *psDlistAdd(psDlist *list,      ///< list to add to (may be NULL)
     1003                    void *data,         ///< data item to add
     1004                    int where           ///< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
    9761005                    );
    9771006
    9781007/** Append to a list */
    979 psDlist *psDlistAppend(psDlist *list,   //!< list to append to (may be NULL)
    980                        void *data       //!< data item to add
     1008psDlist *psDlistAppend(psDlist *list,   ///< list to append to (may be NULL)
     1009                       void *data       ///< data item to add
    9811010                       );
    9821011
    9831012/** Remove from a list */
    984 void *psDlistRemove(psDlist *list,      //!< list to remove element from
    985                     void *data,         //!< data item to remove
    986                     int which           //!< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
    987                                         //!< PS_DLIST_PREV
     1013void *psDlistRemove(psDlist *list,      ///< list to remove element from
     1014                    void *data,         ///< data item to remove
     1015                    int which           ///< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
     1016                                        ///< PS_DLIST_PREV
    9881017                    );
    9891018/** Retrieve from a list */
    990 void *psDlistGet(const psDlist *list,   //!< list to retrieve element from
    991                  int which              //!< index of item, or PS_DLIST_NEXT, or PS_DLIST_PREV
     1019void *psDlistGet(const psDlist *list,   ///< list to retrieve element from
     1020                 int which              ///< index of item, or PS_DLIST_NEXT, or PS_DLIST_PREV
    9921021                 );
    9931022
    9941023/** Convert doubly-linked list to an array */
    995 psVoidPtrArray *psDlistToArray(psDlist *dlist //!< List to convert
     1024psVoidPtrArray *psDlistToArray(psDlist *dlist ///< List to convert
    9961025                               );
    9971026
    9981027/** Convert array to a doubly-linked list */
    999 psDlist *psArrayToDlist(psVoidPtrArray *arr //!< Array to convert
     1028psDlist *psArrayToDlist(psVoidPtrArray *arr ///< Array to convert
    10001029                        );
    10011030\end{verbatim}
     
    10151044\begin{verbatim}
    10161045/** Set the iterator */
    1017 void psDlistSetIterator(psDlist *list,  //!< list to retrieve element from
    1018                         int where,      //!< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
    1019                         int which       //!< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
    1020                                         //!< PS_DLIST_PREV
     1046void psDlistSetIterator(psDlist *list,  ///< list to retrieve element from
     1047                        int where,      ///< index, PS_DLIST_HEAD, or PS_DLIST_TAIL
     1048                        int which       ///< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
     1049                                        ///< PS_DLIST_PREV
    10211050                        );
    10221051
    10231052/** Get next element */
    1024 void *psDlistGetNext(psDlist *list,     //!< list to retrieve element from
    1025                      int which          //!< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
    1026                                         //!< PS_DLIST_PREV
     1053void *psDlistGetNext(psDlist *list,     ///< list to retrieve element from
     1054                     int which          ///< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
     1055                                        ///< PS_DLIST_PREV
    10271056                     );
    10281057
    10291058/** Get previous element */
    1030 void *psDlistGetPrev(psDlist *list,     //!< list to retrieve element from
    1031                      int which          //!< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
    1032                                         //!< PS_DLIST_PREV
     1059void *psDlistGetPrev(psDlist *list,     ///< list to retrieve element from
     1060                     int which          ///< index of item, or PS_DLIST_UNKNOWN, or PS_DLIST_NEXT, or
     1061                                        ///< PS_DLIST_PREV
    10331062                     );
    10341063\end{verbatim}
     
    10481077\code{psDlist}).
    10491078
     1079\subsubsubsection{Rationale}
     1080
     1081\tbd{defer this example to the psDlist section?}
     1082
     1083The \code{psMemBlock.refcounter} is clearly useful for detecting
     1084attempts to free memory that is already free.  A more complex
     1085application is for allowing pointers to complex data-objects (e.g.\
     1086images) to appear in more than one data structure simultaneously:
     1087
     1088\begin{verbatim}
     1089typedef struct {
     1090    char *name;
     1091    int value;
     1092} psSimple;
     1093
     1094psSimple *psSimpleAlloc(const char *name, int val)
     1095{
     1096    psSimple *simp = psAlloc(sizeof(psSimple));
     1097    simp->name = strcpy(psAlloc(strlen(name) + 1), name);
     1098    simp->value = val;
     1099
     1100    return simp;
     1101}
     1102
     1103void psSimpleFree(psSimple *simp)
     1104{
     1105    if (simp == NULL) { return; }
     1106
     1107    if (psMemGetRefCounter(simp) > 1) {
     1108        (void)psMemDecrRefCounter(simp);
     1109        return;
     1110    }
     1111}
     1112\end{verbatim}
     1113
     1114Because of the use of the \code{refcounter} field, we can safely put items of
     1115this type onto many lists:
     1116\goodbreak
     1117\begin{verbatim}
     1118simp = psSimpleAlloc("RHL", 0);
     1119psDlistAppend(list1, psMemIncrRefCounter(simp));
     1120psDlistAppend(list2, psMemIncrRefCounter(simp));
     1121psSimpleFree(simp);
     1122\end{verbatim}
     1123
     1124(Note: in fact there is no need to explicitly increment the counter
     1125in this case, as the \code{psDlistAppend} (section \ref{psDlist})
     1126API specifies that it
     1127does it for you.)
     1128
    10501129\subsection{Hash Tables}
    10511130\hlabel{psHash}
     
    10871166\end{verbatim}
    10881167
    1089 
    10901168A hash table is an abstract type \code{psHash}.  The argument
    10911169\code{nbucket} to \code{psHashAlloc} is a non-binding suggestion
     
    11081186\code{psHashRemove} removes the entry associated with the
    11091187key from the table, and returns the \code{data}; if the key's invalid it returns NULL.
     1188
     1189\code{psHashKeylist} returns the complete list of defined keys
     1190associated with the psHash table. \tbd{API is not yet specified.}
    11101191
    11111192\section{Data manipulation}
     
    11231204\item (Fast) Fourier Transforms;
    11241205\item General functions; and
    1125 \item Minimisation and fitting routines.
     1206\item Minimization and fitting routines.
    11261207\end{itemize}
    11271208
     
    11371218/** A bitmask of arbitrary length. */
    11381219typedef struct {
    1139     int n;                              //!< Number of chars that form the mask
    1140     char *bits;                         //!< The bits
     1220    int n;                              ///< Number of chars that form the mask
     1221    char *bits;                         ///< The bits
    11411222} psBitMask;
    11421223\end{verbatim}
     
    11461227\begin{verbatim}
    11471228/** Constructor */
    1148 psBitMask *psBitMaskAlloc(int n         //!< Number of bits required
     1229psBitMask *psBitMaskAlloc(int n         ///< Number of bits required
    11491230    );
    11501231 
    11511232/** Destructor */
    1152 void psBitMaskFree(psBitMask *restrict myMask //!< Bit mask to destroy
     1233void psBitMaskFree(psBitMask *restrict myMask ///< Bit mask to destroy
    11531234    );
    11541235\end{verbatim}
     
    11651246/** Set a bit mask */
    11661247psBitMask *
    1167 psBitMaskSet(psBitMask *outMask,        //!< Output bit mask or NULL
    1168              const psBitMask *myMask,   //!< Input bit mask
    1169              int bit                    //!< Bit to set
     1248psBitMaskSet(psBitMask *outMask,        ///< Output bit mask or NULL
     1249             const psBitMask *myMask,   ///< Input bit mask
     1250             int bit                    ///< Bit to set
    11701251    );
    11711252\end{verbatim}
     
    11741255/** Check a bit mask.  Returns true or false */
    11751256int
    1176 psBitMaskTest(const psBitMask *checkMask, //!< Bit mask to check
    1177               int bit                   //!< Bit to check
     1257psBitMaskTest(const psBitMask *checkMask, ///< Bit mask to check
     1258              int bit                   ///< Bit to check
    11781259    );
    11791260\end{verbatim}
     
    11821263/** apply the given operator to two bit masks */
    11831264psBitMask *
    1184 psBitMaskOp(psBitMask *outMask,         //!< Output bit mask or NULL
    1185             const psBitMask *restrict inMask1, //!< Input bit mask 1
    1186             char *operator,             //!< bit mask operator (AND, OR, XOR)
    1187             const psBitMask *restrict inMask2 //!< Input bit mask 2
     1265psBitMaskOp(psBitMask *outMask,         ///< Output bit mask or NULL
     1266            const psBitMask *restrict inMask1, ///< Input bit mask 1
     1267            char *operator,             ///< bit mask operator (AND, OR, XOR)
     1268            const psBitMask *restrict inMask2 ///< Input bit mask 2
    11881269    );
    11891270\end{verbatim}
     
    11981279/** Sort an array. Inputs not restrict-ed to allow sort in place */
    11991280psFloatArray *
    1200 psSort(psFloatArray *out,               //!< Sorted array to return. May be NULL
    1201        const psFloatArray *myArray      //!< Array to sort
     1281psSort(psFloatArray *out,               ///< Sorted array to return. May be NULL
     1282       const psFloatArray *myArray      ///< Array to sort
    12021283    );
    12031284\end{verbatim}
     
    12051286We also require the ability to sort one array based on another.  In
    12061287order to facilitate this, we will have a sort function return an array
    1207 containing the indices for the unsorted list in the order appropriate
     1288containing the induces for the unsorted list in the order appropriate
    12081289for the sorted array:
    12091290
     
    12111292/** Sort an array, along with some other stuff.  Returns an index array */
    12121293psIntArray *
    1213 psSortIndex(psIntArray *restrict out;   //!< Output index array (may be NULL)
    1214             const psFloatArray *restrict myArray //!< Array to sort
     1294psSortIndex(psIntArray *restrict out;   ///< Output index array (may be NULL)
     1295            const psFloatArray *restrict myArray ///< Array to sort
    12151296    );
    12161297\end{verbatim}
     
    12511332/** Do Statistics on an array.  Returns a status value. */
    12521333psStats *
    1253 psArrayStats(const psFloatArray *restrict myArray, //!< Array to be analysed
    1254              const psIntArray *restrict maskArray, //!< Ignore elements where (maskArray & maskVal) != 0
    1255                                                    //!< May be NULL
    1256              unsigned int maskVal,      //!< Only mask elements with one of these bits set in maskArray
    1257              psStats *stats             //!< stats structure defines stats to be calculated and how
     1334psArrayStats(const psFloatArray *restrict myArray, ///< Array to be analysed
     1335             const psIntArray *restrict maskArray, ///< Ignore elements where (maskArray & maskVal) != 0
     1336                                                   ///< May be NULL
     1337             unsigned int maskVal,      ///< Only mask elements with one of these bits set in maskArray
     1338             psStats *stats             ///< stats structure defines stats to be calculated and how
    12581339             );
    12591340\end{verbatim}
     
    12651346/** generic statistics structure */
    12661347typedef struct {
    1267     double sampleMean;                  //<! formal mean of sample
    1268     double sampleMedian;                //<! formal median of sample
    1269     double sampleMode;                  //!< Formal mode of sample
    1270     double sampleStdev;                 //<! standard deviation of sample
    1271     double sampleUQ;                    //<! upper quartile of sample
    1272     double sampleLQ;                    //<! lower quartile of sample
    1273     double robustMean;                  //<! robust mean of array
    1274     double robustMeanError;             //<! error on robust mean
    1275     int    robustMeanNvalues;           //<! number of measurements used for robust mean
    1276     double robustMedian;                //<! robust median of array
    1277     double robustMedianError;           //<! error on robust median
    1278     int    robustMedianNvalues;         //<! number of measurements used for robust median
    1279     double robustMode;                  //!< Robust mode of array
    1280     double robustModeErr;               //!< Error in robust mode
    1281     int    robustModeNvalues;           //!< Number of measurements used for robust mode
    1282     double robustStdev;                 //<! robust standard deviation of array
    1283     double robustUQ;                    //<! robust upper quartile
    1284     double robustLQ;                    //<! robust lower quartile
    1285     double clippedMean;                 //<! Nsigma clipped mean
    1286     double clippedMeanError;            //<! error on clipped mean
    1287     int    clippedMeanNvalues;          //<! number of data points used for clipped mean
    1288     double clippedStdev;                //!< standard deviation after clipping
    1289     double clipSigma;                   //<! Nsigma used for clipping; user input
    1290     int    clipIter;                    //!< Number of clipping iterations; user input
    1291     double min;                         //<! minimum data value in array
    1292     double max;                         //<! maximum data value in array
    1293     int    nValues;                     //<! number of data values in array
    1294     psStatsOptions options;             //<! bitmask of calculated values
     1348    double sampleMean;                  ///< formal mean of sample
     1349    double sampleMedian;                ///< formal median of sample
     1350    double sampleMode;                  ///< Formal mode of sample
     1351    double sampleStdev;                 ///< standard deviation of sample
     1352    double sampleUQ;                    ///< upper quartile of sample
     1353    double sampleLQ;                    ///< lower quartile of sample
     1354    double robustMean;                  ///< robust mean of array
     1355    double robustMeanError;             ///< error on robust mean
     1356    int    robustMeanNvalues;           ///< number of measurements used for robust mean
     1357    double robustMedian;                ///< robust median of array
     1358    double robustMedianError;           ///< error on robust median
     1359    int    robustMedianNvalues;         ///< number of measurements used for robust median
     1360    double robustMode;                  ///< Robust mode of array
     1361    double robustModeErr;               ///< Error in robust mode
     1362    int    robustModeNvalues;           ///< Number of measurements used for robust mode
     1363    double robustStdev;                 ///< robust standard deviation of array
     1364    double robustUQ;                    ///< robust upper quartile
     1365    double robustLQ;                    ///< robust lower quartile
     1366    double clippedMean;                 ///< Nsigma clipped mean
     1367    double clippedMeanError;            ///< error on clipped mean
     1368    int    clippedMeanNvalues;          ///< number of data points used for clipped mean
     1369    double clippedStdev;                ///< standard deviation after clipping
     1370    double clipSigma;                   ///< Nsigma used for clipping; user input
     1371    int    clipIter;                    ///< Number of clipping iterations; user input
     1372    double min;                         ///< minimum data value in array
     1373    double max;                         ///< maximum data value in array
     1374    int    nValues;                     ///< number of data values in array
     1375    psStatsOptions options;             ///< bitmask of calculated values
    12951376} psStats;
    12961377\end{verbatim}
     
    13051386/** Histograms */
    13061387typedef struct {
    1307     const psFloatArray *restrict lower; //!< Lower bounds for the bins
    1308     const psFloatArray *restrict upper; //!< Upper bounds for the bins
    1309     psIntArray *nums;                   //!< Number in each of the bins
    1310     const float minVal, maxVal;         //!< Minimum and maximum values
    1311     int minNum, maxNum;                 //!< Number below the minimum and above the maximum
     1388    const psFloatArray *restrict lower; ///< Lower bounds for the bins
     1389    const psFloatArray *restrict upper; ///< Upper bounds for the bins
     1390    psIntArray *nums;                   ///< Number in each of the bins
     1391    const float minVal, maxVal;         ///< Minimum and maximum values
     1392    int minNum, maxNum;                 ///< Number below the minimum and above the maximum
    13121393} psHistogram;
    13131394\end{verbatim}
     
    13211402/** Constructor */
    13221403psHistogram *
    1323 psHistogramAlloc(float lower,           //!< Lower limit for the bins
    1324                  float upper,           //!< Upper limit for the bins
    1325                  float size             //!< Size of the bins
     1404psHistogramAlloc(float lower,           ///< Lower limit for the bins
     1405                 float upper,           ///< Upper limit for the bins
     1406                 float size             ///< Size of the bins
    13261407    );
    13271408\end{verbatim}
     
    13301411/** Generic constructor */
    13311412psHistogram *
    1332 psHistogramAllocGeneric(const psFloatArray *restrict lower, //!< Lower bounds for the bins
    1333                         const psFloatArray *restrict upper, //!< Upper bounds for the bins
    1334                         float minVal,   //!< Minimum value
    1335                         float maxVal    //!< Maximum value
     1413psHistogramAllocGeneric(const psFloatArray *restrict lower, ///< Lower bounds for the bins
     1414                        const psFloatArray *restrict upper, ///< Upper bounds for the bins
     1415                        float minVal,   ///< Minimum value
     1416                        float maxVal    ///< Maximum value
    13361417    );
    13371418\end{verbatim}
     
    13401421/** Destructor */
    13411422void
    1342 psHistogramFree(psHistogram *restrict myHist //!< Histogram to destroy
     1423psHistogramFree(psHistogram *restrict myHist ///< Histogram to destroy
    13431424    );
    13441425\end{verbatim}
     
    13541435/** A matrix */
    13551436typedef struct {
    1356     int xSize, ySize;                   //!< Dimensions in x and y
    1357     float *restrict *restrict value;    //!< Values in matrix
     1437    int xSize, ySize;                   ///< Dimensions in x and y
     1438    float *restrict *restrict value;    ///< Values in matrix
    13581439} psMatrix;
    13591440\end{verbatim}
     
    13641445/** Constructor */
    13651446psMatrix *
    1366 psMatrixAlloc(int Xdimen,                       //!< x dimension of new matrix
    1367               int Ydimen                        //!< y dimension of new matrix
     1447psMatrixAlloc(int Xdimen,                       ///< x dimension of new matrix
     1448              int Ydimen                        ///< y dimension of new matrix
    13681449              );
    13691450\end{verbatim}
     
    13721453/** Destructor */
    13731454void
    1374 psMatrixFree(psMatrix *restrict myMatrix        //!< Matrix to destroy
     1455psMatrixFree(psMatrix *restrict myMatrix        ///< Matrix to destroy
    13751456             );
    13761457\end{verbatim}
     
    13891470/** Invert matrix.  Not using restrict, to allow inversion to be done in-place */
    13901471psMatrix *
    1391 psMatrixInvert(psMatrix *out,           //!< Matrix to return, or NULL
    1392                const psMatrix *myMatrix, //!< Matrix to be inverted
    1393                float *restrict determinant //!< Determinant to return, or NULL
     1472psMatrixInvert(psMatrix *out,           ///< Matrix to return, or NULL
     1473               const psMatrix *myMatrix, ///< Matrix to be inverted
     1474               float *restrict determinant ///< Determinant to return, or NULL
    13941475    );
    13951476\end{verbatim}
     
    14051486/** Matrix operations */
    14061487psMatrix *
    1407 psMatrixOp(psMatrix *out,               //!< Matrix to return, or NULL
    1408            const psMatrix *matrix1,     //!< Matrix 1
    1409            const char *op,              //!< Operation to perform
    1410            const psMatrix *matrix2      //!< Matrix 2
     1488psMatrixOp(psMatrix *out,               ///< Matrix to return, or NULL
     1489           const psMatrix *matrix1,     ///< Matrix 1
     1490           const char *op,              ///< Operation to perform
     1491           const psMatrix *matrix2      ///< Matrix 2
    14111492           );
    14121493\end{verbatim}
     
    14151496/** Transpose Matrix */
    14161497psMatrix *
    1417 psMatrixTranspose(psMatrix *out,        //!< Matrix to return, or NULL
    1418                   const psMatrix *myMatrix //!< Matrix to transpose
     1498psMatrixTranspose(psMatrix *out,        ///< Matrix to return, or NULL
     1499                  const psMatrix *myMatrix ///< Matrix to transpose
    14191500                  );
    14201501\end{verbatim}
     
    14231504/** Convert matrix to vector.  Intended for a 1-d matrix. */
    14241505psVector *
    1425 psMatrixToVector(psMatrix *myMatrix     //!< Matrix to convert
     1506psMatrixToVector(psMatrix *myMatrix     ///< Matrix to convert
    14261507    );
    14271508\end{verbatim}
     
    15731654    is not a Gaussian deviate.  The evaluated Gaussian is: \f[ exp(-\frac{(x-mean)^2}{2\sigma^2}) \f] */
    15741655float
    1575 psGaussian(float x,                     //!< Value at which to evaluate
    1576            float mean,                  //!< Mean for the Gaussian
    1577            float stddev                 //!< Standard deviation for the Gaussian
     1656psGaussian(float x,                     ///< Value at which to evaluate
     1657           float mean,                  ///< Mean for the Gaussian
     1658           float stddev                 ///< Standard deviation for the Gaussian
    15781659           );
    15791660\end{verbatim}
     
    15831664floating-point (for speed) and double-precision (for milli-arcsec
    15841665precision) versions.  This comes from the need to fit over $x$,$y$,
    1585 colour and magnitude simultaneously.  We must also be able to
     1666color and magnitude simultaneously.  We must also be able to
    15861667calculate the errors in the fit coefficients, as well as be able to
    15871668turn on and off each coefficient.  This leads us to define polynomial
     
    15911672/** One-dimensional polynomial */
    15921673typedef struct {
    1593     int n;                              //!< Number of terms
    1594     float *restrict coeff;              //!< Coefficients
    1595     float *restrict coeffErr;           //!< Error in coefficients
    1596     char *restrict mask;                //!< Coefficient mask
     1674    int n;                              ///< Number of terms
     1675    float *restrict coeff;              ///< Coefficients
     1676    float *restrict coeffErr;           ///< Error in coefficients
     1677    char *restrict mask;                ///< Coefficient mask
    15971678} psPolynomial1D;
    15981679\end{verbatim}
     
    16011682/** Two-dimensional polynomial */
    16021683typedef struct {
    1603     int nX, nY;                         //!< Number of terms in x and y
    1604     float *restrict *restrict coeff;    //!< Coefficients
    1605     float *restrict *restrict coeffErr; //!< Error in coefficients
    1606     char *restrict *restrict mask;      //!< Coefficients mask
     1684    int nX, nY;                         ///< Number of terms in x and y
     1685    float *restrict *restrict coeff;    ///< Coefficients
     1686    float *restrict *restrict coeffErr; ///< Error in coefficients
     1687    char *restrict *restrict mask;      ///< Coefficients mask
    16071688} psPolynomial2D;
    16081689\end{verbatim}
     
    16131694/** Double-precision one-dimensional polynomial */
    16141695typedef struct {
    1615     int n;                              //!< Number of terms
    1616     double *restrict coeff;             //!< Coefficients
    1617     double *restrict coeffErr;          //!< Error in coefficients
    1618     char *restrict mask;                //!< Coefficient mask
     1696    int n;                              ///< Number of terms
     1697    double *restrict coeff;             ///< Coefficients
     1698    double *restrict coeffErr;          ///< Error in coefficients
     1699    char *restrict mask;                ///< Coefficient mask
    16191700} psDPolynomial1D;
    16201701\end{verbatim}
     
    16231704/** Double-precision two-dimensional polynomial */
    16241705typedef struct {
    1625     int nX, nY;                         //!< Number of terms in x and y
    1626     double *restrict *restrict coeff;   //!< Coefficients
    1627     double *restrict *restrict coeffErr; //!< Error in coefficients
    1628     char *restrict *restrict mask;      //!< Coefficients mask
     1706    int nX, nY;                         ///< Number of terms in x and y
     1707    double *restrict *restrict coeff;   ///< Coefficients
     1708    double *restrict *restrict coeffErr; ///< Error in coefficients
     1709    char *restrict *restrict mask;      ///< Coefficients mask
    16291710} psDPolynomial2D;
    16301711\end{verbatim}
     
    16361717The constructor and destructor are:
    16371718\begin{verbatim}
    1638 psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY //!< Number of terms in x and y
    1639     );
    1640 void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly //!< Polynomial to destroy
     1719psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY ///< Number of terms in x and y
     1720    );
     1721void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly ///< Polynomial to destroy
    16411722    );
    16421723\end{verbatim}
     
    16471728/** Evaluate 2D polynomial (double precision) */
    16481729double
    1649 psEvalDPolynomial2D(double x,           //!< Value x at which to evaluate
    1650                     double y,           //!< Value y at which to evaluate
    1651                     const psDPolynomial2D *restrict myPoly //!< Coefficients for the polynomial
     1730psEvalDPolynomial2D(double x,           ///< Value x at which to evaluate
     1731                    double y,           ///< Value y at which to evaluate
     1732                    const psDPolynomial2D *restrict myPoly ///< Coefficients for the polynomial
    16521733                    );
    16531734\end{verbatim}
    16541735
     1736\tbd{generate a Gaussian deviate vector}
     1737
    16551738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    16561739
    16571740\subsection{Minimization and fitting routines}
    16581741
    1659 We require a general minimisation routine, a routine that will
    1660 specifically minimise $\chi^2$ given a list of data with associated
     1742We require a general minimization routine, a routine that will
     1743specifically minimize $\chi^2$ given a list of data with associated
    16611744errors, and a function that will analytically determine the polynomial
    16621745fit by least-squares.  The APIs are:
     
    16651748/** Minimize a particular function */
    16661749psFloatArray *
    1667 psMinimize(float (*myFunction)(const psFloatArray *restrict),   //!< Function to minimize
    1668            psFloatArray *restrict initialGuess //!< Initial guess
     1750psMinimize(float (*myFunction)(const psFloatArray *restrict),   ///< Function to minimize
     1751           psFloatArray *restrict initialGuess ///< Initial guess
    16691752           );
    16701753\end{verbatim}
     
    16741757psFloatArray *
    16751758psMinimizeChi2(float (*evalModel)(const psFloatArray *restrict,
    1676                                   const psFloatArray *restrict), //!< Model to fit; receives domain and
    1677                                                                  //!< parameters
    1678                const psFloatArray *restrict domain, //!< The domain values for the corresponding measurements
    1679                const psFloatArray *restrict data, //!< Data to fit
    1680                const psFloatArray *restrict errors, //!< Errors in the data
    1681                psFloatArray *restrict initialGuess, //!< Initial guess
    1682                const psIntArray *restrict guessMask //!< 1 = fit for parameter, 0 = hold parameter constant
     1759                                  const psFloatArray *restrict), ///< Model to fit; receives domain and
     1760                                                                 ///< parameters
     1761               const psFloatArray *restrict domain, ///< The domain values for the corresponding measurements
     1762               const psFloatArray *restrict data, ///< Data to fit
     1763               const psFloatArray *restrict errors, ///< Errors in the data
     1764               psFloatArray *restrict initialGuess, ///< Initial guess
     1765               const psIntArray *restrict guessMask ///< 1 = fit for parameter, 0 = hold parameter constant
    16831766               );
    16841767\end{verbatim}
     
    16871770/** Derive a polynomial that goes through the points --- can be done analytically */
    16881771psFloatArray *
    1689 psGetArrayPolynomial(const psFloatArray *restrict ord, //!< Ordinates (or NULL to just use the indices)
    1690                      const psFloatArray *restrict coord //!< Coordinates
     1772psGetArrayPolynomial(const psFloatArray *restrict ord, ///< Ordinates (or NULL to just use the indices)
     1773                     const psFloatArray *restrict coord ///< Coordinates
    16911774    );
    16921775\end{verbatim}
     
    17181801        psF32 **rows_f32;               ///< pointers to psF32 data
    17191802        psF64 **rows_f64;               ///< pointers to psF64 data
    1720         psComplex **rows_complex;       //!< pointers to psComplex data
     1803        psComplex **rows_complex;       ///< pointers to psComplex data
    17211804    } rows;
    17221805    psImage *parent;                    ///< parent, if a subimage
     
    17321815restricted to the datatypes equivalent to the valid BITPIX values 8,
    1733181616, 32, -32, -64).  The image represented in the data structure may
    1734 represent a subset of the pixels in a complete array.  The offset of
    1735 the \code{(0,0)} pixel in this array relative to the parent array is
    1736 given by the elements \code{(x0,y0)}.  The structure may include
    1737 references to subrasters (\code{children, Nchildren}) and/or to a
    1738 containing array (\code{parent}).
     1817represent a subset of the pixels in a complete array, in which case
     1818the image is considered to be the child of that parent array.  The
     1819offset of the \code{(0,0)} pixel in this array relative to the parent
     1820array is given by the elements \code{(x0,y0)}.  The structure may
     1821include references to subrasters (\code{children, Nchildren}) and/or
     1822to a containing array (\code{parent}).
    17391823
    17401824We require a variety of functions to manipulate these image
     
    17591843/// Create a subimage of the specified area.
    17601844psImage *
    1761 psImageSubset(psImage *out,             //!< Subimage to return, or NULL
     1845psImageSubset(psImage *out,             ///< Subimage to return, or NULL
    17621846              const psImage *image,     ///< parent image
    17631847              int nx,                   ///< subimage width (<= image.nx - x0) 
     
    17791863\begin{verbatim}
    17801864psImage *
    1781 psImageFreePixels(psImage *restrict image //!< Image whose pixels are to be freed
     1865psImageFreePixels(psImage *restrict image ///< Image whose pixels are to be freed
    17821866    );
    17831867\end{verbatim}
     
    18101894\begin{verbatim}
    18111895psFloatArray *
    1812 psImageSlice(psFloatArray *out,         //!< Vector to output, or NULL
     1896psImageSlice(psFloatArray *out,         ///< Vector to output, or NULL
    18131897             const psImage *input,      ///< extract slice from this image
    18141898             int x,                     ///< starting x coord of region to slice
     
    18321916\begin{verbatim}
    18331917psFloatArray *
    1834 psImageCut(psFloatArray *out,           //!< Vector to output, or NULL
     1918psImageCut(psFloatArray *out,           ///< Vector to output, or NULL
    18351919           const psImage *input,        ///< extract cut from this image
    18361920           float xs,                    ///< starting x coord of cut
     
    18441928
    18451929
    1846 Extract radial annulii data to a vector.  A vector is constructed
     1930Extract radial annuli data to a vector.  A vector is constructed
    18471931where each vector elements is derived from the statistics of the
    1848 pixels which land in one of a sequence of annulii.  The annulii are
     1932pixels which land in one of a sequence of annuli.  The annuli are
    18491933centered on the image pixel coordinate \code{x,y}, and have width
    1850 \code{dr}.  The number of annulii is $radius / dr$.  The statistic
     1934\code{dr}.  The number of annuli is $radius / dr$.  The statistic
    18511935used to derive the output vector value is specified by \code{psStats
    18521936stats}
    18531937\begin{verbatim}
    18541938psFloatArray *
    1855 psImageRadialCut(psFloatArray *out,     //!< Vector to output, or NULL
     1939psImageRadialCut(psFloatArray *out,     ///< Vector to output, or NULL
    18561940                 const psImage *input,  ///< extract profile from this image
    18571941                 float x,               ///< center x coord of annulii
     
    18721956\begin{verbatim}
    18731957psImage *
    1874 psImageRebin(psImage *out,              //!< Image to output, or NULL
     1958psImageRebin(psImage *out,              ///< Image to output, or NULL
    18751959             const psImage *input,      ///< rebin this image
    18761960             float scale,               ///< rebinning scale: doutput = scale*dinput
     
    18871971\begin{verbatim}
    18881972psImage *
    1889 psImageRotate(psImage *out,             //!< Image to output, or NULL
     1973psImageRotate(psImage *out,             ///< Image to output, or NULL
    18901974              const psImage *input,     ///< rotate this image
    18911975              float angle               ///< rotate by this amount anti-clockwise (degrees)
     
    18971981values should interpolate between the input pixel values.  The output
    18981982image has the same dimensions as the input image.  Pixels which fall
    1899 off the edge of the output image are loast.  Newly exposed pixels are
     1983off the edge of the output image are lost.  Newly exposed pixels are
    19001984set to the value given by \code{exposed}. 
    19011985\begin{verbatim}
    19021986psImage *
    1903 psImageShift(psImage *out,              //!< Image to output, or NULL
     1987psImageShift(psImage *out,              ///< Image to output, or NULL
    19041988             const psImage *input,      ///< shift this image
    19051989             float dx,                  ///< shift by this amount in x
     
    19141998\begin{verbatim}
    19151999psImage *
    1916 psImageRoll(psImage *out,               //!< Image to output, or NULL
     2000psImageRoll(psImage *out,               ///< Image to output, or NULL
    19172001            const psImage *input,       ///< roll this image
    19182002            int dx,                     ///< roll this amount in x
     
    19412025Fit a 2-D polynomial surface to an image.  The input structure
    19422026\code{coeffs} contains the desired order and terms of interest.
    1943 \tbd{how do we specify the renomalization?}
     2027\tbd{how do we specify the renormalization?}
    19442028\begin{verbatim}
    19452029psPolynomial2D *
     
    20082092
    20092093Write an image section to named file, which may exist.  This
    2010 operatation may write a portion of an image over the existing bytes of
     2094operation may write a portion of an image over the existing bytes of
    20112095an existing image.  If the file does not exist, it should be created.
    20122096If the specified extension does not exist, it should be created.  If
     
    20672151\begin{verbatim}
    20682152psImage *
    2069 psImageFFT(psImage *output,             //!< Output image
     2153psImageFFT(psImage *output,             ///< Output image
    20702154           const psImage *input,        ///< image to FFT
    20712155           int direction                ///< FFT direction
     
    21982282\section{Astronomy-Specific Functions}
    21992283
    2200 Some basic, relatively simple astronomy-specific functions are
    2201 required which will serve as the foundation for building the Phase $N$
    2202 modules.  These functions are not expected to cover every forseeable
    2203 function, but will serve as the building blocks of more complicated
    2204 processing functions.
     2284The previous sections of this document defined basic functionality
     2285needed by a wide range of scientific programming.  The rest of this
     2286document concentrates on aspects of the library which are specific to
     2287astronomy.  Some basic, relatively simple astronomy-specific functions
     2288are required which will serve as the foundation for building the
     2289higher level modules.  These functions are not expected to cover every
     2290foreseeable function, but will serve as the building blocks of more
     2291complicated processing functions. 
    22052292
    22062293We require functions covering each of the following areas:
    22072294\begin{itemize}
    2208 \item Astrometry;
    2209 \item Dates and times;
    2210 \item Image handling;
    2211 \item Metadata;
    2212 \item Detector and sky positions;
    2213 \item Astronomical objects; and
    2214 \item Photometry.
     2295\item Dates and times
     2296\item Metadata
     2297\item Detector and sky positions
     2298\item Astronomy Image
     2299\item Astrometry
     2300\item Photometry
     2301\item Astronomical objects
    22152302\end{itemize}
    2216 These are each dealt with below.
    22172303
    22182304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    22242310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    22252311
    2226 \subsection{Detector and sky positions}
    2227 
    2228 Both detector and sky positions will be used extensively in the IPP.
    2229 Since these both contain two coordinates with their associated errors,
    2230 we bundle these into a single generic structure, \code{psCoord},
    2231 containing \code{union}s to handle the semantic differences.
    2232 
    2233 \begin{verbatim}
    2234 /** A point in 2-D space, with errors.
    2235  */
    2236 typedef union {
    2237     struct {
    2238         double x;                       //!< x position
    2239         double y;                       //!< y position
    2240         double xErr;                    //!< Error in x position
    2241         double yErr;                    //!< Error in y position
    2242     } xy;
    2243     struct {
    2244         double r;                       //!< RA
    2245         double d;                       //!< Dec
    2246         double rErr;                    //!< Error in RA
    2247         double dErr;                    //!< Error in Dec
    2248     } rd;
    2249 } psCoord;
    2250 \end{verbatim}
    2251 
    2252 \subsubsection{Transformations}
    2253 
    2254 We specify two types of transforms between coordinate systems.  The
    2255 first consists simply of two 2D polynomials to transform both
    2256 components; this will be used to apply the coordinate transformations
    2257 between Cells, Chips and the Focal Plane.  The second consists of two
    2258 4D polynomials; this will be used to apply position-, colour- and
    2259 magnitude-dependent distortions between the Focal Plane and the
    2260 Tangent Plane.
    2261 
    2262 \begin{verbatim}
    2263 /** A polynomial transformation between coordinate frames.  This may be a linear relationship, or may
    2264  *  represent a higher-order transformation.
    2265  */
    2266 typedef struct {
    2267     psDPolynomial2D *x;
    2268     psDPolynomial2D *y;
    2269 } psCoordXform;
    2270 \end{verbatim}
    2271 
    2272 \begin{verbatim}
    2273 /** The optical distortion terms.  The lowest two terms are the x and y axis of the target system.  The higher
    2274  *  two terms represent magnitude and color terms.
    2275  */
    2276 typedef struct {
    2277     psDPolynomial4D *x;
    2278     psDPolynomial4D *y;
    2279 } psDistortion;
    2280 \end{verbatim}
    2281 
    2282 We require corresponding functions to apply the transformations:
    2283 
    2284 \begin{verbatim}
    2285 /** apply the coordinate transformation to the given coordinate */
    2286 psCoord *psCoordXformApply (psCoord *out, //!< Output coordinates, or NULL
    2287                             const psCoordXform *frame, ///< coordinate transformation
    2288                             const psCoord *coords ///< input coordiate
    2289     );
    2290 \end{verbatim}
    2291 
    2292 \begin{verbatim}
    2293 /** apply the optical distortion to the given coordinate, magnitude, color */
    2294 psCoord *psDistortionApply (psCoord *out, //!< Output coordinates, or NULL
    2295                             const psdistortion *pattern, ///< optical distortion pattern
    2296                             const psCoord *coords, ///< input coordinate
    2297                             float mag,  ///< magnitude of object
    2298                             float color ///< color of object
    2299     );
    2300 \end{verbatim}
    2301 
    2302 
    2303 \subsubsection{Offsets}
    2304 
    2305 We require a function to calculate the offset between two positions on
    2306 the sky, as well as a function to apply an offset to a position.
    2307 
    2308 \begin{verbatim}
    2309 /** Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical */
    2310 psCoord *
    2311 psGetOffset(const psCoord *restrict position1, //!< Position 1
    2312             const psCoord *restrict position2, //!< Position 2
    2313             const char *type            //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
    2314     );
    2315 \end{verbatim}
    2316 
    2317 \begin{verbatim}
    2318 /** Apply an offset to a position */
    2319 psCoord *
    2320 psApplyOffset(const psCoord *restrict position, //!< Position
    2321               const psCoord *restrict offset, //!< Offset
    2322               const char *type          //!< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
    2323     );
    2324 \end{verbatim}
    2325 
    2326 
    2327 \subsubsection{Positions of Major SS Objects}
    2328 
    2329 We require the ability to calculate the position of major Solar System
    2330 objects, as well as Lunar phase.
    2331 
    2332 \begin{verbatim}
    2333 /** Get Sun Position */
    2334 psCoord *
    2335 psGetSunPos(float mjd                   //!< MJD to get position for
    2336     );
    2337 \end{verbatim}
    2338 
    2339 \begin{verbatim}
    2340 /** Get Moon position */
    2341 psCoord *
    2342 psGetMoonPos(float mjd,                 //!< MJD to get position for
    2343              double latitude,           //!< Latitude for apparent position
    2344              double longitude           //!< Longitude for apparent position
    2345     );
    2346 \end{verbatim}
    2347 
    2348 \begin{verbatim}
    2349 /** Get Moon phase */
    2350 float
    2351 psGetMoonPhase(float mjd                //!< MJD to get phase for
    2352     );
    2353 \end{verbatim}
    2354 
    2355 \begin{verbatim}
    2356 /** Get Planet positions */
    2357 psCoord *
    2358 psGetSolarSystemPos(const char *solarSystemObject, //!< Named S.S. object
    2359                     float mjd           //!< MJD to get position for
    2360     );
    2361 \end{verbatim}
    2362 
    2363 \subsubsection{Celestial Coordinate Conversions}
    2364 
    2365 We need to be able to convert between ICRS, Galactic and Ecliptic
    2366 coordinates.
    2367 
    2368 \begin{verbatim}
    2369 /** Convert ICRS to Ecliptic */
    2370 psCoord *
    2371 psCoordinatesItoE(const psCoord *restrict coordinates //!< ICRS coordinates to convert
    2372     );
    2373 \end{verbatim}
    2374 
    2375 \begin{verbatim}
    2376 /** Convert Ecliptic to ICRS */
    2377 psCoord *
    2378 psCoordinatesEtoI(const psCoord *restrict coordinates //!< Ecliptic coordinates to convert
    2379     );
    2380 \end{verbatim}
    2381 
    2382 \begin{verbatim}
    2383 /** Convert ICRS to Galactic */
    2384 psCoord *
    2385 psCoordinatesItoG(const psCoord *restrict coordinates //!< ICRS coordinates to convert
    2386     );
    2387 \end{verbatim}
    2388 
    2389 \begin{verbatim}
    2390 /** Convert Galactic to ICRS */
    2391 psCoord *
    2392 psCoordinatesGtoI(const psCoord *restrict coordinates //!< Galactic coordinates to convert
    2393     );
    2394 \end{verbatim}
    2395 
    2396 
    2397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2398 
    23992312\subsection{Metadata}
     2313
     2314\subsubsection{Conceptual Overview}
     2315
     2316Within PSLib, we provide a data structure to carry metadata and
     2317mechanisms to manipulate the metadata.  Metadata is a general concept
     2318that requires some discussion.  In any data analysis task, the
     2319ensemble of all possible data may be divided into two or three
     2320classes: there is the specific data of interest, there is data which
     2321is related or critical but not the primary data of interest, and there
     2322is all of the other data which may or may not be interesting.  For
     2323example, consider a simple 2D image obtained of a galaxy from a CCD
     2324camera on a telescope.  If you want to study the galaxy, the specific
     2325data of interest is the collection of pixels.  There are a variety of
     2326other pieces of data which are closely related and crucial to
     2327understanding the data in those pixels, such as the dimensions of the
     2328image, the coordinate system, the time of the image, the exposure
     2329time, and so forth.  Other data may be known which may be less
     2330critical to understanding the image, but which may be interesting or
     2331desired at a later date.  For example, the observer who took the
     2332image, the filter manufacturer, the humidity at the telescope, etc.
     2333
     2334Formally, all of the related data which describe the principal data of
     2335interest are metadata.  Note that which piece is the metadata and
     2336which is the data may depend on the context.  If you are examining the
     2337pixels in an image, the coordinate and flux of an object may be part
     2338of the metadata.  However, if you are analyzing a collection of
     2339objects extracted from an image, you may consider then pixel data
     2340simply part of the metadata associated with the list of objects. 
     2341
     2342There are various ways to handle metadata vs data within a programming
     2343environment.  In C, it is convenient to use structures to group
     2344associated data together.  One possibility is to define the metadata
     2345as part of the associated data structure.  For example, the image data
     2346structure would have elements for all possible associated measurement.
     2347This approach is both cumbersome (because of the large number metadata
     2348types), impractical (because the full range of necessary metadata is
     2349difficult to know in advance) and inflexible (because any change in
     2350the collection of metadata requires addition of new structure elements
     2351and recompilation). 
     2352
     2353An alternative is to place the metadata in a generic container and use
     2354lookup mechanisms to extract the appropriate metadata when needed.  An
     2355example of this is would be a text-based FITS header for an image read
     2356into a flat text buffer.  In this implementation, metadata lookup
     2357functions could return the current value of, for example, NAXIS1 (the
     2358number of columns of the image) by scanning through the header buffer.
     2359This method has the benefits of flexibility and simplicity of
     2360programming interface, but it has the disadvantage that all metadata
     2361is accessed though this lookup mechanism.  This may make the code less
     2362readable and it may slow down the access. 
     2363
     2364We propose an intermediate solution to this problem.  We specify a
     2365flexible, generic metadata container and access methods.  Data types
     2366which require access to a general collection of metadata should
     2367include an entry of this metadata type.  However, a subset of metadata
     2368concepts which are basic and frequently required may be placed in the
     2369coded structure elements.  This approach allows the code to refer to
     2370the basic metadata concepts as part of the data structure (ie,
     2371image.nx), but also allows us to provide access to any arbitrary
     2372metadata which may be generated.  As a practical matter, the choice of
     2373which entries are only in the metadata and which are part of the
     2374explicit structure elements is rather subjective.  Any data elements
     2375which are frequently used should be put in the structure; those which
     2376are only infrequently needed should be left in the generic metadata.
     2377
     2378There are some points of caution which must be noted.  Any
     2379manipulation of the data should be reflected in the metadata where
     2380appropriate.  This is always an issue of concern.  For example,
     2381consider an image of dimensions \code{Nx, Ny}.  If a function extracts
     2382a subraster, it must change the values of \code{Nx, Ny} to match the
     2383new dimensions.  What should it do to the corresponding metadata?
     2384Clearly, it should change the corresponding value which defines
     2385\code{Nx, Ny}.  However, it is not quite so simple: there may be other
     2386metadata values which depend on those values.  These must also be
     2387changed appropriately.  What if the metadata element points to a
     2388copy of the metadata which may be shared by other representations of
     2389the image?  These must be treated differently because the change would
     2390invalidate those other references. 
     2391
     2392A related issue is the definition of metadata names.  Entries in a
     2393structure have the advantage of being hardwired: every instance of
     2394that structure will have the same name for the same entry.  This is
     2395not necessarily the case with a more flexible metadata container.  The
     2396image exposure time is a notorious example in astronomy.  Different
     2397observatories use different header keywords (ie, metadata names) for
     2398the same concept of the exposure time (EXPTIME, EXPOSURE, OPENTIME,
     2399INTTIME, etc).  Any system which operates on these metadata needs to
     2400address the issue of identifying these names.  This issue seems like an
     2401argument for hardwiring metadata in the structure, but in fact it does
     2402not present such a strong case.  If the metadata are hardwired, some
     2403function will still have to know how to interpret the various names to
     2404populate the structure.  The concept can still be localized with
     2405generic metadata containers by including abstract metadata names
     2406within the code which are tied to the various implementations-specific
     2407metadata names. 
     2408
     2409\subsubsection{Metadata Representation}
    24002410
    24012411This section addresses the question of how \PS{} metadata should be
     
    24032413represented on disk.
    24042414
    2405 \subsubsection{Metadata Representation}
    2406 
    24072415We propose that an item of metadata be represented as a C structure with at least the following
    24082416fields:
     
    24102418/** A struct to define a single item of metadata */
    24112419typedef struct {
    2412     const int id;                       //!< unique ID for this item
    2413     char *restrict name;                //!< Name of item
    2414     psMetaDataType type;                //!< type of this item
    2415     psMetaDataFlags flags;              //!< flags associated with this item
     2420    const int id;                       ///< unique ID for this item
     2421    char *restrict name;                ///< Name of item
     2422    psMetaDataType type;                ///< type of this item
     2423    psMetaDataFlags flags;              ///< flags associated with this item
    24162424    const union {
    2417         float f;                        //!< floating value
    2418         int i;                          //!< integer value
    2419         void *v;                        //!< other type
    2420     } val;                              //!< value of metadata
    2421     char *comment;                      //!< optional comment ("", not NULL)
    2422     psDlist *restrict items;            //!< list of psMetaDataItems with the same name
     2425        float f;                        ///< floating value
     2426        int i;                          ///< integer value
     2427        void *v;                        ///< other type
     2428    } val;                              ///< value of metadata
     2429    char *comment;                      ///< optional comment ("", not NULL)
     2430    psDlist *restrict items;            ///< list of psMetaDataItems with the same name
    24232431} psMetaDataItem;
    24242432\end{verbatim}
     
    24372445\begin{verbatim}
    24382446/** Possible types of metadata. */
    2439 typedef enum {                          //!< type of val is:
    2440     PS_META_ITEM_SET = 0,               //!< NULL; metadata is in psMetaDataType.items
    2441     PS_META_FLOAT,                      //!< float (.f)
    2442     PS_META_INT,                        //!< int (.i)
    2443     PS_META_STR,                        //!< string (.v)
    2444     PS_META_IMG,                        //!< image (.v)
    2445     PS_META_JPEG,                       //!< JPEG (.v)
    2446     PS_META_PNG,                        //!< PNG (.v)
    2447     PS_META_ASTROM,                     //!< astrometric coefficients (.v)
    2448     PS_META_UNKNOWN,                    //!< other (.v)
    2449     PS_META_NTYPE                       //!< Number of types; must be last
     2447typedef enum {                          ///< type of val is:
     2448    PS_META_ITEM_SET = 0,               ///< NULL; metadata is in psMetaDataType.items
     2449    PS_META_FLOAT,                      ///< float (.f)
     2450    PS_META_INT,                        ///< int (.i)
     2451    PS_META_STR,                        ///< string (.v)
     2452    PS_META_IMG,                        ///< image (.v)
     2453    PS_META_JPEG,                       ///< JPEG (.v)
     2454    PS_META_PNG,                        ///< PNG (.v)
     2455    PS_META_ASTROM,                     ///< astrometric coefficients (.v)
     2456    PS_META_UNKNOWN,                    ///< other (.v)
     2457    PS_META_NTYPE                       ///< Number of types; must be last
    24502458} psMetaDataType;
    24512459\end{verbatim}
     
    24552463\textbf{Value} & \textbf{Type} & \textbf{member of union} & \textbf{Comments}\\
    24562464\hline
    2457 \code{PS_META_FLOAT} & float & f & value, not pointer, is stored \\
    2458 \code{PS_META_INT} & int & i & value, not pointer, is stored \\
    2459 \code{PS_META_STR} & string & v & value, not pointer to original, is stored \\
    2460 \code{PS_META_IMG} & psImage & v & \\
    2461 \code{PS_META_JPEG} & JPEG & v & \\
    2462 \code{PS_META_PNG} & PNG & v & \\
    2463 \code{PS_META_ASTROM} & psAstrom & v & \\
    2464 \code{\code{PS_META_UNKNOWN} & other & v & \\
    2465 PS_META_NTYPE} & (none) & & The number of types defined
     2465\code{PS_META_FLOAT}   & float    & f & value, not pointer, is stored \\
     2466\code{PS_META_INT}     & int      & i & value, not pointer, is stored \\
     2467\code{PS_META_STR}     & string   & v & value, not pointer to original, is stored \\
     2468\code{PS_META_IMG}     & psImage  & v & \\
     2469\code{PS_META_JPEG}    & JPEG     & v & \\
     2470\code{PS_META_PNG}     & PNG      & v & \\
     2471\code{PS_META_ASTROM}  & psAstrom & v & \\
     2472\code{PS_META_UNKNOWN} & other    & v & \\
     2473\code{PS_META_NTYPE}   & (none)   &  & The number of types defined
    24662474\end{tabular}
    24672475\begin{caption}{Supported Metadata Types}
     
    24762484/** A set of metadata */
    24772485typedef struct {
    2478     psDlist *restrict list;             //!< list of psMetaDataItem
    2479     psHash *restrict table;             //!< hash table of the same metadata
     2486    psDlist *restrict list;             ///< list of psMetaDataItem
     2487    psHash *restrict table;             ///< hash table of the same metadata
    24802488} psMetaDataSet;
    24812489\end{verbatim}
     
    25592567\begin{verbatim}
    25602568/** Constructor */
    2561 psMetaDataItem *psMetaDataItemAlloc(int typeFlags, //!< type of this piece of metadata + flags
    2562                                     const void *val, //!< value of new item N.b. a pointer even if the item
    2563                                                      //!< is of type e.g. int
    2564                                     const char *comment, //!< comment associated with item
    2565                                     const char *name, //!< name of new item of metadata (may be in sprintf
    2566                                                       //!< format)
    2567                                     ... //!< possible arguments for name format
     2569psMetaDataItem *psMetaDataItemAlloc(int typeFlags, ///< type of this piece of metadata + flags
     2570                                    const void *val, ///< value of new item N.b. a pointer even if the item
     2571                                                     ///< is of type e.g. int
     2572                                    const char *comment, ///< comment associated with item
     2573                                    const char *name, ///< name of new item of metadata (may be in sprintf
     2574                                                      ///< format)
     2575                                    ... ///< possible arguments for name format
    25682576    );
    25692577
    25702578/** Destructor */
    2571 void psMetaDataItemFree(psMetaDataItem *ms //!< piece of metadata to destroy
     2579void psMetaDataItemFree(psMetaDataItem *ms ///< piece of metadata to destroy
    25722580    );
    25732581/** Constructor */
    2574 psMetaDataSet *psMetaDataSetAlloc(void);   //!< make a new set of metadata
     2582psMetaDataSet *psMetaDataSetAlloc(void);   ///< make a new set of metadata
    25752583
    25762584/** Destructor */
    2577 void psMetaDataSetFree(psMetaDataSet *ms //!< destroy a set of metadata
     2585void psMetaDataSetFree(psMetaDataSet *ms ///< destroy a set of metadata
    25782586    );
    25792587
     
    25812589
    25822590/// Add entry to the end of the metadata set
    2583 psMetaDataItem *psMetaDataAppend(psMetaDataSet *restrict ms, //!< Metadata set to add to
    2584                                  psMetaDataItem *restrict item //!< Metatdata to add
     2591psMetaDataItem *psMetaDataAppend(psMetaDataSet *restrict ms, ///< Metadata set to add to
     2592                                 psMetaDataItem *restrict item ///< Metatdata to add
    25852593    );
    25862594
    25872595/// delete entry from the metadata set
    2588 psMetaDataItem *psMetaDataRemove(psMetaDataSet *restrict ms, //!< Metadata set to delete from
    2589                                  const char *restrict key //!< Key to delete
     2596psMetaDataItem *psMetaDataRemove(psMetaDataSet *restrict ms, ///< Metadata set to delete from
     2597                                 const char *restrict key ///< Key to delete
    25902598    );
    25912599
    25922600/// reset the iterator to the start of the list
    2593 void psMetaDataSetIterator(psMetaDataSet *ms //!< Metadata set to set iterator for
     2601void psMetaDataSetIterator(psMetaDataSet *ms ///< Metadata set to set iterator for
    25942602    );
    25952603
    25962604/// get the next entry in the sequence
    2597 psMetaDataItem *psMetaDataGetNext(psMetaDataSet *restrict ms, //!< Metadata set to get from
    2598                                   const char *restrict match //!< Match this
     2605psMetaDataItem *psMetaDataGetNext(psMetaDataSet *restrict ms, ///< Metadata set to get from
     2606                                  const char *restrict match ///< Match this
    25992607    );
    26002608
    26012609/// find the metadata with the specified key
    2602 psMetaDataItem *psMetaDataLookup(const psMetaDataSet *restrict ms, //!< Metadata set to look up
    2603                                  const char *restrict key //!< Key to find
     2610psMetaDataItem *psMetaDataLookup(const psMetaDataSet *restrict ms, ///< Metadata set to look up
     2611                                 const char *restrict key ///< Key to find
    26042612    );
    26052613
    26062614/// print metadata item to the specified stream
    2607 void psMetaDataItemPrint(FILE *fd,              //!< file descriptor to write to
    2608                          const psMetaDataItem *restrict ms, //!< item of metadata to print
    2609                          const char *prefix        //!< print this at the beginning of each line
    2610     );
    2611 \end{verbatim}
     2615void psMetaDataItemPrint(FILE *fd,              ///< file descriptor to write to
     2616                         const psMetaDataItem *restrict ms, ///< item of metadata to print
     2617                         const char *prefix        ///< print this at the beginning of each line
     2618    );
     2619\end{verbatim}
     2620
     2621\subsection{Detector and sky positions}
     2622
     2623Both detector and sky positions will be used extensively in the IPP.
     2624The first are linear coordinates which conform to Euclidean geometry
     2625while the second are angular coordinates for which additional care
     2626must often be taken.  Since these both consist of two coordinates with
     2627their associated errors, we bundle these into a single generic
     2628structure, \code{psCoord}, containing \code{union}s to handle the
     2629semantic differences.  A variety of functions should operate
     2630equivalently on both types of structures (\tbd{list}), while other
     2631functions must behave differently when the operand is an angular vs a
     2632linear coordinate system.
     2633
     2634\begin{verbatim}
     2635/** A point in 2-D space, with errors.
     2636 */
     2637typedef union {
     2638    struct {
     2639        double x;                       ///< x position
     2640        double y;                       ///< y position
     2641        double xErr;                    ///< Error in x position
     2642        double yErr;                    ///< Error in y position
     2643    } xy;
     2644    struct {
     2645        double r;                       ///< RA
     2646        double d;                       ///< Dec
     2647        double rErr;                    ///< Error in RA
     2648        double dErr;                    ///< Error in Dec
     2649    } rd;
     2650} psCoord;
     2651\end{verbatim}
     2652
     2653Three major classes of coordinate transformations are necessary.
     2654First, linear coordinates from one frame must be converted to linear
     2655coordinates in a different frame of references.  Simple transformations
     2656of this type are independent of other quantities of the positions --
     2657they are simply mapping between two linear spaces.  In practice, these
     2658transformations may often be a function of the magnitude or color of
     2659the imaged object.  The second type of conversion is the
     2660transformation of linear coordinates to angular coordinates and
     2661vice-versa.  This conversion depends on the desired projection, and
     2662may represent the real mapping performed by the telescope or may
     2663simply represent a convenient mechanism to display 3D coordinates in
     2664useful forms.  The third conversion of interest is the transformation
     2665of one set of spherical coordinates to another set.  Frequently in
     2666astronomy, these conversions consist only of rotations between the two
     2667spherical coordinates systems, where the coordinates of the pole and
     2668equatorial rotation between the two systems define the
     2669transformation.  Conversions between standard coordinate systems such
     2670as Galactic, Ecliptic, and various epochs of the Celestial coordinates
     2671are represented by these spherical transformations. 
     2672
     2673\subsubsection{Linear Coordinate Transformations}
     2674
     2675We specify two types of transforms between coordinate systems.  The
     2676first consists simply of two 2D polynomials to transform both
     2677components -- the output coordinates depend only on the input
     2678coordinates and no other quantities of objects at those coordinates.
     2679The second consists of two 4D polynomials in which the output
     2680coordinates are also specified to be a function of the magnitude and
     2681color of the object with the given coordinates.  This type of
     2682coordinate transformation is necessary to represent the
     2683(color-dependent) optical distortions caused by the atmosphere and
     2684camera optics, and the possibly effects of charge transfer
     2685inefficiency.  We specify two structures to represent the coefficients
     2686of these transformations:
     2687
     2688\begin{verbatim}
     2689/** A polynomial transformation between coordinate frames.  This may be a linear relationship, or may
     2690 *  represent a higher-order transformation.
     2691 */
     2692typedef struct {
     2693    psDPolynomial2D *x;
     2694    psDPolynomial2D *y;
     2695} psCoordXform;
     2696\end{verbatim}
     2697
     2698The \code{psDPolynomial2D} structures represent polynomials of
     2699arbitrary order as a function of two dimensions.  There is one of
     2700these structures for each of the two output dimensions.  As an
     2701example, consider the simple transformation from one linear coordinate
     2702frame \code{x,y} (say a single CCD) to a second frame \code{p,q} (say,
     2703a second CCD image). If we have only first order terms in the
     2704transformation \code{psCoordXform T}, the new coordinates would be
     2705represented by the terms:
     2706%
     2707\begin{verbatim}
     2708p = T.x->coeff[0][0] + x*T.x->coeff[1][0] + y*T.x->coeff[0][1];
     2709q = T.y->coeff[0][0] + x*T.y->coeff[1][0] + y*T.y->coeff[0][1];
     2710\end{verbatim}
     2711%
     2712where we have excluded the basic cross-term (\code{x*y}) by using the
     2713mask: \code{T.x->mask[1][1] = 0; T.y->mask[1][1] = 0;}
     2714
     2715\begin{verbatim}
     2716/** The optical distortion terms.  The lowest two terms are the x and y axis of the target system.  The higher
     2717 *  two terms represent magnitude and color terms.
     2718 */
     2719typedef struct {
     2720    psDPolynomial4D *x;
     2721    psDPolynomial4D *y;
     2722} psDistortion;
     2723\end{verbatim}
     2724
     2725Like \code{psCoordXform}, \code{psDistortion} contains two
     2726\code{psDPolynomial4D} structures representing polynomials of
     2727arbitrary order as a function of four, rather than two dimensions.
     2728There is one of these structures for each of the two output
     2729dimensions.  In this structure, the highest two dimensions could
     2730represent a magnitude and a color.  As an example, consider the simple
     2731transformation from one linear coordinate frame \code{x,y} (say a
     2732single CCD) of an object with magnitude and color \code{m,c} to a
     2733second frame \code{p,q} (say, a second CCD image). If we have only
     2734first order terms in the transformation \code{psCoordXform T}, the new
     2735coordinates would be represented by the terms:
     2736%
     2737\begin{verbatim}
     2738p = T.x->coeff[0][0][0][0] + x*T.x->coeff[1][0][0][0] + y*T.x->coeff[0][1][0][0] + m*T.x->coeff[0][0][1][0] + c*T.x->coeff[0][0][0][1]
     2739q = T.y->coeff[0][0][0][0] + x*T.y->coeff[1][0][0][0] + y*T.y->coeff[0][1][0][0] + m*T.y->coeff[0][0][1][0] + c*T.y->coeff[0][0][0][1]
     2740\end{verbatim}
     2741%
     2742where we have again excluded the cross-terms (\code{x*y}) by using the
     2743mask.
     2744
     2745We require corresponding functions to apply the transformations:
     2746%
     2747\begin{verbatim}
     2748/** apply the coordinate transformation to the given coordinate */
     2749psCoord *psCoordXformApply (psCoord *out, ///< Output coordinates, or NULL
     2750                            const psCoordXform *frame, ///< coordinate transformation
     2751                            const psCoord *coords ///< input coordiate
     2752    );
     2753\end{verbatim}
     2754%
     2755\begin{verbatim}
     2756/** apply the optical distortion to the given coordinate, magnitude, color */
     2757psCoord *psDistortionApply (psCoord *out, ///< Output coordinates, or NULL
     2758                            const psdistortion *pattern, ///< optical distortion pattern
     2759                            const psCoord *coords, ///< input coordinate
     2760                            float mag,  ///< magnitude of object
     2761                            float color ///< color of object
     2762    );
     2763\end{verbatim}
     2764%
     2765
     2766\subsubsection{Celestial Coordinate Conversions}
     2767
     2768We need to be able to convert between ICRS, Galactic and Ecliptic
     2769coordinates, and potentially between arbitrary spherical coordinate
     2770systems.  All of these basic spherical transformations represent
     2771rotations of the spherical coordinate reference.  We specify a general
     2772transformation function which takes a structure \code{psCoordSphere}
     2773defining the relationship between two spherical coordinate systems.
     2774We also define a function to generate \code{psCoordSphere}, which
     2775contains the appropriate sines and cosines of the angles, based on the
     2776three angles describing the location of the pole and the relative
     2777equatorial rotations of the two systems.  We also specify special
     2778coordinate transformations between standard coordinate systems which
     2779define the value of psCoordSphere internally and automatically.
     2780
     2781\begin{verbatim}
     2782/** Convert to new spherical coordinate system */
     2783psCoord *
     2784psCoordTransform (psCoord *coord,
     2785                  psCoordSphere *sphere) ///< ICRS coordinates to convert
     2786;
     2787\end{verbatim}
     2788
     2789\begin{verbatim}
     2790/** Construct  to new spherical coordinate system */
     2791psCoordSphere *
     2792psCoordSphereDefine (double pole1, double pole2, double rotation);
     2793\end{verbatim}
     2794
     2795\begin{verbatim}
     2796/** Convert ICRS to Ecliptic */
     2797psCoord *
     2798psCoordinatesItoE(const psCoord *restrict coordinates ///< ICRS coordinates to convert
     2799    );
     2800\end{verbatim}
     2801
     2802\begin{verbatim}
     2803/** Convert Ecliptic to ICRS */
     2804psCoord *
     2805psCoordinatesEtoI(const psCoord *restrict coordinates ///< Ecliptic coordinates to convert
     2806    );
     2807\end{verbatim}
     2808
     2809\begin{verbatim}
     2810/** Convert ICRS to Galactic */
     2811psCoord *
     2812psCoordinatesItoG(const psCoord *restrict coordinates ///< ICRS coordinates to convert
     2813    );
     2814\end{verbatim}
     2815
     2816\begin{verbatim}
     2817/** Convert Galactic to ICRS */
     2818psCoord *
     2819psCoordinatesGtoI(const psCoord *restrict coordinates ///< Galactic coordinates to convert
     2820    );
     2821\end{verbatim}
     2822
     2823
     2824\subsubsection{Projections}
     2825
     2826We require functions to convert between spherical and linear
     2827coordinate systems based on a variety of projections.  The required
     2828projections include:
     2829\begin{itemize}
     2830\item TAN
     2831\item SIN
     2832\item AIT
     2833\item PAR
     2834\item GLS
     2835\end{itemize}
     2836
     2837\begin{verbatim}
     2838psCoord *psCoordProject (psCoord *coord, char *projection);
     2839\end{verbatim}
     2840
     2841\subsubsection{Offsets}
     2842
     2843We require a function to calculate the offset between two positions on
     2844the sky, as well as a function to apply an offset to a position.
     2845
     2846\begin{verbatim}
     2847/** Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical */
     2848psCoord *
     2849psGetOffset(const psCoord *restrict position1, ///< Position 1
     2850            const psCoord *restrict position2, ///< Position 2
     2851            const char *type            ///< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
     2852    );
     2853\end{verbatim}
     2854
     2855\begin{verbatim}
     2856/** Apply an offset to a position */
     2857psCoord *
     2858psApplyOffset(const psCoord *restrict position, ///< Position
     2859              const psCoord *restrict offset, ///< Offset
     2860              const char *type          ///< Type of offset: Linear, Spherical/Arcsec, Spherical/Degreees etc
     2861    );
     2862\end{verbatim}
     2863
     2864
     2865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    26122866
    26132867\subsection{Astronomy Images}
    26142868
    2615 \subsubsection{Terminology}
    2616 
    2617 Some brief review of terminology would be useful so that previous
    2618 definitions do not influence the understanding of this document.
    2619 
    2620 A ``readout'' is a read of the detector.
    2621 
    2622 A ``cell'' is defined as the smallest element of the detector readout;
    2623 usually associated with an amplifier.  Correspondingly, each cell has
    2624 its own overscan region.  There may be multiple readouts in a cell if
    2625 the cell was used to provide fast guiding.
    2626 
    2627 A ``chip'' is defined as a contiguous piece of silicon, and consists
    2628 of a group of cells.
    2629 
    2630 A ``focal plane'' is defined as a mosaic of chips, and consists of a
    2631 group of chips.
     2869\subsubsection{Overview}
     2870
     2871Above, we have defined a basic container for a single 2D collection of
     2872pixels (\code{psImage}), along with basic operations to manipulate the
     2873image pixels.  For astronomical applications, this data structure is
     2874insufficient for two reasons.  First, it does provide sufficient
     2875additional metadata to describe the data in detail.  Second, astronomy
     2876applications frequent involve multiple, related images.  For
     2877PanSTARRS, and for general astronomical applications, we require a
     2878richer collection of data structures which describe a very general
     2879image concept.  We have defined several layers in the hierarchy which
     2880are necessary to describe the image data which will be produced by the
     2881PanSTARRS Gigapixel cameras as well as other standard astronomical
     2882images. 
     2883
     2884A simple 2D image is a basic data unit for much of astronomical
     2885imaging.  If we consider various optical and IR array cameras, a
     2886single readout of the detector produces a collection of pixels
     2887measurements.  We define our lowest-level astronomical image
     2888structure, \code{psReadout}, to contain the pixels produced by a
     2889single readout of the detector, along with metadata needed to define
     2890that readout: the origin and binning of the image relative to the
     2891original detector pixels explicitly in the structure, a pointer to the
     2892appropriate overscan region, and pointers to the general metadata and
     2893derived objects, if any.
     2894
     2895A single detector may produce more than one read which is associated.
     2896For example, infrared detectors frequently produce an image
     2897immediately after the detector is reset followed by an image after the
     2898basic exposure is complete.  Both readouts correspond to the same
     2899pixels, though the binning or rastering may be different between the
     2900two readouts.  Another example is the video sequence produced by the
     2901PanSTARRS Gigapix camera guide cells, each of which represents a
     2902series of many images from a subraster of pixels in the detector
     2903readout portion.  The second level of our image container hierarchy,
     2904\code{psCell}, consists of a collection of readouts from a single
     2905detector.
     2906
     2907In the PanSTARRS Gigapix camera, the basic readout region is a
     2908fraction of the full imaging area of a single CCD chip.  The chip is
     2909divided into 64 cells, any fraction of which may have been readout
     2910for a given exposure.  In other cameras, such as Megacam at CFHT, the
     2911individual CCDs have multiple amplifiers addressing contiguous
     2912portions of the detector.  In such cameras, each amplifier produces a
     2913separate collection of pixels.  In the third level of our image
     2914container hierarchy, the data structure \code{psChip} represents a
     2915collection of different cells.   
     2916
     2917The top level of our image container hierarchy is a complete focal
     2918plane array (\code{psFPA}).  This structure represents the collection
     2919of chips in the camera, all of which are read out in a given
     2920exposure. 
    26322921
    26332922For example, take a mosaic camera consisting of eight $2k\times 4k$
     
    26412930a few cells may be dead).  Some cells (those containing guide stars
    26422931for the orthogonal transfer) will contain multiple readouts.
     2932
     2933These data structures represent containers with which to carry around
     2934the collection of related image data.  There is no requirement on the
     2935functions or the structures that each instance of one of these data
     2936structures represent the physical hardware.  For example, it is not
     2937necessary that an instance of \code{psFPA} always carry the data for
     2938all 60 (or 64) Gigapixel camera OTAs.  The usage of these structures
     2939is such that all astronomical operations which apply to a CCD image
     2940should be performed on an instance of \code{psFPA}.  If a particular
     2941circumstance only requires a single 2D image, then that is represented
     2942by an instance of \code{psFPA} with one \code{psChip}, which in turn
     2943has one \code{psCell}, which in turn has one \code{psReadout}. 
     2944
     2945These container levels also include in their definition the information
     2946needed to transform the coordinates in one of the levels to the
     2947coordinate system relevant at the higher levels. 
    26432948
    26442949\subsubsection{A Readout}
     
    26542959/** a Readout: a collection of pixels */
    26552960typedef struct {
    2656     int x0, y0;                         //!< Offset from the lower-left corner
     2961    int x0, y0;                         ///< Offset from the lower-left corner
    26572962    psImage *image;                     ///< imaging area of cell
    26582963    psDlist *objects;                   ///< objects derived from cell
    26592964    psImage *overscan;                  ///< bias region (subimage) of cell
    2660     psMetaDataSet *md;                  //!< Readout-level metadata
     2965    psMetaDataSet *md;                  ///< Readout-level metadata
    26612966} psReadout;
    26622967\end{verbatim}   
    2663 
    26642968
    26652969\subsubsection{A Cell}
     
    26862990    int nReadouts;                      ///< number of readouts in this cell realization; each may have its own
    26872991                                        ///< image, objects and overscan.
    2688     struct psReadout *readouts;         //!< Readouts from the cell
     2992    struct psReadout *readouts;         ///< Readouts from the cell
    26892993    psMetaDataSet *md;                  ///< Cell-level metadata
    26902994
     
    27193023    psMetaDataSet *md;                  ///< Chip-level metadata
    27203024    psCoordXform *chipToFPA;            ///< Transformations from chip coordinates to FPA coordinates
    2721     psCoordXform *FPAtoChip;            //!< Transformations from FPA coordinates to chip
     3025    psCoordXform *FPAtoChip;            ///< Transformations from FPA coordinates to chip
    27223026
    27233027    struct psFPA *parentFPA;            ///< FPA which contains this chip
     
    27343038transformation will consist of two 4D polynomials (i.e.\ a function of
    27353039two coordinates in position, the magnitude of the object, and the
    2736 colour of the object) in order to correct for optical distortions and
     3040color of the object) in order to correct for optical distortions and
    27373041the effects of the atmosphere; hence we expect that it is prudent to
    27383042include a reverse transformation which will be derived from
    2739 numerically inverting the forward transformation.  Since colours are
    2740 involved in the transformation, it is necessary to specify the colour
     3043numerically inverting the forward transformation.  Since colors are
     3044involved in the transformation, it is necessary to specify the color
    27413045the transformation is defined for.  We also include some values to
    2742 characterise the quality of the transformation: the root mean square
     3046characterize the quality of the transformation: the root mean square
    27433047deviation for the x and y transformation fits, and the $\chi^2$ for
    27443048the transformation fit.
     
    27563060    psDistortion *TPtoFP;               ///< Transformation term from
    27573061    psDistortion *FPtoTP;               ///< Transformation term from
    2758     psFixedPattern *pattern;            //!< Fixed pattern residual offsets
     3062    psFixedPattern *pattern;            ///< Fixed pattern residual offsets
    27593063    psExposure *exp;                    ///< information about this exposure
    27603064    psPhotSystem colorPlus, colorMinus; ///< Colour reference
    2761     float rmsX, rmsY;                   //!< Dispersion in astrometric solution
    2762     float chi2;                         //!< chi^2 of astrometric solution
     3065    float rmsX, rmsY;                   ///< Dispersion in astrometric solution
     3066    float chi2;                         ///< chi^2 of astrometric solution
    27633067} psFPA;
    27643068\end{verbatim}
    2765 
    27663069
    27673070\subsubsection{Exposure information}
     
    27753078typedef struct {
    27763079    // Telescope longitude, latitude and height are stored separately, since they don't change with pointing
    2777     double ra, dec;                     //!< Telescope boresight
    2778     double ha;                          //!< Hour angle
    2779     double zd;                          //!< Zenith distance
    2780     double az;                          //!< Azimuth
    2781     double lst;                         //!< Local Sidereal Time
    2782     float mjd;                          //!< MJD of observation
    2783     float rotAngle;                     //!< Rotator position angle
    2784     float temp;                         //!< Air temperature, for estimating refraction
    2785     float pressure;                     //!< Air pressure, for calculating refraction
    2786     float humidity;                     //!< Relative humidity, for calculating refraction
    2787     float exptime;                      //!< Exposure time
     3080    double ra, dec;                     ///< Telescope boresight
     3081    double ha;                          ///< Hour angle
     3082    double zd;                          ///< Zenith distance
     3083    double az;                          ///< Azimuth
     3084    double lst;                         ///< Local Sidereal Time
     3085    float mjd;                          ///< MJD of observation
     3086    float rotAngle;                     ///< Rotator position angle
     3087    float temp;                         ///< Air temperature, for estimating refraction
     3088    float pressure;                     ///< Air pressure, for calculating refraction
     3089    float humidity;                     ///< Relative humidity, for calculating refraction
     3090    float exptime;                      ///< Exposure time
    27883091    /* Derived quantities */
    2789     float posAngle;                     //!< Position angle
    2790     float parallactic;                  //!< Parallactic angle
    2791     float airmass;                      //!< Airmass, calculated from zenith distance
    2792     float pf;                           //!< Parallactic factor
     3092    float posAngle;                     ///< Position angle
     3093    float parallactic;                  ///< Parallactic angle
     3094    float airmass;                      ///< Airmass, calculated from zenith distance
     3095    float pf;                           ///< Parallactic factor
    27933096    char *cameraName;                   ///< name of camera which provided exposure
    27943097    char *telescopeName;                ///< name of telescope which provided exposure
    2795     psGrommit *grommit;                 //!< Data needed to convert from the sky to the tangent plane
     3098    psGrommit *grommit;                 ///< Data needed to convert from the sky to the tangent plane
    27963099} psExposure;
    27973100\end{verbatim}
     
    28093112/** Constructor */
    28103113psExposure *
    2811 psExposureAlloc(double ra, double dec,  //!< Telescope boresight
    2812                 double ha,              //!< Hour angle
    2813                 double zd,              //!< Zenith distance
    2814                 double az,              //!< Azimuth
    2815                 double lst,             //!< Local Sidereal Time
    2816                 float mjd,              //!< MJD
    2817                 float rotAngle,         //!< Rotator position angle
    2818                 float temp,             //!< Temperature
    2819                 float pressure,         //!< Pressure
    2820                 float humidity,         //!< Relative humidity
    2821                 float exptime           //!< Exposure time
     3114psExposureAlloc(double ra, double dec,  ///< Telescope boresight
     3115                double ha,              ///< Hour angle
     3116                double zd,              ///< Zenith distance
     3117                double az,              ///< Azimuth
     3118                double lst,             ///< Local Sidereal Time
     3119                float mjd,              ///< MJD
     3120                float rotAngle,         ///< Rotator position angle
     3121                float temp,             ///< Temperature
     3122                float pressure,         ///< Pressure
     3123                float humidity,         ///< Relative humidity
     3124                float exptime           ///< Exposure time
    28223125                );
    28233126\end{verbatim}
     
    28273130
    28283131Astrometry is a basic functionality required for the IPP that will be
    2829 used repeatedly, both for low-precision (roughly where is my favourite
     3132used repeatedly, both for low-precision (roughly where is my favorite
    28303133object?) and high-precision (what is the proper motion of this star?).
    28313134As such, it must be flexible, yet robust.  Accordingly, we will wrap
     
    28473150
    28483151The following steps are required to convert from the cell coordinates to
    2849 the sky:
     3152the sky \tbd{convert Cell->Chip and Chip->FP to psDistortion}:
    28503153\begin{itemize}
    28513154\item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;
    28523155\item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;
    28533156\item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =
    2854 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and colour of the
     3157h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the
    28553158object, respectively; and
    28563159\item TP $\longleftrightarrow$ Sky: SLALib transformation using a
     
    28613164Plane is a four-dimensional polynomial, in order to account for any
    28623165possible dependencies in the astrometry on the stellar magnitude and
    2863 colour; the former serves as a check for charge transfer
     3166color; the former serves as a check for charge transfer
    28643167inefficiencies, while the latter will correct chromatic refraction,
    28653168both through the atmosphere and the corrector lenses.
    2866 
    2867 \textbf{[If the magnitude terms serve to check CTI, then shouldn't we
    2868 put them in the cell $\leftrightarrow$ chip section?]}
    28693169
    28703170We require structures to contain each of the above transformations as
     
    28973197\end{verbatim}
    28983198
    2899 
    29003199\subsubsection{Fixed Pattern}
    29013200
     
    29113210/** The fixed pattern residual offsets.  These are specified via a coarse grid of x and y offsets. */
    29123211typedef struct {
    2913     int nX, nY;                         //!< Number of elements in x and y
    2914     double x0, y0;                      //!< Position of the lower-left corner of the grid on the focal plane
    2915     double xScale, yScale;              //!< Scale of the grid
    2916     double **x, **y;                    //!< The grid of offsets in x and y
     3212    int nX, nY;                         ///< Number of elements in x and y
     3213    double x0, y0;                      ///< Position of the lower-left corner of the grid on the focal plane
     3214    double xScale, yScale;              ///< Scale of the grid
     3215    double **x, **y;                    ///< The grid of offsets in x and y
    29173216} psFixedPattern;
    29183217\end{verbatim}
    29193218
    29203219
    2921 \subsubsection{Finding}
     3220\subsubsection{Position Finding}
    29223221
    29233222We require functions to return the structure containing given
     
    29323231/** returns Chip in FPA which contains the given FPA coordinate */
    29333232psChip *
    2934 psChipInFPA (psChip *out,               //!< Chip to return, or NULL
     3233psChipInFPA (psChip *out,               ///< Chip to return, or NULL
    29353234             const psFPA *fpa,          ///< FPA description
    29363235             const psCoord *coord       ///< coordinate in FPA
     
    29413240/** returns Cell in Chip which contains the given chip coordinate */
    29423241psCell *
    2943 psCellInChip(psCell *out,               //!< Cell to return, or NULL
     3242psCellInChip(psCell *out,               ///< Cell to return, or NULL
    29443243             const psChip *chip,        ///< chip description
    29453244             const psCoord *coord       ///< coordinate in chip
     
    29543253/** Return the cell in FPA which contains the given FPA coordinates */
    29553254psCell *
    2956 psCellInFPA(psCell *out,                //!< Cell to return, or NULL
    2957             const psFPA *fpa,           //!< FPA description
    2958             const psCoord *coord        //!< Coordinate in FPA
     3255psCellInFPA(psCell *out,                ///< Cell to return, or NULL
     3256            const psFPA *fpa,           ///< FPA description
     3257            const psCoord *coord        ///< Coordinate in FPA
    29593258            );
    29603259\end{verbatim}
     
    29653264
    29663265We require functions to convert between the various coordinate frames
    2967 (Section~\ref{sec:coordinateFrames}).  The heirarchy of the coordinate
     3266(Section~\ref{sec:coordinateFrames}).  The hierarchy of the coordinate
    29683267frames and the transformations between each are shown in
    29693268Figure~\ref{fig:coco}.  The functions that employ the transformations
    29703269are shown in Figure~\ref{fig:cocoFunc}.  In addition to
    29713270transformations between each adjoining coordinate frame in the
    2972 heirarchy, we also require higher-level functions to convert between
     3271hierarchy, we also require higher-level functions to convert between
    29733272the Cell and Sky coordinate frames; these will simply perform the
    29743273intermediate steps.
     
    29933292/** Convert (RA,Dec) to cell and cell coordinates */
    29943293psCoord *
    2995 psCoordSkyToCell(psCoord *out,          //!< Coordinates to return, or NULL
    2996                  psCell *cell,          //!< Cell to return
    2997                  const psFPA *fpa       //!< FPA description
     3294psCoordSkyToCell(psCoord *out,          ///< Coordinates to return, or NULL
     3295                 psCell *cell,          ///< Cell to return
     3296                 const psFPA *fpa       ///< FPA description
    29983297                 );
    29993298\end{verbatim}
     
    30023301/** Convert cell and cell coordinate to (RA,Dec) */
    30033302psCoord *
    3004 psCoordCellToSky(psCoord *out,          //!< Coordinates to return, or NULL
    3005                  const psCell *cell,    //!< Cell to get coordinates for
    3006                  const psCoord *coord   //!< cell coordinates to transform
     3303psCoordCellToSky(psCoord *out,          ///< Coordinates to return, or NULL
     3304                 const psCell *cell,    ///< Cell to get coordinates for
     3305                 const psCoord *coord   ///< cell coordinates to transform
    30073306                 );
    30083307\end{verbatim}
     
    30113310/** Quick and dirty cell to (RA,Dec) --- employs cellToSky transformation */
    30123311psCoord *
    3013 psCoordCellToSkyQuick(psCoord *out,     //!< Coordinates to return, or NULL
    3014                       const psCell *cell, //!< Cell description
    3015                       const psCoord *coord //!< cell coordinates to transform
     3312psCoordCellToSkyQuick(psCoord *out,     ///< Coordinates to return, or NULL
     3313                      const psCell *cell, ///< Cell description
     3314                      const psCoord *coord ///< cell coordinates to transform
    30163315                      );
    30173316\end{verbatim}
     
    30203319/** Convert (RA,Dec) to tangent plane coords */
    30213320psCoord *
    3022 psCoordSkyToTP(psCoord *out,            //!< Coordinates to return, or NULL
    3023                const psExposure *exp,   //!< Exposure description
    3024                const psCoord *coord     //!< input Sky coordinate
     3321psCoordSkyToTP(psCoord *out,            ///< Coordinates to return, or NULL
     3322               const psExposure *exp,   ///< Exposure description
     3323               const psCoord *coord     ///< input Sky coordinate
    30253324               );
    30263325\end{verbatim}
     
    30293328/** Convert tangent plane coords to focal plane coordinates */
    30303329psCoord *
    3031 psCoordTPtoFPA(psCoord *out,            //!< Coordinates to return, or NULL
    3032                const psFPA *fpa,        //!< FPA description
    3033                const psCoord *coord     //!< input TP coordinate
     3330psCoordTPtoFPA(psCoord *out,            ///< Coordinates to return, or NULL
     3331               const psFPA *fpa,        ///< FPA description
     3332               const psCoord *coord     ///< input TP coordinate
    30343333               );
    30353334\end{verbatim}
     
    30383337/** converts the specified FPA coord to the coord on the given Chip */
    30393338psCoord *
    3040 psCoordFPAtoChip (psCoord *out,         //!< Coordinates to return, or NULL
     3339psCoordFPAtoChip (psCoord *out,         ///< Coordinates to return, or NULL
    30413340                  const psChip *chip,   ///< Chip of interest
    30423341                  const psCoord *coord  ///< input FPA coordinate
     
    30473346/** converts the specified Chip coord to the coord on the given Cell */
    30483347psCoord *
    3049 psCoordChiptoCell (psCoord *out,        //!< Coordinates to return, or NULL
     3348psCoordChiptoCell (psCoord *out,        ///< Coordinates to return, or NULL
    30503349                   const psCell *cell,  ///< Cell of interest
    30513350                   const psCoord *coord ///< input Chip coordinate
     
    30563355/** converts the specified Cell coord to the coord on the parent Chip */
    30573356psCoord *
    3058 psCoordCelltoChip (psCoord *out,        //!< Coordinates to return, or NULL
     3357psCoordCelltoChip (psCoord *out,        ///< Coordinates to return, or NULL
    30593358                   const psCell *cell,  ///< Cell description
    30603359                   const psCoord *coord ///< input Cell coordinate
     
    30653364/** converts the specified Chip coord to the coord on the parent FPA */
    30663365psCoord *
    3067 psCoordChiptoFPA (psCoord *out,         //!< Coordinates to return, or NULL
     3366psCoordChiptoFPA (psCoord *out,         ///< Coordinates to return, or NULL
    30683367                  const psChip *chip,   ///< Chip description
    30693368                  const psCoord *coord  ///< input Chip coordinate
     
    30743373/** Convert focal plane coords to tangent plane coordinates */
    30753374psCoord *
    3076 psCoordFPAToTP(psCoord *out,            //!< Coordinates to return, or NULL
    3077                const psFPA *fpa,        //!< FPA description
    3078                const psCoord *coord     //!< input FPA coordinate
     3375psCoordFPAToTP(psCoord *out,            ///< Coordinates to return, or NULL
     3376               const psFPA *fpa,        ///< FPA description
     3377               const psCoord *coord     ///< input FPA coordinate
    30793378               );
    30803379\end{verbatim}
     
    30833382/** Convert tangent plane coords to (RA,Dec) */
    30843383psCoord *
    3085 psCoordTPtoSky(psCoord *out,            //!< Coordinates to return, or NULL
    3086                const psExposure *exp,   //!< Exposure description
    3087                const psCoord *coord     //!< input TP coordinate
     3384psCoordTPtoSky(psCoord *out,            ///< Coordinates to return, or NULL
     3385               const psExposure *exp,   ///< Exposure description
     3386               const psCoord *coord     ///< input TP coordinate
    30883387               );
    30893388\end{verbatim}
     
    30923391/** Convert Cell coords to FPA coordinates */
    30933392psCoord *
    3094 psCoordCellToFPA(psCoord *out,          //!< Coordinates to return, or NULL
    3095                  const psCell *cell,    //!< Cell description
    3096                  const psCoord *coord   //!< Input cell coordinates
     3393psCoordCellToFPA(psCoord *out,          ///< Coordinates to return, or NULL
     3394                 const psCell *cell,    ///< Cell description
     3395                 const psCoord *coord   ///< Input cell coordinates
    30973396                 );
    30983397\end{verbatim}
     
    31083407/** Get the airmass for a given position and sidereal time */
    31093408float
    3110 psGetAirmass(const psCoord *coord,      //!< Position on the sky
    3111              double siderealTime,       //!< Sidereal time
    3112              float height               //!< Height above sea level
     3409psGetAirmass(const psCoord *coord,      ///< Position on the sky
     3410             double siderealTime,       ///< Sidereal time
     3411             float height               ///< Height above sea level
    31133412             );
    31143413\end{verbatim}
     
    31173416/** Get the parallactic angle for a given position and sidereal time */
    31183417float
    3119 psGetParallactic(const psCoord *coord,  //!< Position on the sky
    3120                  double siderealTime    //!< Sidereal time
     3418psGetParallactic(const psCoord *coord,  ///< Position on the sky
     3419                 double siderealTime    ///< Sidereal time
    31213420                 );
    31223421\end{verbatim}
     
    31253424/** Estimate atmospheric refraction, along the parallactic */
    31263425float
    3127 psGetRefraction(float colour,           //!< Colour of object
     3426psGetRefraction(float colour,           ///< Colour of object
    31283427                psPhotSystem colorPlus, ///< Colour reference
    31293428                psPhotSystem colorMinus, ///< Colour reference
    3130                 const psExposure *exp   //!< Telescope pointing information, for airmass, temp and pressure
     3429                const psExposure *exp   ///< Telescope pointing information, for airmass, temp and pressure
    31313430                );
    31323431\end{verbatim}
     
    31353434/** Calculate the parallax factor */
    31363435double
    3137 psGetParallaxFactor(const psExposure *exp //!< Exposure details
     3436psGetParallaxFactor(const psExposure *exp ///< Exposure details
    31383437    );
    31393438\end{verbatim}
     
    31613460\begin{verbatim}
    31623461typedef struct {
    3163     int ID;                             //!< ID number for this photometric system
    3164     char *name;                         //!< Name of photometric system
    3165     char *camera;                       //!< Camera for photometric system
    3166     char *filter;                       //!< Filter used for photometric system
    3167     char *detector;                     //!< Detector used for photometric system
     3462    int ID;                             ///< ID number for this photometric system
     3463    char *name;                         ///< Name of photometric system
     3464    char *camera;                       ///< Camera for photometric system
     3465    char *filter;                       ///< Filter used for photometric system
     3466    char *detector;                     ///< Detector used for photometric system
    31683467} psPhotSystem;
    31693468\end{verbatim}
     
    31733472\begin{verbatim}
    31743473typedef struct {
    3175     psPhotSystem src;                   //!< Source photometric system
    3176     psPhotSystem dst;                   //!< Destination photometric system
     3474    psPhotSystem src;                   ///< Source photometric system
     3475    psPhotSystem dst;                   ///< Destination photometric system
    31773476    psPhotSystem pP, pM;                ///< Primary colour reference
    31783477    psPhotSystem sP, sM;                ///< Secondary colour reference
    31793478    float pA, sA;                       ///< Colour offset for primary and secondary references
    3180     psPolynomial3D transform;           //!< Transformation from source to destination
     3479    psPolynomial3D transform;           ///< Transformation from source to destination
    31813480} psPhotTransform;
    31823481\end{verbatim}
     
    31923491are highly reddened, for example.  Derived photometric quantities may
    31933492have been corrected for airmass variations, in which case only color
    3194 terms may be measureable.  The structure defines the transformation
     3493terms may be measurable.  The structure defines the transformation
    31953494between a source photometric system (\code{src}) and a target
    31963495photometric system (\code{dst}).  The photometric system of a primary
     
    32133512\subsection{Astronomical objects}
    32143513
    3215 \textbf{[Deferred.]}
     3514\subsubsection{Positions of Major SS Objects}
     3515
     3516We require the ability to calculate the position of major Solar System
     3517objects, as well as Lunar phase.
     3518
     3519\begin{verbatim}
     3520/** Get Sun Position */
     3521psCoord *
     3522psGetSunPos(float mjd                   ///< MJD to get position for
     3523    );
     3524\end{verbatim}
     3525
     3526\begin{verbatim}
     3527/** Get Moon position */
     3528psCoord *
     3529psGetMoonPos(float mjd,                 ///< MJD to get position for
     3530             double latitude,           ///< Latitude for apparent position
     3531             double longitude           ///< Longitude for apparent position
     3532    );
     3533\end{verbatim}
     3534
     3535\begin{verbatim}
     3536/** Get Moon phase */
     3537float
     3538psGetMoonPhase(float mjd                ///< MJD to get phase for
     3539    );
     3540\end{verbatim}
     3541
     3542\begin{verbatim}
     3543/** Get Planet positions */
     3544psCoord *
     3545psGetSolarSystemPos(const char *solarSystemObject, ///< Named S.S. object
     3546                    float mjd           ///< MJD to get position for
     3547    );
     3548\end{verbatim}
     3549
     3550\tbd{The rest of this section is tentative}
     3551
     3552We may need a variety of other SLALib-type functions:
     3553
     3554\begin{itemize}
     3555\item Lunation calculations to/from psTime
     3556\item rise/set for specified object
     3557\item 12 \& 18 deg twilight for closest sunrise / sunset
     3558\item length of current night
     3559\end{itemize}
    32163560
    32173561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Note: See TracChangeset for help on using the changeset viewer.