sinfo_utl_illumcorr.c

00001 /* $Id: sinfo_utl_illumcorr.c,v 1.18 2012/03/03 10:38:03 amodigli Exp $
00002  *
00003  * This file is part of the CPL (Common Pipeline Library)
00004  * Copyright (C) 2002 European Southern Observatory
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library 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 GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2012/03/03 10:38:03 $
00023  * $Revision: 1.18 $
00024  * $Name: HEAD $
00025  */
00026 
00027  /****************************************************************
00028   *           Object Data reduction                              *
00029   ****************************************************************/
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>          /* allows the program compilation */
00033 #endif
00034 
00035 /*-----------------------------------------------------------------------------
00036                                 Includes
00037 -----------------------------------------------------------------------------*/
00038 
00039 /* std */
00040 #include <strings.h>
00041 #include <string.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044 #include <libgen.h>
00045 
00046 
00047 /* cpl */
00048 #include <cpl.h>  
00049 
00050 /* irplib */
00051 #include <irplib_utils.h>
00052 
00053 /* sinfoni */
00054 #include <sinfo_pro_types.h>
00055 #include <sinfo_product_config.h>
00056 #include <sinfo_prepare_stacked_frames_config.h>
00057 #include <sinfo_objnod_config.h>
00058 #include <sinfo_new_objnod.h>
00059 #include <sinfo_new_prepare_stacked_frames.h>
00060 #include <sinfo_pro_save.h>
00061 #include <sinfo_raw_types.h>
00062 #include <sinfo_functions.h>
00063 #include <sinfo_tpl_utils.h>
00064 #include <sinfo_tpl_dfs.h>
00065 #include <sinfo_hidden.h>
00066 #include <sinfo_globals.h>
00067 #include <sinfo_rec_utils.h>
00068 //Only for sinfo_propertylist_has
00069 #include <sinfo_dfs.h>
00070 
00071 
00072 /*-----------------------------------------------------------------------------
00073                             Function prototypes
00074 -----------------------------------------------------------------------------*/
00075 static int sinfo_utl_illumcorr_create(cpl_plugin *plugin);
00076 static int sinfo_utl_illumcorr_exec(cpl_plugin *plugin);
00077 static int sinfo_utl_illumcorr_destroy(cpl_plugin *plugin);
00078 static int sinfo_utl_illumcorr(cpl_parameterlist *config, cpl_frameset *set);
00079 
00080 
00081 #define SINFO_DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
00082 
00083 static cpl_error_code 
00084 sinfo_tools_sort_double(
00085         double  *   pix_arr,
00086         int         n);
00087 
00088 static cpl_frame* 
00089 sinfo_get_dummy_object(cpl_frameset* obj_set);
00090 
00091 static void 
00092 sinfo_illumcorr_config_add (cpl_parameterlist *list);
00093 
00094 static int 
00095 create_illumcorr (const char* plugin_id, 
00096                  cpl_parameterlist *cpl_cfg, 
00097                  cpl_frameset* sof,
00098                  const char *name_i);
00099 static int 
00100 sinfo_illumcorr_create_bins (cpl_imagelist *sky, 
00101                  int llx, int lly, int urx, int ury,
00102                  int spec_bin, 
00103                  double min_flux,
00104                  int ** start,
00105                  int ** end,
00106                  int z1, int z2);
00107 
00108 static int 
00109 sinfo_juha_function1d_natural_spline(double *, double *, int, double *, 
00110                                      double *, int);
00111 
00112 static int 
00113 sinfo_function1d_search_value(double *, int, double, int *) ;
00114 
00115 static cpl_vector * 
00116 sinfo_vector_filter_median_create(const cpl_vector * v, int  hw);
00117 
00118 static cpl_vector * 
00119 sinfo_juha_vector_filter_median_create(const cpl_vector * v, int  hw);
00120 
00121 static double 
00122 sinfo_image_get_median_window  (const cpl_image *image, 
00123                 int llx, int lly, int urx, int ury);
00124 
00125 
00126 /*-----------------------------------------------------------------------------
00127                             Static variables
00128 -----------------------------------------------------------------------------*/
00129 
00130 static char sinfo_utl_illumcorr_description1[] =
00131 "This recipe calculates illumination correction based on sky emission.\n"
00132 "The input files are sky (or object) frames tagged\n"
00133 " SKY_NODDING (OBJECT_NODDING)\n"
00134 "Master calibration frames:\n";
00135 
00136 
00137 static char sinfo_utl_illumcorr_description2[] =
00138 "A corresponding (DIT) dark frame (tag=MASTER_DARK)"
00139 "A corresponding (band,preoptics) wavelength map image (tag=WAVE_MAP)\n"
00140 "A corresponding (band,preoptics) master flat field (tag=MASTER_FLAT_LAMP)\n"
00141 "A corresponding (band,preoptics) master bad pixel map (tag=MASTER_BP_MAP)\n"
00142 "A corresponding (band,preoptics) slitlets position frame (tag=SLIT_POS)\n"
00143 "A corresponding (band) distortion table (tag=DISTORTION)\n"
00144 "A corresponding (band) slitlet distance table (tag=SLITLETS_DISTANCE)\n";
00145 
00146 
00147 static char sinfo_utl_illumcorr_description3[] =
00148 "The output is a cube resulting from the analysis of sky emission\n";
00149 
00150 
00151 static char sinfo_utl_illumcorr_description4[] =
00152 "Information on relevant parameters can be found with\n"
00153 "esorex --params sinfo_utl_illumcorr\n"
00154 "esorex --help sinfo_utl_illumcorr\n"
00155 "\n";
00156 
00157 static char sinfo_utl_illumcorr_description[1300];
00158 
00159 /*-----------------------------------------------------------------------------
00160                                 Functions code
00161 -----------------------------------------------------------------------------*/
00162 
00164 /*---------------------------------------------------------------------------*/
00169 /*---------------------------------------------------------------------------*/
00170 static int
00171 sinfo_utl_illumcorr_create(cpl_plugin *plugin)
00172 {
00173 
00174   /*
00175    * We have to provide the option we accept to the application.
00176    * We need to setup our parameter list and hook it into the recipe
00177    * interface.
00178    */
00179   cpl_recipe *recipe = (cpl_recipe *)plugin;
00180   recipe->parameters = cpl_parameterlist_new();
00181   if(recipe->parameters == NULL) {
00182     return 1;
00183   }
00184   cpl_error_reset();
00185   irplib_reset();
00186 
00187   /*
00188    * Fill the parameter list.
00189    */
00190   sinfo_product_config_add (recipe->parameters);
00191   sinfo_prepare_stacked_frames_config_add(recipe->parameters);
00192   sinfo_objnod_config_add(recipe->parameters); 
00193   sinfo_illumcorr_config_add (recipe->parameters);
00194  
00195   return 0;
00196 
00197 }
00198 
00199 /*---------------------------------------------------------------------------*/
00205 /*---------------------------------------------------------------------------*/
00206 static int
00207 sinfo_utl_illumcorr_exec(cpl_plugin *plugin)
00208 {
00209  
00210   cpl_recipe *recipe = (cpl_recipe *) plugin;
00211   int code=0;
00212   cpl_errorstate initial_errorstate = cpl_errorstate_get();
00213 
00214   if(recipe->parameters == NULL) {
00215     return 1;
00216   }
00217   if(recipe->frames == NULL) {
00218     return 1;
00219   }
00220   code=sinfo_utl_illumcorr(recipe->parameters, recipe->frames);
00221 
00222   if (!cpl_errorstate_is_equal(initial_errorstate)) {                      
00223     /* Dump the error history since recipe execution start.                
00224        At this point the recipe cannot recover from the error */           
00225     cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);              
00226   } 
00227   return code;
00228 
00229 
00230 }
00231 
00232 /*---------------------------------------------------------------------------*/
00238 /*---------------------------------------------------------------------------*/
00239 static int
00240 sinfo_utl_illumcorr_destroy(cpl_plugin *plugin)
00241 {
00242   cpl_recipe *recipe = (cpl_recipe *) plugin;
00243   /*
00244    * We just destroy what was created during the plugin initializzation phase
00245    * i.e. the parameter list. The frame set is managed by the application which
00246    * called us, so that we must not touch it.
00247    */
00248 
00249   cpl_parameterlist_delete(recipe->parameters);
00250 
00251   return 0;
00252 
00253 }
00254 
00255 /*---------------------------------------------------------------------------*/
00263 /*---------------------------------------------------------------------------*/
00264 int
00265 cpl_plugin_get_info(cpl_pluginlist *list)
00266 {
00267 
00268   cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00269   cpl_plugin *plugin = &recipe->interface;
00270 
00271   strcpy(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description1);
00272   strcat(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description2);
00273   strcat(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description3);
00274   strcat(sinfo_utl_illumcorr_description,sinfo_utl_illumcorr_description4);
00275 
00276   cpl_plugin_init(plugin,
00277           CPL_PLUGIN_API,
00278           SINFONI_BINARY_VERSION,
00279           CPL_PLUGIN_TYPE_RECIPE,
00280           "sinfo_utl_illumcorr",
00281           "Object data reduction",
00282            sinfo_utl_illumcorr_description,
00283           "Juha Reunanen",
00284           "reunanen@strw.leidenuniv.nl",
00285           sinfo_get_license(),
00286           sinfo_utl_illumcorr_create,
00287           sinfo_utl_illumcorr_exec,
00288           sinfo_utl_illumcorr_destroy);
00289 
00290   cpl_pluginlist_append(list, plugin);
00291 
00292   return 0;
00293 
00294 }
00295 
00296 /*
00297  * The actual recipe actually start here.
00298  */
00299 
00300 static int
00301 sinfo_utl_illumcorr(cpl_parameterlist *config, cpl_frameset *set)
00302 {
00303   char outname[FILE_NAME_SZ];
00304 
00305   int i=0;
00306   int k=0;
00307 
00308   int ind=0;
00309   int nsky=0;
00310   int nobj=0;
00311   int ncdb=0;
00312   int nstk=0;
00313 
00314   cpl_frameset  * obj_set=NULL;
00315   cpl_frameset  * sky_set=NULL;
00316   cpl_frameset  * cdb_set=NULL;
00317   cpl_frameset  * wrk_set=NULL;
00318   cpl_frameset  * stk_set=NULL;
00319   cpl_frame     * sky_frm=NULL;
00320 
00321   cpl_frame     * dup_frm=NULL; 
00322   cpl_frame     * cdb_frm=NULL;
00323   cpl_frame     * wrk_frm=NULL;
00324   cpl_frameset  * ref_set=NULL;
00325 
00326   cpl_frame     * dark_frm=NULL;
00327 
00328   fake* fk;
00329 
00330 
00331   cpl_image           *   ima1=NULL ;
00332   cpl_image           *   ima2=NULL ;
00333   cpl_image           *   resima=NULL ;
00334   cpl_propertylist    *   plist=NULL ;
00335   cpl_frame           *   product_frame=NULL;
00336   const char *name_i=NULL;
00337 
00338   /* cpl_parameterlist_dump(config); */
00339         sinfo_msg("Welcome to SINFONI Pipeline release %d.%d.%d",
00340         SINFONI_MAJOR_VERSION,SINFONI_MINOR_VERSION,SINFONI_MICRO_VERSION);
00341 
00342   if(sinfo_dfs_set_groups(set)) {
00343     sinfo_msg_error("Cannot identify RAW and CALIB frames") ;
00344     return -1;
00345   }
00346 
00347   dark_frm = cpl_frameset_find(set,PRO_MASTER_DARK);
00348   if (dark_frm == NULL) {
00349     sinfo_msg_error("Cannot find dark frame") ;
00350     return (-1);
00351   }
00352 
00353   ref_set=cpl_frameset_duplicate(set);
00354 
00355   obj_set=cpl_frameset_new();
00356   sky_set=cpl_frameset_new();
00357   cdb_set=cpl_frameset_new();
00358   fk = sinfo_fake_new();
00359 
00360   sinfo_extract_obj_frames(set,obj_set);
00361   sinfo_extract_sky_frames(set,sky_set);
00362   sinfo_extract_mst_frames(set,cdb_set);
00363 
00364   nobj=cpl_frameset_get_size(obj_set);
00365   nsky=cpl_frameset_get_size(sky_set);
00366   ncdb=cpl_frameset_get_size(cdb_set);
00367 
00368   if ((nobj==0) && (nsky==0)) {
00369     sinfo_msg_error("Empty input set");
00370     cpl_frameset_delete(obj_set);
00371     cpl_frameset_delete(sky_set);
00372     cpl_frameset_delete(cdb_set);
00373     cpl_frameset_delete(ref_set);
00374     sinfo_fake_delete(&fk);
00375     return (-1);
00376   }
00377 
00378 
00379   /*
00380    *  Create median collapsed sky frame either from real SKY frames, 
00381    *  or from jittered OBJECT frames
00382    */
00383   if ( nsky != 0) {
00384     if( (sky_frm = sinfo_get_dummy_object(sky_set)) == NULL) {
00385       sinfo_msg_error("Problem to get dummy frame");
00386       cpl_frameset_delete(obj_set);
00387       cpl_frameset_delete(sky_set);
00388       cpl_frameset_delete(cdb_set);
00389       cpl_frameset_delete(ref_set);
00390       sinfo_fake_delete(&fk);
00391       return (-1);
00392     }
00393   }
00394   else {
00395     if( (sky_frm = sinfo_get_dummy_object(obj_set)) == NULL) {
00396       sinfo_msg_error("Problem to get dummy frame");
00397       cpl_frameset_delete(obj_set);
00398       cpl_frameset_delete(sky_set);
00399       cpl_frameset_delete(cdb_set);
00400       cpl_frameset_delete(ref_set);
00401       sinfo_fake_delete(&fk);
00402       return (-1);
00403     }
00404   }
00405   
00406   /* 
00407    *  Seems it's not possible to use draks as sky (due to INS.GRAT1.ENC)
00408    *  and stacking phase subtracts dark only in special circumstances...
00409    */
00410   ima1 = cpl_image_load(cpl_frame_get_filename(sky_frm),CPL_TYPE_FLOAT,0,0);
00411   ima2 = cpl_image_load(cpl_frame_get_filename(dark_frm),CPL_TYPE_FLOAT,0,0);
00412   resima = cpl_image_subtract_create(ima1, ima2);
00413   plist=cpl_propertylist_load(cpl_frame_get_filename(sky_frm), 0);
00414   cpl_image_delete(ima1);
00415   cpl_image_delete(ima2);
00416 
00417   product_frame = cpl_frame_new();
00418   cpl_frame_set_filename(product_frame, "out_fake_object2.fits") ;
00419   cpl_frame_set_tag(product_frame, "OBJECT_NODDING") ;
00420   cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_IMAGE) ;
00421   cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_RAW) ;
00422   //cpl_frame_set_level(product_frame, CPL_FR) ;
00423   cpl_propertylist_erase_regexp(plist, "^ESO PRO CATG",0);
00424 
00425   cpl_image_save(resima, "out_fake_object2.fits", CPL_BPP_IEEE_FLOAT, plist,
00426          CPL_IO_DEFAULT) ;
00427   cpl_propertylist_delete(plist) ;
00428   cpl_image_delete(resima) ;
00429 
00430 
00431   /*
00432    *  Stack it - with some trickery...
00433    */ 
00434   wrk_set=cpl_frameset_new();
00435 
00436   dup_frm=cpl_frame_duplicate(product_frame);
00437   cpl_frame_set_tag   (dup_frm, "OBJECT_NODDING");
00438   cpl_frame_set_group (dup_frm ,CPL_FRAME_GROUP_RAW);
00439   cpl_frameset_insert(wrk_set,dup_frm);
00440 
00441   /* merge CDB frames to work set */
00442   for(k=0;k<ncdb;k++) {
00443     cdb_frm=cpl_frameset_get_frame(cdb_set,k);
00444     dup_frm=cpl_frame_duplicate(cdb_frm);
00445     cpl_frameset_insert(wrk_set,dup_frm);
00446   }
00447   
00448   
00449   /* defines a new name for the output stacked frame */ 
00450   sprintf(outname,"%s%d%s","out_stack",i,".fits");
00451   if(-1 == sinfo_new_stack_frames(config,wrk_set,
00452             PRO_OBJECT_NODDING_STACKED,i,fk,cpl_func)) {
00453     
00454     cpl_frameset_delete(wrk_set);
00455     //cpl_frameset_delete(tot_set);
00456     cpl_frameset_delete(obj_set);
00457     cpl_frameset_delete(sky_set);
00458     cpl_frameset_delete(cdb_set);
00459     cpl_frameset_delete(ref_set);
00460     sinfo_fake_delete(&fk);
00461     return -1;
00462   }
00463 
00464   stk_set=cpl_frameset_new();
00465   sinfo_contains_frames_kind(wrk_set,stk_set,PRO_STACKED);
00466   nstk=cpl_frameset_get_size(stk_set);
00467 
00468   for(k=0;k<nstk;k++) {
00469     wrk_frm=cpl_frameset_get_frame(stk_set,k);
00470     dup_frm = cpl_frame_duplicate(wrk_frm);
00471     cpl_frameset_insert(set,dup_frm);
00472   }
00473   cpl_frameset_delete(stk_set);
00474   cpl_frameset_delete(wrk_set);
00475 
00476   sinfo_msg("------------------------------") ; 
00477   sinfo_msg("CREATING SKY CUBE");
00478   sinfo_msg("------------------------------") ; 
00479   
00480 
00481   if ( -1 == (ind=sinfo_new_objnod(cpl_func,config, set, PRO_COADD_OBJ ) ) ) {
00482     sinfo_msg_error("NODDING SCIENCE FRAMES no. %d\n", ind) ;
00483     cpl_frameset_delete(obj_set);
00484     cpl_frameset_delete(sky_set);
00485     cpl_frameset_delete(cdb_set);
00486     cpl_frameset_delete(ref_set);
00487     sinfo_fake_delete(&fk);
00488     
00489     return (-1);
00490   }
00491   sinfo_msg("------------------------------") ; 
00492   sinfo_msg("CREATED SKY CUBE");
00493   sinfo_msg("------------------------------") ; 
00494   
00495 
00496   stk_set=cpl_frameset_new();
00497   sinfo_contains_frames_kind(set, stk_set, PRO_OBS_OBJ);
00498   nstk=cpl_frameset_get_size(stk_set);
00499 
00500   wrk_frm=cpl_frameset_get_frame(stk_set,0);  
00501   name_i = cpl_frame_get_filename(wrk_frm);
00502   
00503 
00504   //cpl_frameset_delete(wrk_set);
00505   cpl_frameset_delete(obj_set);
00506   cpl_frameset_delete(sky_set);
00507   cpl_frameset_delete(cdb_set);
00508   cpl_frameset_delete(ref_set);
00509   sinfo_fake_delete(&fk);
00510   cpl_frame_delete(sky_frm);
00511   create_illumcorr (cpl_func, config, set, name_i);
00512 
00513   return (0);
00514 
00515 }
00516 
00517 
00518 static cpl_frame*
00519 sinfo_get_dummy_object(cpl_frameset* obj_set)
00520 {
00521 
00522   cpl_imagelist* obj_list=NULL;
00523   cpl_image* fake_object=NULL;
00524   char filename[FILE_NAME_SZ];
00525   cpl_frame* frame=NULL;
00526   cpl_frame* object_frame=NULL;
00527 
00528   cpl_propertylist* plist=NULL;
00529  
00530   obj_list = cpl_imagelist_load_frameset(obj_set,CPL_TYPE_FLOAT,0,0);
00531   fake_object = cpl_imagelist_collapse_median_create(obj_list);
00532 
00533   frame = cpl_frameset_get_frame(obj_set,0);
00534   strcpy(filename,cpl_frame_get_filename(frame));
00535  
00536   if ((cpl_error_code)((plist = cpl_propertylist_load(filename, 0)) == NULL)) {
00537     sinfo_msg_error("getting header from reference ima frame %s",filename);
00538     cpl_propertylist_delete(plist) ;
00539     return NULL ;
00540   }
00541 
00542   if (sinfo_propertylist_has(plist, KEY_NAME_DPR_TYPE)) {
00543     cpl_propertylist_set_string(plist, KEY_NAME_DPR_TYPE, "OBJECT");
00544   } else {
00545     cpl_propertylist_append_string(plist, KEY_NAME_DPR_TYPE,"OBJECT") ;
00546   }
00547        
00548   if (cpl_image_save(fake_object, "out_fake_object.fits", CPL_BPP_IEEE_FLOAT, 
00549                    plist,CPL_IO_DEFAULT)!=CPL_ERROR_NONE) {
00550     sinfo_msg_error("Cannot save the product %s","out_fake_object.fits");
00551     cpl_propertylist_delete(plist) ;
00552     return NULL ;
00553   }
00554   cpl_propertylist_delete(plist);
00555        
00556   object_frame = cpl_frame_new() ;
00557   cpl_frame_set_filename(object_frame, "out_fake_object.fits") ;
00558   cpl_frame_set_tag(object_frame, "OBJECT") ;
00559   cpl_frame_set_type(object_frame, CPL_FRAME_TYPE_IMAGE);
00560   /*
00561   cpl_frame_set_group(object_frame, CPL_FRAME_GROUP_PRODUCT);
00562   */
00563   cpl_frame_set_level(object_frame, CPL_FRAME_LEVEL_FINAL);
00564   cpl_image_delete(fake_object);
00565   cpl_imagelist_delete(obj_list);
00566 
00567   return object_frame;
00568 }
00569 
00570 static void 
00571 sinfo_illumcorr_config_add (cpl_parameterlist *list) 
00572 {
00573   cpl_parameter *p;
00574 
00575   if (!list) {
00576     return;
00577   }
00578 
00579   p = cpl_parameter_new_range("sinfoni.illumcorr.spec_bin",
00580                               CPL_TYPE_INT,
00581                               "Number of spectral planes to be combined ",
00582                               "sinfoni.illumcorr",
00583                               100, 1, 200);
00584   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-spec_bin");
00585   cpl_parameterlist_append(list, p);
00586 
00587   p = cpl_parameter_new_value("sinfoni.illumcorr.min_flux",
00588                               CPL_TYPE_DOUBLE,
00589                               "Minimum flux in each spectral bin ",
00590                               "sinfoni.illumcorr",
00591                               0.0);
00592   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-min_flux");
00593   cpl_parameterlist_append(list, p);
00594 
00595   p = cpl_parameter_new_value("sinfoni.illumcorr.center_bins",
00596                               CPL_TYPE_BOOL,
00597                               "Center the spectral bins at prominent "
00598                               "emission features ",
00599                               "sinfoni.illumcorr",
00600                               FALSE);
00601   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-center_bins");
00602   cpl_parameterlist_append(list, p);
00603 
00604   p = cpl_parameter_new_enum("sinfoni.illumcorr.order",
00605                  CPL_TYPE_INT,
00606                  "The order of the polynomial to be fitted "
00607                              "for each slitlet",
00608                  "sinfoni.illumcorr",
00609                  0,
00610                  2,0,1);
00611   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-order");
00612   cpl_parameterlist_append(list, p);
00613   
00614   p = cpl_parameter_new_value("sinfoni.illumcorr.sigma",
00615                               CPL_TYPE_DOUBLE,
00616                               "Reject n-sigma deviant pixels on each slitlet ",
00617                               "sinfoni.illumcorr",
00618                               3.0);
00619   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-sigma");
00620   cpl_parameterlist_append(list, p);
00621 
00622   p = cpl_parameter_new_value("sinfoni.illumcorr.iterations",
00623                               CPL_TYPE_INT,
00624                               "Number of sigma rejection iterations to run ",
00625                               "sinfoni.illumcorr",
00626                               3);
00627   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-iter");
00628   cpl_parameterlist_append(list, p);
00629 
00630   p = cpl_parameter_new_range("sinfoni.illumcorr.llx",
00631                               CPL_TYPE_INT,
00632                               "Reference region coordinates ",
00633                               "sinfoni.illumcorr",
00634                               8, 0, 63);
00635   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-llx");
00636   cpl_parameterlist_append(list, p);
00637 
00638   p = cpl_parameter_new_range("sinfoni.illumcorr.lly",
00639                               CPL_TYPE_INT,
00640                               "Reference region coordinates ",
00641                               "sinfoni.illumcorr",
00642                               33, 0, 63);
00643   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-lly");
00644   cpl_parameterlist_append(list, p);
00645 
00646   p = cpl_parameter_new_range("sinfoni.illumcorr.urx",
00647                               CPL_TYPE_INT,
00648                               "Reference region coordinates ",
00649                               "sinfoni.illumcorr",
00650                               60, 0, 63);
00651   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-urx");
00652   cpl_parameterlist_append(list, p);
00653 
00654   p = cpl_parameter_new_range("sinfoni.illumcorr.ury",
00655                               CPL_TYPE_INT,
00656                               "Reference region coordinates ",
00657                               "sinfoni.illumcorr",
00658                               36, 0, 63);
00659   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-ury");
00660   cpl_parameterlist_append(list, p);
00661 
00662   p = cpl_parameter_new_enum("sinfoni.illumcorr.smooth0",
00663                  CPL_TYPE_INT,
00664                  "Smooth zeroth order terms by fitting "
00665                              "with polynomial (1),"
00666                  "with median filter (2) or not (0) ",
00667                  "sinfoni.illumcorr",
00668                  0, 
00669                  3, 0, 1, 2);
00670   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-smooth0");
00671   cpl_parameterlist_append(list, p);
00672 
00673   p = cpl_parameter_new_value("sinfoni.illumcorr.smooth0_order",
00674                               CPL_TYPE_INT,
00675                               "Order of the smoothing polynomial for 0th term",
00676                               "sinfoni.illumcorr",
00677                               2);
00678   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-smooth_order0");
00679   cpl_parameterlist_append(list, p);
00680 
00681   p = cpl_parameter_new_range("sinfoni.illumcorr.smooth0_size",
00682                               CPL_TYPE_INT,
00683                               "Size of the median filter for 0th "
00684                               "order smoothing ",
00685                               "sinfoni.illumcorr",
00686                               51,3, 301);
00687   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-smooth0_size");
00688   cpl_parameterlist_append(list, p);
00689 
00690   p = cpl_parameter_new_value("sinfoni.illumcorr.smooth1",
00691                               CPL_TYPE_BOOL,
00692                               "Smooth higher (>0) order polynomials ",
00693                               "sinfoni.illumcorr",
00694                               TRUE);
00695   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-smooth");
00696   cpl_parameterlist_append(list, p);
00697 
00698   p = cpl_parameter_new_value("sinfoni.illumcorr.smooth1_order",
00699                               CPL_TYPE_INT,
00700                               "Smoothing order for higher terms ",
00701                               "sinfoni.illumcorr",
00702                               2);
00703   cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"illumcorr-smooth_order");
00704   cpl_parameterlist_append(list, p);
00705 
00706   p = cpl_parameter_new_value("sinfoni.illumcorr.illumcorr_sigma",
00707                               CPL_TYPE_DOUBLE,
00708                               "Reject all fits for which the rms is "
00709                               "illumcorr-sigma times bigger than the "
00710                               "median rms in each spectral bin" ,
00711                               "sinfoni.illumcorr",
00712                               5.0);
00713   cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
00714                             "illumcorr-illumcorr_sigma");
00715   cpl_parameterlist_append(list, p);
00716 
00717 }
00718 
00719 static int
00720 create_illumcorr (const char* plugin_id,
00721           cpl_parameterlist *cpl_cfg,
00722           cpl_frameset* sof,
00723           const char *name_i)
00724 {
00725   cpl_parameter *p=NULL;
00726   double        min_flux=0;
00727   double        sigma=0;
00728   double        il_sigma=0;
00729   int           spec_bin=0;
00730   int           _order=0;
00731   cpl_imagelist *sky=NULL;
00732   cpl_imagelist *binnedsky=NULL;
00733   cpl_imagelist *result=NULL;
00734   cpl_image     *temp_image=NULL;
00735   cpl_image     *temp_image2=NULL;
00736   int            nplanes=0;
00737   int            i=0;
00738   int            j=0;
00739   int            k=0;
00740   int            kk=0;
00741   int            n=0;
00742   int            slitlet=0;
00743   int            bin=0;
00744   double        *median=NULL;
00745   double        *pos=NULL;
00746   double         temp=0;
00747   double         temp2=0;
00748   double        *inter_pos=NULL;
00749   double        *inter_val=NULL;
00750   double        *plane_pos=NULL;
00751   double        *plane_val=NULL;
00752   int            llx=0;
00753   int            lly=0;
00754   int            urx=0;
00755   int            ury=0;
00756   int            smooth_order=0;
00757   int            iter=0;
00758   cpl_vector    *row=NULL;
00759   cpl_vector    *model=NULL;
00760   cpl_vector    *xpos=NULL;
00761   cpl_vector    *tempvector=NULL;
00762   cpl_vector *tempvector2=NULL;
00763   double         mse=0.0;
00764   double         stddev=0.0;
00765   cpl_polynomial*poly=NULL;
00766   cpl_polynomial *poly2=NULL;
00767   double        *temparray=NULL;
00768   double  *tempxarray=NULL;
00769   double  * tempsarray=NULL;
00770   cpl_polynomial**coeffs=NULL;
00771   float         *data=NULL;
00772   double        *rms_values=NULL;
00773   double         rms_array[32];
00774   int smooth=0;
00775   int smooth0=0;
00776   int smooth_order0=0;
00777   int smooth_size0=0;
00778   int center_bins = 0;
00779 
00780   int *bin_start=NULL;
00781   int *bin_end=NULL;
00782   int z1=0;
00783   int z2=0;
00784   int nbins=0;
00785 
00786   FILE          *dumpfile=NULL;
00787 
00788   int order[32];
00789   int ok[64];
00790   int nbad=0;
00791 
00792 
00793   /*
00794    *  Get parameters
00795    */
00796   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.spec_bin");
00797   spec_bin = cpl_parameter_get_int(p);
00798   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.min_flux");
00799   min_flux =  cpl_parameter_get_double(p);
00800   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.order");
00801   _order = cpl_parameter_get_int(p);
00802   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.sigma");
00803   sigma = cpl_parameter_get_double(p);
00804   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.llx");
00805   llx = cpl_parameter_get_int(p);
00806   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.lly");
00807   lly = cpl_parameter_get_int(p);
00808   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.urx");
00809   urx = cpl_parameter_get_int(p);
00810   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.ury");
00811   ury = cpl_parameter_get_int(p);
00812   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.illumcorr_sigma");
00813   il_sigma = cpl_parameter_get_double(p);
00814 
00815   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.smooth0");
00816   smooth0 = cpl_parameter_get_int (p);
00817   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.smooth0_order");
00818   smooth_order0 = cpl_parameter_get_int (p);
00819   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.smooth0_size");
00820   smooth_size0 = cpl_parameter_get_int (p);
00821 
00822   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.smooth1");
00823   smooth = cpl_parameter_get_bool (p);
00824   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.smooth1_order");
00825   smooth_order = cpl_parameter_get_int (p);
00826 
00827   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.iterations");
00828   iter = cpl_parameter_get_int (p);
00829 
00830   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.illumcorr.center_bins");
00831   center_bins = cpl_parameter_get_bool (p);
00832 
00833 /*   cpl_msg_set_level(CPL_MSG_DEBUG); */
00834 
00835   /*
00836    *  Allocate resources
00837    */
00838   sky       = cpl_imagelist_load(name_i, CPL_TYPE_FLOAT, 0);
00839   nplanes   = cpl_imagelist_get_size(sky);
00840 
00841   /*  Determine the start and end points of data within the 
00842    *  reference region  */     
00843   z1 = 0;
00844   z2=nplanes -1;
00845   while (z1<nplanes 
00846      && isnan(cpl_image_get_mean_window(cpl_imagelist_get(sky, z1),
00847                         llx, lly, urx, ury)))
00848     z1++;
00849   while (z2>=0
00850      && isnan(cpl_image_get_mean_window(cpl_imagelist_get(sky, z2),
00851                         llx, lly, urx, ury)))
00852     z2--;
00853   z1 += 2;
00854   z2 -= 2;
00855   if (z1>=nplanes || z2 <0 || z2<=z1) {
00856     sinfo_msg_error ("Start z = %d, end z = %d", z1, z2);
00857     cpl_imagelist_delete (sky);
00858     return (-1);
00859   }
00860   sinfo_msg ("Start z = %d, end z = %d", z1, z2);
00861 
00862   binnedsky = cpl_imagelist_new ();
00863   median    = (double*) cpl_calloc(nplanes/spec_bin, sizeof(double));
00864   pos       = (double*) cpl_calloc(nplanes/spec_bin, sizeof(double));
00865   temparray = (double*) cpl_calloc(64, sizeof(double));
00866   tempxarray= (double*) cpl_calloc(64, sizeof(double));
00867   tempsarray= (double*) cpl_calloc (nplanes/spec_bin, sizeof(double));
00868   plane_pos = (double*) cpl_calloc (nplanes/spec_bin, sizeof(double));
00869   plane_val = (double*) cpl_calloc (nplanes/spec_bin, sizeof(double));
00870   coeffs    = (cpl_polynomial**) cpl_calloc(32*(nplanes/spec_bin), 
00871                         sizeof(cpl_polynomial*));
00872   rms_values= (double*) cpl_calloc (32*(nplanes/spec_bin), sizeof (double));
00873   inter_pos = (double*) cpl_calloc (nplanes, sizeof(double));
00874   inter_val = (double*) cpl_calloc (nplanes, sizeof(double));
00875 
00876   model     = cpl_vector_new(64);
00877   xpos      = cpl_vector_new(64);
00878 
00879   for (i=0; i<64; i++)
00880     cpl_vector_set(xpos, i, (double)(i)-((double)urx-(double)llx)/2.0);
00881   for (i=0; i<nplanes; i++)
00882     inter_pos[i] = (double)i;
00883 
00884   /*
00885    *  This array could be given as input file for the recipe.
00886    *  Generally, 0th order fitting is sufficient (and of course
00887    *  more robust), but few slitlets might require 1st order.
00888    */
00889   for (i=0; i<32; i++)
00890     order[i] = _order;
00891 
00892 
00893   if (center_bins == 1) {
00894     sinfo_msg("Using centering on emission features\n");
00895     nbins = sinfo_illumcorr_create_bins (sky,llx, lly, urx, ury,
00896                      spec_bin, min_flux,
00897                      &bin_start, &bin_end,
00898                      z1, z2);
00899   }
00900   else {
00901     sinfo_msg("Using simple spectral binning - "
00902           "not centering on emission features\n");
00903     nbins = (z2-z1)/spec_bin;
00904     bin_start = (int*)cpl_calloc(nbins+1, sizeof(int));
00905     bin_end =  (int*)cpl_calloc(nbins+1, sizeof(int));
00906     for (i = 0; i<nbins; i++) {
00907       bin_start[i] = z1+i*spec_bin;
00908       bin_end[i]   = z1+(i+1)*spec_bin - 1;
00909     }
00910     if (bin_end[nbins-1]<z2-spec_bin/10) {
00911       bin_start[nbins] = bin_end[nbins-1]+1;
00912       bin_end[nbins] = z2;
00913       nbins++;
00914     }
00915   }
00916   
00917   /*
00918    *  - bin the cube in spectral direction
00919    *  - calculate the median (=reference value) in region 
00920    *    (llx,lly) - (urx,ury)
00921    *  - calculate the weighted position of the each spectral bin
00922    */
00923   sinfo_msg("Binning the cube and calculating statistics\n");
00924   for (i=0; i<nbins; i++) {
00925     temp_image = cpl_image_duplicate(cpl_imagelist_get(sky, bin_start[i]));
00926     median[i] = sinfo_image_get_median_window (temp_image, llx, lly, urx, ury);
00927     pos[i] = median[i] * (double)bin_start[i];
00928     cpl_imagelist_set (binnedsky, temp_image, i);
00929     for (j=bin_start[i]+1; j<bin_end[i]; j++) {
00930       temp_image2 = cpl_imagelist_get (sky, j);
00931       cpl_image_add (temp_image, temp_image2);
00932       temp = sinfo_image_get_median_window (temp_image2, llx, lly, urx, ury);
00933       median[i] = median[i] + temp;
00934       pos[i] = pos[i] + temp*(double)j;
00935     }
00936     temp2 =(double)(bin_end[i]-bin_start[i]+1);
00937     cpl_image_divide_scalar (temp_image, temp2);
00938     pos[i] = pos[i]/median[i];
00939     median[i] = median[i] / temp2;
00940     sinfo_msg_debug("median image=%g at %g",median[i], pos[i]); 
00941   }
00942   
00943   sinfo_msg("Fitting slitlets between x=%d - x=%d\n", llx, urx);
00944   sinfo_msg("Fitting order %d\n", _order); 
00945   for (k=0;k<nbins; k++) {
00946     if (median[k]>min_flux) {
00947       for (j=0; j<32; j++) {
00948     row=cpl_vector_new_from_image_row(cpl_imagelist_get(binnedsky,k),2*j+1);
00949     n = 0;
00950     for (i=llx; i<=urx; i++) {
00951       if (!isnan(cpl_vector_get(row, i))) {
00952         ok[i] = 1;
00953         temparray[n]  = cpl_vector_get(row, i);
00954         tempxarray[n] = cpl_vector_get(xpos, i);
00955         n++;
00956       }
00957       else
00958         ok[i] = 0;
00959     }
00960 
00961     /* The ends of cube are always filled with NaNs => n==0*/
00962     if (n>20) {
00963       tempvector = cpl_vector_wrap (n, temparray);
00964       tempvector2= cpl_vector_wrap (n, tempxarray);
00965       poly = cpl_polynomial_fit_1d_create (tempvector2, tempvector, 
00966                                                order[j], &mse);
00967       
00968       if (poly == NULL)
00969         sinfo_msg("Fitting failed (plane %d, row %d): %s",
00970                  k, j, (char* ) cpl_error_get_message());
00971       else {
00972         if (sigma>0 && iter>0) {
00973           for (kk = 0; kk<iter; kk++) {
00974         cpl_vector_fill_polynomial (model, poly, 0.0, 1.0);
00975         cpl_vector_subtract (model, row);
00976         
00977         /* Calculate stdev NaN-correctly */
00978         n = 0;
00979         for (i=llx; i<=urx; i++) 
00980           if (ok[i] == 1) 
00981             temparray[n++]  = cpl_vector_get(model, i);
00982         stddev = cpl_vector_get_stdev(tempvector);
00983         
00984         for (i=llx; i<=urx; i++) 
00985           if (ok[i] == 1) 
00986             if (fabs(cpl_vector_get(model, i))>(stddev*sigma))
00987               ok[i] = 0;
00988         
00989         
00990         n = 0;
00991         for (i=llx; i<=urx; i++) {
00992           if (ok[i] == 1) {
00993             temparray[n]  = cpl_vector_get(row, i);
00994             tempxarray[n] = cpl_vector_get(xpos, i);
00995             n++;
00996           }
00997         }
00998         cpl_polynomial_delete(poly);
00999         if (n>20) {
01000           cpl_vector_unwrap (tempvector);
01001           cpl_vector_unwrap (tempvector2);
01002           tempvector = cpl_vector_wrap (n, temparray);
01003           tempvector2= cpl_vector_wrap (n, tempxarray);
01004           stddev = cpl_vector_get_stdev(tempvector);
01005           
01006           poly = cpl_polynomial_fit_1d_create (tempvector2, 
01007                                                        tempvector, 
01008                                                        order[j], &mse);
01009           if (poly == NULL)
01010             break;
01011         }
01012         else {
01013           poly = NULL;
01014           break;
01015         }
01016 /*           printf ("%d %e ", n, stddev); */
01017           }
01018         }
01019 
01020         if (poly!=NULL) {
01021           coeffs[j*nbins+k] = poly;
01022           rms_values[j*nbins+k] = sqrt(mse);
01023         }
01024         else
01025           coeffs[j*nbins+k] = NULL;
01026       }
01027       cpl_vector_unwrap (tempvector);
01028       cpl_vector_unwrap (tempvector2);
01029     }
01030     cpl_vector_delete(row);
01031       }
01032     }
01033   }
01034 
01035   /*
01036    *   These should (probably) be saved in a fits file...
01037    */
01038   sinfo_msg("Writing dat out_illum.dat\n");
01039   dumpfile = fopen ("out_illum.dat","w");
01040   fprintf (dumpfile, "# slitlet, pos, median, rms, coeff0, coeff1...\n");
01041   for (slitlet = 0; slitlet<32; slitlet++)
01042     for (bin=0; bin<nbins; bin++) {
01043       poly = coeffs[slitlet*nbins+bin];
01044       if (poly != NULL) {
01045     fprintf (dumpfile, "%d %f %f %f ",slitlet, pos[bin],
01046          median[bin],
01047          rms_values[slitlet*nbins+bin]);
01048     for (i=0; i<(cpl_polynomial_get_degree(poly)+1); i++) {
01049       temp = cpl_polynomial_get_coeff (poly, &i);
01050       fprintf (dumpfile, "%f ", temp);
01051     }
01052     fprintf (dumpfile, "\n");
01053       }
01054     }
01055   fclose (dumpfile);
01056 
01057   /*
01058    *    Remove poor fits:
01059    *      - calculate the median rms of all fits
01060    *      - throw away the fits whose rms is il_sigma*median_rms
01061    */
01062   sinfo_msg("Removing poor fits - factor %f", il_sigma);
01063   n = 0;
01064   i = 0;
01065   nbad=0;
01066   sinfo_msg("max loop over bin =%d",nbins);
01067   for (bin=0; bin<nbins; bin++) {
01068     k = 0;
01069     for (slitlet=0; slitlet<32; slitlet++)
01070       if (coeffs[slitlet*nbins+bin] != NULL)
01071     rms_array[k++] = rms_values[slitlet*nbins+bin];
01072     if (k>0) {
01073       /* For some bizarre reason, cpl_tools_get_median_double returns 
01074        *  -1076245448.000000 (is that NaN?). On closer inspection,
01075        * it seems to have replaced one of the numbers in array with NaN...*/
01076       tempvector = cpl_vector_wrap (k, &rms_array[0]);
01077       temp = cpl_vector_get_median (tempvector);
01078       sinfo_msg("median temp=%g",temp);
01079       cpl_vector_unwrap (tempvector);
01080       for (slitlet=0; slitlet<32; slitlet++) 
01081     if (coeffs[slitlet*nbins+bin] != NULL) {
01082       i++;
01083       if (rms_values[slitlet*nbins+bin]>(il_sigma*temp)) {
01084         cpl_polynomial_delete(coeffs[slitlet*nbins+bin]);
01085         coeffs[slitlet*nbins+bin] = NULL;
01086         n++;
01087       }
01088     } else {
01089           nbad++;
01090     }
01091         
01092     }
01093   }
01094   sinfo_msg("Removed %d poor fits out of %d. Bad coeffs=%d", n,i,nbad);
01095 
01096   if(smooth0 == 1) {
01097     sinfo_msg("Smoothing zeroth terms (order %d)", smooth_order0);
01098     /*
01099      *  Since the new centering scheme will pro
01100      */ 
01101     for (slitlet = 0; slitlet<32; slitlet++) {
01102       k = 0;
01103       for (bin=0; bin<nbins; bin++) {
01104     if (coeffs[slitlet*nbins+bin] != NULL) {
01105       poly = coeffs[slitlet*nbins+bin];
01106       i = 0;
01107       temp = cpl_polynomial_get_coeff (poly, &i);
01108       plane_pos[k] = pos[bin];
01109       plane_val[k] = temp/median[bin];
01110       k++;
01111     }
01112       }
01113       if (k>0) {
01114     tempvector = cpl_vector_wrap (k, plane_pos);
01115     tempvector2= cpl_vector_wrap (k, plane_val);
01116     poly2 = cpl_polynomial_fit_1d_create (tempvector, tempvector2, 
01117                                               smooth_order0, &mse);
01118     cpl_vector_unwrap (tempvector);
01119     cpl_vector_unwrap (tempvector2);
01120     for (bin=0; bin<nbins; bin++) {
01121       if (coeffs[slitlet*nbins+bin] != NULL) {
01122         poly = coeffs[slitlet*nbins+bin];
01123         i = 0;
01124         temp2 = cpl_polynomial_eval_1d (poly2, pos[bin], NULL);
01125         cpl_polynomial_set_coeff (poly, &i, temp2*median[bin]);
01126       }
01127     }
01128     cpl_polynomial_delete(poly2); 
01129       }
01130       else 
01131     sinfo_msg_warning ("Not enough data points in slitlet %d", slitlet);
01132     }
01133   }
01134   else if (smooth0 == 2) {
01135     sinfo_msg("Smoothing zeroth terms (median filter size %d)", smooth_size0);
01136     smooth_size0 = smooth_size0/2;
01137     if (smooth_size0 <= 0) smooth_size0 = 1;
01138     for (slitlet = 0; slitlet<32; slitlet++) {
01139       k = 0;
01140       for (bin=0; bin<nbins; bin++) {
01141     if (coeffs[slitlet*nbins+bin] != NULL) {
01142       poly = coeffs[slitlet*nbins+bin];
01143       i = 0;
01144       temp = cpl_polynomial_get_coeff (poly, &i);
01145       //plane_pos[k] = pos[bin];
01146       plane_val[k] = temp/median[bin];
01147       k++;
01148     }
01149       }
01150       if (k>0) {
01151     tempvector = cpl_vector_wrap (k, plane_val);
01152     tempvector2= sinfo_juha_vector_filter_median_create (tempvector, 
01153                                                              smooth_size0);
01154     cpl_vector_unwrap (tempvector);
01155     kk = 0;
01156     for (bin=0; bin<nbins; bin++) {
01157       if (coeffs[slitlet*nbins+bin] != NULL) {
01158         poly = coeffs[slitlet*nbins+bin];
01159         i = 0;
01160         cpl_polynomial_set_coeff(poly, &i, cpl_vector_get(tempvector2, kk++)
01161                       *median[bin]);
01162       }
01163     }
01164     cpl_vector_delete (tempvector2);
01165       }
01166     }
01167   }
01168 
01169   if(smooth == 1) {
01170     sinfo_msg("Smoothing higher terms (with order %d)", smooth_order);
01171     for (slitlet = 0; slitlet<32; slitlet++) {
01172       if (order[slitlet]>0) {
01173     for (j=1; j<=order[slitlet]; j++) {
01174       k = 0;
01175       for (bin=0; bin<nbins; bin++) {
01176         if (coeffs[slitlet*nbins+bin] != NULL) {
01177           poly = coeffs[slitlet*nbins+bin];
01178           i = 0;
01179 /*           temp = cpl_polynomial_get_coeff (poly, &i); */
01180           temp2 = cpl_polynomial_get_coeff (poly, &j);
01181           plane_pos[k] = pos[bin];
01182           plane_val[k] = temp2/median[bin];
01183           k++;
01184         }
01185       }
01186       if (k>0) {
01187         tempvector = cpl_vector_wrap (k, plane_pos);
01188         tempvector2= cpl_vector_wrap (k, plane_val);
01189         poly2 = cpl_polynomial_fit_1d_create (tempvector, tempvector2, 
01190                                                   smooth_order, &mse);
01191         cpl_vector_unwrap (tempvector);
01192         cpl_vector_unwrap (tempvector2);
01193         for (bin=0; bin<nbins; bin++) {
01194           if (coeffs[slitlet*nbins+bin] != NULL) {
01195         poly = coeffs[slitlet*nbins+bin];
01196           i = 0;
01197           /*           temp = cpl_polynomial_get_coeff (poly, &i); */
01198           temp2 = cpl_polynomial_eval_1d (poly2, pos[bin], NULL);
01199           cpl_polynomial_set_coeff (poly, &j, temp2*median[bin]);
01200           }
01201         }
01202         cpl_polynomial_delete(poly2); 
01203       }
01204       else 
01205         sinfo_msg_warning ("Not enough data points in slitlet %d\n", 
01206                                slitlet);
01207     }
01208       }
01209     }
01210   }
01211 
01212   sinfo_msg("Creating cube for illumination correction\n");
01213   result = cpl_imagelist_new ();
01214   for (i=0; i<nplanes; i++) {
01215     temp_image = cpl_image_new (64, 64, CPL_TYPE_FLOAT);
01216     cpl_imagelist_set (result, temp_image, i);
01217   }
01218     
01219   sinfo_msg("nplanes=%d spec_bin=%d",nplanes,spec_bin);
01220   if ( nbins>5) {
01221     sinfo_msg("Interpolating\n");
01222     for (slitlet = 0; slitlet<32; slitlet++) {
01223       for (i=0; i<64; i++) {
01224     k = 0;
01225     for (bin=0; bin<nbins; bin++) {
01226       if (coeffs[slitlet*nbins+bin] != NULL) {
01227         plane_pos[k] = pos[bin];
01228         plane_val[k] = cpl_polynomial_eval_1d(coeffs[slitlet*nbins+bin], 
01229                           cpl_vector_get(xpos, i),NULL)/
01230                                                   median[bin];
01231         k++;
01232       }
01233     }
01234         
01235     if (k>3) {
01236       sinfo_juha_function1d_natural_spline (plane_pos, plane_val, k,
01237                          &inter_pos[(int)plane_pos[0]],
01238                          &inter_val[(int)plane_pos[0]],
01239                          (int)(plane_pos[k-1]-plane_pos[0]));
01240       for (j=0; j<=(int)plane_pos[0]; j++)
01241         inter_val[j] = inter_val[(int)plane_pos[0]+1];
01242       for (j=(int)plane_pos[k-1]-1; j<nplanes; j++)
01243         inter_val[j] = inter_val[(int)plane_pos[k-1]-2];
01244       for (k=0; k<nplanes; k++) {
01245         data = cpl_image_get_data_float(cpl_imagelist_get(result, k));
01246         data[i + (2*slitlet)*64] = inter_val[k];
01247         data[i + (2*slitlet+1)*64] = inter_val[k];
01248             /*sinfo_msg("inter_val=%g",inter_val[k]);*/
01249       }
01250     }
01251     else
01252     sinfo_msg_warning ("Too few points %d\n", slitlet);
01253       }
01254     }
01255   }
01256   else if (nbins==1) {
01257     sinfo_msg("Filling the illumination cube\n");
01258     for (slitlet = 0; slitlet<32; slitlet++) {
01259       for (i=0; i<64; i++) {
01260     if (coeffs[slitlet] != NULL) {
01261       temp = cpl_polynomial_eval_1d(coeffs[slitlet], 
01262                     cpl_vector_get(xpos, i),NULL)/median[0];
01263       for (k=0; k<nplanes; k++) {
01264         data = cpl_image_get_data_float(cpl_imagelist_get(result, k));
01265         data[i + (2*slitlet)*64] = temp;
01266         data[i + (2*slitlet+1)*64] = temp;
01267             sinfo_msg("temp=%g",temp);
01268       }
01269     }
01270       }
01271     }
01272   } else {
01273 
01274   }
01275 
01276 
01277   sinfo_msg("Writing ima out_illum.fits\n");
01278 /*   pl = cpl_propertylist_load (name_i, 0); */
01279 /*   if (sinfo_propertylist_has(pl, KEY_NAME_PRO_CATG)) */
01280 /*     cpl_propertylist_set_string (pl, KEY_NAME_PRO_CATG, PRO_ILL_COR); */
01281 /*   else */
01282 /*     cpl_propertylist_append_string (pl, KEY_NAME_PRO_CATG, PRO_ILL_COR); */
01283 
01284 /*  cpl_imagelist_save(result, "out_illum.fits", CPL_BPP_IEEE_FLOAT, pl, 0); */
01285 
01286   sinfo_pro_save_ims(result,sof,sof,"out_illum.fits", 
01287               PRO_ILL_COR,NULL,plugin_id, cpl_cfg); 
01288 
01289   /*
01290    *   These should (probably) be saved in a fits file...
01291    */
01292   sinfo_msg("Writing dat out_illum2.dat\n");
01293   dumpfile = fopen ("out_illum2.dat","w");
01294   fprintf (dumpfile, "# slitlet, pos, median, rms, coeff0, coeff1...\n");
01295   for (slitlet = 0; slitlet<32; slitlet++)
01296     for (bin=0; bin<nbins; bin++) {
01297       poly = coeffs[slitlet*nbins+bin];
01298       if (poly != NULL) {
01299     fprintf (dumpfile, "%d %f %f %f ",slitlet, pos[bin],
01300          median[bin],
01301          rms_values[slitlet*nbins+bin]);
01302     for (i=0; i<(cpl_polynomial_get_degree(poly)+1); i++) {
01303       temp = cpl_polynomial_get_coeff (poly, &i);
01304       fprintf (dumpfile, "%f ", temp);
01305     }
01306     fprintf (dumpfile, "\n");
01307       }
01308     }
01309   fclose (dumpfile);
01310 
01311   /*
01312    *  Clean up...
01313    */
01314   for (i = 0; i<32*nbins; i++)
01315     if (coeffs[i] != NULL)
01316       cpl_polynomial_delete(coeffs[i]);
01317   cpl_imagelist_delete (sky);
01318   cpl_imagelist_delete (binnedsky);
01319   cpl_imagelist_delete (result);
01320   cpl_free (pos);
01321   cpl_free (median);
01322   cpl_free (temparray);
01323   cpl_free (tempxarray);
01324   cpl_free (tempsarray);
01325   cpl_free (coeffs);
01326   cpl_free (inter_pos);
01327   cpl_free (inter_val);
01328   cpl_free (plane_pos);
01329   cpl_free (plane_val);
01330   cpl_free (rms_values);
01331   cpl_vector_delete (xpos);
01332   cpl_vector_delete (model);
01333 
01334   cpl_free (bin_start);
01335   cpl_free (bin_end);
01336 
01337   return (1);
01338 }
01339 
01340 /*
01341  *  sinfo_illumcorr_create_bins:
01342  *    - searches for the sky emission lines
01343  *    - increases the size of the bin to include two or more emission
01344  *      lines if they are too close to each other
01345  *    - fills the space between emission lines with bins if
01346  *      thermal background has enough flux
01347  *    - copies the start and end points of bins to two arrays
01348  *      (returned in **start and **end)
01349  *
01350  *  Returns: the number bins created
01351  *
01352  *  The arrays start and end must be deallocated with cpl_free()
01353  */
01354 static int
01355 sinfo_illumcorr_create_bins (cpl_imagelist *sky, 
01356                  int llx, int lly, int urx, int ury,
01357                  int spec_bin, 
01358                  double min_flux,
01359                  int ** start,
01360                  int ** end,
01361                  int z1, int z2)
01362 {
01363   int temp_i=0;
01364   double testarray3[15];
01365   double temp_double=0;
01366   int  i=0, j=0, k=0,kk=0,nplanes=0; 
01367 
01368   int norig = 0, nmerged = 0, ncont = 0, nline=0;
01369 
01370   int *pos=NULL;
01371   int *x1=NULL;
01372   int *x2=NULL;
01373   int *x1b=NULL;
01374   int *x2b=NULL;
01375   int *s1=NULL;
01376   int *s2=NULL;
01377   double *flux=NULL;
01378   double *spec=NULL;
01379   double  *spec_cont=NULL;
01380   double *spec_line=NULL;
01381 
01382 
01383   cpl_image     *temp_image=NULL;
01384 
01385   nplanes   = cpl_imagelist_get_size(sky);
01386 
01387   spec = (double*) cpl_calloc(nplanes, sizeof(double));
01388   spec_line = (double*) cpl_calloc(nplanes, sizeof(double));
01389   spec_cont = (double*) cpl_calloc(nplanes, sizeof(double));
01390 
01391   /*  there should be no way of actually needing this large arrays*/
01392   pos = (int*) cpl_calloc(nplanes, sizeof(int));
01393   flux = (double*) cpl_calloc(nplanes, sizeof(double));
01394   x1 = (int*) cpl_calloc(nplanes, sizeof(int));
01395   x2 = (int*) cpl_calloc(nplanes, sizeof(int));
01396   x1b = (int*) cpl_calloc(nplanes, sizeof(int));
01397   x2b = (int*) cpl_calloc(nplanes, sizeof(int));
01398 
01399   for (i=z1; i<=z2; i++) {
01400     temp_image =  cpl_imagelist_get(sky, i);
01401     spec[i] = sinfo_image_get_median_window (temp_image, llx, lly, urx, ury);
01402   }
01403   for (i=z1+7; i<=z2-7; i++) {
01404     k = 0;
01405     for (j=-7; j<=7; j++)
01406       if (!isnan(spec[i+j]))
01407     testarray3[k++] = spec[i+j];
01408     if (k>0) {
01409       sinfo_tools_sort_double (&testarray3[0], k);
01410       spec_cont[i] =  testarray3[1];
01411     }
01412     else
01413       spec_cont[i] =  0./0.;
01414   }
01415 
01416   sinfo_msg_debug("Calculating pure line flux at pos: "
01417                   "original, continuum, line");
01418   for (i=z1; i<=z2; i++) {
01419     spec_line[i] = spec[i] - spec_cont[i];
01420     sinfo_msg_debug("Flux at %i = %g %g %g",
01421                      i,spec[i],spec_cont[i], spec_line[i]);   
01422   }
01423 
01424 
01425   /*
01426    *  Search for peaks
01427    */  
01428   sinfo_msg ("Searching for peaks");
01429   temp_double = -10000.0;
01430   i = z1+2; 
01431   while (i<=z2-2) {
01432     if (!isnan (spec_line[i])) {
01433       if (temp_double<spec_line[i]) {
01434         temp_i = i;
01435         temp_double = spec_line[i];
01436       }
01437       else {
01438         /*  Found a peak! */ 
01439         if (temp_i == i-1 && spec_line[temp_i]>min_flux) {
01440       k = 0;
01441       for (j=-spec_bin/2; j<=spec_bin/2; j++) 
01442         if (j+i>=0 && i+j<nplanes && isnan(spec[i+j])) {
01443           k = 1;
01444           break;
01445         }
01446       if (k==0) {
01447         pos[norig] = temp_i; // - spec_bin/2;
01448         flux[norig]   = temp_double;
01449         x1[norig] = temp_i;
01450         x2[norig] = temp_i;
01451         temp_double = -10000.0; 
01452         while (spec_line[i]<spec_line[i-1])
01453           i++;
01454         i--;
01455         norig++;
01456       }
01457         }
01458       }
01459     }      
01460     i++;
01461   }
01462 
01463   /*
01464    *   Merge the features which are too close to each other
01465    */
01466   sinfo_msg ("Merging emission features too close to each other");
01467   i = 0;
01468   while (i<norig) {
01469     if (flux[i] > 0.0) {
01470       j = i+1;
01471       while (j<norig 
01472          && (x1[j]-x2[i]) <=spec_bin 
01473          && flux[j]>0.0) {
01474     flux[j] = -100.0;
01475     x2[i] = x1[j];
01476     j++;
01477     nmerged++;
01478       }
01479     }
01480     i++;
01481   }
01482 
01483   nline = norig - nmerged;
01484 
01485   j = 0;
01486   for (i=0; i<norig; i++)
01487     if (flux[i]>0.0) {
01488       x1b[j] = x1[i] - spec_bin/2;
01489       x2b[j] = x2[i] + spec_bin/2;
01490       j++;
01491       /* sinfo_msg ("Bin start: %i end %i", x1[i], x2[i]); */
01492     }
01493 
01494   x1b[j] = nplanes+1;
01495 
01496   /*
01497    *  Check whether there is enough continuum (thermal background)
01498    *  for binning
01499    */
01500   j=0;
01501   i=z1;
01502   while (i<=z2) {
01503     if (!isnan (spec[i])) {
01504       if (x1b[j]-i < spec_bin) {
01505     i = x2b[j]+1;
01506     j++;
01507       }
01508       else {
01509     kk = 0;
01510     for (k=0; k<spec_bin; k++) 
01511       if (spec[i+k]>min_flux)
01512         kk++;
01513     if (kk==spec_bin) {
01514       x1[ncont] = i;
01515       x2[ncont] = i+spec_bin-1;
01516       ncont++;
01517       i = i+spec_bin;
01518     }
01519     else
01520       i++;
01521       }
01522     }
01523     else 
01524       i++;
01525   }
01526 
01527   sinfo_msg ("Number of bins centered on emission features:");
01528   sinfo_msg ("  %i - %i (merged) = %i", norig, nmerged, nline);
01529   sinfo_msg ("  %i continuum bins", ncont);
01530 
01531   s1 = (int*)cpl_calloc(norig-nmerged+ncont, sizeof(int));
01532   s2 = (int*)cpl_calloc(norig-nmerged+ncont, sizeof(int));
01533 
01534 
01535   /* 
01536    *  Merge arrays sorted 
01537    */
01538   i=0;
01539   j=0;
01540   k=0;
01541   while (k<norig-nmerged+ncont) {
01542     if (i<norig && j<ncont && x1b[i]<x1[j]) {
01543       s1[k] = x1b[i];
01544       s2[k] = x2b[i];
01545       k++;
01546       i++;
01547     }
01548     else if (i<norig && j<ncont && x1b[i]>x1[j]) {
01549       s1[k] = x1[j];
01550       s2[k] = x2[j];
01551       k++;
01552       j++;
01553     }
01554     else if (i == norig) {
01555       s1[k] = x1[j];
01556       s2[k] = x2[j];
01557       k++;
01558       j++;
01559     }
01560     else if (j == ncont) {
01561       s1[k] = x1b[i];
01562       s2[k] = x2b[i];
01563       k++;
01564       i++;
01565     }
01566     else {
01567       /* Should never happen */
01568       sinfo_msg_warning("Something went wrong when combining "
01569                         "the bins %i and %i", i,j);
01570       break;
01571     }
01572   }
01573 
01574   for (i=0; i<nline+ncont; i++)
01575     sinfo_msg_debug ("Bin start: %i end %i", s1[i], s2[i]);
01576 
01577   *start = s1;
01578   *end   = s2;
01579 
01580   cpl_free (pos);
01581   cpl_free (x1);
01582   cpl_free (x2);
01583   cpl_free (x1b);
01584   cpl_free (x2b);
01585   cpl_free (flux);
01586   cpl_free (spec);
01587   cpl_free (spec_line);
01588   cpl_free (spec_cont);
01589 
01590   return (nline+ncont);
01591 }
01592 
01593 
01594 /*-------------------------------------------------------------------------*/
01621 /*--------------------------------------------------------------------------*/
01622 
01623 static int
01624 sinfo_juha_function1d_natural_spline(
01625     double  *      x,
01626     double  *      y,
01627     int            len,
01628     double  *      splX,
01629     double  *      splY,
01630     int            splLen
01631 )
01632 {
01633   int                         end;
01634   int                         loc, found;
01635   register int        i, j, n;
01636   double              *       h;      /* vector of deltas in x */
01637   double              *       alpha;
01638   double              *       l,
01639     *       mu,
01640     *       z,
01641     *       a,
01642     *       b,
01643     *       c,
01644     *       d,
01645     v;
01646 
01647   end = len - 1;
01648   
01649   a = cpl_malloc(sizeof(double) * splLen * 9) ;
01650   b = a + len;
01651   c = b + len;
01652   d = c + len;
01653   h = d + len;
01654   l = h + len;
01655   z = l + len;
01656   mu = z + len;
01657   alpha = mu + len;
01658   
01659   for (i = 0; i < len; i++) {
01660     a[i] = (double)y[i];
01661   }
01662   
01663   /* Calculate vector of differences */
01664   for (i = 0; i < end; i++) {
01665     h[i] = (double)x[i + 1] - (double)x[i];
01666     if (h[i] < 0.0) {
01667       cpl_free(a) ;
01668       return -1;
01669     }
01670   }
01671   
01672   /* Calculate alpha vector */
01673   for (n = 0, i = 1; i < end; i++, n++) {
01674     /* n = i - 1 */
01675     alpha[i] = 3.0 * ((a[i+1] / h[i]) - (a[i] / h[n]) - (a[i] / h[i]) +
01676               (a[n] / h[n]));
01677   }
01678   
01679   /* Vectors to solve the tridiagonal matrix */
01680   l[0] = l[end] = 1.0;
01681   mu[0] = mu[end] = 0.0;
01682   z[0] = z[end] = 0.0;
01683   c[0] = c[end] = 0.0;
01684   
01685   /* Calculate the intermediate results */
01686   for (n = 0, i = 1; i < end; i++, n++) {
01687     /* n = i-1 */
01688     l[i] = 2 * (h[i] + h[n]) - h[n] * mu[n];
01689     mu[i] = h[i] / l[i];
01690     z[i] = (alpha[i] - h[n] * z[n]) / l[i];
01691   }
01692   for (n = end, j = end - 1; j >= 0; j--, n--) {
01693     /* n = j + 1 */
01694     c[j] = z[j] - mu[j] * c[n];
01695     b[j] = (a[n] - a[j]) / h[j] - h[j] * (c[n] + 2.0 * c[j]) / 3.0;
01696     d[j] = (c[n] - c[j]) / (3.0 * h[j]);
01697   }
01698   
01699   /* Now calculate the new values */
01700   for (j = 0; j < splLen; j++) {
01701     v = (double)splX[j];
01702     splY[j] = (float)0;
01703     
01704     /* Is it outside the interval? */
01705     if ((v < (double)x[0]) || (v > (double)x[end])) {
01706       continue;
01707     }
01708     /* Search for the interval containing v in the x vector */
01709     loc = sinfo_function1d_search_value(x, len, (double)v, &found);
01710     if (found) {
01711       splY[j] = y[loc];
01712     } else {
01713       loc--;
01714       v -= (double)x[loc];
01715       splY[j] = (float)( a[loc] + v * (b[loc] + v * (c[loc] + v * d[loc])));
01716     }
01717   }
01718   cpl_free(a) ;
01719   return 0;
01720 }
01721 
01722 /*-------------------------------------------------------------------------*/
01738 /*--------------------------------------------------------------------------*/
01739 
01740 static int
01741 sinfo_function1d_search_value(
01742     double  *       x,
01743     int             len,
01744     double          key,
01745     int     *       foundPtr
01746 )
01747 {
01748     int high,
01749                 low,
01750                 middle;
01751 
01752     low  = 0;
01753     high = len - 1;
01754 
01755     while (high >= low) {
01756       middle = (high + low) / 2;
01757       if (key > x[middle]) {
01758     low = middle + 1;
01759       } else if (key < x[middle]) {
01760     high = middle - 1;
01761       } else {
01762     *foundPtr = 1;
01763     return (middle);
01764       }
01765     }
01766     *foundPtr = 0;
01767     return (low);
01768 }
01769 
01770 
01771 /*
01772 cpl_vector * sinfo_vector_filter_median_create(
01773         const cpl_vector * v, 
01774         int                hw)
01775 {
01776     cpl_vector * filtered;
01777     double     * row;
01778     int          i, j, k, size;
01779     double temp;
01780     
01781     size = cpl_vector_get_size(v);
01782     filtered = cpl_vector_new(size);
01783 
01784     row = cpl_malloc((2*hw+1) * sizeof(double));
01785     for (i=0; i<size; i++) {
01786       k = 0;
01787       for (j=-hw; j<=hw; j++) 
01788     if ( (i+j) >= 0 && (i+j) < size) {
01789       temp = cpl_vector_get (v, i+j);
01790       row[k] = temp;
01791       k++;
01792     }
01793       cpl_tools_sort_double (row, k);
01794       if (k%2 == 1)
01795     temp = row[k/2];
01796       else
01797     temp = row[k/2-1];
01798       cpl_vector_set (filtered, i, temp);
01799     }
01800     cpl_free(row);
01801     return filtered;
01802 }
01803 */
01804 
01805 static cpl_vector * 
01806 sinfo_juha_vector_filter_median_create(
01807         const cpl_vector * v, 
01808         int                hw)
01809 {
01810     cpl_vector * filtered=NULL;
01811     double     * row=NULL;
01812     int          i, j, k,  size;
01813     double temp;
01814     
01815     size = cpl_vector_get_size(v);
01816     filtered = cpl_vector_new(size);
01817 
01818     row = cpl_malloc((2*hw+1) * sizeof(double));
01819     for (i=0; i<size; i++) {
01820       k = 0;
01821       for (j=-hw; j<=hw; j++) 
01822     if ( (i+j) >= 0 && (i+j) < size) {
01823       temp = cpl_vector_get (v, i+j);
01824       row[k] = temp;
01825       k++;
01826     }
01827       sinfo_tools_sort_double (row, k);
01828 
01829       if (k%2 == 1)
01830     temp = row[k/2];
01831       else
01832     temp = row[k/2-1];
01833       cpl_vector_set (filtered, i, temp);
01834     }
01835     cpl_free(row);
01836     return filtered;
01837 }
01838 
01839 #define CPL_PIX_STACK_SIZE 50
01840 /*---------------------------------------------------------------------------*/
01851 /*---------------------------------------------------------------------------*/
01852 static cpl_error_code sinfo_tools_sort_double(
01853         double  *   pix_arr,
01854         int         n)
01855 {
01856     int         i, ir, j, k, l;
01857     int     *   i_stack ;
01858     int         j_stack ;
01859     double      a ;
01860     
01861     /* Check entries */
01862     cpl_ensure(pix_arr, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT) ;
01863 
01864     ir = n ;
01865     l = 1 ;
01866     j_stack = 0 ;
01867     i_stack = malloc(CPL_PIX_STACK_SIZE * sizeof(double)) ;
01868     for (;;) {
01869         if (ir-l < 7) {
01870             for (j=l+1 ; j<=ir ; j++) {
01871                 a = pix_arr[j-1];
01872                 for (i=j-1 ; i>=1 ; i--) {
01873                     if (pix_arr[i-1] <= a) break;
01874                     pix_arr[i] = pix_arr[i-1];
01875                 }
01876                 pix_arr[i] = a;
01877             }
01878             if (j_stack == 0) break;
01879             ir = i_stack[j_stack-- -1];
01880             l  = i_stack[j_stack-- -1];
01881         } else {
01882             k = (l+ir) >> 1;
01883             SINFO_DOUBLE_SWAP(pix_arr[k-1], pix_arr[l])
01884             if (pix_arr[l] > pix_arr[ir-1]) {
01885                 SINFO_DOUBLE_SWAP(pix_arr[l], pix_arr[ir-1])
01886             }
01887             if (pix_arr[l-1] > pix_arr[ir-1]) {
01888                 SINFO_DOUBLE_SWAP(pix_arr[l-1], pix_arr[ir-1])
01889             }
01890             if (pix_arr[l] > pix_arr[l-1]) {
01891                 SINFO_DOUBLE_SWAP(pix_arr[l], pix_arr[l-1])
01892             }
01893             i = l+1;
01894             j = ir;
01895             a = pix_arr[l-1];
01896             for (;;) {
01897                 do i++; while (pix_arr[i-1] < a);
01898                 do j--; while (pix_arr[j-1] > a);
01899                 if (j < i) break;
01900                 SINFO_DOUBLE_SWAP(pix_arr[i-1], pix_arr[j-1]);
01901             } 
01902             pix_arr[l-1] = pix_arr[j-1];
01903             pix_arr[j-1] = a; 
01904             j_stack += 2; 
01905             if (j_stack > CPL_PIX_STACK_SIZE) {
01906                 /* Should never reach here */
01907                 free(i_stack);
01908                 return CPL_ERROR_ILLEGAL_INPUT ; 
01909             } 
01910             if (ir-i+1 >= j-l) {
01911                 i_stack[j_stack-1] = ir;
01912                 i_stack[j_stack-2] = i;
01913                 ir = j-1;
01914             } else {
01915                 i_stack[j_stack-1] = j-1;
01916                 i_stack[j_stack-2] = l;
01917                 l = i;
01918             }
01919         }
01920     }
01921     free(i_stack) ;
01922     return CPL_ERROR_NONE ;
01923 }
01924 
01925 static cpl_vector * 
01926 sinfo_vector_filter_median_create(
01927         const cpl_vector * v, 
01928         int                hw)
01929 {
01930     cpl_vector * filtered;
01931     cpl_vector * row;
01932     int          i, j, k, size;
01933     double temp;
01934     
01935     /* Create the filtered vector */
01936     size = cpl_vector_get_size(v);
01937     filtered = cpl_vector_new(size);
01938 
01939     /* median filter on all central items */
01940     row = cpl_vector_new((2*hw+1));
01941     for (i=0; i<size; i++) {
01942       k = 0;
01943       for (j=-hw; j<=hw; j++) 
01944     if ( (i+j) >= 0 && (i+j) < size) {
01945       temp = cpl_vector_get (v, i+j);
01946       cpl_vector_set(row,k,temp);
01947       k++;
01948     }
01949       /*  this returns ~2e8 when all the values are 1.0....*/
01950 /*       temp = cpl_tools_get_median_double(row, k); */
01951       cpl_vector_sort(row, +1);
01952       if (k%2 == 1) {
01953     temp = cpl_vector_get(row,k/2);
01954       }
01955       else {
01956     temp = cpl_vector_get(row,k/2-1);
01957       }
01958 
01959       sinfo_msg("value = %g ", temp);
01960       cpl_vector_set (filtered, i, temp);
01961     }
01962     cpl_vector_delete(row);
01963     return filtered;
01964 }
01965 
01966 /*
01967  *  A NaN safe version of cpl_image_get_median_window
01968  */
01969 static double 
01970 sinfo_image_get_median_window  (const cpl_image *image, 
01971                        int llx, int lly, int urx, int ury)
01972 {
01973   cpl_image *window;
01974   float *data;
01975   double *array, median;
01976   int size, i,j;
01977 
01978   window = cpl_image_extract (image, llx, lly, urx, ury);
01979   size = (urx-llx+1)*(ury-lly+1);
01980   data = cpl_image_get_data_float(window);
01981 
01982   array = (double*)cpl_calloc ( size, sizeof(double));
01983   j = 0;
01984   for (i=0; i<size; i++)
01985     if (!isnan(data[i]))
01986       array[j++] = data[i];
01987   
01988   if (j>0)
01989     sinfo_tools_sort_double (array, j);
01990   
01991   if (j == 0 || 2*j<size)
01992     median = 0./0.;
01993   else if (j%2 == 1) 
01994     median = array[j/2];
01995   else 
01996     median = array[j/2-1];
01997 
01998   cpl_image_delete (window);
01999   cpl_free (array);
02000   
02001   return (median);
02002 }

Generated on 3 Mar 2013 for SINFONI Pipeline Reference Manual by  doxygen 1.6.1