VIRCAM Pipeline  2.3.10
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
46 static 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 
93 extern 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 
151 extern 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 
212 extern 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 
281 extern 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 
345 extern 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 
464 extern 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 
554 extern 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 
650 extern 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 
713 extern 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 
761 extern 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 $
837 Revision 1.3 2015/11/18 20:06:47 jim
838 superficial mod
839 
840 Revision 1.2 2015/08/07 13:06:54 jim
841 Fixed copyright to ESO
842 
843 Revision 1.1.1.1 2015/06/12 10:44:32 jim
844 Initial import
845 
846 Revision 1.4 2015/05/13 11:47:57 jim
847 Fixed regular expressions
848 
849 Revision 1.3 2015/01/29 11:56:27 jim
850 modified comments
851 
852 Revision 1.2 2013/11/21 09:38:14 jim
853 detabbed
854 
855 Revision 1.1.1.1 2013-08-27 12:07:48 jim
856 Imported
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)