HAWKI Pipeline Reference Manual 1.8.12
hawki_cal_dark.c
00001 /* $Id: hawki_cal_dark.c,v 1.21 2011/02/16 16:33:21 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/02/16 16:33:21 $
00024  * $Revision: 1.21 $
00025  * $Name: hawki-1_8_12 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <cpl.h>
00038 
00039 #include "irplib_utils.h"
00040 
00041 #include "hawki_utils.h"
00042 #include "hawki_image_stats.h"
00043 #include "hawki_pfits.h"
00044 #include "hawki_dfs.h"
00045 #include "hawki_load.h"
00046 #include "hawki_save.h"
00047 #include "hawki_variance.h"
00048 
00049 /*-----------------------------------------------------------------------------
00050                             Functions prototypes
00051  -----------------------------------------------------------------------------*/
00052 
00053 static int hawki_cal_dark_create(cpl_plugin *) ;
00054 static int hawki_cal_dark_exec(cpl_plugin *) ;
00055 static int hawki_cal_dark_destroy(cpl_plugin *) ;
00056 static int hawki_cal_dark(cpl_parameterlist *, cpl_frameset *) ;
00057 
00058 void hawki_cal_dark_initialise_qc(void);
00059 static int hawki_cal_dark_retrieve_input_param
00060 (cpl_parameterlist * parlist);
00061 static double hawki_cal_dark_ron(const cpl_image *, const cpl_image *, int) ;
00062 static int hawki_cal_dark_save
00063 (const cpl_imagelist *   dark,
00064  const cpl_imagelist *   master_dark_err,
00065  const cpl_imagelist *   bpmdark,
00066  cpl_table           **  raw_dark_stats,
00067  const cpl_vector    **  rons,
00068  const cpl_frameset  *   used_frames,
00069  cpl_parameterlist   *   parlist,
00070  cpl_frameset        *   set);
00071 
00072 /*-----------------------------------------------------------------------------
00073                             Static variables
00074  -----------------------------------------------------------------------------*/
00075 
00076 static struct {
00077     /* Inputs */
00078     int         hsize ;
00079     int         nsamples ;
00080     double      sigma ;
00081     int         llx ;
00082     int         lly ;
00083     int         urx ;
00084     int         ury ;
00085     double      gain;
00086     double      ron;
00087     int         error_tracking;
00088 } hawki_cal_dark_config ;
00089 
00090 static struct {
00091     /* Outputs */
00092     int         nb_badpix[HAWKI_NB_DETECTORS] ;
00093     double      master_dark_mean[HAWKI_NB_DETECTORS] ;
00094     double      master_dark_med[HAWKI_NB_DETECTORS] ;
00095     double      master_dark_stdev[HAWKI_NB_DETECTORS] ;
00096     double      master_dark_error_mean[HAWKI_NB_DETECTORS] ;
00097     double      master_dark_error_med[HAWKI_NB_DETECTORS] ;
00098     double      master_dark_error_stdev[HAWKI_NB_DETECTORS] ;
00099     double      vc_mean[HAWKI_NB_DETECTORS][HAWKI_NB_VC] ;
00100     double      vc_med[HAWKI_NB_DETECTORS][HAWKI_NB_VC] ;
00101     double      vc_stdev[HAWKI_NB_DETECTORS][HAWKI_NB_VC] ;
00102     double      dit;
00103     int         ndit;
00104     int         ndsamples;
00105 } hawki_cal_dark_outputs;
00106 
00107 static char hawki_cal_dark_description[] =
00108 "hawki_cal_dark -- Dark recipe\n"
00109 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00110 "raw-file.fits "HAWKI_CAL_DARK_RAW" or\n"
00111 "raw-file.fits "HAWKI_TEC_FLAT_RAW".\n"
00112 "The recipe creates as an output:\n"
00113 "hawki_cal_dark.fits ("HAWKI_CALPRO_DARK"): The master dark\n"
00114 "hawki_cal_dark_bpmdark.fits("HAWKI_CALPRO_BPM_HOT"): The bad pixel mask associated to the dark\n"
00115 "hawki_cal_dark_stats.fits("HAWKI_CALPRO_DARK_STATS"): Statistics of the raw darks\n"
00116 "Optionally it also creates:\n"
00117 "hawki_cal_dark_err.fits("HAWKI_CALPRO_DARK_ERR"): The error in the master dark\n"
00118 "Return code:\n"
00119 "esorex exits with an error code of 0 if the recipe completes successfully\n"
00120 "or 1 otherwise";
00121 
00122 /*-----------------------------------------------------------------------------
00123                                 Functions code
00124  -----------------------------------------------------------------------------*/
00125 
00126 /*----------------------------------------------------------------------------*/
00135 /*----------------------------------------------------------------------------*/
00136 int cpl_plugin_get_info(cpl_pluginlist * list)
00137 {
00138     cpl_recipe  *   recipe = cpl_calloc(1, sizeof *recipe ) ;
00139     cpl_plugin  *   plugin = &recipe->interface ;
00140 
00141     cpl_plugin_init(plugin,
00142                     CPL_PLUGIN_API,
00143                     HAWKI_BINARY_VERSION,
00144                     CPL_PLUGIN_TYPE_RECIPE,
00145                     "hawki_cal_dark",
00146                     "Dark recipe",
00147                     hawki_cal_dark_description,
00148                     "Cesar Enrique Garcia Dabo",
00149                     PACKAGE_BUGREPORT,
00150                     hawki_get_license(),
00151                     hawki_cal_dark_create,
00152                     hawki_cal_dark_exec,
00153                     hawki_cal_dark_destroy) ;
00154 
00155     cpl_pluginlist_append(list, plugin) ;
00156     
00157     return 0;
00158 }
00159 
00160 /*----------------------------------------------------------------------------*/
00168 /*----------------------------------------------------------------------------*/
00169 static int hawki_cal_dark_create(cpl_plugin * plugin)
00170 {
00171     cpl_recipe      *   recipe ;
00172     cpl_parameter   *   p ;
00173         
00174     /* Check that the plugin is part of a valid recipe */
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 */
00184     p = cpl_parameter_new_value("hawki.hawki_cal_dark.sigma",
00185             CPL_TYPE_DOUBLE, "sigma for hot bad pixels detection",
00186             "hawki.hawki_cal_dark", 10.0) ;
00187     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma") ;
00188     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00189     cpl_parameterlist_append(recipe->parameters, p) ;
00190     /* --nsamples */
00191     p = cpl_parameter_new_value("hawki.hawki_cal_dark.nsamples",
00192             CPL_TYPE_INT, "number of samples for RON computation",
00193             "hawki.hawki_cal_dark", 100) ;
00194     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nsamples") ;
00195     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00196     cpl_parameterlist_append(recipe->parameters, p) ;
00197     /* --hsize */
00198     p = cpl_parameter_new_value("hawki.hawki_cal_dark.hsize",
00199             CPL_TYPE_INT, "half size of the window for RON computation",
00200             "hawki.hawki_cal_dark", 6) ;
00201     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsize") ;
00202     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00203     cpl_parameterlist_append(recipe->parameters, p) ;
00204     /* --zone */
00205     p = cpl_parameter_new_value("hawki.hawki_cal_dark.zone",
00206                                 CPL_TYPE_STRING,
00207                                 "Stats zone",
00208                                 "hawki.hawki_cal_dark",
00209                                 "512,512,1536,1536") ;
00210     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "zone") ;
00211     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00212     cpl_parameterlist_append(recipe->parameters, p) ;
00213     /* --gain */
00214     p = cpl_parameter_new_value("hawki.hawki_cal_dark.gain",
00215                                 CPL_TYPE_DOUBLE,
00216                                 "Detector nominal gain (e-/ADU)",
00217                                 "hawki.hawki_cal_dark",
00218                                 -1.);
00219     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "gain") ;
00220     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00221     cpl_parameterlist_append(recipe->parameters, p) ;
00222     /* --ron */
00223     p = cpl_parameter_new_value("hawki.hawki_cal_dark.ron",
00224                                 CPL_TYPE_DOUBLE,
00225                                 "Detector nominal RON for a single readout (ADU)",
00226                                 "hawki.hawki_cal_dark",
00227                                 -1.);
00228     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ron") ;
00229     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00230     cpl_parameterlist_append(recipe->parameters, p) ;
00231 
00232     /* Return */
00233     return 0;
00234 }
00235 
00236 /*----------------------------------------------------------------------------*/
00242 /*----------------------------------------------------------------------------*/
00243 static int hawki_cal_dark_exec(cpl_plugin * plugin)
00244 {
00245     cpl_recipe  *   recipe ;
00246     
00247     /* Get the recipe out of the plugin */
00248     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00249         recipe = (cpl_recipe *)plugin ;
00250     else return -1 ;
00251 
00252     /* Issue a banner */
00253     hawki_print_banner();
00254 
00255     return hawki_cal_dark(recipe->parameters, recipe->frames) ;
00256 }
00257 
00258 /*----------------------------------------------------------------------------*/
00264 /*----------------------------------------------------------------------------*/
00265 static int hawki_cal_dark_destroy(cpl_plugin * plugin)
00266 {
00267     cpl_recipe  *   recipe ;
00268     
00269     /* Get the recipe out of the plugin */
00270     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00271         recipe = (cpl_recipe *)plugin ;
00272     else return -1 ;
00273 
00274     cpl_parameterlist_delete(recipe->parameters) ; 
00275     return 0 ;
00276 }
00277 
00278 /*----------------------------------------------------------------------------*/
00285 /*----------------------------------------------------------------------------*/
00286 static int hawki_cal_dark(
00287         cpl_parameterlist   *   parlist, 
00288         cpl_frameset        *   frameset)
00289 {
00290     cpl_frameset        *   rawframes ;
00291     cpl_frame           *   ref_frame ;
00292     cpl_propertylist    *   plist ;
00293     cpl_imagelist       *   darks_raw ;
00294     cpl_imagelist       *   master_dark;
00295     cpl_imagelist       *   master_dark_err;
00296     cpl_imagelist       *   bpmdark;
00297     cpl_image           *   bpm ;
00298     cpl_image           *   ima_curr ;
00299     cpl_image           *   ima_next ;
00300     cpl_image           *   ima_accu ;
00301     cpl_image           *   ima_accu_err = NULL;
00302     int                     nframes ;
00303     cpl_vector          *   rons[HAWKI_NB_DETECTORS] ;
00304     cpl_table           **  raw_dark_stats;
00305     double                  ron ;
00306     int                     vc_urx, vc_ury, vc_llx, vc_lly ;
00307     int                     j, k ;
00308     int                     idet;
00309     cpl_errorstate          error_prevstate;      
00310     
00311     /* Initialise */
00312     rawframes = NULL ;
00313     ima_accu = NULL ;
00314     ima_next = NULL ;
00315     master_dark_err = NULL;
00316     hawki_cal_dark_initialise_qc();
00317 
00318     /* Retrieve input parameters */
00319     if(hawki_cal_dark_retrieve_input_param(parlist))
00320     {
00321         cpl_msg_error(__func__, "Wrong parameters");
00322         return -1;
00323     }
00324  
00325     /* Identify the RAW and CALIB frames in the input frameset */
00326     if (hawki_dfs_set_groups(frameset)) {
00327         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00328         return -1 ;
00329     }
00330         
00331     /* Retrieve raw frames */
00332     rawframes = hawki_extract_frameset(frameset, HAWKI_CAL_DARK_RAW) ;
00333 
00334     /* Test if raw frames have been found */
00335     if (rawframes == NULL) {
00336         cpl_msg_error(__func__, "No raw frame in input (%s)",HAWKI_CAL_DARK_RAW);
00337         return -1 ;
00338     }
00339 
00340     /* At least 3 frames */
00341     if (cpl_frameset_get_size(rawframes) < 3) {
00342         cpl_msg_error(__func__, "Not enough input frames");
00343         cpl_frameset_delete(rawframes) ;
00344         return -1 ;
00345     }
00346     
00347     /* Get DIT / NDIT from the header */
00348     error_prevstate = cpl_errorstate_get();
00349     ref_frame = cpl_frameset_get_frame(rawframes, 0) ;
00350     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00351                     0)) == NULL) {
00352         cpl_msg_error(__func__, "Cannot get header from frame");
00353         cpl_msg_indent_less() ;
00354         cpl_frameset_delete(rawframes) ;
00355         return -1 ;
00356     }
00357     hawki_cal_dark_outputs.dit = hawki_pfits_get_dit(plist) ;
00358     hawki_cal_dark_outputs.ndit = hawki_pfits_get_ndit(plist) ;
00359     hawki_cal_dark_outputs.ndsamples = hawki_pfits_get_ndsamples(plist);
00360     cpl_propertylist_delete(plist) ;
00361     if(!cpl_errorstate_is_equal(error_prevstate))
00362     {
00363         cpl_msg_error(__func__, "Cannot get the DIT/NDIT/NDSAMPLES from the header") ;
00364         cpl_msg_indent_less() ;
00365         cpl_frameset_delete(rawframes) ;
00366         return -1 ;
00367     }
00368     cpl_msg_info(__func__, "DIT value: %g sec.", hawki_cal_dark_outputs.dit);
00369     cpl_msg_info(__func__, "NDIT value: %d", hawki_cal_dark_outputs.ndit);
00370     cpl_msg_info(__func__, "NDSAMPLES value: %d", hawki_cal_dark_outputs.ndsamples);
00371     
00372     /* Check that DIT/NDIT and NDSAMPLES are the same for all the frames */
00373     if(!hawki_utils_check_equal_double_keys(rawframes, &hawki_pfits_get_dit) ||
00374        !hawki_utils_check_equal_int_keys(rawframes, &hawki_pfits_get_ndit)||
00375        !hawki_utils_check_equal_int_keys(rawframes, &hawki_pfits_get_ndsamples))
00376     {
00377         cpl_msg_error(__func__, "Not all input darks have the same "
00378                 "DIT/NDIT/NDSAMPLES values");
00379         cpl_msg_indent_less() ;
00380         return -1 ;        
00381     }
00382 
00383     /* Number of frames */
00384     nframes = cpl_frameset_get_size(rawframes) ;
00385 
00386     /* Create the statistics table */
00387     raw_dark_stats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *));
00388     for( idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00389     {
00390         raw_dark_stats[idet] = cpl_table_new(nframes);
00391     }
00392     hawki_image_stats_initialize(raw_dark_stats);
00393     
00394     /* Loop on the detectors */
00395     master_dark = cpl_imagelist_new();
00396     if(hawki_cal_dark_config.error_tracking)
00397         master_dark_err = cpl_imagelist_new();
00398     bpmdark = cpl_imagelist_new();
00399     cpl_msg_info(__func__, "Dark computation");
00400     cpl_msg_indent_more() ;
00401     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) {
00402         cpl_msg_info(__func__, "Handle chip number %d", idet+1) ;
00403 
00404         /* Create the rons vectors */
00405         rons[idet] = cpl_vector_new(nframes) ;
00406         
00407         /* Load the input data */
00408         darks_raw = hawki_load_detector(rawframes, idet+1, CPL_TYPE_FLOAT) ;
00409 
00410         /* Loop on the frames */
00411         for (j=0 ; j<nframes ; j++) {
00412             /* Load the current and next images */
00413             if (j==nframes-1) {
00414                 ima_curr = cpl_imagelist_get(darks_raw, j) ;
00415                 ima_next = cpl_imagelist_get(darks_raw, 0) ;
00416             } else {
00417                 ima_curr = cpl_imagelist_get(darks_raw, j) ;
00418                 ima_next = cpl_imagelist_get(darks_raw, j+1) ;
00419             }
00420 
00421             /* Compute the dark stats and store in table */
00422             if(hawki_image_stats_fill_from_image
00423                 (raw_dark_stats,
00424                  ima_curr,
00425                  hawki_cal_dark_config.llx,
00426                  hawki_cal_dark_config.lly,
00427                  hawki_cal_dark_config.urx,
00428                  hawki_cal_dark_config.ury,
00429                  idet,
00430                  j) != 0)
00431             {
00432                 cpl_msg_error(__func__, "Cannot compute statistics") ;
00433                 cpl_msg_indent_less() ; 
00434                 cpl_frameset_delete(rawframes) ;
00435                 cpl_imagelist_delete(master_dark);
00436                 if(hawki_cal_dark_config.error_tracking)
00437                     cpl_imagelist_delete(master_dark_err);                
00438                 cpl_imagelist_delete(darks_raw); 
00439                 cpl_imagelist_delete(bpmdark) ;
00440                 for (k=0 ; k<=idet ; k++) 
00441                     cpl_vector_delete(rons[k]) ;
00442                 for( idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00443                     cpl_table_delete(raw_dark_stats[idet]);
00444                 cpl_free(raw_dark_stats);
00445                 return -1 ;
00446             }
00447            
00448             /* Compute the RON */
00449             ron = hawki_cal_dark_ron(ima_curr, ima_next, hawki_cal_dark_outputs.ndit) ;
00450             cpl_vector_set(rons[idet], j, ron);
00451         }
00452         
00453         /* Collapse */
00454         if (nframes > 2)
00455         {
00456             ima_accu = cpl_imagelist_collapse_minmax_create(darks_raw, 0, 1) ;
00457             if(hawki_cal_dark_config.error_tracking)
00458             {
00459                 cpl_imagelist * variances;
00460                 cpl_image     * accu_var;
00461                 cpl_msg_info(__func__, "Computing the uncertainty in dark");
00462                 variances = hawki_imglist_create_variances_and_delete
00463                     (darks_raw, hawki_cal_dark_config.gain, 
00464                      hawki_cal_dark_config.ron, hawki_cal_dark_outputs.ndit,
00465                      hawki_cal_dark_outputs.ndsamples);
00466                 /* The variances are collapsed, like the dark_raw. Given that
00467                  * the variances are a monotically increasing function with
00468                  * respect to the dark_raw, the minmax algorithm will select
00469                  * the same values as for the dark_raw 
00470                  * The nframes - 1 is because only one frame is being rejected*/  
00471                 accu_var = cpl_imagelist_collapse_minmax_create(variances,0,1);
00472                 cpl_image_divide_scalar(accu_var, nframes - 1);
00473                 ima_accu_err = cpl_image_duplicate(accu_var);
00474                 cpl_image_power(ima_accu_err, 0.5);
00475                 cpl_imagelist_delete(variances);
00476                 cpl_image_delete(accu_var);
00477             }
00478 
00479         } else {
00480             ima_accu = cpl_imagelist_collapse_create(darks_raw) ;
00481             if(hawki_cal_dark_config.error_tracking)
00482             {
00483                 cpl_imagelist * variances;
00484                 cpl_image     * accu_var;
00485                 cpl_msg_info(__func__, "Computing the uncertainty in dark");
00486                 variances = hawki_imglist_create_variances_and_delete 
00487                     (darks_raw, hawki_cal_dark_config.gain, 
00488                      hawki_cal_dark_config.ron, hawki_cal_dark_outputs.ndit,
00489                      hawki_cal_dark_outputs.ndsamples);
00490                 accu_var = cpl_imagelist_collapse_create(variances);                
00491                 cpl_image_divide_scalar(accu_var, nframes); 
00492                 ima_accu_err = cpl_image_duplicate(accu_var);
00493                 cpl_image_power(ima_accu_err, 0.5);
00494                 cpl_imagelist_delete(variances);
00495                 cpl_image_delete(accu_var);
00496             }
00497         }
00498         if (ima_accu == NULL) {
00499             cpl_msg_error(__func__, "Cannot compute the average") ;
00500             cpl_frameset_delete(rawframes) ;
00501             cpl_imagelist_delete(bpmdark) ;
00502             cpl_imagelist_delete(master_dark) ;
00503             if(ima_accu_err != NULL)
00504                 cpl_image_delete(ima_accu_err);
00505             cpl_imagelist_delete(darks_raw); 
00506             for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00507                 cpl_vector_delete(rons[idet]) ;
00508             for( idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00509                  cpl_table_delete(raw_dark_stats[idet]);
00510             cpl_free(raw_dark_stats);
00511             return -1 ;
00512         }
00513         cpl_imagelist_delete(darks_raw) ;
00514 
00515         /* Put the result in the list */
00516         cpl_imagelist_set(master_dark, ima_accu, idet) ;
00517         if(hawki_cal_dark_config.error_tracking)
00518             cpl_imagelist_set(master_dark_err, ima_accu_err, idet) ;
00519 
00520         /* Compute the dark_med and stdev */
00521         hawki_cal_dark_outputs.master_dark_med[idet]=
00522             cpl_image_get_median(ima_accu) / hawki_cal_dark_outputs.dit;
00523         hawki_cal_dark_outputs.master_dark_mean[idet] =
00524             cpl_image_get_mean(ima_accu) / hawki_cal_dark_outputs.dit;
00525         hawki_cal_dark_outputs.master_dark_stdev[idet] =
00526             cpl_image_get_stdev(ima_accu) / hawki_cal_dark_outputs.dit;
00527         if(hawki_cal_dark_config.error_tracking)
00528         {
00529             hawki_cal_dark_outputs.master_dark_error_med[idet]=
00530                 cpl_image_get_median(ima_accu_err) / hawki_cal_dark_outputs.dit;
00531             hawki_cal_dark_outputs.master_dark_error_mean[idet] =
00532                 cpl_image_get_mean(ima_accu_err) / hawki_cal_dark_outputs.dit;
00533             hawki_cal_dark_outputs.master_dark_error_stdev[idet] =
00534                 cpl_image_get_stdev(ima_accu_err) / hawki_cal_dark_outputs.dit;
00535         }
00536 
00537         /* Compute the Video Channels stats */
00538         vc_lly = 973 ;
00539         vc_ury = 1036 ;
00540         for (j=0 ; j<HAWKI_NB_VC ; j++) {
00541             vc_llx = j*(2048/HAWKI_NB_VC) + 1 ;
00542             vc_urx = (j+1)*(2048/HAWKI_NB_VC) ;
00543 
00544             hawki_cal_dark_outputs.vc_mean[idet][j] =
00545                 cpl_image_get_mean_window(ima_accu, vc_llx, vc_lly,
00546                         vc_urx, vc_ury) ;
00547 
00548             hawki_cal_dark_outputs.vc_med[idet][j] =
00549                 cpl_image_get_median_window(ima_accu, vc_llx, vc_lly,
00550                         vc_urx, vc_ury) ;
00551 
00552             hawki_cal_dark_outputs.vc_stdev[idet][j] =
00553                 cpl_image_get_stdev_window(ima_accu, vc_llx, vc_lly,
00554                         vc_urx, vc_ury) ;
00555         }
00556 
00557         /* Compute the HOT pixels map */
00558         cpl_msg_info(__func__, "Compute the BPM from the dark") ;
00559         cpl_msg_indent_more() ;
00560         if ((bpm=hawki_compute_darkbpm(ima_accu, 
00561                         hawki_cal_dark_config.sigma)) == NULL) {
00562             cpl_msg_error(__func__, "Cannot compute the hot pixels") ;
00563             cpl_msg_indent_less() ; 
00564             cpl_frameset_delete(rawframes) ;
00565             cpl_imagelist_delete(bpmdark) ;
00566             cpl_imagelist_delete(master_dark);
00567             if(hawki_cal_dark_config.error_tracking)
00568                 cpl_imagelist_delete(master_dark_err);
00569             for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00570                 cpl_vector_delete(rons[idet]) ;
00571             for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00572                 cpl_table_delete(raw_dark_stats[idet]);
00573             cpl_free(raw_dark_stats);
00574             return -1 ;
00575         }
00576         cpl_imagelist_set(bpmdark, bpm, idet) ;
00577         hawki_cal_dark_outputs.nb_badpix[idet]=(int)cpl_image_get_flux(bpm);
00578         cpl_msg_indent_less() ;
00579     }
00580     cpl_msg_indent_less() ;
00581     
00582     /* Divide by DIT */
00583     cpl_msg_info(__func__, "Division by DIT") ;
00584     cpl_imagelist_divide_scalar(master_dark, hawki_cal_dark_outputs.dit);
00585     if(hawki_cal_dark_config.error_tracking)
00586         cpl_imagelist_divide_scalar(master_dark_err, hawki_cal_dark_outputs.dit);
00587 
00588     /* Save the product */
00589     cpl_msg_info(__func__, "Save the products") ;
00590     cpl_msg_indent_more() ;
00591     if (hawki_cal_dark_save(master_dark, master_dark_err,
00592                             bpmdark, raw_dark_stats, 
00593                             (const cpl_vector **)rons,
00594                             rawframes,
00595                             parlist, frameset)) 
00596         cpl_msg_warning(__func__,"Some data could not be saved. "
00597                                  "Check permisions or disk space");
00598 
00599     /* Free */
00600     cpl_frameset_delete(rawframes) ;
00601     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00602         cpl_vector_delete(rons[idet]) ;
00603     cpl_imagelist_delete(master_dark) ;
00604     if(hawki_cal_dark_config.error_tracking)
00605         cpl_imagelist_delete(master_dark_err);
00606     cpl_imagelist_delete(bpmdark) ;
00607     cpl_msg_indent_less() ;
00608     for( idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 
00609          cpl_table_delete(raw_dark_stats[idet]);
00610     cpl_free(raw_dark_stats);
00611 
00612     /* Return */
00613     if (cpl_error_get_code())
00614     {
00615         cpl_msg_error(__func__,
00616                       "HAWK-I pipeline could not recover from previous errors");
00617         return -1 ;
00618     }
00619     else return 0 ;
00620 }
00621 
00622 /*----------------------------------------------------------------------------*/
00630 /*----------------------------------------------------------------------------*/
00631 static double hawki_cal_dark_ron(
00632         const cpl_image     *   ima1, 
00633         const cpl_image     *   ima2, 
00634         int                     ndit) 
00635 {
00636     cpl_image       *   ima ;
00637     double              norm ;
00638     double              ron ;
00639 
00640     /* Test entries */
00641     if (ima1 == NULL)   return -1.0 ;
00642     if (ima2 == NULL)   return -1.0 ;
00643     if (ndit < 1)       return -1.0 ;
00644 
00645     /* Compute norm */
00646     norm = 0.5 * ndit ;
00647     norm = sqrt(norm) ;
00648 
00649     /* Subtraction */
00650     if ((ima = cpl_image_subtract_create(ima2, ima1)) == NULL) return -1.0 ;
00651    
00652     /* RON measurement */
00653     cpl_flux_get_noise_window(ima, NULL, hawki_cal_dark_config.hsize,
00654             hawki_cal_dark_config.nsamples, &ron, NULL) ;
00655     cpl_image_delete(ima) ;
00656     return norm*ron ;
00657 }
00658 
00659 /*----------------------------------------------------------------------------*/
00669 /*----------------------------------------------------------------------------*/
00670 static int hawki_cal_dark_save
00671 (const cpl_imagelist *   master_dark,
00672  const cpl_imagelist *   master_dark_err,
00673  const cpl_imagelist *   bpmdark,
00674  cpl_table           **  raw_dark_stats,
00675  const cpl_vector    **  rons,
00676  const cpl_frameset  *   used_frames,
00677  cpl_parameterlist   *   parlist,
00678  cpl_frameset        *   set)
00679 {
00680     cpl_propertylist    **  qclists ;
00681     const cpl_frame     *   ref_frame ;
00682     char                    sval[32] ;
00683     cpl_propertylist    *   inputlist ;
00684     int                     ext_nb ;
00685     const char          *   recipe_name = "hawki_cal_dark" ;
00686     int                     i, j ;
00687     cpl_errorstate          error_prevstate = cpl_errorstate_get();
00688     
00689 
00690     /* Get the reference frame */
00691     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00692 
00693     /* Create the QC lists */
00694     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00695     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
00696         qclists[i] = cpl_propertylist_new();
00697         cpl_propertylist_append_int(qclists[i], "ESO QC DARK NBADPIX",
00698                 hawki_cal_dark_outputs.nb_badpix[i]);
00699         cpl_propertylist_append_double(qclists[i], "ESO QC DARK MEAN",
00700                 hawki_cal_dark_outputs.master_dark_mean[i]);
00701         cpl_propertylist_append_double(qclists[i], "ESO QC DARK MED",
00702                 hawki_cal_dark_outputs.master_dark_med[i]);
00703         cpl_propertylist_append_double(qclists[i], "ESO QC DARK STDEV",
00704                 hawki_cal_dark_outputs.master_dark_stdev[i]);
00705         cpl_propertylist_append_double(qclists[i], "ESO QC DARK NONORM MEAN",
00706                 hawki_cal_dark_outputs.master_dark_mean[i] * hawki_cal_dark_outputs.dit);
00707         cpl_propertylist_append_double(qclists[i], "ESO QC DARK NONORM MED",
00708                 hawki_cal_dark_outputs.master_dark_med[i] * hawki_cal_dark_outputs.dit);
00709         cpl_propertylist_append_double(qclists[i], "ESO QC DARK NONORM STDEV",
00710                 hawki_cal_dark_outputs.master_dark_stdev[i] * hawki_cal_dark_outputs.dit);
00711         if(hawki_cal_dark_config.error_tracking)
00712         {
00713             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR MEAN",
00714                  hawki_cal_dark_outputs.master_dark_error_mean[i]);
00715             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR MED",
00716                  hawki_cal_dark_outputs.master_dark_error_med[i]);
00717             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR STDEV",
00718                  hawki_cal_dark_outputs.master_dark_error_stdev[i]);
00719             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR NONORM MEAN",
00720                  hawki_cal_dark_outputs.master_dark_error_mean[i] * hawki_cal_dark_outputs.dit);
00721             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR NONORM MED",
00722                  hawki_cal_dark_outputs.master_dark_error_med[i] * hawki_cal_dark_outputs.dit);
00723             cpl_propertylist_append_double(qclists[i], "ESO QC DARK ERR NONORM STDEV",
00724                  hawki_cal_dark_outputs.master_dark_error_stdev[i] * hawki_cal_dark_outputs.dit);
00725         }
00726         for (j=0 ; j<HAWKI_NB_VC ; j++) {
00727             sprintf(sval, "ESO QC DARK VC%d MEAN", j+1) ;
00728             cpl_propertylist_append_double(qclists[i], sval,
00729                     hawki_cal_dark_outputs.vc_mean[i][j]) ;
00730             sprintf(sval, "ESO QC DARK VC%d MED", j+1) ;
00731             cpl_propertylist_append_double(qclists[i], sval,
00732                     hawki_cal_dark_outputs.vc_med[i][j]) ;
00733             sprintf(sval, "ESO QC DARK VC%d STDEV", j+1) ;
00734             cpl_propertylist_append_double(qclists[i], sval,
00735                     hawki_cal_dark_outputs.vc_stdev[i][j]) ;
00736         }
00737         for (j=0 ; j<cpl_vector_get_size(rons[i]) ; j++) {
00738             sprintf(sval, "ESO QC RON%d", j+1) ;
00739             cpl_propertylist_append_double(qclists[i], sval,
00740                     cpl_vector_get(rons[i], j)) ;
00741         } 
00742         cpl_propertylist_append_double(qclists[i], "ESO QC RON MEAN",
00743                 cpl_vector_get_mean(rons[i])) ;
00744         cpl_propertylist_append_double(qclists[i], "ESO QC RON MED",
00745                 cpl_vector_get_median_const(rons[i])) ;
00746         cpl_propertylist_append_double(qclists[i], "ESO QC RON STDEV",
00747                 cpl_vector_get_stdev(rons[i])) ;
00748         cpl_propertylist_append_double(qclists[i], "ESO QC DATANCOM",
00749                 cpl_frameset_get_size(set)) ;
00750        
00751         /* Propagate some keywords from input raw frame extensions */
00752         ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
00753         inputlist = cpl_propertylist_load_regexp(
00754                 cpl_frame_get_filename(ref_frame), ext_nb, 
00755                 HAWKI_HEADER_EXT_FORWARD, 0) ;
00756         cpl_propertylist_append(qclists[i], inputlist) ; 
00757         cpl_propertylist_delete(inputlist) ;
00758     }
00759     /* Statistics of the raw images in the QC */
00760     hawki_image_stats_stats(raw_dark_stats, qclists);
00761 
00762     /* Write the dark image */
00763     hawki_imagelist_save(set,
00764                          parlist,
00765                          used_frames, 
00766                          master_dark, 
00767                          recipe_name,
00768                          HAWKI_CALPRO_DARK, 
00769                          HAWKI_PROTYPE_DARK,
00770                          NULL,
00771                          (const cpl_propertylist**)qclists,
00772                          "hawki_cal_dark.fits") ;
00773 
00774     /* Write the dark image error */
00775     if(master_dark_err != NULL)
00776     {
00777         hawki_imagelist_save(set,
00778                              parlist,
00779                              used_frames, 
00780                              master_dark_err, 
00781                              recipe_name,
00782                              HAWKI_CALPRO_DARK_ERR, 
00783                              HAWKI_PROTYPE_DARK_ERR,
00784                              NULL,
00785                              NULL,
00786                              "hawki_cal_dark_err.fits") ;
00787     }
00788 
00789     /* Write the bpmdark pixels image */
00790     hawki_imagelist_save(set,
00791                          parlist,
00792                          used_frames, 
00793                          bpmdark, 
00794                          recipe_name,
00795                          HAWKI_CALPRO_BPM_HOT, 
00796                          HAWKI_PROTYPE_BPM,
00797                          NULL,
00798                          NULL,
00799                          "hawki_cal_dark_bpmdark.fits") ;
00800 
00801     
00802     /* Write the table with the statistics */
00803     hawki_tables_save(set,
00804                       parlist,
00805                       used_frames,
00806                       (const cpl_table **)raw_dark_stats,
00807                       recipe_name,
00808                       HAWKI_CALPRO_DARK_STATS,
00809                       HAWKI_PROTYPE_DARK_STATS,
00810                       NULL,
00811                       NULL,
00812                       "hawki_cal_dark_stats.fits") ;
00813 
00814     /* Free and return */
00815     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
00816         cpl_propertylist_delete(qclists[i]) ;
00817     }
00818     cpl_free(qclists) ;
00819     if(!cpl_errorstate_is_equal(error_prevstate))
00820     {
00821         cpl_errorstate_set(CPL_ERROR_NONE);
00822         return -1;
00823     }
00824     return  0;
00825 }
00826 
00827 static int hawki_cal_dark_retrieve_input_param
00828 (cpl_parameterlist * parlist)
00829 {
00830     cpl_parameter       *   par ;
00831     const char          *   sval ;
00832     cpl_errorstate          error_prevstate = cpl_errorstate_get();
00833     
00834     /* Retrieve input parameters */
00835     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.sigma") ;
00836     hawki_cal_dark_config.sigma = cpl_parameter_get_double(par) ;
00837     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.hsize") ;
00838     hawki_cal_dark_config.hsize = cpl_parameter_get_int(par) ;
00839     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.nsamples") ;
00840     hawki_cal_dark_config.nsamples = cpl_parameter_get_int(par) ;
00841     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.zone") ;
00842     sval = cpl_parameter_get_string(par) ;
00843     if (sscanf(sval, "%d,%d,%d,%d",
00844                     &hawki_cal_dark_config.llx,
00845                     &hawki_cal_dark_config.lly,
00846                     &hawki_cal_dark_config.urx,
00847                     &hawki_cal_dark_config.ury)!=4) {
00848         return -1 ;
00849     }
00850     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.gain") ;
00851     hawki_cal_dark_config.gain = cpl_parameter_get_double(par);
00852     par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_dark.ron") ;
00853     hawki_cal_dark_config.ron = cpl_parameter_get_double(par);
00854     hawki_cal_dark_config.error_tracking = 0; 
00855     if(hawki_cal_dark_config.gain > 0 && hawki_cal_dark_config.ron > 0)
00856         hawki_cal_dark_config.error_tracking = 1; 
00857     
00858     if(!cpl_errorstate_is_equal(error_prevstate))
00859         return -1;
00860 
00861     return 0;
00862 }
00863 
00864 void hawki_cal_dark_initialise_qc(void)
00865 {
00866     int idet;
00867     int j;
00868     
00869     for(idet=0; idet<HAWKI_NB_DETECTORS; idet++) 
00870     {
00871         hawki_cal_dark_outputs.nb_badpix[idet] = -1 ;
00872         hawki_cal_dark_outputs.master_dark_mean[idet] = -1.0 ;
00873         hawki_cal_dark_outputs.master_dark_med[idet] = -1.0 ;
00874         hawki_cal_dark_outputs.master_dark_stdev[idet] = -1.0 ;
00875         hawki_cal_dark_outputs.master_dark_error_mean[idet] = -1.0 ;
00876         hawki_cal_dark_outputs.master_dark_error_med[idet] = -1.0 ;
00877         hawki_cal_dark_outputs.master_dark_error_stdev[idet] = -1.0 ;
00878         for (j=0 ; j<HAWKI_NB_VC ; j++) 
00879         {
00880             hawki_cal_dark_outputs.vc_mean[idet][j] = -1.0 ;
00881             hawki_cal_dark_outputs.vc_med[idet][j] = -1.0 ;
00882             hawki_cal_dark_outputs.vc_stdev[idet][j] = -1.0 ;
00883         }
00884     }
00885 }