hawki_cal_flat.c

00001 /* $Id: hawki_cal_flat.c,v 1.23 2010/08/10 09:39:39 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: 2010/08/10 09:39:39 $
00024  * $Revision: 1.23 $
00025  * $Name: hawki-1_8_0 $
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 <string.h>
00038 #include <cpl.h>
00039 
00040 #include "irplib_utils.h"
00041 
00042 #include "hawki_utils.h"
00043 #include "hawki_image_stats.h"
00044 #include "hawki_load.h"
00045 #include "hawki_save.h"
00046 #include "hawki_pfits.h"
00047 #include "hawki_dfs.h"
00048 
00049 /*-----------------------------------------------------------------------------
00050                             Functions prototypes
00051  -----------------------------------------------------------------------------*/
00052 
00053 static int hawki_cal_flat_create(cpl_plugin *) ;
00054 static int hawki_cal_flat_exec(cpl_plugin *) ;
00055 static int hawki_cal_flat_destroy(cpl_plugin *) ;
00056 static int hawki_cal_flat(cpl_parameterlist *, cpl_frameset *) ;
00057 
00058 static int hawki_cal_flat_retrieve_input_param
00059 (cpl_parameterlist  *  parlist);
00060 static cpl_imagelist ** hawki_cal_flat_reduce(
00061         cpl_frameset    *   flatframes,
00062         const char      *   dark_file,
00063         cpl_table       **  raw_flat_stats,
00064         cpl_table       **  raw_flat_odd_column_stats,
00065         cpl_table       **  raw_flat_even_column_stats,
00066         cpl_table       **  raw_flat_odd_row_stats,
00067         cpl_table       **  raw_flat_even_row_stats,
00068         cpl_vector      **  selected); 
00069 static int hawki_cal_flat_clean_outliers(cpl_image *, cpl_imagelist *,
00070         cpl_imagelist *, cpl_vector *, cpl_image **) ;
00071 static int hawki_cal_flat_save
00072 (cpl_imagelist     ** flat,
00073  cpl_table         ** raw_flat_stats,
00074  cpl_table         ** raw_flat_odd_column_stats,
00075  cpl_table         ** raw_flat_even_column_stats,
00076  cpl_table         ** raw_flat_odd_row_stats,
00077  cpl_table         ** raw_flat_even_row_stats,
00078  cpl_vector        ** raw_selected,
00079  int                  set_nb,
00080  const cpl_frame   *  bpmdark,
00081  cpl_frameset      *  flatframes,
00082  cpl_frameset      *  calibframes,
00083  cpl_parameterlist *  parlist,
00084  cpl_frameset      *  set_tot);
00085 static int hawki_cal_flat_compare(const cpl_frame *, const cpl_frame *) ;
00086 static cpl_imagelist * hawki_cal_flat_merge_bpms
00087 (const cpl_frame *   bpm_orig,
00088  cpl_imagelist   *   bpm_to_add);
00089 static int hawki_cal_flat_select
00090 (cpl_vector  *   meds,
00091  cpl_vector  *   rms,
00092  int             auto_flag,
00093  int             auto_max_bins,
00094  double          min_level,
00095  double          max_level,
00096  double          max_rms,
00097  int             min_nframes,
00098  cpl_vector  *   selection);
00099 static cpl_vector * hawki_cal_flat_extract_vector(cpl_vector *,
00100         cpl_vector *) ;
00101 
00102 /*-----------------------------------------------------------------------------
00103                             Static variables
00104  -----------------------------------------------------------------------------*/
00105 
00106 static struct {
00107     /* Inputs */
00108     int         llx ;
00109     int         lly ;
00110     int         urx ;
00111     int         ury ;
00112     int         normalise ;
00113     int         second_pass ;
00114     double      sigma_badres ;
00115     double      sigma_bpm ;
00116     double      lowval_bpm ;
00117     double      highval_bpm ;
00118     int         select_auto ;
00119     int         select_auto_max_bins;
00120     double      select_min_level[HAWKI_NB_DETECTORS];
00121     double      select_max_level[HAWKI_NB_DETECTORS];
00122     double      select_max_rms[HAWKI_NB_DETECTORS];
00123     int         select_min_nframes ;
00124     int         extra_stats;
00125 } hawki_cal_flat_config ;
00126 
00127 static struct {
00128     /* Outputs */
00129     int         nb_badpix[HAWKI_NB_DETECTORS];
00130     double      norm[HAWKI_NB_DETECTORS];
00131     double      med_stdev[HAWKI_NB_DETECTORS];
00132     double      med_avg[HAWKI_NB_DETECTORS];
00133     double      med_med[HAWKI_NB_DETECTORS];
00134     double      med_min[HAWKI_NB_DETECTORS];
00135     double      med_max[HAWKI_NB_DETECTORS];
00136 } hawki_cal_flat_outputs;
00137 
00138 static char hawki_cal_flat_description[] = 
00139 "hawki_cal_flat -- HAWKĪI imaging flat-field creation from twillight images.\n"
00140 "The input of the recipe files listed in the Set Of Frames (sof-file)\n"
00141 "must be tagged as:\n"
00142 "raw-file.fits "HAWKI_CAL_FLAT_RAW" or\n"
00143 "Optional inputs are:\n"
00144 "bpmdark-file.fits "HAWKI_CALPRO_BPM_HOT"\n"
00145 "dark-file.fits "HAWKI_CALPRO_DARK"\n"
00146 "dark_err-file.fits "HAWKI_CALPRO_DARK_ERR"\n"
00147 "The recipe creates as an output:\n"
00148 "hawki_cal_flat_setxx.fits ("HAWKI_CALPRO_FLAT"): Master flat for filter xx\n"
00149 "hawki_cal_flat_err_setxx.fits ("HAWKI_CALPRO_FLAT_ERRMAP"): Master flat residuals\n"
00150 "hawki_cal_flat_bpmflat_setxx.fits ("HAWKI_CALPRO_BPM_COLD"): BPM from the flat\n"
00151 "hawki_cal_flat_stats_setxx.fits ("HAWKI_CALPRO_FLAT_STATS"): Stats of the individual flats\n"
00152 "Optionally it also creates:\n"
00153 "hawki_cal_flat_bpm_setxx.fits ("HAWKI_CALPRO_BPM"): Bad pixel mask combining bpm from dark and flat\n"
00154 "hawki_cal_flat_stats_ec_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_EVEN_COL"): Stats of the individual flats for even columns\n"
00155 "hawki_cal_flat_stats_oc_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_ODD_COL"): Stats of the individual flats for odd columns\n"
00156 "hawki_cal_flat_stats_er_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_EVEN_ROW"): Stats of the individual flats for even rows\n"
00157 "hawki_cal_flat_stats_or_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_ODD_ROW"): Stats of the individual flats for odd rows\n"
00158 "Return code:\n"
00159 "esorex exits with an error code of 0 if the recipe completes successfully\n"
00160 "or 1 otherwise";
00161 
00162 
00163 
00164 
00165 
00166 /*-----------------------------------------------------------------------------
00167                                 Functions code
00168  -----------------------------------------------------------------------------*/
00169 
00170 /*----------------------------------------------------------------------------*/
00178 /*----------------------------------------------------------------------------*/
00179 int cpl_plugin_get_info(cpl_pluginlist * list)
00180 {
00181     cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
00182     cpl_plugin  *   plugin = &recipe->interface ;
00183 
00184     cpl_plugin_init(plugin,
00185                     CPL_PLUGIN_API,
00186                     HAWKI_BINARY_VERSION,
00187                     CPL_PLUGIN_TYPE_RECIPE,
00188                     "hawki_cal_flat",
00189                     "Twillight flat recipe",
00190                     hawki_cal_flat_description,
00191                     "Cesar Enrique Garcia Dabo",
00192                     PACKAGE_BUGREPORT,  
00193                     hawki_get_license(),
00194                     hawki_cal_flat_create,
00195                     hawki_cal_flat_exec,
00196                     hawki_cal_flat_destroy) ;
00197 
00198     cpl_pluginlist_append(list, plugin) ;
00199     
00200     return 0;
00201 }
00202 
00203 /*----------------------------------------------------------------------------*/
00212 /*----------------------------------------------------------------------------*/
00213 static int hawki_cal_flat_create(cpl_plugin * plugin)
00214 {
00215     cpl_recipe      * recipe ;
00216     cpl_parameter   * p ;
00217 
00218     /* Get the recipe out of the plugin */
00219     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00220         recipe = (cpl_recipe *)plugin ;
00221     else return -1 ;
00222 
00223     /* Create the parameters list in the cpl_recipe object */
00224     recipe->parameters = cpl_parameterlist_new() ;
00225 
00226     /* Fill the parameters list */
00227     /* --zone */
00228     p = cpl_parameter_new_value("hawki.hawki_cal_flat.zone",
00229                                 CPL_TYPE_STRING,
00230                                 "Stats zone",
00231                                 "hawki.hawki_cal_flat",
00232                                 "1,1,2048,2048") ;
00233     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "zone") ;
00234     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00235     cpl_parameterlist_append(recipe->parameters, p) ;
00236 
00237     /* --normalise */
00238     p = cpl_parameter_new_value("hawki.hawki_cal_flat.normalise",
00239             CPL_TYPE_BOOL, "Flag to apply the normalisation",
00240             "hawki.hawki_cal_flat", FALSE) ;
00241     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "normalise") ;
00242     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00243     cpl_parameterlist_append(recipe->parameters, p) ;
00244 
00245     /* --second_pass */
00246     p = cpl_parameter_new_value("hawki.hawki_cal_flat.second_pass",
00247             CPL_TYPE_BOOL, "Flag to apply a second pass computation",
00248             "hawki.hawki_cal_flat", TRUE) ;
00249     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "second_pass") ;
00250     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00251     cpl_parameterlist_append(recipe->parameters, p) ;
00252 
00253     /* --sigma_badres */
00254     p = cpl_parameter_new_value("hawki.hawki_cal_flat.sigma_badres",
00255             CPL_TYPE_DOUBLE, "sigma for detection of bad flat results",
00256             "hawki.hawki_cal_flat", 1.0) ;
00257     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_badres") ;
00258     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00259     cpl_parameterlist_append(recipe->parameters, p) ;
00260 
00261     /* --sigma_bpm */
00262     p = cpl_parameter_new_value("hawki.hawki_cal_flat.sigma_bpm",
00263             CPL_TYPE_DOUBLE, "sigma for detection of bad pixels",
00264             "hawki.hawki_cal_flat", 10.0) ;
00265     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_bpm") ;
00266     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00267     cpl_parameterlist_append(recipe->parameters, p) ;
00268  
00269     /* --lowval_bpm */
00270     p = cpl_parameter_new_value("hawki.hawki_cal_flat.lowval_bpm",
00271             CPL_TYPE_DOUBLE, "values of the flat below this will be included "
00272             "in the bpm. In units of final flat (normalised if normalise is on)",
00273             "hawki.hawki_cal_flat", .1) ;
00274     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lowval_bpm") ;
00275     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00276     cpl_parameterlist_append(recipe->parameters, p) ;
00277  
00278     /* --highval_bpm */
00279     p = cpl_parameter_new_value("hawki.hawki_cal_flat.highval_bpm",
00280             CPL_TYPE_DOUBLE, "values of the flat above this will be included "
00281             "in the bpm. In units of final flat (normalized if normalise is on)",
00282             "hawki.hawki_cal_flat", 10.0) ;
00283     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "highval_bpm") ;
00284     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00285     cpl_parameterlist_append(recipe->parameters, p) ;
00286  
00287     /* --select_auto */
00288     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_auto",
00289             CPL_TYPE_BOOL, "Flag to automatically select the good input frames",
00290             "hawki.hawki_cal_flat", TRUE);
00291     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_auto") ;
00292     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00293     cpl_parameterlist_append(recipe->parameters, p) ;
00294 
00295     /* --select_auto_max_bins */
00296     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_auto_max_bins",
00297             CPL_TYPE_INT, "Maximum number of frames requested",
00298             "hawki.hawki_cal_flat", 10) ;
00299     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_auto_max_bins");
00300     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00301     cpl_parameterlist_append(recipe->parameters, p) ;
00302  
00303     /* --select_min_level */
00304     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_min_level",
00305             CPL_TYPE_STRING, "Minimum ADU level for frames selection",
00306             "hawki.hawki_cal_flat", "-1.0") ;
00307     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_min_level") ;
00308     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00309     cpl_parameterlist_append(recipe->parameters, p) ;
00310  
00311     /* --select_max_level */
00312     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_max_level",
00313             CPL_TYPE_STRING, "Maximum ADU level for frames selection",
00314             "hawki.hawki_cal_flat", "25000");
00315     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_max_level");
00316     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00317     cpl_parameterlist_append(recipe->parameters, p);
00318  
00319     /* --select_max_rms */
00320     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_max_rms",
00321             CPL_TYPE_STRING, "Maximum RMS for frames selection",
00322             "hawki.hawki_cal_flat", "4000");
00323     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_max_rms");
00324     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00325     cpl_parameterlist_append(recipe->parameters, p);
00326  
00327     /* --select_min_nframes */
00328     p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_min_nframes",
00329             CPL_TYPE_INT, "Minimum number of frames requested",
00330             "hawki.hawki_cal_flat", 3);
00331     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_min_nframes") ;
00332     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00333     cpl_parameterlist_append(recipe->parameters, p) ;
00334  
00335     /* --extra_stats */
00336     p = cpl_parameter_new_value("hawki.hawki_cal_flat.extra_stats",
00337             CPL_TYPE_BOOL, "Request for even/odd column/rows statistics",
00338             "hawki.hawki_cal_flat", FALSE) ;
00339     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extra_stats") ;
00340     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00341     cpl_parameterlist_append(recipe->parameters, p) ;
00342 
00343     /* Return */
00344     return 0;
00345 }
00346 
00347 /*----------------------------------------------------------------------------*/
00353 /*----------------------------------------------------------------------------*/
00354 static int hawki_cal_flat_exec(cpl_plugin * plugin)
00355 {
00356     cpl_recipe  *   recipe ;
00357 
00358     /* Get the recipe out of the plugin */
00359     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00360         recipe = (cpl_recipe *)plugin ;
00361     else return -1 ;
00362 
00363     /* Issue a banner */
00364     hawki_print_banner();
00365 
00366     return hawki_cal_flat(recipe->parameters, recipe->frames) ;
00367 }
00368 
00369 /*----------------------------------------------------------------------------*/
00375 /*----------------------------------------------------------------------------*/
00376 static int hawki_cal_flat_destroy(cpl_plugin * plugin)
00377 {
00378     cpl_recipe  *   recipe ;
00379 
00380     /* Get the recipe out of the plugin */
00381     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00382         recipe = (cpl_recipe *)plugin ;
00383     else return -1 ;
00384 
00385     cpl_parameterlist_delete(recipe->parameters) ;
00386     return 0 ;
00387 }
00388 
00389 /*----------------------------------------------------------------------------*/
00396 /*----------------------------------------------------------------------------*/
00397 static int hawki_cal_flat(
00398         cpl_parameterlist   *   parlist, 
00399         cpl_frameset        *   framelist)
00400 {
00401     int             *   labels ;
00402     int                 nlabels ;
00403     cpl_frameset    *   flatframes ;
00404     int                 nflats;
00405     const char      *   dark ;
00406     const char      *   dark_err;
00407     const cpl_frame *   bpmdark ;
00408     cpl_imagelist   **  twflat ;
00409     cpl_table       **  raw_flat_stats;
00410     cpl_table       **  raw_flat_odd_column_stats = NULL;
00411     cpl_table       **  raw_flat_even_column_stats = NULL;
00412     cpl_table       **  raw_flat_odd_row_stats = NULL;
00413     cpl_table       **  raw_flat_even_row_stats = NULL;
00414     cpl_vector      **  raw_selected;
00415     int                 i, j ;
00416     cpl_errorstate      error_prevstate = cpl_errorstate_get();
00417     
00418     /* Retrieve input parameters */
00419     if(hawki_cal_flat_retrieve_input_param(parlist))
00420     {
00421         cpl_msg_error(__func__, "Wrong parameters");
00422         return -1;
00423     }
00424     
00425     /* Identify the RAW and CALIB frames in the input frameset */
00426     if (hawki_dfs_set_groups(framelist)) {
00427         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00428         return -1;
00429     }
00430 
00431     /* Retrieve raw frames */
00432     if ((flatframes = hawki_extract_frameset(framelist,
00433                     HAWKI_CAL_FLAT_RAW)) == NULL) {
00434         cpl_msg_error(__func__, "Cannot find flat frames in the input list (%s)",
00435                       HAWKI_CAL_FLAT_RAW);
00436         return -1 ;
00437     }
00438 
00439     /* Retrieve calibration frames */
00440     bpmdark = cpl_frameset_find_const(framelist, HAWKI_CALPRO_BPM_HOT);
00441     dark = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK);
00442     dark_err = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK_ERR);
00443 
00444     /* Labelise all input flat frames */
00445     labels = cpl_frameset_labelise(flatframes, hawki_cal_flat_compare, 
00446                 &nlabels);
00447     if (labels == NULL) {
00448         cpl_msg_error(__func__, "Cannot labelise input frames") ;
00449         cpl_frameset_delete(flatframes);
00450         return -1;
00451     }
00452    
00453     /* Extract sets and reduce each of them */
00454     for (i=0 ; i<nlabels ; i++) 
00455     {
00456         cpl_frameset    *   this_filter_flats;
00457         
00458         /* Reduce data set nb i */
00459         cpl_msg_info(__func__, "Reduce data set no %d out of %d", i+1, nlabels);
00460         cpl_msg_indent_more() ;
00461         this_filter_flats = cpl_frameset_extract(flatframes, labels, i) ;
00462         nflats = cpl_frameset_get_size(this_filter_flats);
00463         
00464         /* Allocate and initialize statistics */
00465         raw_flat_stats = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*));
00466         raw_selected = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_vector*));
00467         for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00468         {
00469             raw_selected[j] = cpl_vector_new(nflats);
00470             raw_flat_stats[j] = cpl_table_new(nflats);
00471         }
00472         /* Initialize the statistics table */
00473         hawki_image_stats_initialize(raw_flat_stats);
00474         if(hawki_cal_flat_config.extra_stats)
00475         {
00476             raw_flat_odd_column_stats = 
00477                 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*));
00478             raw_flat_even_column_stats = 
00479                 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*));
00480             raw_flat_odd_row_stats = 
00481                 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*));
00482             raw_flat_even_row_stats = 
00483                 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*));
00484             for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00485             {
00486                 raw_flat_odd_column_stats[j] = cpl_table_new(nflats);
00487                 raw_flat_even_column_stats[j] = cpl_table_new(nflats);
00488                 raw_flat_odd_row_stats[j] = cpl_table_new(nflats);
00489                 raw_flat_even_row_stats[j] = cpl_table_new(nflats);
00490             }
00491             /* Initialize the statistics table */
00492             hawki_image_stats_initialize(raw_flat_odd_column_stats);
00493             hawki_image_stats_initialize(raw_flat_even_column_stats);
00494             hawki_image_stats_initialize(raw_flat_odd_row_stats);
00495             hawki_image_stats_initialize(raw_flat_even_row_stats);
00496         }
00497 
00498         /* Reduce */
00499         if ((twflat = hawki_cal_flat_reduce
00500                 (this_filter_flats, 
00501                  dark,
00502                  raw_flat_stats,
00503                  raw_flat_odd_column_stats,
00504                  raw_flat_even_column_stats,
00505                  raw_flat_odd_row_stats,
00506                  raw_flat_even_row_stats,
00507                  raw_selected)) == NULL) 
00508         {
00509             for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00510             {
00511                 cpl_table_delete(raw_flat_stats[j]);
00512                 cpl_vector_delete(raw_selected[j]);
00513             }
00514             cpl_free(raw_flat_stats);
00515             cpl_free(raw_selected);
00516             if(hawki_cal_flat_config.extra_stats)
00517             {
00518                 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00519                 {
00520                     cpl_table_delete(raw_flat_odd_column_stats[j]);
00521                     cpl_table_delete(raw_flat_even_column_stats[j]);
00522                     cpl_table_delete(raw_flat_odd_row_stats[j]);
00523                     cpl_table_delete(raw_flat_even_row_stats[j]);
00524                 }
00525                 cpl_free(raw_flat_odd_column_stats);
00526                 cpl_free(raw_flat_even_column_stats);
00527                 cpl_free(raw_flat_odd_row_stats);
00528                 cpl_free(raw_flat_even_row_stats);
00529             }
00530             cpl_frameset_delete(this_filter_flats);
00531             cpl_frameset_delete(flatframes);
00532             cpl_free(labels);
00533             cpl_msg_error(__func__, "Cannot reduce set nb %d", i+1) ;
00534             return 1;
00535 
00536         } else {
00537             /* Save the products */
00538             cpl_frameset    *   calib_frames;
00539 
00540             cpl_msg_info(__func__, "Save the products") ;
00541             calib_frames = cpl_frameset_new();
00542             if(bpmdark)
00543                 cpl_frameset_insert(calib_frames, cpl_frame_duplicate(bpmdark));
00544             if(dark)
00545                 cpl_frameset_insert(calib_frames,
00546                         cpl_frame_duplicate(cpl_frameset_find_const(framelist, 
00547                                 HAWKI_CALPRO_DARK)));
00548             if(dark_err)
00549                 cpl_frameset_insert(calib_frames,
00550                         cpl_frame_duplicate(cpl_frameset_find_const(framelist, 
00551                                 HAWKI_CALPRO_DARK_ERR)));
00552             hawki_cal_flat_save
00553                 (twflat, raw_flat_stats, 
00554                  raw_flat_odd_column_stats,
00555                  raw_flat_even_column_stats,
00556                  raw_flat_odd_row_stats,
00557                  raw_flat_even_row_stats,
00558                  raw_selected,
00559                  i+1, bpmdark, this_filter_flats, calib_frames, 
00560                  parlist, framelist);
00561             cpl_imagelist_delete(twflat[0]);
00562             cpl_imagelist_delete(twflat[1]);
00563             cpl_imagelist_delete(twflat[2]);
00564             if (hawki_cal_flat_config.second_pass)
00565                 cpl_imagelist_delete(twflat[3]);
00566             cpl_free(twflat);
00567             for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00568             {
00569                 cpl_table_delete(raw_flat_stats[j]);
00570                 cpl_vector_delete(raw_selected[j]);
00571             }
00572             cpl_free(raw_flat_stats);
00573             cpl_free(raw_selected);
00574             if(hawki_cal_flat_config.extra_stats)
00575             {
00576                 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++)
00577                 {
00578                     cpl_table_delete(raw_flat_odd_column_stats[j]);
00579                     cpl_table_delete(raw_flat_even_column_stats[j]);
00580                     cpl_table_delete(raw_flat_odd_row_stats[j]);
00581                     cpl_table_delete(raw_flat_even_row_stats[j]);
00582                 }
00583                 cpl_free(raw_flat_odd_column_stats);
00584                 cpl_free(raw_flat_even_column_stats);
00585                 cpl_free(raw_flat_odd_row_stats);
00586                 cpl_free(raw_flat_even_row_stats);
00587             }
00588             cpl_frameset_delete(calib_frames);            
00589         }
00590         cpl_msg_indent_less();
00591         cpl_frameset_delete(this_filter_flats);
00592     }
00593     
00594     if(!cpl_errorstate_is_equal(error_prevstate))
00595         cpl_msg_warning(__func__,"Probably some data could not be saved. "
00596                                  "Check permisions or disk space");
00597     
00598     
00599     /* Free and return */
00600     cpl_frameset_delete(flatframes);
00601     cpl_free(labels); 
00602 
00603     /* Return */
00604     if (cpl_error_get_code()) return -1 ;
00605     else return 0;
00606 }
00607 
00608 /*----------------------------------------------------------------------------*/
00619 /*----------------------------------------------------------------------------*/
00620 static cpl_imagelist ** hawki_cal_flat_reduce(
00621         cpl_frameset    *   flatframes,
00622         const char      *   dark_file,
00623         cpl_table       **  raw_flat_stats,
00624         cpl_table       **  raw_flat_odd_column_stats,
00625         cpl_table       **  raw_flat_even_column_stats,
00626         cpl_table       **  raw_flat_odd_row_stats,
00627         cpl_table       **  raw_flat_even_row_stats,
00628         cpl_vector      **  selected) 
00629 {
00630     int                     nima ;
00631     cpl_image           *   ima_cur ;
00632     cpl_image           *   big_ima ;
00633     cpl_image           *   big_badres ;
00634     cpl_vector          *   medians[HAWKI_NB_DETECTORS];
00635     cpl_vector          *   stdevs[HAWKI_NB_DETECTORS];
00636     cpl_vector          *   sub_medians ;
00637     cpl_imagelist       *   in_quad ;
00638     cpl_imagelist       **  results ;
00639     cpl_imagelist       *   res_quad[4] ;
00640     cpl_image           *   err_quad[4] ;
00641     cpl_image           *   badres_mask[4] ;
00642     cpl_image           *   flat_image ;
00643     cpl_image           *   dark ;
00644     cpl_propertylist    *   plist;
00645     double                  gradient ;
00646     double                  flat_dit;
00647     cpl_image           *   bpmflat;
00648     int                     j, k ;
00649     int                     idet;
00650 
00651     /* Test entries */
00652     if (flatframes == NULL) return NULL ;
00653 
00654     /* Initialise */
00655     nima = cpl_frameset_get_size(flatframes) ;
00656     if (nima < 3) {
00657         cpl_msg_error(__func__, "Not enough frames (%d)", nima) ;
00658         return NULL ;
00659     }
00660     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00661         hawki_cal_flat_outputs.norm[idet] = 1.0 ;
00662     
00663     /* Compute statistics */
00664     cpl_msg_info(__func__, "Compute statistics") ;
00665     cpl_msg_indent_more() ;
00666     /* Loop on the HAWKI_NB_DETECTORS chips */
00667     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00668     {
00669 
00670         /* Compute some stats on input images */
00671         cpl_msg_info(__func__, "Chip number %d", idet+1) ;
00672         cpl_msg_info(__func__, "image      min        max        med     rms") ;
00673         cpl_msg_info(__func__, "--------------------------------------------") ;
00674         medians[idet] = cpl_vector_new(nima);
00675         stdevs[idet] = cpl_vector_new(nima);
00676         for (j=0 ; j<nima ; j++)
00677         {
00678             /* Load the image */
00679             ima_cur = hawki_load_image(flatframes, j, idet+1, CPL_TYPE_FLOAT) ;
00680 
00681             /* Compute the stats */
00682             if(hawki_image_stats_fill_from_image
00683                 (raw_flat_stats,
00684                  ima_cur,
00685                  hawki_cal_flat_config.llx,
00686                  hawki_cal_flat_config.lly,
00687                  hawki_cal_flat_config.urx,
00688                  hawki_cal_flat_config.ury,
00689                  idet,
00690                  j) !=0 )
00691             {
00692                 cpl_msg_error(__func__, "Cannot compute stats on image %d",j+1);
00693                 cpl_msg_indent_less() ;
00694                 cpl_image_delete(ima_cur);
00695                 for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ;
00696                 for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ;
00697                 return NULL ;
00698             }
00699             
00700             if(hawki_cal_flat_config.extra_stats)
00701             {
00702                 if(hawki_image_stats_odd_even_column_row_fill_from_image
00703                         (raw_flat_odd_column_stats,
00704                          raw_flat_even_column_stats,
00705                          raw_flat_odd_row_stats,
00706                          raw_flat_even_row_stats,
00707                          ima_cur,
00708                          idet,
00709                          j) !=0 )
00710                 {
00711                     cpl_msg_error(__func__, "Cannot compute extra stats");
00712                     cpl_msg_indent_less() ;
00713                     cpl_image_delete(ima_cur);
00714                     for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ;
00715                     for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ;
00716                     return NULL ;
00717                 }
00718             }
00719             cpl_vector_set(medians[idet], j, cpl_table_get_double
00720                            (raw_flat_stats[idet],HAWKI_COL_STAT_MED,j,NULL )) ;
00721             cpl_vector_set(stdevs[idet], j, cpl_table_get_double
00722                            (raw_flat_stats[idet],HAWKI_COL_STAT_RMS,j,NULL )) ;
00723             cpl_msg_info(__func__, "%02d   %10.2f %10.2f %10.2f %10.2f",
00724                     j+1,
00725                     cpl_table_get_double(raw_flat_stats[idet],
00726                                          HAWKI_COL_STAT_MIN,j,NULL ),
00727                     cpl_table_get_double(raw_flat_stats[idet],
00728                                          HAWKI_COL_STAT_MAX,j,NULL ),
00729                     cpl_table_get_double(raw_flat_stats[idet],
00730                                          HAWKI_COL_STAT_MED,j,NULL ),
00731                     cpl_table_get_double(raw_flat_stats[idet],
00732                                          HAWKI_COL_STAT_RMS,j,NULL ));
00733             if (cpl_table_get_double
00734                     (raw_flat_stats[idet],HAWKI_COL_STAT_MED,j,NULL ) < 1e-6) 
00735             {
00736                 cpl_msg_error(__func__, "image %d has negative flux: aborting", 
00737                         j+1) ;
00738                 cpl_msg_indent_less() ;
00739                 for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ;
00740                 for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ;
00741                 return NULL ;
00742             }
00743             cpl_image_delete(ima_cur);
00744         }
00745         cpl_msg_info(__func__, "--------------------------------------------") ;
00746 
00747         /* Compute min max stdev and mean of the medians */
00748         hawki_cal_flat_outputs.med_min[idet]   = 
00749             cpl_vector_get_min(medians[idet]);
00750         hawki_cal_flat_outputs.med_max[idet]   = 
00751             cpl_vector_get_max(medians[idet]);
00752         hawki_cal_flat_outputs.med_avg[idet]   = 
00753             cpl_vector_get_mean(medians[idet]);
00754         hawki_cal_flat_outputs.med_med[idet]   =
00755             cpl_vector_get_median_const(medians[idet]);
00756         hawki_cal_flat_outputs.med_stdev[idet] = 
00757             cpl_vector_get_stdev(medians[idet]);
00758         
00759         /* See if flux gradient is large enough for a correct fit */
00760         gradient=fabs(hawki_cal_flat_outputs.med_max[idet]/ 
00761                 hawki_cal_flat_outputs.med_min[idet]) ;
00762         if (gradient < 4.0) {
00763             /* cpl_msg_warning(__func__, "Low flux gradient: %g", gradient) ;*/
00764         }
00765     }
00766     cpl_msg_indent_less() ;
00767     
00768     /* Allocate for results */
00769     results = cpl_malloc(4 * sizeof(cpl_imagelist*)) ;
00770     results[0] = cpl_imagelist_new() ;
00771     results[1] = cpl_imagelist_new() ;
00772     results[2] = cpl_imagelist_new() ;
00773     if (hawki_cal_flat_config.second_pass)  results[3] = cpl_imagelist_new() ; 
00774     else                                    results[3] = NULL ;
00775 
00776     cpl_msg_info(__func__, "Compute the flat") ;
00777     cpl_msg_indent_more() ;
00778     /* Loop on the HAWKI_NB_DETECTORS chips */
00779     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) {
00780         cpl_msg_info(__func__, "Chip number %d", idet+1) ;
00781         cpl_msg_indent_more() ;
00782        
00783         /* Frames selection */
00784         cpl_msg_info(__func__, "Apply the frames selection");
00785         if ((hawki_cal_flat_select(medians[idet], 
00786                                    stdevs[idet],
00787                                    hawki_cal_flat_config.select_auto,
00788                                    hawki_cal_flat_config.select_auto_max_bins,
00789                                    hawki_cal_flat_config.select_min_level[idet],
00790                                    hawki_cal_flat_config.select_max_level[idet],
00791                                    hawki_cal_flat_config.select_max_rms[idet],
00792                                    hawki_cal_flat_config.select_min_nframes,
00793                                    selected[idet])) == -1)
00794         {
00795             cpl_msg_error(__func__, "Cannot apply the frames selection") ;
00796             cpl_imagelist_delete(results[0]) ;
00797             cpl_imagelist_delete(results[1]) ;
00798             cpl_imagelist_delete(results[2]) ;
00799             if (hawki_cal_flat_config.second_pass) 
00800                 cpl_imagelist_delete(results[3]) ;
00801             cpl_free(results) ;
00802             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00803                 cpl_vector_delete(medians[k]) ;
00804             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00805                 cpl_vector_delete(stdevs[k]) ;
00806             return NULL ;
00807         }
00808 
00809         /* Apply the medians subselection */
00810         sub_medians = hawki_cal_flat_extract_vector
00811             (medians[idet], selected[idet]) ;
00812 
00813         /* Loop on the 4 quadrants */
00814         for (j=0 ; j<4 ; j++) {
00815             /* Load input image chips */
00816             if ((in_quad = hawki_load_quadrants(flatframes, idet+1, j+1, 
00817                             CPL_TYPE_FLOAT))==NULL) {
00818                 cpl_msg_error(__func__, "Cannot load the raw quadrants") ;
00819                 cpl_imagelist_delete(results[0]) ;
00820                 cpl_imagelist_delete(results[1]) ;
00821                 cpl_imagelist_delete(results[2]) ;
00822                 if (hawki_cal_flat_config.second_pass) 
00823                     cpl_imagelist_delete(results[3]) ;
00824                 cpl_free(results) ;
00825                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00826                     cpl_vector_delete(medians[k]) ;
00827                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00828                     cpl_vector_delete(stdevs[k]) ;
00829                 cpl_vector_delete(sub_medians) ;
00830                 return NULL ;
00831             }
00832        
00833             /* Apply subselection of the frames */
00834             cpl_imagelist_erase(in_quad, selected[idet]);
00835 
00836             /* Apply dark correction to all planes if requested */
00837             if (dark_file) {
00838                 if (j==0) cpl_msg_info(__func__, "Subtracting dark") ;
00839                 /* Load dark */
00840                 if ((dark = hawki_load_quadrant_from_file(dark_file,
00841                                 idet+1, j+1, CPL_TYPE_FLOAT)) == NULL) {
00842                     cpl_msg_error(__func__, "Cannot load the dark quadrants") ;
00843                     cpl_imagelist_delete(in_quad) ;
00844                     cpl_imagelist_delete(results[0]) ;
00845                     cpl_imagelist_delete(results[1]) ;
00846                     cpl_imagelist_delete(results[2]) ;
00847                     if (hawki_cal_flat_config.second_pass) 
00848                         cpl_imagelist_delete(results[3]) ;
00849                     cpl_free(results) ;
00850                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00851                         cpl_vector_delete(medians[k]) ;
00852                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00853                         cpl_vector_delete(stdevs[k]) ;
00854                     cpl_vector_delete(sub_medians) ;
00855                     return NULL ;
00856                 }
00857 
00858                 /* Multiply by the dit */
00859                 if ((plist=cpl_propertylist_load
00860                         (cpl_frame_get_filename
00861                          (cpl_frameset_get_first_const(flatframes)), 0)) == NULL) 
00862                 {
00863                     cpl_msg_error(__func__, "Cannot get header from frame");
00864                     cpl_imagelist_delete(in_quad) ;
00865                     cpl_imagelist_delete(results[0]) ;
00866                     cpl_imagelist_delete(results[1]) ;
00867                     cpl_imagelist_delete(results[2]) ;
00868                     if (hawki_cal_flat_config.second_pass) 
00869                         cpl_imagelist_delete(results[3]) ;
00870                     cpl_free(results) ;
00871                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00872                         cpl_vector_delete(medians[k]) ;
00873                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00874                         cpl_vector_delete(stdevs[k]) ;
00875                     cpl_vector_delete(sub_medians) ;
00876                     cpl_image_delete(dark);
00877                     return NULL ;
00878                 }
00879                 flat_dit = hawki_pfits_get_dit(plist);
00880                 cpl_image_multiply_scalar(dark, flat_dit);
00881                 cpl_propertylist_delete(plist);
00882 
00883                 /* Dark correction */
00884                 cpl_imagelist_subtract_image(in_quad, dark) ;
00885                 cpl_image_delete(dark) ;
00886                 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00887                     cpl_msg_warning(__func__,"Cannot subtract the dark frame");
00888                     cpl_error_reset() ;
00889                 }
00890             }
00891         
00892             /* Fit slopes */
00893             err_quad[j] = cpl_image_duplicate(cpl_imagelist_get(in_quad, 0)) ;
00894             res_quad[j] = cpl_fit_imagelist_polynomial(sub_medians, in_quad, 
00895                     0, 1, CPL_FALSE, CPL_TYPE_FLOAT, err_quad[j]) ;
00896             if (res_quad[j] == NULL) {
00897                 cpl_msg_error(__func__, "Cannot create twilight flat-field") ;
00898                 cpl_imagelist_delete(results[0]) ;
00899                 cpl_imagelist_delete(results[1]) ;
00900                 cpl_imagelist_delete(results[2]) ;
00901                 if (hawki_cal_flat_config.second_pass) 
00902                     cpl_imagelist_delete(results[3]) ;
00903                 cpl_free(results) ;
00904                 cpl_imagelist_delete(in_quad) ;
00905                 for (k=0 ; k<j ; k++) cpl_imagelist_delete(res_quad[k]) ;
00906                 for (k=0 ; k<=j ; k++) cpl_image_delete(err_quad[k]) ;
00907                 for (k=0 ; k<j ; k++) 
00908                     if (badres_mask[k]) cpl_image_delete(badres_mask[k]) ;
00909                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00910                     cpl_vector_delete(medians[k]) ;
00911                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00912                     cpl_vector_delete(stdevs[k]) ;
00913                 cpl_vector_delete(sub_medians) ;
00914                 return NULL ;
00915             }
00916 
00917             /* Handle the pixels with a high error */
00918             badres_mask[j] = NULL ;
00919             if (hawki_cal_flat_config.second_pass) {
00920                 if (j==0) cpl_msg_info(__func__, 
00921                         "Second pass to clean the outliers") ;
00922                 if (hawki_cal_flat_clean_outliers(err_quad[j], res_quad[j],
00923                             in_quad, sub_medians, &(badres_mask[j])) == -1) {
00924                     cpl_msg_error(__func__, "Cannot clean the outliers") ;
00925                     cpl_imagelist_delete(results[0]) ;
00926                     cpl_imagelist_delete(results[1]) ;
00927                     cpl_imagelist_delete(results[2]) ;
00928                     cpl_imagelist_delete(results[3]) ;
00929                     cpl_free(results) ;
00930                     cpl_imagelist_delete(in_quad) ;
00931                     for (k=0 ; k<=j ; k++) cpl_imagelist_delete(res_quad[k]) ;
00932                     for (k=0 ; k<=j ; k++) cpl_image_delete(err_quad[k]) ;
00933                     for (k=0 ; k<=j ; k++) cpl_image_delete(badres_mask[k]) ;
00934                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00935                         cpl_vector_delete(medians[k]) ;
00936                     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00937                         cpl_vector_delete(stdevs[k]) ;
00938                     cpl_vector_delete(sub_medians) ;
00939                     cpl_msg_indent_less() ;
00940                     return NULL ;
00941                 }
00942             }
00943             cpl_imagelist_delete(in_quad) ;
00944         }
00945         cpl_vector_delete(sub_medians) ;
00946             
00947         /* Rebuild the quadrants and put in results */
00948         /* Rebuild RESULTS */
00949         big_ima = hawki_rebuild_quadrants(
00950                 cpl_imagelist_get(res_quad[0],1), 
00951                 cpl_imagelist_get(res_quad[1],1), 
00952                 cpl_imagelist_get(res_quad[2],1), 
00953                 cpl_imagelist_get(res_quad[3],1)) ;
00954         for (j=0 ; j<4 ; j++) cpl_imagelist_delete(res_quad[j]) ;
00955         cpl_imagelist_set(results[0], big_ima, idet) ;
00956         if (big_ima == NULL) {
00957             cpl_msg_error(__func__, "Cannot rebuild the image") ;
00958             cpl_imagelist_delete(results[0]) ;
00959             cpl_imagelist_delete(results[1]) ;
00960             cpl_imagelist_delete(results[2]) ;
00961             if (hawki_cal_flat_config.second_pass) 
00962                 cpl_imagelist_delete(results[3]) ;
00963             cpl_free(results) ;
00964             for (j=0 ; j<4 ; j++) cpl_image_delete(err_quad[j]) ;
00965             for (j=0 ; j<4 ; j++) 
00966                 if (badres_mask[j]) cpl_image_delete(badres_mask[j]) ;
00967             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00968                 cpl_vector_delete(medians[k]) ;
00969             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00970                 cpl_vector_delete(stdevs[k]) ;
00971             return NULL ;
00972         }
00973 
00974         /* Rebuild ERROR */
00975         big_ima = hawki_rebuild_quadrants(err_quad[0], err_quad[1], 
00976                 err_quad[2], err_quad[3]) ;
00977         for (j=0 ; j<4 ; j++) cpl_image_delete(err_quad[j]) ;
00978         if (big_ima == NULL) {
00979             cpl_msg_error(__func__, "Cannot rebuild the image") ;
00980             cpl_imagelist_delete(results[0]) ;
00981             cpl_imagelist_delete(results[1]) ;
00982             cpl_imagelist_delete(results[2]) ;
00983             if (hawki_cal_flat_config.second_pass) 
00984                 cpl_imagelist_delete(results[3]) ;
00985             cpl_free(results) ;
00986             for (j=0 ; j<4 ; j++) 
00987                 if (badres_mask[j]) cpl_image_delete(badres_mask[j]) ;
00988             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00989                 cpl_vector_delete(medians[k]) ;
00990             for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
00991                 cpl_vector_delete(stdevs[k]) ;
00992             return NULL ;
00993         }
00994         cpl_imagelist_set(results[1], big_ima, idet) ;
00995        
00996         /* Rebuild BADRES_MASK */
00997         big_badres = hawki_rebuild_quadrants(badres_mask[0], badres_mask[1], 
00998                 badres_mask[2], badres_mask[3]) ;
00999         if (hawki_cal_flat_config.second_pass) {
01000             for (j=0 ; j<4 ; j++) cpl_image_delete(badres_mask[j]) ;
01001             cpl_imagelist_set(results[3], big_badres, idet) ;
01002         }
01003 
01004         if (hawki_cal_flat_config.normalise) {
01005             /* Normalize gain */
01006             cpl_msg_info(__func__, "Normalise the flat") ;
01007             flat_image = cpl_imagelist_get(results[0], idet) ;
01008             hawki_cal_flat_outputs.norm[idet] = 
01009                 cpl_image_get_median(flat_image) ;
01010             cpl_image_divide_scalar
01011                 (flat_image, hawki_cal_flat_outputs.norm[idet]);
01012             if (cpl_error_get_code()) {
01013                 cpl_msg_error(__func__, "Cannot normalise") ;
01014                 cpl_imagelist_delete(results[0]) ;
01015                 cpl_imagelist_delete(results[1]) ;
01016                 cpl_imagelist_delete(results[2]) ;
01017                 if (hawki_cal_flat_config.second_pass) 
01018                     cpl_imagelist_delete(results[3]) ;
01019                 cpl_free(results) ;
01020                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
01021                     cpl_vector_delete(medians[k]) ;
01022                 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 
01023                     cpl_vector_delete(stdevs[k]) ;
01024                 return NULL ;
01025             }
01026         }
01027 
01028         /* BPM from the flat */
01029         cpl_msg_info(__func__, "Compute the BPM from the flat") ;
01030         bpmflat=hawki_compute_flatbpm(cpl_imagelist_get(results[0],idet),
01031                 hawki_cal_flat_config.sigma_bpm,
01032                 hawki_cal_flat_config.lowval_bpm, 
01033                 hawki_cal_flat_config.highval_bpm);
01034         
01035         cpl_imagelist_set(results[2], bpmflat, idet) ;
01036         hawki_cal_flat_outputs.nb_badpix[idet]=
01037             (int)cpl_image_get_flux(bpmflat);
01038 
01039         cpl_msg_indent_less() ;
01040     }
01041     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) cpl_vector_delete(medians[k]) ;
01042     for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) cpl_vector_delete(stdevs[k]) ;
01043     cpl_msg_indent_less() ;
01044 
01045     return results ;
01046 }
01047 
01048 /*----------------------------------------------------------------------------*/
01058 /*----------------------------------------------------------------------------*/
01059 static int hawki_cal_flat_clean_outliers(
01060         cpl_image           *   error,
01061         cpl_imagelist       *   fit_res,
01062         cpl_imagelist       *   raw,
01063         cpl_vector          *   medians,
01064         cpl_image           **  recomp_mask)
01065 {
01066     cpl_mask        *   recompute ;
01067     cpl_binary      *   precompute ;
01068     double              med, stdev, threshold1, threshold2 ;
01069     int                 nx, ny, pos, nbad, nima, out, ind, pix ;
01070     cpl_image       *   cur_ima ;
01071     float           *   pimaf ;
01072     double              val, fit_val, a, b, max ;
01073     cpl_vector      *   z_pix ;
01074     double          *   pz_pix ;
01075     cpl_image       *   onepix ;
01076     cpl_vector      *   med_purged ;
01077     cpl_imagelist   *   raw_purged ;
01078     cpl_imagelist   *   fit_one ;
01079     cpl_image       *   err_one ;
01080     int                 i, j, k ;
01081 
01082     /* Check entries */
01083     if (error == NULL) return -1 ;
01084     if (fit_res == NULL) return -1 ;
01085     if (raw == NULL) return -1 ;
01086 
01087     /* Initialise */
01088     if (recomp_mask) *recomp_mask = NULL ;
01089 
01090     /* Identify the places to recompute */
01091     med = cpl_image_get_median_dev(error, &stdev) ;
01092     threshold1 = med - hawki_cal_flat_config.sigma_badres * stdev ;
01093     threshold2 = med + hawki_cal_flat_config.sigma_badres * stdev ;
01094     recompute = cpl_mask_threshold_image_create(error,threshold1,threshold2) ;
01095     cpl_mask_not(recompute) ;
01096 
01097     if ((nbad=cpl_mask_count(recompute)) == 0) {
01098         if (recomp_mask)    
01099             *recomp_mask = cpl_image_new_from_mask(recompute) ;
01100         cpl_mask_delete(recompute) ;
01101         return 0 ;
01102     }
01103     nx = cpl_image_get_size_x(error) ;
01104     ny = cpl_image_get_size_y(error) ;
01105     nima = cpl_imagelist_get_size(raw) ;
01106 
01107     /* Get access to the mask */
01108     precompute = cpl_mask_get_data(recompute) ;
01109     for (j=0 ; j<ny ; j++) {
01110         for (i=0 ; i<nx ; i++) {
01111             pos = i + j*nx ;
01112             /* The pixel has to be recomputed */
01113             if (precompute[pos] == CPL_BINARY_1) {
01114                 /* Get the pix_val-fit in a vector */
01115                 z_pix = cpl_vector_new(nima) ;
01116                 for (k=0 ; k<nima ; k++) {
01117                     cur_ima = cpl_imagelist_get(fit_res, 0) ;
01118                     pimaf = cpl_image_get_data_float(cur_ima) ;
01119                     a = pimaf[pos] ;
01120                     cur_ima = cpl_imagelist_get(fit_res, 1) ;
01121                     pimaf = cpl_image_get_data_float(cur_ima) ;
01122                     b = pimaf[pos] ;
01123                     med = cpl_vector_get(medians, k) ;
01124                     fit_val = a + b * med ;
01125                     cur_ima = cpl_imagelist_get(raw, k) ;
01126                     pimaf = cpl_image_get_data_float(cur_ima) ;
01127                     cpl_vector_set(z_pix, k, (double)(pimaf[pos]-fit_val)) ;
01128                 }
01129 
01130                 /* Identify the outlier */
01131                 out = -1 ;
01132                 max = -1.0 ;
01133                 pz_pix = cpl_vector_get_data(z_pix) ;
01134                 for (k=0 ; k<nima ; k++) {
01135                     if (fabs(pz_pix[k]) > max) {
01136                         max = fabs(pz_pix[k]) ;
01137                         out = k ;
01138                     }
01139                 }
01140                 cpl_vector_delete(z_pix) ;
01141 
01142                 /* Create 1-pixel purged image list and the purged medians */
01143                 med_purged = cpl_vector_new(nima-1) ;
01144                 raw_purged = cpl_imagelist_new() ;
01145                 ind = 0 ;
01146                 for (k=0 ; k<nima ; k++) {
01147                     if (k != out) {
01148                         /* Fill raw_purged */
01149                         cur_ima = cpl_imagelist_get(raw, k) ;
01150                         onepix=cpl_image_extract(cur_ima, i+1, j+1, i+1, j+1) ;
01151                         cpl_imagelist_set(raw_purged, onepix, ind) ;
01152                         /* Fill med_purged */
01153                         cpl_vector_set(med_purged, ind,
01154                                 cpl_vector_get(medians, k)) ;
01155                         ind ++;
01156                     }
01157                 }
01158 
01159                 /* Perform the fit */
01160                 err_one = cpl_image_duplicate(cpl_imagelist_get(raw_purged,0));
01161                 fit_one = cpl_fit_imagelist_polynomial(med_purged, raw_purged, 
01162                         0, 1, CPL_FALSE, CPL_TYPE_FLOAT, err_one) ;
01163                 if (fit_one == NULL) {
01164                     cpl_msg_error(__func__, "Cannot fit in second pass") ;
01165                     cpl_mask_delete(recompute) ;
01166                     cpl_vector_delete(med_purged) ;
01167                     cpl_imagelist_delete(raw_purged) ;
01168                     cpl_image_delete(err_one) ;
01169                     return -1 ;
01170                 }
01171                 cpl_vector_delete(med_purged) ;
01172                 cpl_imagelist_delete(raw_purged) ;
01173 
01174                 /* Write the result in the input */
01175                 val = cpl_image_get(err_one, 1, 1, &pix) ;
01176                 cpl_image_set(error, i+1, j+1, val) ;
01177                 cpl_image_delete(err_one) ;
01178 
01179                 cur_ima = cpl_imagelist_get(fit_one, 0) ;
01180                 val = cpl_image_get(cur_ima, 1, 1, &pix) ;
01181                 cur_ima = cpl_imagelist_get(fit_res, 0) ;
01182                 cpl_image_set(cur_ima, i+1, j+1, val) ;
01183               
01184                 cur_ima = cpl_imagelist_get(fit_one, 1) ;
01185                 val = cpl_image_get(cur_ima, 1, 1, &pix) ;
01186                 cur_ima = cpl_imagelist_get(fit_res, 1) ;
01187                 cpl_image_set(cur_ima, i+1, j+1, val) ;
01188                 cpl_imagelist_delete(fit_one) ;
01189             }
01190         }
01191     }
01192     if (recomp_mask)    
01193         *recomp_mask = cpl_image_new_from_mask(recompute) ;
01194     cpl_mask_delete(recompute) ;
01195 
01196     /* Return  */
01197     if (cpl_error_get_code()) return -1 ;
01198     else return 0 ;
01199 }
01200 
01201 /*----------------------------------------------------------------------------*/
01213 /*----------------------------------------------------------------------------*/
01214 static int hawki_cal_flat_save
01215 (cpl_imagelist     ** flat,
01216  cpl_table         ** raw_flat_stats,
01217  cpl_table         ** raw_flat_odd_column_stats,
01218  cpl_table         ** raw_flat_even_column_stats,
01219  cpl_table         ** raw_flat_odd_row_stats,
01220  cpl_table         ** raw_flat_even_row_stats,
01221  cpl_vector        ** raw_selected,
01222  int                  set_nb,
01223  const cpl_frame   *  bpmdark,
01224  cpl_frameset      *  flat_frames,
01225  cpl_frameset      *  calib_frames,
01226  cpl_parameterlist *  parlist,
01227  cpl_frameset      *  set_tot)
01228 {
01229     cpl_propertylist    **  qclists ;
01230     cpl_imagelist       *   bpm ;
01231     const cpl_frame     *   ref_frame ;
01232     cpl_frameset        *   used_frames;
01233     char                *   filename ;
01234     cpl_propertylist    *   inputlist ;
01235     int                     ext_nb ;
01236     const char          *   recipe_name = "hawki_cal_flat" ;
01237     int                     i ;
01238     int                     iflat;
01239     int                     nflat;
01240     int                     nused;
01241     char                    key_name[72];
01242 
01243     /* Get the reference frame */
01244     ref_frame = irplib_frameset_get_first_from_group(flat_frames, CPL_FRAME_GROUP_RAW) ;
01245 
01246     /* Create the QC lists */
01247     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
01248     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
01249         qclists[i] = cpl_propertylist_new() ;
01250         
01251         /* Add the raw flat selection keywords */
01252         nflat = cpl_vector_get_size(raw_selected[i]);
01253         nused = 0;
01254         for(iflat = 0; iflat < nflat; ++iflat)
01255         {
01256             snprintf(key_name, 72, "ESO QC RAW%02d USED", iflat + 1);
01257             cpl_propertylist_append_bool
01258                 (qclists[i], key_name, 
01259                 (cpl_vector_get(raw_selected[i], iflat) + 1) / 2);
01260             cpl_table_set_int
01261                 (raw_flat_stats[i],HAWKI_COL_STAT_USED, iflat,
01262                  cpl_vector_get(raw_selected[i], iflat));
01263             if(hawki_cal_flat_config.extra_stats)
01264             {
01265                 cpl_table_set_int
01266                     (raw_flat_odd_column_stats[i],HAWKI_COL_STAT_USED, iflat,
01267                      cpl_vector_get(raw_selected[i], iflat));
01268                 cpl_table_set_int
01269                     (raw_flat_even_column_stats[i],HAWKI_COL_STAT_USED, iflat,
01270                      cpl_vector_get(raw_selected[i], iflat));
01271                 cpl_table_set_int
01272                     (raw_flat_odd_row_stats[i],HAWKI_COL_STAT_USED, iflat,
01273                      cpl_vector_get(raw_selected[i], iflat));
01274                 cpl_table_set_int
01275                     (raw_flat_even_row_stats[i],HAWKI_COL_STAT_USED, iflat,
01276                      cpl_vector_get(raw_selected[i], iflat));
01277             }
01278             if(cpl_vector_get(raw_selected[i], iflat) == 1)
01279                 nused++;
01280         }
01281         
01282         /* Add the master flat statistics keywords */
01283         cpl_propertylist_append_int(qclists[i], "ESO QC FLAT NBADPIX",
01284                                     hawki_cal_flat_outputs.nb_badpix[i]);
01285         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT NORM",
01286                                        hawki_cal_flat_outputs.norm[i]) ;
01287         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMEAN",
01288                                        hawki_cal_flat_outputs.med_avg[i]) ;
01289         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMED",
01290                                        hawki_cal_flat_outputs.med_med[i]) ;
01291         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDSTDEV",
01292                                        hawki_cal_flat_outputs.med_stdev[i]) ;
01293         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMIN",
01294                                        hawki_cal_flat_outputs.med_min[i]) ;
01295         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMAX",
01296                                        hawki_cal_flat_outputs.med_max[i]) ;
01297         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDRANG",
01298                                        hawki_cal_flat_outputs.med_max[i] -
01299                                        hawki_cal_flat_outputs.med_min[i]);
01300         cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDNRANG",
01301                                        (hawki_cal_flat_outputs.med_max[i] -
01302                                         hawki_cal_flat_outputs.med_min[i]) /
01303                                         hawki_cal_flat_outputs.med_med[i]);
01304         cpl_propertylist_append_int(qclists[i], "ESO QC DATANCOM",
01305                                     nused) ;
01306 
01307         /* Propagate some keywords from input raw frame extensions */
01308         ext_nb = hawki_get_ext_from_detector(
01309                 cpl_frame_get_filename(ref_frame), i+1);
01310         inputlist = cpl_propertylist_load_regexp(
01311                 cpl_frame_get_filename(ref_frame), ext_nb,
01312                 HAWKI_HEADER_EXT_FORWARD, 0) ;
01313         cpl_propertylist_append(qclists[i], inputlist) ;
01314 
01315         /* Cleaning */
01316         cpl_propertylist_delete(inputlist) ;
01317     }
01318     /* Statistics of the raw images in the QC */
01319     hawki_image_stats_stats(raw_flat_stats, qclists);
01320 
01321     /* Get the used frames */
01322     used_frames = cpl_frameset_duplicate(flat_frames);
01323     for(i = 0; i< cpl_frameset_get_size(calib_frames); ++i)
01324         cpl_frameset_insert(used_frames, 
01325                 cpl_frame_duplicate(cpl_frameset_get_frame(calib_frames, i)));
01326 
01327     /* Write the flat image */
01328     filename = cpl_sprintf("hawki_cal_flat_set%02d.fits", set_nb) ;
01329     hawki_imagelist_save(set_tot,
01330                          parlist,
01331                          used_frames,
01332                          flat[0],
01333                          recipe_name,
01334                          HAWKI_CALPRO_FLAT,
01335                          HAWKI_PROTYPE_FLAT, 
01336                          NULL,
01337                          (const cpl_propertylist**)qclists,
01338                          filename) ;
01339     cpl_free(filename) ;
01340     
01341     /* Write the error map */
01342     filename = cpl_sprintf("hawki_cal_flat_err_set%02d.fits", set_nb) ;
01343     hawki_imagelist_save(set_tot,
01344                          parlist,
01345                          used_frames,
01346                          flat[1],
01347                          recipe_name,
01348                          HAWKI_CALPRO_FLAT_ERRMAP,
01349                          HAWKI_PROTYPE_ERRMAP, 
01350                          NULL,
01351                          (const cpl_propertylist**)qclists,
01352                          filename) ;
01353     cpl_free(filename) ;
01354  
01355     /* Write the Cold pixels map */
01356     filename = cpl_sprintf("hawki_cal_flat_bpmflat_set%02d.fits", set_nb) ;
01357     hawki_imagelist_save(set_tot,
01358                          parlist,
01359                          used_frames,
01360                          flat[2],
01361                          recipe_name,
01362                          HAWKI_CALPRO_BPM_COLD,
01363                          HAWKI_PROTYPE_BPM,
01364                          NULL,
01365                          (const cpl_propertylist**)qclists,
01366                          filename) ;
01367     cpl_free(filename) ;
01368 
01369     if (flat[3] != NULL) {
01370         /* Write the recomputed map */
01371         filename=cpl_sprintf("hawki_cal_flat_recomputed_set%02d.fits", set_nb) ;
01372         hawki_imagelist_save(set_tot,
01373                              parlist,
01374                              used_frames,
01375                              flat[3],
01376                              recipe_name,
01377                              HAWKI_CALPRO_FLAT_RECOMPUTED,
01378                              HAWKI_PROTYPE_FLAT,
01379                              NULL,
01380                              (const cpl_propertylist**)qclists,
01381                              filename) ;
01382         cpl_free(filename) ;
01383     }
01384 
01385     /* If the HOT pixel map is passed, merge with the COLD one */
01386     if (bpmdark != NULL) {
01387         if ((bpm = hawki_cal_flat_merge_bpms(bpmdark, flat[2])) == NULL) {
01388             cpl_msg_error(__func__, "Cannot merge bad pixel maps") ;
01389         } else {
01390             filename=cpl_sprintf("hawki_cal_flat_bpm_set%02d.fits", set_nb) ;
01391             /* Get the used frames for statistics */
01392             hawki_imagelist_save(set_tot,
01393                                  parlist,
01394                                  used_frames,
01395                                  bpm,
01396                                  recipe_name,
01397                                  HAWKI_CALPRO_BPM,
01398                                  HAWKI_PROTYPE_BPM,
01399                                  NULL,
01400                                  (const cpl_propertylist**)qclists,
01401                                  filename) ;
01402             cpl_free(filename) ;
01403             cpl_imagelist_delete(bpm) ;
01404         }
01405     }
01406     cpl_frameset_delete(used_frames);
01407 
01408     /* Get the used frames for statistics */
01409     used_frames = cpl_frameset_duplicate(flat_frames);
01410     
01411     /* Write the table with the statistics */
01412     filename = cpl_sprintf("hawki_cal_flat_stats_set%02d.fits", set_nb) ;
01413     hawki_tables_save(set_tot,
01414                       parlist,
01415                       used_frames,
01416                       (const cpl_table **)raw_flat_stats,
01417                       recipe_name,
01418                       HAWKI_CALPRO_FLAT_STATS,
01419                       HAWKI_PROTYPE_FLAT_STATS,
01420                       NULL,
01421                       (const cpl_propertylist **)qclists,
01422                       filename) ;
01423     cpl_free(filename) ;
01424     
01425     if(hawki_cal_flat_config.extra_stats)
01426     {
01427         filename = cpl_sprintf("hawki_cal_flat_stats_ec_set%02d.fits", set_nb);
01428         hawki_tables_save(set_tot,
01429                           parlist,
01430                           used_frames,
01431                           (const cpl_table **)raw_flat_even_column_stats,
01432                           recipe_name,
01433                           HAWKI_CALPRO_FLAT_STATS_EVEN_COL,
01434                           HAWKI_PROTYPE_FLAT_STATS_EVEN_COL,
01435                           NULL,
01436                           (const cpl_propertylist **)qclists,
01437                           filename) ;
01438         cpl_free(filename) ;
01439         filename = cpl_sprintf("hawki_cal_flat_stats_oc_set%02d.fits", set_nb);
01440         hawki_tables_save(set_tot,
01441                           parlist,
01442                           used_frames,
01443                           (const cpl_table **)raw_flat_odd_column_stats,
01444                           recipe_name,
01445                           HAWKI_CALPRO_FLAT_STATS_ODD_COL,
01446                           HAWKI_PROTYPE_FLAT_STATS_ODD_COL,
01447                           NULL,
01448                           (const cpl_propertylist **)qclists,
01449                           filename) ;
01450         cpl_free(filename) ;
01451         filename = cpl_sprintf("hawki_cal_flat_stats_er_set%02d.fits", set_nb);
01452         hawki_tables_save(set_tot,
01453                           parlist,
01454                           used_frames,
01455                           (const cpl_table **)raw_flat_even_row_stats,
01456                           recipe_name,
01457                           HAWKI_CALPRO_FLAT_STATS_EVEN_ROW,
01458                           HAWKI_PROTYPE_FLAT_STATS_EVEN_ROW,
01459                           NULL,
01460                           (const cpl_propertylist **)qclists,
01461                           filename) ;
01462         cpl_free(filename) ;
01463         filename = cpl_sprintf("hawki_cal_flat_stats_or_set%02d.fits", set_nb);
01464         hawki_tables_save(set_tot,
01465                           parlist,
01466                           used_frames,
01467                           (const cpl_table **)raw_flat_odd_row_stats,
01468                           recipe_name,
01469                           HAWKI_CALPRO_FLAT_STATS_ODD_ROW,
01470                           HAWKI_PROTYPE_FLAT_STATS_ODD_ROW,
01471                           NULL,
01472                           (const cpl_propertylist **)qclists,
01473                           filename) ;
01474         cpl_free(filename) ;
01475     }
01476     cpl_frameset_delete(used_frames);
01477         
01478     /* Free and return */
01479     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
01480         cpl_propertylist_delete(qclists[i]) ;
01481     }
01482     cpl_free(qclists) ;
01483     if (cpl_error_get_code()) return -1 ;
01484     return  0;
01485 }
01486 
01487 /*----------------------------------------------------------------------------*/
01494 /*----------------------------------------------------------------------------*/
01495 static int hawki_cal_flat_compare(
01496         const cpl_frame *   frame1,
01497         const cpl_frame *   frame2)
01498 {
01499     int                     comparison ;
01500     cpl_propertylist    *   plist1 ;
01501     cpl_propertylist    *   plist2 ;
01502     const char          *   sval1,
01503                         *   sval2 ;
01504     double                  dval1, dval2 ;
01505 
01506     
01507     /* Test entries */
01508     if (frame1==NULL || frame2==NULL) return -1 ;
01509 
01510     /* Get property lists */
01511     if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
01512                     0)) == NULL) {
01513         cpl_msg_error(__func__, "getting header from reference frame");
01514         return -1 ;
01515     }
01516     if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
01517                     0)) == NULL) {
01518         cpl_msg_error(__func__, "getting header from reference frame");
01519         cpl_propertylist_delete(plist1) ;
01520         return -1 ;
01521     }
01522 
01523     /* Test status */
01524     if (cpl_error_get_code()) {
01525         cpl_propertylist_delete(plist1) ;
01526         cpl_propertylist_delete(plist2) ;
01527         return -1 ;
01528     }
01529 
01530     comparison = 1 ;
01531 
01532     /* Compare filters */
01533     sval1 = hawki_pfits_get_filter(plist1) ;
01534     sval2 = hawki_pfits_get_filter(plist2) ;
01535     if (cpl_error_get_code()) {
01536         cpl_msg_error(__func__, "cannot get the filter");
01537         cpl_propertylist_delete(plist1) ;
01538         cpl_propertylist_delete(plist2) ;
01539         return -1 ;
01540     }
01541     if (strcmp(sval1, sval2)) comparison = 0 ;
01542 
01543     /* Compare DITs */
01544     dval1 = hawki_pfits_get_dit(plist1) ;
01545     dval2 = hawki_pfits_get_dit(plist2) ;
01546     if (cpl_error_get_code()) {
01547         cpl_msg_error(__func__, "cannot get the DIT");
01548         cpl_propertylist_delete(plist1) ;
01549         cpl_propertylist_delete(plist2) ;
01550         return -1 ;
01551     }
01552     if (fabs(dval1-dval2) > 1e-4) comparison = 0 ;
01553 
01554     cpl_propertylist_delete(plist1) ;
01555     cpl_propertylist_delete(plist2) ;
01556     return comparison ;
01557 }
01558 
01559 /*----------------------------------------------------------------------------*/
01566 /*----------------------------------------------------------------------------*/
01567 static cpl_imagelist * hawki_cal_flat_merge_bpms
01568 (const cpl_frame *   bpm_orig,
01569  cpl_imagelist   *   bpm_to_merge)
01570 {
01571     cpl_imagelist   *   merged ;
01572     cpl_imagelist   *   bpm_orig_im;
01573     cpl_image       *   tmp ;
01574     int                 i ;
01575 
01576     /* Test entries */
01577     if (bpm_orig==NULL || bpm_to_merge ==NULL) return NULL ;
01578 
01579     /* Create merged */
01580     merged = cpl_imagelist_new() ;
01581 
01582     /* Load the bpm_file */
01583     bpm_orig_im = hawki_load_frame(bpm_orig, CPL_TYPE_INT);
01584     if(bpm_orig_im == NULL)
01585     {
01586         cpl_msg_error(__func__, "Cannot read existing bpm %s",
01587                       cpl_frame_get_filename(bpm_orig));
01588         cpl_imagelist_delete(merged);
01589         return NULL;
01590     }
01591 
01592     /* Loop on the chips */
01593     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
01594 
01595         /* Merge */
01596         tmp = cpl_image_add_create(cpl_imagelist_get(bpm_orig_im, i),
01597                                    cpl_imagelist_get(bpm_to_merge, i));
01598         cpl_image_multiply(cpl_imagelist_get(bpm_orig_im, i),
01599                            cpl_imagelist_get(bpm_to_merge, i));
01600         cpl_image_subtract(tmp, cpl_imagelist_get(bpm_orig_im, i)) ;
01601 
01602         /* Store */
01603         cpl_imagelist_set(merged, tmp, i) ;
01604     }
01605 
01606     /* Clean-up and return */
01607     cpl_imagelist_delete(bpm_orig_im);
01608     return merged ;
01609 }
01610 
01611 /*----------------------------------------------------------------------------*/
01622 /*----------------------------------------------------------------------------*/
01623 static int hawki_cal_flat_select
01624 (cpl_vector  *   meds,
01625  cpl_vector  *   rms,
01626  int             auto_flag,
01627  int             auto_max_bins,
01628  double          min_level,
01629  double          max_level,
01630  double          max_rms,
01631  int             min_nframes,
01632  cpl_vector  *   selection)
01633 {
01634     double      *   pselection ;
01635     double      *   pmeds ;
01636     double      *   prms ;
01637     int             nvals ;
01638     int             nsel ;
01639     double          first_val, last_val, bin_val, dist, dist_min;
01640     double          bin_low_val;
01641     double          bin_up_val;
01642     int             nbins, ind_closest ;
01643     int             ibin;
01644     int             ival;
01645     
01646     /* Test entries */
01647     if (meds == NULL) return -1;
01648     if (rms == NULL) return -1;
01649     if (selection == NULL) return -1;
01650     if(cpl_vector_get_size(meds) != cpl_vector_get_size(selection))
01651     {
01652         cpl_msg_error(__func__, 
01653                       "The meds and selection vectors have not the same size");
01654         return -1;
01655     }
01656 
01657     /* Initialise. All the frames are selected by default */
01658     nvals = cpl_vector_get_size(meds);
01659     pmeds = cpl_vector_get_data(meds);
01660     prms = cpl_vector_get_data(rms);
01661     cpl_vector_fill(selection, 1.0);  
01662 
01663     /* Pointer to selection */
01664     pselection = cpl_vector_get_data(selection) ;
01665 
01666     /* First select based on minimum level, if applies */
01667     if (min_level >= 0.0)
01668     {
01669         for (ival=0 ; ival<nvals ; ival++) 
01670         {
01671             if (pmeds[ival] < min_level)
01672                 pselection[ival] = -1.0 ;
01673         }
01674     }
01675 
01676     /* Second select based on maximum level, if applies */
01677     if (max_level >= 0.0)
01678     {
01679         for (ival=0 ; ival<nvals ; ival++) 
01680         {
01681             if (pmeds[ival] > max_level)
01682                 pselection[ival] = -1.0 ;
01683         }
01684     }
01685 
01686     /* Third select based on rms maximum level, if applies */
01687     if (max_rms >= 0.0)
01688     {
01689         for (ival=0 ; ival<nvals ; ival++) 
01690         {
01691             if (prms[ival] > max_rms)
01692                 pselection[ival] = -1.0 ;
01693         }
01694     }
01695 
01696     /* Apply the histogram selection */
01697     if (auto_flag)
01698     {
01699         /* Automatic  */
01700         cpl_vector * auto_selection;
01701         auto_selection = cpl_vector_new(nvals);
01702         cpl_vector_fill(auto_selection, -1.0);
01703         cpl_msg_info(__func__, "Automatic dynamic range selection");
01704         first_val = hawki_vector_get_min_select(meds, selection);
01705         last_val = hawki_vector_get_max_select(meds, selection);
01706 
01707         nbins = nvals ;
01708         if (auto_max_bins > 0 && auto_max_bins < nvals) nbins = auto_max_bins;
01709         for (ibin=0 ; ibin<nbins ; ibin++) 
01710         {
01711             if(ibin == 0)
01712                 bin_val = first_val + (last_val-first_val)*(ibin+1)/nbins ;
01713             else if(ibin == nbins - 1)
01714                 bin_val = first_val + (last_val-first_val)*(ibin)/nbins ;
01715             else
01716                 bin_val = first_val + (last_val-first_val)*(ibin+0.5)/nbins ;
01717             bin_low_val = first_val + (last_val-first_val)*(ibin)/nbins ;
01718             bin_up_val  = first_val + (last_val-first_val)*(ibin+1)/nbins ;
01719 
01720             /* Select the closest */
01721             dist_min = fabs(pmeds[0] - bin_val) ;
01722             ind_closest = -1;
01723             for (ival=0 ; ival<nvals ; ival++) 
01724             {
01725                 dist = fabs(pmeds[ival] - bin_val) ;
01726                 if (dist < dist_min && pselection[ival] != -1) 
01727                 {
01728                     dist_min = dist;
01729                     ind_closest = ival;
01730                 }
01731             }
01732             if(ind_closest != -1)
01733                 cpl_vector_set(auto_selection, ind_closest, 1.0);
01734         }
01735         /* Use the auto_selection */
01736         cpl_vector_copy(selection, auto_selection);
01737         cpl_vector_delete(auto_selection);
01738     }
01739     
01740     /* Print and count the selected frames */
01741     nsel = 0;
01742     cpl_msg_indent_more();
01743     for (ival=0 ; ival<nvals ; ival++) 
01744     {
01745         if(pselection[ival] != -1)
01746         {
01747             cpl_msg_info(__func__, "Selected frame %d", ival+1) ;
01748             nsel++;
01749         }
01750     }
01751     cpl_msg_indent_less();
01752     
01753     /* Check the number of selected against min_nframes */
01754     if (nsel == 0) {
01755         cpl_msg_error(__func__, "No frame selected. Check selection criteria");
01756         return -1;
01757     }
01758     if (min_nframes >= 0) {
01759         if (nsel < min_nframes) {
01760             cpl_msg_error(__func__, "Not enough selected frames (%d < %d)",
01761                 nsel, min_nframes) ;
01762             return -1;
01763         }
01764     }
01765     
01766     return 0;
01767 }
01768  
01769 /*----------------------------------------------------------------------------*/
01776 /*----------------------------------------------------------------------------*/
01777 static cpl_vector * hawki_cal_flat_extract_vector(
01778         cpl_vector  *   in,
01779         cpl_vector  *   selection)
01780 {
01781     int             nvals ;
01782     cpl_vector  *   selected ;
01783     double      *   pin ;
01784     double      *   pselection ;
01785     double      *   pselected ;
01786     int             nselected ;
01787     int             i ;
01788     
01789     /* Test entries */
01790     if (in == NULL) return NULL ;
01791     if (selection == NULL) return NULL ;
01792 
01793     /* Initialise */
01794     nvals = cpl_vector_get_size(in) ;
01795     nselected = 0 ;
01796     pin = cpl_vector_get_data(in) ;
01797     pselection = cpl_vector_get_data(selection) ;
01798 
01799     /* Test entries */
01800     if (nvals != cpl_vector_get_size(selection)) return NULL ; 
01801 
01802     /* Count the selected values */
01803     for (i=0 ; i<nvals ; i++) {
01804         if (pselection[i] > 0.0) nselected++ ;
01805     } 
01806     if (nselected == 0) return NULL ;
01807 
01808     /* Create the selected vector */
01809     selected = cpl_vector_new(nselected) ;
01810     pselected = cpl_vector_get_data(selected) ;
01811 
01812     nselected = 0 ;
01813     for (i=0 ; i<nvals ; i++) {
01814         if (pselection[i] > 0.0) {
01815             pselected[nselected] = pin[i] ;
01816             nselected++ ;
01817         }
01818     } 
01819     return selected ;
01820 }
01821 
01822 static int hawki_cal_flat_retrieve_input_param
01823 (cpl_parameterlist  *  parlist)
01824 {
01825     const char      * sval;
01826     cpl_parameter   * par;
01827     int               idet;
01828     
01829     /* Initialise */
01830     par = NULL ;
01831     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) {
01832         hawki_cal_flat_outputs.nb_badpix[idet] = -1 ;
01833         hawki_cal_flat_outputs.med_stdev[idet] = -1.0 ;
01834         hawki_cal_flat_outputs.med_avg[idet] = -1.0 ;
01835         hawki_cal_flat_outputs.med_med[idet] = -1.0 ;
01836         hawki_cal_flat_outputs.med_min[idet] = -1.0 ;
01837         hawki_cal_flat_outputs.med_max[idet] = -1.0 ;
01838     }
01839 
01840     /* Retrieve input parameters */
01841     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.zone") ;
01842     sval = cpl_parameter_get_string(par) ;
01843     if (sscanf(sval, "%d,%d,%d,%d",
01844                     &hawki_cal_flat_config.llx,
01845                     &hawki_cal_flat_config.lly,
01846                     &hawki_cal_flat_config.urx,
01847                     &hawki_cal_flat_config.ury)!=4) 
01848     {
01849         return -1 ;
01850     }
01851     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.sigma_badres") ;
01852     hawki_cal_flat_config.sigma_badres = cpl_parameter_get_double(par) ;
01853     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.sigma_bpm") ;
01854     hawki_cal_flat_config.sigma_bpm = cpl_parameter_get_double(par) ;
01855     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.lowval_bpm") ;
01856     hawki_cal_flat_config.lowval_bpm = cpl_parameter_get_double(par) ;
01857     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.highval_bpm") ;
01858     hawki_cal_flat_config.highval_bpm = cpl_parameter_get_double(par) ;
01859     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.normalise") ;
01860     hawki_cal_flat_config.normalise = cpl_parameter_get_bool(par) ;
01861     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.second_pass") ;
01862     hawki_cal_flat_config.second_pass = cpl_parameter_get_bool(par) ;
01863     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.select_auto") ;
01864     hawki_cal_flat_config.select_auto = cpl_parameter_get_bool(par) ;
01865     par = cpl_parameterlist_find(parlist, 
01866             "hawki.hawki_cal_flat.select_auto_max_bins") ;
01867     hawki_cal_flat_config.select_auto_max_bins = cpl_parameter_get_int(par);
01868     par = cpl_parameterlist_find(parlist, 
01869             "hawki.hawki_cal_flat.select_min_level") ;
01870     sval = cpl_parameter_get_string(par);
01871     if (sscanf(sval, "%lf,%lf,%lf,%lf",
01872                &hawki_cal_flat_config.select_min_level[0],
01873                &hawki_cal_flat_config.select_min_level[1],
01874                &hawki_cal_flat_config.select_min_level[2],
01875                &hawki_cal_flat_config.select_min_level[3])!=4)
01876     {
01877         if (sscanf(sval, "%f", &hawki_cal_flat_config.select_min_level[0])!=1)
01878         {
01879             return -1;
01880         }
01881         else
01882         {
01883             hawki_cal_flat_config.select_min_level[1] = 
01884                 hawki_cal_flat_config.select_min_level[0];
01885             hawki_cal_flat_config.select_min_level[2] = 
01886                 hawki_cal_flat_config.select_min_level[0];
01887             hawki_cal_flat_config.select_min_level[3] = 
01888                 hawki_cal_flat_config.select_min_level[0];
01889         }
01890     }
01891     par = cpl_parameterlist_find(parlist, 
01892             "hawki.hawki_cal_flat.select_max_level") ;
01893     sval = cpl_parameter_get_string(par);
01894     if (sscanf(sval, "%lf,%lf,%lf,%lf",
01895                &hawki_cal_flat_config.select_max_level[0],
01896                &hawki_cal_flat_config.select_max_level[1],
01897                &hawki_cal_flat_config.select_max_level[2],
01898                &hawki_cal_flat_config.select_max_level[3])!=4)
01899     {
01900         if (sscanf(sval, "%f", &hawki_cal_flat_config.select_max_level[0])!=1)
01901         {
01902             return -1;
01903         }
01904         else
01905         {
01906             hawki_cal_flat_config.select_max_level[1] = 
01907                 hawki_cal_flat_config.select_max_level[0];
01908             hawki_cal_flat_config.select_max_level[2] = 
01909                 hawki_cal_flat_config.select_max_level[0];
01910             hawki_cal_flat_config.select_max_level[3] = 
01911                 hawki_cal_flat_config.select_max_level[0];
01912         }
01913     }
01914     par = cpl_parameterlist_find(parlist, 
01915             "hawki.hawki_cal_flat.select_max_rms") ;
01916     sval = cpl_parameter_get_string(par);
01917     if (sscanf(sval, "%lf,%lf,%lf,%lf",
01918                hawki_cal_flat_config.select_max_rms,
01919                hawki_cal_flat_config.select_max_rms+1,
01920                hawki_cal_flat_config.select_max_rms+2,
01921                hawki_cal_flat_config.select_max_rms+3)!=4)
01922     {
01923         if (sscanf(sval, "%f", &hawki_cal_flat_config.select_max_rms[0])!=1)
01924         {
01925             return -1;
01926         }
01927         else
01928         {
01929             hawki_cal_flat_config.select_max_rms[1] = 
01930                 hawki_cal_flat_config.select_max_rms[0];
01931             hawki_cal_flat_config.select_max_rms[2] = 
01932                 hawki_cal_flat_config.select_max_rms[0];
01933             hawki_cal_flat_config.select_max_rms[3] = 
01934                 hawki_cal_flat_config.select_max_rms[0];
01935         }
01936     }
01937     par = cpl_parameterlist_find(parlist, 
01938             "hawki.hawki_cal_flat.select_min_nframes") ;
01939     hawki_cal_flat_config.select_min_nframes = cpl_parameter_get_int(par) ;
01940     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.extra_stats") ;
01941     hawki_cal_flat_config.extra_stats = cpl_parameter_get_bool(par) ;
01942 
01943     if(hawki_cal_flat_config.select_auto_max_bins != -1 &&
01944             !hawki_cal_flat_config.select_auto)
01945     {
01946             cpl_msg_error(__func__,"Max bins is only allowed with select_auto");
01947             return -1;
01948     }
01949         
01950     return 0;
01951 }

Generated on Thu Feb 17 17:13:07 2011 for HAWKI Pipeline Reference Manual by  doxygen 1.4.7