sofi_img_jitter.c

00001 /* $Id: sofi_img_jitter.c,v 1.29 2012/01/12 12:56:08 llundin Exp $
00002  *
00003  * This file is part of the SOFI 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: llundin $
00023  * $Date: 2012/01/12 12:56:08 $
00024  * $Revision: 1.29 $
00025  * $Name: sofi-1_5_5 $
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 <string.h>
00038 #include <cpl.h>
00039 
00040 #include "irplib_utils.h"
00041 #include "irplib_calib.h"
00042 
00043 #include "sofi_utils.h"
00044 #include "sofi_pfits.h"
00045 #include "sofi_dfs.h"
00046 
00047 /*-----------------------------------------------------------------------------
00048                                 Define
00049  -----------------------------------------------------------------------------*/
00050 
00051 #define NEGLIG_OFF_DIFF     0.1
00052 #define SQR(x) ((x)*(x))
00053 
00054 /*-----------------------------------------------------------------------------
00055                             Functions prototypes
00056  -----------------------------------------------------------------------------*/
00057 
00058 static int sofi_img_jitter_create(cpl_plugin *);
00059 static int sofi_img_jitter_exec(cpl_plugin *);
00060 static int sofi_img_jitter_destroy(cpl_plugin *);
00061 static int sofi_img_jitter(cpl_parameterlist *, cpl_frameset *);
00062 
00063 static cpl_image ** sofi_img_jitter_reduce(cpl_frameset *, cpl_frameset *, 
00064         const char *, const char *, const char *, cpl_vector **);
00065 static cpl_imagelist ** sofi_img_jitter_load(cpl_frameset *, cpl_frameset *);
00066 static cpl_vector * sofi_img_jitter_sky(cpl_imagelist **, cpl_imagelist *);
00067 static cpl_vector * sofi_img_jitter_sky_running(cpl_imagelist **);
00068 static cpl_image ** sofi_img_jitter_saa(cpl_imagelist *, 
00069         cpl_frameset *);
00070 static int sofi_img_jitter_sub_row_median(cpl_image *);
00071 static cpl_table * sofi_img_jitter_qc(cpl_image *);
00072 static double sofi_img_jitter_get_mode(cpl_vector *);
00073 static int sofi_img_jitter_save(cpl_image *, cpl_table *, cpl_vector *, 
00074         cpl_parameterlist *, cpl_frameset *);
00075 
00076 /*-----------------------------------------------------------------------------
00077                             Static variables
00078  -----------------------------------------------------------------------------*/
00079 
00080 static struct {
00081     /* Inputs */
00082     const char      *   offsets;
00083     const char      *   objects;
00084     int                 crosstalk;
00085     int                 sky_minnb;
00086     int                 sky_halfw;
00087     int                 sky_rejmin;
00088     int                 sky_rejmax;
00089     int                 sx;
00090     int                 sy;
00091     int                 mx;
00092     int                 my;
00093     cpl_geom_combine    comb_meth;
00094     int                 rej_low;
00095     int                 rej_high;
00096     int                 row_med;
00097     /* Outputs */
00098     double          pixscale;
00099     double          dit;
00100     int             nb_obj_frames;
00101     int             nb_sky_frames;
00102     int             nb_rej_frames;
00103     double          iq;
00104     int             nbobjs;
00105     double          fwhm_pix;
00106     double          fwhm_arcsec;
00107     double          fwhm_mode;
00108 } sofi_img_jitter_config;
00109 
00110 static char sofi_img_jitter_description[] =
00111 "sofi_img_jitter -- SOFI imaging jitter recipe.\n"
00112 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00113 "raw-file.fits "SOFI_IMG_JITTER_OBJ_RAW" or\n"
00114 "raw-file.fits "SOFI_IMG_JITTER_SKY_RAW" or\n"
00115 "flat-file.fits "SOFI_CALIB_FLAT" or\n"
00116 "dark-file.fits "SOFI_CALIB_DARK"\n";
00117 
00118 /*-----------------------------------------------------------------------------
00119                                 Functions code
00120  -----------------------------------------------------------------------------*/
00121 
00122 /*----------------------------------------------------------------------------*/
00130 /*----------------------------------------------------------------------------*/
00131 int cpl_plugin_get_info(cpl_pluginlist * list)
00132 {
00133     cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe));
00134     cpl_plugin  *   plugin = &recipe->interface;
00135 
00136     cpl_plugin_init(plugin,
00137                     CPL_PLUGIN_API,
00138                     SOFI_BINARY_VERSION,
00139                     CPL_PLUGIN_TYPE_RECIPE,
00140                     "sofi_img_jitter",
00141                     "Jitter recipe",
00142                     sofi_img_jitter_description,
00143                     "Yves Jung",
00144                     "yjung@eso.org",
00145                     sofi_get_license(),
00146                     sofi_img_jitter_create,
00147                     sofi_img_jitter_exec,
00148                     sofi_img_jitter_destroy);
00149 
00150     cpl_pluginlist_append(list, plugin);
00151     
00152     return 0;
00153 }
00154 
00155 /*----------------------------------------------------------------------------*/
00164 /*----------------------------------------------------------------------------*/
00165 static int sofi_img_jitter_create(cpl_plugin * plugin)
00166 {
00167     cpl_recipe      * recipe;
00168     cpl_parameter   * p;
00169 
00170     /* Get the recipe out of the plugin */
00171     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00172         recipe = (cpl_recipe *)plugin;
00173     else return -1;
00174 
00175     /* Create the parameters list in the cpl_recipe object */
00176     recipe->parameters = cpl_parameterlist_new();
00177 
00178     /* Fill the parameters list */
00179     /* --off */
00180     p = cpl_parameter_new_value("sofi.sofi_img_jitter.offsets", CPL_TYPE_STRING,
00181                                 "Offsets file. If the i'th frame is believed "
00182                                 "to have the offset (CumoffsetX_i, "
00183                                 "CumoffsetY_i), then the i'th line in "
00184                                 "the offset file should be:\n "
00185                                 "X_i Y_i\n "
00186                                 "where\n "
00187                                 "X_i = CumoffsetX_0 - CumoffsetX_i\n "
00188                                 "and\n "
00189                                 "Y_i = CumoffsetY_0 - CumoffsetY_i.\n "
00190                                 "(This implies that the first line in the "
00191                                 "offset file should consist of two zeroes).",
00192                                 "sofi.sofi_img_jitter", NULL);
00193     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "off");
00194     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00195     cpl_parameterlist_append(recipe->parameters, p);
00196 
00197     /* --objs */
00198     p = cpl_parameter_new_value("sofi.sofi_img_jitter.objects", 
00199             CPL_TYPE_STRING, "objects file", "sofi.sofi_img_jitter", NULL);
00200     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "objs");
00201     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00202     cpl_parameterlist_append(recipe->parameters, p);
00203 
00204     /* --crosstalk */
00205     p = cpl_parameter_new_value("sofi.sofi_img_jitter.crosstalk", CPL_TYPE_BOOL,
00206             "flag to remove the crosstalk effect", "sofi.sofi_img_jitter",
00207             TRUE);
00208     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "crosstalk");
00209     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00210     cpl_parameterlist_append(recipe->parameters, p);
00211     
00212     /* --sky_par */
00213     p = cpl_parameter_new_value("sofi.sofi_img_jitter.sky_par",
00214                                 CPL_TYPE_STRING,
00215                                 "Rejection parameters for sky filtering",
00216                                 "sofi.sofi_img_jitter",
00217                                 "10,7,3,3");
00218     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_par");
00219     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00220     cpl_parameterlist_append(recipe->parameters, p);
00221 
00222     /* --xcorr */
00223     p = cpl_parameter_new_value("sofi.sofi_img_jitter.xcorr",
00224                                 CPL_TYPE_STRING,
00225                                 "Cross correlation search and measure sizes",
00226                                 "sofi.sofi_img_jitter",
00227                                 "40,40,65,65");
00228     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcorr");
00229     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00230     cpl_parameterlist_append(recipe->parameters, p);
00231 
00232     /* --comb_meth */
00233     p = cpl_parameter_new_value("sofi.sofi_img_jitter.comb_meth", 
00234             CPL_TYPE_STRING, "union / inter / first", "sofi.sofi_img_jitter",
00235             "union");
00236     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "comb_meth");
00237     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00238     cpl_parameterlist_append(recipe->parameters, p);
00239  
00240     /* --rej */
00241     p = cpl_parameter_new_value("sofi.sofi_img_jitter.rej",
00242                                 CPL_TYPE_STRING,
00243                                 "Low and high number of rejected values",
00244                                 "sofi.sofi_img_jitter",
00245                                 "2,2");
00246     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rej");
00247     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00248     cpl_parameterlist_append(recipe->parameters, p);
00249 
00250     /* --row_med */
00251     p = cpl_parameter_new_value("sofi.sofi_img_jitter.row_med", CPL_TYPE_BOOL,
00252             "flag to subtract the median of each row", "sofi.sofi_img_jitter",
00253             TRUE);
00254     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "row_med");
00255     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00256     cpl_parameterlist_append(recipe->parameters, p);
00257 
00258     /* Return */
00259     return 0;
00260 }
00261 
00262 /*----------------------------------------------------------------------------*/
00268 /*----------------------------------------------------------------------------*/
00269 static int sofi_img_jitter_exec(cpl_plugin * plugin)
00270 {
00271     cpl_recipe  *   recipe;
00272 
00273     /* Get the recipe out of the plugin */
00274     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00275         recipe = (cpl_recipe *)plugin;
00276     else return -1;
00277 
00278     return sofi_img_jitter(recipe->parameters, recipe->frames);
00279 }
00280 
00281 /*----------------------------------------------------------------------------*/
00287 /*----------------------------------------------------------------------------*/
00288 static int sofi_img_jitter_destroy(cpl_plugin * plugin)
00289 {
00290     cpl_recipe  *   recipe;
00291 
00292     /* Get the recipe out of the plugin */
00293     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00294         recipe = (cpl_recipe *)plugin;
00295     else return -1;
00296 
00297     cpl_parameterlist_delete(recipe->parameters);
00298     return 0;
00299 }
00300 
00301 /*----------------------------------------------------------------------------*/
00308 /*----------------------------------------------------------------------------*/
00309 static int sofi_img_jitter(
00310         cpl_parameterlist   *   parlist, 
00311         cpl_frameset        *   framelist)
00312 {
00313     const char      *   sval;
00314     cpl_parameter   *   par;
00315     const char      *   flat;
00316     const char      *   dark;
00317     cpl_frameset    *   objframes;
00318     cpl_frameset    *   skyframes;
00319     cpl_image       **  combined;
00320     cpl_table       *   objs_stats;
00321     cpl_vector      *   sky_bg;
00322 
00323     /* Initialise */
00324     par = NULL;
00325     sofi_img_jitter_config.pixscale = -1.0;
00326     sofi_img_jitter_config.dit = -1.0;
00327     sofi_img_jitter_config.iq = -1.0;
00328     sofi_img_jitter_config.nbobjs = -1;
00329     sofi_img_jitter_config.fwhm_pix = -1.0;
00330     sofi_img_jitter_config.fwhm_arcsec = -1.0;
00331     sofi_img_jitter_config.fwhm_mode = -1.0;
00332     sofi_img_jitter_config.offsets = NULL;
00333     sofi_img_jitter_config.objects = NULL;
00334     sofi_img_jitter_config.nb_obj_frames = 0;
00335     sofi_img_jitter_config.nb_rej_frames = 0;
00336     sofi_img_jitter_config.nb_sky_frames = 0;
00337 
00338     /* Retrieve input parameters */
00339     /* Offsets */
00340     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.offsets");
00341     sofi_img_jitter_config.offsets = cpl_parameter_get_string(par);
00342     /* Objects */
00343     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.objects");
00344     sofi_img_jitter_config.objects = cpl_parameter_get_string(par);
00345     /* Cross-talk */
00346     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.crosstalk");
00347     sofi_img_jitter_config.crosstalk = cpl_parameter_get_bool(par);
00348     /* Rejection parameters for sky filtering */
00349     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.sky_par");
00350     sval = cpl_parameter_get_string(par);
00351     if (sscanf(sval, "%d,%d,%d,%d",
00352                     &sofi_img_jitter_config.sky_minnb,
00353                     &sofi_img_jitter_config.sky_halfw,
00354                     &sofi_img_jitter_config.sky_rejmin,
00355                     &sofi_img_jitter_config.sky_rejmax)!=4) {
00356         return -1;
00357     }
00358     /* Cross correlation windows parameters */
00359     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.xcorr");
00360     sval = cpl_parameter_get_string(par);
00361     if (sscanf(sval, "%d,%d,%d,%d",
00362                     &sofi_img_jitter_config.sx,
00363                     &sofi_img_jitter_config.sy,
00364                     &sofi_img_jitter_config.mx,
00365                     &sofi_img_jitter_config.my)!=4) {
00366         return -1;
00367     }
00368     /* --comb_meth */
00369     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.comb_meth");
00370     sval = cpl_parameter_get_string(par);
00371     if (!strcmp(sval, "union")) 
00372         sofi_img_jitter_config.comb_meth = CPL_GEOM_UNION;
00373     else if (!strcmp(sval, "inter"))
00374         sofi_img_jitter_config.comb_meth = CPL_GEOM_INTERSECT;
00375     else if (!strcmp(sval, "first"))
00376         sofi_img_jitter_config.comb_meth = CPL_GEOM_FIRST;
00377     else {
00378         cpl_msg_error(cpl_func, "Invalid combine method specified");
00379         return -1;
00380     }
00381     
00382      /* Number of rejected values in stacking */
00383     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.rej");
00384     sval = cpl_parameter_get_string(par);
00385     if (sscanf(sval, "%d,%d",
00386                     &sofi_img_jitter_config.rej_low,
00387                     &sofi_img_jitter_config.rej_high)!=2) {
00388         return -1;
00389     }
00390     /* Row median */
00391     par = cpl_parameterlist_find(parlist, "sofi.sofi_img_jitter.row_med");
00392     sofi_img_jitter_config.row_med = cpl_parameter_get_bool(par);
00393 
00394     /* Identify the RAW and CALIB frames in the input frameset */
00395     if (sofi_dfs_set_groups(framelist)) {
00396         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
00397         return -1;
00398     }
00399 
00400     /* Retrieve calibration data */
00401     flat   = sofi_extract_filename(framelist, SOFI_CALIB_FLAT);
00402     dark   = sofi_extract_filename(framelist, SOFI_CALIB_DARK);
00403 
00404     /* Retrieve raw frames */
00405     if ((objframes = sofi_extract_frameset(framelist,
00406                     SOFI_IMG_JITTER_OBJ_RAW)) == NULL) {
00407         cpl_msg_error(cpl_func, "Cannot find objs frames in the input list");
00408         return -1;
00409     }
00410     skyframes = sofi_extract_frameset(framelist, SOFI_IMG_JITTER_SKY_RAW);
00411 
00412     /* Apply the reduction */
00413     cpl_msg_info(cpl_func, "Apply the data recombination");
00414     cpl_msg_indent_more();
00415     if ((combined = sofi_img_jitter_reduce(objframes, skyframes, flat,
00416                     dark, NULL, &sky_bg)) == NULL) {
00417         cpl_msg_error(cpl_func, "Cannot recombine the data");
00418         cpl_frameset_delete(objframes);
00419         if (skyframes) cpl_frameset_delete(skyframes);
00420         cpl_msg_indent_less();
00421         return -1;
00422     }
00423     cpl_frameset_delete(objframes);
00424     if (skyframes) cpl_frameset_delete(skyframes);
00425     cpl_msg_indent_less();
00426    
00427     /* Compute QC parameters from the combined image */
00428     cpl_msg_info(cpl_func, "Compute QC parameters from the combined image");
00429     cpl_msg_indent_more();
00430     if ((objs_stats = sofi_img_jitter_qc(combined[0])) == NULL) {
00431         cpl_msg_warning(cpl_func, "Cannot compute all parameters");
00432     }
00433     cpl_msg_indent_less();
00434     
00435     /* Save the products */
00436     cpl_msg_info(cpl_func, "Save the products");
00437     cpl_msg_indent_more();
00438     if (sofi_img_jitter_save(combined[0], objs_stats, sky_bg, parlist,
00439                 framelist) == -1){
00440         cpl_msg_error(cpl_func, "Cannot save the products");
00441         cpl_image_delete(combined[0]);
00442         cpl_image_delete(combined[1]);
00443         cpl_free(combined);
00444         if (objs_stats) cpl_table_delete(objs_stats);
00445         if (sky_bg) cpl_vector_delete(sky_bg);
00446         cpl_msg_indent_less();
00447         return -1;
00448     }
00449     cpl_msg_indent_less();
00450     
00451     /* Return */
00452     cpl_image_delete(combined[0]);
00453     cpl_image_delete(combined[1]);
00454     cpl_free(combined);
00455     if (objs_stats) cpl_table_delete(objs_stats);
00456         if (sky_bg) cpl_vector_delete(sky_bg);
00457     return 0;
00458 }
00459 
00460 /*----------------------------------------------------------------------------*/
00471 /*----------------------------------------------------------------------------*/
00472 static cpl_image ** sofi_img_jitter_reduce(
00473         cpl_frameset    *   obj,
00474         cpl_frameset    *   sky,
00475         const char      *   flat,
00476         const char      *   dark,
00477         const char      *   bpm,
00478         cpl_vector      **  skybg)
00479 {
00480     cpl_imagelist   **  in;
00481     cpl_image       **  combined;
00482 
00483     /* Initialise */
00484     *skybg = NULL;
00485     
00486     /* Load the input data */
00487     cpl_msg_info(cpl_func, "Load the input data");
00488     cpl_msg_indent_more();
00489     if ((in = sofi_img_jitter_load(obj, sky)) == NULL) {
00490         cpl_msg_error(cpl_func, "Cannot load input data");
00491         cpl_msg_indent_less();
00492         return NULL;
00493     }
00494     cpl_msg_indent_less();
00495 
00496     /* Apply the cross-talk correction */
00497     if (sofi_img_jitter_config.crosstalk) {
00498         cpl_msg_info(cpl_func, "Apply the cross-talk correction");
00499         cpl_msg_indent_more();
00500         if (sofi_correct_crosstalk_list(in[0]) == -1) {
00501             cpl_msg_error(cpl_func, "Cannot correct for Cross-talk");
00502             cpl_imagelist_delete(in[0]);
00503             if (in[1]) cpl_imagelist_delete(in[1]);
00504             cpl_free(in);
00505             cpl_msg_indent_less();
00506             return NULL;
00507         }
00508         if (in[1]) {
00509             if (sofi_correct_crosstalk_list(in[1]) == -1) {
00510                 cpl_msg_error(cpl_func, "Cannot correct for Cross-talk");
00511                 cpl_imagelist_delete(in[0]);
00512                 if (in[1]) cpl_imagelist_delete(in[1]);
00513                 cpl_free(in);
00514                 cpl_msg_indent_less();
00515                 return NULL;
00516             }
00517         }
00518         cpl_msg_indent_less();
00519     }
00520     
00521     /* Apply the calibrations */
00522     if (flat || dark || bpm) {
00523         cpl_msg_info(cpl_func, "Apply the calibrations");
00524         cpl_msg_indent_more();
00525         if (irplib_flat_dark_bpm_calib(in[0], flat, dark, bpm) == -1) {
00526             /* Calibrate the objects */
00527             cpl_msg_error(cpl_func, "Cannot calibrate the objects");
00528             cpl_imagelist_delete(in[0]);
00529             if (in[1]) cpl_imagelist_delete(in[1]);
00530             cpl_free(in);
00531             cpl_msg_indent_less();
00532             return NULL;
00533         }
00534         if (in[1]) {
00535             if (irplib_flat_dark_bpm_calib(in[1], flat, dark, bpm) == -1) {
00536                 /* Calibrate the sky */
00537                 cpl_msg_error(cpl_func, "Cannot calibrate the sky");
00538                 cpl_imagelist_delete(in[0]);
00539                 if (in[1]) cpl_imagelist_delete(in[1]);
00540                 cpl_free(in);
00541                 cpl_msg_indent_less();
00542                 return NULL;
00543             }
00544         }
00545         cpl_msg_indent_less();
00546     }
00547 
00548     /* Apply the sky correction */
00549     cpl_msg_info(cpl_func, "Sky estimation and correction");
00550     cpl_msg_indent_more();
00551     if ((*skybg = sofi_img_jitter_sky(&(in[0]), in[1])) == NULL) {
00552         cpl_msg_error(cpl_func, "Cannot estimate the sky");
00553         cpl_imagelist_delete(in[0]);
00554         if (in[1]) cpl_imagelist_delete(in[1]);
00555         cpl_free(in);
00556         cpl_msg_indent_less();
00557         return NULL;
00558     }
00559     cpl_msg_indent_less();
00560     sofi_img_jitter_config.nb_obj_frames = cpl_imagelist_get_size(in[0]);
00561     if (in[1] != NULL) 
00562         sofi_img_jitter_config.nb_sky_frames = cpl_imagelist_get_size(in[1]);
00563     if (in[1]) cpl_imagelist_delete(in[1]);
00564     in[1] = NULL;
00565     
00566     /* Apply the shift and add */
00567     cpl_msg_info(cpl_func, "Shift and add");
00568     cpl_msg_indent_more();
00569     combined = sofi_img_jitter_saa(in[0], obj);
00570     if (combined == NULL) {
00571         cpl_msg_error(cpl_func, "Cannot apply the shift and add");
00572         cpl_imagelist_delete(in[0]);
00573         cpl_free(in);
00574         if (*skybg != NULL) cpl_vector_delete(*skybg);
00575         *skybg = NULL;
00576         cpl_msg_indent_less();
00577         return NULL;
00578     }
00579     cpl_imagelist_delete(in[0]);
00580     cpl_free(in);
00581     cpl_msg_indent_less();
00582      
00583     /* Post processing on the combined image */
00584     if (sofi_img_jitter_config.row_med) {
00585         cpl_msg_info(cpl_func, "Subtract the median from each row");
00586         sofi_img_jitter_sub_row_median(combined[0]);
00587     }
00588     
00589     return combined;
00590 }
00591 
00592 /*----------------------------------------------------------------------------*/
00599 /*----------------------------------------------------------------------------*/
00600 static cpl_imagelist ** sofi_img_jitter_load(
00601         cpl_frameset    *   obj,
00602         cpl_frameset    *   sky)
00603 {
00604     cpl_imagelist       **  isets;
00605     cpl_frame           *   frame;
00606     cpl_propertylist    *   plist;
00607     
00608     /* Test entries */
00609     if (obj == NULL) return NULL;
00610 
00611     /* Check if ok */
00612     if (cpl_error_get_code()) return NULL;
00613    
00614     /* Get the frame type pixscale and DIT value */
00615     frame = cpl_frameset_get_frame(obj, 0);
00616     plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
00617     sofi_img_jitter_config.pixscale = sofi_pfits_get_pixscale(plist);
00618     sofi_img_jitter_config.dit = sofi_pfits_get_dit(plist);
00619     cpl_propertylist_delete(plist);
00620     if (cpl_error_get_code()) {
00621         cpl_msg_error(cpl_func, "Missing keyword in FITS header");
00622         return NULL;
00623     }
00624 
00625     /* Allocate the image sets */
00626     isets = cpl_malloc(2 * sizeof(cpl_imagelist *));
00627     isets[0] = cpl_imagelist_load_frameset(obj, CPL_TYPE_FLOAT, 1, 0);
00628     if (sky != NULL) 
00629         isets[1] = cpl_imagelist_load_frameset(sky, CPL_TYPE_FLOAT, 1, 0);
00630     else isets[1] = NULL;
00631     
00632     /* Check if at least the objects are there */
00633     if (isets[0] == NULL) {
00634         cpl_msg_error(cpl_func, "The objects frames could not be loaded");
00635         if (isets[1] != NULL) cpl_imagelist_delete(isets[1]);
00636         cpl_free(isets);
00637         return NULL;
00638     }
00639     /* Return */
00640     return isets;
00641 }
00642 
00643 /*----------------------------------------------------------------------------*/
00650 /*----------------------------------------------------------------------------*/
00651 static cpl_vector * sofi_img_jitter_sky(
00652         cpl_imagelist   **  objs,
00653         cpl_imagelist   *   skys)
00654 {
00655     cpl_image       *   sky;
00656     cpl_vector      *   bg;
00657     int                 sky_method;
00658     int                 nframes, nskys;
00659     double              median;
00660     cpl_image       *   cur_ima;
00661     int                 i;
00662 
00663     /* Initialise */
00664     nframes = cpl_imagelist_get_size(*objs);
00665     bg = NULL;
00666 
00667     /* Decide the sky method */
00668     if (sofi_img_jitter_config.sky_minnb > nframes) sky_method = 1;
00669     else sky_method = 2;
00670 
00671     /* Compute the sky frame */
00672     if (skys != NULL) {
00673         cpl_msg_info(cpl_func, "Median of sky images");
00674         /* Get the median of the sky images */
00675         nskys = cpl_imagelist_get_size(skys);
00676         bg = cpl_vector_new(nskys);
00677         for (i=0 ; i<nskys ; i++) {
00678             median = cpl_image_get_median(cpl_imagelist_get(skys, i));
00679             cpl_vector_set(bg, i, median);
00680         }
00681         /* Use sky images */
00682         if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) {
00683             cpl_msg_error(cpl_func, "Cannot compute the median of sky images");
00684             cpl_vector_delete(bg);
00685             return NULL;
00686         }
00687         /* Correct the objects images  */
00688         if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
00689             cpl_msg_error(cpl_func, "Cannot correct the obj images from the sky");
00690             cpl_image_delete(sky);
00691             cpl_vector_delete(bg);
00692             return NULL;
00693         }
00694         cpl_image_delete(sky);
00695         /* Normalise the object planes */
00696         for (i=0 ; i<nframes ; i++) {
00697             cur_ima = cpl_imagelist_get(*objs, i);
00698             median = cpl_image_get_median(cur_ima);
00699             cpl_image_subtract_scalar(cur_ima, median);
00700         }
00701     } else if (sky_method == 1) {
00702         cpl_msg_info(cpl_func, "Median of object images");
00703          /* Use objs images */
00704         if ((sky = cpl_imagelist_collapse_median_create(*objs)) == NULL) {
00705             cpl_msg_error(cpl_func, "Cannot compute the median of obj images");
00706             return NULL;
00707         }
00708         /* Correct the objects images  */
00709         if (cpl_imagelist_subtract_image(*objs, sky) != CPL_ERROR_NONE) {
00710             cpl_msg_error(cpl_func, "Cannot correct the obj images from the sky");
00711             cpl_image_delete(sky);
00712             return NULL;
00713         }
00714         /* Create a 1 value vector */
00715         bg = cpl_vector_new(1);
00716         cpl_vector_set(bg, 0, cpl_image_get_median(sky));
00717         cpl_image_delete(sky);
00718         /* Normalise the object planes */
00719         for (i=0 ; i<nframes ; i++) {
00720             cur_ima = cpl_imagelist_get(*objs, i);
00721             median = cpl_image_get_median(cur_ima);
00722             cpl_image_subtract_scalar(cur_ima, median);
00723         }
00724     } else if (sky_method == 2) {
00725         cpl_msg_info(cpl_func, "Running filter on object images");
00726         /* Use objects images */
00727         if ((bg = sofi_img_jitter_sky_running(objs)) == NULL) {
00728             cpl_msg_error(cpl_func, "Cannot apply the running filter for the sky");
00729             return NULL;
00730         }
00731     }
00732     /* Free and return */
00733     return bg;
00734 }
00735 
00736 /*----------------------------------------------------------------------------*/
00755 /*----------------------------------------------------------------------------*/
00756 static cpl_vector * sofi_img_jitter_sky_running(cpl_imagelist ** in) 
00757 {
00758     int                 rejmin, rejmax, halfw;
00759     cpl_imagelist   *   filtres;
00760     int                 ni, nx, ny, pos;
00761     cpl_vector      *   medians;
00762     cpl_image       *   cur_ima;
00763     float           *   pcur_ima;
00764     cpl_image       *   tmp_ima;
00765     float           *   ptmp_ima;
00766     cpl_vector      *   localwin;
00767     int                 fr_p, to_p, n_curp;
00768     cpl_vector      *   bg;
00769     double              bg_val, out;
00770     float               one_med;
00771     int                 i, j, k;
00772 
00773     /* Test entries */
00774     if (in==NULL || *in == NULL) return NULL;
00775 
00776     /* Initialise */
00777     rejmin = sofi_img_jitter_config.sky_rejmin;
00778     rejmax = sofi_img_jitter_config.sky_rejmax;
00779     halfw  = sofi_img_jitter_config.sky_halfw;
00780     ni = cpl_imagelist_get_size(*in);
00781     cur_ima = cpl_imagelist_get(*in, 0);
00782     nx = cpl_image_get_size_x(cur_ima);
00783     ny = cpl_image_get_size_y(cur_ima);
00784     
00785     /* Tests on validity of rejection parameters */
00786     if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) {
00787         cpl_msg_error(cpl_func, "cannot run filter with rej parms %d (%d-%d)",
00788                 halfw, rejmin, rejmax);
00789         return NULL;
00790     }   
00791     /* Pre-compute median value in each plane */
00792     medians = cpl_vector_new(ni);
00793     for (i=0 ; i<ni ; i++) {
00794         cur_ima = cpl_imagelist_get(*in, i);
00795         cpl_vector_set(medians, i, cpl_image_get_median(cur_ima));
00796     }
00797     /* Allocate output cube */
00798     filtres = cpl_imagelist_new();
00799 
00800     /* Allocate output bg */
00801     bg = cpl_vector_new(ni);
00802     
00803     /* Main loop over input planes */
00804     for (k=0 ; k<ni ; k++) {
00805         /* Allocate output plane */
00806         tmp_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00807         ptmp_ima = cpl_image_get_data_float(tmp_ima);
00808         /* Compute border indices */
00809         fr_p = k - halfw;
00810         to_p = k + halfw;
00811         if (fr_p<0) fr_p=0;
00812         if (to_p>(ni-1)) to_p=ni-1;
00813 
00814         /* Number of valid planes to consider after edge effects */
00815         n_curp = to_p - fr_p;
00816 
00817         /* Allocate local window */
00818         localwin = cpl_vector_new(n_curp);
00819         
00820         bg_val = 0.0;
00821         /* Loop over all pixels */
00822         for (pos=0 ; pos<nx*ny ; pos++) {
00823             /* Fill up local window */
00824             j=0;
00825             for (i=fr_p ; i<=to_p ; i++) {
00826                 if (i!=k) {
00827                     cur_ima = cpl_imagelist_get(*in, i);
00828                     pcur_ima = cpl_image_get_data_float(cur_ima);
00829                     cpl_vector_set(localwin, j,
00830                             (double)pcur_ima[pos]-cpl_vector_get(medians, i));
00831                     j++;
00832                 }
00833             }
00834             /* Sort window */
00835             cpl_vector_sort(localwin, 1);
00836             /* Reject min and max, accumulate other pixels */
00837             out = 0.0;
00838             for (i=rejmin ; i<(n_curp-rejmax) ; i++) {
00839                 out += cpl_vector_get(localwin, i);
00840             }
00841             /* Take the mean */
00842             out /= (double)(n_curp - rejmin - rejmax);
00843             /* Assign value */
00844             cur_ima = cpl_imagelist_get(*in, k);
00845             pcur_ima = cpl_image_get_data_float(cur_ima);
00846             ptmp_ima[pos] = pcur_ima[pos] - 
00847                 (float)(out + cpl_vector_get(medians, k));
00848 
00849             bg_val += (out+cpl_vector_get(medians, k));
00850         }
00851         cpl_vector_delete(localwin);
00852         cpl_vector_set(bg, k, bg_val/(nx*ny));
00853         cpl_imagelist_set(filtres, tmp_ima, k);
00854     }
00855     cpl_imagelist_delete(*in);
00856     cpl_vector_delete(medians);
00857 
00858     /* Subtract median from each frame */
00859     for (i=0 ; i<ni ; i++) {
00860         cur_ima = cpl_imagelist_get(filtres, i);
00861         one_med = cpl_image_get_median(cur_ima);
00862         cpl_image_subtract_scalar(cur_ima, one_med);
00863     }
00864     *in = filtres;
00865     return bg;
00866 }
00867 
00868 /*----------------------------------------------------------------------------*/
00875 /*----------------------------------------------------------------------------*/
00876 static cpl_image ** sofi_img_jitter_saa(
00877         cpl_imagelist   *   in,
00878         cpl_frameset    *   objframes)
00879 {
00880     cpl_frame           *   frame;
00881     cpl_propertylist    *   plist;
00882     cpl_bivector        *   offsets_est;
00883     double              *   offsets_est_x;
00884     double              *   offsets_est_y;
00885     cpl_bivector        *   objs;
00886     double              *   objs_x;
00887     double              *   objs_y;
00888     cpl_apertures       *   aperts;
00889     cpl_image           **  combined;
00890     cpl_vector          *   thresh_vect;
00891     cpl_image           *   diff;
00892     int                     nfiles;
00893     int                     i;
00894 
00895     /* Get the number of images */
00896     nfiles = cpl_imagelist_get_size(in);
00897     if (cpl_frameset_get_size(objframes) != nfiles) {
00898         cpl_msg_error(cpl_func, "Invalid input objects sizes");
00899         return NULL;
00900     }
00901     
00902     /* Get the offsets estimation of each input file pair */
00903     cpl_msg_info(cpl_func, "Get the offsets estimation");
00904     offsets_est = NULL;
00905     if (sofi_img_jitter_config.offsets &&
00906             sofi_img_jitter_config.offsets[0] != (char)0) {
00907         /* A file has been provided on the command line */
00908         offsets_est = cpl_bivector_read(sofi_img_jitter_config.offsets);
00909         if ((offsets_est==NULL)||(cpl_bivector_get_size(offsets_est)!=nfiles)) {
00910             cpl_msg_error(cpl_func, "Cannot get offsets from %s", 
00911                     sofi_img_jitter_config.offsets);
00912             return NULL;
00913         }
00914     } else {
00915         /* Get the offsets from the header */
00916         offsets_est = cpl_bivector_new(nfiles);
00917         offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00918         offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00919         for (i=0 ; i<nfiles ; i++) {
00920             if (cpl_error_get_code()) {
00921                 cpl_bivector_delete(offsets_est);
00922                 cpl_ensure(0, cpl_error_get_code(), NULL);
00923             }
00924             /* X and Y offsets */
00925             frame = cpl_frameset_get_frame(objframes, i);
00926             plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0);
00927             offsets_est_x[i] = -1.0 * sofi_pfits_get_cumoffsetx(plist);
00928             offsets_est_y[i] = -1.0 * sofi_pfits_get_cumoffsety(plist);
00929             cpl_propertylist_delete(plist);
00930             if (cpl_error_get_code()) {
00931                 cpl_msg_warning(cpl_func, "Cannot get offsets from header");
00932                 cpl_bivector_delete(offsets_est);
00933                 cpl_ensure(0, cpl_error_get_code(), NULL);
00934             }
00935         }
00936         /* Subtract the first offset to all offsets */
00937         for (i=1 ; i<nfiles ; i++) {
00938             offsets_est_x[i] -= offsets_est_x[0];
00939             offsets_est_y[i] -= offsets_est_y[0];
00940         }
00941         offsets_est_x[0] = offsets_est_y[0] = 0.00;
00942     }
00943 
00944     /* Read the provided objects file if provided */
00945     objs = NULL;
00946     if (sofi_img_jitter_config.objects &&
00947             sofi_img_jitter_config.objects[0] != (char)0) {
00948         cpl_msg_info(cpl_func, "Get the user provided correlation objects");
00949         /* A file has been provided on the command line */
00950         objs = cpl_bivector_read(sofi_img_jitter_config.objects);
00951         if (objs==NULL) {
00952             cpl_msg_error(cpl_func, "Cannot get objects from %s",
00953                     sofi_img_jitter_config.objects);
00954             if (offsets_est) cpl_bivector_delete(offsets_est);
00955             return NULL;
00956         }
00957     }
00958 
00959     /* Get a correlation point from the difference of the first images */
00960     if (objs == NULL) {
00961         cpl_msg_info(cpl_func, "Get a cross-correlation point");
00962         thresh_vect = cpl_vector_new(4);
00963         cpl_vector_set(thresh_vect, 0, 5.0);
00964         cpl_vector_set(thresh_vect, 1, 2.0);
00965         cpl_vector_set(thresh_vect, 2, 1.0);
00966         cpl_vector_set(thresh_vect, 3, 0.5);
00967         diff = cpl_image_subtract_create(cpl_imagelist_get(in, 0),
00968                 cpl_imagelist_get(in, 1));
00969         if ((aperts = cpl_apertures_extract_window(diff, thresh_vect, 
00970                         200, 200, 800, 800, NULL)) == NULL) {
00971             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
00972             if (offsets_est) cpl_bivector_delete(offsets_est);
00973             cpl_vector_delete(thresh_vect);
00974             cpl_image_delete(diff);
00975             return NULL;
00976         }
00977         cpl_image_delete(diff);
00978         cpl_vector_delete(thresh_vect);
00979         cpl_apertures_sort_by_npix(aperts);
00980         objs = cpl_bivector_new(1);
00981         objs_x = cpl_bivector_get_x_data(objs);
00982         objs_y = cpl_bivector_get_y_data(objs);
00983         objs_x[0] = cpl_apertures_get_max_x(aperts, 1);
00984         objs_y[0] = cpl_apertures_get_max_y(aperts, 1);
00985         cpl_apertures_delete(aperts);
00986         if (objs == NULL) {
00987             cpl_msg_error(cpl_func, "Cannot find any cross-correlation point");
00988             if (offsets_est) cpl_bivector_delete(offsets_est);
00989             return NULL;
00990         }
00991         cpl_msg_info(cpl_func, "Correlation point: %g %g\n", objs_x[0], objs_y[0]);
00992     }
00993     
00994     /* Recombine the images */
00995     cpl_msg_info(cpl_func, "Recombine the images set");
00996     cpl_msg_indent_more();
00997     if ((combined = cpl_geom_img_offset_combine(in, offsets_est, 1, objs,
00998                     NULL, NULL,
00999                     sofi_img_jitter_config.sx, 
01000                     sofi_img_jitter_config.sy,
01001                     sofi_img_jitter_config.mx, 
01002                     sofi_img_jitter_config.my,
01003                     sofi_img_jitter_config.rej_low,
01004                     sofi_img_jitter_config.rej_high,
01005                     sofi_img_jitter_config.comb_meth)) == NULL) {
01006         cpl_msg_error(cpl_func, "Cannot recombine the images");
01007         if (offsets_est) cpl_bivector_delete(offsets_est);
01008         cpl_bivector_delete(objs);
01009         cpl_msg_indent_less();
01010         return NULL;
01011     }
01012     /* Update QC params */
01013     i = (int)(cpl_image_get_max(combined[1]));
01014     sofi_img_jitter_config.nb_rej_frames = 
01015         sofi_img_jitter_config.nb_obj_frames - i;
01016     sofi_img_jitter_config.nb_obj_frames = i;
01017     cpl_msg_indent_less();
01018 
01019     /* Free and return */
01020     if (offsets_est) cpl_bivector_delete(offsets_est);
01021     cpl_bivector_delete(objs);
01022     return combined;
01023 }
01024 
01025 /*----------------------------------------------------------------------------*/
01031 /*----------------------------------------------------------------------------*/
01032 static int sofi_img_jitter_sub_row_median(cpl_image * in)
01033 {
01034     float           *   pin;
01035     int                 nx, ny;
01036     double              median;
01037     int                 i, j;
01038 
01039     /* Test entries */
01040     if (in == NULL) return -1;
01041 
01042     /* Initialise */
01043     nx = cpl_image_get_size_x(in);
01044     ny = cpl_image_get_size_y(in);
01045     pin = cpl_image_get_data_float(in);
01046  
01047     for (i=0 ; i<ny ; i++) {
01048         median = cpl_image_get_median_window(in, 1, i+1, nx, i+1);
01049         for (j=0 ; j<nx ; j++) {
01050             pin[j+i*nx] -= (float)median;
01051         }
01052     }
01053     return 0;
01054 }
01055 
01056 /*----------------------------------------------------------------------------*/
01062 /*----------------------------------------------------------------------------*/
01063 static cpl_table * sofi_img_jitter_qc(cpl_image * combined)
01064 {
01065     cpl_apertures   *   aperts;
01066     cpl_bivector    *   fwhms;
01067     double          *   fwhms_x;
01068     double          *   fwhms_y;
01069     cpl_vector      *   fwhms_good;
01070     double          *   fwhms_good_data;
01071     int                 nb_val, nb_good;
01072     double              f_min, f_max, fr, fx, fy;
01073     cpl_vector      *   thresh_vec;
01074     cpl_table       *   out_tab;
01075     int                 nb_objs;
01076     int                 i, j;
01077     
01078     /* Initialise */
01079     double              seeing_min_arcsec = 0.1;
01080     double              seeing_max_arcsec = 5.0;
01081     double              seeing_fwhm_var   = 0.2;
01082 
01083     /* Check entries */
01084     if (combined == NULL) return NULL;
01085     
01086     /* Create the vector for the detection thresholds */
01087     thresh_vec = cpl_vector_new(4);
01088     cpl_vector_set(thresh_vec, 0, 5.0);
01089     cpl_vector_set(thresh_vec, 1, 2.0);
01090     cpl_vector_set(thresh_vec, 2, 1.0);
01091     cpl_vector_set(thresh_vec, 3, 0.5);
01092 
01093     /* Detect apertures */
01094     if ((aperts = cpl_apertures_extract(combined, thresh_vec, NULL)) == NULL) {
01095         cpl_msg_error(cpl_func, "Cannot detect any aperture");
01096         cpl_vector_delete(thresh_vec);
01097         return NULL;
01098     }
01099     cpl_vector_delete(thresh_vec);
01100 
01101     /* Number of detected objects */
01102     nb_objs = cpl_apertures_get_size(aperts);
01103     sofi_img_jitter_config.nbobjs = nb_objs;
01104 
01105     /* Compute the FHWM of the detected apertures */
01106     if ((fwhms = cpl_apertures_get_fwhm(combined, aperts)) == NULL) {
01107         cpl_msg_error(cpl_func, "Cannot compute the FWHMs");
01108         cpl_apertures_delete(aperts);
01109         return NULL;
01110     }
01111 
01112     /* Access the data */
01113     nb_val = cpl_bivector_get_size(fwhms);
01114     fwhms_x = cpl_bivector_get_x_data(fwhms);
01115     fwhms_y = cpl_bivector_get_y_data(fwhms);
01116 
01117     /* Store everything in the output table */
01118     out_tab = cpl_table_new(nb_objs);
01119     cpl_table_new_column(out_tab, "POS_X", CPL_TYPE_DOUBLE);
01120     cpl_table_new_column(out_tab, "POS_Y", CPL_TYPE_DOUBLE);
01121     cpl_table_new_column(out_tab, "FWHM_X", CPL_TYPE_DOUBLE);
01122     cpl_table_new_column(out_tab, "FWHM_Y", CPL_TYPE_DOUBLE);
01123     cpl_table_new_column(out_tab, "FLUX", CPL_TYPE_DOUBLE);
01124     for (i=0 ; i<nb_objs ; i++) {
01125         cpl_table_set_double(out_tab, "POS_X", i, 
01126                 cpl_apertures_get_centroid_x(aperts, i+1));
01127         cpl_table_set_double(out_tab, "POS_Y", i, 
01128                 cpl_apertures_get_centroid_y(aperts, i+1));
01129         cpl_table_set_double(out_tab, "FWHM_X", i, fwhms_x[i]);
01130         cpl_table_set_double(out_tab, "FWHM_Y", i, fwhms_y[i]);
01131         cpl_table_set_double(out_tab, "FLUX", i, 
01132                 cpl_apertures_get_flux(aperts, i+1));
01133     }
01134     cpl_apertures_delete(aperts);
01135 
01136     /* Get the number of good values */
01137     nb_good = 0;
01138     for (i=0 ; i<nb_val ; i++) {
01139         if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) nb_good++;
01140     }
01141     if (nb_good == 0) {
01142         cpl_table_delete(out_tab);
01143         cpl_bivector_delete(fwhms);
01144         (void)cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
01145         return NULL;
01146     }
01147     
01148     /* Get the good values */
01149     fwhms_good = cpl_vector_new(nb_good);
01150     fwhms_good_data = cpl_vector_get_data(fwhms_good);
01151     j=0;
01152     for (i=0 ; i<nb_val ; i++) {
01153         if ((fwhms_x[i] > 0.0) && (fwhms_y[i] > 0.0)) {
01154             fwhms_good_data[j] = (fwhms_x[i]+fwhms_y[i])/2.0;
01155             j++;
01156         }
01157     }
01158    
01159     /* Compute the fwhm */
01160     if (nb_good < 3) {
01161         /* Too few values to compute the median */
01162         sofi_img_jitter_config.fwhm_pix = fwhms_good_data[0];
01163     } else {
01164         /* Compute the median */
01165         sofi_img_jitter_config.fwhm_pix = cpl_vector_get_median_const(fwhms_good);
01166     }
01167     sofi_img_jitter_config.fwhm_arcsec = 
01168         sofi_img_jitter_config.fwhm_pix * sofi_img_jitter_config.pixscale;
01169 
01170     /* Compute the mode of the FWHMs */
01171     if (nb_good > 5) {
01172         sofi_img_jitter_config.fwhm_mode = 
01173             sofi_img_jitter_get_mode(fwhms_good);
01174     }
01175     cpl_vector_delete(fwhms_good);
01176     
01177     /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */
01178     /* Compute f_min and f_max */
01179     f_min = seeing_min_arcsec / sofi_img_jitter_config.pixscale;
01180     f_max = seeing_max_arcsec / sofi_img_jitter_config.pixscale;
01181 
01182     /* Get the number of good values */
01183     nb_good = 0;
01184     for (i=0 ; i<nb_val ; i++) {
01185         fx = fwhms_x[i];
01186         fy = fwhms_y[i];
01187         fr = 2.0 * fabs(fx-fy) / (fx+fy);
01188         if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01189             (fr < seeing_fwhm_var)) nb_good++;
01190     }
01191     if (nb_good == 0) {
01192         cpl_table_delete(out_tab);
01193         cpl_bivector_delete(fwhms);
01194         (void)cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
01195         return NULL;
01196     }
01197 
01198     /* Get the good values */
01199     fwhms_good = cpl_vector_new(nb_good);
01200     fwhms_good_data = cpl_vector_get_data(fwhms_good);
01201     j=0;
01202     for (i=0 ; i<nb_val ; i++) {
01203         fx = fwhms_x[i];
01204         fy = fwhms_y[i];
01205         fr = 2.0 * fabs(fx-fy) / (fx+fy);
01206         if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) &&
01207             (fr < seeing_fwhm_var)) {
01208             fwhms_good_data[j] = (fx + fy)/2.0;
01209             j++;
01210         }
01211     }
01212     cpl_bivector_delete(fwhms);
01213     
01214     /* Compute the fwhm */
01215     if (nb_good < 3) {
01216         /* Too few values to compute the median */
01217         sofi_img_jitter_config.iq = fwhms_good_data[0];
01218     } else {
01219         /* Compute the median */
01220         sofi_img_jitter_config.iq = cpl_vector_get_median_const(fwhms_good);
01221     }
01222     cpl_vector_delete(fwhms_good);
01223     sofi_img_jitter_config.iq *= sofi_img_jitter_config.pixscale;
01224 
01225     return out_tab;
01226 }
01227         
01228 /*----------------------------------------------------------------------------*/
01234 /*----------------------------------------------------------------------------*/
01235 static double sofi_img_jitter_get_mode(cpl_vector * vec)
01236 {
01237     int                 nb;
01238     int                 nbins;
01239     double              min, max;
01240     double              bin_size;
01241     cpl_bivector    *   hist;
01242     cpl_vector      *   hist_x;
01243     cpl_vector      *   hist_y;
01244     double              cur_val;
01245     int                 cur_bin;
01246     double              max_val;
01247     int                 max_bin;
01248     double              mode;
01249     int                 i;
01250 
01251     /* Test entries  */
01252     if (vec == NULL) return -1.0;
01253     
01254     /* Initialise */
01255     nb = cpl_vector_get_size(vec);
01256 
01257     /* Create the histogram */
01258     nbins = 10;
01259     min = cpl_vector_get_min(vec);
01260     max = cpl_vector_get_max(vec);
01261     bin_size = (max-min)/nbins;
01262     hist = cpl_bivector_new(nbins);
01263     hist_x = cpl_bivector_get_x(hist);
01264     hist_y = cpl_bivector_get_y(hist);
01265     cpl_vector_fill(hist_x, 0.0);
01266     cpl_vector_fill(hist_y, 0.0);
01267     for (i=0 ; i<nbins ; i++) {
01268         cpl_vector_set(hist_x, i, min + i * bin_size);
01269     }
01270     for (i=0 ; i<nb ; i++) {
01271         cur_val = cpl_vector_get(vec, i);
01272         cur_bin = (int)((cur_val - min) / bin_size);
01273         if (cur_bin >= nbins) cur_bin -= 1.0;
01274         cur_val = cpl_vector_get(hist_y, cur_bin);
01275         cur_val += 1.0;
01276         cpl_vector_set(hist_y, cur_bin, cur_val);
01277     }
01278     
01279     /* Get the mode of the histogram */
01280     max_val = cpl_vector_get(hist_y, 0);
01281     max_bin = 0;
01282     for (i=0 ; i<nbins ; i++) {
01283         cur_val = cpl_vector_get(hist_y, i);
01284         if (cur_val > max_val) {
01285             max_val = cur_val;
01286             max_bin = i;
01287         }
01288     }
01289     mode = cpl_vector_get(hist_x, max_bin);
01290     cpl_bivector_delete(hist);
01291     return mode;
01292 }
01293         
01294 /*----------------------------------------------------------------------------*/
01304 /*----------------------------------------------------------------------------*/
01305 static int sofi_img_jitter_save(
01306         cpl_image           *   combined,
01307         cpl_table           *   objs_stats,
01308         cpl_vector          *   sky_bg,
01309         cpl_parameterlist   *   parlist,
01310         cpl_frameset        *   set)
01311 {
01312     const cpl_frame     *   ref_frame;
01313     cpl_propertylist    *   plist;
01314     cpl_propertylist    *   paflist;
01315     cpl_propertylist    *   qclist;
01316     double                  pscale, dit, bg_mean, bg_stdev, bg_instmag;
01317     cpl_table           *   sky_bg_tab;
01318     int                     i;
01319  
01320     /* Get the QC params in qclist */
01321     qclist = cpl_propertylist_new();
01322 
01323     if (sky_bg != NULL) {
01324         pscale = sofi_img_jitter_config.pixscale;
01325         dit = sofi_img_jitter_config.dit;
01326         bg_mean = cpl_vector_get_mean(sky_bg);
01327         if (cpl_vector_get_size(sky_bg) < 2) bg_stdev = 0;
01328         else bg_stdev = cpl_vector_get_stdev(sky_bg);
01329         bg_instmag = -2.5 * log(bg_mean/(pscale*pscale*dit));
01330         cpl_propertylist_append_double(qclist, "ESO QC BACKGD MEAN", bg_mean);
01331         cpl_propertylist_append_double(qclist, "ESO QC BACKGD STDEV", bg_stdev);
01332         cpl_propertylist_append_double(qclist, "ESO QC BACKGD INSTMAG", 
01333                 bg_instmag);
01334     }
01335     cpl_propertylist_append_int(qclist, "ESO QC NBOBJS",
01336             sofi_img_jitter_config.nbobjs);
01337     cpl_propertylist_append_double(qclist, "ESO QC IQ",
01338             sofi_img_jitter_config.iq);
01339     cpl_propertylist_append_double(qclist, "ESO QC FWHM PIX",
01340             sofi_img_jitter_config.fwhm_pix);
01341     cpl_propertylist_append_double(qclist, "ESO QC FWHM ARCSEC",
01342             sofi_img_jitter_config.fwhm_arcsec);
01343     cpl_propertylist_append_double(qclist, "ESO QC FWHM MODE",
01344             sofi_img_jitter_config.fwhm_mode);
01345     cpl_propertylist_append_int(qclist, "ESO QC NB_OBJ_F",
01346             sofi_img_jitter_config.nb_obj_frames);
01347     cpl_propertylist_append_int(qclist, "ESO QC NB_SKY_F",
01348             sofi_img_jitter_config.nb_sky_frames);
01349     cpl_propertylist_append_int(qclist, "ESO QC NB_REJ_F",
01350             sofi_img_jitter_config.nb_rej_frames);
01351 
01352     /* Write the image */
01353     irplib_dfs_save_image(set,
01354             parlist,
01355             set,
01356             combined,
01357             CPL_BPP_IEEE_FLOAT,
01358             "sofi_img_jitter",
01359             SOFI_IMG_JITTER_COMB,
01360             qclist,
01361             NULL,
01362             PACKAGE "/" PACKAGE_VERSION,
01363             "sofi_img_jitter.fits");
01364 
01365 
01366     /* Write the FITS background table */
01367     if (sky_bg) {
01368         /* First create the table from the vector */
01369         sky_bg_tab = cpl_table_new(cpl_vector_get_size(sky_bg));
01370         cpl_table_new_column(sky_bg_tab, "SKY_BG", CPL_TYPE_DOUBLE);
01371         for (i=0 ; i<cpl_vector_get_size(sky_bg) ; i++) {
01372             cpl_table_set_double(sky_bg_tab, "SKY_BG", i,
01373                     cpl_vector_get(sky_bg, i));
01374         }
01375         irplib_dfs_save_table(set,
01376                 parlist,
01377                 set,
01378                 sky_bg_tab,
01379                 NULL,
01380                 "sofi_img_jitter",
01381                 SOFI_IMG_JITTER_BG,
01382                 qclist,
01383                 NULL,
01384                 PACKAGE "/" PACKAGE_VERSION,
01385                 "sofi_img_jitter_bg.fits");
01386         cpl_table_delete(sky_bg_tab);
01387     }
01388 
01389     /* Write the FITS table */
01390     if (objs_stats) {
01391         irplib_dfs_save_table(set,
01392                 parlist,
01393                 set,
01394                 objs_stats,
01395                 NULL,
01396                 "sofi_img_jitter",
01397                 SOFI_IMG_JITTER_STARS,
01398                 qclist,
01399                 NULL,
01400                 PACKAGE "/" PACKAGE_VERSION,
01401                 "sofi_img_jitter_stars.fits");
01402     }
01403 
01404     /* Get the reference frame */
01405     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01406 
01407     /* Get FITS header from reference file */
01408     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01409                     0)) == NULL) {
01410         cpl_msg_error(cpl_func, "getting header from reference frame");
01411         cpl_propertylist_delete(qclist);
01412         return -1;
01413     }
01414 
01415     /* Get the keywords for the paf file */
01416     paflist = cpl_propertylist_new();
01417     cpl_propertylist_copy_property_regexp(paflist, plist,
01418         "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01419         "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO OBS ID|ESO INS PIXSCALE)$", 0);
01420     cpl_propertylist_delete(plist);
01421 
01422     /* Copy the QC in paflist */
01423     cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01424     cpl_propertylist_delete(qclist);
01425 
01426     /* Save the PAF file */
01427     cpl_dfs_save_paf("SOFI",
01428             "sofi_img_jitter",
01429             paflist,
01430             "sofi_img_jitter.paf");
01431     cpl_propertylist_delete(paflist);
01432     return  0;
01433 }
01434  

Generated on Thu Mar 7 16:21:06 2013 for SOFI Pipeline Reference Manual by  doxygen 1.5.8