SkyCoordinates.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, Reinhard Prix, Teviet Creighton, John Whelan
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /** \file
00021  * \ingroup SkyCoordinates
00022  * \author Creighton, T. D.
00023  * \date $Date: 2007/06/08 14:41:47 $
00024  * \brief Automatically converts among sky coordinate systems.
00025  * 
00026  * $Id: SkyCoordinates.c,v 1.12 2007/06/08 14:41:47 bema Exp $
00027  * 
00028 
00029 \par Description
00030 
00031 The function LALConvertSkyCoordinates() transforms the contents
00032 of \a *input to the system  
00033 specified in \a *params, storing the result in \a *output
00034 (which may point to the same object as \a *input for an in-place
00035 transformation).  The routine makes calls to the functions in
00036 CelestialCoordinates.c and TerrestrialCoordinates.c as
00037 required; the \a *params object must store any data fields
00038 required by these functions, or an error will occur.
00039 
00040 
00041 The function LALNormalizeSkyPosition() ``normalizes'' any given
00042 (spherical) sky-position (in radians), which means it projects the
00043 angles into \f$[0, 2\pi) \times [-\pi/2, \pi/2]\f$ if they lie outside.
00044 
00045 
00046 \par Algorithm
00047 
00048 LALConvertSkyCoordinates() is structured as a simple loop over
00049 transformations, each of which moves the output sky position one step
00050 closer to the desired final coordinates system.  The usual ``flow'' of
00051 the algorithm is: 
00052 \image html inject_ConvFlow.png
00053 \latexonly
00054 \begin{center}
00055 horizon
00056 \makebox[0pt][l]{\raisebox{0.4ex}{$\rightarrow$}}%
00057 \makebox[0pt][l]{\raisebox{-0.2ex}{$\leftarrow$}}
00058 \quad geographic
00059 \makebox[0pt][l]{\raisebox{0.4ex}{$\rightarrow$}}%
00060 \makebox[0pt][l]{\raisebox{-0.2ex}{$\leftarrow$}}
00061 \quad equatorial
00062 \makebox[0pt][l]{\raisebox{2.2ex}{$\nearrow$}}%
00063 \makebox[0pt][l]{\raisebox{1.8ex}{$\,\swarrow$}}%
00064 \makebox[0pt][l]{\raisebox{-1.8ex}{$\,\searrow$}}%
00065 \makebox[0pt][l]{\raisebox{-2.2ex}{$\nwarrow$}}
00066 \quad
00067 \makebox[0pt][l]{\raisebox{4ex}{ecliptic}}%
00068 \makebox[0pt][l]{\raisebox{-4ex}{Galactic}}
00069 \end{center}
00070 \endlatexonly
00071 although one can also convert directly between equatorial and horizon
00072 coordinate systems if \a params->zenith is given in equatorial
00073 coordinates (i.e.\ if its longitudinal coordinate is the local mean
00074 sidereal time rather than the geographic longitude of the observer).
00075 This leads to the only error checking done within this function: when
00076 transforming to horizon coordinates, it checks that
00077 \a params->zenith is either in sky-fixed equatorial or Earth-fixed
00078 geographic coordinates.  Other than this, error checking is left to
00079 the secondary function call; if a parameter is absent or poorly
00080 formatted, the called function will return an error.
00081 
00082 \par Uses
00083 \code 
00084 LALHorizonToSystem()            LALSystemToHorizon()
00085 LALGeographicToEquatorial()     LALEquatorialToGeographic()
00086 LALEquatorialToEcliptic()       LALEclipticToEquatorial()
00087 LALEquatorialToGalactic()       LALGalacticToEquatorial()
00088 \endcode
00089 
00090 */
00091 
00092 /*---------- laldoc-version of documentation follows ---------- */
00093 
00094 /******************************* <lalVerbatim file="SkyCoordinatesCV">
00095 Author: Creighton, T. D.
00096 $Id: SkyCoordinates.c,v 1.12 2007/06/08 14:41:47 bema Exp $
00097 **************************************************** </lalVerbatim> */
00098 
00099 /********************************************************** <lalLaTeX>
00100 
00101 \subsection{Module \texttt{SkyCoordinates.c}}
00102 \label{ss:SkyCoordinates.c}
00103 
00104 Automatically converts among sky coordinate systems.
00105 
00106 \subsubsection*{Prototypes}
00107 \vspace{0.1in}
00108 \input{SkyCoordinatesCP}
00109 \idx{LALConvertSkyCoordinates()}
00110 \idx{LALNormalizeSkyPosition()}
00111 
00112 \subsubsection*{Description}
00113 
00114 The function \verb+LALConvertSkyCoordinates()+ transforms the contents
00115 of <tt>*input</tt> to the system  
00116 specified in <tt>*params</tt>, storing the result in <tt>*output</tt>
00117 (which may point to the same object as <tt>*input</tt> for an in-place
00118 transformation).  The routine makes calls to the functions in
00119 <tt>CelestialCoordinates.c</tt> and <tt>TerrestrialCoordinates.c</tt> as
00120 required; the <tt>*params</tt> object must store any data fields
00121 required by these functions, or an error will occur.
00122 
00123 
00124 The function \verb+LALNormalizeSkyPosition()+ ``normalizes'' any given
00125 (spherical) sky-position (in radians), which means it projects the
00126 angles into $[0, 2\pi) \times [-\pi/2, \pi/2]$ if they lie outside.
00127 
00128 
00129 \subsubsection*{Algorithm}
00130 
00131 \verb+LALConvertSkyCoordinates()+ is structured as a simple loop over
00132 transformations, each 
00133 of which moves the output sky position one step closer to the desired
00134 final coordinates system.  The usual ``flow'' of the algorithm is:
00135 \begin{center}
00136 horizon
00137 \makebox[0pt][l]{\raisebox{0.4ex}{$\rightarrow$}}%
00138 \makebox[0pt][l]{\raisebox{-0.2ex}{$\leftarrow$}}
00139 \quad geographic
00140 \makebox[0pt][l]{\raisebox{0.4ex}{$\rightarrow$}}%
00141 \makebox[0pt][l]{\raisebox{-0.2ex}{$\leftarrow$}}
00142 \quad equatorial
00143 \makebox[0pt][l]{\raisebox{2.2ex}{$\nearrow$}}%
00144 \makebox[0pt][l]{\raisebox{1.8ex}{$\,\swarrow$}}%
00145 \makebox[0pt][l]{\raisebox{-1.8ex}{$\,\searrow$}}%
00146 \makebox[0pt][l]{\raisebox{-2.2ex}{$\nwarrow$}}
00147 \quad
00148 \makebox[0pt][l]{\raisebox{4ex}{ecliptic}}%
00149 \makebox[0pt][l]{\raisebox{-4ex}{Galactic}}
00150 \end{center}
00151 although one can also convert directly between equatorial and horizon
00152 coordinate systems if <tt>params->zenith</tt> is given in equatorial
00153 coordinates (i.e.\ if its longitudinal coordinate is the local mean
00154 sidereal time rather than the geographic longitude of the observer).
00155 This leads to the only error checking done within this function: when
00156 transforming to horizon coordinates, it checks that
00157 <tt>params->zenith</tt> is either in sky-fixed equatorial or Earth-fixed
00158 geographic coordinates.  Other than this, error checking is left to
00159 the secondary function call; if a parameter is absent or poorly
00160 formatted, the called function will return an error.
00161 
00162 \subsubsection*{Uses}
00163 \begin{verbatim}
00164 LALHorizonToSystem()            LALSystemToHorizon()
00165 LALGeographicToEquatorial()     LALEquatorialToGeographic()
00166 LALEquatorialToEcliptic()       LALEclipticToEquatorial()
00167 LALEquatorialToGalactic()       LALGalacticToEquatorial()
00168 \end{verbatim}
00169 
00170 \subsubsection*{Notes}
00171 
00172 \vfill{\footnotesize\input{SkyCoordinatesCV}}
00173 
00174 ******************************************************* </lalLaTeX> */
00175 
00176 #include <math.h>
00177 #include <lal/LALStdlib.h>
00178 #include <lal/LALConstants.h>
00179 #include <lal/SkyCoordinates.h>
00180 
00181 #define LAL_ALPHAGAL (3.366032942)
00182 #define LAL_DELTAGAL (0.473477302)
00183 #define LAL_LGAL     (0.576)
00184 
00185 NRCSID( SKYCOORDINATESC, "$Id: SkyCoordinates.c,v 1.12 2007/06/08 14:41:47 bema Exp $" );
00186 
00187 /* <lalVerbatim file="SkyCoordinatesCP"> */
00188 void
00189 LALConvertSkyCoordinates( LALStatus        *stat,
00190                           SkyPosition      *output,
00191                           SkyPosition      *input,
00192                           ConvertSkyParams *params )
00193 { /* </lalVerbatim> */
00194   SkyPosition temp; /* temporary sky position (duh) */
00195 
00196   INITSTATUS( stat, "LALConvertSkyCoordinates", SKYCOORDINATESC );
00197   ATTATCHSTATUSPTR( stat );
00198 
00199   /* Make sure parameter structures exist. */
00200   ASSERT( input, stat, SKYCOORDINATESH_ENUL, SKYCOORDINATESH_MSGENUL );
00201   ASSERT( output, stat, SKYCOORDINATESH_ENUL, SKYCOORDINATESH_MSGENUL );
00202   ASSERT( params, stat, SKYCOORDINATESH_ENUL, SKYCOORDINATESH_MSGENUL );
00203 
00204   /* Start looping! */
00205   temp = *input;
00206   while ( temp.system != params->system ) {
00207 
00208     if ( temp.system == COORDINATESYSTEM_HORIZON )
00209       /* Only one possible direction. */
00210       TRY( LALHorizonToSystem( stat->statusPtr, &temp, &temp,
00211                                params->zenith ), stat );
00212 
00213     else if ( temp.system == COORDINATESYSTEM_GEOGRAPHIC ) {
00214       /* Two possible directions.  But, if headed towards the horizon
00215          coordinate system, make sure we can get there! */
00216       if ( params->system == COORDINATESYSTEM_HORIZON ) {
00217         if ( params->zenith ) {
00218           if ( params->zenith->system == COORDINATESYSTEM_GEOGRAPHIC )
00219             TRY( LALSystemToHorizon( stat->statusPtr, &temp, &temp,
00220                                      params->zenith ), stat );
00221           else if ( params->zenith->system == COORDINATESYSTEM_EQUATORIAL )
00222             TRY( LALGeographicToEquatorial( stat->statusPtr, &temp, &temp,
00223                                             params->gpsTime ), stat );
00224           else
00225             ABORT( stat, SKYCOORDINATESH_ESYS, SKYCOORDINATESH_MSGESYS );
00226         } else
00227           ABORT( stat, SKYCOORDINATESH_ENUL, SKYCOORDINATESH_MSGENUL );
00228       } else
00229         TRY( LALGeographicToEquatorial( stat->statusPtr, &temp, &temp,
00230                                         params->gpsTime ), stat );
00231     }
00232 
00233     else if ( temp.system == COORDINATESYSTEM_EQUATORIAL ) {
00234       /* Up to four possible directions, depending on
00235          params->zenith->system. */
00236       if ( ( params->system == COORDINATESYSTEM_HORIZON ) &&
00237            ( params->zenith ) &&
00238            ( params->zenith->system == COORDINATESYSTEM_EQUATORIAL ) )
00239         TRY( LALSystemToHorizon( stat->statusPtr, &temp, &temp,
00240                                  params->zenith ), stat );
00241       else if ( params->system == COORDINATESYSTEM_ECLIPTIC )
00242         TRY( LALEquatorialToEcliptic( stat->statusPtr, &temp, &temp ),
00243              stat );
00244       else if ( params->system == COORDINATESYSTEM_GALACTIC )
00245         TRY( LALEquatorialToGalactic( stat->statusPtr, &temp, &temp ),
00246              stat );
00247       else
00248         TRY( LALEquatorialToGeographic( stat->statusPtr, &temp, &temp,
00249                                         params->gpsTime ), stat );
00250     }
00251 
00252     else if ( temp.system == COORDINATESYSTEM_ECLIPTIC ) {
00253       /* Only one possible direction. */
00254       TRY( LALEclipticToEquatorial( stat->statusPtr, &temp, &temp ),
00255            stat );
00256     }
00257 
00258     else if ( temp.system == COORDINATESYSTEM_GALACTIC ) {
00259       /* Only one possible direction. */
00260       TRY( LALGalacticToEquatorial( stat->statusPtr, &temp, &temp ),
00261            stat );
00262     }
00263 
00264     else
00265       ABORT( stat, SKYCOORDINATESH_ESYS, SKYCOORDINATESH_MSGESYS );
00266   }
00267 
00268   /* We've gotten to the correct coordinate system.  Set the output
00269      and return. */
00270   *output = temp;
00271   DETATCHSTATUSPTR( stat );
00272   RETURN( stat );
00273 
00274 } /* LALConvertSkyCoordinates */
00275 
00276 
00277 
00278 /** LAL interface to XLALNormalizeSkyPosition() 
00279  */
00280 void
00281 LALNormalizeSkyPosition (LALStatus *stat, 
00282                          SkyPosition *posOut,           /**< [out] normalized sky-position */
00283                          const SkyPosition *posIn)      /**< [in] general sky-position */
00284 {
00285   SkyPosition tmp;      /* allow posOut == posIn */
00286 
00287   INITSTATUS( stat, "NormalizeSkyPosition", SKYCOORDINATESC);
00288   
00289   ASSERT (posIn, stat, SKYCOORDINATESH_ENUL ,  SKYCOORDINATESH_MSGENUL );
00290   ASSERT (posOut, stat, SKYCOORDINATESH_ENUL ,  SKYCOORDINATESH_MSGENUL );
00291 
00292   tmp = *posIn;
00293 
00294   XLALNormalizeSkyPosition ( &tmp );
00295 
00296   *posOut = tmp;
00297 
00298   RETURN (stat);
00299 
00300 } /* LALNormalizeSkyPosition() */
00301 
00302 
00303 /** If sky-position is not in the canonical range 
00304  * \f$(\alpha,\delta)\in [0,2\pi]\times[-\pi/2, \pi/2]\f$, normalize it
00305  * by mapping it into this coordinate-interval.
00306  * Based on Alicia's function with some additional "unwinding" added.  
00307  * return 0 = OK, -1 = ERROR
00308  */
00309 int
00310 XLALNormalizeSkyPosition ( SkyPosition *posInOut ) /**< [in,out] sky-position to normalize*/
00311 {
00312   SkyPosition tmp;
00313 
00314   if ( !posInOut )
00315     return -1;
00316 
00317   tmp = *posInOut;
00318   
00319   /* FIRST STEP: completely "unwind" positions, i.e. make sure that 
00320    * [0 <= alpha < 2pi] and [-pi < delta <= pi] */
00321   /* normalize longitude */
00322   while (tmp.longitude < 0)
00323     tmp.longitude += LAL_TWOPI;
00324   while (tmp.longitude >= LAL_TWOPI)
00325     tmp.longitude -= LAL_TWOPI;
00326 
00327   /* pre-normalize (unwind) latitude */
00328   while (tmp.latitude <= -LAL_PI)
00329     tmp.latitude += LAL_TWOPI;
00330   while (tmp.latitude > LAL_TWOPI)
00331     tmp.latitude -= LAL_TWOPI;
00332 
00333   /* SECOND STEP: get latitude into canonical interval [-pi/2 <= delta <= pi/2 ] */
00334   /* this requires also a change in longitude by adding/subtracting PI */
00335   if (tmp.latitude > LAL_PI_2)
00336     {
00337       tmp.latitude = LAL_PI - tmp.latitude;
00338       if (tmp.longitude < LAL_PI)
00339         {
00340           tmp.longitude += LAL_PI;
00341         }
00342       else
00343         {
00344           tmp.longitude -= LAL_PI;
00345         }
00346     }
00347 
00348   if (tmp.latitude < -LAL_PI_2)
00349     {
00350       tmp.latitude = -LAL_PI - tmp.latitude;
00351       if (tmp.longitude < LAL_PI)
00352         {
00353           tmp.longitude += LAL_PI;
00354         }
00355       else
00356         {
00357           tmp.longitude -= LAL_PI;
00358         }
00359     }
00360 
00361   *posInOut = tmp;
00362 
00363   return 0;
00364 
00365 } /* XLALNormalizeSkyPosition() */

Generated on Sat Oct 11 02:32:09 2008 for LAL by  doxygen 1.5.2