Changeset 747 for trunk/doc/pslib/psLibSDRS.tex
- Timestamp:
- May 19, 2004, 5:41:50 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/doc/pslib/psLibSDRS.tex (modified) (86 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/pslib/psLibSDRS.tex
r703 r747 1 %%% $Id: psLibSDRS.tex,v 1.4 5 2004-05-16 04:50:56eugene Exp $1 %%% $Id: psLibSDRS.tex,v 1.46 2004-05-20 03:41:49 eugene Exp $ 2 2 \documentclass[panstarrs]{panstarrs} 3 3 … … 17 17 18 18 \setlength{\topsep}{-2pt} 19 19 20 20 \begin{document} 21 21 \maketitle 22 \sloppy 22 23 23 24 % -- Revision History -- … … 29 30 DR & 2004 Mar 29 & Draft \\ \hline 30 31 00 & 2004 Apr 1 & First version, sent to MHPCC \\ \hline 31 01 & 2004 Apr 23 & Added section on error handling\\ \hline32 01 & 2004 May 19 & Extensive modifications, see appendix \\ \hline 32 33 \RevisionsEnd 33 34 … … 62 63 well-defined, concise operations which can be coded with only a modest 63 64 number of lines. PSLib is a library of basic functions required by 64 the IPP, but should includemany programming concepts which may be useful65 the IPP, and it includes many programming concepts which may be useful 65 66 for other software projects, especially those which deal with 66 67 astronomical data handling tasks. … … 80 81 on the functions and data types of the earlier entries. 81 82 82 The installed base of code for PSLib consists of header files, the83 binary library code, \code{libpslib.a} and the shared-library 84 equivalent, \code{libpslib.so} (or \code{libpslib.dylib} in the case 85 of OS/X). Assuming these components have been installed into the 86 library and search path, PSLib may be used within a program by 87 including the line \code{#include <pslib.h>} into the C code and 88 linking with\code{-lpslib}.83 The installed code base for PSLib consists of header files, the binary 84 library code, \code{libpslib.a} and the shared-library equivalent, 85 \code{libpslib.so} (or \code{libpslib.dylib} in the case of OS/X). 86 Assuming these components have been installed into the library and 87 search path, PSLib may be used within a program by including the line 88 \code{#include <pslib.h>} into the C code and linking with 89 \code{-lpslib}. 89 90 90 91 This document describes the data structures and details the functions 91 92 calls. The specified data structures and functions follow the naming 92 conventions detailed in the IPP Code Conventions (PSDC-430-004). In93 particular, these coding conventions restrict the namespace used by 94 the library functions by requiring that all globally visible symbols 95 start with the two letters \code{ps}. Further namespace organization 96 is achieved by encouraging functions to be named in the form 97 psNounVerbPhrase, where Noun is the data type of principle relevance 98 and VerbPhase describes the operation applied to that data type. For 99 example, the function which copies an image (of type \code{psImage}) 100 is called \code{psImageCopy()}.93 conventions detailed in the IPP Software Requirements Specification 94 (PSDC-430-005). In particular, these coding conventions restrict the 95 namespace used by the library functions by requiring that all globally 96 visible symbols start with the two letters \code{ps}. Further 97 namespace organization is achieved by encouraging functions to be 98 named in the form psNounVerbPhrase, where Noun is the data type of 99 principle relevance and VerbPhase describes the operation applied to 100 that data type. For example, the function which copies an image (of 101 type \code{psImage}) is called \code{psImageCopy()}. 101 102 102 103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 107 108 document will be implemented through wrapping external libraries: 108 109 \begin{itemize} 109 \item Many of the matrix functions, some of the polynomial and 110 minimisation functions functions will wrap the GNU Scientific Library 111 (GSL; \href{www.gnu.org/software/gsl/}{\tt www.gnu.org/software/gsl}); 112 \item The sort functions will wrap the system \code{qsort} call; 113 \item Some of the Fourier transform functions will wrap the Fastest Fourier 114 Transform in the West library (FFTW; \href{www.fftw.org}{\tt www.fftw.org}); 115 \item The FITS functions will wrap the CFITSIO library 116 (\href{heasarc.gsfc.nasa.gov/docs/software/fitsio/}{\tt 117 heasarc.gsfc.nasa.gov/docs/software/fitsio/}); and 110 \item Many of the matrix functions, some of the polynomial and some of 111 the minimization functions functions should wrap the GNU Scientific 112 Library (GSL): 113 114 \href{www.gnu.org/software/gsl/}{\tt www.gnu.org/software/gsl}); 115 116 \item The sort functions should wrap the system \code{qsort} call 117 118 \item Some of the Fourier transform functions should wrap the Fastest Fourier 119 Transform in the West library (FFTW): 120 121 \href{www.fftw.org}{\tt www.fftw.org} 122 123 \item The FITS functions should wrap the CFITSIO library: 124 125 \href{heasarc.gsfc.nasa.gov/docs/software/fitsio}{\tt heasarc.gsfc.nasa.gov/docs/software/fitsio} 126 118 127 \item Many of the astronomy routines will wrap the StarLink Positional 119 Astronomy libraries (SLALib; 128 Astronomy libraries (SLALib): 129 120 130 \href{star-www.rl.ac.uk/star/docs/sun67.htx/sun67.html}{\tt 121 star-www.rl.ac.uk/star/docs/sun67.htx/sun67.html} .122 \item \tbd{Some graphics library, possibly the SM library.} 131 star-www.rl.ac.uk/star/docs/sun67.htx/sun67.html} 132 123 133 \end{itemize} 124 134 … … 144 154 \subsubsection{Introduction} 145 155 146 The \PS{} software system will need a level of memory management 147 placed between the operating system (\code{malloc}/\code{free}) and 148 the high level routines (e.g.\ \code{psMetaDataAlloc}). This layer is 149 in addition to the possibility that specific heavily used data types 150 may need their own special-purpose memory managers. However, since we 151 require that all user-level objects be allocated via associated 152 \code{Alloc/Free} functions, we will easily be able to implement such 153 functionalitywithout impacting the facilities described here.156 PSLib needs a level of memory management placed between the operating 157 system (\code{malloc}/\code{free}) and the high level routines (e.g.\ 158 \code{psMetadataAlloc}). This layer is in addition to the possibility 159 that specific heavily used data types may need their own 160 special-purpose memory managers. However, since we require that all 161 user-level objects be allocated via associated \code{Alloc/Free} 162 functions, we will easily be able to implement such functionality 163 without impacting the facilities described here. 154 164 155 165 \subsubsection{Rationale} … … 162 172 We wish to insulate ourselves from the details of the system-provided 163 173 \code{malloc}. There is no guarantee that the goals of the system 164 architect align with those of the \PS{} processing174 architect align with those of the PSLib or the IPP. 165 175 166 176 \item … … 173 183 While it is possible to do this by linking with external libraries 174 184 (e.g.\ \href{gnu.org}{Electric Fence}), it is convenient to do so 175 within the \PS{} framework.185 within the framework provided by PSLib. 176 186 177 187 \item … … 191 201 \subsubsection{Memory Management} 192 202 193 In the following sections, we specify the API set ,and define the194 appropriate data structures ,needed by the PSLib memory management203 In the following sections, we specify the API set and define the 204 appropriate data structures needed by the PSLib memory management 195 205 system in order to meet the requirements specified by the desiderata 196 listed above. 206 listed above. 197 207 198 208 Within the PSLib memory management system, every allocated memory … … 200 210 memory segments. The segment preceeding the user-memory contains data 201 211 describing the allocated block, using the \code{psMemBlock} structure. 202 The first and last elements of this structure \code{void} pointers212 The first and last elements of this structure are \code{void} pointers 203 213 called \code{startblock} and \code{endblock}, which are assigned a 204 214 special value, \code{PS_MEM_MAGIC}. The segment following the 205 215 user-memory block consists of a single \code{void} pointer, and is 206 216 also assigned the special value of \code{PS_MEM_MAGIC}. This address 207 is pointed to by the structure element s\code{endpost}.208 209 In practice, these bounding memory blocks mean that when a user is217 is pointed to by the structure element \code{endpost}. 218 219 In practice, these bounding memory blocks mean that when a user 210 220 requests $N$ bytes of memory, the memory management system in fact 211 221 allocates \code{N + sizeof(psMemBlock) + sizeof(void)} bytes, starting 212 222 at a particular address, \code{ADDR}. It then fills in the first 213 223 \code{sizeof(psMemBlock)} bytes with the data of the \code{psMemBlock} 214 structure, and the last \code{sizeof(void)} bytes with the224 structure, and the last \code{sizeof(void)} bytes with 215 225 \code{PS_MEM_MAGIC}. It returns to the user the pointer corresponding 216 226 to the address \code{ADDR + sizeof(psMemBlock)}. If the memory 217 227 management system reallocates a block of memory, it must also allocate 218 228 the additional space and fill in the boundary values. If the memory 219 management system is given a specific pointer for some operation, it is220 able to find the corresponding \code{psMemBlock} by simply subtracting 221 \code{sizeof(psMemBlock)} from the pointer address.229 management system is given a specific pointer for some operation, it 230 is able to find the corresponding \code{psMemBlock} by simply 231 subtracting \code{sizeof(psMemBlock)} from the pointer address. 222 232 223 233 The purpose of the three boundary markers is to catch corruption and … … 227 237 is one where the coder mis-counts the range and either fills the data 228 238 just before the start of the valid memory or just after the end of the 229 valid memory. These actions will (hopefully)alter the boundary-post239 valid memory. These actions are likely to alter the boundary-post 230 240 values, which can be detected by the memory management system. In the 231 241 second case, hexadecimal dumps of large blocks of memory are easier to … … 245 255 const int lineno; ///< set from __LINE__ in e.g. p_psAlloc 246 256 int refCounter; ///< how many times pointer is referenced 247 const void **endpost; ///< pointer to endpost,initialised to PS_MEM_MAGIC248 const void *endblock; ///< initialised to PS_MEM_MAGIC257 const void **endpost; ///< initialised to PS_MEM_MAGIC 258 const void *endblock; ///< initialised to PS_MEM_MAGIC 249 259 } psMemBlock; 250 260 \end{verbatim} … … 267 277 memory. As discussed below, the basic free function, \code{psFree}, 268 278 is specified to free the memory block only if the reference counter is 269 set to 1. See the discussion of the \code{psDlist} and \code{psHash}270 data containers for an example of the usage. Usage of this feature is 271 strongly encouraged, but notenforced by the memory management system.279 set to 1. See the discussion in section~\ref{sec:free} for an example 280 of the usage. Usage of this feature is strongly encouraged, but not 281 enforced by the memory management system. 272 282 273 283 In order to trace double frees and other memory errors, the memory … … 276 286 data are left behind. If endpost points to the memory location 277 287 immediately following the \code{psMemBlock} data, then the memory 278 block has been freed. This state shall be enforcesby \code{psFree}.288 block has been freed. This state must be enforced by \code{psFree}. 279 289 280 290 \subsubsection{APIs for Allocating and Freeing} 281 291 282 PSLib provides the following APIs to create and destroy memory blocks: 292 PSLib must provide the following APIs to create and destroy memory 293 blocks: 283 294 % 284 295 \begin{verbatim} … … 291 302 \code{psRealloc}, and \code{psFree} have identical semantics to the 292 303 standard C library functions \code{malloc}, \code{realloc}, and 293 \code{free}. In fact, these functions sh allbe implemented as C304 \code{free}. In fact, these functions should be implemented as C 294 305 preprocessor macros which call the following private functions: 295 306 % … … 309 320 310 321 In order to enforce the use of the PSLib versions, the header file 311 shalltake steps to ensure that code calling the functions322 must take steps to ensure that code calling the functions 312 323 \code{malloc}, \code{calloc}, \code{realloc}, or \code{free} will not 313 324 compile. This may be achieved by defining preprocessor macros which 314 mask these functions with invalid statements (\eg{} \code{#define malloc(S) for}). 315 In exceptional cases, such as the memory management system itself, 316 programmers may choose to override this prohibition by defining the 317 symbol \code{PS_ALLOW_MALLOC}. Application code will call 318 \code{p_psAlloc,p_psRealloc,p_psFree} via the macros defined above. 325 mask these functions with invalid statements (\eg{} \code{#define 326 malloc(S) for}). In exceptional cases, such as the memory management 327 system itself, programmers may choose to override this prohibition by 328 defining the symbol \code{PS_ALLOW_MALLOC}. Application code will 329 call \code{p_psAlloc}, \code{p_psRealloc}, or \code{p_psFree} via the 330 macros defined above. 319 331 320 The functions \code{psAlloc} and \code{psRealloc} shallnever return a332 The functions \code{psAlloc} and \code{psRealloc} must never return a 321 333 \code{NULL} pointer. If they are unable to provide the requested 322 memory they shouldattempt to obtain the desired memory by calling the334 memory they must attempt to obtain the desired memory by calling the 323 335 routine registered by \code{psMemExhaustedSetCallback} (see 324 336 \S\ref{secMemAdvanced}), and if still unsuccessful, call … … 351 363 types, specified below. The callbacks are set using functions with 352 364 names of the form \code{psCallbackSet}. In all cases, the 353 `\code{Set}' routine takes a pointer to the desired callback 354 function and returns a pointer to the one that was previously 355 installed. If the function pointer is \code{NULL}, the default 356 callback function is reinstalled. We discuss the use of each of the 357 four callbacks below. 365 `\code{Set}' routine takes a pointer to the desired callback function 366 and returns a pointer to the one that was previously installed. The 367 defaults for each of these callbacks is \code{NULL}, in which case the 368 corresponding callback is skipped. If the function pointer passed to 369 the functions above is \code{NULL}, the default behavior is set. We 370 discuss the use of each of the four callbacks below. 358 371 359 372 \subsubsubsection{\tt psMemExhaustedCallback} … … 396 409 information. No return value is accepted, and no specific operations 397 410 are expected. The callback is for informational purposes only. Where 398 practical and efficient, the memory manager shallcall the routine411 practical and efficient, the memory manager must call the routine 399 412 registered using \code{psMemProblemCallbackSet} whenever a corrupted block 400 413 of memory is discovered. For example, doubly-freed blocks can be … … 426 439 typedef long (*psMemFreeCallback)(const psMemBlock *ptr); 427 440 psMemFreeCallback psMemFreeCallbackSet(psMemFreeCallback func); 441 long psMemGetId(void); 428 442 \end{verbatim} 429 443 % … … 432 446 \code{psMemAllocateIDSet} accept the desired ID value and return the 433 447 old value to the user. The return values of the handlers installed by 434 \code{psMemAllocateCallbackSet} and \code{psMemFreeCallbackSet} are used to435 increment the values of \code{p_psMemAllocateID} and448 \code{psMemAllocateCallbackSet} and \code{psMemFreeCallbackSet} are 449 used to increment the values of \code{p_psMemAllocateID} and 436 450 \code{p_psMemFreeID} respectively. For example, a return value of 437 451 \code{0} implies that the value is unchanged; if the value is \code{2} 438 452 the callback will be called again when the memory ID counter has 439 453 increased by two. This functionality may be useful to check, for 440 example, every 100th block allocated. The function , \code{long psMemGetId(void);}454 example, every 100th block allocated. The function \code{psMemGetId} 441 455 returns the next identification number to be assigned to a memory 442 456 block. This function can be used to guide the choice of ID set with … … 463 477 464 478 If the argument \code{array} is non-\code{NULL}, then \code{**array} 465 is set to an array of \code{psMemBlock *} pointerswhen the function479 is set to an array of pointers to \code{psMemBlock} when the function 466 480 returns. These pointers represent the blocks which have been 467 481 allocated but not freed. It is the caller's responsibility to free … … 479 493 The return value is the number of corrupted blocks detected. If the 480 494 argument \code{abort_on_error} is true, \code{psMemCheckCorruption} 481 shallcall \code{psAbort} as soon as memory corruption is detected.495 must call \code{psAbort} as soon as memory corruption is detected. 482 496 483 497 \subsubsection{Reference Counting} … … 491 505 and decrement it when those references are removed. The memory 492 506 management routines respect the use of the \code{refCounter} field: 493 \code{psFree} will not free a block for which \code{refCounter != 1},494 and \code{psAlloc} will initialize the field to 1. \code{psFree}495 must generate an error if \code{refCounter != 1}. However, they do496 not (and cannot practically) enforce the use of the counters; thisis497 a requirement of external APIs which intend to use the feature.507 \code{psFree} will not free a block for which \code{refCounter} is not 508 1, and \code{psAlloc} will initialize the field to 1. \code{psFree} 509 must generate an error if \code{refCounter} is not 1. However, they 510 do not (and cannot practically) enforce the use of the counters; this 511 is a requirement of external APIs which intend to use the feature. 498 512 499 513 Several APIs are provided to manage the reference counters. These … … 508 522 The functions all take a pointer to the start of a user block of 509 523 memory. The first simply returns the value of the reference counter. 510 The next two functions increment or decrement the reference counter, 511 returning the pointer which was passed in. These functions must 512 validate the memory pointer by determining the corresponding 524 If \code{vptr} is \code{NULL}, this function must return a value of 525 NULL. The next two functions increment or decrement the reference 526 counter, returning the pointer which was passed in. These functions 527 must validate the memory pointer by determining the corresponding 513 528 \code{psMemBlock.id} and checking for consistency in the internal 514 memory block table (the table pointer for \code{psMemBlock.id} should 515 be in the valid range and should correspond to the address of the 516 \code{psMemBlock}). For an example implementation of the 517 \code{refCounter} facilities, see the discussion of \code{psDlist} 518 (\S\ref{sec:psDlist}). 529 memory block table (the table pointer for \code{psMemBlock.id} must be 530 in the valid range and must correspond to the address of the 531 \code{psMemBlock}). 519 532 520 533 \subsubsection{Relation of Memory Management to Structures} 521 534 \label{sec:free} 522 535 523 In this document, we specify several C \code{struct}s. It is expected 524 that instances of, for example, \code{struct psMyType} will be 525 constructed using \code{psMyTypeAlloc()} calls, and destroyed using 536 Within PSLib and throughout the Pan-STARRS project, we specify a 537 variety of rich data structures. The IPP Software Requirements 538 Specification states that structures should be defined with 539 corresponding constructors and destructors. Instances of, for 540 example, \code{psMyType} should be constructed using 541 \code{psMyTypeAlloc()} calls, and destroyed using 526 542 \code{psMyTypeFree()} calls. The allocator will allocate the required 527 543 memory with \code{psAlloc} and increment the appropriate … … 536 552 537 553 \begin{verbatim} 538 void psMyTypeFree(psMyType *myType ///< Object to destroy 539 ) 554 void psMyTypeFree(psMyType *myType) 540 555 { 541 /* No operation if object is NULL*/542 if ( myType == NULL) {556 /* data is not defined */ 557 if (psMemGetRefCounter(myType) < 1) { 543 558 return; 544 559 } 545 560 /* Only call psFree if reference counter is 1 */ 546 561 if (psMemGetRefCounter(myType) == 1) { 562 psSubFree (myType->sub); 547 563 psFree(myType); 548 564 return; … … 553 569 \end{verbatim} 554 570 555 This allows, for example, the \code{psMyType} to be imported into the 556 metadata (\S\ref{sec:metadata}) without the user worrying about the 557 details of the memory allocation/deallocation: 558 559 \begin{verbatim} 560 void psFooMetadata(psMetadata *md) 561 { 562 psFoo *foo = psFooAlloc(); 563 (void) psMetaDataAppend(md, psMetaDataItemAlloc(PS_META_FOO,foo,"Comment","foo.bar")); 564 (void) psFooFree(foo); 565 } 566 \end{verbatim} 567 568 In the above case, \code{foo} is created, stuffed into the metadata, 569 and then the programmer follows the rule of ``for every \code{alloc}, 570 there is an equal and opposite free'' before the function returns. 571 However, the metadata needs to carry around the \code{psFoo}, and so 572 it is important that \code{psFooFree} does not free the memory for 573 \code{foo}, but only decrements its \code{refCounter}. Hence, at the 574 conclusion of the function, the memory pointed to by \code{foo} in the 575 course of the function remains allocated, and the corresponding 576 \code{refCounter} is 1 (specifically, the reference in the metadata). 571 Note that the element of \code{myType}, \code{myType.sub} is 572 explicitly freed with its associated destructor. If this element 573 points to a data block with multiple references, this call would only 574 decrement the counter. 577 575 578 576 \subsection{Tracing and Logging} … … 604 602 top-level. If the user needs to dig deeper into the code, the trace 605 603 level should be set lower, and the more detailed messages could be 606 examined. In a case of a real, poorly-understood problem with the604 examined. In a case of a serious, poorly-understood problem with the 607 605 code, the trace threshold would be placed to the bottom and the 608 606 lowest-level step-by-step messages would be printed. 609 607 610 The PSLib tracing facility will providethe above functionality, along608 The PSLib tracing facility provides the above functionality, along 611 609 with the ability to assign different trace levels to messages from 612 different software components. Each trace message when placed in the613 code is assigned to be part of a specific tracing 'facility', defined610 different software components. Each trace message, when placed in the 611 code, is assigned to be part of a specific tracing 'facility', defined 614 612 in more detail below. The trace level for that specific message is 615 613 also set when the message is placed. Each facility may have its trace … … 664 662 which returns the trace level of the named facility following the 665 663 rules specified above. A specified trace message (identified by 666 \code{psTrace}) shallbe printed if and only if664 \code{psTrace}) must be printed if and only if 667 665 \code{psTraceGetLevel(facil)} returns a value greater than or equal to 668 666 the value of \code{myLevel} for that message. That is, a larger … … 670 668 hence is more verbose. 671 669 672 PSLib will include a utility function for examining the current 673 tracing levels of all facilities: \code{void psTracePrintLevels(void);}. 674 This function will print the hierarchy of trace facilities along with 675 the current trace level for each facility. For example, a particular 670 PSLib includes a utility function for examining the current tracing 671 levels of all facilities: 672 % 673 \begin{verbatim} 674 void psTracePrintLevels(void); 675 \end{verbatim}. 676 % 677 This function prints the hierarchy of trace facilities along with the 678 current trace level for each facility. For example, a particular 676 679 program may have a few facilities defined, along with their trace 677 680 levels. A call to \code{psTracePrintLevels} may produce a listing … … 706 709 flat-field image is foo.fits 707 710 doing the divide 708 got an invalid pixel value (NaN) at 500,20711 got an invalid pixel value (NaN) at 500,20 709 712 divide is done 710 713 \end{verbatim} … … 722 725 % 723 726 724 The availability of the tracing facility at run-time, shallbe decided727 The availability of the tracing facility at run-time, must be decided 725 728 at compilation: If the C pre-processor macro \code{PS_NO_TRACE} is 726 defined, all trace code shallbe replaced by empty space so that none729 defined, all trace code must be replaced by empty space so that none 727 730 of the code is compiled. This can be implemented via macro front-ends 728 731 to private versions of the user APIs. In addition, a function … … 733 736 with \code{psTraceSetDestination}: 734 737 \begin{verbatim} 735 void psTraceSetDestination(FILE *fp // Open file pointer to write to 736 ); 738 void psTraceSetDestination(FILE *fp); 737 739 \end{verbatim} 738 740 If the \code{fp} is \code{NULL}, then the trace is sent to standard 739 output .741 output, otherwise it is sent to the specified file pointer. 740 742 741 743 \subsubsection{Message Logging} … … 761 763 \begin{verbatim} 762 764 void psLogMsg(char *name, int myLevel, char *fmt, ...); 763 void psLog VMsg(char *name, int myLevel, char *fmt, va_list ap);765 void psLogMsgV(char *name, int myLevel, char *fmt, va_list ap); 764 766 \end{verbatim} 765 767 where \code{name} is a word to describe the source of the message, … … 767 769 is a printf-style formatting statement defining the actual message, 768 770 and is followed by the arguments to the formatting code. The second 769 form, \code{psLog VMsg} is an equivalent command which takes a771 form, \code{psLogMsgV} is an equivalent command which takes a 770 772 \code{va_list} argument. 771 773 … … 777 779 \end{verbatim} 778 780 % 779 The default level is set to \code{PS_LOG_INFO}.780 781 781 782 At any time, the program may set the current log level, the level … … 789 790 invoked with \code{psLogMsg} is only printed if its value of 790 791 \code{myLevel} is less than the current value set by 791 \code{psLogSetLevel}. 792 \code{psLogSetLevel}. The default log level is set to 793 \code{PS_LOG_INFO}. 792 794 793 795 Log messages are sent to the destination most recently set using: 794 796 % 795 797 \begin{verbatim} 796 int psLogSetDestination(int dest); 797 \end{verbatim} 798 % 799 The only values that are initially defined are \code{PS_LOG_TO_STDERR} 800 and \code{PS_LOG_TO_STDOUT} to write to \code{stderr} and 801 \code{stdout} respectively, and \code{PS_LOG_TO_NONE} to turn off 802 logging. \tbd{Log to a server via TCP/IP; will possibly set these 803 values to negative integers and allow psLogSetDestination to take 804 a positive-integer file descriptor.}. 798 int psLogSetDestination(char *dest); 799 \end{verbatim} 800 % 801 The destination string consists of a URL in the form 802 \code{protocol:location}. The \code{protocol} value may be 803 \code{file}, to send the log to a local file named by the value of 804 \code{location}. Future expansion may allow the logger to send 805 messages to an IP logger, with a protocol to be defined later. Three 806 other special values are allowed for \code{dest}: \code{stderr} and 807 \code{stdout}, which write to \code{stderr} and \code{stdout} 808 respectively, and \code{none} to turn off logging. 805 809 806 810 The output format is controlled with the function: … … 826 830 \code{PS_LOG_ERROR}, \code{PS_LOG_WARN}, and \code{PS_LOG_INFO} 827 831 respectively. Other levels are represented numerically (\code{5} 828 etc.). The other two field , \code{name} and \code{msg}are the832 etc.). The other two fields, \code{name} and \code{msg}, are the 829 833 arguments to \code{psLogMsg}; note that \code{name} has a fixed width 830 834 of 15 characters. If \code{msg} doesn't end in a newline, a single … … 849 853 \hlabel{errorStack} 850 854 851 \PS{} errors shall be raised using a function, \code{psError}, with 852 the caller supplying a component name and error message. It is 853 desireable to be able to trace an error through the program so that 854 the events that led to the error may be quickly and clearly 855 identified. 856 857 \begin{verbatim} 858 /// Prints an error message and doesn't abort; returns code 859 int psError(const char *name, ///< Category of code that caused the error 860 psErrorCode code, ///< class of error (equivalent to errno) 861 psErrorStatus status, ///< is this a new error? 862 const char *fmt, ///< Format 863 ... ///< Extra arguments to use format 864 ); 865 866 typedef enum { 867 PS_OLD_ERROR = 0, ///< This is an old error, and should append to the error stack 868 PS_NEW_ERROR = 1, ///< This is a new error and should clear the error stack 869 } psErrorStatus; 855 \PS{} errors must be raised using a function, \code{psError}, with the 856 caller supplying a component name and error message. It is desireable 857 to be able to trace an error through the program so that the events 858 that led to the error may be quickly and clearly identified. 859 \code{psError} prints an error message and doesn't abort, but instead 860 returns the error code. 861 \begin{verbatim} 862 int psError(const char *name, psErrorCode code, int status, const char *fmt, ...); 870 863 \end{verbatim} 871 864 872 865 The \code{name} is of the form \code{aaa.bbb.ccc} and identifies the 873 component raising the error. The \code{ psErrorCode} is an enumerated874 typewhich lists the possible \textit{classes} of errors866 component raising the error. The \code{code} is an enumerated type 867 which lists the possible \textit{classes} of errors 875 868 (e.g. \code{PS_ERR_IO}) that \PS{} code can generate (see section 876 \ref{psErrorCodes}). \code{status} specifies whether this is a new 877 error, or whether this call to \code{psError} is in response to an 878 error that has already resulted in a call to \code{psError}. The 869 \ref{psErrorCodes}). The \code{new} argument takes a boolean which, if 870 \code{TRUE} specifies that the error was set initially at this 871 location, and if \code{FALSE} specifies that an error was passed to 872 this location. Raising new error should clear the error stack. The 879 873 final required argument, \code{fmt}, is a \code{printf}-style format 880 that is passed to \code{psLog VMsg} with code \code{PS_LOG_ERROR}.881 882 The result of a call to \code{psError} shall be to push an error onto 883 a stack; this stack is cleared if \code{psErrorStatus} is true, or by a call 884 to \code{psErrorClear}. The errors are defined as the following: 885 874 that is passed to \code{psLogMsgV} with code \code{PS_LOG_ERROR}. The 875 result of a call to \code{psError} must be to push an error onto a 876 stack; this stack is cleared if \code{psErrorStatus} is true, or by a 877 call to \code{psErrorClear}. 878 879 The errors on the error stack are defined as the following: 886 880 \begin{verbatim} 887 881 typedef struct { … … 892 886 \end{verbatim} 893 887 894 895 The last error reported is available from \code{psLastError}; if no 896 errors are current, a non-\code{NULL} \code{psErr} shall be returned 897 with code \code{PS_ERR_NONE}. Previous errors on the stack shall be 898 returned by \code{psGetError} (a value of \code{0} passed to 899 \code{psGetError} is equivalent to a call to \code{psLastError}). 900 901 \begin{verbatim} 902 const psErr *psErrorGet(int which); ///< return specified error (or an "error" with code PS_ERR_NONE) 903 const psErr *psErrorLast(void); ///< return last error (or an "error" with code PS_ERR_NONE) 904 \end{verbatim} 905 906 The error stack may be completely cleared: 907 908 \begin{verbatim} 909 void psErrorClear(void); ///< Clear the error stack 888 The last error reported is available from \code{psErrorLast}; if no 889 errors are current, a non-\code{NULL} \code{psErr} must be returned 890 with code \code{PS_ERR_NONE}. Previous errors on the stack must be 891 returned by \code{psErrorGet} (a value of \code{0} passed to 892 \code{psErrorGet} is equivalent to a call to \code{psErrorLast}). 893 The error stack may be completely cleared with \code{psErrorClear}. 894 % 895 \begin{verbatim} 896 const psErr *psErrorGet(int which); 897 const psErr *psErrorLast(void); 898 void psErrorClear(void); 910 899 \end{verbatim} 911 900 912 901 The entire error stack may be printed to an open file descriptor by 913 calling \code{psErrorStackPrint} (or \code{psError VStackPrint}); if902 calling \code{psErrorStackPrint} (or \code{psErrorStackPrintV}); if 914 903 and only if there are current errors, the printf-style string 915 904 \code{fmt} is first printed to the file descriptor \code{fd}. In this 916 printout, error codes shallbe replaced by their string equivalents as905 printout, error codes must be replaced by their string equivalents as 917 906 defined in the next section. Note that these are also available in 918 907 the \code{psErr} structure. The successive lines of the traceback 919 908 should be indented by an additional space (see example). 920 \code{psErrorVStackPrint} shall not invoke \code{va_end}. 921 922 \begin{verbatim} 923 void psErrorStackPrint(FILE *fd, const char *fmt, ...); ///< print the errorstack to this file descriptor 924 void psErrorVStackPrint(FILE *fd, const char *fmt, va_list va); ///< print the errorstack to this file 925 ///< descriptor 909 \code{psErrorStackPrintV} must not invoke \code{va_end}. 910 % 911 \begin{verbatim} 912 void psErrorStackPrint(FILE *fd, const char *fmt, ...); 913 void psErrorStackPrintV(FILE *fd, const char *fmt, va_list va); 926 914 \end{verbatim} 927 915 928 916 Any \code{errorCode}s less then or equal to \code{PS_ERR_BASE} (see 929 next section) shallbe taken to be valid values of \code{errno}, and930 \code{psErrorStackPrint} shallprint the value returned by917 next section) must be taken to be valid values of \code{errno}, and 918 \code{psErrorStackPrint} must print the value returned by 931 919 \code{strerror} if such error codes are encountered. 932 920 933 921 The routine \code{psErrorCodeString} returns the string associated 934 922 with an error code: 935 936 \begin{verbatim} 937 const char *psErrorCodeString(psErrorCode code); ///< return the string associated with an error code. 938 \end{verbatim} 939 923 \begin{verbatim} 924 const char *psErrorCodeString(psErrorCode code); 925 \end{verbatim} 940 926 941 927 \subsubsection{Error Codes} … … 943 929 944 930 Both error codes for PSLib and error codes for projects that use PSLib 945 may be registered. In the former case, the error codes shallbe946 registered on initialisation, whereas in the latter case, it is947 required to explicitly register.931 may be registered. In the former case, the error codes must be 932 registered on initialisation, whereas in the latter case, they must be 933 explicitly registered by the programmer. 948 934 949 935 \paragraph{Registering error codes} 950 936 951 An array of error codes may be registered with the PSLib error handler 952 using a private function: 953 954 \begin{verbatim} 955 void p_psErrorRegister(const psErrorDescription *errors, ///< register a set of errors 956 int nerror ///< number of errors 957 ); 958 \end{verbatim} 959 960 Where the errors are represented internally as follows: 937 PSLib and any project needed to use PSLib must define the necessary 938 error codes and associated message strings. An array of error codes 939 may be registered with the PSLib error handler using a private 940 function: 941 \begin{verbatim} 942 void psErrorRegisterSet(const psErrorDescription *errors, int nerror); 943 \end{verbatim} 944 where the errors are represented internally as follows: 961 945 \begin{verbatim} 962 946 typedef struct { … … 965 949 } psErrorDescription; 966 950 \end{verbatim} 967 968 Projects wishing to employ the PSLib error handler should define 969 a function, 970 \begin{verbatim} 971 void prefixErrorRegister(void); 972 \end{verbatim} 973 where \code{prefix} is particular to the project. For example, PSLib 974 should have a function, 975 \begin{verbatim} 976 void psErrorRegister(void); 977 \end{verbatim} 978 In this case (i.e., error codes for PSLib), the function should be 979 called upon initialisation. As another example, MOPS should implement 980 a function, 981 \begin{verbatim} 982 void mopsErrorRegister(void); 983 \end{verbatim} 984 which would be called explicitly when MOPS utilises PSLib. 985 986 It is left to the external project to produce the appropriate 987 \code{prefixErrorRegister()}, but they may find helpful the 988 implementation discussed below for use in PSLib. 989 990 There is a clear need to coordinate the choice of error numbers. It 991 is expected that error code ranges for different projects shall be 992 managed by the Project Office. 951 PSLib internal errors must be registered with the function 952 psErrorRegister, which should be called as part of the program 953 initialization to set up the error codes. It is left to the external 954 project to produce their own error registration functions which must 955 also be called during initialization. There is a clear need to 956 coordinate the choice of error numbers. It is expected that error 957 code ranges for different projects must be managed by the Project 958 Office within Pan-STARRS. 993 959 994 960 \paragraph{Error Codes for PSLib} 995 961 996 For ease of maintenance, error codes for PSLib shallbe defined by an962 For ease of maintenance, error codes for PSLib must be defined by an 997 963 auxiliary file, conventionally named \file{psErrorCodes.dat}. The 998 format of this file shallconsist of a number of lines, each of the964 format of this file must consist of a number of lines, each of the 999 965 form: 1000 966 \begin{verbatim} … … 1003 969 where \code{[ = value]} and the comma are optional, and no spaces are 1004 970 significant except in the STRING. Comments extend from \code{#} to 1005 the end of the line (except that a \code{\#} shallbe replaced by971 the end of the line (except that a \code{\#} must be replaced by 1006 972 \code{#} and not taken to start a comment). For example, 1007 973 \begin{verbatim} … … 1019 985 The values \code{NONE = 0} and {UNKNOWN} must be present. 1020 986 1021 A script, called from the Makefiles, shallgenerate two files,987 A script, called from the Makefiles, must generate two files, 1022 988 \file{psErrorCodes.h} and \file{psErrorCodes.c} from the input file 1023 \file{psErrorCodes.dat}. \file{psErrorCodes.h} shalldefine an989 \file{psErrorCodes.dat}. \file{psErrorCodes.h} must define an 1024 990 enumerated type \code{psErrorCode} with elements \code{PS_ERR_NAME} 1025 991 and values as specified in \file{psErrorCodes.dat}, e.g. … … 1040 1006 \end{verbatim} 1041 1007 1042 Any \code{errorCode}s less then or equal to \code{PS_ERR_BASE} shall be taken 1043 to be valid values of \code{errno}. 1044 1045 \file{psErrorCodes.c} shall define the necessary function to register 1046 the error codes. 1047 1048 \subsubsection{Example} 1049 1050 The following example code: 1051 1052 \begin{verbatim} 1053 #include "psLib.h" 1054 1055 static int primary(int i) 1056 { 1057 if (i != 0) { // let's pretend it's an I/O error 1058 return psError("tst.error.primary", PS_ERR_IO, 1, "Primary error"); 1059 } 1060 1061 return 0; 1062 } 1063 1064 static int middle(void) 1065 { 1066 if (primary(1) != 0) { 1067 return psError("tst.error.middle", PS_ERR_UNKNOWN, 0, "Secondary error"); 1068 } 1069 1070 return 0; 1071 } 1072 1073 static int toplevel(void) 1074 { 1075 if (middle() != 0) { 1076 return psError("tst.error", PS_ERR_UNKNOWN, 0, "Toplevel error"); 1077 } 1078 1079 return 0; 1080 } 1081 1082 int main(void) 1083 { 1084 if (toplevel() != 0) { 1085 psErrorStackPrint(stdout, "Traceback:\n"); 1086 1087 if (psErrorLast()->code == PS_ERR_UNKNOWN) { 1088 fprintf(stderr, "Last error is of unknown type\n"); 1089 } 1090 if (psErrorGet(2)->code == PS_ERR_IO) { 1091 fprintf(stderr, "Third oldest error is of type IO\n"); 1092 } 1093 } 1094 1095 psErrorClear(); 1096 psErrorStackPrint(stdout, "Traceback:\n"); 1097 1098 if (psErrorLast()->code == PS_ERR_NONE) { 1099 fprintf(stderr, "No errors. Hurrah\n"); 1100 } 1101 1102 return 0; 1103 } 1104 \end{verbatim} 1105 1106 1107 Produces the following output: 1108 1109 \begin{verbatim} 1110 Traceback: 1111 tst.error.primary I/O error Primary error 1112 tst.error.middle unknown error Secondary error 1113 tst.error unknown error Toplevel error 1114 Last error is of unknown type 1115 Third oldest error is of type IO 1116 No errors. Hurrah 1117 \end{verbatim} 1008 Any \code{errorCode}s less then or equal to \code{PS_ERR_BASE} must be 1009 taken to be valid values of \code{errno}. \file{psErrorCodes.c} must 1010 define the necessary function to register the error codes. 1118 1011 1119 1012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 1121 1014 \subsection{Abort} 1122 1015 1123 \code{psAbort}, shallcall \code{psMsgLog} with a1016 \code{psAbort}, must call \code{psMsgLog} with a 1124 1017 level of \code{PS_LOG_ABORT}, and then call \code{abort}. 1125 1018 … … 1144 1037 1145 1038 Throughout PSLib, we require a variety of structures which correspond 1146 to different mathematical data concepts. For example, we have several1147 data structures which correspond to one-dimensional arrays (vectors) 1148 of different data types (\code{int}, \code{float}, etc). We also have 1149 d ifferent data structures which correspond to two-dimensional arrays1150 (images or matrices), again with different data types for the 1151 individual elements. 1039 to different mathematical data concepts. For example, we have a data 1040 structure which corresponds to one-dimensional arrays (vectors) of 1041 different data types (\code{int}, \code{float}, etc). We also have a 1042 data structure which corresponds to two-dimensional arrays (images or 1043 matrices), again with different data types for the individual 1044 elements. 1152 1045 1153 1046 A variety of functions perform operations which are equivalent for … … 1163 1056 operation if $x$ is a vector and $y$ is a matrix. Nor does it matter 1164 1057 mathematically that the element data types match; the sum of a float 1165 and an integer is a well-defined quantity !One constraint should be1058 and an integer is a well-defined quantity. One constraint should be 1166 1059 noted: the size of the elements in each dimension must match. For 1167 1060 example, if $x$ were a vector of 100 elements, but $y$ were a vector … … 1170 1063 1171 1064 Given that some functions should be able to operate equivalently (or 1172 identically) on a wide range of data types, it seems cumbersome to be 1173 forced into defining a large number of C functions to handle the 1174 different data types, just because we have different structures. 1175 Admittedly, some details of the function would have to vary for 1176 different data types, but since the basic function is the same, it 1177 would help both the user and programmer if the same function could be 1178 used for different data types. We therefore define a mechanism which 1179 allows the C functions to accept a generic data type, and determine 1180 the type of the data on the basis of the data. The mechanism uses the 1181 structure \code{psType}. 1182 1183 Each of these equivalent data types is defined by a structure in which 1184 the first element is always of type \code{psType}. This element 1185 defines both the dimensions of the array and the data type of each 1186 element. The structure is as follows: 1065 identically) on a wide range of data types, we define a mechanism 1066 which allows the C functions to accept a generic data type, and 1067 determine the type of the data on the basis of the data. 1068 Supported data types must be defined by a structure in which 1069 the first element is always of type \code{psType}: 1187 1070 \begin{verbatim} 1188 1071 typedef struct { … … 1193 1076 where \code{psDimen dimen} defines the dimensionality of the data and 1194 1077 \code{psElemType type} defines the data type of each element. These 1195 two variable types are defined as structures:1078 two variable types are defined as: 1196 1079 \begin{verbatim} 1197 1080 typedef enum { … … 1200 1083 PS_DIMEN_TRANSV, ///< A transposed vector 1201 1084 PS_DIMEN_IMAGE, ///< An image (matrix) 1202 PS_DIMEN_OTHER ///< Something else that's not supported for arithmetic1085 PS_DIMEN_OTHER ///< Not supported for arithmetic 1203 1086 } psDimen; 1204 1087 \end{verbatim} … … 1216 1099 PS_TYPE_F32, ///< Floating point 1217 1100 PS_TYPE_F64, ///< Double-precision floating point 1218 PS_TYPE_C32, ///< Complex numbers consisting of float ing point1219 PS_TYPE_OTHER, ///< Something else that's not supported for arithmetic1101 PS_TYPE_C32, ///< Complex numbers consisting of floats 1102 PS_TYPE_OTHER, ///< Not supported for arithmetic 1220 1103 } psElemType; 1221 1104 \end{verbatim} … … 1234 1117 psType type; ///< vector data type and dimension 1235 1118 const int n; ///< size of vector 1236 const int nalloc; ///< data region relative to parent1119 const int nalloc; ///< allocated data block 1237 1120 union { 1238 psF32 *arr; ///< Pointers to floating-point data (default) 1239 psS8 *arr_S8; ///< Pointers to short-integer data 1240 psS16 *arr_S16; ///< Pointers to short-integer data 1241 psS32 *arr_S32; ///< Pointers to integer data 1242 psS64 *arr_S64; ///< Pointers to long-integer data 1243 psU8 *arr_U18; ///< Pointers to unsigned-short-integer data 1244 psU16 *arr_U16; ///< Pointers to unsigned-short-integer data 1245 psU32 *arr_U32; ///< Pointers to unsigned-integer data 1246 psU64 *arr_U64; ///< Pointers to unsigned-long-integer data 1247 psF32 *arr_F32; ///< Pointers to floating-point data 1248 psF64 *arr_F64; ///< Pointers to double-precision data 1249 psF32 *arr_C32; ///< Pointers to complex floating-point data 1250 void **arr_v; 1251 } arr; 1121 psS8 *S8; ///< Pointers to short-integer data 1122 psS16 *S16; ///< Pointers to short-integer data 1123 psS32 *S32; ///< Pointers to integer data 1124 psS64 *S64; ///< Pointers to long-integer data 1125 psU8 *U18; ///< Pointers to unsigned-short-integer data 1126 psU16 *U16; ///< Pointers to unsigned-short-integer data 1127 psU32 *U32; ///< Pointers to unsigned-integer data 1128 psU64 *U64; ///< Pointers to unsigned-long-integer data 1129 psF32 *F32; ///< Pointers to floating-point data 1130 psF64 *F64; ///< Pointers to double-precision data 1131 psF32 *C32; ///< Pointers to complex floating-point data 1132 void **void; 1133 } data; 1252 1134 } psVector; 1253 1135 \end{verbatim} … … 1256 1138 (the number of elements); \code{nalloc} is the number of elements 1257 1139 allocated ($nalloc \ge n$). The allocated memory is available in the 1258 union \code{ arr} which consists of pointers to each of the defined1140 union \code{data} which consists of pointers to each of the defined 1259 1141 primitive data types. Note the parallelism in the names of the types, 1260 1142 union elements, and the psElemType names. This parallelism allows us 1261 1143 to use automatic construction mechanisms effectively. The data type 1262 is defined by the first element, \code{psType}. The 1263 structure isassociated with a constructor and a destructor:1144 is defined by the first element, \code{psType}. The structure is 1145 associated with a constructor and a destructor: 1264 1146 % 1265 1147 \begin{verbatim} 1266 1148 psVector *psVectorAlloc(int nalloc, psElemType type); 1267 1149 psVector *psVectorRealloc(const psVector *vector, int nalloc); 1268 void psVectorFree(psVector *restrict vector );1150 void psVectorFree(psVector *restrict vector, void (*elemFree)(void *)); 1269 1151 \end{verbatim} 1270 1152 % … … 1277 1159 \code{nalloc} is larger than the current value of \code{psVector.n}, 1278 1160 \code{psVector.n} is left intact. If the value of \code{myArray} is 1279 \code{NULL}, then \code{psVectorRealloc} must return an error. 1280 1281 \subsection{Arrays of Pointer Types} 1282 1283 Arrays of pointer types need some additional specification. We 1284 require an array of pointers of type \code{void}, with which we can 1285 carry around a collection of data of an arbitrary type which is more 1286 complicated than the simple numeric types above. The structure is as 1287 follows: 1288 % 1289 \begin{verbatim} 1290 typedef struct { 1291 psType type; ///< Type of data. Must be first element 1292 int nAlloc; ///< Total number of elements available 1293 int n; ///< Number of elements in use 1294 void **arr; ///< The array data 1295 } psVoidPtrArray; 1296 \end{verbatim} 1297 % 1298 There is also an equivalent set of constructors and destructor: 1299 % 1300 \begin{verbatim} 1301 psVoidPtrArray *psVoidPtrArrayAlloc(int nAlloc); 1302 psVoidPtrArray *psVoidPtrArrayRealloc(psVoidPtrArray *myArray, int nAlloc); 1303 void psVoidPtrArrayFree(psVoidPtrArray *restrict myArray, void (*elemFree)(void *)); 1304 \end{verbatim} 1305 % 1306 The only difference with the numeric array types is the addition of a 1307 destructor function which is passed to \code{psVoidPrtArrayFree}. 1308 This function, which may be \code{NULL}, is called for each existing 1309 element of the array before the array itself is freed. If the 1310 function is \code{NULL}, the elements are are not freed. 1311 1312 The routine \code{psVoidPtrArrayFree} assumes that all pointers had 1313 their reference counters incremented when they were inserted onto the 1314 array.\footnote{\eg{} \code{va->arr[i] = psMemIncrRefCounter(ptr);}} 1315 If \code{psVoidPtrArrayFree}'s argument \code{elemFree} is NULL, the 1316 list should be deleted, but not the elements on it (an error should be 1317 raised if the \code{refCounter} is 1; otherwise their 1318 \code{refCounter}'s should be decremented) --- this is to account for 1319 an array of heterogeneous types. 1161 \code{NULL}, then \code{psVectorRealloc} must return an error. In 1162 \code{psVectorFree}, the function \code{elemFree} is required for 1163 arrays of pointer types; it is the destructor appropriate to the data 1164 pointed to by the pointers. This function, which may be \code{NULL}, 1165 is called for each existing element of the array before the array 1166 itself is freed. If the function is \code{NULL}, the elements are are 1167 not freed. This function must not be defined for any data type except 1168 the \code{void} pointer array. 1320 1169 1321 1170 \subsection{Simple Images} … … 1331 1180 const int x0, y0; ///< data region relative to parent 1332 1181 union { 1333 psF32 **rows; ///< Pointers to floating-point data (default) 1334 psS8 **rows_S8; ///< Pointers to char data 1335 psS16 **rows_S16; ///< Pointers to short-integer data 1336 psS32 **rows_S32; ///< Pointers to integer data 1337 psS64 **rows_S64; ///< Pointers to long-integer data 1338 psU8 **rows_U8; ///< Pointers to unsigned-char data 1339 psU16 **rows_U16; ///< Pointers to unsigned-short-integer data 1340 psU32 **rows_U32; ///< Pointers to unsigned-integer data 1341 psU64 **rows_U64; ///< Pointers to unsigned-long-integer data 1342 psF32 **rows_F32; ///< Pointers to floating-point data 1343 psF64 **rows_F64; ///< Pointers to double-precision data 1344 psC32 **rows_C32; ///< Pointers to complex floating-point data 1345 } rows; 1182 psS8 **S8; ///< Pointers to char data 1183 psS16 **S16; ///< Pointers to short-integer data 1184 psS32 **S32; ///< Pointers to integer data 1185 psS64 **S64; ///< Pointers to long-integer data 1186 psU8 **U8; ///< Pointers to unsigned-char data 1187 psU16 **U16; ///< Pointers to unsigned-short-integer data 1188 psU32 **U32; ///< Pointers to unsigned-integer data 1189 psU64 **U64; ///< Pointers to unsigned-long-integer data 1190 psF32 **F32; ///< Pointers to floating-point data 1191 psF64 **F64; ///< Pointers to double-precision data 1192 psC32 **C32; ///< Pointers to complex floating-point data 1193 } data; 1346 1194 const struct psImage *parent; ///< parent, if a subimage 1347 1195 int Nchildren; ///< number of subimages 1348 struct psImage **children; ///< children of this region ; array of Nchildren pointers1196 struct psImage **children; ///< children of this region (Nchildren total) 1349 1197 } psImage; 1350 1198 \end{verbatim} … … 1366 1214 (\code{parent}). Unless this is image is a child of another image 1367 1215 (represents a subset of the pixels of another image), the image data 1368 is allocated in a contiguous block. 1369 1370 Create an image of a specified width, height, and data type. This 1371 function must allow any of the valid image data types and not restrict 1372 to the valid FITS BITPIX types. 1216 is allocated in a contiguous block. We define the following 1217 supporting functions: 1218 1373 1219 \begin{verbatim} 1374 1220 psImage *psImageAlloc (int width, int height, psElemType type); 1375 1221 \end{verbatim} 1376 where \code{width} and \code{height} specify the size of the image and 1377 \code{type} specifies the data type and the image dimensionality 1378 (which must be 2). 1379 1222 Create an image of a specified \code{width}, \code{height}, and data 1223 \code{type}. This function must allow any of the valid image data 1224 types and not restrict to the valid FITS BITPIX types. The image 1225 dimensionality must be 2. 1226 1227 \begin{verbatim} 1228 void psImageFree(psImage *image); 1229 \end{verbatim} 1380 1230 Free the memory associated with a specific image, including the pixel 1381 1231 data. Free the children of the image if they exist. 1382 \begin{verbatim}1383 void psImageFree(psImage *image);1384 \end{verbatim}1385 1386 Free only the pixels for a specified image:1387 \begin{verbatim}1388 psImage *psImageFreePixels(psImage *image);1389 \end{verbatim}1390 1232 1391 1233 \subsection{Doubly-linked lists} … … 1405 1247 The type \code{psDlist} represents the container of the list. It has 1406 1248 a pointer to the first element in the linked list (\code{head}), a 1407 pointer to the last element in the list (\code{tail}), \tbd{an entry1408 for the current cursor location (\code{iter})}, and an entry to define1409 thenumber of elements in the list (\code{n}).1249 pointer to the last element in the list (\code{tail}), an entry for 1250 the current cursor location (\code{iter}), and an entry to define the 1251 number of elements in the list (\code{n}). 1410 1252 1411 1253 The elements of the list are defined by the type \code{psDlistElem}: … … 1422 1264 (\code{next}), the previous element in the list (\code{prev}), and a 1423 1265 \code{void} pointer to whatever data is represented by this list 1424 element. 1425 1426 A list may be created with the function 1266 element. The following supporting functions are required: 1267 1427 1268 \begin{verbatim} 1428 1269 psDlist *psDlistAlloc(void *data); 1429 1270 \end{verbatim} 1430 which may take a pointer to a data item, or it may take \code{NULL}. 1431 The allocator creates both the \code{psDlist} and the first element in 1432 the list, pointed to by both \code{psDlist.head} and 1433 \code{psDlist. tail}. If the data entry is \code{NULL}, then an empty1434 list, with both pointers are set to \code{NULL} should be created. 1435 1436 An entry may be added to the list with the function: 1271 Create a list. This function may take a pointer to a data item, or it 1272 may take \code{NULL}. The allocator creates both the \code{psDlist} 1273 and the first element in the list, pointed to by both 1274 \code{psDlist.head} and \code{psDlist.tail}. If the data entry is 1275 \code{NULL}, then an empty list, with both pointers are set to 1276 \code{NULL} should be created. 1277 1437 1278 \begin{verbatim} 1438 1279 psDlist *psDlistAdd(psDlist *list, void *data, int where); 1439 1280 \end{verbatim} 1440 which takes a pointer to the list and also returns a pointer to the 1441 list. The returned pointer must be used as the value of 1442 \code{psDlist} may have changed. The value of \code{where} specifies 1443 if the specified data item should be placed on the front of the list 1444 (\code{PS_DLIST_HEAD}), at the end of the list (\code{PS_DLIST_TAIL}), 1445 t o add after (\code{PS_DLIST_NEXT}) or before (\code{PS_DLIST_PREV})1446 the current element (specified by the iteration cursor), or an index 1447 that the new \code{data} should inhabit. 1448 1449 A data item may be retrieved from the list with the function: 1281 Add an entry to the list with this function, which takes a pointer to 1282 the list and also returns a pointer to the list. The returned pointer 1283 must be used as the value of \code{psDlist} may have changed. The 1284 value of \code{where} specifies if the specified data item should be 1285 placed on the front of the list (\code{PS_DLIST_HEAD}), at the end of 1286 the list (\code{PS_DLIST_TAIL}), to add after (\code{PS_DLIST_NEXT}) 1287 or before (\code{PS_DLIST_PREV}) the current element (specified by the 1288 iteration cursor), or an index that the new \code{data} should 1289 inhabit. 1290 1450 1291 \begin{verbatim} 1451 1292 void *psDlistGet(psDlist *list, int which); 1452 1293 \end{verbatim} 1453 The value of \code{which} may be the numerical index or it may be one 1454 of the special values: \code{PS_DLIST_HEAD}, \code{PS_DLIST_TAIL}, 1294 A data item may be retrieved from the list with this function. The 1295 value of \code{which} may be the numerical index or it may be one of 1296 the special values: \code{PS_DLIST_HEAD}, \code{PS_DLIST_TAIL}, 1455 1297 \code{PS_DLIST_PREV}, and \code{PS_DLIST_NEXT}, all of which are 1456 1298 defined as negative integers, allowing \code{where} to also be the 1457 1299 index of one of the data items. 1458 1300 1459 A data item may be removed from the list with the function:1460 1301 \begin{verbatim} 1461 1302 void *psDlistRemove(psDlist *list, void *data, int which); 1462 1303 \end{verbatim} 1463 The value of \code{which} may be the numerical index or it may be one 1464 of the special values: \code{PS_DLIST_HEAD}, \code{PS_DLIST_TAIL}, 1304 A data item may be removed from the list with this function. The 1305 value of \code{which} may be the numerical index or it may be one of 1306 the special values: \code{PS_DLIST_HEAD}, \code{PS_DLIST_TAIL}, 1465 1307 \code{PS_DLIST_PREV}, \code{PS_DLIST_UNKNOWN}, and 1466 1308 \code{PS_DLIST_NEXT}, all of which are defined as negative integers. 1467 1309 If the value of \code{which} is \code{PS_DLIST_UNKNOWN}, then the data 1468 item is identified by matching the pointer value with \code{void *data}. 1469 1470 All data items placed onto lists (\code{psDlistAdd}) shall have their 1310 item is identified by matching the pointer value with \code{void 1311 *data}. 1312 1313 All data items placed onto lists (\code{psDlistAdd}) must have their 1471 1314 reference counters (section \ref{secMemRefcounter}) incremented. When 1472 elements are removed from a list with \code{psDlistRemove}, they shall1315 elements are removed from a list with \code{psDlistRemove}, they must 1473 1316 have their reference counters decremented. The action of retrieving 1474 data from a list (with \code{psDlistGet}) shallnot affect their1317 data from a list (with \code{psDlistGet}) must not affect their 1475 1318 reference counter. 1476 1319 1477 A complete list may be freed with the destructor:1478 1320 \begin{verbatim} 1479 1321 void psDlistFree(psDlist *list, void (*elemFree)(void *)); 1480 1322 \end{verbatim} 1481 If the element destructor (\code{elemFree}) is \code{NULL}, the list 1482 should be deleted, but not the elements, although their 1483 \code{refcounter}s should be decremented. 1484 1485 Two functions are available to convert between the \code{psDlist} and 1486 \code{psVoidPtrArray} containers: 1487 \begin{verbatim} 1488 psVoidPtrArray *psDlistToArray(psDlist *dlist); 1489 psDlist *psArrayToDlist(psVoidPtrArray *arr); 1490 \end{verbatim} 1491 These functions do not free the elements or destroy the input 1492 collection. Rather, they increment the reference counter for each of 1493 the elements. 1494 1495 Iteration over all elements of the list using the iteration cursor 1496 \code{iter} is provided by the functions: 1323 A complete list may be freed with this destructor. If the element 1324 destructor (\code{elemFree}) is \code{NULL}, the list should be 1325 deleted, but not the elements, although their \code{refcounter}s 1326 should be decremented. 1327 1328 \begin{verbatim} 1329 psVector *psDlistToVector(psDlist *dlist); 1330 psDlist *psVectorToDlist(psVector *vector); 1331 \end{verbatim} 1332 These two functions are available to convert between the 1333 \code{psDlist} and \code{psVector} containers. These functions do not 1334 free the elements or destroy the input collection. Rather, they 1335 increment the reference counter for each of the elements. 1336 1497 1337 \begin{verbatim} 1498 1338 void psDlistSetIterator(psDlist *list, int where, int which); … … 1500 1340 void *psDlistGetPrev(psDlist *list, int which); 1501 1341 \end{verbatim} 1502 The first of these functions uses the value of \code{where} to set the 1503 iteration cursor for the given list to the beginning 1504 \code{PS_DLIST_HEAD} or the end \code{PS_DLIST_TAIL} for the iterator 1505 specified by \code{which}. The next two functions move the iteration 1506 cursor forward or backwards, returning the data item from the 1507 resulting list entry, or returning \code{NULL} at the end of the list. 1508 Explicit traversal of the list using the \code{psDlistElem}s 1509 \code{prev} and \code{next} pointers is also supported. 1510 1342 Iteration over all elements of the list using the iteration cursor 1343 \code{iter} is provided by these functions. The first of these 1344 functions uses the value of \code{where} to set the iteration cursor 1345 for the given list to the beginning \code{PS_DLIST_HEAD} or the end 1346 \code{PS_DLIST_TAIL} for the iterator specified by \code{which}. The 1347 next two functions move the iteration cursor forward or backwards, 1348 returning the data item from the resulting list entry, or returning 1349 \code{NULL} at the end of the list. Explicit traversal of the list 1350 using the \code{psDlistElem}s \code{prev} and \code{next} pointers is 1351 also supported. 1352 1353 \begin{verbatim} 1354 psDlist *psDlistSort(psDlist *list, int (*compare)(const void *a, const void *b) ); 1355 \end{verbatim} 1511 1356 A list may be sorted using \code{psDlistSort}, which requires the 1512 1357 specification of a comparison function to specify how the objects on 1513 1358 the list should be sorted. The motivation is primarily to be able to 1514 1359 iterate on a sorted list of keys from a hash. 1515 \begin{verbatim}1516 psDlist *psDlistSort(psDlist *list, int (*compare)(const void *a, const void *b) );1517 \end{verbatim}1518 1360 1519 1361 \subsection{Hash Tables} … … 1614 1456 \section{Data manipulation} 1615 1457 1616 There are a number of data concepts which can be naturally represented 1617 in C as structures. We require a variety of basic data manipulation 1618 functions which will act upon data (in particular, arrays/vectors). 1619 We require the following capabilities: 1458 We require a variety of basic data manipulation functions which will 1459 act upon data (in particular, arrays/vectors). We require the 1460 following capabilities: 1620 1461 \begin{itemize} 1621 1462 \item Bit masks; … … 1633 1474 \subsection{Bitsets} 1634 1475 1635 Bitsets are required in order to turn options on and off. We 1636 require the capability to have a bitset of arbitrary length (i.e., 1637 not limited by the length of a \code{long}, say). The1638 \code{psBitset} structure is defined below. Note that the entry 1639 \code{ bits} is an array of type \code{char} storing the bits as bits1640 of each byte in the array, with 8 bits available for each byte inthe1641 array. Also note that the constructor is passed the number of 1642 required bits, which implies that \code{ceil(n / 8)} bytes must be 1643 allocated. The bitset structure isdefine by:1476 Bitsets are required in order to turn options on and off. We require 1477 the capability to have a bitset of arbitrary length (i.e., not limited 1478 by the length of a \code{long}, say). The \code{psBitset} structure 1479 is defined below. Note that the entry \code{bits} is an array of type 1480 \code{char} storing the bits as bits of each byte in the array, with 8 1481 bits available for each byte in the array. Also note that the 1482 constructor is passed the number of required bits, which implies that 1483 \code{ceil(n/8)} bytes must be allocated. The bitset structure is 1484 define by: 1644 1485 \begin{verbatim} 1645 1486 typedef struct { … … 1656 1497 where \code{n} is the requested number of bits. 1657 1498 1658 Fourbasic operations on bitsets are required:1499 Several basic operations on bitsets are required: 1659 1500 \begin{itemize} 1660 1501 \item Set a bit; 1661 1502 \item Check if a bit is set; and 1662 1503 \item \code{OR}, \code{AND} and \code{XOR} two bitsets. 1504 \item \code{NOT} a bitset. 1663 1505 \end{itemize} 1664 1506 The corresponding APIs are defined below: … … 1695 1537 \subsection{Sorting} 1696 1538 1697 We require the ability to sort a n array of floating-point values. The1698 following function returns the array, sorted from the smallest (i.e.\ 1699 most negative) value in the first element, and the largest (i.e.\ most 1700 positive) value in the last element. The input array, \code{in}, may 1701 be sorted in-place if it is also specified as the \code{out} 1702 array. This function is specified for input types \code{psU8, psU16,1703 psF 32, psF64}. The input and output vectors must have the same type.1539 We require the ability to sort a vector. The following function 1540 returns the vector, sorted from the smallest (i.e.\ most negative) 1541 value in the first element, and the largest (i.e.\ most positive) 1542 value in the last element. The input vector, \code{in}, may be sorted 1543 in-place if it is also specified as the \code{out} vector. This 1544 function is specified for input types \code{psU8, psU16, psF32, 1545 psF64}. The input and output vectors must have the same type. 1704 1546 1705 1547 \begin{verbatim} … … 1707 1549 \end{verbatim} 1708 1550 1709 We also require the ability to sort one arraybased on another. For1551 We also require the ability to sort one vector based on another. For 1710 1552 example, we may want to sort both \code{x} and \code{y} by the value 1711 1553 in \code{x}. In order to facilitate this, we will have a sort 1712 function return a n arraycontaining the indices for the unsorted list1713 in the order appropriate for the sorted array. The output vector must1554 function return a vector containing the indices for the unsorted list 1555 in the order appropriate for the sorted vector. The output vector must 1714 1556 be of type \code{psU32}. This function is specified for input types 1715 1557 \code{psU8, psU16, psF32, psF64}. … … 1719 1561 \end{verbatim} 1720 1562 1721 The sorted arrays may be accessed in the following manner:1722 \begin{verbatim} 1723 index Array= psSortIndex(NULL, x);1724 for (int i = 0; i < index Array.n; i++) {1725 doMyFunc(x[index Array.arr.arr_U32[i]], y[indexArray[i].arr.arr_U32]);1563 The sorted vectors may be accessed in the following manner: 1564 \begin{verbatim} 1565 indexVector = psSortIndex(NULL, x); 1566 for (int i = 0; i < indexVector.n; i++) { 1567 doMyFunc(x[indexVector.arr.arr_U32[i]], y[indexVector[i].arr.arr_U32]); 1726 1568 } 1727 1569 \end{verbatim} … … 1731 1573 \subsection{Statistics Functions} 1732 1574 1733 \subsubsection{ ArrayStatistics}1734 1735 We require a very general statistics function, which, given a n array1575 \subsubsection{Vector Statistics} 1576 1577 We require a very general statistics function, which, given a vector 1736 1578 of floating-point values, will be able to calculate the following 1737 1579 statistics: … … 1748 1590 \item Clipped mean and number of values used to calculate; 1749 1591 \item Clipped standard deviation; and 1750 \item Minimum and maximum value in array.1592 \item Minimum and maximum value in vector. 1751 1593 \end{itemize} 1752 1594 1753 1595 For definitions of each of these, see the accompanying Algorithms 1754 1596 Definition Document (ADD), but in general, ``sample'' refers to the 1755 entire array, ``robust'' refers to fitting the distribution in the1756 arraywith a model, and ``clipped'' refers to clipping the1757 distribution. Each of these shallbe available from a single1597 entire vector, ``robust'' refers to fitting the distribution in the 1598 vector with a model, and ``clipped'' refers to clipping the 1599 distribution. Each of these must be available from a single 1758 1600 function: 1759 1601 1760 1602 \begin{verbatim} 1761 psStats *ps ArrayStats(const psVector *restrict in,1762 const psVector *restrict mask,1763 unsigned int maskVal,1764 psStats *stats);1603 psStats *psVectorStats(const psVector *restrict in, 1604 const psVector *restrict mask, 1605 unsigned int maskVal, 1606 psStats *stats); 1765 1607 \end{verbatim} 1766 1608 % … … 1768 1610 in \code{mask}, so that the user may explicitly reject specific 1769 1611 entries) and a \code{psStats} structure, which will be altered and 1770 returned. The input vector may be of type \code{psU8}, \code{psU16}, 1771 \code{psF32}, \code{psF64}; the mask must be of type \code{psU8}. 1612 returned. The \code{psStats} structure includes several fields which 1613 are used for both input and output: \code{min} and \code{max} may be 1614 used to specify a value range for which the statistics are calculated. 1615 \code{binsize} specifies a choice for the robust statistics histogram 1616 bin size. If these are to be used, the user should set the 1617 corresponding \code{options} bits \code{PS_STAT_USE_RANGE} or 1618 \code{PS_STAT_USE_BINSIZE}. \code{clipSigma} specifies the number of 1619 standard deviations for which data should be clipped. \code{clipIter} 1620 specifies the number of iterations which should be used for clipping. 1621 The defaults for these two numbers is both 3. Since the sample 1622 statistics scale like $N\log N$, for large numbers of input data 1623 points, it is faster to use the robust statistics. If the number of 1624 data points is large, \code{psStats} must revert to the robust 1625 calculation even if the user requested sample statistics. The values 1626 should be returned in the \code{sample} fields, but the bit 1627 \code{PS_STAT_ROBUST_FOR_SAMPLE} in \code{options} must be set in this 1628 case. The cutoff for this decision must be made on the basis of the 1629 value in \code{sampleLimit},which should have a default of \tbd{3e5}. 1630 Default input field values must be set by the \code{psStats} 1631 constructor. The input vector may be of type \code{psU8}, 1632 \code{psU16}, \code{psF32}, \code{psF64}; the mask must be of type 1633 \code{psU8}. 1772 1634 1773 1635 The \code{psStats} structure is defined with entries for each of the … … 1782 1644 double sampleUQ; ///< upper quartile of sample 1783 1645 double sampleLQ; ///< lower quartile of sample 1646 double sampleLimit; ///< Number of datapoints to 1784 1647 double robustMean; ///< robust mean of data 1785 int robustMeanNvalues; ///< number of measurements used for robust mean1786 1648 double robustMedian; ///< robust median of data 1787 int robustMedianNvalues; ///< number of measurements used for robust median1788 1649 double robustMode; ///< Robust mode of data 1789 int robustModeNvalues; ///< Number of measurements used for robust mode1790 1650 double robustStdev; ///< robust standard deviation of data 1791 1651 double robustUQ; ///< robust upper quartile 1792 1652 double robustLQ; ///< robust lower quartile 1653 int robustN50; ///< Number of points UQ-LQ 1654 int robustNfit; ///< Number of points in Gauss. fit 1793 1655 double clippedMean; ///< Nsigma clipped mean 1794 int clippedMeanNvalues; ///< number of data points used for clipped mean1795 1656 double clippedStdev; ///< standard deviation after clipping 1657 int clippedNvalues; ///< number of data points used for clipped mean 1796 1658 double clipSigma; ///< Nsigma used for clipping; user input 1797 1659 int clipIter; ///< Number of clipping iterations; user input 1798 double min; ///< minimum data value in data 1799 double max; ///< maximum data value in data 1800 int nValues; ///< number of data values in data1660 double min; ///< minimum data value in data; input range 1661 double max; ///< maximum data value in data; input range 1662 double binsize; ///< binsize for robust fit (input/output) 1801 1663 psStatsOptions options; ///< bitmask of calculated values 1802 1664 } psStats; … … 1811 1673 PS_STAT_SAMPLE_MEDIAN = 0x000002, 1812 1674 PS_STAT_SAMPLE_STDEV = 0x000004, 1813 PS_STAT_SAMPLE_UQ = 0x000008, 1814 PS_STAT_SAMPLE_LQ = 0x000010, 1815 PS_STAT_ROBUST_MEAN = 0x000020, 1816 PS_STAT_ROBUST_MEAN_NVALUES = 0x000040, 1817 PS_STAT_ROBUST_MEDIAN = 0x000080, 1818 PS_STAT_ROBUST_MEDIAN_NVALUES = 0x000100, 1819 PS_STAT_ROBUST_MODE = 0x000200, 1820 PS_STAT_ROBUST_MODE_NVALUES = 0x000400, 1821 PS_STAT_ROBUST_STDEV = 0x000800, 1822 PS_STAT_ROBUST_UQ = 0x001000, 1823 PS_STAT_ROBUST_LQ = 0x002000, 1824 PS_STAT_CLIPPED_MEAN = 0x004000, 1825 PS_STAT_CLIPPED_MEAN_NVALUES = 0x008000, 1826 PS_STAT_CLIPPED_MEAN_NSIGMA = 0x010000, 1827 PS_STAT_CLIPPED_STDEV = 0x020000, 1828 PS_STAT_MAX = 0x040000, 1829 PS_STAT_MIN = 0x080000, 1830 PS_STAT_NVALUES = 0x100000 1675 PS_STAT_SAMPLE_QUARTILE = 0x000008, 1676 PS_STAT_ROBUST_MEAN = 0x000010, 1677 PS_STAT_ROBUST_MEDIAN = 0x000020, 1678 PS_STAT_ROBUST_MODE = 0x000040, 1679 PS_STAT_ROBUST_STDEV = 0x000080, 1680 PS_STAT_ROBUST_QUARTILE = 0x000100, 1681 PS_STAT_CLIPPED_MEAN = 0x000200, 1682 PS_STAT_CLIPPED_STDEV = 0x000400, 1683 PS_STAT_MAX = 0x000800, 1684 PS_STAT_MIN = 0x001000, 1685 PS_STAT_USE_RANGE = 0x002000, 1686 PS_STAT_USE_BINSIZE = 0x004000 1687 PS_STAT_ROBUST_FOR_SAMPLE = 0x008000 1831 1688 } psStatsOptions; 1832 1689 \end{verbatim} … … 1849 1706 const psVector *restrict bounds; ///< Bounds for the bins 1850 1707 psVector *nums; ///< Number in each of the bins 1851 int minNum, maxNum; ///< Number below the minimum and above the maximum1708 int minNum, maxNum; ///< Number below minimum / above maximum 1852 1709 int uniform; ///< Is it a uniform distribution? 1853 1710 } psHistogram; … … 1895 1752 \end{verbatim} 1896 1753 The input vector may be of types \code{psU8, psU16, psF32, psF64}. 1754 1755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1756 1757 \subsection{Analytical functions} 1758 1759 \subsubsection{General Polynomials} 1760 1761 PSLib provides APIs to represent and interact with polynomials in up 1762 to four dimensions, with both floating-point and double-precision 1763 numbers. In Pan-STARRS processing, the astrometry requirements push 1764 the need for at least four dimensions ($x$,$y$, color and magnitude) 1765 and double-precision (for milli-arcsec precision) versions. We must 1766 also be able to calculate the errors in the fit coefficients, as well 1767 as be able to turn on and off each coefficient. This leads us to 1768 define the following polynomial types: 1769 1770 \begin{verbatim} 1771 /** One-dimensional polynomial */ 1772 typedef struct { 1773 int n; ///< Number of terms 1774 float *restrict coeff; ///< Coefficients 1775 float *restrict coeffErr; ///< Error in coefficients 1776 char *restrict mask; ///< Coefficient mask 1777 } psPolynomial1D; 1778 \end{verbatim} 1779 1780 \begin{verbatim} 1781 /** Two-dimensional polynomial */ 1782 typedef struct { 1783 int nX, nY; ///< Number of terms in x and y 1784 float *restrict *restrict coeff; ///< Coefficients 1785 float *restrict *restrict coeffErr; ///< Error in coefficients 1786 char *restrict *restrict mask; ///< Coefficients mask 1787 } psPolynomial2D; 1788 \end{verbatim} 1789 1790 etc., up to four dimensions. We also define double-precision versions: 1791 1792 \begin{verbatim} 1793 /** Double-precision one-dimensional polynomial */ 1794 typedef struct { 1795 int n; ///< Number of terms 1796 double *restrict coeff; ///< Coefficients 1797 double *restrict coeffErr; ///< Error in coefficients 1798 char *restrict mask; ///< Coefficient mask 1799 } psDPolynomial1D; 1800 \end{verbatim} 1801 1802 \begin{verbatim} 1803 /** Double-precision two-dimensional polynomial */ 1804 typedef struct { 1805 int nX, nY; ///< Number of terms in x and y 1806 double *restrict *restrict coeff; ///< Coefficients 1807 double *restrict *restrict coeffErr; ///< Error in coefficients 1808 char *restrict *restrict mask; ///< Coefficients mask 1809 } psDPolynomial2D; 1810 \end{verbatim} 1811 1812 etc. In what follows, we only show the version for double-precision 1813 two-dimensionals; the others may be inferred following the standard 1814 naming convention exampled above. 1815 1816 The constructor and destructor are: 1817 \begin{verbatim} 1818 psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY); 1819 void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly); 1820 \end{verbatim} 1821 where \code{nX} and \code{nY} are the number of terms in x and y 1822 respectively. The coefficients and errors are set initially to 0.0. 1823 1824 To evaluate the polynomials at specific coordinates, we define: 1825 \begin{verbatim} 1826 double psDPolynomial2DEval(double x, double y, const psDPolynomial2D *restrict myPoly); 1827 \end{verbatim} 1828 1829 \subsubsection{Gaussians} 1830 1831 Gaussians are used extensively in any data-analysis system, in 1832 particular to represent a real population distribution. We require 1833 a function to evaluate a Gaussian for a given coordinate and one which 1834 generates a Gaussian deviate; a collection of data points whose 1835 distribution obeys a specified Gaussian. 1836 1837 The Gaussian evaluation is provide by: 1838 \begin{verbatim} 1839 float psGaussian(float x, float mean, float sigma, int normal); 1840 \end{verbatim} 1841 which evaluates a Gaussian with the given \code{mean} and \code{sigma} 1842 at the given coordinate \code{x}. If \code{normal} is true, the 1843 Gaussian is normalized (total integral = 1), otherwise, the Gaussian 1844 is non-normalized (central peak value = 1). The evaluated Gaussian 1845 is: 1846 1847 \[ \frac{1}{\sqrt{2\pi\sigma^2}} exp^{-\frac{(x-mean)^2}{2\sigma^2}} \] 1848 1849 In the case of the non-normalized Gaussian, the leading coefficient is 1850 dropped. 1851 1852 A vector with a specified Gaussian deviate distribution is provide by: 1853 \begin{verbatim} 1854 psVector *psGaussianDev(float mean, float sigma, int Npts); 1855 \end{verbatim} 1856 which generates a vector (type \code{psF32}) of \code{Npts} elements 1857 whose distribution has the given \code{mean} and \code{sigma}. 1858 1859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1860 1861 \subsection{Minimization and fitting routines} 1862 1863 We require a general minimization routine, a routine that will 1864 specifically minimize $\chi^2$ given a list of data with associated 1865 errors, and a function that will analytically determine the best 1866 polynomial fit by minimizing $\chi^2$. 1867 1868 Consider a function \code{myFunction} which is a function of a 1869 collection of parameters \code{params} and coordiate vector 1870 \code{coord}, and returns a single floating point value. We define 1871 \code{psMinimize}, which determines the parameters of 1872 \code{myFunction} which minimize the function for the coordinate 1873 \code{coord}. The returned vector must be the same length as the 1874 vector argument to the input function. 1875 \begin{verbatim} 1876 float myFunction (psVector *params, psVector *coord); 1877 float myFuncDeriv (psVector *params, psVector *coord); 1878 psVector *psMinimize(psVector *restrict initialGuess, 1879 float (*myFunction)(psVector *, psVector *), 1880 float (*myFuncDeriv)(psVector *, psVector *), 1881 const psVector *restrict coord, 1882 const psVector *restrict paramMask); 1883 \end{verbatim} 1884 \code{psMinimize} determines and returns the vector that minimizes the 1885 specified function. It takes as input a function, \code{myFunction}, 1886 an initial guess for the vector that minimizes the function, 1887 \code{initialGuess}, the current coordiate \code{coord}, and an 1888 optional mask for the vector elements (function parameters) to 1889 minimize, \code{paramMask} (all parameters are fit if \code{NULL}). 1890 Note that \code{paramMask} must be of type \code{psU8}, while 1891 \code{params} must be of type \code{psF32}. The optional function, 1892 \code{myFuncDeriv} returns the derivative of the function. 1893 1894 \begin{verbatim} 1895 psVector *psMinimizeChi2(psVector *restrict initialGuess, 1896 float (*evalModel)(psVector *, psVector *), 1897 const psVector *restrict domain, 1898 const psVector *restrict data, 1899 const psVector *restrict errors, 1900 const psVector *restrict paramMask, 1901 float *ChiSq); 1902 \end{verbatim} 1903 \code{psMinimizeChi2} fits a model to observations by minimizing 1904 $\chi^2$, returing the best-fit parameters. The input parameters are 1905 a function that evaluates the model for a specified domain, given the 1906 parameters, \code{evalModel}; a list of observations, (\code{domain}, 1907 \code{data}, and \code{errors}); an initial guess at the best-fit 1908 parameters, \code{initialGuess} which is returned with the best-fit 1909 parameters, and an optional mask specifying which parameters are to be 1910 fit, \code{paramMask}, which must be of type \code{psU8}. All 1911 parameters are fit if this vector is \code{NULL}. 1912 1913 \begin{verbatim} 1914 psPolynomial1D *psVectorFitPolynomial1D(psPolynomial1D myPoly, 1915 const psVector *restrict x, 1916 const psVector *restrict y, 1917 const psVector *restrict yErr); 1918 \end{verbatim} 1919 \code{psVectorFitPolynomial} returns the polynomial that best fits the 1920 observations. The input parameters are a polynomial that specifies 1921 the fit order, \code{myPoly}, which will be altered and returned with 1922 the best-fit coefficients; and the observations, \code{x}, \code{y} 1923 and \code{yErr}. The independent variable list, \code{x} may be 1924 \code{NULL}, in which case the vector index is used. The dependent 1925 variable error, \code{yErr} may be null, in which case the solution is 1926 determined in the assumption that all data errors are equal. This 1927 function must be valid for types \code{psU8}, \code{psU16}, 1928 \code{psF32}, \code{psF64}. 1929 1930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1931 1932 \subsection{Image Operations} 1933 1934 We require a variety of functions to manipulate these image 1935 structures, including creation, destruction, input, output, and 1936 various manipulations of the pixels. The required functions are 1937 listed below, and fall into several categories. 1938 1939 \subsubsection{Image Structure Manipulation} 1940 1941 \begin{verbatim} 1942 psImage *psImageSubset(const psImage *image, int nx, int ny, int x0, int y0); 1943 \end{verbatim} 1944 Define a subimage of the specified area of the given image. This 1945 function must return an error if the requested subset area lies 1946 outside of the parent image. The argument \code{image} is the parent 1947 image, \code{nx,ny} specify the dimensions of the desired subraster, 1948 and \code{x0, y0} specify the starting pixel of the subraster. The 1949 entire subraster must be contained within the raster of the parent 1950 image. Note that the \code{refCounter} for the parent should be 1951 incremented. This function must be defined for the following types: 1952 \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, \code{psF32}, 1953 \code{psF64}, \code{psC32}, \code{psC64}. 1954 1955 \begin{verbatim} 1956 psImage *psImageCopy(psImage *output, const psImage *input, psElemType type); 1957 \end{verbatim} 1958 Create a copy of the specified image, converting the type in the 1959 process. If the output target pointer is not NULL, place the result 1960 in the specified structure. The output image data must be allocated 1961 as a single, contiguous block of memory. The output image may not be 1962 the input image. This function must be defined for the following 1963 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 1964 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 1965 1966 \subsubsection{Image Pixel Extractions} 1967 1968 \begin{verbatim} 1969 psVector *psImageSlice(psVector *out, const psImage *input, 1970 int x, int y, int nx, int ny, 1971 int direction, const psStats *stats); 1972 \end{verbatim} 1973 Extract pixels from rectlinear region to a vector (array of floats). 1974 The output vector contains either \code{nx} or \code{ny} elements, 1975 based on the value of the direction: e.g., if \code{direction} is 1976 \tbd{+x}, there are \code{nx} elements. The input region is collapsed 1977 in the perpendicular direction, and each element of the output vectors 1978 is derived from the statistics of the pixels at that direction 1979 coordinate. The statistic used to derive the output vector value is 1980 specified by \code{stats}. This function must be defined for the 1981 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 1982 1983 \begin{verbatim} 1984 psVector *psImageCut(psVector *out, const psImage *input, 1985 float xs, float ys, float xe, float ye, 1986 float dw, const psStats *stats); 1987 \end{verbatim} 1988 Extract pixels from an image along a line to a vector (array of 1989 floats). The vector \code{(xs,ys)} - \code{(xe,ye)} forms the basis of 1990 the output vector. Pixels are considered in a rectangular region of 1991 width \code{dw} about this vector. The input region is collapsed in 1992 the perpendicular direction, and each element of the output vector 1993 represents pixel-sized boxes, where the value is derived from the 1994 statistics of the pixels interpolated along the perpendicular 1995 direction. The statistic used to derive the output vector value is 1996 specified by \code{stats}. This function must be defined for the 1997 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64} 1998 1999 \begin{verbatim} 2000 psVector *psImageRadialCut(psVector *out, const psImage *input, float x, float y, 2001 const psVector *radii, const psStats *stats); 2002 \end{verbatim} 2003 Extract radial annuli data to a vector. A vector is constructed where 2004 each vector elements is derived from the statistics of the pixels 2005 which land in one of a sequence of annuli. The annuli are centered on 2006 the image pixel coordinate \code{x,y}, and have width \code{dr}. The 2007 number of annuli is $radius / dr$. The statistic used to derive the 2008 output vector value is specified by \code{stats}. This function must be defined for the 2009 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2010 2011 \subsubsection{Image Geometry Manipulation} 2012 2013 \begin{verbatim} 2014 psImage *psImageRebin(psImage *out, const psImage *in, 2015 float scale, const psStats *stats); 2016 \end{verbatim} 2017 Rebin image to new scale. A new image is constructed in which the 2018 dimensions are reduced by a factor of \code{scale} $\le 1$ (it is an 2019 error for \code{scale} $> 1$). The \code{scale} is equal in each 2020 dimension. The output image is generated from all input image pixels. 2021 Each pixel in the output image is derived from the statistics of the 2022 corresponding set of input image pixels based on the statistics 2023 specified by \code{stats}. This function must be defined for the 2024 following types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2025 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2026 2027 \begin{verbatim} 2028 psImage *psImageRotate(psImage *out, const psImage *input, float angle); 2029 \end{verbatim} 2030 Rotate the input image by given angle, specified in degrees. The 2031 output image must contain all of the pixels from the input image in 2032 their new frame. Pixels in the output image which do not map to input 2033 pixels should be set to \tbd{value}. The center of rotation is always 2034 the center pixel of the image. The rotation is specified in the sense 2035 that a positive angle is an anti-clockwise rotation. This function 2036 must be defined for the following types: \code{psU8}, \code{psU16}, 2037 \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, 2038 \code{psC64}. 2039 2040 \begin{verbatim} 2041 psImage *psImageShift(psImage *out, const psImage *input, 2042 float dx, float dy, float exposed); 2043 \end{verbatim} 2044 Shift image by an arbitrary number of pixels (\code{dx,dy}) in either 2045 direction. If the shift values are fractional, the output pixel 2046 values should interpolate between the input pixel values. The output 2047 image has the same dimensions as the input image. Pixels which fall 2048 off the edge of the output image are lost. Newly exposed pixels are 2049 set to the value given by \code{exposed}. This function must be 2050 defined for the following types: \code{psU8}, \code{psU16}, 2051 \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, 2052 \code{psC64}. 2053 2054 \begin{verbatim} 2055 psImage *psImageRoll(psImage *out, const psImage *input, int dx, int dy); 2056 \end{verbatim} 2057 Roll image by an integer number of pixels (\code{dx,dy}) in either 2058 direction. The output image is the same dimensions as the input 2059 image. Edge pixels wrap to the other side (no values are lost). This 2060 function must be defined for the following types: \code{psU8}, 2061 \code{psU16}, \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, 2062 \code{psC32}, \code{psC64}. 2063 2064 \subsubsection{Image Statistical Functions} 2065 2066 \begin{verbatim} 2067 psStats *psImageGetStats(psStats *stats, const psImage *input); 2068 \end{verbatim} 2069 Determine statistics for image (or subimage). The statistics to be 2070 determined are specified by \code{stats}. This function must be 2071 defined for the following types: \code{psU8}, \code{psU16}, 2072 \code{psF32}, \code{psF64}. 2073 2074 \begin{verbatim} 2075 psHistogram *psImageHistogram(psHistogram *hist, const psImage *input); 2076 \end{verbatim} 2077 Construct a histogram from an image (or subimage). The histogram to 2078 generate is specified by \code{psHistogram hist} (see 2079 section~\ref{sec:histograms}). This function must be defined for the 2080 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2081 2082 \begin{verbatim} 2083 psPolynomial2D *psImageFitPolynomial(psPolynomial2D *coeffs, const psImage *input); 2084 \end{verbatim} 2085 Fit a 2-D Chebychev polynomial surface to an image. The input 2086 structure \code{coeffs} contains the desired order and terms of 2087 interest. This function must be defined for the 2088 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2089 2090 \begin{verbatim} 2091 psImage *psImageEvalPolynomial(psImage *input, const psPolynomial2D *coeffs); 2092 \end{verbatim} 2093 Evaluate a 2-D polynomial surface for the image pixels. Given the 2094 input polynomial coefficients, set the image pixel values on the basis 2095 of the polynomial function. This function must be defined for the 2096 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2097 2098 \subsubsection{Image I/O Functions} 2099 2100 \begin{verbatim} 2101 psImage *psImageReadSection(psImage *output, int x0, int y0, int nx, int ny, int z, 2102 const char *extname, int extnum, const char *filename); 2103 \end{verbatim} 2104 Read an image or subimage from a named file. This function is a 2105 wrapper to the FITS library function. The input parameters allow a 2106 full image or a subimage to be read. The starting pixel of the region 2107 is specified by \code{x,y}, while the dimensions of the requested 2108 region are specified by \code{nx,ny}. A negative value of -1 for 2109 these two parameters specifies the full array of the requested image, 2110 less absolute value of the variable. If the native image is a cube, 2111 the value of z specifies the requested slice of the image. The data 2112 is read from the extension specified by extname (matching the EXTNAME 2113 keyword) or by the extnum value (with 0 representing the PHU, 1 the 2114 first extension, etc). This function must call \code{psError} and 2115 return \code{NULL} if any of the specified parameters are out of range 2116 for the data in the image file, if the specified image file does not 2117 exist, or the image on disk is zero- or one-dimensional. 2118 2119 \begin{verbatim} 2120 psImage *psImageFReadSection(psImage *output, int x, int y, int nx, int ny, int z, 2121 const char *extname, int extnum, FILE *f); 2122 \end{verbatim} 2123 Read an image or subimage from file descriptor. The input parameters 2124 and their behavior for this function are identical with those in 2125 \code{psImageReadSection}. 2126 2127 \begin{verbatim} 2128 psImage *psImageWriteSection(const psImage *input, int x, int y, int z, 2129 const char *extname, int extnum, const char *filename); 2130 \end{verbatim} 2131 Write an image section to the named file, which may exist. This 2132 operation may write a portion of an image over the existing bytes of 2133 an existing image. If the file does not exist, it should be created. 2134 If the specified extension does not exist, it should be created. If 2135 an extension is specified and no PHU exists, a basic PHU should be 2136 created. 2137 2138 \begin{verbatim} 2139 psImage *psImageFWriteSection(const psImage *input, int x, int y, int z, 2140 const char *extname, int extnum, FILE *f); 2141 \end{verbatim} 2142 Write an image section to file descriptor as above: 2143 2144 \subsubsection{Image Pixel Manipulations} 2145 2146 \begin{verbatim} 2147 int psImageClip(psImage *input, float min, float vmin, float max, float vmax); 2148 \end{verbatim} 2149 Clip image values outside of range to given values. All pixels with 2150 values \code{< min} are set to the value \code{vmin}. All pixels with 2151 values \code{> max} are set to the value \code{vmax}. Returns the 2152 number of clipped pixels. This function must be defined for the 2153 following types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2154 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2155 2156 \begin{verbatim} 2157 int psImageClipNaN(psImage *input, float value); 2158 \end{verbatim} 2159 Clip \code{NaN} image pixels to given value. Pixels with \code{NaN}, 2160 \code{+Inf} or \code{-Inf} values are set to the specified value. 2161 Returns the number of clipped pixels. This function must be defined 2162 for the following types: \code{psU8}, \code{psU16}, \code{psS8}, 2163 \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2164 2165 \begin{verbatim} 2166 int psImageOverlaySection(psImage *image, const psImage *overlay, 2167 int x0, int y0, const char *op); 2168 \end{verbatim} 2169 Overlay subregion of image with another image. Replace the pixels in 2170 the \code{image} which correspond to the pixels in \code{overlay} with 2171 values derived from the values in \code{image} and \code{overlay} 2172 based on the given operator \code{op}. Valid operators are \code{=} 2173 (set image value to overlay value), \code{+} (add overlay value to 2174 image value), \code{-} (subtract overlay from image), \code{*} 2175 (multiply overlay times image), \code{/} (divide image by overlay). 2176 This function must be defined for the following types: \code{psU8}, 2177 \code{psU16}, \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, 2178 \code{psC32}, \code{psC64}. 2179 2180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2181 2182 \subsection{Vector and Image Arithmetic} 2183 \label{sec:arithmetic} 2184 2185 We will need to be able to perform various operations on vectors and 2186 images, e.g.\ dividing one image by another, subtracting a vector 2187 from an image, etc. Both binary operations and unary operations are 2188 required. To avoid the burden of memorizing a ton of APIs, we specify 2189 two generic APIs for the binary and unary operations. 2190 2191 \begin{verbatim} 2192 psType *psBinaryOp (void *out, void *in1, char *op, void *in2); 2193 psType *psUnaryOp (void *out, void *in, char *op); 2194 \end{verbatim} 2195 These functions determine the type of the operands on the basis of 2196 their \code{psType} elements, which always are the first elements. 2197 Note that these functions return a pointer to the appropriate type for 2198 the operation. Since the result may is cast to \code{psType}, the 2199 resulting type may be determined by examining the return value. It is 2200 expected that the implementation of these functions will employ 2201 pre-processor macros to perform the onerous task of creating the 2202 loops. Also note that \code{psVector} is equivalent to 2203 \code{psVector}. An attempt to perform an arithmetic operation on 2204 an object of dimension \code{PS_DIMEN_OTHER} should produce an error. 2205 2206 Binary operations between an image and a vector have a potential 2207 ambiguity --- do the vector elements correspond to the rows or the 2208 columns? For this reason, we define two vector types: a ``vector'' 2209 (\code{PS_DIMEN_VECTOR}), and a ``transposed vector'' 2210 (\code{PS_DIMEN_TRANSV}). We specify that a ``vector'', when involved 2211 in binary operations on an image, acts on the rows, while a 2212 ``transposed vector'' in the same context acts on the columns. 2213 Vectors, when created, will be created as ``vectors'', but may be 2214 converted to ``transposed vectors'' using the following function: 2215 \begin{verbatim} 2216 psVector *psVectorTranspose(psVector *out, psVector *myVector); 2217 \end{verbatim} 2218 2219 It is further desirable to allow scalar values to be used within these 2220 functions, which requires the following additions: 2221 \begin{verbatim} 2222 p_ps_Scalar *psScalar (double value); 2223 p_ps_Scalar *psScalarType (char *mode, ...); 2224 \end{verbatim} 2225 The first creates a psType-ed structure from a constant value, while 2226 the second creates a psType-ed structure for a specified type. The 2227 structure which carries a scalar value is specified as the following 2228 private type, and is analogous to the \code{psVector} and 2229 \code{psImage} structures: 2230 \begin{verbatim} 2231 typedef struct { 2232 psType type; ///< data type information 2233 union { 2234 psS32 S32; ///< integer value entry 2235 psF32 F32; ///< float value entry 2236 psF64 F64; ///< double value entry 2237 psC32 C32; ///< complex value entry 2238 } data; 2239 } p_psScalar; 2240 \end{verbatim} 2241 2242 This allows one to write the following to take the sine of the square 2243 of all pixels in an image: 2244 \begin{verbatim} 2245 psImage A,B; 2246 2247 B = psBinaryOp (NULL, A, "^", psScalar(2)); 2248 (void) psUnaryOp(B, B, "sin"); 2249 \end{verbatim} 2250 2251 Note that the \code{psUnaryOp} is performed on \code{B} in-place. 1897 2252 1898 2253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 1945 2300 \end{verbatim} 1946 2301 1947 Matrix arithmetic is supported through \code{psMatrixOp}. Note that 1948 \code{psMatrixOp} differs from \code{psBinaryOp} in that 1949 multiplication with \code{psBinaryOp} acts on corresponding elements, 1950 while \code{psMatrixOp} performs classical matrix multiplication 1951 involving row and column operations. Addition and subtraction by 1952 \code{psMatrixOp} are identical to that for \code{psBinaryOp} (since 1953 that is how matrix addition is defined). Matrix division is not 1954 defined. \tbd{why specify addition as an operator? why not only 1955 define operators which are different for matrices?}. This function is 2302 Matrix multiplication is supported through \code{psMatrixMultiply}. This function is 1956 2303 specified for data types \code{psF32, psF64}. 1957 1958 \begin{verbatim} 1959 psImage *psMatrixOp(psImage *out, const psImage *in1, const char *op, const psImage *in2); 2304 \begin{verbatim} 2305 psImage *psMatrixMultiply(psImage *out, const psImage *in1, const psImage *in2); 1960 2306 \end{verbatim} 1961 2307 … … 2009 2355 always \code{psC32}. If the input vector is \code{psF32}, the 2010 2356 direction must be forward. Neither the forward or inverse transforms 2011 shallmultiply by $1/N$ (or $1/N^{1/2}$), and so it falls to the2357 must multiply by $1/N$ (or $1/N^{1/2}$), and so it falls to the 2012 2358 responsibility of the user to multiply a vector that has been forward- 2013 2359 and reverse-transformed by $1/N$. … … 2030 2376 \begin{verbatim} 2031 2377 psImage *psImageFFT(const psImage *image, int direction); 2032 psImage *psImagePowerSpectrum(const psImage *image);2033 2378 psImage *psImageReal(psImage *out, const psImage *in); 2034 psImage *psImage Real(psImage *out, const psImage *in);2035 psImage *psImage Real(psImage *out, const psImage *in);2379 psImage *psImageImaginary(psImage *out, const psImage *in); 2380 psImage *psImageComplex(psImage *real, const psImage *imag); 2036 2381 psImage *psImageConjugate(psImage *out, const psImage *in); 2037 \end{verbatim} 2038 2039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2040 2041 \subsection{Analytical functions} 2042 2043 We require two types of general functions which will be used in fitting: 2044 Gaussians and Polynomials. The Gaussian is defined as: 2045 \begin{verbatim} 2046 float psGaussian(float x, float mean, float stdev); 2047 \end{verbatim} 2048 2049 which evaluates a non-normalized Gaussian with the given mean and 2050 sigma at the given coordianate. Note that this is not a Gaussian 2051 deviate. The evaluated Gaussian is: 2052 2053 \[ 1/(\sqrt(2\pi)\sigma) exp(-\frac{(x-mean)^2}{2\sigma^2}) \] 2054 2055 For the polynomial, \PS{} astrometry requirements lead us to specify 2056 that we must be able to support at least four dimensions, in both 2057 floating-point (for speed) and double-precision (for milli-arcsec 2058 precision) versions. This comes from the need to fit over $x$,$y$, 2059 color and magnitude simultaneously. We must also be able to 2060 calculate the errors in the fit coefficients, as well as be able to 2061 turn on and off each coefficient. This leads us to define polynomial 2062 types: 2063 2064 \begin{verbatim} 2065 /** One-dimensional polynomial */ 2066 typedef struct { 2067 int n; ///< Number of terms 2068 float *restrict coeff; ///< Coefficients 2069 float *restrict coeffErr; ///< Error in coefficients 2070 char *restrict mask; ///< Coefficient mask 2071 } psPolynomial1D; 2072 \end{verbatim} 2073 2074 \begin{verbatim} 2075 /** Two-dimensional polynomial */ 2076 typedef struct { 2077 int nX, nY; ///< Number of terms in x and y 2078 float *restrict *restrict coeff; ///< Coefficients 2079 float *restrict *restrict coeffErr; ///< Error in coefficients 2080 char *restrict *restrict mask; ///< Coefficients mask 2081 } psPolynomial2D; 2082 \end{verbatim} 2083 2084 etc., up to four dimensions. We also define double-precision versions: 2085 2086 \begin{verbatim} 2087 /** Double-precision one-dimensional polynomial */ 2088 typedef struct { 2089 int n; ///< Number of terms 2090 double *restrict coeff; ///< Coefficients 2091 double *restrict coeffErr; ///< Error in coefficients 2092 char *restrict mask; ///< Coefficient mask 2093 } psDPolynomial1D; 2094 \end{verbatim} 2095 2096 \begin{verbatim} 2097 /** Double-precision two-dimensional polynomial */ 2098 typedef struct { 2099 int nX, nY; ///< Number of terms in x and y 2100 double *restrict *restrict coeff; ///< Coefficients 2101 double *restrict *restrict coeffErr; ///< Error in coefficients 2102 char *restrict *restrict mask; ///< Coefficients mask 2103 } psDPolynomial2D; 2104 \end{verbatim} 2105 2106 etc. In what follows, we only show the version for double-precision 2107 two-dimensionals; the others may be inferred following the standard 2108 naming convention exampled above. 2109 2110 The constructor and destructor are: 2111 \begin{verbatim} 2112 psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY); 2113 void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly); 2114 \end{verbatim} 2115 where \code{nX} and \code{nY} are the number of terms in x and y 2116 respectively. 2117 2118 To evaluate the polynomials at specific coordinates, we define: 2119 \begin{verbatim} 2120 double psEvalDPolynomial2D(double x, double y, const psDPolynomial2D *restrict myPoly); 2121 \end{verbatim} 2122 2123 \tbd{Generate a vector of random Gaussian deviates} 2124 2125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2126 2127 \subsection{Minimization and fitting routines} 2128 2129 \tbd{I am concerned the minimization functions defined here are 2130 missing details - gene} 2131 2132 We require a general minimization routine, a routine that will 2133 specifically minimize $\chi^2$ given a list of data with associated 2134 errors, and a function that will analytically determine the best 2135 polynomial fit by minimizing $\chi^2$. 2136 2137 First, we define \code{psMinimize}, which returns the vector which 2138 minimizes the specified function, which is itself a function of a 2139 single vector. The returned vector must be the same length as the 2140 vector argument to the input function. 2141 \begin{verbatim} 2142 psVector *psMinimize(psVector *restrict initialGuess, 2143 float (*myFunction)(const psVector *restrict), 2144 float (*myFuncDeriv)(const psVector *restrict), 2145 const psVector *restrict paramMask); 2146 \end{verbatim} 2147 2148 \code{psMinimize} determines and returns the vector that minimizes the 2149 specified function. It takes as input a function, \code{myFunction}, 2150 an initial guess for the vector that minimizes the function, 2151 \code{initialGuess}, and an optional mask for the vector elements 2152 (function parameters) to minimize, \code{paramMask} (all parameters 2153 are fit if \code{NULL}). Note that \code{paramMask} must be of type 2154 \code{psU8}, while \tbd{what are valid types for the function 2155 parameter lists?}. The optional function, \code{myFuncDeriv} returns 2156 the derivative of the function. \tbd{is this sufficient? clear?} 2157 2158 \begin{verbatim} 2159 psVector *psMinimizeChi2(psVector *restrict initialGuess, 2160 float (*evalModel)(const psVector *restrict, const psVector *restrict), 2161 const psVector *restrict domain, 2162 const psVector *restrict data, 2163 const psVector *restrict errors, 2164 const psVector *restrict paramMask); 2165 \end{verbatim} 2166 \code{psMinimizeChi2} fits a model to observations by minimizing 2167 $\chi^2$, returing the best-fit parameters. The input parameters are 2168 a function that evaluates the model for a specified domain, given the 2169 parameters, \code{evalModel}; a list of observations, (\code{domain}, 2170 \code{data}, and \code{errors}); an initial guess at the best-fit 2171 parameters, \code{initialGuess} which is returned with the best-fit 2172 parameters \tbd{how? unclear!}, and an optional mask specifying which 2173 parameters are to be fit, \code{paramMask}, which must be of type 2174 \code{psU8}. All parameters are fit if this vector is \code{NULL}. 2175 2176 \begin{verbatim} 2177 psPolynomial1D *psGetArrayPolynomial(psPolynomial1D myPoly, 2178 const psVector *restrict x, 2179 const psVector *restrict y, 2180 const psVector *restrict yErr); 2181 \end{verbatim} 2182 \code{psGetArrayPolynomial} returns the polynomial that best fits the 2183 observations. The input parameters are a polynomial that specifies 2184 the fit order, \code{myPoly}, which will be altered and returned with 2185 the best-fit coefficients; and the observations, \code{x}, \code{y} 2186 and \code{yErr}. The independent variable list, \code{x} may be 2187 \code{NULL}, in which case the vector index is used. The dependent 2188 variable error, \code{yErr} may be null, in which case the solution is 2189 determined in the assumption that all data errors are equal. 2190 \tbd{valid types?} 2191 2192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2193 2194 \subsection{Image Operations} 2195 2196 \subsubsection{Image Structure Manipulation} 2197 2198 We require a variety of functions to manipulate these image 2199 structures, including creation, destruction, input, output, and 2200 various manipulations of the pixels. The required functions are 2201 listed below, and fall into several categories. 2202 2203 Define a subimage of the specified area of the given image. This 2204 function must return an error if the requested subset area lies 2205 outside of the parent image. 2206 \begin{verbatim} 2207 psImage *psImageSubset(const psImage *image, int nx, int ny, int x0, int y0); 2208 \end{verbatim} 2209 where \code{image} is the parent image, \code{nx,ny} specify the 2210 dimensions of the desired subraster, and \code{x0, y0} specify the 2211 starting pixel of the subraster. The entire subraster must be 2212 contained within the raster of the parent image. Note that the 2213 \code{refCounter} for the parent should be incremented. This function 2214 must be defined for the following types: \code{psU8}, \code{psU16}, 2215 \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, 2216 \code{psC64}. 2217 2218 Create a copy of the specified image, converting the type in the 2219 process. If the output target pointer is not NULL, place the result 2220 in the specified structure. The output image data must be allocated 2221 as a single, contiguous block of memory. The output image may not be 2222 the input image. This function must be defined for the following 2223 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2224 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2225 \begin{verbatim} 2226 psImage *psImageCopy(psImage *output, const psImage *input, psElemType type); 2227 \end{verbatim} 2228 2229 \subsubsection{Image Pixel Extractions} 2230 2231 Extract pixels from rectlinear region to a vector (array of floats). 2232 The output vector contains either \code{nx} or \code{ny} elements, 2233 based on the value of the direction: e.g., if \code{direction} is 2234 \tbd{+x}, there are \code{nx} elements. The input region is collapsed 2235 in the perpendicular direction, and each element of the output vectors 2236 is derived from the statistics of the pixels at that direction 2237 coordinate. The statistic used to derive the output vector value is 2238 specified by \code{stats}. This function must be defined for the 2239 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2240 \begin{verbatim} 2241 psVector *psImageSlice(psVector *out, const psImage *input, int x, int y, int nx, int ny, 2242 int direction, const psStats *stats); 2243 \end{verbatim} 2244 2245 Extract pixels from an image along a line to a vector (array of 2246 floats). The vector \code{(xs,ys)} - \code{(xe,ye)} forms the basis of 2247 the output vector. Pixels are considered in a rectangular region of 2248 width \code{dw} about this vector. The input region is collapsed in 2249 the perpendicular direction, and each element of the output vector 2250 represents pixel-sized boxes, where the value is derived from the 2251 statistics of the pixels interpolated along the perpendicular 2252 direction. The statistic used to derive the output vector value is 2253 specified by \code{stats}. This function must be defined for the 2254 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64} 2255 \begin{verbatim} 2256 psVector *psImageCut(psVector *out, const psImage *input, float xs, float ys, float xe, float ye, 2257 float dw, const psStats *stats); 2258 \end{verbatim} 2259 2260 Extract radial annuli data to a vector. A vector is constructed where 2261 each vector elements is derived from the statistics of the pixels 2262 which land in one of a sequence of annuli. The annuli are centered on 2263 the image pixel coordinate \code{x,y}, and have width \code{dr}. The 2264 number of annuli is $radius / dr$. The statistic used to derive the 2265 output vector value is specified by \code{stats}. This function must be defined for the 2266 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2267 \begin{verbatim} 2268 psVector *psImageRadialCut(psVector *out, const psImage *input, float x, float y, 2269 const psVector *radii, const psStats *stats); 2270 \end{verbatim} 2271 2272 \subsubsection{Image Geometry Manipulation} 2273 2274 Rebin image to new scale. A new image is constructed in which the 2275 dimensions are reduced by a factor of \code{scale} $\le 1$ (it is an 2276 error for \code{scale} $> 1$). The \code{scale} is equal in each 2277 dimension. The output image is generated from all input image pixels. 2278 Each pixel in the output image is derived from the statistics of the 2279 corresponding set of input image pixels based on the statistics 2280 specified by \code{stats}. This function must be defined for the following 2281 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2282 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2283 \begin{verbatim} 2284 psImage *psImageRebin(psImage *out, const psImage *input, float scale, const psStats *stats); 2285 \end{verbatim} 2286 2287 Rotate the input image by given angle, specified in degrees. The 2288 output image must contain all of the pixels from the input image in 2289 their new frame. Pixels in the output image which do not map to input 2290 pixels should be set to \tbd{value}. The center of rotation is always 2291 the center pixel of the image. The rotation is specified in the sense 2292 that a positive angle is an anti-clockwise rotation. This function must be defined for the following 2293 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2294 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2295 \begin{verbatim} 2296 psImage *psImageRotate(psImage *out, const psImage *input, float angle); 2297 \end{verbatim} 2298 2299 Shift image by an arbitrary number of pixels (\code{dx,dy}) in either 2300 direction. If the shift values are fractional, the output pixel 2301 values should interpolate between the input pixel values. The output 2302 image has the same dimensions as the input image. Pixels which fall 2303 off the edge of the output image are lost. Newly exposed pixels are 2304 set to the value given by \code{exposed}. This function must be defined for the following 2305 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2306 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2307 \begin{verbatim} 2308 psImage *psImageShift(psImage *out, const psImage *input, float dx, float dy, float exposed); 2309 \end{verbatim} 2310 2311 Roll image by an integer number of pixels (\code{dx,dy}) in either 2312 direction. The output image is the same dimensions as the input 2313 image. Edge pixels wrap to the other side (no values are lost). This function must be defined for the following 2314 types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2315 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2316 \begin{verbatim} 2317 psImage *psImageRoll(psImage *out, const psImage *input, int dx, int dy); 2318 \end{verbatim} 2319 2320 \subsubsection{Image Statistical Functions} 2321 2322 Determine statistics for image (or subimage). The statistics to be 2323 determined are specified by \code{stats}. This function must be defined for the 2324 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2325 \begin{verbatim} 2326 psStats *psImageGetStats(psStats *stats, const psImage *input); 2327 \end{verbatim} 2328 2329 Construct a histogram from an image (or subimage). The histogram to 2330 generate is specified by \code{psHistogram hist} (see 2331 section~\ref{sec:histograms}). This function must be defined for the 2332 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2333 \begin{verbatim} 2334 psHistogram *psImageHistogram(psHistogram *hist, const psImage *input); 2335 \end{verbatim} 2336 2337 Fit a 2-D Chebychev polynomial surface to an image. The input 2338 structure \code{coeffs} contains the desired order and terms of 2339 interest. This function must be defined for the 2340 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2341 \begin{verbatim} 2342 psPolynomial2D *psImageFitPolynomial(psPolynomial2D *coeffs, const psImage *input); 2343 \end{verbatim} 2344 2345 Evaluate a 2-D polynomial surface for the image pixels. Given the 2346 input polynomial coefficients, set the image pixel values on the basis 2347 of the polynomial function. This function must be defined for the 2348 following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}. 2349 \begin{verbatim} 2350 psImage *psImageEvalPolynomial(psImage *input, const psPolynomial2D *coeffs); 2351 \end{verbatim} 2352 2353 \subsubsection{Image I/O Functions} 2354 2355 Read an image or subimage from a named file. This function is a 2356 wrapper to the FITS library function. The input parameters allow a 2357 full image or a subimage to be read. The starting pixel of the region 2358 is specified by \code{x,y}, while the dimensions of the requested 2359 region are specified by \code{nx,ny}. A negative value of -1 for 2360 these two parameters specifies the full array of the requested image, 2361 less absolute value of the variable. If the native image is a cube, 2362 the value of z specifies the requested slice of the image. The data 2363 is read from the extension specified by extname (matching the EXTNAME 2364 keyword) or by the extnum value (with 0 representing the PHU, 1 the 2365 first extension, etc). This function must call \code{psError} and 2366 return \code{NULL} if any of the specified parameters are out of range 2367 for the data in the image file, if the specified image file does not 2368 exist, or the image on disk is zero- or one-dimensional. 2369 \begin{verbatim} 2370 psImage *psImageReadSection(psImage *output, int x0, int y0, int nx, int ny, int z, 2371 const char *extname, int extnum, const char *filename); 2372 \end{verbatim} 2373 2374 Read an image or subimage from file descriptor. The input parameters 2375 and their behavior for this function are identical with those in 2376 \code{psImageReadSection}. 2377 \begin{verbatim} 2378 psImage *psImageFReadSection(psImage *output, int x, int y, int nx, int ny, int z, 2379 const char *extname, int extnum, FILE *f); 2380 \end{verbatim} 2381 \tbd{The use of \code{FILE*} to carry around the file descriptor is to be reviewed.} 2382 2383 Write an image section to the named file, which may exist. This 2384 operation may write a portion of an image over the existing bytes of 2385 an existing image. If the file does not exist, it should be created. 2386 If the specified extension does not exist, it should be created. If 2387 an extension is specified and no PHU exists, a basic PHU should be 2388 created. 2389 \begin{verbatim} 2390 psImage *psImageWriteSection(const psImage *input, int x, int y, int z, 2391 const char *extname, int extnum, const char *filename); 2392 \end{verbatim} 2393 2394 Write an image section to file descriptor as above: 2395 \begin{verbatim} 2396 psImage *psImageFWriteSection(const psImage *input, int x, int y, int z, 2397 const char *extname, int extnum, FILE *f); 2398 \end{verbatim} 2399 \tbd{The use of \code{FILE*} to carry around the file descriptor is to be reviewed.} 2400 2401 Read header data from a FITS image file into a \code{psMetaData} 2402 structure (see section~\ref{sec:metadata}. The \code{extname} and 2403 \code{extnum} parameters specify the extension of interest as above. 2404 If the named extension does not exist, the function should return an 2405 error. 2406 \begin{verbatim} 2407 psMetadata *psImageReadHeader(psMetadata *output, const char *extname, int extnum, const char *filename); 2408 \end{verbatim} 2409 2410 Read header data from a FITS image file descriptor into a 2411 \code{psMetaData} structure. 2412 \begin{verbatim} 2413 psMetadata *psImageFReadHeader(psMetadata *output, const char *extname, int extnum, FILE *f); 2414 \end{verbatim} 2415 2416 \subsubsection{Image Pixel Manipulations} 2417 2418 Clip image values outside of range to given values. All pixels with 2419 values \code{< min} are set to the value \code{vmin}. All pixels with 2420 values \code{> max} are set to the value \code{vmax}. Returns the 2421 number of clipped pixels. This function must be defined for the 2422 following types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16}, 2423 \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2424 \begin{verbatim} 2425 int psImageClip(psImage *input, float min, float vmin, float max, float vmax); 2426 \end{verbatim} 2427 2428 Clip \code{NaN} image pixels to given value. Pixels with \code{NaN}, 2429 \code{+Inf} or \code{-Inf} values are set to the specified value. 2430 Returns the number of clipped pixels. This function must be defined 2431 for the following types: \code{psU8}, \code{psU16}, \code{psS8}, 2432 \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}. 2433 \begin{verbatim} 2434 int psImageClipNaN(psImage *input, float value); 2435 \end{verbatim} 2436 2437 Overlay subregion of image with another image. Replace the pixels in 2438 the \code{image} which correspond to the pixels in \code{overlay} with 2439 values derived from the values in \code{image} and \code{overlay} 2440 based on the given operator \code{op}. Valid operators are \code{=} 2441 (set image value to overlay value), \code{+} (add overlay value to 2442 image value), \code{-} (subtract overlay from image), \code{*} 2443 (multiply overlay times image), \code{/} (divide image by overlay). 2444 This function must be defined for the following types: \code{psU8}, 2445 \code{psU16}, \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, 2446 \code{psC32}, \code{psC64}. 2447 \begin{verbatim} 2448 int psImageOverlaySection(psImage *image, const psImage *overlay, int x0, int y0, const char *op); 2449 \end{verbatim} 2450 2451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2452 2453 \subsection{Vector and Image Arithmetic} 2454 \label{sec:arithmetic} 2455 2456 We will need to be able to perform various operations on vectors and 2457 images, e.g.\ dividing one image by another, subtracting a vector 2458 from an image, etc. Both binary operations and unary operations are 2459 required. To avoid the burden of memorizing a ton of APIs, we specify 2460 two generic APIs for the binary and unary operations. 2461 2462 \begin{verbatim} 2463 psType *psBinaryOp (void *out, void *in1, char *op, void *in2); 2464 psType *psUnaryOp (void *out, void *in, char *op); 2465 \end{verbatim} 2466 These functions determine the type of the operands on the basis of 2467 their \code{psType} elements, which always are the first elements. 2468 Note that these functions return a pointer to the appropriate type for 2469 the operation. Since the result may is cast to \code{psType}, the 2470 resulting type may be determined by examining the return value. It is 2471 expected that the implementation of these functions will employ 2472 pre-processor macros to perform the onerous task of creating the 2473 loops. Also note that \code{psVector} is equivalent to 2474 \code{psVector}. An attempt to perform an arithmetic operation on 2475 an object of dimension \code{PS_DIMEN_OTHER} should produce an error. 2476 2477 Binary operations between an image and a vector have a potential 2478 ambiguity --- do the vector elements correspond to the rows or the 2479 columns? For this reason, we define two vector types: a ``vector'' 2480 (\code{PS_DIMEN_VECTOR}), and a ``transposed vector'' 2481 (\code{PS_DIMEN_TRANSV}). We specify that a ``vector'', when involved 2482 in binary operations on an image, acts on the rows, while a 2483 ``transposed vector'' in the same context acts on the columns. 2484 Vectors, when created, will be created as ``vectors'', but may be 2485 converted to ``transposed vectors'' using the following function: 2486 2487 \begin{verbatim} 2488 /** Transpose a vector. Changes the type to a PS_DIMEN_TRANSV */ 2489 psVector *psVectorTranspose(psVector *out, //!< Output vector, or NULL 2490 psVector *myVector //!< Vector to be transposed 2491 ); 2492 \end{verbatim} 2493 2494 It is further desirable to allow scalar values to be used within these 2495 functions, which requires the following additions: 2496 2497 \begin{verbatim} 2498 /** create a psType-ed structure from a constant value. */ 2499 p_ps_Scalar * 2500 psScalar (double value); 2501 \end{verbatim} 2502 2503 \begin{verbatim} 2504 /** create a psType-ed structure from a specified type */ 2505 p_ps_Scalar * 2506 psScalarType (char *mode, ///< type description 2507 ... ///< value (or values) of specified types 2508 ); 2509 \end{verbatim} 2510 2511 \begin{verbatim} 2512 /** private structure used to pass constant values into the math operators. */ 2513 typedef struct { 2514 psType type; ///< data type information 2515 union { 2516 int i; ///< integer value entry 2517 float f; ///< float value entry 2518 double d; ///< double value entry 2519 complex float c; ///< complex value entry 2520 } val; 2521 } p_psScalar; 2522 \end{verbatim} 2523 2524 This allows one to write the following to take the sine of the square 2525 of all pixels in an image: 2526 \begin{verbatim} 2527 psImage A,B; 2528 2529 B = psBinaryOp (NULL, A, "^", psScalar(2)); 2530 (void) psUnaryOp(B, B, "sin"); 2531 \end{verbatim} 2532 2533 Note that the \code{psUnaryOp} is performed on \code{B} in-place. 2382 psImage *psImagePowerSpectrum(const psImage *in); 2383 \end{verbatim} 2534 2384 2535 2385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 2561 2411 \subsection{Dates and times} 2562 2412 2563 \textbf{[May be deferred.]} 2413 We require a collection of functions to manipulate time data. These 2414 operations primarily consist of conversions between specific time 2415 formats. PSLib wraps the libTAI structure \code{taia} for use as the 2416 native time format. 2417 \begin{verbatim} 2418 typedef struct { 2419 struct taia t; 2420 } psTime; 2421 \end{verbatim} 2422 2423 Two utility functions provide the current time in two formats, MJD 2424 (modified Julian day) and the Sidereal time. 2425 2426 \begin{verbatim} 2427 psTime psGetMJD(void); 2428 psTime psGetSidereal(float mjd, float longitude); 2429 \end{verbatim} 2430 2431 A collection of functions convert from the native \code{psTime} format 2432 to various external formats. Note that ISO Time is represented by 2433 YYYY/MM/DD,HH:MM:SS.SSS. 2434 \begin{verbatim} 2435 char *psTimeToISOTime (psTime time); 2436 double psTimeToUTC (psTime time); 2437 double psTimeToMJD (psTime time); 2438 double psTimeToJD (psTime time); 2439 struct timeval *psTimeToTimeval (psTime time); 2440 struct tm *psTimeToTm (psTime time); 2441 \end{verbatim} 2442 2443 A matching set of functions convert from the external formats to the 2444 native \code{psTime}: 2445 \begin{verbatim} 2446 psTime *psISOTimeToTime (char *input); 2447 psTime *psUTCToTime (double input); 2448 psTime *psMJDToTime (double input); 2449 psTime *psJDToTime (double input); 2450 psTime *psTimevalToTime (struct timeval *input); 2451 psTime *psTMtoTime (struct tm *input); 2452 \end{verbatim} 2564 2453 2565 2454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 2618 2507 readable and it may slow down the access. 2619 2508 2620 We propose an intermediate solution to this problem. We specify a 2621 flexible, generic metadata container and access methods. Data types2622 which require a ccess toa general collection of metadata should2509 PSLib implements an intermediate solution to this problem. We specify 2510 a flexible, generic metadata container and access methods. Data types 2511 which require association with a general collection of metadata should 2623 2512 include an entry of this metadata type. However, a subset of metadata 2624 2513 concepts which are basic and frequently required may be placed in the 2625 2514 coded structure elements. This approach allows the code to refer to 2626 2515 the basic metadata concepts as part of the data structure (ie, 2627 image.nx), but also allows us to provide access to any arbitrary 2628 metadata which may be generated. As a practical matter, the choice of 2629 which entries are only in the metadata and which are part of the 2630 explicit structure elements is rather subjective. Any data elements 2631 which are frequently used should be put in the structure; those which 2632 are only infrequently needed should be left in the generic metadata. 2516 \code{image.nx}), but also allows us to provide access to any 2517 arbitrary metadata which may be generated. As a practical matter, the 2518 choice of which entries are only in the metadata and which are part of 2519 the explicit structure elements is rather subjective. Any data 2520 elements which are frequently used should be put in the structure; 2521 those which are only infrequently needed should be left in the generic 2522 metadata. 2633 2523 2634 2524 There are some points of caution which must be noted. Any 2635 2525 manipulation of the data should be reflected in the metadata where 2636 2526 appropriate. This is always an issue of concern. For example, 2637 consider an image of dimensions \code{n X, nY}. If a function extracts2638 a subraster, it must change the values of \code{n X, nY} to match the2527 consider an image of dimensions \code{nx, ny}. If a function extracts 2528 a subraster, it must change the values of \code{nx, ny} to match the 2639 2529 new dimensions. What should it do to the corresponding metadata? 2640 2530 Clearly, it should change the corresponding value which defines … … 2644 2534 copy of the metadata which may be shared by other representations of 2645 2535 the image? These must be treated differently because the change would 2646 invalidate those other references. 2536 invalidate those other references. Care must be taken, therefore, 2537 when writing functions which operate on the data to consider all of 2538 the relevant metadata entries which must also be updated. 2647 2539 2648 2540 A related issue is the definition of metadata names. Entries in a … … 2665 2557 \subsubsection{Metadata Representation} 2666 2558 2667 \tbd{descriptions in this section need to be clarified}2668 2669 2559 This section addresses the question of how \PS{} metadata should be 2670 represented in memory. We do not (yet) address how it should be 2671 represented on disk. 2672 2673 We propose that an item of metadata be represented as a C structure with at least the following 2674 fields: 2675 \begin{verbatim} 2676 /** A struct to define a single item of metadata */ 2560 represented in memory, not how it should be represented on disk. 2561 2562 We define an item of metadata with the following structure: 2563 \begin{verbatim} 2677 2564 typedef struct { 2678 2565 const int id; ///< unique ID for this item … … 2681 2568 psMetadataFlags flags; ///< flags associated with this item 2682 2569 const union { 2683 double d; ///< doublevalue2684 float f;///< floating value2685 int i; ///< integervalue2686 void *v ;///< other type2687 } val;///< value of metadata2570 psS32 S32; ///< integer value 2571 psF32 F32; ///< floating value 2572 psF64 F64; ///< double value 2573 void *void; ///< other type 2574 } data; ///< value of metadata 2688 2575 char *comment; ///< optional comment ("", not NULL) 2689 2576 psDlist *restrict items; ///< list of psMetadataItems with the same name … … 2691 2578 \end{verbatim} 2692 2579 2693 The \code{id} is a unique identifier for this item of metadata; experience 2694 shows that such tags are useful. 2695 2696 The \code{psMetadataType type} entry specifies the type of the data 2697 being represented; the possibilities are listed in section \ref{metadataTypes}. 2698 2699 \paragraph{Possible Types of Metadata} 2700 \label{metadataTypes} 2701 2702 The possible types of metadata are identified by the enumerated type 2703 \code{psMetadataType} (see also table \ref{tabMetaDataTypes}); the initial defined values are: 2704 \begin{verbatim} 2705 /** Possible types of metadata. */ 2580 The \code{id} is a unique identifier for this item of metadata; 2581 experience shows that such tags are useful. The entry \code{name} 2582 specifies the name of the metadata item. Metadata naming conventions 2583 for the Pan-STARRS IPP are specified in the IPP Software Requirements 2584 Specification (PSDC-430-005). The value of the metadata is given by 2585 the union \code{data}, and may be of type \code{psS32}, \code{psF32}, 2586 \code{psF64}, or an arbitrary rich structure pointed at by the 2587 \code{void} pointer \code{void}. A character string comment 2588 associated with this metadata item may be stored in the element 2589 \code{comment}. The \code{type} entry specifies the type of the data 2590 being represented, given by the enumerated type \code{psMetadataType}: 2591 \begin{verbatim} 2706 2592 typedef enum { ///< type of val is: 2707 2593 PS_META_ITEM_SET = 0, ///< NULL; metadata is in psMetadataType.items 2708 PS_META_FLOAT, ///< float (.f) 2709 PS_META_INT, ///< int (.i) 2710 PS_META_STR, ///< string (.v) 2711 PS_META_IMG, ///< image (.v) 2712 PS_META_JPEG, ///< JPEG (.v) 2713 PS_META_PNG, ///< PNG (.v) 2714 PS_META_ASTROM, ///< astrometric coefficients (.v) 2715 PS_META_UNKNOWN, ///< other (.v) 2594 PS_META_S32, ///< int (.S32) 2595 PS_META_F32, ///< float (.F32) 2596 PS_META_F64, ///< double (.F64) 2597 PS_META_STR, ///< string (.void) 2598 PS_META_IMG, ///< image (.void) 2599 PS_META_JPEG, ///< JPEG (.void) 2600 PS_META_PNG, ///< PNG (.void) 2601 PS_META_ASTROM, ///< astrometric coefficients (.void) 2602 PS_META_UNKNOWN, ///< other (.void) 2716 2603 PS_META_NTYPE ///< Number of types; must be last 2717 2604 } psMetadataType; 2718 2605 \end{verbatim} 2719 2720 \begin{table} 2721 \begin{tabular}{llll} 2722 \textbf{Value} & \textbf{Type} & \textbf{member of union} & \textbf{Comments}\\ 2723 \hline 2724 \code{PS_META_FLOAT} & float & f & value, not pointer, is stored \\ 2725 \code{PS_META_INT} & int & i & value, not pointer, is stored \\ 2726 \code{PS_META_STR} & string & v & value, not pointer to original, is stored \\ 2727 \code{PS_META_IMG} & psImage & v & \\ 2728 \code{PS_META_JPEG} & JPEG & v & \\ 2729 \code{PS_META_PNG} & PNG & v & \\ 2730 \code{PS_META_ASTROM} & psAstrom & v & \\ 2731 \code{PS_META_UNKNOWN} & other & v & \\ 2732 \code{PS_META_NTYPE} & (none) & & The number of types defined 2733 \end{tabular} 2734 \begin{caption}{Supported Metadata Types} 2735 \label{tabMetaDataTypes} 2736 Possible types of metadata 2737 \end{caption} 2738 \end{table} 2739 2740 \subsubsection{Collections of Metadata} 2741 2742 \begin{verbatim} 2743 /** A set of metadata */ 2606 The \code{flags} entry specifies some optional characteristics of the 2607 metadata type, given by the enumerated type \code{psMetadataFlags}: 2608 \begin{verbatim} 2609 typedef enum { 2610 PS_META_TYPE_MASK = 0xffff, ///< the type enum must fit in this mask 2611 PS_META_UNIQUE = 0x10000, ///< the name must be unique (default) 2612 PS_META_NON_UNIQUE = 0x20000, ///< the name may be repeated 2613 } psMetadataFlags; 2614 \end{verbatim} 2615 2616 A collection of metadata is represented by the \code{psMetadata} structure: 2617 \begin{verbatim} 2744 2618 typedef struct { 2745 2619 psDlist *restrict list; ///< list of psMetadataItem … … 2747 2621 } psMetadata; 2748 2622 \end{verbatim} 2749 2750 2623 The type \code{psMetadata} is a container class for metadata. Note 2751 2624 that there are in fact \emph{two} representations of the metadata … … 2756 2629 second representation employs a hash table which allows fast look-up 2757 2630 given a specific metadata keyword. 2631 2632 Certain metadata names (such as the FITS keywords \code{COMMENT} and 2633 \code{HISTORY} in a FITS header) may be repeated with different 2634 values. The \code{psMetadataAppend} routine is required to check that 2635 all metadata names are unique unless the type is qualified as 2636 \code{PS_META_NON_UNIQUE}; in this case a unique integer must be added 2637 to each name specified. 2638 2639 \subsubsection{Metadata APIs} 2640 2641 In this section, we explain the metadata APIs more fully. 2642 2643 The allocator for \code{psMetadataItem} returns a full 2644 \code{psMetadataItem} ready for insertion into the \code{psMetadata}. 2645 The \code{name} entry specifies the name to use for this metadata 2646 item, and may include \code{sprintf}-stype formating codes. The 2647 \code{format} entry, which specifies both the metadata type and the 2648 optional flags, is constructed by bit-wise or'ing the appropriate type 2649 and flag. The \code{comment} entry is a fixed string which is used 2650 for the comment associated with this metadata item. The arguments to 2651 the \code{name} formatting codes and the metadata data itself are 2652 passed to \code{psMetadataItemAlloc} as arguments following the 2653 comment string. The data must be a pointer for any data types which 2654 are stored in the element \code{data.void}, while other data types are 2655 passed as numeric values. The argument list must be interpreted 2656 appropriately by the \code{va_list} operators in the function. 2657 \begin{verbatim} 2658 psMetadataItem *psMetadataItemAlloc(const char *name, int format, const char *comment, ...); 2659 psMetadataItem *psMetadataItemAllocV(const char *name, int format, const char *comment, va_list list); 2660 \end{verbatim} 2661 2662 The \code{psMetadataItem} destructor is specified below. Note that 2663 the destructor for \code{psMetadataItem} must call the appropriate 2664 destructor for the \code{val} (recall that it is the duty of the 2665 \code{psMyTypeFree}s to decrement the \code{refCounter} and free the 2666 memory if and only if the \code{refCounter == 1} --- see 2667 \S\ref{sec:free}). 2668 \begin{verbatim} 2669 void psMetadataItemFree(psMetadataItem *item); 2670 \end{verbatim} 2671 2672 The constructor for the collection of metadata, \code{psMetadata}, 2673 simply returns an empty metadata container (employing the constructors 2674 for the doubly-linked list and hash table). The destructor needs to 2675 free each of the \code{psMetadataItem}s using \code{psMetadataItemFree}. 2676 \begin{verbatim} 2677 psMetadata *psMetadataAlloc(void); 2678 void psMetadataFree(psMetadata *md); 2679 \end{verbatim} 2680 2681 Items may be added to the metadata in one of two ways --- firstly, an 2682 item may be added by appending a \code{psMetadataItem} which has 2683 already been created; and secondly by directly providing the data to 2684 be appended. In both cases, the \code{psMetadataItem} that is 2685 appended to the metadata is returned. The second function, 2686 \code{psMetadataAppend} takes a pointer or value which is interpretted 2687 by the \code{va_list} operators in the function. 2688 % 2689 \begin{verbatim} 2690 psMetadataItem *psMetadataAppendItem(psMetadata *restrict md, 2691 psMetadataItem *restrict item); 2692 psMetadataItem *psMetadataAppend(psMetadata *restrict md, const char *name, 2693 int format, const char *comment, ...); 2694 \end{verbatim} 2695 2696 Items may be removed from the metadata by specifying a key. If the 2697 key matches a metadata item, the item is removed from the metadata and 2698 returned; otherwise, \code{NULL} is returned. If the key is not 2699 unique, then \emph{all} items corresponding to the key are removed, 2700 and the first item is returned. Care should be taken not to leak 2701 memory when appending an item for which the key already exists in the 2702 metadata (and is not \code{PS_META_NON_UNIQUE}). 2703 % 2704 \begin{verbatim} 2705 psMetadataItem *psMetadataRemove(psMetadata *restrict md, const char *restrict key); 2706 \end{verbatim} 2707 2708 The metadata may be iterated over by (re-)setting the iterator for the 2709 appropriate \code{psMetadata}, and getting the next item. 2710 \code{psMetadataGetNext} has the ability to match the beginning of a 2711 key, e.g., if the user only wants to iterate through 2712 \code{IPP.machines.sky} and doesn't want to bother with 2713 \code{IPP.machines.detector}. The iterator should iterate over every 2714 item of metadata --- even those that are non-unique. 2715 \begin{verbatim} 2716 void psMetadataSetIterator(psMetadata *md); 2717 psMetadataItem *psMetadataGetNext(psMetadata *restrict md, const char *restrict match); 2718 \end{verbatim} 2719 2720 Items may be found within the metadata by providing a key. In the 2721 event that the key is non-unique, the first item is returned. 2722 \begin{verbatim} 2723 psMetadataItem *psMetadataLookup(const psMetadata *restrict md, 2724 const char *restrict key); 2725 \end{verbatim} 2726 2727 Metadata items may be printed to an open file descriptor, optionally 2728 pre-pending a specified string. 2729 \begin{verbatim} 2730 void psMetadataItemPrint(FILE *fd, const psMetadataItem *restrict md, 2731 const char *prefix); 2732 \end{verbatim} 2733 2734 \begin{verbatim} 2735 psMetadata *psMetadataReadHeader(psMetadata *output, const char *extname, 2736 int extnum, const char *filename); 2737 \end{verbatim} 2738 Read header data from a FITS image file into a \code{psMetadata} 2739 structure (see section~\ref{sec:metadata}. The \code{extname} and 2740 \code{extnum} parameters specify the extension of interest as above. 2741 If the named extension does not exist, the function should return an 2742 error. 2743 2744 \begin{verbatim} 2745 psMetadata *psMetadataFReadHeader(psMetadata *output, const char *extname, 2746 int extnum, FILE *f); 2747 \end{verbatim} 2748 Read header data from a FITS image file descriptor into a 2749 \code{psMetadata} structure. 2750 2751 \subsection{Detector and sky positions} 2752 2753 Both detector and sky positions will be used extensively in the IPP. 2754 The first are linear coordinates which conform to Euclidean geometry 2755 while the second are angular coordinates for which additional care 2756 must often be taken. We put these into two structures, \code{psPlane} 2757 and \code{psSphere}, respectively. Partitioning these two will enable 2758 error-checking. 2759 % 2760 \begin{verbatim} 2761 typedef struct { 2762 double x; ///< x position 2763 double y; ///< y position 2764 double xErr; ///< Error in x position 2765 double yErr; ///< Error in y position 2766 } psPlane; 2767 2768 typedef struct { 2769 double r; ///< RA 2770 double d; ///< Dec 2771 double rErr; ///< Error in RA 2772 double dErr; ///< Error in Dec 2773 } psSphere; 2774 \end{verbatim} 2775 2776 Three major classes of coordinate transformations are necessary. 2777 First, linear coordinates from one frame must be converted to linear 2778 coordinates in a different frame of references. Simple transformations 2779 of this type are independent of other quantities of the positions -- 2780 they are simply mapping between two linear spaces. In practice, these 2781 transformations may often be a function of the magnitude or color of 2782 the imaged object. The second type of conversion is the 2783 transformation of linear coordinates to angular coordinates and 2784 vice-versa. This conversion depends on the desired projection, and 2785 may represent the real mapping performed by the telescope or may 2786 simply represent a convenient mechanism to display 3D coordinates in 2787 useful forms. The third conversion of interest is the transformation 2788 of one set of spherical coordinates to another set. Frequently in 2789 astronomy, these conversions consist only of rotations between the two 2790 spherical coordinates systems, where the coordinates of the pole and 2791 equatorial rotation between the two systems define the 2792 transformation. Conversions between standard coordinate systems such 2793 as Galactic, Ecliptic, and various epochs of the Celestial coordinates 2794 are represented by these spherical transformations. 2795 2796 \subsubsection{Linear Coordinate Transformations} 2797 2798 We specify two types of transforms between coordinate systems. The 2799 first consists simply of two 2D polynomials to transform both 2800 components -- the output coordinates depend only on the input 2801 coordinates and no other quantities of objects at those coordinates. 2802 The second consists of two 4D polynomials in which the output 2803 coordinates are also specified to be a function of the magnitude and 2804 color of the object with the given coordinates. This type of 2805 coordinate transformation is necessary to represent the 2806 (color-dependent) optical distortions caused by the atmosphere and 2807 camera optics, and the possibly effects of charge transfer 2808 inefficiency. We specify two structures to represent the coefficients 2809 of these transformations: 2810 2811 \begin{verbatim} 2812 typedef struct { 2813 psDPolynomial2D *x; 2814 psDPolynomial2D *y; 2815 } psPlaneTransform; 2816 \end{verbatim} 2817 2818 The \code{psDPolynomial2D} structures represent polynomials of 2819 arbitrary order as a function of two dimensions. There is one of 2820 these structures for each of the two output dimensions. As an 2821 example, consider the simple transformation from one linear coordinate 2822 frame ($x,y$), e.g., on a CCD, to a second frame ($p,q$), e.g., on a 2823 chip. If we have only first order terms in the transformation 2824 \code{psPlaneTransform T}, the new coordinates would be represented by 2825 the terms: 2826 % 2827 \begin{verbatim} 2828 p = T.x->coeff[0][0] + x*T.x->coeff[1][0] + y*T.x->coeff[0][1]; 2829 q = T.y->coeff[0][0] + x*T.y->coeff[1][0] + y*T.y->coeff[0][1]; 2830 \end{verbatim} 2831 % 2832 where we have excluded the basic cross-term ($x \times y$) by using 2833 the mask: \code{T.x->mask[1][1] = 0; T.y->mask[1][1] = 0;} 2834 2835 The \code{psPlaneDistortion} represents an optical distortion. The 2836 lowest two terms are the $x$ and $y$ axis of the target system. The 2837 higher two terms may represent magnitude and color terms. 2838 \begin{verbatim} 2839 typedef struct { 2840 psDPolynomial4D *x; 2841 psDPolynomial4D *y; 2842 } psPlaneDistort; 2843 \end{verbatim} 2844 2845 Like \code{psPlaneTransform}, \code{psPlaneDistort} contains two 2846 \code{psDPolynomial4D} structures representing polynomials of 2847 arbitrary order as a function of four, rather than two dimensions. 2848 There is one of these structures for each of the two output 2849 dimensions. In this structure, the highest two dimensions could 2850 represent a magnitude and a color. As an example, consider the simple 2851 transformation from one linear coordinate frame ($x,y$), e.g., on a 2852 CCD, of an object with magnitude and color ($m,c$) to a second frame 2853 ($p,q$), e.g., the focal plane. If we have only first order terms in 2854 the transformation \code{psPlaneTransform T}, the new coordinates 2855 would be represented by the terms: 2856 % 2857 \begin{verbatim} 2858 p = T.x->coeff[0][0][0][0] + x*T.x->coeff[1][0][0][0] + y*T.x->coeff[0][1][0][0] 2859 + m*T.x->coeff[0][0][1][0] + c*T.x->coeff[0][0][0][1] 2860 q = T.y->coeff[0][0][0][0] + x*T.y->coeff[1][0][0][0] + y*T.y->coeff[0][1][0][0] 2861 + m*T.y->coeff[0][0][1][0] + c*T.y->coeff[0][0][0][1] 2862 \end{verbatim} 2863 % 2864 where we have again excluded the cross-term ($x \times y$) by using the 2865 mask. 2866 2867 We require corresponding functions to apply the transformations to a 2868 specified coordinate \code{coords}: 2869 % 2870 \begin{verbatim} 2871 psPlane *psPlaneTransformApply (psPlane *out, 2872 const psPlaneTransform *transform, 2873 const psPlane *coords); 2874 psPlane *psPlaneDistortApply (psPlane *out, 2875 const psPlaneDistort *distort, 2876 const psPlane *coords, 2877 float term3, float term4); 2878 \end{verbatim} 2879 2880 \subsubsection{Celestial Coordinate Conversions} 2881 2882 We need to be able to convert between ICRS, Galactic and Ecliptic 2883 coordinates, and potentially between arbitrary spherical coordinate 2884 systems. All of these basic spherical transformations represent 2885 rotations of the spherical coordinate reference. We specify a general 2886 transformation function which takes a structure, 2887 \code{psSphereTransform}, defining the transformation between two 2888 spherical coordinate systems (the structure contains the sines and 2889 cosines of the angles involved so as to minimize computation time for 2890 repeated transformations). We also define a function to generate 2891 \code{psSphereTransform}, based on the three angles 2892 describing the location of the pole and the relative equatorial 2893 rotations of the two systems. We also specify special functions to 2894 return the \code{psSphereTransform} for transformations 2895 between standard coordinate systems. 2896 2897 \begin{verbatim} 2898 typedef struct { 2899 double sinNPlon; ///< sin of North Pole longitude 2900 double cosNPlon; ///< cos of North Pole longitude 2901 double sinNPlat; ///< sin of North Pole lattitude 2902 double cosNPlat; ///< cos of North Pole lattitude 2903 double sinZP; ///< sin of First PT of Ares lon 2904 double cosZP; ///< cos of First PT of Ares lon 2905 } psSphereTransform; 2906 \end{verbatim} 2907 2908 The constructor and destructor are defined as follows: 2909 \begin{verbatim} 2910 psSphereTransform *psSphereTransformAlloc(double NPlon, double NPlat, double ZP); 2911 void psSphereTransformFree(psSphereTransform *trans); 2912 \end{verbatim} 2913 where \code{NPlon} and \code{NPlat} define the coordinates in the 2914 input system of the north pole in the output system and \code{ZP} 2915 defines the longitude in the input system of the equatorial 2916 intersection between the two systems (e.g, the first point of Ares). 2917 2918 Spherical coordinates may be transformed by providing the 2919 transformation and the coordinate in the input system to 2920 \code{psSphereTransform}: 2921 \begin{verbatim} 2922 psSphere *psSphereTransformApply(psSphere *out, 2923 const psSphereTransform *transform, 2924 const psSphere *coord); 2925 \end{verbatim} 2926 2927 The following functions simply return the appropriate 2928 \code{psSphereTransform} to convert between predefined spherical 2929 coordinate systems (i.e., {\bf I}CRS, {\bf E}cliptic and {\bf 2930 G}alactic). 2931 % 2932 \begin{verbatim} 2933 psSphereTransform *psSphereTransformItoE(void); 2934 psSphereTransform *psSphereTransformEtoI(void); 2935 psSphereTransform *psSphereTransformItoG(void); 2936 psSphereTransform *psSphereTransformGtoI(void); 2937 \end{verbatim} 2938 2939 \subsubsection{Projections} 2940 2941 We require functions to convert between spherical and linear 2942 coordinate systems based on a variety of projections. The required 2943 projections include: 2944 \begin{itemize} 2945 \item TAN 2946 \item SIN 2947 \item AIT 2948 \item PAR 2949 \item GLS 2950 \end{itemize} 2951 2952 We specify the following structure \code{psProjection} to define the 2953 parameters of the projection: 2954 \begin{verbatim} 2955 typedef struct { 2956 double R, D; ///< coordinates of projection center 2957 double Xs, Ys; ///< plate-scale in X and Y directions 2958 psProjectionType type; ///< projection type 2959 } psProjection; 2960 \end{verbatim} 2961 2962 The projection type is defined by the following enumerated type \code{psProjectionType}: 2963 \begin{verbatim} 2964 typedef enum { ///< type of val is: 2965 PS_PROJ_TAN, ///< Tangent projection 2966 PS_PROJ_SIN, ///< Sine projection 2967 PS_PROJ_AIT, ///< Aitoff projection 2968 PS_PROJ_PAR, ///< Par projection 2969 PS_PROJ_GLS, ///< GLS projection 2970 PS_PROJ_NTYPE ///< Number of types; must be last 2971 } psProjectionType; 2972 \end{verbatim} 2973 2974 The following functions will project and deproject (respectively) 2975 spherical coordinates: 2976 2977 \begin{verbatim} 2978 psPlane *psProject(const psSphere *coord, const psProjection *projection); 2979 psSphere *psDeproject(const psPlane *coord, const psProjection *projection); 2980 \end{verbatim} 2981 2982 \subsubsection{Offsets} 2983 We require a function to calculate the offset between two positions on 2984 the sky, as well as a function to apply an offset to a position. The 2985 first determines the offset (RA,Dec) on the sky between two positions. 2986 The second applies the given offset to the coordinate. The offsets may 2987 be of type: \tbd{Linear, Spherical/Arcsec, Spherical/Degreees, etc.} 2988 2989 \begin{verbatim} 2990 psSphere *psSphereGetOffset(const psSphere *restrict position1, 2991 const psSphere *restrict position2, 2992 const char *type); 2993 psSphere *psSphereSetOffset(const psSphere *restrict position, 2994 const psSphere *restrict offset, 2995 const char *type); 2996 \end{verbatim} 2997 Note that these should propagate the errors appropriately. 2998 2999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3000 3001 \subsection{Astronomical Images} 3002 3003 \subsubsection{Overview} 3004 3005 Above, we have defined a basic container for a single 2D collection of 3006 pixels (\code{psImage}), along with basic operations to manipulate the 3007 image pixels. For astronomical applications, this data structure is 3008 insufficient for two reasons. First, it does provide sufficient 3009 additional metadata to describe the data in detail. Second, astronomy 3010 applications frequent involve multiple, related images. For 3011 PanSTARRS, and for general astronomical applications, we require a 3012 richer collection of data structures which describe a very general 3013 image concept. We have defined several layers in the hierarchy which 3014 are necessary to describe the image data which will be produced by the 3015 PanSTARRS Gigapixel cameras as well as other standard astronomical 3016 images. 3017 3018 A simple 2D image is a basic data unit for much of astronomical 3019 imaging. If we consider various optical and IR array cameras, a 3020 single readout of the detector produces a collection of pixels 3021 measurements. We define our lowest-level astronomical image 3022 structure, \code{psReadout}, to contain the pixels produced by a 3023 single readout of the detector, along with metadata needed to define 3024 that readout: the origin and binning of the image relative to the 3025 original detector pixels explicitly in the structure, and pointers to 3026 the general metadata and derived objects, if any. 3027 3028 A single detector may produce more than one read which is associated. 3029 For example, infrared detectors frequently produce an image 3030 immediately after the detector is reset followed by an image after the 3031 basic exposure is complete. Both readouts correspond to the same 3032 pixels, though the binning or rastering may be different between the 3033 two readouts. Another example is the video sequence produced by the 3034 PanSTARRS Gigapix camera guide cells, each of which represents a 3035 series of many images from a subraster of pixels in the detector 3036 readout portion. The second level of our image container hierarchy, 3037 \code{psCell}, consists of a collection of readouts from a single 3038 detector. 3039 3040 In the PanSTARRS Gigapix camera, the basic readout region is a 3041 fraction of the full imaging area of a single CCD chip. The chip is 3042 divided into 64 cells, any fraction of which may have been readout 3043 for a given exposure. In other cameras, such as Megacam at CFHT, the 3044 individual CCDs have multiple amplifiers addressing contiguous 3045 portions of the detector. In such cameras, each amplifier produces a 3046 separate collection of pixels. In the third level of our image 3047 container hierarchy, the data structure \code{psChip} represents a 3048 collection of different cells. 3049 3050 The top level of our image container hierarchy is a complete focal 3051 plane array (\code{psFPA}). This structure represents the collection 3052 of chips in the camera, all of which are read out in a given 3053 exposure. 3054 3055 For example, take a mosaic camera consisting of eight $2k\times 4k$ 3056 CCDs, each of which is read out through two amplifiers. Then there 3057 would be sixteen cells in total, each of which is presumably $2k\times 3058 2k$. There would be eight chips, each consisting of two cells, and 3059 the focal plane consists of these eight chips. 3060 3061 As another example, consider an observation by PS1. The focal plane 3062 would consist of 60 chips, each of which consist of 64 cells (or less; 3063 a few cells may be dead). Some cells (those containing guide stars 3064 for the orthogonal transfer) will contain multiple readouts. 3065 3066 These data structures represent containers with which to carry around 3067 the collection of related image data. There is no requirement on the 3068 functions or the structures that each instance of one of these data 3069 structures represent the physical hardware. For example, it is not 3070 necessary that an instance of \code{psFPA} always carry the data for 3071 all 60 (or 64) Gigapixel camera OTAs. The usage of these structures 3072 is such that all astronomical operations which apply to a CCD image 3073 should be performed on an instance of \code{psFPA}. If a particular 3074 circumstance only requires a single 2D image, then that is represented 3075 by an instance of \code{psFPA} with one \code{psChip}, which in turn 3076 has one \code{psCell}, which in turn has one \code{psReadout}. 3077 3078 These container levels also include in their definition the information 3079 needed to transform the coordinates in one of the levels to the 3080 coordinate system relevant at the higher levels. 3081 3082 \subsubsection{A Readout} 3083 3084 A readout is the result of a single read of a cell (or a portion 3085 thereof). It contains a pointer to the pixel data, and additional 3086 pointers to the objects found in the readout, and the readout 3087 metadata. It also contains the offset from the lower-left corner of 3088 the chip, in the case that the CCD was windowed. 3089 3090 \begin{verbatim} 3091 typedef struct { 3092 const int x0, y0; ///< Offset from the lower-left corner 3093 const int nx, ny; ///< Image binning 3094 psImage *image; ///< imaging area of cell 3095 psDlist *objects; ///< objects derived from cell 3096 psMetadata *md; ///< Readout-level metadata 3097 } psReadout; 3098 \end{verbatim} 3099 3100 \subsubsection{A Cell} 3101 3102 A cell consists of one or more readouts (usually only one except in the 3103 case that the cell has been used for fast guiding). It also contains 3104 a pointer to the cell metadata, and a pointer to its parent chip. On 3105 the astrometry side, it also contains coordinate transforms from the 3106 cell to the chip and, as a convenience, from the cell to the focal 3107 plane. It is expected that these transforms will consist of two 3108 first-order 2D polynomials, simply specifying a translation, rotation 3109 and magnification; hence they are easily inverted, and there is no 3110 need to add reverse transformations. We also add an additional 3111 transformation, which is intended to provide a ``quick and dirty'' 3112 transform from the cell coordinates to the sky; this transformation 3113 not guaranteed to be as precise as the ``standard'' transformation of 3114 Cell $\rightarrow$ Chip $\rightarrow$ Focal Plane $\rightarrow$ 3115 Tangent Plane $\rightarrow$ Sky, but will be faster. 3116 3117 \begin{verbatim} 3118 typedef struct { 3119 int nReadouts; ///< number of readouts in this cell 3120 struct psReadout *readouts; ///< Readouts from the cell 3121 psMetadata *md; ///< Cell-level metadata 3122 psPlaneTransform *cellToChip; ///< Transformations from cell to chip coords 3123 psPlaneTransform *cellToFPA; ///< Transformations from cell to FPA coords 3124 psPlaneTransform *cellToSky; ///< Direct from cell to sky coords 3125 struct psChip *parentChip; ///< chip which contains this cell 3126 } psCell; 3127 \end{verbatim} 3128 3129 \subsubsection{A Chip} 3130 3131 A chip consists of one or more cells (according to the number of 3132 amplifiers on the CCD). It contains a pointer to the chip metadata, 3133 and a pointer to the parent focal plane. For astrometry, it contains 3134 a coordinate transform from the chip to the focal plane. It is 3135 expected that this transforms will consist of two second-order 2D 3136 polynomials; hence we think that it is prudent to include a reverse 3137 transformation which will be derived from numerically inverting the 3138 forward transformation. 3139 3140 \begin{verbatim} 3141 typedef struct { 3142 int nCells; ///< Number of Cells assigned 3143 struct psCell *cells; ///< Cells in the Chip 3144 psMetadata *md; ///< Chip-level metadata 3145 psPlaneTransform *chipToFPA; ///< Transformations from chip to FPA coords 3146 psPlaneTransform *FPAtoChip; ///< Transformations from FPA to chip 3147 struct psFPA *parentFPA; ///< FPA which contains this chip 3148 } psChip; 3149 \end{verbatim} 3150 3151 \subsubsection{A Focal Plane} 3152 3153 A focal plane consists of one or more chips (according to the number 3154 of pieces of contiguous silicon). It contains pointers to the focal 3155 plane metadata and the exposure information. For astrometry, it 3156 contains a transformation from the focal plane to the tangent plane 3157 and the fixed pattern residuals. It is expected that the 3158 transformation will consist of two 4D polynomials (i.e.\ a function of 3159 two coordinates in position, the magnitude of the object, and the 3160 color of the object) in order to correct for optical distortions and 3161 the effects of the atmosphere; hence we think that it is prudent to 3162 include a reverse transformation which will be derived from 3163 numerically inverting the forward transformation. Since colors are 3164 involved in the transformation, it is necessary to specify the color 3165 the transformation is defined for. We also include some values to 3166 characterize the quality of the transformation: the root mean square 3167 deviation for the x and y transformation fits, and the $\chi^2$ for 3168 the transformation fit. 3169 3170 \begin{verbatim} 3171 typedef struct { 3172 int nChips; ///< Number of Cells assigned 3173 int nAlloc; ///< Number of Cells available 3174 struct psChip *chips; ///< Chips in the Focal Plane Array 3175 psMetadata *md; ///< FPA-level metadata 3176 psPlaneDistort *TPtoFP; ///< Transformation term from 3177 psPlaneDistort *FPtoTP; ///< Transformation term from 3178 psFixedPattern *pattern; ///< Fixed pattern residual offsets 3179 const psExposure *exp; ///< information about this exposure 3180 psPhotSystem colorPlus, colorMinus; ///< Colour reference 3181 float rmsX, rmsY; ///< Dispersion in astrometric solution 3182 float chi2; ///< chi^2 of astrometric solution 3183 } psFPA; 3184 \end{verbatim} 3185 3186 \subsubsection{Exposure information} 3187 3188 We need several quantities from the telescope in order to make a 3189 first guess at the astrometric solution. From these quantities, 3190 further quantities can be derived and stored for later use. 3191 3192 \begin{verbatim} 3193 typedef struct { 3194 const double ra, dec; ///< Telescope boresight 3195 const double ha; ///< Hour angle 3196 const double zd; ///< Zenith distance 3197 const double az; ///< Azimuth 3198 const double lst; ///< Local Sidereal Time 3199 const float mjd; ///< MJD of observation 3200 const float rotAngle; ///< Rotator position angle 3201 const float temp; ///< Air temperature, for estimating refraction 3202 const float pressure; ///< Air pressure, for calculating refraction 3203 const float humidity; ///< Relative humidity, for refraction 3204 const float exptime; ///< Exposure time 3205 /* Derived quantities */ 3206 const float posAngle; ///< Position angle 3207 const float parallactic; ///< Parallactic angle 3208 const float airmass; ///< Airmass, calculated from zenith distance 3209 const float pf; ///< Parallactic factor 3210 const char *cameraName; ///< name of camera which provided exposure 3211 const char *telescopeName; ///< name of telescope which provided exposure 3212 } psExposure; 3213 \end{verbatim} 3214 3215 \subsubsection{Constructors and Destructors} 3216 3217 Each of the above structures needs an appropriate constructor and 3218 destructor. Other than \code{psExposure}, which contains significant 3219 non-pointer types, the constructors should not take any arguments, and 3220 the destructors should only take the structure to be destroyed. 3221 The constructor for \code{psExposure} is specified below. 3222 3223 \begin{verbatim} 3224 psExposure * 3225 psExposureAlloc(double ra, double dec, ///< Telescope boresight 3226 double ha, ///< Hour angle 3227 double zd, ///< Zenith distance 3228 double az, ///< Azimuth 3229 double lst, ///< Local Sidereal Time 3230 float mjd, ///< MJD 3231 float rotAngle, ///< Rotator position angle 3232 float temp, ///< Temperature 3233 float pressure, ///< Pressure 3234 float humidity, ///< Relative humidity 3235 float exptime); ///< Exposure time 3236 \end{verbatim} 3237 3238 \subsection{Astrometry} 3239 3240 Astrometry is a basic functionality required for the IPP that will be 3241 used repeatedly, both for low-precision (roughly where is my favorite 3242 object?) and high-precision (what is the proper motion of this star?). 3243 As such, it must be flexible, yet robust. Accordingly, we will wrap 3244 the StarLink Astronomy Libraries (SLALib), which has already been 3245 developed. 3246 3247 \subsubsection{Coordinate frames} 3248 \label{sec:coordinateFrames} 3249 3250 There are five coordinate frames that we need to worry about for the 3251 purposes of astrometry: 3252 \begin{itemize} 3253 \item Cell: $(x,y)$ in pixels --- raw coordinates; 3254 \item Chip: $(X,Y)$ in pixels --- the location on the silicon; 3255 \item Focal Plane: $(p,q)$ in microns --- the location on the focal plane; 3256 \item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and 3257 \item Sky: (RA,Dec) --- ICRS. 3258 \end{itemize} 3259 3260 The following steps are required to convert from the cell coordinates to 3261 the sky: 3262 \begin{itemize} 3263 \item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$; 3264 \item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$; 3265 \item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) = 3266 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the 3267 object, respectively; and 3268 \item TP $\longleftrightarrow$ Sky: SLALib transformation using a 3269 transform pre-computed for each pointing. 3270 \end{itemize} 3271 3272 Note that the transformation between the Focal Plane and the Tangent 3273 Plane is a four-dimensional polynomial, in order to account for any 3274 possible dependencies in the astrometry on the stellar magnitude and 3275 color; the former serves as a check for charge transfer 3276 inefficiencies, while the latter will correct chromatic refraction, 3277 both through the atmosphere and the corrector lenses. 3278 3279 We require structures to contain each of the above transformations as 3280 well as the pixel data. 3281 3282 \subsubsection{SLALib information} 3283 3284 SLALib requires several elements to perform the transformations 3285 between the tangent plane and the sky. Pre-computing these quantities 3286 for each exposure means that subsequent transformations are faster. 3287 For historical reasons, this structure is known colloquially as 3288 ``Wallace's Grommit''. 3289 3290 \begin{verbatim} 3291 typedef struct { 3292 const double latitude; ///< geodetic latitude (radians) 3293 const double sinLat, cosLat; ///< sine and cosine of geodetic latitude 3294 const double abberationMag; ///< magnitude of diurnal aberration vector 3295 const double height; ///< height (HM) 3296 const double temperature; ///< ambient temperature (TDK) 3297 const double pressure; ///< pressure (PMB) 3298 const double humidity; ///< relative humidity (RH) 3299 const double wavelength; ///< wavelength (WL) 3300 const double lapseRate; ///< lapse rate (TLR) 3301 const double refractA, refractB; ///< refraction constants A and B (radians) 3302 const double longitudeOffset; ///< longitude + ... (radians) 3303 const double siderealTime; ///< local apparent sidereal time (radians) 3304 } psGrommit; 3305 \end{verbatim} 3306 3307 The \code{psGrommit} is calculated from telescope information for the 3308 particular exposure: 3309 \begin{verbatim} 3310 psGrommit *psGrommitAlloc(const psExposure *exp); 3311 void psGrommitFree(psGrommit *grommit); 3312 \end{verbatim} 3313 3314 \subsubsection{Fixed Pattern} 3315 3316 The fixed pattern is a correction to the general astrometric solution 3317 formed by summing the residuals from many observations. The intent is 3318 to correct for higher-order distortions in the camera system on a 3319 coarse grid (larger than individual pixels, but smaller than a single 3320 cell). Hence, in addition to the offsets, we need to specify the size 3321 and scale of the grid in $x$ and $y$, as well as the origin of the 3322 grid. 3323 3324 \begin{verbatim} 3325 typedef struct { 3326 int nX, nY; ///< Number of elements in x and y 3327 double x0, y0; ///< Position of 0,0 corner on focal plane 3328 double xScale, yScale; ///< Scale of the grid 3329 double **x, **y; ///< The grid of offsets in x and y 3330 } psFixedPattern; 3331 \end{verbatim} 3332 3333 \subsubsection{Position Finding} 3334 3335 We require functions to return the structure containing given 3336 coordinates. For example, we want the chip that corresponds to the 3337 focal plane coordinates $(p,q) = (-1.234,+5.678)$. These routines 3338 handle the one-to-many problem --- i.e., for one given focal plane 3339 coordinate, there are many chips that this coordinate may be 3340 correspond to; these functions will select the correct one. 3341 % 3342 \begin{verbatim} 3343 psCell *psCellInFPA (psCell *out, const psPlane *coord, const psFPA *fpa); 3344 psChip *psChipInFPA (psChip *out, const psPlane *coord, const psFPA *fpa); 3345 psCell *psCellInChip(psCell *out, const psPlane *coord, const psChip *chip); 3346 \end{verbatim} 3347 3348 \subsubsection{Conversion Functions} 3349 3350 We require functions to convert between the various coordinate frames 3351 (Section~\ref{sec:coordinateFrames}). The hierarchy of the coordinate 3352 frames and the transformations between each are shown in 3353 Figure~\ref{fig:coco}. The functions that employ the transformations 3354 are shown in Figure~\ref{fig:cocoFunc}. In addition to 3355 transformations between each adjoining coordinate frame in the 3356 hierarchy, we also require higher-level functions to convert between 3357 the Cell and Sky coordinate frames; these will simply perform the 3358 intermediate steps. 3359 3360 \begin{figure} 3361 \psfig{file=coordinateFrames,height=7in,angle=-90} 3362 \caption{The coordinate systems in the \PS{} IPP, and the relation 3363 between each by transformations contained in the appropriate 3364 structures.} 3365 \label{fig:coco} 3366 \end{figure} 3367 3368 \begin{figure} 3369 \psfig{file=coordinateConv,height=7in,angle=-90} 3370 \caption{Conversion between coordinate systems by PSLib.} 3371 \label{fig:cocoFunc} 3372 \end{figure} 3373 3374 We specify the following functions to convert between coordinates in 3375 one type of frame to another type of frame. The first group consist 3376 of unambiguous transformations: from the coordinates in a low-level 3377 frame to the coordinates in the containing higher-level frame, of 3378 which only one exists. In all of these functions, the output 3379 coordinate structure may be \code{NULL} or may be supplied by the 3380 calling function. In the former case, the structure must be 3381 allocated; in the latter case, the supplied structure must be used. 3382 3383 \begin{verbatim} 3384 psPlane *psCoordCelltoChip (psPlane *out, const psPlane *in, const psCell *cell); 3385 \end{verbatim} 3386 which converts coordindates \code{in} on the specified \code{cell} to 3387 the coordinates on the parent chip. 3388 3389 \begin{verbatim} 3390 psPlane *psCoordChiptoFPA (psPlane *out, const psPlane *in, const psChip *chip); 3391 \end{verbatim} 3392 which converts the coordinates \code{in} on the specified \code{chip} 3393 to the coordinates on the parent FPA. 3394 3395 \begin{verbatim} 3396 psPlane *psCoordFPAToTP(psPlane *out, const psPlane *in, const psFPA *fpa); 3397 \end{verbatim} 3398 which converts coordinates \code{in} on the specified focal plane 3399 \code{fpa} to tangent plane coordinates, applying the appropriate 3400 distortion terms. 3401 3402 \begin{verbatim} 3403 psSphere *psCoordTPtoSky(psSphere *out, const psPlane *in, const psGrommit *grommit); 3404 \end{verbatim} 3405 which converts the tangent plane coordinates \code{in} to (RA,Dec) on 3406 the sky, based on the environmental information specified by 3407 \code{grommit}. 3408 3409 \begin{verbatim} 3410 psPlane *psCoordCellToFPA(psPlane *out, const psPlane *in, const psCell *cell); 3411 \end{verbatim} 3412 which performs the single-step conversion between Cell coordinates 3413 \code{in} and FPA coordinates. 3414 3415 \begin{verbatim} 3416 psSphere *psCoordCellToSky(psSphere *out, const psPlane *in, const psCell *cell); 3417 \end{verbatim} 3418 which converts coordinates on the specified cell to (RA,Dec). This 3419 transformation must be performed using the intermediate stage 3420 transformations of Cell to Chip, Chip to FPA, FPA to Tangent Plane, 3421 Tangent Plane to Sky. The information needed for each of these 3422 transformations is available in the \code{.parent} elements of 3423 \code{psCell} and \code{psChip}, and the \code{psFPA.exposure} 3424 element. 3425 3426 \begin{verbatim} 3427 psSphere *psCoordCellToSkyQD(psSphere *out, const psPlane *in, const psCell *cell); 3428 \end{verbatim} 3429 which uses the 'quick-and-dirty' transformation to convert coordinates 3430 on the specified cell to (RA,Dec). This transformation should use the 3431 locally linear transformation specified by the element 3432 \code{psCell.cellToSky}. Although the accuracy of this transformation 3433 is lower than the complete transformation above, the calculation is 3434 substantially faster as it only involves linear transformations. 3435 3436 The following functions convert from high-level frames to the 3437 coordinates of contained lower-level frames. 3438 3439 \begin{verbatim} 3440 psPlane *psCoordSkyToTP(psPlane *out, const psSphere *in, const psGrommit *grommit); 3441 \end{verbatim} 3442 which converts (RA,Dec) coordinates \code{in} to tangent plane coords 3443 based on the enviromental information supplied by \code{grommit}. 3444 3445 \begin{verbatim} 3446 psPlane *psCoordTPtoFPA(psPlane *out, const psPlane *in, const psFPA *fpa); 3447 \end{verbatim} 3448 which converts the tangent plane coordinates \code{in} to focal plane coordinates. 3449 3450 \begin{verbatim} 3451 psPlane *psCoordFPAtoChip (psPlane *out, const psPlane *in, const psChip *chip); 3452 \end{verbatim} 3453 which converts the specified FPA coordinates \code{in} to the 3454 coordinates on the given Chip. The specified chip need not contain 3455 the input coordinate. To find the chip which contains a particular 3456 coordinate, the function \code{psChipInFPA}, defined above, should be 3457 used. 3458 3459 \begin{verbatim} 3460 psPlane *psCoordChiptoCell (psPlane *out, const psPlane *in, const psCell *cell); 3461 \end{verbatim} 3462 which converts the specified Chip coordinate \code{in} to the 3463 coordinate on the given Cell. The specified Cell need not contain the 3464 input coordinate. To find the cell which contains a particular 3465 coordinate, the function \code{psCellInChip}, defined above, should be 3466 used. 3467 3468 \begin{verbatim} 3469 psPlane *psCoordSkyToCell(psPlane *out, const psSphere *in, psCell *cell); 3470 \end{verbatim} 3471 which directly converts (RA,Dec) \code{in} to coordinates on the 3472 specified cell. The specified cell need not contain the input 3473 coordinates. 3474 3475 \begin{verbatim} 3476 psPlane *psCoordSkyToCellQD(psPlane *out, const psSphere *in, psCell *cell); 3477 \end{verbatim} 3478 which directly converts (RA,Dec) \code{in} to coordinates on the 3479 specified cell. The specified cell need not contain the input 3480 coordinates. This transformation should use the locally linear 3481 transformation specified by the element \code{psCell.cellToSky}. 3482 Although the accuracy of this transformation is lower than the 3483 complete transformation above, the calculation is substantially faster 3484 as it only involves linear transformations. 3485 3486 \subsubsection{Additional functions} 3487 3488 We require additional functions to perform general functions which 3489 will be useful for astrometry. Given coordinates on the sky, we 3490 need to get the airmass, the parallactic angle, and an estimate of 3491 the atmospheric refraction. 3492 3493 \begin{verbatim} 3494 float psGetAirmass(const psSphere *coord, double siderealTime, float height); 3495 \end{verbatim} 3496 which returns the airmass for a given position and sidereal time. 3497 3498 \begin{verbatim} 3499 float psGetParallactic(const psSphere *coord, double siderealTime); 3500 \end{verbatim} 3501 which returns the parallactic angle for a given position and sidereal time. 3502 3503 \begin{verbatim} 3504 float psGetRefraction(float colour, ///< Colour of object 3505 psPhotSystem colorPlus, ///< Colour reference 3506 psPhotSystem colorMinus, ///< Colour reference 3507 const psExposure *exp); ///< Telescope pointing information 3508 \end{verbatim} 3509 which provides an estimate of the atmospheric refraction, along the parallactic angle. 3510 3511 \begin{verbatim} 3512 double psGetParallaxFactor(const psExposure *exp) 3513 \end{verbatim} 3514 Calculate the parallax factor for the given exposure \tbd{why do we 3515 need this?}. 3516 3517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3518 3519 \subsection{Photometry} 3520 3521 Photometric observations are performed in an instrumental photometric 3522 system, and must be related to other photometric systems. We 3523 require a data structure which defines a photometric system, as well 3524 as a structure to define the transformation between photometric 3525 systems. 3526 3527 The photometric system is defined by the psPhotSystem structure. 3528 A photometric system is identified by a human-readable \code{name} 3529 (ie, SDSS.g, Landolt92.B, GPC1.OTA32.r). Each photometric system is 3530 given a unique identifier \code{ID}. Observations taken with a 3531 specific camera, detector, and filter represent their own photometric 3532 system, and it may be necessary to perform transformations between 3533 these systems. Photometric systems associated with observations from 3534 a specific camera/detector/filter combination can be associated with 3535 those components. 3536 \begin{verbatim} 3537 typedef struct { 3538 const int ID; ///< ID number for this photometric system 3539 const char *name; ///< Name of photometric system 3540 const char *camera; ///< Camera for photometric system 3541 const char *filter; ///< Filter used for photometric system 3542 const char *detector; ///< Detector used for photometric system 3543 } psPhotSystem; 3544 \end{verbatim} 3545 3546 The following structure defines the transformation between two 3547 photometric systems. 3548 \begin{verbatim} 3549 typedef struct { 3550 psPhotSystem src; ///< Source photometric system 3551 psPhotSystem dst; ///< Destination photometric system 3552 psPhotSystem pP, pM; ///< Primary color reference 3553 psPhotSystem sP, sM; ///< Secondary color reference 3554 float pA, sA; ///< Color offset for references 3555 psPolynomial3D transform; ///< Transformation from source to destination 3556 } psPhotTransform; 3557 \end{verbatim} 3558 3559 The transformation between two photometric systems may depend on the 3560 airmass of the observation and on the colors of the object of 3561 interest. For a specific observation, such a transformations can be 3562 defined as a polynomial function of the color of the star and the 3563 airmass of the observations. If sufficient data exists, the 3564 transformation between the photometric systems may include more than 3565 one color, constraining the curvature of the stellar spectral energy 3566 distributions. This latter term may be significant for stars which 3567 are highly reddened, for example. Derived photometric quantities may 3568 have been corrected for airmass variations, in which case only color 3569 terms may be measurable. The structure defines the transformation 3570 between a source photometric system (\code{src}) and a target 3571 photometric system (\code{dst}). The photometric system of a primary 3572 color is defined by \code{pP, pM} such that the color is constructed 3573 as $pP - pM$. A secondary color is defined by \code{sP, sM}. For 3574 both, a reference color is specified (\code{pA, sA}): the polynomial 3575 transformation terms refer to colors in the form $pP - pM - pA$. The 3576 transformation is specified as a 3D polynomial. For a star of 3577 magnitude $M_{\rm src}$ in the source photometric system, with 3578 additional magnitude information in the other systems $M_{\rm pP}$, 3579 $M_{\rm pM}$, $M_{\rm sP}$, $M_{\rm sM}$, observed at an airmass of 3580 $z$, the magnitude of the star in the target system $M_{\rm dst}$ is 3581 given by: $M_{\rm dst} = M_{\rm src} + transform(z, M_{\rm pP} - 3582 M_{\rm pM} - pA, M_{\rm sP} - M_{\rm sM} - sA)$. 3583 3584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3585 3586 \subsection{Astronomical objects} 3587 3588 \subsubsection{Positions of Major SS Objects} 3589 3590 We require the ability to calculate the position of major Solar System 3591 objects, as well as Lunar phase. These functions all take the 3592 specified modified julian date, \code{mjd}, and the latitude/longitude 3593 of the observer. 3594 3595 \begin{verbatim} 3596 psSphere *psSunGetPos(psTime time); 3597 psTime *psSunGetRise (psTime *twi15, psTime *twi18, psTime time); 3598 psTime *psSunGetSet (psTime *twi15, psTime *twi18, psTime time); 3599 3600 psSphere *psMoonGetPos(psTime time, psSphere location); 3601 psTime *psMoonGetRise (psTime *twi15, psTime *twi18, psTime time); 3602 psTime *psMoonGetSet (psTime *twi15, psTime *twi18, psTime time); 3603 float psGetMoonPhase(psTime time); 3604 3605 psSphere *psPlanetGetPos(psTime time, psSphere location); 3606 psTime *psPlanetGetRise (psTime *twi15, psTime *twi18, psTime time); 3607 psTime *psPlanetGetSet (psTime *twi15, psTime *twi18, psTime time); 3608 3609 \end{verbatim} 3610 3611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3612 3613 \appendix 3614 3615 \pagebreak 3616 \section{API Summary: all functions} 3617 3618 \subsection{System Utilities} 3619 \input{psSystemGroup.tex} 3620 3621 \subsection{Data Containers} 3622 \input{psDataGroup.tex} 3623 3624 \subsection{Math Utilities} 3625 \input{psMathGroup.tex} 3626 3627 \subsection{Astronomy Functions} 3628 \input{psAstroGroup.tex} 3629 3630 \pagebreak 3631 \section{API Summary: all structures} 3632 \input{psStructures.tex} 3633 3634 \section{Revision Change Log} 3635 \input{ChangeLogSDRS.tex} 3636 3637 \bibliographystyle{plain} \bibliography{panstarrs} 3638 3639 \end{document} 3640 2758 3641 2759 3642 An example of the usage of the metadata APIs is as follows: … … 2794 3677 \null\qquad\qquad\code{IPP.phase1.ota12.biassec}. 2795 3678 2796 We shallset in place a system for assigning the top-level `domains'3679 We must set in place a system for assigning the top-level `domains' 2797 3680 to responsible individuals, and for gathering a complete list of 2798 3681 all metadata names in use throughout the project. … … 2815 3698 } 2816 3699 \end{verbatim} 2817 2818 It is an unfortunate fact that certain metadata keywords (such as2819 \code{COMMENT} and \code{HISTORY} in a FITS header) may be repeated2820 with different values. The \code{psMetadataAppend} routine is2821 required to check that all metadata names are unique unless the type2822 is qualified as \code{PS_META_NON_UNIQUE}; in this case a unique2823 integer will be added to each name that you specify. In this case, you2824 may either delete individual element separately or as a complete set:2825 \begin{verbatim}2826 psMetadataItemFree(psMetadataRemove(ms, "lang.hello.0"));2827 psMetadataItemFree(psMetadataRemove(ms, "lang.hello"));2828 \end{verbatim}2829 2830 \subsubsection{Metadata APIs}2831 2832 In this section, we explain the metadata APIs more fully.2833 2834 The allocator for \code{psMetadataItem} returns a full2835 \code{psMetadataItem} ready for insertion into the2836 \code{psMetadata}. It is important to note that, in order to2837 support multiple types, the data being input must be a pointer, even2838 if it is a \code{float} or \code{int}, for example. The name of the2839 \code{psMetadataItem} takes a \code{sprintf} format string, with the2840 corresponding arguments following.2841 2842 Note that the destructor for \code{psMetadataItem} must call the2843 appropriate destructor for the \code{val} (recall that it is the duty2844 of the \code{psMyTypeFree}s to decrement the \code{refCounter} and2845 free the memory if and only if the \code{refCounter == 1} --- see2846 \S\ref{sec:free}).2847 2848 \begin{verbatim}2849 /** Constructor */2850 psMetadataItem *psMetadataItemAlloc(int typeFlags, ///< type of this piece of metadata + flags2851 const void *val, ///< value of new item N.b. a pointer even if the item2852 ///< is of type e.g. int2853 const char *comment, ///< comment associated with item2854 const char *name, ///< name of new item of metadata (may be in sprintf2855 ///< format)2856 ... ///< possible arguments for name format2857 );2858 2859 /** Destructor */2860 void psMetadataItemFree(psMetadataItem *ms ///< piece of metadata to destroy2861 );2862 \end{verbatim}2863 2864 2865 The constructor for the collection of metadata, \code{psMetadata},2866 simply returns an empty metadata container (employing the constructors2867 for the doubly-linked list and hash table). The destructor needs to2868 free each of the \code{psMetadataItem}s using2869 \code{psMetadataItemFree}.2870 2871 \begin{verbatim}2872 /** Constructor */2873 psMetadata *psMetadataAlloc(void); ///< make a new set of metadata2874 2875 /** Destructor */2876 void psMetadataFree(psMetadata *md ///< destroy a set of metadata2877 );2878 \end{verbatim}2879 2880 2881 Items may be added to the metadata in one of two ways --- firstly, an2882 item may be added by appending a \code{psMetadataItem} which has2883 already been created; and secondly by directly providing the data to2884 be appended. In both cases, the \code{psMetadataItem} that is2885 appended to the metadata is returned.2886 2887 \begin{verbatim}2888 /// Add item to the end of the metadata2889 psMetadataItem *psMetadataAppendItem(psMetadata *restrict md, ///< metadata to add to2890 psMetadataItem *restrict item ///< Metatdata to add2891 );2892 2893 /// Add item to the end of the metadata. Combines psMetadataItemAlloc and psMetadataAppendItem2894 psMetadataItem *psMetadataAppend(psMetadata *restrict md, ///< Metadata to add to2895 int typeFlags ///< type of this piece of metadata + flags2896 const void *val, ///< value of new item N.b. a pointer even if the item2897 ///< is of type e.g. int2898 const char *comment, ///< comment associated with item2899 const char *name, ///< name of new item of metadata (may be in sprintf2900 ///< format)2901 ... ///< possible arguments for name format2902 );2903 \end{verbatim}2904 2905 Items may be removed from the metadata by specifying a key. If the2906 key matches a metadata item, the item is removed from the metadata and2907 returned; otherwise, \code{NULL} is returned. If the key is not2908 unique, then \emph{all} items corresponding to the key are removed,2909 and the \tbd{first} item is returned.2910 2911 Care should be taken not to leak memory when appending an item for2912 which the key already exists in the metadata (and is not2913 \code{PS_META_NON_UNIQUE}).2914 2915 \begin{verbatim}2916 /// delete entry from the metadata2917 psMetadataItem *psMetadataRemove(psMetadata *restrict md, ///< metadata to delete from2918 const char *restrict key ///< Key to delete2919 );2920 \end{verbatim}2921 2922 The metadata may be iterated over by (re-)setting the iterator for the2923 appropriate \code{psMetadata}, and getting the next item.2924 \code{psMetadataGetNext} has the ability to match the beginning of a2925 key, e.g., if the user only wants to iterate through2926 \code{IPP.machines.sky} and doesn't want to bother with2927 \code{IPP.machines.detector}. The iterator should iterate over every2928 item of metadata --- even those that are non-unique.2929 2930 \begin{verbatim}2931 /// reset the iterator to the start of the list2932 void psMetadataSetIterator(psMetadata *md ///< metadata to set iterator for2933 );2934 2935 /// get the next item in the sequence2936 psMetadataItem *psMetadataGetNext(psMetadata *restrict md, ///< metadata to get from2937 const char *restrict match, ///< Match this2938 int which ///< Which iterator to use2939 );2940 \end{verbatim}2941 2942 Items may be found within the metadata by providing a key. In the2943 event that the key is non-unique, the first item is returned.2944 2945 \begin{verbatim}2946 /// find the metadata with the specified key2947 psMetadataItem *psMetadataLookup(const psMetadata *restrict md, ///< metadata to look up2948 const char *restrict key ///< Key to find2949 );2950 \end{verbatim}2951 2952 Metadata items may be printed to an open file descriptor, optionally2953 pre-pending a specified string.2954 2955 \begin{verbatim}2956 /// print metadata item to the specified stream2957 void psMetadataItemPrint(FILE *fd, ///< file descriptor to write to2958 const psMetadataItem *restrict md, ///< item of metadata to print2959 const char *prefix ///< print this at the beginning of each line2960 );2961 \end{verbatim}2962 2963 \subsection{Detector and sky positions}2964 2965 Both detector and sky positions will be used extensively in the IPP.2966 The first are linear coordinates which conform to Euclidean geometry2967 while the second are angular coordinates for which additional care2968 must often be taken. We put these into two structures,2969 \code{psPlaneCoord} and \code{psSphereCoord}, respectively.2970 Partitioning these two will enable error-checking.2971 2972 \begin{verbatim}2973 /** A point in 2-D space, with errors. */2974 typedef struct {2975 double x; ///< x position2976 double y; ///< y position2977 double xErr; ///< Error in x position2978 double yErr; ///< Error in y position2979 } psPlaneCoord;2980 2981 /** A point on the surface of a sphere, with errors */2982 typedef struct {2983 double r; ///< RA2984 double d; ///< Dec2985 double rErr; ///< Error in RA2986 double dErr; ///< Error in Dec2987 } psSphereCoord;2988 \end{verbatim}2989 2990 Three major classes of coordinate transformations are necessary.2991 First, linear coordinates from one frame must be converted to linear2992 coordinates in a different frame of references. Simple transformations2993 of this type are independent of other quantities of the positions --2994 they are simply mapping between two linear spaces. In practice, these2995 transformations may often be a function of the magnitude or color of2996 the imaged object. The second type of conversion is the2997 transformation of linear coordinates to angular coordinates and2998 vice-versa. This conversion depends on the desired projection, and2999 may represent the real mapping performed by the telescope or may3000 simply represent a convenient mechanism to display 3D coordinates in3001 useful forms. The third conversion of interest is the transformation3002 of one set of spherical coordinates to another set. Frequently in3003 astronomy, these conversions consist only of rotations between the two3004 spherical coordinates systems, where the coordinates of the pole and3005 equatorial rotation between the two systems define the3006 transformation. Conversions between standard coordinate systems such3007 as Galactic, Ecliptic, and various epochs of the Celestial coordinates3008 are represented by these spherical transformations.3009 3010 \subsubsection{Linear Coordinate Transformations}3011 3012 We specify two types of transforms between coordinate systems. The3013 first consists simply of two 2D polynomials to transform both3014 components -- the output coordinates depend only on the input3015 coordinates and no other quantities of objects at those coordinates.3016 The second consists of two 4D polynomials in which the output3017 coordinates are also specified to be a function of the magnitude and3018 color of the object with the given coordinates. This type of3019 coordinate transformation is necessary to represent the3020 (color-dependent) optical distortions caused by the atmosphere and3021 camera optics, and the possibly effects of charge transfer3022 inefficiency. We specify two structures to represent the coefficients3023 of these transformations:3024 3025 \begin{verbatim}3026 /** A polynomial transformation between coordinate frames. This may be a linear relationship, or may3027 * represent a higher-order transformation.3028 */3029 typedef struct {3030 psDPolynomial2D *x;3031 psDPolynomial2D *y;3032 } psPlaneCoordXform;3033 \end{verbatim}3034 3035 The \code{psDPolynomial2D} structures represent polynomials of3036 arbitrary order as a function of two dimensions. There is one of3037 these structures for each of the two output dimensions. As an3038 example, consider the simple transformation from one linear coordinate3039 frame \code{x,y} (say a single CCD) to a second frame \code{p,q} (say,3040 a second CCD image). If we have only first order terms in the3041 transformation \code{psPlaneCoordXform T}, the new coordinates would be3042 represented by the terms:3043 %3044 \begin{verbatim}3045 p = T.x->coeff[0][0] + x*T.x->coeff[1][0] + y*T.x->coeff[0][1];3046 q = T.y->coeff[0][0] + x*T.y->coeff[1][0] + y*T.y->coeff[0][1];3047 \end{verbatim}3048 %3049 where we have excluded the basic cross-term (\code{x*y}) by using the3050 mask: \code{T.x->mask[1][1] = 0; T.y->mask[1][1] = 0;}3051 3052 \begin{verbatim}3053 /** The optical distortion terms. The lowest two terms are the x and y axis of the target system. The higher3054 * two terms represent magnitude and color terms.3055 */3056 typedef struct {3057 psDPolynomial4D *x;3058 psDPolynomial4D *y;3059 } psPlaneDistortion;3060 \end{verbatim}3061 3062 Like \code{psPlaneCoordXform}, \code{psPlaneDistortion} contains two3063 \code{psDPolynomial4D} structures representing polynomials of3064 arbitrary order as a function of four, rather than two dimensions.3065 There is one of these structures for each of the two output3066 dimensions. In this structure, the highest two dimensions could3067 represent a magnitude and a color. As an example, consider the simple3068 transformation from one linear coordinate frame \code{x,y} (say a3069 single CCD) of an object with magnitude and color \code{m,c} to a3070 second frame \code{p,q} (say, a second CCD image). If we have only3071 first order terms in the transformation \code{psPlaneCoordXform T}, the new3072 coordinates would be represented by the terms:3073 %3074 \begin{verbatim}3075 p = 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]3076 + c*T.x->coeff[0][0][0][1]3077 q = 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]3078 + c*T.y->coeff[0][0][0][1]3079 \end{verbatim}3080 %3081 where we have again excluded the cross-terms (\code{x*y}) by using the3082 mask.3083 3084 We require corresponding functions to apply the transformations:3085 %3086 \begin{verbatim}3087 /** apply the coordinate transformation to the given coordinate */3088 psPlaneCoord *psPlaneCoordXformApply (psPlaneCoord *out, ///< Output coordinates, or NULL3089 const psPlaneCoordXform *frame, ///< coordinate transformation3090 const psPlaneCoord *coords ///< input coordiate3091 );3092 3093 /** apply the optical distortion to the given coordinate, magnitude, color */3094 psPlaneCoord *psPlaneDistortionApply (psPlaneCoord *out, ///< Output coordinates, or NULL3095 const psPlaneDistortion *pattern, ///< optical distortion pattern3096 const psPlaneCoord *coords, ///< input coordinate3097 float mag, ///< magnitude of object3098 float color ///< color of object3099 );3100 \end{verbatim}3101 %3102 3103 \subsubsection{Celestial Coordinate Conversions}3104 3105 We need to be able to convert between ICRS, Galactic and Ecliptic3106 coordinates, and potentially between arbitrary spherical coordinate3107 systems. All of these basic spherical transformations represent3108 rotations of the spherical coordinate reference. We specify a general3109 transformation function which takes a structure,3110 \code{psSphereCoordTransformation}, defining the transformation3111 between two spherical coordinate systems (the structure contains the3112 sines and cosines of the angles involved so as to minimize computation3113 time for repeated transformations). We also define a function to3114 generate \code{psSphereCoordTransformation}, based on the three angles3115 describing the location of the pole and the relative equatorial3116 rotations of the two systems. We also specify special functions to3117 return the \code{psSphereCoordTransformation} for transformations3118 between standard coordinate systems.3119 3120 \begin{verbatim}3121 /** General spherical transformation */3122 typedef struct {3123 double sin1, sin2, sin3, cos1, cos2, cos3; ///< Sines and cosines for transformation3124 } psSphereCoordTransformation;3125 \end{verbatim}3126 3127 The constructor and destructor are defined as follows:3128 3129 \begin{verbatim}3130 /** Constructor */3131 psSphereCoordTransformation *3132 psSphereCoordTransformationAlloc(double pole1, ///< First location of pole3133 double pole2, ///< Second location of pole3134 double rotation ///< Rotation between systems3135 );3136 3137 /** Destructor */3138 void psSphereCoordTranformationFree(psSphereCoordTransformation *trans ///< Transformation to destroy3139 );3140 \end{verbatim}3141 3142 Spherical coordinates may be transformed by providing the transformation to3143 \code{psSphereCoordTransform}:3144 3145 \begin{verbatim}3146 /** Apply general spherical transformation */3147 psSphereCoord *3148 psSphereCoordTransform(const psSphereCoord *coord, ///< Coordinates to convert3149 psSphereCoordSystem *sys ///< System to use to convert3150 );3151 \end{verbatim}3152 3153 The following functions simply return the appropriate3154 \code{psSphereCoordTransformation} to convert between predefined3155 spherical coordinate systems (i.e., ICRS, Ecliptic and Galactic).3156 3157 \begin{verbatim}3158 /** Return transformation structure to convert ICRS to Ecliptic */3159 psSphereCoordTransformation *psSphereCoordTransformationItoE(void);3160 3161 /** Return transformation structure to convert Ecliptic to ICRS */3162 psSphereCoordTransformation *psSphereCoordTransformationEtoI(void);3163 3164 /** Return transformation structure to convert ICRS to Galactic */3165 psSphereCoordTransformation *psSphereCoordTransformationItoG(void);3166 3167 /** Return transformation structure to convert Galactic to ICRS */3168 psSphereCoordTransformation *psSphereCoordTransformationGtoI(void);3169 \end{verbatim}3170 3171 3172 \subsubsection{Projections}3173 3174 We require functions to convert between spherical and linear3175 coordinate systems based on a variety of projections. The required3176 projections include:3177 \begin{itemize}3178 \item TAN3179 \item SIN3180 \item AIT3181 \item PAR3182 \item GLS3183 \end{itemize}3184 3185 The following functions will project and deproject (respectively)3186 spherical coordinates:3187 3188 \begin{verbatim}3189 /** Project spherical system onto a plane */3190 psPlaneCoord *3191 psCoordProject(const psSphereCoord *coord, ///< Spherical coordinates to project3192 const char *projection ///< Projection to use3193 );3194 3195 /** Deproject plane onto spherical system */3196 psSphereCoord *3197 psCoordDeproject(const psPlaneCoord *coord, ///< Plane coordinates to deproject3198 const char *projection ///< Projection to use3199 );3200 \end{verbatim}3201 3202 \subsubsection{Offsets}3203 3204 We require a function to calculate the offset between two positions on3205 the sky, as well as a function to apply an offset to a position.3206 3207 \begin{verbatim}3208 /** Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical */3209 psSphereCoord *3210 psSphereCoordGetOffset(const psSphereCoord *restrict position1, ///< Position 13211 const psSphereCoord *restrict position2, ///< Position 23212 const char *type ///< Type of offset: Linear, Spherical/Arcsec,3213 ///< Spherical/Degreees etc3214 );3215 3216 /** Apply an offset to a position */3217 psSphereCoord *3218 psSphereCoordApplyOffset(const psSphereCoord *restrict position, ///< Position3219 const psSphereCoord *restrict offset, ///< Offset3220 const char *type ///< Type of offset: Linear, Spherical/Arcsec,3221 ///< Spherical/Degreees etc3222 );3223 \end{verbatim}3224 3225 Note that these should propagate the errors appropriately.3226 3227 3228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3229 3230 \subsection{Astronomical Images}3231 3232 \subsubsection{Overview}3233 3234 Above, we have defined a basic container for a single 2D collection of3235 pixels (\code{psImage}), along with basic operations to manipulate the3236 image pixels. For astronomical applications, this data structure is3237 insufficient for two reasons. First, it does provide sufficient3238 additional metadata to describe the data in detail. Second, astronomy3239 applications frequent involve multiple, related images. For3240 PanSTARRS, and for general astronomical applications, we require a3241 richer collection of data structures which describe a very general3242 image concept. We have defined several layers in the hierarchy which3243 are necessary to describe the image data which will be produced by the3244 PanSTARRS Gigapixel cameras as well as other standard astronomical3245 images.3246 3247 A simple 2D image is a basic data unit for much of astronomical3248 imaging. If we consider various optical and IR array cameras, a3249 single readout of the detector produces a collection of pixels3250 measurements. We define our lowest-level astronomical image3251 structure, \code{psReadout}, to contain the pixels produced by a3252 single readout of the detector, along with metadata needed to define3253 that readout: the origin and binning of the image relative to the3254 original detector pixels explicitly in the structure, and pointers to3255 the general metadata and derived objects, if any.3256 3257 A single detector may produce more than one read which is associated.3258 For example, infrared detectors frequently produce an image3259 immediately after the detector is reset followed by an image after the3260 basic exposure is complete. Both readouts correspond to the same3261 pixels, though the binning or rastering may be different between the3262 two readouts. Another example is the video sequence produced by the3263 PanSTARRS Gigapix camera guide cells, each of which represents a3264 series of many images from a subraster of pixels in the detector3265 readout portion. The second level of our image container hierarchy,3266 \code{psCell}, consists of a collection of readouts from a single3267 detector.3268 3269 In the PanSTARRS Gigapix camera, the basic readout region is a3270 fraction of the full imaging area of a single CCD chip. The chip is3271 divided into 64 cells, any fraction of which may have been readout3272 for a given exposure. In other cameras, such as Megacam at CFHT, the3273 individual CCDs have multiple amplifiers addressing contiguous3274 portions of the detector. In such cameras, each amplifier produces a3275 separate collection of pixels. In the third level of our image3276 container hierarchy, the data structure \code{psChip} represents a3277 collection of different cells.3278 3279 The top level of our image container hierarchy is a complete focal3280 plane array (\code{psFPA}). This structure represents the collection3281 of chips in the camera, all of which are read out in a given3282 exposure.3283 3284 For example, take a mosaic camera consisting of eight $2k\times 4k$3285 CCDs, each of which is read out through two amplifiers. Then there3286 would be sixteen cells in total, each of which is presumably $2k\times3287 2k$. There would be eight chips, each consisting of two cells, and3288 the focal plane consists of these eight chips.3289 3290 As another example, consider an observation by PS1. The focal plane3291 would consist of 60 chips, each of which consist of 64 cells (or less;3292 a few cells may be dead). Some cells (those containing guide stars3293 for the orthogonal transfer) will contain multiple readouts.3294 3295 These data structures represent containers with which to carry around3296 the collection of related image data. There is no requirement on the3297 functions or the structures that each instance of one of these data3298 structures represent the physical hardware. For example, it is not3299 necessary that an instance of \code{psFPA} always carry the data for3300 all 60 (or 64) Gigapixel camera OTAs. The usage of these structures3301 is such that all astronomical operations which apply to a CCD image3302 should be performed on an instance of \code{psFPA}. If a particular3303 circumstance only requires a single 2D image, then that is represented3304 by an instance of \code{psFPA} with one \code{psChip}, which in turn3305 has one \code{psCell}, which in turn has one \code{psReadout}.3306 3307 These container levels also include in their definition the information3308 needed to transform the coordinates in one of the levels to the3309 coordinate system relevant at the higher levels.3310 3311 \tbd{the following discussions include astrometry issues which should3312 be deferred to the astrometry section}3313 3314 \subsubsection{A Readout}3315 3316 A readout is the result of a single read of a cell (or a portion3317 thereof). It contains a pointer to the pixel data, and additional3318 pointers to the objects found in the readout, and the readout3319 metadata. It also contains the offset from the lower-left corner of3320 the chip, in the case that the CCD was windowed.3321 3322 \begin{verbatim}3323 /** a Readout: a collection of pixels */3324 typedef struct {3325 const int x0, y0; ///< Offset from the lower-left corner3326 const int nx, ny; ///< Image binning3327 psImage *image; ///< imaging area of cell3328 psDlist *objects; ///< objects derived from cell3329 psMetadata *md; ///< Readout-level metadata3330 } psReadout;3331 \end{verbatim}3332 3333 \subsubsection{A Cell}3334 3335 A cell consists of one or more readouts (usually only one except in the3336 case that the cell has been used for fast guiding). It also contains3337 a pointer to the cell metadata, and a pointer to its parent chip. On3338 the astrometry side, it also contains coordinate transforms from the3339 cell to the chip and, as a convenience, from the cell to the focal3340 plane. It is expected that these transforms will consist of two3341 first-order 2D polynomials, simply specifying a translation, rotation3342 and magnification; hence they are easily inverted, and there is no3343 need to add reverse transformations. We also add an additional3344 transformation, which is intended to provide a ``quick and dirty''3345 transform from the cell coordinates to the sky; this transformation3346 not guaranteed to be as precise as the ``standard'' transformation of3347 Cell $\rightarrow$ Chip $\rightarrow$ Focal Plane $\rightarrow$3348 Tangent Plane $\rightarrow$ Sky, but will be faster.3349 3350 \begin{verbatim}3351 /** a Cell: a collection of readouts.3352 */3353 typedef struct {3354 int nReadouts; ///< number of readouts in this cell realization; each may have its3355 ///< own image, objects and overscan.3356 struct psReadout *readouts; ///< Readouts from the cell3357 psMetadata *md; ///< Cell-level metadata3358 3359 psPlaneCoordXform *cellToChip; ///< Transformations from cell coordinates to chip coordinates3360 psPlaneCoordXform *cellToFPA; ///< Transformations from cell coordinates to FPA coordinates3361 psPlaneCoordXform *cellToSky; ///< Quick and Dirty transformations from cell coordinates to sky3362 3363 struct psChip *parentChip; ///< chip which contains this cell3364 } psCell;3365 \end{verbatim}3366 3367 3368 \subsubsection{A Chip}3369 3370 A chip consists of one or more cells (according to the number of3371 amplifiers on the CCD). It contains a pointer to the chip metadata,3372 and a pointer to the parent focal plane. For astrometry, it contains3373 a coordinate transform from the chip to the focal plane. It is3374 expected that this transforms will consist of two second-order 2D3375 polynomials; hence we think that it is prudent to include a reverse3376 transformation which will be derived from numerically inverting the3377 forward transformation.3378 3379 \begin{verbatim}3380 /** a Chip: a collection of cells. Not all valid cells in a chip need to be listed in an3381 * instance of psChip.3382 */3383 typedef struct {3384 int nCells; ///< Number of Cells assigned3385 struct psCell *cells; ///< Cells in the Chip3386 3387 psMetadata *md; ///< Chip-level metadata3388 psPlaneCoordXform *chipToFPA; ///< Transformations from chip coordinates to FPA coordinates3389 psPlaneCoordXform *FPAtoChip; ///< Transformations from FPA coordinates to chip3390 3391 struct psFPA *parentFPA; ///< FPA which contains this chip3392 } psChip;3393 \end{verbatim}3394 3395 \subsubsection{A Focal Plane}3396 3397 A focal plane consists of one or more chips (according to the number3398 of pieces of contiguous silicon). It contains pointers to the focal3399 plane metadata and the exposure information. For astrometry, it3400 contains a transformation from the focal plane to the tangent plane3401 and the fixed pattern residuals. It is expected that the3402 transformation will consist of two 4D polynomials (i.e.\ a function of3403 two coordinates in position, the magnitude of the object, and the3404 color of the object) in order to correct for optical distortions and3405 the effects of the atmosphere; hence we think that it is prudent to3406 include a reverse transformation which will be derived from3407 numerically inverting the forward transformation. Since colors are3408 involved in the transformation, it is necessary to specify the color3409 the transformation is defined for. We also include some values to3410 characterize the quality of the transformation: the root mean square3411 deviation for the x and y transformation fits, and the $\chi^2$ for3412 the transformation fit.3413 3414 \begin{verbatim}3415 /** a Focal plane array: a collection of chips. Not all chips in a camera need to be listed in an instance of3416 * psFPA.3417 */3418 typedef struct {3419 int nChips; ///< Number of Cells assigned3420 int nAlloc; ///< Number of Cells available3421 struct psChip *chips; ///< Chips in the Focal Plane Array3422 3423 psMetadata *md; ///< FPA-level metadata3424 psPlaneDistortion *TPtoFP; ///< Transformation term from3425 psPlaneDistortion *FPtoTP; ///< Transformation term from3426 psFixedPattern *pattern; ///< Fixed pattern residual offsets3427 const psExposure *exp; ///< information about this exposure3428 psPhotSystem colorPlus, colorMinus; ///< Colour reference3429 float rmsX, rmsY; ///< Dispersion in astrometric solution3430 float chi2; ///< chi^2 of astrometric solution3431 } psFPA;3432 \end{verbatim}3433 3434 \subsubsection{Exposure information}3435 3436 We need several quantities from the telescope in order to make a3437 first guess at the astrometric solution. From these quantities,3438 further quantities can be derived and stored for later use.3439 3440 \begin{verbatim}3441 /** Exposure information from the telescope */3442 typedef struct {3443 // Telescope longitude, latitude and height are stored separately, since they don't change with pointing3444 const double ra, dec; ///< Telescope boresight3445 const double ha; ///< Hour angle3446 const double zd; ///< Zenith distance3447 const double az; ///< Azimuth3448 const double lst; ///< Local Sidereal Time3449 const float mjd; ///< MJD of observation3450 const float rotAngle; ///< Rotator position angle3451 const float temp; ///< Air temperature, for estimating refraction3452 const float pressure; ///< Air pressure, for calculating refraction3453 const float humidity; ///< Relative humidity, for calculating refraction3454 const float exptime; ///< Exposure time3455 /* Derived quantities */3456 const float posAngle; ///< Position angle3457 const float parallactic; ///< Parallactic angle3458 const float airmass; ///< Airmass, calculated from zenith distance3459 const float pf; ///< Parallactic factor3460 const char *cameraName; ///< name of camera which provided exposure3461 const char *telescopeName; ///< name of telescope which provided exposure3462 } psExposure;3463 \end{verbatim}3464 3465 3466 \subsubsection{Constructors and Destructors}3467 3468 Each of the above structures needs an appropriate constructor and3469 destructor. Other than \code{psExposure}, which contains significant3470 non-pointer types, the constructors should not take any arguments, and3471 the destructors should only take the structure to be destroyed.3472 The constructor for \code{psExposure} is specified below.3473 3474 \begin{verbatim}3475 /** Constructor */3476 psExposure *3477 psExposureAlloc(double ra, double dec, ///< Telescope boresight3478 double ha, ///< Hour angle3479 double zd, ///< Zenith distance3480 double az, ///< Azimuth3481 double lst, ///< Local Sidereal Time3482 float mjd, ///< MJD3483 float rotAngle, ///< Rotator position angle3484 float temp, ///< Temperature3485 float pressure, ///< Pressure3486 float humidity, ///< Relative humidity3487 float exptime ///< Exposure time3488 );3489 \end{verbatim}3490 3491 3492 \subsection{Astrometry}3493 3494 Astrometry is a basic functionality required for the IPP that will be3495 used repeatedly, both for low-precision (roughly where is my favorite3496 object?) and high-precision (what is the proper motion of this star?).3497 As such, it must be flexible, yet robust. Accordingly, we will wrap3498 the StarLink Astronomy Libraries (SLALib), which has already been3499 developed.3500 3501 \subsubsection{Coordinate frames}3502 \label{sec:coordinateFrames}3503 3504 There are five coordinate frames that we need to worry about for the3505 purposes of astrometry:3506 \begin{itemize}3507 \item Cell: $(x,y)$ in pixels --- raw coordinates;3508 \item Chip: $(X,Y)$ in pixels --- the location on the silicon;3509 \item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;3510 \item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and3511 \item Sky: (RA,Dec) --- ICRS.3512 \end{itemize}3513 3514 The following steps are required to convert from the cell coordinates to3515 the sky \tbd{convert Cell-$>$Chip and Chip-$>$FP to psDistortion}:3516 \begin{itemize}3517 \item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;3518 \item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;3519 \item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =3520 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the3521 object, respectively; and3522 \item TP $\longleftrightarrow$ Sky: SLALib transformation using a3523 transform pre-computed for each pointing.3524 \end{itemize}3525 3526 Note that the transformation between the Focal Plane and the Tangent3527 Plane is a four-dimensional polynomial, in order to account for any3528 possible dependencies in the astrometry on the stellar magnitude and3529 color; the former serves as a check for charge transfer3530 inefficiencies, while the latter will correct chromatic refraction,3531 both through the atmosphere and the corrector lenses.3532 3533 We require structures to contain each of the above transformations as3534 well as the pixel data.3535 3536 \subsubsection{SLALib information}3537 3538 SLALib requires several elements to perform the transformations3539 between the tangent plane and the sky. Pre-computing these quantities3540 for each exposure means that subsequent transformations are faster.3541 For historical reasons, this structure is known colloquially as3542 ``Wallace's Grommit''.3543 3544 \begin{verbatim}3545 /** Information needed (by SLALIB) to convert Apparent to Observed Position */3546 typedef struct {3547 const double latitude; ///< geodetic latitude (radians)3548 const double sinLat, cosLat; ///< sine and cosine of geodetic latitude3549 const double abberationMag; ///< magnitude of diurnal aberration vector3550 const double height; ///< height (HM)3551 const double temperature; ///< ambient temperature (TDK)3552 const double pressure; ///< pressure (PMB)3553 const double humidity; ///< relative humidity (RH)3554 const double wavelength; ///< wavelength (WL)3555 const double lapseRate; ///< lapse rate (TLR)3556 const double refractA, refractB; ///< refraction constants A and B (radians)3557 const double longitudeOffset; ///< longitude + eqn of equinoxes + ``sidereal UT'' (radians)3558 const double siderealTime; ///< local apparent sidereal time (radians)3559 } psGrommit;3560 \end{verbatim}3561 3562 The \code{psGrommit} is calculated from telescope information for the3563 particular exposure:3564 3565 \begin{verbatim}3566 /** Constructor */3567 psGrommit *3568 psGrommitAlloc(const psExposure *exp ///< Relevant exposure3569 );3570 3571 /** Destructor */3572 void3573 psGrommitFree(psGrommit *grommit ///< Grommit to destroy3574 );3575 \end{verbatim}3576 3577 \subsubsection{Fixed Pattern}3578 3579 The fixed pattern is a correction to the general astrometric solution3580 formed by summing the residuals from many observations. The intent is3581 to correct for higher-order distortions in the camera system on a3582 coarse grid (larger than individual pixels, but smaller than a single3583 cell). Hence, in addition to the offsets, we need to specify the size3584 and scale of the grid in $x$ and $y$, as well as the origin of the3585 grid.3586 3587 \begin{verbatim}3588 /** The fixed pattern residual offsets. These are specified via a coarse grid of x and y offsets. */3589 typedef struct {3590 int nX, nY; ///< Number of elements in x and y3591 double x0, y0; ///< Position of the lower-left corner of the grid on the focal plane3592 double xScale, yScale; ///< Scale of the grid3593 double **x, **y; ///< The grid of offsets in x and y3594 } psFixedPattern;3595 \end{verbatim}3596 3597 3598 \subsubsection{Position Finding}3599 3600 We require functions to return the structure containing given3601 coordinates. For example, we want the chip that corresponds to the3602 focal plane coordinates $(p,q) = (-1.234,+5.678)$. These routines3603 handle the one-to-many problem --- i.e., for one given focal plane3604 coordinate, there are many chips that this coordinate may be3605 correspond to; these functions will select the correct one.3606 3607 3608 \begin{verbatim}3609 /** returns Chip in FPA which contains the given FPA coordinate */3610 psChip *3611 psChipInFPA (psChip *out, ///< Chip to return, or NULL3612 const psPlaneCoord *coord ///< coordinate in FPA3613 const psFPA *fpa, ///< FPA description3614 );3615 3616 /** returns Cell in Chip which contains the given chip coordinate */3617 psCell *3618 psCellInChip(psCell *out, ///< Cell to return, or NULL3619 const psPlaneCoord *coord ///< coordinate in chip3620 const psChip *chip, ///< chip description3621 );3622 3623 /** Return the cell in FPA which contains the given FPA coordinates */3624 psCell *3625 psCellInFPA(psCell *out, ///< Cell to return, or NULL3626 const psPlaneCoord *coord ///< Coordinate in FPA3627 const psFPA *fpa, ///< FPA description3628 );3629 \end{verbatim}3630 3631 3632 3633 \subsubsection{Conversion Functions}3634 3635 We require functions to convert between the various coordinate frames3636 (Section~\ref{sec:coordinateFrames}). The hierarchy of the coordinate3637 frames and the transformations between each are shown in3638 Figure~\ref{fig:coco}. The functions that employ the transformations3639 are shown in Figure~\ref{fig:cocoFunc}. In addition to3640 transformations between each adjoining coordinate frame in the3641 hierarchy, we also require higher-level functions to convert between3642 the Cell and Sky coordinate frames; these will simply perform the3643 intermediate steps.3644 3645 \begin{figure}3646 \psfig{file=coordinateFrames,height=7in,angle=-90}3647 \caption{The coordinate systems in the \PS{} IPP, and the relation3648 between each by transformations contained in the appropriate3649 structures.}3650 \label{fig:coco}3651 \end{figure}3652 3653 \begin{figure}3654 \psfig{file=coordinateConv,height=7in,angle=-90}3655 \caption{Conversion between coordinate systems by PSLib.}3656 \label{fig:cocoFunc}3657 \end{figure}3658 3659 The function prototypes are:3660 3661 \begin{verbatim}3662 /** Convert (RA,Dec) to cell and cell coordinates */3663 psPlaneCoord *3664 psCoordSkyToCell(psPlaneCoord *out, ///< Coordinates to return, or NULL3665 psCell *cell, ///< Cell to return3666 const psSphereCoord *in, ///< Input coordinates3667 const psFPA *fpa ///< FPA description3668 );3669 3670 /** Convert cell and cell coordinate to (RA,Dec) */3671 psSphereCoord *3672 psCoordCellToSky(psSphereCoord *out, ///< Coordinates to return, or NULL3673 const psPlaneCoord *coord ///< cell coordinates to transform3674 const psCell *cell, ///< Cell to get coordinates for3675 );3676 3677 /** Quick and dirty cell to (RA,Dec) --- employs cellToSky transformation */3678 psSphereCoord *3679 psCoordCellToSkyQuick(psSphereCoord *out, ///< Coordinates to return, or NULL3680 const psPlaneCoord *coord ///< cell coordinates to transform3681 const psCell *cell, ///< Cell description3682 );3683 3684 /** Convert (RA,Dec) to tangent plane coords */3685 psPlaneCoord *3686 psCoordSkyToTP(psPlaneCoord *out, ///< Coordinates to return, or NULL3687 const psSphereCoord *coord ///< input Sky coordinate3688 const psGrommit *grommit, ///< Grommit for fast conversion3689 );3690 3691 /** Convert tangent plane coords to focal plane coordinates */3692 psPlaneCoord *3693 psCoordTPtoFPA(psPlaneCoord *out, ///< Coordinates to return, or NULL3694 const psPlaneCoord *coord ///< input TP coordinate3695 const psFPA *fpa, ///< FPA description3696 );3697 3698 /** converts the specified FPA coord to the coord on the given Chip */3699 psPlaneCoord *3700 psCoordFPAtoChip (psPlaneCoord *out, ///< Coordinates to return, or NULL3701 const psPlaneCoord *coord ///< input FPA coordinate3702 const psChip *chip, ///< Chip of interest3703 );3704 3705 /** converts the specified Chip coord to the coord on the given Cell */3706 psPlaneCoord *3707 psCoordChiptoCell (psPlaneCoord *out, ///< Coordinates to return, or NULL3708 const psPlaneCoord *coord ///< input Chip coordinate3709 const psCell *cell, ///< Cell of interest3710 );3711 3712 /** converts the specified Cell coord to the coord on the parent Chip */3713 psPlaneCoord *3714 psCoordCelltoChip (psPlaneCoord *out, ///< Coordinates to return, or NULL3715 const psPlaneCoord *coord ///< input Cell coordinate3716 const psCell *cell, ///< Cell description3717 );3718 3719 /** converts the specified Chip coord to the coord on the parent FPA */3720 psPlaneCoord *3721 psCoordChiptoFPA (psPlaneCoord *out, ///< Coordinates to return, or NULL3722 const psPlaneCoord *coord ///< input Chip coordinate3723 const psChip *chip, ///< Chip description3724 );3725 3726 /** Convert focal plane coords to tangent plane coordinates */3727 psPlaneCoord *3728 psCoordFPAToTP(psPlaneCoord *out, ///< Coordinates to return, or NULL3729 const psPlaneCoord *coord ///< input FPA coordinate3730 const psFPA *fpa, ///< FPA description3731 );3732 3733 /** Convert tangent plane coords to (RA,Dec) */3734 psSphereCoord *3735 psCoordTPtoSky(psSphereCoord *out, ///< Coordinates to return, or NULL3736 const psPlaneCoord *coord ///< input TP coordinate3737 const psGrommit *grommit, ///< Grommit for fast conversion3738 );3739 3740 /** Convert Cell coords to FPA coordinates */3741 psPlaneCoord *3742 psCoordCellToFPA(psPlaneCoord *out, ///< Coordinates to return, or NULL3743 const psPlaneCoord *coord ///< Input cell coordinates3744 const psCell *cell, ///< Cell description3745 );3746 \end{verbatim}3747 3748 \subsubsection{Additional functions}3749 3750 We require additional functions to perform general functions which3751 will be useful for astrometry. Given coordinates on the sky, we3752 need to get the airmass, the parallactic angle, and an estimate of3753 the atmospheric refraction.3754 3755 \begin{verbatim}3756 /** Get the airmass for a given position and sidereal time */3757 float3758 psGetAirmass(const psSphereCoord *coord, ///< Position on the sky3759 double siderealTime, ///< Sidereal time3760 float height ///< Height above sea level3761 );3762 \end{verbatim}3763 3764 \begin{verbatim}3765 /** Get the parallactic angle for a given position and sidereal time */3766 float3767 psGetParallactic(const psSphereCoord *coord, ///< Position on the sky3768 double siderealTime ///< Sidereal time3769 );3770 \end{verbatim}3771 3772 \begin{verbatim}3773 /** Estimate atmospheric refraction, along the parallactic */3774 float3775 psGetRefraction(float colour, ///< Colour of object3776 psPhotSystem colorPlus, ///< Colour reference3777 psPhotSystem colorMinus, ///< Colour reference3778 const psExposure *exp ///< Telescope pointing information, for airmass, temp and pressure3779 );3780 \end{verbatim}3781 3782 \begin{verbatim}3783 /** Calculate the parallax factor */3784 double3785 psGetParallaxFactor(const psExposure *exp ///< Exposure details3786 );3787 \end{verbatim}3788 3789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3790 3791 \subsection{Photometry}3792 3793 3794 Photometric observations are performed in an instrumental photometric3795 system, and must be related to other photometric systems. We3796 require a data structure which defines a photometric system, as well3797 as a structure to define the transformation between photometric3798 systems.3799 3800 The photometric system is defined by the psPhotSystem structure.3801 A photometric system is identified by a human-readable \code{name}3802 (ie, SDSS.g, Landolt92.B, GPC1.OTA32.r). Each photometric system is3803 given a unique identifier \code{ID}. Observations taken with a3804 specific camera, detector, and filter represent their own photometric3805 system, and it may be necessary to perform transformations between3806 these systems. Photometric systems associated with observations from3807 a specific camera/detector/filter combination can be associated with3808 those components.3809 \begin{verbatim}3810 typedef struct {3811 const int ID; ///< ID number for this photometric system3812 const char *name; ///< Name of photometric system3813 const char *camera; ///< Camera for photometric system3814 const char *filter; ///< Filter used for photometric system3815 const char *detector; ///< Detector used for photometric system3816 } psPhotSystem;3817 \end{verbatim}3818 3819 The following structure defines the transformation between two3820 photometric systems.3821 \begin{verbatim}3822 typedef struct {3823 psPhotSystem src; ///< Source photometric system3824 psPhotSystem dst; ///< Destination photometric system3825 psPhotSystem pP, pM; ///< Primary colour reference3826 psPhotSystem sP, sM; ///< Secondary colour reference3827 float pA, sA; ///< Colour offset for primary and secondary references3828 psPolynomial3D transform; ///< Transformation from source to destination3829 } psPhotTransform;3830 \end{verbatim}3831 3832 The transformation between two photometric systems may depend on the3833 airmass of the observation and on the colors of the object of3834 interest. For a specific observation, such a transformations can be3835 defined as a polynomial function of the color of the star and the3836 airmass of the observations. If sufficient data exists, the3837 transformation between the photometric systems may include more than3838 one color, constraining the curvature of the stellar spectral energy3839 distributions. This latter term may be significant for stars which3840 are highly reddened, for example. Derived photometric quantities may3841 have been corrected for airmass variations, in which case only color3842 terms may be measurable. The structure defines the transformation3843 between a source photometric system (\code{src}) and a target3844 photometric system (\code{dst}). The photometric system of a primary3845 color is defined by \code{pP, pM} such that the color is constructed3846 as $pP - pM$. A secondary color is defined by \code{sP, sM}. For3847 both, a reference color is specified (\code{pA, sA}): the polynomial3848 transformation terms refer to colors in the form $pP - pM - pA$. The3849 transformation is specified as a 3D polynomial. For a star of3850 magnitude $M_{\rm src}$ in the source photometric system, with3851 additional magnitude information in the other systems $M_{\rm pP}$,3852 $M_{\rm pM}$, $M_{\rm sP}$, $M_{\rm sM}$, observed at an airmass of3853 $z$, the magnitude of the star in the target system $M_{\rm dst}$ is3854 given by: $M_{\rm dst} = M_{\rm src} + transform(z, M_{\rm pP} -3855 M_{\rm pM} - pA, M_{\rm sP} - M_{\rm sM} - sA)$.3856 3857 \TBD{Really want a set of polynomials defined for specific colour3858 ranges.}3859 3860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3863 3864 \subsection{Astronomical objects}3865 3866 \subsubsection{Positions of Major SS Objects}3867 3868 We require the ability to calculate the position of major Solar System3869 objects, as well as Lunar phase.3870 3871 \begin{verbatim}3872 /** Get Sun Position */3873 psSphereCoord *3874 psGetSunPos(float mjd ///< MJD to get position for3875 );3876 3877 /** Get Moon position */3878 psSphereCoord *3879 psGetMoonPos(float mjd, ///< MJD to get position for3880 double latitude, ///< Latitude for apparent position3881 double longitude ///< Longitude for apparent position3882 );3883 3884 /** Get Moon phase */3885 float3886 psGetMoonPhase(float mjd ///< MJD to get phase for3887 );3888 3889 /** Get Planet positions */3890 psSphereCoord *3891 psGetSolarSystemPos(const char *solarSystemObject, ///< Named S.S. object3892 float mjd ///< MJD to get position for3893 );3894 \end{verbatim}3895 3896 \tbd{The rest of this section is tentative}3897 3898 We may need a variety of other SLALib-type functions:3899 3900 \begin{itemize}3901 \item Lunation calculations to/from psTime3902 \item rise/set for specified object3903 \item 12 \& 18 deg twilight for closest sunrise / sunset3904 \item length of current night3905 \end{itemize}3906 3907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%3908 3909 %\appendix3910 %3911 %\pagebreak3912 %\section{API Summary: all functions}3913 %3914 %\subsection{System Utilities}3915 %\input{psSystemGroup.tex}3916 %3917 %\subsection{Data Containers}3918 %\input{psDataGroup.tex}3919 %3920 %\subsection{Math Utilities}3921 %\input{psMathGroup.tex}3922 %3923 %\subsection{Astronomy Functions}3924 %\input{psAstroGroup.tex}3925 %3926 %\pagebreak3927 %\section{API Summary: all structures}3928 %\input{psStructures.tex}3929 3930 \bibliographystyle{plain} \bibliography{panstarrs}3931 3932 \end{document}3933
Note:
See TracChangeset
for help on using the changeset viewer.
