HAWKI Pipeline Reference Manual 1.8.1

hawki_step_detect_obj.c

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