vircam_wcsutils.c

00001 /* $Id: vircam_wcsutils.c,v 1.28 2008/07/10 13:05:53 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jim $
00023  * $Date: 2008/07/10 13:05:53 $
00024  * $Revision: 1.28 $
00025  * $Name:  $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <cpl.h>
00035 #include <math.h>
00036 
00037 #include "vircam_wcsutils.h"
00038 #include "vircam_pfits.h"
00039 #include "vircam_utils.h"
00040 
00041 #define WCS_FATAL_ERR(_p) {cpl_msg_error(fctid,"Unable to find keyword %s",_p); cpl_error_reset(); return(wcs);}
00042 
00043 /* WCS keywords that should be removed from FITS tables*/
00044 
00045 #define NNOTABKEYS 6
00046 static const char *notabkeys[NNOTABKEYS] = {"^CRVAL[1-2]*$","^CRPIX[1-2]*",
00047                                             "^CD[1-2]*_[1-2]*","^CDELT[1-2]*",
00048                                             "^CTYPE[1-2]*","^PV2_[1-5]*"};
00049 
00050 /* Define a list of VIRCAM WCS header keywords */
00051 
00052 #define NWCSKEYS 15
00053 static const char *vir_wcskeys[NWCSKEYS] = {"CTYPE1","CTYPE2","CRVAL1",
00054                                             "CRVAL2","CRPIX1","CRPIX2","CD1_1",
00055                                             "CD1_2","CD2_1","CD2_2","PV2_1",
00056                                             "PV2_2","PV2_3","PV2_4","PV2_5"};
00057 
00058 #define SZKEY 9
00059 
00075 /*---------------------------------------------------------------------------*/
00101 /*---------------------------------------------------------------------------*/
00102 
00103 extern void vircam_xytoradec(cpl_wcs *wcs, double x, double y, double *ra,
00104                              double *dec) {
00105     double *xy,*radec;
00106     cpl_matrix *from,*to;
00107     cpl_array *status;
00108     int stat;
00109 
00110     /* Load up the information */
00111     
00112     from = cpl_matrix_new(1,2);
00113     xy = cpl_matrix_get_data(from);
00114     xy[0] = x;
00115     xy[1] = y;
00116 
00117     /* Call the conversion routine */
00118 
00119     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2WORLD);
00120 
00121     /* Pass it back now */
00122 
00123     radec = cpl_matrix_get_data(to);
00124     *ra = radec[0];
00125     *dec = radec[1];
00126 
00127     /* Tidy and exit */
00128 
00129     cpl_matrix_delete(from);
00130     cpl_matrix_delete(to);
00131     cpl_array_delete(status);
00132     return;
00133 }
00134 
00135 /*---------------------------------------------------------------------------*/
00160 /*---------------------------------------------------------------------------*/
00161 
00162 extern void vircam_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x,
00163                              double *y) {
00164     double *xy,*radec;
00165     cpl_matrix *from,*to;
00166     cpl_array *status;
00167     int stat;
00168 
00169     /* Load up the information */
00170     
00171     from = cpl_matrix_new(1,2);
00172     radec = cpl_matrix_get_data(from);
00173     radec[0] = ra;
00174     radec[1] = dec;
00175 
00176     /* Call the conversion routine */
00177 
00178     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2PHYS);
00179 
00180     /* Pass it back now */
00181 
00182     xy = cpl_matrix_get_data(to);
00183     *x = xy[0];
00184     *y = xy[1];
00185 
00186     /* Tidy and exit */
00187 
00188     cpl_matrix_delete(from);
00189     cpl_matrix_delete(to);
00190     cpl_array_delete(status);
00191 }
00192 
00193 /*---------------------------------------------------------------------------*/
00219 /*---------------------------------------------------------------------------*/
00220 
00221 extern void vircam_radectoxieta(cpl_wcs *wcs, double ra, double dec, 
00222                                 double *xi, double *eta) {
00223 
00224     double *xy,*radec;
00225     cpl_matrix *from,*to;
00226     cpl_array *status;
00227     int stat;
00228 
00229     /* Load up the information */
00230     
00231     from = cpl_matrix_new(1,2);
00232     radec = cpl_matrix_get_data(from);
00233     radec[0] = ra;
00234     radec[1] = dec;
00235 
00236     /* Call the conversion routine */
00237 
00238     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2STD);
00239 
00240     /* Pass it back now */
00241 
00242     xy = cpl_matrix_get_data(to);
00243     *xi = xy[0]/DEGRAD;
00244     *eta = xy[1]/DEGRAD;
00245 
00246     /* Tidy and exit */
00247 
00248     cpl_matrix_delete(from);
00249     cpl_matrix_delete(to);
00250     cpl_array_delete(status);
00251 }
00252 
00253 /*---------------------------------------------------------------------------*/
00284 /*---------------------------------------------------------------------------*/
00285 
00286 extern int vircam_coverage(cpl_propertylist *plist, int fudge, double *ra1, 
00287                            double *ra2, double *dec1, double *dec2, 
00288                            int *status) {
00289 
00290     cpl_wcs *wcs;
00291     double ra,dec,x,y,dra,ddec,boxfudge,min_4q,max_1q;
00292     int first_quad,fourth_quad,*naxes;
00293     long i,j;
00294     cpl_array *a;
00295 
00296     /* Initialise these in case of failure later*/
00297 
00298     *ra1 = 0.0;
00299     *ra2 = 0.0;
00300     *dec1 = 0.0;
00301     *dec2 = 0.0;
00302     if (*status != VIR_OK)
00303         return(*status);
00304 
00305     /* Grab the WCS info from the property list */
00306 
00307     wcs = cpl_wcs_new_from_propertylist(plist);
00308     if (wcs == NULL) 
00309         FATAL_ERROR
00310 
00311     /* Get the size of the data array */
00312 
00313     a = cpl_wcs_get_image_dims(wcs);
00314     naxes = cpl_array_get_data_int(a);
00315 
00316     /* Find the RA and Dec limits of the image */
00317 
00318     *ra1 = 370.0;
00319     *ra2 = -370.0;
00320     *dec1 = 95.0;
00321     *dec2 = -95.0;
00322     first_quad = 0;
00323     fourth_quad = 0;
00324     min_4q = 370.0;
00325     max_1q = 0.0;
00326     for (j = 1; j < naxes[1]; j += 10) {
00327         j = min(j,naxes[1]);
00328         y = (double)j;
00329         for (i = 1; i < naxes[0]; i += 10) {
00330             i = min(i,naxes[0]);
00331             x = (double)i;
00332             vircam_xytoradec(wcs,x,y,&ra,&dec);
00333             if (ra >= 0.0 && ra <= 90.0) {
00334                 first_quad = 1;
00335                 max_1q = max(ra,max_1q);
00336             } else if (ra >= 270.0 && ra <= 360.0) {
00337                 fourth_quad = 1;
00338                 min_4q = min((ra-360.0),min_4q);
00339             }
00340             *ra1 = min(*ra1,ra);
00341             *ra2 = max(*ra2,ra);
00342             *dec1 = min(*dec1,dec);
00343             *dec2 = max(*dec2,dec);
00344         }
00345     }
00346     cpl_wcs_delete(wcs);
00347 
00348     /* Now have a look to see if you had RA values in both the first and
00349        fourth quadrants.  If you have, then make the minimum RA a negative
00350        value.  This will be the signal to the caller that you have the
00351        wraparound... */
00352 
00353     if (first_quad && fourth_quad) {
00354         *ra1 = min_4q;
00355         *ra2 = max_1q;
00356     }
00357 
00358     /* Pad out search a bit */
00359 
00360     if (fudge) {
00361         boxfudge = 0.01*(float)fudge;
00362         dra = 0.5*boxfudge*(*ra2 - *ra1);
00363         *ra1 -= dra;
00364         *ra2 += dra;
00365         ddec = 0.5*boxfudge*(*dec2 - *dec1);
00366         *dec1 -= ddec;
00367         *dec2 += ddec;
00368     }
00369 
00370     /* Exit */
00371 
00372     GOOD_STATUS
00373 }
00374 
00375 /*---------------------------------------------------------------------------*/
00401 /*---------------------------------------------------------------------------*/
00402 
00403 extern int vircam_crpixshift(cpl_propertylist *p, double scalefac, 
00404                              double sh[]) {
00405     int i;
00406     double val;
00407     char key[SZKEY];
00408     cpl_type type;
00409     const char *fctid = "vircam_crpixshift";
00410 
00411     /* Make sure that the scale factor isn't zero */
00412 
00413     if (scalefac == 0.0) {
00414         cpl_msg_error(fctid,"Scale factor is zero!");
00415         return(VIR_FATAL);
00416     }
00417 
00418     /* Loop through both axes. Shift and scale the values of crpix */
00419 
00420     for (i = 1; i <= 2; i++) {
00421         snprintf(key,SZKEY,"CRPIX%d",i);
00422 
00423         /* First make sure the property exists. It damn well better exist! */
00424 
00425         if (cpl_propertylist_has(p,key) == 0) {
00426             cpl_msg_error(fctid,"Header is missing WCS key %s",key);
00427             return(VIR_FATAL);
00428         }
00429 
00430         /* Now find the type... */
00431 
00432         type = cpl_propertylist_get_type(p,key);
00433 
00434         /* Switch for the type. If it's neither float nor double, then 
00435            signal an error as this is clearly nonsense. */
00436 
00437         switch (type) {
00438         case CPL_TYPE_FLOAT:
00439             val = (double)cpl_propertylist_get_float(p,key);
00440             break;
00441         case CPL_TYPE_DOUBLE:
00442             val = cpl_propertylist_get_double(p,key);
00443             break;
00444         default:
00445             cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
00446                           key);
00447             return(VIR_FATAL);
00448         }
00449 
00450         /* Right, now do the actual work */
00451 
00452         val = (val - sh[i-1])/scalefac - 1.0;
00453 
00454         /* And update the property now */
00455 
00456         switch (type) {
00457         case CPL_TYPE_FLOAT:
00458             cpl_propertylist_update_float(p,key,(float)val);
00459             break;
00460         case CPL_TYPE_DOUBLE:
00461             cpl_propertylist_update_double(p,key,val);
00462             break;
00463         default:
00464             break;
00465         }
00466     }
00467     return(VIR_OK);
00468 }
00469 
00470 /*---------------------------------------------------------------------------*/
00492 /*---------------------------------------------------------------------------*/
00493 
00494 extern int vircam_rescalecd(cpl_propertylist *p, double scalefac) {
00495     int i,j;
00496     cpl_type type;
00497     char key[SZKEY];
00498     const char *fctid = "vircam_rescalecd";
00499     double val;
00500 
00501     /* Make sure that the scale factor isn't zero */
00502 
00503     if (scalefac == 0.0) {
00504         cpl_msg_error(fctid,"Scale factor is zero!");
00505         return(VIR_FATAL);
00506     }
00507 
00508     /* Loop through both axes. Shift and scale the values of cd */
00509 
00510     for (i = 1; i <= 2; i++) {
00511         for (j = 1; j <= 2; j++) {
00512             snprintf(key,SZKEY,"CD%d_%d",i,j);
00513 
00514             /* First make sure the property exists. It damn well better exist! */
00515 
00516             if (cpl_propertylist_has(p,key) == 0) {
00517                 cpl_msg_error(fctid,"Header is missing WCS key %s",key);
00518                 return(VIR_FATAL);
00519             }
00520 
00521             /* Now find the type... */
00522 
00523             type = cpl_propertylist_get_type(p,key);
00524 
00525             /* Switch for the type. If it's neither float nor double, then 
00526                signal an error as this is clearly nonsense. */
00527 
00528             switch (type) {
00529             case CPL_TYPE_FLOAT:
00530                 val = (double)cpl_propertylist_get_float(p,key);
00531                 break;
00532             case CPL_TYPE_DOUBLE:
00533                 val = cpl_propertylist_get_double(p,key);
00534                 break;
00535             default:
00536                 cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
00537                               key);
00538                 return(VIR_FATAL);
00539             }
00540 
00541             /* Right, now do the actual work */
00542 
00543             val *= scalefac;
00544 
00545             /* And update the property now */
00546 
00547             switch (type) {
00548             case CPL_TYPE_FLOAT:
00549                 cpl_propertylist_update_float(p,key,(float)val);
00550                 break;
00551             case CPL_TYPE_DOUBLE:
00552                 cpl_propertylist_update_double(p,key,val);
00553                 break;
00554             default:
00555                 break;
00556             }
00557         }
00558     }
00559     return(VIR_OK);
00560 }
00561     
00562 /*---------------------------------------------------------------------------*/
00588 /*---------------------------------------------------------------------------*/
00589 
00590 extern int vircam_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff,
00591                             float *yoff, int *status) {
00592     double xc,yc,ra,dec,xnew,ynew;
00593     cpl_array *a;
00594     int *dims;
00595     const char *fctid = "vircam_diffxywcs";
00596 
00597     /* Inherited status */
00598 
00599     *xoff = 0.0;
00600     *yoff = 0.0;
00601     if (*status != VIR_OK) 
00602         return(*status);
00603 
00604     /* Check for rubbish input */
00605 
00606     if (wcs == NULL || wcsref == NULL) {
00607         cpl_msg_error(fctid,"NULL wcs information");
00608         FATAL_ERROR
00609     }
00610 
00611     /* Work out the ra and dec of the central pixel in the reference image */
00612 
00613     a = cpl_wcs_get_image_dims(wcsref);
00614     dims = cpl_array_get_data_int(a);
00615     xc = 0.5*(double)dims[0];
00616     yc = 0.5*(double)dims[1];
00617     vircam_xytoradec(wcsref,xc,yc,&ra,&dec);
00618 
00619     /* Ok, calculate where in x,y space these equatorial coordinates fall on
00620        the programme image */
00621 
00622     vircam_radectoxy(wcs,ra,dec,&xnew,&ynew);
00623 
00624     /* Right, now return the offsets */
00625 
00626     *xoff = (float)(xc - xnew);
00627     *yoff = (float)(yc - ynew);
00628     GOOD_STATUS
00629 }
00630 
00631 /*---------------------------------------------------------------------------*/
00651 /*---------------------------------------------------------------------------*/
00652 
00653 extern int vircam_removewcs(cpl_propertylist *p, int *status) {
00654     int i;
00655     const char *fctid = "vircam_removewcs";
00656 
00657     /* Inherited status */
00658 
00659     if (*status != VIR_OK)
00660         return(*status);
00661     if (p == NULL) {
00662         cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
00663         FATAL_ERROR
00664     }
00665 
00666     /* Loop through all the template keywords and remove them */
00667 
00668     for (i = 0; i < NNOTABKEYS; i++) 
00669         cpl_propertylist_erase_regexp(p,notabkeys[i],0);
00670 
00671     GOOD_STATUS
00672 }
00673 
00674 /*---------------------------------------------------------------------------*/
00699 /*---------------------------------------------------------------------------*/
00700 
00701 extern int vircam_tabwcs(cpl_propertylist *p, int xcol, int ycol, 
00702                          int *status) {
00703     int i;
00704     char key[9],key2[9],*fctid="vircam_tabwcs";
00705 
00706     /* Inherited status */
00707 
00708     if (*status != VIR_OK)
00709         return(*status);
00710     if (p == NULL) {
00711         cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
00712         FATAL_ERROR
00713     }
00714 
00715     /* If either of the columns are -1, then just get rid of the image WCS 
00716        and get out of here */
00717 
00718     if (xcol == -1 || ycol == -1) {
00719         vircam_removewcs(p,status);
00720         GOOD_STATUS
00721     }
00722 
00723     /* Go through the standard VIRCAM WCS header keywords one by one
00724        and translate them.  Start with CTYPE */
00725 
00726     (void)snprintf(key,8,"TCTYP%d",xcol);
00727     vircam_rename_property(p,"CTYPE1",key);
00728     (void)snprintf(key,8,"TCTYP%d",ycol);
00729     vircam_rename_property(p,"CTYPE2",key);
00730 
00731 
00732     /* Now CRVAL */
00733 
00734     (void)snprintf(key,8,"TCRVL%d",xcol);
00735     vircam_rename_property(p,"CRVAL1",key);
00736     (void)snprintf(key,8,"TCRVL%d",ycol);
00737     vircam_rename_property(p,"CRVAL2",key);
00738 
00739     /* Now CRPIX */
00740 
00741     (void)snprintf(key,8,"TCRPX%d",xcol);
00742     vircam_rename_property(p,"CRPIX1",key);
00743     (void)snprintf(key,8,"TCRPX%d",ycol);
00744     vircam_rename_property(p,"CRPIX2",key);
00745 
00746     /* Now PV matrix */
00747 
00748     for (i = 1; i <= 5; i++) {
00749         (void)snprintf(key2,8,"PV2_%d",i);
00750         (void)snprintf(key,8,"TV%d_%d",ycol,i);
00751         if (cpl_propertylist_has(p,key2))
00752             vircam_rename_property(p,key2,key);
00753     }
00754 
00755     /* Now the CD matrix */
00756 
00757     (void)snprintf(key,8,"TC%d_%d",xcol,xcol);
00758     vircam_rename_property(p,"CD1_1",key);
00759     (void)snprintf(key,8,"TC%d_%d",xcol,ycol);
00760     vircam_rename_property(p,"CD1_2",key);
00761     (void)snprintf(key,8,"TC%d_%d",ycol,xcol);
00762     vircam_rename_property(p,"CD2_1",key);
00763     (void)snprintf(key,8,"TC%d_%d",ycol,ycol);
00764     vircam_rename_property(p,"CD2_2",key);
00765 
00766     /* Now get out of here */
00767 
00768     GOOD_STATUS
00769     
00770 }
00771 
00772 
00775 /*
00776 
00777 $Log: vircam_wcsutils.c,v $
00778 Revision 1.28  2008/07/10 13:05:53  jim
00779 Modified to use v4.2 version of cpl_wcs
00780 
00781 Revision 1.27  2008/06/20 11:14:01  jim
00782 Fixed dodgy call to cpl_wcs_get_image_dims
00783 
00784 Revision 1.26  2008/05/06 08:40:10  jim
00785 Modified to use cpl_wcs interface
00786 
00787 Revision 1.25  2007/10/25 17:34:01  jim
00788 Modified to remove lint warnings
00789 
00790 Revision 1.24  2007/10/15 12:50:28  jim
00791 Modified for compatibility with cpl_4.0
00792 
00793 Revision 1.23  2007/05/14 15:25:28  jim
00794 Fixed formatting of wcs floating point parameters in vircam_wcsopen
00795 
00796 Revision 1.22  2007/05/03 11:15:33  jim
00797 Fixed little problem with table wcs
00798 
00799 Revision 1.21  2007/05/02 12:53:11  jim
00800 typo fixes in docs
00801 
00802 Revision 1.20  2007/05/02 09:16:12  jim
00803 Added vircam_tabwcs
00804 
00805 Revision 1.19  2007/03/01 12:42:42  jim
00806 Modified slightly after code checking
00807 
00808 Revision 1.18  2007/01/17 23:54:01  jim
00809 Plugged some memory leaks
00810 
00811 Revision 1.17  2007/01/08 19:12:49  jim
00812 Fixed stupid calloc
00813 
00814 Revision 1.16  2006/10/05 09:23:00  jim
00815 Small modifications to a couple of cpl calls to bring them into line with
00816 cpl v3.0
00817 
00818 Revision 1.15  2006/08/11 12:45:41  jim
00819 Modified to use wcslib
00820 
00821 Revision 1.14  2006/07/04 09:19:06  jim
00822 replaced all sprintf statements with snprintf
00823 
00824 Revision 1.13  2006/07/03 09:33:19  jim
00825 Fixed a few things to keep the compiler happy
00826 
00827 Revision 1.12  2006/06/14 14:13:58  jim
00828 fixed minor doc problem
00829 
00830 Revision 1.11  2006/06/13 14:09:54  jim
00831 Added vircam_removewcs
00832 
00833 Revision 1.10  2006/05/24 13:36:15  jim
00834 Added vircam_diffxywcs
00835 
00836 Revision 1.9  2006/04/20 11:30:29  jim
00837 Added naxis1 and naxis2 to the structure
00838 
00839 Revision 1.8  2006/03/22 13:58:32  jim
00840 Cosmetic fixes to keep lint happy
00841 
00842 Revision 1.7  2006/02/18 11:48:55  jim
00843 *** empty log message ***
00844 
00845 Revision 1.6  2006/01/23 10:30:50  jim
00846 Mainly documentation mods
00847 
00848 Revision 1.5  2005/12/14 22:17:33  jim
00849 Updated docs
00850 
00851 Revision 1.4  2005/11/29 11:37:38  jim
00852 fixed bug in error macro
00853 
00854 Revision 1.3  2005/11/25 15:33:22  jim
00855 Some code fixes to keep splint happy
00856 
00857 Revision 1.2  2005/11/03 13:28:51  jim
00858 All sorts of changes to tighten up error handling
00859 
00860 Revision 1.1.1.1  2005/08/05 08:29:09  jim
00861 Initial import
00862 
00863 
00864 */

Generated on Wed Apr 10 04:01:57 2013 for VIRCAM Pipeline by  doxygen 1.5.1