hawki_sci_jitter.c

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

Generated on 10 Jun 2010 for HAWKI Pipeline Reference Manual by  doxygen 1.6.1