Changeset 3564
- Timestamp:
- Mar 30, 2005, 11:14:48 AM (21 years ago)
- Location:
- trunk/doc/pslib
- Files:
-
- 3 added
- 5 edited
-
ChangeLogADD.tex (modified) (5 diffs)
-
ChangeLogSDRS.tex (modified) (4 diffs)
-
psLibADD.tex (modified) (63 diffs)
-
psLibSDRS.tex (modified) (24 diffs)
-
psLibSDRS_Astrom.tex (modified) (4 diffs)
-
rotations.ps (added)
-
rotations.sxd (added)
-
transforms.ps (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/pslib/ChangeLogADD.tex
r3438 r3564 1 1 2 \subsection{Changes from version 06 to version 07}2 \subsection{Changes from version 06 (7 September 2004) to version 07 (24 November 2004)} 3 3 4 4 \begin{itemize} … … 12 12 \end{itemize} 13 13 14 \subsection{Changes from version 07 to version 08}14 \subsection{Changes from version 07 (24 November 2004) to version 08 (8 January 2005)} 15 15 16 16 \begin{itemize} … … 20 20 \end{itemize} 21 21 22 \subsection{Changes from version 08 to version 09}22 \subsection{Changes from version 08 (8 January 2005) to version 09 (14 February 2005)} 23 23 24 24 \begin{itemize} … … 27 27 \code{PS_RESAMPLE_LAGRANGE}. 28 28 \item Added section on FITS WCS. 29 \end{itemize} 30 31 \subsection{Changes from version 09 (14 February 2005) to version 10 (29 March 2005} 32 33 \begin{itemize} 29 34 \item Changes to the Time section: 30 35 \begin{itemize} … … 36 41 \item Verbatim Fortran code for UT1 interpolation 37 42 \end{itemize} 43 44 \item section reorganization: 45 \begin{itemize} 46 \item renamed Astronomical Image Manipulations to Image Manipulations 47 \item moved Image Manipulations to own subsection before Astronomy Utilities 48 \item promoted all PSLib subsections to sections 38 49 \end{itemize} 50 51 \end{itemize} -
trunk/doc/pslib/ChangeLogSDRS.tex
r3537 r3564 1 %%% $Id: ChangeLogSDRS.tex,v 1.7 7 2005-03-29 03:42:16 price Exp $1 %%% $Id: ChangeLogSDRS.tex,v 1.78 2005-03-30 21:14:48 eugene Exp $ 2 2 3 3 \subsection{Changes from version 00 to version 01} … … 464 464 \end{itemize} 465 465 466 \subsection{Changes from Revision 12 (9 February 2005) to Revision 13 ( Present)}466 \subsection{Changes from Revision 12 (9 February 2005) to Revision 13 (30 March 2005)} 467 467 468 468 \begin{itemize} … … 481 481 from a file. 482 482 \item \code{psMetadataAddV} changed to use \code{va_list} parameter (bug 312). 483 \item Added \code{psPixels} structure, \code{psPixelsToMask}, 484 \code{psMaskToPixels}, \code{psPixelsConcatenate} and 485 \code{psPixelsTransform}. 483 486 484 \item Modified \code{psImageTransform} in preparation for image combination. 485 486 \item Added \code{psPixels} structure and related functions 487 487 \item Added \code{psPlaneTransformDeriv}. 488 488 \item Added \code{psImageGrowMask}. 489 \item Added Earth Orientation Calculations Section 490 489 491 \item Changes to the Time section: 490 492 \begin{itemize} … … 508 510 \item Adding logical operations (and, or) to \code{psBinaryOp}. 509 511 \end{itemize} 512 513 \item Substantial reorganization: 514 \begin{itemize} 515 \item Moved Metadata, Database, and XML sections to new section 516 \item Re-named Detector \& Sky Coordinates to Linear \& Spherical Coordinates 517 \item Moved Exposure and Observatory information out of 'Astronomical Images' 518 \item Moved Celestial Coordinate Systems out of 'Detector \& Sky Coordinates' 519 \item Added Atmospheric Effects section, incorporating psGrommit and airmass functions from other sections) 520 \item Moved Fixed Pattern out of Astronomical Images 521 \end{itemize} 522 \end{itemize} -
trunk/doc/pslib/psLibADD.tex
r3448 r3564 1 %%% $Id: psLibADD.tex,v 1. 69 2005-03-18 20:40:14 jhoblittExp $1 %%% $Id: psLibADD.tex,v 1.70 2005-03-30 21:14:48 eugene Exp $ 2 2 \documentclass[panstarrs]{panstarrs} 3 3 … … 14 14 \project{Pan-STARRS Image Processing Pipeline} 15 15 \organization{Institute for Astronomy} 16 \version{ 09}16 \version{10} 17 17 \docnumber{PSDC-430-006} 18 19 \setcounter{tocdepth}{5} % lowest level to be included in toc 18 20 19 21 \newcommand\citealt{} … … 31 33 01 & 2004 May 21 & Added section on 2D Chebyshev fitting, then removed. \\ \hline 32 34 02 & 2004 Jun 22 & modified stats specification \\ \hline 33 03--05 & ??? & ??? \\ \hline 34 06 & 2004 Sep 7 & Frozen for PSLib-2 \\ \hline 35 03 & 2004 Jul 13 & \\ \hline 36 04 & 2004 Aug 16 & \\ \hline 37 05 & 2004 Sep 01 & \\ \hline 38 06 & 2004 Sep 07 & Frozen for PSLib-2 \\ \hline 35 39 07 & 2004 Nov 24 & Frozen for Cycle 4 \\ \hline 36 40 08 & 2005 Jan 21 & Draft for Cycle 5 \\ \hline 37 41 09 & 2005 Feb 14 & Frozen for Cycle 5 \\ \hline 42 10 & 2005 Mar 21 & Draft for Cycle 6 \\ \hline 38 43 \RevisionsEnd 39 44 … … 69 74 \pagenumbering{arabic} 70 75 71 \section{Pan-STARRS Library PSLib}72 73 \s ubsection{Math Utilities}74 75 \subs ubsection{Sorting}76 % \section{Pan-STARRS Library PSLib} 77 78 \section{PSLib Math Utilities} 79 80 \subsection{Sorting} 76 81 77 82 A variety of sorting algorithms exist, with a wide range in speed for … … 103 108 \code{in.arr[out->arr[0]]} to \code{in.arr[out->arr[in.n - 1]]}. 104 109 105 \subs ubsection{Smoothing: Boxcar and Gaussian}110 \subsection{Smoothing: Boxcar and Gaussian} 106 111 \label{smooth} 107 112 … … 135 140 \end{equation} 136 141 137 \subs ubsection{Statistics}142 \subsection{Statistics} 138 143 139 144 The general statistics function \code{psStats} performs a variety of … … 148 153 sample and robust estimators. 149 154 150 \ paragraph{Sample Statistics}155 \subsubsection{Sample Statistics} 151 156 152 157 We define the following statistical terms, assuming there is a set of 153 158 data elements $x_i$ with (standard) errors $\sigma_i$. 154 159 155 \ subparagraph{Mean}160 \paragraph{Mean} 156 161 157 162 The simple mean is defined as: … … 160 165 \end{equation} 161 166 162 \ subparagraph{Weighted Mean}167 \paragraph{Weighted Mean} 163 168 164 169 The weighted mean is defined as: … … 170 175 standard definition of the mean. 171 176 172 \ subparagraph{Median}177 \paragraph{Median} 173 178 174 179 The median is defined as the value for which 50\% of the data values … … 181 186 calculating the sample median. 182 187 183 \ subparagraph{Upper and Lower Quartiles}188 \paragraph{Upper and Lower Quartiles} 184 189 185 190 The upper and lower quartiles ($U_{\frac{1}{4}}$ and … … 196 201 the sample quartiles. 197 202 198 \ subparagraph{Standard Deviation}203 \paragraph{Standard Deviation} 199 204 200 205 The standard deviation of the sample is given by: … … 218 223 219 224 220 \ paragraph{Clipped Statistics}225 \subsubsection{Clipped Statistics} 221 226 222 227 The clipped statistics are used to determine the mean and standard … … 255 260 \bar{x}| > k \sigma_i$. 256 261 257 \ paragraph{Robust Statistics}262 \subsubsection{Robust Statistics} 258 263 259 264 The robust version of the statistics provides estimators of basic … … 312 317 quartiles are estimated in the same manner as above. 313 318 314 \ paragraph{Histograms}319 \subsubsection{Histograms} 315 320 316 321 When calculating histograms in the presence of known errors in the … … 342 347 Note that the total adds to one --- the number of values added. 343 348 344 \subs ubsection{Matrix Operations}349 \subsection{Matrix Operations} 345 350 346 351 In this section, we define the linear algebra operations performed on … … 361 366 \code{gsl_linalg_LU_decomp}. 362 367 363 \ paragraph{LU Decomposition}368 \subsubsection{LU Decomposition} 364 369 \label{LUdecomp} 365 370 … … 402 407 \end{equation} 403 408 404 \ paragraph{Calculate a matrix determinant}409 \subsubsection{Calculate a matrix determinant} 405 410 406 411 The determinant $D$ of a matrix $a_{ij}$ is calculated from the … … 418 423 shall be used. 419 424 420 \ paragraph{Solving a Linear Equation}425 \subsubsection{Solving a Linear Equation} 421 426 422 427 The LU decomposition of a matrix may be used to solve the … … 438 443 \end{eqnarray} 439 444 440 \ paragraph{Invert a matrix}445 \subsubsection{Invert a matrix} 441 446 442 447 Inversion of a matrix using the LU decomposition is performed by … … 447 452 operation shall be implemented using the GSL function \code{gsl_linalg_LU_invert}. 448 453 449 \ paragraph{Perform matrix addition, subtraction and multiplication}454 \subsubsection{Perform matrix addition, subtraction and multiplication} 450 455 451 456 Matrix binary arithmetic operations differ from image binary … … 471 476 \times$. 472 477 473 \ paragraph{Transpose a matrix}478 \subsubsection{Transpose a matrix} 474 479 475 480 The transpose of a matrix is simply the reorganization of the matrix … … 484 489 where $M_{ij}$ is the matrix to be transposed. 485 490 486 \ paragraph{Convert a matrix to a vector}491 \subsubsection{Convert a matrix to a vector} 487 492 488 493 Matrix-to-vector conversion is only defined for a matrix that has a … … 493 498 matrix is converted to a \code{PS_DIMEN_TRANV}-type vector. 494 499 495 \subs ubsection{Fitting}496 497 \ paragraph{Chi-squared}500 \subsection{Fitting} 501 502 \subsubsection{Chi-squared} 498 503 \label{chisq} 499 504 … … 506 511 \end{equation} 507 512 508 \ paragraph{General Polynomial Fitting}513 \subsubsection{General Polynomial Fitting} 509 514 510 515 Given a set of data values $y_i$ with errors $\sigma_i$, related to … … 531 536 (section~\ref{LUdecomp}). 532 537 533 \subs ubsection{Non-linear Minimization}534 535 \ paragraph{Levenberg-Marquardt Method}538 \subsection{Non-linear Minimization} 539 540 \subsubsection{Levenberg-Marquardt Method} 536 541 537 542 In the Levenberg-Marquardt Method (LMM; see NR \S 15.5), we make a … … 612 617 613 618 614 \ paragraph{Powell's method}619 \subsubsection{Powell's method} 615 620 616 621 Powell's method is a type of ``Direction Set'' methods in … … 621 626 manner until the advances along the vectors are smaller than some 622 627 pre-defined tolerance. Such direction set methods, including Powell's 623 Quadratically Convergent method are discussed in NR \S10.5.628 Quadratically Convergent method are discussed in NR \S 10.5. 624 629 625 630 We will use for our algorithm the modified version of Powell's … … 665 670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 666 671 667 \subs ubsection{Polynomials}672 \subsection{Polynomials} 668 673 \label{sec:polynomials} 669 674 … … 703 708 $-1 < x < 1$. 704 709 705 \ paragraph{Multi-dimensional polynomials}710 \subsubsection{Multi-dimensional polynomials} 706 711 707 712 Multi-dimensional polynomials shall be composed of multiplications of … … 711 716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 712 717 713 \subs ubsection{(Fast) Fourier Transforms}718 \subsection{(Fast) Fourier Transforms} 714 719 715 720 (Fast) Fourier Transforms (FFTs) shall be implemented using the … … 717 722 library}. 718 723 719 \ paragraph{FFTW Plans}724 \subsubsection{FFTW Plans} 720 725 721 726 FFTW requires the user to create a ``plan'' for each transform size, … … 733 738 initialisation of the PSLib FFT functions and saved at the conclusion. 734 739 735 \ paragraph{Function mapping}740 \subsubsection{Function mapping} 736 741 737 742 The forward and reverse transforms call the corresponding … … 750 755 place to avoid the need to pad the input array to hold the output. 751 756 752 \ paragraph{More Complicated Functions}757 \subsubsection{More Complicated Functions} 753 758 754 759 \code{psFFTCrossCorrelate()} and \code{psFFTConvolve()} both involve … … 772 777 caller, and choose to normalise by $1/N^2$. 773 778 779 \subsection{Image Manipulations} 780 781 \subsubsection{Interpolation} 782 783 Interpolation is needed in various image manipulation operations, 784 including rotation and resampling. We have specified a function to 785 perform the interpolation using one of several possible interpolation 786 methods, defined below. It is important in the discussions that 787 follow to remember that a pixel with column,row if $i,j$ has 788 coordinate at the center of $i+0.5,j+0.5$ and corners with coordinates 789 from $i,j$ to $i+1,j+1$. Thus, the interpolation of a coordinate 790 $x,y$ = 5.0,4.0 is a value midway between the four pixels with 791 column,row of (5,4), (5,5), (6,4), (6,5). 792 793 \paragraph{Nearest Pixel Interpolation ({\tt PS\_INTERPOLATE\_FLAT})} 794 795 In this interpolation, the value of the closest pixel is returned. 796 This is equivalent to pixel duplication or replication. 797 798 \paragraph{Bilinear Interpolation ({\tt PS\_INTERPOLATE\_BILINEAR})} 799 800 In this interpolation, the value at the coordinate is calculated using 801 linear interpolation in two dimensions from the four nearest neighbor 802 pixels. The bilinear interpolation value at a coordinate $x,y$ 803 depends on the four nearest neighbor pixels and the fractional 804 distance $fx,fy$ of the given coordinates from the centers of those 805 four pixels. Consider four neighboring pixels at column,row of $i,j$, 806 $i+1,j$, $i,j+1$, and $i+1,j+1$ with pixel values $V_{0,0}$, 807 $V_{1,0}$, $V_{0,1}$, $V_{1,1}$. The value at $x,y$ is given by: 808 \[ V = (V_{0,0}(1 - f_x) + V_{1,0}f_x)(1 - f_y) + (V_{0,1}(1-f_x) + V_{1,1}f_x)f_y \] 809 This expression is more efficiently evaluated by factoring and 810 calculating the expresion as: 811 \[ r_x = V_{0,0} + (V_{1,0} - V_{0,0})f_x \] 812 \[ V = r_x + (V_{0,1} + (V_{1,1} - V_{0,1})f_x - r_x)f_y \] 813 814 Note that the values of $f_x$ and $f_y$ require some care. Given a 815 coordinate $x,y$, the value of $f_x$ is calculated as $f_x - 0.5 - 816 int(f_x - 0.5)$. For example, when interpolating the value at 817 (5.8.5.2), the relevant neighbor pixels are (5,4), (6,4), (5,5), (6,5) 818 and the fractional coordinate values $f_x, f_y = 0.3, 0.7$. The 819 resulting coordinate would be contained within the pixel at column,row 820 (5,5). 821 822 \paragraph{Sinc Interpolation ({\tt PS\_INTERPOLATE\_LANCZOS[234]})} 823 824 Because it would be slow to specify the size of the kernel 825 dynamically, we specify three hard-coded kernel sizes: 4, 6 and 8 826 pixels in each dimension (a kernel of size 2 pixels in each dimension 827 is handled by the bilinear interpolation). These correspond to the 828 options \code{PS_INTERPOLATE_LANCZOS2}, \code{PS_INTERPOLATE_LANCZOS3} and 829 \code{PS_INTERPOLATE_LANCZOS4}, respectively. 830 831 Given a position on the input image, $(x_0,y_0)$, a kernel is derived 832 according to pixels local to the position: 833 \begin{equation} 834 h(x,y) = {\rm sinc}(\pi \delta x) {\rm sinc}(\pi \delta x / N) \rm{sinc}(\pi \delta y) \rm{sinc}(\pi \delta y / N) 835 \end{equation} 836 where 837 \begin{eqnarray} 838 \delta x & = & x - x_0 \\ 839 \delta y & = & y - y_0 \\ 840 {\rm sinc}(z) & = & \sin(z)/z 841 \end{eqnarray} 842 and $N$ corresponds to the choice of kernel size. For $N = 2$, the 843 kernel size is 4 pixels in each dimension (i.e., $-2 < \delta x \le 844 2$). For $N = 3$, the kernel size is 6 pixels in each dimension 845 (i.e., $-3 < \delta x \le 3$). For $N = 4$, the kernel size is 8 846 pixels in each dimension (i.e., $-4 < \delta x \le 4$). 847 848 The interpolated value at the given position, $(x_0,y_0)$, is then 849 simply the dot product of the kernel and the fluxes: 850 \begin{equation} 851 f(x_0,y_0) = \sum_R f(x,y) h(x,y) 852 \end{equation} 853 where $R$ is the region defined by the kernel size, and $f(x,y)$ is 854 the flux at the pixel position. 855 856 For further information, see the 857 \href{http://terapix.iap.fr/IMG/pdf/swarp.pdf}{SWarp manual}. 858 859 \subsubsection{Image Cuts and Slices} 860 861 Several functions specify operations which manipulate a collection of 862 pixels to return a statistic on the pixel collection. In the simplest 863 case, these are trivial to define: if the boundaries of the region of 864 interest are specified along integral pixel coordinates, then the 865 pixels used to measure the statistic are always an exact integer. 866 This is the case for the function \code{psImageSlice} which requires a 867 starting coordinate which is an integer and a width in both dimensions 868 which is an integer. For the case of the functions \code{psImageCut} 869 and \code{psImageRadialCut}, the situation is a bit more subtle. In 870 both of these cases, the region is unlikely to contain only whole 871 pixels and some choices must be made. 872 873 One posibility which we reject is to identify the fractional pixels 874 which are overlapped by the region of interest and add that fraction 875 of the pixel's flux when calculating the statistic of interest. This 876 is computationally intensive, and not necessarily well defined for all 877 statistics. 878 879 In PSLib, we instead identify the pixels overlapped by the region, use 880 the complete set of pixel values, treating all pixels equally, and 881 renormalize as needed. To perform this, the region of interest is 882 laid on top of the image pixels. Any pixels which overlap the region 883 are identified as part of the input sample. The statistic (ie, sample 884 mean, robust mode, etc), is then calculated on this collection of 885 pixels. If the output statistic is an average value, the measured 886 value is reported. If the output statistic is a sum value (sum of 887 counts, sum of pixels), then the value is renormalized by the ratio of 888 pixels used in the calculation to the pixel area of the region of 889 interest. For example, if the sum within a radial aperture is 890 requested, the circle of the specified radius and center is placed on 891 the pixel grid. Any pixels which touch the circle are then placed in 892 a list to be analysed. The statistic of interest is the measured for 893 this collection of pixels. In the case of a circular aperture which 894 is centered at the coordinate (2,2) and has a radius of 2, the number 895 of pixels which are touched by the circle is 16, while the total pixel 896 area of the circle is 12.57 square pixels. In this case, the pixel 897 sum is renormalized by the ratio (12.57/16.00). 898 899 \paragraph{Radial Cuts} 900 901 Consider an image with pixels $x_i,y_i$ and a reference coordinate 902 $x_c, y_c$. We want to construct a radial cut by measuring statistics 903 for pixels in a sequence of radial annulii $r_s < r < r_e$. For each 904 annulus, we need to select the pixels which fall within this annulus. 905 The coordinates of the center of pixel $i,j$ are $i+0.5,j+0.5$. A 906 given pixel has a distance from the reference coordinate of $dX = x_c 907 - i - 0.5, dY = y_c - j - 0.5$. The pixels to be used for a given 908 radial annulus are all of those pixels for which $r_s < \sqrt{dX^2 + 909 dY^2} < r_e$. This is more efficiently calculated by comparing the 910 square of the radii and distances. All pixels which satisfy the above 911 condition are included in a specific annular radius. All average 912 quantities are calculated directly from the pixel ensemble 913 statistics. 914 915 \paragraph{Arbitrary Linear Cuts} 916 917 Select the pixels which lie along a line following steps of 1 pixel 918 length: 919 920 \begin{verbatim} 921 922 dX = xe - xs; 923 dY = ye - ys; 924 L = hypot (dX, dY); 925 dX = dX / L; 926 dY = dY / L; 927 928 REALLOCATE (xvec[0].elements, float, MAX (L, 1)); 929 REALLOCATE (yvec[0].elements, float, MAX (L, 1)); 930 xvec[0].Nelements = L; 931 yvec[0].Nelements = L; 932 933 V = (float *)buf[0].matrix.buffer; 934 for (i = 0; i < L; i++) { 935 xi = xs + i*dX - 0.5; 936 yi = ys + i*dY - 0.5; 937 xvec[0].elements[i] = i; 938 yvec[0].elements[i] = V[xi + Nx*yi]; 939 } 940 \end{verbatim} 941 942 \subsubsection{Image Rotation} 943 944 Image rotation can be performed in two possible ways under different 945 circumstances, identified in the following discussion. 946 947 In the simplest case, the rotation angle is an integer multiple of 90 948 degrees ($\pi/2$ rad). In these cases, the input and output pixels 949 have a one-to-one mapping. If the input image has dimensions of $N_x, 950 N_y$, then the output image will have dimensions of either $N_x, N_y$ 951 (for even multiples of 90 degrees) or $N_y, N_x$ (for odd multiples). 952 953 If the angle of the rotation is not a multiple of 90, then the output 954 pixels necessarily result from the interpolation of several input 955 pixels. In this case, for an input image of dimensions $N_x, N_y$ and 956 rotation angle $\theta$, the output image has dimensions $Lx = |N_x 957 \cos \theta| + |N_y \sin \theta|$ and $Ly = |N_x \sin \theta| + |N_y 958 \cos \theta|$, each dimension rounded up to the nearest integer as 959 needed. Every pixel in the output image is in general derived from an 960 interpolation over 4 neighboring pixels. The coordinate of a pixel in 961 the output image ($i,j$) corresponds to a fractional pixel coordinate 962 ($x,y$) in the input image according to: 963 \[ x = (i - i_o)*\cos\theta + (j - j_o)*\sin\theta \] 964 \[ y = (i_o - i)*\sin\theta + (j - j_o)*\cos\theta \] 965 where the offset coordinate ($i_o,j_o$) depends on the sign of the 966 sine of the angle $\theta$. If the sign of that sine is positive, the 967 offset coordinate is ($N_y\sin\theta$,0), otherwise it is 968 (0,$-N_x\sin\theta$). 969 774 970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 775 971 776 \subsection{Astronomy Utilities} 972 \pagebreak 973 \section{PSLib Astronomy Utilities} 777 974 778 975 Most of the astronomy utilities will be implemented through wrapping … … 782 979 the next release} 783 980 784 \subs ubsection{Time}981 \subsection{Time} 785 982 786 983 Correct time representation is \emph{critical} in astronomical software. PSLib … … 799 996 ``1970-01-01T00:00:00Z'' UTC. 800 997 801 \ paragraph{Coordinated Universal Time (UTC)}998 \subsubsection{Coordinated Universal Time (UTC)} 802 999 803 1000 Coordinated Univeral Time (UTC) is defined by the International … … 829 1026 timezone is forbidden.} 830 1027 831 \ paragraph{International Atomic Time (TAI)}1028 \subsubsection{International Atomic Time (TAI)} 832 1029 833 1030 International Atomic Time or Temps Atomique International (TAI) is a system of … … 845 1042 seconds since the UNIX epoch of ``1970-01-01T00:00:00Z''. 846 1043 847 \ paragraph{Leap-seconds}1044 \subsubsection{Leap-seconds} 848 1045 849 1046 Leap seconds keep UTC within 0.9s of UT1. The offset between TAI and … … 883 1080 This data is available from: \code{ftp://maia.usno.navy.mil/ser7/tai-utc.dat} 884 1081 885 \ paragraph{Gregorian dates to seconds}1082 \subsubsection{Gregorian dates to seconds} 886 1083 887 1084 The Perl code below, based on an algorithm described in the book ``Calendrical … … 1003 1200 \end{verbatim} 1004 1201 Outputs year, month, day as \code{$y, $m, $d}. 1202 %$ 1005 1203 1006 1204 \emph{The above code was taken [and slightly altered] from … … 1011 1209 1012 1210 1013 \ paragraph{Universal Time (UT1)}1211 \subsubsection{Universal Time (UT1)} 1014 1212 \label{sec:ut1} 1015 1213 … … 1054 1252 IERS publications references above, and should be interpolated in the same way. 1055 1253 1056 \ paragraph{Julian Date and Modified Julian Date}1254 \subsubsection{Julian Date and Modified Julian Date} 1057 1255 1058 1256 The follow definitions of Julian Date (JD) and Modified Julian Date (MJD) was … … 1062 1260 http://www.iers.org/iers/earth/resolutions/UAI\_b1.html}. 1063 1261 1064 \ subparagraph{Julian Date}1262 \paragraph{Julian Date} 1065 1263 1066 1264 \begin{verbatim} … … 1089 1287 \end{verbatim} 1090 1288 1091 \ subparagraph{Modified Julian Date}1289 \paragraph{Modified Julian Date} 1092 1290 1093 1291 \begin{verbatim} … … 1097 1295 \end{verbatim} 1098 1296 1099 \ subparagraph{JD and MJD conversion}1297 \paragraph{JD and MJD conversion} 1100 1298 1101 1299 Conversion between \code{psTime} values and MJD and JD are determined … … 1115 1313 \end{equation} 1116 1314 1117 \ paragraph{Terrestrial Time (TT)}1315 \subsubsection{Terrestrial Time (TT)} 1118 1316 1119 1317 Terrestrial Time (TT) is defined as a fixed offset from TAI. … … 1123 1321 \end{equation} 1124 1322 1125 \ paragraph{TT as Julian Centuries since J2000.0}1323 \subsubsection{TT as Julian Centuries since J2000.0} 1126 1324 1127 1325 The algorithm for calulating GMST requires TT formated in Julian centruies … … 1131 1329 \end{equation} 1132 1330 1133 \ paragraph{UT1 as Julian Centuries since J2000.0}1331 \subsubsection{UT1 as Julian Centuries since J2000.0} 1134 1332 1135 1333 The algorithm for calulating GMST requires UT1 be formated in Julian centuries … … 1140 1338 \end{equation} 1141 1339 1142 \paragraph{Greenwich Mean Sidereal Time (GMST)} 1340 \subsubsection{Local Mean Sidereal Time (LMST)} 1341 1342 Local Mean Sidereal Time (LMST) is Greenwich Mean Sideral Time (GMST) plus the 1343 observer's location in East longitude. Calculating LMST requires the input of 1344 Universal Time (UT1), Terrestrial Dynamical Time (TT) and a longitude (measured 1345 East of Greenwich). 1346 1347 \begin{equation} 1348 LMST = GMST00(t_u, t) + longitude 1349 \end{equation} 1350 1351 Gives $LMST$ in seconds. 1352 1353 \subsubsection{Greenwich Mean Sidereal Time (GMST)} 1143 1354 1144 1355 Greenwich Mean Sidereal Time (GMST) is caclulated from UT1 and TT. This … … 1159 1370 Gives $GMST00$ in seconds. 1160 1371 1161 1162 \paragraph{Longitude} 1372 \subsubsection{Longitude} 1163 1373 1164 1374 Longitudes are often expressed in the form of decimal degrees while the … … 1169 1379 \end{equation} 1170 1380 1171 \paragraph{Local Mean Sidereal Time (LMST)} 1172 1173 Local Mean Sidereal Time (LMST) is Greenwich Mean Sideral Time (GMST) plus the 1174 observer's location in East longitude. Calculating LMST requires the input of 1175 Universal Time (UT1), Terrestrial Dynamical Time (TT) and a longitude (measured 1176 East of Greenwich). 1177 1178 \begin{equation} 1179 LMST = GMST00(t_u, t) + longitude 1180 \end{equation} 1181 1182 Gives $LMST$ in seconds. 1183 1184 \paragraph{Polar Motion} 1381 \subsubsection{Polar Motion} 1382 \tbd{move this to Earth Motion section} 1185 1383 1186 1384 The polar coordinates, $x_p$ and $y_p$, required for the transformation from … … 1190 1388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1191 1389 1192 \subsubsection{Astronomical Image Manipulations} 1193 1194 \paragraph{Interpolation} 1195 1196 Interpolation is needed in various image manipulation operations, 1197 including rotation and resampling. We have specified a function to 1198 perform the interpolation using one of several possible interpolation 1199 methods, defined below. It is important in the discussions that 1200 follow to remember that a pixel with column,row if $i,j$ has 1201 coordinate at the center of $i+0.5,j+0.5$ and corners with coordinates 1202 from $i,j$ to $i+1,j+1$. Thus, the interpolation of a coordinate 1203 $x,y$ = 5.0,4.0 is a value midway between the four pixels with 1204 column,row of (5,4), (5,5), (6,4), (6,5). 1205 1206 \subparagraph{Nearest Pixel Interpolation ({\tt PS\_INTERPOLATE\_FLAT})} 1207 1208 In this interpolation, the value of the closest pixel is returned. 1209 This is equivalent to pixel duplication or replication. 1210 1211 \subparagraph{Bilinear Interpolation ({\tt PS\_INTERPOLATE\_BILINEAR})} 1212 1213 In this interpolation, the value at the coordinate is calculated using 1214 linear interpolation in two dimensions from the four nearest neighbor 1215 pixels. The bilinear interpolation value at a coordinate $x,y$ 1216 depends on the four nearest neighbor pixels and the fractional 1217 distance $fx,fy$ of the given coordinates from the centers of those 1218 four pixels. Consider four neighboring pixels at column,row of $i,j$, 1219 $i+1,j$, $i,j+1$, and $i+1,j+1$ with pixel values $V_{0,0}$, 1220 $V_{1,0}$, $V_{0,1}$, $V_{1,1}$. The value at $x,y$ is given by: 1221 \[ V = (V_{0,0}(1 - f_x) + V_{1,0}f_x)(1 - f_y) + (V_{0,1}(1-f_x) + V_{1,1}f_x)f_y \] 1222 This expression is more efficiently evaluated by factoring and 1223 calculating the expresion as: 1224 \[ r_x = V_{0,0} + (V_{1,0} - V_{0,0})f_x \] 1225 \[ V = r_x + (V_{0,1} + (V_{1,1} - V_{0,1})f_x - r_x)f_y \] 1226 1227 Note that the values of $f_x$ and $f_y$ require some care. Given a 1228 coordinate $x,y$, the value of $f_x$ is calculated as $f_x - 0.5 - 1229 int(f_x - 0.5)$. For example, when interpolating the value at 1230 (5.8.5.2), the relevant neighbor pixels are (5,4), (6,4), (5,5), (6,5) 1231 and the fractional coordinate values $f_x, f_y = 0.3, 0.7$. The 1232 resulting coordinate would be contained within the pixel at column,row 1233 (5,5). 1234 1235 \subparagraph{Sinc Interpolation ({\tt PS\_INTERPOLATE\_LANCZOS[234]})} 1236 1237 Because it would be slow to specify the size of the kernel 1238 dynamically, we specify three hard-coded kernel sizes: 4, 6 and 8 1239 pixels in each dimension (a kernel of size 2 pixels in each dimension 1240 is handled by the bilinear interpolation). These correspond to the 1241 options \code{PS_INTERPOLATE_LANCZOS2}, \code{PS_INTERPOLATE_LANCZOS3} and 1242 \code{PS_INTERPOLATE_LANCZOS4}, respectively. 1243 1244 Given a position on the input image, $(x_0,y_0)$, a kernel is derived 1245 according to pixels local to the position: 1246 \begin{equation} 1247 h(x,y) = {\rm sinc}(\pi \delta x) {\rm sinc}(\pi \delta x / N) \rm{sinc}(\pi \delta y) \rm{sinc}(\pi \delta y / N) 1248 \end{equation} 1249 where 1250 \begin{eqnarray} 1251 \delta x & = & x - x_0 \\ 1252 \delta y & = & y - y_0 \\ 1253 {\rm sinc}(z) & = & \sin(z)/z 1254 \end{eqnarray} 1255 and $N$ corresponds to the choice of kernel size. For $N = 2$, the 1256 kernel size is 4 pixels in each dimension (i.e., $-2 < \delta x \le 1257 2$). For $N = 3$, the kernel size is 6 pixels in each dimension 1258 (i.e., $-3 < \delta x \le 3$). For $N = 4$, the kernel size is 8 1259 pixels in each dimension (i.e., $-4 < \delta x \le 4$). 1260 1261 The interpolated value at the given position, $(x_0,y_0)$, is then 1262 simply the dot product of the kernel and the fluxes: 1263 \begin{equation} 1264 f(x_0,y_0) = \sum_R f(x,y) h(x,y) 1265 \end{equation} 1266 where $R$ is the region defined by the kernel size, and $f(x,y)$ is 1267 the flux at the pixel position. 1268 1269 For further information, see the 1270 \href{http://terapix.iap.fr/IMG/pdf/swarp.pdf}{SWarp manual}. 1271 1272 \paragraph{Image Cuts and Slices} 1273 1274 Several functions specify operations which manipulate a collection of 1275 pixels to return a statistic on the pixel collection. In the simplest 1276 case, these are trivial to define: if the boundaries of the region of 1277 interest are specified along integral pixel coordinates, then the 1278 pixels used to measure the statistic are always an exact integer. 1279 This is the case for the function \code{psImageSlice} which requires a 1280 starting coordinate which is an integer and a width in both dimensions 1281 which is an integer. For the case of the functions \code{psImageCut} 1282 and \code{psImageRadialCut}, the situation is a bit more subtle. In 1283 both of these cases, the region is unlikely to contain only whole 1284 pixels and some choices must be made. 1285 1286 One posibility which we reject is to identify the fractional pixels 1287 which are overlapped by the region of interest and add that fraction 1288 of the pixel's flux when calculating the statistic of interest. This 1289 is computationally intensive, and not necessarily well defined for all 1290 statistics. 1291 1292 In PSLib, we instead identify the pixels overlapped by the region, use 1293 the complete set of pixel values, treating all pixels equally, and 1294 renormalize as needed. To perform this, the region of interest is 1295 laid on top of the image pixels. Any pixels which overlap the region 1296 are identified as part of the input sample. The statistic (ie, sample 1297 mean, robust mode, etc), is then calculated on this collection of 1298 pixels. If the output statistic is an average value, the measured 1299 value is reported. If the output statistic is a sum value (sum of 1300 counts, sum of pixels), then the value is renormalized by the ratio of 1301 pixels used in the calculation to the pixel area of the region of 1302 interest. For example, if the sum within a radial aperture is 1303 requested, the circle of the specified radius and center is placed on 1304 the pixel grid. Any pixels which touch the circle are then placed in 1305 a list to be analysed. The statistic of interest is the measured for 1306 this collection of pixels. In the case of a circular aperture which 1307 is centered at the coordinate (2,2) and has a radius of 2, the number 1308 of pixels which are touched by the circle is 16, while the total pixel 1309 area of the circle is 12.57 square pixels. In this case, the pixel 1310 sum is renormalized by the ratio (12.57/16.00). 1311 1312 \subparagraph{Radial Cuts} 1313 1314 Consider an image with pixels $x_i,y_i$ and a reference coordinate 1315 $x_c, y_c$. We want to construct a radial cut by measuring statistics 1316 for pixels in a sequence of radial annulii $r_s < r < r_e$. For each 1317 annulus, we need to select the pixels which fall within this annulus. 1318 The coordinates of the center of pixel $i,j$ are $i+0.5,j+0.5$. A 1319 given pixel has a distance from the reference coordinate of $dX = x_c 1320 - i - 0.5, dY = y_c - j - 0.5$. The pixels to be used for a given 1321 radial annulus are all of those pixels for which $r_s < \sqrt{dX^2 + 1322 dY^2} < r_e$. This is more efficiently calculated by comparing the 1323 square of the radii and distances. All pixels which satisfy the above 1324 condition are included in a specific annular radius. All average 1325 quantities are calculated directly from the pixel ensemble 1326 statistics. 1327 1328 \subparagraph{Arbitrary Linear Cuts} 1329 1330 Select the pixels which lie along a line following steps of 1 pixel 1331 length: 1390 \subsection{2D transformations} 1391 1392 In PSLib, we implement 2-dimensional transformations using 1393 \code{psPlaneTransform}, which contains a matrix of polynomial 1394 coefficients for each dimension. Since we are using these to model 1395 the real world, where, for example, a particular point on the detector 1396 maps to a particular point on the sky, we consider only 1397 transformations that are ``one-to-one''. This makes it possible to 1398 speak of inverse transformations, and of combining multiple 1399 transformations. 1400 1401 Given a transformation, $f(x,y)$, the inverse transformation, 1402 $g(x,y)$, is that for which $g(f(x,y)) = (x,y)$ for $(x,y)$ over the 1403 range of interest (not necessarily the entire set of real numbers). 1404 1405 Given two transformations, $f(x,y)$ and $g(x,y)$, the combined 1406 transformation is the transformation, $h(x,y) = g(f(x,y))$ for $(x,y)$ 1407 over the range of interest (not necessarily the entire set of real 1408 numbers). 1409 1410 Both of these operations are straightforward if the transformation is 1411 linear. If the function $(u,v) = f(x,y)$ is: 1412 \begin{eqnarray} 1413 u & = & a + bx + cy \\ 1414 v & = & d + ex + fy 1415 \end{eqnarray} 1416 then the inverse transformation $(x,y) = g(u,v)$ is: 1417 \begin{eqnarray} 1418 x & = & (-fa+cd)/\Delta + fu/\Delta - cv/\Delta \\ 1419 y & = & (ae-bd)/\Delta - eu/\Delta + bv/\Delta 1420 \end{eqnarray} 1421 where $\Delta = bf - ce$ is the matrix determinant. Given two 1422 functions $f_i(x,y)$ for $i=1,2$: 1423 \begin{eqnarray} 1424 u & = & a_i + b_i x + c_i y \\ 1425 v & = & d_i + e_i x + f_i y 1426 \end{eqnarray} 1427 then the combined transformation, $(u,v) = f_2(f_1(x,y))$ is: 1428 \begin{eqnarray} 1429 u & = & (a_2 + b_2 a_1 + c_2 d_1) + (b_2 b_1 + c_2 e_1) x + (b_2 c_1 + c_2 f_1) y \\ 1430 v & = & (d_2 + e_2 a_1 + f_2 d_1) + (e_2 b_1 + f_2 e_1) x + (e_2 c_1 + f_2 f_1) y 1431 \end{eqnarray} 1432 1433 When the transformations are not linear, the inverse and combined 1434 transformations can be estimated by sampling a grid over the region of 1435 interest, calculating the transformation (or double transformation) 1436 for each sample, and using this information to derive the best fit 1437 transformation that produces the inverse or combined transformation. 1438 The inverse transformation should be of the same order as that of the 1439 forward transformation, while the combined transformation should be of 1440 the higher order of the two component transformations. 1441 1442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1443 1444 \subsection{Spherical Rotations with Quaternions} 1445 1446 \subsubsection{Quaternion Construction} 1447 1448 The following describes the algorithms needed to implement 3-D 1449 rotations in terms of quaternions. A quaternion is an ordered set of 1450 four numbers, $\bar{q} = (q_0, q_1, q_2, q_3)$. A rotation of angle 1451 $\theta$ about the axis defined by the unit vector $(v_x, v_y, v_z)$ 1452 has quaternion components: 1453 \begin{eqnarray} 1454 q_0 & = & v_x sin(\theta/2), \\ 1455 q_1 & = & v_y sin(\theta/2), \\ 1456 q_2 & = & v_z sin(\theta/2), and \\ 1457 q_3 & = & cos(\theta/2). \\ 1458 \end{eqnarray} 1459 Note that the sine and cosine are taken of the half angle of the 1460 rotation. Note also that this implies that the quaternion components 1461 are normalized such that $|\bar{q}| \def q_0^2 + q_1^2 + q_2^2 + q_3^2 1462 = 1$. 1463 1464 The 3-vector representation of the angle of the pole is determined 1465 from the coordinate of the pole ($\alpha_p, \delta_p$) by: 1466 \begin{eqnarray} 1467 v_x & = & \cos \delta_p \cos \alpha_p \\ 1468 v_y & = & \cos \delta_p \sin \alpha_p \\ 1469 v_x & = & \sin \delta_p \\ 1470 \end{eqnarray} 1471 1472 \subsubsection{Combining Two Rotations} 1473 1474 Given two quaternions $\bar{p1}$ and $\bar{p2}$, there is a third 1475 quaternion, $\bar{p}$, which represents the result of first applying 1476 $\bar{p1}$, and then $\bar{p2}$. The components of $\bar{p}$ are given 1477 by: 1332 1478 1333 1479 \begin{verbatim} 1334 1335 dX = xe - xs; 1336 dY = ye - ys; 1337 L = hypot (dX, dY); 1338 dX = dX / L; 1339 dY = dY / L; 1340 1341 REALLOCATE (xvec[0].elements, float, MAX (L, 1)); 1342 REALLOCATE (yvec[0].elements, float, MAX (L, 1)); 1343 xvec[0].Nelements = L; 1344 yvec[0].Nelements = L; 1345 1346 V = (float *)buf[0].matrix.buffer; 1347 for (i = 0; i < L; i++) { 1348 xi = xs + i*dX - 0.5; 1349 yi = ys + i*dY - 0.5; 1350 xvec[0].elements[i] = i; 1351 yvec[0].elements[i] = V[xi + Nx*yi]; 1352 } 1480 p_0 & = & p2_3 p1_0 + p2_2 p1_1 - p2_1 p1_2 + p2_0 p1_3 \\ 1481 p_1 & = & -p2_2 p1_0 + p2_3 p1_1 + p2_0 p1_2 + p2_1 p1_3 \\ 1482 p_2 & = & p2_1 p1_0 - p2_0 p1_1 + p2_3 p1_2 + p2_2 p1_3 \\ 1483 p_3 & = & -p2_0 p1_0 - p2_1 p1_1 - p2_2 p1_2 + p2_3 p1_3 \\ 1353 1484 \end{verbatim} 1354 1485 1355 \paragraph{Image Rotation} 1356 1357 Image rotation can be performed in two possible ways under different 1358 circumstances, identified in the following discussion. 1359 1360 In the simplest case, the rotation angle is an integer multiple of 90 1361 degrees ($\pi/2$ rad). In these cases, the input and output pixels 1362 have a one-to-one mapping. If the input image has dimensions of $N_x, 1363 N_y$, then the output image will have dimensions of either $N_x, N_y$ 1364 (for even multiples of 90 degrees) or $N_y, N_x$ (for odd multiples). 1365 1366 If the angle of the rotation is not a multiple of 90, then the output 1367 pixels necessarily result from the interpolation of several input 1368 pixels. In this case, for an input image of dimensions $N_x, N_y$ and 1369 rotation angle $\theta$, the output image has dimensions $Lx = |N_x 1370 \cos \theta| + |N_y \sin \theta|$ and $Ly = |N_x \sin \theta| + |N_y 1371 \cos \theta|$, each dimension rounded up to the nearest integer as 1372 needed. Every pixel in the output image is in general derived from an 1373 interpolation over 4 neighboring pixels. The coordinate of a pixel in 1374 the output image ($i,j$) corresponds to a fractional pixel coordinate 1375 ($x,y$) in the input image according to: 1376 \[ x = (i - i_o)*\cos\theta + (j - j_o)*\sin\theta \] 1377 \[ y = (i_o - i)*\sin\theta + (j - j_o)*\cos\theta \] 1378 where the offset coordinate ($i_o,j_o$) depends on the sign of the 1379 sine of the angle $\theta$. If the sign of that sine is positive, the 1380 offset coordinate is ($N_y\sin\theta$,0), otherwise it is 1381 (0,$-N_x\sin\theta$). 1382 1383 \subsubsection{Celestial Coordinate Conversions} 1486 \subsubsection{Rotating a Vector} 1487 1488 You may rotate a unit vector by first constructing a quaternion 1489 $\bar{p2}$, whose first three components are the components of the 1490 unit vector, and whose fourth component is zero. To rotate this vector 1491 by a quaternion $\bar{p1}$, you apply the formula above for combining 1492 two quaternions. The rotated vector is found in the first three 1493 components of the resulting quaternion, $\bar{p}$. 1494 1495 \subsubsection{Rotation Matrix} 1496 1497 The rotation matrix representation of a rotation may be derived 1498 directly from the quaternion representation. The following formulae 1499 convert a quaternion to a rotation matrix: 1500 1501 \begin{eqnarray} 1502 rot_{x,x} & = & q_0 q_0 - q_1 q_1 - q_2 q_2 + q_3 q_3 \\ 1503 rot_{y,y} & = & -q_0 q_0 + q_1 q_1 - q_2 q_2 + q_3 q_3 \\ 1504 rot_{z,z} & = & -q_0 q_0 - q_1 q_1 + q_2 q_2 + q_3 q_3 \\ 1505 1506 rot_{x,y} & = & 2 (q_0 q_1 + q_2 q_3) \\ 1507 rot_{y,x} & = & 2 (q_0 q_1 - q_2 q_3) \\ 1508 1509 rot_{x,z} & = & 2 (q_0 q_2 - q_1 q_3) \\ 1510 rot_{z,x} & = & 2 (q_0 q_2 + q_1 q_3) \\ 1511 1512 rot_{y,z} & = & 2 (q_1 q_2 + q_0 q_3) \\ 1513 rot_{z,y} & = & 2 (q_1 q_2 - q_0 q_3) \\ 1514 \end{eqnarray} 1515 1516 \subsubsection{Conversion to Other Representations} 1517 1518 You may convert a rotation matrix, m, to a quaternion, p, with the following 1519 code: 1520 1521 \begin{verbatim} 1522 double diag_sum[3]; 1523 int maxi; 1524 double recip; 1525 1526 diag_sum[0]=1+m[0][0]-m[1][1]-m[2][2]; 1527 diag_sum[1]=1-m[0][0]+m[1][1]-m[2][2]; 1528 diag_sum[2]=1-m[0][0]-m[1][1]+m[2][2]; 1529 diag_sum[3]=1+m[0][0]+m[1][1]+m[2][2]; 1530 1531 1532 maxi=0; 1533 for(i=1;i<4;++i) { 1534 if(diag_sum[i]>diag_sum[maxi]) maxi=i; 1535 } 1536 1537 1538 p[maxi]=0.5*sqrt(diag_sum[maxi]); 1539 recip=1./(4.*p[maxi]); 1540 1541 if(maxi==0) { 1542 p[1]=recip*(m[0][1]+m[1][0]); 1543 p[2]=recip*(m[2][0]+m[0][2]); 1544 p[3]=recip*(m[1][2]-m[2][1]); 1545 1546 } else if(maxi==1) { 1547 p[0]=recip*(m[0][1]+m[1][0]); 1548 p[2]=recip*(m[1][2]+m[2][1]); 1549 p[3]=recip*(m[2][0]-m[0][2]); 1550 1551 } else if(maxi==2) { 1552 p[0]=recip*(m[2][0]+m[0][2]); 1553 p[1]=recip*(m[1][2]+m[2][1]); 1554 p[3]=recip*(m[0][1]-m[1][0]); 1555 1556 } else if(maxi==3) { 1557 p[0]=recip*(m[1][2]-m[2][1]); 1558 p[1]=recip*(m[2][0]-m[0][2]); 1559 p[2]=recip*(m[0][1]-m[1][0]); 1560 } 1561 \end{verbatim} 1562 1563 \subsection{Celestial Coordinate Conversions} 1384 1564 1385 1565 Changes between spherical coordinate systems (ie, Ecliptic, Galactic, … … 1426 1606 the forward transformation. 1427 1607 1428 \ paragraph{Galactic to ICRS}1608 \subsubsection{Galactic to ICRS} 1429 1609 1430 1610 The appropriate values, from the Hipparcos and Tycho Catalogues are: … … 1435 1615 \end{eqnarray} 1436 1616 1437 \ paragraph{Ecliptic to ICRS}1617 \subsubsection{Ecliptic to ICRS} 1438 1618 1439 1619 The appropriate values, from Zombeck, are: … … 1445 1625 where $T$ is the time in Julian centuries since 1900. 1446 1626 1447 \ paragraph{Precession}1627 \subsubsection{Precession} 1448 1628 1449 1629 The appropriate values, from Elixir, are: … … 1457 1637 1458 1638 1459 \ paragraph{Suggested test cases}1639 \subsubsection{Suggested test cases} 1460 1640 1461 1641 $(\alpha,\delta) = (0^\circ,0^\circ)$ transforms to Galactic … … 1479 1659 1480 1660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1481 \subsubsection{2D transformations} 1482 1483 In PSLib, we implement 2-dimensional transformations using 1484 \code{psPlaneTransform}, which contains a matrix of polynomial 1485 coefficients for each dimension. Since we are using these to model 1486 the real world, where, for example, a particular point on the detector 1487 maps to a particular point on the sky, we consider only 1488 transformations that are ``one-to-one''. This makes it possible to 1489 speak of inverse transformations, and of combining multiple 1490 transformations. 1491 1492 Given a transformation, $f(x,y)$, the inverse transformation, 1493 $g(x,y)$, is that for which $g(f(x,y)) = (x,y)$ for $(x,y)$ over the 1494 range of interest (not necessarily the entire set of real numbers). 1495 1496 Given two transformations, $f(x,y)$ and $g(x,y)$, the combined 1497 transformation is the transformation, $h(x,y) = g(f(x,y))$ for $(x,y)$ 1498 over the range of interest (not necessarily the entire set of real 1499 numbers). 1500 1501 Both of these operations are straightforward if the transformation is 1502 linear. If the function $(u,v) = f(x,y)$ is: 1503 \begin{eqnarray} 1504 u & = & a + bx + cy \\ 1505 v & = & d + ex + fy 1506 \end{eqnarray} 1507 then the inverse transformation $(x,y) = g(u,v)$ is: 1508 \begin{eqnarray} 1509 x & = & (-fa+cd)/\Delta + fu/\Delta - cv/\Delta \\ 1510 y & = & (ae-bd)/\Delta - eu/\Delta + bv/\Delta 1511 \end{eqnarray} 1512 where $\Delta = bf - ce$ is the matrix determinant. Given two 1513 functions $f_i(x,y)$ for $i=1,2$: 1514 \begin{eqnarray} 1515 u & = & a_i + b_i x + c_i y \\ 1516 v & = & d_i + e_i x + f_i y 1517 \end{eqnarray} 1518 then the combined transformation, $(u,v) = f_2(f_1(x,y))$ is: 1519 \begin{eqnarray} 1520 u & = & (a_2 + b_2 a_1 + c_2 d_1) + (b_2 b_1 + c_2 e_1) x + (b_2 c_1 + c_2 f_1) y \\ 1521 v & = & (d_2 + e_2 a_1 + f_2 d_1) + (e_2 b_1 + f_2 e_1) x + (e_2 c_1 + f_2 f_1) y 1522 \end{eqnarray} 1523 1524 When the transformations are not linear, the inverse and combined 1525 transformations can be estimated by sampling a grid over the region of 1526 interest, calculating the transformation (or double transformation) 1527 for each sample, and using this information to derive the best fit 1528 transformation that produces the inverse or combined transformation. 1529 The inverse transformation should be of the same order as that of the 1530 forward transformation, while the combined transformation should be of 1531 the higher order of the two component transformations. 1532 1533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1534 1535 \subsubsection{Projections} 1536 1537 We implement three types of projections: {\em zenithal}, {\em 1538 cylindrical} and {\em pseudocylindrical}, each requiring slightly 1539 different handling. Our representations are based on the treatment of 1540 projections presented by 1541 \href{http://www.cv.nrao.edu/fits/documents/wcs/wcs.all.ps}{Greisen \& 1542 Calabretta (1995, ADASS, 4, 233)}. In all of these projections, we 1543 are converting from a spherical coordinate $\alpha,\delta$ to a linear 1544 (2-D) coordinate $x_p,y_p$. The projection is defined by the 1545 projection type, the projection center ($\alpha_p, \delta_p$) and the 1546 the plate scales in the $x_p$ and $y_p$ directions ($\rho_x,\rho_y$). 1547 1548 In the structure, \code{psProjection}, the projection type is defined 1549 by the element \code{type}, the projection center $\alpha_p,\delta_p$ 1550 is defined by the elements \code{R,D}, and the plate scales, 1551 $\rho_x,\rho_y$, are defined by the elements \code{Xs,Ys}. The plate 1552 scales are applied independently to the $x$ and $y$ coordinates to 1553 convert them to the corresponding linear units (ie, pixels): 1554 % 1555 \begin{eqnarray} 1556 x_p & = & \rho_x x \\ 1557 y_p & = & \rho_y y \\ 1558 \end{eqnarray} 1559 % 1560 In the discussions below, we ignore this last step (or first step, 1561 depending on the direction of the conversion). 1562 1563 \paragraph{Zenithal Projections} 1564 1565 The {\em zenithal} projections are defined relative to a set of 1566 spherical coordinates with pole at the center of the projection 1567 ($\alpha_p, \delta_p$), and which thus represents a coordinate system 1568 rotated relative to the coordinate system of $\alpha, \delta$. In 1569 this spherical coordinate system, the coordinate of longitude is 1570 labeled $\phi$, and has domain of $-\pi < \phi \le \pi$, while the 1571 latitude, measured from the pole, is labeled $\theta$ and has domain 1572 $0 \le \theta \le \pi$. The coordinate frame of $\phi,\theta$ is 1573 defined so that $\phi_p$, the longitude of the target system pole, is 1574 0.0. 1575 1576 For an arbitrary projection center, it is necessary to convert the 1577 spherical coordinates to be projected ($\alpha,\delta$) to the 1578 projection spherical coordinate system coordinates ($\phi, \theta$). 1579 In practice, we construct the following useful trigonometric 1580 relationships between $\phi$ and $\theta$ which may be employed in the 1581 equations of $x,y$ below: 1582 % 1583 \begin{eqnarray} 1584 \sin \theta & = & \sin \delta \sin \delta_p + \cos \delta \cos \delta_p \cos (\alpha - \alpha_p) \\ 1585 \cos \theta \cos \phi & = & \sin \delta \cos \delta_p - \cos \delta \sin \delta_p \cos (\alpha - \alpha_p) \\ 1586 \cos \theta \sin \phi & = & - \cos \delta \sin (\alpha - \alpha_p) 1587 \end{eqnarray} 1588 % 1589 For the inverse transformations, the equivalent relationships are: 1590 % 1591 \begin{eqnarray} 1592 \sin \delta & = & \sin \theta \sin \delta_p + \cos \theta \cos \delta_p \cos \phi \\ 1593 \cos \delta \cos (\alpha - \alpha_p) & = & \sin \theta \cos \delta_p - \cos \theta \sin \delta_p \cos \phi \\ 1594 \cos \delta \sin (\alpha - \alpha_p) & = & - \cos \theta \sin \phi 1595 \end{eqnarray} 1596 % 1597 For zenithal projections, the linear coordinates are related to 1598 $\phi,\theta$ by: 1599 % 1600 \begin{eqnarray} 1601 x & = & R_\theta \sin \phi \\ 1602 y & = & -R_\theta \cos \phi 1603 \end{eqnarray} 1604 % 1605 and the inverse: 1606 % 1607 \begin{eqnarray} 1608 R_\theta & = & \sqrt{x^2 + y^2} \\ 1609 \phi & = & {\rm atan} (-y,x) 1610 \end{eqnarray} 1611 % 1612 The coordinates $x,y$ above are defined to be in angular units (ie, 1613 radians). 1614 1615 From these relationships, we can calculate $\alpha, \delta$ as: 1616 % 1617 \begin{eqnarray} 1618 \alpha - \alpha_p & = & \arctan (\sin \alpha, \cos \alpha) \\ 1619 \delta & = & \arcsin (\sin \delta) \\ 1620 \end{eqnarray} 1621 % 1622 Note that if $(x,y) = (0,0)$, then $\alpha = \alpha_p, \delta = \delta_p$. 1623 1624 \subparagraph{Gnomonic} 1625 1626 The Gnomonic projection (``TAN'') is a zenithal projection with 1627 $R_\theta = \cot \theta$. The resulting relationships for $(x,y)$ and 1628 for $\sin \theta, \cos \theta$ are: 1629 1630 \begin{eqnarray} 1631 x & = & \frac{\cos \theta \sin \phi}{\sin \theta} \\ 1632 y & = & \frac{-\cos \theta \cos \phi}{\sin \theta} \\ 1633 \sin \theta & = & \zeta / \sqrt{1 + \zeta^2} \\ 1634 \cos \theta & = & 1 / \sqrt{1 + \zeta^2} \\ 1635 \end{eqnarray} 1636 1637 where $\zeta = 1 / R_\theta$. 1638 1639 \subparagraph{Orthographic} 1640 1641 The Orthographic projection (``SIN'') is a zenithal projection with 1642 $R_\theta = \cos \theta$. The resulting relationships for $(x,y)$ and 1643 for $\sin \theta, \cos \theta$ are: 1644 1645 \begin{eqnarray} 1646 x & = & \cos \theta \sin \phi \\ 1647 y & = & -\cos \theta \cos \phi \\ 1648 \sin \theta & = & \sqrt{1 - R_\theta^2} \\ 1649 \cos \theta & = & R_\theta \\ 1650 \end{eqnarray} 1651 1652 \paragraph{Cylindrical and Pseudocylindrical Projections} 1653 1654 The {\em cylindrical} and {\em pseudocylindrical} projections are 1655 defined relative to a set of cylindrical coordinates whose pole is 1656 coincident with the pole of the spherical coordinates. These 1657 projections are particularly used for full-sky representations, and 1658 are only defined for projection centers with $\delta_p = 0$. In this 1659 spherical coordinate system, the coordinate of longitude is labeled 1660 $\phi$, and has domain of $-\pi < \phi \le \pi$, while the latitude, 1661 measured from the pole, is labeled $\theta$ and has domain $0 \le 1662 \theta \le \pi$. The projection center longitude, $\alpha_p$ 1663 corresponds to $\phi = 0$, thus the value of $\phi$ is determined as 1664 $\alpha - \alpha_p$ for all such projections. 1665 1666 \subparagraph{Cartesian} 1667 1668 The Cartesian projection (``CAR'') is a very simple cylindrical 1669 projection with the following relationships between $x,y$ and 1670 $\phi,\theta$: 1671 1672 \begin{eqnarray} 1673 x & = & \phi \\ 1674 y & = & \theta 1675 \end{eqnarray} 1676 1677 \subparagraph{Mercator} 1678 1679 The Mercator projection (``MER'') is a cylindrical projection. 1680 1681 \begin{eqnarray} 1682 x & = & \phi \\ 1683 y & = & \ln \left( \tan (\pi/4 + \theta/2) \right) \\ 1684 {\rm and}\hspace{1cm} \theta & = & 2 \arctan \left( e^y \right) - \pi/2 1685 \end{eqnarray} 1686 1687 \subparagraph{Hammer-Aitoff} 1688 1689 The Hammer-Aitoff projection(``AIT'') is a pseudocylindrical projection, and is defined: 1690 1691 \begin{eqnarray} 1692 x & = & 2 \zeta \cos \theta \sin \frac{\phi}{2} \\ 1693 y & = & \zeta \sin \theta \\ 1694 {\rm where}\hspace{1cm} \zeta^{-1} & \equiv & \sqrt{\frac{1}{2}\left(1 + \cos \theta \cos \frac{\phi}{2} \right)} 1695 \end{eqnarray} 1696 1697 And in reverse: 1698 1699 \begin{eqnarray} 1700 \phi & = & 2 {\rm \arctan} (2z^2 - 1, x z) \\ 1701 \theta & = & \arcsin (yz) \\ 1702 {\rm where}\hspace{1cm} z & \equiv & \sqrt{1 - (x/2)^2 - y^2} 1703 \end{eqnarray} 1704 1705 \subparagraph{Parabolic} 1706 1707 The Parabolic projection (``PAR'') is a pseudocylindrical projection, and is defined: 1708 1709 \begin{eqnarray} 1710 x & = & \phi \left( 2 \cos \frac{2 \theta}{3} - 1 \right) \\ 1711 y & = & \pi \sin \frac{\theta}{3} \\ 1712 \end{eqnarray} 1713 1714 And in reverse: 1715 1716 \begin{eqnarray} 1717 \theta & = & 3 \sin^{-1} \rho \\ 1718 \phi & = & \frac{x}{1 - 4\rho^2} \\ 1719 {\rm where}\hspace{1cm} \rho & \equiv & y/\pi \\ 1720 \end{eqnarray} 1721 1722 \subsubsection{Offset} 1723 1724 Coordinate offsets can be either spherical offsets or linear offsets. 1725 1726 A spherical offset is performed by adding the components of the 1727 offset, after unit conversion, to the given position. The resulting 1728 coordinates must be wrapped to within the allowed range ($-\pi$ to 1729 $\pi$, 0 to $2\pi$). 1730 1731 A linear offset is defined to be a linear offset in a tangent 1732 projection centered on the starting coordinate with $y$ axis aligned 1733 with the local direction or increasing Declination. This projection 1734 is undefined only for the coordinates exactly at the north and south 1735 poles, in which case the orientation is defined to have the $y$ axis 1736 parallel to the line of RA = 0.0. The scale of the projection is 1.0 1737 (ie, 1 'pixel' is 1 radian) and the given offsets must the scaled 1738 based on the given offset units. 1739 1740 Pseudo-code to implement the above for an offset: 1741 1742 \begin{verbatim} 1743 psSphere *psSphereSetOffset (psSphere pos, psSphere offset) { 1744 1745 psPlane lin; 1746 psSphere new; 1747 psProjection proj; 1748 1749 proj.R = pos->r; 1750 proj.D = pos->d; 1751 proj.X = 0; 1752 proj.Y = 0; 1753 proj.type = PS_PROJ_TAN; 1754 1755 lin.x = offset.r; 1756 lin.y = offset.d; 1757 1758 new = psDeproject (&lin, &proj); 1759 return (new); 1760 } 1761 \end{verbatim} 1762 1763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1764 1765 \subsubsection{Tangent Plane to Sky} 1661 1662 \subsection{Tangent Plane to Sky} 1766 1663 1767 1664 \tbd{we will replace the SLALIB version of AOPPA with a new function} … … 1798 1695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1799 1696 1800 \subsubsection{The One-to-Many Problem with Mosaic Cameras} 1697 \subsection{Sky to Tangent Plane (II)} 1698 1699 This section describes the transformation between celestial coordinates 1700 (R.A., Dec.) and local terrestrial coordinates (Az, Alt). This transformation 1701 is broken down into a number of steps as described below. 1702 1703 \paragraph{Reference Implementations} 1704 1705 There are two reference implementatins for the code to account for the 1706 motion of the Earth in space. The first are the sample routines 1707 provided by the IERS to accompany chaper 5 of IERS Bulletin 32. This 1708 document and the code can be downloaded from 1709 http://maia.usno.navy.mil/conv2003.html . The second reference 1710 implementation is the SOFA software package managed by the IAU and 1711 available at http://www.iau-sofa.rl.ac.uk Only the 2003-04-29 version 1712 of SOFA should be used. The IERS code requires a few of the rotation 1713 matrix utility routines from SOFA. 1714 1715 Both implementations are in FORTRAN 77. The SOFA code has a more 1716 complex implementation of precession-nutation for backward 1717 compatibility with the pre 2003-01-01 conventions. The IERS code 1718 includes some tricks to achieve greater precision in the fundamental 1719 arguments of nutation, which the SOFA code omits. Therefore, the main 1720 reference for psLib should be the IERS code. Note that the IERS code 1721 calculates the transform from terrestrial to celestial coordinates, 1722 while the SOFA code calculates its inverse. 1723 1724 \subsubsection{Coordinate Systems} 1725 1726 \begin{figure} 1727 \psfig{file=transforms.ps} 1728 \caption{Coordinates systems and the transformations between them} 1729 1730 \end{figure} 1731 Figure X shows the transformation steps and intermediate coordinate systems 1732 between celestial and local terrestrial coordinate systems. The intermediate 1733 coordinate systems are defined below. 1734 1735 \paragraph{ICRS} 1736 The official IAU-sanctioned celestial coordinate system is the 1737 International Celestial Reference System (ICRS). It is defined in terms of 1738 a number of radio sources whose positions have been measured using VLBI. 1739 It can be tied to the optical through the Hipparcos catalog. The ICRS has its 1740 origin at the solar system barycenter. 1741 1742 \paragraph{GCRS} 1743 The Geocentric Celestial Reference System (GCRS) corresponds to the ICRS, but 1744 has its origin at the center of the Earth. The differences between the two 1745 systems are due to the velocity of the Earth (aberration), the position of 1746 the Earth (parallax), and general relativistic bending of light rays. 1747 There is no net rotation between the ICRS and the GCRS. 1748 1749 \paragraph{ITRS} 1750 The International Terrestrial Reference System (ITRS) is a coordinate 1751 system which is fixed with respect to the Earth's crust. 1752 1753 \paragraph{Intermediate Coordinate Systems - CIP, CEO, TEO} 1754 The transform between the GCRS and ITRS is conventionally 1755 decomposed into three parts in order to isolate the relatively rapid rotation 1756 of the Earth from the movement of the Earth's rotational axis in the GCRS 1757 and ITRS. All three sub-transforms are rigid rotations. 1758 1759 This decomposition results in two intermediate coordinate systems. Both of 1760 these share the same pole, known as the Celestial Intermediate Pole (CIP). 1761 The CIP is defined by its motion in the GCRS to match the Tisserand 1762 mean axis of the Earth (Seidelmann 1982, Celesial Mechanics 27, 78-106), 1763 excluding motions with periods less than or equal 1764 to two days. The CIP approximates the angular momentum vector of the 1765 rotating Earth. 1766 1767 The X axes of the intermediate coordinate systems are known as the 1768 Celestial and Terrestrial Ephemeris Origins. (CEO and TEO). Both are defined 1769 to be non-rotating origins. A non-rotating origin is a point on the equator 1770 whose instantaneous motion is always orthogonal to the equator 1771 (Kaplan 2003 IAU XXV Joint Discussion 16 1772 \footnote{http://aa.usno.navy.mil/kaplan/NROs\%5BJD16proc\%5D.pdf}). 1773 Thus the CEO is defined by its position in the GCRS at some epoch and by the 1774 motion of the CIP in the GCRS since that date. Similarly the TEO is 1775 defined by its position in the ITRS at some epoch and the motion of the 1776 CIP in the ITRS since that date. 1777 1778 \subsubsection{ICRS - GCRS} 1779 1780 The transformation between barycentric (ICRS) and geocentric (GCRS) coordinates 1781 involves two components. These are 1782 the general relativistic deflection of light rays by the Sun's gravity, and 1783 aberration, due to the orbital motion 1784 of the Earth. 1785 1786 \paragraph{Gravitational Deflection} 1787 1788 The Sun's gravity bends the path of light rays which pass near it. 1789 To first order, a light ray is deflected by an angle of $4GM/c^2r_0$ radians, 1790 where $G$ is the gravitational constant, 1791 $M$ is the mass of the Sun, 1792 $c$ is the speed of light, and 1793 $r_0$ is the point of closest approach to the light ray to the Sun. 1794 To the same order this is equal to the impact parameter - i.e. the point 1795 of closest approach if the light ray were not deflected. Note that 1796 $r_0/d = \tan(\theta)$, where $d$ is the distance from the Earth 1797 to the Sun, and $\theta$ 1798 is the angular separation of the star from the center of the Sun. 1799 1800 There is a maximum deflection of 1.75 arc seconds if we set 1801 $r_0$ to the radius of the sun. 1802 Since the Sun bends light rays toward it, a star appears shifted away from the sun in the sky. 1803 1804 \paragraph{Aberration} 1805 1806 Aberration is the apparent change in direction of a ray of light in the 1807 reference frame of a moving observer. Traditionally the aberration 1808 calculation has been done with a linear expansion of the full 1809 relativistic expression, often neglecting all but the linear term in 1810 $v/c$, since the relativistic terms are on the order of a miliarcsecond. 1811 However, the full relativistic expression poses no challenge for modern 1812 computers, so psLib will use the following procedure to calculate aberration. 1813 1814 Suppose an observer has a velocity $\beta\hat{\beta}$, with respect to 1815 the Solar System barycenter, where $\beta$ is in units of the speed of 1816 light, and $\hat{\beta}$ is a unit vector. Suppose also that the unit vector 1817 $\hat{r}$ points toward a star in the barycenter frame of reference 1818 (i.e. the ``actual'' position). 1819 and $\hat{r}'$ gives the direction of the star in the observer's frame, 1820 (i.e. the apparent position). 1821 1822 First, decompose $\hat{r}$ into components parallel and perpendicular to 1823 $\hat{\beta}$ by calculating 1824 $\mu = \hat{r}\cdot\hat{\beta}$ and 1825 $\vec{r}_\perp = \hat{r} - \mu \hat{\beta}$. 1826 1827 Next, use the following expression for relativistic beaming, modified 1828 slightly from equation 4.8b of Rybicki and Lightman: 1829 \begin{equation} 1830 \mu' = \mu + \beta \frac{\mu^2 - 1}{1 - \beta\mu} 1831 \end{equation} 1832 where $\mu' = \hat{r}' \cdot \hat{\beta}$. 1833 1834 Now, the component of $\hat{r}'$ perpendicular to $\hat{\beta}$ 1835 (i.e. $\vec{r}_\perp'$) must point 1836 in the same direction as $\vec{r}_\perp$, but will have a different magnitude 1837 because $\hat{r}'$ is a unit vector. In other words, 1838 $\vec{r}_\perp' = a\vec{r}_\perp$, for some scalar $a$. So the next step is 1839 to calculate $a = \sqrt{(1-\mu'^2)/\vec{r}_\perp}$. 1840 1841 Finally, reassemble the components of 1842 $\hat{r}' = \mu'\hat{\beta} + a \vec{r_\perp}$. 1843 1844 1845 \subsubsection{GCRS - ITRS} 1846 The transformation between geocentric celestial coordinates and terrestrial 1847 coordinates is a solid body rotation due to the motion of the Earth is space. 1848 This is conventionally broken down into three components to isolate the 1849 relatively rapid rotation of the Earth from the motion of its rotational axis. 1850 1851 This section is largely a summary of 1852 Chapter 5 of IERS Technical Note 32 \footnote{http://maia.usno.navy.mil/conv2003.html} 1853 (hereafter IERS32), 1854 which is a description of the implementation of the Resoltions of the 1855 XXIVth General Assembly of the IAU, available from the same URL as above. 1856 These two documents describe a set of conventions which have been in effect 1857 since 2003-01-01. The conventions in effect before that date will not be 1858 implemented by psLib. 1859 1860 1861 \paragraph{Precession/Nutation} 1862 1863 The transform between the GCRS and the CIP/CEO coordinate systems is described 1864 by the IAU 2000A precession-nutation model, which is accurate to the 1865 0.2 mas level. 1866 For higher accuracy the user must apply corrections to the model, which are tabulated by the IERS. 1867 1868 1869 1870 The IAU 2000A precession-nutation model may be calculated in the following 1871 way. First calculate the time $t$ as the number of Julian centuries since 1872 2000-01-01T12:00:00 TT. 1873 1874 Next calculate the fundamental arguments of nutation using equations (40) 1875 and (41) of IERS32, reproduced below: 1876 \begin{eqnarray} 1877 F_1\equiv l\quad =~&\ Mean\ Anomaly\ of\ the\ Moon \cr 1878 =~& 134.96340251^\circ + 1717915923.2178'' t 1879 + 31.8792'' t^2 + 0.051635'' t^3 - 0.00024470'' t^4,\cr 1880 F_2\equiv l'\quad =~&\ Mean\ Anomaly\ of\ the\ Sun\cr 1881 =~& 357.52910918^\circ + 129596581.0481'' t 1882 - 0.5532'' t^2 + 0.000136'' t^3 - 0.00001149'' t^4,\cr 1883 F_3\equiv F\quad =~& L - \Omega\cr 1884 =~& 93.27209062^\circ + 1739527262.8478'' t - 12.7512'' t^2 1885 - 0.001037'' t^3 + 0.00000417'' t^4,\cr 1886 F_4\equiv D\quad =~&\ Mean\ Elongation\ of\ the\ Moon\ from\ the\ Sun\cr 1887 =~& 297.85019547^\circ + 1602961601.2090'' t - 6.3706'' t^2 1888 + 0.006593'' t^3 - 0.00003169'' t^4,\cr 1889 F_5\equiv\Omega\quad =~&\ Mean\ Longitude\ of\ the\ Ascending\ Node\ of\ 1890 the\ Moon\cr 1891 =~& 125.04455501^\circ - 6962890.5431'' t + 7.4722'' t^2 + 0.007702'' t^3 - 0.00005939'' t^4 \cr 1892 F_6\ \equiv l_{Me}\quad =~& 4.402 608 842 + 2608.7903 141 574\times t,\cr 1893 F_7\ \equiv l_{Ve}\quad =~& 3.176 146 697 + 1021.3285 546 211 \times t,\cr 1894 F_8\ \equiv l_{E\ }\quad =~& 1.753 470 314 + 628.3075 849 991 \times t,\cr 1895 F_9\equiv l_{Ma}\quad =~& 6.203 480 913 + 334.0612 426 700 \times t,\cr 1896 F_{10}\equiv l_{Ju}\quad =~& 0.599 546 497 + 52.9690 962 641 \times t,\cr 1897 F_{11}\equiv l_{Sa}\quad =~& 0.874 016 757 + 21.3299 104 960 \times t,\cr 1898 F_{12}\equiv l_{Ur}\quad =~& 5.481 293 872 + 7.4781 598 567 \times t,\cr 1899 F_{13}\equiv l_{Ne}\quad =~& 5.311 886 287 + 3.8133 035 638 \times t,\cr 1900 F_{14}\equiv p_{a\ }\quad =~& 0.024 381 750 \times t + 0.000 005 386 91 \times t^2. 1901 \end{eqnarray} 1902 1903 Next calculate the quantities $X$, $Y$, and $s$, using expressions of the form: 1904 1905 \begin{equation} 1906 \sum_{j} p_j t^j + \sum_{j}\sum_{i}[ 1907 (a_{{\rm s},j})_i t^j \sin ({\rm \scriptstyle {ARG_{i,j}}}) 1908 + (a_{{\rm c},j})_i t^j \cos ({\rm \scriptstyle {ARG_{i,j}}})] 1909 , 1910 \end{equation} 1911 1912 where the $\rm \scriptstyle{ARG_{i,j}} = \sum_{k} w_{i,j,k} F_k$ represent linear 1913 combinations of the fundamental arguments of nutation. 1914 1915 The constants $p_j$, $w_{i,j,k}$, $(a_{{\rm s},j})_i$, and $(a_{{\rm c},j})_i$ 1916 are given in the ASCII files: 1917 tab5.2a.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2a.txt} (for $X$), 1918 tab5.2b.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2b.txt} (for $Y$), and 1919 tab5.2c.txt \footnote{http://maia.usno.navy.mil/conv2000/chapter5/tab5.2c.txt} (for $s+XY/2$). 1920 Note that the expansion is given for $s+XY/2$, since this series converges 1921 more rapidly than the one for $s$ alone. 1922 1923 Each file contains a human-readable header, which includes the polynomial 1924 coeficients, $p_j$ under the heading ``Polynomial part''. The data part of the 1925 file lists the remaining constants, with rows cycling first through $i$, and 1926 then through $j$. There is a separate heading each time $j$ increments. 1927 Each row contains the following columns: 1928 1929 \begin{itemize} 1930 \item col 1 - A running index of rows in the table. 1931 \item col 2 - The sine coeficients, $(a_{{\rm s},j})_i$ 1932 \item col 3 - The cosine coeficients, $(a_{{\rm c},j})_i$ 1933 \item cols 4 - 17 The weighting factors for the fundamental arguments of 1934 nutation, $w_{i,j,k}$. 1935 \end{itemize} 1936 1937 1938 A FORTRAN reference implementation for the precession/nutation model is available from the IERS 1939 \footnote{http://maia.usno.navy.mil/conv2000/chapter5/XYS2000A.f}. 1940 The psLib results should agree with the reference implementation to within 1941 the limits of numerical precision. 1942 1943 Next, corrections to $X$, and $Y$ may be obtained from the IERS as part of 1944 Bulletin A, or B. It is recommended to use the values published daily in 1945 http://maia.usno.navy.mil/ser7/finals2000A.daily, which has the format 1946 described by http://maia.usno.navy.mil/ser7/readme.finals2000A. The 1947 quantities of interest are labeled dX and dY. Note that UT1$-$UTC and the 1948 polar motion values are obtained from this same table. 1949 1950 By convention, nutation terms with periods of less 1951 than two days 1952 are accounted for by the corresponding polar motion. So it is sufficient to 1953 interpolate the corrections tabulated daily by the IERS, and take the result as 1954 instantaneous values. 1955 1956 The final step is to use $X$, $Y$, and $s$ to calculate the rotation 1957 matrix from the CIP/CEO system to the GCRS using IERS32 equation (10), 1958 reproduced below: 1959 1960 \begin{equation} 1961 \begin{pmatrix}1-aX^2& -aXY& X\cr -aXY& 1-aY^2& Y\cr -X& -Y& 1962 1-a(X^2+Y^2)\cr 1963 \end{pmatrix} \cdot R_3(s), 1964 \end{equation} 1965 where $R_3$ denotes a rotation about the Z axis, 1966 $a = 1/(1+\sqrt{1 - X^2 + Y^2})$, 1967 and $X$ and $Y$ are expressed in radians. 1968 A FORTRAN reference implementation for this calculation is given 1969 by the IERS \footnote{http://maia.usno.navy.mil/conv2000/chapter5/BPN2000.f}. 1970 1971 Note that above we gave the expression for the transform toward celestial 1972 coordinates (upward in figure X), in order to match the IERS reference code. 1973 The inverse transform may be found by inverting the resulting rotation. 1974 1975 \paragraph{Rotation of the Earth} 1976 1977 The transform from the CIP/CEO to CIP/TEO coordinate systems is a 1978 rotation about the CIP (i.e. the Z axis) by an angle known as the 1979 ``Earth Rotation Angle''. 1980 By definition the Earth Rotation Angle is given by 1981 equation (13) of IERS32, reproduced below: 1982 \begin{equation} 1983 \theta(T_u)=2\pi(0.7790572732640 + 1.00273781191135448T_u), 1984 \end{equation} 1985 where $T_u$ is the Julian UT1 date minus 2451545.0 . 1986 1987 \paragraph{Polar Motion} 1988 1989 The motion of the CIP in the ITRS is known as ``polar motion''. Similarly to 1990 precession/nutation, the instantaneous position of the CIP in the 1991 ITRS is specified by the quantites $x_p$, and $y_p$, and a third quantity, 1992 $s'$, gives the position of the TEO with respect to the ITRS. 1993 The values of $x_p$ and $y_p$ are published daily by the IERS in 1994 http://maia.usno.navy.mil/ser7/finals2000A.daily, which has the format 1995 described by http://maia.usno.navy.mil/ser7/readme.finals2000A. 1996 The UT1$-$UTC, and the precession/nutation corrections (discussed elsewhere 1997 in this document) come from this same source. 1998 1999 The polar motion coordinates should be interpolated using a third order 2000 polynomial, as described in 2001 IERS Gazette \#13 \footnote{http://maia.usno.navy.mil/iers-gaz13}, 2002 which gives a 2003 FORTRAN reference implementation of the correct procedure. 2004 2005 \tbd{reference to interpolation in this doc?} 2006 2007 The values published by the IERS are smoothed to remove noise and 2008 variations on the timescale of a day or less. There are two sources of 2009 short timescale variations - tidal effects on the order of 0.1 milliarcseconds, 2010 and short period nutation terms on the order of 15 microarcseconds. 2011 Both of these effects may be modeled and added to the interpolated values 2012 for higher accuracy. 2013 2014 The tidal effects should be included using the FORTRAN reference implementation 2015 of the Ray tidal model given in IERS Gazette \#13. This code should be 2016 mimiced to machine accuracy by psLib. 2017 2018 By definition of the CIP, nutation terms with periods less than 2 days are 2019 not included in the IAU 2000A precession/nutation model. 2020 So these motions 2021 must be compensated for by their equivalent polar motions. These may 2022 be calculated using a form similar to that of the precession/nutation $X$, 2023 and $Y$. The constants to use are given in Table 5.1 of IERS32. 2024 Note that only the terms with periods less than 2 days should be used. 2025 2026 The quantity $s'$ may be approximated with microarcsecond accuracy over this 2027 century by $s' = -4.7 \times 10^{-5} t$ in arcseconds. There is no need 2028 to apply short timescale corrections to $s'$. 2029 2030 The transform from the ITRS to the CIP/TEO frame can be constructed by 2031 first rotating about the X axis by $y_p$, then rotating about the X axis by 2032 $x_p$, and finally rotating about the Z axis by $s'$. 2033 The IERS reference implementation for this is given in the subroutine 2034 POM2000 \footnote{http://maia.usno.navy.mil/conv2000/chapter5/POM2000.f}. 2035 Note that we describe the transform toward celestial coordinates (upward in 2036 figure X), in order to match the reference implementation. 2037 2038 \subsubsection{ITRS - Alt/Az} 2039 2040 \paragraph{Orientation of the Observer} 2041 2042 An observer's astronomical longitude and latitude give the orientation of 2043 the local vertical with respect to the ITRS. Note that these coordinates 2044 can be approximated by the geographic longitude and latitude of the observatory, 2045 but their exact values must be calibrated from observation of stars 2046 with known coordinates in the ICRS. 2047 2048 The transform from the ITRS to Az/Alt in the absence of atmospheric refraction 2049 is first a rotation about the Z axis by the observer's astronomical longitude, 2050 and then a rotation about the Y axis of 90 degrees minus the observer's 2051 astronomical latitude, followed by a rotation about the Z axis of 180 degrees 2052 so that North is zero azimuth. 2053 2054 \paragraph{Atmospheric Refraction} 2055 2056 \tbd{add in summary of Ken's paper} 2057 2058 \subsection{Projections} 2059 2060 We implement three types of projections: {\em zenithal}, {\em 2061 cylindrical} and {\em pseudocylindrical}, each requiring slightly 2062 different handling. Our representations are based on the treatment of 2063 projections presented by 2064 \href{http://www.cv.nrao.edu/fits/documents/wcs/wcs.all.ps}{Greisen \& 2065 Calabretta (1995, ADASS, 4, 233)}. In all of these projections, we 2066 are converting from a spherical coordinate $\alpha,\delta$ to a linear 2067 (2-D) coordinate $x_p,y_p$. The projection is defined by the 2068 projection type, the projection center ($\alpha_p, \delta_p$) and the 2069 the plate scales in the $x_p$ and $y_p$ directions ($\rho_x,\rho_y$). 2070 2071 In the structure, \code{psProjection}, the projection type is defined 2072 by the element \code{type}, the projection center $\alpha_p,\delta_p$ 2073 is defined by the elements \code{R,D}, and the plate scales, 2074 $\rho_x,\rho_y$, are defined by the elements \code{Xs,Ys}. The plate 2075 scales are applied independently to the $x$ and $y$ coordinates to 2076 convert them to the corresponding linear units (ie, pixels): 2077 % 2078 \begin{eqnarray} 2079 x_p & = & \rho_x x \\ 2080 y_p & = & \rho_y y \\ 2081 \end{eqnarray} 2082 % 2083 In the discussions below, we ignore this last step (or first step, 2084 depending on the direction of the conversion). 2085 2086 \subsubsection{Zenithal Projections} 2087 2088 The {\em zenithal} projections are defined relative to a set of 2089 spherical coordinates with pole at the center of the projection 2090 ($\alpha_p, \delta_p$), and which thus represents a coordinate system 2091 rotated relative to the coordinate system of $\alpha, \delta$. In 2092 this spherical coordinate system, the coordinate of longitude is 2093 labeled $\phi$, and has domain of $-\pi < \phi \le \pi$, while the 2094 latitude, measured from the pole, is labeled $\theta$ and has domain 2095 $0 \le \theta \le \pi$. The coordinate frame of $\phi,\theta$ is 2096 defined so that $\phi_p$, the longitude of the target system pole, is 2097 0.0. 2098 2099 For an arbitrary projection center, it is necessary to convert the 2100 spherical coordinates to be projected ($\alpha,\delta$) to the 2101 projection spherical coordinate system coordinates ($\phi, \theta$). 2102 In practice, we construct the following useful trigonometric 2103 relationships between $\phi$ and $\theta$ which may be employed in the 2104 equations of $x,y$ below: 2105 % 2106 \begin{eqnarray} 2107 \sin \theta & = & \sin \delta \sin \delta_p + \cos \delta \cos \delta_p \cos (\alpha - \alpha_p) \\ 2108 \cos \theta \cos \phi & = & \sin \delta \cos \delta_p - \cos \delta \sin \delta_p \cos (\alpha - \alpha_p) \\ 2109 \cos \theta \sin \phi & = & - \cos \delta \sin (\alpha - \alpha_p) 2110 \end{eqnarray} 2111 % 2112 For the inverse transformations, the equivalent relationships are: 2113 % 2114 \begin{eqnarray} 2115 \sin \delta & = & \sin \theta \sin \delta_p + \cos \theta \cos \delta_p \cos \phi \\ 2116 \cos \delta \cos (\alpha - \alpha_p) & = & \sin \theta \cos \delta_p - \cos \theta \sin \delta_p \cos \phi \\ 2117 \cos \delta \sin (\alpha - \alpha_p) & = & - \cos \theta \sin \phi 2118 \end{eqnarray} 2119 % 2120 For zenithal projections, the linear coordinates are related to 2121 $\phi,\theta$ by: 2122 % 2123 \begin{eqnarray} 2124 x & = & R_\theta \sin \phi \\ 2125 y & = & -R_\theta \cos \phi 2126 \end{eqnarray} 2127 % 2128 and the inverse: 2129 % 2130 \begin{eqnarray} 2131 R_\theta & = & \sqrt{x^2 + y^2} \\ 2132 \phi & = & {\rm atan} (-y,x) 2133 \end{eqnarray} 2134 % 2135 The coordinates $x,y$ above are defined to be in angular units (ie, 2136 radians). 2137 2138 From these relationships, we can calculate $\alpha, \delta$ as: 2139 % 2140 \begin{eqnarray} 2141 \alpha - \alpha_p & = & \arctan (\sin \alpha, \cos \alpha) \\ 2142 \delta & = & \arcsin (\sin \delta) \\ 2143 \end{eqnarray} 2144 % 2145 Note that if $(x,y) = (0,0)$, then $\alpha = \alpha_p, \delta = \delta_p$. 2146 2147 \paragraph{Gnomonic} 2148 2149 The Gnomonic projection (``TAN'') is a zenithal projection with 2150 $R_\theta = \cot \theta$. The resulting relationships for $(x,y)$ and 2151 for $\sin \theta, \cos \theta$ are: 2152 2153 \begin{eqnarray} 2154 x & = & \frac{\cos \theta \sin \phi}{\sin \theta} \\ 2155 y & = & \frac{-\cos \theta \cos \phi}{\sin \theta} \\ 2156 \sin \theta & = & \zeta / \sqrt{1 + \zeta^2} \\ 2157 \cos \theta & = & 1 / \sqrt{1 + \zeta^2} \\ 2158 \end{eqnarray} 2159 2160 where $\zeta = 1 / R_\theta$. 2161 2162 \paragraph{Orthographic} 2163 2164 The Orthographic projection (``SIN'') is a zenithal projection with 2165 $R_\theta = \cos \theta$. The resulting relationships for $(x,y)$ and 2166 for $\sin \theta, \cos \theta$ are: 2167 2168 \begin{eqnarray} 2169 x & = & \cos \theta \sin \phi \\ 2170 y & = & -\cos \theta \cos \phi \\ 2171 \sin \theta & = & \sqrt{1 - R_\theta^2} \\ 2172 \cos \theta & = & R_\theta \\ 2173 \end{eqnarray} 2174 2175 \subsubsection{Cylindrical and Pseudocylindrical Projections} 2176 2177 The {\em cylindrical} and {\em pseudocylindrical} projections are 2178 defined relative to a set of cylindrical coordinates whose pole is 2179 coincident with the pole of the spherical coordinates. These 2180 projections are particularly used for full-sky representations, and 2181 are only defined for projection centers with $\delta_p = 0$. In this 2182 spherical coordinate system, the coordinate of longitude is labeled 2183 $\phi$, and has domain of $-\pi < \phi \le \pi$, while the latitude, 2184 measured from the pole, is labeled $\theta$ and has domain $0 \le 2185 \theta \le \pi$. The projection center longitude, $\alpha_p$ 2186 corresponds to $\phi = 0$, thus the value of $\phi$ is determined as 2187 $\alpha - \alpha_p$ for all such projections. 2188 2189 \paragraph{Cartesian} 2190 2191 The Cartesian projection (``CAR'') is a very simple cylindrical 2192 projection with the following relationships between $x,y$ and 2193 $\phi,\theta$: 2194 2195 \begin{eqnarray} 2196 x & = & \phi \\ 2197 y & = & \theta 2198 \end{eqnarray} 2199 2200 \paragraph{Mercator} 2201 2202 The Mercator projection (``MER'') is a cylindrical projection. 2203 2204 \begin{eqnarray} 2205 x & = & \phi \\ 2206 y & = & \ln \left( \tan (\pi/4 + \theta/2) \right) \\ 2207 {\rm and}\hspace{1cm} \theta & = & 2 \arctan \left( e^y \right) - \pi/2 2208 \end{eqnarray} 2209 2210 \paragraph{Hammer-Aitoff} 2211 2212 The Hammer-Aitoff projection(``AIT'') is a pseudocylindrical projection, and is defined: 2213 2214 \begin{eqnarray} 2215 x & = & 2 \zeta \cos \theta \sin \frac{\phi}{2} \\ 2216 y & = & \zeta \sin \theta \\ 2217 {\rm where}\hspace{1cm} \zeta^{-1} & \equiv & \sqrt{\frac{1}{2}\left(1 + \cos \theta \cos \frac{\phi}{2} \right)} 2218 \end{eqnarray} 2219 2220 And in reverse: 2221 2222 \begin{eqnarray} 2223 \phi & = & 2 {\rm \arctan} (2z^2 - 1, x z) \\ 2224 \theta & = & \arcsin (yz) \\ 2225 {\rm where}\hspace{1cm} z & \equiv & \sqrt{1 - (x/2)^2 - y^2} 2226 \end{eqnarray} 2227 2228 \paragraph{Parabolic} 2229 2230 The Parabolic projection (``PAR'') is a pseudocylindrical projection, and is defined: 2231 2232 \begin{eqnarray} 2233 x & = & \phi \left( 2 \cos \frac{2 \theta}{3} - 1 \right) \\ 2234 y & = & \pi \sin \frac{\theta}{3} \\ 2235 \end{eqnarray} 2236 2237 And in reverse: 2238 2239 \begin{eqnarray} 2240 \theta & = & 3 \sin^{-1} \rho \\ 2241 \phi & = & \frac{x}{1 - 4\rho^2} \\ 2242 {\rm where}\hspace{1cm} \rho & \equiv & y/\pi \\ 2243 \end{eqnarray} 2244 2245 \subsection{Offset} 2246 2247 Coordinate offsets can be either spherical offsets or linear offsets. 2248 2249 A spherical offset is performed by adding the components of the 2250 offset, after unit conversion, to the given position. The resulting 2251 coordinates must be wrapped to within the allowed range ($-\pi$ to 2252 $\pi$, 0 to $2\pi$). 2253 2254 A linear offset is defined to be a linear offset in a tangent 2255 projection centered on the starting coordinate with $y$ axis aligned 2256 with the local direction or increasing Declination. This projection 2257 is undefined only for the coordinates exactly at the north and south 2258 poles, in which case the orientation is defined to have the $y$ axis 2259 parallel to the line of RA = 0.0. The scale of the projection is 1.0 2260 (ie, 1 'pixel' is 1 radian) and the given offsets must the scaled 2261 based on the given offset units. 2262 2263 Pseudo-code to implement the above for an offset: 2264 2265 \begin{verbatim} 2266 psSphere *psSphereSetOffset (psSphere pos, psSphere offset) { 2267 2268 psPlane lin; 2269 psSphere new; 2270 psProjection proj; 2271 2272 proj.R = pos->r; 2273 proj.D = pos->d; 2274 proj.X = 0; 2275 proj.Y = 0; 2276 proj.type = PS_PROJ_TAN; 2277 2278 lin.x = offset.r; 2279 lin.y = offset.d; 2280 2281 new = psDeproject (&lin, &proj); 2282 return (new); 2283 } 2284 \end{verbatim} 2285 2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2287 2288 \subsection{The One-to-Many Problem with Mosaic Cameras} 1801 2289 1802 2290 The \PS{} focal plane consists of several chips, so we will often want … … 1820 2308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1821 2309 1822 \subs ubsection{General Astronomy Functions}2310 \subsection{General Astronomy Functions} 1823 2311 1824 2312 \tbd{we will provide a new airmass function} … … 1854 2342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1855 2343 1856 \subs ubsection{Positions of Major Solar System Objects}2344 \subsection{Positions of Major Solar System Objects} 1857 2345 1858 2346 \tbd{ephemerides code to replace this} … … 1869 2357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1870 2358 1871 \subsection{Missing and Todo} 1872 1873 \tbd{define sunrise, sunset, sun position} 1874 1875 \tbd{define moonrise, moonset, moon position, moon phase} 1876 1877 \tbd{define planet functions} 1878 1879 \tbd{clean up FITS I/O issues} 1880 1881 \tbd{define Brent's method \& minimization bracketing} 1882 2359 \pagebreak 1883 2360 \section{Pan-STARRS Modules} 1884 2361 … … 2225 2702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2226 2703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2704 2705 \section{Missing and Todo} 2706 2707 \tbd{define sunrise, sunset, sun position} 2708 2709 \tbd{define moonrise, moonset, moon position, moon phase} 2710 2711 \tbd{define planet functions} 2712 2713 \tbd{clean up FITS I/O issues} 2714 2715 \tbd{define Brent's method \& minimization bracketing} 2716 2227 2717 \appendix 2228 2718 \section{Change Log} … … 2230 2720 2231 2721 \end{document} 2232 2233 2234 \section{Modules}2235 2236 \subsection{Image Processing Modules}2237 \subsubsection{debias}2238 \subsubsection{mask}2239 \subsubsection{trim}2240 \subsubsection{flatten}2241 \subsubsection{sky/fringe subtract}2242 \subsubsection{warp}2243 \subsubsection{stack}2244 \subsubsection{difference}2245 \subsubsection{kernel convolution}2246 \subsubsection{special stack}2247 2248 \subsection{Object Detection Modules}2249 \subsubsection{find peaks}2250 \subsubsection{background }2251 \subsubsection{aperture photometry}2252 \subsubsection{get shape}2253 2254 \subsection{Miscellaneous Modules}2255 2256 \section{Analysis Stages}2257 \subsection{Phase 1}2258 \subsection{Phase 2}2259 \subsection{Phase 3}2260 \subsection{Phase 4}2261 \subsection{Cal 1}2262 \subsection{Cal 2}2263 \subsection{Cal 3}2264 \subsection{Astrom Ref}2265 \subsection{Photom Ref}2266 2267 \section{Architectual Components}2268 -
trunk/doc/pslib/psLibSDRS.tex
r3537 r3564 1 %%% $Id: psLibSDRS.tex,v 1.19 1 2005-03-29 03:42:21 price Exp $1 %%% $Id: psLibSDRS.tex,v 1.192 2005-03-30 21:14:48 eugene Exp $ 2 2 \documentclass[panstarrs,spec]{panstarrs} 3 3 … … 11 11 \project{Pan-STARRS Image Processing Pipeline} 12 12 \organization{Institute for Astronomy} 13 \version{1 2}13 \version{13} 14 14 \docnumber{PSDC-430-007} 15 15 16 % \setcounter{tocdepth}{5} % lowest level to be included in toc 16 17 \setlength{\topsep}{-2pt} 17 18 … … 137 138 \href{heasarc.gsfc.nasa.gov/docs/software/fitsio}{\tt heasarc.gsfc.nasa.gov/docs/software/fitsio} 138 139 139 \item \tbd{SLALIB support is likely to be dropped} Many of the 140 astronomy routines will wrap the StarLink Positional Astronomy 141 libraries (SLALib): 140 \item the StarLink Positional Astronomy libraries (SLALib) are a 141 useful reference: 142 142 143 143 \href{star-www.rl.ac.uk/star/docs/sun67.htx/sun67.html}{\tt … … 183 183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 184 184 185 \pagebreak 185 186 \section{System Utilities} 186 187 … … 1193 1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1194 1195 1196 \pagebreak 1195 1197 \section{Basic Data Types and Collections} 1196 1198 … … 1894 1896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1895 1897 1898 \pagebreak 1896 1899 \section{Data manipulation} 1897 1900 … … 3028 3031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3029 3032 3033 \subsection{Image Pixel Lists} 3034 3035 Usually an image mask is the best way to carry information about what 3036 pixels mean what. However, in the case where the number of pixels in 3037 which we are interested is limited, it is more efficient to simply 3038 carry a list of pixels. An example of this is in the image 3039 combination code, where we want to perform an operation on a 3040 relatively small fraction of pixels, and it is inefficient to go 3041 through an entire mask image checking each pixel. 3042 3043 \begin{verbatim} 3044 typedef struct { 3045 psVector *x; // x coordinate 3046 psVector *y; // y coordinate 3047 } psPixels; 3048 \end{verbatim} 3049 3050 Of course, the size of each of the vectors should match. In the event 3051 that they do not match, any function which detects the problem shall 3052 generate a warning and use the size of the shorter of the vectors as 3053 the size. The order in which the pixels are kept is not considered 3054 important. 3055 3056 \begin{verbatim} 3057 psImage *psPixelsToMask(psImage *out, const psPixels *pixels, const psRegion *region, unsigned int maskVal); 3058 psPixels *psMaskToPixels(psPixels *out, const psImage *mask, unsigned int maskVal); 3059 \end{verbatim} 3060 3061 \code{psPixelsToMask} shall return an image of type U8 with the 3062 \code{pixels} lying within the specified \code{region} set to the 3063 \code{maskVal}. The \code{out} image shall be modified if supplied, 3064 or allocated and returned if \code{NULL}. The size of the output 3065 image shall be \code{region->x1 - region->x0} by \code{region->y1 - 3066 region->y0}, with \code{out->x0 = region->x0} and \code{out->y0 = 3067 region->y0}. In the event that either of \code{pixels} or 3068 \code{region} are \code{NULL}, the function shall generate an error 3069 and return \code{NULL}. 3070 3071 \code{psMaskToPixels} shall return a \code{psPixels} consisting of the 3072 coordinates in the \code{mask} that match the \code{maskVal}. The 3073 \code{out} pixel list shall be modified if supplied, or allocated and 3074 returned if \code{NULL}. In hte event that \code{mask} is 3075 \code{NULL}, the function shall generate an error and return 3076 \code{NULL}. 3077 3078 \begin{verbatim} 3079 psPixels *psPixelsConcatenate(psPixels *out, const psPixels *pixels); 3080 \end{verbatim} 3081 3082 \code{psPixelsConcatenate} shall concatenate \code{pixels} onto 3083 \code{out}. In the event that \code{out} is \code{NULL}, a new 3084 \code{psPixels} shall be allocated, and the contents of \code{pixels} 3085 simply copied in. If \code{pixels} is \code{NULL}, the function shall 3086 generate an error and return \code{NULL}. The function shall take 3087 care to ensure that there are no duplicate pixels in \code{out} (since 3088 the order in which the pixels are stored is not important, the values 3089 may be sorted, allowing the use of a faster algorithm than a linear 3090 scan). 3091 3092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3093 3094 \subsection{Image Regions} 3095 3096 In many places, we need to refer to a rectangular area. We define a 3097 structure to represent a rectangle: 3098 \begin{verbatim} 3099 typedef struct { 3100 float x0; 3101 float x1; 3102 float y0; 3103 float y1; 3104 } psRegion; 3105 psRegion *psRegionAlloc (float x0, float x1, float y0, float y1); 3106 \end{verbatim} 3107 3108 \begin{verbatim} 3109 psRegion *psRegionFromString (char *region); 3110 \end{verbatim} 3111 This function converts the IRAF description of a region in the form 3112 \code{[x0:x1,y0:y1]}, used for header entries such as \code{BIASSEC}, 3113 into the corresponding \code{psRegion} structure. 3114 3030 3115 \subsection{Vector and Image Arithmetic} 3031 3116 \label{sec:arithmetic} … … 3443 3528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3444 3529 3530 \pagebreak 3531 \section{Rich Data Structures and I/O} 3532 3533 \subsection{Metadata} 3534 \label{sec:metadata} 3535 3536 \subsubsection{Conceptual Overview} 3537 3538 Within PSLib, we provide a data structure to carry metadata and 3539 mechanisms to manipulate the metadata. Metadata is a general concept 3540 that requires some discussion. In any data analysis task, the 3541 ensemble of all possible data may be divided into two or three 3542 classes: there is the specific data of interest, there is data which 3543 is related or critical but not the primary data of interest, and there 3544 is all of the other data which may or may not be interesting. For 3545 example, consider a simple 2D image obtained of a galaxy from a CCD 3546 camera on a telescope. If you want to study the galaxy, the specific 3547 data of interest is the collection of pixels. There are a variety of 3548 other pieces of data which are closely related and crucial to 3549 understanding the data in those pixels, such as the dimensions of the 3550 image, the coordinate system, the time of the image, the exposure 3551 time, and so forth. Other data may be known which may be less 3552 critical to understanding the image, but which may be interesting or 3553 desired at a later date. For example, the observer who took the 3554 image, the filter manufacturer, the humidity at the telescope, etc. 3555 3556 Formally, all of the related data which describe the principal data of 3557 interest are metadata. Note that which piece is the metadata and 3558 which is the data may depend on the context. If you are examining the 3559 pixels in an image, the coordinate and flux of an object may be part 3560 of the metadata. However, if you are analyzing a collection of 3561 objects extracted from an image, you may consider then pixel data 3562 simply part of the metadata associated with the list of objects. 3563 3564 There are various ways to handle metadata vs data within a programming 3565 environment. In C, it is convenient to use structures to group 3566 associated data together. One possibility is to define the metadata 3567 as part of the associated data structure. For example, the image data 3568 structure would have elements for all possible associated measurement. 3569 This approach is both cumbersome (because of the large number metadata 3570 types), impractical (because the full range of necessary metadata is 3571 difficult to know in advance) and inflexible (because any change in 3572 the collection of metadata requires addition of new structure elements 3573 and recompilation). 3574 3575 An alternative is to place the metadata in a generic container and use 3576 lookup mechanisms to extract the appropriate metadata when needed. An 3577 example of this is would be a text-based FITS header for an image read 3578 into a flat text buffer. In this implementation, metadata lookup 3579 functions could return the current value of, for example, NAXIS1 (the 3580 number of columns of the image) by scanning through the header buffer. 3581 This method has the benefits of flexibility and simplicity of 3582 programming interface, but it has the disadvantage that all metadata 3583 is accessed though this lookup mechanism. This may make the code less 3584 readable and it may slow down the access. 3585 3586 PSLib implements an intermediate solution to this problem. We specify 3587 a flexible, generic metadata container and access methods. Data types 3588 which require association with a general collection of metadata should 3589 include an entry of this metadata type. However, a subset of metadata 3590 concepts which are basic and frequently required may be placed in the 3591 coded structure elements. This approach allows the code to refer to 3592 the basic metadata concepts as part of the data structure (ie, 3593 \code{image.nx}), but also allows us to provide access to any 3594 arbitrary metadata which may be generated. As a practical matter, the 3595 choice of which entries are only in the metadata and which are part of 3596 the explicit structure elements is rather subjective. Any data 3597 elements which are frequently used should be put in the structure; 3598 those which are only infrequently needed should be left in the generic 3599 metadata. 3600 3601 There are some points of caution which must be noted. Any 3602 manipulation of the data should be reflected in the metadata where 3603 appropriate. This is always an issue of concern. For example, 3604 consider an image of dimensions \code{nx, ny}. If a function extracts 3605 a subraster, it must change the values of \code{nx, ny} to match the 3606 new dimensions. What should it do to the corresponding metadata? 3607 Clearly, it should change the corresponding value which defines 3608 \code{nX, nY}. However, it is not quite so simple: there may be other 3609 metadata values which depend on those values. These must also be 3610 changed appropriately. What if the metadata element points to a 3611 copy of the metadata which may be shared by other representations of 3612 the image? These must be treated differently because the change would 3613 invalidate those other references. Care must be taken, therefore, 3614 when writing functions which operate on the data to consider all of 3615 the relevant metadata entries which must also be updated. 3616 3617 A related issue is the definition of metadata names. Entries in a 3618 structure have the advantage of being hardwired: every instance of 3619 that structure will have the same name for the same entry. This is 3620 not necessarily the case with a more flexible metadata container. The 3621 image exposure time is a notorious example in astronomy. Different 3622 observatories use different header keywords (ie, metadata names) for 3623 the same concept of the exposure time (\code{EXPTIME}, 3624 \code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc). Any system 3625 which operates on these metadata needs to address the issue of 3626 identifying these names. This issue seems like an argument for 3627 hardwiring metadata in the structure, but in fact it does not present 3628 such a strong case. If the metadata are hardwired, some function will 3629 still have to know how to interpret the various names to populate the 3630 structure. The concept can still be localized with generic metadata 3631 containers by including abstract metadata names within the code which 3632 are tied to the various implementations-specific metadata names. 3633 3634 \subsubsection{Metadata Representation} 3635 3636 \begin{figure} 3637 \psfig{file=Metadata,width=6.5in} 3638 \caption{Metadata Structures\label{fig:metadata}} 3639 \end{figure} 3640 3641 This section addresses the question of how \PS{} metadata should be 3642 represented in memory, not how it should be represented on disk. 3643 3644 We define an item of metadata with the following structure: 3645 \filbreak 3646 \begin{verbatim} 3647 typedef struct { 3648 int id; ///< unique ID for this item 3649 char *name; ///< Name of item 3650 psMetadataType type; ///< type of this item 3651 psElemType ptype; ///< primitive data type 3652 const union { 3653 psS32 S32; ///< integer data 3654 psF32 F32; ///< floating-point data 3655 psF64 F64; ///< double-precision data 3656 void *V; ///< other type 3657 psList *list; ///< psList entry 3658 psMetadata *md; ///< psMetadata entry 3659 } data; ///< value of metadata 3660 char *comment; ///< optional comment ("", not NULL) 3661 } psMetadataItem; 3662 \end{verbatim} 3663 3664 The \code{id} is a unique identifier for this item of metadata; 3665 experience shows that such tags are useful. The entry \code{name} 3666 specifies the name of the metadata item. The value of the metadata is 3667 given by the union \code{data}, and may be of type \code{psS32}, 3668 \code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at 3669 by the \code{void} pointer \code{V}. A character string comment 3670 associated with this metadata item may be stored in the element 3671 \code{comment}. The \code{type} entry specifies how to interpret the 3672 type of the data being represented, given by the enumerated type 3673 \code{psMetadataType}: 3674 % 3675 \filbreak 3676 \begin{verbatim} 3677 typedef enum { ///< type of item.data is: 3678 PS_META_PRIMITIVE, ///< primitive type: use item.ptype 3679 PS_META_LIST, ///< psList; use item.data.list (used for non-unique data) 3680 PS_META_META, ///< psMetadata: use item.data.list 3681 PS_META_STR, ///< string (item.data.V) 3682 PS_META_MATH, ///< psScalar, psVector, psImage (item.data.V) 3683 PS_META_JPEG, ///< JPEG (item.data) 3684 PS_META_PNG, ///< PNG (item.data) 3685 PS_META_ASTROM, ///< astrometric coefficients (item.data) 3686 PS_META_UNKNOWN, ///< other (item.data) 3687 PS_META_NTYPE ///< Number of types; must be last 3688 } psMetadataType; 3689 \end{verbatim} 3690 If the data is a PSLib primitive data value, the primitive data type 3691 is given by the value of \code{ptype}. 3692 3693 A collection of metadata is represented by the \code{psMetadata} structure: 3694 \begin{verbatim} 3695 typedef struct { 3696 psList *list; ///< list of psMetadataItem 3697 psHash *table; ///< hash table of the same metadata 3698 } psMetadata; 3699 \end{verbatim} 3700 The type \code{psMetadata} is a container class for metadata. Note 3701 that there are in fact \emph{two} representations of the metadata 3702 (each \code{psMetadataItem} appears on both). The first 3703 representation employs a doubly-linked list that allows the order of 3704 the metadata to be preserved (e.g., if FITS headers are read in a 3705 particular order, they should be written in the same order). The 3706 second representation employs a hash table which allows fast look-up 3707 given a specific metadata keyword. 3708 3709 Certain metadata names (such as the FITS keywords \code{COMMENT} and 3710 \code{HISTORY} in a FITS header) may be repeated with different 3711 values. In such a case, the \code{psMetadata.list} structure contains 3712 the entries in their original sequence with duplicate keys. The 3713 \code{psMetadata.hash} entries, which are required to have unique 3714 keys, would have a single entry with the keyword of the repeated key, 3715 with the value of \code{psMetadataType} set to \code{PS_META_LIST}, 3716 and the \code{psMetadataItem.data} element pointing to a \code{psList} 3717 containing the actual entries. If \code{psMetadataItemAlloc} is 3718 called with the type set to \code{PS_META_LIST}, such a repeated key 3719 is created. If the data value passed to \code{psMetadataItemAlloc} 3720 (the quantity in ellipsis) is \code{NULL}, then an empty 3721 \code{psMetadataItem} with the given keyword is created to hold future 3722 entries of that keyword. 3723 3724 The \code{psMetadataAdd} routine is required to check that all 3725 metadata names are unique unless the type is already qualified as 3726 \code{PS_META_LIST}; in this case the data are added to the 3727 corresponding \code{psMetadataItem.data} list. 3728 3729 \subsubsection{Metadata APIs} 3730 3731 The allocator for \code{psMetadataItem} returns a full 3732 \code{psMetadataItem} ready for insertion into the \code{psMetadata}. 3733 The \code{name} entry specifies the name to use for this metadata 3734 item, and may include \code{sprintf}-type formating codes. The 3735 \code{comment} entry is a fixed string which is used for the comment 3736 associated with this metadata item. The metadata data and the 3737 arguments to the \code{name} formatting codes are passed, in that 3738 order (metadata pointer first), to \code{psMetadataItemAlloc} as 3739 arguments following the comment string. The data must be a pointer 3740 for any data types which are stored in the element \code{data.void}, 3741 while other data types are passed as numeric values. The argument 3742 list must be interpreted appropriately by the \code{va_list} operators 3743 in the function. 3744 \begin{verbatim} 3745 psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...); 3746 psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list); 3747 \end{verbatim} 3748 3749 The constructor for the collection of metadata, \code{psMetadata}, 3750 simply returns an empty metadata container (employing the constructors 3751 for the doubly-linked list and hash table). The destructor needs to 3752 free each of the \code{psMetadataItem}s using \code{psMetadataItemFree}. 3753 \begin{verbatim} 3754 psMetadata *psMetadataAlloc(void); 3755 \end{verbatim} 3756 3757 Items may be added to the metadata in one of two ways --- firstly, an 3758 item may be added by appending a \code{psMetadataItem} which has 3759 already been created; and secondly by directly providing the data to 3760 be appended. In both cases, the return value defines the success 3761 (\code{true}) or failure of the operation. The second function, 3762 \code{psMetadataAdd} takes a pointer or value which is interpreted by 3763 the function using variadic argument interpretation. The third 3764 version is the \code{va_list} version of the second function. All 3765 three functions take a parameter, \code{location}, which specifies 3766 where in the list to place the element, following the conventions for 3767 the \code{psList}. The entry \code{mode} for \code{psMetadataAddItem} 3768 is a bit mask constructed by OR-ing the allowed option flags (eg, 3769 \code{PS_META_REPLACE}) which specifies minor variations on the 3770 behavior. The \code{format} entry, which specifies both the metadata 3771 type and the optional flags, is constructed by bit-wise OR-ing the 3772 appropriate \code{psMetadataType} and allowed option option flags. 3773 Care should be taken not to leak memory when appending an item for 3774 which the key already exists in the metadata (and is not 3775 \code{PS_META_LIST}). 3776 % 3777 \begin{verbatim} 3778 bool psMetadataAddItem(psMetadata *md, psMetadataItem *item, int location, int mode); 3779 bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...); 3780 bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment, 3781 va_list list); 3782 \end{verbatim} 3783 3784 The functions above take option flags which modify the behavior when 3785 metadata items are added to the metadata list. These flags must be 3786 bit-exclusive of those used above for the \code{psMetadataTypes}. The 3787 flags have the following meanings: 3788 3789 \code{PS_META_DEFAULT}: This is the zero bit mask, to allow the 3790 default behavior for \code{psMetadataAddItem} above. If this is OR-ed 3791 with a \code{psMetadataType}, the result is as if no OR-ing took 3792 place. 3793 3794 \code{PS_META_REPLACE}: If the given metadata item exists in the 3795 metadata list, and is not of type \code{PS_META_LIST} or 3796 \code{PS_META_META} (ie, not a container type), then this entry is 3797 allowed to replace the existing entry. If this mode bit is not set, a 3798 duplicate (non-container-type) entry is an error. 3799 3800 \begin{verbatim} 3801 typedef enum { ///< option flags for psMetadata functions 3802 PS_META_DEFAULT, ///< default behavior (0x0000) for use in mode above 3803 PS_META_REPLACE, ///< allow entry to be replaced 3804 } psMetadataFlags; 3805 \end{verbatim} 3806 3807 An example of code to use these metadata APIs to generate the 3808 structure seen in Figure~\ref{fig:metadata} is given below. 3809 3810 \begin{verbatim} 3811 md = psMetadataAlloc(); 3812 3813 psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE", PS_META_BOOL, "basic fits", TRUE); 3814 psMetadataAdd(md, PS_LIST_TAIL, "BLANK", PS_META_S32, "invalid pixel data", -32768); 3815 psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR, "observing date UT", " 2004-6-16"); 3816 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_LIST, "head of comment block", NULL); 3817 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "DATA"); 3818 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "PARAMS"); 3819 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32, "exposure time (sec)", 1.05); 3820 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "FOO"); 3821 3822 cell = psMetadataAlloc(); 3823 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD00"); 3824 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-00"); 3825 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.00"); 3826 psMetadataAdd(md, PS_LIST_TAIL, "CELL.00", PS_META_META, "", cell); 3827 3828 cell = psMetadataAlloc(); 3829 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD01"); 3830 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-01"); 3831 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.01"); 3832 psMetadataAdd(md, PS_LIST_TAIL, "CELL.01", PS_META_META, "", cell); 3833 \end{verbatim} 3834 3835 The following code shows how to use the APIs to replace one of these values: 3836 \begin{verbatim} 3837 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32 | PS_REPLACE, "new exposure time (sec)", 2.05); 3838 \end{verbatim} 3839 3840 Items may be removed from the metadata by specifying a key or a 3841 location in the list. If the value of \code{name} is \code{NULL}, the 3842 value of \code{location} is used. If the value of \code{name} is not 3843 \code{NULL}, then \code{location} must be set to 3844 \code{PS_LIST_UNKNOWN}. If the key matches a metadata item, the item 3845 is removed from the metadata and \code{true} is returned; otherwise, 3846 \code{false} is returned. If the key is not unique, then \emph{all} 3847 items corresponding to the key are removed, and \code{true} is 3848 returned. 3849 % 3850 \begin{verbatim} 3851 bool psMetadataRemove(psMetadata *md, int location, const char *key); 3852 \end{verbatim} 3853 3854 Items may be found within the metadata by providing a key. In the 3855 event that the key is non-unique, the first item is returned. 3856 \begin{verbatim} 3857 psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key); 3858 \end{verbatim} 3859 3860 Several utility functions are provided for simple cases. These 3861 functions perform the effort of casting the data to the appropriate 3862 type. The numerical functions shall return 0.0 if their key is not 3863 found. If the pointer value of \code{status} is not \code{NULL}, it 3864 is set to reflect the success or failure of the lookup. 3865 \begin{verbatim} 3866 void *psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key); 3867 psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key); 3868 psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key); 3869 \end{verbatim} 3870 3871 Items may be retrieved from the metadata by their entry position. The 3872 value of which specifies the desired entry in the fashion of 3873 \code{psList}. 3874 \begin{verbatim} 3875 psMetadataItem *psMetadataGet(const psMetadata *md, int location); 3876 \end{verbatim} 3877 3878 The metadata list component may be iterated over by using a 3879 \code{psListIterator} in a fashion equivalent to the usage for 3880 \code{psList}. The iterator may be set to a location in the 3881 \code{psMetadata} list, and the user may get the previous or next item 3882 in the list relative to that location. \code{psMetadataGetNext} has 3883 the ability to match the key using a POSIX regex, e.g., if the user 3884 only wants to iterate through \code{IPP.machines.sky} and doesn't want 3885 to bother with \code{IPP.machines.detector}. The iterator should 3886 iterate over every item in the metadata list, even those that are 3887 contained in a \code{PS_META_LIST}. The value \code{iterator} 3888 specifies the iterator to be used. In setting the iterator, the 3889 position of the iterator is defined by \code{location}, which follows 3890 the conventions of the \code{psList} iterators. 3891 \begin{verbatim} 3892 psListIterator *psMetadataIteratorAlloc(psMetadata *md, int location, bool mutable); 3893 bool psMetadataIteratorSet(psListIterator *iterator, int location); 3894 psMetadataItem *psMetadataGetAndIncrement(psListIterator *iterator, const char *regex); 3895 psMetadataItem *psMetadataGetAndDecrement(psListIterator *iterator, const char *regex); 3896 \end{verbatim} 3897 3898 Metadata items may be printed to an open file descriptor based on a 3899 provided format. The format string is an sprintf format statement 3900 with exactly one \% formatting command. If the metadata item type is 3901 a numeric type, this formatting command must also be numeric, and type 3902 conversion performed to the value to match the format type. If the 3903 metadata item type is a string, the formatting command must also be 3904 for a string (\%s type of command). If the metadata type is any other 3905 data type, printing is not allowed. 3906 \begin{verbatim} 3907 bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *md); 3908 \end{verbatim} 3909 3910 \subsubsection{Configuration files} 3911 \label{sec:configspec} 3912 3913 It will be necessary for the \PS{} system, in order to load 3914 pre-defined settings, to parse a configuration file into a 3915 \code{psMetadata} structure. This shall be performed by the 3916 function \code{psMetadataParseConfig}, as described below. 3917 3918 \begin{verbatim} 3919 psMetadata *psMetadataParseConfig(psMetadata *md, int *nFail, const char *filename, bool overwrite); 3920 \end{verbatim} 3921 3922 Given a metadata container, \code{md}, and the name of a configuration 3923 file, \code{filename}, \code{psMetadataParseConfig} shall parse the 3924 configuration file, placing the contained key/type/value/comment quads 3925 into the metadata, and returning a pointer to the metadata structure. 3926 The number of lines that failed to parse is returned in \code{nFail}. 3927 Multiple specifications of a key that haven't been declared (see 3928 below) are overwritten if and only if \code{overwrite} is \code{true}. 3929 If the metadata container is \code{NULL}, it shall be allocated. 3930 3931 On error, the function shall return \code{NULL}. 3932 3933 The configuration file shall consist of plain text with 3934 key/type/value/comment quads on separate lines. Blank lines, 3935 including those consisting solely of whitespace (both spaces and 3936 tabs), shall be ignored, as shall lines that commence with the comment 3937 character (a hash mark, \code{#}), either immediately at the start of 3938 the line, or preceded by whitespace. The key/type/value/comment quads 3939 shall all lie on a single line, separated by whitespace. 3940 3941 The key shall be first, possibly preceded on the line by whitespace 3942 which should not form part of the key. 3943 3944 Next, to assist the casting of the value, shall be a string 3945 identifying the type of the value, which shall correspond to one of 3946 the simple types supported in \code{psMetadata}: 3947 \code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to abbreviate 3948 \code{STRING}. 3949 3950 \tbd{May, in the future, require more types, including U8,S16,C64, 3951 which will also necessitate updating the definition of psMetadata.} 3952 3953 The value shall follow the type: strings may consist of multiple 3954 words, and shall have all leading and trailing whitespace removed; 3955 booleans shall simply be either \code{T} or \code{F}. 3956 3957 Following the value may be an optional comment, preceded by a comment 3958 character (a hash mark, \code{#}), which in the case of a string 3959 value, serves to mark the end of the value, and for other types serves 3960 to identify the comment to the reader. Only one comment character may 3961 be present on any single line (i.e., neither strings nor comments are 3962 permitted to contain the comment character). The comment may consist 3963 of multiple words, and shall have leading and trailing whitespace 3964 removed. 3965 3966 One wrinkle is the specification of vectors. Keys for which the value 3967 is to be parsed as a vector shall be preceded immediately by a 3968 ``vector symbol'', which we choose to be the ``at'' sign, \code{@}. 3969 In this case, the type shall be interpreted as the type for the 3970 vector, which may be any of the signed or unsigned integer or floating 3971 point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not 3972 the complex floating point types; and the value shall consist of 3973 multiple numbers, separated either by a comma or whitespace. These 3974 values shall populate a \code{psVector} of the appropriate type in the 3975 order in which they appear in the configuration file. 3976 3977 \tbd{May add complex types, likely to be specified with values such as 3978 1.23+4.56i in the future.} 3979 3980 An additional hurdle is the specification of keys that may be 3981 non-unique (such as the \code{COMMENT} keyword in a FITS header). 3982 These keys shall be specified in the configuration file as non-unique 3983 by specifying the key at the start of the line (possibly preceded by 3984 whitespace) and specifying the type as a ``multiple symbol'', which we 3985 choose to be an asterisk, \code{*}. No other data may be provided on 3986 this line, though a comment, preceeded by the comment marker, is 3987 valid. A warning shall be produced when a key which has not been 3988 specified to be non-unique is repeated; in this case, the former value 3989 shall be overwritten if \code{overwrite} is \code{true}, otherwise the 3990 line shall be ignored and counted as one that could not be parsed. 3991 3992 If a line does not conform to the rules laid out here, a warning shall 3993 be generated, it shall be ignored and counted as a line that could not 3994 be parsed. The total number of lines that were not able to be parsed 3995 (including those that were ignored because \code{overwrite} is 3996 \code{false}, and any other parsing problems, but not including blank 3997 lines and comment lines) shall be returned by the function in the 3998 argument \code{nFail}. 3999 4000 Here are some examples of lines of a valid configuration file: 4001 \filbreak 4002 \begin{verbatim} 4003 Double F64 1.23456789 # This is a comment 4004 Float F32 0.98765 # This is a comment too 4005 String STR This is the string that forms the value #comment 4006 4007 # This is a comment line and is to be ignored 4008 boolean BOOL T # The value of `boolean' is `true' 4009 4010 @primes U8 2,3 5 7,11,13 17 # These are prime numbers 4011 4012 comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique 4013 comment STR This 4014 comment STR is 4015 comment STR a 4016 comment STR non-unique 4017 comment STR key 4018 Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored 4019 \end{verbatim} 4020 4021 Of course, a real configuration file should look much nicer to humans 4022 than the above example, but PSLib must be able to parse such ugly 4023 files. 4024 4025 We extend \code{psMetadataParseConfig} to allow a modest tree 4026 structure by defining a reserved keyword \code{TYPE}. Any line in the 4027 config file which starts with the word \code{TYPE} shall be 4028 interpretted as defining a new valid type. The defined type name 4029 follows the word \code{TYPE}, and is in turn followed by an arbitrary 4030 number of words. These words are to be interpreted as the names of an 4031 embedded \code{psMetadata} entry, where the values are given on any 4032 line which (following the \code{TYPE} definition) employs the new type 4033 name. For example, a new type may be defined as: 4034 \begin{verbatim} 4035 TYPE CELL EXTNAME BIASSEC CHIP 4036 CELL.00 CELL CCD00 BSEC-00 CHIP.00 4037 CELL.01 CELL CCD01 BSEC-01 CHIP.00 4038 \end{verbatim} 4039 4040 When \code{psMetadataParseConfig} encounters the \code{TYPE} line, it 4041 should construct a \code{psMetadata} container and fill it with 4042 \code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP}, 4043 with type \code{PS_META_STR}, but data allocated. When it next 4044 encounters an entry of type \code{CELL}, it should then use the given 4045 name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy 4046 the \code{psMetadata} data onto the \code{psMetadataItem.data.md} 4047 entry, filling in the values from the rest of the line (\code{CCD00, 4048 BSEC-00, CHIP.00}). This hierarchical structure is illustrated in 4049 Figure~\ref{fig:metadata}. 4050 4051 We further extend \code{psMetadataParseConfig} to allow the definition 4052 of a \code{psMetadata} entry using a sequence of successive lines to 4053 define the values of the \code{psMetadataItem} entries. The initial 4054 line defines the new \code{psMetadata} entry and its name. The 4055 following lines have the same format as the other metadata config file 4056 entries. The sequence is terminated with a line with a single word 4057 \code{END}. For example, a metadata entry may be defined as: 4058 \begin{verbatim} 4059 CELL METADATA 4060 EXTNAME STR CCD00 4061 BIASSEC STR BSEC-00 4062 CHIP STR CHIP.00 4063 NCELL S32 24 4064 END 4065 \end{verbatim} 4066 4067 A series of test inputs is contained in 4068 \S\ref{sec:configtest}. 4069 4070 \subsection{XML Functions} 4071 4072 Within Pan-STARRS, we will use XML documents as a transport mechanism 4073 to carry data between programs and between IPP and other subsystems. 4074 Configuration information may be stored as well as XML documents, in 4075 addition to the text format discussed in the discussion on Metadata. 4076 XML is an extremely variable document format, and it is not currently 4077 the intention of PSLib to provide a complete PSLib version of XML 4078 operations. Rather, a limited number of operations are defined to 4079 convert specific data structures to an appropriate XML document. To 4080 maximize the simplicity of the XML APIs, we will use the convention 4081 that a single XML document to be parsed by PSLib shall contain only a 4082 single data structure. Each of the XML APIs therefore take as input a 4083 reference to a complete XML document and return a PSLib data 4084 structure, or take a PSLib data structure and return a complete XML 4085 document. 4086 4087 We start by defining a PSLib wrapper type which is a pointer to an XML 4088 document in memory. We wrap the \code{libxml2} version of an XML 4089 document pointer for now: 4090 \begin{verbatim} 4091 typedef xmlDocPtr psXMLDoc; 4092 void psXMLDocFree(psXMLDoc *doc); 4093 \end{verbatim} 4094 4095 The next pair of functions convert a \code{psMetadata} data structure 4096 to a complete \code{psXMLDoc} (in memory) and vice versa: 4097 \begin{verbatim} 4098 psXMLDoc *psMetadataToXMLDoc(const psMetadata *metadata); 4099 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc); 4100 \end{verbatim} 4101 4102 The next pair of functions loads the data in a named file into a 4103 complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc} 4104 to a named file: 4105 \begin{verbatim} 4106 psXMLDoc *psXMLParseFile(const char *filename); 4107 int psXMLDocToFile(const psXMLDoc *doc, const char *filename); 4108 \end{verbatim} 4109 4110 The next pair of functions accepts a block of memory and parses it 4111 into a complete \code{psXMLDoc} (also in memory), and vice versa: 4112 \begin{verbatim} 4113 psXMLDoc *psXMLParseMemory(const char *buffer, const int size); 4114 int psXMLDocToMemory(const psXMLDoc *doc, char *buffer); 4115 \end{verbatim} 4116 4117 The next pair of functions read from and write to a file descriptor. 4118 The first converts the imcoming data to a complete \code{psXMLDoc} 4119 (also in memory), the second writes the \code{psXMLDoc} to the file 4120 descriptor: 4121 \begin{verbatim} 4122 psXMLDoc *psXMLParseFD(int fd); 4123 int psXMLDocToFD(const psXMLDoc *doc, int fd); 4124 \end{verbatim} 4125 4126 \subsection{Database Functions} 4127 4128 Many of the applications that PSLib will be used for will require 4129 access to a simple relational database. PSLib includes generic 4130 database-independent interface mechanisms as part of its API set. The 4131 most important aspect of PSLib's database support is to abstract as 4132 much database specific complexity as is feasible. As almost all RDBMS 4133 provide at least a simple transactional model, commit and rollback 4134 support should be provided. 4135 4136 Currently, only support for MySQL 4.1.x is required but other backends 4137 may be added as options in the future. As a particular example which 4138 has implications for the database interaction model, support for 4139 SQLite may be required in the future. Currently, the choice of 4140 backend database interface may be made as a compile option. Details 4141 of the specified APIs in the discussion below refer to the relevant 4142 MySQL functions. 4143 4144 Database errors must be trapped and placed onto the psError stack. 4145 The complete error message should be retrieved with the database's 4146 error function. 4147 4148 \subsubsection{Managing the Database Connection} 4149 4150 We specify a database handle which carries the information about the 4151 database connection: 4152 4153 \begin{verbatim} 4154 typedef struct { 4155 MYSQL *mysql; 4156 } psDB; 4157 \end{verbatim} 4158 4159 The following collection of functions provides basic database functionality: 4160 4161 \begin{verbatim} 4162 // wraps mysql_init() & mysql_real_connect() 4163 psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname); 4164 4165 // wraps mysql_close() 4166 void psDBCleanup(psDB *dbh); 4167 4168 // wraps mysql_create_db() 4169 bool psDBCreate(psDB *dbh, const char *dbname); 4170 4171 // wraps mysql_select_db() 4172 bool psDBChange(psDB *dbh, const char *dbname); 4173 4174 // wraps mysql_drop_db() 4175 bool psDBDrop(psDB *dbh, const char *dbname); 4176 \end{verbatim} 4177 4178 For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and 4179 \code{mysql_real_connect()} in order to initialize a psDB structure and 4180 establish a database connection. A null pointer should be returned on 4181 failure. 4182 4183 When implementing support for SQLite, or other DB which is purely 4184 file-based, the \code{host}, \code{user}, and \code{passwd} arguments 4185 would be ignored while \code{dbname} would specify the path to the 4186 SQLite db file. 4187 4188 \subsubsection{Interacting with Database Tables} 4189 4190 The functions in this section perform high level interactions with the 4191 database tables. All of them should behave ``atomically'' with 4192 respect to the state of the database. Specifically, all interactions 4193 with the database should be done as a part of a transaction that is 4194 rolled-back on failure and committed only after all queries used by 4195 the API have been run. In general, this API set attempts to treat a 4196 database table as a 2D matrix where columns can be represented by a 4197 \code{psVector} and rows as a \code{psMetadata} type. A 4198 \code{psMetadata} collection is also used to define the columns of a 4199 table and as part of the query restrictions. 4200 4201 \begin{verbatim} 4202 bool psDBCreateTable(psDB *dbh, const char *tableName, psMetadata *md); 4203 \end{verbatim} 4204 4205 This function generates and executes the SQL needed to create a table 4206 named \code{tableName}, with the column names and datatypes as 4207 described in \code{md}. Each data item in the \code{psMetadata} 4208 collection represents a single table field. The name of the field is 4209 given by the name of the \code{psMetadataItem} and the data type is 4210 give by the \code{psMetadataItem.type} and \code{psMetadataItem.ptype} 4211 entries. A lookup table should be used to convert from PSLib types 4212 into MySQL compatible SQL data types. For example, a 4213 \code{PS_META_STR} would map to an SQL99 varchar. If the value of 4214 \code{type} is \code{PS_META_STR} then the \code{psMetadataItem.data} 4215 element is set to a string with the length for the field written as a 4216 text string. The value of the \code{psMetadataItem.data} element is 4217 unused for the \code{PS_META_PRIMITIVE} types. Other metadata types 4218 beyond \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed 4219 in a table definition metadata collection. 4220 4221 Database indexes can be specified setting the \code{comment} field to 4222 ``\code{Primary Key}'' or ``\code{Key}''. Comment are otherwise 4223 ignored. 4224 4225 \begin{verbatim} 4226 bool psDBDropTable(psDB *dbh, const char *tableName); 4227 \end{verbatim} 4228 4229 This function deletes the specified table. 4230 4231 \begin{verbatim} 4232 psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, const psU64 limit); 4233 psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType pType, const psU64 limit); 4234 \end{verbatim} 4235 4236 These functions generates and executes the SQL needed to select an entire 4237 column from a table or up to \code{limit} rows from it. If \code{limit} is 0, 4238 the entire range is returned. The database response is processed and a 4239 \code{psArray} of strings is returned. The Num version of the function returns 4240 the data in a \code{psVector}, data cast to \code{pType}. It returns an error 4241 (NULL) if the requested field is not a numerical type. 4242 4243 \begin{verbatim} 4244 psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, const psU64 limit); 4245 \end{verbatim} 4246 4247 This function returns rows from the specified table which match 4248 the restrictions given by \code{where}. The restrictions are 4249 specified as field / value pairs. The \code{psMetadata} collection 4250 where must consist of valid database fields, though the database query 4251 checking functions may be used to validate the fields as part of the 4252 query. If \code{where} is \code{NULL}, then there are no restrictions 4253 on the rows selected. The selected rows are returned as a 4254 \code{psArray} of \code{psMetadata} values, one per row. 4255 4256 \begin{verbatim} 4257 bool psDBInsertOneRow(psDB *dbh, const char *tableName, psMetadata *row); 4258 \end{verbatim} 4259 4260 Insert the data from \code{row} into \code{tableName}. It should be noted in 4261 the API reference that if fields are specified in \code{row} that do not exist 4262 in \code{tablename}, the insert will fail. 4263 4264 \begin{verbatim} 4265 bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet); 4266 \end{verbatim} 4267 4268 Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once 4269 and is atomic for the complete set of rows. 4270 4271 \begin{verbatim} 4272 psArray *psDBDumpRows(psDB *dbh, const char *tableName); 4273 \end{verbatim} 4274 4275 Fetch all rows as an psArray of psMetadata. 4276 4277 \begin{verbatim} 4278 psMetadata *psDBDumpCols(psDB *dbh, const char *tableName); 4279 \end{verbatim} 4280 4281 Fetch all columns, as either a psVector or a psArray depnding on whether or not 4282 the column is numeric, and return them in a psMetadata structure where 4283 psMetadataItem.name contains the column's name. 4284 4285 \begin{verbatim} 4286 psS64 psDBUpdateRows(psDB *dbh, const char *tableName, psMetadata *where, psMetadata *values); 4287 \end{verbatim} 4288 4289 Update the columns contained in \code{values} in the row(s) that have a field 4290 with the value indicated by \code{where} (note that this is only allows very 4291 limited use of SQL99's ``where'' semantics). The number of rows modified is 4292 returned. A negative value is return to indicate an error. If there are 4293 multiple psMetadataItems in \code{where} then each item should be considered as 4294 an additional constraint. e.g. ``where foo = x and where bar = y'' 4295 4296 \begin{verbatim} 4297 psS64 psDBDeleteRows(psDB *dbh, const char *tableName, psMetadata *where); 4298 \end{verbatim} 4299 4300 Delete the rows that are matched by \code{where} using the same semantics for 4301 \code{where} as in psDBUpdateRow(). A negative value is returned to indicate an 4302 error. 4303 4304 \subsection{FITS I/O Functions} 4305 4306 We need a variety of I/O functions between the disk and certain of our 4307 PSLib data structures. We need the ability to access FITS headers, 4308 images and tables (both ASCII and Binary). We define here the FITS 4309 I/O functions, all of which are currently specified as wrappers to 4310 functions within CFITSIO. CFITSIO provides a wide range of utilities 4311 which we do not feel are particularly appropriate as part of a generic 4312 I/O library, such as assumptions about names which change the data 4313 interpretation, etc. We are defining our calls to avoid the hidden 4314 'features'. The CFITSIO functions which are wrapped should in general 4315 be the most basic versions. 4316 4317 \begin{verbatim} 4318 typedef struct { 4319 fitsfile fd; 4320 } psFits; 4321 \end{verbatim} 4322 We begin by defining a datatype to wrap the CFITSIO \code{fitsfile} 4323 structure. This is necessary to allow repeated access to the data in 4324 a file without multiple open commands (which are expensive). 4325 4326 \subsubsection{FITS File Manipulations} 4327 4328 \begin{verbatim} 4329 psFits *psFitsAlloc(const char *filename); 4330 \end{verbatim} 4331 4332 Opens a FITS file at positions the pointer to the PHU. 4333 4334 \begin{verbatim} 4335 bool psFitsMoveExtName(psFits *fits, const char *extname); 4336 \end{verbatim} 4337 4338 Positions the pointer to the beginning of the specified 4339 \code{extname}. If the \code{extname} does not exist, the function 4340 shall fail. 4341 4342 \begin{verbatim} 4343 bool psFitsMoveExtNum(psFits* fits, int extnum, bool relative); 4344 \end{verbatim} 4345 4346 Moves the pointer to the beginning of the specified HDU number. If 4347 \code{relative} is TRUE, \code{extnum} represents the number of HDUs 4348 relative to the current HDU. The PHU is entry number 0, while the 4349 extended data segments start at number 1. 4350 4351 \begin{verbatim} 4352 int psFitsGetExtNum(psFits* fits); 4353 \end{verbatim} 4354 4355 Returns the current HDU number (i.e., file position). 4356 4357 \begin{verbatim} 4358 int psFitsGetSize(psFits* fits); 4359 \end{verbatim} 4360 4361 Returns the number of HDUs in the file. 4362 4363 \begin{verbatim} 4364 psFitsType psFitsGetExtType(psFits* fits); 4365 \end{verbatim} 4366 4367 Gets the current HDU's type (table or image). 4368 4369 \subsubsection{FITS Header I/O Functions} 4370 4371 \begin{verbatim} 4372 psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits); 4373 \end{verbatim} 4374 Read header data into a \code{psMetadata} structure. The data is read 4375 from the current HDU pointed at by the \code{psFits *fits} entry. If 4376 \code{out} is \code{NULL}, a new psMetadata is created. 4377 4378 \begin{verbatim} 4379 psMetadata *psFitsReadHeaderSet (psFits *fits); 4380 \end{verbatim} 4381 Load a complete set of headers from the \code{psFits} file pointer. 4382 This function loads the headers from all extensions into a 4383 \code{psMetadata} collection, each entry of which is a pointer to a 4384 \code{psMetadata} structure containing the header data. The metadata 4385 entry names are the \code{EXTNAME} values for each header (with the 4386 value of \code{PHU} for the primary header unit). At the start of the 4387 operation, the file pointer is rewound to the beginning of the file. 4388 At the end, it is positioned where it started when the function was 4389 called. 4390 4391 \begin{verbatim} 4392 bool psFitsWriteHeader(psMetadata *output, const psFits *fits); 4393 \end{verbatim} 4394 Write metadata into the header of a FITS image file. The header is 4395 written at the current HDU. 4396 4397 \subsubsection{FITS Image I/O Functions} 4398 4399 \begin{verbatim} 4400 psImage *psFitsReadImage(psImage *output, psFits *fits, psRegion region, int z); 4401 \end{verbatim} 4402 Read an image or subimage from the \code{psFits} file pointer. This 4403 function is a wrapper to the CFITSIO library function. The input 4404 parameters allow a full image or a subimage to be read. The region to 4405 be read is specified by \code{region}. A negative value for either of 4406 \code{region.x1} or \code{region.y1} specifies the size of the region 4407 to be read counting down from the end of the array. 4408 4409 If the native image is a cube, the value of z specifies the requested 4410 slice of the image. This function must call \code{psError} and return 4411 \code{NULL} if any of the specified parameters are out of range for 4412 the data in the image file, or if the image on disk is zero- or 4413 one-dimensional. This function need only read images of the native 4414 FITS image types (\code{psU8}, \code{psS16}, \code{psS32}, 4415 \code{psF32}, \code{psF64}). The user is expected to convert the data 4416 type as needed with \code{psImageCopy}. 4417 4418 \begin{verbatim} 4419 bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z); 4420 \end{verbatim} 4421 \tbd{we have discussed this as the alternate name} 4422 Write an image section to the open \code{psFits} file pointer. This 4423 operation may write a portion of an image over the existing bytes of 4424 an existing image. Care must be taken to interpret \code{region}, 4425 which specified the output pixels to be written / over-written. If 4426 the combination of \code{region} and the size of \code{psImage *input} 4427 implies writing pixels outside the existing data area of the image, 4428 the function shall return an error (ie, if \code{region.x0 + image.nx 4429 >= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >= 4430 NAXIS3}). This function will only write images of the native FITS 4431 image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, 4432 \code{psF64}). The user is expected to convert the data type as 4433 needed with \code{psImageCopy}. The return value must be 0 for a 4434 successful operation and 1 for an error. 4435 4436 \begin{verbatim} 4437 bool psFitsWriteImage(psFits *fits, psMetadata *header, const psImage *input, int depth); 4438 \end{verbatim} 4439 Create a new image based on the dimensions specified for the image and 4440 the requested depth. The header and image data segments are written 4441 in the file at the current position of the \code{psFits} pointer. 4442 This function will only write images of the native FITS image types 4443 (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}). 4444 The user is expected to convert the data type as needed with 4445 \code{psImageCopy}. The return value must be 0 for a successful 4446 operation and 1 for an error. 4447 4448 \subsubsection{FITS Table I/O Functions} 4449 4450 \begin{verbatim} 4451 psMetadata *psFitsReadTableRow (psFits *fits, int row); 4452 \end{verbatim} 4453 This function reads a single row of the table in the extension pointed 4454 at by the \code{psFits} file pointer. The row number to be read is 4455 given by \code{row}. The result is returned as a \code{psMetadata} 4456 collection with elements of the apporpriate types and keys 4457 corresponding to the table column names. The function must apply the 4458 needed byte-swapping on the data in the row based on the description 4459 of the table data in the table header. \tbr{we may need to be more 4460 flexible here: if we call this function repeatedly, it would be more 4461 efficient to pass the corresponding header or keep it somewhere (and 4462 the file pointer location, for that matter).} 4463 4464 \begin{verbatim} 4465 void *psFitsReadTableRowRaw (int *nBytes, psFits *fits, int row); 4466 \end{verbatim} 4467 This function reads a single row of the table in the extension pointed 4468 at by the \code{psFits} file pointer. The row number to be read is 4469 given by \code{row}. The result is returned as collection of 4470 \code{nBytes} bytes allocated by the function. The function must 4471 apply the needed byte-swapping on the data in the row based on the 4472 description of the table data in the table header. \tbr{we may need 4473 to be more flexible here: if we call this function repeatedly, it 4474 would be more efficient to pass the corresponding header or keep it 4475 somewhere (and the file pointer location, for that matter).} 4476 4477 \begin{verbatim} 4478 psArray *psFitsReadTableColumn (psFits *fits, char *colname); 4479 \end{verbatim} 4480 This function reads a single column of the table in the extension 4481 pointed at by the \code{psFits} file pointer. The column is specified 4482 by the FITS table column key given by \code{row}. The result is 4483 returned as a \code{psArray}, with the data from one row of the table 4484 column per array element. 4485 4486 \begin{verbatim} 4487 psVector *psFitsReadTableColumnNum (psFits *fits, char *colname); 4488 \end{verbatim} 4489 This function reads a single column of the table in the extension 4490 pointed at by the \code{psFits} file pointer. The column is specified 4491 by the FITS table column key given by \code{row} and must be of a 4492 numeric data type. The result is returned as a \code{psVector} of the 4493 appropriate data type, with the data from one row of the table column 4494 per array element. 4495 4496 \begin{verbatim} 4497 psArray *psFitsReadTableRaw (int *nBytes, psFits *fits); 4498 \end{verbatim} 4499 This function reads the entire data block from a table into the a 4500 \code{psArray}, with one element of the array per row. The number of 4501 bytes per row is returned in \code{nBytes}. The function must apply 4502 the needed byte-swapping on the data in each row based on the 4503 description of the table data in the table header. 4504 4505 \begin{verbatim} 4506 psArray *psFitsReadTable (psFits *fits); 4507 \end{verbatim} 4508 This function reads the entire data block from a table into the a 4509 \code{psArray}, with one element of the array per row. Each row is 4510 stored as a \code{psMetadata} collection as described above for 4511 \code{psFitsReadTableRow}. 4512 4513 \begin{verbatim} 4514 bool psFitsWriteTable(psFits* fits, psMetadata *header, psArray* table); 4515 \end{verbatim} 4516 Accepts a \code{psArray} of \code{psMetadata} and writes it to the 4517 current HDU. If the current HDU is not a table type, this will fail 4518 and return FALSE. 4519 4520 \begin{verbatim} 4521 bool psFitsUpdateTable(psFits* fits, psMetadata *header, psMetadata* data, int row); 4522 \end{verbatim} 4523 Writes the \code{psMetadata} data to a FITS table at the specified row 4524 in the current HDU. If the current HDU is not a table type, this will 4525 fail and return FALSE. 4526 4527 \pagebreak 3445 4528 \section{Astronomy-Specific Functions} 3446 4529 … … 3457 4540 \begin{itemize} 3458 4541 \item Dates and times 3459 \item Metadata3460 4542 \item Detector and sky positions 3461 \item Astronom y Image4543 \item Astronomical Image Containers 3462 4544 \item Astrometry 3463 4545 \item Photometry … … 3487 4569 3488 4570 typedef enum { 3489 PS_IERS_A, ///< IERS Bull iten A3490 PS_IERS_B, ///< IERS Bull iten B3491 } psTimeBull iten;4571 PS_IERS_A, ///< IERS Bulletin A 4572 PS_IERS_B, ///< IERS Bulletin B 4573 } psTimeBulletin; 3492 4574 3493 4575 typedef struct { 3494 4576 psS64 sec; ///< seconds, negative values represent dates before 1970 3495 psU32 nsec; ///< nan seconds4577 psU32 nsec; ///< nanoseconds 3496 4578 bool leapsecond; ///< if time falls on a UTC leapsecond 3497 4579 psTimeType type; ///< type of time … … 3523 4605 This function may be used to convert between the various \code{psTimeType} time 3524 4606 representations. The \code{time} is modified and returned. Conversion between 3525 all of the \emph{SI} length second systems should be implimented asfirst4607 all of the \emph{SI} length second systems should be implimented by first 3526 4608 converting to TAI and then to the destination system. UT1 is a special case 3527 4609 for conversion as it uses variable length secounds. Conversation to UT1, via 3528 4610 TAI, is allowed but conversion \emph{from} UT1 is currently forbidden. 3529 4611 3530 To convert to Local Mean Sidereal Time, it is necessary to provide the local 3531 longitude (specified in radians, positive East of Greenwich) as well: 4612 The following function converts to Local Mean Sidereal Time. It is 4613 necessary to provide the local longitude (specified in radians, 4614 positive East of Greenwich) as well: 3532 4615 3533 4616 \begin{verbatim} … … 3535 4618 \end{verbatim} 3536 4619 3537 The function may accept any of the \code{psTimeType} types with \emph{SI} 3538 length seconds. The \code{time} is modified and returned. Note that this 3539 function must supply the value $UT1-UTC$, which is available externally (see 3540 \code{psTimeGetUT1Delta()}) and should use the UT1 values interpolated from 3541 IERS bulliten B. The following utility function encapsulates the PSLib 3542 mechanism to extract the value of $UT1-UTC$: 3543 3544 \begin{verbatim} 3545 double psTimeGetUT1Delta(const psTime *time, psTimeBulliten bulliten); 3546 psSphere *psTimeGetPoleCoords(const psTime *time, psTimeBulliten bulliten); 3547 \end{verbatim} 3548 3549 Leap seconds are added to UTC in order to keep it within $0.9s$ of UT1 (which 3550 is defined relative to the Earth's rotation, and hence is useful for 3551 astronomical purposes). 4620 The function may accept any of the \code{psTimeType} types with 4621 \emph{SI} length seconds. The \code{time} is modified and returned. 4622 Note that this function requires the value $UT1-UTC$ (see 4623 \code{psTimeGetUT1Delta()}) and should use the UT1 values interpolated 4624 from IERS bulletin B. 4625 4626 The following utility function encapsulates the PSLib mechanism to 4627 extract the value of $UT1-UTC$ from the IERS Time Tables: 4628 4629 \begin{verbatim} 4630 double psTimeGetUT1Delta(const psTime *time, psTimeBulletin bulletin); 4631 \end{verbatim} 4632 4633 The following function provides tidal corrections to UT1-UTC, using 4634 the Ray model of Simon et al (REF). 4635 \begin{verbatim} 4636 psTime *psTime_TideUT1Corr(const psTime *time); 4637 \end{verbatim} 4638 4639 Leap seconds are added to UTC in order to keep it within $0.9s$ of UT1 4640 (which is defined relative to the Earth's rotation, and hence is 4641 useful for astronomical purposes). The following function calculates 4642 the absolute number of leap seconds different between two times. 3552 4643 3553 4644 \begin{verbatim} … … 3555 4646 \end{verbatim} 3556 4647 3557 This function calculates the absolute number of leap seconds different between 3558 two times. 4648 The following function accepts \code{PS_TIME_UTC} objects and 4649 determines if the time is potentaly a leapsecond, returning 4650 \code{TRUE} if so. 3559 4651 3560 4652 \begin{verbatim} 3561 4653 bool psTimeIsLeapSecond(const psTime *utc); 3562 4654 \end{verbatim} 3563 3564 This function only accepts \code{PS_TIME_UTC} objects and determines if the3565 time is potentaly a leapsecond.3566 4655 3567 4656 \subsubsection{External Date and Time Formats} … … 3581 4670 \end{verbatim} 3582 4671 3583 The \code{psTimeToISO()} function will convertion\code{PS_TIME_UTC} objects3584 with the \code{leapsecond} flag set to represent the number of seconds as3585 ``:60''.4672 The \code{psTimeToISO()} function converts \code{PS_TIME_UTC} objects 4673 with the \code{leapsecond} flag set to represent the number of seconds 4674 as ``:60''. 3586 4675 3587 4676 \subsubsection{Date and Time Parsing} … … 3622 4711 \code{psS64} (the type of \code{psTime.sec}). 3623 4712 3624 Note that in both these functions , when handling UTC, that the difference3625 between two times is not inclusive of leap seconds. For example, if we add 30 3626 seconds to 1998-12-31T23:59:45Z, the result is 1999-01-01T00:00:14Z, since a 3627 leap second was introduced at 1999-01-01T00:00:00Z. 3628 3629 Time math may only be done on the of \code{psTime} objects of the same type, 3630 and in the case of UT1, the functions shall internally convert the 3631 \code{psTime} inputs to TAI before performing the math; this is in order that3632 leap seconds are accounted for. 3633 3634 The type of the time returned by \code{psTimeMath} shall be the same as that of 3635 the input \code{time}. 3636 4713 Note that in both these functions the difference between two times is 4714 the elapsed number of seconds, inclusing leap seconds. For example, 4715 if we add 30 seconds to 1998-12-31T23:59:45Z, the result is 4716 1999-01-01T00:00:14Z, since a leap second was introduced at 4717 1999-01-01T00:00:00Z. 4718 4719 Time math may only be done on \code{psTime} objects of the same type, 4720 and except in the case of UT1, the functions shall internally convert 4721 the \code{psTime} inputs to TAI before performing the math; this 4722 ensures that leap seconds are correctly counted. 4723 4724 The type of the time returned by \code{psTimeMath} shall be the same 4725 as that of the input \code{time}. 3637 4726 3638 4727 \subsubsection{Time Tables} … … 3645 4734 3646 4735 \begin{itemize} 3647 \item IERS Bull iten A \& B (1 year ago $\rightarrow$ now + $\sim$3 months)4736 \item IERS Bulletin A \& B (1 year ago $\rightarrow$ now + $\sim$3 months) 3648 4737 \begin{itemize} 3649 4738 \item \code{ftp://maia.usno.navy.mil/ser7/finals.daily} 3650 4739 \end{itemize} 3651 4740 3652 \item IERS Bull iten A \& B (1973-1-2 $\rightarrow$ now + $\sim$1 year)4741 \item IERS Bulletin A \& B (1973-1-2 $\rightarrow$ now + $\sim$1 year) 3653 4742 \begin{itemize} 3654 4743 \item \code{ftp://maia.usno.navy.mil/ser7/finals.all} … … 3673 4762 format of these files shall be simple, for speed in reading. Each line shall 3674 4763 contain the date in MJD and the following values from both the A \& B IERS 3675 bull itens: $x_p$ (in arcseconds), $y_p$ (in arcseconds) and $\Delta$UT (in4764 bulletins: $x_p$ (in arcseconds), $y_p$ (in arcseconds) and $\Delta$UT (in 3676 4765 seconds). This format must be readable by \code{psLookupTableRead}. For 3677 4766 example: … … 3756 4845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3757 4846 3758 \subsection{Regions} 3759 3760 In many places, we need to refer to a rectangular area. We define a 3761 structure to represent a rectangle: 3762 \begin{verbatim} 3763 typedef struct { 3764 float x0; 3765 float x1; 3766 float y0; 3767 float y1; 3768 } psRegion; 3769 psRegion *psRegionAlloc (float x0, float x1, float y0, float y1); 3770 \end{verbatim} 3771 3772 \begin{verbatim} 3773 psRegion *psRegionFromString (char *region); 3774 \end{verbatim} 3775 This function converts the IRAF description of a region in the form 3776 \code{[x0:x1,y0:y1]}, used for header entries such as \code{BIASSEC}, 3777 into the corresponding \code{psRegion} structure. 3778 3779 \subsection{Metadata} 3780 \label{sec:metadata} 3781 3782 \subsubsection{Conceptual Overview} 3783 3784 Within PSLib, we provide a data structure to carry metadata and 3785 mechanisms to manipulate the metadata. Metadata is a general concept 3786 that requires some discussion. In any data analysis task, the 3787 ensemble of all possible data may be divided into two or three 3788 classes: there is the specific data of interest, there is data which 3789 is related or critical but not the primary data of interest, and there 3790 is all of the other data which may or may not be interesting. For 3791 example, consider a simple 2D image obtained of a galaxy from a CCD 3792 camera on a telescope. If you want to study the galaxy, the specific 3793 data of interest is the collection of pixels. There are a variety of 3794 other pieces of data which are closely related and crucial to 3795 understanding the data in those pixels, such as the dimensions of the 3796 image, the coordinate system, the time of the image, the exposure 3797 time, and so forth. Other data may be known which may be less 3798 critical to understanding the image, but which may be interesting or 3799 desired at a later date. For example, the observer who took the 3800 image, the filter manufacturer, the humidity at the telescope, etc. 3801 3802 Formally, all of the related data which describe the principal data of 3803 interest are metadata. Note that which piece is the metadata and 3804 which is the data may depend on the context. If you are examining the 3805 pixels in an image, the coordinate and flux of an object may be part 3806 of the metadata. However, if you are analyzing a collection of 3807 objects extracted from an image, you may consider then pixel data 3808 simply part of the metadata associated with the list of objects. 3809 3810 There are various ways to handle metadata vs data within a programming 3811 environment. In C, it is convenient to use structures to group 3812 associated data together. One possibility is to define the metadata 3813 as part of the associated data structure. For example, the image data 3814 structure would have elements for all possible associated measurement. 3815 This approach is both cumbersome (because of the large number metadata 3816 types), impractical (because the full range of necessary metadata is 3817 difficult to know in advance) and inflexible (because any change in 3818 the collection of metadata requires addition of new structure elements 3819 and recompilation). 3820 3821 An alternative is to place the metadata in a generic container and use 3822 lookup mechanisms to extract the appropriate metadata when needed. An 3823 example of this is would be a text-based FITS header for an image read 3824 into a flat text buffer. In this implementation, metadata lookup 3825 functions could return the current value of, for example, NAXIS1 (the 3826 number of columns of the image) by scanning through the header buffer. 3827 This method has the benefits of flexibility and simplicity of 3828 programming interface, but it has the disadvantage that all metadata 3829 is accessed though this lookup mechanism. This may make the code less 3830 readable and it may slow down the access. 3831 3832 PSLib implements an intermediate solution to this problem. We specify 3833 a flexible, generic metadata container and access methods. Data types 3834 which require association with a general collection of metadata should 3835 include an entry of this metadata type. However, a subset of metadata 3836 concepts which are basic and frequently required may be placed in the 3837 coded structure elements. This approach allows the code to refer to 3838 the basic metadata concepts as part of the data structure (ie, 3839 \code{image.nx}), but also allows us to provide access to any 3840 arbitrary metadata which may be generated. As a practical matter, the 3841 choice of which entries are only in the metadata and which are part of 3842 the explicit structure elements is rather subjective. Any data 3843 elements which are frequently used should be put in the structure; 3844 those which are only infrequently needed should be left in the generic 3845 metadata. 3846 3847 There are some points of caution which must be noted. Any 3848 manipulation of the data should be reflected in the metadata where 3849 appropriate. This is always an issue of concern. For example, 3850 consider an image of dimensions \code{nx, ny}. If a function extracts 3851 a subraster, it must change the values of \code{nx, ny} to match the 3852 new dimensions. What should it do to the corresponding metadata? 3853 Clearly, it should change the corresponding value which defines 3854 \code{nX, nY}. However, it is not quite so simple: there may be other 3855 metadata values which depend on those values. These must also be 3856 changed appropriately. What if the metadata element points to a 3857 copy of the metadata which may be shared by other representations of 3858 the image? These must be treated differently because the change would 3859 invalidate those other references. Care must be taken, therefore, 3860 when writing functions which operate on the data to consider all of 3861 the relevant metadata entries which must also be updated. 3862 3863 A related issue is the definition of metadata names. Entries in a 3864 structure have the advantage of being hardwired: every instance of 3865 that structure will have the same name for the same entry. This is 3866 not necessarily the case with a more flexible metadata container. The 3867 image exposure time is a notorious example in astronomy. Different 3868 observatories use different header keywords (ie, metadata names) for 3869 the same concept of the exposure time (\code{EXPTIME}, 3870 \code{EXPOSURE}, \code{OPENTIME}, \code{INTTIME}, etc). Any system 3871 which operates on these metadata needs to address the issue of 3872 identifying these names. This issue seems like an argument for 3873 hardwiring metadata in the structure, but in fact it does not present 3874 such a strong case. If the metadata are hardwired, some function will 3875 still have to know how to interpret the various names to populate the 3876 structure. The concept can still be localized with generic metadata 3877 containers by including abstract metadata names within the code which 3878 are tied to the various implementations-specific metadata names. 3879 3880 \subsubsection{Metadata Representation} 3881 3882 \begin{figure} 3883 \psfig{file=Metadata,width=6.5in} 3884 \caption{Metadata Structures\label{fig:metadata}} 3885 \end{figure} 3886 3887 This section addresses the question of how \PS{} metadata should be 3888 represented in memory, not how it should be represented on disk. 3889 3890 We define an item of metadata with the following structure: 3891 \filbreak 3892 \begin{verbatim} 3893 typedef struct { 3894 int id; ///< unique ID for this item 3895 char *name; ///< Name of item 3896 psMetadataType type; ///< type of this item 3897 psElemType ptype; ///< primitive data type 3898 const union { 3899 psS32 S32; ///< integer data 3900 psF32 F32; ///< floating-point data 3901 psF64 F64; ///< double-precision data 3902 void *V; ///< other type 3903 psList *list; ///< psList entry 3904 psMetadata *md; ///< psMetadata entry 3905 } data; ///< value of metadata 3906 char *comment; ///< optional comment ("", not NULL) 3907 } psMetadataItem; 3908 \end{verbatim} 3909 3910 The \code{id} is a unique identifier for this item of metadata; 3911 experience shows that such tags are useful. The entry \code{name} 3912 specifies the name of the metadata item. The value of the metadata is 3913 given by the union \code{data}, and may be of type \code{psS32}, 3914 \code{psF32}, \code{psF64}, or an arbitrary rich structure pointed at 3915 by the \code{void} pointer \code{V}. A character string comment 3916 associated with this metadata item may be stored in the element 3917 \code{comment}. The \code{type} entry specifies how to interpret the 3918 type of the data being represented, given by the enumerated type 3919 \code{psMetadataType}: 3920 % 3921 \filbreak 3922 \begin{verbatim} 3923 typedef enum { ///< type of item.data is: 3924 PS_META_PRIMITIVE, ///< primitive type: use item.ptype 3925 PS_META_LIST, ///< psList; use item.data.list (used for non-unique data) 3926 PS_META_META, ///< psMetadata: use item.data.list 3927 PS_META_STR, ///< string (item.data.V) 3928 PS_META_MATH, ///< psScalar, psVector, psImage (item.data.V) 3929 PS_META_JPEG, ///< JPEG (item.data) 3930 PS_META_PNG, ///< PNG (item.data) 3931 PS_META_ASTROM, ///< astrometric coefficients (item.data) 3932 PS_META_UNKNOWN, ///< other (item.data) 3933 PS_META_NTYPE ///< Number of types; must be last 3934 } psMetadataType; 3935 \end{verbatim} 3936 If the data is a PSLib primitive data value, the primitive data type 3937 is given by the value of \code{ptype}. 3938 3939 A collection of metadata is represented by the \code{psMetadata} structure: 3940 \begin{verbatim} 3941 typedef struct { 3942 psList *list; ///< list of psMetadataItem 3943 psHash *table; ///< hash table of the same metadata 3944 } psMetadata; 3945 \end{verbatim} 3946 The type \code{psMetadata} is a container class for metadata. Note 3947 that there are in fact \emph{two} representations of the metadata 3948 (each \code{psMetadataItem} appears on both). The first 3949 representation employs a doubly-linked list that allows the order of 3950 the metadata to be preserved (e.g., if FITS headers are read in a 3951 particular order, they should be written in the same order). The 3952 second representation employs a hash table which allows fast look-up 3953 given a specific metadata keyword. 3954 3955 Certain metadata names (such as the FITS keywords \code{COMMENT} and 3956 \code{HISTORY} in a FITS header) may be repeated with different 3957 values. In such a case, the \code{psMetadata.list} structure contains 3958 the entries in their original sequence with duplicate keys. The 3959 \code{psMetadata.hash} entries, which are required to have unique 3960 keys, would have a single entry with the keyword of the repeated key, 3961 with the value of \code{psMetadataType} set to \code{PS_META_LIST}, 3962 and the \code{psMetadataItem.data} element pointing to a \code{psList} 3963 containing the actual entries. If \code{psMetadataItemAlloc} is 3964 called with the type set to \code{PS_META_LIST}, such a repeated key 3965 is created. If the data value passed to \code{psMetadataItemAlloc} 3966 (the quantity in ellipsis) is \code{NULL}, then an empty 3967 \code{psMetadataItem} with the given keyword is created to hold future 3968 entries of that keyword. 3969 3970 The \code{psMetadataAdd} routine is required to check that all 3971 metadata names are unique unless the type is already qualified as 3972 \code{PS_META_LIST}; in this case the data are added to the 3973 corresponding \code{psMetadataItem.data} list. 3974 3975 \subsubsection{Metadata APIs} 3976 3977 The allocator for \code{psMetadataItem} returns a full 3978 \code{psMetadataItem} ready for insertion into the \code{psMetadata}. 3979 The \code{name} entry specifies the name to use for this metadata 3980 item, and may include \code{sprintf}-type formating codes. The 3981 \code{comment} entry is a fixed string which is used for the comment 3982 associated with this metadata item. The metadata data and the 3983 arguments to the \code{name} formatting codes are passed, in that 3984 order (metadata pointer first), to \code{psMetadataItemAlloc} as 3985 arguments following the comment string. The data must be a pointer 3986 for any data types which are stored in the element \code{data.void}, 3987 while other data types are passed as numeric values. The argument 3988 list must be interpreted appropriately by the \code{va_list} operators 3989 in the function. 3990 \begin{verbatim} 3991 psMetadataItem *psMetadataItemAlloc(const char *name, psMetadataType type, const char *comment, ...); 3992 psMetadataItem *psMetadataItemAllocV(const char *name, psMetadataType type, const char *comment, va_list list); 3993 \end{verbatim} 3994 3995 The constructor for the collection of metadata, \code{psMetadata}, 3996 simply returns an empty metadata container (employing the constructors 3997 for the doubly-linked list and hash table). The destructor needs to 3998 free each of the \code{psMetadataItem}s using \code{psMetadataItemFree}. 3999 \begin{verbatim} 4000 psMetadata *psMetadataAlloc(void); 4001 \end{verbatim} 4002 4003 Items may be added to the metadata in one of two ways --- firstly, an 4004 item may be added by appending a \code{psMetadataItem} which has 4005 already been created; and secondly by directly providing the data to 4006 be appended. In both cases, the return value defines the success 4007 (\code{true}) or failure of the operation. The second function, 4008 \code{psMetadataAdd} takes a pointer or value which is interpreted by 4009 the function using variadic argument interpretation. The third 4010 version is the \code{va_list} version of the second function. All 4011 three functions take a parameter, \code{location}, which specifies 4012 where in the list to place the element, following the conventions for 4013 the \code{psList}. The entry \code{mode} for \code{psMetadataAddItem} 4014 is a bit mask constructed by OR-ing the allowed option flags (eg, 4015 \code{PS_META_REPLACE}) which specifies minor variations on the 4016 behavior. The \code{format} entry, which specifies both the metadata 4017 type and the optional flags, is constructed by bit-wise OR-ing the 4018 appropriate \code{psMetadataType} and allowed option option flags. 4019 Care should be taken not to leak memory when appending an item for 4020 which the key already exists in the metadata (and is not 4021 \code{PS_META_LIST}). 4022 % 4023 \begin{verbatim} 4024 bool psMetadataAddItem(psMetadata *md, psMetadataItem *item, int location, int mode); 4025 bool psMetadataAdd(psMetadata *md, int location, const char *name, int format, const char *comment, ...); 4026 bool psMetadataAddV(psMetadata *md, int location, const char *name, int format, const char *comment, 4027 va_list list); 4028 \end{verbatim} 4029 4030 The functions above take option flags which modify the behavior when 4031 metadata items are added to the metadata list. These flags must be 4032 bit-exclusive of those used above for the \code{psMetadataTypes}. The 4033 flags have the following meanings: 4034 4035 \code{PS_META_DEFAULT}: This is the zero bit mask, to allow the 4036 default behavior for \code{psMetadataAddItem} above. If this is OR-ed 4037 with a \code{psMetadataType}, the result is as if no OR-ing took 4038 place. 4039 4040 \code{PS_META_REPLACE}: If the given metadata item exists in the 4041 metadata list, and is not of type \code{PS_META_LIST} or 4042 \code{PS_META_META} (ie, not a container type), then this entry is 4043 allowed to replace the existing entry. If this mode bit is not set, a 4044 duplicate (non-container-type) entry is an error. 4045 4046 \begin{verbatim} 4047 typedef enum { ///< option flags for psMetadata functions 4048 PS_META_DEFAULT, ///< default behavior (0x0000) for use in mode above 4049 PS_META_REPLACE, ///< allow entry to be replaced 4050 } psMetadataFlags; 4051 \end{verbatim} 4052 4053 An example of code to use these metadata APIs to generate the 4054 structure seen in Figure~\ref{fig:metadata} is given below. 4055 4056 \begin{verbatim} 4057 md = psMetadataAlloc(); 4058 4059 psMetadataAdd(md, PS_LIST_TAIL, "SIMPLE", PS_META_BOOL, "basic fits", TRUE); 4060 psMetadataAdd(md, PS_LIST_TAIL, "BLANK", PS_META_S32, "invalid pixel data", -32768); 4061 psMetadataAdd(md, PS_LIST_TAIL, "DATE-OBS", PS_META_STR, "observing date UT", " 2004-6-16"); 4062 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_LIST, "head of comment block", NULL); 4063 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "DATA"); 4064 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "PARAMS"); 4065 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32, "exposure time (sec)", 1.05); 4066 psMetadataAdd(md, PS_LIST_TAIL, "COMMENT", PS_META_STR, "", "FOO"); 4067 4068 cell = psMetadataAlloc(); 4069 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD00"); 4070 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-00"); 4071 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.00"); 4072 psMetadataAdd(md, PS_LIST_TAIL, "CELL.00", PS_META_META, "", cell); 4073 4074 cell = psMetadataAlloc(); 4075 psMetadataAdd(cell, PS_LIST_TAIL, "EXTNAME", PS_META_STR, "", "CCD01"); 4076 psMetadataAdd(cell, PS_LIST_TAIL, "BIASNAME", PS_META_STR, "", "BSEC-01"); 4077 psMetadataAdd(cell, PS_LIST_TAIL, "CHIP", PS_META_STR, "", "CHIP.01"); 4078 psMetadataAdd(md, PS_LIST_TAIL, "CELL.01", PS_META_META, "", cell); 4079 \end{verbatim} 4080 4081 The following code shows how to use the APIs to replace one of these values: 4082 \begin{verbatim} 4083 psMetadataAdd(md, PS_LIST_TAIL, "EXPTIME", PS_META_F32 | PS_REPLACE, "new exposure time (sec)", 2.05); 4084 \end{verbatim} 4085 4086 Items may be removed from the metadata by specifying a key or a 4087 location in the list. If the value of \code{name} is \code{NULL}, the 4088 value of \code{location} is used. If the value of \code{name} is not 4089 \code{NULL}, then \code{location} must be set to 4090 \code{PS_LIST_UNKNOWN}. If the key matches a metadata item, the item 4091 is removed from the metadata and \code{true} is returned; otherwise, 4092 \code{false} is returned. If the key is not unique, then \emph{all} 4093 items corresponding to the key are removed, and \code{true} is 4094 returned. 4095 % 4096 \begin{verbatim} 4097 bool psMetadataRemove(psMetadata *md, int location, const char *key); 4098 \end{verbatim} 4099 4100 Items may be found within the metadata by providing a key. In the 4101 event that the key is non-unique, the first item is returned. 4102 \begin{verbatim} 4103 psMetadataItem *psMetadataLookup(const psMetadata *md, const char *key); 4104 \end{verbatim} 4105 4106 Several utility functions are provided for simple cases. These 4107 functions perform the effort of casting the data to the appropriate 4108 type. The numerical functions shall return 0.0 if their key is not 4109 found. If the pointer value of \code{status} is not \code{NULL}, it 4110 is set to reflect the success or failure of the lookup. 4111 \begin{verbatim} 4112 void *psMetadataLookupPtr(bool *status, const psMetadata *md, const char *key); 4113 psS32 psMetadataLookupS32(bool *status, const psMetadata *md, const char *key); 4114 psF64 psMetadataLookupF64(bool *status, const psMetadata *md, const char *key); 4115 \end{verbatim} 4116 4117 Items may be retrieved from the metadata by their entry position. The 4118 value of which specifies the desired entry in the fashion of 4119 \code{psList}. 4120 \begin{verbatim} 4121 psMetadataItem *psMetadataGet(const psMetadata *md, int location); 4122 \end{verbatim} 4123 4124 The metadata list component may be iterated over by using a 4125 \code{psListIterator} in a fashion equivalent to the usage for 4126 \code{psList}. The iterator may be set to a location in the 4127 \code{psMetadata} list, and the user may get the previous or next item 4128 in the list relative to that location. \code{psMetadataGetNext} has 4129 the ability to match the key using a POSIX regex, e.g., if the user 4130 only wants to iterate through \code{IPP.machines.sky} and doesn't want 4131 to bother with \code{IPP.machines.detector}. The iterator should 4132 iterate over every item in the metadata list, even those that are 4133 contained in a \code{PS_META_LIST}. The value \code{iterator} 4134 specifies the iterator to be used. In setting the iterator, the 4135 position of the iterator is defined by \code{location}, which follows 4136 the conventions of the \code{psList} iterators. 4137 \begin{verbatim} 4138 psListIterator *psMetadataIteratorAlloc(psMetadata *md, int location, bool mutable); 4139 bool psMetadataIteratorSet(psListIterator *iterator, int location); 4140 psMetadataItem *psMetadataGetAndIncrement(psListIterator *iterator, const char *regex); 4141 psMetadataItem *psMetadataGetAndDecrement(psListIterator *iterator, const char *regex); 4142 \end{verbatim} 4143 4144 Metadata items may be printed to an open file descriptor based on a 4145 provided format. The format string is an sprintf format statement 4146 with exactly one \% formatting command. If the metadata item type is 4147 a numeric type, this formatting command must also be numeric, and type 4148 conversion performed to the value to match the format type. If the 4149 metadata item type is a string, the formatting command must also be 4150 for a string (\%s type of command). If the metadata type is any other 4151 data type, printing is not allowed. 4152 \begin{verbatim} 4153 bool psMetadataItemPrint(FILE *fd, const char *format, const psMetadataItem *md); 4154 \end{verbatim} 4155 4156 \subsubsection{Configuration files} 4157 \label{sec:configspec} 4158 4159 It will be necessary for the \PS{} system, in order to load 4160 pre-defined settings, to parse a configuration file into a 4161 \code{psMetadata} structure. This shall be performed by the 4162 function \code{psMetadataParseConfig}, as described below. 4163 4164 \begin{verbatim} 4165 psMetadata *psMetadataParseConfig(psMetadata *md, int *nFail, const char *filename, bool overwrite); 4166 \end{verbatim} 4167 4168 Given a metadata container, \code{md}, and the name of a configuration 4169 file, \code{filename}, \code{psMetadataParseConfig} shall parse the 4170 configuration file, placing the contained key/type/value/comment quads 4171 into the metadata, and returning a pointer to the metadata structure. 4172 The number of lines that failed to parse is returned in \code{nFail}. 4173 Multiple specifications of a key that haven't been declared (see 4174 below) are overwritten if and only if \code{overwrite} is \code{true}. 4175 If the metadata container is \code{NULL}, it shall be allocated. 4176 4177 On error, the function shall return \code{NULL}. 4178 4179 The configuration file shall consist of plain text with 4180 key/type/value/comment quads on separate lines. Blank lines, 4181 including those consisting solely of whitespace (both spaces and 4182 tabs), shall be ignored, as shall lines that commence with the comment 4183 character (a hash mark, \code{#}), either immediately at the start of 4184 the line, or preceded by whitespace. The key/type/value/comment quads 4185 shall all lie on a single line, separated by whitespace. 4186 4187 The key shall be first, possibly preceded on the line by whitespace 4188 which should not form part of the key. 4189 4190 Next, to assist the casting of the value, shall be a string 4191 identifying the type of the value, which shall correspond to one of 4192 the simple types supported in \code{psMetadata}: 4193 \code{STRING,BOOL,S32,F32,F64}; \code{STR} may be used to abbreviate 4194 \code{STRING}. 4195 4196 \tbd{May, in the future, require more types, including U8,S16,C64, 4197 which will also necessitate updating the definition of psMetadata.} 4198 4199 The value shall follow the type: strings may consist of multiple 4200 words, and shall have all leading and trailing whitespace removed; 4201 booleans shall simply be either \code{T} or \code{F}. 4202 4203 Following the value may be an optional comment, preceded by a comment 4204 character (a hash mark, \code{#}), which in the case of a string 4205 value, serves to mark the end of the value, and for other types serves 4206 to identify the comment to the reader. Only one comment character may 4207 be present on any single line (i.e., neither strings nor comments are 4208 permitted to contain the comment character). The comment may consist 4209 of multiple words, and shall have leading and trailing whitespace 4210 removed. 4211 4212 One wrinkle is the specification of vectors. Keys for which the value 4213 is to be parsed as a vector shall be preceded immediately by a 4214 ``vector symbol'', which we choose to be the ``at'' sign, \code{@}. 4215 In this case, the type shall be interpreted as the type for the 4216 vector, which may be any of the signed or unsigned integer or floating 4217 point types (\code{U8,U16,U32,U64,S8,S16,S32,S32,S64,F32,F64}) but not 4218 the complex floating point types; and the value shall consist of 4219 multiple numbers, separated either by a comma or whitespace. These 4220 values shall populate a \code{psVector} of the appropriate type in the 4221 order in which they appear in the configuration file. 4222 4223 \tbd{May add complex types, likely to be specified with values such as 4224 1.23+4.56i in the future.} 4225 4226 An additional hurdle is the specification of keys that may be 4227 non-unique (such as the \code{COMMENT} keyword in a FITS header). 4228 These keys shall be specified in the configuration file as non-unique 4229 by specifying the key at the start of the line (possibly preceded by 4230 whitespace) and specifying the type as a ``multiple symbol'', which we 4231 choose to be an asterisk, \code{*}. No other data may be provided on 4232 this line, though a comment, preceeded by the comment marker, is 4233 valid. A warning shall be produced when a key which has not been 4234 specified to be non-unique is repeated; in this case, the former value 4235 shall be overwritten if \code{overwrite} is \code{true}, otherwise the 4236 line shall be ignored and counted as one that could not be parsed. 4237 4238 If a line does not conform to the rules laid out here, a warning shall 4239 be generated, it shall be ignored and counted as a line that could not 4240 be parsed. The total number of lines that were not able to be parsed 4241 (including those that were ignored because \code{overwrite} is 4242 \code{false}, and any other parsing problems, but not including blank 4243 lines and comment lines) shall be returned by the function in the 4244 argument \code{nFail}. 4245 4246 Here are some examples of lines of a valid configuration file: 4247 \filbreak 4248 \begin{verbatim} 4249 Double F64 1.23456789 # This is a comment 4250 Float F32 0.98765 # This is a comment too 4251 String STR This is the string that forms the value #comment 4252 4253 # This is a comment line and is to be ignored 4254 boolean BOOL T # The value of `boolean' is `true' 4255 4256 @primes U8 2,3 5 7,11,13 17 # These are prime numbers 4257 4258 comment MULTI # The rest of this line is ignored, but `comment' is set to be non-unique 4259 comment STR This 4260 comment STR is 4261 comment STR a 4262 comment STR non-unique 4263 comment STR key 4264 Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored 4265 \end{verbatim} 4266 4267 Of course, a real configuration file should look much nicer to humans 4268 than the above example, but PSLib must be able to parse such ugly 4269 files. 4270 4271 We extend \code{psMetadataParseConfig} to allow a modest tree 4272 structure by defining a reserved keyword \code{TYPE}. Any line in the 4273 config file which starts with the word \code{TYPE} shall be 4274 interpretted as defining a new valid type. The defined type name 4275 follows the word \code{TYPE}, and is in turn followed by an arbitrary 4276 number of words. These words are to be interpreted as the names of an 4277 embedded \code{psMetadata} entry, where the values are given on any 4278 line which (following the \code{TYPE} definition) employs the new type 4279 name. For example, a new type may be defined as: 4280 \begin{verbatim} 4281 TYPE CELL EXTNAME BIASSEC CHIP 4282 CELL.00 CELL CCD00 BSEC-00 CHIP.00 4283 CELL.01 CELL CCD01 BSEC-01 CHIP.00 4284 \end{verbatim} 4285 4286 When \code{psMetadataParseConfig} encounters the \code{TYPE} line, it 4287 should construct a \code{psMetadata} container and fill it with 4288 \code{psMetadataItems} having the names \code{EXTNAME, BIASSEC, CHIP}, 4289 with type \code{PS_META_STR}, but data allocated. When it next 4290 encounters an entry of type \code{CELL}, it should then use the given 4291 name (e.g., \code{CELL.00}) for the \code{psMetadataItem}, and copy 4292 the \code{psMetadata} data onto the \code{psMetadataItem.data.md} 4293 entry, filling in the values from the rest of the line (\code{CCD00, 4294 BSEC-00, CHIP.00}). This hierarchical structure is illustrated in 4295 Figure~\ref{fig:metadata}. 4296 4297 We further extend \code{psMetadataParseConfig} to allow the definition 4298 of a \code{psMetadata} entry using a sequence of successive lines to 4299 define the values of the \code{psMetadataItem} entries. The initial 4300 line defines the new \code{psMetadata} entry and its name. The 4301 following lines have the same format as the other metadata config file 4302 entries. The sequence is terminated with a line with a single word 4303 \code{END}. For example, a metadata entry may be defined as: 4304 \begin{verbatim} 4305 CELL METADATA 4306 EXTNAME STR CCD00 4307 BIASSEC STR BSEC-00 4308 CHIP STR CHIP.00 4309 NCELL S32 24 4310 END 4311 \end{verbatim} 4312 4313 A series of test inputs is contained in 4314 \S\ref{sec:configtest}. 4315 4316 \subsection{XML Functions} 4317 4318 Within Pan-STARRS, we will use XML documents as a transport mechanism 4319 to carry data between programs and between IPP and other subsystems. 4320 Configuration information may be stored as well as XML documents, in 4321 addition to the text format discussed in the discussion on Metadata. 4322 XML is an extremely variable document format, and it is not currently 4323 the intention of PSLib to provide a complete PSLib version of XML 4324 operations. Rather, a limited number of operations are defined to 4325 convert specific data structures to an appropriate XML document. To 4326 maximize the simplicity of the XML APIs, we will use the convention 4327 that a single XML document to be parsed by PSLib shall contain only a 4328 single data structure. Each of the XML APIs therefore take as input a 4329 reference to a complete XML document and return a PSLib data 4330 structure, or take a PSLib data structure and return a complete XML 4331 document. 4332 4333 We start by defining a PSLib wrapper type which is a pointer to an XML 4334 document in memory. We wrap the \code{libxml2} version of an XML 4335 document pointer for now: 4336 \begin{verbatim} 4337 typedef xmlDocPtr psXMLDoc; 4338 void psXMLDocFree(psXMLDoc *doc); 4339 \end{verbatim} 4340 4341 The next pair of functions convert a \code{psMetadata} data structure 4342 to a complete \code{psXMLDoc} (in memory) and vice versa: 4343 \begin{verbatim} 4344 psXMLDoc *psMetadataToXMLDoc(const psMetadata *metadata); 4345 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc); 4346 \end{verbatim} 4347 4348 The next pair of functions loads the data in a named file into a 4349 complete \code{psXMLDoc} (in memory) and write out the \code{psXMLDoc} 4350 to a named file: 4351 \begin{verbatim} 4352 psXMLDoc *psXMLParseFile(const char *filename); 4353 int psXMLDocToFile(const psXMLDoc *doc, const char *filename); 4354 \end{verbatim} 4355 4356 The next pair of functions accepts a block of memory and parses it 4357 into a complete \code{psXMLDoc} (also in memory), and vice versa: 4358 \begin{verbatim} 4359 psXMLDoc *psXMLParseMemory(const char *buffer, const int size); 4360 int psXMLDocToMemory(const psXMLDoc *doc, char *buffer); 4361 \end{verbatim} 4362 4363 The next pair of functions read from and write to a file descriptor. 4364 The first converts the imcoming data to a complete \code{psXMLDoc} 4365 (also in memory), the second writes the \code{psXMLDoc} to the file 4366 descriptor: 4367 \begin{verbatim} 4368 psXMLDoc *psXMLParseFD(int fd); 4369 int psXMLDocToFD(const psXMLDoc *doc, int fd); 4370 \end{verbatim} 4371 4372 \subsection{Database Functions} 4373 4374 Many of the applications that PSLib will be used for will require 4375 access to a simple relational database. PSLib includes generic 4376 database-independent interface mechanisms as part of its API set. The 4377 most important aspect of PSLib's database support is to abstract as 4378 much database specific complexity as is feasible. As almost all RDBMS 4379 provide at least a simple transactional model, commit and rollback 4380 support should be provided. 4381 4382 Currently, only support for MySQL 4.1.x is required but other backends 4383 may be added as options in the future. As a particular example which 4384 has implications for the database interaction model, support for 4385 SQLite may be required in the future. Currently, the choice of 4386 backend database interface may be made as a compile option. Details 4387 of the specified APIs in the discussion below refer to the relevant 4388 MySQL functions. 4389 4390 Database errors must be trapped and placed onto the psError stack. 4391 The complete error message should be retrieved with the database's 4392 error function. 4393 4394 \subsubsection{Managing the Database Connection} 4395 4396 We specify a database handle which carries the information about the 4397 database connection: 4398 4399 \begin{verbatim} 4400 typedef struct { 4401 MYSQL *mysql; 4402 } psDB; 4403 \end{verbatim} 4404 4405 The following collection of functions provides basic database functionality: 4406 4407 \begin{verbatim} 4408 // wraps mysql_init() & mysql_real_connect() 4409 psDB *psDBInit(const char *host, const char *user, const char *passwd, const char *dbname); 4410 4411 // wraps mysql_close() 4412 void psDBCleanup(psDB *dbh); 4413 4414 // wraps mysql_create_db() 4415 bool psDBCreate(psDB *dbh, const char *dbname); 4416 4417 // wraps mysql_select_db() 4418 bool psDBChange(psDB *dbh, const char *dbname); 4419 4420 // wraps mysql_drop_db() 4421 bool psDBDrop(psDB *dbh, const char *dbname); 4422 \end{verbatim} 4423 4424 For MySQL support, \code{psDBInit()} wraps \code{mysql_init()} and 4425 \code{mysql_real_connect()} in order to initialize a psDB structure and 4426 establish a database connection. A null pointer should be returned on 4427 failure. 4428 4429 When implementing support for SQLite, or other DB which is purely 4430 file-based, the \code{host}, \code{user}, and \code{passwd} arguments 4431 would be ignored while \code{dbname} would specify the path to the 4432 SQLite db file. 4433 4434 \subsubsection{Interacting with Database Tables} 4435 4436 The functions in this section perform high level interactions with the 4437 database tables. All of them should behave ``atomically'' with 4438 respect to the state of the database. Specifically, all interactions 4439 with the database should be done as a part of a transaction that is 4440 rolled-back on failure and committed only after all queries used by 4441 the API have been run. In general, this API set attempts to treat a 4442 database table as a 2D matrix where columns can be represented by a 4443 \code{psVector} and rows as a \code{psMetadata} type. A 4444 \code{psMetadata} collection is also used to define the columns of a 4445 table and as part of the query restrictions. 4446 4447 \begin{verbatim} 4448 bool psDBCreateTable(psDB *dbh, const char *tableName, psMetadata *md); 4449 \end{verbatim} 4450 4451 This function generates and executes the SQL needed to create a table 4452 named \code{tableName}, with the column names and datatypes as 4453 described in \code{md}. Each data item in the \code{psMetadata} 4454 collection represents a single table field. The name of the field is 4455 given by the name of the \code{psMetadataItem} and the data type is 4456 give by the \code{psMetadataItem.type} and \code{psMetadataItem.ptype} 4457 entries. A lookup table should be used to convert from PSLib types 4458 into MySQL compatible SQL data types. For example, a 4459 \code{PS_META_STR} would map to an SQL99 varchar. If the value of 4460 \code{type} is \code{PS_META_STR} then the \code{psMetadataItem.data} 4461 element is set to a string with the length for the field written as a 4462 text string. The value of the \code{psMetadataItem.data} element is 4463 unused for the \code{PS_META_PRIMITIVE} types. Other metadata types 4464 beyond \code{PS_META_STR} and \code{PS_META_PRIMITIVE} are not allowed 4465 in a table definition metadata collection. 4466 4467 Database indexes can be specified setting the \code{comment} field to 4468 ``\code{Primary Key}'' or ``\code{Key}''. Comment are otherwise 4469 ignored. 4470 4471 \begin{verbatim} 4472 bool psDBDropTable(psDB *dbh, const char *tableName); 4473 \end{verbatim} 4474 4475 This function deletes the specified table. 4476 4477 \begin{verbatim} 4478 psArray *psDBSelectColumn(psDB *dbh, const char *tableName, const char *col, const psU64 limit); 4479 psVector *psDBSelectColumnNum(psDB *dbh, const char *tableName, const char *col, psElemType pType, const psU64 limit); 4480 \end{verbatim} 4481 4482 These functions generates and executes the SQL needed to select an entire 4483 column from a table or up to \code{limit} rows from it. If \code{limit} is 0, 4484 the entire range is returned. The database response is processed and a 4485 \code{psArray} of strings is returned. The Num version of the function returns 4486 the data in a \code{psVector}, data cast to \code{pType}. It returns an error 4487 (NULL) if the requested field is not a numerical type. 4488 4489 \begin{verbatim} 4490 psArray *psDBSelectRows(psDB *dbh, const char *tableName, psMetadata *where, const psU64 limit); 4491 \end{verbatim} 4492 4493 This function returns rows from the specified table which match 4494 the restrictions given by \code{where}. The restrictions are 4495 specified as field / value pairs. The \code{psMetadata} collection 4496 where must consist of valid database fields, though the database query 4497 checking functions may be used to validate the fields as part of the 4498 query. If \code{where} is \code{NULL}, then there are no restrictions 4499 on the rows selected. The selected rows are returned as a 4500 \code{psArray} of \code{psMetadata} values, one per row. 4501 4502 \begin{verbatim} 4503 bool psDBInsertOneRow(psDB *dbh, const char *tableName, psMetadata *row); 4504 \end{verbatim} 4505 4506 Insert the data from \code{row} into \code{tableName}. It should be noted in 4507 the API reference that if fields are specified in \code{row} that do not exist 4508 in \code{tablename}, the insert will fail. 4509 4510 \begin{verbatim} 4511 bool psDBInsertRows(psDB *dbh, const char *tableName, psArray *rowSet); 4512 \end{verbatim} 4513 4514 Similar to \code{psDBInsertOneRow()}, this function inserts many rows at once 4515 and is atomic for the complete set of rows. 4516 4517 \begin{verbatim} 4518 psArray *psDBDumpRows(psDB *dbh, const char *tableName); 4519 \end{verbatim} 4520 4521 Fetch all rows as an psArray of psMetadata. 4522 4523 \begin{verbatim} 4524 psMetadata *psDBDumpCols(psDB *dbh, const char *tableName); 4525 \end{verbatim} 4526 4527 Fetch all columns, as either a psVector or a psArray depnding on whether or not 4528 the column is numeric, and return them in a psMetadata structure where 4529 psMetadataItem.name contains the column's name. 4530 4531 \begin{verbatim} 4532 psS64 psDBUpdateRows(psDB *dbh, const char *tableName, psMetadata *where, psMetadata *values); 4533 \end{verbatim} 4534 4535 Update the columns contained in \code{values} in the row(s) that have a field 4536 with the value indicated by \code{where} (note that this is only allows very 4537 limited use of SQL99's ``where'' semantics). The number of rows modified is 4538 returned. A negative value is return to indicate an error. If there are 4539 multiple psMetadataItems in \code{where} then each item should be considered as 4540 an additional constraint. e.g. ``where foo = x and where bar = y'' 4541 4542 \begin{verbatim} 4543 psS64 psDBDeleteRows(psDB *dbh, const char *tableName, psMetadata *where); 4544 \end{verbatim} 4545 4546 Delete the rows that are matched by \code{where} using the same semantics for 4547 \code{where} as in psDBUpdateRow(). A negative value is returned to indicate an 4548 error. 4549 4550 \subsection{FITS I/O Functions} 4551 4552 We need a variety of I/O functions between the disk and certain of our 4553 PSLib data structures. We need the ability to access FITS headers, 4554 images and tables (both ASCII and Binary). We define here the FITS 4555 I/O functions, all of which are currently specified as wrappers to 4556 functions within CFITSIO. CFITSIO provides a wide range of utilities 4557 which we do not feel are particularly appropriate as part of a generic 4558 I/O library, such as assumptions about names which change the data 4559 interpretation, etc. We are defining our calls to avoid the hidden 4560 'features'. The CFITSIO functions which are wrapped should in general 4561 be the most basic versions. 4562 4563 \begin{verbatim} 4564 typedef struct { 4565 fitsfile fd; 4566 } psFits; 4567 \end{verbatim} 4568 We begin by defining a datatype to wrap the CFITSIO \code{fitsfile} 4569 structure. This is necessary to allow repeated access to the data in 4570 a file without multiple open commands (which are expensive). 4571 4572 \subsubsection{FITS File Manipulations} 4573 4574 \begin{verbatim} 4575 psFits *psFitsAlloc(const char *filename); 4576 \end{verbatim} 4577 4578 Opens a FITS file at positions the pointer to the PHU. 4579 4580 \begin{verbatim} 4581 bool psFitsMoveExtName(psFits *fits, const char *extname); 4582 \end{verbatim} 4583 4584 Positions the pointer to the beginning of the specified 4585 \code{extname}. If the \code{extname} does not exist, the function 4586 shall fail. 4587 4588 \begin{verbatim} 4589 bool psFitsMoveExtNum(psFits* fits, int extnum, bool relative); 4590 \end{verbatim} 4591 4592 Moves the pointer to the beginning of the specified HDU number. If 4593 \code{relative} is TRUE, \code{extnum} represents the number of HDUs 4594 relative to the current HDU. The PHU is entry number 0, while the 4595 extended data segments start at number 1. 4596 4597 \begin{verbatim} 4598 int psFitsGetExtNum(psFits* fits); 4599 \end{verbatim} 4600 4601 Returns the current HDU number (i.e., file position). 4602 4603 \begin{verbatim} 4604 int psFitsGetSize(psFits* fits); 4605 \end{verbatim} 4606 4607 Returns the number of HDUs in the file. 4608 4609 \begin{verbatim} 4610 psFitsType psFitsGetExtType(psFits* fits); 4611 \end{verbatim} 4612 4613 Gets the current HDU's type (table or image). 4614 4615 \subsubsection{FITS Header I/O Functions} 4616 4617 \begin{verbatim} 4618 psMetadata *psFitsReadHeader(psMetadata *out, const psFits *fits); 4619 \end{verbatim} 4620 Read header data into a \code{psMetadata} structure. The data is read 4621 from the current HDU pointed at by the \code{psFits *fits} entry. If 4622 \code{out} is \code{NULL}, a new psMetadata is created. 4623 4624 \begin{verbatim} 4625 psMetadata *psFitsReadHeaderSet (psFits *fits); 4626 \end{verbatim} 4627 Load a complete set of headers from the \code{psFits} file pointer. 4628 This function loads the headers from all extensions into a 4629 \code{psMetadata} collection, each entry of which is a pointer to a 4630 \code{psMetadata} structure containing the header data. The metadata 4631 entry names are the \code{EXTNAME} values for each header (with the 4632 value of \code{PHU} for the primary header unit). At the start of the 4633 operation, the file pointer is rewound to the beginning of the file. 4634 At the end, it is positioned where it started when the function was 4635 called. 4636 4637 \begin{verbatim} 4638 bool psFitsWriteHeader(psMetadata *output, const psFits *fits); 4639 \end{verbatim} 4640 Write metadata into the header of a FITS image file. The header is 4641 written at the current HDU. 4642 4643 \subsubsection{FITS Image I/O Functions} 4644 4645 \begin{verbatim} 4646 psImage *psFitsReadImage(psImage *output, psFits *fits, psRegion region, int z); 4647 \end{verbatim} 4648 Read an image or subimage from the \code{psFits} file pointer. This 4649 function is a wrapper to the CFITSIO library function. The input 4650 parameters allow a full image or a subimage to be read. The region to 4651 be read is specified by \code{region}. A negative value for either of 4652 \code{region.x1} or \code{region.y1} specifies the size of the region 4653 to be read counting down from the end of the array. 4654 4655 If the native image is a cube, the value of z specifies the requested 4656 slice of the image. This function must call \code{psError} and return 4657 \code{NULL} if any of the specified parameters are out of range for 4658 the data in the image file, or if the image on disk is zero- or 4659 one-dimensional. This function need only read images of the native 4660 FITS image types (\code{psU8}, \code{psS16}, \code{psS32}, 4661 \code{psF32}, \code{psF64}). The user is expected to convert the data 4662 type as needed with \code{psImageCopy}. 4663 4664 \begin{verbatim} 4665 bool psFitsUpdateImage(psFits *fits, const psImage *input, psRegion region, int z); 4666 \end{verbatim} 4667 \tbd{we have discussed this as the alternate name} 4668 Write an image section to the open \code{psFits} file pointer. This 4669 operation may write a portion of an image over the existing bytes of 4670 an existing image. Care must be taken to interpret \code{region}, 4671 which specified the output pixels to be written / over-written. If 4672 the combination of \code{region} and the size of \code{psImage *input} 4673 implies writing pixels outside the existing data area of the image, 4674 the function shall return an error (ie, if \code{region.x0 + image.nx 4675 >= NAXIS1}, \code{region.y0 + image.ny >= NAXIS2}, or \code{z >= 4676 NAXIS3}). This function will only write images of the native FITS 4677 image types (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, 4678 \code{psF64}). The user is expected to convert the data type as 4679 needed with \code{psImageCopy}. The return value must be 0 for a 4680 successful operation and 1 for an error. 4681 4682 \begin{verbatim} 4683 bool psFitsWriteImage(psFits *fits, psMetadata *header, const psImage *input, int depth); 4684 \end{verbatim} 4685 Create a new image based on the dimensions specified for the image and 4686 the requested depth. The header and image data segments are written 4687 in the file at the current position of the \code{psFits} pointer. 4688 This function will only write images of the native FITS image types 4689 (\code{psU8}, \code{psS16}, \code{psS32}, \code{psF32}, \code{psF64}). 4690 The user is expected to convert the data type as needed with 4691 \code{psImageCopy}. The return value must be 0 for a successful 4692 operation and 1 for an error. 4693 4694 \subsubsection{FITS Table I/O Functions} 4695 4696 \begin{verbatim} 4697 psMetadata *psFitsReadTableRow (psFits *fits, int row); 4698 \end{verbatim} 4699 This function reads a single row of the table in the extension pointed 4700 at by the \code{psFits} file pointer. The row number to be read is 4701 given by \code{row}. The result is returned as a \code{psMetadata} 4702 collection with elements of the apporpriate types and keys 4703 corresponding to the table column names. The function must apply the 4704 needed byte-swapping on the data in the row based on the description 4705 of the table data in the table header. \tbr{we may need to be more 4706 flexible here: if we call this function repeatedly, it would be more 4707 efficient to pass the corresponding header or keep it somewhere (and 4708 the file pointer location, for that matter).} 4709 4710 \begin{verbatim} 4711 void *psFitsReadTableRowRaw (int *nBytes, psFits *fits, int row); 4712 \end{verbatim} 4713 This function reads a single row of the table in the extension pointed 4714 at by the \code{psFits} file pointer. The row number to be read is 4715 given by \code{row}. The result is returned as collection of 4716 \code{nBytes} bytes allocated by the function. The function must 4717 apply the needed byte-swapping on the data in the row based on the 4718 description of the table data in the table header. \tbr{we may need 4719 to be more flexible here: if we call this function repeatedly, it 4720 would be more efficient to pass the corresponding header or keep it 4721 somewhere (and the file pointer location, for that matter).} 4722 4723 \begin{verbatim} 4724 psArray *psFitsReadTableColumn (psFits *fits, char *colname); 4725 \end{verbatim} 4726 This function reads a single column of the table in the extension 4727 pointed at by the \code{psFits} file pointer. The column is specified 4728 by the FITS table column key given by \code{row}. The result is 4729 returned as a \code{psArray}, with the data from one row of the table 4730 column per array element. 4731 4732 \begin{verbatim} 4733 psVector *psFitsReadTableColumnNum (psFits *fits, char *colname); 4734 \end{verbatim} 4735 This function reads a single column of the table in the extension 4736 pointed at by the \code{psFits} file pointer. The column is specified 4737 by the FITS table column key given by \code{row} and must be of a 4738 numeric data type. The result is returned as a \code{psVector} of the 4739 appropriate data type, with the data from one row of the table column 4740 per array element. 4741 4742 \begin{verbatim} 4743 psArray *psFitsReadTableRaw (int *nBytes, psFits *fits); 4744 \end{verbatim} 4745 This function reads the entire data block from a table into the a 4746 \code{psArray}, with one element of the array per row. The number of 4747 bytes per row is returned in \code{nBytes}. The function must apply 4748 the needed byte-swapping on the data in each row based on the 4749 description of the table data in the table header. 4750 4751 \begin{verbatim} 4752 psArray *psFitsReadTable (psFits *fits); 4753 \end{verbatim} 4754 This function reads the entire data block from a table into the a 4755 \code{psArray}, with one element of the array per row. Each row is 4756 stored as a \code{psMetadata} collection as described above for 4757 \code{psFitsReadTableRow}. 4758 4759 \begin{verbatim} 4760 bool psFitsWriteTable(psFits* fits, psMetadata *header, psArray* table); 4761 \end{verbatim} 4762 Accepts a \code{psArray} of \code{psMetadata} and writes it to the 4763 current HDU. If the current HDU is not a table type, this will fail 4764 and return FALSE. 4765 4766 \begin{verbatim} 4767 bool psFitsUpdateTable(psFits* fits, psMetadata *header, psMetadata* data, int row); 4768 \end{verbatim} 4769 Writes the \code{psMetadata} data to a FITS table at the specified row 4770 in the current HDU. If the current HDU is not a table type, this will 4771 fail and return FALSE. 4772 4773 \subsection{Detector and Sky Coordinates} 4847 \subsection{Linear and Spherical Coordinates} 4774 4848 4775 4849 Both detector and sky positions will be used extensively in the IPP. 4776 4850 The first are linear coordinates which conform to Euclidean geometry 4777 while the second are angular coordinates for which additional care 4778 must often be taken. We put these into two structures, \code{psPlane} 4779 and \code{psSphere}, respectively. Partitioning these two will enable 4780 error-checking. 4851 while the second are angular coordinates which define a position on 4852 the sphere of the sky. We put these into two structures, 4853 \code{psPlane} and \code{psSphere}, respectively. Partitioning these 4854 two will enable error-checking. An alternative representation for 4855 angular positions is the 3-D unit vector. These are used in 4856 particular as part of spherical rotation calculations. We define 4857 \code{psCube} to represent such an element. 4781 4858 % 4782 4859 \begin{verbatim} … … 4794 4871 double dErr; ///< Error in Dec 4795 4872 } psSphere; 4873 4874 typedef struct { 4875 double x; ///< cos (DEC) cos (RA) 4876 double y; ///< cos (DEC) sin (RA) 4877 double z; ///< sin (DEC) 4878 double xErr; ///< Error in x 4879 double yErr; ///< Error in y 4880 double zErr; ///< Error in z 4881 } psCube; 4796 4882 \end{verbatim} 4797 4883 … … 4818 4904 Constructors for these are straight-forward: 4819 4905 \begin{verbatim} 4820 psPlane *psPlaneAlloc(void);4906 psPlane *psPlaneAlloc(void); 4821 4907 psSphere *psSphereAlloc(void); 4908 psCube *psCubeAlloc(void); 4822 4909 \end{verbatim} 4823 4910 Initialization of the structures is not necessary. … … 4985 5072 \code{NULL}, the function shall generate an error and return 4986 5073 \code{NULL}. 4987 4988 4989 \subsubsection{Celestial Coordinate Conversions}4990 4991 We need to be able to convert between ICRS, Galactic and Ecliptic4992 coordinates, and potentially between arbitrary spherical coordinate4993 systems. All of these basic spherical transformations represent4994 rotations of the spherical coordinate reference. We specify a general4995 transformation function which takes a structure,4996 \code{psSphereTransform}, defining the transformation between two4997 spherical coordinate systems (the structure contains the sines and4998 cosines of the angles involved so as to minimize computation time for4999 repeated transformations). We also define a function to generate5000 \code{psSphereTransform}, based on the three angles5001 describing the location of the pole and the relative equatorial5002 rotations of the two systems. We also specify special functions to5003 return the \code{psSphereTransform} for transformations5004 between standard coordinate systems.5005 5006 \begin{verbatim}5007 typedef struct {5008 double cosDeltaP; ///< Cosine of target pole latitude in the source system5009 double sinDeltaP; ///< Sine of target pole latitude in the source system5010 double alphaP; ///< Longitude of the target system pole in the source system5011 double phiP; ///< Longitude of the ascending node in the target system5012 } psSphereTransform;5013 \end{verbatim}5014 5015 The constructor is defined as follows:5016 \begin{verbatim}5017 psSphereTransform *psSphereTransformAlloc(double alphaP, double deltaP, double phiP);5018 \end{verbatim}5019 where \code{alphaP} and \code{deltaP} define the coordinates in the5020 input system of the north pole in the output system and \code{phiP}5021 defines the longitude in the input system of the equatorial5022 intersection between the two systems (e.g, the first point of Ares).5023 The constructor must calculate the sines and cosines above.5024 5025 Spherical coordinates may be transformed by providing the5026 transformation and the coordinate in the input system to5027 \code{psSphereTransform}:5028 \begin{verbatim}5029 psSphere *psSphereTransformApply(psSphere *out,5030 const psSphereTransform *transform,5031 const psSphere *coord);5032 \end{verbatim}5033 5034 The following functions simply return the appropriate5035 \code{psSphereTransform} to convert between predefined spherical5036 coordinate systems (i.e., ICRS, Ecliptic and Galactic). These are5037 constructors as well as the above \code{psSphereTransformAlloc}.5038 %5039 \begin{verbatim}5040 psSphereTransform *psSphereTransformICRSToEcliptic(psTime *time);5041 psSphereTransform *psSphereTransformEclipticToICRS(psTime *time);5042 psSphereTransform *psSphereTransformICRSToGalactic(void);5043 psSphereTransform *psSphereTransformGalacticToICRS(void);5044 \end{verbatim}5045 5046 We also require the ability to precess coordinates from one equinox to5047 another.5048 5049 \begin{verbatim}5050 psSphere *psSpherePrecess(psSphere *coords, const psTime *fromTime, const psTime *toTime);5051 \end{verbatim}5052 5053 Given coordinates, \code{coords}, with equinox for \code{fromTime},5054 the coordinates are precessed to equinox for \code{toTime}. The5055 \code{coords} are modified in-place. Equinoxes shall be Julian5056 equinoxes (as opposed to Bessellian).5057 5058 \subsubsection{Projections}5059 5060 We require functions to convert between spherical and linear5061 coordinate systems based on a variety of projections. The required5062 projections include:5063 \begin{itemize}5064 \item TAN5065 \item SIN5066 \item AIT5067 \item PAR5068 \end{itemize}5069 5070 We specify the following structure \code{psProjection} to define the5071 parameters of the projection:5072 \begin{verbatim}5073 typedef struct {5074 double R, D; ///< coordinates of projection center5075 double Xs, Ys; ///< plate-scale in X and Y directions5076 psProjectionType type; ///< projection type5077 } psProjection;5078 \end{verbatim}5079 5080 The projection type is defined by the following enumerated type \code{psProjectionType}:5081 \begin{verbatim}5082 typedef enum { ///< type of val is:5083 PS_PROJ_TAN, ///< Tangent projection5084 PS_PROJ_SIN, ///< Sine projection5085 PS_PROJ_AIT, ///< Aitoff projection5086 PS_PROJ_PAR, ///< Par projection5087 PS_PROJ_NTYPE ///< Number of types; must be last5088 } psProjectionType;5089 \end{verbatim}5090 5091 The constructor is straight-forward:5092 \begin{verbatim}5093 psProjection *psProjectionAlloc(double R, double D, double Xs, double Ys, psProjectionType type);5094 \end{verbatim}5095 5096 The following functions will project and deproject (respectively)5097 spherical coordinates:5098 5099 \begin{verbatim}5100 psPlane *psProject(const psSphere *coord, const psProjection *projection);5101 psSphere *psDeproject(const psPlane *coord, const psProjection *projection);5102 \end{verbatim}5103 5104 \subsubsection{Offsets}5105 We require a function to calculate the offset between two positions on5106 the sky, as well as a function to apply an offset to a position. The5107 first determines the offset (RA,Dec) on the sky between two positions.5108 The second applies the given offset to the coordinate. Both an offset5109 mode and an offset unit may be defined. The mode may be either5110 \code{PS_SPHERICAL}, in which case the specified offset corresponds to5111 an offset in angles, or it may be \code{PS_LINEAR}, in which case the5112 offset corresponds to a linear offset in a local projection. The5113 offset unit may be in one of \code{PS_ARCSEC}, \code{PS_ARCMIN},5114 \code{PS_DEGREE}, and \code{PS_RADIAN}, which specifies the units of5115 the offset only.5116 5117 \begin{verbatim}5118 psSphere *psSphereGetOffset(const psSphere *position1,5119 const psSphere *position2,5120 psSphereOffsetMode mode,5121 psSphereOffsetUnit unit);5122 5123 psSphere *psSphereSetOffset(const psSphere *position,5124 const psSphere *offset,5125 psSphereOffsetMode mode,5126 psSphereOffsetUnit unit);5127 5128 typedef enum {5129 PS_SPHERICAL; ///< Offset on a sphere5130 PS_LINEAR; ///< Linear offset5131 } psSphereOffsetMode;5132 5133 typedef enum {5134 PS_ARCSEC; ///< Arcseconds5135 PS_ARCMIN; ///< Arcminutes5136 PS_DEGREE; ///< Degrees5137 PS_RADIAN; ///< Radians5138 } psSphereOffsetUnit;5139 \end{verbatim}5140 Note that these should propagate the errors appropriately.5141 5142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5143 5144 %%% Astronomical Images and Astrometry5145 \include{psLibSDRS_Astrom}5146 5147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5148 5149 \subsection{Pixel Lists}5150 5151 Usually an image mask is the best way to carry information about what5152 pixels mean what. However, in the case where the number of pixels in5153 which we are interested is limited, it is more efficient to simply5154 carry a list of pixels. An example of this is in the image5155 combination code, where we want to perform an operation on a5156 relatively small fraction of pixels, and it is inefficient to go5157 through an entire mask image checking each pixel.5158 5159 \begin{verbatim}5160 typedef struct {5161 psVector *x; // x coordinate5162 psVector *y; // y coordinate5163 } psPixels;5164 \end{verbatim}5165 5166 Of course, the size of each of the vectors should match. In the event5167 that they do not match, any function which detects the problem shall5168 generate a warning and use the size of the shorter of the vectors as5169 the size. The order in which the pixels are kept is not considered5170 important.5171 5172 \begin{verbatim}5173 psImage *psPixelsToMask(psImage *out, const psPixels *pixels, const psRegion *region, unsigned int maskVal);5174 psPixels *psMaskToPixels(psPixels *out, const psImage *mask, unsigned int maskVal);5175 \end{verbatim}5176 5177 \code{psPixelsToMask} shall return an image of type U8 with the5178 \code{pixels} lying within the specified \code{region} set to the5179 \code{maskVal}. The \code{out} image shall be modified if supplied,5180 or allocated and returned if \code{NULL}. The size of the output5181 image shall be \code{region->x1 - region->x0} by \code{region->y1 -5182 region->y0}, with \code{out->x0 = region->x0} and \code{out->y0 =5183 region->y0}. In the event that either of \code{pixels} or5184 \code{region} are \code{NULL}, the function shall generate an error5185 and return \code{NULL}.5186 5187 \code{psMaskToPixels} shall return a \code{psPixels} consisting of the5188 coordinates in the \code{mask} that match the \code{maskVal}. The5189 \code{out} pixel list shall be modified if supplied, or allocated and5190 returned if \code{NULL}. In hte event that \code{mask} is5191 \code{NULL}, the function shall generate an error and return5192 \code{NULL}.5193 5194 \begin{verbatim}5195 psPixels *psPixelsConcatenate(psPixels *out, const psPixels *pixels);5196 \end{verbatim}5197 5198 \code{psPixelsConcatenate} shall concatenate \code{pixels} onto5199 \code{out}. In the event that \code{out} is \code{NULL}, a new5200 \code{psPixels} shall be allocated, and the contents of \code{pixels}5201 simply copied in. If \code{pixels} is \code{NULL}, the function shall5202 generate an error and return \code{NULL}. The function shall take5203 care to ensure that there are no duplicate pixels in \code{out} (since5204 the order in which the pixels are stored is not important, the values5205 may be sorted, allowing the use of a faster algorithm than a linear5206 scan).5207 5074 5208 5075 \begin{verbatim} … … 5228 5095 and return \code{NULL}. 5229 5096 5230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5097 \subsubsection{Spherical Rotations} 5098 5099 Spherical rotations represent coordinate transformation in 3-D, as 5100 well as the effects of precession and nutation. We need spherical 5101 rotatations to convert between ICRS, Galactic and Ecliptic 5102 coordinates, and to determine Alt-Az coordinates for sources. All of 5103 these basic spherical transformations represent rotations of the 5104 spherical coordinate reference. We specify a general transformation 5105 function which takes a structure, \code{psSphereRot}, defining the 5106 transformation between two spherical coordinate systems. The 5107 structure contains the elements of a quaternion to represent the 5108 spherical rotational. We define two allocators for 5109 \code{psSphereRot}, one which defines the rotation in terms of the 5110 coordinate of the pole and the rotation about that pole. The other 5111 defines the rotation from the elements of the quaternion. We also 5112 specify functions to manipulate \code{psSphereRot} in several useful 5113 way. 5114 5115 \begin{verbatim} 5116 typedef struct { 5117 double q0; 5118 double q1; 5119 double q2; 5120 double q3; 5121 } psSphereRot; 5122 \end{verbatim} 5123 5124 The constructor is defined as follows: 5125 \begin{verbatim} 5126 psSphereRot *psSphereRotAlloc(double alphaP, double deltaP, double phiP); 5127 \end{verbatim} 5128 where \code{alphaP} and \code{deltaP} define the coordinates in the 5129 input system of the axis of rotation (the north pole of the output 5130 system), while \code{phiP} defines the rotation about that pole. This 5131 last angle is also equal to 270\degree - $\phi_a$, where $\phi_a$ is 5132 the longitude in the output system of the ascending node (equatorial 5133 intersection between the two systems, e.g, the first point of Ares). 5134 5135 The \code{psSphereRot} may also be constructed by supplying the 5136 elements of the quaternion to the following function: 5137 \begin{verbatim} 5138 psSphereRot *psSphereRotQuat(double q0, double q1, double q2, double q3); 5139 \end{verbatim} 5140 This function normalizes the quaternion, so the input elements need 5141 not be normalized. 5142 5143 Spherical coordinates may be transformed by providing the 5144 transformation and the coordinate in the input system to 5145 \code{psSphereRot}. The output pointer may be optionally supplied, or 5146 if \code{NULL}, is allocated by the function. 5147 5148 \begin{verbatim} 5149 psSphere *psSphereRotApply(psSphere *out, const psSphereRot *transform, const psSphere *coord); 5150 \end{verbatim} 5151 5152 The following function combines two rotations, to produce a single 5153 rotation which is the equivallent of applying the first rotation and 5154 then the second. The output rotation may be supplied, or will be 5155 allocated if \code{NULL}. 5156 5157 \begin{verbatim} 5158 psSphereRot *psSphereRotCombine(psSphereRot *out, psSphereRot *rot1, psSphereRot *rot2) 5159 \end{verbatim} 5160 5161 The following function changes the given rotation to its inverse: 5162 5163 \begin{verbatim} 5164 psSphereRot *psSphereRotInvert(psSphereRot *rot) 5165 \end{verbatim} 5166 5167 The 3-vector representation of the angles (\code{psCube}) is needed to 5168 implement these functions, and is useful in other circumstances as 5169 well. Two utility functions are provided to convert between the 5170 angular and 3-vector representations: 5171 \begin{verbatim} 5172 psSphere *psCubeToSphere(psCube *cube); 5173 psCube *psSphereToCube(psSphere *sphere); 5174 \end{verbatim} 5175 5176 \subsubsection{Offsets} 5177 We require a function to calculate the offset between two positions on 5178 the sky, as well as a function to apply an offset to a position. The 5179 first determines the offset (RA,Dec) on the sky between two positions. 5180 The second applies the given offset to the coordinate. Both an offset 5181 mode and an offset unit may be defined. The mode may be either 5182 \code{PS_SPHERICAL}, in which case the specified offset corresponds to 5183 an offset in angles, or it may be \code{PS_LINEAR}, in which case the 5184 offset corresponds to a linear offset in a local projection. The 5185 offset unit may be in one of \code{PS_ARCSEC}, \code{PS_ARCMIN}, 5186 \code{PS_DEGREE}, and \code{PS_RADIAN}, which specifies the units of 5187 the offset only. 5188 5189 \begin{verbatim} 5190 psSphere *psSphereGetOffset(const psSphere *position1, 5191 const psSphere *position2, 5192 psSphereOffsetMode mode, 5193 psSphereOffsetUnit unit); 5194 5195 psSphere *psSphereSetOffset(const psSphere *position, 5196 const psSphere *offset, 5197 psSphereOffsetMode mode, 5198 psSphereOffsetUnit unit); 5199 5200 typedef enum { 5201 PS_SPHERICAL; ///< Offset on a sphere 5202 PS_LINEAR; ///< Linear offset 5203 } psSphereOffsetMode; 5204 5205 typedef enum { 5206 PS_ARCSEC; ///< Arcseconds 5207 PS_ARCMIN; ///< Arcminutes 5208 PS_DEGREE; ///< Degrees 5209 PS_RADIAN; ///< Radians 5210 } psSphereOffsetUnit; 5211 \end{verbatim} 5212 Note that these should propagate the errors appropriately. 5213 5214 \subsection{Celestial Coordinate Systems} 5215 5216 The following functions simply return the appropriate 5217 \code{psSphereRot} to convert between predefined spherical 5218 coordinate systems (i.e., ICRS, Ecliptic and Galactic). These are 5219 constructors as well as the above \code{psSphereRotAlloc}. 5220 % 5221 \begin{verbatim} 5222 psSphereRot *psSphereRotICRSToEcliptic(psTime *time); 5223 psSphereRot *psSphereRotEclipticToICRS(psTime *time); 5224 psSphereRot *psSphereRotICRSToGalactic(void); 5225 psSphereRot *psSphereRotGalacticToICRS(void); 5226 \end{verbatim} 5227 5228 \subsection{Earth Orientation Calculations} 5229 5230 One of the critical sets of calculations in astronomy is the sequence 5231 of steps needed to convert between the celestial coordinates of an 5232 object and the observed coordinates of the object. This problem is 5233 best divided into two major components: transformation between the 5234 celestial sphere and coordinates relative to the surface of the solid 5235 earth, excluding the effects of the atmosphere, and compensation for 5236 the effects of the atmosphere. In this section, we address the first 5237 of these two transformations: the Earth Orientation Calculations. 5238 5239 The Earth Orientation Calculations are further subdivided into several 5240 steps, illustrated in Figure~\ref{CoordinateSystems} . Celestial 5241 coordinates are defined in the International Celestial Reference 5242 System (ICRS), which has the solar barycenter as its reference 5243 position and velocity. The next coordinate system is the Geocentric 5244 Celestial Reference System (GCRS), which uses the earth barycenter as 5245 a reference. The transformation between these two includes the 5246 abberation due to the Earth's velocity, the parallax of the object, 5247 which depends on both the Earth's position and the distance to the 5248 object of interest, and the general relativistic correction for the 5249 bending of light as it approaches the Earth. 5250 5251 The next set of transformations compenstate for the 3-D rotation of 5252 the Earth on various timescales, including the effects of precession, 5253 nutation, and simple solid-body rotation. These calculations can be 5254 performed using different amounts of information for higher levels of 5255 precision. Since the Earth's rotation is constantly affected by 5256 stochastic processes (weather, earthquakes, etc), these conversions 5257 are constantly modified by observations reported by authoratative 5258 sources such as the US Naval Observatory. The target of this 5259 transformation is the International Terrestrial Reference System 5260 (ITRS), which is fixed with respect to the Earth's crust. This 5261 transformation is subdivided into slow precesion and nutation 5262 (yielding the coordinate system CIP/CEO), followed by the Earth's 5263 rotation (yielding the coordinate system CIP/TEO), and finally 5264 corrections for the short-period motion of the Earth's pole. 5265 5266 \subsubsection{Transformation from ICRS to GCRS} 5267 5268 \tbd{we need a function to construct the direction and speed elements 5269 given the time}. 5270 5271 \tbd{supply the velocity as an un-normalized 3 vector?} 5272 5273 \paragraph{Aberration} 5274 The following function calculates the \code{apparent} position of a 5275 star, given its \code{actual} position and the velocity vector of the 5276 observer, represented as a speed and a direction: 5277 \begin{verbatim} 5278 psAberration(psSphere *apparent, psSphere *actual, psSphere direction, double speed); 5279 \end{verbatim} 5280 The \code{actual} and \code{apparent} positions are represented as 5281 \code{psSphere} entries, as is the \code{direction} of motion. The 5282 speed in that direction is given in units of the speed of light. 5283 5284 \paragraph{Gravitational Deflection} 5285 5286 \paragraph{Parallax} 5287 5288 \begin{verbatim} 5289 double psEOC_ParallaxFactor(psSphere *coords, psTime *time); 5290 \end{verbatim} 5291 Calculate the parallax factor for the given position and time. 5292 5293 \subsubsection{Transformation from GCRS to ITRS} 5294 5295 \paragraph{Precession/Nutation} 5296 5297 The following routine calculates the components of the rotation 5298 between the CEO and GCRS frames, $X$, $Y$, and $s$, using to the 5299 IAU2000A precession \& nutation model: 5300 % 5301 \begin{verbatim} 5302 psSphere *psEOC_PrecessionModel(double *s, const psTime *time) 5303 \end{verbatim} 5304 % 5305 The input to this function is the desired \code{time}, which may be 5306 represented in any format other than UT1. This routine must give 5307 results identical to the IERS XYS2000A subroutine within the limits of 5308 machine accuracy. 5309 5310 The following function provides interpolated corrections to $X$ and 5311 $Y$ from the tables provided by the IERS, just as it does for UT1 and 5312 polar motion. 5313 5314 \begin{verbatim} 5315 psSphere *psEOC_GetPolarCorr(const psTime *time, psTimeBulletin bulletin); 5316 \end{verbatim} 5317 5318 The polar correction is applied to the $X$ and $Y$ elements of the 5319 rotation to provide higher accuracy. The spherical rotation term is 5320 generated by providing the three elements of the rotation to the 5321 following function: 5322 \begin{verbatim} 5323 psSphereRot *psSphereRot_CEOtoGCRS(double s, const psSphere *pole) 5324 \end{verbatim} 5325 The retulting \code{psSphereRot} may be used to determine the rotation 5326 from CIP/CEO to GCRS. This function must give results identical to 5327 the IERS BPN2000, within the limits of machine accuracy. 5328 5329 \paragraph{Earth Rotation} 5330 5331 The following routine calculates the rotation of the Earth about the CIP: 5332 \begin{verbatim} 5333 psSphereRot *psSphereRot_TEOtoCEO(const psTime *time) 5334 \end{verbatim} 5335 The IERS code to create the comparable rotation is embedded in 5336 T2C2000, with the Earth Rotation Angle calculated by ERA2000. 5337 5338 \paragraph{Polar Motion} 5339 5340 The following function provides interpolated values of the polar 5341 motion components, $x_p$ and $y_p$, extracted from the IERS tables. 5342 \begin{verbatim} 5343 psSphere *psEOC_GetPoleCoords(const psTime *time, psTimeBulletin bulletin); 5344 \end{verbatim} 5345 5346 The following function provides tidal corrections to the polar motion 5347 components, $x_p$ and $y_p$, using the Ray model of Simon et al (see 5348 ADD). 5349 \begin{verbatim} 5350 psSphere *psEOC_TidePolarCorr(const psTime *time); 5351 \end{verbatim} 5352 5353 The following function provides the additional corrections due to nutation 5354 terms with periods less than or equal to two days: 5355 \begin{verbatim} 5356 psSphere *psEOC_NutationCorr(psTime *time); 5357 \end{verbatim} 5358 5359 The following function should generate the \code{psSphereRot} transform from 5360 ITRS to CIP/TEO: 5361 \begin{verbatim} 5362 psSphereRot *psSphereRot_ITRStoTEO(psSphere pole, psTime *time); 5363 \end{verbatim} 5364 The time argument should be used to internally calculate $s'$. 5365 This function should give identical results to the IERS POM2000 subroutine. 5366 5367 \subsubsection{Earth Orientation Wrappers} 5368 5369 The following function generates the complete spherical rotation to 5370 account for precession between two times. If \code{NULL} is provided 5371 for either time, it is assumed to have the reference equinox value of 5372 J2000. 5373 \begin{verbatim} 5374 psSphere *psSpherePrecess(const psTime *fromTime, const psTime *toTime, psPrecessMethod mode); 5375 \end{verbatim} 5376 The mode argument is used to specify the level of detail used in the 5377 calculation. 5378 5379 \begin{verbatim} 5380 typedef enum { 5381 PS_PRECESS_ROUGH, 5382 PS_PRECESS_COMPLETE, 5383 PS_PRECESS_IAU2000A, 5384 } psPrecessMethod; 5385 \end{verbatim} 5386 5387 \subsection{Atmospheric Effects} 5388 5389 \tbd{The ATM effects components should be deferred until we clean up 5390 the refraction definitions} 5391 5392 A-priori astrometric transformations between the telescope orientation 5393 (Alt/Az) and the predicted stellar coordinates above the atmosphere 5394 (DEC/HA) requires several pieces of information describing the current 5395 environmental conditions. These quantities are consistent across an 5396 image, and may vary only slowly with time. Pre-computing these 5397 quantities for exposures means that subsequent transformations are 5398 faster. The structure below carries the environmental data of interest. 5399 For historical reasons, this structure is known colloquially as ``the 5400 Grommit''. 5401 5402 \tbd{this structure needs to be modified to correspond to what we 5403 actually need to carry around for the atmosphere functions} 5404 5405 \tbd{provide a single Grommit to carry around all EOC + ATM 5406 pre-calculated entries and a separate structure for ATM effect?} 5407 5408 \begin{verbatim} 5409 typedef struct { 5410 const double latitude; ///< geodetic latitude (radians) 5411 const double longitude; ///< longitude + ... (radians) 5412 const double height; ///< height (HM) 5413 const double abberationMag; ///< magnitude of diurnal aberration vector 5414 const double temperature; ///< ambient temperature (TDK) 5415 const double pressure; ///< pressure (PMB) 5416 const double humidity; ///< relative humidity (RH) 5417 const double wavelength; ///< wavelength (WL) 5418 const double lapseRate; ///< lapse rate (TLR) 5419 const double refractA, refractB; ///< refraction constants A and B (radians) 5420 const double siderealTime; ///< local apparent sidereal time (radians) 5421 } psGrommit; 5422 \end{verbatim} 5423 5424 The \code{psGrommit} is calculated from telescope information for the 5425 particular exposure, \code{exp}: 5426 \begin{verbatim} 5427 psGrommit *psGrommitAlloc(const psExposure *exp); 5428 \end{verbatim} 5429 5430 \tbd{these functions probably need to take the ATM structure} 5431 5432 We require additional functions to perform general functions which 5433 will be useful for astrometry. Given coordinates on the sky, we 5434 need to get the airmass, the parallactic angle, and an estimate of 5435 the atmospheric refraction. 5436 5437 \begin{verbatim} 5438 float psGetAirmass(const psSphere *coord, psTime *lst, float height); 5439 \end{verbatim} 5440 which returns the airmass for a given position and local sidereal time 5441 (\code{lst}). 5442 5443 \begin{verbatim} 5444 float psGetParallactic(const psSphere *coord, double siderealTime); 5445 \end{verbatim} 5446 which returns the parallactic angle for a given position and sidereal time. 5447 5448 \begin{verbatim} 5449 float psGetRefraction(float colour, ///< Colour of object 5450 psPhotSystem colorPlus, ///< Colour reference 5451 psPhotSystem colorMinus, ///< Colour reference 5452 const psExposure *exp); ///< Telescope pointing information 5453 \end{verbatim} 5454 which provides an estimate of the atmospheric refraction, along the parallactic angle. 5455 5456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5457 5458 \subsection{Fixed Pattern} 5459 5460 The fixed pattern is a correction to the general astrometric solution 5461 formed by summing the residuals from many observations. The intent is 5462 to correct for higher-order distortions in the camera system on a 5463 coarse grid (larger than individual pixels, but smaller than a single 5464 cell). Hence, in addition to the offsets, we need to specify the size 5465 and scale of the grid in $x$ and $y$, as well as the origin of the 5466 grid. 5467 5468 \begin{verbatim} 5469 typedef struct { 5470 int nX, nY; ///< Number of elements in x and y 5471 double x0, y0; ///< Position of 0,0 corner on focal plane 5472 double xScale, yScale; ///< Scale of the grid 5473 double **x, **y; ///< The grid of offsets in x and y 5474 } psFixedPattern; 5475 \end{verbatim} 5476 5477 The constructor for \code{psFixedPattern} shall be: 5478 \begin{verbatim} 5479 psFixedPattern *psFixedPatternAlloc(double x0, double y0, 5480 double xScale, double yScale, 5481 const psImage *x, const psImage *y); 5482 \end{verbatim} 5483 Here, \code{x0}, \code{y0}, \code{xScale} and \code{yScale} have the 5484 same meaning as in the \code{psFixedPattern} structure. Note that the 5485 values of the fixed pattern offsets are specified as images, the 5486 values from which need to be copied into the \code{double **x} and 5487 \code{double **y} of \code{psFixedPattern}, and that the number of 5488 elements may be derived from the size of the images. 5489 5490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 5491 5492 \subsection{Projections} 5493 5494 We require functions to convert between spherical and linear 5495 coordinate systems based on a variety of projections. The required 5496 projections include: 5497 \begin{itemize} 5498 \item TAN 5499 \item SIN 5500 \item AIT 5501 \item PAR 5502 \end{itemize} 5503 5504 We specify the following structure \code{psProjection} to define the 5505 parameters of the projection: 5506 \begin{verbatim} 5507 typedef struct { 5508 double R, D; ///< coordinates of projection center 5509 double Xs, Ys; ///< plate-scale in X and Y directions 5510 psProjectionType type; ///< projection type 5511 } psProjection; 5512 \end{verbatim} 5513 5514 The projection type is defined by the following enumerated type \code{psProjectionType}: 5515 \begin{verbatim} 5516 typedef enum { ///< type of val is: 5517 PS_PROJ_TAN, ///< Tangent projection 5518 PS_PROJ_SIN, ///< Sine projection 5519 PS_PROJ_AIT, ///< Aitoff projection 5520 PS_PROJ_PAR, ///< Par projection 5521 PS_PROJ_NTYPE ///< Number of types; must be last 5522 } psProjectionType; 5523 \end{verbatim} 5524 5525 The constructor is straight-forward: 5526 \begin{verbatim} 5527 psProjection *psProjectionAlloc(double R, double D, double Xs, double Ys, psProjectionType type); 5528 \end{verbatim} 5529 5530 The following functions will project and deproject (respectively) 5531 spherical coordinates: 5532 5533 \begin{verbatim} 5534 psPlane *psProject(const psSphere *coord, const psProjection *projection); 5535 psSphere *psDeproject(const psPlane *coord, const psProjection *projection); 5536 \end{verbatim} 5537 5538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 5231 5539 5232 5540 \subsection{Photometry} … … 5298 5606 M_{\rm pM} - pA, M_{\rm sP} - M_{\rm sM} - sA)$. 5299 5607 5300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5609 5610 %%% Astronomical Images and Astrometry 5611 \include{psLibSDRS_Astrom} 5301 5612 5302 5613 \subsection{Astronomical objects} … … 5329 5640 \appendix 5330 5641 5642 \pagebreak 5331 5643 \section{Configuration File Test Inputs} 5332 5644 \label{sec:configtest} -
trunk/doc/pslib/psLibSDRS_Astrom.tex
r3181 r3564 270 270 \code{TRUE} if they are all correctly assigned, otherwise \code{FALSE}. 271 271 272 \subsubsection{ Coordinate Transformations}272 \subsubsection{Detector Coordinate Transformations} 273 273 274 274 \begin{figure} … … 322 322 \end{verbatim} 323 323 324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 325 326 % add psExposure to metadata? 327 % add grommit to metadata? 328 % add photsystem data to metadata? 329 % add statistics to metadata? 330 331 \subsubsection{Observatory data} 324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 325 326 \subsection{Astrometry} 327 328 Astrometry is a basic functionality required for the IPP that will be 329 used repeatedly, both for low-precision (roughly where is my favorite 330 object?) and high-precision (what is the proper motion of this star?). 331 As such, it must be flexible, yet robust. 332 333 \subsubsection{Coordinate frames} 334 \label{sec:coordinateFrames} 335 336 There are five coordinate frames that we need to worry about for the 337 purposes of astrometry: 338 \begin{itemize} 339 \item Cell: $(x,y)$ in pixels --- raw coordinates; 340 \item Chip: $(X,Y)$ in pixels --- the location on the silicon; 341 \item Focal Plane: $(p,q)$ in microns --- the location on the focal plane; 342 \item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and 343 \item Sky: (RA,Dec) --- ICRS. 344 \end{itemize} 345 346 The following steps are required to convert from the cell coordinates to 347 the sky: 348 \begin{itemize} 349 \item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$; 350 \item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$; 351 \item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) = 352 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the 353 object, respectively; and 354 \item TP $\longleftrightarrow$ Sky: transformation to the sky using 355 pre-computed coefficients for each pointing. 356 \end{itemize} 357 358 Note that the transformation between the Focal Plane and the Tangent 359 Plane is a four-dimensional polynomial, in order to account for any 360 possible dependencies in the astrometry on the stellar magnitude and 361 color; the former serves as a check for charge transfer 362 inefficiencies, while the latter will correct chromatic refraction, 363 both through the atmosphere and the corrector lenses. 364 365 We require structures to contain each of the above transformations as 366 well as the pixel data. 367 368 \subsubsection{Position Finding} 369 370 We require functions to return the structure containing given 371 coordinates. For example, we want the chip that corresponds to the 372 focal plane coordinates $(p,q) = (-1.234,+5.678)$. These routines 373 handle the one-to-many problem --- i.e., for one given focal plane 374 coordinate, there are many chips that this coordinate may be 375 correspond to; these functions will select the correct one. 376 % 377 \begin{verbatim} 378 psCell *psCellInFPA (const psPlane *coord, const psFPA *fpa); 379 psChip *psChipInFPA (const psPlane *coord, const psFPA *fpa); 380 psCell *psCellInChip(const psPlane *coord, const psChip *chip); 381 \end{verbatim} 382 383 \subsubsection{Conversion Functions} 384 385 We require functions to convert between the various coordinate frames 386 (Section~\ref{sec:coordinateFrames}). The hierarchy of the coordinate 387 frames and the transformations between each are shown in 388 Figure~\ref{fig:coco}. The functions that employ the transformations 389 are shown in Figure~\ref{fig:cocoFunc}. In addition to 390 transformations between each adjoining coordinate frame in the 391 hierarchy, we also require higher-level functions to convert between 392 the Cell and Sky coordinate frames; these will simply perform the 393 intermediate steps. 394 395 \begin{figure} 396 \psfig{file=coordinateFrames,height=7in,angle=-90} 397 \caption{The coordinate systems in the \PS{} IPP, and the relation 398 between each by transformations contained in the appropriate 399 structures.} 400 \label{fig:coco} 401 \end{figure} 402 403 \begin{figure} 404 \psfig{file=coordinateConv,height=7in,angle=-90} 405 \caption{Conversion between coordinate systems by PSLib.} 406 \label{fig:cocoFunc} 407 \end{figure} 408 409 We specify the following functions to convert between coordinates in 410 one type of frame to another type of frame. The first group consist 411 of unambiguous transformations: from the coordinates in a low-level 412 frame to the coordinates in the containing higher-level frame, of 413 which only one exists. In all of these functions, the output 414 coordinate structure may be \code{NULL} or may be supplied by the 415 calling function. In the former case, the structure must be 416 allocated; in the latter case, the supplied structure must be used. 417 418 \begin{verbatim} 419 psPlane *psCoordCellToChip (psPlane *out, const psPlane *in, const psCell *cell); 420 % astrometry comes from cell (no need for parent) 421 \end{verbatim} 422 which converts coordindates \code{in} on the specified \code{cell} to 423 the coordinates on the parent chip. 424 425 \begin{verbatim} 426 psPlane *psCoordChipToFPA (psPlane *out, const psPlane *in, const psChip *chip); 427 % astrometry comes from chip (no need for parent) 428 \end{verbatim} 429 which converts the coordinates \code{in} on the specified \code{chip} 430 to the coordinates on the parent FPA. 431 432 \begin{verbatim} 433 psPlane *psCoordFPAToTP(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa); 434 % astrometry comes from FPA (no need for parent) 435 \end{verbatim} 436 which converts coordinates \code{in} on the specified focal plane 437 \code{fpa} to tangent plane coordinates, applying the appropriate 438 distortion terms. The \code{color} and magnitude (\code{mag}) of the 439 source is necessary in order to perform the distortion between the 440 focal plane and the tangent plane. 441 442 \begin{verbatim} 443 psSphere *psCoordTPToSky(psSphere *out, const psPlane *in, const psGrommit *grommit); 444 \end{verbatim} 445 which converts the tangent plane coordinates \code{in} to (RA,Dec) on 446 the sky, based on the environmental information specified by 447 \code{grommit}. 448 449 % astrometry comes from cell 450 \begin{verbatim} 451 psPlane *psCoordCellToFPA(psPlane *out, const psPlane *in, const psCell *cell); 452 \end{verbatim} 453 which performs the single-step conversion between Cell coordinates 454 \code{in} and FPA coordinates. 455 456 % astrometry comes from cell,chip,fpa (PARENT IS NEEDED HERE) 457 \begin{verbatim} 458 psSphere *psCoordCellToSky(psSphere *out, const psPlane *in, float color, float mag, const psCell *cell); 459 \end{verbatim} 460 which converts coordinates on the specified cell to (RA,Dec). This 461 transformation must be performed using the intermediate stage 462 transformations of Cell to Chip, Chip to FPA, FPA to Tangent Plane, 463 Tangent Plane to Sky. The information needed for each of these 464 transformations is available in the \code{.parent} elements of 465 \code{psCell} and \code{psChip}, and the \code{psFPA.exposure} 466 element. The \code{color} and magnitude (\code{mag}) of the source is 467 necessary in order to perform the distortion between the focal plane 468 and the tangent plane. 469 470 % astrometry comes from cell (no need for parent) 471 \begin{verbatim} 472 psSphere *psCoordCellToSkyQuick(psSphere *out, const psPlane *in, const psCell *cell); 473 \end{verbatim} 474 which uses the 'quick-and-dirty' transformation to convert coordinates 475 on the specified cell to (RA,Dec). This transformation should use the 476 locally linear transformation specified by the element 477 \code{psCell.toTP}. Although the accuracy of this transformation 478 is lower than the complete transformation above, the calculation is 479 substantially faster as it only involves linear transformations. 480 481 The following functions convert from high-level frames to the 482 coordinates of contained lower-level frames. 483 484 \begin{verbatim} 485 psPlane *psCoordSkyToTP(psPlane *out, const psSphere *in, const psGrommit *grommit); 486 \end{verbatim} 487 which converts (RA,Dec) coordinates \code{in} to tangent plane coords 488 based on the enviromental information supplied by \code{grommit}. 489 490 \begin{verbatim} 491 psPlane *psCoordTPToFPA(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa); 492 \end{verbatim} 493 which converts the tangent plane coordinates \code{in} to focal plane 494 coordinates. The \code{color} and magnitude (\code{mag}) of the 495 source is necessary in order to perform the distortion between the 496 focal plane and the tangent plane. 497 498 \begin{verbatim} 499 psPlane *psCoordFPAToChip (psPlane *out, const psPlane *in, const psChip *chip); 500 \end{verbatim} 501 which converts the specified FPA coordinates \code{in} to the 502 coordinates on the given Chip. The specified chip need not contain 503 the input coordinate. To find the chip which contains a particular 504 coordinate, the function \code{psChipInFPA}, defined above, should be 505 used. 506 507 \begin{verbatim} 508 psPlane *psCoordChipToCell (psPlane *out, const psPlane *in, const psCell *cell); 509 \end{verbatim} 510 which converts the specified Chip coordinate \code{in} to the 511 coordinate on the given Cell. The specified Cell need not contain the 512 input coordinate. To find the cell which contains a particular 513 coordinate, the function \code{psCellInChip}, defined above, should be 514 used. 515 516 \begin{verbatim} 517 psPlane *psCoordSkyToCell(psPlane *out, const psSphere *in, float color, float mag, psCell *cell); 518 \end{verbatim} 519 which directly converts (RA,Dec) \code{in} to coordinates on the 520 specified cell. The specified cell need not contain the input 521 coordinates. The \code{color} and magnitude (\code{mag}) of the 522 source is necessary in order to perform the distortion between the 523 focal plane and the tangent plane. 524 525 \begin{verbatim} 526 psPlane *psCoordSkyToCellQuick(psPlane *out, const psSphere *in, psCell *cell); 527 \end{verbatim} 528 which directly converts (RA,Dec) \code{in} to coordinates on the 529 specified cell. The specified cell need not contain the input 530 coordinates. This transformation should use the locally linear 531 transformation specified by the element \code{psCell.toTP}. 532 Although the accuracy of this transformation is lower than the 533 complete transformation above, the calculation is substantially faster 534 as it only involves linear transformations. 535 536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 537 538 \subsection{Astrometry and World Coordinate System} 539 540 The FITS World Coordinate System (WCS) headers are commonly employed 541 with astronomical images in order to relate pixels to celestial (or 542 otherwise) coordinates. Since it is a FITS standard, we must be able 543 to read and write from WCS into our internal format. For the time 544 being, we will consider only celestial WCS (i.e., no spectral 545 wavelength calibrations, etc). Because WCS does not support the 546 multiple layers that we have built for \PS{}, we will use a simple 547 internal representation: a transformation, which handles any 548 distortions (i.e., goes directly from the coordinate frame of the 549 image to the tangent plane); and the projection. 550 551 \begin{verbatim} 552 bool psAstrometryReadWCS(psPlaneTransform **transform, // Output transformation 553 psProjection **projection, // Output projection 554 psMetadata *header // Input FITS header 555 ); 556 bool psAstrometryWriteWCS(psMetadata *header, // Output FITS header 557 psPlaneTransform *transform, // Input transformation 558 psProjection *projection, // Input projection 559 double color, // Mean color to use 560 double magnitude, // Mean magnitude to use 561 ); 562 bool psAstrometrySimplify(psPlaneTransform **transform, // Output transformation 563 psProjection **projection, // Output projection 564 psCell *cell // Cell for which to generate transform and projection 565 ); 566 \end{verbatim} 567 568 \code{pmReadAstrometry} shall parse the specified FITS \code{header}, 569 returning new instances of the \code{transform} and \code{projection} 570 that represent the WCS. The function shall return \code{true} if it 571 was able to successfully generate the outputs; otherwise it shall 572 return \code{false}. 573 574 \code{pmWriteAstrometry} shall add WCS keywords to the supplied FITS 575 \code{header} that implement the given \code{transform} and 576 \code{projection}. The function shall return \code{true} if it was 577 able to successfully generate the output; otherwise it shall return 578 \code{false}. 579 580 \code{pmSimplifyAstrometry} shall take a \code{cell} and simplify the 581 internal astrometric representation (\code{cell->toFPA} or equivalent, 582 \code{cell->parent->parent->toTangentPlane} and 583 \code{cell->parent->parent->grommit}) to a single \code{transform} and 584 \code{projection}. This allows the subsequent use of 585 \code{pmWriteAstrometry} in the case that we have only the 586 multi-layered \PS{} internal astrometric representation. The function 587 shall return \code{true} if it was able to successfully generate the 588 output; otherwise it shall return \code{false}. 589 590 \subsection{Observatory data} 332 591 333 592 We need a container for the observatory data that doesn't change per … … 350 609 \end{verbatim} 351 610 352 \subs ubsection{Exposure information}611 \subsection{Exposure information} 353 612 354 613 We need several quantities from the telescope in order to make a … … 388 647 \end{verbatim} 389 648 390 \subsubsection{Environmental Information}391 392 A-priori astrometric transformations between the tangent plane and the393 sky require several pieces of information describing the current394 environmental conditions. These quantities are consistent from image395 to image, and may vary only slowly with time. Pre-computing these396 quantities for exposures means that subsequent transformations are397 faster. The structure below carries the environment data of interest.398 For historical reasons, this structure is known colloquially as ``the399 Grommit''.400 401 \begin{verbatim}402 typedef struct {403 const double latitude; ///< geodetic latitude (radians)404 const double sinLat, cosLat; ///< sine and cosine of geodetic latitude405 const double abberationMag; ///< magnitude of diurnal aberration vector406 const double height; ///< height (HM)407 const double temperature; ///< ambient temperature (TDK)408 const double pressure; ///< pressure (PMB)409 const double humidity; ///< relative humidity (RH)410 const double wavelength; ///< wavelength (WL)411 const double lapseRate; ///< lapse rate (TLR)412 const double refractA, refractB; ///< refraction constants A and B (radians)413 const double longitudeOffset; ///< longitude + ... (radians)414 const double siderealTime; ///< local apparent sidereal time (radians)415 } psGrommit;416 \end{verbatim}417 418 The \code{psGrommit} is calculated from telescope information for the419 particular exposure, \code{exp}:420 \begin{verbatim}421 psGrommit *psGrommitAlloc(const psExposure *exp);422 \end{verbatim}423 424 \subsubsection{Fixed Pattern}425 426 The fixed pattern is a correction to the general astrometric solution427 formed by summing the residuals from many observations. The intent is428 to correct for higher-order distortions in the camera system on a429 coarse grid (larger than individual pixels, but smaller than a single430 cell). Hence, in addition to the offsets, we need to specify the size431 and scale of the grid in $x$ and $y$, as well as the origin of the432 grid.433 434 \begin{verbatim}435 typedef struct {436 int nX, nY; ///< Number of elements in x and y437 double x0, y0; ///< Position of 0,0 corner on focal plane438 double xScale, yScale; ///< Scale of the grid439 double **x, **y; ///< The grid of offsets in x and y440 } psFixedPattern;441 \end{verbatim}442 443 The constructor for \code{psFixedPattern} shall be:444 \begin{verbatim}445 psFixedPattern *psFixedPatternAlloc(double x0, double y0,446 double xScale, double yScale,447 const psImage *x, const psImage *y);448 \end{verbatim}449 Here, \code{x0}, \code{y0}, \code{xScale} and \code{yScale} have the450 same meaning as in the \code{psFixedPattern} structure. Note that the451 values of the fixed pattern offsets are specified as images, the452 values from which need to be copied into the \code{double **x} and453 \code{double **y} of \code{psFixedPattern}, and that the number of454 elements may be derived from the size of the images.455 456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%457 458 \subsection{Astrometry}459 460 Astrometry is a basic functionality required for the IPP that will be461 used repeatedly, both for low-precision (roughly where is my favorite462 object?) and high-precision (what is the proper motion of this star?).463 As such, it must be flexible, yet robust. Accordingly, we will wrap464 the StarLink Astronomy Libraries (SLALib), which has already been465 developed. \tbd{SLAlib functions will be replaced in the next466 release}.467 468 \subsubsection{Coordinate frames}469 \label{sec:coordinateFrames}470 471 There are five coordinate frames that we need to worry about for the472 purposes of astrometry:473 \begin{itemize}474 \item Cell: $(x,y)$ in pixels --- raw coordinates;475 \item Chip: $(X,Y)$ in pixels --- the location on the silicon;476 \item Focal Plane: $(p,q)$ in microns --- the location on the focal plane;477 \item Tangent Plane: $(l,m)$ in arcsec from the telescope boresight; and478 \item Sky: (RA,Dec) --- ICRS.479 \end{itemize}480 481 The following steps are required to convert from the cell coordinates to482 the sky:483 \begin{itemize}484 \item Cell $\longleftrightarrow$ Chip: two 2D polynomials, $(X,Y) = f(x,y)$;485 \item Chip $\longleftrightarrow$ FP: two 2D polynomials, $(p,q) = g(X,Y)$;486 \item FP $\longleftrightarrow$ TP: two 4D polynomials, $(l,m) =487 h(p,q,m,c)$, where $m$ and $c$ are the magnitude and color of the488 object, respectively; and489 \item TP $\longleftrightarrow$ Sky: transformation to the sky using490 pre-computed coefficients for each pointing.491 \end{itemize}492 493 Note that the transformation between the Focal Plane and the Tangent494 Plane is a four-dimensional polynomial, in order to account for any495 possible dependencies in the astrometry on the stellar magnitude and496 color; the former serves as a check for charge transfer497 inefficiencies, while the latter will correct chromatic refraction,498 both through the atmosphere and the corrector lenses.499 500 We require structures to contain each of the above transformations as501 well as the pixel data.502 503 \subsubsection{Position Finding}504 505 We require functions to return the structure containing given506 coordinates. For example, we want the chip that corresponds to the507 focal plane coordinates $(p,q) = (-1.234,+5.678)$. These routines508 handle the one-to-many problem --- i.e., for one given focal plane509 coordinate, there are many chips that this coordinate may be510 correspond to; these functions will select the correct one.511 %512 \begin{verbatim}513 psCell *psCellInFPA (const psPlane *coord, const psFPA *fpa);514 psChip *psChipInFPA (const psPlane *coord, const psFPA *fpa);515 psCell *psCellInChip(const psPlane *coord, const psChip *chip);516 \end{verbatim}517 518 \subsubsection{Conversion Functions}519 520 We require functions to convert between the various coordinate frames521 (Section~\ref{sec:coordinateFrames}). The hierarchy of the coordinate522 frames and the transformations between each are shown in523 Figure~\ref{fig:coco}. The functions that employ the transformations524 are shown in Figure~\ref{fig:cocoFunc}. In addition to525 transformations between each adjoining coordinate frame in the526 hierarchy, we also require higher-level functions to convert between527 the Cell and Sky coordinate frames; these will simply perform the528 intermediate steps.529 530 \begin{figure}531 \psfig{file=coordinateFrames,height=7in,angle=-90}532 \caption{The coordinate systems in the \PS{} IPP, and the relation533 between each by transformations contained in the appropriate534 structures.}535 \label{fig:coco}536 \end{figure}537 538 \begin{figure}539 \psfig{file=coordinateConv,height=7in,angle=-90}540 \caption{Conversion between coordinate systems by PSLib.}541 \label{fig:cocoFunc}542 \end{figure}543 544 We specify the following functions to convert between coordinates in545 one type of frame to another type of frame. The first group consist546 of unambiguous transformations: from the coordinates in a low-level547 frame to the coordinates in the containing higher-level frame, of548 which only one exists. In all of these functions, the output549 coordinate structure may be \code{NULL} or may be supplied by the550 calling function. In the former case, the structure must be551 allocated; in the latter case, the supplied structure must be used.552 553 \begin{verbatim}554 psPlane *psCoordCellToChip (psPlane *out, const psPlane *in, const psCell *cell);555 % astrometry comes from cell (no need for parent)556 \end{verbatim}557 which converts coordindates \code{in} on the specified \code{cell} to558 the coordinates on the parent chip.559 560 \begin{verbatim}561 psPlane *psCoordChipToFPA (psPlane *out, const psPlane *in, const psChip *chip);562 % astrometry comes from chip (no need for parent)563 \end{verbatim}564 which converts the coordinates \code{in} on the specified \code{chip}565 to the coordinates on the parent FPA.566 567 \begin{verbatim}568 psPlane *psCoordFPAToTP(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);569 % astrometry comes from FPA (no need for parent)570 \end{verbatim}571 which converts coordinates \code{in} on the specified focal plane572 \code{fpa} to tangent plane coordinates, applying the appropriate573 distortion terms. The \code{color} and magnitude (\code{mag}) of the574 source is necessary in order to perform the distortion between the575 focal plane and the tangent plane.576 577 \begin{verbatim}578 psSphere *psCoordTPToSky(psSphere *out, const psPlane *in, const psGrommit *grommit);579 \end{verbatim}580 which converts the tangent plane coordinates \code{in} to (RA,Dec) on581 the sky, based on the environmental information specified by582 \code{grommit}.583 584 \begin{verbatim}585 psPlane *psCoordCellToFPA(psPlane *out, const psPlane *in, const psCell *cell);586 % astrometry comes from cell587 \end{verbatim}588 which performs the single-step conversion between Cell coordinates589 \code{in} and FPA coordinates.590 591 \begin{verbatim}592 psSphere *psCoordCellToSky(psSphere *out, const psPlane *in, float color, float mag, const psCell *cell);593 % astrometry comes from cell,chip,fpa (PARENT IS NEEDED HERE)594 \end{verbatim}595 which converts coordinates on the specified cell to (RA,Dec). This596 transformation must be performed using the intermediate stage597 transformations of Cell to Chip, Chip to FPA, FPA to Tangent Plane,598 Tangent Plane to Sky. The information needed for each of these599 transformations is available in the \code{.parent} elements of600 \code{psCell} and \code{psChip}, and the \code{psFPA.exposure}601 element. The \code{color} and magnitude (\code{mag}) of the source is602 necessary in order to perform the distortion between the focal plane603 and the tangent plane.604 605 \begin{verbatim}606 psSphere *psCoordCellToSkyQuick(psSphere *out, const psPlane *in, const psCell *cell);607 % astrometry comes from cell (no need for parent)608 \end{verbatim}609 which uses the 'quick-and-dirty' transformation to convert coordinates610 on the specified cell to (RA,Dec). This transformation should use the611 locally linear transformation specified by the element612 \code{psCell.toTP}. Although the accuracy of this transformation613 is lower than the complete transformation above, the calculation is614 substantially faster as it only involves linear transformations.615 616 The following functions convert from high-level frames to the617 coordinates of contained lower-level frames.618 619 \begin{verbatim}620 psPlane *psCoordSkyToTP(psPlane *out, const psSphere *in, const psGrommit *grommit);621 \end{verbatim}622 which converts (RA,Dec) coordinates \code{in} to tangent plane coords623 based on the enviromental information supplied by \code{grommit}.624 625 \begin{verbatim}626 psPlane *psCoordTPToFPA(psPlane *out, const psPlane *in, float color, float mag, const psFPA *fpa);627 \end{verbatim}628 which converts the tangent plane coordinates \code{in} to focal plane629 coordinates. The \code{color} and magnitude (\code{mag}) of the630 source is necessary in order to perform the distortion between the631 focal plane and the tangent plane.632 633 \begin{verbatim}634 psPlane *psCoordFPAToChip (psPlane *out, const psPlane *in, const psChip *chip);635 \end{verbatim}636 which converts the specified FPA coordinates \code{in} to the637 coordinates on the given Chip. The specified chip need not contain638 the input coordinate. To find the chip which contains a particular639 coordinate, the function \code{psChipInFPA}, defined above, should be640 used.641 642 \begin{verbatim}643 psPlane *psCoordChipToCell (psPlane *out, const psPlane *in, const psCell *cell);644 \end{verbatim}645 which converts the specified Chip coordinate \code{in} to the646 coordinate on the given Cell. The specified Cell need not contain the647 input coordinate. To find the cell which contains a particular648 coordinate, the function \code{psCellInChip}, defined above, should be649 used.650 651 \begin{verbatim}652 psPlane *psCoordSkyToCell(psPlane *out, const psSphere *in, float color, float mag, psCell *cell);653 \end{verbatim}654 which directly converts (RA,Dec) \code{in} to coordinates on the655 specified cell. The specified cell need not contain the input656 coordinates. The \code{color} and magnitude (\code{mag}) of the657 source is necessary in order to perform the distortion between the658 focal plane and the tangent plane.659 660 \begin{verbatim}661 psPlane *psCoordSkyToCellQuick(psPlane *out, const psSphere *in, psCell *cell);662 \end{verbatim}663 which directly converts (RA,Dec) \code{in} to coordinates on the664 specified cell. The specified cell need not contain the input665 coordinates. This transformation should use the locally linear666 transformation specified by the element \code{psCell.toTP}.667 Although the accuracy of this transformation is lower than the668 complete transformation above, the calculation is substantially faster669 as it only involves linear transformations.670 671 \subsubsection{Additional functions}672 673 We require additional functions to perform general functions which674 will be useful for astrometry. Given coordinates on the sky, we675 need to get the airmass, the parallactic angle, and an estimate of676 the atmospheric refraction.677 678 \begin{verbatim}679 float psGetAirmass(const psSphere *coord, psTime *lst, float height);680 \end{verbatim}681 which returns the airmass for a given position and local sidereal time682 (\code{lst}).683 684 \begin{verbatim}685 float psGetParallactic(const psSphere *coord, double siderealTime);686 \end{verbatim}687 which returns the parallactic angle for a given position and sidereal time.688 689 \begin{verbatim}690 float psGetRefraction(float colour, ///< Colour of object691 psPhotSystem colorPlus, ///< Colour reference692 psPhotSystem colorMinus, ///< Colour reference693 const psExposure *exp); ///< Telescope pointing information694 \end{verbatim}695 which provides an estimate of the atmospheric refraction, along the parallactic angle.696 697 \begin{verbatim}698 double psGetParallaxFactor(const psExposure *exp)699 \end{verbatim}700 Calculate the parallax factor for the given exposure. \tbd{Why do we need this?}.701 702 703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%704 705 \subsection{Astrometry and World Coordinate System}706 707 The FITS World Coordinate System (WCS) headers are commonly employed708 with astronomical images in order to relate pixels to celestial (or709 otherwise) coordinates. Since it is a FITS standard, we must be able710 to read and write from WCS into our internal format. For the time711 being, we will consider only celestial WCS (i.e., no spectral712 wavelength calibrations, etc). Because WCS does not support the713 multiple layers that we have built for \PS{}, we will use a simple714 internal representation: a transformation, which handles any715 distortions (i.e., goes directly from the coordinate frame of the716 image to the tangent plane); and the projection.717 718 \begin{verbatim}719 bool psAstrometryReadWCS(psPlaneTransform **transform, // Output transformation720 psProjection **projection, // Output projection721 psMetadata *header // Input FITS header722 );723 bool psAstrometryWriteWCS(psMetadata *header, // Output FITS header724 psPlaneTransform *transform, // Input transformation725 psProjection *projection, // Input projection726 double color, // Mean color to use727 double magnitude, // Mean magnitude to use728 );729 bool psAstrometrySimplify(psPlaneTransform **transform, // Output transformation730 psProjection **projection, // Output projection731 psCell *cell // Cell for which to generate transform and projection732 );733 \end{verbatim}734 735 \code{pmReadAstrometry} shall parse the specified FITS \code{header},736 returning new instances of the \code{transform} and \code{projection}737 that represent the WCS. The function shall return \code{true} if it738 was able to successfully generate the outputs; otherwise it shall739 return \code{false}.740 741 \code{pmWriteAstrometry} shall add WCS keywords to the supplied FITS742 \code{header} that implement the given \code{transform} and743 \code{projection}. The function shall return \code{true} if it was744 able to successfully generate the output; otherwise it shall return745 \code{false}.746 747 \code{pmSimplifyAstrometry} shall take a \code{cell} and simplify the748 internal astrometric representation (\code{cell->toFPA} or equivalent,749 \code{cell->parent->parent->toTangentPlane} and750 \code{cell->parent->parent->grommit}) to a single \code{transform} and751 \code{projection}. This allows the subsequent use of752 \code{pmWriteAstrometry} in the case that we have only the753 multi-layered \PS{} internal astrometric representation. The function754 shall return \code{true} if it was able to successfully generate the755 output; otherwise it shall return \code{false}.756
Note:
See TracChangeset
for help on using the changeset viewer.
