hawki_sci_jitter.c

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

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