vircam_match.c

00001 /* $Id: vircam_match.c,v 1.13 2007/10/19 09:25:10 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: 2007/10/19 09:25:10 $
00024  * $Revision: 1.13 $
00025  * $Name:  $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <math.h>
00035 
00036 #include <cpl.h>
00037 #include <string.h>
00038 
00039 #include "vircam_mods.h"
00040 #include "vircam_stats.h"
00041 #include "vircam_utils.h"
00042 
00043 #define NX 2048
00044 #define NY 2048
00045 #define NGRIDMAX 31
00046 
00047 static cpl_table *vircam_mkmstd_table(cpl_table *objtab, cpl_table *stdstab);
00048 
00051 /*---------------------------------------------------------------------------*/
00099 /*---------------------------------------------------------------------------*/
00100 
00101 extern int vircam_matchxy(cpl_table *progtab, cpl_table *template, float srad,
00102                           float *xoffset, float *yoffset, int *nm, 
00103                           int *status) {
00104     cpl_propertylist *p;
00105     float *xprog,*yprog,*xtemp,*ytemp,aveden,errlim,xoffbest,yoffbest,xoff;
00106     float yoff,x,y,*xoffs,*yoffs;
00107     const char *fctid = "vircam_matchxy";
00108     int nprog,ntemp,ngrid,ngrid2,ibest,ig,jg,nmatch,k,jm;
00109 
00110     /* Inherited status */
00111 
00112     *xoffset = 0.0;
00113     *yoffset = 0.0;
00114     *nm = 0;
00115     if (*status != VIR_OK)
00116         return(*status);
00117 
00118     /* Check the size of each of the tables */
00119 
00120     nprog = cpl_table_get_nrow(progtab);
00121     ntemp = cpl_table_get_nrow(template);
00122     if (nprog == 0) {
00123         cpl_msg_warning(fctid,"Program table has no rows");
00124         WARN_RETURN
00125     } else if (ntemp == 0) {
00126         cpl_msg_warning(fctid,"Template table has no rows");
00127         WARN_RETURN
00128     }
00129 
00130     /* First, sort the two tables by the Y coordinate */
00131 
00132     p = cpl_propertylist_new();
00133     cpl_propertylist_append_bool(p,"Y_coordinate",0);
00134     if (cpl_table_sort(progtab,p) != CPL_ERROR_NONE) {
00135         cpl_propertylist_delete(p);
00136         FATAL_ERROR
00137     }
00138     if (cpl_table_sort(template,p) != CPL_ERROR_NONE) {
00139         cpl_propertylist_delete(p);
00140         FATAL_ERROR
00141     }
00142     cpl_propertylist_delete(p);
00143 
00144     /* Get the x,y coordinates for each table */
00145 
00146     xprog = cpl_table_get_data_float(progtab,"X_coordinate");
00147     yprog = cpl_table_get_data_float(progtab,"Y_coordinate");
00148     xtemp = cpl_table_get_data_float(template,"X_coordinate");
00149     ytemp = cpl_table_get_data_float(template,"Y_coordinate");
00150     if (xprog == NULL || yprog == NULL || xtemp == NULL || ytemp == NULL)
00151         FATAL_ERROR
00152 
00153     /* Calculate the error limit and the number of grid points */
00154 
00155     aveden = (float)ntemp/(float)(NX*NY);
00156     errlim = 1.0/sqrt(4.0*M_PI*aveden);
00157     errlim = min(errlim,5.0);
00158     ngrid = (int)(srad/errlim);
00159     ngrid = (ngrid/2)*2 + 1;
00160     ngrid = max(5,min(NGRIDMAX,ngrid));
00161     ngrid2 = ngrid/2 + 1;
00162 
00163     /* Now search for the best solution */
00164 
00165     ibest = 0;
00166     xoffbest = 0.0;
00167     yoffbest = 0.0;
00168     for (ig = -ngrid2; ig <= ngrid2; ig++) {
00169         xoff = (float)ig*errlim*M_SQRT2;
00170         for (jg = -ngrid2; jg <= ngrid2; jg++) {
00171             yoff = (float)jg*errlim*M_SQRT2;
00172             nmatch = 0;
00173             for (k = 0; k < nprog; k++) {
00174                 x = xprog[k] + xoff;
00175                 y = yprog[k] + yoff;
00176                 if (vircam_fndmatch(x,y,xtemp,ytemp,ntemp,errlim) > -1) 
00177                     nmatch++;
00178             }
00179             if (nmatch > ibest) {
00180                 ibest = nmatch;
00181                 xoffbest = xoff;
00182                 yoffbest = yoff;
00183             }
00184         }
00185     }
00186 
00187     /* Now allocate some workspace so that you can calculate a good median
00188        coordinate difference */
00189 
00190     xoffs = cpl_malloc(nprog*sizeof(*xoffs));
00191     yoffs = cpl_malloc(nprog*sizeof(*yoffs));
00192 
00193     /* Now get the coordinate differences and find the medians */
00194 
00195     nmatch = 0;
00196     for (k = 0; k < nprog; k++) {
00197         x = xprog[k] + xoffbest;
00198         y = yprog[k] + yoffbest;
00199         jm = vircam_fndmatch(x,y,xtemp,ytemp,ntemp,errlim);
00200         if (jm > -1) {
00201             xoffs[nmatch] = xtemp[jm] - xprog[k];
00202             yoffs[nmatch] = ytemp[jm] - yprog[k];
00203             nmatch++;
00204         }
00205     }
00206     if (nmatch > 0) {
00207         *xoffset = vircam_med(xoffs,NULL,nmatch);
00208         *yoffset = vircam_med(yoffs,NULL,nmatch);
00209     } else {
00210         *xoffset = 0.0;
00211         *yoffset = 0.0;
00212     }
00213     *nm = nmatch;
00214 
00215     /* Tidy and exit */
00216 
00217     freespace(xoffs);
00218     freespace(yoffs);
00219     GOOD_STATUS
00220 }
00221 
00222 /*---------------------------------------------------------------------------*/
00267 /*---------------------------------------------------------------------------*/
00268 
00269 extern int vircam_matchstds(cpl_table *objtab, cpl_table *stdstab, float srad,
00270                             cpl_table **outtab, int *status) {
00271     const char *fctid = "vircam_matchstds";
00272     char *colname;
00273     int nobj,nstd,ngrid,ngrid2,ibest,ig,jg,nmatch,k,*matches,jm,l,dont,null;
00274     float *xstd,*ystd,*xobj,*yobj,aveden,errlim,xoffbest,yoffbest,*xoffs;
00275     float *yoffs,x,y,x2,y2,r2,x1,y1,r1,xoffmed,sigx,yoffmed,sigy,xoff,yoff;
00276     cpl_propertylist *p;
00277     cpl_table *mstds;
00278 
00279     /* Inherited status */
00280 
00281     *outtab = NULL;
00282     if (*status != VIR_OK)
00283         return(*status);
00284 
00285     /* Check the size of each of the tables */
00286 
00287     nobj = cpl_table_get_nrow(objtab);
00288     nstd = cpl_table_get_nrow(stdstab);
00289     if (nobj == 0) {
00290         cpl_msg_warning(fctid,"Object table has no rows");
00291         mstds = vircam_mkmstd_table(objtab,stdstab);
00292         *outtab = cpl_table_extract_selected(mstds);
00293         cpl_table_delete(mstds);
00294         WARN_RETURN
00295     } else if (nstd == 0) {
00296         cpl_msg_warning(fctid,"Standards RA/DEC table has no rows");
00297         mstds = vircam_mkmstd_table(objtab,stdstab);
00298         *outtab = cpl_table_extract_selected(mstds);
00299         cpl_table_delete(mstds);
00300         WARN_RETURN
00301     }
00302 
00303     /* First, sort the two tables by the Y coordinate */
00304 
00305     p = cpl_propertylist_new();
00306     cpl_propertylist_append_bool(p,"Y_coordinate",0);
00307     if (cpl_table_sort(objtab,p) != CPL_ERROR_NONE) {
00308         cpl_propertylist_delete(p);
00309         FATAL_ERROR
00310     }
00311     cpl_propertylist_erase(p,"Y_coordinate");
00312     cpl_propertylist_append_bool(p,"ypredict",0);
00313     if (cpl_table_sort(stdstab,p) != CPL_ERROR_NONE) {
00314         cpl_propertylist_delete(p);
00315         FATAL_ERROR
00316     }
00317     cpl_propertylist_delete(p);
00318 
00319     /* Get the x,y coordinates for each table */
00320 
00321     xobj = cpl_table_get_data_float(objtab,"X_coordinate");
00322     yobj = cpl_table_get_data_float(objtab,"Y_coordinate");
00323     xstd = cpl_table_get_data_float(stdstab,"xpredict");
00324     ystd = cpl_table_get_data_float(stdstab,"ypredict");
00325     if (xstd == NULL || ystd == NULL || xobj == NULL || yobj == NULL)
00326         FATAL_ERROR
00327 
00328     /* Calculate the error limit and the number of grid points */
00329 
00330     aveden = (float)nstd/(float)(NX*NY);
00331     errlim = 1.0/sqrt(4.0*M_PI*aveden);
00332     errlim = min(errlim,5.0);
00333     ngrid = (int)(srad/errlim);
00334     ngrid = (ngrid/2)*2 + 1;
00335     ngrid = max(5,min(NGRIDMAX,ngrid));
00336     ngrid2 = ngrid/2 + 1;
00337 
00338     /* Now search for the best solution */
00339 
00340     ibest = 0;
00341     xoffbest = 0.0;
00342     yoffbest = 0.0;
00343     for (ig = -ngrid2; ig <= ngrid2; ig++) {
00344         xoff = (float)ig*errlim*M_SQRT2;
00345         for (jg = -ngrid2; jg <= ngrid2; jg++) {
00346             yoff = (float)jg*errlim*M_SQRT2;
00347             nmatch = 0;
00348             for (k = 0; k < nobj; k++) {
00349                 x = xobj[k] + xoff;
00350                 y = yobj[k] + yoff;
00351                 if (vircam_fndmatch(x,y,xstd,ystd,nstd,errlim) > -1) 
00352                     nmatch++;
00353             }
00354             if (nmatch > ibest) {
00355                 ibest = nmatch;
00356                 xoffbest = xoff;
00357                 yoffbest = yoff;
00358             }
00359         }
00360     }
00361 
00362     /* Now allocate some workspace so that you can calculate a good median
00363        coordinate difference */
00364 
00365     xoffs = cpl_malloc(nstd*sizeof(*xoffs));
00366     yoffs = cpl_malloc(nstd*sizeof(*yoffs));
00367     matches = cpl_malloc(nstd*sizeof(*matches));
00368     for (k = 0; k < nstd; k++)
00369         matches[k] = -1;
00370 
00371     /* Now get the best matches */
00372 
00373     nmatch = 0;
00374     for (k = 0; k < nstd; k++) {
00375         x = xstd[k] - xoffbest;
00376         y = ystd[k] - yoffbest;
00377         jm = vircam_fndmatch(x,y,xobj,yobj,nobj,errlim);
00378         if (jm > -1) {
00379             dont = 0;
00380             x2 = xobj[jm] - x;
00381             y2 = yobj[jm] - y;
00382             r2 = sqrt(x2*x2 + y2*y2);
00383             for (l = 0; l < nstd; l++) {
00384                 if (matches[l] == jm) {
00385                     x1 = xobj[jm] - (xstd[l] - xoffbest);
00386                     y1 = yobj[jm] - (ystd[l] - yoffbest);
00387                     r1 = sqrt(x1*x1 + y1*y1);
00388                     if (r2 < r1) 
00389                         matches[l] = -1;
00390                     else
00391                         dont = 1;
00392                     break;
00393                 }
00394             }
00395             if (dont == 0)
00396                 matches[k] = jm;
00397         }
00398     }
00399 
00400     /* Now get the coordinate difference for the best matches */
00401 
00402     for (k = 0; k < nstd; k++) {
00403         jm = matches[k];
00404         if (jm != -1) {
00405             xoffs[nmatch] = xobj[jm] - xstd[k];
00406             yoffs[nmatch] = yobj[jm] - ystd[k];
00407             nmatch++;
00408         }
00409     }
00410     if (nmatch == 0) {
00411         xoffmed = 0.0;
00412         sigx = 1.0;
00413         yoffmed = 0.0;
00414         sigy = 1.0;
00415     } else {
00416         vircam_medmad(xoffs,NULL,nmatch,&xoffmed,&sigx);
00417         sigx *= 1.48;
00418         vircam_medmad(yoffs,NULL,nmatch,&yoffmed,&sigy);
00419         sigy *= 1.48;
00420     }
00421 
00422     /* Now go through one final time with a reduced error box and get
00423        the final matches */
00424 
00425     errlim = 3.0*max(sigx,sigy);
00426     for (k = 0; k < nstd; k++)
00427         matches[k] = -1;
00428     for (k = 0; k < nstd; k++) {
00429         x = xstd[k] + xoffmed;
00430         y = ystd[k] + yoffmed;
00431         jm = vircam_fndmatch(x,y,xobj,yobj,nobj,errlim);
00432         if (jm > -1) {
00433             dont = 0;
00434             x2 = xobj[jm] - x;
00435             y2 = yobj[jm] - y;
00436             r2 = sqrt(x2*x2 + y2*y2);
00437             for (l = 0; l < nstd; l++) {
00438                 if (matches[l] == jm) {
00439                     x1 = xobj[jm] - (xstd[l] + xoffmed);
00440                     y1 = yobj[jm] - (ystd[l] + yoffmed);
00441                     r1 = sqrt(x1*x1 + y1*y1);
00442                     if (r2 < r1) 
00443                         matches[l] = -1;
00444                     else
00445                         dont = 1;
00446 /*                  break; */
00447                 }
00448             }
00449             if (dont == 0)
00450                 matches[k] = jm;
00451         }
00452     }
00453     jm = matches[1];
00454 
00455     /* Make a copy of the standards table and add all the columns from the
00456        object catalogue to it. Ingore the RA and DEC columns in the catalogue
00457        as the standards table will already have these.*/
00458 
00459     mstds = cpl_table_duplicate(stdstab);
00460     colname = (char *)cpl_table_get_column_name(objtab);
00461     while (colname != NULL) {
00462         if (strcmp(colname,"RA") && strcmp(colname,"DEC"))
00463             cpl_table_new_column(mstds,colname,
00464                                  cpl_table_get_column_type(objtab,colname));
00465         colname = (char *)cpl_table_get_column_name(NULL);
00466     }
00467     cpl_table_unselect_all(mstds);
00468 
00469     /* Now go through and find the matches */
00470 
00471     for (k = 0; k < nstd; k++) {
00472         jm = matches[k];
00473         if (jm != -1) {
00474             colname = (char *)cpl_table_get_column_name(objtab);
00475             while (colname != NULL) {
00476                 if (!strcmp(colname,"RA") || !strcmp(colname,"DEC")) {
00477                     colname = (char *)cpl_table_get_column_name(NULL);
00478                     continue;
00479                 }
00480                 null = 0;
00481                 switch (cpl_table_get_column_type(objtab,colname)) {
00482                 case CPL_TYPE_INT:
00483                     cpl_table_set_int(mstds,colname,k,
00484                                       cpl_table_get_int(objtab,colname,jm,
00485                                                         &null));
00486                     break;
00487                 case CPL_TYPE_FLOAT:
00488                     cpl_table_set_float(mstds,colname,k,
00489                                         cpl_table_get_float(objtab,colname,jm,
00490                                                             &null));
00491                     break;
00492                 case CPL_TYPE_DOUBLE:
00493                     cpl_table_set_double(mstds,colname,k,
00494                                          cpl_table_get_double(objtab,colname,
00495                                                               jm,&null));
00496                     break;
00497                 default:
00498                     cpl_table_set_float(mstds,colname,k,
00499                                         cpl_table_get_float(objtab,colname,jm,
00500                                                             &null));
00501                     break;
00502                 }
00503                 colname = (char *)cpl_table_get_column_name(NULL);
00504             }
00505             cpl_table_select_row(mstds,k);
00506         }
00507     }
00508 
00509     /* Now extract the selected rows into the output table */
00510 
00511     *outtab = cpl_table_extract_selected(mstds);
00512     cpl_table_delete(mstds);
00513 
00514     /* Tidy up */
00515 
00516     freespace(matches);
00517     freespace(xoffs);
00518     freespace(yoffs);
00519     GOOD_STATUS
00520 }
00521 
00522 /*---------------------------------------------------------------------------*/
00542 /*---------------------------------------------------------------------------*/
00543     
00544 static cpl_table *vircam_mkmstd_table(cpl_table *objtab, cpl_table *stdstab) {
00545     cpl_table *mstds;
00546     char *colname;
00547 
00548     /* Copy the input standards table */
00549 
00550     mstds = cpl_table_duplicate(stdstab);
00551 
00552     /* Loop throught the object table columns and copy all of them over, 
00553        except for the RA and DEC tables */
00554 
00555     colname = (char *)cpl_table_get_column_name(objtab);
00556     while (colname != NULL) {
00557         if (strcmp(colname,"RA") && strcmp(colname,"DEC"))
00558             cpl_table_new_column(mstds,colname,
00559                                  cpl_table_get_column_type(objtab,colname));
00560         colname = (char *)cpl_table_get_column_name(NULL);
00561     }
00562     cpl_table_unselect_all(mstds);
00563 
00564     /* Get out of here */
00565 
00566     return(mstds);
00567 }
00568         
00572 /*
00573 
00574 $Log: vircam_match.c,v $
00575 Revision 1.13  2007/10/19 09:25:10  jim
00576 Fixed problems with missing includes
00577 
00578 Revision 1.12  2007/04/23 13:02:02  jim
00579 Added static routine to make the matched standards table
00580 
00581 Revision 1.11  2007/03/29 12:19:39  jim
00582 Little changes to improve documentation
00583 
00584 Revision 1.10  2007/03/01 12:42:42  jim
00585 Modified slightly after code checking
00586 
00587 Revision 1.9  2007/02/25 06:34:20  jim
00588 Plugged memory leak
00589 
00590 Revision 1.8  2006/07/03 09:33:18  jim
00591 Fixed a few things to keep the compiler happy
00592 
00593 Revision 1.7  2006/05/26 15:04:07  jim
00594 Fixed sign error
00595 
00596 Revision 1.6  2006/05/18 12:33:38  jim
00597 Fixed bugs in the definition of the matched standard catalogue
00598 
00599 Revision 1.5  2006/05/17 12:06:56  jim
00600 Modified to take new definition of matched standards catalogue into account
00601 
00602 Revision 1.4  2006/03/23 21:18:51  jim
00603 Minor changes mainly to comment headers
00604 
00605 Revision 1.3  2006/03/22 13:58:32  jim
00606 Cosmetic fixes to keep lint happy
00607 
00608 Revision 1.2  2006/02/22 14:10:21  jim
00609 Fixed omission in docs
00610 
00611 Revision 1.1  2006/02/18 11:52:34  jim
00612 new file
00613 
00614 
00615 */

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