CR2RE Pipeline Reference Manual 1.6.10
irplib_wcs.c
1/* $Id: irplib_wcs.c,v 1.8 2010-10-07 14:10:55 llundin Exp $
2 *
3 * This file is part of the irplib package
4 * Copyright (C) 2002,2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: llundin $
23 * $Date: 2010-10-07 14:10:55 $
24 * $Revision: 1.8 $
25 * $Name: not supported by cvs2svn $
26 */
27
28/*-----------------------------------------------------------------------------
29 Includes
30 -----------------------------------------------------------------------------*/
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "irplib_wcs.h"
37
38#include <math.h>
39
40/*----------------------------------------------------------------------------*/
44/*----------------------------------------------------------------------------*/
45
46static cpl_error_code irplib_wcs_is_iso8601(int, int, int, int, int, double);
47
48/* Standard year-2000 form: CCYY-MM-DD[Thh:mm:ss[.sss...]] */
49#define IRPLIB_ISO8601_FORMAT "%4d-%2d-%2dT%2d:%2d:%lf"
50
53/*----------------------------------------------------------------------------*/
64/*----------------------------------------------------------------------------*/
65cpl_error_code irplib_wcs_xytoradec(const cpl_wcs *wcs,
66 double x,
67 double y,
68 double *ra,
69 double *dec)
70{
71 cpl_matrix * xy;
72 cpl_matrix * radec = NULL;
73 cpl_array * status = NULL;
74 cpl_error_code error;
75
76 cpl_ensure_code(ra != NULL, CPL_ERROR_NULL_INPUT);
77 cpl_ensure_code(dec != NULL, CPL_ERROR_NULL_INPUT);
78
79 /* Load up the information */
80 xy = cpl_matrix_new(1, 2);
81 cpl_matrix_set(xy, 0, 0, x);
82 cpl_matrix_set(xy, 0, 1, y);
83
84 /* Call the conversion routine */
85 error = cpl_wcs_convert(wcs, xy, &radec, &status, CPL_WCS_PHYS2WORLD);
86
87 cpl_matrix_delete(xy);
88
89 if (!error) {
90
91 /* Pass it back now */
92 *ra = cpl_matrix_get(radec, 0, 0);
93 *dec = cpl_matrix_get(radec, 0, 1);
94
95 }
96
97 /* Tidy and propagate error, if any */
98 cpl_matrix_delete(radec);
99 cpl_array_delete(status);
100
101 return cpl_error_set_where(cpl_func);
102}
103
104/*----------------------------------------------------------------------------*/
115/*----------------------------------------------------------------------------*/
116cpl_error_code irplib_wcs_radectoxy(const cpl_wcs * wcs,
117 double ra,
118 double dec,
119 double * x,
120 double * y)
121{
122 cpl_matrix * radec;
123 cpl_matrix * xy = NULL;
124 cpl_array * status = NULL;
125 cpl_error_code error;
126
127 cpl_ensure_code(x != NULL, CPL_ERROR_NULL_INPUT);
128 cpl_ensure_code(y != NULL, CPL_ERROR_NULL_INPUT);
129
130 /* Feed the matrix with RA, DEC */
131 radec = cpl_matrix_new(1, 2);
132 cpl_matrix_set(radec, 0, 0, ra);
133 cpl_matrix_set(radec, 0, 1, dec);
134
135 error = cpl_wcs_convert(wcs, radec, &xy, &status, CPL_WCS_WORLD2PHYS);
136
137 cpl_matrix_delete(radec);
138
139 if (!error) {
140
141 *x = cpl_matrix_get(xy, 0, 0);
142 *y = cpl_matrix_get(xy, 0, 1);
143
144 }
145
146 /* Tidy and propagate error, if any */
147 cpl_array_delete(status);
148 cpl_matrix_delete(xy);
149
150 return cpl_error_set_where(cpl_func);
151
152}
153
154/*----------------------------------------------------------------------------*/
164/*----------------------------------------------------------------------------*/
165double irplib_wcs_great_circle_dist(double ra1,
166 double dec1,
167 double ra2,
168 double dec2)
169{
170
171 /* Convert all input from degrees to radian - and back for the result */
172 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
173 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
174
175 dec1 *= CPL_MATH_RAD_DEG;
176 dec2 *= CPL_MATH_RAD_DEG;
177
178 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
179 * CPL_MATH_DEG_RAD;
180}
181
182
183/*----------------------------------------------------------------------------*/
197/*----------------------------------------------------------------------------*/
198cpl_error_code irplib_wcs_mjd_from_iso8601(double * pmjd, int year, int month,
199 int day, int hour, int minute,
200 double second)
201{
202
203 cpl_ensure_code(pmjd != NULL, CPL_ERROR_NULL_INPUT);
204 cpl_ensure_code(!irplib_wcs_is_iso8601(year, month, day, hour, minute,
205 second), cpl_error_get_code());
206
207 /* Compute MJD. */
208 *pmjd = (double)((1461*(year - (12-month)/10 + 4712))/4
209 + (306*((month+9)%12) + 5)/10
210 - (3*((year - (12-month)/10 + 4900)/100))/4
211 + day - 2399904)
212 + (hour + (minute + second/60.0)/60.0)/24.0;
213
214 return CPL_ERROR_NONE;
215
216}
217
218
219/*----------------------------------------------------------------------------*/
235/*----------------------------------------------------------------------------*/
236cpl_error_code irplib_wcs_iso8601_from_string(int * pyear, int * pmonth,
237 int * pday, int * phour,
238 int * pminute, double * psecond,
239 const char * iso8601)
240{
241
242 int nret;
243
244 cpl_ensure_code(pyear != NULL, CPL_ERROR_NULL_INPUT);
245 cpl_ensure_code(pmonth != NULL, CPL_ERROR_NULL_INPUT);
246 cpl_ensure_code(pday != NULL, CPL_ERROR_NULL_INPUT);
247 cpl_ensure_code(phour != NULL, CPL_ERROR_NULL_INPUT);
248 cpl_ensure_code(pminute != NULL, CPL_ERROR_NULL_INPUT);
249 cpl_ensure_code(psecond != NULL, CPL_ERROR_NULL_INPUT);
250 cpl_ensure_code(iso8601 != NULL, CPL_ERROR_NULL_INPUT);
251
252 nret = sscanf(iso8601, IRPLIB_ISO8601_FORMAT, pyear, pmonth,
253 pday, phour, pminute, psecond);
254
255 if (nret != 6) {
256 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Parsed"
257 " %d != 6: input %s is not in format %s",
258 nret, iso8601, IRPLIB_ISO8601_FORMAT);
259 }
260
261 return irplib_wcs_is_iso8601(*pyear, *pmonth, *pday, *phour, *pminute,
262 *psecond)
263 ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
264}
265
266
267/*----------------------------------------------------------------------------*/
276/*----------------------------------------------------------------------------*/
277cpl_error_code irplib_wcs_mjd_from_string(double * pmjd, const char * iso8601)
278{
279
280
281 int year, day, month, hour, minute;
282 double second;
283
284 return irplib_wcs_iso8601_from_string(&year, &month, &day, &hour,
285 &minute, &second, iso8601)
286 || irplib_wcs_mjd_from_iso8601(pmjd, year, month, day, hour, minute,
287 second)
288 ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
289}
290
291
292
293/*----------------------------------------------------------------------------*/
307/*----------------------------------------------------------------------------*/
308cpl_error_code irplib_wcs_iso8601_from_mjd(int * pyear, int * pmonth,
309 int * pday, int * phour,
310 int * pminute, double * psecond,
311 double mjd)
312{
313
314 int jd, n4, dd;
315 double t;
316
317 cpl_ensure_code(pyear != NULL, CPL_ERROR_NULL_INPUT);
318 cpl_ensure_code(pmonth != NULL, CPL_ERROR_NULL_INPUT);
319 cpl_ensure_code(pday != NULL, CPL_ERROR_NULL_INPUT);
320 cpl_ensure_code(phour != NULL, CPL_ERROR_NULL_INPUT);
321 cpl_ensure_code(pminute != NULL, CPL_ERROR_NULL_INPUT);
322 cpl_ensure_code(psecond != NULL, CPL_ERROR_NULL_INPUT);
323
324 /* Copied from datfix() in wcslib (v. 4.4.4) */
325
326 jd = 2400001 + (int)mjd;
327
328 n4 = 4*(jd + ((2*((4*jd - 17918)/146097)*3)/4 + 1)/2 - 37);
329 dd = 10*(((n4-237)%1461)/4) + 5;
330
331 *pyear = n4/1461 - 4712;
332 *pmonth = (2 + dd/306)%12 + 1;
333 *pday = (dd%306)/10 + 1;
334
335 t = mjd - (int)mjd; /* t is now days */
336
337 t *= 24.0; /* t is now hours */
338 *phour = (int)t;
339 t = 60.0 * (t - *phour); /* t is now minutes */
340 *pminute = (int)t;
341 *psecond = 60.0 * (t - *pminute);
342
343 /* A failure here implies that this code has a bug */
344 cpl_ensure_code(!irplib_wcs_is_iso8601(*pyear, *pmonth, *pday, *phour,
345 *pminute, *psecond),
346 CPL_ERROR_UNSPECIFIED);
347
348 return CPL_ERROR_NONE;
349}
350
351
354/*----------------------------------------------------------------------------*/
366/*----------------------------------------------------------------------------*/
367static cpl_error_code irplib_wcs_is_iso8601(int year, int month,
368 int day, int hour,
369 int minute, double second)
370{
371
372 const cpl_boolean is_leap = (year % 4) ? CPL_FALSE : CPL_TRUE;
373 const int mlen[] = {0, 31, is_leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30,
374 31, 30, 31};
375
376 cpl_ensure_code(month > 0, CPL_ERROR_ILLEGAL_INPUT);
377 cpl_ensure_code(month <= 12, CPL_ERROR_ILLEGAL_INPUT);
378
379 cpl_ensure_code(day > 0, CPL_ERROR_ILLEGAL_INPUT);
380 cpl_ensure_code(day <= mlen[month], CPL_ERROR_ILLEGAL_INPUT);
381
382 cpl_ensure_code(minute < 60, CPL_ERROR_ILLEGAL_INPUT);
383 cpl_ensure_code(minute >= 0, CPL_ERROR_ILLEGAL_INPUT);
384
385 cpl_ensure_code(second < 60.0, CPL_ERROR_ILLEGAL_INPUT);
386 cpl_ensure_code(second >= 0.0, CPL_ERROR_ILLEGAL_INPUT);
387
388 cpl_ensure_code(hour >= 0, CPL_ERROR_ILLEGAL_INPUT);
389 /* 24:00:00 is valid ISO-8601 */
390 cpl_ensure_code(hour <= (minute > 0 || second > 0.0 ? 23 : 24),
391 CPL_ERROR_ILLEGAL_INPUT);
392
393 return CPL_ERROR_NONE;
394}