Changeset 276
- Timestamp:
- Mar 22, 2004, 12:23:02 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/doc/pslib/psLibSDRS.tex (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/pslib/psLibSDRS.tex
r275 r276 4 4 % basic document variables 5 5 \title{Pan-STARRS IPP Library Design} 6 \author{ }6 \author{Paul Price, Eugene Magnier, Robert Lupton} 7 7 \shorttitle{PSLib Design} 8 8 \group{Pan-STARRS Algorithm Group} … … 67 67 \section{System Utilities} 68 68 69 \note{INSERT HERE STUFF FROM RHL'S \file{utils.pdf}} 70 71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 69 \subsection{Memory Management} 70 \hlabel{psMemBlock} 71 72 \subsubsection{Introduction} 73 74 The \PS{} software system will need a level of memory management 75 placed between the operating system (malloc/free) and the high level 76 routines (e.g. \code{psMetaDataAlloc}). 77 78 This layer is in addition to the possibility that specific heavily 79 used data types may need their own special-purpose memory managers; 80 but as we have specified that all user-level objects be allocated via 81 \code{typeAlloc/typeFree} functions, we will easily be able to 82 implement such functionality without impacting on the facilities 83 described here. 84 85 All of the memory management APIs should be provided in a header file 86 \file{psMemory.h} which is included by \file{psUtils.h}. 87 88 \subsubsection{Rationale} 89 90 We wish to insert our own layer of memory management for a number of 91 reasons: 92 93 \begin{itemize} 94 \item 95 We wish to insulate ourselves from the details of the system-provided 96 \code{malloc}. There is no guarantee that the goals of the system 97 architect align with those of the \PS{} processing 98 99 \item 100 We need at least a wrapper layer which handles failed memory 101 requests without requiring the application programmer to check 102 every attempted allocation. 103 104 \item 105 We need to provide a mechanism for tracking and fixing memory 106 leaks. While it is possible to do this by linking with external 107 libraries (\tbd{reference}), it is convenient to do so within the 108 \PS{} framework. 109 110 \item 111 Similarly, we wish to provide convenient hooks to detect and diagnose 112 memory corruption. 113 114 \item 115 While debugging complex scientific code, it is very useful to be 116 able to trace a given data structure as it passed through the 117 processing pipeline. 118 119 \item 120 There may be other features that we wish to add in the future (e.g. 121 associating a type with every allocation). 122 \end{itemize} 123 124 \subsubsection{A Minimal Specification} 125 126 The previous section laid out a number of desiderata for a memory 127 management system. Rather than implement our own heap-manager at this 128 stage of the project, I propose that we put in place a sufficient 129 set of data structures and APIs, but initially implement only 130 a simple subset (e.g. that we not implement a multi-bucket memory 131 manager that takes in 100Mb chunks from the system and performs 132 sophisticated defragmentation and garbage collection). 133 134 Subject to agreement with the IfA, some of the functions proposed 135 here may be omitted from the initial implementation; in particular 136 the routines \code{psMemCheckCorruption} and \code{psMemCheckLeaks} 137 may be hard to build efficiently in a simple implementation based 138 upon adding extra fields to allocation requests. 139 140 \paragraph{Extra information to be saved by Memory Allocation Functions} 141 142 It is required that a table of all allocated memory blocks be 143 maintained by the \PS{} memory system. 144 145 Each allocated block should preserve at least the information present 146 in the following struct definition: 147 \begin{verbatim} 148 typedef struct { 149 const unsigned long id; // a unique ID for this allocation 150 const char *file; // set from __FILE__ in e.g. p_psAlloc 151 const int lineno; // set from __LINE__ in e.g. p_psAlloc 152 int refcntr; // how many times pointer is referenced 153 const void *magic; // initialised to P_PS_MEMMAGIC 154 } psMemBlock; 155 \end{verbatim} 156 157 The value of \code{P_PS_MEMMAGIC} shall be \code{(void *)0xdeadbeef}% 158 \footnote{Why this choice? Tradition, and because it's easy to notice 159 in a hex dump.} 160 161 \paragraph{APIs for using Memory Allocation Functions} 162 163 \begin{table} 164 \begin{verbatim} 165 void *psAlloc(size_t size); 166 void *psRealloc(void *ptr, size_t size); 167 void psFree(void *ptr); 168 169 void *p_psAlloc(size_t size, const char *file, int lineno); 170 void *p_psRealloc(void *ptr, size_t size, const char *file, int lineno); 171 void p_psFree(void *ptr, const char *file, int lineno); 172 173 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__) 174 #define psRealloc(ptr, size) p_psRealloc(ptr, size, __FILE__, __LINE__) 175 #define psFree(size) p_psFree(size, __FILE__, __LINE__) 176 \end{verbatim} 177 \begin{caption}{The APIs required to use the \PS{} memory allocation routines} 178 \hlabel{tabUsageAPI} 179 The APIs required to use the \PS{} memory allocation routines, and as 180 provided by \file{psMemory.h}. 181 \end{caption} 182 \end{table} 183 184 The types and function prototypes for the part of the memory API 185 concerned with allocating and freeing memory are given in table 186 \ref{tabUsageAPI}). 187 188 N.b. 189 \begin{itemize} 190 \item 191 The functions \code{psAlloc}, \code{psRealloc}, and 192 \code{psFree} are defined, and are required to be equivalent to 193 \code{p_psAlloc}, \code{p_psRealloc}, and \code{p_psFree} 194 with the final two arguments \code{"(unknown)"} and \code{0}. 195 196 In the descriptions that follow, I shall not distinguish between the 197 functions with and without the \code{p_} prefix. 198 199 \item 200 Except as specified below, the functions \code{psAlloc}, 201 \code{psRealloc}, and \code{psFree} have identical semantics 202 to the standard C library functins \code{malloc}, \code{realloc}, 203 and \code{free}. 204 205 \item 206 The file \file{psMemory.h} shall take steps to ensure that 207 code calling the functions \code{malloc}, \code{calloc}, \code{realloc}, 208 or \code{free} shall not compile (\eg{} \code{#define malloc(S) for}) 209 unless the symbol \code{PS_ALLOC_MALLOC} is defined. 210 211 \item 212 In all cases, application code will call 213 \code{p_\{psAlloc,psRealloc,psFree\}} via the macros defined above. 214 215 \item 216 The functions \code{psAlloc} and \code{psRealloc} shall never 217 return a \code{NULL} pointer. If they are unable to provide 218 the requested memory they should attempt to obtain the desired 219 memory by calling the routine registered by \code{psMemExhaustedSetCB} (see 220 subsubsection \ref{secMemAdvanced}), and if still unsuccessful, 221 call \code{abort()}. 222 223 \item 224 The memory management routines shall maintain the field 225 \code{psMemBlock.refcntr}. It should be set to \code{1} 226 when a block is returned to the user. It is an error to 227 attempt to free a block with \code{psMemBlock.refcntr != 1} 228 (see subsubsection \ref{secMemRefcounter}). 229 230 \item 231 Where practical and efficient, the memory manager shall call 232 the routine registered using the \code{psMemProblemSetCB} 233 (see section \ref{secMemAdvanced}) 234 whenever a corrupted block of memory is discovered. For example, 235 doubly-freed blocks can be detected by checking \code{psMemBlock.refcntr}. 236 237 \item 238 There is no \code{psCalloc} function. Initialisation of data is 239 almost always more complex than setting all bytes to 0. 240 \end{itemize} 241 242 \paragraph{APIs for Tracing and Debugging Memory} 243 \hlabel{secMemAdvanced} 244 245 \begin{table} 246 \begin{verbatim} 247 typedef int (*psMemCallback)(const psMemBlock *ptr); 248 typedef void (*psMemProblemCallback)(const psMemBlock *ptr, 249 const char *file, int lineno); 250 typedef void *(*psMemExhaustedCallback)(size_t size); 251 252 psMemProblemCallback psMemProblemSetCB(psMemProblemCallback func); 253 psMemExhaustedCallback psMemExhaustedSetCB(psMemExhaustedCallback func); 254 255 psMemCallback psMemAllocateSetCB(psMemCallback func); 256 psMemCallback psMemFreeSetCB(psMemCallback func); 257 258 int psMemGetId(void); // get next memory ID 259 260 long psMemSetAllocateID(long id); // set p_psMemAllocateID to id 261 long psMemSetFreeID(long id); // set p_psMemFreeID to id 262 263 int psMemCheckLeaks( 264 int id0, // don't list blocks with id < id0 265 psMemBlock ***arr, // pointer to array of pointers to 266 //leaked blocks, or NULL 267 FILE *fd); // print list of leaks to fd (or NULL) 268 int psMemCheckCorruption(int abort_on_error); 269 \end{verbatim} 270 \begin{caption}{The APIs required to use the \PS{} memory allocation routines} 271 \hlabel{tabCallbackAPI} 272 The APIs required to use the callback and tracing facilities 273 in \PS{} memory allocation routines, as defined in \file{psMemory.h}. 274 \end{caption} 275 \end{table} 276 277 The types and function prototypes for this part of the memory API 278 are given in table \ref{tabCallbackAPI}. 279 280 \paragraph{Callback Routines} 281 282 The four `\code{SetCB}' routines are: 283 284 \begin{tabular}{ll|l} 285 \textbf{type} & \textbf{Name} & \textbf{Function of callback} \\ 286 psMemProblemCallback & psMemProblemSetCB & 287 Called when a problem is detected with data being managed on the heap \\ 288 psMemExhaustedCallback & psMemExhaustedSetCB & 289 Called when \code{psAlloc} is unable to satisfy a memory request. \\ 290 psMemCallback & psMemAllocateSetCB & 291 Callback is called when the \code{psMemBlock} with a specified ID is 292 allocated. \\ 293 psMemCallback & psMemFreeSetCB & 294 Callback is called when the \code{psMemBlock} with a specified ID is 295 freed. \\ 296 \end{tabular} 297 298 N.b. 299 \begin{itemize} 300 \item 301 In all cases, the `\code{SetCB}' routine takes a pointer to the 302 desired callback function, and returns a pointer to the one that was 303 previously installed. If the function pointer is \code{NULL}, the 304 default callback function is reinstalled. 305 306 \item 307 The routine installed by \code{psMemExhaustedSetCB} should return 308 a pointer to the desired memory or \code{NULL}; in the latter case 309 \code{psAlloc} will call \code{abort()} 310 311 \item 312 \code{psMemGetId} returns the current value of \code{psMemBlock.id}. 313 314 \item 315 The handler specified by \code{psMemAllocateSetCB} is called just 316 before the pointer with \code{psMemBlock.id} equal to 317 \code{p_psMemAllocateID} is returned to the user. The variable 318 \code{p_psMemAllocateID} should not be set directly in any 319 delivered code, \code{psMemSetAllocateID} should be used instead. 320 321 \item 322 The handler specified by \code{psMemFreeSetCB} is called just 323 before the pointer with \code{psMemBlock.id} equal to 324 \code{p_psMemFreeID} is freed. The variable 325 \code{p_psMemFreeID} should not be set directly in any delivered 326 code, \code{psMemSetFreeID} should be used instead. 327 328 \item 329 The routines \code{psMemSetFreeID} and \code{psMemSetAllocateID} 330 accept the desired ID value (see previous two items) and return 331 the old value to the user. 332 333 \item 334 The return values of the handlers installed by \code{psMemAllocateSetCB} 335 and \code{psMemFreeSetCB} are used to increment the values of 336 \code{p_psMemAllocateID} and \code{p_psMemFreeID} respectively. 337 338 For example, the return value \code{0} implies that the value is unchanged; 339 if the value is \code{2} the callback will be called again when the 340 memory ID counter has increased by two. 341 \end{itemize} 342 343 \paragraph{Memory Tracing and Corruption Routines} 344 345 The routine \code{psMemCheckLeaks} may be used to check for memory 346 leaks. The return value is the number of blocks that have been 347 allocated but not freed. 348 349 Only blocks with \code{psMemBlock.id} greater than \code{id0} 350 are checked; this allows the user to ignore blocks allocated 351 by initialisation routines. 352 353 If the argument \code{arr} is non-\code{NULL}, then upon entering 354 the call \code{**arr} should be \code{NULL}. Upon return it is set 355 to an array of \code{psMemBlock *} pointers, one for each block 356 allocated but not freed. It is the caller's responsibility to free 357 this array with \code{psFree}. 358 359 If the argument \code{fd} is non\code{NULL}, a one-line summary 360 of each block that has been allocated but not freed is written to that 361 file descriptor. 362 363 The routine \code{psMemCheckCorruption} checks the entire heap for 364 corruption, calling the routine registered with 365 \code{psMemProblemSetCB} for each block detected as being corrupted. 366 The return value is the number of corrupted blocks detected. If the 367 argument \code{abort_on_error} is true, 368 \code{psMemCheckCorruption} shall call \code{abort()} as soon as 369 memory corruption is detected. 370 371 \paragraph{Reference Counting} 372 \hlabel{secMemRefcounter} 373 374 The memory management routines include a field 375 \code{psMemBlock.refcntr} which must equal \code{1} whenever 376 a pointer is presented to \code{psFree}. 377 378 The API for this field is: 379 \begin{verbatim} 380 int psMemGetRefCounter(void *vptr); // return refcounter 381 void *psMemIncrRefCounter(void *vptr); // increment refcounter and return vptr 382 void *psMemDecrRefCounter(void *vptr); // decrement refcounter and return vptr 383 \end{verbatim} 384 385 The functions \code{psMemIncrRefCounter} and \code{psMemDecrRefCounter} shall 386 return \code{NULL} if passed a \code{NULL} pointer. 387 388 \subsubsubsection{Rationale} 389 390 \begin{table} 391 \begin{verbatim} 392 typedef struct { 393 char *name; 394 int value; 395 } psSimple; 396 397 psSimple *psSimpleAlloc(const char *name, int val) 398 { 399 psSimple *simp = psAlloc(sizeof(psSimple)); 400 simp->name = strcpy(psAlloc(strlen(name) + 1), name); 401 simp->value = val; 402 403 return simp; 404 } 405 406 void psSimpleFree(psSimple *simp) 407 { 408 if (simp == NULL) { return; } 409 410 if (psMemGetRefCounter(simp) > 1) { 411 (void)psMemDecrRefCounter(simp); 412 return; 413 } 414 } 415 \end{verbatim} 416 \begin{caption}{An example of reference counting} 417 \hlabel{tabReferenceCounting} 418 An example of using reference counting 419 \end{caption} 420 \end{table} 421 422 The \code{psMemBlock.refcounter} is clearly useful for detecting 423 attempts to free memory that is already free. A more complex 424 application is for allowing pointers to complex data-objects (e.g. 425 images) to appear in more than one data structure simultaneously 426 (see table \ref{tabReferenceCounting}). 427 428 Because of the use of the \code{refcounter} field, we can safely put items of 429 this type onto many lists: 430 \goodbreak 431 \begin{verbatim} 432 simp = psSimpleAlloc("RHL", 0); 433 psDlistAppend(list1, psMemIncrRefCounter(simp)); 434 psDlistAppend(list2, psMemIncrRefCounter(simp)); 435 psSimpleFree(simp); 436 \end{verbatim} 437 438 (Note: in fact there is no need to explicitly increment the counter 439 in this case, as the \code{psDlistAppend} (section \ref{psDlist}) 440 API specifies that it 441 does it for you.) 442 443 \subsection{Tracing and Logging} 444 445 This document defines the \PS{} Tracing and Logging APIs; the former 446 refers to debug information that we wish to be able to turn on and off 447 without recompiling (although it will \emph{not} be available in 448 production code); the latter means information about the processing 449 that must be collected and saved, even in the production system. 450 451 We envision that we will make extensive use of \code{psTrace} throughout 452 the \PS{} code. 453 454 \subsubsection{Tracing APIs} 455 \hlabel{psTrace} 456 457 \begin{table} 458 \begin{verbatim} 459 #if defined(PS_NTRACE) 460 # define psTrace(facil, level, ...) /* do nothing */ 461 #else 462 # define psTrace(facil, level, ...) \ 463 p_psTrace(facil, level, __VA_ARGS__) 464 #endif 465 466 void p_psTrace(const char *facil, int level, ...); 467 468 int psSetTraceLevel(const char *facil, // facilty of interest 469 int level); // desired trace level 470 int psGetTraceLevel(const char *name); // facilty of interest 471 472 void psTraceReset(void); // turn off all tracing, and free trace's allocated memory 473 474 void psPrintTraceLevels(void); // print trace levels 475 \end{verbatim} 476 \begin{caption}{The public API for the trace facility 477 from \file{psTrace.h}.} 478 \hlabel{tabTraceAPI} 479 \end{caption} 480 \end{table} 481 482 The public API for the trace facility (table \ref{tabTraceAPI}) 483 should be provided in a header file \file{psTrace.h} which 484 is included by \file{psUtils.h}. 485 486 \begin{itemize} 487 \item 488 Logging is provided by the function \code{psTrace}, 489 which is actually a macro. When the macro \code{PS_NTRACE} 490 is defined, all occurrences of \code{psTrace} shall 491 be replaced by whitespace. 492 493 \item 494 The first argument to \code{psTrace} is a name of the form 495 \code{aaa.bbb.ccc}. The second is an integer, 496 \code{level}. The remaining arguments are a printf-style format 497 and a (possibly empty) set of values for that formatting 498 string. When this trace is active, \code{psTrace} shall generate 499 the requested output on \code{stdout}, preceded by \code{level} 500 spaces. 501 502 \item 503 The call \code{psSetTraceLevel(name, level)} shall set the trace 504 level for \code{name} to \code{level}. 505 506 \item 507 The call \code{psGetTraceLevel(name)} shall return the level 508 associated with \code{name}. If \code{name} has not been 509 associated with a level, the routine shall remove the \textit{last} 510 element of \code{name} and attempt to look up its level; this 511 procedure shall be applied recursively until the name is reduced 512 to \code{""}; if this name has no level associated with 513 it, then the value \code{0} shall be returned (see examples 514 below). 515 516 \item 517 The call \code{psTrace(name, level, ...)} 518 shall print the message if and only if 519 \code{psGetTraceLevel(name)} returns a value greater than 520 or equal to \code{level}. 521 522 \item 523 \code{psPrintTraceLevels} shall print a listing of all 524 declared levels, displayed as a hierarchy with sub-components 525 sorted within each component (see examples below). 526 527 Note in particular that the root of the tree, the name \code{""} 528 should print as \code{(root)}, and nodes which have not 529 been assigned a value should list their level as \code{.}. 530 531 \item 532 All of the tracing facilities shall be SWIGed, with the exception 533 of \code{p_psTrace}. 534 535 \item 536 There is no requirement that \code{psTrace} be usable from 537 within the functions that implement \file{psTrace.h} 538 or \file{psMemory.h} systems. 539 540 \item 541 \code{psTraceReset} shall reset all tracing to the state that it 542 had at program initiation, including freeing any memory that the 543 tracing subsystem may have allocated. 544 \end{itemize} 545 546 \paragraph{Examples of the use of Tracing Facilities} 547 548 For example, after the commands: 549 \begin{verbatim} 550 psSetTraceLevel("utils.dlist.add.head", 9); 551 psSetTraceLevel("utils.dlist.add", 3); 552 psSetTraceLevel("utils.dlist.remove", 4); 553 psSetTraceLevel("coadd", 2); 554 psSetTraceLevel("coadd.CR.remove.morphology", 5); 555 psSetTraceLevel("utils.hash", 2); 556 psSetTraceLevel("utils.dlist.add", 9); 557 psSetTraceLevel("utils", 1); 558 \end{verbatim} 559 the command \code{psPrintTraceLevels()} should print: 560 \begin{verbatim} 561 (root) 0 562 utils 1 563 hash 2 564 dlist . 565 remove 4 566 add 9 567 head 9 568 coadd 2 569 CR . 570 remove . 571 morphology 5 572 \end{verbatim} 573 where \code{.} means that the trace level should be inherited from its parent. 574 575 After this set of \code{psSetTraceLevel} commands, and if 576 \code{PS_NTRACE} is not defined, the following commands 577 \begin{verbatim} 578 psTrace("utils.dlist.remove", 2, "Removing psDList key \"%s\"\n", "my_key"); 579 psTrace("utils", 2, "Initialising utilities library\n"); 580 psTrace("", 2, "This is turned on by trace component \"\""); 581 psTrace("utils.dlist", 2, "Initialising psDList\n"); 582 psTrace("utils.dlist.remove", 4, "Removing psDList key \"%s\" (value: \"%d\")\n", "my_key", 12345); 583 psTrace("utils.hash.remove", 4, "Removing hash key \"%s\" (value: \"%d\")\n", "my_key", 12345); 584 psTrace("utils.dlist.add", 1, "Adding psDList key \"%s\"\n", "your_key"); 585 psTrace("utils.dlist.find", 2, "Looking up psDList key \"%s\"\n", "some_key"); 586 psTrace("coadd.CR.remove", 4, "Removing CRs\n"); 587 psTrace("coadd.CR.remove.morphology", 4, "CRs are not fuzzy\n"); 588 \end{verbatim} 589 should produce this output: 590 \begin{verbatim} 591 Removing psDList key "my_key" 592 Removing psDList key "my_key" (value: "12345") 593 Adding psDList key "your_key" 594 CRs are not fuzzy 595 \end{verbatim} 596 597 Note that 598 \begin{description} 599 \item 600 \code{utils.dlist} messages are at level 1, inherited from \code{utils}, so the 601 \code{Initialising utilities library}, \code{Initialising psDList}, and 602 \code{Looking up psDList key} messages are \emph{not} printed (the traces are at level 2). 603 604 \item 605 \code{utils.dlist.remove} messages are at level 4, and are printed. 606 607 \item 608 \code{utils.hash} messages are at level 2, and are not printed (the traces are at level 4) 609 610 \item 611 \code{coadd.CR.remove} is at level 2 (inherited from \code{coadd}) so \code{Removing CRs} 612 isn't printed. \code{coadd.CR.remove.morphology} is at level 4, so \code{CRs are not fuzzy} is printed. 613 \end{description} 614 615 \subsubsection{Message Logging} 616 \hlabel{psLogMsg} 617 618 \begin{table} 619 \begin{verbatim} 620 enum { PS_LOG_ABORT = 0, PS_LOG_ERROR, PS_LOG_WARN, PS_LOG_INFO }; 621 622 enum { PS_LOG_TO_STDERR, PS_LOG_TO_STDOUT }; 623 624 void psLogMsg(const char *name, int level, const char *fmt, ...); 625 void p_psVLogMsg(const char *name, int level, const char *fmt, va_list ap); 626 627 int psSetLogDestination(int dest); 628 void psSetLogFormat(const char *fmt); 629 630 int psSetLogLevel(int level); 631 \end{verbatim} 632 \begin{caption}{API for message logging} 633 \hlabel{tabLogMsgAPI} 634 The API for message logging. 635 \end{caption} 636 \end{table} 637 638 The public API for the logging facility (table \ref{tabLogMsgAPI}) 639 should be provided in a header file \file{psLogMsg.h} which 640 is included by \file{psUtils.h}. 641 642 The function \code{psSetLogLevel} may be used to set the current 643 level of logging; the previous value is returned. 644 The default value is \code{PS_LOG_INFO}. Valid values are 0---9 645 inclusive (note that only the first four are required to have 646 symbolic names). 647 648 A call to \code{psLogMsg(name, level, msg, ...)} shall generate 649 a log message if \code{level} is less than or equal to the 650 value most recently set using \code{psSetLogLevel}. The function 651 \code{p_psLogMsg} is identical, except that it expects a 652 final \code{va_list} argument. 653 654 The format of the log message shall be of the form: 655 \begin{verbatim} 656 YYYY:MM:DD hh:mm:ssZ|hostname|l|name |msg 657 \end{verbatim} 658 \code{YYYY}, \code{MM}, \code{DD}, \code{hh}, \code{mm}, and \code{ss} 659 are the year, month (Jan == 1), day of the month, hours (0--23), 660 minutes, and seconds when the log message was received. Note that the 661 timestamp is in ISO order, and that the timezone is GMT (hence the 662 \code{Z}). 663 664 The \code{hostname} is returned by \code{gethostname}, \code{l} is a 665 letter associated with the level (\code{A}, \code{E}, \code{W}, and 666 \code{I} for \code{PS_LOG_ABORT}, \code{PS_LOG_ERROR}, \code{PS_LOG_WARN}, 667 and \code{PS_LOG_INFO} respectively. Other levels are represented 668 numerically (\code{5} etc.). The other two field, \code{name} and 669 \code{msg} are arguments to \code{psLogMsg}; note that \code{name} has 670 a fixed width of 15 characters. If \code{msg} doesn't end in a newline, 671 a single newline is emitted to terminate the message. 672 673 An example message is: 674 \begin{verbatim} 675 2004:02:24 20:14:18Z|alibaba.IfA.Hawaii.Edu|I|utils |Hello World 676 \end{verbatim} 677 678 Log messages are sent to the destination most recently set using 679 \code{psSetLogDestination}. The only two values that are initially 680 defined are \code{PS_LOG_TO_STDERR} and \code{PS_LOG_TO_STDOUT} to 681 write to \code{stderr} and \code{stdout} respectively. 682 683 The fields included in the log message may be controlled using \code{psSetLogFormat} which 684 expects a string consisting of the letters \code{H} (host), \code{L} (level), \code{M} (message), 685 \code{N} (name), and \code{T} (time). The default is \code{HLMNT}. 686 73 687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 688 … … 84 698 \end{itemize} 85 699 86 \note{INSERT HERE STUFF FROM RHL'S \file{utils.pdf}} 700 \subsection{The Pan-STARRS \texttt{psDlist} doubly-linked list type} 701 \hlabel{psDlist} 702 703 Pan-STARRS supports doubly linked lists through a type \code{psDlist}. 704 The type is defined in the header file \file{psDlist.h}, and consists 705 of the following definitions: 706 707 \begin{verbatim} 708 typedef struct psDlistElem { 709 struct psDlistElem *prev; // previous link in list 710 struct psDlistElem *next; // next link in list 711 void *data; // real data item 712 } psDlistElem; 713 714 typedef struct { 715 int n; // number of elements on list 716 psDlistElem *head; // first element on list (may be NULL) 717 psDlistElem *tail; // last element on list (may be NULL) 718 psDlistElem *iter; // iteration cursor; private 719 } psDlist; 720 721 enum { // Special values of index into list 722 psDlistHead = 0, // at head 723 psDlistTail = -1, // at tail 724 psDlistUnknown = -2, // unknown position 725 psDlistPrev = -3, // previous element 726 psDlistNext = -4 // next element 727 }; 728 \end{verbatim} 729 730 The API is: 731 732 \begin{verbatim} 733 psDlist *psDlistAlloc(void *data); // initial data item; may be NULL 734 735 void psDlistFree(psDlist *list, // list to destroy 736 void (*elemFree)(void *)); // destructor for list data, or NULL 737 738 /* 739 * List maintainence functions 740 */ 741 psDlist *psDlistAdd(psDlist *list, // list to add to (may be NULL) 742 void *data, // data item to add 743 int where); // index, psDlistHead, or psDlistTail 744 psDlist *psDlistAppend(psDlist *list, // list to append to (may be NULL) 745 void *data); // data item to add 746 void *psDlistRemove(psDlist *list, // list to remove element from 747 void *data, // data item to remove 748 int which); // index of item, or psDlistUnknown, 749 // or psDlistNext, or psDlistPrev 750 void *psDlistGet(const psDlist *list, // list to retrieve element from 751 int which); // index of item, or psDlistNext, 752 // or psDlistPrev 753 /* 754 * Conversions to/from arrays 755 */ 756 psVoidPtrArray *psDlistToArray(psDlist *dlist); 757 psDlist *psArrayToDlist(psVoidPtrArray *arr); 758 \end{verbatim} 759 760 All data items placed onto lists (e.g. with \code{psDlistAdd}) 761 shall have their reference counters (section \ref{secMemRefcounter}) incremented. 762 When elements 763 are removed from a list with \code{psDlistRemove}, they shall 764 have their reference counters decremented. The action of retrieving 765 data from a list (with \code{psDlistGet}) shall not affect 766 their reference counter. 767 768 If \code{psDlistFree}'s argument \code{elemFree} is NULL, the 769 list should be deleted, but not the elements on it (although their 770 \code{refcounter}'s should be decremented). 771 772 Iteration over all elements of the list is provided by the functions: 773 \begin{verbatim} 774 void psDlistSetIterator(psDlist *list, int where, int which); 775 void *psDlistGetNext(psDlist *list, int which); 776 void *psDlistGetPrev(psDlist *list, int which); 777 \end{verbatim} 778 in which the \code{where} argument must be \code{PS_DLIST_HEAD} or \code{PS_DLIST_TAIL}, 779 to start at the head or tail of the list, and \code{psDlistGetNext} and \code{psDlistGetPrev} 780 return the next/previous element. The argument \code{which} identifies which of potentially 781 many iteration cursors should be used; it must currently always be \code{0}. 782 783 Explicit traversal of the list using the \code{psDlistElem}'s 784 \code{prev} and \code{next} pointers is also supported. 785 786 The routines to convert to and from \code{psVoidPtrArray}s, 787 \code{psDlistToArray} and \code{psArrayToDlist} shall ensure that the 788 objects on the arrays and lists have had their reference pointers 789 correctly incremented (see section \ref{secArrayVoidPtr}) (\eg{} that 790 \code{psArrayToDlist(psDlistToArray(list))} returns a properly-formed 791 \code{psDlist}). 792 793 \subsection{The \PS{} Array types} 794 795 \begin{table} 796 \begin{verbatim} 797 \end{verbatim} 798 \begin{caption}{The array creation macros defined in \file{psArray.h}} 799 \hlabel{tabPsArray} 800 \end{caption} 801 \end{table} 802 803 \subsubsection{Arrays of Simple Types} 804 805 Any \PS/ datatype \code{psType} may be associated with an array type 806 \code{psTypeArray}: 807 \begin{verbatim} 808 typedef struct { 809 int size; 810 int n; 811 psType *arr; 812 } psTypeArray; 813 \end{verbatim} 814 with associated constructors and a destructor: 815 \begin{verbatim} 816 psTypeArray *psTypeAlloc(int n, int size); 817 psTypeArray *psTypeRealloc(psTypeArray *arr, int n); 818 void psTypeFree(psTypeArray *arr); 819 \end{verbatim} 820 821 The argument \code{n} is the dimension of the array; \code{size} 822 is the number of elements allocated ($s \ge n$). 823 824 This type and functions may be declared and defined using two macros 825 from \file{psArray.h} (table \ref{tabPsArray}), 826 \code{PS_DECLARE_ARRAY_TYPE(psType)} and 827 \code{PS_CREATE_ARRAY_TYPE(psType)}. The former defines the typedef 828 and declares the prototypes (and is thus suitable for use in a 829 header file); the latter generates the code for the three functions 830 \code{psType(Alloc|Realloc|Free} (and should thus appear in exactly one 831 source file for a given type). 832 833 The \code{psType} should be a single word (e.g. \code{psXY}); in particular, 834 there is no requirement to support a pointer type (\eg{} \code{psXY *}); 835 see next section. 836 837 \subsubsection{Arrays of Pointer Types} 838 839 The data type created with \code{PS_CREATE_ARRAY_TYPE} (\code{psType}) 840 contains an array of \code{psType}s not 841 pointers to \code{psType}s; this means that the individual elements are 842 not allocated using \code{psTypeAlloc}, are not correctly initialized, 843 and shouldn't be individually deleted with \code{psTypeFree}; 844 845 If you wish to use arrays of pointers, use the macros 846 \code{PS_DECLARE_ARRAY_PTR_TYPE(psType)} and 847 \code{PS_CREATE_ARRAY_PTR_TYPE(psType)} (table \ref{tabPsArray}). These 848 create types \code{typedef psType *psTypePtr} and \code{psTypePtrArray}: 849 \begin{verbatim} 850 typedef struct { 851 int size; 852 int n; 853 psTypePtr *arr; 854 } psTypePtrArray; 855 \end{verbatim} 856 with associated constructors and a destructor: 857 \begin{verbatim} 858 psTypePtrArray *psTypePtrAlloc(int n, int size); 859 psTypePtrArray *psTypePtrRealloc(psTypePtrArray *arr, int n); 860 void psTypePtrArrayFree(psTypePtrArray *arr); 861 \end{verbatim} 862 863 These constructors create arrays of \code{psType *} and call 864 \code{psTypeAlloc} and \code{psTypeFree} to allocate and free the 865 elements. As for the simple arrays, The former defines the typedef and 866 declares the prototypes (and is thus suitable for use in a header 867 file) and the latter generates the code for the three functions 868 \code{psType(Alloc|Realloc|Free} (and should thus appear in exactly one 869 source file for a given type). 870 871 The objects pointed to by these types have had their \code{refCounter}s 872 incremented (see \ref{secMemRefcounter}); to remove an element from the array you 873 need to say something like: 874 \begin{verbatim} 875 psTypePtrArray *pt = psTypePtrArrayAlloc(10, 10); 876 psType *xy = psMemDecrRefCounter(pt->arr[0]); 877 pt->arr[0] = NULL; 878 \end{verbatim} 879 880 \subsubsection{Arrays of \texttt{void *}} 881 \hlabel{secArrayVoidPtr} 882 883 Arrays of \code{void *} are different, as the need an explicitly-specified 884 destructor. 885 886 \file{psArray.h} shall specify a type \code{psVoidPtrArray} that 887 behaves in all respects as if it had been created with: 888 \begin{verbatim} 889 typedef void *psVoidPtr; 890 PS_DECLARE_ARRAY_TYPE(psVoidPtr); 891 PS_CREATE_ARRAY_TYPE(psVoidPtr); 892 \end{verbatim} 893 except that its destructor is specified as: 894 \begin{verbatim} 895 void psVoidPtrArrayFree(psVoidPtrArray *arr, // array to destroy 896 void (*elemFree)(void *)); // destructor for array data 897 \end{verbatim} 898 899 The routine \code{psVoidPtrArrayFree} assumes that all pointers 900 had their reference counters incremented 901 when they were inserted onto the array.\footnote{% 902 \eg{} \code{va->arr[i] = psMemIncrRefCounter(ptr);}} 903 904 If \code{psVoidPtrArrayFree}'s argument \code{elemFree} is NULL, the 905 list should be deleted, but not the elements on it (although their 906 \code{refcounter}'s should be decremented). 907 908 \subsubsection{Examples of Array Types} 909 910 The following is a complete C program that illustrates the use of 911 \code{array}s. 912 \begin{verbatim} 913 #include "psUtils.h" 914 915 typedef struct { 916 int x, y; 917 } psXY; 918 919 psXY *psXYAlloc(void) 920 { 921 return psAlloc(sizeof(psXY)); 922 } 923 924 void psXYFree(psXY *xy) 925 { 926 psFree(xy); 927 } 928 929 PS_DECLARE_ARRAY_TYPE(psXY); 930 PS_CREATE_ARRAY_TYPE(psXY); 931 932 PS_DECLARE_ARRAY_PTR_TYPE(psXY); 933 PS_CREATE_ARRAY_PTR_TYPE(psXY); 934 935 int main(void) 936 { 937 psXYArray *t = psXYArrayAlloc(10, 15); 938 psXYPtrArray *pt = psXYPtrArrayAlloc(10, 10); 939 940 for (int i = 0; i < t->n; i++) { 941 t->arr[i].x = i; 942 pt->arr[i]->y = 10*i; 943 } 944 945 t = psXYArrayRealloc(t, 5); 946 t = psXYArrayRealloc(t, 8); 947 948 for (int i = 0; i < t->n; i++) { 949 printf("%d %d ", t->arr[i].x, pt->arr[i]->y); 950 } 951 printf("\n"); 952 953 psXYArrayFree(t); 954 955 psXY *xy = psMemDecrRefCounter(pt->arr[0]); 956 pt->arr[0] = NULL; 957 psXYFree(xy); 958 959 psXYPtrArrayFree(pt); 960 961 psMemCheckLeaks(0, NULL, stderr); 962 963 return 0; 964 } 965 \end{verbatim} 966 967 \subsection{Hash Tables} 968 \hlabel{psHash} 969 970 \begin{table} 971 \begin{verbatim} 972 typedef struct HashTable psHash; 973 974 psHash *psHashAlloc(int nbucket); // initial number of buckets 975 void psHashFree(psHash *table, // hash table to be freed 976 void (*itemFree)(void *item)); // how to free hashed data; 977 // or NULL 978 979 void *psHashInsert(psHash *table, // table to insert in 980 const char *key, // key to use 981 void *data, // data to insert 982 void (*itemFree)(void *item)); // how to free hashed data; 983 // or NULL 984 void *psHashLookup(psHash *table, // table to lookup key in 985 const char *key); // key to lookup 986 987 void *psHashRemove(psHash *table, // table to lookup key in 988 const char *key); // key to lookup 989 \end{verbatim} 990 \begin{caption}{The public API for hash tables from \file{psHash.h}} 991 \hlabel{tabPsHash} 992 \end{caption} 993 \end{table} 994 995 The public API for the hash table (table \ref{tabPsHash}) 996 should be provided in a header file \file{psHash.h} which 997 is included by \file{psUtils.h}. 998 \footnote{ 999 We choose not to use the posix function \code{hcreate}, 1000 \code{hdestroy}, and \code{hsearch} as they only support 1001 a single hash table at any one time.} 1002 1003 A hash table is an abstract type \code{psHash}. The argument 1004 \code{nbucket} to \code{psHashAlloc} is a non-binding suggestion 1005 from the user for the initial size of the hash table. 1006 1007 If the \code{itemFree} argument to \code{psHashFree} is non-NULL, 1008 it will be used to delete the data items that have been stored 1009 in the hash table; if it is NULL this is the responsibility of 1010 the caller. 1011 1012 The routine \code{psHashInsert} must provide a non-NULL \code{itemFree} 1013 argument if it wishes to change the value previously inserted keys; 1014 if \code{itemFree} is NULL attempting to insert a pre-existing key 1015 is an error, and the routine will return NULL. If \code{psHashInsert} 1016 succeeds it returns \code{data}. 1017 1018 \code{psHashLookup} returns the \code{data} associated with the 1019 key, or NULL if the key's invalid. 1020 1021 \code{psHashRemove} removes the entry associated with the 1022 key from the table, and returns the \code{data}; if the key's invalid it returns NULL. 1023 1024 \subsection{Miscellaneous Utilities} 1025 1026 The API for miscellaneous \PS{} utilities is provided by \file{psMisc.h} 1027 which shall be included by \file{psUtils.h}. 1028 1029 \begin{table} 1030 \begin{verbatim} 1031 #define PS_CONCAT(A, B) A ## B // Expands to AB 1032 #define PS_CONCAT2(A, B) PS_CONCAT(A, B) // Also expands to AB 1033 #define PS_CONCAT3(A, B, C) A ## B ## C // Expands to ABC 1034 1035 #define PS_STRING(S) #S // converts argument S to string 1036 1037 void psAbort(const char *name, const char *fmt, ...); 1038 void psError(const char *name, const char *fmt, ...); 1039 char *psStringCopy(const char *str); 1040 \end{verbatim} 1041 \begin{caption}{The utilities provided by \file{psMisc.h}} 1042 \hlabel{psMisc} 1043 \end{caption} 1044 \end{table} 1045 1046 \code{psAbort} shall call \code{psMsgLog} with a level of \code{PS_LOG_ABORT}, 1047 and then call \code{abort}. 1048 \code{psError} shall call \code{psMsgLog} with a level of \code{PS_LOG_ERROR}, 1049 and then return. 1050 In cases of doubt, a good choice for 1051 \code{name} is \code{__func__}. 1052 1053 \code{psStringCopy} shall allocate and return a copy of the input string. 87 1054 88 1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 641 1608 642 1609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1610 1611 \subsection{Image handling} 1612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1613 1614 \subsection{Basic Images} 1615 1616 The most important data product produced by the telescope is an image. 1617 The simplest image is a 2-D collection of pixels, each with some 1618 value. We require a basic image data type: 1619 1620 \begin{verbatim} 1621 /// basic image data structure. 1622 typedef struct psImage { 1623 psType type; ///< image data type and dimension 1624 int nx, ny; ///< size of image 1625 int x0, y0; ///< data region relative to parent 1626 union { 1627 psF32 **rows; ///< == rows_f32 1628 psS8 **rows_s8; ///< pointers to psS8 data 1629 psS16 **rows_s16; ///< pointers to psS16 data 1630 psS32 **rows_s32; ///< pointers to psS32 data 1631 psU8 **rows_u8; ///< pointers to psU8 data 1632 psU16 **rows_u16; ///< pointers to psU16 data 1633 psU32 **rows_u32; ///< pointers to psU32 data 1634 psF32 **rows_f32; ///< pointers to psF32 data 1635 psF64 **rows_f64; ///< pointers to psF64 data 1636 } rows; 1637 struct psImage *parent; ///< parent, if a subimage 1638 struct psImage *children; ///< children of this region 1639 int Nchildren; ///< number of subimages 1640 } psImage; 1641 \end{verbatim} 1642 1643 This structure represents an image consisting of a 2-D array of 1644 pixels. The size of this array is given by the elements \code{(nx, 1645 ny)}. The data type of the pixel is defined by the \code{psType type} 1646 entry (see \ref{TBD}). (n.b. that for FITS images, these values are 1647 restricted to the datatypes equivalent to the valid BITPIX values 8, 1648 16, 32, -32, -64). The image represented in the data structure may 1649 represent a subset of the pixels in a complete array. The offset of 1650 the \code{(0,0)} pixel in this array relative to the parent array is 1651 given by the elements \code{(x0,y0)}. The structure may include 1652 references to subrasters (\code{children, Nchildren}) and/or to a 1653 containing array (\code{parent}). 1654 1655 We require a variety of functions to manipulate these image 1656 structures, including creation, destruction, input, output, and 1657 various manipulations of the pixels. The required functions are 1658 listed below. 1659 1660 Create an image of a specified width, height, and data type. This 1661 function must allow any of the valid image data types and not restrict 1662 to the valid FITS BITPIX types. 1663 \begin{verbatim} 1664 psImage * 1665 psImageAlloc (int nx, ///< image width 1666 int ny, ///< image height 1667 psType type) ///< image data type 1668 \end{verbatim} 1669 1670 Define a subimage of the specified area of the given image. This 1671 function must return an error if the requested subset area lies 1672 outside of the parent image. 1673 \begin{verbatim} 1674 psImage * 1675 psImageSubset (psImage *image, ///< parent image 1676 int nx, ///< subimage width (<= image.nx - x0) 1677 int ny, ///< subimage width (<= image.ny - y0) 1678 int x0, ///< subimage x-offset (0 <= x0 < nx) 1679 int y0) ///< subimage y-offset (0 <= y0 < ny) 1680 \end{verbatim} 1681 1682 Free the memory associated with a specific image. \note{does this 1683 free the input structure or just the allocated elements?} Free the 1684 children of the image if they exist. 1685 \begin{verbatim} 1686 void 1687 psImageFree (psImage *image) ///< free this image 1688 \end{verbatim} 1689 1690 Free the memory associated with the children of a specific image. 1691 \begin{verbatim} 1692 int 1693 psImageFreeChildren (psImage *image) ///< free children of this image 1694 \end{verbatim} 1695 1696 Create a copy of the specified image. If the output target pointer is 1697 not NULL, place the result in the specified structure. 1698 \begin{verbatim} 1699 psImage * 1700 psImageCopy (psImage *output, ///< target structure for output image data 1701 psImage *input) ///< copy this image 1702 \end{verbatim} 1703 1704 Extract pixels from rectlinear region to a vector (array of floats). 1705 The output vector contains either \code{nx} or \code{ny} elements, 1706 based on the value of the direction: e.g., if \code{direction} is 1707 \tbd{+x}, there are \code{nx} elements. The input region is collapsed 1708 in the perpendicular direction, and each element of the output vectors 1709 is derived from the statistics of the pixels at that direction 1710 coordinate. The statistic used to derive the output vector value is 1711 specified by \code{psStats stats}. 1712 \begin{verbatim} 1713 psFloatArray * 1714 psImageSlice (psImage *input, ///< extract slice from this image 1715 int x, ///< starting x coord of region to slice 1716 int y, ///< starting y coord of region to slice 1717 int nx, ///< width of region in x 1718 int ny, ///< width of region in y 1719 int direction, ///< direction of vector along slice 1720 psStats *stats) ///< defines statistics used to find output values 1721 \end{verbatim} 1722 1723 Extract pixels from an image along a line to a vector (array of 1724 floats). The vector \code{xs,ys} - \code{xe,ye} forms the basis of 1725 the output vector. Pixels are considered in a rectangular region of 1726 width \code{dw} about this vector. The input region is collapsed in 1727 the perpendicular direction, and each element of the output vector 1728 represents a pixel-sized boxes, where the value is derived from the 1729 statistics of the pixels interpolated along the perpendicular 1730 direction. The statistic used to derive the output vector value is 1731 specified by \code{psStats stats}. 1732 \begin{verbatim} 1733 psFloatArray * 1734 psImageCut (psImage *input, ///< extract cut from this image 1735 float xs, ///< starting x coord of cut 1736 float ys, ///< starting y coord of cut 1737 float xe, ///< ending x coord of cut 1738 float ye, ///< ending y coord of cut 1739 float dw, ///< width of cut 1740 psStats *stats) ///< defines statistics used to find output values 1741 \end{verbatim} 1742 1743 1744 Extract radial annulii data to a vector. A vector is constructed 1745 where each vector elements is derived from the statistics of the 1746 pixels which land in one of a sequence of annulii. The annulii are 1747 centered on the image pixel coordinate \code{x,y}, and have width 1748 \code{dr}. The number of annulii is $radius / dr$. The statistic 1749 used to derive the output vector value is specified by \code{psStats 1750 stats} 1751 \begin{verbatim} 1752 psFloatArray * 1753 psImageRadialCut (psImage *input, ///< extract profile from this image 1754 float x, ///< center x coord of annulii 1755 float y, ///< center y coord of annulii 1756 float radius, ///< outer radius of annulii 1757 float dr, ///< radial step size of annulii 1758 psStats *stats) ///< defines statistics used to find output values 1759 \end{verbatim} 1760 1761 %/// Extract a 2-d contour from an image at the given threshold. 1762 %\begin{verbatim} 1763 %psFloatArray * 1764 %psImageContour (psImage *input, ///< create contour for this image 1765 % float threshold, ///< contour image at this threshold 1766 % int binning) ///< bin image by this value for contour calculation 1767 %\end{verbatim} 1768 1769 Rebin image to new scale. A new image is constructed in which the 1770 dimensions are reduced by a factor of \code{scale}. The output image 1771 represents a one-to-one mapping of the pixels in the input image, 1772 except for edge effects. Each pixel in the output image is derived 1773 from the statistics of the corresponding input image pixels based on 1774 the statistics specified by \code{psStats stats}. 1775 \tbd{interpolation?} 1776 \begin{verbatim} 1777 psImage * 1778 psImageRebin (psImage *input, ///< rebin this image 1779 float scale, ///< rebinning scale: doutput = scale*dinput 1780 psStats *stats) ///< defines statistics used to find output values 1781 \end{verbatim} 1782 1783 Rotate the input image by given angle, specified in degrees. The 1784 output image must contain all of the pixels from the input image in 1785 their new frame. Pixels in the output image which do not map to input 1786 pixels should be set of \tbd{value}. The center of rotation is always 1787 the center pixel of the image. The rotation is specified in the sense 1788 that a positive value is a clock-wise rotation. 1789 \begin{verbatim} 1790 psImage * 1791 psImageRotate (psImage *input, ///< rotate this image 1792 float angle) ///< rotate by this amount (degrees) 1793 \end{verbatim} 1794 1795 Shift image by an arbitrary number of pixels (\code{dx,dy}) in either 1796 direction. If the shift values are fractional, the output pixel 1797 values shoul interpolate between the input pixel values. The output 1798 image has the same dimensions as the input image. Pixels which fall 1799 off the edge of the output image are loast. Newly exposed pixels are 1800 set to the value given by \code{exposed}. 1801 \begin{verbatim} 1802 psImage * 1803 psImageShift (psImage *input, ///< shift this image 1804 float dx, ///< shift by this amount in x 1805 float dy, ///< shift by this amount in y 1806 float exposed) ///< set exposed pixels to this value 1807 \end{verbatim} 1808 1809 Roll image by an integer number of pixels in either direction. The 1810 output image is the same dimensions as the input image. Edge pixels 1811 wrap to the other side (no values are lost). 1812 \begin{verbatim} 1813 psImage * 1814 psImageRoll (psImage *input, ///< roll this image 1815 int dx, ///< roll this amount in x 1816 int dy) ///< roll this amount in y 1817 \end{verbatim} 1818 1819 Determine statistics for image (or subimage). The statistics to be 1820 determined are specified by \code{psStats stats}. 1821 \begin{verbatim} 1822 psStats * 1823 psImageGetStats (psImage *input, ///< image (or subimage) to calculate stats 1824 psStats *stats) ///< defines statistics to be calculated 1825 \end{verbatim} 1826 1827 Construct a histogram from an image (or subimage). The histogram to 1828 generate is specified by \code{psHistogram hist}. 1829 \begin{verbatim} 1830 psHistogram * 1831 psImageHistogram (psHistogram *hist, ///< input histogram description & target 1832 psImage *input) ///< determine histogram of this image 1833 \end{verbatim} 1834 1835 Fit a 2-D polynomial surface to an image. The input structure 1836 \code{coeffs} contains the desired order and terms of interest. 1837 \tbd{how do we specify the renomalization?} 1838 \begin{verbatim} 1839 psPolynomial2D * 1840 psImageFitPolynomial (psImage *input, ///< image to fit 1841 psPolynomial2D *coeffs) ///< coefficient structure carries in desired terms 1842 \end{verbatim} 1843 1844 Evaluate a 2-D polynomial surface to image pixels. Given the input 1845 polynomial coefficients, return an image generated on the basis of the 1846 input image pixels which evaluates the polynomial for all pixels in 1847 the image.a 1848 \begin{verbatim} 1849 int 1850 psImageEvalPolynomial (psImage *input, ///< image to fit 1851 psPolynomial2D *coeffs) ///< coefficient structure carries in desired terms 1852 \end{verbatim} 1853 1854 Read an image or subimage from a named file. This function is a 1855 wrapper to the FITS library function. The input parameters allow or a 1856 subimage to be read. The starting pixel of the region is specified by 1857 \code{x,y}, while the dimensions of the requested region are specified 1858 by \code{nx,ny}. A value of -1 for these two parameters specifies the 1859 full array of the requested image. If the native image is a cube, the 1860 value of z specifies the requested slice of the image. The data is 1861 read from the extension specified by extname (matching the EXTNAME 1862 keyword) or by the extnum value (with -1 representing the PHU, 0 the 1863 first extension, etc). This function must return an error if any of 1864 the specified parameters are out of range for the data in the image 1865 file, if the specified image file does not exist. \tbd{what do we do 1866 with a 0D or 1D image?} 1867 \begin{verbatim} 1868 psImage * 1869 psImageReadSection (psImage *output, ///< place data in this structure for output 1870 int x, ///< starting x coord of region 1871 int y, ///< starting y coord of region 1872 int nx, ///< x size of region (-1 for full range) 1873 int ny, ///< y size of region (-1 for full range) 1874 int z, ///< plane of interest 1875 char *extname, ///< MEF extension name ("PHU" for primary header) 1876 int extnum, ///< MEF extension sequence number (-1 for PHU) 1877 char *filename) ///< file to read data from 1878 \end{verbatim} 1879 1880 Read an image or subimage from file descriptor. The input parameters 1881 and their behavior for this function are identical with those in 1882 \code{psImageReadSection}. 1883 \begin{verbatim} 1884 psImage * 1885 psImageFReadSection (psImage *output, ///< place data in this structure for output 1886 int x, ///< starting x coord of region 1887 int y, ///< starting y coord of region 1888 int dx, ///< x size of region (-1 for full range) 1889 int dy, ///< y size of region (-1 for full range) 1890 int z, ///< plane of interest 1891 char *extname, ///< MEF extension name ("PHU" for primary header) 1892 FILE *f) ///< file descriptor to read data from 1893 \end{verbatim} 1894 1895 Write an image section to named file, which may exist. This 1896 operatation may write a portion of an image over the existing bytes of 1897 an existing image. If the file does not exist, it should be created. 1898 If the specified extention does not exist, it should be created. If 1899 an extension is specified and no PHU exists, a basic PHU should be 1900 created. 1901 \begin{verbatim} 1902 psImage * 1903 psImageWriteSection (psImage *input, ///< image to write out 1904 int x, ///< starting x coord of region 1905 int y, ///< starting y coord of region 1906 int z, ///< plane of interest 1907 char *extname, ///< MEF extension name ("PHU" for primary header) 1908 char *filename) ///< file to write data to 1909 \end{verbatim} 1910 1911 Write an image section to file descriptor. 1912 \begin{verbatim} 1913 psImage * 1914 psImageFWriteSection(psImage *input, ///< image to write out 1915 int x, ///< starting x coord of region 1916 int y, ///< starting y coord of region 1917 int z, ///< plane of interest 1918 char *extname, ///< MEF extension name 1919 FILE *f) ///< file descriptor to write data to 1920 \end{verbatim} 1921 1922 Read header data from a FITS image file into a \code{psMetaData} 1923 structure. If the named extension does not exist, the function should 1924 return an error. 1925 \begin{verbatim} 1926 struct psMetadata * 1927 psImageReadHeader(struct psMetadata *output, ///< read data to this structure 1928 char *extname, ///< MEF extension name ("PHU" for primary header) 1929 int extnum, ///< MEF extension number (-1 for "PHU", 0 : Nextend - 1) 1930 char *filename) ///< file to read from 1931 \end{verbatim} 1932 1933 Read header data from a FITS image file descriptor into a \code{psMetaData} 1934 structure. 1935 \begin{verbatim} 1936 struct psMetadata * 1937 psImageFReadHeader (struct psMetadata *output, ///< read data to this structure 1938 char *extname, ///< MEF extension name ("PHU" for primary header) 1939 int extnum, ///< MEF extension number (-1 for "PHU", 0 : Nextend - 1) 1940 FILE *f) ///< file descriptor to read from 1941 \end{verbatim} 1942 1943 Perform a 2-D FFT on the specified image. 1944 \begin{verbatim} 1945 psImage * 1946 psImageFFT (psImage *input, ///< image to FFT 1947 int direction) ///< FFT direction 1948 \end{verbatim} 1949 1950 Clip image values outside of range to given values. All pixels with 1951 values $<$ min are set to the value vmin. All pixels with values $>$ 1952 max are set to the value vmax. 1953 \begin{verbatim} 1954 int 1955 psImageClip (psImage *input, ///< clip this image 1956 float min, ///< clip pixels with values < min 1957 float vmin, ///< set min-clipped pixels to vmin 1958 float max, ///< clip pixels with values > max 1959 float vmax) ///< set max-clipped pixels to vmax 1960 \end{verbatim} 1961 1962 Clip NaN image pixels to given value. Pixels with NaN or Inf values 1963 are set to the specified value. 1964 \begin{verbatim} 1965 int 1966 psImageClipNaN (psImage *input, ///< clip this image 1967 float value) ///< set nan pixels to this value 1968 \end{verbatim} 1969 1970 Overlay subregion of image with another image. Replace the pixels in 1971 the \code{image} which correspond to the pixels in \code{overlay} with 1972 values derived from the values in \code{image} and \code{overlay} 1973 based on the given operator. Valid operators are ``='' (set image 1974 value to overlay value), ``+'' (add overlay value to image value), 1975 ``-'' (subtract overlay from image), ``*'' (multiply overlay times 1976 image), ``/'' (divide image by overlay). 1977 \begin{verbatim} 1978 int 1979 psImageOverlaySection (psImage *image, ///< input image 1980 psImage *overlay, ///< image to overlay 1981 int x0, ///< x offset of overlay subimage 1982 int y0, ///< y offset of overlay subimage 1983 char *operator) ///< overlay operation 1984 \end{verbatim} 643 1985 644 1986 \subsection{Astrometry} … … 1181 2523 1182 2524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2525 1183 2526 \subsection{Dates and times} 1184 2527 … … 1186 2529 1187 2530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1188 \subsection{Image handling}1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1190 Gene --- done.1191 2531 1192 2532 \subsection{Metadata} 1193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1194 Gene --- done. 2533 2534 This section addresses the question of how \PS{} metadata should be 2535 represented in memory. We do not (yet) address how it should be 2536 represented on disk. 2537 2538 \subsubsection{Metadata Representation} 2539 2540 We propose that an item of metadata be represented as a C structure with at least the following 2541 fields: 2542 \begin{verbatim} 2543 /* 2544 * A struct to define a single item of metadata 2545 */ 2546 typedef struct { 2547 const int id; // unique ID for this item 2548 2549 char *name; // Name of item 2550 psMetaDataType type; // type of this item 2551 const union { 2552 float f; // floating value 2553 int i; // integer value 2554 void *v; // other type 2555 } val; // value of metadata 2556 char *comment; // optional comment ("", not NULL) 2557 } psMetaDataItem; 2558 \end{verbatim} 2559 2560 The \code{id} is a unique identifier for this item of metadata; experience 2561 shows that such tags are useful. 2562 2563 The \code{psMetaDataType type} entry specifies the type of the data 2564 being represented; the possibilities are listed in section \ref{metadataTypes}. 2565 2566 \paragraph{Possible Types of Metadata} 2567 \label{metadataTypes} 2568 2569 The possible types of metadata are identified by the enumerated type 2570 \code{psMetaDataType} (see also table \ref{tabMetaDataTypes}); the initial defined values are: 2571 \begin{verbatim} 2572 /* 2573 * Possible types of metadata. 2574 */ 2575 typedef enum { // type of val is: 2576 psMetaFloat, // float (.f) 2577 psMetaInt, // int (.i) 2578 psMetaStr, // string (.v) 2579 psMetaImg, // image (.v) 2580 psMetaJPEG, // JPEG (.v) 2581 psMetaPNG, // PNG (.v) 2582 psMetaAstrom, // astrometric coefficients (.v) 2583 psMetaUnknown, // other (.v) 2584 psMetaNType // Number of types; must be last 2585 } psMetaDataType; 2586 \end{verbatim} 2587 2588 \begin{table} 2589 \begin{tabular}{llll} 2590 \textbf{Value} & \textbf{Type} & \textbf{member of union} & \textbf{Comments}\\ 2591 \hline 2592 psMetaFloat & float & f & value, not pointer, is stored \\ 2593 psMetaInt & int & i & value, not pointer, is stored \\ 2594 psMetaStr & string & v & value, not pointer to original, is stored \\ 2595 psMetaImg & psImage & v & \\ 2596 psMetaJPEG & JPEG & v & \\ 2597 psMetaPNG & PNG & v & \\ 2598 psMetaAstrom & psAstrom & v & \\ 2599 psMetaUnknown & other & v & \\ 2600 psMetaNType & (none) & & The number of types defined 2601 \end{tabular} 2602 \begin{caption}{Supported Metadata Types} 2603 \label{tabMetaDataTypes} 2604 Possible types of metadata 2605 \end{caption} 2606 \end{table} 2607 2608 \subsubsection{Collections of Metadata} 2609 2610 \begin{verbatim} 2611 typedef struct { 2612 psDlist *list; // list of psMetaDataItem 2613 psHash *table; // hash table of the same metadata 2614 } psMetaDataSet; 2615 \end{verbatim} 2616 2617 The type \code{psMetaDataSet} is a container class for metadata. Note that there are 2618 in fact \emph{two} representations of the metadata (each \code{psMetaDataItem} appears 2619 on both). 2620 2621 We are using the standard \PS{} doubly-linked list types \code{psDlist} and \code{psHash} 2622 (see \href{file:utils#psDlist}{utils.pdf:psDlist} and \href{file:utils#psHash}{utils.pdf:psHash} for details). 2623 For example: 2624 \begin{verbatim} 2625 for (int i = 0; i < 10; i += 5) { 2626 float sqrti = sqrt(i); 2627 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_INT, &i, NULL, "const.%d", i)); 2628 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_FLOAT, &sqrti, "square root", "const.sqrt%d", i)); 2629 } 2630 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_STR, "Bonjour", "French", "lang.hello")); 2631 /* 2632 * Remove a key 2633 */ 2634 psMetaDataItemFree(psMetaDataRemove(ms, "lang.hello")); 2635 /* 2636 * Print all metadata 2637 */ 2638 fprintf(stdout, "------\n"); 2639 psMetaDataSetIterator(ms); 2640 while ((meta = psMetaDataGetNext(ms, NULL)) != NULL) { 2641 psMetaDataItemPrint(stdout, meta, ""); 2642 } 2643 /* 2644 * Look up a key by name 2645 */ 2646 fprintf(stdout, "------\n"); 2647 fprintf(stdout, "Looking up by name:\n"); 2648 meta = psMetaDataLookup(ms, "const.5"); 2649 if (meta != NULL) { 2650 psMetaDataItemPrint(stdout, meta, ""); 2651 } 2652 \end{verbatim} 2653 2654 \subsubsection{Naming convention for MetaData} 2655 2656 The \code{psMetaDataItem} struct includes a name. This name should be of 2657 the form \code{name1.name2.name3$\cdots$}, e.g.\hfil\break 2658 \null\qquad\qquad\code{IPP.phase1.ota12.biassec}. 2659 2660 We shall set in place a system for assigning the top-level `domains' 2661 to responsible individuals, and for gathering a complete list of 2662 all metadata names in use throughout the project. 2663 2664 \paragraph{Support for Multiple Values for a Given Name} 2665 2666 \begin{verbatim} 2667 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_STR | PS_META_NON_UNIQUE, 2668 "Bonjour", "French", "lang.hello")); 2669 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_STR | PS_META_NON_UNIQUE, 2670 "Aloha", "Hawaiian", "lang.hello")); 2671 psMetaDataAppend(ms, psMetaDataItemAlloc(PS_META_STR | PS_META_NON_UNIQUE, 2672 "Good Morning", "English", "lang.hello")); 2673 /* 2674 * Print all metadata starting "lang" 2675 */ 2676 psMetaDataSetIterator(ms); 2677 while ((meta = psMetaDataGetNext(ms, "lang")) != NULL) { 2678 psMetaDataItemPrint(stdout, meta, ""); 2679 } 2680 \end{verbatim} 2681 2682 It is an unfortunate fact that certain metadata keywords (such as \code{COMMENT} in a FITS header) 2683 may be repeated with different values. The \code{psMetaDataAppend} routine is required 2684 to check that all metadata names are unique unless the type is qualified as \code{PS_META_NON_UNIQUE}; 2685 in this case a unique integer will be added to each name that you specify. In this case, 2686 you may either delete individual element separately or as a complete set: 2687 \begin{verbatim} 2688 psMetaDataItemFree(psMetaDataRemove(ms, "lang.hello.0")); 2689 psMetaDataItemFree(psMetaDataRemove(ms, "lang.hello")); 2690 \end{verbatim} 2691 2692 \subsubsection{MetaData APIs} 2693 2694 \begin{verbatim} 2695 psMetaDataItem *psMetaDataItemAlloc( 2696 psMetaDataType type, // type of this piece of metadata 2697 const void *val, // value of new item 2698 // N.b. a pointer even if the item 2699 // is of type e.g. int 2700 const char *comment, // comment associated with item 2701 const char *name, // name of new item of metadata (may be an sprintf format) 2702 ...); // possible arguments for name format 2703 2704 void psMetaDataItemFree(psMetaDataItem *ms); // piece of metadata to destroy 2705 2706 psMetaDataSet *psMetaDataSetAlloc(void); // make a new set of metadata 2707 void psMetaDataSetDel(psMetaDataSet *ms); // destroy a set of metadata 2708 2709 /*****************************************************************************/ 2710 /* 2711 * Utilities 2712 */ 2713 psMetaDataItem *psMetaDataAppend(psMetaDataSet *restrict ms, psMetaDataItem *restrict item); 2714 psMetaDataItem *psMetaDataRemove(psMetaDataSet *restrict ms, const char *restrict key); 2715 2716 void psMetaDataSetIterator(psMetaDataSet *ms); 2717 psMetaDataItem *psMetaDataGetNext(psMetaDataSet *ms); 2718 psMetaDataItem *psMetaDataLookup(const psMetaDataSet *ms, const char *key); 2719 2720 void psMetaDataItemPrint(FILE *fd, // file descriptor to write to 2721 const psMetaDataItem *ms); // item of metadata to print 2722 \end{verbatim} 1195 2723 1196 2724 \subsection{Detector and sky positions} … … 1375 2903 \subsection{Photometry} 1376 2904 1377 Gene --- done. 2905 2906 Photometric observations are performed in a photometric system, and 2907 are must be related to other photometric systems. We require a data 2908 structure which defines a photometric system, as well as a structure 2909 to define the transformation between photometric systems. 2910 2911 The photometric system is defined by the psPhotSystem structure. 2912 A photometric system is identified by a human-readable \code{name} 2913 (ie, SDSS.g, Landolt92.B, GPC1.OTA32.r). Each photometric system is 2914 given a unique identifier \code{ID}. Observations taken with a 2915 specific camera, detector, and filter represent their own photometric 2916 system, and it may be necessary to perform transformations between 2917 these systems. Photometric systems associated with observations from 2918 a specific camera/detector/filter combination can be associated with 2919 those components. 2920 \begin{verbatim} 2921 typedef struct { 2922 int ID; 2923 char *name; 2924 char *camera; 2925 char *filter; 2926 char *detector; 2927 } psPhotSystem; 2928 \end{verbatim} 2929 2930 The following structure defines the transformation between two 2931 photometric systems. 2932 \begin{verbatim} 2933 typedef struct { 2934 psPhotSystem src; 2935 psPhotSystem dst; 2936 psPhotSystem pP, pM; ///< Colour reference 2937 psPhotSystem sP, sM; ///< Colour reference 2938 float pA, sA; ///< 2939 psPolynomial3D transform; 2940 } psPhotTransform; 2941 \end{verbatim} 2942 2943 The transformation between two photometric systems may depend on the 2944 airmass of the observation and on the colors of the object of 2945 interest. For a specific observation, such a transformations can be 2946 defined as a polynomial function of the color the star and the airmass 2947 of the observations. If sufficient data exists, the transformation 2948 between the photometric systems may include more than one color, 2949 constraining the curvature of the stellar spectral energy 2950 distributions. This latter term may be significant for stars which 2951 are highly reddened, for example. Derived photometric quantities may 2952 have been corrected for airmass variations, in which case only color 2953 terms may be measureable. The structure defines the transformation 2954 between a source photometric system (\code{src}) and a target 2955 photometric system (\code{dst}). The photometric system of a primary 2956 color is defined by \code{pP, pM} such that the color is constructed 2957 as $pP - pM$. A secondary color is defined by \code{sP, sM}. For 2958 both, a reference color is specified (\code{pA, sA}): the polynomial 2959 transformation terms refer to colors in the form $pP - pM - pA$. The 2960 transformation is specified as a 3D polynomial. For a star of 2961 magnitude $M_{\rm src}$ in the source photometric system, with 2962 additional magnitude information in the other systems $M_{\rm pP}$, 2963 $M_{\rm pM}$, $M_{\rm sP}$, $M_{\rm sM}$, observed at an airmass of 2964 $z$, the magnitude of the star in the target system $M_{\rm dst}$ is 2965 given by: 2966 $M_{\rm dst} = M_{\rm src} + transform(z, M_{\rm pP} - M_{\rm pM} - pA, M_{\rm sP} - M_{\rm sM} - sA)$ 1378 2967 1379 2968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 1381 2970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1382 2971 2972 \appendix 2973 2974 \section{API Summary: all functions} 2975 2976 \subsection{System Utilities} 2977 \begin{CompactItemize} 2978 \item 2979 int {\bf ps\-Set\-Log\-Destination} (int dest) 2980 \begin{CompactList}\small\item\em Sets the log destination.\item\end{CompactList}\item 2981 int {\bf ps\-Set\-Log\-Level} (int level) 2982 \begin{CompactList}\small\item\em Sets the log level.\item\end{CompactList}\item 2983 void {\bf ps\-Set\-Log\-Format} (const char $\ast$fmt) 2984 \begin{CompactList}\small\item\em sets the log format\item\end{CompactList}\item 2985 void {\bf ps\-Log\-Msg} (const char $\ast$name, int level, const char $\ast$fmt,...) 2986 \begin{CompactList}\small\item\em Logs a message.\item\end{CompactList}\item 2987 void {\bf p\_\-ps\-VLog\-Msg} (const char $\ast$name, int level, const char $\ast$fmt, va\_\-list ap) 2988 \begin{CompactList}\small\item\em Logs a message from varargs.\item\end{CompactList}\item 2989 void $\ast$ {\bf p\_\-ps\-Alloc} (size\_\-t size, const char $\ast$file, int lineno) 2990 \begin{CompactList}\small\item\em Memory allocation. Underlying private function called by macro ps\-Alloc.\item\end{CompactList}\item 2991 void $\ast$ {\bf p\_\-ps\-Realloc} (void $\ast$ptr, size\_\-t size, const char $\ast$file, int lineno) 2992 \begin{CompactList}\small\item\em Memory re-allocation. Underlying private function called by macro ps\-Realloc.\item\end{CompactList}\item 2993 void {\bf p\_\-ps\-Free} (void $\ast$ptr, const char $\ast$file, int lineno) 2994 \begin{CompactList}\small\item\em Free memory. Underlying private function called by macro ps\-Free.\item\end{CompactList}\item 2995 int {\bf ps\-Mem\-Check\-Leaks} (int id0, {\bf ps\-Mem\-Block} $\ast$$\ast$$\ast$arr, FILE $\ast$fd) 2996 \begin{CompactList}\small\item\em Check for memory leaks.\item\end{CompactList}\item 2997 int {\bf ps\-Mem\-Check\-Corruption} (int abort\_\-on\_\-error) 2998 \begin{CompactList}\small\item\em Check for memory corruption.\item\end{CompactList}\item 2999 int {\bf ps\-Mem\-Get\-Ref\-Counter} (void $\ast$vptr) 3000 \begin{CompactList}\small\item\em Return reference counter.\item\end{CompactList}\item 3001 void $\ast$ {\bf ps\-Mem\-Incr\-Ref\-Counter} (void $\ast$vptr) 3002 \begin{CompactList}\small\item\em Increment reference counter and return the pointer.\item\end{CompactList}\item 3003 void $\ast$ {\bf ps\-Mem\-Decr\-Ref\-Counter} (void $\ast$vptr) 3004 \begin{CompactList}\small\item\em Decrement reference counter and return the pointer.\item\end{CompactList}\item 3005 {\bf ps\-Mem\-Problem\-Callback} {\bf ps\-Mem\-Problem\-Set\-CB} ({\bf ps\-Mem\-Problem\-Callback} func) 3006 \begin{CompactList}\small\item\em Set callback for problems.\item\end{CompactList}\item 3007 {\bf ps\-Mem\-Exhausted\-Callback} {\bf ps\-Mem\-Exhausted\-Set\-CB} ({\bf ps\-Mem\-Exhausted\-Callback} func) 3008 \begin{CompactList}\small\item\em Set callback for out-of-memory.\item\end{CompactList}\item 3009 {\bf ps\-Mem\-Callback} {\bf ps\-Mem\-Allocate\-Set\-CB} ({\bf ps\-Mem\-Callback} func) 3010 \begin{CompactList}\small\item\em Set call back for when a particular memory block is allocated.\item\end{CompactList}\item 3011 {\bf ps\-Mem\-Callback} {\bf ps\-Mem\-Free\-Set\-CB} ({\bf ps\-Mem\-Callback} func) 3012 \begin{CompactList}\small\item\em Set call back for when a particular memory block is freed.\item\end{CompactList}\item 3013 int {\bf ps\-Mem\-Get\-Id} (void) 3014 \begin{CompactList}\small\item\em get next memory ID\item\end{CompactList}\item 3015 long {\bf ps\-Mem\-Set\-Allocate\-ID} (long id) 3016 \begin{CompactList}\small\item\em set p\_\-ps\-Mem\-Allocate\-ID to id\item\end{CompactList}\item 3017 long {\bf ps\-Mem\-Set\-Free\-ID} (long id) 3018 \begin{CompactList}\small\item\em set p\_\-ps\-Mem\-Free\-ID to id\item\end{CompactList}\item 3019 void {\bf ps\-Abort} (const char $\ast$name, const char $\ast$fmt,...) 3020 \begin{CompactList}\small\item\em Prints an error message and aborts.\item\end{CompactList}\item 3021 void {\bf ps\-Error} (const char $\ast$name, const char $\ast$fmt,...) 3022 \begin{CompactList}\small\item\em Prints an error message and doesn't abort.\item\end{CompactList}\item 3023 char $\ast$ {\bf ps\-String\-Copy} (const char $\ast$str) 3024 \begin{CompactList}\small\item\em Allocates and returns a copy of a string.\item\end{CompactList}\item 3025 void {\bf p\_\-ps\-Trace} (const char $\ast$facil, int level,...) 3026 \begin{CompactList}\small\item\em Send a trace message.\item\end{CompactList}\item 3027 int {\bf ps\-Set\-Trace\-Level} (const char $\ast$facil, int level) 3028 \begin{CompactList}\small\item\em Set trace level.\item\end{CompactList}\item 3029 int {\bf ps\-Get\-Trace\-Level} (const char $\ast$name) 3030 \begin{CompactList}\small\item\em Get the trace level.\item\end{CompactList}\item 3031 void {\bf ps\-Trace\-Reset} (void) 3032 \begin{CompactList}\small\item\em turn off all tracing, and free trace's allocated memory\item\end{CompactList}\item 3033 void {\bf ps\-Print\-Trace\-Levels} (void) 3034 \begin{CompactList}\small\item\em print trace levels\item\end{CompactList}\end{CompactItemize} 3035 3036 \subsection{Data Containers} 3037 \begin{CompactItemize} 3038 \item 3039 {\bf ps\-Dlist} $\ast$ {\bf ps\-Dlist\-Alloc} (void $\ast$data) 3040 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3041 void {\bf ps\-Dlist\-Free} ({\bf ps\-Dlist} $\ast$list, void($\ast$elem\-Free)(void $\ast$)) 3042 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3043 {\bf ps\-Dlist} $\ast$ {\bf ps\-Dlist\-Add} ({\bf ps\-Dlist} $\ast$list, void $\ast$data, int where) 3044 \begin{CompactList}\small\item\em Add to list.\item\end{CompactList}\item 3045 {\bf ps\-Dlist} $\ast$ {\bf ps\-Dlist\-Append} ({\bf ps\-Dlist} $\ast$list, void $\ast$data) 3046 \begin{CompactList}\small\item\em Append to a list.\item\end{CompactList}\item 3047 void $\ast$ {\bf ps\-Dlist\-Remove} ({\bf ps\-Dlist} $\ast$list, void $\ast$data, int which) 3048 \begin{CompactList}\small\item\em PS\_\-DLIST\_\-PREV.\item\end{CompactList}\item 3049 void $\ast$ {\bf ps\-Dlist\-Get} (const {\bf ps\-Dlist} $\ast$list, int which) 3050 \begin{CompactList}\small\item\em Retrieve from a list.\item\end{CompactList}\item 3051 void {\bf ps\-Dlist\-Set\-Iterator} ({\bf ps\-Dlist} $\ast$list, int where, int which) 3052 \begin{CompactList}\small\item\em PS\_\-DLIST\_\-PREV.\item\end{CompactList}\item 3053 void $\ast$ {\bf ps\-Dlist\-Get\-Next} ({\bf ps\-Dlist} $\ast$list, int which) 3054 \begin{CompactList}\small\item\em PS\_\-DLIST\_\-PREV.\item\end{CompactList}\item 3055 void $\ast$ {\bf ps\-Dlist\-Get\-Prev} ({\bf ps\-Dlist} $\ast$list, int which) 3056 \begin{CompactList}\small\item\em PS\_\-DLIST\_\-PREV.\item\end{CompactList}\item 3057 {\bf ps\-Void\-Ptr\-Array} $\ast$ {\bf ps\-Dlist\-To\-Array} ({\bf ps\-Dlist} $\ast$dlist) 3058 \begin{CompactList}\small\item\em Convert doubly-linked list to an array.\item\end{CompactList}\item 3059 {\bf ps\-Dlist} $\ast$ {\bf ps\-Array\-To\-Dlist} ({\bf ps\-Void\-Ptr\-Array} $\ast$arr) 3060 \begin{CompactList}\small\item\em Convert array to a doubly-linked list.\item\end{CompactList}\item 3061 {\bf ps\-Hash} $\ast$ {\bf ps\-Hash\-Alloc} (int nbucket) 3062 \begin{CompactList}\small\item\em Allocate hash buckets in table.\item\end{CompactList}\item 3063 void {\bf ps\-Hash\-Free} ({\bf ps\-Hash} $\ast$table, void($\ast$item\-Free)(void $\ast$item)) 3064 \begin{CompactList}\small\item\em Free hash buckets from table.\item\end{CompactList}\item 3065 void $\ast$ {\bf ps\-Hash\-Insert} ({\bf ps\-Hash} $\ast$table, const char $\ast$key, void $\ast$data, void($\ast$item\-Free)(void $\ast$item)) 3066 \begin{CompactList}\small\item\em Insert entry into table.\item\end{CompactList}\item 3067 void $\ast$ {\bf ps\-Hash\-Lookup} ({\bf ps\-Hash} $\ast$table, const char $\ast$key) 3068 \begin{CompactList}\small\item\em Lookup key in table.\item\end{CompactList}\item 3069 void $\ast$ {\bf ps\-Hash\-Remove} ({\bf ps\-Hash} $\ast$table, const char $\ast$key) 3070 \begin{CompactList}\small\item\em Remove key from table.\item\end{CompactList}\item 3071 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Float\-Array\-Alloc} (int s, int n) 3072 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3073 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Float\-Array\-Realloc} ({\bf ps\-Float\-Array} $\ast$my\-Array, int s) 3074 \begin{CompactList}\small\item\em Reallocator.\item\end{CompactList}\item 3075 void {\bf ps\-Float\-Array\-Free} ({\bf ps\-Float\-Array} $\ast$restrict my\-Array) 3076 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3077 {\bf ps\-Complex\-Array} $\ast$ {\bf ps\-Complex\-Array\-Alloc} (int s, int n) 3078 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3079 {\bf ps\-Complex\-Array} $\ast$ {\bf ps\-Complex\-Array\-Realloc} ({\bf ps\-Complex\-Array} $\ast$my\-Array, int s) 3080 \begin{CompactList}\small\item\em Reallocator.\item\end{CompactList}\item 3081 void {\bf ps\-Complex\-Array\-Free} ({\bf ps\-Complex\-Array} $\ast$restrict my\-Array) 3082 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3083 {\bf ps\-Int\-Array} $\ast$ {\bf ps\-Int\-Array\-Alloc} (int s, int n) 3084 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3085 {\bf ps\-Int\-Array} $\ast$ {\bf ps\-Int\-Array\-Realloc} ({\bf ps\-Int\-Array} $\ast$my\-Array, int s) 3086 \begin{CompactList}\small\item\em Reallocator.\item\end{CompactList}\item 3087 void {\bf ps\-Int\-Array\-Free} ({\bf ps\-Int\-Array} $\ast$restrict my\-Array) 3088 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3089 {\bf ps\-Double\-Array} $\ast$ {\bf ps\-Double\-Array\-Alloc} (int s, int n) 3090 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3091 {\bf ps\-Double\-Array} $\ast$ {\bf ps\-Double\-Array\-Realloc} ({\bf ps\-Double\-Array} $\ast$my\-Array, int s) 3092 \begin{CompactList}\small\item\em Reallocator.\item\end{CompactList}\item 3093 void {\bf ps\-Double\-Array\-Free} ({\bf ps\-Double\-Array} $\ast$restrict my\-Array) 3094 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3095 {\bf ps\-Vector\-Array} $\ast$ {\bf ps\-Vector\-Array\-Alloc} (int s, int n) 3096 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3097 {\bf ps\-Vector\-Array} $\ast$ {\bf ps\-Vector\-Array\-Realloc} ({\bf ps\-Vector\-Array} $\ast$my\-Array, int s) 3098 \begin{CompactList}\small\item\em Reallocator.\item\end{CompactList}\item 3099 void {\bf ps\-Vector\-Array\-Free} ({\bf ps\-Vector\-Array} $\ast$restrict my\-Array) 3100 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3101 {\bf ps\-Void\-Ptr\-Array} $\ast$ {\bf ps\-Void\-Ptr\-Array\-Alloc} (int n, int s) 3102 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3103 {\bf ps\-Void\-Ptr\-Array} $\ast$ {\bf ps\-Void\-Ptr\-Array\-Realloc} ({\bf ps\-Void\-Ptr\-Array} $\ast$arr, int n) 3104 \begin{CompactList}\small\item\em Reallocate.\item\end{CompactList}\item 3105 void {\bf ps\-Void\-Ptr\-Array\-Free} ({\bf ps\-Void\-Ptr\-Array} $\ast$arr, void($\ast$elem\-Free)(void $\ast$)) 3106 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\end{CompactItemize} 3107 3108 \subsection{Math Utilities} 3109 \begin{CompactItemize} 3110 \item 3111 {\bf ps\-Bit\-Mask} $\ast$ {\bf ps\-Bit\-Mask\-Alloc} (int n) 3112 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3113 void {\bf ps\-Bit\-Mask\-Free} ({\bf ps\-Bit\-Mask} $\ast$restrict my\-Mask) 3114 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3115 {\bf ps\-Bit\-Mask} $\ast$ {\bf ps\-Bit\-Mask\-Set} ({\bf ps\-Bit\-Mask} $\ast$out\-Mask, const {\bf ps\-Bit\-Mask} $\ast$my\-Mask, int bit) 3116 \begin{CompactList}\small\item\em Set a bit mask.\item\end{CompactList}\item 3117 int {\bf ps\-Bit\-Mask\-Test} (const {\bf ps\-Bit\-Mask} $\ast$check\-Mask, int bit) 3118 \begin{CompactList}\small\item\em Check a bit mask.\item\end{CompactList}\item 3119 {\bf ps\-Bit\-Mask} $\ast$ {\bf ps\-Bit\-Mask\-Op} ({\bf ps\-Bit\-Mask} $\ast$out\-Mask, const {\bf ps\-Bit\-Mask} $\ast$restrict in\-Mask1, char $\ast$operator, const {\bf ps\-Bit\-Mask} $\ast$restrict in\-Mask2) 3120 \begin{CompactList}\small\item\em apply the given operator to two bit masks\item\end{CompactList}\item 3121 {\bf ps\-Complex\-Array} $\ast$ {\bf ps\-Real\-FFT} ({\bf ps\-Complex\-Array} $\ast$restrict out, const {\bf ps\-Float\-Array} $\ast$restrict my\-Array) 3122 \begin{CompactList}\small\item\em Return Fourier Transform of an array.\item\end{CompactList}\item 3123 {\bf ps\-Complex\-Array} $\ast$ {\bf ps\-Complex\-FFT} ({\bf ps\-Complex\-Array} $\ast$restrict out, const {\bf ps\-Complex\-Array} $\ast$restrict my\-Array, int sign) 3124 \begin{CompactList}\small\item\em Return [inverse?] Fourier Transform of a complex array.\item\end{CompactList}\item 3125 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Power\-Spec} ({\bf ps\-Float\-Array} $\ast$restrict out, const {\bf ps\-Float\-Array} $\ast$restrict my\-Array) 3126 \begin{CompactList}\small\item\em Return Power spectrum of a array.\item\end{CompactList}\item 3127 {\bf ps\-Polynomial1D} $\ast$ {\bf ps\-Polynomial1DAlloc} (int n) 3128 \begin{CompactList}\small\item\em Constructors.\item\end{CompactList}\item 3129 {\bf ps\-Polynomial2D} $\ast$ {\bf ps\-Polynomial2DAlloc} (int n\-X, int n\-Y) 3130 \item 3131 {\bf ps\-Polynomial3D} $\ast$ {\bf ps\-Polynomial3DAlloc} (int n\-X, int n\-Y, int n\-Z) 3132 \item 3133 {\bf ps\-Polynomial4D} $\ast$ {\bf ps\-Polynomial4DAlloc} (int n\-W, int n\-X, int n\-Y, int n\-Z) 3134 \item 3135 void {\bf ps\-Polynomial1DFree} ({\bf ps\-Polynomial1D} $\ast$restrict my\-Poly) 3136 \begin{CompactList}\small\item\em Destructors.\item\end{CompactList}\item 3137 void {\bf ps\-Polynomial2DFree} ({\bf ps\-Polynomial2D} $\ast$restrict my\-Poly) 3138 \item 3139 void {\bf ps\-Polynomial3DFree} ({\bf ps\-Polynomial3D} $\ast$restrict my\-Poly) 3140 \item 3141 void {\bf ps\-Polynomial4DFree} ({\bf ps\-Polynomial4D} $\ast$restrict my\-Poly) 3142 \item 3143 float {\bf ps\-Eval\-Polynomial1D} (float x, const {\bf ps\-Polynomial1D} $\ast$restrict my\-Poly) 3144 \begin{CompactList}\small\item\em Evaluate 1D polynomial.\item\end{CompactList}\item 3145 float {\bf ps\-Eval\-Polynomial2D} (float x, float y, const {\bf ps\-Polynomial2D} $\ast$restrict my\-Poly) 3146 \begin{CompactList}\small\item\em Evaluate 2D polynomial.\item\end{CompactList}\item 3147 float {\bf ps\-Eval\-Polynomial3D} (float x, float y, float z, const {\bf ps\-Polynomial3D} $\ast$restrict my\-Poly) 3148 \begin{CompactList}\small\item\em Evaluate 3D polynomial.\item\end{CompactList}\item 3149 float {\bf ps\-Eval\-Polynomial4D} (float w, float x, float y, float z, const {\bf ps\-Polynomial4D} $\ast$restrict my\-Poly) 3150 \begin{CompactList}\small\item\em Evaluate 4D polynomial.\item\end{CompactList}\item 3151 {\bf ps\-DPolynomial1D} $\ast$ {\bf ps\-DPolynomial1DAlloc} (int n) 3152 \begin{CompactList}\small\item\em Constructors.\item\end{CompactList}\item 3153 {\bf ps\-DPolynomial2D} $\ast$ {\bf ps\-DPolynomial2DAlloc} (int n\-X, int n\-Y) 3154 \item 3155 {\bf ps\-DPolynomial3D} $\ast$ {\bf ps\-DPolynomial3DAlloc} (int n\-X, int n\-Y, int n\-Z) 3156 \item 3157 {\bf ps\-DPolynomial4D} $\ast$ {\bf ps\-DPolynomial4DAlloc} (int n\-W, int n\-X, int n\-Y, int n\-Z) 3158 \item 3159 void {\bf ps\-DPolynomial1DFree} ({\bf ps\-DPolynomial1D} $\ast$restrict my\-Poly) 3160 \begin{CompactList}\small\item\em Destructors.\item\end{CompactList}\item 3161 void {\bf ps\-DPolynomial2DFree} ({\bf ps\-DPolynomial2D} $\ast$restrict my\-Poly) 3162 \item 3163 void {\bf ps\-DPolynomial3DFree} ({\bf ps\-DPolynomial3D} $\ast$restrict my\-Poly) 3164 \item 3165 void {\bf ps\-DPolynomial4DFree} ({\bf ps\-DPolynomial4D} $\ast$restrict my\-Poly) 3166 \item 3167 double {\bf ps\-Eval\-DPolynomial1D} (double x, const {\bf ps\-DPolynomial1D} $\ast$restrict my\-Poly) 3168 \begin{CompactList}\small\item\em Evaluate 1D polynomial (double precision).\item\end{CompactList}\item 3169 double {\bf ps\-Eval\-DPolynomial2D} (double x, double y, const {\bf ps\-DPolynomial2D} $\ast$restrict my\-Poly) 3170 \begin{CompactList}\small\item\em Evaluate 2D polynomial (double precision).\item\end{CompactList}\item 3171 double {\bf ps\-Eval\-DPolynomial3D} (double x, double y, double z, const {\bf ps\-DPolynomial3D} $\ast$restrict my\-Poly) 3172 \begin{CompactList}\small\item\em Evaluate 3D polynomial (double precision).\item\end{CompactList}\item 3173 double {\bf ps\-Eval\-DPolynomial4D} (double w, double x, double y, double z, const {\bf ps\-DPolynomial4D} $\ast$restrict my\-Poly) 3174 \begin{CompactList}\small\item\em Evaluate 4D polynomial (double precision).\item\end{CompactList}\item 3175 {\bf ps\-Type} $\ast$ {\bf ps\-Binary\-Op} (void $\ast$out, void $\ast$in1, char $\ast$operator, void $\ast$in2) 3176 \begin{CompactList}\small\item\em Perform a binary operation on two data items ({\bf ps\-Image} {\rm (p.\,\pageref{structpsImage})}, ps\-Vector, ps\-Scalar).\item\end{CompactList}\item 3177 {\bf ps\-Type} $\ast$ {\bf ps\-Unary\-Op} (void $\ast$out, void $\ast$in, char $\ast$operator) 3178 \begin{CompactList}\small\item\em Perform a binary operation on two data items ({\bf ps\-Image} {\rm (p.\,\pageref{structpsImage})}, ps\-Vector, ps\-Scalar).\item\end{CompactList}\item 3179 {\bf p\_\-ps\-Scalar} $\ast$ {\bf ps\-Scalar} (double value) 3180 \begin{CompactList}\small\item\em create a {\bf ps\-Type} {\rm (p.\,\pageref{structpsType})}-ed structure from a constant double value.\item\end{CompactList}\item 3181 {\bf p\_\-ps\-Scalar} $\ast$ {\bf ps\-Scalar\-Type} (char $\ast$mode,...) 3182 \begin{CompactList}\small\item\em create a {\bf ps\-Type} {\rm (p.\,\pageref{structpsType})}-ed structure from a specified type\item\end{CompactList}\item 3183 {\bf ps\-Matrix} $\ast$ {\bf ps\-Matrix\-Alloc} (int Xdimen, int Ydimen) 3184 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3185 void {\bf ps\-Matrix\-Free} ({\bf ps\-Matrix} $\ast$restrict my\-Matrix) 3186 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3187 {\bf ps\-Matrix} $\ast$ {\bf ps\-Matrix\-Invert} ({\bf ps\-Matrix} $\ast$out, const {\bf ps\-Matrix} $\ast$my\-Matrix, float $\ast$restrict determinant) 3188 \begin{CompactList}\small\item\em Invert matrix.\item\end{CompactList}\item 3189 float {\bf ps\-Matrix\-Determinant} (const {\bf ps\-Matrix} $\ast$restrict my\-Matrix) 3190 \begin{CompactList}\small\item\em Matrix determinant.\item\end{CompactList}\item 3191 {\bf ps\-Matrix} $\ast$ {\bf ps\-Matrix\-Op} ({\bf ps\-Matrix} $\ast$out, const {\bf ps\-Matrix} $\ast$matrix1, const char $\ast$op, const {\bf ps\-Matrix} $\ast$matrix2) 3192 \begin{CompactList}\small\item\em Matrix operations.\item\end{CompactList}\item 3193 {\bf ps\-Matrix} $\ast$ {\bf ps\-Matrix\-Transpose} ({\bf ps\-Matrix} $\ast$out, const {\bf ps\-Matrix} $\ast$my\-Matrix) 3194 \begin{CompactList}\small\item\em Transpose Matrix.\item\end{CompactList}\item 3195 {\bf ps\-Vector} $\ast$ {\bf ps\-Matrix\-To\-Vector} ({\bf ps\-Matrix} $\ast$my\-Matrix) 3196 \begin{CompactList}\small\item\em Convert matrix to vector.\item\end{CompactList}\item 3197 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Minimize} (float($\ast$my\-Function)(const {\bf ps\-Float\-Array} $\ast$restrict), {\bf ps\-Float\-Array} $\ast$restrict initial\-Guess) 3198 \begin{CompactList}\small\item\em Minimize a particular function.\item\end{CompactList}\item 3199 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Minimize\-Chi2} (float($\ast$eval\-Model)(const {\bf ps\-Float\-Array} $\ast$restrict, const {\bf ps\-Float\-Array} $\ast$restrict), const {\bf ps\-Float\-Array} $\ast$restrict domain, const {\bf ps\-Float\-Array} $\ast$restrict data, const {\bf ps\-Float\-Array} $\ast$restrict errors, {\bf ps\-Float\-Array} $\ast$restrict initial\-Guess, const {\bf ps\-Int\-Array} $\ast$restrict guess\-Mask) 3200 \begin{CompactList}\small\item\em Minimize chi$^\wedge$2 for input data.\item\end{CompactList}\item 3201 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Get\-Array\-Polynomial} (const {\bf ps\-Float\-Array} $\ast$restrict ord, const {\bf ps\-Float\-Array} $\ast$restrict coord) 3202 \begin{CompactList}\small\item\em Derive a polynomial that goes through the points --- can be done analytically.\item\end{CompactList}\item 3203 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Sort} ({\bf ps\-Float\-Array} $\ast$out, const {\bf ps\-Float\-Array} $\ast$my\-Array) 3204 \begin{CompactList}\small\item\em Sort an array.\item\end{CompactList}\item 3205 {\bf ps\-Int\-Array} $\ast$ {\bf ps\-Sort\-Index} ({\bf ps\-Int\-Array} $\ast$restrict out, const {\bf ps\-Float\-Array} $\ast$restrict my\-Array) 3206 \begin{CompactList}\small\item\em Sort an array, along with some other stuff.\item\end{CompactList}\item 3207 {\bf ps\-Stats} $\ast$ {\bf ps\-Array\-Stats} (const {\bf ps\-Float\-Array} $\ast$restrict my\-Array, const {\bf ps\-Int\-Array} $\ast$restrict mask\-Array, unsigned int mask\-Val, {\bf ps\-Stats} $\ast$stats) 3208 \begin{CompactList}\small\item\em Do Statistics on an array.\item\end{CompactList}\item 3209 {\bf ps\-Histogram} $\ast$ {\bf ps\-Histogram\-Alloc} (float lower, float upper, float size) 3210 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3211 {\bf ps\-Histogram} $\ast$ {\bf ps\-Histogram\-Alloc\-Generic} (const {\bf ps\-Float\-Array} $\ast$restrict lower, const {\bf ps\-Float\-Array} $\ast$restrict upper, float min\-Val, float max\-Val) 3212 \begin{CompactList}\small\item\em Generic constructor.\item\end{CompactList}\item 3213 void {\bf ps\-Histogram\-Free} ({\bf ps\-Histogram} $\ast$restrict my\-Hist) 3214 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3215 {\bf ps\-Histogram} $\ast$ {\bf ps\-Get\-Array\-Histogram} ({\bf ps\-Histogram} $\ast$restrict my\-Hist, const {\bf ps\-Float\-Array} $\ast$restrict my\-Array) 3216 \begin{CompactList}\small\item\em Calculate a histogram.\item\end{CompactList}\end{CompactItemize} 3217 3218 \subsection{Astronomy Functions} 3219 \begin{CompactItemize} 3220 \item 3221 {\bf ps\-Chip} $\ast$ {\bf ps\-Chip\-In\-FPA} ({\bf ps\-FPA} $\ast$fpa, {\bf ps\-Coord} $\ast$coord) 3222 \begin{CompactList}\small\item\em returns Chip in FPA which contains the given FPA coordinate\item\end{CompactList}\item 3223 {\bf ps\-Cell} $\ast$ {\bf ps\-Cell\-In\-Chip} ({\bf ps\-Chip} $\ast$chip, {\bf ps\-Coord} $\ast$coord) 3224 \begin{CompactList}\small\item\em returns Cell in Chip which contains the given chip coordinate\item\end{CompactList}\item 3225 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-Sky\-To\-TP} ({\bf ps\-Exposure} $\ast$exp, {\bf ps\-Coord} $\ast$coord) 3226 \begin{CompactList}\small\item\em Convert (RA,Dec) to tangent plane coords.\item\end{CompactList}\item 3227 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-TPto\-FPA} ({\bf ps\-FPA} $\ast$fpa, {\bf ps\-Coord} $\ast$coord) 3228 \begin{CompactList}\small\item\em Convert tangent plane coords to focal plane coordinates.\item\end{CompactList}\item 3229 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-FPAto\-Chip} ({\bf ps\-FPA} $\ast$fpa, {\bf ps\-Chip} $\ast$chip, {\bf ps\-Coord} $\ast$coord) 3230 \begin{CompactList}\small\item\em converts the specified FPA coord to the coord on the given Chip\item\end{CompactList}\item 3231 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-Chipto\-Cell} ({\bf ps\-Chip} $\ast$chip, {\bf ps\-Cell} $\ast$cell, {\bf ps\-Coord} $\ast$coord) 3232 \begin{CompactList}\small\item\em converts the specified Chip coord to the coord on the given Cell\item\end{CompactList}\item 3233 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-Cellto\-Chip} ({\bf ps\-Cell} $\ast$cell, {\bf ps\-Coord} $\ast$coord) 3234 \begin{CompactList}\small\item\em converts the specified Cell coord to the coord on the parent Chip\item\end{CompactList}\item 3235 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-Chipto\-FPA} ({\bf ps\-Chip} $\ast$chip, {\bf ps\-Coord} $\ast$coord) 3236 \begin{CompactList}\small\item\em converts the specified Chip coord to the coord on the parent FPA\item\end{CompactList}\item 3237 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-FPATo\-TP} ({\bf ps\-FPA} $\ast$fpa, {\bf ps\-Coord} $\ast$coord) 3238 \begin{CompactList}\small\item\em Convert focal plane coords to tangent plane coordinates.\item\end{CompactList}\item 3239 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-TPto\-Sky} ({\bf ps\-Exposure} $\ast$exp, {\bf ps\-Coord} $\ast$coord) 3240 \begin{CompactList}\small\item\em Convert tangent plane coords to (RA,Dec).\item\end{CompactList}\item 3241 float {\bf ps\-Get\-Airmass} ({\bf ps\-Coord} $\ast$coord, double sidereal\-Time) 3242 \begin{CompactList}\small\item\em Get the airmass for a given position and sidereal time.\item\end{CompactList}\item 3243 float {\bf ps\-Get\-Parallactic} ({\bf ps\-Coord} $\ast$coord, double sidereal\-Time) 3244 \begin{CompactList}\small\item\em Get the parallactic angle for a given position and sidereal time.\item\end{CompactList}\item 3245 float {\bf ps\-Get\-Refraction} (float colour, {\bf ps\-Phot\-System} color\-Plus, {\bf ps\-Phot\-System} color\-Minus, {\bf ps\-Exposure} $\ast$exp) 3246 \begin{CompactList}\small\item\em Estimate atmospheric refraction, along the parallactic.\item\end{CompactList}\item 3247 {\bf ps\-Exposure} $\ast$ {\bf ps\-Exposure\-Alloc} (double ra, double dec, double ha, double zd, double az, double lst, float mjd, float rot\-Angle, float temp, float pressure, float humidity, float exptime) 3248 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3249 void {\bf ps\-Exposure\-Free} ({\bf ps\-Exposure} $\ast$restrict my\-Exp) 3250 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3251 double {\bf ps\-Get\-MJD} (void) 3252 \begin{CompactList}\small\item\em Get current MJD, for a timestamp.\item\end{CompactList}\item 3253 double {\bf ps\-Get\-Sidereal} (float mjd, float longitude) 3254 \begin{CompactList}\small\item\em Get current sidereal time at longitude.\item\end{CompactList}\item 3255 char $\ast$ {\bf ps\-Time\-To\-ISOTime} (ps\-Time time) 3256 \begin{CompactList}\small\item\em Convert ps\-Time to ISOTime (Human-readable date/time string YYYY/MM/DD,HH:MM:SS.SSS).\item\end{CompactList}\item 3257 double {\bf ps\-Time\-To\-UTC} (ps\-Time time) 3258 \begin{CompactList}\small\item\em Convert ps\-Time to UTC.\item\end{CompactList}\item 3259 double {\bf ps\-Time\-To\-MJD} (ps\-Time time) 3260 \begin{CompactList}\small\item\em Convert ps\-Time to MJD.\item\end{CompactList}\item 3261 double {\bf ps\-Time\-To\-JD} (ps\-Time time) 3262 \begin{CompactList}\small\item\em Convert ps\-Time to JD.\item\end{CompactList}\item 3263 timeval $\ast$ {\bf ps\-Time\-To\-Timeval} (ps\-Time time) 3264 \begin{CompactList}\small\item\em Convert ps\-Time to timeval (struct timeval).\item\end{CompactList}\item 3265 tm $\ast$ {\bf ps\-Time\-To\-Tm} (ps\-Time time) 3266 \begin{CompactList}\small\item\em Convert ps\-Time to broken-down time (struct tm).\item\end{CompactList}\item 3267 ps\-Time $\ast$ {\bf ps\-ISOTime\-To\-Time} (char $\ast$input) 3268 \begin{CompactList}\small\item\em Convert ISOTime (Human-readable date/time string YYYY/MM/DD,HH:MM:SS.SSS) to ps\-Time.\item\end{CompactList}\item 3269 ps\-Time $\ast$ {\bf ps\-UTCTo\-Time} (double input) 3270 \begin{CompactList}\small\item\em Convert UTC to ps\-Time.\item\end{CompactList}\item 3271 ps\-Time $\ast$ {\bf ps\-MJDTo\-Time} (double input) 3272 \begin{CompactList}\small\item\em Convert MJD to ps\-Time.\item\end{CompactList}\item 3273 ps\-Time $\ast$ {\bf ps\-JDTo\-Time} (double input) 3274 \begin{CompactList}\small\item\em Convert JD to ps\-Time.\item\end{CompactList}\item 3275 ps\-Time $\ast$ {\bf ps\-Timeval\-To\-Time} (struct timeval $\ast$input) 3276 \begin{CompactList}\small\item\em Convert timeval to ps\-Time (struct timeval).\item\end{CompactList}\item 3277 ps\-Time $\ast$ {\bf ps\-TMto\-Time} (struct tm $\ast$input) 3278 \begin{CompactList}\small\item\em Convert broken-to ps\-Time down time (struct tm).\item\end{CompactList}\item 3279 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Alloc} (int nx, int ny, {\bf ps\-Type} type) 3280 \begin{CompactList}\small\item\em Create an image of the specified size and type.\item\end{CompactList}\item 3281 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Subset} ({\bf ps\-Image} $\ast$image, int nx, int ny, int x0, int y0) 3282 \begin{CompactList}\small\item\em Create a subimage of the specified area.\item\end{CompactList}\item 3283 void {\bf ps\-Image\-Free} ({\bf ps\-Image} $\ast$image) 3284 \begin{CompactList}\small\item\em Destroy the specified image (destroy children if they exist).\item\end{CompactList}\item 3285 int {\bf ps\-Image\-Free\-Children} ({\bf ps\-Image} $\ast$image) 3286 \begin{CompactList}\small\item\em Destroy the children of the specified image.\item\end{CompactList}\item 3287 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Copy} ({\bf ps\-Image} $\ast$output, {\bf ps\-Image} $\ast$input) 3288 \begin{CompactList}\small\item\em Create a copy of the specified image.\item\end{CompactList}\item 3289 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Image\-Slice} ({\bf ps\-Image} $\ast$input, int x, int y, int nx, int ny, int direction, {\bf ps\-Stats} $\ast$stats) 3290 \begin{CompactList}\small\item\em Extract pixels from rectlinear region to a vector.\item\end{CompactList}\item 3291 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Image\-Cut} ({\bf ps\-Image} $\ast$input, float xs, float ys, float xe, float ye, float dw, {\bf ps\-Stats} $\ast$stats) 3292 \begin{CompactList}\small\item\em Extract pixels along a line to a vector.\item\end{CompactList}\item 3293 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Image\-Radial\-Cut} ({\bf ps\-Image} $\ast$input, float x, float y, float radius, float dr, {\bf ps\-Stats} $\ast$stats) 3294 \begin{CompactList}\small\item\em Extract radial annulii data to a vector.\item\end{CompactList}\item 3295 {\bf ps\-Float\-Array} $\ast$ {\bf ps\-Image\-Contour} ({\bf ps\-Image} $\ast$input, float threshold, int binning) 3296 \begin{CompactList}\small\item\em Extract a 2-d contour from an image at the given threshold.\item\end{CompactList}\item 3297 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Rebin} ({\bf ps\-Image} $\ast$input, float scale, {\bf ps\-Stats} $\ast$stats) 3298 \begin{CompactList}\small\item\em Rebin image to new scale.\item\end{CompactList}\item 3299 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Rotate} ({\bf ps\-Image} $\ast$input, float angle) 3300 \begin{CompactList}\small\item\em Rotate image by given angle.\item\end{CompactList}\item 3301 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Shift} ({\bf ps\-Image} $\ast$input, float dx, float dy, float exposed) 3302 \begin{CompactList}\small\item\em Shift image by an arbitrary number of pixels in either direction.\item\end{CompactList}\item 3303 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Roll} ({\bf ps\-Image} $\ast$input, int dx, int dy) 3304 \begin{CompactList}\small\item\em Roll image by an integer number of pixels in either direction.\item\end{CompactList}\item 3305 {\bf ps\-Stats} $\ast$ {\bf ps\-Image\-Get\-Stats} ({\bf ps\-Image} $\ast$input, {\bf ps\-Stats} $\ast$stats) 3306 \begin{CompactList}\small\item\em defines statistics to be calculated\item\end{CompactList}\item 3307 {\bf ps\-Histogram} $\ast$ {\bf ps\-Image\-Histogram} ({\bf ps\-Histogram} $\ast$hist, {\bf ps\-Image} $\ast$input) 3308 \begin{CompactList}\small\item\em Construct a histogram from an image (or subimage).\item\end{CompactList}\item 3309 {\bf ps\-Polynomial2D} $\ast$ {\bf ps\-Image\-Fit\-Polynomial} ({\bf ps\-Image} $\ast$input, {\bf ps\-Polynomial2D} $\ast$coeffs) 3310 \begin{CompactList}\small\item\em Fit a 2-D polynomial surface to an image.\item\end{CompactList}\item 3311 int {\bf ps\-Image\-Eval\-Polynomial} ({\bf ps\-Image} $\ast$input, {\bf ps\-Polynomial2D} $\ast$coeffs) 3312 \begin{CompactList}\small\item\em Evaluate a 2-D polynomial surface to image pixels.\item\end{CompactList}\item 3313 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Read\-Section} ({\bf ps\-Image} $\ast$output, int x, int y, int dx, int dy, int z, char $\ast$extname, char $\ast$filename) 3314 \begin{CompactList}\small\item\em Read an image or subimage from a named file.\item\end{CompactList}\item 3315 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-FRead\-Section} ({\bf ps\-Image} $\ast$output, int x, int y, int dx, int dy, int z, char $\ast$extname, FILE $\ast$f) 3316 \begin{CompactList}\small\item\em Read an image or subimage from file descriptor.\item\end{CompactList}\item 3317 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Write\-Section} ({\bf ps\-Image} $\ast$input, int x, int y, int z, char $\ast$extname, char $\ast$filename) 3318 \begin{CompactList}\small\item\em Write an image section to named file (which may exist).\item\end{CompactList}\item 3319 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-FWrite\-Section} ({\bf ps\-Image} $\ast$input, int x, int y, int z, char $\ast$extname, FILE $\ast$f) 3320 \begin{CompactList}\small\item\em Write an image section to named file (which may exist).\item\end{CompactList}\item 3321 ps\-Metadata $\ast$ {\bf ps\-Image\-Read\-Header} (struct ps\-Metadata $\ast$output, char $\ast$extname, char $\ast$filename) 3322 \begin{CompactList}\small\item\em Read only header from image file.\item\end{CompactList}\item 3323 ps\-Metadata $\ast$ {\bf ps\-Image\-FRead\-Header} (struct ps\-Metadata $\ast$output, char $\ast$extname, FILE $\ast$f) 3324 \begin{CompactList}\small\item\em Read only header from image file descriptor.\item\end{CompactList}\item 3325 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-FFT} ({\bf ps\-Image} $\ast$input, int direction) 3326 \begin{CompactList}\small\item\em Perform an FFT on the image.\item\end{CompactList}\item 3327 int {\bf ps\-Image\-Clip} ({\bf ps\-Image} $\ast$input, float min, float vmin, float max, float vmax) 3328 \begin{CompactList}\small\item\em Clip image values outside of range to given values.\item\end{CompactList}\item 3329 int {\bf ps\-Image\-Clip\-Na\-N} ({\bf ps\-Image} $\ast$input, float value) 3330 \begin{CompactList}\small\item\em Clip Na\-N image pixels to given value.\item\end{CompactList}\item 3331 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Binary\-Op} ({\bf ps\-Image} $\ast$out, {\bf ps\-Image} $\ast$in1, char $\ast$operator, {\bf ps\-Image} $\ast$in2) 3332 \begin{CompactList}\small\item\em Perform a binary operation on two images.\item\end{CompactList}\item 3333 {\bf ps\-Image} $\ast$ {\bf ps\-Image\-Unary\-Op} ({\bf ps\-Image} $\ast$out, {\bf ps\-Image} $\ast$in1, char $\ast$operator) 3334 \begin{CompactList}\small\item\em Perform a unary operation on an image.\item\end{CompactList}\item 3335 int {\bf ps\-Image\-Overlay\-Section} ({\bf ps\-Image} $\ast$image, {\bf ps\-Image} $\ast$overlay, int x0, int y0, char $\ast$operator) 3336 \begin{CompactList}\small\item\em Overlay subregion of image with another image.\item\end{CompactList}\item 3337 {\bf ps\-Meta\-Data\-Item} $\ast$ {\bf ps\-Meta\-Data\-Item\-Alloc} (int type\-Flags, const void $\ast$val, const char $\ast$comment, const char $\ast$name,...) 3338 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3339 void {\bf ps\-Meta\-Data\-Item\-Free} ({\bf ps\-Meta\-Data\-Item} $\ast$ms) 3340 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3341 {\bf ps\-Meta\-Data\-Set} $\ast$ {\bf ps\-Meta\-Data\-Set\-Alloc} (void) 3342 \begin{CompactList}\small\item\em Constructor.\item\end{CompactList}\item 3343 void {\bf ps\-Meta\-Data\-Set\-Free} ({\bf ps\-Meta\-Data\-Set} $\ast$ms) 3344 \begin{CompactList}\small\item\em Destructor.\item\end{CompactList}\item 3345 {\bf ps\-Meta\-Data\-Item} $\ast$ {\bf ps\-Meta\-Data\-Append} ({\bf ps\-Meta\-Data\-Set} $\ast$restrict ms, {\bf ps\-Meta\-Data\-Item} $\ast$restrict item) 3346 \item 3347 {\bf ps\-Meta\-Data\-Item} $\ast$ {\bf ps\-Meta\-Data\-Remove} ({\bf ps\-Meta\-Data\-Set} $\ast$restrict ms, const char $\ast$restrict key) 3348 \item 3349 void {\bf ps\-Meta\-Data\-Set\-Iterator} ({\bf ps\-Meta\-Data\-Set} $\ast$ms) 3350 \item 3351 {\bf ps\-Meta\-Data\-Item} $\ast$ {\bf ps\-Meta\-Data\-Get\-Next} ({\bf ps\-Meta\-Data\-Set} $\ast$restrict ms, const char $\ast$restrict match) 3352 \item 3353 {\bf ps\-Meta\-Data\-Item} $\ast$ {\bf ps\-Meta\-Data\-Lookup} (const {\bf ps\-Meta\-Data\-Set} $\ast$restrict ms, const char $\ast$restrict key) 3354 \item 3355 void {\bf ps\-Meta\-Data\-Item\-Print} (FILE $\ast$fd, const {\bf ps\-Meta\-Data\-Item} $\ast$restrict ms, const char $\ast$prefix) 3356 \item 3357 {\bf ps\-Coord} $\ast$ {\bf ps\-Coord\-Xform\-Apply} ({\bf ps\-Coord\-Xform} $\ast$frame, {\bf ps\-Coord} $\ast$coords) 3358 \begin{CompactList}\small\item\em apply the coordinate transformation to the given coordinate\item\end{CompactList}\item 3359 {\bf ps\-Coord} $\ast$ {\bf ps\-Distortion\-Apply} ({\bf ps\-Distortion} $\ast$pattern, {\bf ps\-Coord} $\ast$coords, float mag, float color) 3360 \begin{CompactList}\small\item\em apply the optical distortion to the given coordinate, magnitude, color\item\end{CompactList}\item 3361 {\bf ps\-Coord} $\ast$ {\bf ps\-Get\-Offset} (const {\bf ps\-Coord} $\ast$restrict position1, const {\bf ps\-Coord} $\ast$restrict position2, char $\ast$system) 3362 \begin{CompactList}\small\item\em Get offset (RA,Dec) on the sky between two positions position1 and position2 may not be identical.\item\end{CompactList}\item 3363 {\bf ps\-Coord} $\ast$ {\bf ps\-Apply\-Offset} (const {\bf ps\-Coord} $\ast$restrict position, const {\bf ps\-Coord} $\ast$restrict offset, char $\ast$system) 3364 \begin{CompactList}\small\item\em Apply an offset to a position.\item\end{CompactList}\item 3365 {\bf ps\-Coord} $\ast$ {\bf ps\-Get\-Sun\-Pos} (float mjd) 3366 \begin{CompactList}\small\item\em Get Sun Position.\item\end{CompactList}\item 3367 {\bf ps\-Coord} $\ast$ {\bf ps\-Get\-Moon\-Pos} (float mjd, double latitude, double longitude) 3368 \begin{CompactList}\small\item\em Get Moon position.\item\end{CompactList}\item 3369 float {\bf ps\-Get\-Moon\-Phase} (float mjd) 3370 \begin{CompactList}\small\item\em Get Moon phase.\item\end{CompactList}\item 3371 {\bf ps\-Coord} $\ast$ {\bf ps\-Get\-Solar\-System\-Pos} (char $\ast$solar\-System\-Object, float mjd) 3372 \begin{CompactList}\small\item\em Get Planet positions.\item\end{CompactList}\item 3373 {\bf ps\-Coord} $\ast$ {\bf ps\-Coordinates\-Ito\-E} (const {\bf ps\-Coord} $\ast$restrict coordinates) 3374 \begin{CompactList}\small\item\em Convert ICRS to Ecliptic.\item\end{CompactList}\item 3375 {\bf ps\-Coord} $\ast$ {\bf ps\-Coordinates\-Eto\-I} (const {\bf ps\-Coord} $\ast$restrict coordinates) 3376 \begin{CompactList}\small\item\em Convert Ecliptic to ICRS.\item\end{CompactList}\item 3377 {\bf ps\-Coord} $\ast$ {\bf ps\-Coordinates\-Ito\-G} (const {\bf ps\-Coord} $\ast$restrict coordinates) 3378 \begin{CompactList}\small\item\em Convert ICRS to Galactic.\item\end{CompactList}\item 3379 {\bf ps\-Coord} $\ast$ {\bf ps\-Coordinates\-Gto\-I} (const {\bf ps\-Coord} $\ast$restrict coordinates) 3380 \begin{CompactList}\small\item\em Convert Galactic to ICRS.\item\end{CompactList}\end{CompactItemize} 3381 3382 1383 3383 \bibliographystyle{plain} \bibliography{panstarrs} 1384 3384
Note:
See TracChangeset
for help on using the changeset viewer.
