HAWKI Pipeline Reference Manual 1.8.12
hawki_sci_jitter.c
00001 /* $Id: hawki_sci_jitter.c,v 1.34 2013/01/15 09:58:25 cgarcia Exp $
00002  *
00003  * This file is part of the HAWKI Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: cgarcia $
00023  * $Date: 2013/01/15 09:58:25 $
00024  * $Revision: 1.34 $
00025  * $Name: hawki-1_8_12 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <cpl.h>
00038 #include <string.h>
00039 
00040 #include "irplib_utils.h"
00041 #include "irplib_calib.h"
00042 
00043 #include "hawki_utils.h"
00044 #include "hawki_calib.h"
00045 #include "hawki_load.h"
00046 #include "hawki_save.h"
00047 #include "hawki_pfits.h"
00048 #include "hawki_dfs.h"
00049 #include "hawki_saa.h"
00050 #include "hawki_bkg.h"
00051 #include "hawki_distortion.h"
00052 #include "hawki_properties_tel.h"
00053 #include "hawki_image_stats.h"
00054 #include "hawki_obj_det.h"
00055 
00056 /*-----------------------------------------------------------------------------
00057                                 Define
00058  -----------------------------------------------------------------------------*/
00059 
00060 #define NEGLIG_OFF_DIFF     0.1
00061 #define SQR(x) ((x)*(x))
00062 
00063 /*-----------------------------------------------------------------------------
00064                             Functions prototypes
00065  -----------------------------------------------------------------------------*/
00066 
00067 #ifdef __cplusplus
00068 extern "C"
00069 #endif
00070 int cpl_plugin_get_info(cpl_pluginlist * list);
00071 
00072 static int hawki_sci_jitter_create(cpl_plugin *) ;
00073 static int hawki_sci_jitter_exec(cpl_plugin *) ;
00074 static int hawki_sci_jitter_destroy(cpl_plugin *) ;
00075 static int hawki_sci_jitter(cpl_parameterlist *, cpl_frameset *) ;
00076 
00077 static int hawki_sci_jitter_retrieve_input_param
00078 (cpl_parameterlist  *  parlist);
00079 static cpl_image ** hawki_sci_jitter_reduce
00080 (cpl_frameset      *   jitters,
00081  cpl_frameset      *   sky,
00082  const char        *   flat,
00083  const char        *   dark,
00084  const char        *   bpm,
00085  cpl_table         **  bkg_stats);
00086 static int hawki_sci_jitter_sky
00087 (cpl_imagelist   *   jitters,
00088  cpl_imagelist   *   skys,
00089  cpl_table       **  bkg_stats,
00090  int                 idet);
00091 static int hawki_sci_jitter_sky_running
00092 (cpl_imagelist *  in,
00093  cpl_table     ** bkg_stats,
00094  int              idet); 
00095 static cpl_image ** hawki_sci_jitter_saa(cpl_imagelist **, cpl_bivector *, 
00096         double *, double *);
00097 static int hawki_sci_jitter_qc
00098 (cpl_frameset *   science_frames,
00099  cpl_image   **   combined, 
00100  cpl_table   **   obj_charac);
00101 static int hawki_sci_jitter_read_calib
00102 (const char *  flat,
00103  const char *  dark,
00104  const char *  bpm,
00105  cpl_image  ** flat_image,
00106  cpl_image  ** dark_image,
00107  cpl_image  ** bpm_image,
00108  int           idet);
00109 static int hawki_sci_jitter_save
00110 (cpl_image           **  combined,
00111  cpl_image           *   stitched,
00112  cpl_table           **  objs_charac,
00113  cpl_table           **  raw_jitter_stats,
00114  cpl_table           **  bkg_stats,
00115  const cpl_table     *   raw_obj_tel_info,
00116  cpl_frameset        *   science_frames,
00117  cpl_frameset        *   calib_frames,
00118  cpl_parameterlist   *   parlist,
00119  cpl_frameset        *   set);
00120 int hawki_sci_jitter_whole_image_algo
00121 (cpl_frameset       *  obj,
00122  cpl_table          ** raw_jitter_stats,
00123  cpl_table          *  raw_obj_tel_info,
00124  cpl_parameterlist  *  parlist,
00125  cpl_frameset       *  recipe_set);
00126 int hawki_sci_jitter_save_stats
00127 (cpl_table          ** raw_jitter_stats,
00128  cpl_table          *  raw_obj_tel_info,
00129  cpl_frameset       *  jitter_frames,
00130  cpl_parameterlist  *  parlist,
00131  cpl_frameset       *  recipe_set);
00132 
00133 /*-----------------------------------------------------------------------------
00134                             Static variables
00135  -----------------------------------------------------------------------------*/
00136 
00137 static struct 
00138 {
00139     /* Inputs */
00140     const char      *   offsets ;
00141     const char      *   objects ;
00142     int                 offset_max ;
00143     int                 sky_minnb ;
00144     int                 sky_halfw ;
00145     int                 sky_rejmin ;
00146     int                 sky_rejmax ;
00147     int                 refine ;
00148     int                 sx ;
00149     int                 sy ;
00150     int                 mx ;
00151     int                 my ;
00152     int                 borders ;
00153     cpl_geom_combine    comb_meth ;
00154     int                 rej_low ;
00155     int                 rej_high ;
00156     int                 max_njitter;
00157 } hawki_sci_jitter_config;
00158 
00159 static struct 
00160 {
00161     /* Outputs */
00162     double          pixscale;
00163     double          dit;
00164     double          mean_airmass;
00165     double          iq[HAWKI_NB_DETECTORS];
00166     int             nbobjs[HAWKI_NB_DETECTORS];
00167     double          fwhm_pix[HAWKI_NB_DETECTORS];
00168     double          fwhm_arcsec[HAWKI_NB_DETECTORS];
00169     double          fwhm_mode[HAWKI_NB_DETECTORS];
00170     double          combined_pos_x[HAWKI_NB_DETECTORS];
00171     double          combined_pos_y[HAWKI_NB_DETECTORS];
00172     double          combined_cumoffset_x[HAWKI_NB_DETECTORS];
00173     double          combined_cumoffset_y[HAWKI_NB_DETECTORS];
00174     int             ncomb[HAWKI_NB_DETECTORS];
00175 } hawki_sci_jitter_output;
00176 
00177 static char hawki_sci_jitter_description[] =
00178 "hawki_sci_jitter -- hawki imaging jitter recipe.\n\n"
00179 "The input of the recipe files listed in the Set Of Frames (sof-file)\n"
00180 "must be tagged as:\n"
00181 "raw-file.fits "HAWKI_IMG_JITTER_RAW" or\n"
00182 "raw-file.fits "HAWKI_IMG_JITTER_SKY_RAW" or\n"
00183 "flat-file.fits "HAWKI_CALPRO_FLAT" or\n"
00184 "dark-file.fits "HAWKI_CALPRO_DARK" \n"
00185 "bpm-file.fits "HAWKI_CALPRO_BPM"\n"
00186 "distortion_x-file.fits "HAWKI_CALPRO_DISTORTION_X"\n"
00187 "distortion_y-file.fits "HAWKI_CALPRO_DISTORTION_Y"\n\n"
00188 "The recipe creates as an output:\n"
00189 "hawki_sci_jitter.fits ("HAWKI_CALPRO_COMBINED")\n"
00190 "hawki_sci_jitter_stitched.fits ("HAWKI_CALPRO_STITCHED")\n"
00191 "hawki_sci_jitter_stars.fits ("HAWKI_CALPRO_OBJ_PARAM"): Detected objects properties\n"
00192 "hawki_sci_jitter_stats.fits ("HAWKI_CALPRO_JITTER_STATS"): Stats of the individual images\n"
00193 "hawki_sci_jitter_bkg_stats.fits ("HAWKI_CALPRO_JITTER_BKG_STATS"): Statistics on the bkg\n\n"
00194 "The recipe performs the following steps:\n"
00195 "1) Frame statistics\n"
00196 "2) Basic reduction (using "HAWKI_CALPRO_FLAT" and "HAWKI_CALPRO_BPM")\n"
00197 "3) Background computation (the algorithm depends on parameter --sky_par) \n"
00198 "4) Offset refinement (uses parameters --off, --refine and --xcorr)\n"
00199 "5) Stacking of jitter frames (uses --comb_meth, --rej,\n"
00200 "   --offset_max, --borders, --max_njitter)\n"
00201 "6) Stitching of the four detectors into one image\n"
00202 "7) Object detection in the stacked image\n\n"
00203 "Return code:\n"
00204 "esorex exits with an error code of 0 if the recipe completes successfully\n"
00205 "or 1 otherwise";
00206 
00207 /*-----------------------------------------------------------------------------
00208                                 Functions code
00209  -----------------------------------------------------------------------------*/
00210 
00211 /*----------------------------------------------------------------------------*/
00219 /*----------------------------------------------------------------------------*/
00220 int cpl_plugin_get_info(cpl_pluginlist * list)
00221 {
00222     cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
00223     cpl_plugin  *   plugin = &recipe->interface ;
00224 
00225     cpl_plugin_init(plugin,
00226                     CPL_PLUGIN_API,
00227                     HAWKI_BINARY_VERSION,
00228                     CPL_PLUGIN_TYPE_RECIPE,
00229                     "hawki_sci_jitter",
00230                     "Jitter recipe",
00231                     hawki_sci_jitter_description,
00232                     "Cesar Enrique Garcia",
00233                     PACKAGE_BUGREPORT,
00234                     hawki_get_license(),
00235                     hawki_sci_jitter_create,
00236                     hawki_sci_jitter_exec,
00237                     hawki_sci_jitter_destroy) ;
00238 
00239     cpl_pluginlist_append(list, plugin) ;
00240     
00241     return 0;
00242 }
00243 
00244 /*----------------------------------------------------------------------------*/
00253 /*----------------------------------------------------------------------------*/
00254 static int hawki_sci_jitter_create(cpl_plugin * plugin)
00255 {
00256     cpl_recipe      * recipe ;
00257     cpl_parameter   * p ;
00258 
00259     /* Get the recipe out of the plugin */
00260     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00261         recipe = (cpl_recipe *)plugin ;
00262     else return -1 ;
00263 
00264     /* Create the parameters list in the cpl_recipe object */
00265     recipe->parameters = cpl_parameterlist_new() ;
00266     if (recipe->parameters == NULL)
00267         return 1;
00268 
00269     /* Fill the parameters list */
00270     /* --offsets */
00271     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.offsets", 
00272             CPL_TYPE_STRING, "offsets file", "hawki.hawki_sci_jitter", NULL) ;
00273     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offsets") ;
00274     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00275     cpl_parameterlist_append(recipe->parameters, p) ;
00276 
00277     /* --objects */
00278     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.objects", 
00279             CPL_TYPE_STRING, "objects file", "hawki.hawki_sci_jitter", NULL) ;
00280     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "objects") ;
00281     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00282     cpl_parameterlist_append(recipe->parameters, p) ;
00283 
00284     /* --offset_max */
00285     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.offset_max",
00286                                 CPL_TYPE_INT,
00287                                 "Maximum offset allowed",
00288                                 "hawki.hawki_sci_jitter",
00289                                 1500) ;
00290     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset_max") ;
00291     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00292     cpl_parameterlist_append(recipe->parameters, p) ;
00293 
00294     /* --sky_par */
00295     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.sky_par",
00296                                 CPL_TYPE_STRING,
00297                                 "Rejection parameters for sky filtering",
00298                                 "hawki.hawki_sci_jitter",
00299                                 "10,7,3,3") ;
00300     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_par") ;
00301     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00302     cpl_parameterlist_append(recipe->parameters, p) ;
00303 
00304     /* --refine */
00305     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.refine",
00306             CPL_TYPE_BOOL, "refine offsets", "hawki.hawki_sci_jitter",
00307             FALSE);
00308     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "refine") ;
00309     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00310     cpl_parameterlist_append(recipe->parameters, p) ;
00311 
00312     /* --xcorr */
00313     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.xcorr",
00314                                 CPL_TYPE_STRING,
00315                                 "Cross correlation search and measure sizes",
00316                                 "hawki.hawki_sci_jitter",
00317                                 "20,20,25,25") ;
00318     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcorr") ;
00319     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00320     cpl_parameterlist_append(recipe->parameters, p) ;
00321 
00322     /* --comb_meth */
00323     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.comb_meth", 
00324             CPL_TYPE_STRING, "union / inter / first", "hawki.hawki_sci_jitter",
00325             "union") ;
00326     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "comb_meth") ;
00327     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00328     cpl_parameterlist_append(recipe->parameters, p) ;
00329   
00330     /* --rej */
00331     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.rej",
00332                                 CPL_TYPE_STRING,
00333                                 "Low and high number of rejected values",
00334                                 "hawki.hawki_sci_jitter",
00335                                 "1,1") ;
00336     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rej") ;
00337     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00338     cpl_parameterlist_append(recipe->parameters, p) ;
00339 
00340     /* --borders */
00341     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.borders",
00342                                 CPL_TYPE_INT,
00343                                 "Borders rejected",
00344                                 "hawki.hawki_sci_jitter",
00345                                 4) ;
00346     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "borders") ;
00347     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00348     cpl_parameterlist_append(recipe->parameters, p) ;
00349 
00350     /* --max_njitter */
00351     p = cpl_parameter_new_value("hawki.hawki_sci_jitter.max_njitter",
00352                                 CPL_TYPE_INT,
00353                                 "Maximum numbers of jitter frames to combine",
00354                                 "hawki.hawki_sci_jitter",
00355                                 -1);
00356     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "max_njitter");
00357     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00358     cpl_parameterlist_append(recipe->parameters, p);
00359 
00360     /* Return */
00361     return 0;
00362 }
00363 
00364 /*----------------------------------------------------------------------------*/
00370 /*----------------------------------------------------------------------------*/
00371 static int hawki_sci_jitter_exec(cpl_plugin * plugin)
00372 {
00373     cpl_recipe  *   recipe ;
00374 
00375     /* Get the recipe out of the plugin */
00376     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00377         recipe = (cpl_recipe *)plugin ;
00378     else return -1 ;
00379 
00380     /* Issue a banner */
00381     hawki_print_banner();
00382 
00383     return hawki_sci_jitter(recipe->parameters, recipe->frames) ;
00384 }
00385 
00386 /*----------------------------------------------------------------------------*/
00392 /*----------------------------------------------------------------------------*/
00393 static int hawki_sci_jitter_destroy(cpl_plugin * plugin)
00394 {
00395     cpl_recipe  *   recipe ;
00396 
00397     /* Get the recipe out of the plugin */
00398     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00399         recipe = (cpl_recipe *)plugin ;
00400     else return -1 ;
00401 
00402     cpl_parameterlist_delete(recipe->parameters) ;
00403     return 0 ;
00404 }
00405 
00406 /*----------------------------------------------------------------------------*/
00413 /*----------------------------------------------------------------------------*/
00414 static int hawki_sci_jitter(
00415         cpl_parameterlist   *   parlist, 
00416         cpl_frameset        *   framelist)
00417 {
00418     const char      *   flat;
00419     const char      *   dark;
00420     const char      *   bpm;
00421     const cpl_frame *   distx;
00422     const cpl_frame *   disty;
00423     cpl_frameset    *   jitterframes ;
00424     cpl_frameset    *   skyframes ;
00425     cpl_frameset    *   science_frames;
00426     cpl_frameset    *   calib_frames;
00427     cpl_image       **  combined ;
00428     cpl_table       **  obj_charac;
00429     cpl_table       **  raw_jitter_stats; 
00430     cpl_table       **  bkg_stats; 
00431     cpl_table       *   raw_obj_tel_info;
00432     cpl_image       *   stitched ;
00433     int                 i;
00434 
00435     /* Initialise */
00436     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 
00437     {
00438         hawki_sci_jitter_output.iq[i] = -1.0 ;
00439         hawki_sci_jitter_output.nbobjs[i] = -1 ;
00440         hawki_sci_jitter_output.fwhm_pix[i] = -1.0 ;
00441         hawki_sci_jitter_output.fwhm_arcsec[i] = -1.0 ;
00442         hawki_sci_jitter_output.fwhm_mode[i] = -1.0 ;
00443         hawki_sci_jitter_output.combined_pos_x[i] = -1.0 ;
00444         hawki_sci_jitter_output.combined_pos_y[i] = -1.0 ;
00445         hawki_sci_jitter_output.combined_cumoffset_x[i] = -1.0 ;
00446         hawki_sci_jitter_output.combined_cumoffset_y[i] = -1.0 ;
00447     }
00448     hawki_sci_jitter_output.pixscale = -1.0 ;
00449     hawki_sci_jitter_output.dit = -1.0 ;
00450     hawki_sci_jitter_config.offsets = NULL ;
00451     hawki_sci_jitter_config.objects = NULL ;
00452     calib_frames = cpl_frameset_new();
00453 
00454     /* Retrieve input parameters */
00455     if(hawki_sci_jitter_retrieve_input_param(parlist))
00456     {
00457         cpl_msg_error(cpl_func, "Wrong parameters");
00458         cpl_frameset_delete(calib_frames);
00459         return -1;
00460     }
00461 
00462     /* Identify the RAW and CALIB frames in the input frameset */
00463     if (hawki_dfs_set_groups(framelist)) {
00464         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames") ;
00465         cpl_frameset_delete(calib_frames);
00466         return -1 ;
00467     }
00468 
00469     /* Retrieve calibration data */
00470     flat   = hawki_extract_first_filename(framelist, HAWKI_CALPRO_FLAT) ;
00471     dark   = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK);
00472     bpm    = hawki_extract_first_filename(framelist, HAWKI_CALPRO_BPM) ;
00473     distx  = cpl_frameset_find_const(framelist, HAWKI_CALPRO_DISTORTION_X);
00474     disty  = cpl_frameset_find_const(framelist, HAWKI_CALPRO_DISTORTION_Y);
00475     if((distx == NULL && disty !=NULL) || (distx != NULL && disty ==NULL))
00476     {
00477         cpl_msg_error(cpl_func, "Both distortion in X (%s) and Y (%s) must be provided",
00478                       HAWKI_CALPRO_DISTORTION_X, HAWKI_CALPRO_DISTORTION_Y);
00479         cpl_frameset_delete(calib_frames);
00480         return -1 ;
00481     }
00482     if(flat)
00483         cpl_frameset_insert(calib_frames, cpl_frame_duplicate(
00484                 cpl_frameset_find_const(framelist, HAWKI_CALPRO_FLAT)));
00485     if(dark)
00486         cpl_frameset_insert(calib_frames, cpl_frame_duplicate(
00487                 cpl_frameset_find_const(framelist, HAWKI_CALPRO_DARK)));
00488     if(bpm)
00489         cpl_frameset_insert(calib_frames, cpl_frame_duplicate(
00490                 cpl_frameset_find_const(framelist, HAWKI_CALPRO_BPM)));
00491     if(distx)
00492     {
00493         cpl_frameset_insert(calib_frames, cpl_frame_duplicate(distx));
00494         cpl_frameset_insert(calib_frames, cpl_frame_duplicate(disty));
00495     }
00496         
00497 
00498     /* Retrieve raw frames */
00499     jitterframes = hawki_extract_frameset(framelist, HAWKI_IMG_JITTER_RAW) ;
00500     if (jitterframes == NULL) {
00501         cpl_msg_error(cpl_func, "Cannot find jitter frames in the input list (%s)",
00502                       HAWKI_IMG_JITTER_RAW);
00503         cpl_frameset_delete(calib_frames);
00504         return -1 ;
00505     }
00506     science_frames = cpl_frameset_duplicate(jitterframes);
00507     skyframes = hawki_extract_frameset(framelist, HAWKI_IMG_JITTER_SKY_RAW) ;
00508     if (skyframes != NULL) 
00509     {
00510         int isky;
00511         for(isky = 0; isky< cpl_frameset_get_size(skyframes); ++isky)
00512             cpl_frameset_insert(science_frames, 
00513                     cpl_frame_duplicate(cpl_frameset_get_frame(skyframes, isky)));
00514     }
00515     
00516     /* Create the statistics table */
00517     raw_jitter_stats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *));
00518     for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00519     {
00520         raw_jitter_stats[i] = cpl_table_new(cpl_frameset_get_size(jitterframes));
00521     }
00522     hawki_image_stats_initialize(raw_jitter_stats);
00523     bkg_stats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *));
00524     for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00525     {
00526         bkg_stats[i] = cpl_table_new(cpl_frameset_get_size(jitterframes));
00527     }
00528     hawki_image_stats_initialize(bkg_stats);
00529 
00530     /* Create the  telescope statistics parameters from the raw images */
00531     raw_obj_tel_info = cpl_table_new(cpl_frameset_get_size(jitterframes));
00532     /* Add the proper columns of the pcs table */
00533     if(hawki_prop_tel_initialize(raw_obj_tel_info))
00534     {
00535         cpl_msg_error(cpl_func,"Could not initialize the pcs table");
00536         cpl_frameset_delete(jitterframes) ;
00537         for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00538         {
00539             cpl_table_delete(raw_jitter_stats[i]) ;
00540             cpl_table_delete(bkg_stats[i]) ;
00541         }
00542         cpl_free(raw_jitter_stats) ;
00543         cpl_free(bkg_stats) ;
00544         cpl_table_delete(raw_obj_tel_info);
00545         if (skyframes) cpl_frameset_delete(skyframes) ;
00546         cpl_frameset_delete(calib_frames);
00547         cpl_msg_indent_less() ;
00548         return -1;
00549     }
00550     
00551     /* Do the algorithms that need the whole image */
00552     hawki_sci_jitter_whole_image_algo(jitterframes,
00553                                       raw_jitter_stats,
00554                                       raw_obj_tel_info,
00555                                       parlist,
00556                                       framelist);
00557 
00558     /* Apply the reduction */
00559     /* Do the algorithms that can be applied to subsection of the images */
00560     cpl_msg_info(cpl_func, "Apply the data combination") ;
00561     cpl_msg_indent_more() ;
00562     if ((combined = hawki_sci_jitter_reduce(jitterframes, skyframes, flat, dark,
00563                     bpm, bkg_stats)) == NULL) 
00564     {
00565         cpl_msg_error(cpl_func, "Cannot recombine the data");
00566         cpl_frameset_delete(jitterframes);
00567         for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00568         {
00569             cpl_table_delete(raw_jitter_stats[i]) ;
00570             cpl_table_delete(bkg_stats[i]) ;
00571         }
00572         cpl_free(raw_jitter_stats) ;
00573         cpl_free(bkg_stats) ;
00574         cpl_table_delete(raw_obj_tel_info);
00575         if (skyframes) cpl_frameset_delete(skyframes) ;
00576         cpl_frameset_delete(calib_frames);
00577         cpl_msg_indent_less() ;
00578         return -1 ;
00579     }
00580     cpl_msg_indent_less() ;
00581 
00582     /* Compute QC parameters from the combined image */
00583     cpl_msg_info(cpl_func, "Compute QC parameters from the combined images") ;
00584     cpl_msg_indent_more() ;
00585     obj_charac = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table*)) ;
00586     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00587     {
00588         obj_charac[i] = cpl_table_new(0);
00589     }
00590     if ((hawki_sci_jitter_qc(jitterframes, combined, obj_charac)) != 0)
00591     {
00592         cpl_msg_warning(cpl_func, "Cannot compute all parameters") ;
00593     }
00594     cpl_msg_indent_less();
00595     cpl_frameset_delete(jitterframes);
00596     if (skyframes) cpl_frameset_delete(skyframes);
00597 
00598  
00599     /* Correct for the distortion */
00600     if (distx && disty)
00601     {
00602         cpl_msg_info(cpl_func, "Applying the distortion correction") ;
00603         cpl_msg_indent_more() ;
00604         if (hawki_distortion_correct_alldetectors(combined, distx, disty) == -1) 
00605         {
00606             cpl_msg_error(cpl_func, "Cannot correct the distortion") ;
00607             for (i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00608                 cpl_image_delete(combined[i]) ;
00609             cpl_free(combined) ;
00610             if (obj_charac) {
00611                 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 
00612                     cpl_table_delete(obj_charac[i]) ;
00613                 cpl_free(obj_charac);
00614             }
00615             cpl_table_delete(raw_obj_tel_info);
00616             for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00617             {
00618                 cpl_table_delete(raw_jitter_stats[i]);
00619                 cpl_table_delete(bkg_stats[i]);
00620             }
00621             cpl_free(raw_jitter_stats);
00622             cpl_free(bkg_stats);
00623             cpl_frameset_delete(calib_frames);
00624             cpl_frameset_delete(science_frames);
00625             cpl_msg_indent_less() ;
00626             return -1;
00627         }
00628         cpl_msg_indent_less() ;
00629     }
00630 
00631     /* Compute the stitched image */
00632     cpl_msg_info(cpl_func, "Compute the stiched image") ;
00633     if ((stitched = hawki_images_stitch(combined, 
00634                     hawki_sci_jitter_output.combined_pos_x,
00635                     hawki_sci_jitter_output.combined_pos_y)) == NULL)
00636     {
00637         cpl_msg_error(cpl_func, "Cannot stitch the images") ;
00638         for (i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00639             cpl_image_delete(combined[i]) ;
00640         cpl_free(combined) ;
00641         if (obj_charac) {
00642             for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 
00643                 cpl_table_delete(obj_charac[i]) ;
00644             cpl_free(obj_charac);
00645         }
00646         cpl_table_delete(raw_obj_tel_info);
00647         for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00648         {
00649             cpl_table_delete(raw_jitter_stats[i]);
00650             cpl_table_delete(bkg_stats[i]);
00651         }
00652         cpl_free(raw_jitter_stats);
00653         cpl_free(bkg_stats);
00654         cpl_frameset_delete(calib_frames);
00655         cpl_frameset_delete(science_frames);
00656         return -1;
00657     }
00658 
00659     /* Save the products */
00660     cpl_msg_info(cpl_func, "Save the products") ;
00661     cpl_msg_indent_more() ;
00662     if (hawki_sci_jitter_save(combined, stitched, obj_charac,
00663                               raw_jitter_stats, bkg_stats, 
00664                               raw_obj_tel_info,
00665                               science_frames,
00666                               calib_frames,
00667                               parlist, framelist) == -1)
00668         cpl_msg_warning(cpl_func,"Some data could not be saved. "
00669                                  "Check permisions or disk space");
00670     
00671     /* Return */
00672     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00673         cpl_image_delete(combined[i]) ;
00674     cpl_free(combined) ;
00675     if (obj_charac) {
00676         for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 
00677             cpl_table_delete(obj_charac[i]) ;
00678         cpl_free(obj_charac);
00679     }
00680     if (stitched) cpl_image_delete(stitched) ;
00681     cpl_table_delete(raw_obj_tel_info);
00682     for( i=0 ; i<HAWKI_NB_DETECTORS ; i++)
00683     {
00684         cpl_table_delete(raw_jitter_stats[i]);
00685         cpl_table_delete(bkg_stats[i]);
00686     }
00687     cpl_free(raw_jitter_stats);
00688     cpl_free(bkg_stats);
00689     cpl_frameset_delete(calib_frames);
00690     cpl_frameset_delete(science_frames);
00691     cpl_msg_indent_less() ;
00692 
00693     /* Return */
00694     if (cpl_error_get_code())
00695     {
00696         cpl_msg_error(cpl_func,
00697                       "HAWK-I pipeline could not recover from previous errors");
00698         return -1 ;
00699     }
00700     else return 0 ;
00701 }
00702 
00703 int hawki_sci_jitter_retrieve_input_param
00704 (cpl_parameterlist  *  parlist)
00705 {
00706     cpl_parameter   *   par ;
00707     const char      *   sval ;
00708     par = NULL ;
00709     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.offsets");
00710     hawki_sci_jitter_config.offsets = cpl_parameter_get_string(par);
00711     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.objects");
00712     hawki_sci_jitter_config.objects = cpl_parameter_get_string(par);
00713     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.offset_max");
00714     hawki_sci_jitter_config.offset_max = cpl_parameter_get_int(par);
00715     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.sky_par");
00716     sval = cpl_parameter_get_string(par);
00717     if (sscanf(sval, "%d,%d,%d,%d",
00718                &hawki_sci_jitter_config.sky_minnb,
00719                &hawki_sci_jitter_config.sky_halfw,
00720                &hawki_sci_jitter_config.sky_rejmin,
00721                &hawki_sci_jitter_config.sky_rejmax)!=4)
00722     {
00723         return -1;
00724     }
00725     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.xcorr");
00726     sval = cpl_parameter_get_string(par);
00727     if (sscanf(sval, "%d,%d,%d,%d",
00728                &hawki_sci_jitter_config.sx,
00729                &hawki_sci_jitter_config.sy,
00730                &hawki_sci_jitter_config.mx,
00731                &hawki_sci_jitter_config.my)!=4)
00732     {
00733         return -1;
00734     }
00735     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.refine");
00736     hawki_sci_jitter_config.refine = cpl_parameter_get_bool(par);
00737     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.comb_meth");
00738     sval = cpl_parameter_get_string(par);
00739     if (!strcmp(sval, "union"))
00740     hawki_sci_jitter_config.comb_meth = CPL_GEOM_UNION;
00741     else if (!strcmp(sval, "inter"))
00742     hawki_sci_jitter_config.comb_meth = CPL_GEOM_INTERSECT;
00743     else if (!strcmp(sval, "first"))
00744     hawki_sci_jitter_config.comb_meth = CPL_GEOM_FIRST;
00745     else
00746     {
00747         cpl_msg_error(cpl_func, "Invalid combine method specified");
00748         return -1;
00749     }
00750     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.borders");
00751     hawki_sci_jitter_config.borders = cpl_parameter_get_int(par);
00752     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.rej");
00753     sval = cpl_parameter_get_string(par);
00754     if (sscanf(sval, "%d,%d",
00755                &hawki_sci_jitter_config.rej_low,
00756                &hawki_sci_jitter_config.rej_high)!=2)
00757     {
00758         return -1;
00759     }
00760     par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.max_njitter");
00761     hawki_sci_jitter_config.max_njitter = cpl_parameter_get_int(par);
00762     return 0;
00763 }
00764 
00765 
00766 
00767 /*----------------------------------------------------------------------------*/
00778 /*----------------------------------------------------------------------------*/
00779 static cpl_image ** hawki_sci_jitter_reduce
00780 (cpl_frameset      *   jitters,
00781  cpl_frameset      *   sky,
00782  const char        *   flat,
00783  const char        *   dark,
00784  const char        *   bpm,
00785  cpl_table         **  bkg_stats)
00786 {
00787     cpl_frame           *   frame ;
00788     cpl_propertylist    *   plist ;
00789     cpl_image           **  comb_chip ;
00790     cpl_image           **  combined ;
00791     cpl_bivector        *   offsets ;
00792     cpl_vector          *   offset_x_sort; 
00793     cpl_vector          *   offset_y_sort; 
00794     double              *   offs_est_x ;
00795     double              *   offs_est_y ;
00796     double                  off_0_x;
00797     double                  off_0_y;
00798     double                  max_x, max_y ;
00799     int                     idet;
00800     int                     ioff;
00801     
00802     /* Get the header infos */
00803     frame = cpl_frameset_get_frame(jitters, 0) ;
00804     plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0) ;
00805     hawki_sci_jitter_output.pixscale = hawki_pfits_get_pixscale(plist) ;
00806     hawki_sci_jitter_output.dit = hawki_pfits_get_dit(plist) ;
00807     cpl_propertylist_delete(plist) ;
00808     if (cpl_error_get_code()) {
00809         cpl_msg_error(cpl_func, "Missing keyword in FITS header") ;
00810         return NULL ;
00811     }
00812 
00813     /* Check that DIT/NDIT and NDSAMPLES are the same for all the frames */
00814     if(!hawki_utils_check_equal_double_keys(jitters, &hawki_pfits_get_dit) ||
00815        !hawki_utils_check_equal_int_keys(jitters, &hawki_pfits_get_ndit)||
00816        !hawki_utils_check_equal_int_keys(jitters, &hawki_pfits_get_ndsamples))
00817     {
00818         cpl_msg_error(__func__, "Not all input science have the same "
00819                 "DIT/NDIT/NDSAMPLES values");
00820         cpl_msg_indent_less() ;
00821         return NULL;        
00822     }
00823     
00824     /* Check that pointing is the same for all the frames */
00825     if(!hawki_utils_check_equal_double_keys(jitters, &hawki_pfits_get_targ_alpha_hhmmss) ||
00826        !hawki_utils_check_equal_double_keys(jitters, &hawki_pfits_get_targ_delta_ddmmss))
00827     {
00828         cpl_msg_error(__func__, "Not all input science frames belong to the "
00829                 "same pointing/target. Check keywords TEL TARG ALPHA/DELTA");
00830         cpl_msg_indent_less() ;
00831         return NULL;        
00832     }
00833     
00834     /* Get the offsets */
00835     if ((offsets = hawki_get_header_tel_offsets(jitters)) == NULL) {
00836         cpl_msg_error(cpl_func, "Cannot load the offsets") ;
00837         return NULL ;
00838     }
00839     offs_est_x = cpl_bivector_get_x_data(offsets) ;
00840     offs_est_y = cpl_bivector_get_y_data(offsets) ;
00841 
00842     /* Print the header offsets */
00843     for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) {
00844         cpl_msg_info(cpl_func, "Telescope offsets (Frame %d): %g %g", ioff+1,
00845                 offs_est_x[ioff], offs_est_y[ioff]) ;
00846     }
00847 
00848     /* Subtract the first offset to all offsets */
00849     off_0_x = -offs_est_x[0]; // This is to get the cpl convention
00850     off_0_y = -offs_est_y[0];
00851     for (ioff=1 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) 
00852     {
00853         offs_est_x[ioff] -= offs_est_x[0] ;
00854         offs_est_y[ioff] -= offs_est_y[0] ;
00855     }
00856     offs_est_x[0] = offs_est_y[0] = 0.00 ;
00857 
00858     /* Check if the max offset is not too big */
00859     /* The criteria is that for a given frame, the closest frame cannot be 
00860      * further than hawki_sci_jitter_config.offset_max (in both dimensions) */
00861     offset_x_sort = cpl_vector_duplicate(cpl_bivector_get_x(offsets));
00862     offset_y_sort = cpl_vector_duplicate(cpl_bivector_get_y(offsets));
00863     cpl_vector_sort(offset_x_sort, +1);
00864     cpl_vector_sort(offset_y_sort, +1);
00865     for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) - 1 ; ioff++)
00866     {
00867         double diff_x, diff_y;
00868         diff_x = cpl_vector_get(offset_x_sort,ioff+1)-cpl_vector_get(offset_x_sort,ioff);
00869         cpl_vector_set(offset_x_sort, ioff, diff_x);
00870         diff_y = cpl_vector_get(offset_y_sort,ioff+1)-cpl_vector_get(offset_y_sort,ioff);
00871         cpl_vector_set(offset_y_sort, ioff, diff_y);
00872     }
00873     cpl_vector_set(offset_x_sort, cpl_bivector_get_size(offsets)-1, 0.);
00874     cpl_vector_set(offset_y_sort, cpl_bivector_get_size(offsets)-1, 0.);
00875     max_x = cpl_vector_get_max(offset_x_sort);
00876     max_y = cpl_vector_get_max(offset_y_sort);
00877     cpl_vector_delete(offset_x_sort);
00878     cpl_vector_delete(offset_y_sort);
00879     
00880     if (max_x > hawki_sci_jitter_config.offset_max || 
00881         max_y > hawki_sci_jitter_config.offset_max) 
00882     {
00883         cpl_msg_error(cpl_func, "Sorry, no support for frames further than %d from its closest neighbour",
00884                 hawki_sci_jitter_config.offset_max) ;
00885         cpl_bivector_delete(offsets);
00886         return NULL ;
00887     }
00888     
00889     /* Create output object */
00890     combined = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_image*)) ;
00891   
00892     /* Loop on the detectors */
00893     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00894     {
00895         cpl_frameset  *  selected_jitter;
00896         cpl_bivector  *  selected_offsets;
00897         cpl_image     *  flat_ima = NULL;
00898         cpl_image     *  dark_ima = NULL;
00899         cpl_image     *  bpm_ima = NULL;
00900         cpl_imagelist *  in = NULL;
00901         cpl_imagelist *  in_sky = NULL;
00902         int              nrejected;
00903         
00904         cpl_msg_info(cpl_func, "Combine chip number %d", idet+1) ;
00905         cpl_msg_indent_more() ;
00906         
00907         /* Apply frame selection based on offset values */
00908         selected_jitter     = cpl_frameset_duplicate(jitters);
00909         selected_offsets = cpl_bivector_duplicate(offsets);
00910         if(hawki_sci_jitter_config.max_njitter != -1)
00911         {
00912             if(hawki_sci_jitter_config.max_njitter <
00913                     cpl_frameset_get_size(selected_jitter))
00914             {
00915                 while(cpl_frameset_get_size(selected_jitter) >
00916                       hawki_sci_jitter_config.max_njitter)
00917                 {
00918                     int irm = cpl_frameset_get_size(selected_jitter) - 1;
00919                     cpl_frameset_erase_frame
00920                         (selected_jitter,
00921                          cpl_frameset_get_frame(selected_jitter,irm));
00922                 }
00923                 cpl_vector_set_size(cpl_bivector_get_x(selected_offsets),
00924                                     hawki_sci_jitter_config.max_njitter);
00925                 cpl_vector_set_size(cpl_bivector_get_y(selected_offsets),
00926                                     hawki_sci_jitter_config.max_njitter);
00927             }
00928         }
00929         hawki_sci_jitter_output.ncomb[idet] = 
00930             cpl_frameset_get_size(selected_jitter);
00931         nrejected = cpl_frameset_get_size(selected_jitter) - 
00932             cpl_frameset_get_size(jitters);
00933         if(nrejected != 0)
00934             cpl_msg_info(cpl_func,"%d frames reject due to large offsets", 
00935                          nrejected); 
00936                 
00937         
00938         /* Load the input data */
00939         cpl_msg_info(cpl_func, "Load the input data") ;
00940         cpl_msg_indent_more() ;
00941         if ((in = hawki_load_detector(selected_jitter,
00942                                   idet+1, CPL_TYPE_FLOAT)) == NULL) {
00943             cpl_msg_error(cpl_func, "Cannot load chip %d", idet+1) ;
00944             cpl_free(combined) ;
00945             cpl_bivector_delete(offsets) ;
00946             cpl_msg_indent_less() ;
00947             cpl_msg_indent_less() ;
00948             return NULL ;
00949         }
00950         if (sky) {
00951             if ((in_sky = hawki_load_detector(sky, idet+1, CPL_TYPE_FLOAT)) == NULL) 
00952             {
00953                 cpl_msg_warning(cpl_func, "Cannot load sky for chip %d",idet+1);
00954             }
00955         } else in_sky = NULL ;
00956         cpl_msg_indent_less() ;
00957 
00958         /* Read the calibrations */
00959         cpl_msg_info(cpl_func, "Load the calibration data") ;
00960         if(hawki_sci_jitter_read_calib(flat, dark, bpm,
00961                                        &flat_ima, &dark_ima, &bpm_ima,
00962                                        idet) != 0)
00963         {
00964             cpl_msg_error(cpl_func, "Cannot read some of the calibrations");
00965             cpl_imagelist_delete(in);
00966             cpl_free(combined);
00967             if (in_sky) cpl_imagelist_delete(in_sky);
00968             cpl_bivector_delete(offsets);
00969             cpl_msg_indent_less();
00970             cpl_msg_indent_less();
00971             return NULL ;
00972         }
00973         
00974         /* Apply the calibrations */
00975         if (flat || dark || bpm ) 
00976         {
00977             cpl_msg_info(cpl_func, "Apply the calibrations") ;
00978             cpl_msg_indent_more() ;
00979             /* Basic calibration of the OBJECTS */
00980             if (hawki_flat_dark_bpm_detector_calib
00981                     (in, flat_ima, dark_ima, bpm_ima) == -1) 
00982             {
00983                 cpl_msg_error(cpl_func, "Cannot calibrate the objects") ;
00984                 cpl_imagelist_delete(in) ;
00985                 cpl_free(combined) ;
00986                 if (in_sky) cpl_imagelist_delete(in_sky) ;
00987                 cpl_bivector_delete(offsets) ;
00988                 cpl_image_delete(flat_ima);
00989                 cpl_image_delete(dark_ima);
00990                 cpl_image_delete(bpm_ima);
00991                 cpl_msg_indent_less() ;
00992                 cpl_msg_indent_less() ;
00993                 return NULL ;
00994             }
00995             /* Basic calibration of the SKY */
00996             if (in_sky) {
00997                 if (hawki_flat_dark_bpm_detector_calib
00998                         (in_sky, flat_ima, dark_ima, bpm_ima) == -1) 
00999                 {
01000                     cpl_msg_warning(cpl_func, "Cannot calibrate the sky") ;
01001                     cpl_imagelist_delete(in_sky) ;
01002                     in_sky = NULL ;
01003                 }
01004             }
01005             cpl_msg_indent_less() ;
01006         }
01007         cpl_image_delete(flat_ima);
01008         cpl_image_delete(dark_ima);
01009         cpl_image_delete(bpm_ima);
01010 
01011         /* Apply the sky correction */
01012         cpl_msg_info(cpl_func, "Sky estimation and correction") ;
01013         cpl_msg_indent_more() ;
01014         if (hawki_sci_jitter_sky(in, in_sky, bkg_stats, idet) == -1)
01015         {
01016             cpl_msg_error(cpl_func, "Cannot estimate the sky") ;
01017             cpl_imagelist_delete(in) ;
01018             if (in_sky) cpl_imagelist_delete(in_sky) ;
01019             cpl_free(combined) ;
01020             cpl_bivector_delete(offsets) ;
01021             cpl_msg_indent_less() ;
01022             cpl_msg_indent_less() ;
01023             return NULL ;
01024         }
01025         if (in_sky) cpl_imagelist_delete(in_sky) ;
01026         cpl_msg_indent_less() ;
01027     
01028         /* Apply the shift and add */
01029         cpl_msg_info(cpl_func, "Shift and stacking") ;
01030         cpl_msg_indent_more() ;
01031         comb_chip = hawki_sci_jitter_saa(&in, selected_offsets, 
01032                 &(hawki_sci_jitter_output.combined_pos_x[idet]),
01033                 &(hawki_sci_jitter_output.combined_pos_y[idet])) ;
01034         hawki_sci_jitter_output.combined_cumoffset_x[idet] = 
01035             hawki_sci_jitter_output.combined_pos_x[idet] - off_0_x;
01036         hawki_sci_jitter_output.combined_cumoffset_y[idet] = 
01037             hawki_sci_jitter_output.combined_pos_y[idet] - off_0_y;
01038         if (comb_chip == NULL) {
01039             cpl_msg_error(cpl_func, "Cannot apply the shift and add") ;
01040             cpl_imagelist_delete(in) ;
01041             cpl_free(combined) ;
01042             cpl_bivector_delete(offsets) ;
01043             cpl_msg_indent_less() ;
01044             cpl_msg_indent_less() ;
01045             return NULL ;
01046         }
01047         cpl_imagelist_delete(in) ;
01048         cpl_msg_indent_less() ;
01049 
01050         /* Put the results in the image list */
01051         combined[idet] = comb_chip[0] ;
01052         cpl_image_delete(comb_chip[1]) ;
01053         cpl_free(comb_chip) ;
01054         cpl_msg_indent_less() ;
01055         
01056         /* Free */
01057         cpl_frameset_delete(selected_jitter);
01058         cpl_bivector_delete(selected_offsets);
01059     }
01060     cpl_bivector_delete(offsets) ;
01061 
01062     return combined ;
01063 }
01064 
01065 /*----------------------------------------------------------------------------*/
01072 /*----------------------------------------------------------------------------*/
01073 static int hawki_sci_jitter_sky
01074 (cpl_imagelist   *   objs,
01075  cpl_imagelist   *   skys,
01076  cpl_table       **  bkg_stats,
01077  int                 idet)
01078 {
01079     cpl_image       *   sky ;
01080     int                 nframes;
01081     double              median ;
01082     cpl_image       *   cur_ima ;
01083     int                 i ;
01084 
01085     /* Initialise */
01086     nframes = cpl_imagelist_get_size(objs) ;
01087 
01088     /* Compute the sky frame */
01089     if (skys != NULL) {
01090        cpl_msg_info(cpl_func, "Median of sky images") ;
01091         /* Use sky images */
01092         if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) {
01093             cpl_msg_error(cpl_func, "Cannot compute the median of sky images") ;
01094             return -1;
01095         }
01096         
01097         /* Statistics on the background */
01098         if(bkg_stats != NULL)
01099         {
01100             cpl_table_set_size(bkg_stats[idet], 1);
01101             hawki_image_stats_fill_from_image
01102                 (bkg_stats, sky,
01103                  1,
01104                  1,
01105                  cpl_image_get_size_x(sky),
01106                  cpl_image_get_size_y(sky),
01107                  idet, 0);
01108         }
01109         
01110         /* Correct the objects images  */
01111         if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) {
01112             cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
01113             cpl_image_delete(sky) ;
01114             return -1;
01115         }
01116         cpl_image_delete(sky) ;
01117         /* Normalise the object planes */
01118         for (i=0 ; i<nframes ; i++) {
01119             cur_ima = cpl_imagelist_get(objs, i) ;
01120             median = cpl_image_get_median(cur_ima) ;
01121             cpl_image_subtract_scalar(cur_ima, median) ;
01122         }
01123     } else if (hawki_sci_jitter_config.sky_minnb > nframes) {
01124         cpl_msg_info(cpl_func, "Median of object images") ;
01125          /* Use objs images */
01126         if ((sky = cpl_imagelist_collapse_median_create(objs)) == NULL) {
01127             cpl_msg_error(cpl_func, "Cannot compute the median of obj images") ;
01128             return -1;
01129         }
01130 
01131         /* Statistics on the background */
01132         if(bkg_stats != NULL)
01133         {
01134             cpl_table_set_size(bkg_stats[idet], 1);
01135             hawki_image_stats_fill_from_image
01136                 (bkg_stats, sky,
01137                  1,
01138                  1,
01139                  cpl_image_get_size_x(sky),
01140                  cpl_image_get_size_y(sky),
01141                  idet, 0);
01142         }
01143         
01144         /* Correct the objects images  */
01145         if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) {
01146             cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
01147             cpl_image_delete(sky) ;
01148             return -1;
01149         }
01150         /* Normalise the object planes */
01151         for (i=0 ; i<nframes ; i++) {
01152             cur_ima = cpl_imagelist_get(objs, i) ;
01153             median = cpl_image_get_median(cur_ima) ;
01154             cpl_image_subtract_scalar(cur_ima, median) ;
01155         }
01156         /* Delete sky image */
01157         cpl_image_delete(sky) ;
01158     } else {
01159         cpl_msg_info(cpl_func, "Computing running median on jitter images") ;
01160         /* Use objects images */
01161         if (hawki_sci_jitter_sky_running(objs, bkg_stats, idet) == -1)
01162         {
01163             cpl_msg_error(cpl_func, 
01164                     "Cannot apply the running median");
01165             return -1;
01166         }
01167     }
01168     return 0;
01169 }
01170 
01171 /*----------------------------------------------------------------------------*/
01190 /*----------------------------------------------------------------------------*/
01191 static int hawki_sci_jitter_sky_running
01192 (cpl_imagelist *  in,
01193  cpl_table     ** bkg_stats,
01194  int              idet) 
01195 {
01196     int                 rejmin, rejmax, halfw;
01197     cpl_imagelist   *   result_buffer;
01198     int                 ni, nx, ny;
01199     cpl_vector      *   medians;
01200     cpl_image       *   cur_ima;
01201     cpl_image       *   tmp_ima;
01202     double              one_med;
01203     int                 i, k;
01204     int                 first_buffered = 0;
01205     int                 next_not_to_be_used;
01206 
01207     /* Test entries */
01208     if (in==NULL) return -1;
01209 
01210     /* Initialise */
01211     rejmin = hawki_sci_jitter_config.sky_rejmin ;
01212     rejmax = hawki_sci_jitter_config.sky_rejmax ;
01213     halfw  = hawki_sci_jitter_config.sky_halfw ;
01214     ni = cpl_imagelist_get_size(in) ;
01215     cur_ima = cpl_imagelist_get(in, 0) ;
01216     nx = cpl_image_get_size_x(cur_ima) ;
01217     ny = cpl_image_get_size_y(cur_ima) ;
01218     
01219     /* Tests on validity of rejection parameters */
01220     if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) {
01221         cpl_msg_error(cpl_func, "cannot compute running median with "
01222                 "rejection  parameters %d (%d-%d)",
01223                 halfw, rejmin, rejmax);
01224         return -1;
01225     }   
01226     /* Pre-compute median value in each plane */
01227     medians = cpl_vector_new(ni) ;
01228     for (i=0 ; i<ni ; i++) {
01229         cur_ima = cpl_imagelist_get(in, i) ;
01230         cpl_vector_set(medians, i, cpl_image_get_median(cur_ima)) ;
01231     }
01232     /* Allocate output cube */
01233     result_buffer = cpl_imagelist_new() ;
01234 
01235     /* Allocate output bg stats */
01236     cpl_table_set_size(bkg_stats[idet], ni);
01237     
01238     /* Main loop over input planes */
01239     for (k=0 ; k<ni ; k++)
01240     {
01241         cpl_image * bkg;
01242 
01243         /* Create the background image, to later compute stats */
01244         bkg = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01245 
01246         hawki_bkg_from_running_mean
01247             (in, medians, k, halfw, rejmin, rejmax, bkg);
01248 
01249         /* Subtract the background from the current image */
01250         tmp_ima = cpl_image_subtract_create(cpl_imagelist_get(in, k), bkg);
01251         
01252         /* Statistics on the background */
01253         if(bkg_stats != NULL)
01254         {
01255             hawki_image_stats_fill_from_image
01256                 (bkg_stats, bkg,
01257                  1, 1, nx, ny,
01258                  idet, k);
01259         }
01260         cpl_image_delete(bkg);
01261        
01262         /* Place the new image in a result buffer */
01263         cpl_imagelist_set(result_buffer, tmp_ima,
01264                           cpl_imagelist_get_size(result_buffer));
01265         
01266         /* Empty the buffer as much as possible */
01267         next_not_to_be_used = k - halfw;
01268         while(next_not_to_be_used >= first_buffered)
01269         {
01270             cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0),
01271                               first_buffered);
01272             first_buffered++;
01273         }
01274     }
01275     /* Empty the buffer finally */
01276     next_not_to_be_used = ni - 1;
01277     while(next_not_to_be_used >= first_buffered)
01278     {
01279         cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0),
01280                           first_buffered);
01281         first_buffered++;
01282     }
01283     cpl_imagelist_delete(result_buffer);
01284     cpl_vector_delete(medians);
01285 
01286     /* Subtract median from each frame */
01287     for (i=0 ; i<ni ; i++) {
01288         cur_ima = cpl_imagelist_get(in, i);
01289         one_med = cpl_image_get_median(cur_ima) ;
01290         cpl_image_subtract_scalar(cur_ima, one_med) ;
01291     }
01292     return 0;
01293 }
01294 
01295 /*----------------------------------------------------------------------------*/
01304 /*----------------------------------------------------------------------------*/
01305 static cpl_image ** hawki_sci_jitter_saa(
01306         cpl_imagelist   **  in,
01307         cpl_bivector    *   offsets,
01308         double          *   pos_x,
01309         double          *   pos_y)
01310 {
01311     cpl_bivector        *   offs_est;
01312     cpl_bivector        *   offs_used;
01313     cpl_bivector        *   objs ;
01314     cpl_image           **  combined ;
01315     int                     nfiles, ngood, nima, nx, ny ;
01316     int                     i;
01317 
01318     /* Check entries */
01319     if (pos_x == NULL || pos_y == NULL) return NULL ;
01320     if (offsets == NULL) return NULL ;
01321 
01322     /* Get the number of images */
01323     nfiles = cpl_imagelist_get_size(*in) ;
01324     if (cpl_bivector_get_size(offsets) != nfiles) {
01325         cpl_msg_error(cpl_func, "Invalid input objects sizes") ; 
01326         return NULL ;
01327     }
01328     
01329     /* Get the offsets estimation of each input file pair */
01330     cpl_msg_info(cpl_func, "Get the offsets estimation") ;
01331     offs_est = NULL ;
01332     if (hawki_sci_jitter_config.offsets &&
01333             hawki_sci_jitter_config.offsets[0] != (char)0) {
01334         /* A file has been provided on the command line */
01335         offs_est = cpl_bivector_read((char*)hawki_sci_jitter_config.offsets);
01336         if ((offs_est==NULL)||(cpl_bivector_get_size(offs_est)!=nfiles)) {
01337             cpl_msg_error(cpl_func, "Cannot get offsets from %s", 
01338                     hawki_sci_jitter_config.offsets) ;
01339             return NULL ;
01340         }
01341     } else {
01342         /* Use the offsets from the header */
01343         offs_est = cpl_bivector_duplicate(offsets) ;
01344         cpl_vector_multiply_scalar(cpl_bivector_get_x(offs_est), -1.0) ;
01345         cpl_vector_multiply_scalar(cpl_bivector_get_y(offs_est), -1.0) ;
01346     }
01347 
01348     /* Read the provided objects file if provided */
01349     objs = NULL ;
01350     if (hawki_sci_jitter_config.refine &&
01351             hawki_sci_jitter_config.objects &&
01352             hawki_sci_jitter_config.objects[0] != (char)0) {
01353         cpl_msg_info(cpl_func, "Get the user provided correlation objects") ;
01354         /* A file has been provided on the command line */
01355         objs = cpl_bivector_read((char*)hawki_sci_jitter_config.objects) ;
01356         if (objs==NULL) {
01357             cpl_msg_error(cpl_func, "Cannot get objects from %s",
01358                     hawki_sci_jitter_config.objects) ;
01359             cpl_bivector_delete(offs_est) ;
01360             return NULL ;
01361         }
01362     }
01363 
01364     /* Get a correlation point from the difference of the first images */
01365     if (hawki_sci_jitter_config.refine && objs == NULL) {
01366         cpl_apertures  *   aperts;
01367         cpl_image      *   detect_image;
01368         cpl_vector     *   thresh_vect;
01369         double         *   objs_x ;
01370         double         *   objs_y ;
01371         cpl_msg_info(cpl_func, "Get a cross-correlation point") ;
01372         thresh_vect = cpl_vector_new(4) ;
01373         cpl_vector_set(thresh_vect, 0, 5.0) ;
01374         cpl_vector_set(thresh_vect, 1, 2.0) ;
01375         cpl_vector_set(thresh_vect, 2, 1.0) ;
01376         cpl_vector_set(thresh_vect, 3, 0.5) ;
01377         detect_image  = cpl_imagelist_get(*in, 0);
01378         if ((aperts = cpl_apertures_extract_window(detect_image, thresh_vect, 
01379                         400, 400, 1600, 1600, NULL)) == NULL) {
01380             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ;
01381             cpl_bivector_delete(offs_est) ;
01382             cpl_vector_delete(thresh_vect) ;
01383             return NULL ;
01384         }
01385         cpl_vector_delete(thresh_vect) ;
01386         cpl_apertures_sort_by_npix(aperts) ;
01387         objs = cpl_bivector_new(1) ;
01388         objs_x = cpl_bivector_get_x_data(objs) ;
01389         objs_y = cpl_bivector_get_y_data(objs) ;
01390         objs_x[0] = cpl_apertures_get_pos_x(aperts, 1) ;
01391         objs_y[0] = cpl_apertures_get_pos_y(aperts, 1) ;
01392         cpl_apertures_delete(aperts) ;
01393         if (objs == NULL) {
01394             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ;
01395             cpl_bivector_delete(offs_est) ;
01396             return NULL ;
01397         }
01398         cpl_msg_info(cpl_func, 
01399                 "Correlation point: %g %g\n", objs_x[0], objs_y[0]);
01400     }
01401 
01402     /* Refine the offsets */
01403     if (hawki_sci_jitter_config.refine) {
01404         cpl_bivector *   offs_refined;
01405         double       *   offs_refined_x;
01406         double       *   offs_refined_y;
01407         double       *   offs_est_x;
01408         double       *   offs_est_y;
01409         cpl_vector   *   correl ;
01410         double       *   correl_data ;
01411         cpl_msg_info(cpl_func, "Refine the offsets");
01412         cpl_msg_indent_more() ;
01413         nima = cpl_imagelist_get_size(*in) ;
01414         correl = cpl_vector_new(nima) ;
01415         if ((offs_refined = cpl_geom_img_offset_fine(*in, offs_est, objs,
01416                         hawki_sci_jitter_config.sx, 
01417                         hawki_sci_jitter_config.sy,
01418                         hawki_sci_jitter_config.mx, 
01419                         hawki_sci_jitter_config.my,
01420                         correl)) == NULL) {
01421             cpl_msg_error(cpl_func, "Cannot refine the offsets");
01422             cpl_bivector_delete(offs_est) ;
01423             if (objs != NULL) cpl_bivector_delete(objs) ;
01424             cpl_vector_delete(correl) ;
01425             return NULL ;
01426         }
01427         if (objs != NULL) cpl_bivector_delete(objs) ;
01428 
01429         /* Display the results */
01430         offs_est_x = cpl_bivector_get_x_data(offs_est);
01431         offs_est_y = cpl_bivector_get_y_data(offs_est);
01432         offs_refined_x = cpl_bivector_get_x_data(offs_refined);
01433         offs_refined_y = cpl_bivector_get_y_data(offs_refined) ;
01434         correl_data = cpl_vector_get_data(correl) ;
01435         cpl_msg_info(cpl_func, "Refined offsets [correlation factor]") ;
01436         ngood = 0 ;
01437         for (i=0 ; i<nima ; i++) {
01438             cpl_msg_info(cpl_func, "#%02d: %8.2f %8.2f [%12.2f]",
01439                     i+1, offs_refined_x[i], offs_refined_y[i], correl_data[i]);
01440             if (correl_data[i] > -0.5) ngood++ ;
01441         }
01442         if (ngood == 0) {
01443             cpl_msg_error(cpl_func, "No frame correctly correlated") ;
01444             cpl_bivector_delete(offs_est);
01445             cpl_bivector_delete(offs_refined);
01446             cpl_vector_delete(correl);
01447             return NULL ;
01448         }
01449         cpl_msg_indent_less();
01450 
01451         /* Replace bad correlated images with the nominal offsets */
01452         cpl_msg_info(cpl_func, "Using nominal offsets for badly "
01453                      "correlated images (%d out of %d)", nima-ngood, nima);
01454         for (i=0 ; i<nima ; i++) {
01455             if (correl_data[i] < -0.5) {
01456                 offs_refined_x[i] = offs_est_x[i];
01457                 offs_refined_y[i] = offs_est_y[i];
01458             }
01459         }
01460         offs_used = cpl_bivector_duplicate(offs_refined);
01461         cpl_bivector_delete(offs_est);
01462         cpl_bivector_delete(offs_refined);
01463         cpl_vector_delete(correl);
01464     }
01465     else
01466     {
01467         offs_used = cpl_bivector_duplicate(offs_est);
01468         cpl_bivector_delete(offs_est);
01469     }
01470 
01471     /* Discard the pixels on the sides */
01472     if (hawki_sci_jitter_config.borders > 0) {
01473         cpl_imagelist  *   in_ext ;
01474         cpl_image      *   tmp1 ;
01475         cpl_image      *   tmp2 ;
01476         nx = cpl_image_get_size_x(cpl_imagelist_get(*in, 0)) ;
01477         ny = cpl_image_get_size_y(cpl_imagelist_get(*in, 0)) ;
01478         in_ext = cpl_imagelist_new() ;
01479         while(cpl_imagelist_get_size(*in) > 0)
01480         {
01481             tmp1 = cpl_imagelist_unset(*in, 0);
01482             tmp2 = cpl_image_extract(tmp1, 
01483                     hawki_sci_jitter_config.borders+1, 
01484                     hawki_sci_jitter_config.borders+1, 
01485                     nx-hawki_sci_jitter_config.borders, 
01486                     ny-hawki_sci_jitter_config.borders) ;
01487             cpl_image_delete(tmp1);
01488             cpl_imagelist_set(in_ext, tmp2, cpl_imagelist_get_size(in_ext)) ;
01489         }
01490         cpl_imagelist_delete(*in) ;
01491         *in = in_ext ;
01492     }
01493 
01494     /* Apply the shift & add */
01495     cpl_msg_info(cpl_func, "Recombine the images set") ;
01496     cpl_msg_indent_more() ;
01497     if ((combined=cpl_geom_img_offset_saa(*in, offs_used,
01498                     CPL_KERNEL_DEFAULT, 
01499                     hawki_sci_jitter_config.rej_low,
01500                     hawki_sci_jitter_config.rej_high,
01501                     hawki_sci_jitter_config.comb_meth,
01502                     pos_x, pos_y)) == NULL) {
01503         cpl_msg_error(cpl_func, "Cannot apply the shift and add") ;
01504         cpl_bivector_delete(offs_used) ;
01505         cpl_msg_indent_less() ;
01506         return NULL ;
01507     }
01508     cpl_msg_indent_less() ;
01509     *pos_x -= hawki_sci_jitter_config.borders ;
01510     *pos_y -= hawki_sci_jitter_config.borders ;
01511 
01512     /* Free and return */
01513     cpl_bivector_delete(offs_used) ;
01514     return combined ;
01515 }
01516 
01517 /*----------------------------------------------------------------------------*/
01524 /*----------------------------------------------------------------------------*/
01525 static int hawki_sci_jitter_qc
01526 (cpl_frameset *   science_frames,
01527  cpl_image   **   combined_images, 
01528  cpl_table   **   obj_charac)
01529 {
01530     cpl_vector      *   thresh_vec ;
01531     cpl_apertures   *   aperts ;
01532     int                 nb_objs ;
01533     double              angle ;
01534     double          *   fwhms_x ;
01535     double          *   fwhms_y ;
01536     cpl_bivector    *   iqe ;
01537     int                 nb_good ;
01538     cpl_vector      *   fwhms_good ;
01539     double          *   fwhms_good_data ;
01540     double              f_min, f_max, fr, fx, fy ;
01541     int                 chip;
01542     int                 iobj;
01543     int                 j;
01544     
01545     /* Initialise */
01546     double              seeing_min_arcsec = 0.1 ;
01547     double              seeing_max_arcsec = 5.0 ;
01548     double              seeing_fwhm_var   = 0.2 ;
01549 
01550     /* Check entries */
01551     if (combined_images  == NULL) return -1 ;
01552     if (obj_charac       == NULL) return -1 ;
01553 
01554     /* Create the vector for the detection thresholds */
01555     thresh_vec = cpl_vector_new(11) ;
01556     cpl_vector_set(thresh_vec, 0, 100.0) ;
01557     cpl_vector_set(thresh_vec, 0, 90.0) ;
01558     cpl_vector_set(thresh_vec, 0, 80.0) ;
01559     cpl_vector_set(thresh_vec, 0, 70.0) ;
01560     cpl_vector_set(thresh_vec, 0, 60.0) ;
01561     cpl_vector_set(thresh_vec, 0, 50.0) ;
01562     cpl_vector_set(thresh_vec, 1, 40.0) ;
01563     cpl_vector_set(thresh_vec, 1, 30.0) ;
01564     cpl_vector_set(thresh_vec, 1, 20.0) ;
01565     cpl_vector_set(thresh_vec, 1, 10.0) ;
01566     cpl_vector_set(thresh_vec, 2, 5.0) ;
01567 
01568     /* Get the mean airmass */
01569     hawki_sci_jitter_output.mean_airmass = 
01570         hawki_get_mean_airmass(science_frames);;
01571     
01572     /* Loop on the HAWK-I detectors */
01573     for (chip=0 ; chip<HAWKI_NB_DETECTORS ; chip++) 
01574     {
01575         /* Check entries */
01576         if (combined_images[chip]  == NULL) return -1 ;
01577         if (obj_charac[chip] == NULL) return -1 ;
01578     
01579         /* Detect apertures */
01580         if ((aperts = cpl_apertures_extract
01581                 (combined_images[chip], thresh_vec, NULL)) == NULL) {
01582             cpl_msg_warning(cpl_func, "Cannot detect any aperture on chip %d",
01583                             chip+1) ;
01584             continue;
01585         }
01586 
01587         /* Number of detected objects */
01588         nb_objs = cpl_apertures_get_size(aperts);
01589         cpl_msg_info(cpl_func, "%d objects detected on chip %d",nb_objs,chip+1);
01590         hawki_sci_jitter_output.nbobjs[chip] = nb_objs ;
01591         fwhms_x = cpl_malloc(nb_objs * sizeof(double)) ;
01592         fwhms_y = cpl_malloc(nb_objs * sizeof(double)) ;
01593         
01594         /* Initialize the output table */
01595         cpl_table_set_size(obj_charac[chip], nb_objs);
01596         cpl_table_new_column
01597             (obj_charac[chip], HAWKI_COL_OBJ_POSX, CPL_TYPE_DOUBLE);
01598         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSX,"pix");
01599         cpl_table_new_column
01600             (obj_charac[chip], HAWKI_COL_OBJ_POSY, CPL_TYPE_DOUBLE);
01601         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSY,"pix");
01602         cpl_table_new_column
01603             (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, CPL_TYPE_DOUBLE);
01604         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_ANGLE,"grad");
01605         cpl_table_new_column
01606             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, CPL_TYPE_DOUBLE);
01607         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MAJAX,"pix");
01608         cpl_table_new_column
01609             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, CPL_TYPE_DOUBLE);
01610         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MINAX,"pix");
01611         cpl_table_new_column
01612             (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, CPL_TYPE_DOUBLE);
01613         cpl_table_new_column
01614             (obj_charac[chip], HAWKI_COL_OBJ_FLUX, CPL_TYPE_DOUBLE);
01615         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FLUX,"ADU");
01616         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01617         {
01618             /* Fill with the already known information */
01619             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSX, iobj, 
01620                                  cpl_apertures_get_centroid_x(aperts, iobj+1));
01621             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSY, iobj, 
01622                                  cpl_apertures_get_centroid_y(aperts, iobj+1));
01623             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_FLUX, iobj, 
01624                                  cpl_apertures_get_flux(aperts, iobj+1)) ;
01625             /* Compute the FWHM informations */
01626             if ((iqe = cpl_image_iqe(combined_images[chip], 
01627                 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) - 10,
01628                 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) - 10,
01629                 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) + 10,
01630                 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) + 10))==NULL)
01631             {
01632                 cpl_error_reset() ;
01633                 cpl_msg_debug(cpl_func, "Cannot get FWHM for obj at pos %g %g",
01634                               cpl_apertures_get_centroid_x(aperts, iobj+1),
01635                               cpl_apertures_get_centroid_y(aperts, iobj+1)) ;
01636                 fwhms_x[iobj] = -1.0 ;
01637                 fwhms_y[iobj] = -1.0 ;
01638                 angle = 0.0 ;
01639             }
01640             else 
01641             {
01642                 fwhms_x[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 2) ;
01643                 fwhms_y[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 3) ;
01644                 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4) ;
01645                 cpl_bivector_delete(iqe) ;
01646                 cpl_msg_debug(cpl_func,
01647                               "FWHM for obj at pos %g %g: %g x %g (%g)",
01648                               cpl_apertures_get_centroid_x(aperts, iobj+1),
01649                               cpl_apertures_get_centroid_y(aperts, iobj+1),
01650                               fwhms_x[iobj], fwhms_y[iobj], angle) ;
01651             }
01652             cpl_table_set_double
01653                 (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, iobj, angle) ;
01654             cpl_table_set_double
01655                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, iobj,
01656                  fwhms_x[iobj]);
01657             cpl_table_set_double
01658                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, iobj,
01659                  fwhms_y[iobj]);
01660             cpl_table_set_double
01661                 (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, iobj,
01662                  1 - fwhms_y[iobj] / fwhms_x[iobj]);
01663         }
01664         cpl_apertures_delete(aperts) ;
01665 
01666         /* Get the number of good values */
01667         nb_good = 0 ;
01668         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01669         {
01670             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) nb_good++ ;
01671         }
01672         if (nb_good == 0)
01673         {
01674             cpl_msg_warning(cpl_func, "No objects to compute FWHM on chip %d",
01675                             chip+1);
01676             cpl_free(fwhms_x) ;
01677             cpl_free(fwhms_y) ;
01678             continue;
01679         }
01680     
01681         /* Get the good values */
01682         fwhms_good = cpl_vector_new(nb_good) ;
01683         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
01684         j=0 ;
01685         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01686         {
01687             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) 
01688             {
01689                 fwhms_good_data[j] = (fwhms_x[iobj]+fwhms_y[iobj])/2.0 ;
01690                 j++ ;
01691             }
01692         }
01693    
01694         /* Compute the fwhm */
01695         if (nb_good < 3) 
01696         {
01697             /* Too few values to compute the median */
01698             hawki_sci_jitter_output.fwhm_pix[chip] = fwhms_good_data[0] ;
01699         } 
01700         else 
01701         {
01702             /* Compute the median */
01703             hawki_sci_jitter_output.fwhm_pix[chip] =
01704                 cpl_vector_get_median_const(fwhms_good) ;
01705         }
01706         hawki_sci_jitter_output.fwhm_arcsec[chip] = 
01707             hawki_sci_jitter_output.fwhm_pix[chip] *
01708             hawki_sci_jitter_output.pixscale ;
01709 
01710         /* Compute the mode of the FWHMs */
01711         if (nb_good > 5) 
01712         {
01713             hawki_sci_jitter_output.fwhm_mode[chip] =
01714                 hawki_vector_get_mode(fwhms_good);
01715             hawki_sci_jitter_output.fwhm_mode[chip] *= 
01716                 hawki_sci_jitter_output.pixscale ;
01717         }
01718         cpl_vector_delete(fwhms_good) ;
01719     
01720         /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */
01721         /* Compute f_min and f_max */
01722         f_min = seeing_min_arcsec / hawki_sci_jitter_output.pixscale ;
01723         f_max = seeing_max_arcsec / hawki_sci_jitter_output.pixscale ;
01724 
01725         /* Get the number of good values */
01726         nb_good = 0 ;
01727         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01728         {
01729             fx = fwhms_x[iobj] ;
01730             fy = fwhms_y[iobj] ;
01731             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
01732             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01733                     (fr < seeing_fwhm_var)) nb_good++ ;
01734         }
01735         if (nb_good == 0) 
01736         {
01737             cpl_msg_warning(cpl_func, "No objects to compute IQ on chip %d",
01738                             chip+1);
01739             cpl_free(fwhms_x) ;
01740             cpl_free(fwhms_y) ;
01741             continue;
01742         }
01743 
01744         /* Get the good values */
01745         fwhms_good = cpl_vector_new(nb_good) ;
01746         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
01747         j=0 ;
01748         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01749         {
01750             fx = fwhms_x[iobj] ;
01751             fy = fwhms_y[iobj] ;
01752             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
01753             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01754                     (fr < seeing_fwhm_var)) 
01755             {
01756                 fwhms_good_data[j] = (fx + fy)/2.0 ;
01757                 j++ ;
01758             }
01759         }
01760         cpl_free(fwhms_x) ;
01761         cpl_free(fwhms_y) ;
01762     
01763         /* Compute the fwhm */
01764         if (nb_good < 3) 
01765         {
01766             /* Too few values to compute the median */
01767             hawki_sci_jitter_output.iq[chip] = fwhms_good_data[0] ;
01768         }
01769         else 
01770         {
01771             /* Compute the median */
01772             hawki_sci_jitter_output.iq[chip] = 
01773                 cpl_vector_get_median_const(fwhms_good) ;
01774         }
01775         cpl_vector_delete(fwhms_good) ;
01776         hawki_sci_jitter_output.iq[chip] *= hawki_sci_jitter_output.pixscale ;
01777     }
01778     
01779     /* Cleanup */
01780     cpl_vector_delete(thresh_vec) ;
01781     
01782     return 0;
01783 }
01784 
01785 /*----------------------------------------------------------------------------*/
01797 /*----------------------------------------------------------------------------*/
01798 static int hawki_sci_jitter_read_calib
01799 (const char *  flat,
01800  const char *  dark,
01801  const char *  bpm,
01802  cpl_image  ** flat_image,
01803  cpl_image  ** dark_image,
01804  cpl_image  ** bpm_image,
01805  int           idet)
01806 {
01807     const char * reffile;
01808     int          ext_nb;
01809     
01810     if(flat == NULL && dark == NULL && bpm == NULL)
01811         return 0;
01812     if(*flat_image != NULL || *dark_image != NULL || *bpm_image != NULL)
01813         return 0;
01814     
01815     /* Get the extension number for this detector */
01816     if(flat != NULL)
01817         reffile = flat;
01818     else if(dark != NULL)
01819         reffile = dark;
01820     else
01821         reffile = bpm;
01822 
01823     /* Guess which is the extension to read */
01824     if ((ext_nb = hawki_get_ext_from_detector(reffile, idet + 1)) == -1) {
01825         cpl_msg_error(cpl_func, "Cannot get the extension with detector %d",
01826                       idet + 1);
01827         return -1;
01828     }
01829 
01830     /* Load the dark image */
01831     if(dark != NULL)
01832         *dark_image = cpl_image_load(dark, CPL_TYPE_FLOAT, 0, ext_nb);
01833     /* Load the flat image */
01834     if(flat != NULL)
01835         *flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, ext_nb);
01836     /* Load the bpm image */
01837     if(bpm != NULL)
01838         *bpm_image = cpl_image_load(bpm, CPL_TYPE_FLOAT, 0, ext_nb);
01839     
01840     /* Multiply the dark image by the science exposure time */
01841     if(dark != NULL)
01842         cpl_image_multiply_scalar(*dark_image, hawki_sci_jitter_output.dit);
01843 
01844     /* Return */
01845     return 0;
01846 }
01847 
01848 /*----------------------------------------------------------------------------*/
01857 /*----------------------------------------------------------------------------*/
01858 static int hawki_sci_jitter_save
01859 (cpl_image           **  combined,
01860  cpl_image           *   stitched,
01861  cpl_table           **  obj_charac,
01862  cpl_table           **  raw_jitter_stats,
01863  cpl_table           **  bkg_stats,
01864  const cpl_table     *   raw_obj_tel_info,
01865  cpl_frameset        *   science_frames,
01866  cpl_frameset        *   calib_frames,
01867  cpl_parameterlist   *   parlist,
01868  cpl_frameset        *   set)
01869 {
01870     cpl_propertylist    *   plist ;
01871     double                  pscale, dit, bg_mean, bg_stdev, bg_instmag ;
01872     cpl_propertylist    **  qclists ;
01873     const cpl_frame     *   ref_frame ;
01874     cpl_frameset        *   used_frames;
01875     cpl_propertylist    *   wcslist ;
01876     cpl_propertylist    *   telstats;
01877     cpl_propertylist    *   inputlist ;
01878     double                  crpix1, crpix2 ;
01879     int                     ext_nb ;
01880     const char          *   recipe_name = "hawki_sci_jitter" ;
01881     int                     i;
01882     int                     ext_chip_1;
01883     cpl_errorstate          error_prevstate = cpl_errorstate_get();
01884 
01885     /* Initialise */
01886     pscale = hawki_sci_jitter_output.pixscale;
01887     dit = hawki_sci_jitter_output.dit;
01888 
01889     /* Get reference frame */
01890     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01891 
01892     /* Get the used frames */ 
01893     used_frames = cpl_frameset_duplicate(science_frames);
01894     for(i = 0; i< cpl_frameset_get_size(calib_frames); ++i)
01895         cpl_frameset_insert(used_frames, 
01896                 cpl_frame_duplicate(cpl_frameset_get_frame(calib_frames, i)));
01897 
01898     /* Create the telescope data statistics */
01899     telstats = cpl_propertylist_new();
01900     hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats);
01901 
01902     /* Create the QC lists */
01903     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
01904     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
01905 
01906         /* Get the extension number */
01907         ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
01908 
01909         /* Handle WCS keys */
01910         wcslist = cpl_propertylist_load_regexp(
01911                 cpl_frame_get_filename(ref_frame), ext_nb, HAWKI_HEADER_WCS, 0);
01912         qclists[i] = cpl_propertylist_new() ;
01913 
01914         /* Compute bg_instmag */
01915         bg_mean = cpl_table_get_column_mean(bkg_stats[i], HAWKI_COL_STAT_MEAN);
01916         if (cpl_table_get_nrow(bkg_stats[i]) < 2) bg_stdev = 0 ;
01917         else bg_stdev = cpl_table_get_column_stdev
01918             (bkg_stats[i], HAWKI_COL_STAT_MEAN);
01919         if(bg_mean >= 0)
01920             bg_instmag = -2.5 * log10(bg_mean/(pscale*pscale*dit));
01921         else
01922             bg_instmag = 0;
01923 
01924         /* Fill the QC */
01925         cpl_propertylist_append_double
01926             (qclists[i], "ESO QC BACKGD MEAN", bg_mean);
01927         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD MEAN",
01928                                      "Mean of all the image mean backgrounds");
01929         cpl_propertylist_append_double
01930             (qclists[i], "ESO QC BACKGD STDEV", bg_stdev);
01931         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD STDEV",
01932                    "The standard deviation of all the image mean backgrounds");
01933         cpl_propertylist_append_double
01934             (qclists[i], "ESO QC BACKGD INSTMAG", bg_instmag) ;
01935         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD INSTMAG",
01936           "Mean of all the image mean backgrounds in instrumental magnitudes");
01937         cpl_propertylist_append_int
01938             (qclists[i], "ESO QC NBOBJS", hawki_sci_jitter_output.nbobjs[i]);
01939         cpl_propertylist_set_comment(qclists[i], "ESO QC NBOBJS",
01940                            "Number of detected objects in the combined image");
01941         cpl_propertylist_append_double
01942             (qclists[i], "ESO QC IQ", hawki_sci_jitter_output.iq[i]);
01943         cpl_propertylist_set_comment(qclists[i], "ESO QC IQ",
01944                            "Estimated image quality [arcsec]");
01945         cpl_propertylist_append_double
01946             (qclists[i], "ESO QC IQ DIFF AMBI",
01947              hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double
01948                  (telstats, "ESO QC TEL AMBI FWHM MEAN"));
01949         cpl_propertylist_set_comment(qclists[i], "ESO QC IQ DIFF AMBI",
01950                            "Mean Observatory seeing measured by AS");
01951         cpl_propertylist_append_double
01952             (qclists[i], "ESO QC IQ DIFF TEL",
01953              hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double
01954                  (telstats, "ESO QC TEL IA FWHM MEAN"));
01955         cpl_propertylist_set_comment(qclists[i], "ESO QC IQ DIFF TEL",
01956                 "Mean Observatory seeing measured by AS corrected by airmass");
01957         cpl_propertylist_append_double
01958             (qclists[i], "ESO QC FWHM PIX",
01959              hawki_sci_jitter_output.fwhm_pix[i]);
01960         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM PIX",
01961                                      "The median FWHM in the image [pixels]");
01962         cpl_propertylist_append_double
01963             (qclists[i], "ESO QC FWHM ARCSEC",
01964              hawki_sci_jitter_output.fwhm_arcsec[i]);
01965         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM ARCSEC",
01966                                      "The median FWHM in the image [arcsec]");
01967         cpl_propertylist_append_double
01968             (qclists[i], "ESO QC FWHM MODE",
01969              hawki_sci_jitter_output.fwhm_mode[i]);
01970         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM MODE",
01971                                      "The mode FWHM in the image [pixels]");
01972         cpl_propertylist_append_double
01973             (qclists[i], "ESO QC COMBINED POSX",
01974              hawki_sci_jitter_output.combined_pos_x[i]);
01975         cpl_propertylist_set_comment(qclists[i], "ESO QC COMBINED POSX",
01976                                      "Position in X of the first image");
01977         cpl_propertylist_append_double
01978             (qclists[i], "ESO QC COMBINED POSY",
01979              hawki_sci_jitter_output.combined_pos_y[i]);
01980         cpl_propertylist_set_comment(qclists[i], "ESO QC COMBINED POSY",
01981                                      "Position in Y of the first image");
01982         cpl_propertylist_append_double
01983             (qclists[i], "ESO QC COMBINED CUMOFFSETX",
01984              hawki_sci_jitter_output.combined_cumoffset_x[i]);
01985         cpl_propertylist_append_double
01986             (qclists[i], "ESO QC COMBINED CUMOFFSETY",
01987              hawki_sci_jitter_output.combined_cumoffset_y[i]);
01988         cpl_propertylist_append_int
01989             (qclists[i], "ESO QC DATANCOM",hawki_sci_jitter_output.ncomb[i]);
01990         cpl_propertylist_set_comment(qclists[i], "ESO QC DATANCOM",
01991                                      "Number of files used for the reduction");
01992         cpl_propertylist_append_double
01993             (qclists[i], "ESO QC AIRMASS MEAN",
01994              hawki_sci_jitter_output.mean_airmass);
01995         cpl_propertylist_set_comment(qclists[i], "ESO QC AIRMASS MEAN",
01996                                      "Average airmass");
01997 
01998         /* Update WCS and write them */
01999         crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 
02000         crpix1 += hawki_sci_jitter_output.combined_pos_x[i];
02001         cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ;
02002         crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 
02003         crpix2 += hawki_sci_jitter_output.combined_pos_y[i] ;
02004         cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ;
02005         cpl_propertylist_copy_property_regexp
02006             (qclists[i], wcslist, HAWKI_HEADER_WCS, 0) ;
02007         cpl_propertylist_delete(wcslist);
02008 
02009         /* Propagate some keywords from input raw frame extensions */
02010         inputlist = cpl_propertylist_load_regexp(
02011                 cpl_frame_get_filename(ref_frame), ext_nb,
02012                 HAWKI_HEADER_EXT_FORWARD, 0) ;
02013         cpl_propertylist_append(qclists[i], inputlist);
02014         cpl_propertylist_delete(inputlist) ;
02015     }
02016     
02017     /* Statistics of the raw images in the QC */
02018     hawki_image_stats_stats(raw_jitter_stats, qclists);
02019     
02020     /* Statistics of the detected objects in the QC */
02021     hawki_obj_prop_stats(obj_charac, qclists);
02022 
02023     /* Write the combined image */
02024     hawki_images_save(set,
02025                       parlist,
02026                       used_frames,
02027                       (const cpl_image **)combined,
02028                       recipe_name,
02029                       HAWKI_CALPRO_COMBINED,
02030                       HAWKI_PROTYPE_COMBINED, 
02031                       NULL,
02032                       (const cpl_propertylist**)qclists,
02033                       "hawki_sci_jitter.fits");
02034 
02035     /* Erase the WCS */
02036     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
02037         cpl_propertylist_erase_regexp(qclists[i], HAWKI_HEADER_WCS, 0) ;
02038     }
02039 
02040     /* Create a propertylist for PRO.x */
02041     plist = cpl_propertylist_new();
02042     cpl_propertylist_append_string(plist, CPL_DFS_PRO_TYPE,
02043                                    HAWKI_PROTYPE_STITCHED) ;
02044     cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG,
02045                                    HAWKI_CALPRO_STITCHED) ;
02046     /* Handle WCS keys */
02047     ext_chip_1 = 1;
02048     wcslist = cpl_propertylist_load_regexp(
02049             cpl_frame_get_filename(ref_frame), ext_chip_1, HAWKI_HEADER_WCS, 0);
02050     /* Update WCS and write them */
02051     crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 
02052     crpix1 += hawki_sci_jitter_output.combined_pos_x[0];
02053     cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ;
02054     crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 
02055     crpix2 += hawki_sci_jitter_output.combined_pos_y[0] ;
02056     cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ;
02057     cpl_propertylist_append(plist, wcslist);
02058     cpl_propertylist_delete(wcslist) ;
02059     /* Write the stitched image */
02060     cpl_dfs_save_image(set,
02061                        NULL,
02062                        parlist,
02063                        used_frames,
02064                        NULL,
02065                        stitched,
02066                        CPL_BPP_IEEE_FLOAT,
02067                        recipe_name,
02068                        plist,
02069                        NULL,
02070                        PACKAGE "/" PACKAGE_VERSION,
02071                        "hawki_sci_jitter_stitched.fits");
02072     cpl_propertylist_delete(plist);
02073 
02074     /* Write the FITS table with the objects statistics */
02075     if (obj_charac) 
02076     {
02077         hawki_tables_save(set,
02078                           parlist,
02079                           used_frames,
02080                           (const cpl_table **)obj_charac,
02081                           recipe_name,
02082                           HAWKI_CALPRO_OBJ_PARAM,
02083                           HAWKI_PROTYPE_OBJ_PARAM,
02084                           NULL,
02085                           (const cpl_propertylist**)qclists,
02086                           "hawki_sci_jitter_stars.fits");
02087     }
02088 
02089     /* Write the table with the background statistics */
02090     hawki_tables_save(set,
02091                       parlist,
02092                       used_frames,   
02093                       (const cpl_table **)bkg_stats,
02094                       recipe_name,
02095                       HAWKI_CALPRO_JITTER_BKG_STATS,
02096                       HAWKI_PROTYPE_JITTER_BKG_STATS,
02097                       NULL,
02098                       (const cpl_propertylist **)qclists,
02099                       "hawki_sci_jitter_bkg_stats.fits");
02100 
02101     /* Free and return */
02102     cpl_frameset_delete(used_frames);
02103     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
02104         cpl_propertylist_delete(qclists[i]) ;
02105     }
02106     cpl_propertylist_delete(telstats) ;
02107     cpl_free(qclists) ;
02108     if(!cpl_errorstate_is_equal(error_prevstate))
02109     {
02110         cpl_errorstate_set(CPL_ERROR_NONE);
02111         return -1;
02112     }
02113     return  0;
02114 }
02115 
02116 int hawki_sci_jitter_whole_image_algo
02117 (cpl_frameset       *  obj,
02118  cpl_table          ** raw_jitter_stats,
02119  cpl_table          *  raw_obj_tel_info,
02120  cpl_parameterlist  *  parlist,
02121  cpl_frameset       *  recipe_set)
02122 {
02123     int                 nframes;
02124     int                 iframe;
02125 
02126     
02127     nframes = cpl_frameset_get_size(obj);
02128     for( iframe = 0 ; iframe < nframes ; ++iframe)
02129     {
02130         /* Local storage variables */
02131         cpl_frame        * this_target_frame;
02132         cpl_propertylist * this_properties;
02133 
02134         /* Computing statistics for this frame */
02135         cpl_msg_info(cpl_func, "Getting statistics for image %d", iframe + 1);
02136         this_target_frame = cpl_frameset_get_frame(obj, iframe);
02137         hawki_image_stats_fill_from_frame
02138             (raw_jitter_stats, this_target_frame, iframe);
02139 
02140         /* Compute the telescope pcs statistics */
02141         this_properties = cpl_propertylist_load
02142             (cpl_frame_get_filename(this_target_frame), 0);
02143         if(this_properties == NULL)
02144         {
02145             cpl_msg_error(cpl_func,"Could not read the header of object frame");
02146             return  -1;
02147         }
02148         if(hawki_extract_prop_tel_qc(this_properties, raw_obj_tel_info, iframe))
02149         {
02150             cpl_msg_warning(cpl_func,"Some telescope properties could not be "
02151                             "read for image %d", iframe+1);
02152             cpl_errorstate_set(CPL_ERROR_NONE);
02153         }
02154         cpl_propertylist_delete(this_properties);
02155     }
02156 
02157     /* Saving the already computed products */
02158     cpl_msg_info(cpl_func, "Saving image statistics");
02159     if(hawki_sci_jitter_save_stats(raw_jitter_stats, raw_obj_tel_info, 
02160                                    obj,
02161                                    parlist, recipe_set) != 0)
02162         cpl_msg_warning(cpl_func,"Some data could not be saved. "
02163                         "Check permisions or disk space");
02164         
02165     
02166     /* Free and return */
02167     return 0;
02168 }
02169 
02170 int hawki_sci_jitter_save_stats
02171 (cpl_table          ** raw_jitter_stats,
02172  cpl_table          *  raw_obj_tel_info,
02173  cpl_frameset       *  jitter_frames,
02174  cpl_parameterlist  *  parlist,
02175  cpl_frameset       *  recipe_set)
02176 {
02177     int                 idet;
02178     const cpl_frame  *  ref_frame;
02179     cpl_propertylist ** qcstats;
02180     cpl_propertylist *  telstats;
02181     const char       *  recipe_name = "hawki_sci_jitter" ;
02182     cpl_errorstate      error_prevstate = cpl_errorstate_get();
02183     
02184     /* Statistics of the raw images in the QC */
02185     qcstats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*));
02186     /* Create the QC lists */
02187     ref_frame = irplib_frameset_get_first_from_group
02188         (recipe_set, CPL_FRAME_GROUP_RAW);
02189     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
02190     {
02191         int                ext_nb;
02192         cpl_propertylist * reflist;
02193         
02194         qcstats[idet] = cpl_propertylist_new();
02195         /* Propagate some keywords from input raw frame extensions */
02196         ext_nb = 
02197             hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), idet+1);
02198         reflist = cpl_propertylist_load_regexp
02199             (cpl_frame_get_filename(ref_frame), ext_nb,
02200              HAWKI_HEADER_EXT_FORWARD, 0) ;
02201         cpl_propertylist_append(qcstats[idet], reflist);
02202         cpl_propertylist_delete(reflist);
02203     }
02204     hawki_image_stats_stats(raw_jitter_stats, qcstats);
02205     /* Write the table with the raw jitter objects statistics */
02206     hawki_tables_save(recipe_set,
02207                       parlist,
02208                       jitter_frames,
02209                       (const cpl_table **)raw_jitter_stats,
02210                       recipe_name,
02211                       HAWKI_CALPRO_JITTER_STATS,
02212                       HAWKI_PROTYPE_JITTER_STATS,
02213                       NULL,
02214                       (const cpl_propertylist**)qcstats,
02215                       "hawki_sci_jitter_stats.fits");
02216     /* Free qcstats */
02217     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
02218         cpl_propertylist_delete(qcstats[idet]);
02219     
02220     /* Write the FITS table with the raw telescope data */
02221     telstats = cpl_propertylist_new();
02222     cpl_propertylist_append_string(telstats, CPL_DFS_PRO_TYPE,
02223                                    HAWKI_PROTYPE_SCIENCE_PCS);
02224     cpl_propertylist_append_string(telstats, CPL_DFS_PRO_CATG,
02225                                    HAWKI_CALPRO_SCIENCE_PCS);
02226     hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats);
02227     if(cpl_dfs_save_table(recipe_set,
02228                           NULL,
02229                           parlist,
02230                           jitter_frames,
02231                           NULL,
02232                           raw_obj_tel_info,
02233                           NULL,
02234                           recipe_name,
02235                           telstats,
02236                           NULL,
02237                           PACKAGE "/" PACKAGE_VERSION,
02238                           "hawki_sci_jitter_pcs.fits") != CPL_ERROR_NONE)
02239         cpl_msg_error(cpl_func,"Cannot save PCS table");
02240     
02241     /* Free and return */
02242     cpl_propertylist_delete(telstats);
02243     cpl_free(qcstats);
02244     if(!cpl_errorstate_is_equal(error_prevstate))
02245     {
02246         cpl_errorstate_set(CPL_ERROR_NONE);
02247         return -1;
02248     }
02249         
02250     return 0;
02251 }