VIRCAM Pipeline  1.3.3
vircam_wcsutils.c
1 /* $Id: vircam_wcsutils.c,v 1.33 2013-10-15 16:57:39 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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: 2013-10-15 16:57:39 $
24  * $Revision: 1.33 $
25  * $Name: not supported by cvs2svn $
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 "vircam_wcsutils.h"
38 #include "vircam_pfits.h"
39 #include "vircam_utils.h"
40 
41 #define WCS_FATAL_ERR(_p) {cpl_msg_error(fctid,"Unable to find keyword %s",_p); cpl_error_reset(); return(wcs);}
42 
43 /* WCS keywords that should be removed from FITS tables*/
44 
45 #define SZKEY 9
46 #define NNOTABKEYS 6
47 static const char *notabkeys[NNOTABKEYS] = {"^CRVAL[1-2]*$","^CRPIX[1-2]*",
48  "^CD[1-2]*_[1-2]*","^CDELT[1-2]*",
49  "^CTYPE[1-2]*","^PV2_[1-5]*"};
50 
66 /*---------------------------------------------------------------------------*/
92 /*---------------------------------------------------------------------------*/
93 
94 extern void vircam_xytoradec(cpl_wcs *wcs, double x, double y, double *ra,
95  double *dec) {
96  double *xy,*radec;
97  cpl_matrix *from,*to;
98  cpl_array *status;
99 
100  /* Load up the information */
101 
102  from = cpl_matrix_new(1,2);
103  xy = cpl_matrix_get_data(from);
104  xy[0] = x;
105  xy[1] = y;
106 
107  /* Call the conversion routine */
108 
109  cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2WORLD);
110 
111  /* Pass it back now */
112 
113  radec = cpl_matrix_get_data(to);
114  *ra = radec[0];
115  *dec = radec[1];
116 
117  /* Tidy and exit */
118 
119  cpl_matrix_delete(from);
120  cpl_matrix_delete(to);
121  cpl_array_delete(status);
122  return;
123 }
124 
125 /*---------------------------------------------------------------------------*/
150 /*---------------------------------------------------------------------------*/
151 
152 extern void vircam_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x,
153  double *y) {
154  double *xy,*radec;
155  cpl_matrix *from,*to;
156  cpl_array *status;
157 
158  /* Load up the information */
159 
160  from = cpl_matrix_new(1,2);
161  radec = cpl_matrix_get_data(from);
162  radec[0] = ra;
163  radec[1] = dec;
164 
165  /* Call the conversion routine */
166 
167  cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2PHYS);
168 
169  /* Pass it back now */
170 
171  xy = cpl_matrix_get_data(to);
172  *x = xy[0];
173  *y = xy[1];
174 
175  /* Tidy and exit */
176 
177  cpl_matrix_delete(from);
178  cpl_matrix_delete(to);
179  cpl_array_delete(status);
180 }
181 
182 /*---------------------------------------------------------------------------*/
211 /*---------------------------------------------------------------------------*/
212 
213 extern void vircam_xytoxy_list(cpl_wcs *wcs1, cpl_wcs *wcs2, int nc,
214  double *x_1, double *y_1, double *x_2,
215  double *y_2) {
216  double *xy1;
217  cpl_matrix *from,*radec;
218  cpl_array *status;
219  int i;
220 
221  /* Load up the information */
222 
223  from = cpl_matrix_new(nc,2);
224  xy1 = cpl_matrix_get_data(from);
225  for (i = 0; i < nc; i++) {
226  xy1[2*i] = x_1[i];
227  xy1[2*i+1] = y_1[i];
228  }
229 
230  /* Convert to RA and Dec */
231 
232  cpl_wcs_convert(wcs1,from,&radec,&status,CPL_WCS_PHYS2WORLD);
233  cpl_array_delete(status);
234  cpl_matrix_delete(from);
235 
236  /* Now convert to x,y in the reference frame of the second image */
237 
238  cpl_wcs_convert(wcs2,radec,&from,&status,CPL_WCS_WORLD2PHYS);
239  cpl_array_delete(status);
240  cpl_matrix_delete(radec);
241 
242  /* No pass it back now */
243 
244  xy1 = cpl_matrix_get_data(from);
245  for (i = 0; i < nc; i++) {
246  x_2[i] = xy1[2*i];
247  y_2[i] = xy1[2*i+1];
248  }
249 
250  /* Tidy and exit */
251 
252  cpl_matrix_delete(from);
253 }
254 
255 /*---------------------------------------------------------------------------*/
281 /*---------------------------------------------------------------------------*/
282 
283 extern void vircam_radectoxieta(cpl_wcs *wcs, double ra, double dec,
284  double *xi, double *eta) {
285 
286  double *xy,*radec;
287  cpl_matrix *from,*to;
288  cpl_array *status;
289 
290  /* Load up the information */
291 
292  from = cpl_matrix_new(1,2);
293  radec = cpl_matrix_get_data(from);
294  radec[0] = ra;
295  radec[1] = dec;
296 
297  /* Call the conversion routine */
298 
299  cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2STD);
300 
301  /* Pass it back now */
302 
303  xy = cpl_matrix_get_data(to);
304  *xi = xy[0]/DEGRAD;
305  *eta = xy[1]/DEGRAD;
306 
307  /* Tidy and exit */
308 
309  cpl_matrix_delete(from);
310  cpl_matrix_delete(to);
311  cpl_array_delete(status);
312 }
313 
314 /*---------------------------------------------------------------------------*/
345 /*---------------------------------------------------------------------------*/
346 
347 extern int vircam_coverage(cpl_propertylist *plist, int fudge, double *ra1,
348  double *ra2, double *dec1, double *dec2,
349  int *status) {
350 
351  cpl_wcs *wcs;
352  double ra,dec,x,y,dra,ddec,boxfudge,min_4q,max_1q;
353  int first_quad,fourth_quad,ni,nj,istep;
354  const int *naxes;
355  long i,j;
356  const cpl_array *a;
357 
358  /* Initialise these in case of failure later*/
359 
360  *ra1 = 0.0;
361  *ra2 = 0.0;
362  *dec1 = 0.0;
363  *dec2 = 0.0;
364  if (*status != VIR_OK)
365  return(*status);
366 
367  /* Grab the WCS info from the property list */
368 
369  wcs = cpl_wcs_new_from_propertylist(plist);
370  if (wcs == NULL)
371  FATAL_ERROR
372 
373  /* Get the size of the data array */
374 
375  a = cpl_wcs_get_image_dims(wcs);
376  naxes = cpl_array_get_data_int_const(a);
377 
378  /* Find the RA and Dec limits of the image */
379 
380  *ra1 = 370.0;
381  *ra2 = -370.0;
382  *dec1 = 95.0;
383  *dec2 = -95.0;
384  first_quad = 0;
385  fourth_quad = 0;
386  min_4q = 370.0;
387  max_1q = 0.0;
388  istep = 10;
389  nj = naxes[1]/istep + 2;
390  ni = naxes[0]/istep + 2;
391  for (j = 1; j <= nj; j++) {
392  y = (double)min(naxes[1],(istep*(j-1)+1));
393  for (i = 1; i <= ni; i++) {
394  x = (double)min(naxes[0],(istep*(i-1)+1));
395  vircam_xytoradec(wcs,x,y,&ra,&dec);
396  if (ra >= 0.0 && ra <= 90.0) {
397  first_quad = 1;
398  max_1q = max(ra,max_1q);
399  } else if (ra >= 270.0 && ra <= 360.0) {
400  fourth_quad = 1;
401  min_4q = min((ra-360.0),min_4q);
402  }
403  *ra1 = min(*ra1,ra);
404  *ra2 = max(*ra2,ra);
405  *dec1 = min(*dec1,dec);
406  *dec2 = max(*dec2,dec);
407  }
408  }
409  cpl_wcs_delete(wcs);
410 
411  /* Now have a look to see if you had RA values in both the first and
412  fourth quadrants. If you have, then make the minimum RA a negative
413  value. This will be the signal to the caller that you have the
414  wraparound... */
415 
416  if (first_quad && fourth_quad) {
417  *ra1 = min_4q;
418  *ra2 = max_1q;
419  }
420 
421  /* Pad out search a bit */
422 
423  if (fudge) {
424  boxfudge = 0.01*(float)fudge;
425  dra = 0.5*boxfudge*(*ra2 - *ra1);
426  *ra1 -= dra;
427  *ra2 += dra;
428  ddec = 0.5*boxfudge*(*dec2 - *dec1);
429  *dec1 -= ddec;
430  *dec2 += ddec;
431  }
432 
433  /* Exit */
434 
435  GOOD_STATUS
436 }
437 
438 /*---------------------------------------------------------------------------*/
464 /*---------------------------------------------------------------------------*/
465 
466 extern int vircam_crpixshift(cpl_propertylist *p, double scalefac,
467  double sh[]) {
468  int i;
469  double val;
470  char key[SZKEY];
471  cpl_type type;
472  const char *fctid = "vircam_crpixshift";
473 
474  /* Make sure that the scale factor isn't zero */
475 
476  if (scalefac == 0.0) {
477  cpl_msg_error(fctid,"Scale factor is zero!");
478  return(VIR_FATAL);
479  }
480 
481  /* Loop through both axes. Shift and scale the values of crpix */
482 
483  for (i = 1; i <= 2; i++) {
484  snprintf(key,SZKEY,"CRPIX%d",i);
485 
486  /* First make sure the property exists. It damn well better exist! */
487 
488  if (cpl_propertylist_has(p,key) == 0) {
489  cpl_msg_error(fctid,"Header is missing WCS key %s",key);
490  return(VIR_FATAL);
491  }
492 
493  /* Now find the type... */
494 
495  type = cpl_propertylist_get_type(p,key);
496 
497  /* Switch for the type. If it's neither float nor double, then
498  signal an error as this is clearly nonsense. */
499 
500  switch (type) {
501  case CPL_TYPE_FLOAT:
502  val = (double)cpl_propertylist_get_float(p,key);
503  break;
504  case CPL_TYPE_DOUBLE:
505  val = cpl_propertylist_get_double(p,key);
506  break;
507  default:
508  cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
509  key);
510  return(VIR_FATAL);
511  }
512 
513  /* Right, now do the actual work */
514 
515  val = (val - sh[i-1])/scalefac - 1.0;
516 
517  /* And update the property now */
518 
519  switch (type) {
520  case CPL_TYPE_FLOAT:
521  cpl_propertylist_update_float(p,key,(float)val);
522  break;
523  case CPL_TYPE_DOUBLE:
524  cpl_propertylist_update_double(p,key,val);
525  break;
526  default:
527  break;
528  }
529  }
530  return(VIR_OK);
531 }
532 
533 /*---------------------------------------------------------------------------*/
555 /*---------------------------------------------------------------------------*/
556 
557 extern int vircam_rescalecd(cpl_propertylist *p, double scalefac) {
558  int i,j;
559  cpl_type type;
560  char key[SZKEY];
561  const char *fctid = "vircam_rescalecd";
562  double val;
563 
564  /* Make sure that the scale factor isn't zero */
565 
566  if (scalefac == 0.0) {
567  cpl_msg_error(fctid,"Scale factor is zero!");
568  return(VIR_FATAL);
569  }
570 
571  /* Loop through both axes. Shift and scale the values of cd */
572 
573  for (i = 1; i <= 2; i++) {
574  for (j = 1; j <= 2; j++) {
575  snprintf(key,SZKEY,"CD%d_%d",i,j);
576 
577  /* First make sure the property exists. It damn well better exist! */
578 
579  if (cpl_propertylist_has(p,key) == 0) {
580  cpl_msg_error(fctid,"Header is missing WCS key %s",key);
581  return(VIR_FATAL);
582  }
583 
584  /* Now find the type... */
585 
586  type = cpl_propertylist_get_type(p,key);
587 
588  /* Switch for the type. If it's neither float nor double, then
589  signal an error as this is clearly nonsense. */
590 
591  switch (type) {
592  case CPL_TYPE_FLOAT:
593  val = (double)cpl_propertylist_get_float(p,key);
594  break;
595  case CPL_TYPE_DOUBLE:
596  val = cpl_propertylist_get_double(p,key);
597  break;
598  default:
599  cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
600  key);
601  return(VIR_FATAL);
602  }
603 
604  /* Right, now do the actual work */
605 
606  val *= scalefac;
607 
608  /* And update the property now */
609 
610  switch (type) {
611  case CPL_TYPE_FLOAT:
612  cpl_propertylist_update_float(p,key,(float)val);
613  break;
614  case CPL_TYPE_DOUBLE:
615  cpl_propertylist_update_double(p,key,val);
616  break;
617  default:
618  break;
619  }
620  }
621  }
622  return(VIR_OK);
623 }
624 
625 /*---------------------------------------------------------------------------*/
651 /*---------------------------------------------------------------------------*/
652 
653 extern int vircam_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff,
654  float *yoff, int *status) {
655  double xc,yc,ra,dec,xnew,ynew;
656  const cpl_array *a;
657  const int *dims;
658  const char *fctid = "vircam_diffxywcs";
659 
660  /* Inherited status */
661 
662  *xoff = 0.0;
663  *yoff = 0.0;
664  if (*status != VIR_OK)
665  return(*status);
666 
667  /* Check for rubbish input */
668 
669  if (wcs == NULL || wcsref == NULL) {
670  cpl_msg_error(fctid,"NULL wcs information");
671  FATAL_ERROR
672  }
673 
674  /* Work out the ra and dec of the central pixel in the reference image */
675 
676  a = cpl_wcs_get_image_dims(wcsref);
677  dims = cpl_array_get_data_int_const(a);
678  xc = 0.5*(double)dims[0];
679  yc = 0.5*(double)dims[1];
680  vircam_xytoradec(wcsref,xc,yc,&ra,&dec);
681 
682  /* Ok, calculate where in x,y space these equatorial coordinates fall on
683  the programme image */
684 
685  vircam_radectoxy(wcs,ra,dec,&xnew,&ynew);
686 
687  /* Right, now return the offsets */
688 
689  *xoff = (float)(xc - xnew);
690  *yoff = (float)(yc - ynew);
691  GOOD_STATUS
692 }
693 
694 /*---------------------------------------------------------------------------*/
714 /*---------------------------------------------------------------------------*/
715 
716 extern int vircam_removewcs(cpl_propertylist *p, int *status) {
717  int i;
718  const char *fctid = "vircam_removewcs";
719 
720  /* Inherited status */
721 
722  if (*status != VIR_OK)
723  return(*status);
724  if (p == NULL) {
725  cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
726  FATAL_ERROR
727  }
728 
729  /* Loop through all the template keywords and remove them */
730 
731  for (i = 0; i < NNOTABKEYS; i++)
732  cpl_propertylist_erase_regexp(p,notabkeys[i],0);
733 
734  GOOD_STATUS
735 }
736 
737 /*---------------------------------------------------------------------------*/
762 /*---------------------------------------------------------------------------*/
763 
764 extern int vircam_tabwcs(cpl_propertylist *p, int xcol, int ycol,
765  int *status) {
766  int i;
767  char key[9],key2[9];
768  const char *fctid="vircam_tabwcs";
769 
770  /* Inherited status */
771 
772  if (*status != VIR_OK)
773  return(*status);
774  if (p == NULL) {
775  cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
776  FATAL_ERROR
777  }
778 
779  /* If either of the columns are -1, then just get rid of the image WCS
780  and get out of here */
781 
782  if (xcol == -1 || ycol == -1) {
783  vircam_removewcs(p,status);
784  GOOD_STATUS
785  }
786 
787  /* Go through the standard VIRCAM WCS header keywords one by one
788  and translate them. Start with CTYPE */
789 
790  (void)snprintf(key,8,"TCTYP%d",xcol);
791  vircam_rename_property(p,"CTYPE1",key);
792  (void)snprintf(key,8,"TCTYP%d",ycol);
793  vircam_rename_property(p,"CTYPE2",key);
794 
795 
796  /* Now CRVAL */
797 
798  (void)snprintf(key,8,"TCRVL%d",xcol);
799  vircam_rename_property(p,"CRVAL1",key);
800  (void)snprintf(key,8,"TCRVL%d",ycol);
801  vircam_rename_property(p,"CRVAL2",key);
802 
803  /* Now CRPIX */
804 
805  (void)snprintf(key,8,"TCRPX%d",xcol);
806  vircam_rename_property(p,"CRPIX1",key);
807  (void)snprintf(key,8,"TCRPX%d",ycol);
808  vircam_rename_property(p,"CRPIX2",key);
809 
810  /* Now PV matrix */
811 
812  for (i = 1; i <= 5; i++) {
813  (void)snprintf(key2,8,"PV2_%d",i);
814  (void)snprintf(key,8,"TV%d_%d",ycol,i);
815  if (cpl_propertylist_has(p,key2))
816  vircam_rename_property(p,key2,key);
817  }
818 
819  /* Now the CD matrix */
820 
821  (void)snprintf(key,8,"TC%d_%d",xcol,xcol);
822  vircam_rename_property(p,"CD1_1",key);
823  (void)snprintf(key,8,"TC%d_%d",xcol,ycol);
824  vircam_rename_property(p,"CD1_2",key);
825  (void)snprintf(key,8,"TC%d_%d",ycol,xcol);
826  vircam_rename_property(p,"CD2_1",key);
827  (void)snprintf(key,8,"TC%d_%d",ycol,ycol);
828  vircam_rename_property(p,"CD2_2",key);
829 
830  /* Now get out of here */
831 
832  GOOD_STATUS
833 
834 }
835 
836 
839 /*
840 
841 $Log: not supported by cvs2svn $
842 Revision 1.32 2010/06/30 12:42:00 jim
843 A few fixes to stop compiler compaints
844 
845 Revision 1.31 2009/02/20 11:35:43 jim
846 Removed superfluous declarations
847 
848 Revision 1.30 2008/11/21 10:14:28 jim
849 Fixed small bug in vircam_coverage which means it was missing out the last
850 bit of the image
851 
852 Revision 1.29 2008/10/21 08:44:00 jim
853 Fixed some declarations to make them constant
854 
855 Revision 1.28 2008/07/10 13:05:53 jim
856 Modified to use v4.2 version of cpl_wcs
857 
858 Revision 1.27 2008/06/20 11:14:01 jim
859 Fixed dodgy call to cpl_wcs_get_image_dims
860 
861 Revision 1.26 2008/05/06 08:40:10 jim
862 Modified to use cpl_wcs interface
863 
864 Revision 1.25 2007/10/25 17:34:01 jim
865 Modified to remove lint warnings
866 
867 Revision 1.24 2007/10/15 12:50:28 jim
868 Modified for compatibility with cpl_4.0
869 
870 Revision 1.23 2007/05/14 15:25:28 jim
871 Fixed formatting of wcs floating point parameters in vircam_wcsopen
872 
873 Revision 1.22 2007/05/03 11:15:33 jim
874 Fixed little problem with table wcs
875 
876 Revision 1.21 2007/05/02 12:53:11 jim
877 typo fixes in docs
878 
879 Revision 1.20 2007/05/02 09:16:12 jim
880 Added vircam_tabwcs
881 
882 Revision 1.19 2007/03/01 12:42:42 jim
883 Modified slightly after code checking
884 
885 Revision 1.18 2007/01/17 23:54:01 jim
886 Plugged some memory leaks
887 
888 Revision 1.17 2007/01/08 19:12:49 jim
889 Fixed stupid calloc
890 
891 Revision 1.16 2006/10/05 09:23:00 jim
892 Small modifications to a couple of cpl calls to bring them into line with
893 cpl v3.0
894 
895 Revision 1.15 2006/08/11 12:45:41 jim
896 Modified to use wcslib
897 
898 Revision 1.14 2006/07/04 09:19:06 jim
899 replaced all sprintf statements with snprintf
900 
901 Revision 1.13 2006/07/03 09:33:19 jim
902 Fixed a few things to keep the compiler happy
903 
904 Revision 1.12 2006/06/14 14:13:58 jim
905 fixed minor doc problem
906 
907 Revision 1.11 2006/06/13 14:09:54 jim
908 Added vircam_removewcs
909 
910 Revision 1.10 2006/05/24 13:36:15 jim
911 Added vircam_diffxywcs
912 
913 Revision 1.9 2006/04/20 11:30:29 jim
914 Added naxis1 and naxis2 to the structure
915 
916 Revision 1.8 2006/03/22 13:58:32 jim
917 Cosmetic fixes to keep lint happy
918 
919 Revision 1.7 2006/02/18 11:48:55 jim
920 *** empty log message ***
921 
922 Revision 1.6 2006/01/23 10:30:50 jim
923 Mainly documentation mods
924 
925 Revision 1.5 2005/12/14 22:17:33 jim
926 Updated docs
927 
928 Revision 1.4 2005/11/29 11:37:38 jim
929 fixed bug in error macro
930 
931 Revision 1.3 2005/11/25 15:33:22 jim
932 Some code fixes to keep splint happy
933 
934 Revision 1.2 2005/11/03 13:28:51 jim
935 All sorts of changes to tighten up error handling
936 
937 Revision 1.1.1.1 2005/08/05 08:29:09 jim
938 Initial import
939 
940 
941 */