HAWKI Pipeline Reference Manual 1.8.10
hawki_sci_jitter.c
00001 /* $Id: hawki_sci_jitter.c,v 1.31 2012/12/04 09:41:34 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: 2012/12/04 09:41:34 $
00024  * $Revision: 1.31 $
00025  * $Name: hawki-1_8_10 $
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     /* Get the offsets */
00825     if ((offsets = hawki_get_header_tel_offsets(jitters)) == NULL) {
00826         cpl_msg_error(cpl_func, "Cannot load the offsets") ;
00827         return NULL ;
00828     }
00829     offs_est_x = cpl_bivector_get_x_data(offsets) ;
00830     offs_est_y = cpl_bivector_get_y_data(offsets) ;
00831 
00832     /* Print the header offsets */
00833     for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) {
00834         cpl_msg_info(cpl_func, "Telescope offsets (Frame %d): %g %g", ioff+1,
00835                 offs_est_x[ioff], offs_est_y[ioff]) ;
00836     }
00837 
00838     /* Subtract the first offset to all offsets */
00839     off_0_x = -offs_est_x[0]; // This is to get the cpl convention
00840     off_0_y = -offs_est_y[0];
00841     for (ioff=1 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) 
00842     {
00843         offs_est_x[ioff] -= offs_est_x[0] ;
00844         offs_est_y[ioff] -= offs_est_y[0] ;
00845     }
00846     offs_est_x[0] = offs_est_y[0] = 0.00 ;
00847 
00848     /* Check if the max offset is not too big */
00849     /* The criteria is that for a given frame, the closest frame cannot be 
00850      * further than hawki_sci_jitter_config.offset_max (in both dimensions) */
00851     offset_x_sort = cpl_vector_duplicate(cpl_bivector_get_x(offsets));
00852     offset_y_sort = cpl_vector_duplicate(cpl_bivector_get_y(offsets));
00853     cpl_vector_sort(offset_x_sort, +1);
00854     cpl_vector_sort(offset_y_sort, +1);
00855     for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) - 1 ; ioff++)
00856     {
00857         double diff_x, diff_y;
00858         diff_x = cpl_vector_get(offset_x_sort,ioff+1)-cpl_vector_get(offset_x_sort,ioff);
00859         cpl_vector_set(offset_x_sort, ioff, diff_x);
00860         diff_y = cpl_vector_get(offset_y_sort,ioff+1)-cpl_vector_get(offset_y_sort,ioff);
00861         cpl_vector_set(offset_y_sort, ioff, diff_y);
00862     }
00863     cpl_vector_set(offset_x_sort, cpl_bivector_get_size(offsets)-1, 0.);
00864     cpl_vector_set(offset_y_sort, cpl_bivector_get_size(offsets)-1, 0.);
00865     max_x = cpl_vector_get_max(offset_x_sort);
00866     max_y = cpl_vector_get_max(offset_y_sort);
00867     cpl_vector_delete(offset_x_sort);
00868     cpl_vector_delete(offset_y_sort);
00869     
00870     if (max_x > hawki_sci_jitter_config.offset_max || 
00871         max_y > hawki_sci_jitter_config.offset_max) 
00872     {
00873         cpl_msg_error(cpl_func, "Sorry, no support for frames further than %d from its closest neighbour",
00874                 hawki_sci_jitter_config.offset_max) ;
00875         cpl_bivector_delete(offsets);
00876         return NULL ;
00877     }
00878     
00879     /* Create output object */
00880     combined = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_image*)) ;
00881   
00882     /* Loop on the detectors */
00883     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
00884     {
00885         cpl_frameset  *  selected_jitter;
00886         cpl_bivector  *  selected_offsets;
00887         cpl_image     *  flat_ima = NULL;
00888         cpl_image     *  dark_ima = NULL;
00889         cpl_image     *  bpm_ima = NULL;
00890         cpl_imagelist *  in = NULL;
00891         cpl_imagelist *  in_sky = NULL;
00892         int              nrejected;
00893         
00894         cpl_msg_info(cpl_func, "Combine chip number %d", idet+1) ;
00895         cpl_msg_indent_more() ;
00896         
00897         /* Apply frame selection based on offset values */
00898         selected_jitter     = cpl_frameset_duplicate(jitters);
00899         selected_offsets = cpl_bivector_duplicate(offsets);
00900         if(hawki_sci_jitter_config.max_njitter != -1)
00901         {
00902             if(hawki_sci_jitter_config.max_njitter <
00903                     cpl_frameset_get_size(selected_jitter))
00904             {
00905                 while(cpl_frameset_get_size(selected_jitter) >
00906                       hawki_sci_jitter_config.max_njitter)
00907                 {
00908                     int irm = cpl_frameset_get_size(selected_jitter) - 1;
00909                     cpl_frameset_erase_frame
00910                         (selected_jitter,
00911                          cpl_frameset_get_frame(selected_jitter,irm));
00912                 }
00913                 cpl_vector_set_size(cpl_bivector_get_x(selected_offsets),
00914                                     hawki_sci_jitter_config.max_njitter);
00915                 cpl_vector_set_size(cpl_bivector_get_y(selected_offsets),
00916                                     hawki_sci_jitter_config.max_njitter);
00917             }
00918         }
00919         hawki_sci_jitter_output.ncomb[idet] = 
00920             cpl_frameset_get_size(selected_jitter);
00921         nrejected = cpl_frameset_get_size(selected_jitter) - 
00922             cpl_frameset_get_size(jitters);
00923         if(nrejected != 0)
00924             cpl_msg_info(cpl_func,"%d frames reject due to large offsets", 
00925                          nrejected); 
00926                 
00927         
00928         /* Load the input data */
00929         cpl_msg_info(cpl_func, "Load the input data") ;
00930         cpl_msg_indent_more() ;
00931         if ((in = hawki_load_detector(selected_jitter,
00932                                   idet+1, CPL_TYPE_FLOAT)) == NULL) {
00933             cpl_msg_error(cpl_func, "Cannot load chip %d", idet+1) ;
00934             cpl_free(combined) ;
00935             cpl_bivector_delete(offsets) ;
00936             cpl_msg_indent_less() ;
00937             cpl_msg_indent_less() ;
00938             return NULL ;
00939         }
00940         if (sky) {
00941             if ((in_sky = hawki_load_detector(sky, idet+1, CPL_TYPE_FLOAT)) == NULL) 
00942             {
00943                 cpl_msg_warning(cpl_func, "Cannot load sky for chip %d",idet+1);
00944             }
00945         } else in_sky = NULL ;
00946         cpl_msg_indent_less() ;
00947 
00948         /* Read the calibrations */
00949         cpl_msg_info(cpl_func, "Load the calibration data") ;
00950         if(hawki_sci_jitter_read_calib(flat, dark, bpm,
00951                                        &flat_ima, &dark_ima, &bpm_ima,
00952                                        idet) != 0)
00953         {
00954             cpl_msg_error(cpl_func, "Cannot read some of the calibrations");
00955             cpl_imagelist_delete(in);
00956             cpl_free(combined);
00957             if (in_sky) cpl_imagelist_delete(in_sky);
00958             cpl_bivector_delete(offsets);
00959             cpl_msg_indent_less();
00960             cpl_msg_indent_less();
00961             return NULL ;
00962         }
00963         
00964         /* Apply the calibrations */
00965         if (flat || dark || bpm ) 
00966         {
00967             cpl_msg_info(cpl_func, "Apply the calibrations") ;
00968             cpl_msg_indent_more() ;
00969             /* Basic calibration of the OBJECTS */
00970             if (hawki_flat_dark_bpm_detector_calib
00971                     (in, flat_ima, dark_ima, bpm_ima) == -1) 
00972             {
00973                 cpl_msg_error(cpl_func, "Cannot calibrate the objects") ;
00974                 cpl_imagelist_delete(in) ;
00975                 cpl_free(combined) ;
00976                 if (in_sky) cpl_imagelist_delete(in_sky) ;
00977                 cpl_bivector_delete(offsets) ;
00978                 cpl_image_delete(flat_ima);
00979                 cpl_image_delete(dark_ima);
00980                 cpl_image_delete(bpm_ima);
00981                 cpl_msg_indent_less() ;
00982                 cpl_msg_indent_less() ;
00983                 return NULL ;
00984             }
00985             /* Basic calibration of the SKY */
00986             if (in_sky) {
00987                 if (hawki_flat_dark_bpm_detector_calib
00988                         (in_sky, flat_ima, dark_ima, bpm_ima) == -1) 
00989                 {
00990                     cpl_msg_warning(cpl_func, "Cannot calibrate the sky") ;
00991                     cpl_imagelist_delete(in_sky) ;
00992                     in_sky = NULL ;
00993                 }
00994             }
00995             cpl_msg_indent_less() ;
00996         }
00997         cpl_image_delete(flat_ima);
00998         cpl_image_delete(dark_ima);
00999         cpl_image_delete(bpm_ima);
01000 
01001         /* Apply the sky correction */
01002         cpl_msg_info(cpl_func, "Sky estimation and correction") ;
01003         cpl_msg_indent_more() ;
01004         if (hawki_sci_jitter_sky(in, in_sky, bkg_stats, idet) == -1)
01005         {
01006             cpl_msg_error(cpl_func, "Cannot estimate the sky") ;
01007             cpl_imagelist_delete(in) ;
01008             if (in_sky) cpl_imagelist_delete(in_sky) ;
01009             cpl_free(combined) ;
01010             cpl_bivector_delete(offsets) ;
01011             cpl_msg_indent_less() ;
01012             cpl_msg_indent_less() ;
01013             return NULL ;
01014         }
01015         if (in_sky) cpl_imagelist_delete(in_sky) ;
01016         cpl_msg_indent_less() ;
01017     
01018         /* Apply the shift and add */
01019         cpl_msg_info(cpl_func, "Shift and stacking") ;
01020         cpl_msg_indent_more() ;
01021         comb_chip = hawki_sci_jitter_saa(&in, selected_offsets, 
01022                 &(hawki_sci_jitter_output.combined_pos_x[idet]),
01023                 &(hawki_sci_jitter_output.combined_pos_y[idet])) ;
01024         hawki_sci_jitter_output.combined_cumoffset_x[idet] = 
01025             hawki_sci_jitter_output.combined_pos_x[idet] - off_0_x;
01026         hawki_sci_jitter_output.combined_cumoffset_y[idet] = 
01027             hawki_sci_jitter_output.combined_pos_y[idet] - off_0_y;
01028         if (comb_chip == NULL) {
01029             cpl_msg_error(cpl_func, "Cannot apply the shift and add") ;
01030             cpl_imagelist_delete(in) ;
01031             cpl_free(combined) ;
01032             cpl_bivector_delete(offsets) ;
01033             cpl_msg_indent_less() ;
01034             cpl_msg_indent_less() ;
01035             return NULL ;
01036         }
01037         cpl_imagelist_delete(in) ;
01038         cpl_msg_indent_less() ;
01039 
01040         /* Put the results in the image list */
01041         combined[idet] = comb_chip[0] ;
01042         cpl_image_delete(comb_chip[1]) ;
01043         cpl_free(comb_chip) ;
01044         cpl_msg_indent_less() ;
01045         
01046         /* Free */
01047         cpl_frameset_delete(selected_jitter);
01048         cpl_bivector_delete(selected_offsets);
01049     }
01050     cpl_bivector_delete(offsets) ;
01051 
01052     return combined ;
01053 }
01054 
01055 /*----------------------------------------------------------------------------*/
01062 /*----------------------------------------------------------------------------*/
01063 static int hawki_sci_jitter_sky
01064 (cpl_imagelist   *   objs,
01065  cpl_imagelist   *   skys,
01066  cpl_table       **  bkg_stats,
01067  int                 idet)
01068 {
01069     cpl_image       *   sky ;
01070     int                 nframes;
01071     double              median ;
01072     cpl_image       *   cur_ima ;
01073     int                 i ;
01074 
01075     /* Initialise */
01076     nframes = cpl_imagelist_get_size(objs) ;
01077 
01078     /* Compute the sky frame */
01079     if (skys != NULL) {
01080        cpl_msg_info(cpl_func, "Median of sky images") ;
01081         /* Use sky images */
01082         if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) {
01083             cpl_msg_error(cpl_func, "Cannot compute the median of sky images") ;
01084             return -1;
01085         }
01086         
01087         /* Statistics on the background */
01088         if(bkg_stats != NULL)
01089         {
01090             cpl_table_set_size(bkg_stats[idet], 1);
01091             hawki_image_stats_fill_from_image
01092                 (bkg_stats, sky,
01093                  1,
01094                  1,
01095                  cpl_image_get_size_x(sky),
01096                  cpl_image_get_size_y(sky),
01097                  idet, 0);
01098         }
01099         
01100         /* Correct the objects images  */
01101         if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) {
01102             cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
01103             cpl_image_delete(sky) ;
01104             return -1;
01105         }
01106         cpl_image_delete(sky) ;
01107         /* Normalise the object planes */
01108         for (i=0 ; i<nframes ; i++) {
01109             cur_ima = cpl_imagelist_get(objs, i) ;
01110             median = cpl_image_get_median(cur_ima) ;
01111             cpl_image_subtract_scalar(cur_ima, median) ;
01112         }
01113     } else if (hawki_sci_jitter_config.sky_minnb > nframes) {
01114         cpl_msg_info(cpl_func, "Median of object images") ;
01115          /* Use objs images */
01116         if ((sky = cpl_imagelist_collapse_median_create(objs)) == NULL) {
01117             cpl_msg_error(cpl_func, "Cannot compute the median of obj images") ;
01118             return -1;
01119         }
01120 
01121         /* Statistics on the background */
01122         if(bkg_stats != NULL)
01123         {
01124             cpl_table_set_size(bkg_stats[idet], 1);
01125             hawki_image_stats_fill_from_image
01126                 (bkg_stats, sky,
01127                  1,
01128                  1,
01129                  cpl_image_get_size_x(sky),
01130                  cpl_image_get_size_y(sky),
01131                  idet, 0);
01132         }
01133         
01134         /* Correct the objects images  */
01135         if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) {
01136             cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky");
01137             cpl_image_delete(sky) ;
01138             return -1;
01139         }
01140         /* Normalise the object planes */
01141         for (i=0 ; i<nframes ; i++) {
01142             cur_ima = cpl_imagelist_get(objs, i) ;
01143             median = cpl_image_get_median(cur_ima) ;
01144             cpl_image_subtract_scalar(cur_ima, median) ;
01145         }
01146         /* Delete sky image */
01147         cpl_image_delete(sky) ;
01148     } else {
01149         cpl_msg_info(cpl_func, "Computing running median on jitter images") ;
01150         /* Use objects images */
01151         if (hawki_sci_jitter_sky_running(objs, bkg_stats, idet) == -1)
01152         {
01153             cpl_msg_error(cpl_func, 
01154                     "Cannot apply the running median");
01155             return -1;
01156         }
01157     }
01158     return 0;
01159 }
01160 
01161 /*----------------------------------------------------------------------------*/
01180 /*----------------------------------------------------------------------------*/
01181 static int hawki_sci_jitter_sky_running
01182 (cpl_imagelist *  in,
01183  cpl_table     ** bkg_stats,
01184  int              idet) 
01185 {
01186     int                 rejmin, rejmax, halfw;
01187     cpl_imagelist   *   result_buffer;
01188     int                 ni, nx, ny;
01189     cpl_vector      *   medians;
01190     cpl_image       *   cur_ima;
01191     cpl_image       *   tmp_ima;
01192     double              one_med;
01193     int                 i, k;
01194     int                 first_buffered = 0;
01195     int                 next_not_to_be_used;
01196 
01197     /* Test entries */
01198     if (in==NULL) return -1;
01199 
01200     /* Initialise */
01201     rejmin = hawki_sci_jitter_config.sky_rejmin ;
01202     rejmax = hawki_sci_jitter_config.sky_rejmax ;
01203     halfw  = hawki_sci_jitter_config.sky_halfw ;
01204     ni = cpl_imagelist_get_size(in) ;
01205     cur_ima = cpl_imagelist_get(in, 0) ;
01206     nx = cpl_image_get_size_x(cur_ima) ;
01207     ny = cpl_image_get_size_y(cur_ima) ;
01208     
01209     /* Tests on validity of rejection parameters */
01210     if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) {
01211         cpl_msg_error(cpl_func, "cannot compute running median with "
01212                 "rejection  parameters %d (%d-%d)",
01213                 halfw, rejmin, rejmax);
01214         return -1;
01215     }   
01216     /* Pre-compute median value in each plane */
01217     medians = cpl_vector_new(ni) ;
01218     for (i=0 ; i<ni ; i++) {
01219         cur_ima = cpl_imagelist_get(in, i) ;
01220         cpl_vector_set(medians, i, cpl_image_get_median(cur_ima)) ;
01221     }
01222     /* Allocate output cube */
01223     result_buffer = cpl_imagelist_new() ;
01224 
01225     /* Allocate output bg stats */
01226     cpl_table_set_size(bkg_stats[idet], ni);
01227     
01228     /* Main loop over input planes */
01229     for (k=0 ; k<ni ; k++)
01230     {
01231         cpl_image * bkg;
01232 
01233         /* Create the background image, to later compute stats */
01234         bkg = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01235 
01236         hawki_bkg_from_running_mean
01237             (in, medians, k, halfw, rejmin, rejmax, bkg);
01238 
01239         /* Subtract the background from the current image */
01240         tmp_ima = cpl_image_subtract_create(cpl_imagelist_get(in, k), bkg);
01241         
01242         /* Statistics on the background */
01243         if(bkg_stats != NULL)
01244         {
01245             hawki_image_stats_fill_from_image
01246                 (bkg_stats, bkg,
01247                  1, 1, nx, ny,
01248                  idet, k);
01249         }
01250         cpl_image_delete(bkg);
01251        
01252         /* Place the new image in a result buffer */
01253         cpl_imagelist_set(result_buffer, tmp_ima,
01254                           cpl_imagelist_get_size(result_buffer));
01255         
01256         /* Empty the buffer as much as possible */
01257         next_not_to_be_used = k - halfw;
01258         while(next_not_to_be_used >= first_buffered)
01259         {
01260             cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0),
01261                               first_buffered);
01262             first_buffered++;
01263         }
01264     }
01265     /* Empty the buffer finally */
01266     next_not_to_be_used = ni - 1;
01267     while(next_not_to_be_used >= first_buffered)
01268     {
01269         cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0),
01270                           first_buffered);
01271         first_buffered++;
01272     }
01273     cpl_imagelist_delete(result_buffer);
01274     cpl_vector_delete(medians);
01275 
01276     /* Subtract median from each frame */
01277     for (i=0 ; i<ni ; i++) {
01278         cur_ima = cpl_imagelist_get(in, i);
01279         one_med = cpl_image_get_median(cur_ima) ;
01280         cpl_image_subtract_scalar(cur_ima, one_med) ;
01281     }
01282     return 0;
01283 }
01284 
01285 /*----------------------------------------------------------------------------*/
01294 /*----------------------------------------------------------------------------*/
01295 static cpl_image ** hawki_sci_jitter_saa(
01296         cpl_imagelist   **  in,
01297         cpl_bivector    *   offsets,
01298         double          *   pos_x,
01299         double          *   pos_y)
01300 {
01301     cpl_bivector        *   offs_est;
01302     cpl_bivector        *   offs_used;
01303     cpl_bivector        *   objs ;
01304     cpl_image           **  combined ;
01305     int                     nfiles, ngood, nima, nx, ny ;
01306     int                     i;
01307 
01308     /* Check entries */
01309     if (pos_x == NULL || pos_y == NULL) return NULL ;
01310     if (offsets == NULL) return NULL ;
01311 
01312     /* Get the number of images */
01313     nfiles = cpl_imagelist_get_size(*in) ;
01314     if (cpl_bivector_get_size(offsets) != nfiles) {
01315         cpl_msg_error(cpl_func, "Invalid input objects sizes") ; 
01316         return NULL ;
01317     }
01318     
01319     /* Get the offsets estimation of each input file pair */
01320     cpl_msg_info(cpl_func, "Get the offsets estimation") ;
01321     offs_est = NULL ;
01322     if (hawki_sci_jitter_config.offsets &&
01323             hawki_sci_jitter_config.offsets[0] != (char)0) {
01324         /* A file has been provided on the command line */
01325         offs_est = cpl_bivector_read((char*)hawki_sci_jitter_config.offsets);
01326         if ((offs_est==NULL)||(cpl_bivector_get_size(offs_est)!=nfiles)) {
01327             cpl_msg_error(cpl_func, "Cannot get offsets from %s", 
01328                     hawki_sci_jitter_config.offsets) ;
01329             return NULL ;
01330         }
01331     } else {
01332         /* Use the offsets from the header */
01333         offs_est = cpl_bivector_duplicate(offsets) ;
01334         cpl_vector_multiply_scalar(cpl_bivector_get_x(offs_est), -1.0) ;
01335         cpl_vector_multiply_scalar(cpl_bivector_get_y(offs_est), -1.0) ;
01336     }
01337 
01338     /* Read the provided objects file if provided */
01339     objs = NULL ;
01340     if (hawki_sci_jitter_config.refine &&
01341             hawki_sci_jitter_config.objects &&
01342             hawki_sci_jitter_config.objects[0] != (char)0) {
01343         cpl_msg_info(cpl_func, "Get the user provided correlation objects") ;
01344         /* A file has been provided on the command line */
01345         objs = cpl_bivector_read((char*)hawki_sci_jitter_config.objects) ;
01346         if (objs==NULL) {
01347             cpl_msg_error(cpl_func, "Cannot get objects from %s",
01348                     hawki_sci_jitter_config.objects) ;
01349             cpl_bivector_delete(offs_est) ;
01350             return NULL ;
01351         }
01352     }
01353 
01354     /* Get a correlation point from the difference of the first images */
01355     if (hawki_sci_jitter_config.refine && objs == NULL) {
01356         cpl_apertures  *   aperts;
01357         cpl_image      *   detect_image;
01358         cpl_vector     *   thresh_vect;
01359         double         *   objs_x ;
01360         double         *   objs_y ;
01361         cpl_msg_info(cpl_func, "Get a cross-correlation point") ;
01362         thresh_vect = cpl_vector_new(4) ;
01363         cpl_vector_set(thresh_vect, 0, 5.0) ;
01364         cpl_vector_set(thresh_vect, 1, 2.0) ;
01365         cpl_vector_set(thresh_vect, 2, 1.0) ;
01366         cpl_vector_set(thresh_vect, 3, 0.5) ;
01367         detect_image  = cpl_imagelist_get(*in, 0);
01368         if ((aperts = cpl_apertures_extract_window(detect_image, thresh_vect, 
01369                         400, 400, 1600, 1600, NULL)) == NULL) {
01370             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ;
01371             cpl_bivector_delete(offs_est) ;
01372             cpl_vector_delete(thresh_vect) ;
01373             return NULL ;
01374         }
01375         cpl_vector_delete(thresh_vect) ;
01376         cpl_apertures_sort_by_npix(aperts) ;
01377         objs = cpl_bivector_new(1) ;
01378         objs_x = cpl_bivector_get_x_data(objs) ;
01379         objs_y = cpl_bivector_get_y_data(objs) ;
01380         objs_x[0] = cpl_apertures_get_pos_x(aperts, 1) ;
01381         objs_y[0] = cpl_apertures_get_pos_y(aperts, 1) ;
01382         cpl_apertures_delete(aperts) ;
01383         if (objs == NULL) {
01384             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ;
01385             cpl_bivector_delete(offs_est) ;
01386             return NULL ;
01387         }
01388         cpl_msg_info(cpl_func, 
01389                 "Correlation point: %g %g\n", objs_x[0], objs_y[0]);
01390     }
01391 
01392     /* Refine the offsets */
01393     if (hawki_sci_jitter_config.refine) {
01394         cpl_bivector *   offs_refined;
01395         double       *   offs_refined_x;
01396         double       *   offs_refined_y;
01397         double       *   offs_est_x;
01398         double       *   offs_est_y;
01399         cpl_vector   *   correl ;
01400         double       *   correl_data ;
01401         cpl_msg_info(cpl_func, "Refine the offsets");
01402         cpl_msg_indent_more() ;
01403         nima = cpl_imagelist_get_size(*in) ;
01404         correl = cpl_vector_new(nima) ;
01405         if ((offs_refined = cpl_geom_img_offset_fine(*in, offs_est, objs,
01406                         hawki_sci_jitter_config.sx, 
01407                         hawki_sci_jitter_config.sy,
01408                         hawki_sci_jitter_config.mx, 
01409                         hawki_sci_jitter_config.my,
01410                         correl)) == NULL) {
01411             cpl_msg_error(cpl_func, "Cannot refine the offsets");
01412             cpl_bivector_delete(offs_est) ;
01413             if (objs != NULL) cpl_bivector_delete(objs) ;
01414             cpl_vector_delete(correl) ;
01415             return NULL ;
01416         }
01417         if (objs != NULL) cpl_bivector_delete(objs) ;
01418 
01419         /* Display the results */
01420         offs_est_x = cpl_bivector_get_x_data(offs_est);
01421         offs_est_y = cpl_bivector_get_y_data(offs_est);
01422         offs_refined_x = cpl_bivector_get_x_data(offs_refined);
01423         offs_refined_y = cpl_bivector_get_y_data(offs_refined) ;
01424         correl_data = cpl_vector_get_data(correl) ;
01425         cpl_msg_info(cpl_func, "Refined offsets [correlation factor]") ;
01426         ngood = 0 ;
01427         for (i=0 ; i<nima ; i++) {
01428             cpl_msg_info(cpl_func, "#%02d: %8.2f %8.2f [%12.2f]",
01429                     i+1, offs_refined_x[i], offs_refined_y[i], correl_data[i]);
01430             if (correl_data[i] > -0.5) ngood++ ;
01431         }
01432         if (ngood == 0) {
01433             cpl_msg_error(cpl_func, "No frame correctly correlated") ;
01434             cpl_bivector_delete(offs_est);
01435             cpl_bivector_delete(offs_refined);
01436             cpl_vector_delete(correl);
01437             return NULL ;
01438         }
01439         cpl_msg_indent_less();
01440 
01441         /* Replace bad correlated images with the nominal offsets */
01442         cpl_msg_info(cpl_func, "Using nominal offsets for badly "
01443                      "correlated images (%d out of %d)", nima-ngood, nima);
01444         for (i=0 ; i<nima ; i++) {
01445             if (correl_data[i] < -0.5) {
01446                 offs_refined_x[i] = offs_est_x[i];
01447                 offs_refined_y[i] = offs_est_y[i];
01448             }
01449         }
01450         offs_used = cpl_bivector_duplicate(offs_refined);
01451         cpl_bivector_delete(offs_est);
01452         cpl_bivector_delete(offs_refined);
01453         cpl_vector_delete(correl);
01454     }
01455     else
01456     {
01457         offs_used = cpl_bivector_duplicate(offs_est);
01458         cpl_bivector_delete(offs_est);
01459     }
01460 
01461     /* Discard the pixels on the sides */
01462     if (hawki_sci_jitter_config.borders > 0) {
01463         cpl_imagelist  *   in_ext ;
01464         cpl_image      *   tmp1 ;
01465         cpl_image      *   tmp2 ;
01466         nx = cpl_image_get_size_x(cpl_imagelist_get(*in, 0)) ;
01467         ny = cpl_image_get_size_y(cpl_imagelist_get(*in, 0)) ;
01468         in_ext = cpl_imagelist_new() ;
01469         while(cpl_imagelist_get_size(*in) > 0)
01470         {
01471             tmp1 = cpl_imagelist_unset(*in, 0);
01472             tmp2 = cpl_image_extract(tmp1, 
01473                     hawki_sci_jitter_config.borders+1, 
01474                     hawki_sci_jitter_config.borders+1, 
01475                     nx-hawki_sci_jitter_config.borders, 
01476                     ny-hawki_sci_jitter_config.borders) ;
01477             cpl_image_delete(tmp1);
01478             cpl_imagelist_set(in_ext, tmp2, cpl_imagelist_get_size(in_ext)) ;
01479         }
01480         cpl_imagelist_delete(*in) ;
01481         *in = in_ext ;
01482     }
01483 
01484     /* Apply the shift & add */
01485     cpl_msg_info(cpl_func, "Recombine the images set") ;
01486     cpl_msg_indent_more() ;
01487     if ((combined=cpl_geom_img_offset_saa(*in, offs_used,
01488                     CPL_KERNEL_DEFAULT, 
01489                     hawki_sci_jitter_config.rej_low,
01490                     hawki_sci_jitter_config.rej_high,
01491                     hawki_sci_jitter_config.comb_meth,
01492                     pos_x, pos_y)) == NULL) {
01493         cpl_msg_error(cpl_func, "Cannot apply the shift and add") ;
01494         cpl_bivector_delete(offs_used) ;
01495         cpl_msg_indent_less() ;
01496         return NULL ;
01497     }
01498     cpl_msg_indent_less() ;
01499     *pos_x -= hawki_sci_jitter_config.borders ;
01500     *pos_y -= hawki_sci_jitter_config.borders ;
01501 
01502     /* Free and return */
01503     cpl_bivector_delete(offs_used) ;
01504     return combined ;
01505 }
01506 
01507 /*----------------------------------------------------------------------------*/
01514 /*----------------------------------------------------------------------------*/
01515 static int hawki_sci_jitter_qc
01516 (cpl_frameset *   science_frames,
01517  cpl_image   **   combined_images, 
01518  cpl_table   **   obj_charac)
01519 {
01520     cpl_vector      *   thresh_vec ;
01521     cpl_apertures   *   aperts ;
01522     int                 nb_objs ;
01523     double              angle ;
01524     double          *   fwhms_x ;
01525     double          *   fwhms_y ;
01526     cpl_bivector    *   iqe ;
01527     int                 nb_good ;
01528     cpl_vector      *   fwhms_good ;
01529     double          *   fwhms_good_data ;
01530     double              f_min, f_max, fr, fx, fy ;
01531     int                 chip;
01532     int                 iobj;
01533     int                 j;
01534     
01535     /* Initialise */
01536     double              seeing_min_arcsec = 0.1 ;
01537     double              seeing_max_arcsec = 5.0 ;
01538     double              seeing_fwhm_var   = 0.2 ;
01539 
01540     /* Check entries */
01541     if (combined_images  == NULL) return -1 ;
01542     if (obj_charac       == NULL) return -1 ;
01543 
01544     /* Create the vector for the detection thresholds */
01545     thresh_vec = cpl_vector_new(11) ;
01546     cpl_vector_set(thresh_vec, 0, 100.0) ;
01547     cpl_vector_set(thresh_vec, 0, 90.0) ;
01548     cpl_vector_set(thresh_vec, 0, 80.0) ;
01549     cpl_vector_set(thresh_vec, 0, 70.0) ;
01550     cpl_vector_set(thresh_vec, 0, 60.0) ;
01551     cpl_vector_set(thresh_vec, 0, 50.0) ;
01552     cpl_vector_set(thresh_vec, 1, 40.0) ;
01553     cpl_vector_set(thresh_vec, 1, 30.0) ;
01554     cpl_vector_set(thresh_vec, 1, 20.0) ;
01555     cpl_vector_set(thresh_vec, 1, 10.0) ;
01556     cpl_vector_set(thresh_vec, 2, 5.0) ;
01557 
01558     /* Get the mean airmass */
01559     hawki_sci_jitter_output.mean_airmass = 
01560         hawki_get_mean_airmass(science_frames);;
01561     
01562     /* Loop on the HAWK-I detectors */
01563     for (chip=0 ; chip<HAWKI_NB_DETECTORS ; chip++) 
01564     {
01565         /* Check entries */
01566         if (combined_images[chip]  == NULL) return -1 ;
01567         if (obj_charac[chip] == NULL) return -1 ;
01568     
01569         /* Detect apertures */
01570         if ((aperts = cpl_apertures_extract
01571                 (combined_images[chip], thresh_vec, NULL)) == NULL) {
01572             cpl_msg_warning(cpl_func, "Cannot detect any aperture on chip %d",
01573                             chip+1) ;
01574             continue;
01575         }
01576 
01577         /* Number of detected objects */
01578         nb_objs = cpl_apertures_get_size(aperts);
01579         cpl_msg_info(cpl_func, "%d objects detected on chip %d",nb_objs,chip+1);
01580         hawki_sci_jitter_output.nbobjs[chip] = nb_objs ;
01581         fwhms_x = cpl_malloc(nb_objs * sizeof(double)) ;
01582         fwhms_y = cpl_malloc(nb_objs * sizeof(double)) ;
01583         
01584         /* Initialize the output table */
01585         cpl_table_set_size(obj_charac[chip], nb_objs);
01586         cpl_table_new_column
01587             (obj_charac[chip], HAWKI_COL_OBJ_POSX, CPL_TYPE_DOUBLE);
01588         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSX,"pix");
01589         cpl_table_new_column
01590             (obj_charac[chip], HAWKI_COL_OBJ_POSY, CPL_TYPE_DOUBLE);
01591         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSY,"pix");
01592         cpl_table_new_column
01593             (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, CPL_TYPE_DOUBLE);
01594         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_ANGLE,"grad");
01595         cpl_table_new_column
01596             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, CPL_TYPE_DOUBLE);
01597         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MAJAX,"pix");
01598         cpl_table_new_column
01599             (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, CPL_TYPE_DOUBLE);
01600         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MINAX,"pix");
01601         cpl_table_new_column
01602             (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, CPL_TYPE_DOUBLE);
01603         cpl_table_new_column
01604             (obj_charac[chip], HAWKI_COL_OBJ_FLUX, CPL_TYPE_DOUBLE);
01605         cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FLUX,"ADU");
01606         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01607         {
01608             /* Fill with the already known information */
01609             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSX, iobj, 
01610                                  cpl_apertures_get_centroid_x(aperts, iobj+1));
01611             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSY, iobj, 
01612                                  cpl_apertures_get_centroid_y(aperts, iobj+1));
01613             cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_FLUX, iobj, 
01614                                  cpl_apertures_get_flux(aperts, iobj+1)) ;
01615             /* Compute the FWHM informations */
01616             if ((iqe = cpl_image_iqe(combined_images[chip], 
01617                 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) - 10,
01618                 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) - 10,
01619                 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) + 10,
01620                 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) + 10))==NULL)
01621             {
01622                 cpl_error_reset() ;
01623                 cpl_msg_debug(cpl_func, "Cannot get FWHM for obj at pos %g %g",
01624                               cpl_apertures_get_centroid_x(aperts, iobj+1),
01625                               cpl_apertures_get_centroid_y(aperts, iobj+1)) ;
01626                 fwhms_x[iobj] = -1.0 ;
01627                 fwhms_y[iobj] = -1.0 ;
01628                 angle = 0.0 ;
01629             }
01630             else 
01631             {
01632                 fwhms_x[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 2) ;
01633                 fwhms_y[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 3) ;
01634                 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4) ;
01635                 cpl_bivector_delete(iqe) ;
01636                 cpl_msg_debug(cpl_func,
01637                               "FWHM for obj at pos %g %g: %g x %g (%g)",
01638                               cpl_apertures_get_centroid_x(aperts, iobj+1),
01639                               cpl_apertures_get_centroid_y(aperts, iobj+1),
01640                               fwhms_x[iobj], fwhms_y[iobj], angle) ;
01641             }
01642             cpl_table_set_double
01643                 (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, iobj, angle) ;
01644             cpl_table_set_double
01645                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, iobj,
01646                  fwhms_x[iobj]);
01647             cpl_table_set_double
01648                 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, iobj,
01649                  fwhms_y[iobj]);
01650             cpl_table_set_double
01651                 (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, iobj,
01652                  1 - fwhms_y[iobj] / fwhms_x[iobj]);
01653         }
01654         cpl_apertures_delete(aperts) ;
01655 
01656         /* Get the number of good values */
01657         nb_good = 0 ;
01658         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01659         {
01660             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) nb_good++ ;
01661         }
01662         if (nb_good == 0)
01663         {
01664             cpl_msg_warning(cpl_func, "No objects to compute FWHM on chip %d",
01665                             chip+1);
01666             cpl_free(fwhms_x) ;
01667             cpl_free(fwhms_y) ;
01668             continue;
01669         }
01670     
01671         /* Get the good values */
01672         fwhms_good = cpl_vector_new(nb_good) ;
01673         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
01674         j=0 ;
01675         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01676         {
01677             if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) 
01678             {
01679                 fwhms_good_data[j] = (fwhms_x[iobj]+fwhms_y[iobj])/2.0 ;
01680                 j++ ;
01681             }
01682         }
01683    
01684         /* Compute the fwhm */
01685         if (nb_good < 3) 
01686         {
01687             /* Too few values to compute the median */
01688             hawki_sci_jitter_output.fwhm_pix[chip] = fwhms_good_data[0] ;
01689         } 
01690         else 
01691         {
01692             /* Compute the median */
01693             hawki_sci_jitter_output.fwhm_pix[chip] =
01694                 cpl_vector_get_median_const(fwhms_good) ;
01695         }
01696         hawki_sci_jitter_output.fwhm_arcsec[chip] = 
01697             hawki_sci_jitter_output.fwhm_pix[chip] *
01698             hawki_sci_jitter_output.pixscale ;
01699 
01700         /* Compute the mode of the FWHMs */
01701         if (nb_good > 5) 
01702         {
01703             hawki_sci_jitter_output.fwhm_mode[chip] =
01704                 hawki_vector_get_mode(fwhms_good);
01705             hawki_sci_jitter_output.fwhm_mode[chip] *= 
01706                 hawki_sci_jitter_output.pixscale ;
01707         }
01708         cpl_vector_delete(fwhms_good) ;
01709     
01710         /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */
01711         /* Compute f_min and f_max */
01712         f_min = seeing_min_arcsec / hawki_sci_jitter_output.pixscale ;
01713         f_max = seeing_max_arcsec / hawki_sci_jitter_output.pixscale ;
01714 
01715         /* Get the number of good values */
01716         nb_good = 0 ;
01717         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01718         {
01719             fx = fwhms_x[iobj] ;
01720             fy = fwhms_y[iobj] ;
01721             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
01722             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01723                     (fr < seeing_fwhm_var)) nb_good++ ;
01724         }
01725         if (nb_good == 0) 
01726         {
01727             cpl_msg_warning(cpl_func, "No objects to compute IQ on chip %d",
01728                             chip+1);
01729             cpl_free(fwhms_x) ;
01730             cpl_free(fwhms_y) ;
01731             continue;
01732         }
01733 
01734         /* Get the good values */
01735         fwhms_good = cpl_vector_new(nb_good) ;
01736         fwhms_good_data = cpl_vector_get_data(fwhms_good) ;
01737         j=0 ;
01738         for (iobj=0 ; iobj<nb_objs ; iobj++) 
01739         {
01740             fx = fwhms_x[iobj] ;
01741             fy = fwhms_y[iobj] ;
01742             fr = 2.0 * fabs(fx-fy) / (fx+fy) ;
01743             if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01744                     (fr < seeing_fwhm_var)) 
01745             {
01746                 fwhms_good_data[j] = (fx + fy)/2.0 ;
01747                 j++ ;
01748             }
01749         }
01750         cpl_free(fwhms_x) ;
01751         cpl_free(fwhms_y) ;
01752     
01753         /* Compute the fwhm */
01754         if (nb_good < 3) 
01755         {
01756             /* Too few values to compute the median */
01757             hawki_sci_jitter_output.iq[chip] = fwhms_good_data[0] ;
01758         }
01759         else 
01760         {
01761             /* Compute the median */
01762             hawki_sci_jitter_output.iq[chip] = 
01763                 cpl_vector_get_median_const(fwhms_good) ;
01764         }
01765         cpl_vector_delete(fwhms_good) ;
01766         hawki_sci_jitter_output.iq[chip] *= hawki_sci_jitter_output.pixscale ;
01767     }
01768     
01769     /* Cleanup */
01770     cpl_vector_delete(thresh_vec) ;
01771     
01772     return 0;
01773 }
01774 
01775 /*----------------------------------------------------------------------------*/
01787 /*----------------------------------------------------------------------------*/
01788 static int hawki_sci_jitter_read_calib
01789 (const char *  flat,
01790  const char *  dark,
01791  const char *  bpm,
01792  cpl_image  ** flat_image,
01793  cpl_image  ** dark_image,
01794  cpl_image  ** bpm_image,
01795  int           idet)
01796 {
01797     const char * reffile;
01798     int          ext_nb;
01799     
01800     if(flat == NULL && dark == NULL && bpm == NULL)
01801         return 0;
01802     if(*flat_image != NULL || *dark_image != NULL || *bpm_image != NULL)
01803         return 0;
01804     
01805     /* Get the extension number for this detector */
01806     if(flat != NULL)
01807         reffile = flat;
01808     else if(dark != NULL)
01809         reffile = dark;
01810     else
01811         reffile = bpm;
01812 
01813     /* Guess which is the extension to read */
01814     if ((ext_nb = hawki_get_ext_from_detector(reffile, idet + 1)) == -1) {
01815         cpl_msg_error(cpl_func, "Cannot get the extension with detector %d",
01816                       idet + 1);
01817         return -1;
01818     }
01819 
01820     /* Load the dark image */
01821     if(dark != NULL)
01822         *dark_image = cpl_image_load(dark, CPL_TYPE_FLOAT, 0, ext_nb);
01823     /* Load the flat image */
01824     if(flat != NULL)
01825         *flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, ext_nb);
01826     /* Load the bpm image */
01827     if(bpm != NULL)
01828         *bpm_image = cpl_image_load(bpm, CPL_TYPE_FLOAT, 0, ext_nb);
01829     
01830     /* Multiply the dark image by the science exposure time */
01831     if(dark != NULL)
01832         cpl_image_multiply_scalar(*dark_image, hawki_sci_jitter_output.dit);
01833 
01834     /* Return */
01835     return 0;
01836 }
01837 
01838 /*----------------------------------------------------------------------------*/
01847 /*----------------------------------------------------------------------------*/
01848 static int hawki_sci_jitter_save
01849 (cpl_image           **  combined,
01850  cpl_image           *   stitched,
01851  cpl_table           **  obj_charac,
01852  cpl_table           **  raw_jitter_stats,
01853  cpl_table           **  bkg_stats,
01854  const cpl_table     *   raw_obj_tel_info,
01855  cpl_frameset        *   science_frames,
01856  cpl_frameset        *   calib_frames,
01857  cpl_parameterlist   *   parlist,
01858  cpl_frameset        *   set)
01859 {
01860     cpl_propertylist    *   plist ;
01861     double                  pscale, dit, bg_mean, bg_stdev, bg_instmag ;
01862     cpl_propertylist    **  qclists ;
01863     const cpl_frame     *   ref_frame ;
01864     cpl_frameset        *   used_frames;
01865     cpl_propertylist    *   wcslist ;
01866     cpl_propertylist    *   telstats;
01867     cpl_propertylist    *   inputlist ;
01868     double                  crpix1, crpix2 ;
01869     int                     ext_nb ;
01870     const char          *   recipe_name = "hawki_sci_jitter" ;
01871     int                     i;
01872     int                     ext_chip_1;
01873     cpl_errorstate          error_prevstate = cpl_errorstate_get();
01874 
01875     /* Initialise */
01876     pscale = hawki_sci_jitter_output.pixscale;
01877     dit = hawki_sci_jitter_output.dit;
01878 
01879     /* Get reference frame */
01880     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01881 
01882     /* Get the used frames */ 
01883     used_frames = cpl_frameset_duplicate(science_frames);
01884     for(i = 0; i< cpl_frameset_get_size(calib_frames); ++i)
01885         cpl_frameset_insert(used_frames, 
01886                 cpl_frame_duplicate(cpl_frameset_get_frame(calib_frames, i)));
01887 
01888     /* Create the telescope data statistics */
01889     telstats = cpl_propertylist_new();
01890     hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats);
01891 
01892     /* Create the QC lists */
01893     qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
01894     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
01895 
01896         /* Get the extension number */
01897         ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
01898 
01899         /* Handle WCS keys */
01900         wcslist = cpl_propertylist_load_regexp(
01901                 cpl_frame_get_filename(ref_frame), ext_nb, HAWKI_HEADER_WCS, 0);
01902         qclists[i] = cpl_propertylist_new() ;
01903 
01904         /* Compute bg_instmag */
01905         bg_mean = cpl_table_get_column_mean(bkg_stats[i], HAWKI_COL_STAT_MEAN);
01906         if (cpl_table_get_nrow(bkg_stats[i]) < 2) bg_stdev = 0 ;
01907         else bg_stdev = cpl_table_get_column_stdev
01908             (bkg_stats[i], HAWKI_COL_STAT_MEAN);
01909         if(bg_mean >= 0)
01910             bg_instmag = -2.5 * log10(bg_mean/(pscale*pscale*dit));
01911         else
01912             bg_instmag = 0;
01913 
01914         /* Fill the QC */
01915         cpl_propertylist_append_double
01916             (qclists[i], "ESO QC BACKGD MEAN", bg_mean);
01917         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD MEAN",
01918                                      "Mean of all the image mean backgrounds");
01919         cpl_propertylist_append_double
01920             (qclists[i], "ESO QC BACKGD STDEV", bg_stdev);
01921         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD STDEV",
01922                    "The standard deviation of all the image mean backgrounds");
01923         cpl_propertylist_append_double
01924             (qclists[i], "ESO QC BACKGD INSTMAG", bg_instmag) ;
01925         cpl_propertylist_set_comment(qclists[i], "ESO QC BACKGD INSTMAG",
01926           "Mean of all the image mean backgrounds in instrumental magnitudes");
01927         cpl_propertylist_append_int
01928             (qclists[i], "ESO QC NBOBJS", hawki_sci_jitter_output.nbobjs[i]);
01929         cpl_propertylist_set_comment(qclists[i], "ESO QC NBOBJS",
01930                            "Number of detected objects in the combined image");
01931         cpl_propertylist_append_double
01932             (qclists[i], "ESO QC IQ", hawki_sci_jitter_output.iq[i]);
01933         cpl_propertylist_set_comment(qclists[i], "ESO QC IQ",
01934                            "Estimated image quality [arcsec]");
01935         cpl_propertylist_append_double
01936             (qclists[i], "ESO QC IQ DIFF AMBI",
01937              hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double
01938                  (telstats, "ESO QC TEL AMBI FWHM MEAN"));
01939         cpl_propertylist_append_double
01940             (qclists[i], "ESO QC IQ DIFF TEL",
01941              hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double
01942                  (telstats, "ESO QC TEL IA FWHM MEAN"));
01943         cpl_propertylist_append_double
01944             (qclists[i], "ESO QC FWHM PIX",
01945              hawki_sci_jitter_output.fwhm_pix[i]);
01946         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM PIX",
01947                                      "The median FWHM in the image [pixels]");
01948         cpl_propertylist_append_double
01949             (qclists[i], "ESO QC FWHM ARCSEC",
01950              hawki_sci_jitter_output.fwhm_arcsec[i]);
01951         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM ARCSEC",
01952                                      "The median FWHM in the image [arcsec]");
01953         cpl_propertylist_append_double
01954             (qclists[i], "ESO QC FWHM MODE",
01955              hawki_sci_jitter_output.fwhm_mode[i]);
01956         cpl_propertylist_set_comment(qclists[i], "ESO QC FWHM MODE",
01957                                      "The mode FWHM in the image [pixels]");
01958         cpl_propertylist_append_double
01959             (qclists[i], "ESO QC COMBINED POSX",
01960              hawki_sci_jitter_output.combined_pos_x[i]);
01961         cpl_propertylist_set_comment(qclists[i], "ESO QC COMBINED POSX",
01962                                      "Position in X of the first image");
01963         cpl_propertylist_append_double
01964             (qclists[i], "ESO QC COMBINED POSY",
01965              hawki_sci_jitter_output.combined_pos_y[i]);
01966         cpl_propertylist_set_comment(qclists[i], "ESO QC COMBINED POSY",
01967                                      "Position in Y of the first image");
01968         cpl_propertylist_append_double
01969             (qclists[i], "ESO QC COMBINED CUMOFFSETX",
01970              hawki_sci_jitter_output.combined_cumoffset_x[i]);
01971         cpl_propertylist_append_double
01972             (qclists[i], "ESO QC COMBINED CUMOFFSETY",
01973              hawki_sci_jitter_output.combined_cumoffset_y[i]);
01974         cpl_propertylist_append_int
01975             (qclists[i], "ESO QC DATANCOM",hawki_sci_jitter_output.ncomb[i]);
01976         cpl_propertylist_set_comment(qclists[i], "ESO QC DATANCOM",
01977                                      "Number of files used for the reduction");
01978         cpl_propertylist_append_double
01979             (qclists[i], "ESO QC AIRMASS MEAN",
01980              hawki_sci_jitter_output.mean_airmass);
01981         cpl_propertylist_set_comment(qclists[i], "ESO QC AIRMASS MEAN",
01982                                      "Average airmass");
01983 
01984         /* Update WCS and write them */
01985         crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 
01986         crpix1 += hawki_sci_jitter_output.combined_pos_x[i];
01987         cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ;
01988         crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 
01989         crpix2 += hawki_sci_jitter_output.combined_pos_y[i] ;
01990         cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ;
01991         cpl_propertylist_copy_property_regexp
01992             (qclists[i], wcslist, HAWKI_HEADER_WCS, 0) ;
01993         cpl_propertylist_delete(wcslist);
01994 
01995         /* Propagate some keywords from input raw frame extensions */
01996         inputlist = cpl_propertylist_load_regexp(
01997                 cpl_frame_get_filename(ref_frame), ext_nb,
01998                 HAWKI_HEADER_EXT_FORWARD, 0) ;
01999         cpl_propertylist_append(qclists[i], inputlist);
02000         cpl_propertylist_delete(inputlist) ;
02001     }
02002     
02003     /* Statistics of the raw images in the QC */
02004     hawki_image_stats_stats(raw_jitter_stats, qclists);
02005     
02006     /* Statistics of the detected objects in the QC */
02007     hawki_obj_prop_stats(obj_charac, qclists);
02008 
02009     /* Write the combined image */
02010     hawki_images_save(set,
02011                       parlist,
02012                       used_frames,
02013                       (const cpl_image **)combined,
02014                       recipe_name,
02015                       HAWKI_CALPRO_COMBINED,
02016                       HAWKI_PROTYPE_COMBINED, 
02017                       NULL,
02018                       (const cpl_propertylist**)qclists,
02019                       "hawki_sci_jitter.fits");
02020 
02021     /* Erase the WCS */
02022     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
02023         cpl_propertylist_erase_regexp(qclists[i], HAWKI_HEADER_WCS, 0) ;
02024     }
02025 
02026     /* Create a propertylist for PRO.x */
02027     plist = cpl_propertylist_new();
02028     cpl_propertylist_append_string(plist, CPL_DFS_PRO_TYPE,
02029                                    HAWKI_PROTYPE_STITCHED) ;
02030     cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG,
02031                                    HAWKI_CALPRO_STITCHED) ;
02032     /* Handle WCS keys */
02033     ext_chip_1 = 1;
02034     wcslist = cpl_propertylist_load_regexp(
02035             cpl_frame_get_filename(ref_frame), ext_chip_1, HAWKI_HEADER_WCS, 0);
02036     /* Update WCS and write them */
02037     crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 
02038     crpix1 += hawki_sci_jitter_output.combined_pos_x[0];
02039     cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ;
02040     crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 
02041     crpix2 += hawki_sci_jitter_output.combined_pos_y[0] ;
02042     cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ;
02043     cpl_propertylist_append(plist, wcslist);
02044     cpl_propertylist_delete(wcslist) ;
02045     /* Write the stitched image */
02046     cpl_dfs_save_image(set,
02047                        NULL,
02048                        parlist,
02049                        used_frames,
02050                        NULL,
02051                        stitched,
02052                        CPL_BPP_IEEE_FLOAT,
02053                        recipe_name,
02054                        plist,
02055                        NULL,
02056                        PACKAGE "/" PACKAGE_VERSION,
02057                        "hawki_sci_jitter_stitched.fits");
02058     cpl_propertylist_delete(plist);
02059 
02060     /* Write the FITS table with the objects statistics */
02061     if (obj_charac) 
02062     {
02063         hawki_tables_save(set,
02064                           parlist,
02065                           used_frames,
02066                           (const cpl_table **)obj_charac,
02067                           recipe_name,
02068                           HAWKI_CALPRO_OBJ_PARAM,
02069                           HAWKI_PROTYPE_OBJ_PARAM,
02070                           NULL,
02071                           (const cpl_propertylist**)qclists,
02072                           "hawki_sci_jitter_stars.fits");
02073     }
02074 
02075     /* Write the table with the background statistics */
02076     hawki_tables_save(set,
02077                       parlist,
02078                       used_frames,   
02079                       (const cpl_table **)bkg_stats,
02080                       recipe_name,
02081                       HAWKI_CALPRO_JITTER_BKG_STATS,
02082                       HAWKI_PROTYPE_JITTER_BKG_STATS,
02083                       NULL,
02084                       (const cpl_propertylist **)qclists,
02085                       "hawki_sci_jitter_bkg_stats.fits");
02086 
02087     /* Free and return */
02088     cpl_frameset_delete(used_frames);
02089     for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
02090         cpl_propertylist_delete(qclists[i]) ;
02091     }
02092     cpl_propertylist_delete(telstats) ;
02093     cpl_free(qclists) ;
02094     if(!cpl_errorstate_is_equal(error_prevstate))
02095     {
02096         cpl_errorstate_set(CPL_ERROR_NONE);
02097         return -1;
02098     }
02099     return  0;
02100 }
02101 
02102 int hawki_sci_jitter_whole_image_algo
02103 (cpl_frameset       *  obj,
02104  cpl_table          ** raw_jitter_stats,
02105  cpl_table          *  raw_obj_tel_info,
02106  cpl_parameterlist  *  parlist,
02107  cpl_frameset       *  recipe_set)
02108 {
02109     int                 nframes;
02110     int                 iframe;
02111 
02112     
02113     nframes = cpl_frameset_get_size(obj);
02114     for( iframe = 0 ; iframe < nframes ; ++iframe)
02115     {
02116         /* Local storage variables */
02117         cpl_frame        * this_target_frame;
02118         cpl_propertylist * this_properties;
02119 
02120         /* Computing statistics for this frame */
02121         cpl_msg_info(cpl_func, "Getting statistics for image %d", iframe + 1);
02122         this_target_frame = cpl_frameset_get_frame(obj, iframe);
02123         hawki_image_stats_fill_from_frame
02124             (raw_jitter_stats, this_target_frame, iframe);
02125 
02126         /* Compute the telescope pcs statistics */
02127         this_properties = cpl_propertylist_load
02128             (cpl_frame_get_filename(this_target_frame), 0);
02129         if(this_properties == NULL)
02130         {
02131             cpl_msg_error(cpl_func,"Could not read the header of object frame");
02132             return  -1;
02133         }
02134         if(hawki_extract_prop_tel_qc(this_properties, raw_obj_tel_info, iframe))
02135         {
02136             cpl_msg_warning(cpl_func,"Some telescope properties could not be "
02137                             "read for image %d", iframe+1);
02138             cpl_errorstate_set(CPL_ERROR_NONE);
02139         }
02140         cpl_propertylist_delete(this_properties);
02141     }
02142 
02143     /* Saving the already computed products */
02144     cpl_msg_info(cpl_func, "Saving image statistics");
02145     if(hawki_sci_jitter_save_stats(raw_jitter_stats, raw_obj_tel_info, 
02146                                    obj,
02147                                    parlist, recipe_set) != 0)
02148         cpl_msg_warning(cpl_func,"Some data could not be saved. "
02149                         "Check permisions or disk space");
02150         
02151     
02152     /* Free and return */
02153     return 0;
02154 }
02155 
02156 int hawki_sci_jitter_save_stats
02157 (cpl_table          ** raw_jitter_stats,
02158  cpl_table          *  raw_obj_tel_info,
02159  cpl_frameset       *  jitter_frames,
02160  cpl_parameterlist  *  parlist,
02161  cpl_frameset       *  recipe_set)
02162 {
02163     int                 idet;
02164     const cpl_frame  *  ref_frame;
02165     cpl_propertylist ** qcstats;
02166     cpl_propertylist *  telstats;
02167     const char       *  recipe_name = "hawki_sci_jitter" ;
02168     cpl_errorstate      error_prevstate = cpl_errorstate_get();
02169     
02170     /* Statistics of the raw images in the QC */
02171     qcstats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*));
02172     /* Create the QC lists */
02173     ref_frame = irplib_frameset_get_first_from_group
02174         (recipe_set, CPL_FRAME_GROUP_RAW);
02175     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
02176     {
02177         int                ext_nb;
02178         cpl_propertylist * reflist;
02179         
02180         qcstats[idet] = cpl_propertylist_new();
02181         /* Propagate some keywords from input raw frame extensions */
02182         ext_nb = 
02183             hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), idet+1);
02184         reflist = cpl_propertylist_load_regexp
02185             (cpl_frame_get_filename(ref_frame), ext_nb,
02186              HAWKI_HEADER_EXT_FORWARD, 0) ;
02187         cpl_propertylist_append(qcstats[idet], reflist);
02188         cpl_propertylist_delete(reflist);
02189     }
02190     hawki_image_stats_stats(raw_jitter_stats, qcstats);
02191     /* Write the table with the raw jitter objects statistics */
02192     hawki_tables_save(recipe_set,
02193                       parlist,
02194                       jitter_frames,
02195                       (const cpl_table **)raw_jitter_stats,
02196                       recipe_name,
02197                       HAWKI_CALPRO_JITTER_STATS,
02198                       HAWKI_PROTYPE_JITTER_STATS,
02199                       NULL,
02200                       (const cpl_propertylist**)qcstats,
02201                       "hawki_sci_jitter_stats.fits");
02202     /* Free qcstats */
02203     for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
02204         cpl_propertylist_delete(qcstats[idet]);
02205     
02206     /* Write the FITS table with the raw telescope data */
02207     telstats = cpl_propertylist_new();
02208     cpl_propertylist_append_string(telstats, CPL_DFS_PRO_TYPE,
02209                                    HAWKI_PROTYPE_SCIENCE_PCS);
02210     cpl_propertylist_append_string(telstats, CPL_DFS_PRO_CATG,
02211                                    HAWKI_CALPRO_SCIENCE_PCS);
02212     hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats);
02213     if(cpl_dfs_save_table(recipe_set,
02214                           NULL,
02215                           parlist,
02216                           jitter_frames,
02217                           NULL,
02218                           raw_obj_tel_info,
02219                           NULL,
02220                           recipe_name,
02221                           telstats,
02222                           NULL,
02223                           PACKAGE "/" PACKAGE_VERSION,
02224                           "hawki_sci_jitter_pcs.fits") != CPL_ERROR_NONE)
02225         cpl_msg_error(cpl_func,"Cannot save PCS table");
02226     
02227     /* Free and return */
02228     cpl_propertylist_delete(telstats);
02229     cpl_free(qcstats);
02230     if(!cpl_errorstate_is_equal(error_prevstate))
02231     {
02232         cpl_errorstate_set(CPL_ERROR_NONE);
02233         return -1;
02234     }
02235         
02236     return 0;
02237 }