/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
 */
/*----------------------------------------------------------------------------

   File name    :       sinfo_new_stdstar.c
   Author       :    J. Schreiber
   Created on   :    December 3, 2003
   Description  :    this routine doess the optimal extraction of a spectrum
                        of an already reduced data cube of a standard star
                        observation. Additionally, a conversion factor from
                        mag to counts/sec can be determined if the magnitude
                        of the standard star is known.
                        This is done for a number of jittered data cubes and
                        the results are averaged by rejecting the extreme
                        values

 ---------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*----------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <math.h>

//Used only for sinfo_propertylist_has
#include <irplib_stdstar.h>
#include <sinfo_cpl_size.h>
#include "irplib_utils.h"
#include "sinfo_dfs.h"
#include "sinfo_tpl_utils.h"

#include "sinfo_new_stdstar.h"
#include "sinfo_standstar_ini_by_cpl.h"
#include "sinfo_pro_save.h"
#include "sinfo_pfits.h"
#include "sinfo_utilities_scired.h"
#include "sinfo_spectrum_ops.h"
#include "sinfo_hidden.h"
#include "sinfo_functions.h"
#include "sinfo_utl_efficiency.h"
#include "sinfo_error.h"
#include "sinfo_utils_wrappers.h"
/*----------------------------------------------------------------------------
                                Defines
 ---------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
                             Function Definitions
 ---------------------------------------------------------------------------*/
/* temporally commented out as not yet used
static int
sinfo_compute_efficiency(cpl_frameset* sof,
                              const char* name,
			      standstar_config ** cfg,
			      cpl_imagelist  * cube,
			 cpl_table** tbl_spectrum);

*/

/**@{*/
/**
 * @addtogroup sinfo_rec_jitter telluric standard data reduction
 *
 * TBD
 */

/*----------------------------------------------------------------------------
   Function     :       sinfo_stdstar()
   In           :       ini_file: file name of according .ini file
   Out          :       integer (0 if it worked, -1 if it doesn't)
   Job          :     this routine carries through the data cube creation of an
                        object science observation using object-sky nodding
                        and jittering. This script expects jittered frames that
                were already sky-subtracted
                        averaged, flatfielded, spectral tilt corrected and
            interleaved if necessary
 ---------------------------------------------------------------------------*/
