HAWKI Pipeline Reference Manual 1.8.12
hawki_step_photom_2mass.c
00001 /* $Id: hawki_step_photom_2mass.c,v 1.18 2013/01/14 15:58:23 cgarcia Exp $
00002  *
00003  * This file is part of the HAWKI Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
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: cgarcia $
00023  * $Date: 2013/01/14 15:58:23 $
00024  * $Revision: 1.18 $
00025  * $Name: hawki-1_8_12 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <cpl.h>
00038 #include <string.h>
00039 
00040 #include "irplib_utils.h"
00041 
00042 #include "hawki_alloc.h"
00043 #include "hawki_utils.h"
00044 #include "hawki_load.h"
00045 #include "hawki_save.h"
00046 #include "hawki_pfits.h"
00047 #include "hawki_dfs.h"
00048 #include "irplib_cat.h"
00049 #include "irplib_stdstar.h"
00050 
00051 /*-----------------------------------------------------------------------------
00052                             Functions prototypes
00053  -----------------------------------------------------------------------------*/
00054 
00055 #ifdef __cplusplus
00056 extern "C"
00057 #endif
00058 int cpl_plugin_get_info(cpl_pluginlist * list);
00059 
00060 static int hawki_step_photom_2mass_create(cpl_plugin *) ;
00061 static int hawki_step_photom_2mass_exec(cpl_plugin *) ;
00062 static int hawki_step_photom_2mass_destroy(cpl_plugin *) ;
00063 static int hawki_step_photom_2mass(cpl_parameterlist   *   parlist,
00064                                    cpl_frameset        *   frameset);
00065 
00066 
00067 cpl_table ** hawki_step_photom_2mass_get_zpoints
00068 (cpl_frameset *     cat_2mass,
00069  cpl_frameset *     obj_param,
00070  cpl_frameset *     obj_ima);
00071 
00072 static cpl_table * hawki_step_photom_2mass_retrieve_stars
00073 (cpl_frameset *     cat_2mass,
00074  cpl_propertylist * wcs_keywords);
00075 
00076 static cpl_array *  hawki_step_photom_2mass_ppm
00077 (cpl_table *  stars_2mass,
00078  cpl_table *  obj_det);
00079 
00080 static cpl_table * hawki_step_photom_2mass_fill_zpoint_table
00081 (cpl_table *        stars_2mass,
00082  cpl_table *        obj_det_param,
00083  cpl_array *        matches,
00084  cpl_propertylist * plist,
00085  int                idet);
00086 
00087 static cpl_propertylist ** hawki_step_photom_2mass_qc
00088 (cpl_table ** zpoint_table);
00089 
00090 static int hawki_step_photom_2mass_save
00091 (cpl_table **              zpoints,
00092  cpl_parameterlist *       parlist,
00093  cpl_propertylist **       qclists,
00094  cpl_frameset *            set);
00095 
00096 /*-----------------------------------------------------------------------------
00097                             Static variables
00098  -----------------------------------------------------------------------------*/
00099 
00100 static char hawki_step_photom_2mass_description[] = 
00101 "hawki_step_photom_2mass -- HAWK-I photometric autocalibration using 2MASS.\n"
00102 "The input files must be tagged:\n"
00103 "obj_param.fits "HAWKI_CALPRO_OBJ_PARAM"\n"
00104 "image.fits "HAWKI_CALPRO_COMBINED"\n"
00105 "2mass_master_index.fits "HAWKI_UTIL_CAT_2MASS"\n"
00106 "The recipe creates as an output:\n"
00107 "hawki_cal_photom_2mass.fits ("HAWKI_CALPRO_ZPOINT_TAB"): \n"
00108 "The recipe does the following steps:\n"
00109 "-Search the 2MASS catalogue for stars in the FOV\n"
00110 "-Matches the input detected object catalogue and the 2MASS stars\n"
00111 "-Computes photometric characteristics for each matched star\n"
00112 "Return code:\n"
00113 "esorex exits with an error code of 0 if the recipe completes successfully\n"
00114 "or 1 otherwise";
00115 
00116 /*-----------------------------------------------------------------------------
00117                                 Functions code
00118  -----------------------------------------------------------------------------*/
00119 
00120 /*----------------------------------------------------------------------------*/
00128 /*----------------------------------------------------------------------------*/
00129 int cpl_plugin_get_info(cpl_pluginlist * list)
00130 {
00131     cpl_recipe *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
00132     cpl_plugin *   plugin = &recipe->interface ;
00133 
00134     cpl_plugin_init(plugin,
00135                     CPL_PLUGIN_API,
00136                     HAWKI_BINARY_VERSION,
00137                     CPL_PLUGIN_TYPE_RECIPE,
00138                     "hawki_step_photom_2mass",
00139                     "2MASS photometric calibration",
00140                     hawki_step_photom_2mass_description,
00141                     "Cesar Enrique Garcia Dabo",
00142                     PACKAGE_BUGREPORT,  
00143                     hawki_get_license(),
00144                     hawki_step_photom_2mass_create,
00145                     hawki_step_photom_2mass_exec,
00146                     hawki_step_photom_2mass_destroy);
00147 
00148     cpl_pluginlist_append(list, plugin) ;
00149     
00150     return 0;
00151 }
00152 
00153 /*----------------------------------------------------------------------------*/
00162 /*----------------------------------------------------------------------------*/
00163 static int hawki_step_photom_2mass_create(cpl_plugin * plugin)
00164 {
00165     cpl_recipe *   recipe ;
00166 
00167     /* Get the recipe out of the plugin */
00168     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00169         recipe = (cpl_recipe *)plugin ;
00170     else return -1 ;
00171 
00172     /* Create the parameters list in the cpl_recipe object */
00173     recipe->parameters = cpl_parameterlist_new() ;
00174     if (recipe->parameters == NULL)
00175         return 1;
00176 
00177     /* Return */
00178     return 0;
00179 }
00180 
00181 /*----------------------------------------------------------------------------*/
00187 /*----------------------------------------------------------------------------*/
00188 static int hawki_step_photom_2mass_exec(cpl_plugin * plugin)
00189 {
00190     cpl_recipe  *   recipe ;
00191 
00192     /* Get the recipe out of the plugin */
00193     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00194         recipe = (cpl_recipe *)plugin ;
00195     else return -1 ;
00196 
00197     /* Issue a banner */
00198     hawki_print_banner();
00199 
00200     return hawki_step_photom_2mass(recipe->parameters, recipe->frames) ;
00201 }
00202 
00203 /*----------------------------------------------------------------------------*/
00209 /*----------------------------------------------------------------------------*/
00210 static int hawki_step_photom_2mass_destroy(cpl_plugin * plugin)
00211 {
00212     cpl_recipe  *   recipe ;
00213 
00214     /* Get the recipe out of the plugin */
00215     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00216         recipe = (cpl_recipe *)plugin ;
00217     else return -1 ;
00218 
00219     cpl_parameterlist_delete(recipe->parameters) ;
00220     return 0 ;
00221 }
00222 
00223 /*----------------------------------------------------------------------------*/
00229 /*----------------------------------------------------------------------------*/
00230 static int hawki_step_photom_2mass(cpl_parameterlist *   parlist,
00231                                    cpl_frameset *        frameset)
00232 {
00233     cpl_frameset *      cat_2mass;
00234     cpl_frameset *      obj_param;
00235     cpl_frameset *      obj_ima;
00236     cpl_table **        zpoint_table;
00237     cpl_propertylist ** qclists;
00238     int                 idet;
00239     
00240     /* Identify the RAW and CALIB frames in the input frameset */
00241     if (hawki_dfs_set_groups(frameset)) {
00242         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00243         return -1 ;
00244     }
00245 
00246     /* Retrieve 2MASS catalogue */
00247     if ((cat_2mass = hawki_extract_frameset(frameset,
00248                     HAWKI_UTIL_CAT_2MASS)) == NULL) 
00249     {
00250         cpl_msg_error(__func__, "Cannot find 2MASS catalogue (%s)",
00251                 HAWKI_UTIL_CAT_2MASS);
00252         return -1 ;
00253     }
00254 
00255     /* Retrieve obj param */
00256     if ((obj_param = hawki_extract_frameset
00257             (frameset, HAWKI_CALPRO_OBJ_PARAM)) == NULL) 
00258     {
00259         cpl_msg_error(__func__, "Cannot find object parameters (%s)",
00260                 HAWKI_CALPRO_OBJ_PARAM);
00261         return -1 ;
00262     }
00263 
00264     /* Retrieve reference image */
00265     if ((obj_ima = hawki_extract_frameset
00266             (frameset, HAWKI_CALPRO_COMBINED)) == NULL) 
00267     {
00268         cpl_msg_error(__func__, "Cannot find combined image (%s) ",
00269                 HAWKI_CALPRO_COMBINED);
00270         return -1 ;
00271     }
00272 
00273     /* Compute the zpoints */
00274     zpoint_table = hawki_step_photom_2mass_get_zpoints
00275         (cat_2mass, obj_param, obj_ima);
00276     if(zpoint_table == NULL)
00277     {
00278         cpl_msg_error(__func__,"Could not get the zpoints");
00279         cpl_frameset_delete(cat_2mass);
00280         cpl_frameset_delete(obj_param);
00281         cpl_frameset_delete(obj_ima);
00282         return -1;
00283     }
00284     
00285     /* Get some QC */
00286     qclists =  hawki_step_photom_2mass_qc(zpoint_table);
00287     if(zpoint_table == NULL)
00288     {
00289         cpl_msg_error(__func__,"Could not compute quality controls");
00290         cpl_frameset_delete(cat_2mass);
00291         cpl_frameset_delete(obj_param);
00292         cpl_frameset_delete(obj_ima);
00293         hawki_table_delete(zpoint_table);
00294         return -1;
00295     }
00296     
00297     /* Save the products */
00298     cpl_msg_info(__func__,"Saving products");
00299     if(hawki_step_photom_2mass_save(zpoint_table, parlist, qclists, frameset) == -1)
00300     {
00301         cpl_msg_error(__func__,"Could not save products");
00302         cpl_frameset_delete(cat_2mass);
00303         cpl_frameset_delete(obj_param);
00304         cpl_frameset_delete(obj_ima);
00305         hawki_table_delete(zpoint_table);
00306         return -1;
00307     }
00308     
00309     /* Free and return */
00310     cpl_frameset_delete(cat_2mass);
00311     cpl_frameset_delete(obj_param);
00312     cpl_frameset_delete(obj_ima);
00313     hawki_table_delete(zpoint_table);
00314     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00315         cpl_propertylist_delete(qclists[idet]);
00316     cpl_free(qclists);
00317 
00318     /* Return */
00319     if (cpl_error_get_code())
00320     {
00321         cpl_msg_error(__func__,
00322                       "HAWK-I pipeline could not recover from previous errors");
00323         return -1 ;
00324     }
00325     else return 0 ;
00326 }
00327 
00328 cpl_table ** hawki_step_photom_2mass_get_zpoints
00329 (cpl_frameset *     cat_2mass,
00330  cpl_frameset *     obj_param,
00331  cpl_frameset *     obj_ima)
00332 {
00333     cpl_table **       zpoint_table;
00334     cpl_table **       obj_det_param;
00335     cpl_propertylist * plist;
00336     int                idet;
00337     cpl_errorstate     error_prevstate = cpl_errorstate_get();
00338     
00339     /* Allocate zpoint_table */
00340     zpoint_table = cpl_malloc(sizeof(cpl_table *) * HAWKI_NB_DETECTORS);
00341 
00342     /* Load detected obj */
00343     obj_det_param = hawki_load_tables(cpl_frameset_get_first(obj_param));
00344      
00345     /* Read the main header */
00346     plist = cpl_propertylist_load
00347         (cpl_frame_get_filename(cpl_frameset_get_first(obj_ima)), 0);
00348     /* Loop on detectors */    
00349     for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
00350     {
00351         cpl_propertylist * wcs_info;
00352         cpl_table        * stars_2mass;
00353         cpl_array        * matches;
00354         int                ext_nb;
00355 
00356         cpl_msg_info(__func__,"Working on chip %d", idet + 1);
00357         cpl_msg_indent_more();
00358          
00359         /* Retrieve stars */
00360         ext_nb=hawki_get_ext_from_detector
00361             (cpl_frame_get_filename(cpl_frameset_get_first(obj_ima)),idet+1);
00362         wcs_info = cpl_propertylist_load
00363             (cpl_frame_get_filename(cpl_frameset_get_first(obj_ima)), ext_nb);
00364         stars_2mass = 
00365             hawki_step_photom_2mass_retrieve_stars(cat_2mass, wcs_info);        
00366         if(stars_2mass == NULL)
00367         {
00368             int jdet;
00369             cpl_msg_error(__func__, "Cannot retrieve stars");
00370             cpl_propertylist_delete(plist);
00371             cpl_propertylist_delete(wcs_info);
00372             hawki_table_delete(obj_det_param);
00373             for(jdet = 0; jdet <idet; ++jdet)
00374                 cpl_table_delete(zpoint_table[jdet]);
00375             cpl_free(zpoint_table);
00376             return NULL;
00377         }
00378          
00379         /* Pattern matching btw stars in 2MASS and detected ones */
00380         cpl_msg_info(__func__,"Matching %"CPL_SIZE_FORMAT
00381                      " 2MASS stars and %"CPL_SIZE_FORMAT" detections",
00382                      cpl_table_get_nrow(stars_2mass),
00383                      cpl_table_get_nrow(obj_det_param[idet]));
00384         matches = hawki_step_photom_2mass_ppm(stars_2mass, obj_det_param[idet]);
00385         
00386         /* Fill the zpoint table */
00387         cpl_msg_info(__func__,"Computing zero points");
00388         zpoint_table[idet] = hawki_step_photom_2mass_fill_zpoint_table
00389             (stars_2mass, obj_det_param[idet], matches, plist, idet);
00390         if(zpoint_table[idet] == NULL)
00391         {
00392             int jdet;
00393             cpl_msg_error(__func__, "Could not compute the zero points");
00394             cpl_propertylist_delete(plist);
00395             cpl_propertylist_delete(wcs_info);
00396             hawki_table_delete(obj_det_param);
00397             cpl_table_delete(stars_2mass);
00398             for(jdet = 0; jdet <idet; ++jdet)
00399                 cpl_table_delete(zpoint_table[jdet]);
00400             cpl_free(zpoint_table);
00401             cpl_array_delete(matches);
00402             return NULL;
00403         }
00404         
00405         /* Cleaning resources */
00406         cpl_msg_indent_less();
00407         cpl_propertylist_delete(wcs_info);
00408         cpl_table_delete(stars_2mass);
00409         cpl_array_delete(matches);
00410     }
00411     
00412     /* Free and return */
00413     hawki_table_delete(obj_det_param);
00414     cpl_propertylist_delete(plist);
00415     if(!cpl_errorstate_is_equal(error_prevstate))
00416     {
00417         int jdet;
00418         for(jdet = 0; jdet <HAWKI_NB_DETECTORS; ++jdet)
00419             cpl_table_delete(zpoint_table[jdet]);
00420         cpl_free(zpoint_table);
00421         cpl_msg_error(__func__, "A problem happened computing the zero point");
00422         cpl_errorstate_set(CPL_ERROR_NONE);
00423         return NULL;
00424     }
00425     return zpoint_table;
00426 }
00427 
00428 static cpl_table *  hawki_step_photom_2mass_retrieve_stars
00429 (cpl_frameset *     cat_2mass,
00430  cpl_propertylist * wcs_keywords)
00431 {
00432     char *          catpath;
00433     char *          catname;
00434     cpl_table *     stars;
00435     cpl_wcs *       wcs;
00436     int             nstars;
00437     int             istar;
00438     double          ra1;
00439     double          ra2;
00440     double          dec1;
00441     double          dec2;
00442     double          extra_search = 0.;
00443     cpl_matrix *    from_coord;
00444     cpl_matrix *    to_coord;
00445     cpl_array *     status;
00446     
00447 
00448     /* Extract the catalog path */
00449     if (irplib_2mass_get_catpars(cpl_frameset_get_first(cat_2mass),
00450                                  &catpath, &catname) != CPL_ERROR_NONE) 
00451         return NULL;
00452     
00453     /* Get the WCS info */
00454     wcs = cpl_wcs_new_from_propertylist(wcs_keywords);
00455     if(cpl_error_get_code() == CPL_ERROR_NO_WCS)
00456     {
00457         cpl_msg_error(__func__,"Not compiled with WCS support.");
00458         return NULL;
00459     }
00460     
00461     /* Get the limits to search */
00462     if(irplib_cat_get_image_limits(wcs, extra_search, 
00463                                    &ra1, &ra2, &dec1, &dec2) == 
00464                                        CPL_ERROR_DATA_NOT_FOUND)
00465     {
00466         cpl_msg_error(__func__,"No WCS information found");
00467         cpl_free(catname);
00468         cpl_free(catpath);
00469         cpl_wcs_delete(wcs);
00470         return NULL;
00471     }
00472     cpl_msg_info(__func__,"Searching stars in RA=[%f,%f] DEC=[%f,%f]",
00473                  ra1/15., ra2/15., dec1, dec2);
00474     
00475     
00476     /* Search the stars */
00477     stars = irplib_2mass_extract(catpath, ra1, ra2, dec1, dec2);
00478     if(stars == NULL)
00479     {
00480         cpl_msg_error(__func__,"Error retrieving 2mass stars: %s ",
00481                       cpl_error_get_message());
00482         cpl_free(catname);
00483         cpl_free(catpath);
00484         cpl_wcs_delete(wcs);
00485         return NULL;
00486     }
00487     nstars = cpl_table_get_nrow(stars);
00488     cpl_msg_indent_more();
00489     cpl_msg_info(__func__, "%d 2MASS stars found", nstars);
00490 
00491     /* Convert Ra, Dec to X,Y using the WCS information from image */
00492     from_coord = cpl_matrix_new(nstars, 2);
00493     for (istar=0; istar<nstars; istar++)
00494     {
00495         cpl_matrix_set(from_coord, istar, 0, cpl_table_get_float
00496                        (stars, HAWKI_COL_2MASS_RA, istar, NULL));
00497         cpl_matrix_set(from_coord, istar, 1, cpl_table_get_float
00498                        (stars, HAWKI_COL_2MASS_DEC, istar, NULL));
00499     }
00500 
00501     to_coord = NULL;
00502     status   = NULL;
00503     if(cpl_wcs_convert(wcs, from_coord, &to_coord, 
00504                        &status, CPL_WCS_WORLD2PHYS) != CPL_ERROR_NONE)
00505     {
00506         cpl_array_delete(status);
00507         cpl_matrix_delete(from_coord);
00508         cpl_matrix_delete(to_coord);
00509         cpl_free(catname);
00510         cpl_free(catpath);
00511         cpl_wcs_delete(wcs);
00512         cpl_msg_error(cpl_func,"Error in cpl_wcs conversion. %s",
00513                       cpl_error_get_message());
00514         return NULL;
00515     }
00516 
00517     /* Add the predicted x,y coordinate columns to the  2MASS table */
00518     cpl_table_new_column(stars, HAWKI_COL_2MASS_XPREDICT, CPL_TYPE_FLOAT);
00519     cpl_table_set_column_unit(stars,HAWKI_COL_2MASS_XPREDICT, "pixels");
00520     cpl_table_new_column(stars, HAWKI_COL_2MASS_YPREDICT, CPL_TYPE_FLOAT);
00521     cpl_table_set_column_unit(stars, HAWKI_COL_2MASS_YPREDICT, "pixels");
00522     for(istar=0; istar< nstars; istar++)
00523     {
00524         float xpredict = (float)cpl_matrix_get(to_coord, istar, 0);
00525         float ypredict = (float)cpl_matrix_get(to_coord, istar, 1);
00526         cpl_table_set_float(stars,"xpredict", istar, xpredict);
00527         cpl_table_set_float(stars,"ypredict", istar, ypredict);
00528     }
00529     
00530     /* Free and return */
00531     cpl_array_delete(status);
00532     cpl_matrix_delete(from_coord);
00533     cpl_matrix_delete(to_coord);
00534     cpl_wcs_delete(wcs);
00535     cpl_free(catname);
00536     cpl_free(catpath);
00537     cpl_msg_indent_less();
00538     return stars;
00539 }
00540 
00541 /*----------------------------------------------------------------------------*/
00547 /*----------------------------------------------------------------------------*/
00548 static cpl_array *   hawki_step_photom_2mass_ppm
00549 (cpl_table *  stars_2mass,
00550  cpl_table *  obj_det)
00551 {
00552     int                istar;
00553     int                iobj;
00554     int                iter;
00555     int                nstars_2mass;
00556     int                nstars_2mass_used_match;
00557     int                nobj;
00558     int                nobj_used_match;
00559     int                nmatches;
00560     int                nmax_match_pattern = 30;
00561     cpl_matrix *       pattern;
00562     cpl_array *        matches;
00563     double             tol = 0.1;
00564     double             pradius = 30.0;
00565     double             mean_data_pos_err = 5.;
00566     int                ppm_max_iter = 5;
00567     double             scale = 1;
00568     double             angle;
00569     cpl_matrix *       obj_pos;
00570     cpl_propertylist * sort_prop;
00571     
00572     
00573     /* Sort the detected objects */
00574     cpl_msg_indent_more();
00575     sort_prop = cpl_propertylist_new();
00576     cpl_propertylist_append_bool(sort_prop, HAWKI_COL_OBJ_FLUX, 1);
00577     if (cpl_table_sort(obj_det, sort_prop) != CPL_ERROR_NONE) 
00578     {
00579         cpl_msg_error(cpl_func,"Cannot sort detected sources table");
00580         cpl_propertylist_delete(sort_prop);
00581         return NULL;
00582     }
00583 
00584     /* Create matrix of X,Y coordinates of detected objects*/
00585     nobj = cpl_table_get_nrow(obj_det);
00586     obj_pos = cpl_matrix_new(2, nobj);
00587     for (iobj=0; iobj<nobj; iobj++)
00588     {
00589         float xim = cpl_table_get_double
00590             (obj_det, HAWKI_COL_OBJ_POSX, iobj, NULL); 
00591         float yim = cpl_table_get_double
00592             (obj_det, HAWKI_COL_OBJ_POSY, iobj, NULL);
00593         cpl_matrix_set(obj_pos, 0, iobj, xim);
00594         cpl_matrix_set(obj_pos, 1, iobj, yim);
00595     }
00596 
00597     /* Sort the 2MASS stars by magnitude */
00598     cpl_propertylist_empty(sort_prop);
00599     cpl_propertylist_append_bool(sort_prop, HAWKI_COL_2MASS_K_MAG, 0);
00600     if (cpl_table_sort(stars_2mass, sort_prop) != CPL_ERROR_NONE) 
00601     {
00602         cpl_msg_error(cpl_func,"Cannot sort 2MASS stars table");
00603         cpl_propertylist_delete(sort_prop);
00604         return NULL;
00605     }
00606 
00607     /* Prepare the 2MASS matrix for the pattern matching */
00608     nstars_2mass = cpl_table_get_nrow(stars_2mass);
00609     pattern = cpl_matrix_new(2, nstars_2mass);
00610     for(istar=0; istar<nstars_2mass ; istar++)
00611     {
00612         float x = cpl_table_get_float
00613             (stars_2mass, HAWKI_COL_2MASS_XPREDICT, istar, NULL);
00614         float y = cpl_table_get_float
00615             (stars_2mass, HAWKI_COL_2MASS_YPREDICT, istar, NULL);
00616         cpl_matrix_set(pattern, 0, istar, x);
00617         cpl_matrix_set(pattern, 1, istar, y);
00618     }
00619     
00620     /* Do the ppm */
00621     nstars_2mass_used_match = nmax_match_pattern;
00622     if(nstars_2mass < nmax_match_pattern)
00623         nstars_2mass_used_match = nstars_2mass;
00624     nobj_used_match = (int)(1.7 * nstars_2mass_used_match);
00625     if(nobj_used_match > nobj)
00626         nobj_used_match = nobj;
00627     if(nobj_used_match < nstars_2mass_used_match)
00628         nobj_used_match = nstars_2mass_used_match;
00629     cpl_msg_info(__func__,"The first step match will use %d stars "
00630                  "and %d objects", nstars_2mass_used_match,nobj_used_match);
00631     for (iter = 0; iter < ppm_max_iter; iter++)
00632     {
00633         int nmatchsize;
00634         nmatches = 0;
00635         matches = cpl_ppm_match_points(obj_pos, nobj_used_match, 
00636                                        mean_data_pos_err,
00637                                        pattern, nstars_2mass_used_match,
00638                                        1, tol, pradius,
00639                                        NULL, NULL, &scale, &angle);
00640         if(matches != NULL)
00641         {
00642             nmatchsize = cpl_array_get_size(matches);
00643             nmatches = nmatchsize -
00644                 cpl_array_count_invalid(matches);
00645         }
00646         else
00647         {
00648             nmatchsize = 0;
00649             nmatches = 0;
00650         }
00651         
00652         cpl_msg_info(cpl_func,"Total matches: %d. Valid matches: %d",
00653                      nmatchsize, nmatches);
00654         cpl_msg_info(cpl_func,"Scale=%g angle=%g", scale, angle);
00655         if((matches == NULL) || (nmatches < floor(nobj_used_match*0.1))) 
00656         {
00657             nobj_used_match = nobj_used_match + 10;
00658             cpl_msg_info(cpl_func,
00659                          "Increasing number of detections used in PPM to %d",
00660                          nobj_used_match);
00661             continue;
00662         }
00663         else
00664             break;
00665     }
00666 
00667     /* Output debug messages */
00668     cpl_msg_indent_more();
00669     cpl_msg_debug(__func__,"Matched stars:");
00670     cpl_msg_indent_more();
00671     cpl_msg_debug(__func__,"X_OBJ  Y_OBJ    X_STAR Y_STAR   X_DIFF Y_DIFF:");
00672     for(istar=0; istar < nstars_2mass; ++istar)
00673     {
00674         int  null;
00675         double x_obj, y_obj, x_star, y_star, x_diff, y_diff;
00676         iobj  = cpl_array_get_int(matches, istar, &null);
00677         
00678         if(null != 0)
00679             continue;
00680         x_obj = cpl_matrix_get(obj_pos, 0, iobj);
00681         y_obj = cpl_matrix_get(obj_pos, 1, iobj);
00682         x_star = cpl_matrix_get(pattern, 0, istar);
00683         y_star = cpl_matrix_get(pattern, 1, istar);
00684         x_diff = x_obj - x_star;
00685         y_diff = y_obj - y_star;
00686         cpl_msg_debug(__func__,"%6.1f %6.1f  %6.1f %6.1f   %6.1f %6.1f\n",
00687                       x_obj, y_obj, x_star, y_star, x_diff, y_diff);
00688     }
00689     cpl_msg_indent_less();    
00690     cpl_msg_indent_less();
00691     
00692     cpl_matrix_delete(pattern);
00693     cpl_msg_info(cpl_func, "%d points matched", nmatches);
00694 
00695     if(matches == NULL || nmatches == 0)
00696     {
00697         if(nmatches == 0)
00698             cpl_array_delete(matches);
00699         cpl_msg_error(cpl_func,"Error in PPM. %s",cpl_error_get_message());
00700         cpl_matrix_delete(obj_pos);
00701         cpl_propertylist_delete(sort_prop);
00702         cpl_msg_indent_less();
00703         return NULL;
00704     }
00705     
00706     if(nmatches < floor(nobj_used_match*0.1))
00707     {
00708         cpl_msg_warning(cpl_func,"PPM detected matched only %d objects."
00709                         " Results could be unreliable",nmatches);
00710     }
00711     
00712     /* Free and return */
00713     cpl_matrix_delete(obj_pos);
00714     cpl_propertylist_delete(sort_prop);
00715     cpl_msg_indent_less();
00716     return matches;
00717 }
00718 
00719 /*----------------------------------------------------------------------------*/
00724 /*----------------------------------------------------------------------------*/
00725 static cpl_table * hawki_step_photom_2mass_fill_zpoint_table
00726 (cpl_table *        stars_2mass,
00727  cpl_table *        obj_det_param,
00728  cpl_array *        matches,
00729  cpl_propertylist * plist,
00730  int                idet)
00731 {
00732     cpl_table    * zpoints;
00733     int            nmatches;
00734     int            nstars;
00735     int            imatch;
00736     int            istar;
00737     const char   * filter;
00738     char           magcol_2mass[100];
00739     char           magerrcol_2mass[100];
00740     double         dit;
00741     double         airmass;
00742     double         pixscale;
00743     double         extinction;
00744     cpl_errorstate error_prevstate = cpl_errorstate_get();
00745     
00746     /* Read parameters from the propertylist */
00747     airmass  = (hawki_pfits_get_airmass_start(plist) +
00748                 hawki_pfits_get_airmass_end(plist)) / 2.;
00749     filter   = hawki_pfits_get_filter(plist);
00750     dit      = hawki_pfits_get_dit(plist);
00751     pixscale = hawki_pfits_get_pixscale(plist);
00752     switch (hawki_get_band(filter))
00753     {
00754         case HAWKI_BAND_J:    
00755             extinction = 0.098;
00756             strncpy(magcol_2mass, HAWKI_COL_2MASS_J_MAG, 98);
00757             strncpy(magerrcol_2mass, HAWKI_COL_2MASS_J_MAGSIG, 98);
00758             break ;
00759         case HAWKI_BAND_H:
00760             extinction = 0.039;
00761             strncpy(magcol_2mass, HAWKI_COL_2MASS_H_MAG, 98);
00762             strncpy(magerrcol_2mass, HAWKI_COL_2MASS_H_MAGSIG, 98);
00763             break ;
00764         case HAWKI_BAND_K:
00765             extinction = 0.065;
00766             strncpy(magcol_2mass, HAWKI_COL_2MASS_K_MAG, 98);
00767             strncpy(magerrcol_2mass, HAWKI_COL_2MASS_K_MAGSIG, 98);
00768             break ;
00769         default: 
00770             extinction = 0.00;
00771             cpl_msg_warning(__func__,"The filter %s does not exist in 2MASS. "
00772                             "The 2MASS K band will be used instead. "
00773                             "Columns %s, %s, %s and %s in product will not "
00774                             "be accurate", filter, 
00775                             HAWKI_COL_ZPOINT_MAG, HAWKI_COL_ZPOINT_ERRMAG,
00776                             HAWKI_COL_ZPOINT_ZPOINT, HAWKI_COL_ZPOINT_ATX0);
00777             strncpy(magcol_2mass, HAWKI_COL_2MASS_K_MAG, 98);
00778             strncpy(magerrcol_2mass, HAWKI_COL_2MASS_K_MAGSIG, 98);
00779             break ;
00780     }
00781                 
00782     /* Select only stars in 2MASS that have the given magnitude */
00783     //irplib_stdstar_select_stars_mag(stars_2mass, magcol_2mass);
00784     //cpl_msg_warning(__func__,"Paso irplib");
00785     
00786     /* Create the table */
00787     nstars = cpl_table_get_nrow(stars_2mass);
00788     nmatches = cpl_array_get_size(matches) - cpl_array_count_invalid(matches);
00789     zpoints = cpl_table_new(nmatches) ;
00790     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_CHIP, CPL_TYPE_INT) ;
00791     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_POSX, CPL_TYPE_DOUBLE) ;
00792     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_POSY, CPL_TYPE_DOUBLE) ;
00793     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_ZPOINT, CPL_TYPE_DOUBLE) ;
00794     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_ATX0, CPL_TYPE_DOUBLE) ;
00795     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_MAG, CPL_TYPE_DOUBLE) ;
00796     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_ERRMAG, CPL_TYPE_DOUBLE) ;
00797     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_AIRMASS, CPL_TYPE_DOUBLE) ;
00798     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FLUX, CPL_TYPE_DOUBLE) ;
00799     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FILTER, CPL_TYPE_STRING) ;
00800 //    cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_PEAK, CPL_TYPE_DOUBLE) ;
00801 //    cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_BGD, CPL_TYPE_DOUBLE) ;
00802     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHMX, CPL_TYPE_DOUBLE) ;
00803     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHMY, CPL_TYPE_DOUBLE) ;
00804     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHM, CPL_TYPE_DOUBLE) ;
00805     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHMX_AS, CPL_TYPE_DOUBLE) ;
00806     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHMY_AS, CPL_TYPE_DOUBLE) ;
00807     cpl_table_new_column(zpoints, HAWKI_COL_ZPOINT_FWHM_AS, CPL_TYPE_DOUBLE) ;
00808     imatch = 0;
00809     
00810     for (istar=0; istar<nstars; istar++) 
00811     {
00812         int      iobj;
00813         int      null;
00814         double   zpoint;
00815         double   atx0;
00816         double   flux;
00817         double   mag;
00818         double   errmag;
00819         double   fwhm_x;
00820         double   fwhm_y;
00821         double   fwhm;
00822         
00823         iobj  = cpl_array_get_int(matches, istar, &null);
00824         
00825         if(null != 0)
00826             continue;
00827         if(!cpl_table_is_selected(stars_2mass, istar))
00828             continue;
00829        
00830         flux = cpl_table_get_double
00831             (obj_det_param, HAWKI_COL_OBJ_FLUX, iobj, NULL);
00832         mag = cpl_table_get_float
00833             (stars_2mass, magcol_2mass, istar, NULL); 
00834         errmag = cpl_table_get_float
00835             (stars_2mass, magerrcol_2mass, istar, NULL);
00836         zpoint = mag + 2.5 * log10(flux) - 2.5 * log10(dit);
00837         atx0 = zpoint + airmass * extinction;
00838         fwhm_x = cpl_table_get_double
00839             (obj_det_param, HAWKI_COL_OBJ_FWHM_MAJAX, iobj, NULL);
00840         fwhm_y = cpl_table_get_double
00841             (obj_det_param, HAWKI_COL_OBJ_FWHM_MINAX, iobj, NULL);
00842         fwhm   = sqrt(fwhm_x*fwhm_y); 
00843 
00844         cpl_table_set_int(zpoints, HAWKI_COL_ZPOINT_CHIP, imatch, idet + 1) ;
00845         cpl_table_set_double
00846             (zpoints, HAWKI_COL_ZPOINT_MAG, imatch, mag);
00847         cpl_table_set_double
00848             (zpoints, HAWKI_COL_ZPOINT_ERRMAG, imatch, errmag);
00849         cpl_table_set_string
00850             (zpoints, HAWKI_COL_ZPOINT_FILTER, imatch, filter);
00851         cpl_table_set_double
00852             (zpoints, HAWKI_COL_ZPOINT_AIRMASS, imatch, airmass);
00853         cpl_table_set_double
00854             (zpoints, HAWKI_COL_ZPOINT_POSX, imatch, cpl_table_get_double
00855              (obj_det_param, HAWKI_COL_OBJ_POSX, iobj, NULL));
00856         cpl_table_set_double
00857             (zpoints, HAWKI_COL_ZPOINT_POSY, imatch, cpl_table_get_double
00858              (obj_det_param, HAWKI_COL_OBJ_POSY, iobj, NULL));
00859         cpl_table_set_double(zpoints, HAWKI_COL_ZPOINT_ZPOINT, imatch, zpoint);
00860         cpl_table_set_double(zpoints, HAWKI_COL_ZPOINT_ATX0, imatch, atx0);
00861         cpl_table_set_double
00862             (zpoints, HAWKI_COL_ZPOINT_FLUX, imatch, flux);
00863 //        cpl_table_set_double(tab, HAWKI_COL_ZPOINT_PEAK, imatch, 
00864 //                hawki_img_zpoint_outputs.peak[labels[iframe]-1]) ;
00865 //        cpl_table_set_double(tab, HAWKI_COL_ZPOINT_BGD, imatch, 
00866 //                hawki_img_zpoint_outputs.bgd[labels[iframe]-1]) ;
00867         cpl_table_set_double
00868             (zpoints, HAWKI_COL_ZPOINT_FWHMX, imatch, fwhm_x);
00869         cpl_table_set_double
00870             (zpoints, HAWKI_COL_ZPOINT_FWHMY, imatch, fwhm_y);
00871         cpl_table_set_double
00872             (zpoints, HAWKI_COL_ZPOINT_FWHM, imatch, fwhm);
00873         cpl_table_set_double
00874             (zpoints, HAWKI_COL_ZPOINT_FWHMX_AS, imatch, fwhm_x * pixscale);
00875         cpl_table_set_double
00876             (zpoints, HAWKI_COL_ZPOINT_FWHMY_AS, imatch, fwhm_y * pixscale);
00877         cpl_table_set_double
00878             (zpoints, HAWKI_COL_ZPOINT_FWHM_AS, imatch, fwhm * pixscale);
00879         ++imatch;
00880     }
00881     
00882     /* Check error and return */
00883     if(!cpl_errorstate_is_equal(error_prevstate))
00884     {
00885         cpl_msg_error(__func__,"An error happened filling the zpoint table: %s",
00886                       cpl_error_get_message());
00887         cpl_table_delete(zpoints);
00888         return NULL;
00889     }
00890     return zpoints;
00891 }
00892 
00893 /*----------------------------------------------------------------------------*/
00898 /*----------------------------------------------------------------------------*/
00899 static cpl_propertylist ** hawki_step_photom_2mass_qc
00900 (cpl_table ** zpoint_table)
00901 {
00902     int idet;
00903     cpl_propertylist ** qclists;
00904     
00905     /* Allocate the qclists */
00906     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00907     
00908     /* Loop on the detectors to get the mean zpoint */
00909     for(idet = 0 ; idet < HAWKI_NB_DETECTORS ; ++idet)
00910     {
00911         double mean_zpoint;
00912 
00913         /* Allocate this qclist */
00914         qclists[idet] = cpl_propertylist_new() ;
00915         
00916         /* Compute the mean zpoint */
00917         mean_zpoint = cpl_table_get_column_mean(zpoint_table[idet],
00918                                                 HAWKI_COL_ZPOINT_ZPOINT);
00919         
00920         cpl_propertylist_append_double
00921             (qclists[idet], "ESO QC ZPOINT", mean_zpoint);
00922     }
00923     
00924     return qclists;
00925 }
00926 
00927 /*----------------------------------------------------------------------------*/
00937 /*----------------------------------------------------------------------------*/
00938 static int hawki_step_photom_2mass_save
00939 (cpl_table **         zpoints,
00940  cpl_parameterlist *  parlist,
00941  cpl_propertylist **  qclists,
00942  cpl_frameset *       set)
00943 {
00944     cpl_propertylist *   protype;
00945     cpl_frame *          ref_frame ;
00946     cpl_frameset *       combinedframes;
00947     int                  nframes ;
00948     const char *         recipe_name = "hawki_step_photom_2mass" ;
00949 
00950     /* Initialise */
00951     nframes = cpl_frameset_get_size(set) ;
00952 
00953     /* Get the reference frame */
00954     combinedframes = hawki_extract_frameset(set, HAWKI_CALPRO_COMBINED);
00955     ref_frame = cpl_frameset_get_first(combinedframes);
00956 
00957     /* Create the protype lists */
00958     protype = cpl_propertylist_new();
00959     cpl_propertylist_append_string(protype, "ESO PRO TYPE",
00960             HAWKI_PROTYPE_ZPOINT_TAB);
00961 
00962     /* Write the zpoint table  */
00963     hawki_tables_save(set,
00964                       parlist,
00965                       set,
00966                       (const cpl_table **)zpoints,
00967                       recipe_name,
00968                       HAWKI_CALPRO_ZPOINT_TAB,
00969                       HAWKI_PROTYPE_ZPOINT_TAB,
00970                       protype,
00971                       (const cpl_propertylist **)qclists,
00972                       "hawki_step_photom_2mass.fits") ;
00973 
00974     /* Free and return */
00975     cpl_propertylist_delete(protype);
00976     cpl_frameset_delete(combinedframes);
00977     return  0;
00978 }