irplib_wcs.c

00001 /* $Id: irplib_wcs.c,v 1.8 2010/10/07 14:10:55 llundin Exp $
00002  *
00003  * This file is part of the irplib package
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2010/10/07 14:10:55 $
00024  * $Revision: 1.8 $
00025  * $Name: uves-4_9_1 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <cpl.h>
00038 
00039 #include "irplib_wcs.h"
00040 
00041 /*----------------------------------------------------------------------------*/
00045 /*----------------------------------------------------------------------------*/
00046 
00047 static cpl_error_code irplib_wcs_is_iso8601(int, int, int, int, int, double);
00048 
00051 /*----------------------------------------------------------------------------*/
00062 /*----------------------------------------------------------------------------*/
00063 cpl_error_code irplib_wcs_xytoradec(const cpl_wcs *wcs,
00064                                     double         x,
00065                                     double         y,
00066                                     double        *ra,
00067                                     double        *dec)
00068 {
00069     cpl_matrix   * xy;
00070     cpl_matrix   * radec  = NULL;
00071     cpl_array    * status = NULL;
00072     cpl_error_code error;
00073 
00074     cpl_ensure_code(ra  != NULL, CPL_ERROR_NULL_INPUT);
00075     cpl_ensure_code(dec != NULL, CPL_ERROR_NULL_INPUT);
00076 
00077     /* Load up the information */
00078     xy = cpl_matrix_new(1, 2);
00079     cpl_matrix_set(xy, 0, 0, x);
00080     cpl_matrix_set(xy, 0, 1, y);
00081 
00082     /* Call the conversion routine */
00083     error = cpl_wcs_convert(wcs, xy, &radec, &status, CPL_WCS_PHYS2WORLD);
00084 
00085     cpl_matrix_delete(xy);
00086 
00087     if (!error) {
00088 
00089         /* Pass it back now */
00090         *ra  = cpl_matrix_get(radec, 0, 0);
00091         *dec = cpl_matrix_get(radec, 0, 1);
00092 
00093     }
00094 
00095     /* Tidy and propagate error, if any */
00096     cpl_matrix_delete(radec);
00097     cpl_array_delete(status);
00098 
00099     return cpl_error_set_where(cpl_func);
00100 }
00101 
00102 /*----------------------------------------------------------------------------*/
00113 /*----------------------------------------------------------------------------*/
00114 cpl_error_code irplib_wcs_radectoxy(const cpl_wcs * wcs,
00115                                     double          ra,
00116                                     double          dec,
00117                                     double        * x,
00118                                     double        * y)
00119 {
00120     cpl_matrix   * radec;
00121     cpl_matrix   * xy = NULL;
00122     cpl_array    * status   = NULL;
00123     cpl_error_code error;
00124 
00125     cpl_ensure_code(x != NULL, CPL_ERROR_NULL_INPUT);
00126     cpl_ensure_code(y != NULL, CPL_ERROR_NULL_INPUT);
00127 
00128     /* Feed the matrix with RA, DEC */
00129     radec = cpl_matrix_new(1, 2);
00130     cpl_matrix_set(radec, 0, 0, ra);
00131     cpl_matrix_set(radec, 0, 1, dec);
00132 
00133     error = cpl_wcs_convert(wcs, radec, &xy, &status, CPL_WCS_WORLD2PHYS);
00134 
00135     cpl_matrix_delete(radec);
00136 
00137     if (!error) {
00138 
00139         *x  = cpl_matrix_get(xy, 0, 0);
00140         *y  = cpl_matrix_get(xy, 0, 1);
00141 
00142     }
00143 
00144     /* Tidy and propagate error, if any */
00145     cpl_array_delete(status);
00146     cpl_matrix_delete(xy);
00147 
00148     return cpl_error_set_where(cpl_func);
00149 
00150 }
00151 
00152 /*----------------------------------------------------------------------------*/
00162 /*----------------------------------------------------------------------------*/
00163 double irplib_wcs_great_circle_dist(double ra1,
00164                                     double dec1,
00165                                     double ra2,
00166                                     double dec2)
00167 {
00168 
00169     /* Convert all input from degrees to radian - and back for the result */
00170     const double dra  = sin( CPL_MATH_RAD_DEG * (ra2  - ra1 )/2.0 );
00171     const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
00172 
00173     dec1 *= CPL_MATH_RAD_DEG;
00174     dec2 *= CPL_MATH_RAD_DEG;
00175 
00176     return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
00177         * CPL_MATH_DEG_RAD;
00178 }
00179 
00180 
00181 /*----------------------------------------------------------------------------*/
00195 /*----------------------------------------------------------------------------*/
00196 cpl_error_code irplib_wcs_mjd_from_iso8601(double * pmjd, int year, int month,
00197                                            int day, int hour, int minute,
00198                                            double second)
00199 {
00200 
00201     cpl_ensure_code(pmjd  != NULL,        CPL_ERROR_NULL_INPUT);
00202     cpl_ensure_code(!irplib_wcs_is_iso8601(year, month, day, hour, minute,
00203                                            second), cpl_error_get_code());
00204 
00205     /* Compute MJD. */
00206     *pmjd = (double)((1461*(year - (12-month)/10 + 4712))/4
00207                      + (306*((month+9)%12) + 5)/10
00208                      - (3*((year - (12-month)/10 + 4900)/100))/4
00209                      + day - 2399904)
00210         + (hour + (minute + second/60.0)/60.0)/24.0;
00211 
00212     return CPL_ERROR_NONE;
00213 
00214 }
00215 
00216 
00217 /*----------------------------------------------------------------------------*/
00233 /*----------------------------------------------------------------------------*/
00234 cpl_error_code irplib_wcs_iso8601_from_string(int * pyear, int * pmonth,
00235                                               int * pday, int * phour,
00236                                               int * pminute, double * psecond,
00237                                               const char * iso8601)
00238 {
00239 
00240     /* Standard year-2000 form: CCYY-MM-DD[Thh:mm:ss[.sss...]] */
00241     const char * iso8601format = "%4d-%2d-%2dT%2d:%2d:%lf";
00242 
00243     cpl_ensure_code(pyear   != NULL, CPL_ERROR_NULL_INPUT);
00244     cpl_ensure_code(pmonth  != NULL, CPL_ERROR_NULL_INPUT);
00245     cpl_ensure_code(pday    != NULL, CPL_ERROR_NULL_INPUT);
00246     cpl_ensure_code(phour   != NULL, CPL_ERROR_NULL_INPUT);
00247     cpl_ensure_code(pminute != NULL, CPL_ERROR_NULL_INPUT);
00248     cpl_ensure_code(psecond != NULL, CPL_ERROR_NULL_INPUT);
00249     cpl_ensure_code(iso8601 != NULL, CPL_ERROR_NULL_INPUT);
00250 
00251     cpl_error_ensure(sscanf(iso8601, iso8601format, pyear, pmonth,
00252                             pday, phour, pminute, psecond) == 6,
00253                      CPL_ERROR_ILLEGAL_INPUT, return cpl_error_get_code(),
00254                      "%s is not formatted as %s", iso8601, iso8601format);
00255 
00256     cpl_ensure_code(!irplib_wcs_is_iso8601(*pyear, *pmonth, *pday, *phour,
00257                                            *pminute, *psecond),
00258                     cpl_error_get_code());
00259 
00260     return CPL_ERROR_NONE;
00261 }
00262 
00263 
00264 /*----------------------------------------------------------------------------*/
00273 /*----------------------------------------------------------------------------*/
00274 cpl_error_code irplib_wcs_mjd_from_string(double * pmjd, const char * iso8601)
00275 {
00276 
00277 
00278     int year, day, month, hour, minute;
00279     double second;
00280 
00281     return irplib_wcs_iso8601_from_string(&year, &month, &day, &hour,
00282                                           &minute, &second, iso8601)
00283         || irplib_wcs_mjd_from_iso8601(pmjd, year, month, day, hour, minute,
00284                                        second)
00285         ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
00286 }
00287 
00288 
00289 
00290 /*----------------------------------------------------------------------------*/
00304 /*----------------------------------------------------------------------------*/
00305 cpl_error_code irplib_wcs_iso8601_from_mjd(int * pyear, int * pmonth,
00306                                            int * pday, int * phour,
00307                                            int * pminute, double * psecond,
00308                                            double mjd)
00309 {
00310 
00311     int jd, n4, dd;
00312     double t;
00313 
00314     cpl_ensure_code(pyear   != NULL, CPL_ERROR_NULL_INPUT);
00315     cpl_ensure_code(pmonth  != NULL, CPL_ERROR_NULL_INPUT);
00316     cpl_ensure_code(pday    != NULL, CPL_ERROR_NULL_INPUT);
00317     cpl_ensure_code(phour   != NULL, CPL_ERROR_NULL_INPUT);
00318     cpl_ensure_code(pminute != NULL, CPL_ERROR_NULL_INPUT);
00319     cpl_ensure_code(psecond != NULL, CPL_ERROR_NULL_INPUT);
00320 
00321     /* Copied from datfix() in wcslib (v. 4.4.4) */
00322 
00323     jd = 2400001 + (int)mjd;
00324 
00325     n4 =  4*(jd + ((2*((4*jd - 17918)/146097)*3)/4 + 1)/2 - 37);
00326     dd = 10*(((n4-237)%1461)/4) + 5;
00327 
00328     *pyear  = n4/1461 - 4712;
00329     *pmonth = (2 + dd/306)%12 + 1;
00330     *pday   = (dd%306)/10 + 1;
00331 
00332     t = mjd - (int)mjd; /* t is now days */
00333 
00334     t *= 24.0; /* t is now hours */
00335     *phour = (int)t;
00336     t = 60.0 * (t - *phour); /* t is now minutes */
00337     *pminute = (int)t;
00338     *psecond = 60.0 * (t - *pminute);
00339 
00340     /* A failure here implies that this code has a bug */
00341     cpl_ensure_code(!irplib_wcs_is_iso8601(*pyear, *pmonth, *pday, *phour,
00342                                            *pminute, *psecond),
00343                     CPL_ERROR_UNSPECIFIED);
00344 
00345     return CPL_ERROR_NONE;
00346 }
00347 
00348 
00351 /*----------------------------------------------------------------------------*/
00363 /*----------------------------------------------------------------------------*/
00364 static cpl_error_code irplib_wcs_is_iso8601(int year, int month,
00365                                             int day, int hour,
00366                                             int minute, double second)
00367 {
00368 
00369     const cpl_boolean is_leap = year % 4 ? CPL_FALSE : CPL_TRUE;
00370     const int mlen[] = {0, 31, is_leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30,
00371                         31, 30, 31};
00372 
00373     cpl_ensure_code(month > 0,            CPL_ERROR_ILLEGAL_INPUT);
00374     cpl_ensure_code(month <= 12,          CPL_ERROR_ILLEGAL_INPUT);
00375 
00376     cpl_ensure_code(day   > 0,            CPL_ERROR_ILLEGAL_INPUT);
00377     cpl_ensure_code(day   <= mlen[month], CPL_ERROR_ILLEGAL_INPUT);
00378 
00379     cpl_ensure_code(minute  < 60,         CPL_ERROR_ILLEGAL_INPUT);
00380     cpl_ensure_code(minute  >= 0,         CPL_ERROR_ILLEGAL_INPUT);
00381 
00382     cpl_ensure_code(second  < 60.0,       CPL_ERROR_ILLEGAL_INPUT);
00383     cpl_ensure_code(second  >= 0.0,       CPL_ERROR_ILLEGAL_INPUT);
00384 
00385     cpl_ensure_code(hour  >= 0,           CPL_ERROR_ILLEGAL_INPUT);
00386     /* 24:00:00 is valid ISO-8601 */
00387     cpl_ensure_code(hour  <= (minute > 0 || second > 0.0 ? 23 : 24),
00388                     CPL_ERROR_ILLEGAL_INPUT);
00389 
00390     return CPL_ERROR_NONE;
00391 }

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1