VIRCAM Pipeline 2.3.15
casu_wcsutils.c
1/* $Id: casu_wcsutils.c,v 1.3 2015/11/18 20:06:47 jim Exp $
2 *
3 * This file is part of the CASU Pipeline utilities
4 * Copyright (C) 2015 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jim $
23 * $Date: 2015/11/18 20:06:47 $
24 * $Revision: 1.3 $
25 * $Name: $
26 */
27
28/* Includes */
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include <cpl.h>
35#include <math.h>
36
37#include "casu_wcsutils.h"
38#include "casu_utils.h"
39
40#define WCS_FATAL_ERR(_p) {cpl_msg_error(fctid,"Unable to find keyword %s",_p); cpl_error_reset(); return(wcs);}
41
42/* WCS keywords that should be removed from FITS tables*/
43
44#define SZKEY 9
45#define NNOTABKEYS 6
46static const char *notabkeys[NNOTABKEYS] = {"^CRVAL[1-2]*","^CRPIX[1-2]*",
47 "^CD[1-2]*_[1-2]*","^CDELT[1-2]*",
48 "^CTYPE[1-2]*","^PV[1-9]*_[1-9]*"};
49
65/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
93extern void casu_xytoradec(cpl_wcs *wcs, double x, double y, double *ra,
94 double *dec) {
95 double *xy,*radec;
96 cpl_matrix *from,*to;
97 cpl_array *status;
98
99 /* Load up the information */
100
101 from = cpl_matrix_new(1,2);
102 xy = cpl_matrix_get_data(from);
103 xy[0] = x;
104 xy[1] = y;
105
106 /* Call the conversion routine */
107
108 cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2WORLD);
109
110 /* Pass it back now */
111
112 radec = cpl_matrix_get_data(to);
113 *ra = radec[0];
114 *dec = radec[1];
115
116 /* Tidy and exit */
117
118 cpl_matrix_delete(from);
119 cpl_matrix_delete(to);
120 cpl_array_delete(status);
121 return;
122}
123
124/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151extern void casu_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x,
152 double *y) {
153 double *xy,*radec;
154 cpl_matrix *from,*to;
155 cpl_array *status;
156
157 /* Load up the information */
158
159 from = cpl_matrix_new(1,2);
160 radec = cpl_matrix_get_data(from);
161 radec[0] = ra;
162 radec[1] = dec;
163
164 /* Call the conversion routine */
165
166 cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2PHYS);
167
168 /* Pass it back now */
169
170 xy = cpl_matrix_get_data(to);
171 *x = xy[0];
172 *y = xy[1];
173
174 /* Tidy and exit */
175
176 cpl_matrix_delete(from);
177 cpl_matrix_delete(to);
178 cpl_array_delete(status);
179}
180
181/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
212extern void casu_xytoxy_list(cpl_wcs *wcs1, cpl_wcs *wcs2, int nc, double *x_1,
213 double *y_1, double *x_2, double *y_2) {
214 double *xy1;
215 cpl_matrix *from,*radec;
216 cpl_array *status;
217 int i;
218
219 /* Load up the information */
220
221 from = cpl_matrix_new(nc,2);
222 xy1 = cpl_matrix_get_data(from);
223 for (i = 0; i < nc; i++) {
224 xy1[2*i] = x_1[i];
225 xy1[2*i+1] = y_1[i];
226 }
227
228 /* Convert to RA and Dec */
229
230 cpl_wcs_convert(wcs1,from,&radec,&status,CPL_WCS_PHYS2WORLD);
231 cpl_array_delete(status);
232 cpl_matrix_delete(from);
233
234 /* Now convert to x,y in the reference frame of the second image */
235
236 cpl_wcs_convert(wcs2,radec,&from,&status,CPL_WCS_WORLD2PHYS);
237 cpl_array_delete(status);
238 cpl_matrix_delete(radec);
239
240 /* No pass it back now */
241
242 xy1 = cpl_matrix_get_data(from);
243 for (i = 0; i < nc; i++) {
244 x_2[i] = xy1[2*i];
245 y_2[i] = xy1[2*i+1];
246 }
247
248 /* Tidy and exit */
249
250 cpl_matrix_delete(from);
251}
252
253/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281extern void casu_radectoxieta(cpl_wcs *wcs, double ra, double dec,
282 double *xi, double *eta) {
283
284 double *xy,*radec;
285 cpl_matrix *from,*to;
286 cpl_array *status;
287
288 /* Load up the information */
289
290 from = cpl_matrix_new(1,2);
291 radec = cpl_matrix_get_data(from);
292 radec[0] = ra;
293 radec[1] = dec;
294
295 /* Call the conversion routine */
296
297 cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2STD);
298
299 /* Pass it back now */
300
301 xy = cpl_matrix_get_data(to);
302 *xi = xy[0]/DEGRAD;
303 *eta = xy[1]/DEGRAD;
304
305 /* Tidy and exit */
306
307 cpl_matrix_delete(from);
308 cpl_matrix_delete(to);
309 cpl_array_delete(status);
310}
311
312/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345extern int casu_coverage(cpl_propertylist *plist, int fudge, double *ra1,
346 double *ra2, double *dec1, double *dec2,
347 int *status) {
348
349 cpl_wcs *wcs;
350 double ra,dec,x,y,dra,ddec,boxfudge,min_4q,max_1q;
351 int first_quad,fourth_quad,ni,nj,istep;
352 const int *naxes;
353 long i,j;
354 const cpl_array *a;
355
356 /* Initialise these in case of failure later*/
357
358 *ra1 = 0.0;
359 *ra2 = 0.0;
360 *dec1 = 0.0;
361 *dec2 = 0.0;
362 if (*status != CASU_OK)
363 return(*status);
364
365 /* Grab the WCS info from the property list */
366
367 wcs = cpl_wcs_new_from_propertylist(plist);
368 if (wcs == NULL)
369 FATAL_ERROR
370
371 /* Get the size of the data array */
372
373 a = cpl_wcs_get_image_dims(wcs);
374 naxes = cpl_array_get_data_int_const(a);
375
376 /* Find the RA and Dec limits of the image */
377
378 *ra1 = 370.0;
379 *ra2 = -370.0;
380 *dec1 = 95.0;
381 *dec2 = -95.0;
382 first_quad = 0;
383 fourth_quad = 0;
384 min_4q = 370.0;
385 max_1q = 0.0;
386 istep = 10;
387 nj = naxes[1]/istep + 2;
388 ni = naxes[0]/istep + 2;
389 for (j = 1; j <= nj; j++) {
390 y = (double)min(naxes[1],(istep*(j-1)+1));
391 for (i = 1; i <= ni; i++) {
392 x = (double)min(naxes[0],(istep*(i-1)+1));
393 casu_xytoradec(wcs,x,y,&ra,&dec);
394 if (ra >= 0.0 && ra <= 90.0) {
395 first_quad = 1;
396 max_1q = max(ra,max_1q);
397 } else if (ra >= 270.0 && ra <= 360.0) {
398 fourth_quad = 1;
399 min_4q = min((ra-360.0),min_4q);
400 }
401 *ra1 = min(*ra1,ra);
402 *ra2 = max(*ra2,ra);
403 *dec1 = min(*dec1,dec);
404 *dec2 = max(*dec2,dec);
405 }
406 }
407 cpl_wcs_delete(wcs);
408
409 /* Now have a look to see if you had RA values in both the first and
410 fourth quadrants. If you have, then make the minimum RA a negative
411 value. This will be the signal to the caller that you have the
412 wraparound... */
413
414 if (first_quad && fourth_quad) {
415 *ra1 = min_4q;
416 *ra2 = max_1q;
417 }
418
419 /* Pad out search a bit */
420
421 if (fudge) {
422 boxfudge = 0.01*(float)fudge;
423 dra = 0.5*boxfudge*(*ra2 - *ra1);
424 *ra1 -= dra;
425 *ra2 += dra;
426 ddec = 0.5*boxfudge*(*dec2 - *dec1);
427 *dec1 -= ddec;
428 *dec2 += ddec;
429 }
430
431 /* Exit */
432
433 GOOD_STATUS
434}
435
436/*---------------------------------------------------------------------------*/
462/*---------------------------------------------------------------------------*/
463
464extern int casu_crpixshift(cpl_propertylist *p, double scalefac, double sh[]) {
465 int i;
466 double val;
467 char key[SZKEY];
468 cpl_type type;
469 const char *fctid = "casu_crpixshift";
470
471 /* Make sure that the scale factor isn't zero */
472
473 if (scalefac == 0.0) {
474 cpl_msg_error(fctid,"Scale factor is zero!");
475 return(CASU_FATAL);
476 }
477
478 /* Loop through both axes. Shift and scale the values of crpix */
479
480 for (i = 1; i <= 2; i++) {
481 snprintf(key,SZKEY,"CRPIX%d",i);
482
483 /* First make sure the property exists. It damn well better exist! */
484
485 if (cpl_propertylist_has(p,key) == 0) {
486 cpl_msg_error(fctid,"Header is missing WCS key %s",key);
487 return(CASU_FATAL);
488 }
489
490 /* Now find the type... */
491
492 type = cpl_propertylist_get_type(p,key);
493
494 /* Switch for the type. If it's neither float nor double, then
495 signal an error as this is clearly nonsense. */
496
497 switch (type) {
498 case CPL_TYPE_FLOAT:
499 val = (double)cpl_propertylist_get_float(p,key);
500 break;
501 case CPL_TYPE_DOUBLE:
502 val = cpl_propertylist_get_double(p,key);
503 break;
504 default:
505 cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
506 key);
507 return(CASU_FATAL);
508 }
509
510 /* Right, now do the actual work */
511
512 val = (val - sh[i-1])/scalefac - 1.0;
513
514 /* And update the property now */
515
516 switch (type) {
517 case CPL_TYPE_FLOAT:
518 cpl_propertylist_update_float(p,key,(float)val);
519 break;
520 case CPL_TYPE_DOUBLE:
521 cpl_propertylist_update_double(p,key,val);
522 break;
523 default:
524 break;
525 }
526 }
527 return(CASU_OK);
528}
529
530/*---------------------------------------------------------------------------*/
552/*---------------------------------------------------------------------------*/
553
554extern int casu_rescalecd(cpl_propertylist *p, double scalefac) {
555 int i,j;
556 cpl_type type;
557 char key[SZKEY];
558 const char *fctid = "casu_rescalecd";
559 double val;
560
561 /* Make sure that the scale factor isn't zero */
562
563 if (scalefac == 0.0) {
564 cpl_msg_error(fctid,"Scale factor is zero!");
565 return(CASU_FATAL);
566 }
567
568 /* Loop through both axes. Shift and scale the values of cd */
569
570 for (i = 1; i <= 2; i++) {
571 for (j = 1; j <= 2; j++) {
572 snprintf(key,SZKEY,"CD%d_%d",i,j);
573
574 /* First make sure the property exists. It damn well better exist! */
575
576 if (cpl_propertylist_has(p,key) == 0) {
577 cpl_msg_error(fctid,"Header is missing WCS key %s",key);
578 return(CASU_FATAL);
579 }
580
581 /* Now find the type... */
582
583 type = cpl_propertylist_get_type(p,key);
584
585 /* Switch for the type. If it's neither float nor double, then
586 signal an error as this is clearly nonsense. */
587
588 switch (type) {
589 case CPL_TYPE_FLOAT:
590 val = (double)cpl_propertylist_get_float(p,key);
591 break;
592 case CPL_TYPE_DOUBLE:
593 val = cpl_propertylist_get_double(p,key);
594 break;
595 default:
596 cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
597 key);
598 return(CASU_FATAL);
599 }
600
601 /* Right, now do the actual work */
602
603 val *= scalefac;
604
605 /* And update the property now */
606
607 switch (type) {
608 case CPL_TYPE_FLOAT:
609 cpl_propertylist_update_float(p,key,(float)val);
610 break;
611 case CPL_TYPE_DOUBLE:
612 cpl_propertylist_update_double(p,key,val);
613 break;
614 default:
615 break;
616 }
617 }
618 }
619 return(CASU_OK);
620}
621
622/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649
650extern int casu_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff,
651 float *yoff, int *status) {
652 double xc,yc,ra,dec,xnew,ynew;
653 const cpl_array *a;
654 const int *dims;
655 const char *fctid = "casu_diffxywcs";
656
657 /* Inherited status */
658
659 *xoff = 0.0;
660 *yoff = 0.0;
661 if (*status != CASU_OK)
662 return(*status);
663
664 /* Check for rubbish input */
665
666 if (wcs == NULL || wcsref == NULL) {
667 cpl_msg_error(fctid,"NULL wcs information");
668 FATAL_ERROR
669 }
670
671 /* Work out the ra and dec of the central pixel in the reference image */
672
673 a = cpl_wcs_get_image_dims(wcsref);
674 dims = cpl_array_get_data_int_const(a);
675 xc = 0.5*(double)dims[0];
676 yc = 0.5*(double)dims[1];
677 casu_xytoradec(wcsref,xc,yc,&ra,&dec);
678
679 /* Ok, calculate where in x,y space these equatorial coordinates fall on
680 the programme image */
681
682 casu_radectoxy(wcs,ra,dec,&xnew,&ynew);
683
684 /* Right, now return the offsets */
685
686 *xoff = (float)(xc - xnew);
687 *yoff = (float)(yc - ynew);
688 GOOD_STATUS
689}
690
691/*---------------------------------------------------------------------------*/
711/*---------------------------------------------------------------------------*/
712
713extern int casu_removewcs(cpl_propertylist *p, int *status) {
714 int i;
715 const char *fctid = "casu_removewcs";
716
717 /* Inherited status */
718
719 if (*status != CASU_OK)
720 return(*status);
721 if (p == NULL) {
722 cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
723 FATAL_ERROR
724 }
725
726 /* Loop through all the template keywords and remove them */
727
728 for (i = 0; i < NNOTABKEYS; i++)
729 cpl_propertylist_erase_regexp(p,notabkeys[i],0);
730
731 GOOD_STATUS
732}
733
734/*---------------------------------------------------------------------------*/
759/*---------------------------------------------------------------------------*/
760
761extern int casu_tabwcs(cpl_propertylist *p, int xcol, int ycol, int *status) {
762 int i;
763 char key[9],key2[9];
764 const char *fctid="casu_tabwcs";
765
766 /* Inherited status */
767
768 if (*status != CASU_OK)
769 return(*status);
770 if (p == NULL) {
771 cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
772 FATAL_ERROR
773 }
774
775 /* If either of the columns are -1, then just get rid of the image WCS
776 and get out of here */
777
778 if (xcol == -1 || ycol == -1) {
779 casu_removewcs(p,status);
780 GOOD_STATUS
781 }
782
783 /* Go through the standard WCS header keywords one by one
784 and translate them. Start with CTYPE */
785
786 (void)snprintf(key,8,"TCTYP%d",xcol);
787 casu_rename_property(p,"CTYPE1",key);
788 (void)snprintf(key,8,"TCTYP%d",ycol);
789 casu_rename_property(p,"CTYPE2",key);
790
791
792 /* Now CRVAL */
793
794 (void)snprintf(key,8,"TCRVL%d",xcol);
795 casu_rename_property(p,"CRVAL1",key);
796 (void)snprintf(key,8,"TCRVL%d",ycol);
797 casu_rename_property(p,"CRVAL2",key);
798
799 /* Now CRPIX */
800
801 (void)snprintf(key,8,"TCRPX%d",xcol);
802 casu_rename_property(p,"CRPIX1",key);
803 (void)snprintf(key,8,"TCRPX%d",ycol);
804 casu_rename_property(p,"CRPIX2",key);
805
806 /* Now PV matrix */
807
808 for (i = 1; i <= 5; i++) {
809 (void)snprintf(key2,8,"PV2_%d",i);
810 (void)snprintf(key,8,"TV%d_%d",ycol,i);
811 if (cpl_propertylist_has(p,key2))
812 casu_rename_property(p,key2,key);
813 }
814
815 /* Now the CD matrix */
816
817 (void)snprintf(key,8,"TC%d_%d",xcol,xcol);
818 casu_rename_property(p,"CD1_1",key);
819 (void)snprintf(key,8,"TC%d_%d",xcol,ycol);
820 casu_rename_property(p,"CD1_2",key);
821 (void)snprintf(key,8,"TC%d_%d",ycol,xcol);
822 casu_rename_property(p,"CD2_1",key);
823 (void)snprintf(key,8,"TC%d_%d",ycol,ycol);
824 casu_rename_property(p,"CD2_2",key);
825
826 /* Now get out of here */
827
828 GOOD_STATUS
829
830}
831
834/*
835
836$Log: casu_wcsutils.c,v $
837Revision 1.3 2015/11/18 20:06:47 jim
838superficial mod
839
840Revision 1.2 2015/08/07 13:06:54 jim
841Fixed copyright to ESO
842
843Revision 1.1.1.1 2015/06/12 10:44:32 jim
844Initial import
845
846Revision 1.4 2015/05/13 11:47:57 jim
847Fixed regular expressions
848
849Revision 1.3 2015/01/29 11:56:27 jim
850modified comments
851
852Revision 1.2 2013/11/21 09:38:14 jim
853detabbed
854
855Revision 1.1.1.1 2013-08-27 12:07:48 jim
856Imported
857
858
859*/
void casu_rename_property(cpl_propertylist *p, const char *oldname, char *newname)
Rename a property in a given propertylist.
Definition: casu_utils.c:485
int casu_removewcs(cpl_propertylist *p, int *status)
void casu_radectoxieta(cpl_wcs *wcs, double ra, double dec, double *xi, double *eta)
int casu_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff, float *yoff, int *status)
int casu_rescalecd(cpl_propertylist *p, double scalefac)
void casu_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x, double *y)
int casu_tabwcs(cpl_propertylist *p, int xcol, int ycol, int *status)
void casu_xytoradec(cpl_wcs *wcs, double x, double y, double *ra, double *dec)
Definition: casu_wcsutils.c:93
void casu_xytoxy_list(cpl_wcs *wcs1, cpl_wcs *wcs2, int nc, double *x_1, double *y_1, double *x_2, double *y_2)
int casu_crpixshift(cpl_propertylist *p, double scalefac, double sh[])
int casu_coverage(cpl_propertylist *plist, int fudge, double *ra1, double *ra2, double *dec1, double *dec2, int *status)