vircam_wcsutils.c

00001 /* $Id: vircam_wcsutils.c,v 1.32 2010/06/30 12:42:00 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: 2010/06/30 12:42:00 $
00024  * $Revision: 1.32 $
00025  * $Name: vcam-1_3_2 $
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 SZKEY 9
00046 #define NNOTABKEYS 6
00047 static const char *notabkeys[NNOTABKEYS] = {"^CRVAL[1-2]*$","^CRPIX[1-2]*",
00048                                             "^CD[1-2]*_[1-2]*","^CDELT[1-2]*",
00049                                             "^CTYPE[1-2]*","^PV2_[1-5]*"};
00050 
00066 /*---------------------------------------------------------------------------*/
00092 /*---------------------------------------------------------------------------*/
00093 
00094 extern void vircam_xytoradec(cpl_wcs *wcs, double x, double y, double *ra,
00095                              double *dec) {
00096     double *xy,*radec;
00097     cpl_matrix *from,*to;
00098     cpl_array *status;
00099 
00100     /* Load up the information */
00101     
00102     from = cpl_matrix_new(1,2);
00103     xy = cpl_matrix_get_data(from);
00104     xy[0] = x;
00105     xy[1] = y;
00106 
00107     /* Call the conversion routine */
00108 
00109     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_PHYS2WORLD);
00110 
00111     /* Pass it back now */
00112 
00113     radec = cpl_matrix_get_data(to);
00114     *ra = radec[0];
00115     *dec = radec[1];
00116 
00117     /* Tidy and exit */
00118 
00119     cpl_matrix_delete(from);
00120     cpl_matrix_delete(to);
00121     cpl_array_delete(status);
00122     return;
00123 }
00124 
00125 /*---------------------------------------------------------------------------*/
00150 /*---------------------------------------------------------------------------*/
00151 
00152 extern void vircam_radectoxy(cpl_wcs *wcs, double ra, double dec, double *x,
00153                              double *y) {
00154     double *xy,*radec;
00155     cpl_matrix *from,*to;
00156     cpl_array *status;
00157 
00158     /* Load up the information */
00159     
00160     from = cpl_matrix_new(1,2);
00161     radec = cpl_matrix_get_data(from);
00162     radec[0] = ra;
00163     radec[1] = dec;
00164 
00165     /* Call the conversion routine */
00166 
00167     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2PHYS);
00168 
00169     /* Pass it back now */
00170 
00171     xy = cpl_matrix_get_data(to);
00172     *x = xy[0];
00173     *y = xy[1];
00174 
00175     /* Tidy and exit */
00176 
00177     cpl_matrix_delete(from);
00178     cpl_matrix_delete(to);
00179     cpl_array_delete(status);
00180 }
00181 
00182 /*---------------------------------------------------------------------------*/
00208 /*---------------------------------------------------------------------------*/
00209 
00210 extern void vircam_radectoxieta(cpl_wcs *wcs, double ra, double dec, 
00211                                 double *xi, double *eta) {
00212 
00213     double *xy,*radec;
00214     cpl_matrix *from,*to;
00215     cpl_array *status;
00216 
00217     /* Load up the information */
00218     
00219     from = cpl_matrix_new(1,2);
00220     radec = cpl_matrix_get_data(from);
00221     radec[0] = ra;
00222     radec[1] = dec;
00223 
00224     /* Call the conversion routine */
00225 
00226     cpl_wcs_convert(wcs,from,&to,&status,CPL_WCS_WORLD2STD);
00227 
00228     /* Pass it back now */
00229 
00230     xy = cpl_matrix_get_data(to);
00231     *xi = xy[0]/DEGRAD;
00232     *eta = xy[1]/DEGRAD;
00233 
00234     /* Tidy and exit */
00235 
00236     cpl_matrix_delete(from);
00237     cpl_matrix_delete(to);
00238     cpl_array_delete(status);
00239 }
00240 
00241 /*---------------------------------------------------------------------------*/
00272 /*---------------------------------------------------------------------------*/
00273 
00274 extern int vircam_coverage(cpl_propertylist *plist, int fudge, double *ra1, 
00275                            double *ra2, double *dec1, double *dec2, 
00276                            int *status) {
00277 
00278     cpl_wcs *wcs;
00279     double ra,dec,x,y,dra,ddec,boxfudge,min_4q,max_1q;
00280     int first_quad,fourth_quad,ni,nj,istep;
00281     const int *naxes;
00282     long i,j;
00283     const cpl_array *a;
00284 
00285     /* Initialise these in case of failure later*/
00286 
00287     *ra1 = 0.0;
00288     *ra2 = 0.0;
00289     *dec1 = 0.0;
00290     *dec2 = 0.0;
00291     if (*status != VIR_OK)
00292         return(*status);
00293 
00294     /* Grab the WCS info from the property list */
00295 
00296     wcs = cpl_wcs_new_from_propertylist(plist);
00297     if (wcs == NULL) 
00298         FATAL_ERROR
00299 
00300     /* Get the size of the data array */
00301 
00302     a = cpl_wcs_get_image_dims(wcs);
00303     naxes = cpl_array_get_data_int_const(a);
00304 
00305     /* Find the RA and Dec limits of the image */
00306 
00307     *ra1 = 370.0;
00308     *ra2 = -370.0;
00309     *dec1 = 95.0;
00310     *dec2 = -95.0;
00311     first_quad = 0;
00312     fourth_quad = 0;
00313     min_4q = 370.0;
00314     max_1q = 0.0;
00315     istep = 10;
00316     nj = naxes[1]/istep + 2;
00317     ni = naxes[0]/istep + 2;
00318     for (j = 1; j <= nj; j++) {
00319         y = (double)min(naxes[1],(istep*(j-1)+1));
00320         for (i = 1; i <= ni; i++) {
00321             x = (double)min(naxes[0],(istep*(i-1)+1));
00322             vircam_xytoradec(wcs,x,y,&ra,&dec);
00323             if (ra >= 0.0 && ra <= 90.0) {
00324                 first_quad = 1;
00325                 max_1q = max(ra,max_1q);
00326             } else if (ra >= 270.0 && ra <= 360.0) {
00327                 fourth_quad = 1;
00328                 min_4q = min((ra-360.0),min_4q);
00329             }
00330             *ra1 = min(*ra1,ra);
00331             *ra2 = max(*ra2,ra);
00332             *dec1 = min(*dec1,dec);
00333             *dec2 = max(*dec2,dec);
00334         }       
00335     }
00336     cpl_wcs_delete(wcs);
00337 
00338     /* Now have a look to see if you had RA values in both the first and
00339        fourth quadrants.  If you have, then make the minimum RA a negative
00340        value.  This will be the signal to the caller that you have the
00341        wraparound... */
00342 
00343     if (first_quad && fourth_quad) {
00344         *ra1 = min_4q;
00345         *ra2 = max_1q;
00346     }
00347 
00348     /* Pad out search a bit */
00349 
00350     if (fudge) {
00351         boxfudge = 0.01*(float)fudge;
00352         dra = 0.5*boxfudge*(*ra2 - *ra1);
00353         *ra1 -= dra;
00354         *ra2 += dra;
00355         ddec = 0.5*boxfudge*(*dec2 - *dec1);
00356         *dec1 -= ddec;
00357         *dec2 += ddec;
00358     }
00359 
00360     /* Exit */
00361 
00362     GOOD_STATUS
00363 }
00364 
00365 /*---------------------------------------------------------------------------*/
00391 /*---------------------------------------------------------------------------*/
00392 
00393 extern int vircam_crpixshift(cpl_propertylist *p, double scalefac, 
00394                              double sh[]) {
00395     int i;
00396     double val;
00397     char key[SZKEY];
00398     cpl_type type;
00399     const char *fctid = "vircam_crpixshift";
00400 
00401     /* Make sure that the scale factor isn't zero */
00402 
00403     if (scalefac == 0.0) {
00404         cpl_msg_error(fctid,"Scale factor is zero!");
00405         return(VIR_FATAL);
00406     }
00407 
00408     /* Loop through both axes. Shift and scale the values of crpix */
00409 
00410     for (i = 1; i <= 2; i++) {
00411         snprintf(key,SZKEY,"CRPIX%d",i);
00412 
00413         /* First make sure the property exists. It damn well better exist! */
00414 
00415         if (cpl_propertylist_has(p,key) == 0) {
00416             cpl_msg_error(fctid,"Header is missing WCS key %s",key);
00417             return(VIR_FATAL);
00418         }
00419 
00420         /* Now find the type... */
00421 
00422         type = cpl_propertylist_get_type(p,key);
00423 
00424         /* Switch for the type. If it's neither float nor double, then 
00425            signal an error as this is clearly nonsense. */
00426 
00427         switch (type) {
00428         case CPL_TYPE_FLOAT:
00429             val = (double)cpl_propertylist_get_float(p,key);
00430             break;
00431         case CPL_TYPE_DOUBLE:
00432             val = cpl_propertylist_get_double(p,key);
00433             break;
00434         default:
00435             cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
00436                           key);
00437             return(VIR_FATAL);
00438         }
00439 
00440         /* Right, now do the actual work */
00441 
00442         val = (val - sh[i-1])/scalefac - 1.0;
00443 
00444         /* And update the property now */
00445 
00446         switch (type) {
00447         case CPL_TYPE_FLOAT:
00448             cpl_propertylist_update_float(p,key,(float)val);
00449             break;
00450         case CPL_TYPE_DOUBLE:
00451             cpl_propertylist_update_double(p,key,val);
00452             break;
00453         default:
00454             break;
00455         }
00456     }
00457     return(VIR_OK);
00458 }
00459 
00460 /*---------------------------------------------------------------------------*/
00482 /*---------------------------------------------------------------------------*/
00483 
00484 extern int vircam_rescalecd(cpl_propertylist *p, double scalefac) {
00485     int i,j;
00486     cpl_type type;
00487     char key[SZKEY];
00488     const char *fctid = "vircam_rescalecd";
00489     double val;
00490 
00491     /* Make sure that the scale factor isn't zero */
00492 
00493     if (scalefac == 0.0) {
00494         cpl_msg_error(fctid,"Scale factor is zero!");
00495         return(VIR_FATAL);
00496     }
00497 
00498     /* Loop through both axes. Shift and scale the values of cd */
00499 
00500     for (i = 1; i <= 2; i++) {
00501         for (j = 1; j <= 2; j++) {
00502             snprintf(key,SZKEY,"CD%d_%d",i,j);
00503 
00504             /* First make sure the property exists. It damn well better exist! */
00505 
00506             if (cpl_propertylist_has(p,key) == 0) {
00507                 cpl_msg_error(fctid,"Header is missing WCS key %s",key);
00508                 return(VIR_FATAL);
00509             }
00510 
00511             /* Now find the type... */
00512 
00513             type = cpl_propertylist_get_type(p,key);
00514 
00515             /* Switch for the type. If it's neither float nor double, then 
00516                signal an error as this is clearly nonsense. */
00517 
00518             switch (type) {
00519             case CPL_TYPE_FLOAT:
00520                 val = (double)cpl_propertylist_get_float(p,key);
00521                 break;
00522             case CPL_TYPE_DOUBLE:
00523                 val = cpl_propertylist_get_double(p,key);
00524                 break;
00525             default:
00526                 cpl_msg_error(fctid,"Header has WCS key %s as non-floating point!",
00527                               key);
00528                 return(VIR_FATAL);
00529             }
00530 
00531             /* Right, now do the actual work */
00532 
00533             val *= scalefac;
00534 
00535             /* And update the property now */
00536 
00537             switch (type) {
00538             case CPL_TYPE_FLOAT:
00539                 cpl_propertylist_update_float(p,key,(float)val);
00540                 break;
00541             case CPL_TYPE_DOUBLE:
00542                 cpl_propertylist_update_double(p,key,val);
00543                 break;
00544             default:
00545                 break;
00546             }
00547         }
00548     }
00549     return(VIR_OK);
00550 }
00551     
00552 /*---------------------------------------------------------------------------*/
00578 /*---------------------------------------------------------------------------*/
00579 
00580 extern int vircam_diffxywcs(cpl_wcs *wcs, cpl_wcs *wcsref, float *xoff,
00581                             float *yoff, int *status) {
00582     double xc,yc,ra,dec,xnew,ynew;
00583     const cpl_array *a;
00584     const int *dims;
00585     const char *fctid = "vircam_diffxywcs";
00586 
00587     /* Inherited status */
00588 
00589     *xoff = 0.0;
00590     *yoff = 0.0;
00591     if (*status != VIR_OK) 
00592         return(*status);
00593 
00594     /* Check for rubbish input */
00595 
00596     if (wcs == NULL || wcsref == NULL) {
00597         cpl_msg_error(fctid,"NULL wcs information");
00598         FATAL_ERROR
00599     }
00600 
00601     /* Work out the ra and dec of the central pixel in the reference image */
00602 
00603     a = cpl_wcs_get_image_dims(wcsref);
00604     dims = cpl_array_get_data_int_const(a);
00605     xc = 0.5*(double)dims[0];
00606     yc = 0.5*(double)dims[1];
00607     vircam_xytoradec(wcsref,xc,yc,&ra,&dec);
00608 
00609     /* Ok, calculate where in x,y space these equatorial coordinates fall on
00610        the programme image */
00611 
00612     vircam_radectoxy(wcs,ra,dec,&xnew,&ynew);
00613 
00614     /* Right, now return the offsets */
00615 
00616     *xoff = (float)(xc - xnew);
00617     *yoff = (float)(yc - ynew);
00618     GOOD_STATUS
00619 }
00620 
00621 /*---------------------------------------------------------------------------*/
00641 /*---------------------------------------------------------------------------*/
00642 
00643 extern int vircam_removewcs(cpl_propertylist *p, int *status) {
00644     int i;
00645     const char *fctid = "vircam_removewcs";
00646 
00647     /* Inherited status */
00648 
00649     if (*status != VIR_OK)
00650         return(*status);
00651     if (p == NULL) {
00652         cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
00653         FATAL_ERROR
00654     }
00655 
00656     /* Loop through all the template keywords and remove them */
00657 
00658     for (i = 0; i < NNOTABKEYS; i++) 
00659         cpl_propertylist_erase_regexp(p,notabkeys[i],0);
00660 
00661     GOOD_STATUS
00662 }
00663 
00664 /*---------------------------------------------------------------------------*/
00689 /*---------------------------------------------------------------------------*/
00690 
00691 extern int vircam_tabwcs(cpl_propertylist *p, int xcol, int ycol, 
00692                          int *status) {
00693     int i;
00694     char key[9],key2[9];
00695     const char *fctid="vircam_tabwcs";
00696 
00697     /* Inherited status */
00698 
00699     if (*status != VIR_OK)
00700         return(*status);
00701     if (p == NULL) {
00702         cpl_msg_error(fctid,"Propertylist passed is NULL\nProgramming error");
00703         FATAL_ERROR
00704     }
00705 
00706     /* If either of the columns are -1, then just get rid of the image WCS 
00707        and get out of here */
00708 
00709     if (xcol == -1 || ycol == -1) {
00710         vircam_removewcs(p,status);
00711         GOOD_STATUS
00712     }
00713 
00714     /* Go through the standard VIRCAM WCS header keywords one by one
00715        and translate them.  Start with CTYPE */
00716 
00717     (void)snprintf(key,8,"TCTYP%d",xcol);
00718     vircam_rename_property(p,"CTYPE1",key);
00719     (void)snprintf(key,8,"TCTYP%d",ycol);
00720     vircam_rename_property(p,"CTYPE2",key);
00721 
00722 
00723     /* Now CRVAL */
00724 
00725     (void)snprintf(key,8,"TCRVL%d",xcol);
00726     vircam_rename_property(p,"CRVAL1",key);
00727     (void)snprintf(key,8,"TCRVL%d",ycol);
00728     vircam_rename_property(p,"CRVAL2",key);
00729 
00730     /* Now CRPIX */
00731 
00732     (void)snprintf(key,8,"TCRPX%d",xcol);
00733     vircam_rename_property(p,"CRPIX1",key);
00734     (void)snprintf(key,8,"TCRPX%d",ycol);
00735     vircam_rename_property(p,"CRPIX2",key);
00736 
00737     /* Now PV matrix */
00738 
00739     for (i = 1; i <= 5; i++) {
00740         (void)snprintf(key2,8,"PV2_%d",i);
00741         (void)snprintf(key,8,"TV%d_%d",ycol,i);
00742         if (cpl_propertylist_has(p,key2))
00743             vircam_rename_property(p,key2,key);
00744     }
00745 
00746     /* Now the CD matrix */
00747 
00748     (void)snprintf(key,8,"TC%d_%d",xcol,xcol);
00749     vircam_rename_property(p,"CD1_1",key);
00750     (void)snprintf(key,8,"TC%d_%d",xcol,ycol);
00751     vircam_rename_property(p,"CD1_2",key);
00752     (void)snprintf(key,8,"TC%d_%d",ycol,xcol);
00753     vircam_rename_property(p,"CD2_1",key);
00754     (void)snprintf(key,8,"TC%d_%d",ycol,ycol);
00755     vircam_rename_property(p,"CD2_2",key);
00756 
00757     /* Now get out of here */
00758 
00759     GOOD_STATUS
00760     
00761 }
00762 
00763 
00766 /*
00767 
00768 $Log: vircam_wcsutils.c,v $
00769 Revision 1.32  2010/06/30 12:42:00  jim
00770 A few fixes to stop compiler compaints
00771 
00772 Revision 1.31  2009/02/20 11:35:43  jim
00773 Removed superfluous declarations
00774 
00775 Revision 1.30  2008/11/21 10:14:28  jim
00776 Fixed small bug in vircam_coverage which means it was missing out the last
00777 bit of the image
00778 
00779 Revision 1.29  2008/10/21 08:44:00  jim
00780 Fixed some declarations to make them constant
00781 
00782 Revision 1.28  2008/07/10 13:05:53  jim
00783 Modified to use v4.2 version of cpl_wcs
00784 
00785 Revision 1.27  2008/06/20 11:14:01  jim
00786 Fixed dodgy call to cpl_wcs_get_image_dims
00787 
00788 Revision 1.26  2008/05/06 08:40:10  jim
00789 Modified to use cpl_wcs interface
00790 
00791 Revision 1.25  2007/10/25 17:34:01  jim
00792 Modified to remove lint warnings
00793 
00794 Revision 1.24  2007/10/15 12:50:28  jim
00795 Modified for compatibility with cpl_4.0
00796 
00797 Revision 1.23  2007/05/14 15:25:28  jim
00798 Fixed formatting of wcs floating point parameters in vircam_wcsopen
00799 
00800 Revision 1.22  2007/05/03 11:15:33  jim
00801 Fixed little problem with table wcs
00802 
00803 Revision 1.21  2007/05/02 12:53:11  jim
00804 typo fixes in docs
00805 
00806 Revision 1.20  2007/05/02 09:16:12  jim
00807 Added vircam_tabwcs
00808 
00809 Revision 1.19  2007/03/01 12:42:42  jim
00810 Modified slightly after code checking
00811 
00812 Revision 1.18  2007/01/17 23:54:01  jim
00813 Plugged some memory leaks
00814 
00815 Revision 1.17  2007/01/08 19:12:49  jim
00816 Fixed stupid calloc
00817 
00818 Revision 1.16  2006/10/05 09:23:00  jim
00819 Small modifications to a couple of cpl calls to bring them into line with
00820 cpl v3.0
00821 
00822 Revision 1.15  2006/08/11 12:45:41  jim
00823 Modified to use wcslib
00824 
00825 Revision 1.14  2006/07/04 09:19:06  jim
00826 replaced all sprintf statements with snprintf
00827 
00828 Revision 1.13  2006/07/03 09:33:19  jim
00829 Fixed a few things to keep the compiler happy
00830 
00831 Revision 1.12  2006/06/14 14:13:58  jim
00832 fixed minor doc problem
00833 
00834 Revision 1.11  2006/06/13 14:09:54  jim
00835 Added vircam_removewcs
00836 
00837 Revision 1.10  2006/05/24 13:36:15  jim
00838 Added vircam_diffxywcs
00839 
00840 Revision 1.9  2006/04/20 11:30:29  jim
00841 Added naxis1 and naxis2 to the structure
00842 
00843 Revision 1.8  2006/03/22 13:58:32  jim
00844 Cosmetic fixes to keep lint happy
00845 
00846 Revision 1.7  2006/02/18 11:48:55  jim
00847 *** empty log message ***
00848 
00849 Revision 1.6  2006/01/23 10:30:50  jim
00850 Mainly documentation mods
00851 
00852 Revision 1.5  2005/12/14 22:17:33  jim
00853 Updated docs
00854 
00855 Revision 1.4  2005/11/29 11:37:38  jim
00856 fixed bug in error macro
00857 
00858 Revision 1.3  2005/11/25 15:33:22  jim
00859 Some code fixes to keep splint happy
00860 
00861 Revision 1.2  2005/11/03 13:28:51  jim
00862 All sorts of changes to tighten up error handling
00863 
00864 Revision 1.1.1.1  2005/08/05 08:29:09  jim
00865 Initial import
00866 
00867 
00868 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1