HAWKI Pipeline Reference Manual 1.8.6
hawki_step_detect_obj.c
00001 /* $Id: hawki_step_detect_obj.c,v 1.25 2011/12/22 14:28:22 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: 2011/12/22 14:28:22 $
00024  * $Revision: 1.25 $
00025  * $Name: hawki-1_8_6 $
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 #include "irplib_calib.h"
00042 
00043 #include "hawki_utils.h"
00044 #include "hawki_obj_det.h"
00045 #include "hawki_mask.h"
00046 #include "hawki_image_stats.h"
00047 #include "hawki_calib.h"
00048 #include "hawki_load.h"
00049 #include "hawki_save.h"
00050 #include "hawki_pfits.h"
00051 #include "hawki_dfs.h"
00052 
00053 /*-----------------------------------------------------------------------------
00054                             Functions prototypes
00055  -----------------------------------------------------------------------------*/
00056 
00057 static int hawki_step_detect_obj_create(cpl_plugin *) ;
00058 static int hawki_step_detect_obj_exec(cpl_plugin *) ;
00059 static int hawki_step_detect_obj_destroy(cpl_plugin *) ;
00060 static int hawki_step_detect_obj(cpl_parameterlist *, cpl_frameset *) ;
00061 
00062 static void hawki_step_detect_obj_init_output(void);
00063 static void hawki_step_detect_obj_get_pscale
00064 (cpl_frameset * combframes);
00065 static int hawki_step_detect_obj_retrieve_input_param
00066 (cpl_parameterlist  *  parlist);
00067 static cpl_apertures  ** hawki_step_detect_obj_mask_and_apertures
00068 (cpl_frameset    *  combframes,
00069  cpl_image       ** mask_image,
00070  cpl_image       ** comb_image);
00071 static int hawki_step_detect_obj_aper_params
00072 (cpl_image      **  combined_images, 
00073  cpl_apertures  **  apertures,
00074  cpl_table      **  obj_charac);
00075 static int hawki_step_detect_obj_save
00076 (cpl_image           **  mask_images,
00077  cpl_table           **  obj_charac,
00078  cpl_propertylist    **  obj_stats,
00079  cpl_parameterlist   *   parlist,
00080  cpl_frameset        *   framelist);
00081 
00082 /*-----------------------------------------------------------------------------
00083                             Static variables
00084  -----------------------------------------------------------------------------*/
00085 
00086 static struct 
00087 {
00088     /* Inputs */
00089     double sigma_det;
00090     int    growing_radius;
00091 } hawki_step_detect_obj_config;
00092 
00093 static struct 
00094 {
00095     /* Outputs */
00096     double          pixscale;
00097     double          iq[HAWKI_NB_DETECTORS] ;
00098     int             nbobjs[HAWKI_NB_DETECTORS] ;
00099     double          fwhm_pix[HAWKI_NB_DETECTORS] ;
00100     double          fwhm_arcsec[HAWKI_NB_DETECTORS] ;
00101     double          fwhm_mode[HAWKI_NB_DETECTORS] ;
00102     double          pos_x[HAWKI_NB_DETECTORS] ;
00103     double          pos_y[HAWKI_NB_DETECTORS] ;
00104 } hawki_step_detect_obj_output;
00105 
00106 static char hawki_step_detect_obj_description[] =
00107 "hawki_step_detect_obj -- hawki detect objects recipe.\n"
00108 "This recipe detects objects from the combined image creating a mask\n"
00109 "and a list of object properties\n"
00110 "The input of the recipe files listed in the Set Of Frames (sof-file)\n"
00111 "must be tagged as:\n"
00112 "combined.fits "HAWKI_CALPRO_COMBINED"\n"
00113 "The recipe creates as an output:\n"
00114 "hawki_step_detect_obj_mask.fits ("HAWKI_CALPRO_OBJ_MASK"): A mask with 1 where the objects are present and 0 elsewhere\n"
00115 "hawki_step_detect_obj_stars.fits ("HAWKI_CALPRO_OBJ_PARAM"): A table with the detected objects characteristics\n"
00116 "Return code:\n"
00117 "esorex exits with an error code of 0 if the recipe completes successfully\n"
00118 "or 1 otherwise";
00119 
00120 
00121 
00122 /*-----------------------------------------------------------------------------
00123                                 Functions code
00124  -----------------------------------------------------------------------------*/
00125 
00126 /*----------------------------------------------------------------------------*/
00134 /*----------------------------------------------------------------------------*/
00135 int cpl_plugin_get_info(cpl_pluginlist * list)
00136 {
00137     cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
00138     cpl_plugin  *   plugin = &recipe->interface ;
00139 
00140     cpl_plugin_init(plugin,
00141                     CPL_PLUGIN_API,
00142                     HAWKI_BINARY_VERSION,
00143                     CPL_PLUGIN_TYPE_RECIPE,
00144                     "hawki_step_detect_obj",
00145                     "Object detection recipe",
00146                     hawki_step_detect_obj_description,
00147                     "Cesar Enrique Garcia Dabo",
00148                     PACKAGE_BUGREPORT,  
00149                     hawki_get_license(),
00150                     hawki_step_detect_obj_create,
00151                     hawki_step_detect_obj_exec,
00152                     hawki_step_detect_obj_destroy) ;
00153 
00154     cpl_pluginlist_append(list, plugin) ;
00155     
00156     return 0;
00157 }
00158 
00159 /*----------------------------------------------------------------------------*/
00168 /*----------------------------------------------------------------------------*/
00169 static int hawki_step_detect_obj_create(cpl_plugin * plugin)
00170 {
00171     cpl_recipe      * recipe ;
00172     cpl_parameter   * p ;
00173 
00174     /* Get the recipe out of the plugin */
00175     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00176         recipe = (cpl_recipe *)plugin ;
00177     else return -1 ;
00178 
00179     /* Create the parameters list in the cpl_recipe object */
00180     recipe->parameters = cpl_parameterlist_new() ;
00181     if (recipe->parameters == NULL)
00182         return 1;
00183 
00184     /* Fill the parameters list */
00185     /* --sigma_det */
00186     p = cpl_parameter_new_value("hawki.hawki_step_detect_obj.sigma_det", 
00187                                 CPL_TYPE_DOUBLE, "detection level",
00188                                 "hawki.hawki_step_detect_obj", 6.);
00189     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_det");
00190     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00191     cpl_parameterlist_append(recipe->parameters, p);
00192 
00193     /* --growing_radius */
00194     p = cpl_parameter_new_value("hawki.hawki_step_detect_obj.growing_radius", 
00195                                 CPL_TYPE_INT,
00196                                 "radius of convolution kernel to apply to objects",
00197                                 "hawki.hawki_step_detect_obj", 5);
00198     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "growing_radius");
00199     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00200     cpl_parameterlist_append(recipe->parameters, p);
00201 
00202     /* Return */
00203     return 0;
00204 }
00205 
00206 /*----------------------------------------------------------------------------*/
00212 /*----------------------------------------------------------------------------*/
00213 static int hawki_step_detect_obj_exec(cpl_plugin * plugin)
00214 {
00215     cpl_recipe  *   recipe ;
00216 
00217     /* Get the recipe out of the plugin */
00218     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00219         recipe = (cpl_recipe *)plugin ;
00220     else return -1 ;
00221 
00222     /* Issue a banner */
00223     hawki_print_banner();
00224 
00225     return hawki_step_detect_obj(recipe->parameters, recipe->frames) ;
00226 }
00227 
00228 /*----------------------------------------------------------------------------*/
00234 /*----------------------------------------------------------------------------*/
00235 static int hawki_step_detect_obj_destroy(cpl_plugin * plugin)
00236 {
00237     cpl_recipe  *   recipe ;
00238 
00239     /* Get the recipe out of the plugin */
00240     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00241         recipe = (cpl_recipe *)plugin ;
00242     else return -1 ;
00243 
00244     cpl_parameterlist_delete(recipe->parameters) ;
00245     return 0 ;
00246 }
00247 
00248 /*----------------------------------------------------------------------------*/
00255 /*----------------------------------------------------------------------------*/
00256 static int hawki_step_detect_obj(
00257         cpl_parameterlist   *   parlist, 
00258         cpl_frameset        *   framelist)
00259 {
00260     cpl_frameset     *   combframes;
00261     cpl_image        **  mask_image;
00262     cpl_image        **  comb_image;
00263     cpl_apertures    **  apertures;
00264     cpl_table        **  obj_charac;
00265     cpl_propertylist **  obj_stats;
00266     int                  idet;
00267     
00268     /* Initialise */
00269     hawki_step_detect_obj_init_output();
00270 
00271     /* Retrieve input parameters */
00272     if(hawki_step_detect_obj_retrieve_input_param(parlist))
00273     {
00274         cpl_msg_error(__func__, "Wrong parameters");
00275         return -1;
00276     }
00277 
00278     /* Identify the RAW and CALIB frames in the input frameset */
00279     if (hawki_dfs_set_groups(framelist)) {
00280         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00281         return -1 ;
00282     }
00283 
00284     /* Retrieve raw frames */
00285     combframes = hawki_extract_frameset(framelist, HAWKI_CALPRO_COMBINED) ;
00286     if (combframes == NULL) 
00287     {
00288         cpl_msg_error(__func__, "Cannot find combined images in the input (%s)",
00289                 HAWKI_CALPRO_COMBINED);
00290         return -1 ;
00291     }
00292     if (cpl_frameset_get_size(combframes) != 1)
00293     {
00294         cpl_msg_error(__func__, "Only one combined image must be provided");
00295         return -1 ;
00296     }
00297 
00298     /* Get info from the headers */
00299     hawki_step_detect_obj_get_pscale(combframes);
00300     
00301     /* Get the mask with the points above the background 
00302      * and the associated apertures*/
00303     cpl_msg_info(__func__, "Getting the object masks") ;
00304     mask_image = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_image *));
00305     comb_image = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_image *));
00306     apertures =  hawki_step_detect_obj_mask_and_apertures
00307         (combframes, mask_image, comb_image);
00308     if(apertures == NULL)
00309     {
00310         cpl_msg_error(__func__,"Could not detect objects in image");
00311         cpl_frameset_delete(combframes);
00312         cpl_free(mask_image);
00313         cpl_free(comb_image);
00314         return -1;
00315     }
00316     
00317     /* Get object characterizations and statistics */
00318     cpl_msg_info(__func__, "Getting object parameters") ;
00319     obj_charac = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *)) ;
00320     obj_stats  = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist *));
00321     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00322     {
00323         obj_charac[idet] = cpl_table_new
00324             (cpl_apertures_get_size(apertures[idet]));
00325         obj_stats[idet] = cpl_propertylist_new();
00326     }
00327     hawki_step_detect_obj_aper_params(comb_image, apertures, obj_charac);
00328  
00329     /* Statistics of the detected objects in the QC */
00330     hawki_obj_prop_stats(obj_charac, obj_stats);
00331 
00332     /* Save the products */
00333     cpl_msg_info(__func__, "Save the products") ;
00334     if (hawki_step_detect_obj_save(mask_image, obj_charac, obj_stats,
00335                                    parlist, framelist) == -1)
00336     {
00337         cpl_msg_warning(__func__, "Some data could not be saved. "
00338                         "Check permisions or disk space") ;
00339         for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00340         {
00341             cpl_table_delete(obj_charac[idet]);
00342             cpl_propertylist_delete(obj_stats[idet]);
00343             cpl_apertures_delete(apertures[idet]);
00344         }
00345         cpl_free(apertures);
00346         cpl_free(obj_charac);
00347         cpl_free(obj_stats);
00348         cpl_frameset_delete(combframes);
00349         for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00350         {
00351             cpl_image_delete(mask_image[idet]);
00352             cpl_image_delete(comb_image[idet]);
00353         }
00354         cpl_free(mask_image);
00355         cpl_free(comb_image);
00356         return -1 ;
00357     }
00358     
00359     /* Return */
00360     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00361     {
00362         cpl_table_delete(obj_charac[idet]);
00363         cpl_propertylist_delete(obj_stats[idet]);
00364         cpl_apertures_delete(apertures[idet]);
00365         cpl_image_delete(mask_image[idet]);
00366         cpl_image_delete(comb_image[idet]);
00367     }
00368     cpl_free(apertures);
00369     cpl_free(obj_charac);
00370     cpl_free(obj_stats);
00371     cpl_frameset_delete(combframes);
00372     cpl_free(mask_image);
00373     cpl_free(comb_image);
00374 
00375     /* Return */
00376     if (cpl_error_get_code())
00377     {
00378         cpl_msg_error(__func__,
00379                       "HAWK-I pipeline could not recover from previous errors");
00380         return -1 ;
00381     }
00382     else return 0 ;
00383 }
00384 
00385 int hawki_step_detect_obj_retrieve_input_param
00386 (cpl_parameterlist  *  parlist)
00387 {
00388     cpl_parameter   *   par ;
00389 
00390     par = NULL ;
00391     par = cpl_parameterlist_find
00392         (parlist, "hawki.hawki_step_detect_obj.sigma_det");
00393     hawki_step_detect_obj_config.sigma_det = cpl_parameter_get_double(par);
00394     par = cpl_parameterlist_find
00395         (parlist, "hawki.hawki_step_detect_obj.growing_radius");
00396     hawki_step_detect_obj_config.growing_radius = cpl_parameter_get_int(par);
00397     if(hawki_step_detect_obj_config.growing_radius > 100)
00398     {
00399         cpl_msg_error(__func__,"The maximum radius allowed is 100");
00400         return -1;
00401     }
00402     if(hawki_step_detect_obj_config.sigma_det <= 0 )
00403     {
00404         cpl_msg_error(__func__,"Detection sigma has to be greater than 0");
00405         return -1;
00406     }
00407 
00408     return 0;
00409 }
00410 
00411 
00412 
00413 /*----------------------------------------------------------------------------*/
00423 /*----------------------------------------------------------------------------*/
00424 static cpl_apertures  ** hawki_step_detect_obj_mask_and_apertures
00425 (cpl_frameset    *  combframes,
00426  cpl_image       ** mask_image,
00427  cpl_image       ** comb_image)
00428 {
00429     cpl_apertures   **  apertures;
00430     int                 idet;
00431 
00432     /* Create output object */
00433     apertures = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_apertures *));
00434   
00435     /* Loop on the detectors */
00436     cpl_msg_indent_more();
00437     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00438     {
00439         cpl_image  * chip_image;
00440         cpl_image  * chip_image_sort;
00441         cpl_mask   * object_mask;
00442         cpl_mask   * kernel_op;
00443         cpl_matrix * kernel;
00444         cpl_image  * labels;
00445         cpl_size     nobj;
00446         double       bkg_level;
00447         double       bkg_noise;
00448         double       threshold;
00449         int          kernel_size;
00450         int          ix;
00451         int          iy;
00452 
00453         cpl_msg_info(__func__, "Detecting objects on chip number %d", idet+1) ;
00454         cpl_msg_indent_more();
00455         
00456         /* Load the input data */
00457         cpl_msg_info(__func__, "Load the input data") ;
00458         chip_image = hawki_load_image(combframes, 0, idet+1, CPL_TYPE_FLOAT);
00459         if (chip_image == NULL) 
00460         {
00461             cpl_msg_error(__func__, "Cannot load chip %d", idet+1) ;
00462             cpl_msg_indent_less() ;
00463             cpl_free(apertures);
00464             return NULL ;
00465         }
00466         
00467         /* Subtract the median of the frame first */
00468         chip_image_sort = cpl_image_duplicate(chip_image);
00469         bkg_level = cpl_image_get_median(chip_image);
00470         bkg_noise = hawki_image_float_get_sigma_from_quartile(chip_image_sort); 
00471         cpl_image_delete(chip_image_sort);
00472         threshold = bkg_level + hawki_step_detect_obj_config.sigma_det * bkg_noise;        
00473         cpl_msg_info(__func__, "Background:       %f",bkg_level);
00474         cpl_msg_info(__func__, "Background noise: %f",bkg_noise);
00475         
00476         /* Create the mask */
00477         cpl_msg_info(__func__, "Mask creation with threshold: %f",threshold);
00478         object_mask = cpl_mask_threshold_image_create
00479             (chip_image, threshold, DBL_MAX);
00480 
00481         /* Apply a morphological opening to remove single pixel detections */
00482         cpl_msg_info(__func__, "Removing single pixel detections");
00483         kernel_op = cpl_mask_new(3, 3); 
00484         cpl_mask_not(kernel_op);
00485         if (cpl_mask_filter(object_mask, object_mask, kernel_op, 
00486                             CPL_FILTER_OPENING, 
00487                             CPL_BORDER_ZERO) != CPL_ERROR_NONE)
00488         {
00489             cpl_mask_delete(object_mask);
00490             cpl_mask_delete(kernel_op);
00491             return NULL;
00492         }
00493         cpl_mask_delete(kernel_op);
00494         
00495         /* Apply dilation to the mask */
00496         if(hawki_step_detect_obj_config.growing_radius>0)
00497         {
00498             cpl_msg_info(__func__, "Growing the mask with radius %d",
00499                     hawki_step_detect_obj_config.growing_radius);
00500             kernel_size = hawki_step_detect_obj_config.growing_radius*2+1;
00501             kernel = cpl_matrix_new(kernel_size, kernel_size);
00502             for(ix=0;ix<kernel_size;++ix)
00503                 for(iy=0;iy<kernel_size;++iy)
00504                 {
00505                     double xpos = ix+0.5-kernel_size/2.;
00506                     double ypos = iy+0.5-kernel_size/2.;
00507                     double kernel_func = 1-sqrt(xpos*xpos+ypos*ypos)/
00508                     hawki_step_detect_obj_config.growing_radius;
00509                     if(kernel_func<0)
00510                         kernel_func = 0;
00511                     cpl_matrix_set(kernel, ix, iy, kernel_func);
00512                 }
00513             if (hawki_mask_convolve(object_mask, kernel) != CPL_ERROR_NONE) {
00514                 cpl_mask_delete(object_mask) ;
00515                 cpl_matrix_delete(kernel) ;
00516                 return NULL;
00517             }
00518             cpl_matrix_delete(kernel);
00519         }
00520     
00521         /* Put the mask and the chip image in the imagelist */
00522         mask_image[idet] =  cpl_image_new_from_mask(object_mask);
00523         comb_image[idet] =  chip_image;
00524         
00525         /* Labelise the different detected apertures */
00526         cpl_msg_info(__func__, "Labelise mask") ;
00527         labels = cpl_image_labelise_mask_create(object_mask, &nobj);
00528         if (labels == NULL) 
00529         {
00530             int jdet;
00531             cpl_free(apertures);
00532             cpl_mask_delete(object_mask);
00533             for (jdet=0 ; jdet<idet + 1 ; jdet++)
00534             {
00535                 cpl_image_delete(mask_image[jdet]);
00536                 cpl_image_delete(comb_image[jdet]);
00537             }
00538         }
00539         cpl_msg_info(__func__, "Number of objects detected: %d", nobj) ;
00540 
00541         /* Create the detected apertures list */
00542         cpl_msg_info(__func__, "Create apertures") ;
00543         apertures[idet] = cpl_apertures_new_from_image(chip_image, labels);
00544         if (apertures[idet] == NULL)
00545         {
00546             int jdet;
00547             cpl_free(apertures);
00548             cpl_mask_delete(object_mask);
00549             for (jdet=0 ; jdet<idet + 1 ; jdet++)
00550             {
00551                 cpl_image_delete(mask_image[jdet]);
00552                 cpl_image_delete(comb_image[jdet]);
00553             }
00554             return NULL;
00555         }
00556         
00557         /* Free */
00558         cpl_mask_delete(object_mask);
00559         cpl_image_delete(labels);
00560         cpl_msg_indent_less();
00561     }
00562 
00563     /* Free and return */
00564     cpl_msg_indent_less();
00565     return apertures;
00566 }
00567 
00568 /*----------------------------------------------------------------------------*/
00575 /*----------------------------------------------------------------------------*/
00576 static int hawki_step_detect_obj_aper_params
00577 (cpl_image      **  combined_images, 
00578  cpl_apertures  **  apertures,
00579  cpl_table      **  obj_charac)
00580 {
00581     int                 nb_objs ;
00582     double              angle ;
00583     double          *   fwhms_x ;
00584     double          *   fwhms_y ;
00585     cpl_bivector    *   iqe ;
00586     int                 nb_good ;
00587     cpl_vector      *   fwhms_good ;
00588     double          *   fwhms_good_data ;
00589     double              f_min, f_max, fr, fx, fy ;
00590     int                 chip;
00591     int                 iobj;
00592     int                 j;
00593     
00594     /* Initialise */
00595     double              seeing_min_arcsec = 0.1 ;
00596     double              seeing_max_arcsec = 5.0 ;
00597     double              seeing_fwhm_var   = 0.2 ;
00598 
00599     /* Check entries */
00600     if (combined_images  == NULL) return -1 ;
00601     if (obj_charac       == NULL) return -1 ;
00602 
00603     /* Loop on the HAWK-I detectors */
00604     cpl_msg_indent_more();
00605     for (chip=0 ; chip<HAWKI_NB_DETECTORS ; chip++) 
00606     {
00607 
00608         /* Number of detected objects */
00609         nb_objs = cpl_apertures_get_size(apertures[chip]);
00610         cpl_msg_info(__func__, "%d objects detected on chip %d",nb_objs,chip+1);
00611         hawki_step_detect_obj_output.nbobjs[chip] = nb_objs ;
00612         fwhms_x = cpl_malloc(nb_objs * sizeof(double)) ;
00613         fwhms_y = cpl_malloc(nb_objs * sizeof(double)) ;
00614         
00615         /* Initialize the output table */
00616         cpl_table_set_size(obj_charac[chip], nb_objs);
00617         cpl_table_new_column
00618             (obj_charac[chip], HAWKI_COL_OBJ_POSX, CPL_TYPE_DOUBLE);
00619         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSX,"pix");
00620         cpl_table_new_column
00621             (obj_charac[chip], HAWKI_COL_OBJ_POSY, CPL_TYPE_DOUBLE);
00622         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSY,"pix");
00623         cpl_table_new_column
00624             (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, CPL_TYPE_DOUBLE);
00625         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_ANGLE,"grad");
00626         cpl_table_new_column
00627             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, CPL_TYPE_DOUBLE);
00628         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MAJAX,"pix");
00629         cpl_table_new_column
00630             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, CPL_TYPE_DOUBLE);
00631         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MINAX,"pix");
00632         cpl_table_new_column
00633             (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, CPL_TYPE_DOUBLE);
00634         cpl_table_new_column
00635             (obj_charac[chip], HAWKI_COL_OBJ_FLUX, CPL_TYPE_DOUBLE);
00636         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FLUX,"ADU");
00637         for (iobj=0 ; iobj<nb_objs ; iobj++)
00638         {
00639             /* Fill with the already known information */
00640             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSX, iobj, 
00641                                  cpl_apertures_get_centroid_x(apertures[chip],
00642                                                               iobj+1));
00643             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSY, iobj, 
00644                                  cpl_apertures_get_centroid_y(apertures[chip],
00645                                                               iobj+1));
00646             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_FLUX, iobj, 
00647                                  cpl_apertures_get_flux(apertures[chip],
00648                                                         iobj+1));
00649             /* Compute the FWHM informations */
00650             iqe = cpl_image_iqe(combined_images[chip], 
00651                 (int)cpl_apertures_get_centroid_x(apertures[chip], iobj+1)- 10,
00652                 (int)cpl_apertures_get_centroid_y(apertures[chip], iobj+1)- 10,
00653                 (int)cpl_apertures_get_centroid_x(apertures[chip], iobj+1)+ 10,
00654                 (int)cpl_apertures_get_centroid_y(apertures[chip], iobj+1)+ 10);
00655             if (iqe == NULL)
00656             {
00657                 cpl_error_reset() ;
00658                 cpl_msg_debug(__func__, "Cannot get FWHM for obj at pos %g %g",
00659                               cpl_apertures_get_centroid_x(apertures[chip],
00660                                                            iobj+1),
00661                               cpl_apertures_get_centroid_y(apertures[chip],
00662                                                            iobj+1)) ;
00663                 fwhms_x[iobj] = -1.0 ;
00664                 fwhms_y[iobj] = -1.0 ;
00665                 angle = 0.0 ;
00666             }
00667             else 
00668             {
00669                 fwhms_x[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 2) ;
00670                 fwhms_y[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 3) ;
00671                 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4) ;
00672                 cpl_bivector_delete(iqe) ;
00673                 cpl_msg_debug(__func__,
00674                               "FWHM for obj at pos %g %g: %g x %g (%g)",
00675                               cpl_apertures_get_centroid_x(apertures[chip],
00676                                                            iobj+1),
00677                               cpl_apertures_get_centroid_y(apertures[chip],
00678                                                            iobj+1),
00679                               fwhms_x[iobj], fwhms_y[iobj], angle) ;
00680             }
00681             cpl_table_set_double
00682                 (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, iobj, angle) ;
00683             cpl_table_set_double
00684                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, iobj,
00685                  fwhms_x[iobj]);
00686             cpl_table_set_double
00687                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, iobj,
00688                  fwhms_y[iobj]);
00689             cpl_table_set_double
00690                 (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, iobj,
00691                  1 - fwhms_y[iobj] / fwhms_x[iobj]);
00692         }
00693 
00694         /* Get the number of good values */
00695         nb_good = 0 ;
00696         for (iobj=0 ; iobj<nb_objs ; iobj++) 
00697         {
00698             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) nb_good++ ;
00699         }
00700         if (nb_good == 0) 
00701         {
00702             cpl_msg_warning
00703                 (__func__, "No objects to compute mean FWHM on chip %d",chip+1);
00704             cpl_free(fwhms_x) ;
00705             cpl_free(fwhms_y) ;
00706             continue;
00707         }
00708     
00709         /* Get the good values */
00710         fwhms_good = cpl_vector_new(nb_good) ;
00711         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
00712         j=0 ;
00713         for (iobj=0 ; iobj<nb_objs ; iobj++) 
00714         {
00715             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) 
00716             {
00717                 fwhms_good_data[j] = (fwhms_x[iobj]+fwhms_y[iobj])/2.0 ;
00718                 j++ ;
00719             }
00720         }
00721    
00722         /* Compute the fwhm */
00723         if (nb_good < 3) 
00724         {
00725             /* Too few values to compute the median */
00726             hawki_step_detect_obj_output.fwhm_pix[chip] = fwhms_good_data[0] ;
00727             cpl_msg_warning
00728                 (__func__, "Fewer than 3 objects, using the first object FWHM");
00729         } 
00730         else 
00731         {
00732             /* Compute the median */
00733             hawki_step_detect_obj_output.fwhm_pix[chip] =
00734                 cpl_vector_get_median_const(fwhms_good);
00735         }
00736         hawki_step_detect_obj_output.fwhm_arcsec[chip] = 
00737             hawki_step_detect_obj_output.fwhm_pix[chip] *
00738                 hawki_step_detect_obj_output.pixscale ;
00739 
00740         /* Compute the mode of the FWHMs */
00741         if (nb_good > 5)
00742         {
00743             hawki_step_detect_obj_output.fwhm_mode[chip] =
00744                 hawki_vector_get_mode(fwhms_good);
00745             hawki_step_detect_obj_output.fwhm_mode[chip] *= 
00746                 hawki_step_detect_obj_output.pixscale;
00747         }
00748         cpl_vector_delete(fwhms_good);
00749     
00750         /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */
00751         /* Compute f_min and f_max */
00752         f_min = seeing_min_arcsec / hawki_step_detect_obj_output.pixscale;
00753         f_max = seeing_max_arcsec / hawki_step_detect_obj_output.pixscale; 
00754 
00755         /* Get the number of good values */
00756         nb_good = 0 ;
00757         for (iobj=0 ; iobj<nb_objs ; iobj++) 
00758         {
00759             fx = fwhms_x[iobj] ;
00760             fy = fwhms_y[iobj] ;
00761             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
00762             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
00763                     (fr < seeing_fwhm_var)) nb_good++ ;
00764         }
00765         if (nb_good == 0) 
00766         {
00767             cpl_msg_warning(__func__, "No objects to compute IQ on chip %d",
00768                             chip+1);
00769             cpl_free(fwhms_x) ;
00770             cpl_free(fwhms_y) ;
00771             continue;
00772         }
00773 
00774         /* Get the good values */
00775         fwhms_good = cpl_vector_new(nb_good) ;
00776         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
00777         j=0 ;
00778         for (iobj=0 ; iobj<nb_objs ; iobj++) 
00779         {
00780             fx = fwhms_x[iobj] ;
00781             fy = fwhms_y[iobj] ;
00782             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
00783             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
00784                     (fr < seeing_fwhm_var)) 
00785             {
00786                 fwhms_good_data[j] = (fx + fy)/2.0 ;
00787                 j++ ;
00788             }
00789         }
00790         cpl_free(fwhms_x) ;
00791         cpl_free(fwhms_y) ;
00792     
00793         /* Compute the fwhm */
00794         if (nb_good < 3) 
00795         {
00796             /* Too few values to compute the median */
00797             hawki_step_detect_obj_output.iq[chip] = fwhms_good_data[0] ;
00798         }
00799         else 
00800         {
00801             /* Compute the median */
00802             hawki_step_detect_obj_output.iq[chip] = 
00803                 cpl_vector_get_median_const(fwhms_good) ;
00804         }
00805         cpl_vector_delete(fwhms_good);
00806         hawki_step_detect_obj_output.iq[chip] *= 
00807             hawki_step_detect_obj_output.pixscale;
00808     }
00809     cpl_msg_indent_less();
00810     
00811     return 0;
00812 }
00813         
00814         
00815 /*----------------------------------------------------------------------------*/
00824 /*----------------------------------------------------------------------------*/
00825 static int hawki_step_detect_obj_save
00826 (cpl_image           **  mask_images,
00827  cpl_table           **  obj_charac,
00828  cpl_propertylist    **  obj_stats,
00829  cpl_parameterlist   *   parlist,
00830  cpl_frameset        *   framelist)
00831 {
00832     const cpl_frame     *   ref_frame ;
00833     cpl_propertylist    **  qclists;
00834     int                     ext_nb ;
00835     const char          *   recipe_name = "hawki_step_detect_obj" ;
00836     int                     i;
00837     cpl_errorstate          error_prevstate = cpl_errorstate_get();
00838     
00839 
00840 
00841     /* Load the WCS keys */
00842     ref_frame = irplib_frameset_get_first_from_group
00843         (framelist, CPL_FRAME_GROUP_RAW);
00844 
00845     /* Create the QC lists */
00846     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00847     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00848     {
00849         cpl_propertylist    *   inputlist;
00850         cpl_propertylist    *   offsetlist;
00851         cpl_propertylist    *   wcslist;
00852 
00853         /* Get the extension number */
00854         ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
00855         qclists[i] = cpl_propertylist_new() ;
00856 
00857         /* Fill the QC */
00858         cpl_propertylist_append_int
00859             (qclists[i], "ESO QC NBOBJS", 
00860              hawki_step_detect_obj_output.nbobjs[i]);
00861         cpl_propertylist_append_double
00862             (qclists[i], "ESO QC IQ", hawki_step_detect_obj_output.iq[i]);
00863         cpl_propertylist_append_double
00864             (qclists[i], "ESO QC FWHM PIX",
00865              hawki_step_detect_obj_output.fwhm_pix[i]);
00866         cpl_propertylist_append_double
00867             (qclists[i], "ESO QC FWHM ARCSEC",
00868              hawki_step_detect_obj_output.fwhm_arcsec[i]);
00869         cpl_propertylist_append_double
00870             (qclists[i], "ESO QC FWHM MODE",
00871              hawki_step_detect_obj_output.fwhm_mode[i]);
00872 
00873         /* Propagate some keywords from input raw frame extensions */
00874         inputlist = cpl_propertylist_load_regexp(
00875                 cpl_frame_get_filename(ref_frame), ext_nb,
00876                 HAWKI_HEADER_EXT_FORWARD, 0);
00877         offsetlist = cpl_propertylist_load_regexp(
00878                 cpl_frame_get_filename(ref_frame), ext_nb,
00879                 HAWKI_HEADER_COMB_OFFSETS, 0);
00880         wcslist = cpl_propertylist_load_regexp(
00881                 cpl_frame_get_filename(ref_frame), ext_nb,
00882                 HAWKI_HEADER_WCS, 0);
00883         cpl_propertylist_append(qclists[i], inputlist);
00884         cpl_propertylist_append(qclists[i], offsetlist);
00885         cpl_propertylist_append(qclists[i], wcslist);
00886         cpl_propertylist_delete(inputlist);
00887         cpl_propertylist_delete(offsetlist);
00888         cpl_propertylist_delete(wcslist);
00889         
00890         /* Add the object statistics keywords */
00891         cpl_propertylist_append(qclists[i], obj_stats[i]);
00892     }
00893 
00894 
00895     /* Write the object mask */
00896     hawki_images_save(framelist,
00897                       parlist,
00898                       framelist, 
00899                       (const cpl_image**)mask_images, 
00900                       recipe_name,
00901                       HAWKI_CALPRO_OBJ_MASK, 
00902                       HAWKI_PROTYPE_OBJ_MASK,
00903                       NULL,
00904                       (const cpl_propertylist**)qclists,
00905                       "hawki_step_detect_obj_mask.fits") ;
00906 
00907     /* Write the FITS table with the objects statistics */
00908     hawki_tables_save(framelist,
00909                       parlist,
00910                       framelist,    
00911                       (const cpl_table **)obj_charac,
00912                       recipe_name,
00913                       HAWKI_CALPRO_OBJ_PARAM,
00914                       HAWKI_PROTYPE_OBJ_PARAM,
00915                       NULL,
00916                       (const cpl_propertylist**)qclists,
00917                       "hawki_step_detect_obj_stars.fits") ;
00918 
00919 
00920     /* Free and return */
00921     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
00922         cpl_propertylist_delete(qclists[i]) ;
00923     }
00924     cpl_free(qclists) ;
00925     if(!cpl_errorstate_is_equal(error_prevstate))
00926     {
00927         cpl_errorstate_set(CPL_ERROR_NONE);
00928         return -1;
00929     }
00930     return  0;
00931 }
00932 
00933 static void hawki_step_detect_obj_init_output(void)
00934 {
00935     int    idet;
00936     
00937     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00938     {
00939         hawki_step_detect_obj_output.iq[idet] = -1.0 ;
00940         hawki_step_detect_obj_output.nbobjs[idet] = -1 ;
00941         hawki_step_detect_obj_output.fwhm_pix[idet] = -1.0 ;
00942         hawki_step_detect_obj_output.fwhm_arcsec[idet] = -1.0 ;
00943         hawki_step_detect_obj_output.fwhm_mode[idet] = -1.0 ;
00944         hawki_step_detect_obj_output.pos_x[idet] = -1.0 ;
00945         hawki_step_detect_obj_output.pos_y[idet] = -1.0 ;
00946     }
00947     hawki_step_detect_obj_output.pixscale = -1.0;
00948 }
00949 
00950 static void hawki_step_detect_obj_get_pscale
00951 (cpl_frameset * combframes)
00952 {
00953     cpl_propertylist  * plist;
00954     cpl_frame         * firstframe;
00955     cpl_errorstate      error_prevstate = cpl_errorstate_get();
00956     
00957     /* Get the header infos */
00958     firstframe = cpl_frameset_get_frame(combframes, 0) ;
00959     plist=cpl_propertylist_load(cpl_frame_get_filename(firstframe), 0) ;
00960     hawki_step_detect_obj_output.pixscale = hawki_pfits_get_pixscale(plist);
00961     cpl_propertylist_delete(plist) ;
00962     if(!cpl_errorstate_is_equal(error_prevstate))
00963     {
00964         cpl_msg_error(__func__, "Missing PIXSCALE keyword in FITS header") ;
00965         cpl_errorstate_set(CPL_ERROR_NONE);
00966         return;
00967     }
00968 }
00969