Changeset 4166 for trunk/doc/pslib/psLibSDRS.tex
- Timestamp:
- Jun 8, 2005, 2:40:48 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/doc/pslib/psLibSDRS.tex (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/pslib/psLibSDRS.tex
r4165 r4166 1 %%% $Id: psLibSDRS.tex,v 1.2 69 2005-06-09 00:35:55 price Exp $1 %%% $Id: psLibSDRS.tex,v 1.270 2005-06-09 00:40:48 eugene Exp $ 2 2 \documentclass[panstarrs,spec]{panstarrs} 3 3 … … 1512 1512 given \code{type}. 1513 1513 1514 \begin{prototype} 1515 int psVectorInit(psVector *image, ...); 1516 \end{prototype} 1517 1518 \code{psVectorInit} shall initialize the vector with the given value. 1519 The input data is cast to match the vector datatype, allowing for 1520 integers to be preserved. 1521 1514 1522 \subsection{Simple Images} 1515 1523 … … 1573 1581 dimensionality must be 2. 1574 1582 1583 \subsubsection{Support Functions} 1584 1575 1585 \begin{prototype} 1576 1586 psImage* psImageRecycle( … … 1588 1598 1589 1599 \begin{prototype} 1590 int psImageFreeChildren(psImage *image);1600 int psImageFreeChildren(psImage *image); 1591 1601 \end{prototype} 1592 1602 1593 1603 \code{psImageFreeChildren} shall free all child images of the given 1594 1604 \code{image}. 1605 1606 \begin{prototype} 1607 int psImageInit(psImage *image, ...); 1608 \end{prototype} 1609 1610 \code{psImageInit} shall initialize the image with the given value. 1611 The input data is cast to match the image datatype, allowing for 1612 integers to be preserved. 1613 1614 \subsubsection{Image Regions} 1615 1616 In many places, we need to refer to a rectangular area. We define a 1617 structure to represent a rectangle: 1618 \begin{datatype} 1619 typedef struct { 1620 float x0; 1621 float x1; 1622 float y0; 1623 float y1; 1624 } psRegion; 1625 \end{datatype} 1626 This structure is used in psLib as an abbreviation for the four 1627 floats, and is defined statically. Functions which accept or return a 1628 \code{psRegion} shall do so by value, not by pointer. 1629 1630 We define two functions to set and return the value of a 1631 \code{psRegion}. The first defines the region by the corner 1632 coordinates. The second function converts the IRAF description of a 1633 region in the form \code{[x0:x1,y0:y1]}, used for header entries such 1634 as \code{BIASSEC}, into the corresponding \code{psRegion} structure 1635 (any values that do not parse correctly shall be returned as 1636 \code{NaN}). We also define a function that converts a 1637 \code{psRegion} to the corresponding IRAF description. 1638 1639 \begin{prototype} 1640 psRegion psRegionSet(float x0, float x1, float y0, float y1); 1641 psRegion psRegionFromString(const char *region); 1642 char *psRegionToString(const psRegion region); 1643 \end{prototype} 1644 1645 All functions which use a psRegion must interpret the definition of 1646 $(x0,y0)$ and $(x1,y1)$ in the same way. The coordinate $(x0,y0)$ 1647 defines the starting pixel in the region. The coordinate $(x1,y1)$ 1648 defines the outer bound of the region. The size of the region is 1649 $(x1-x0,y1-y1)$. If either $x1$ or $y1$ is less than or equal to 0, 1650 the value is added to the image dimensions ($Nx + x1$). Thus a region 1651 \code{[0:0,0:0]} refers to the full image array, while 1652 \code{[0:-10,0:-20]} trims the last 10 columns and the last 20 rows. 1653 1654 \begin{prototype} 1655 psRegion psRegionForImage (psImage *image, psRegion in); 1656 \end{prototype} 1657 1658 An image region defined with negative upper limits may be rationalized 1659 for the bounds of a specific image with \code{psRegionForImage}. The 1660 output of this function is a region with negative upper limits 1661 replaced by their corrected value appropriate to the given image. 1595 1662 1596 1663 \subsection{Math Casting} … … 2102 2169 2103 2170 \pagebreak 2171 2172 \subsection{BitSets} 2173 2174 BitSets are required in order to turn options on and off. We require 2175 the capability to have a bitset of arbitrary length (i.e., not limited 2176 by the length of a \code{long}, say). The \code{psBitSet} structure 2177 is defined below. Note that the entry \code{bits} is an array of type 2178 \code{char} storing the bits as bits of each byte in the array, with 8 2179 bits available for each byte in the array. Also note that the 2180 constructor is passed the number of required bits, which implies that 2181 \code{ceil(n/8)} bytes must be allocated. The bitset structure is 2182 define by: 2183 \begin{datatype} 2184 typedef struct { 2185 long n; ///< Number of chars that form the bitset 2186 char *bits; ///< The bits 2187 } psBitSet; 2188 \end{datatype} 2189 2190 We also require the corresponding constructor and destructor: 2191 \begin{prototype} 2192 psBitSet *psBitSetAlloc(long nalloc); 2193 \end{prototype} 2194 where \code{n} is the requested number of bits. 2195 2196 Several basic operations on bitsets are required: 2197 \begin{itemize} 2198 \item Set a bit; 2199 \item Check if a bit is set; and 2200 \item \code{OR}, \code{AND} and \code{XOR} two bitsets. 2201 \item \code{NOT} a bitset. 2202 \end{itemize} 2203 The corresponding APIs are defined below: 2204 2205 \begin{prototype} 2206 psBitSet *psBitSetSet(psBitSet *bitSet, long bit); 2207 psBitSet* psBitSetClear(psBitSet *bitSet, long bit); 2208 psBitSet *psBitSetOp(psBitSet *outBitSet, const psBitSet *inBitSet1, const char *operator, const psBitSet *inBitSet2); 2209 psBitSet *psBitSetNot(psBitSet *outBitSet, const psBitSet *inBitSet); 2210 bool psBitSetTest(const psBitSet *bitSet, long bit); 2211 char *psBitSetToString(const psBitSet* bitSet); 2212 \end{prototype} 2213 2214 \code{psBitSetSet} sets the specified \code{bit} in the 2215 \code{psBitSet}, and returns the updated bitset. The input bitset 2216 will be modified. 2217 2218 \code{psBitSetClear} clears the specified \code{bit} in the \code{bitSet} 2219 and returns the updated bitset. The input bitset will be modified. 2220 2221 \code{psBitSetOp} returns the \code{psBitSet} that is the result of 2222 performing the specified \code{operator} (one of \code{"AND"}, 2223 \code{"OR"}, or \code{"XOR"}) on \code{inBitSet1} and \code{inBitSet2}. 2224 If the output bitset \code{outBitSet} is \code{NULL}, it is created by 2225 the function. 2226 2227 \code{psBitSetNot} applies a unary \code{NOT} to a bitset, placing the 2228 answer in the bitset \code{out}, or creating a new bitset if 2229 \code{out} is \code{NULL}. 2230 2231 \code{psBitSetTest} returns a true value if the specified \code{bit} 2232 is set; otherwise, it returns a false value. 2233 2234 Finally, \code{psBitSetToString} returns a string representation of 2235 the specified \code{bits}. 2236 2237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2238 2239 \section{Rich Data Structures and I/O} 2240 2241 \subsection{Metadata} 2242 \label{sec:metadata} 2243 2244 \subsubsection{Conceptual Overview} 2245 2246 Within PSLib, we provide a data structure to carry metadata and 2247 mechanisms to manipulate the metadata. Metadata is a general concept 2248 that requires some discussion. In any data analysis task, the 2249 ensemble of all possible data may be divided into two or three 2250 classes: there is the specific data of interest, there is data which 2251 is related or critical but not the primary data of interest, and there 2252 is all of the other data which may or may not be interesting. For 2253 example, consider a simple 2D image obtained of a galaxy from a CCD 2254 camera on a telescope. If you want to study the galaxy, the specific 2255 data of interest is the collection of pixels. There are a variety of 2256 other pieces of data which are closely related and crucial to 2257 understanding the data in those pixels, such as the dimensions of the 2258 image, the coordinate system, the time of the image, the exposure 2259 time, and so forth. Other data may be known which may be less 2260 critical to understanding the image, but which may be interesting or 2261 desired at a later date. For example, the observer who took the 2262 image, the filter manufacturer, the humidity at the telescope, etc. 2263 2264 Formally, all of the related data which describe the principal data of 2265 interest are metadata. Note that which piece is the metadata and 2266 which is the data may depend on the context. If you are examining the 2267 pixels in an image, the coordinate and flux of an object may be part 2268 of the metadata. However, if you are analyzing a collection of 2269 objects extracted from an image, you may consider then pixel data 2270 simply part of the metadata associated with the list of objects. 2271 2272 There are various ways to handle metadata vs data within a programming 2273 environment. In C, it is convenient to use structures to group 2274 associated data together. One possibility is to define the metadata 2275 as part of the associated data structure. For example, the image data 2276 structure would have elements for all possible associated measurement. 2277 This approach is both cumbersome (because of the large number metadata 2278 types), impractical (because the full range of necessary metadata is 2279 difficult to know in advance) and inflexible (because any change in 2280 the collection of metadata requires addition of new structure elements 2281 and recompilation). 2282 2283 An alternative is to place the metadata in a generic container and use 2284 lookup mechanisms to extract the appropriate metadata when needed. An 2285 example of this is would be a text-based FITS header for an image read 2286 into a flat text buffer. In this implementation, metadata lookup 2287 functions could return the current value of, for example, NAXIS1 (the 2288 number of columns of the image) by scanning through the header buffer. 2289 This method has the benefits of flexibility and simplicity of 2290 programming interface, but it has the disadvantage that all metadata 2291 is accessed though this lookup mechanism. This may make the code less 2292 readable and it may slow down the access. 2293 2294 PSLib implements an intermediate solution to this problem. We specify 2295 a flexible, generic metadata container and access methods. Data types 2296 which require association with a general collection of metadata should 2297 include an entry of this metadata type. However, a subset of metadata 2298 concepts which are basic and frequently required may be placed in the 2299 coded structure elements. This approach allows the code to refer to 2300 the basic metadata concepts as part of the data structure (ie, 2301 \code{image.nx}), but also allows us to provide access to any 2302 arbitrary metadata which may be generated. As a practical matter, the 2303 choice of which entries are only in the metadata and which are part of 2304 the explicit structure elements is rather subjective. Any data 2305 elements which are frequently used should be put in the structure; 2306 those which are only infrequently needed should be left in the generic 2307 metadata. 2308 2309 There are some points of caution which must be noted. Any 2310 manipulation of the data should be reflected in the metadata where 2311 appropriate. This is always an issue of concern. For example, 2312 consider an image of dimensions \code{nx, ny}. If a function extracts 2313 a subraster, it must change the values of \code{nx, ny} to match the 2314 new dimensions. What should it do to the corresponding metadata? 2315 Clearly, it should change the corresponding value which defines 2316 \code{nX, nY}. However, it is not quite so simple: there may be other 2317 metadata values which depend on those values. These must also be 2318 changed appropriately. What if the metadata element points to a 2319 copy of the metadata which may be shared by other representations of 2320 the image? These must be treated differently because the change would 2321 invalidate those other references. Care must be taken, therefore, 2322 when writing functions which operate on the data to consider all of 2323 the relevant metadata entries which must also be updated. 2324 2325 A related issue is the definition of metadata names. Entries in a 2326 structure have the advantage of being hardwired: every instance of 2327 that structure will have the same name for the same entry. This is 2328 not necessarily the case with a more flexible metadata container. The 2329 image exposure time is a notorious example in astronomy. Different 2330 observatories use different header keywords (ie, metadata names) for 2331 the same concept of the exposure time (\code{EXPTIME}, 2332 \code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc). Any system 2333 which operates on these metadata needs to address the issue of 2334 identifying these names. This issue seems like an argument for 2335 hardwiring metadata in the structure, but in fact it does not present 2336 such a strong case. If the metadata are hardwired, some function will 2337 still have to know how to interpret the various names to populate the 2338 structure. The concept can still be localized with generic metadata 2339 containers by including abstract metadata names within the code which 2340 are tied to the various implementations-specific metadata names. 2341 2342 \subsubsection{Metadata Representation} 2343 2344 \begin{figure} 2345 \psfig{file=Metadata,width=6.5in} 2346 \caption{Metadata Structures\label{fig:metadata}} 2347 \end{figure} 2348 2349 This section addresses the question of how \PS{} metadata should be 2350 represented in memory, not how it should be represented on disk. 2351 2352 We define an item of metadata with the following structure: 2353 \filbreak 2354 \begin{datatype} 2355 typedef struct { 2356 const psS32 id; ///< unique ID for this item 2357 char *name; ///< Name of item 2358 psMetadataType type; ///< type of this item 2359 const union { 2360 psS32 S32; ///< integer data 2361 psF32 F32; ///< floating-point data 2362 psF64 F64; ///< double-precision data 2363 psList *list; ///< psList entry 2364 psMetadata *md; ///< psMetadata entry 2365 psPtr V; ///< other type 2366 } data; ///< value of metadata 2367 char *comment; ///< optional comment ("", not NULL) 2368 } psMetadataItem; 2369 \end{datatype} 2370 2371 The \code{id} is a unique identifier for this item of metadata; 2372 experience shows that such tags are useful. The entry \code{name} 2373 specifies the name of the metadata item. The value of the metadata is 2374 given by the union \code{data}, and may be of type \code{psS32}, 2375 \code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at 2376 by the \code{void} pointer \code{V}. A character string comment 2377 associated with this metadata item may be stored in the element 2378 \code{comment}. The \code{type} entry specifies how to interpret the 2379 type of the data being represented, given by the enumerated type 2380 \code{psMetadataType}: 2381 % 2382 \filbreak 2383 \begin{datatype} 2384 typedef enum { ///< type of item.data is: 2385 PS_META_S32 = PS_TYPE_S32, ///< psS32 primitive data. 2386 PS_META_F32 = PS_TYPE_F32, ///< psF32 primitive data. 2387 PS_META_F64 = PS_TYPE_F64, ///< psF64 primitive data. 2388 PS_META_BOOL = PS_TYPE_BOOL, ///< psBool primitive data. 2389 PS_META_LIST = 0x10000, ///< List data (Stored as item.data.list). 2390 PS_META_STR, ///< String data (Stored as item.data.V). 2391 PS_META_META, ///< Metadata (Stored as item.data.md). 2392 PS_META_VEC, ///< Vector data (Stored as item.data.V). 2393 PS_META_IMG, ///< Image data (Stored as item.data.V). 2394 PS_META_HASH, ///< Hash data (Stored as item.data.V). 2395 PS_META_LOOKUPTABLE, ///< Lookup table data (Stored as item.data.V). 2396 PS_META_JPEG, ///< JPEG data (Stored as item.data.V). 2397 PS_META_PNG, ///< PNG data (Stored as item.data.V). 2398 PS_META_ASTROM, ///< Astrometric coefficients (Stored as item.data.V). 2399 PS_META_TIME, ///< psTime object (Stored as item.data.V). 2400 PS_META_UNKNOWN, ///< Other data (Stored as item.data.V). 2401 PS_META_MULTI ///< Used internally, do not create a metadata item of this type. 2402 } psMetadataType; 2403 \end{datatype} 2404 The macro \code{PS_META_IS_PRIMITIVE(psMetadataType.type)} returns 2405 true if the type is one of the primitive data types (S32, F64, etc). 2406 In such a case, the data value is directly available. Otherwise, a 2407 pointer to the data is available. 2408 2409 A collection of metadata is represented by the \code{psMetadata} structure: 2410 \begin{datatype} 2411 typedef struct { 2412 psList *list; ///< list of psMetadataItem 2413 psHash *hash; ///< hash table of the same metadata 2414 } psMetadata; 2415 \end{datatype} 2416 The type \code{psMetadata} is a container class for metadata. Note 2417 that there are in fact \emph{two} representations of the metadata 2418 (each \code{psMetadataItem} appears on both). The first 2419 representation employs a doubly-linked list that allows the order of 2420 the metadata to be preserved (e.g., if FITS headers are read in a 2421 particular order, they should be written in the same order). The 2422 second representation employs a hash table which allows fast look-up 2423 given a specific metadata keyword. 2424 2425 Certain metadata names (such as the FITS keywords \code{COMMENT} and 2426 \code{HISTORY} in a FITS header) may be repeated with different 2427 values. In such a case, the \code{psMetadata.list} structure contains 2428 the entries in their original sequence with duplicate keys. The 2429 \code{psMetadata.hash} entries, which are required to have unique 2430 keys, would have a single entry with the keyword of the repeated key, 2431 with the value of \code{psMetadataType} set to \code{PS_META_MULTI}, 2432 and the \code{psMetadataItem.data} element pointing to a \code{psList} 2433 containing the actual entries. If \code{psMetadataItemAlloc} is 2434 called with the type set to \code{PS_META_MULTI}, such a repeated key 2435 is created. In this case, the data value passed to 2436 \code{psMetadataItemAlloc} (the quantity in ellipsis) must be 2437 \code{NULL}. An empty \code{psMetadataItem} with the given keyword is 2438 created to hold future entries of that keyword. 2439 2440 As a convenience to the user, the following type-specific functions are 2441 also defined: 2442 \begin{prototype} 2443 psMetadataItem* psMetadataItemAllocStr(const char* name, const char* comment, const char* value); 2444 psMetadataItem* psMetadataItemAllocF32(const char* name, const char* comment, psF32 value); 2445 psMetadataItem* psMetadataItemAllocF64(const char* name, const char* comment, psF64 value); 2446 psMetadataItem* psMetadataItemAllocS32(const char* name, const char* comment, psS32 value); 2447 psMetadataItem* psMetadataItemAllocBool(const char* name, const char* comment, bool value); 2448 psMetadataItem* psMetadataItemAllocPtr(const char* name, psMetadataType type, const char* comment, psPtr value); 2449 \end{prototype} 2450 2451 \subsubsection{Metadata APIs} 2452 2453 \begin{prototype} 2454 psMetadata *psMetadataAlloc(void); 2455 \end{prototype} 2456 2457 The constructor for the collection of metadata, \code{psMetadata}, 2458 simply returns an empty metadata container (employing the constructors 2459 for the doubly-linked list and hash table). The destructor needs to 2460 free each of the \code{psMetadataItem}s. 2461 2462 \begin{prototype} 2463 psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...); 2464 psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list); 2465 \end{prototype} 2466 2467 The allocator for \code{psMetadataItem} returns a full 2468 \code{psMetadataItem} ready for insertion into the \code{psMetadata}. 2469 The \code{name} entry specifies the name to use for this metadata 2470 item, and may include \code{sprintf}-type formating codes. The 2471 \code{comment} entry is a fixed string which is used for the comment 2472 associated with this metadata item. The metadata data and the 2473 arguments to the \code{name} formatting codes are passed, in that 2474 order (metadata pointer first), to \code{psMetadataItemAlloc} as 2475 arguments following the comment string. The data must be a pointer 2476 for any data types which are stored in the element \code{data.void}, 2477 while other data types are passed as numeric values. The argument 2478 list must be interpreted appropriately by the \code{va_list} operators 2479 in the function. 2480 2481 \begin{prototype} 2482 bool psMetadataAddItem(psMetadata *md, const psMetadataItem *item, psS32 location, psS32 flags); 2483 bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...); 2484 bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment, 2485 va_list list); 2486 \end{prototype} 2487 2488 Items may be added to the metadata in one of two ways --- firstly, an 2489 item may be added by appending a \code{psMetadataItem} which has 2490 already been created; and secondly by directly providing the data to 2491 be appended. In both cases, the return value defines the success 2492 (\code{true}) or failure of the operation. The second function, 2493 \code{psMetadataAdd} takes a pointer or value which is interpreted by 2494 the function using variadic argument interpretation. The third 2495 version is the \code{va_list} version of the second function. All 2496 three functions take a parameter, \code{location}, which specifies 2497 where in the list to place the element, following the conventions for 2498 the \code{psList}. The entry \code{mode} for \code{psMetadataAddItem} 2499 is a bit mask constructed by OR-ing the allowed option flags (eg, 2500 \code{PS_META_REPLACE}) which specify minor variations on the 2501 behavior. The \code{format} entry, which specifies both the metadata 2502 type and the optional flags, is constructed by bit-wise OR-ing the 2503 appropriate \code{psMetadataType} and allowed option flags. Care 2504 should be taken not to leak memory when appending an item for which 2505 the key already exists in the metadata (and is not 2506 \code{PS_META_MULTI}). 2507 % 2508 2509 \begin{datatype} 2510 typedef enum { ///< option flags for psMetadata functions 2511 PS_META_DEFAULT = 0, ///< default behavior (0x0000) for use in mode above 2512 PS_META_REPLACE = 0x1000000 ///< allow entry to be replaced 2513 PS_META_DUPLICATE_OK = 0x2000000 ///< allow duplicate entries 2514 PS_META_NULL = 0x4000000 ///< psMetadataItem.data is a NULL value 2515 } psMetadataFlags; 2516 \end{datatype} 2517 2518 The functions above take option flags which modify the behavior when 2519 metadata items are added to the metadata list. These flags must be 2520 bit-exclusive of those used above for the \code{psMetadataTypes}. The 2521 flags have the following meanings: 2522 2523 \code{PS_META_DEFAULT}: This is the zero bit mask, to allow the 2524 default behavior for \code{psMetadataAddItem} above. If this is OR-ed 2525 with a \code{psMetadataType}, the result is as if no OR-ing took 2526 place. 2527 2528 \code{PS_META_REPLACE}: Replace an existing, unique entry. If the 2529 given metadata item exists in the metadata collection, and is not of 2530 type \code{PS_META_MULTI}, then the item replaces the existing entry. 2531 2532 \code{PS_META_DUPLICATE_OK}: Allow the new metadata item key to be a 2533 duplicate (ie, \code{PS_META_MULTI}). If an existing item with the 2534 same key is already \code{PS_META_MULTI}, the new item is added to the 2535 \code{PS_META_MULTI} list. If the existing item is not 2536 \code{PS_META_MULTI}, a \code{PS_META_MULTI} list is created to 2537 contain both the existing item and the new item. The original entry's 2538 location on the psMetadata.list must be maintained. 2539 2540 \code{PS_META_NULL}: Indicates that \code{psMetadataItem.data} should be 2541 ignored and that the the current value is ``NULL'' or undefined. The 2542 \code{psMetadataItem} must have a proper \code{type} set and it's \code{data} 2543 field shall have a valid value. e.g. A \code{type} of \code{PS_META_STR} would 2544 require that 's \code{data} is set to \code{NULL}. 2545 2546 There are several of cases to handle for duplication of an existing 2547 key by a new key, some identified above. The following situations 2548 must also be handled: 2549 2550 If the new key already exists, but is not \code{PS_META_MULTI}, and 2551 the new item is not flagged as either \code{PS_META_DUPLICATE_OK} or 2552 \code{PS_META_REPLACE}, an error is raised. 2553 2554 If the new key already exists, and the existing item is 2555 \code{PS_META_MULTI}, the new item is added to the MULTI list. Note 2556 that if the new item is also of type \code{PS_META_MULTI}, no action 2557 is taken, but a successful exit status is returned (the action of 2558 adding a \code{PS_META_MULTI} item to the metadata is equivalent to 2559 setting that key to be tagged as \code{PS_META_MULTI}. If it is 2560 {\em already} \code{PS_META_MULTI}, this effect has already been 2561 achieved). 2562 2563 An example of code to use these metadata APIs to generate the 2564 structure seen in Figure~\ref{fig:metadata} is given below. 2565 2566 \begin{verbatim} 2567 md = psMetadataAlloc(); 2568 2569 psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE", PS_META_BOOL, "basic fits", TRUE); 2570 psMetadataAdd(md, PS_LIST_TAIL, "BLANK", PS_META_S32, "invalid pixel data", -32768); 2571 psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR, "observing date UT", " 2004-6-16"); 2572 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_LIST, "head of comment block", NULL); 2573 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "DATA"); 2574 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "PARAMS"); 2575 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32, "exposure time (sec)", 1.05); 2576 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "FOO"); 2577 2578 cell = psMetadataAlloc(); 2579 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD00"); 2580 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-00"); 2581 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.00"); 2582 psMetadataAdd(md, PS_LIST_TAIL, "CELL.00", PS_META_META, "", cell); 2583 2584 cell = psMetadataAlloc(); 2585 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD01"); 2586 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-01"); 2587 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.01"); 2588 psMetadataAdd(md, PS_LIST_TAIL, "CELL.01", PS_META_META, "", cell); 2589 \end{verbatim} 2590 2591 The following code shows how to use the APIs to replace one of these values: 2592 \begin{verbatim} 2593 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32 | PS_REPLACE, "new exposure time (sec)", 2.05); 2594 \end{verbatim} 2595 2596 As a convenience to the user, the following type-specific functions 2597 are specified: 2598 \begin{prototype} 2599 bool psMetadataAddStr(psMetadata* md, psS32 location, const char* name, const char* comment, 2600 const char* value); 2601 bool psMetadataAddS32(psMetadata* md, psS32 location, const char* name, const char* comment, psS32 value); 2602 bool psMetadataAddF32(psMetadata* md, psS32 location, const char* name, const char* comment, psF32 value); 2603 bool psMetadataAddF64(psMetadata* md, psS32 location, const char* name, const char* comment, psF64 value); 2604 bool psMetadataAddBool(psMetadata* md, psS32 location, const char* name, const char* comment, bool value); 2605 bool psMetadataAddPtr(psMetadata* md, psS32 location, const char* name, psMetadataType type, 2606 const char* comment, psPtr value); 2607 \end{prototype} 2608 2609 2610 Items may be removed from the metadata by specifying a key or a 2611 location in the list. If the value of \code{name} is \code{NULL}, the 2612 value of \code{location} is used. If the value of \code{name} is not 2613 \code{NULL}, then \code{location} must be set to 2614 \code{PS_LIST_UNKNOWN}. If the key matches a metadata item, the item 2615 is removed from the metadata and \code{true} is returned; otherwise, 2616 \code{false} is returned. If the key is not unique, then \emph{all} 2617 items corresponding to the key are removed, and \code{true} is 2618 returned. 2619 % 2620 \begin{prototype} 2621 bool psMetadataRemove(psMetadata *md, int location, const char *key); 2622 \end{prototype} 2623 2624 Items may be found within the metadata by providing a key. In the 2625 event that the key is non-unique, the first item is returned. 2626 \begin{prototype} 2627 psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key); 2628 \end{prototype} 2629 2630 Several utility functions are provided for simple cases. These 2631 functions perform the effort of casting the data to the appropriate 2632 type. The numerical functions shall return 0.0 if their key is not 2633 found. If the pointer value of \code{status} is not \code{NULL}, it 2634 is set to reflect the success or failure of the lookup. 2635 \begin{prototype} 2636 psPtr psMetadataLookupStr(bool *status, const psMetadata *md, const char *key); 2637 psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key); 2638 psF32 psMetadataLookupF32(bool *status, const psMetadata *md, const char *key); 2639 psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key); 2640 bool psMetadataLookupBool(bool *status, const psMetadata *md, const char *key); 2641 psPtr psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key); 2642 \end{prototype} 2643 2644 Items may be retrieved from the metadata by their entry position. The 2645 value of which specifies the desired entry in the fashion of 2646 \code{psList}. 2647 \begin{prototype} 2648 psMetadataItem *psMetadataGet(const psMetadata *md, int location); 2649 \end{prototype} 2650 2651 The metadata list component may be iterated over by using a 2652 \code{psMetadataIterator} in a fashion equivalent to the 2653 \code{psListIterator}: 2654 \begin{datatype} 2655 typedef struct { 2656 psListIterator* iter; ///< iterator for the psMetadata's psList 2657 regex_t* regex; ///< the subsetting regular expression 2658 } psMetadataIterator; 2659 \end{datatype} 2660 2661 The iterator may be set to a location in the \code{psMetadata} list, 2662 and the user may get the previous or next item in the list relative to 2663 that location. \code{psMetadataGetNext} has the ability to match the 2664 key using a POSIX \code{regex}, e.g., if the user only wants to 2665 iterate through \code{IPP.machines.sky} and doesn't want to bother 2666 with \code{IPP.machines.detector}. The iterator should iterate over 2667 every item in the metadata list, even those that are contained in a 2668 \code{PS_META_LIST}. The value \code{iterator} specifies the iterator 2669 to be used. In setting the iterator, the position of the iterator is 2670 defined by \code{location}, which follows the conventions of the 2671 \code{psList} iterators. 2672 \begin{prototype} 2673 psMetadataIterator *psMetadataIteratorAlloc(psMetadata *md, int location, const char *regex); 2674 bool psMetadataIteratorSet(psMetadataIterator *iterator, int location); 2675 psMetadataItem *psMetadataGetAndIncrement(psMetadataIterator *iterator); 2676 psMetadataItem *psMetadataGetAndDecrement(psMetadataIterator *iterator); 2677 \end{prototype} 2678 2679 Metadata items may be printed to an open file descriptor based on a 2680 provided format. The format string is an sprintf format statement 2681 with exactly one \% formatting command. If the metadata item type is 2682 a numeric type, this formatting command must also be numeric, and type 2683 conversion performed to the value to match the format type. If the 2684 metadata item type is a string, the formatting command must also be 2685 for a string (\%s type of command). If the metadata type is any other 2686 data type, printing is not allowed. 2687 \begin{prototype} 2688 bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *item); 2689 \end{prototype} 2690 2691 \subsubsection{Configuration files} 2692 \label{sec:configspec} 2693 2694 It will be necessary for the \PS{} system, in order to load 2695 pre-defined settings, to parse a configuration file into a 2696 \code{psMetadata} structure. This shall be performed by the 2697 function \code{psMetadataConfigParse}, as described below. 2698 2699 \begin{prototype} 2700 psMetadata *psMetadataConfigParse(psMetadata *md, int *nFail, const char *filename, bool overwrite); 2701 \end{prototype} 2702 2703 Given a metadata container, \code{md}, and the name of a configuration 2704 file, \code{filename}, \code{psMetadataConfigParse} shall parse the 2705 configuration file, placing the contained key/type/value/comment quads 2706 into the metadata, and returning a pointer to the metadata structure. 2707 The number of lines that failed to parse is returned in \code{nFail}. 2708 Multiple specifications of a key that haven't been declared (see 2709 below) are overwritten if and only if \code{overwrite} is \code{true}. 2710 If the metadata container is \code{NULL}, it shall be allocated. 2711 2712 On error, the function shall return \code{NULL}. 2713 2714 It is also useful to be able to convert a \code{psMetadata} structure into the 2715 Configuration File format for debugging purposes and to enable persistent 2716 configuration. 2717 2718 \begin{prototype} 2719 char *psMetadataConfigFormat(psMetadata *md); 2720 bool psMetadataConfigWrite(psMetadata *md, const char *filename); 2721 \end{prototype} 2722 2723 The \code{psMetadataConfigFormat} function converts a \code{psMetadata} 2724 structure (including any nested \code{psMetadata}) into a Configuration File 2725 formatted string. A \code{NULL} shall be returned on error. The 2726 \code{psMetadataConfigWrite} behaves the same as \code{psMetadataConfigFormat} 2727 except that the string is written out to \code{filename}. \code{false} is 2728 returned on failure. 2729 2730 \paragraph{Comments} 2731 2732 The configuration file shall consist of plain text with 2733 key/type/value/comment quads on separate lines. Blank lines, 2734 including those consisting solely of whitespace (both spaces and 2735 tabs), shall be ignored, as shall lines that commence with the comment 2736 character (a hash mark, \code{#}), either immediately at the start of 2737 the line, or preceded by whitespace. The key/type/value/comment quads 2738 shall all lie on a single line, separated by whitespace. 2739 2740 The key shall be first, possibly preceded on the line by whitespace 2741 which should not form part of the key. 2742 2743 \paragraph{NULL values} 2744 2745 The ``value'' of a quad may be declare to be undefined with the \code{NULL} 2746 keyword. \code{NULL} is allowed to co-exist with a ``comment'' and may be 2747 surrounded by whitespace. Any non-whitespace character will cause of the 2748 ``value'' to be interpreted as a string. 2749 2750 \begin{verbatim} 2751 foo STR NULL # string with a NULL value 2752 bar STR NULL a # string with a value of "NULL a" 2753 \end{verbatim} 2754 2755 \paragraph{Types} 2756 \subparagraph{Scalar \& Vector} 2757 2758 Next, to assist the casting of the value, shall be a string identifying the 2759 type of the value, which shall correspond to one of the simple types supported 2760 in \code{psMetadata}: \code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to 2761 abbreviate \code{STRING}; valid time types are \code{UTC,UT1,TAI,TT}. 2762 2763 \tbd{May, in the future, require more types, including U8,S16,C64, 2764 which will also necessitate updating the definition of psMetadata.} 2765 2766 The value shall follow the type: strings may consist of multiple words, and 2767 shall have all leading and trailing whitespace removed; booleans shall simply 2768 be either \code{T} or \code{F}. Time type values will be in the ISO8601 2769 compatible format of "YYYY-MM-DDTHH:MM:SS,sZ". When parsed, time types shall 2770 be represented as a \code{psTime} object. 2771 2772 Following the value may be an optional comment, preceded by a comment 2773 character (a hash mark, \code{#}), which in the case of a string 2774 value, serves to mark the end of the value, and for other types serves 2775 to identify the comment to the reader. Only one comment character may 2776 be present on any single line (i.e., neither strings nor comments are 2777 permitted to contain the comment character). The comment may consist 2778 of multiple words, and shall have leading and trailing whitespace 2779 removed. 2780 2781 One wrinkle is the specification of vectors. Keys for which the value 2782 is to be parsed as a vector shall be preceded immediately by a 2783 ``vector symbol'', which we choose to be the ``at'' sign, \code{@}. 2784 In this case, the type shall be interpreted as the type for the 2785 vector, which may be any of the signed or unsigned integer or floating 2786 point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not 2787 the complex floating point types; and the value shall consist of 2788 multiple numbers, separated either by a comma or whitespace. These 2789 values shall populate a \code{psVector} of the appropriate type in the 2790 order in which they appear in the configuration file. 2791 2792 \tbd{May add complex types, likely to be specified with values such as 2793 1.23+4.56i in the future.} 2794 2795 \tbd{May add null, Not-a-Number (NaN), de-normalized, underflow, overflow, 2796 and/or +/-infinity values for selected types.} 2797 2798 \subparagraph{MULTI} 2799 2800 An additional hurdle is the specification of keys that may be non-unique (such 2801 as the \code{COMMENT} keyword in a FITS header). These keys shall be specified 2802 in the configuration file as non-unique with a \code{MULTI} declaration. In 2803 the form \code{[keyword] MULTI}. No other data may be provided on this line, 2804 though a comment, preceded by the comment marker, is valid. A warning shall 2805 be produced when a key which has not been specified to be non-unique is 2806 repeated; in this case, the former value shall be overwritten if 2807 \code{overwrite} is \code{true}, otherwise the line shall be ignored and 2808 counted as one that could not be parsed. It should be noted that non-unique 2809 keys may be of mixed type (even the \code{TYPE} and \code{METADATA} complex 2810 types). For example: 2811 \begin{verbatim} 2812 comment MULTI # a comment 2813 comment STR some string 2814 comment F32 1.23456 2815 comment BOOL T 2816 \end{verbatim} 2817 2818 If a line does not conform to the rules laid out here, a warning shall 2819 be generated, it shall be ignored and counted as a line that could not 2820 be parsed. The total number of lines that were not able to be parsed 2821 (including those that were ignored because \code{overwrite} is 2822 \code{false}, and any other parsing problems, but not including blank 2823 lines and comment lines) shall be returned by the function in the 2824 argument \code{nFail}. 2825 2826 Here are some examples of lines of a valid configuration file: 2827 \filbreak 2828 \begin{verbatim} 2829 Double F64 1.23456789 # This is a comment 2830 Float F32 0.98765 # This is a comment too 2831 String STR This is the string that forms the value #comment 2832 2833 # This is a comment line and is to be ignored 2834 boolean BOOL T # The value of `boolean' is `true' 2835 2836 @primes U8 2,3 5 7,11,13 17 # These are prime numbers 2837 2838 comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique 2839 comment STR This 2840 comment STR is 2841 comment STR a 2842 comment STR non-unique 2843 comment STR key 2844 Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored 2845 \end{verbatim} 2846 2847 Of course, a real configuration file should look much nicer to humans 2848 than the above example, but PSLib must be able to parse such ugly 2849 files. 2850 2851 \paragraph{Complex Types} 2852 \subparagraph{TYPE} 2853 2854 We support a modest tree structure by defining a reserved keyword \code{TYPE}. 2855 Any line in the config file which starts with the word \code{TYPE} shall be 2856 interpreted as defining a new valid type. The defined type name follows the 2857 word \code{TYPE}, and is in turn followed by an arbitrary number of words. 2858 These words are to be interpreted as the names of an embedded \code{psMetadata} 2859 entry, where the values are given on any line which (following the \code{TYPE} 2860 definition) employs the new type name. For example, a new type may be defined 2861 as: 2862 \begin{verbatim} 2863 TYPE CELL EXTNAME BIASSEC CHIP 2864 CELL.00 CELL CCD00 BSEC-00 CHIP.00 2865 CELL.01 CELL CCD01 BSEC-01 CHIP.00 2866 \end{verbatim} 2867 2868 When \code{psMetadataConfigParse} encounters the \code{TYPE} line, it 2869 should construct a \code{psMetadata} container and fill it with 2870 \code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP}, 2871 with type \code{PS_META_STR}, but data allocated. When it next 2872 encounters an entry of type \code{CELL}, it should then use the given 2873 name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy 2874 the \code{psMetadata} data onto the \code{psMetadataItem.data.md} 2875 entry, filling in the values from the rest of the line (\code{CCD00, 2876 BSEC-00, CHIP.00}). This hierarchical structure is illustrated in 2877 Figure~\ref{fig:metadata}. 2878 2879 \subparagraph{METADATA} 2880 2881 Another way to form a tree-like structure is to directly define a 2882 \code{psMetadata} entry using a sequence of successive lines to define the 2883 values of the \code{psMetadataItem} entries. The initial line defines the new 2884 \code{psMetadata} entry and its name. The following lines have the same format 2885 as the other metadata config file entries. The sequence is terminated with a 2886 line with a single word \code{END}. For example, a metadata entry may be 2887 defined as: 2888 \begin{verbatim} 2889 CELL METADATA 2890 EXTNAME STR CCD00 2891 BIASSEC STR BSEC-00 2892 CHIP STR CHIP.00 2893 NCELL S32 24 2894 END 2895 \end{verbatim} 2896 2897 \paragraph{Scoping Rules} 2898 2899 A simple set of ``Scoping Rules'' are required to properly parse a 2900 configuration file. ``Scope'' refers to the current ``level'' of 2901 \code{METADATA} that a statement appears in. Statements that are not contained 2902 in a nested \code{METADATA} are said to be in the ``Top level scope''. Each 2903 level of nested \code{METADATA} statements create a new ``lower level scope''. 2904 2905 \begin{itemize} 2906 \item 2907 Variable names are unique only to the current level of scope. 2908 2909 \item 2910 non-unique keywords (\code{MULTI}) apply only to the current scope. i.e. They 2911 are invalid in ``higher'' or ``lower'' level scopes. 2912 2913 \item 2914 \code{TYPE} declarations apply only to the current scope. 2915 2916 \item 2917 \code{METADATA} declarations must begin and end in the same scope. i.e. They 2918 may not be declared and end in two different nested METADATA and the same 2919 depth. 2920 \end{itemize} 2921 2922 A series of test inputs is contained in 2923 \S\ref{sec:configtest}. 2924 2925 \subsection{XML Functions} 2926 2927 Within Pan-STARRS, we will use XML documents as a transport mechanism 2928 to carry data between programs and between IPP and other subsystems. 2929 Configuration information may be stored as well as XML documents, in 2930 addition to the text format discussed in the discussion on Metadata. 2931 XML is an extremely variable document format, and it is not currently 2932 the intention of PSLib to provide a complete PSLib version of XML 2933 operations. Rather, a limited number of operations are defined to 2934 convert specific data structures to an appropriate XML document. To 2935 maximize the simplicity of the XML APIs, we will use the convention 2936 that a single XML document to be parsed by PSLib shall contain only a 2937 single data structure. Each of the XML APIs therefore take as input a 2938 reference to a complete XML document and return a PSLib data 2939 structure, or take a PSLib data structure and return a complete XML 2940 document. 2941 2942 We start by defining a PSLib wrapper type which is a pointer to an XML 2943 document in memory. We wrap the \code{libxml2} version of an XML 2944 document pointer for now: 2945 \begin{datatype} 2946 typedef xmlDocPtr psXMLDoc; 2947 \end{datatype} 2948 2949 \begin{prototype} 2950 psXMLDoc *psXMLDocAlloc(void); 2951 \end{prototype} 2952 2953 The next pair of functions convert a \code{psMetadata} data structure 2954 to a complete \code{psXMLDoc} (in memory) and vice versa: 2955 \begin{prototype} 2956 psXMLDoc *psMetadataToXMLDoc(const psMetadata *md); 2957 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc); 2958 \end{prototype} 2959 2960 The next pair of functions loads the data in a named file into a 2961 complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc} 2962 to a named file: 2963 \begin{prototype} 2964 psXMLDoc *psXMLParseFile(const char *filename); 2965 int psXMLDocToFile(const psXMLDoc *doc, const char *filename); 2966 \end{prototype} 2967 2968 The next pair of functions accepts a block of memory and parses it 2969 into a complete \code{psXMLDoc} (also in memory), and vice versa: 2970 \begin{prototype} 2971 psXMLDoc *psXMLParseMem(const char *buffer, int size); 2972 int psXMLDocToMem(const psXMLDoc *doc, char *buffer); 2973 \end{prototype} 2974 2975 The next pair of functions read from and write to a file descriptor. 2976 The first converts the incoming data to a complete \code{psXMLDoc} 2977 (also in memory), the second writes the \code{psXMLDoc} to the file 2978 descriptor: 2979 \begin{prototype} 2980 psXMLDoc *psXMLParseFD(int fd); 2981 int psXMLDocToFD(const psXMLDoc *doc, int fd); 2982 \end{prototype} 2983 2984 \subsection{Database Functions} 2985 2986 Many of the applications that PSLib will be used for will require 2987 access to a simple relational database. PSLib includes generic 2988 database-independent interface mechanisms as part of its API set. The 2989 most important aspect of PSLib's database support is to abstract as 2990 much database specific complexity as is feasible. As almost all RDBMS 2991 provide at least a simple transactional model, commit and rollback 2992 support should be provided. 2993 2994 Currently, only support for MySQL 4.1.x is required but other backends 2995 may be added as options in the future. As a particular example which 2996 has implications for the database interaction model, support for 2997 SQLite may be required in the future. Currently, the choice of 2998 backend database interface may be made as a compile option. Details 2999 of the specified APIs in the discussion below refer to the relevant 3000 MySQL functions. 3001 3002 Database errors must be trapped and placed onto the psError stack. 3003 The complete error message should be retrieved with the database's 3004 error function. 3005 3006 \subsubsection{Managing the Database Connection} 3007 3008 We specify a database handle which carries the information about the 3009 database connection: 3010 3011 \begin{datatype} 3012 typedef struct { 3013 MYSQL *mysql; 3014 } psDB; 3015 \end{datatype} 3016 3017 The following collection of functions provides basic database functionality: 3018 3019 \begin{prototype} 3020 // wraps mysql_init() & mysql_real_connect() 3021 psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname); 3022 3023 // wraps mysql_close() 3024 void psDBCleanup(psDB *dbh); 3025 3026 // wraps mysql_create_db() 3027 bool psDBCreate(psDB *dbh, const char *dbname); 3028 3029 // wraps mysql_select_db() 3030 bool psDBChange(psDB *dbh, const char *dbname); 3031 3032 // wraps mysql_drop_db() 3033 bool psDBDrop(psDB *dbh, const char *dbname); 3034 \end{prototype} 3035 3036 For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and 3037 \code{mysql_real_connect()} in order to initialize a psDB structure and 3038 establish a database connection. A null pointer should be returned on 3039 failure. 3040 3041 When implementing support for SQLite, or other DB which is purely 3042 file-based, the \code{host}, \code{user}, and \code{passwd} arguments 3043 would be ignored while \code{dbname} would specify the path to the 3044 SQLite db file. 3045 3046 \subsubsection{Interacting with Database Tables} 3047 3048 The functions in this section perform high level interactions with the 3049 database tables. All of them should behave ``atomically'' with 3050 respect to the state of the database. Specifically, all interactions 3051 with the database should be done as a part of a transaction that is 3052 rolled-back on failure and committed only after all queries used by 3053 the API have been run. In general, this API set attempts to treat a 3054 database table as a 2D matrix where columns can be represented by a 3055 \code{psVector} and rows as a \code{psMetadata} type. A 3056 \code{psMetadata} collection is also used to define the columns of a 3057 table and as part of the query restrictions. 3058 3059 \begin{prototype} 3060 bool psDBCreateTable(psDB *dbh, const char *tableName, const psMetadata *md); 3061 \end{prototype} 3062 3063 This function generates and executes the SQL needed to create a table 3064 named \code{tableName}, with the column names and datatypes as 3065 described in \code{md}. Each data item in the \code{psMetadata} 3066 collection represents a single table field. The name of the field is 3067 given by the name of the \code{psMetadataItem} and the data type is 3068 given by the \code{psMetadataItem.type} entry. A lookup table should 3069 be used to convert from PSLib types into MySQL compatible SQL data 3070 types. For example, a \code{PS_META_STR} would map to an SQL99 3071 varchar. If the value of \code{type} is \code{PS_META_STR} then the 3072 \code{psMetadataItem.data} element is set to a string with the length 3073 for the field written as a text string. The value of the 3074 \code{psMetadataItem.data} element is unused for the 3075 \code{PS_META_PRIMITIVE} types. Other metadata types beyond 3076 \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed in a 3077 table definition metadata collection. 3078 3079 Database indexes can be specified by setting the \code{comment} field to 3080 ``\code{Primary Key}'' or ``\code{Key}''. ``Auto-incrementing'' columns may be 3081 specified by setting the \code{comment} field to ``\code{AUTO_INCREMENT}''. 3082 Indexes and auto-increments maybe be combined in the same \code{comment}. They 3083 must be separated by optional whitespace, a comma, and then more optional 3084 whitespace. The \code{comment} field is otherwise ignored. 3085 3086 \begin{prototype} 3087 bool psDBDropTable(psDB *dbh, const char *tableName); 3088 \end{prototype} 3089 3090 This function deletes the specified table. 3091 3092 \begin{prototype} 3093 bool p_psDBRunQuery(psDB *dbh, const char *query); 3094 \end{prototype} 3095 3096 This function will execute a string as a raw SQL query. No additional 3097 processing of the string or abstraction of the underlying database's SQL 3098 dialect is provided. 3099 3100 \begin{prototype} 3101 psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, unsigned long limit); 3102 psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType type, unsigned long limit); 3103 \end{prototype} 3104 3105 These functions generates and executes the SQL needed to select an entire 3106 column from a table or up to \code{limit} rows from it. If \code{limit} is 0, 3107 the entire range is returned. The database response is processed and a 3108 \code{psArray} of strings is returned. The Num version of the function returns 3109 the data in a \code{psVector}, data cast to \code{type}. It returns an error 3110 (NULL) if the requested field is not a numerical type. 3111 3112 \begin{prototype} 3113 psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, unsigned long limit); 3114 \end{prototype} 3115 3116 This function returns rows from the specified table which match 3117 the restrictions given by \code{where}. The restrictions are 3118 specified as field / value pairs. The \code{psMetadata} collection 3119 where must consist of valid database fields, though the database query 3120 checking functions may be used to validate the fields as part of the 3121 query. If \code{where} is \code{NULL}, then there are no restrictions 3122 on the rows selected. The selected rows are returned as a 3123 \code{psArray} of \code{psMetadata} values, one per row. 3124 3125 \begin{prototype} 3126 bool psDBInsertOneRow(psDB *dbh, const char *tableName, const psMetadata *row); 3127 \end{prototype} 3128 3129 Insert the data from \code{row} into \code{tableName}. It should be noted in 3130 the API reference that if fields are specified in \code{row} that do not exist 3131 in \code{tablename}, the insert will fail. 3132 3133 \begin{prototype} 3134 bool psDBInsertRows(psDB *dbh, const char *tableName, const psArray *rowSet); 3135 \end{prototype} 3136 3137 Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once 3138 and is atomic for the complete set of rows. 3139 3140 \begin{prototype} 3141 psArray *psDBDumpRows(psDB *dbh, const char *tableName); 3142 \end{prototype} 3143 3144 Fetch all rows as an psArray of psMetadata. 3145 3146 \begin{prototype} 3147 psMetadata *psDBDumpCols(psDB *dbh, const char *tableName); 3148 \end{prototype} 3149 3150 Fetch all columns, as either a psVector or a psArray depending on whether or not 3151 the column is numeric, and return them in a psMetadata structure where 3152 psMetadataItem.name contains the column's name. 3153 3154 \begin{prototype} 3155 psS64 psDBUpdateRows(psDB *dbh, const char *tableName, const psMetadata *where, const psMetadata *values); 3156 \end{prototype} 3157 3158 Update the columns contained in \code{values} in the row(s) that have a field 3159 with the value indicated by \code{where} (note that this is only allows very 3160 limited use of SQL99's ``where'' semantics). The number of rows modified is 3161 returned. A negative value is return to indicate an error. If there are 3162 multiple psMetadataItems in \code{where} then each item should be considered as 3163 an additional constraint. e.g. ``where foo = x and where bar = y'' 3164 3165 \begin{prototype} 3166 psS64 psDBDeleteRows(psDB *dbh, const char *tableName, const psMetadata *where); 3167 \end{prototype} 3168 3169 Delete the rows that are matched by \code{where} using the same semantics for 3170 \code{where} as in psDBUpdateRow(). A negative value is returned to indicate an 3171 error. 3172 3173 \subsection{FITS I/O Functions} 3174 3175 We need a variety of I/O functions between the disk and certain of our 3176 PSLib data structures. We need the ability to access FITS headers, 3177 images and tables (both ASCII and Binary). We define here the FITS 3178 I/O functions, all of which are currently specified as wrappers to 3179 functions within CFITSIO. CFITSIO provides a wide range of utilities 3180 which we do not feel are particularly appropriate as part of a generic 3181 I/O library, such as assumptions about names which change the data 3182 interpretation, etc. We are defining our calls to avoid the hidden 3183 'features'. The CFITSIO functions which are wrapped should in general 3184 be the most basic versions. 3185 3186 \begin{datatype} 3187 typedef struct { 3188 fitsfile fd; 3189 } psFits; 3190 \end{datatype} 3191 We begin by defining a datatype to wrap the CFITSIO \code{fitsfile} 3192 structure. This is necessary to allow repeated access to the data in 3193 a file without multiple open commands (which are expensive). 3194 3195 \subsubsection{FITS File Manipulations} 3196 3197 \begin{prototype} 3198 psFits *psFitsOpen(const char *filename); 3199 \end{prototype} 3200 3201 Opens a FITS file and positions the pointer to the PHU. 3202 3203 \begin{prototype} 3204 bool psFitsClose(psFits *fits); 3205 \end{prototype} 3206 3207 Closes a FITS file. 3208 3209 \begin{prototype} 3210 bool psFitsMoveExtName(const psFits *fits, const char *extname); 3211 \end{prototype} 3212 3213 Positions the pointer to the beginning of the specified 3214 \code{extname}. If the \code{extname} does not exist, the function 3215 shall fail. 3216 3217 \begin{prototype} 3218 bool psFitsMoveExtNum(const psFits* fits, int extnum, bool relative); 3219 \end{prototype} 3220 3221 Moves the pointer to the beginning of the specified HDU number. If 3222 \code{relative} is TRUE, \code{extnum} represents the number of HDUs 3223 relative to the current HDU. The PHU is entry number 0, while the 3224 extended data segments start at number 1. 3225 3226 \begin{prototype} 3227 int psFitsGetExtNum(const psFits* fits); 3228 \end{prototype} 3229 3230 Returns the current HDU number (i.e., file position). 3231 3232 \begin{prototype} 3233 int psFitsGetSize(const psFits* fits); 3234 \end{prototype} 3235 3236 Returns the number of HDUs in the file. 3237 3238 \begin{datatype} 3239 typedef enum { 3240 PS_FITS_TYPE_NONE, 3241 PS_FITS_TYPE_IMAGE, 3242 PS_FITS_TYPE_BINARY_TABLE, 3243 PS_FITS_TYPE_ASCII_TABLE, 3244 PS_FITS_TYPE_ANY 3245 } psFitsType; 3246 \end{datatype} 3247 3248 \begin{prototype} 3249 psFitsType psFitsGetExtType(const psFits* fits); 3250 \end{prototype} 3251 3252 Gets the current HDU's type (table or image). 3253 3254 \begin{prototype} 3255 char *psFitsGetExtName(const psFits* fits); 3256 bool psFitsSetExtName(psFits* fits, const char* name); 3257 \end{prototype} 3258 3259 \code{psFitsGetExtName} shall return the name of the current extension 3260 for the given \code{fits} file (as specified by the \code{EXTNAME} 3261 header). \code{psFitsSetExtName} shall change the name of the current 3262 extension for the given \code{fits} file to \code{name}, returning 3263 \code{true} upon success and \code{false} otherwise. 3264 3265 \subsubsection{FITS Header I/O Functions} 3266 3267 \begin{prototype} 3268 psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits); 3269 \end{prototype} 3270 Read header data into a \code{psMetadata} structure. The data is read 3271 from the current HDU pointed at by the \code{psFits *fits} entry. If 3272 \code{out} is \code{NULL}, a new psMetadata is created. 3273 3274 \begin{prototype} 3275 psMetadata *psFitsReadHeaderSet(const psFits *fits); 3276 \end{prototype} 3277 Load a complete set of headers from the \code{psFits} file pointer. 3278 This function loads the headers from all extensions into a 3279 \code{psMetadata} collection, each entry of which is a pointer to a 3280 \code{psMetadata} structure containing the header data. The metadata 3281 entry names are the \code{EXTNAME} values for each header (with the 3282 value of \code{PHU} for the primary header unit). At the start of the 3283 operation, the file pointer is rewound to the beginning of the file. 3284 At the end, it is positioned where it started when the function was 3285 called. 3286 3287 \begin{prototype} 3288 bool psFitsWriteHeader(const psMetadata *output, psFits *fits); 3289 \end{prototype} 3290 Write metadata into the header of a FITS image file. The header is 3291 written at the current HDU. 3292 3293 \subsubsection{FITS Image I/O Functions} 3294 3295 \begin{prototype} 3296 psImage *psFitsReadImage(psImage *out, const psFits *fits, psRegion region, int z); 3297 \end{prototype} 3298 Read an image or subimage from the \code{psFits} file pointer. This 3299 function is a wrapper to the CFITSIO library function. The input 3300 parameters allow a full image or a subimage to be read. The region to 3301 be read is specified by \code{region}. A negative value for either of 3302 \code{region.x1} or \code{region.y1} specifies the size of the region 3303 to be read counting down from the end of the array. 3304 3305 If the native image is a cube, the value of z specifies the requested 3306 slice of the image. This function must call \code{psError} and return 3307 \code{NULL} if any of the specified parameters are out of range for 3308 the data in the image file, or if the image on disk is zero- or 3309 one-dimensional. This function need only read images of the native 3310 FITS image types (\code{psU8}, \code{psS16}, \code{psS32}, 3311 \code{psF32}, \code{psF64}). The user is expected to convert the data 3312 type as needed with \code{psImageCopy}. 3313 3314 \begin{prototype} 3315 bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z); 3316 \end{prototype} 3317 Write an image section to the open \code{psFits} file pointer. This 3318 operation may write a portion of an image over the existing bytes of 3319 an existing image. Care must be taken to interpret \code{region}, 3320 which specified the output pixels to be written / over-written. If 3321 the combination of \code{region} and the size of \code{psImage *input} 3322 implies writing pixels outside the existing data area of the image, 3323 the function shall return an error (ie, if \code{region.x0 + image.nx 3324 >= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >= 3325 NAXIS3}). This function will only write images of the native FITS 3326 image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, 3327 \code{psF64}). The user is expected to convert the data type as 3328 needed with \code{psImageCopy}. The return value must be 0 for a 3329 successful operation and 1 for an error. 3330 3331 \begin{prototype} 3332 bool psFitsWriteImage(psFits *fits, const psMetadata *header, const psImage *input, int depth); 3333 \end{prototype} 3334 Create a new image based on the dimensions specified for the image and 3335 the requested depth. The header and image data segments are written 3336 in the file at the current position of the \code{psFits} pointer. 3337 This function will only write images of the native FITS image types 3338 (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}). 3339 The user is expected to convert the data type as needed with 3340 \code{psImageCopy}. The return value must be 0 for a successful 3341 operation and 1 for an error. 3342 3343 \subsubsection{FITS Table I/O Functions} 3344 3345 \begin{prototype} 3346 psMetadata *psFitsReadTableRow(const psFits *fits, int row); 3347 \end{prototype} 3348 This function reads a single row of the table in the extension pointed 3349 at by the \code{psFits} file pointer. The row number to be read is 3350 given by \code{row}. The result is returned as a \code{psMetadata} 3351 collection with elements of the appropriate types and keys 3352 corresponding to the table column names. The function must apply the 3353 needed byte-swapping on the data in the row based on the description 3354 of the table data in the table header. \tbr{we may need to be more 3355 flexible here: if we call this function repeatedly, it would be more 3356 efficient to pass the corresponding header or keep it somewhere (and 3357 the file pointer location, for that matter).} 3358 3359 \begin{prototype} 3360 void *psFitsReadTableRowRaw(size_t *size, const psFits *fits, int row); 3361 \end{prototype} 3362 This function reads a single row of the table in the extension pointed 3363 at by the \code{psFits} file pointer. The row number to be read is 3364 given by \code{row}. The result is returned as collection of 3365 \code{size} bytes allocated by the function. The function must 3366 apply the needed byte-swapping on the data in the row based on the 3367 description of the table data in the table header. \tbr{we may need 3368 to be more flexible here: if we call this function repeatedly, it 3369 would be more efficient to pass the corresponding header or keep it 3370 somewhere (and the file pointer location, for that matter).} 3371 3372 \begin{prototype} 3373 psArray *psFitsReadTableColumn(const psFits *fits, const char *colname); 3374 \end{prototype} 3375 This function reads a single column of the table in the extension 3376 pointed at by the \code{psFits} file pointer. The column is specified 3377 by the FITS table column key given by \code{row}. The result is 3378 returned as a \code{psArray}, with the data from one row of the table 3379 column per array element. 3380 3381 \begin{prototype} 3382 psVector *psFitsReadTableColumnNum(const psFits *fits, const char *colname); 3383 \end{prototype} 3384 This function reads a single column of the table in the extension 3385 pointed at by the \code{psFits} file pointer. The column is specified 3386 by the FITS table column key given by \code{row} and must be of a 3387 numeric data type. The result is returned as a \code{psVector} of the 3388 appropriate data type, with the data from one row of the table column 3389 per array element. 3390 3391 \begin{prototype} 3392 psArray *psFitsReadTableRaw(size_t *size, const psFits *fits); 3393 \end{prototype} 3394 This function reads the entire data block from a table into the a 3395 \code{psArray}, with one element of the array per row. The number of 3396 bytes per row is returned in \code{size}. The function must apply 3397 the needed byte-swapping on the data in each row based on the 3398 description of the table data in the table header. 3399 3400 \begin{prototype} 3401 psArray *psFitsReadTable (psFits *fits); 3402 \end{prototype} 3403 This function reads the entire data block from a table into the a 3404 \code{psArray}, with one element of the array per row. Each row is 3405 stored as a \code{psMetadata} collection as described above for 3406 \code{psFitsReadTableRow}. 3407 3408 \begin{prototype} 3409 bool psFitsWriteTable(psFits* fits, const psMetadata *header, const psArray* table); 3410 \end{prototype} 3411 Accepts a \code{psArray} of \code{psMetadata} and writes it to the 3412 current HDU. If the current HDU is not a table type, this will fail 3413 and return FALSE. 3414 3415 \begin{prototype} 3416 bool psFitsUpdateTable(psFits* fits, const psMetadata* data, int row); 3417 \end{prototype} 3418 Writes the \code{psMetadata} data to a FITS table at the specified row 3419 in the current HDU. If the current HDU is not a table type, this will 3420 fail and return FALSE. 3421 3422 \pagebreak 2104 3423 \section{Data manipulation} 2105 3424 … … 2117 3436 \item Minimization and fitting routines. 2118 3437 \end{itemize} 2119 2120 \subsection{BitSets}2121 2122 BitSets are required in order to turn options on and off. We require2123 the capability to have a bitset of arbitrary length (i.e., not limited2124 by the length of a \code{long}, say). The \code{psBitSet} structure2125 is defined below. Note that the entry \code{bits} is an array of type2126 \code{char} storing the bits as bits of each byte in the array, with 82127 bits available for each byte in the array. Also note that the2128 constructor is passed the number of required bits, which implies that2129 \code{ceil(n/8)} bytes must be allocated. The bitset structure is2130 define by:2131 \begin{datatype}2132 typedef struct {2133 long n; ///< Number of chars that form the bitset2134 char *bits; ///< The bits2135 } psBitSet;2136 \end{datatype}2137 2138 We also require the corresponding constructor and destructor:2139 \begin{prototype}2140 psBitSet *psBitSetAlloc(long nalloc);2141 \end{prototype}2142 where \code{n} is the requested number of bits.2143 2144 Several basic operations on bitsets are required:2145 \begin{itemize}2146 \item Set a bit;2147 \item Check if a bit is set; and2148 \item \code{OR}, \code{AND} and \code{XOR} two bitsets.2149 \item \code{NOT} a bitset.2150 \end{itemize}2151 The corresponding APIs are defined below:2152 2153 \begin{prototype}2154 psBitSet *psBitSetSet(psBitSet *bitSet, long bit);2155 psBitSet* psBitSetClear(psBitSet *bitSet, long bit);2156 psBitSet *psBitSetOp(psBitSet *outBitSet, const psBitSet *inBitSet1, const char *operator, const psBitSet *inBitSet2);2157 psBitSet *psBitSetNot(psBitSet *outBitSet, const psBitSet *inBitSet);2158 bool psBitSetTest(const psBitSet *bitSet, long bit);2159 char *psBitSetToString(const psBitSet* bitSet);2160 \end{prototype}2161 2162 \code{psBitSetSet} sets the specified \code{bit} in the2163 \code{psBitSet}, and returns the updated bitset. The input bitset2164 will be modified.2165 2166 \code{psBitSetClear} clears the specified \code{bit} in the \code{bitSet}2167 and returns the updated bitset. The input bitset will be modified.2168 2169 \code{psBitSetOp} returns the \code{psBitSet} that is the result of2170 performing the specified \code{operator} (one of \code{"AND"},2171 \code{"OR"}, or \code{"XOR"}) on \code{inBitSet1} and \code{inBitSet2}.2172 If the output bitset \code{outBitSet} is \code{NULL}, it is created by2173 the function.2174 2175 \code{psBitSetNot} applies a unary \code{NOT} to a bitset, placing the2176 answer in the bitset \code{out}, or creating a new bitset if2177 \code{out} is \code{NULL}.2178 2179 \code{psBitSetTest} returns a true value if the specified \code{bit}2180 is set; otherwise, it returns a false value.2181 2182 Finally, \code{psBitSetToString} returns a string representation of2183 the specified \code{bits}.2184 2185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%2186 3438 2187 3439 \subsection{Sorting} … … 2673 3925 2674 3926 \begin{prototype} 2675 bool psMinimizeLMChi2(psMinimization *min, psImage *covar, psVector *params, 2676 const psVector *paramMask, const psArray *x, const psVector *y, 2677 const psVector *yErr, psMinimizeLMChi2Func func); 3927 bool psMinimizeLMChi2(psMinimization *min, 3928 psImage *covar, 3929 psVector *params, 3930 const psVector *paramMask, 3931 const psArray *x, 3932 const psVector *y, 3933 const psVector *yErr, 3934 psMinimizeLMChi2Func func); 2678 3935 \end{prototype} 2679 3936 … … 2713 3970 be of type \code{psF32}. The \code{func} function must be valid only 2714 3971 for types \code{psF32}, \code{psF64}. 3972 3973 \begin{prototype} 3974 bool psMinimizeGaussNewtonDelta(psVector *delta, 3975 const psVector *params, 3976 const psVector *paramMask, 3977 const psArray *x, 3978 const psVector *y, 3979 const psVector *yErr, 3980 psMinimizeLMChi2Func func); 3981 \end{prototype} 3982 3983 The function \code{psMinimizeGaussNewtonDelta} can be used to evaluate 3984 the goodness of a fit. This function returns the distances of the 3985 current parameter set from the minimization parameters expected from 3986 Gauss-Newton minimization. The arguments are identical to those of 3987 \code{psMinimizeLMChi2}, except only the single vector \code{delta}, 3988 consisting of the distances, is returned. This vector must be 3989 pre-allocated to the dimenstions of \code{params}. 2715 3990 2716 3991 %% \subsubsubsection{Pre-defined Functions for LM} … … 2915 4190 listed below, and fall into several categories. 2916 4191 2917 \subsubsection{Image Regions}2918 2919 In many places, we need to refer to a rectangular area. We define a2920 structure to represent a rectangle:2921 \begin{datatype}2922 typedef struct {2923 float x0;2924 float x1;2925 float y0;2926 float y1;2927 } psRegion;2928 \end{datatype}2929 This structure is used in psLib as an abbreviation for the four2930 floats, and is defined statically. Functions which accept or return a2931 \code{psRegion} shall do so by value, not by pointer.2932 2933 We define two functions to set and return the value of a2934 \code{psRegion}. The first defines the region by the corner2935 coordinates. The second function converts the IRAF description of a2936 region in the form \code{[x0:x1,y0:y1]}, used for header entries such2937 as \code{BIASSEC}, into the corresponding \code{psRegion} structure2938 (any values that do not parse correctly shall be returned as2939 \code{NaN}). We also define a function that converts a2940 \code{psRegion} to the corresponding IRAF description.2941 2942 \begin{prototype}2943 psRegion psRegionSet(float x0, float x1, float y0, float y1);2944 psRegion psRegionFromString(const char *region);2945 char *psRegionToString(const psRegion region);2946 \end{prototype}2947 2948 All functions which use a psRegion must interpret the definition of2949 $(x0,y0)$ and $(x1,y1)$ in the same way. The coordinate $(x0,y0)$2950 defines the starting pixel in the region. The coordinate $(x1,y1)$2951 defines the outer bound of the region. The size of the region is2952 $(x1-x0,y1-y1)$. If either $x1$ or $y1$ is less than or equal to 0,2953 the value is added to the image dimensions ($Nx + x1$). Thus a region2954 \code{[0:0,0:0]} refers to the full image array, while2955 \code{[0:-10,0:-20]} trims the last 10 columns and the last 20 rows.2956 2957 4192 \subsubsection{Image Structure Manipulation} 2958 4193 … … 3202 4437 int inputMaskVal, 3203 4438 const psPlaneTransform *outToIn, 3204 constpsRegion region,4439 psRegion region, 3205 4440 const psPixels *pixels, 3206 4441 psImageInterpolateMode mode, … … 3418 4653 3419 4654 \begin{prototype} 3420 psImage *psPixelsToMask(psImage *out, const psPixels *pixels, constpsRegion region, unsigned int maskVal);4655 psImage *psPixelsToMask(psImage *out, const psPixels *pixels, psRegion region, unsigned int maskVal); 3421 4656 psPixels *psPixelsFromMask(psPixels *out, const psImage *mask, unsigned int maskVal); 3422 4657 \end{prototype} … … 3727 4962 PSF-matching. 3728 4963 4964 \subsubsection{Basic Image Smoothing} 4965 4966 \begin{prototype} 4967 void psImageSmooth (psImage *image, double sigma, double Nsigma); 4968 \end{prototype} 4969 4970 The quickest way to smooth an image is to smooth by parts, using 1D 4971 gaussian smoothing in X and Y independently. \code{psImageSmooth} 4972 applies a single parameter Gaussian (circularly symmetric) by 4973 smoothing first in the X and then in the Y directions with just a 4974 vector. In general, for a Gaussian of dimension N, this process is 2N 4975 faster than for the 2D convolution defined below. The arguments to 4976 this function include the image to be smoothed, the width of the 4977 smoothing kernel in pixels (\code{sigma}), and the size of the 4978 smoothing box in sigmas. 4979 3729 4980 \subsubsection{Kernel definition} 3730 4981 … … 3881 5132 3882 5133 \pagebreak 3883 \section{Rich Data Structures and I/O}3884 3885 \subsection{Metadata}3886 \label{sec:metadata}3887 3888 \subsubsection{Conceptual Overview}3889 3890 Within PSLib, we provide a data structure to carry metadata and3891 mechanisms to manipulate the metadata. Metadata is a general concept3892 that requires some discussion. In any data analysis task, the3893 ensemble of all possible data may be divided into two or three3894 classes: there is the specific data of interest, there is data which3895 is related or critical but not the primary data of interest, and there3896 is all of the other data which may or may not be interesting. For3897 example, consider a simple 2D image obtained of a galaxy from a CCD3898 camera on a telescope. If you want to study the galaxy, the specific3899 data of interest is the collection of pixels. There are a variety of3900 other pieces of data which are closely related and crucial to3901 understanding the data in those pixels, such as the dimensions of the3902 image, the coordinate system, the time of the image, the exposure3903 time, and so forth. Other data may be known which may be less3904 critical to understanding the image, but which may be interesting or3905 desired at a later date. For example, the observer who took the3906 image, the filter manufacturer, the humidity at the telescope, etc.3907 3908 Formally, all of the related data which describe the principal data of3909 interest are metadata. Note that which piece is the metadata and3910 which is the data may depend on the context. If you are examining the3911 pixels in an image, the coordinate and flux of an object may be part3912 of the metadata. However, if you are analyzing a collection of3913 objects extracted from an image, you may consider then pixel data3914 simply part of the metadata associated with the list of objects.3915 3916 There are various ways to handle metadata vs data within a programming3917 environment. In C, it is convenient to use structures to group3918 associated data together. One possibility is to define the metadata3919 as part of the associated data structure. For example, the image data3920 structure would have elements for all possible associated measurement.3921 This approach is both cumbersome (because of the large number metadata3922 types), impractical (because the full range of necessary metadata is3923 difficult to know in advance) and inflexible (because any change in3924 the collection of metadata requires addition of new structure elements3925 and recompilation).3926 3927 An alternative is to place the metadata in a generic container and use3928 lookup mechanisms to extract the appropriate metadata when needed. An3929 example of this is would be a text-based FITS header for an image read3930 into a flat text buffer. In this implementation, metadata lookup3931 functions could return the current value of, for example, NAXIS1 (the3932 number of columns of the image) by scanning through the header buffer.3933 This method has the benefits of flexibility and simplicity of3934 programming interface, but it has the disadvantage that all metadata3935 is accessed though this lookup mechanism. This may make the code less3936 readable and it may slow down the access.3937 3938 PSLib implements an intermediate solution to this problem. We specify3939 a flexible, generic metadata container and access methods. Data types3940 which require association with a general collection of metadata should3941 include an entry of this metadata type. However, a subset of metadata3942 concepts which are basic and frequently required may be placed in the3943 coded structure elements. This approach allows the code to refer to3944 the basic metadata concepts as part of the data structure (ie,3945 \code{image.nx}), but also allows us to provide access to any3946 arbitrary metadata which may be generated. As a practical matter, the3947 choice of which entries are only in the metadata and which are part of3948 the explicit structure elements is rather subjective. Any data3949 elements which are frequently used should be put in the structure;3950 those which are only infrequently needed should be left in the generic3951 metadata.3952 3953 There are some points of caution which must be noted. Any3954 manipulation of the data should be reflected in the metadata where3955 appropriate. This is always an issue of concern. For example,3956 consider an image of dimensions \code{nx, ny}. If a function extracts3957 a subraster, it must change the values of \code{nx, ny} to match the3958 new dimensions. What should it do to the corresponding metadata?3959 Clearly, it should change the corresponding value which defines3960 \code{nX, nY}. However, it is not quite so simple: there may be other3961 metadata values which depend on those values. These must also be3962 changed appropriately. What if the metadata element points to a3963 copy of the metadata which may be shared by other representations of3964 the image? These must be treated differently because the change would3965 invalidate those other references. Care must be taken, therefore,3966 when writing functions which operate on the data to consider all of3967 the relevant metadata entries which must also be updated.3968 3969 A related issue is the definition of metadata names. Entries in a3970 structure have the advantage of being hardwired: every instance of3971 that structure will have the same name for the same entry. This is3972 not necessarily the case with a more flexible metadata container. The3973 image exposure time is a notorious example in astronomy. Different3974 observatories use different header keywords (ie, metadata names) for3975 the same concept of the exposure time (\code{EXPTIME},3976 \code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc). Any system3977 which operates on these metadata needs to address the issue of3978 identifying these names. This issue seems like an argument for3979 hardwiring metadata in the structure, but in fact it does not present3980 such a strong case. If the metadata are hardwired, some function will3981 still have to know how to interpret the various names to populate the3982 structure. The concept can still be localized with generic metadata3983 containers by including abstract metadata names within the code which3984 are tied to the various implementations-specific metadata names.3985 3986 \subsubsection{Metadata Representation}3987 3988 \begin{figure}3989 \psfig{file=Metadata,width=6.5in}3990 \caption{Metadata Structures\label{fig:metadata}}3991 \end{figure}3992 3993 This section addresses the question of how \PS{} metadata should be3994 represented in memory, not how it should be represented on disk.3995 3996 We define an item of metadata with the following structure:3997 \filbreak3998 \begin{datatype}3999 typedef struct {4000 const psS32 id; ///< unique ID for this item4001 char *name; ///< Name of item4002 psMetadataType type; ///< type of this item4003 const union {4004 psS32 S32; ///< integer data4005 psF32 F32; ///< floating-point data4006 psF64 F64; ///< double-precision data4007 psList *list; ///< psList entry4008 psMetadata *md; ///< psMetadata entry4009 psPtr V; ///< other type4010 } data; ///< value of metadata4011 char *comment; ///< optional comment ("", not NULL)4012 } psMetadataItem;4013 \end{datatype}4014 4015 The \code{id} is a unique identifier for this item of metadata;4016 experience shows that such tags are useful. The entry \code{name}4017 specifies the name of the metadata item. The value of the metadata is4018 given by the union \code{data}, and may be of type \code{psS32},4019 \code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at4020 by the \code{void} pointer \code{V}. A character string comment4021 associated with this metadata item may be stored in the element4022 \code{comment}. The \code{type} entry specifies how to interpret the4023 type of the data being represented, given by the enumerated type4024 \code{psMetadataType}:4025 %4026 \filbreak4027 \begin{datatype}4028 typedef enum { ///< type of item.data is:4029 PS_META_S32 = PS_TYPE_S32, ///< psS32 primitive data.4030 PS_META_F32 = PS_TYPE_F32, ///< psF32 primitive data.4031 PS_META_F64 = PS_TYPE_F64, ///< psF64 primitive data.4032 PS_META_BOOL = PS_TYPE_BOOL, ///< psBool primitive data.4033 PS_META_LIST = 0x10000, ///< List data (Stored as item.data.list).4034 PS_META_STR, ///< String data (Stored as item.data.V).4035 PS_META_META, ///< Metadata (Stored as item.data.md).4036 PS_META_VEC, ///< Vector data (Stored as item.data.V).4037 PS_META_IMG, ///< Image data (Stored as item.data.V).4038 PS_META_HASH, ///< Hash data (Stored as item.data.V).4039 PS_META_LOOKUPTABLE, ///< Lookup table data (Stored as item.data.V).4040 PS_META_JPEG, ///< JPEG data (Stored as item.data.V).4041 PS_META_PNG, ///< PNG data (Stored as item.data.V).4042 PS_META_ASTROM, ///< Astrometric coefficients (Stored as item.data.V).4043 PS_META_TIME, ///< psTime object (Stored as item.data.V).4044 PS_META_UNKNOWN, ///< Other data (Stored as item.data.V).4045 PS_META_MULTI ///< Used internally, do not create a metadata item of this type.4046 } psMetadataType;4047 \end{datatype}4048 The macro \code{PS_META_IS_PRIMITIVE(psMetadataType.type)} returns4049 true if the type is one of the primitive data types (S32, F64, etc).4050 In such a case, the data value is directly available. Otherwise, a4051 pointer to the data is available.4052 4053 A collection of metadata is represented by the \code{psMetadata} structure:4054 \begin{datatype}4055 typedef struct {4056 psList *list; ///< list of psMetadataItem4057 psHash *hash; ///< hash table of the same metadata4058 } psMetadata;4059 \end{datatype}4060 The type \code{psMetadata} is a container class for metadata. Note4061 that there are in fact \emph{two} representations of the metadata4062 (each \code{psMetadataItem} appears on both). The first4063 representation employs a doubly-linked list that allows the order of4064 the metadata to be preserved (e.g., if FITS headers are read in a4065 particular order, they should be written in the same order). The4066 second representation employs a hash table which allows fast look-up4067 given a specific metadata keyword.4068 4069 Certain metadata names (such as the FITS keywords \code{COMMENT} and4070 \code{HISTORY} in a FITS header) may be repeated with different4071 values. In such a case, the \code{psMetadata.list} structure contains4072 the entries in their original sequence with duplicate keys. The4073 \code{psMetadata.hash} entries, which are required to have unique4074 keys, would have a single entry with the keyword of the repeated key,4075 with the value of \code{psMetadataType} set to \code{PS_META_MULTI},4076 and the \code{psMetadataItem.data} element pointing to a \code{psList}4077 containing the actual entries. If \code{psMetadataItemAlloc} is4078 called with the type set to \code{PS_META_MULTI}, such a repeated key4079 is created. In this case, the data value passed to4080 \code{psMetadataItemAlloc} (the quantity in ellipsis) must be4081 \code{NULL}. An empty \code{psMetadataItem} with the given keyword is4082 created to hold future entries of that keyword.4083 4084 As a convenience to the user, the following type-specific functions are4085 also defined:4086 \begin{prototype}4087 psMetadataItem* psMetadataItemAllocStr(const char* name, const char* comment, const char* value);4088 psMetadataItem* psMetadataItemAllocF32(const char* name, const char* comment, psF32 value);4089 psMetadataItem* psMetadataItemAllocF64(const char* name, const char* comment, psF64 value);4090 psMetadataItem* psMetadataItemAllocS32(const char* name, const char* comment, psS32 value);4091 psMetadataItem* psMetadataItemAllocBool(const char* name, const char* comment, bool value);4092 psMetadataItem* psMetadataItemAllocPtr(const char* name, psMetadataType type, const char* comment, psPtr value);4093 \end{prototype}4094 4095 \subsubsection{Metadata APIs}4096 4097 \begin{prototype}4098 psMetadata *psMetadataAlloc(void);4099 \end{prototype}4100 4101 The constructor for the collection of metadata, \code{psMetadata},4102 simply returns an empty metadata container (employing the constructors4103 for the doubly-linked list and hash table). The destructor needs to4104 free each of the \code{psMetadataItem}s.4105 4106 \begin{prototype}4107 psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...);4108 psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list);4109 \end{prototype}4110 4111 The allocator for \code{psMetadataItem} returns a full4112 \code{psMetadataItem} ready for insertion into the \code{psMetadata}.4113 The \code{name} entry specifies the name to use for this metadata4114 item, and may include \code{sprintf}-type formating codes. The4115 \code{comment} entry is a fixed string which is used for the comment4116 associated with this metadata item. The metadata data and the4117 arguments to the \code{name} formatting codes are passed, in that4118 order (metadata pointer first), to \code{psMetadataItemAlloc} as4119 arguments following the comment string. The data must be a pointer4120 for any data types which are stored in the element \code{data.void},4121 while other data types are passed as numeric values. The argument4122 list must be interpreted appropriately by the \code{va_list} operators4123 in the function.4124 4125 \begin{prototype}4126 bool psMetadataAddItem(psMetadata *md, const psMetadataItem *item, psS32 location, psS32 flags);4127 bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...);4128 bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment,4129 va_list list);4130 \end{prototype}4131 4132 Items may be added to the metadata in one of two ways --- firstly, an4133 item may be added by appending a \code{psMetadataItem} which has4134 already been created; and secondly by directly providing the data to4135 be appended. In both cases, the return value defines the success4136 (\code{true}) or failure of the operation. The second function,4137 \code{psMetadataAdd} takes a pointer or value which is interpreted by4138 the function using variadic argument interpretation. The third4139 version is the \code{va_list} version of the second function. All4140 three functions take a parameter, \code{location}, which specifies4141 where in the list to place the element, following the conventions for4142 the \code{psList}. The entry \code{mode} for \code{psMetadataAddItem}4143 is a bit mask constructed by OR-ing the allowed option flags (eg,4144 \code{PS_META_REPLACE}) which specify minor variations on the4145 behavior. The \code{format} entry, which specifies both the metadata4146 type and the optional flags, is constructed by bit-wise OR-ing the4147 appropriate \code{psMetadataType} and allowed option flags. Care4148 should be taken not to leak memory when appending an item for which4149 the key already exists in the metadata (and is not4150 \code{PS_META_MULTI}).4151 %4152 4153 \begin{datatype}4154 typedef enum { ///< option flags for psMetadata functions4155 PS_META_DEFAULT = 0, ///< default behavior (0x0000) for use in mode above4156 PS_META_REPLACE = 0x1000000 ///< allow entry to be replaced4157 PS_META_DUPLICATE_OK = 0x2000000 ///< allow duplicate entries4158 PS_META_NULL = 0x4000000 ///< psMetadataItem.data is a NULL value4159 } psMetadataFlags;4160 \end{datatype}4161 4162 The functions above take option flags which modify the behavior when4163 metadata items are added to the metadata list. These flags must be4164 bit-exclusive of those used above for the \code{psMetadataTypes}. The4165 flags have the following meanings:4166 4167 \code{PS_META_DEFAULT}: This is the zero bit mask, to allow the4168 default behavior for \code{psMetadataAddItem} above. If this is OR-ed4169 with a \code{psMetadataType}, the result is as if no OR-ing took4170 place.4171 4172 \code{PS_META_REPLACE}: Replace an existing, unique entry. If the4173 given metadata item exists in the metadata collection, and is not of4174 type \code{PS_META_MULTI}, then the item replaces the existing entry.4175 4176 \code{PS_META_DUPLICATE_OK}: Allow the new metadata item key to be a4177 duplicate (ie, \code{PS_META_MULTI}). If an existing item with the4178 same key is already \code{PS_META_MULTI}, the new item is added to the4179 \code{PS_META_MULTI} list. If the existing item is not4180 \code{PS_META_MULTI}, a \code{PS_META_MULTI} list is created to4181 contain both the existing item and the new item. The original entry's4182 location on the psMetadata.list must be maintained.4183 4184 \code{PS_META_NULL}: Indicates that \code{psMetadataItem.data} should be4185 ignored and that the the current value is ``NULL'' or undefined. The4186 \code{psMetadataItem} must have a proper \code{type} set and it's \code{data}4187 field shall have a valid value. e.g. A \code{type} of \code{PS_META_STR} would4188 require that 's \code{data} is set to \code{NULL}.4189 4190 There are several of cases to handle for duplication of an existing4191 key by a new key, some identified above. The following situations4192 must also be handled:4193 4194 If the new key already exists, but is not \code{PS_META_MULTI}, and4195 the new item is not flagged as either \code{PS_META_DUPLICATE_OK} or4196 \code{PS_META_REPLACE}, an error is raised.4197 4198 If the new key already exists, and the existing item is4199 \code{PS_META_MULTI}, the new item is added to the MULTI list. Note4200 that if the new item is also of type \code{PS_META_MULTI}, no action4201 is taken, but a successful exit status is returned (the action of4202 adding a \code{PS_META_MULTI} item to the metadata is equivalent to4203 setting that key to be tagged as \code{PS_META_MULTI}. If it is4204 {\em already} \code{PS_META_MULTI}, this effect has already been4205 achieved).4206 4207 An example of code to use these metadata APIs to generate the4208 structure seen in Figure~\ref{fig:metadata} is given below.4209 4210 \begin{verbatim}4211 md = psMetadataAlloc();4212 4213 psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE", PS_META_BOOL, "basic fits", TRUE);4214 psMetadataAdd(md, PS_LIST_TAIL, "BLANK", PS_META_S32, "invalid pixel data", -32768);4215 psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR, "observing date UT", " 2004-6-16");4216 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_LIST, "head of comment block", NULL);4217 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "DATA");4218 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "PARAMS");4219 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32, "exposure time (sec)", 1.05);4220 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "FOO");4221 4222 cell = psMetadataAlloc();4223 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD00");4224 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-00");4225 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.00");4226 psMetadataAdd(md, PS_LIST_TAIL, "CELL.00", PS_META_META, "", cell);4227 4228 cell = psMetadataAlloc();4229 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD01");4230 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-01");4231 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.01");4232 psMetadataAdd(md, PS_LIST_TAIL, "CELL.01", PS_META_META, "", cell);4233 \end{verbatim}4234 4235 The following code shows how to use the APIs to replace one of these values:4236 \begin{verbatim}4237 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32 | PS_REPLACE, "new exposure time (sec)", 2.05);4238 \end{verbatim}4239 4240 As a convenience to the user, the following type-specific functions4241 are specified:4242 \begin{prototype}4243 bool psMetadataAddStr(psMetadata* md, psS32 location, const char* name, const char* comment,4244 const char* value);4245 bool psMetadataAddS32(psMetadata* md, psS32 location, const char* name, const char* comment, psS32 value);4246 bool psMetadataAddF32(psMetadata* md, psS32 location, const char* name, const char* comment, psF32 value);4247 bool psMetadataAddF64(psMetadata* md, psS32 location, const char* name, const char* comment, psF64 value);4248 bool psMetadataAddBool(psMetadata* md, psS32 location, const char* name, const char* comment, bool value);4249 bool psMetadataAddPtr(psMetadata* md, psS32 location, const char* name, psMetadataType type,4250 const char* comment, psPtr value);4251 \end{prototype}4252 4253 4254 Items may be removed from the metadata by specifying a key or a4255 location in the list. If the value of \code{name} is \code{NULL}, the4256 value of \code{location} is used. If the value of \code{name} is not4257 \code{NULL}, then \code{location} must be set to4258 \code{PS_LIST_UNKNOWN}. If the key matches a metadata item, the item4259 is removed from the metadata and \code{true} is returned; otherwise,4260 \code{false} is returned. If the key is not unique, then \emph{all}4261 items corresponding to the key are removed, and \code{true} is4262 returned.4263 %4264 \begin{prototype}4265 bool psMetadataRemove(psMetadata *md, int location, const char *key);4266 \end{prototype}4267 4268 Items may be found within the metadata by providing a key. In the4269 event that the key is non-unique, the first item is returned.4270 \begin{prototype}4271 psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key);4272 \end{prototype}4273 4274 Several utility functions are provided for simple cases. These4275 functions perform the effort of casting the data to the appropriate4276 type. The numerical functions shall return 0.0 if their key is not4277 found. If the pointer value of \code{status} is not \code{NULL}, it4278 is set to reflect the success or failure of the lookup.4279 \begin{prototype}4280 psPtr psMetadataLookupStr(bool *status, const psMetadata *md, const char *key);4281 psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key);4282 psF32 psMetadataLookupF32(bool *status, const psMetadata *md, const char *key);4283 psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key);4284 bool psMetadataLookupBool(bool *status, const psMetadata *md, const char *key);4285 psPtr psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key);4286 \end{prototype}4287 4288 Items may be retrieved from the metadata by their entry position. The4289 value of which specifies the desired entry in the fashion of4290 \code{psList}.4291 \begin{prototype}4292 psMetadataItem *psMetadataGet(const psMetadata *md, int location);4293 \end{prototype}4294 4295 The metadata list component may be iterated over by using a4296 \code{psMetadataIterator} in a fashion equivalent to the4297 \code{psListIterator}:4298 \begin{datatype}4299 typedef struct {4300 psListIterator* iter; ///< iterator for the psMetadata's psList4301 regex_t* regex; ///< the subsetting regular expression4302 } psMetadataIterator;4303 \end{datatype}4304 4305 The iterator may be set to a location in the \code{psMetadata} list,4306 and the user may get the previous or next item in the list relative to4307 that location. \code{psMetadataGetNext} has the ability to match the4308 key using a POSIX \code{regex}, e.g., if the user only wants to4309 iterate through \code{IPP.machines.sky} and doesn't want to bother4310 with \code{IPP.machines.detector}. The iterator should iterate over4311 every item in the metadata list, even those that are contained in a4312 \code{PS_META_LIST}. The value \code{iterator} specifies the iterator4313 to be used. In setting the iterator, the position of the iterator is4314 defined by \code{location}, which follows the conventions of the4315 \code{psList} iterators.4316 \begin{prototype}4317 psMetadataIterator *psMetadataIteratorAlloc(psMetadata *md, int location, const char *regex);4318 bool psMetadataIteratorSet(psMetadataIterator *iterator, int location);4319 psMetadataItem *psMetadataGetAndIncrement(psMetadataIterator *iterator);4320 psMetadataItem *psMetadataGetAndDecrement(psMetadataIterator *iterator);4321 \end{prototype}4322 4323 Metadata items may be printed to an open file descriptor based on a4324 provided format. The format string is an sprintf format statement4325 with exactly one \% formatting command. If the metadata item type is4326 a numeric type, this formatting command must also be numeric, and type4327 conversion performed to the value to match the format type. If the4328 metadata item type is a string, the formatting command must also be4329 for a string (\%s type of command). If the metadata type is any other4330 data type, printing is not allowed.4331 \begin{prototype}4332 bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *item);4333 \end{prototype}4334 4335 \subsubsection{Configuration files}4336 \label{sec:configspec}4337 4338 It will be necessary for the \PS{} system, in order to load4339 pre-defined settings, to parse a configuration file into a4340 \code{psMetadata} structure. This shall be performed by the4341 function \code{psMetadataConfigParse}, as described below.4342 4343 \begin{prototype}4344 psMetadata *psMetadataConfigParse(psMetadata *md, int *nFail, const char *filename, bool overwrite);4345 \end{prototype}4346 4347 Given a metadata container, \code{md}, and the name of a configuration4348 file, \code{filename}, \code{psMetadataConfigParse} shall parse the4349 configuration file, placing the contained key/type/value/comment quads4350 into the metadata, and returning a pointer to the metadata structure.4351 The number of lines that failed to parse is returned in \code{nFail}.4352 Multiple specifications of a key that haven't been declared (see4353 below) are overwritten if and only if \code{overwrite} is \code{true}.4354 If the metadata container is \code{NULL}, it shall be allocated.4355 4356 On error, the function shall return \code{NULL}.4357 4358 It is also useful to be able to convert a \code{psMetadata} structure into the4359 Configuration File format for debugging purposes and to enable persistent4360 configuration.4361 4362 \begin{prototype}4363 char *psMetadataConfigFormat(psMetadata *md);4364 bool psMetadataConfigWrite(psMetadata *md, const char *filename);4365 \end{prototype}4366 4367 The \code{psMetadataConfigFormat} function converts a \code{psMetadata}4368 structure (including any nested \code{psMetadata}) into a Configuration File4369 formatted string. A \code{NULL} shall be returned on error. The4370 \code{psMetadataConfigWrite} behaves the same as \code{psMetadataConfigFormat}4371 except that the string is written out to \code{filename}. \code{false} is4372 returned on failure.4373 4374 \paragraph{Comments}4375 4376 The configuration file shall consist of plain text with4377 key/type/value/comment quads on separate lines. Blank lines,4378 including those consisting solely of whitespace (both spaces and4379 tabs), shall be ignored, as shall lines that commence with the comment4380 character (a hash mark, \code{#}), either immediately at the start of4381 the line, or preceded by whitespace. The key/type/value/comment quads4382 shall all lie on a single line, separated by whitespace.4383 4384 The key shall be first, possibly preceded on the line by whitespace4385 which should not form part of the key.4386 4387 \paragraph{NULL values}4388 4389 The ``value'' of a quad may be declare to be undefined with the \code{NULL}4390 keyword. \code{NULL} is allowed to co-exist with a ``comment'' and may be4391 surrounded by whitespace. Any non-whitespace character will cause of the4392 ``value'' to be interpreted as a string.4393 4394 \begin{verbatim}4395 foo STR NULL # string with a NULL value4396 bar STR NULL a # string with a value of "NULL a"4397 \end{verbatim}4398 4399 \paragraph{Types}4400 \subparagraph{Scalar \& Vector}4401 4402 Next, to assist the casting of the value, shall be a string identifying the4403 type of the value, which shall correspond to one of the simple types supported4404 in \code{psMetadata}: \code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to4405 abbreviate \code{STRING}; valid time types are \code{UTC,UT1,TAI,TT}.4406 4407 \tbd{May, in the future, require more types, including U8,S16,C64,4408 which will also necessitate updating the definition of psMetadata.}4409 4410 The value shall follow the type: strings may consist of multiple words, and4411 shall have all leading and trailing whitespace removed; booleans shall simply4412 be either \code{T} or \code{F}. Time type values will be in the ISO86014413 compatible format of "YYYY-MM-DDTHH:MM:SS,sZ". When parsed, time types shall4414 be represented as a \code{psTime} object.4415 4416 Following the value may be an optional comment, preceded by a comment4417 character (a hash mark, \code{#}), which in the case of a string4418 value, serves to mark the end of the value, and for other types serves4419 to identify the comment to the reader. Only one comment character may4420 be present on any single line (i.e., neither strings nor comments are4421 permitted to contain the comment character). The comment may consist4422 of multiple words, and shall have leading and trailing whitespace4423 removed.4424 4425 One wrinkle is the specification of vectors. Keys for which the value4426 is to be parsed as a vector shall be preceded immediately by a4427 ``vector symbol'', which we choose to be the ``at'' sign, \code{@}.4428 In this case, the type shall be interpreted as the type for the4429 vector, which may be any of the signed or unsigned integer or floating4430 point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not4431 the complex floating point types; and the value shall consist of4432 multiple numbers, separated either by a comma or whitespace. These4433 values shall populate a \code{psVector} of the appropriate type in the4434 order in which they appear in the configuration file.4435 4436 \tbd{May add complex types, likely to be specified with values such as4437 1.23+4.56i in the future.}4438 4439 \tbd{May add null, Not-a-Number (NaN), de-normalized, underflow, overflow,4440 and/or +/-infinity values for selected types.}4441 4442 \subparagraph{MULTI}4443 4444 An additional hurdle is the specification of keys that may be non-unique (such4445 as the \code{COMMENT} keyword in a FITS header). These keys shall be specified4446 in the configuration file as non-unique with a \code{MULTI} declaration. In4447 the form \code{[keyword] MULTI}. No other data may be provided on this line,4448 though a comment, preceded by the comment marker, is valid. A warning shall4449 be produced when a key which has not been specified to be non-unique is4450 repeated; in this case, the former value shall be overwritten if4451 \code{overwrite} is \code{true}, otherwise the line shall be ignored and4452 counted as one that could not be parsed. It should be noted that non-unique4453 keys may be of mixed type (even the \code{TYPE} and \code{METADATA} complex4454 types). For example:4455 \begin{verbatim}4456 comment MULTI # a comment4457 comment STR some string4458 comment F32 1.234564459 comment BOOL T4460 \end{verbatim}4461 4462 If a line does not conform to the rules laid out here, a warning shall4463 be generated, it shall be ignored and counted as a line that could not4464 be parsed. The total number of lines that were not able to be parsed4465 (including those that were ignored because \code{overwrite} is4466 \code{false}, and any other parsing problems, but not including blank4467 lines and comment lines) shall be returned by the function in the4468 argument \code{nFail}.4469 4470 Here are some examples of lines of a valid configuration file:4471 \filbreak4472 \begin{verbatim}4473 Double F64 1.23456789 # This is a comment4474 Float F32 0.98765 # This is a comment too4475 String STR This is the string that forms the value #comment4476 4477 # This is a comment line and is to be ignored4478 boolean BOOL T # The value of `boolean' is `true'4479 4480 @primes U8 2,3 5 7,11,13 17 # These are prime numbers4481 4482 comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique4483 comment STR This4484 comment STR is4485 comment STR a4486 comment STR non-unique4487 comment STR key4488 Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored4489 \end{verbatim}4490 4491 Of course, a real configuration file should look much nicer to humans4492 than the above example, but PSLib must be able to parse such ugly4493 files.4494 4495 \paragraph{Complex Types}4496 \subparagraph{TYPE}4497 4498 We support a modest tree structure by defining a reserved keyword \code{TYPE}.4499 Any line in the config file which starts with the word \code{TYPE} shall be4500 interpreted as defining a new valid type. The defined type name follows the4501 word \code{TYPE}, and is in turn followed by an arbitrary number of words.4502 These words are to be interpreted as the names of an embedded \code{psMetadata}4503 entry, where the values are given on any line which (following the \code{TYPE}4504 definition) employs the new type name. For example, a new type may be defined4505 as:4506 \begin{verbatim}4507 TYPE CELL EXTNAME BIASSEC CHIP4508 CELL.00 CELL CCD00 BSEC-00 CHIP.004509 CELL.01 CELL CCD01 BSEC-01 CHIP.004510 \end{verbatim}4511 4512 When \code{psMetadataConfigParse} encounters the \code{TYPE} line, it4513 should construct a \code{psMetadata} container and fill it with4514 \code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP},4515 with type \code{PS_META_STR}, but data allocated. When it next4516 encounters an entry of type \code{CELL}, it should then use the given4517 name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy4518 the \code{psMetadata} data onto the \code{psMetadataItem.data.md}4519 entry, filling in the values from the rest of the line (\code{CCD00,4520 BSEC-00, CHIP.00}). This hierarchical structure is illustrated in4521 Figure~\ref{fig:metadata}.4522 4523 \subparagraph{METADATA}4524 4525 Another way to form a tree-like structure is to directly define a4526 \code{psMetadata} entry using a sequence of successive lines to define the4527 values of the \code{psMetadataItem} entries. The initial line defines the new4528 \code{psMetadata} entry and its name. The following lines have the same format4529 as the other metadata config file entries. The sequence is terminated with a4530 line with a single word \code{END}. For example, a metadata entry may be4531 defined as:4532 \begin{verbatim}4533 CELL METADATA4534 EXTNAME STR CCD004535 BIASSEC STR BSEC-004536 CHIP STR CHIP.004537 NCELL S32 244538 END4539 \end{verbatim}4540 4541 \paragraph{Scoping Rules}4542 4543 A simple set of ``Scoping Rules'' are required to properly parse a4544 configuration file. ``Scope'' refers to the current ``level'' of4545 \code{METADATA} that a statement appears in. Statements that are not contained4546 in a nested \code{METADATA} are said to be in the ``Top level scope''. Each4547 level of nested \code{METADATA} statements create a new ``lower level scope''.4548 4549 \begin{itemize}4550 \item4551 Variable names are unique only to the current level of scope.4552 4553 \item4554 non-unique keywords (\code{MULTI}) apply only to the current scope. i.e. They4555 are invalid in ``higher'' or ``lower'' level scopes.4556 4557 \item4558 \code{TYPE} declarations apply only to the current scope.4559 4560 \item4561 \code{METADATA} declarations must begin and end in the same scope. i.e. They4562 may not be declared and end in two different nested METADATA and the same4563 depth.4564 \end{itemize}4565 4566 A series of test inputs is contained in4567 \S\ref{sec:configtest}.4568 4569 \subsection{XML Functions}4570 4571 Within Pan-STARRS, we will use XML documents as a transport mechanism4572 to carry data between programs and between IPP and other subsystems.4573 Configuration information may be stored as well as XML documents, in4574 addition to the text format discussed in the discussion on Metadata.4575 XML is an extremely variable document format, and it is not currently4576 the intention of PSLib to provide a complete PSLib version of XML4577 operations. Rather, a limited number of operations are defined to4578 convert specific data structures to an appropriate XML document. To4579 maximize the simplicity of the XML APIs, we will use the convention4580 that a single XML document to be parsed by PSLib shall contain only a4581 single data structure. Each of the XML APIs therefore take as input a4582 reference to a complete XML document and return a PSLib data4583 structure, or take a PSLib data structure and return a complete XML4584 document.4585 4586 We start by defining a PSLib wrapper type which is a pointer to an XML4587 document in memory. We wrap the \code{libxml2} version of an XML4588 document pointer for now:4589 \begin{datatype}4590 typedef xmlDocPtr psXMLDoc;4591 \end{datatype}4592 4593 \begin{prototype}4594 psXMLDoc *psXMLDocAlloc(void);4595 \end{prototype}4596 4597 The next pair of functions convert a \code{psMetadata} data structure4598 to a complete \code{psXMLDoc} (in memory) and vice versa:4599 \begin{prototype}4600 psXMLDoc *psMetadataToXMLDoc(const psMetadata *md);4601 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc);4602 \end{prototype}4603 4604 The next pair of functions loads the data in a named file into a4605 complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc}4606 to a named file:4607 \begin{prototype}4608 psXMLDoc *psXMLParseFile(const char *filename);4609 int psXMLDocToFile(const psXMLDoc *doc, const char *filename);4610 \end{prototype}4611 4612 The next pair of functions accepts a block of memory and parses it4613 into a complete \code{psXMLDoc} (also in memory), and vice versa:4614 \begin{prototype}4615 psXMLDoc *psXMLParseMem(const char *buffer, int size);4616 int psXMLDocToMem(const psXMLDoc *doc, char *buffer);4617 \end{prototype}4618 4619 The next pair of functions read from and write to a file descriptor.4620 The first converts the incoming data to a complete \code{psXMLDoc}4621 (also in memory), the second writes the \code{psXMLDoc} to the file4622 descriptor:4623 \begin{prototype}4624 psXMLDoc *psXMLParseFD(int fd);4625 int psXMLDocToFD(const psXMLDoc *doc, int fd);4626 \end{prototype}4627 4628 \subsection{Database Functions}4629 4630 Many of the applications that PSLib will be used for will require4631 access to a simple relational database. PSLib includes generic4632 database-independent interface mechanisms as part of its API set. The4633 most important aspect of PSLib's database support is to abstract as4634 much database specific complexity as is feasible. As almost all RDBMS4635 provide at least a simple transactional model, commit and rollback4636 support should be provided.4637 4638 Currently, only support for MySQL 4.1.x is required but other backends4639 may be added as options in the future. As a particular example which4640 has implications for the database interaction model, support for4641 SQLite may be required in the future. Currently, the choice of4642 backend database interface may be made as a compile option. Details4643 of the specified APIs in the discussion below refer to the relevant4644 MySQL functions.4645 4646 Database errors must be trapped and placed onto the psError stack.4647 The complete error message should be retrieved with the database's4648 error function.4649 4650 \subsubsection{Managing the Database Connection}4651 4652 We specify a database handle which carries the information about the4653 database connection:4654 4655 \begin{datatype}4656 typedef struct {4657 MYSQL *mysql;4658 } psDB;4659 \end{datatype}4660 4661 The following collection of functions provides basic database functionality:4662 4663 \begin{prototype}4664 // wraps mysql_init() & mysql_real_connect()4665 psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname);4666 4667 // wraps mysql_close()4668 void psDBCleanup(psDB *dbh);4669 4670 // wraps mysql_create_db()4671 bool psDBCreate(psDB *dbh, const char *dbname);4672 4673 // wraps mysql_select_db()4674 bool psDBChange(psDB *dbh, const char *dbname);4675 4676 // wraps mysql_drop_db()4677 bool psDBDrop(psDB *dbh, const char *dbname);4678 \end{prototype}4679 4680 For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and4681 \code{mysql_real_connect()} in order to initialize a psDB structure and4682 establish a database connection. A null pointer should be returned on4683 failure.4684 4685 When implementing support for SQLite, or other DB which is purely4686 file-based, the \code{host}, \code{user}, and \code{passwd} arguments4687 would be ignored while \code{dbname} would specify the path to the4688 SQLite db file.4689 4690 \subsubsection{Interacting with Database Tables}4691 4692 The functions in this section perform high level interactions with the4693 database tables. All of them should behave ``atomically'' with4694 respect to the state of the database. Specifically, all interactions4695 with the database should be done as a part of a transaction that is4696 rolled-back on failure and committed only after all queries used by4697 the API have been run. In general, this API set attempts to treat a4698 database table as a 2D matrix where columns can be represented by a4699 \code{psVector} and rows as a \code{psMetadata} type. A4700 \code{psMetadata} collection is also used to define the columns of a4701 table and as part of the query restrictions.4702 4703 \begin{prototype}4704 bool psDBCreateTable(psDB *dbh, const char *tableName, const psMetadata *md);4705 \end{prototype}4706 4707 This function generates and executes the SQL needed to create a table4708 named \code{tableName}, with the column names and datatypes as4709 described in \code{md}. Each data item in the \code{psMetadata}4710 collection represents a single table field. The name of the field is4711 given by the name of the \code{psMetadataItem} and the data type is4712 given by the \code{psMetadataItem.type} entry. A lookup table should4713 be used to convert from PSLib types into MySQL compatible SQL data4714 types. For example, a \code{PS_META_STR} would map to an SQL994715 varchar. If the value of \code{type} is \code{PS_META_STR} then the4716 \code{psMetadataItem.data} element is set to a string with the length4717 for the field written as a text string. The value of the4718 \code{psMetadataItem.data} element is unused for the4719 \code{PS_META_PRIMITIVE} types. Other metadata types beyond4720 \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed in a4721 table definition metadata collection.4722 4723 Database indexes can be specified by setting the \code{comment} field to4724 ``\code{Primary Key}'' or ``\code{Key}''. ``Auto-incrementing'' columns may be4725 specified by setting the \code{comment} field to ``\code{AUTO_INCREMENT}''.4726 Indexes and auto-increments maybe be combined in the same \code{comment}. They4727 must be separated by optional whitespace, a comma, and then more optional4728 whitespace. The \code{comment} field is otherwise ignored.4729 4730 \begin{prototype}4731 bool psDBDropTable(psDB *dbh, const char *tableName);4732 \end{prototype}4733 4734 This function deletes the specified table.4735 4736 \begin{prototype}4737 bool p_psDBRunQuery(psDB *dbh, const char *query);4738 \end{prototype}4739 4740 This function will execute a string as a raw SQL query. No additional4741 processing of the string or abstraction of the underlying database's SQL4742 dialect is provided.4743 4744 \begin{prototype}4745 psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, unsigned long limit);4746 psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType type, unsigned long limit);4747 \end{prototype}4748 4749 These functions generates and executes the SQL needed to select an entire4750 column from a table or up to \code{limit} rows from it. If \code{limit} is 0,4751 the entire range is returned. The database response is processed and a4752 \code{psArray} of strings is returned. The Num version of the function returns4753 the data in a \code{psVector}, data cast to \code{type}. It returns an error4754 (NULL) if the requested field is not a numerical type.4755 4756 \begin{prototype}4757 psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, unsigned long limit);4758 \end{prototype}4759 4760 This function returns rows from the specified table which match4761 the restrictions given by \code{where}. The restrictions are4762 specified as field / value pairs. The \code{psMetadata} collection4763 where must consist of valid database fields, though the database query4764 checking functions may be used to validate the fields as part of the4765 query. If \code{where} is \code{NULL}, then there are no restrictions4766 on the rows selected. The selected rows are returned as a4767 \code{psArray} of \code{psMetadata} values, one per row.4768 4769 \begin{prototype}4770 bool psDBInsertOneRow(psDB *dbh, const char *tableName, const psMetadata *row);4771 \end{prototype}4772 4773 Insert the data from \code{row} into \code{tableName}. It should be noted in4774 the API reference that if fields are specified in \code{row} that do not exist4775 in \code{tablename}, the insert will fail.4776 4777 \begin{prototype}4778 bool psDBInsertRows(psDB *dbh, const char *tableName, const psArray *rowSet);4779 \end{prototype}4780 4781 Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once4782 and is atomic for the complete set of rows.4783 4784 \begin{prototype}4785 psArray *psDBDumpRows(psDB *dbh, const char *tableName);4786 \end{prototype}4787 4788 Fetch all rows as an psArray of psMetadata.4789 4790 \begin{prototype}4791 psMetadata *psDBDumpCols(psDB *dbh, const char *tableName);4792 \end{prototype}4793 4794 Fetch all columns, as either a psVector or a psArray depending on whether or not4795 the column is numeric, and return them in a psMetadata structure where4796 psMetadataItem.name contains the column's name.4797 4798 \begin{prototype}4799 psS64 psDBUpdateRows(psDB *dbh, const char *tableName, const psMetadata *where, const psMetadata *values);4800 \end{prototype}4801 4802 Update the columns contained in \code{values} in the row(s) that have a field4803 with the value indicated by \code{where} (note that this is only allows very4804 limited use of SQL99's ``where'' semantics). The number of rows modified is4805 returned. A negative value is return to indicate an error. If there are4806 multiple psMetadataItems in \code{where} then each item should be considered as4807 an additional constraint. e.g. ``where foo = x and where bar = y''4808 4809 \begin{prototype}4810 psS64 psDBDeleteRows(psDB *dbh, const char *tableName, const psMetadata *where);4811 \end{prototype}4812 4813 Delete the rows that are matched by \code{where} using the same semantics for4814 \code{where} as in psDBUpdateRow(). A negative value is returned to indicate an4815 error.4816 4817 \subsection{FITS I/O Functions}4818 4819 We need a variety of I/O functions between the disk and certain of our4820 PSLib data structures. We need the ability to access FITS headers,4821 images and tables (both ASCII and Binary). We define here the FITS4822 I/O functions, all of which are currently specified as wrappers to4823 functions within CFITSIO. CFITSIO provides a wide range of utilities4824 which we do not feel are particularly appropriate as part of a generic4825 I/O library, such as assumptions about names which change the data4826 interpretation, etc. We are defining our calls to avoid the hidden4827 'features'. The CFITSIO functions which are wrapped should in general4828 be the most basic versions.4829 4830 \begin{datatype}4831 typedef struct {4832 fitsfile fd;4833 } psFits;4834 \end{datatype}4835 We begin by defining a datatype to wrap the CFITSIO \code{fitsfile}4836 structure. This is necessary to allow repeated access to the data in4837 a file without multiple open commands (which are expensive).4838 4839 \subsubsection{FITS File Manipulations}4840 4841 \begin{prototype}4842 psFits *psFitsOpen(const char *filename);4843 \end{prototype}4844 4845 Opens a FITS file and positions the pointer to the PHU.4846 4847 \begin{prototype}4848 bool psFitsClose(psFits *fits);4849 \end{prototype}4850 4851 Closes a FITS file.4852 4853 \begin{prototype}4854 bool psFitsMoveExtName(const psFits *fits, const char *extname);4855 \end{prototype}4856 4857 Positions the pointer to the beginning of the specified4858 \code{extname}. If the \code{extname} does not exist, the function4859 shall fail.4860 4861 \begin{prototype}4862 bool psFitsMoveExtNum(const psFits* fits, int extnum, bool relative);4863 \end{prototype}4864 4865 Moves the pointer to the beginning of the specified HDU number. If4866 \code{relative} is TRUE, \code{extnum} represents the number of HDUs4867 relative to the current HDU. The PHU is entry number 0, while the4868 extended data segments start at number 1.4869 4870 \begin{prototype}4871 int psFitsGetExtNum(const psFits* fits);4872 \end{prototype}4873 4874 Returns the current HDU number (i.e., file position).4875 4876 \begin{prototype}4877 int psFitsGetSize(const psFits* fits);4878 \end{prototype}4879 4880 Returns the number of HDUs in the file.4881 4882 \begin{datatype}4883 typedef enum {4884 PS_FITS_TYPE_NONE,4885 PS_FITS_TYPE_IMAGE,4886 PS_FITS_TYPE_BINARY_TABLE,4887 PS_FITS_TYPE_ASCII_TABLE,4888 PS_FITS_TYPE_ANY4889 } psFitsType;4890 \end{datatype}4891 4892 \begin{prototype}4893 psFitsType psFitsGetExtType(const psFits* fits);4894 \end{prototype}4895 4896 Gets the current HDU's type (table or image).4897 4898 \begin{prototype}4899 char *psFitsGetExtName(const psFits* fits);4900 bool psFitsSetExtName(psFits* fits, const char* name);4901 \end{prototype}4902 4903 \code{psFitsGetExtName} shall return the name of the current extension4904 for the given \code{fits} file (as specified by the \code{EXTNAME}4905 header). \code{psFitsSetExtName} shall change the name of the current4906 extension for the given \code{fits} file to \code{name}, returning4907 \code{true} upon success and \code{false} otherwise.4908 4909 \subsubsection{FITS Header I/O Functions}4910 4911 \begin{prototype}4912 psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits);4913 \end{prototype}4914 Read header data into a \code{psMetadata} structure. The data is read4915 from the current HDU pointed at by the \code{psFits *fits} entry. If4916 \code{out} is \code{NULL}, a new psMetadata is created.4917 4918 \begin{prototype}4919 psMetadata *psFitsReadHeaderSet(const psFits *fits);4920 \end{prototype}4921 Load a complete set of headers from the \code{psFits} file pointer.4922 This function loads the headers from all extensions into a4923 \code{psMetadata} collection, each entry of which is a pointer to a4924 \code{psMetadata} structure containing the header data. The metadata4925 entry names are the \code{EXTNAME} values for each header (with the4926 value of \code{PHU} for the primary header unit). At the start of the4927 operation, the file pointer is rewound to the beginning of the file.4928 At the end, it is positioned where it started when the function was4929 called.4930 4931 \begin{prototype}4932 bool psFitsWriteHeader(const psMetadata *output, psFits *fits);4933 \end{prototype}4934 Write metadata into the header of a FITS image file. The header is4935 written at the current HDU.4936 4937 \subsubsection{FITS Image I/O Functions}4938 4939 \begin{prototype}4940 psImage *psFitsReadImage(psImage *out, const psFits *fits, const psRegion region, int z);4941 \end{prototype}4942 Read an image or subimage from the \code{psFits} file pointer. This4943 function is a wrapper to the CFITSIO library function. The input4944 parameters allow a full image or a subimage to be read. The region to4945 be read is specified by \code{region}. A negative value for either of4946 \code{region.x1} or \code{region.y1} specifies the size of the region4947 to be read counting down from the end of the array.4948 4949 If the native image is a cube, the value of z specifies the requested4950 slice of the image. This function must call \code{psError} and return4951 \code{NULL} if any of the specified parameters are out of range for4952 the data in the image file, or if the image on disk is zero- or4953 one-dimensional. This function need only read images of the native4954 FITS image types (\code{psU8}, \code{psS16}, \code{psS32},4955 \code{psF32}, \code{psF64}). The user is expected to convert the data4956 type as needed with \code{psImageCopy}.4957 4958 \begin{prototype}4959 bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z);4960 \end{prototype}4961 Write an image section to the open \code{psFits} file pointer. This4962 operation may write a portion of an image over the existing bytes of4963 an existing image. Care must be taken to interpret \code{region},4964 which specified the output pixels to be written / over-written. If4965 the combination of \code{region} and the size of \code{psImage *input}4966 implies writing pixels outside the existing data area of the image,4967 the function shall return an error (ie, if \code{region.x0 + image.nx4968 >= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >=4969 NAXIS3}). This function will only write images of the native FITS4970 image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32},4971 \code{psF64}). The user is expected to convert the data type as4972 needed with \code{psImageCopy}. The return value must be 0 for a4973 successful operation and 1 for an error.4974 4975 \begin{prototype}4976 bool psFitsWriteImage(psFits *fits, const psMetadata *header, const psImage *input, int depth);4977 \end{prototype}4978 Create a new image based on the dimensions specified for the image and4979 the requested depth. The header and image data segments are written4980 in the file at the current position of the \code{psFits} pointer.4981 This function will only write images of the native FITS image types4982 (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}).4983 The user is expected to convert the data type as needed with4984 \code{psImageCopy}. The return value must be 0 for a successful4985 operation and 1 for an error.4986 4987 \subsubsection{FITS Table I/O Functions}4988 4989 \begin{prototype}4990 psMetadata *psFitsReadTableRow(const psFits *fits, int row);4991 \end{prototype}4992 This function reads a single row of the table in the extension pointed4993 at by the \code{psFits} file pointer. The row number to be read is4994 given by \code{row}. The result is returned as a \code{psMetadata}4995 collection with elements of the appropriate types and keys4996 corresponding to the table column names. The function must apply the4997 needed byte-swapping on the data in the row based on the description4998 of the table data in the table header. \tbr{we may need to be more4999 flexible here: if we call this function repeatedly, it would be more5000 efficient to pass the corresponding header or keep it somewhere (and5001 the file pointer location, for that matter).}5002 5003 \begin{prototype}5004 void *psFitsReadTableRowRaw(size_t *size, const psFits *fits, int row);5005 \end{prototype}5006 This function reads a single row of the table in the extension pointed5007 at by the \code{psFits} file pointer. The row number to be read is5008 given by \code{row}. The result is returned as collection of5009 \code{size} bytes allocated by the function. The function must5010 apply the needed byte-swapping on the data in the row based on the5011 description of the table data in the table header. \tbr{we may need5012 to be more flexible here: if we call this function repeatedly, it5013 would be more efficient to pass the corresponding header or keep it5014 somewhere (and the file pointer location, for that matter).}5015 5016 \begin{prototype}5017 psArray *psFitsReadTableColumn(const psFits *fits, const char *colname);5018 \end{prototype}5019 This function reads a single column of the table in the extension5020 pointed at by the \code{psFits} file pointer. The column is specified5021 by the FITS table column key given by \code{row}. The result is5022 returned as a \code{psArray}, with the data from one row of the table5023 column per array element.5024 5025 \begin{prototype}5026 psVector *psFitsReadTableColumnNum(const psFits *fits, const char *colname);5027 \end{prototype}5028 This function reads a single column of the table in the extension5029 pointed at by the \code{psFits} file pointer. The column is specified5030 by the FITS table column key given by \code{row} and must be of a5031 numeric data type. The result is returned as a \code{psVector} of the5032 appropriate data type, with the data from one row of the table column5033 per array element.5034 5035 \begin{prototype}5036 psArray *psFitsReadTableRaw(size_t *size, const psFits *fits);5037 \end{prototype}5038 This function reads the entire data block from a table into the a5039 \code{psArray}, with one element of the array per row. The number of5040 bytes per row is returned in \code{size}. The function must apply5041 the needed byte-swapping on the data in each row based on the5042 description of the table data in the table header.5043 5044 \begin{prototype}5045 psArray *psFitsReadTable (psFits *fits);5046 \end{prototype}5047 This function reads the entire data block from a table into the a5048 \code{psArray}, with one element of the array per row. Each row is5049 stored as a \code{psMetadata} collection as described above for5050 \code{psFitsReadTableRow}.5051 5052 \begin{prototype}5053 bool psFitsWriteTable(psFits* fits, const psMetadata *header, const psArray* table);5054 \end{prototype}5055 Accepts a \code{psArray} of \code{psMetadata} and writes it to the5056 current HDU. If the current HDU is not a table type, this will fail5057 and return FALSE.5058 5059 \begin{prototype}5060 bool psFitsUpdateTable(psFits* fits, const psMetadata* data, int row);5061 \end{prototype}5062 Writes the \code{psMetadata} data to a FITS table at the specified row5063 in the current HDU. If the current HDU is not a table type, this will5064 fail and return FALSE.5065 5066 \pagebreak5067 5134 \section{Astronomy-Specific Functions} 5068 5135
Note:
See TracChangeset
for help on using the changeset viewer.