int
sinfo_new_stdstar(const char* plugin_id,
                  cpl_parameterlist* config,
                  cpl_frameset* sof,cpl_frameset* ref_set)
{

  cpl_errorstate clean_state = cpl_errorstate_get();
    standstar_config * cfg=NULL ;
    cpl_imagelist  * cube=NULL ;

    cpl_imagelist  * list_object=NULL ;
    cpl_image ** spectrum=NULL ;
    cpl_image * img_spct=NULL ;



    cpl_frameset* raw=NULL;
    cpl_frame* frame=NULL;
    cpl_image* std_med_ima=NULL;
    cpl_image* std_med_dup=NULL;

    cpl_table* qclog_tbl=NULL;
    cpl_table* tbl_spectrum=NULL;
    cpl_propertylist* plist=NULL;
    //char band[FILE_NAME_SZ];

    char * name=NULL ;
    int fra=0;
    float exptime=0 ;
    double convfactor=0;
    double cleanfactor=0;
    float* factor=NULL;

    char std_med_filename[MAX_NAME_SIZE];
    char std_cub_filename[MAX_NAME_SIZE];

    double max_ima_cx=0;
    double max_ima_cy=0;
    cpl_size max_ima_x=0;
    cpl_size max_ima_y=0;
    double norm=0;
    double xcen=0;
    double ycen=0;
    double sig_x=0;
    double sig_y=0;
    double fwhm_x=0;
    double fwhm_y=0;
    double disp=0;
    double dispersion=0;
    int i=0;
    int wllx=0;
    int wlly=0;
    int wurx=0;
    int wury=0;
    int psf_sz=40;
    int qc_info=0;
    int ima_szx=0;
    int ima_szy=0;
    int check1=0;
    int check2=0;
    int check3=0;
    int check4=0;
    double xshift=0;
    double yshift=0;

    float cenpix = 0;
    float cenLambda = 0;

    int no=0;
    double lo_cut=0.;
    double hi_cut=0.;

    const char* stdstars=NULL;
    const char* sed=NULL;
    cpl_frame* frm_sci=NULL;
    cpl_frame* frm_atmext=NULL;
    cpl_frame* frm_std_cat=NULL;
    cpl_table* tot_eff=NULL;
    double fpar[7];
    double dpar[7];
    int mpar[7];
    int do_compute_eff=0;
    cpl_parameter* p=NULL;


    //For new way to compute efficiency
    //char band[80];
    //const char  *   seds_file=NULL;
    //const char  *   filter=NULL;
    //cpl_table* tbl_eff=NULL;
    /*
       parse the file names and parameters to the cube_config
       data structure cfg
     */

    /* sinfo_msg("Parse cpl input"); */
     check_nomsg(raw=cpl_frameset_new());

    cknull(cfg=sinfo_parse_cpl_input_standstar(config,sof,&raw),
       "could not parse cpl input!") ;

 
    cknull_nomsg(p = cpl_parameterlist_find(config,
				     "sinfoni.std_star.compute_eff"));
 
    check_nomsg(do_compute_eff = cpl_parameter_get_bool(p));
     cknull(list_object = cpl_imagelist_new (),
       "could not allocate memory");


    sed = sinfo_extract_filename(sof, SINFO_CALIB_SED) ;
    stdstars = sinfo_extract_filename(sof, SINFO_CALIB_STDSTARS) ;


    if (cfg->convInd == 1) {
      factor = sinfo_new_floatarray(cfg->nframes);
    }

    if(NULL != cpl_frameset_find(sof,PRO_COADD_STD)) {
      frame = cpl_frameset_find(sof,PRO_COADD_STD);
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
    } else if(NULL != cpl_frameset_find(sof,PRO_COADD_PSF)) {
      frame = cpl_frameset_find(sof,PRO_COADD_PSF);
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
    } else if(NULL != cpl_frameset_find(sof,PRO_COADD_OBJ)) {
      frame = cpl_frameset_find(sof,PRO_COADD_OBJ);
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
    } else if(NULL != cpl_frameset_find(sof,PRO_COADD_PUPIL)) {
      frame = cpl_frameset_find(sof,PRO_COADD_PUPIL);
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
    } else {
      sinfo_msg_error("Frame %s, %s, %s or %s not found! Exit!",
                       PRO_COADD_STD,PRO_COADD_PSF,
                       PRO_COADD_OBJ,PRO_COADD_PUPIL );
      goto cleanup;
    }


    cknull(plist = cpl_propertylist_load(std_cub_filename, 0),
      "getting header from reference ima frame %s",std_cub_filename);

    cenpix = sinfo_pfits_get_crpix3(plist);
    cenLambda = sinfo_pfits_get_crval3(plist);
    dispersion = sinfo_pfits_get_cdelt3(plist);


    if (sinfo_propertylist_has(plist, KEY_NAME_CDELT3)) {
      disp=cpl_propertylist_get_double(plist, KEY_NAME_CDELT3);
    } else {
      sinfo_msg_warning("Keyword %s not found.",KEY_NAME_CDELT3);
    }


    sinfo_free_propertylist(&plist) ;

    /* we find automatiocally extraction parameters */


    if(NULL != cpl_frameset_find(sof,PRO_MED_COADD_STD)) {
      frame = cpl_frameset_find(sof,PRO_MED_COADD_STD);
      strcpy(std_med_filename,cpl_frame_get_filename(frame));
      check_nomsg(std_med_ima=cpl_image_load(std_med_filename,
                                             CPL_TYPE_FLOAT,0,0));
    } else if(NULL != cpl_frameset_find(sof,PRO_OBS_STD)) {
      check_nomsg(frame = cpl_frameset_find(sof,PRO_OBS_STD));
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
      check_nomsg(cube = cpl_imagelist_load(std_cub_filename,
                                             CPL_TYPE_FLOAT,0));
      strcpy(std_med_filename,STDSTAR_OUT_MED_CUBE);
      check_nomsg(std_med_ima=cpl_imagelist_collapse_median_create(cube));
      sinfo_free_imagelist(&cube);

      ck0(sinfo_pro_save_ima(std_med_ima,ref_set,sof,STDSTAR_OUT_MED_CUBE,
                 PRO_MED_OBS_PSF,NULL,plugin_id,config),
      "Error saving image %s tag %s",STDSTAR_OUT_MED_CUBE,PRO_MED_OBS_PSF);

    } else if(NULL != cpl_frameset_find(sof,PRO_MED_COADD_PSF)) {
      check_nomsg(frame = cpl_frameset_find(sof,PRO_MED_COADD_PSF));
      strcpy(std_med_filename,cpl_frame_get_filename(frame));
      check_nomsg(std_med_ima=cpl_image_load(std_med_filename,
                                             CPL_TYPE_FLOAT,0,0));
    } else if(NULL != cpl_frameset_find(sof,PRO_OBS_PSF)) {
      check_nomsg(frame = cpl_frameset_find(sof,PRO_OBS_PSF));
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
      check_nomsg(cube=cpl_imagelist_load(std_cub_filename,CPL_TYPE_FLOAT,0));
      strcpy(std_med_filename,STDSTAR_OUT_MED_CUBE);
      check_nomsg(std_med_ima=cpl_imagelist_collapse_median_create(cube));
      sinfo_free_imagelist(&cube);

      ck0(sinfo_pro_save_ima(std_med_ima,ref_set,sof,STDSTAR_OUT_MED_CUBE,
                 PRO_MED_OBS_PSF,NULL,plugin_id,config),
      "Error saving image %s tag %s",STDSTAR_OUT_MED_CUBE,PRO_MED_OBS_PSF);

    } else if(NULL != cpl_frameset_find(sof,PRO_MED_COADD_OBJ)) {
      check_nomsg(frame = cpl_frameset_find(sof,PRO_MED_COADD_OBJ));
      strcpy(std_med_filename,cpl_frame_get_filename(frame));
      check_nomsg(std_med_ima=cpl_image_load(std_med_filename,
                                             CPL_TYPE_FLOAT,0,0));
    } else if(NULL != cpl_frameset_find(sof,PRO_OBS_OBJ)) {
      check_nomsg(frame = cpl_frameset_find(sof,PRO_OBS_OBJ));
      strcpy(std_cub_filename,cpl_frame_get_filename(frame));
      check_nomsg(cube = cpl_imagelist_load(std_cub_filename,
                                             CPL_TYPE_FLOAT,0));
      strcpy(std_med_filename,STDSTAR_OUT_MED_CUBE);
      check_nomsg(std_med_ima=cpl_imagelist_collapse_median_create(cube));
      sinfo_free_imagelist(&cube);

      ck0(sinfo_pro_save_ima(std_med_ima,ref_set,sof,STDSTAR_OUT_MED_CUBE,
                 PRO_MED_OBS_OBJ,NULL,plugin_id,config),
      "Error saving image %s tag %s",STDSTAR_OUT_MED_CUBE,PRO_MED_OBS_OBJ);
    } else {
      sinfo_msg_error("Frame %s %s %s %s %s %s not found! Exit!",
              PRO_MED_COADD_STD, PRO_OBS_STD,
                      PRO_MED_COADD_PSF, PRO_OBS_PSF,
                      PRO_MED_COADD_OBJ, PRO_OBS_OBJ);
      goto cleanup;
    }


    check_nomsg(std_med_dup=cpl_image_duplicate(std_med_ima));
    sinfo_clean_nan(&std_med_dup);
    check_nomsg(cpl_image_get_maxpos(std_med_dup,&max_ima_x,&max_ima_y));
    sinfo_free_image(&std_med_dup);


    ima_szx=cpl_image_get_size_x(std_med_ima);
    ima_szy=cpl_image_get_size_y(std_med_ima);
    wllx= ((max_ima_x-psf_sz)>0)       ? (max_ima_x-psf_sz) : 1;
    wlly= ((max_ima_y-psf_sz)>0)       ? (max_ima_y-psf_sz) : 1;
    wurx= ((max_ima_x+psf_sz)<ima_szx) ? (max_ima_x+psf_sz) : ima_szx ;
    wury= ((max_ima_y+psf_sz)<ima_szy) ? (max_ima_y+psf_sz) : ima_szy ;
    /*
    sinfo_msg("wllx=%d wlly=%d wurx=%d wury=%d\n",wllx,wlly,wurx,wury);
    cpl_image_get_maxpos_window(std_med_ima,wllx,wlly,wurx,wury,
                                &max_ima_x,&max_ima_y);
    */
    check_nomsg(qclog_tbl = sinfo_qclog_init());
    check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(std_med_ima,wllx,
                                                           wlly,wurx,wury));
    check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(std_med_ima,wllx,
                                                             wlly,wurx,wury));


      xshift=max_ima_cx-ima_szx/2;
      yshift=max_ima_cy-ima_szy/2;

      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SHIFTX",xshift,
                                       "X shift centroid - center image","%f"));

      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SHIFTY",yshift,
                                       "Y shift centroid - center image","%f"));

    if(
          ((max_ima_x-psf_sz) < 1) ||
          ((max_ima_y-psf_sz) < 1) ||
          ((max_ima_x+psf_sz) > ima_szx) ||
          ((max_ima_x+psf_sz) > ima_szy)
      )
      {
        psf_sz = (psf_sz < (max_ima_x-1))     ? psf_sz : (max_ima_x-1);
        psf_sz = (psf_sz < (max_ima_y-1))     ? psf_sz : (max_ima_y-1);
        psf_sz = (psf_sz < ima_szx-max_ima_x) ? psf_sz : (ima_szx-max_ima_x);
        psf_sz = (psf_sz < ima_szy-max_ima_y) ? psf_sz : (ima_szy-max_ima_y);
        //added to prevent seg fault by cpl_image_fit_gaussian
        psf_sz = (psf_sz > 4) ? psf_sz : 4;
      }


      ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC FWHM LLX",cfg->llx,
                                    "STD star FWHM LLX","%d"));
      ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC FWHM LLY",cfg->lly,
                                    "STD star FWHM LLY","%d"));
      ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC FWHM HBX",cfg->halfbox_x,
                                    "STD star FWHM HBX","%d"));
      ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC FWHM HBX",cfg->halfbox_y,
                                    "STD star FWHM HBY","%d"));


    /* call the 2D-Gaussian fit routine */
    for ( i = 0 ; i < 7 ; i++ )
    {
        mpar[i] = 1 ;
    }


     if(-1 == sinfo_new_fit_2d_gaussian(std_med_ima,
                                  fpar,
                                  dpar,
                                  mpar,
                                  cfg->llx,
                                  cfg->lly,
                                  cfg->halfbox_x,
                                  cfg->halfbox_y,
                                  &check4 ) ) {
      irplib_error_recover(clean_state,"2d Gaussian fit failed");
      /* return 0; */

     } else {

      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM MAJ",fpar[4],
                                       "STD star FWHM on major axis","%f"));
      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM MIN",fpar[5],
                                       "STD star FWHM on minor axis","%f"));
      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC THETA",fpar[6],
                                       "STD star ellipsis angle theta","%f"));


     }


    /*
    sinfo_msg("Gauss fit params: xc,yc,amp,bkg,fwhm_x,fwhm_y,angle\n");
    for ( i = 0 ; i < 7 ; i++ )
      {
        sinfo_msg("fpar[%d]=%f dpar[%d]=%f\n",i,fpar[i],i,dpar[i]);
      }
    */
    if(CPL_ERROR_NONE == cpl_image_fit_gaussian(std_med_ima,
                                                max_ima_x,
                                                max_ima_y,
                                                psf_sz,
                                                &norm,
                                                &xcen,
                                                &ycen,
                                                &sig_x,
                                                &sig_y,
                                                &fwhm_x,
                                                &fwhm_y)) {


      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHMX",fwhm_x,
                                       "STD star FWHM on X","%f"));
      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHMY",fwhm_y,
                                       "STD star FWHM on Y","%f"));

      cfg -> halfbox_x =  (floor)(0.5*(fwhm_x+fwhm_y)*cfg->fwhm_factor+0.5);

      cfg -> halfbox_y =  (floor)(0.5*(fwhm_x+fwhm_y)*cfg->fwhm_factor+0.5);

    } else {

      irplib_error_recover(clean_state,"Problem fitting Gaussian");
      cpl_error_reset();

    }
    sinfo_free_image(&std_med_ima);

      /*
      sinfo_msg("max ima=%d %d psf_sz=%d\n",max_ima_x,max_ima_y,psf_sz);
      sinfo_msg("centroid ima=%f %f\n",max_ima_cx,max_ima_cy);
      sinfo_msg("gauss=norm=%f xcen=%f ycen=%f sig_x=%f "
                "sig_y=%f fwhm_x=%f fwhm_y=%f\n",
                          norm,xcen,ycen,sig_x,sig_y,fwhm_x,fwhm_y);
      */

      cfg -> llx = (int)(xcen-cfg->halfbox_x);
      cfg -> llx = (cfg -> llx  > 0 ) ? cfg -> llx  : 1;

      if((cfg->llx+2*cfg->halfbox_x) >= ima_szx) {
    cfg -> halfbox_x=(int) ((ima_szx-cfg->llx-1)/2);
        check1++;
      }

      cfg -> lly = (int)(ycen-cfg->halfbox_y);
      cfg -> lly = (cfg -> lly  > 0 ) ? cfg -> lly  : 1;
      if((cfg->lly+2*cfg->halfbox_y) >= ima_szy) {
    cfg -> halfbox_y=(int) ((ima_szy-cfg->lly-1)/2);
        check1++;
      }
     ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC CHECK1",check1,
                                    "Check on evaluation box","%d"));


    /*
      sinfo_msg("llx= %d lly= %d\n",cfg->llx, cfg->lly);
      sinfo_msg("halfbox_x=%d halfbox_y=%d\n",cfg->halfbox_x,cfg->halfbox_y);
     */

    /*
#----------------------------------------------------------------------
#---------------------------EXTRACTION---------------------------------
#----------------------------------------------------------------------
    */

      sinfo_msg("Extraction");
      cknull(spectrum = (cpl_image**) cpl_calloc (cfg -> nframes,
                                                  sizeof(cpl_image*)),
                            "Could not allocate memory for spectrum image");

      for (fra=0; fra < cfg->nframes; fra++) {
         name = cfg->inFrameList[fra];
         if(sinfo_is_fits_file(name) != 1) {
            sinfo_msg_error("Input file %s is not FITS",name);
            goto cleanup;
	 }
         cknull(cube = cpl_imagelist_load(name,CPL_TYPE_FLOAT,0),
        "could not load data cube" );

         if (exptime == FLAG) {
	   sinfo_msg_error("could not find exposure time in the fits header");
	   return -1;
	 }
         exptime = sinfo_pfits_get_ditndit(name);

         sinfo_msg("cfg->gain %f",cfg->gain);
         check_nomsg(tbl_spectrum=cpl_table_new(cpl_imagelist_get_size(cube)));
        if(NULL==(spectrum[fra]=sinfo_new_optimal_extraction_from_cube( cube,
                                      cfg->llx,
                                      cfg->lly,
                                      cfg->halfbox_x,
                                      cfg->halfbox_y,
                                      cfg->fwhm_factor,
                                      BKG_VARIANCE,
                                      SKY_FLUX,
                                      cfg->gain,
                                      exptime,
                                      name,
                                      &tbl_spectrum,
                                      qc_info,
                                      &check2))){

      irplib_error_recover(clean_state,
			   "could not do sinfo_optimalExtractionFromCube");
     } else {
     check_nomsg(cpl_imagelist_set(list_object,
                     cpl_image_duplicate(spectrum[fra]), fra));

     }



	ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC CHECK2",
                                       check2,"Check on evaluation box","%d"));


        ck0(sinfo_pro_save_tbl(tbl_spectrum,ref_set,sof,
                                      (char*)STDSTAR_OUT_TABLE,
                      PRO_STD_STAR_SPECTRA,qclog_tbl,
                plugin_id,config),
         "cannot dump ima %s", "out_std_star_spectrum.fits");


     sinfo_free_table(&qclog_tbl);

     if (do_compute_eff!=0 && frm_std_cat !=NULL && frm_atmext != NULL) {
        sinfo_msg("compute efficiency");
        frm_sci     = cpl_frameset_find(sof,PRO_STD_STAR_SPECTRA);
        frm_std_cat = cpl_frameset_find(sof,FLUX_STD_CATALOG);
        frm_atmext  = cpl_frameset_find(sof,EXTCOEFF_TABLE);



        check_nomsg(tot_eff=sinfo_efficiency_compute(frm_sci,frm_std_cat,
                                                     frm_atmext));
        ck0(sinfo_pro_save_tbl(tot_eff,ref_set,sof,(char*)EFFICIENCY_FILENAME,
                               PRO_EFFICIENCY,qclog_tbl,plugin_id,config),
            "cannot dump ima %s", "out_.fits");
     }




     /*
         if(spectrum[fra] != NULL ) {
         sinfo_free_image(&(spectrum)[fra]);
         }
     */
     /*----determine the intensity conversion factor if wished--------*/
     if (cfg->convInd == 1) {
       sinfo_msg("Determines convertion factor");

           convfactor = sinfo_new_determine_conversion_factor( cube,
                                                cfg->mag,
                                                exptime,
                                                cfg->llx,
                                                cfg->lly,
                                                cfg->halfbox_x,
                                                cfg->halfbox_y,
                                                &check3 );


            if (convfactor < -100000.) {
            sinfo_msg_warning("could not do sinfo_determineConversionFactor!" );
           /* goto cleanup; */
        } else {
             sinfo_new_array_set_value(factor, convfactor, fra);
        }
     }
     sinfo_free_imagelist(&cube);
      } /* end loop over fra */

      sinfo_free_table(&tbl_spectrum);
      sinfo_free_image_array(&spectrum,cfg->nframes);
      if (cfg->convInd == 1) {
	sinfo_msg("Determines clean factor");
        cleanfactor = sinfo_new_clean_mean(factor,
                                 cfg->nframes,
                                 cfg->lo_reject*100.,
                 cfg->hi_reject*100.);
      }
      if (cleanfactor > 100000. || cleanfactor == FLAG) {
	sinfo_msg_error("could not do sinfo_clean_mean!" );
        goto cleanup;
      }


  /*---read the fits header to change the gain and noise parameter-----*/
      sinfo_msg("Average with rejection");

      no=cpl_imagelist_get_size(list_object);
      lo_cut=(floor)(cfg->lo_reject*no+0.5);
      hi_cut=(floor)(cfg->hi_reject*no+0.5);
      if(no > 0) {
         cknull(img_spct=cpl_imagelist_collapse_minmax_create(list_object,
                                                              lo_cut,hi_cut),
                          "sinfo_average_with_rejection failed" );
      }

      sinfo_free_imagelist(&list_object);
      if(no > 0) {
	check_nomsg(qclog_tbl = sinfo_qclog_init());

        ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC CONVFCT",cleanfactor,
                                         "Conversion factor","%g"));

        ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC CHECK3",check3,
                                      "Check evaluation box","%d"));


        ck0(sinfo_pro_save_ima(img_spct,ref_set,sof,cfg->outName,
                    PRO_STD_STAR_SPECTRUM,qclog_tbl,
                 plugin_id,config),
	    "cannot dump ima %s", cfg->outName);

        sinfo_new_set_wcs_spectrum(img_spct,cfg->outName,cenLambda,disp,cenpix);
        sinfo_free_table(&qclog_tbl);
      }
      /*#---free memory---*/
      if(factor != NULL) sinfo_new_destroy_array(&factor);
      sinfo_free_image(&img_spct);
      sinfo_stdstar_free(&cfg);
      sinfo_free_frameset(&raw);

      return 0;

 cleanup:
      sinfo_free_table(&tbl_spectrum);
      sinfo_free_table(&qclog_tbl);
      sinfo_free_imagelist(&list_object);
      if(spectrum != NULL) sinfo_free_image_array(&spectrum,cfg->nframes);
      sinfo_free_image(&std_med_ima);
      sinfo_free_image(&std_med_dup);
      sinfo_free_imagelist(&cube);
      sinfo_free_propertylist(&plist) ;
      if(factor != NULL) sinfo_new_destroy_array(&factor);
      sinfo_free_image(&img_spct);
      sinfo_stdstar_free (&cfg);
      sinfo_free_frameset(&raw);
    return -1;

}


/**@}*/
