vircam_getstds.c

00001 /* $Id: vircam_getstds.c,v 1.25 2012/01/15 17:40:09 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: 2012/01/15 17:40:09 $
00024  * $Revision: 1.25 $
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 <sys/stat.h>
00035 #include <sys/types.h>
00036 #include <unistd.h>
00037 #include <string.h>
00038 #include <cpl.h>
00039 
00040 #include <math.h>
00041 
00042 #include "vircam_mods.h"
00043 #include "vircam_utils.h"
00044 #include "vircam_wcsutils.h"
00045 
00046 #define CACHEDIR ".catcache"
00047 #define CACHEIND ".catcache/index"
00048 #define SZBUF 1024
00049 
00050 static cpl_table *vircam_2mass_extract(char *path, float ramin, float ramax,
00051                                        float decmin, float decmax);
00052 static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im, 
00053                               float dec1_im, float dec2_im);
00054 static void addto_cache(cpl_table *stds, char *catname, float ramin, 
00055                         float ramax, float decmin, float decmax);
00056 
00059 /*---------------------------------------------------------------------------*/
00108 /*---------------------------------------------------------------------------*/
00109 
00110 extern int vircam_getstds(cpl_propertylist *plist, int cache, char *path,
00111                           char *catname, cpl_table **stds, int *status) {
00112     const char *fctid = "vircam_getstds";
00113     double xx1,xx2,yy1,yy2,r,d,xx,yy;
00114     float ramin,ramax,decmin,decmax,*ra,*dec,*x,*y;
00115     cpl_wcs *wcs;
00116     int n,i;
00117     cpl_propertylist *p;
00118 
00119     /* Inherited status */
00120 
00121     *stds = NULL;
00122     if (*status != VIR_OK)
00123         return(*status);
00124 
00125     /* Get the coverage of the input WCS */
00126 
00127     (void)vircam_coverage(plist,0,&xx1,&xx2,&yy1,&yy2,status);
00128     ramin = (float)xx1;
00129     ramax = (float)xx2;
00130     decmin = (float)yy1;
00131     decmax = (float)yy2;
00132 
00133     /* If using the cache, then check if for a previously used table */
00134 
00135     *stds = NULL;
00136     if (cache)
00137         *stds = check_cache(catname,ramin,ramax,decmin,decmax);
00138 
00139     /* If there was nothing in the cache (or you didn't use it) then search
00140        the standard 2mass catalogues */
00141 
00142     if (*stds == NULL) {        
00143 
00144         /* Read the standards from the catalogue */
00145 
00146         *stds = vircam_2mass_extract(path,ramin,ramax,decmin,decmax);
00147         if (*stds == NULL) {
00148             cpl_msg_error(fctid,"Unable to extract data in %s\n",path);
00149             FATAL_ERROR
00150         }
00151         
00152         /* Add this table to the cache if you want to */
00153 
00154         if (cache)
00155             addto_cache(*stds,catname,ramin,ramax,decmin,decmax);
00156     }
00157 
00158     /* If there are no rows in the table, this may be a cause for concern.
00159        So add the columns into the table and then set a warning return 
00160        status */
00161 
00162     n = (int)cpl_table_get_nrow(*stds);
00163     if (n == 0) {
00164         cpl_table_new_column(*stds,"xpredict",CPL_TYPE_FLOAT);
00165         cpl_table_new_column(*stds,"ypredict",CPL_TYPE_FLOAT);
00166         WARN_RETURN
00167     }
00168 
00169     /* Now fill the coordinates in */
00170 
00171     wcs = cpl_wcs_new_from_propertylist((const cpl_propertylist *)plist);
00172     ra = cpl_table_get_data_float(*stds,"RA");
00173     dec = cpl_table_get_data_float(*stds,"Dec");
00174     x = cpl_malloc(n*sizeof(*x));
00175     y = cpl_malloc(n*sizeof(*y));
00176     for (i = 0; i < n; i++) {
00177         r = (double)ra[i];
00178         d = (double)dec[i];
00179         vircam_radectoxy(wcs,r,d,&xx,&yy);
00180         x[i] = (float)xx;
00181         y[i] = (float)yy;
00182     }
00183     cpl_wcs_delete(wcs);
00184     
00185     /* Add the predicted x,y coordinates columns to the table */
00186 
00187     cpl_table_wrap_float(*stds,x,"xpredict");
00188     cpl_table_set_column_unit(*stds,"xpredict","pixels");
00189     cpl_table_wrap_float(*stds,y,"ypredict");
00190     cpl_table_set_column_unit(*stds,"ypredict","pixels");
00191 
00192     /* Finally sort this by ypredict */
00193 
00194     p = cpl_propertylist_new();
00195     cpl_propertylist_append_bool(p,"ypredict",0);
00196     cpl_table_sort(*stds,p);
00197     cpl_propertylist_delete(p);
00198 
00199     /* Get out of here */
00200 
00201     GOOD_STATUS
00202 }
00203 
00204 
00205 /*---------------------------------------------------------------------------*/
00233 /*---------------------------------------------------------------------------*/
00234 
00235 static cpl_table *vircam_2mass_extract(char *path, float ramin1, float ramax1, 
00236                                        float decmin, float decmax) {
00237     cpl_table *t,*s,*o;
00238     int i,nrows,start,finish,first_index,last_index,irow,init,j;
00239     int first_index_ra,last_index_ra,wrap,iwrap;
00240     float dectest,ratest,ramin,ramax;
00241     char fullname[SZBUF];
00242     cpl_array *a;
00243     char *deccol = "Dec";
00244     cpl_propertylist *p;
00245 
00246     /* Create an output table */
00247 
00248     o = cpl_table_new(0);
00249     init = 1;
00250 
00251     /* Create a cpl array */
00252 
00253     a = cpl_array_wrap_string(&deccol,1);
00254 
00255     /* Is there a wrap around problem? */
00256 
00257     wrap = (ramin1 < 0.0 && ramax1 > 0.0) ? 2 : 1;
00258 
00259     /* Loop for each query. If there is a wrap around problem then we need 2
00260        queries. If not, then we only need 1 */
00261 
00262     for (iwrap = 0; iwrap < wrap; iwrap++) {
00263         if (wrap == 2) {
00264             if (iwrap == 0) {
00265                 ramin = ramin1 + 360.0;
00266                 ramax = 360.0;
00267             } else {
00268                 ramin = 0.000001;
00269                 ramax = ramax1;
00270             }
00271         } else {
00272             ramin = ramin1;
00273             ramax = ramax1;
00274         }
00275 
00276         /* Find out where in the index to look */
00277 
00278         first_index_ra = (int)ramin;
00279         last_index_ra = min((int)ramax,359);
00280         
00281         /* Look at the min and max RA and decide which files need to be 
00282            opened. */
00283 
00284         for (i = first_index_ra; i <= last_index_ra; i++) {
00285 
00286             /* Ok, we've found one that needs opening. Read the file with 
00287                the relevant CPL call */
00288 
00289             (void)snprintf(fullname,SZBUF,"%s/npsc%03d.fits",path,i);
00290 
00291             /* Read the propertylist so that you know how many rows there
00292                are in the table */
00293 
00294             p = cpl_propertylist_load(fullname,1);
00295             if (p == NULL) {
00296                 freetable(o);
00297                 cpl_array_unwrap(a);
00298                 return(NULL);
00299             }
00300             nrows = cpl_propertylist_get_int(p,"NAXIS2");
00301             cpl_propertylist_delete(p);
00302 
00303             /* Load various rows until you find the Dec range that you 
00304                have specified. First the minimum Dec */
00305 
00306             start = 0;
00307             finish = nrows;
00308             first_index = nrows/2;
00309             while (finish - start >= 2) {
00310                 t = cpl_table_load_window(fullname,1,0,a,(cpl_size)first_index,
00311                                           1);
00312                 dectest = cpl_table_get_float(t,"Dec",0,NULL);
00313                 cpl_table_delete(t);
00314                 if (dectest < decmin) {
00315                     start = first_index;
00316                     first_index = (first_index + finish)/2;
00317                 } else {
00318                     finish = first_index;
00319                     first_index = (first_index + start)/2;
00320                 }
00321             }
00322 
00323             /* Load various rows until you find the Dec range that you 
00324                have specified. Now the maximum Dec */
00325 
00326             start = first_index;
00327             finish = nrows;
00328             last_index = start + (finish - start)/2;
00329             while (finish - start >= 2) {
00330                 t = cpl_table_load_window(fullname,1,0,a,(cpl_size)last_index,
00331                                           1);
00332                 dectest = cpl_table_get_float(t,"Dec",0,NULL);
00333                 cpl_table_delete(t);
00334                 if (dectest < decmax) {
00335                     start = last_index;
00336                     last_index = (last_index + finish)/2;
00337                 } else {
00338                     finish = last_index;
00339                     last_index = (last_index + start)/2;
00340                 }
00341             }    
00342             if (last_index < first_index)
00343                 last_index = first_index;
00344 
00345             /* Ok now now load all the rows in the relevant dec limits */
00346 
00347             nrows = last_index - first_index + 1;
00348             if ((t = cpl_table_load_window(fullname,1,0,NULL,
00349                                            (cpl_size)first_index,
00350                                            (cpl_size)nrows)) == NULL) {
00351                 freetable(o);
00352                 cpl_array_unwrap(a);
00353                 return(NULL);
00354             }
00355             cpl_table_unselect_all(t);
00356 
00357             /* Right, we now know what range of rows to search. Go through 
00358                these and pick the ones that are in the correct range of RA.
00359                If a row qualifies, then 'select' it. */
00360 
00361             for (j = 0; j < nrows; j++) {
00362                 ratest = cpl_table_get_float(t,"RA",(cpl_size)j,NULL);
00363                 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00364                     cpl_table_delete(t);
00365                     cpl_array_unwrap(a);
00366                     freetable(o);
00367                     return(NULL);
00368                 }
00369                 if (ratest >= ramin && ratest <= ramax)
00370                     cpl_table_select_row(t,(cpl_size)j);
00371             }
00372 
00373             /* Extract the rows that have been selected now and append them
00374                onto the output table */
00375 
00376             s = cpl_table_extract_selected(t);
00377             if (init == 1) {
00378                 cpl_table_copy_structure(o,t);
00379                 init = 0;
00380             }
00381             irow = (int)cpl_table_get_nrow(o) + 1;
00382             cpl_table_insert(o,s,(cpl_size)irow);
00383 
00384             /* Tidy up */
00385 
00386             cpl_table_delete(t);
00387             cpl_table_delete(s);
00388         }
00389     }
00390 
00391     /* Ok, now just return the table and get out of here */
00392 
00393     cpl_array_unwrap(a);
00394     return(o);
00395 }
00396         
00397 /*---------------------------------------------------------------------------*/
00425 /*---------------------------------------------------------------------------*/
00426 
00427 static cpl_table *check_cache(char *catname, float ra1_im, float ra2_im, 
00428                               float dec1_im, float dec2_im) {
00429     int wrap1,wrap2;
00430     FILE *fd;
00431     char fname[BUFSIZ],catname2[SZBUF],cat_cache[SZBUF];
00432     float best,ra1_cat,ra2_cat,dec1_cat,dec2_cat,d1,d2,fra,fdec,ftot;
00433     cpl_table *out_cat;
00434 
00435     /* Open the index file.  NB the path and file name are hardcoded */
00436 
00437     fd = fopen(CACHEIND,"r");
00438     if (fd == NULL)
00439         return(NULL);
00440 
00441     /* Check to see if there is wrap around in the coordinates */
00442 
00443     wrap1 = (ra1_im < 0.0 ? 1 : 0);
00444 
00445     /* Now see if you have any matching entries */
00446 
00447     best = 0.0;
00448     while (fscanf(fd,"%s %s %g %g %g %g",fname,catname2,&ra1_cat,&ra2_cat,
00449                   &dec1_cat,&dec2_cat) != EOF) {
00450         wrap2 = (ra1_cat < 0.0 ? 1 : 0);
00451         if (wrap1 != wrap2)
00452             continue;
00453         if (strcmp(catname,catname2))
00454             continue;
00455         
00456         /* Check to see if there is at least some overlap */
00457 
00458         if (!(((ra1_im >= ra1_cat && ra1_im <= ra2_cat) ||
00459              (ra2_im >= ra1_cat && ra2_im <= ra2_cat)) &&
00460             ((dec1_im >= dec1_cat && dec1_im <= dec2_cat) ||
00461              (dec2_im >= dec1_cat && dec2_im <= dec2_cat))))
00462             continue;
00463 
00464         /* Work out exactly how much there is in each coordinate */
00465 
00466         d1 = max(0.0,ra1_cat-ra1_im);
00467         d2 = max(0.0,ra2_im-ra2_cat);
00468         fra = 1.0 - (d1 + d2)/(ra2_im - ra1_im);
00469         d1 = max(0.0,dec1_cat-dec1_im);
00470         d2 = max(0.0,dec2_im-dec2_cat);
00471         fdec = 1.0 - (d1 + d2)/(dec2_im - dec1_im);
00472         ftot = fra*fdec;
00473 
00474         /* Keep track of which is the best one */
00475 
00476         if (ftot > best) {
00477             snprintf(cat_cache,SZBUF,"%s/%s",CACHEDIR,fname);
00478             best = ftot;
00479         }
00480     }
00481     fclose(fd);
00482 
00483     /* Return a bad status if there isn't sufficient overlap */
00484 
00485     if (best < 0.9)
00486         return(NULL);
00487 
00488     /* If there is enough overlap, then try and read the FITS table. If it
00489        reads successfully, then return the table pointer */
00490 
00491     out_cat = cpl_table_load(cat_cache,1,0);
00492     return(out_cat);
00493 }
00494     
00495 /*---------------------------------------------------------------------------*/
00521 /*---------------------------------------------------------------------------*/
00522 
00523 static void addto_cache(cpl_table *stds, char *catname, float ramin, 
00524                         float ramax, float decmin, float decmax) {
00525     FILE *fd;
00526     char newname[SZBUF];
00527     int i;
00528 
00529     /* Check to see if the cache directory exists.  If it doesn't, then create
00530        it. */
00531 
00532     if (access(CACHEDIR,0) != 0)
00533         mkdir(CACHEDIR,0755);
00534 
00535     /* Open the index file with 'append' access */
00536 
00537     fd = fopen(CACHEIND,"a");
00538 
00539     /* Check the files in the directory to get a number that isn't already
00540        being used */
00541 
00542     i = 0;
00543     while (i >= 0) {
00544         i++;
00545         snprintf(newname,SZBUF,"%s/cch_%08d",CACHEDIR,i);
00546         if (access(newname,F_OK) != 0) 
00547             break;
00548     }
00549 
00550     /* Now write the current entry and make a copy of the file into the 
00551        directory */
00552 
00553     snprintf(newname,SZBUF,"%s/cch_%08d",CACHEDIR,i);
00554     cpl_table_save(stds,NULL,NULL,newname,CPL_IO_DEFAULT);
00555     snprintf(newname,SZBUF,"cch_%08d",i);
00556     if (cpl_error_get_code() == CPL_ERROR_NONE)
00557         fprintf(fd, "%s %s %g %g %g %g\n",newname,catname,ramin-0.0005,
00558                 ramax+0.0005,decmin-0.0005,decmax+0.0005);
00559     fclose(fd);
00560 }
00561 
00565 /* 
00566 
00567 $Log: vircam_getstds.c,v $
00568 Revision 1.25  2012/01/15 17:40:09  jim
00569 Minor modifications to take into accout the changes in cpl API for v6
00570 
00571 Revision 1.24  2012/01/04 08:57:09  jim
00572 Renamed cache directories
00573 
00574 Revision 1.23  2010/07/13 11:16:50  jim
00575 A few changes to deal with compiler whinges
00576 
00577 Revision 1.22  2010/06/03 12:15:31  jim
00578 A few mods to get rid of compiler warnings
00579 
00580 Revision 1.21  2008/05/06 08:40:10  jim
00581 Modified to use cpl_wcs interface
00582 
00583 Revision 1.20  2007/10/25 17:34:00  jim
00584 Modified to remove lint warnings
00585 
00586 Revision 1.19  2007/10/19 09:25:09  jim
00587 Fixed problems with missing includes
00588 
00589 Revision 1.18  2007/10/19 06:55:06  jim
00590 Modifications made to use new method for directing the recipes to the
00591 standard catalogues using the sof
00592 
00593 Revision 1.17  2007/10/15 12:50:53  jim
00594 Modified to read new version of 2mass catalogue files
00595 
00596 Revision 1.16  2007/03/29 12:19:39  jim
00597 Little changes to improve documentation
00598 
00599 Revision 1.15  2007/03/01 12:42:41  jim
00600 Modified slightly after code checking
00601 
00602 Revision 1.14  2007/02/25 06:34:20  jim
00603 Plugged memory leak
00604 
00605 Revision 1.13  2007/01/17 23:54:00  jim
00606 Plugged some memory leaks
00607 
00608 Revision 1.12  2006/12/18 17:14:17  jim
00609 Another tidy of some error messages
00610 
00611 Revision 1.11  2006/12/18 16:41:47  jim
00612 Added bit to check for the existence of the index file rather than asking cpl
00613 to do that check with loading the table
00614 
00615 Revision 1.10  2006/12/18 12:51:20  jim
00616 Tightened up some of the error reporting
00617 
00618 Revision 1.9  2006/12/15 12:03:27  jim
00619 Fixed bug in 2mass_extract where index was offset by -1
00620 
00621 Revision 1.8  2006/11/27 12:07:22  jim
00622 Argument list now contains catname. Modified caching routines to take this
00623 into account.
00624 
00625 Revision 1.7  2006/08/11 12:45:41  jim
00626 Modified to use wcslib
00627 
00628 Revision 1.6  2006/07/04 09:19:05  jim
00629 replaced all sprintf statements with snprintf
00630 
00631 Revision 1.5  2006/06/08 14:50:09  jim
00632 Initialised output table to NULL and fixed a problem in check_cache that
00633 resets the cpl error code
00634 
00635 Revision 1.4  2006/03/23 21:18:47  jim
00636 Minor changes mainly to comment headers
00637 
00638 Revision 1.3  2006/03/22 13:58:31  jim
00639 Cosmetic fixes to keep lint happy
00640 
00641 Revision 1.2  2006/01/23 16:05:33  jim
00642 tidied up error handling
00643 
00644 Revision 1.1  2006/01/23 10:31:56  jim
00645 New file
00646 
00647 
00648 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1