/*                                                                            *
 *   This file is part of the ESO X-shooter Pipeline                          *
 *   Copyright (C) 2006 European Southern Observatory                         *
 *                                                                            *
 *   This library 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 PURsPOSE.  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     *
 *                                                                            */

/*
 * $Author: amodigli $
 * $Date: 2013-08-29 10:51:22 $
 * $Revision: 1.72 $
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*----------------------------------------------------------------------------*/
/**
 * @defgroup xsh_respon_slit_stare  xsh_respon_slit_stare
 * @ingroup recipes
 *
 * This recipe computes the response function for UVB / VIS
 * See man-page for details.
 */
/*----------------------------------------------------------------------------*/
/**@{*/

/*-----------------------------------------------------------------------------
  Includes
  ----------------------------------------------------------------------------*/


/* DRL steps */

/* Error handling */
#include <xsh_error.h>
/* Utility fonctions */
#include <xsh_utils_scired_slit.h>
#include <xsh_model_utils.h>
#include <xsh_utils.h>
#include <xsh_utils_table.h>
#include <xsh_msg.h>
/* DFS functions */
#include <xsh_dfs.h>
/* DRL functions */
#include <xsh_drl.h>
#include <xsh_drl_check.h>
#include <xsh_pfits.h>
#include <xsh_data_spectrum1D.h>
#include <xsh_model_arm_constants.h>
#include <xsh_parameters.h>

/* Library */
#include <cpl.h>
/* CRH Remove */


/*-----------------------------------------------------------------------------
  Defines
  ----------------------------------------------------------------------------*/

#define RECIPE_ID "xsh_respon_slit_stare"
#define RECIPE_AUTHOR "P.Goldoni, L.Guglielmi, R. Haigron, F. Royer, D. Bramich, A. Modigliani"
#define RECIPE_CONTACT "amodigli@eso.org "

/*-----------------------------------------------------------------------------
  Functions prototypes
  ----------------------------------------------------------------------------*/

/*
 *   Plugin initalization, execute and cleanup handlers
 */

static int xsh_respon_slit_stare_create(cpl_plugin *);
static int xsh_respon_slit_stare_exec(cpl_plugin *);
static int xsh_respon_slit_stare_destroy(cpl_plugin *);

/* The actual executor function */
static cpl_error_code xsh_respon_slit_stare(cpl_parameterlist *, cpl_frameset *);

/*-----------------------------------------------------------------------------
  Static variables
  ----------------------------------------------------------------------------*/
static char xsh_respon_slit_stare_description_short[] =
"Compute the response function in SLIT stare mode";

static char xsh_respon_slit_stare_description[] =
"This recipe computes the response function for arm\n\
Input Frames : \n\
  - A RAW frame (Tag = STD_FLUX_SLIT_STARE_arm, Type = RAW)\n\
  - [UVB,VIS] A master bias frame (Tag = MASTER_BIAS_arm, Type = PRE)\n\
  - A master dark frame (Tag = MASTER_DARK_arm Type = PRE)\n\
  - A master flat frame (Tag = MASTER_FLAT_SLIT_arm Type = PRE)\n\
  - An order table frame(Tag = ORDER_TAB_EDGES_arm Type = ORD)\n\
  - A wave solution frame(Tag = WAVE_TAB_2D_arm, Type = WAV)\n\
  - [OPTIONAL] Table with dispersion coefficients (Tag = DISP_TAB_arm)\n\
  - [OPTIONAL] A telluric model catalog (Tag = TELL_MOD_CAT_arm arm=VIS,NIR)\n\
  - A standard star fluxes catalog (Tag = FLUX_STD_CATALOG_arm Type = FLX)\n\
  - A table to set response sampling points (Tag = RESP_FIT_POINTS_CAT_arm)\n\
  - An atmospheric extinction table (Tag = ATMOS_EXT_arm)\n\
  - [OPTIONAL] A master response curve table (Tag = MRESPONSE_MERGE1D_SLIT_arm)\n\
    if provided this is the one used to flux calibrate the spectra\n\
Products : \n\
  - [If STD is in catal] The response ord-by-ord function (Tag = PREFIX_RESPONSE_ORDER1D_SLIT_arm)\n\
  - [If STD is in catal] The response merged function (Tag = PREFIX_RESPONSE_MERGE1D_SLIT_arm)\n\
  - The extracted 2D specturm (Tag = PREFIX_ORDER2D_arm)\n\
  - The extracted 1D specturm (Tag = PREFIX_ORDER1D_arm)\n\
  - The merged 2D specturm (Tag = PREFIX_MERGE2D_arm)\n\
  - The merged 1D specturm (Tag = PREFIX_MERGE1D_arm)\n\
  - The merged 2D sky frame (Tag = SLY_SLIT_MERGED2D)\n\
 - [If STD is in catal] Flux calibrated merged 2D spectrum (Tag = PREFIX_FLUX_ORDER2D_arm)\n\
 - [If STD is in catal] Flux calibrated merged 1D spectrum (Tag = PREFIX_FLUX_ORDER1D_arm)\n\
 - [If STD is in catal] Flux calibrated merged 2D spectrum (Tag = PREFIX_FLUX_MERGE2D_arm)\n\
 - [If STD is in catal] Flux calibrated merged 1D spectrum (Tag = PREFIX_FLUX_MERGE1D_arm)\n\
 - [If STD is in catal] The efficiency (Tag = EFFICIENCY_SLIT_arm)\n\
 - where PREFIX is SCI, FLUX, TELL if input raw DPR.TYPE contains OBJECT or FLUX or TELLURIC";

/*-----------------------------------------------------------------------------
  Functions code
  ----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
   @brief    Build the list of available plugins, for this module.
   @param    list    the plugin list
   @return   0 if everything is ok, -1 otherwise

   Create the recipe instance and make it available to the application using the
   interface. This function is exported.
*/
/*----------------------------------------------------------------------------*/

int cpl_plugin_get_info(cpl_pluginlist *list) {
  cpl_recipe *recipe = NULL;
  cpl_plugin *plugin = NULL;

  recipe = cpl_calloc(1, sizeof(*recipe));
  if ( recipe == NULL ){
    return -1;
  }

  plugin = &recipe->interface ;

  cpl_plugin_init(plugin,
                  CPL_PLUGIN_API,                    /* Plugin API */
                  XSH_BINARY_VERSION,             /* Plugin version */
                  CPL_PLUGIN_TYPE_RECIPE,            /* Plugin type */
                  RECIPE_ID,                         /* Plugin name */
                  xsh_respon_slit_stare_description_short, /* Short help */
                  xsh_respon_slit_stare_description,       /* Detailed help */
                  RECIPE_AUTHOR,                     /* Author name */
                  RECIPE_CONTACT,                    /* Contact address */
                  xsh_get_license(),                 /* Copyright */
                  xsh_respon_slit_stare_create,
                  xsh_respon_slit_stare_exec,
                  xsh_respon_slit_stare_destroy);

  cpl_pluginlist_append(list, plugin);

  return (cpl_error_get_code() != CPL_ERROR_NONE);
}

/*----------------------------------------------------------------------------*/
/**
   @brief    Setup the recipe options
   @param    plugin  the plugin
   @return   0 if everything is ok

   Create the recipe instance and make it available to the application using the
   interface.

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

static int xsh_respon_slit_stare_create(cpl_plugin *plugin){
  cpl_recipe *recipe = NULL;

  xsh_remove_crh_single_param crh_single = {0.1, 20,2.0, 4} ;
  /* First param (conv_kernel) should be initialized correctly ! */
   xsh_rectify_param rectify = { "tanh",
                                CPL_KERNEL_DEFAULT, 
                                2,
                                -1.0, 
                                -1.0, 
                                1, 
                                0, 0.} ;


  xsh_subtract_sky_single_param sky_single = {3000, 3000,7,20, 5., -1, -1,
                                              MEDIAN_METHOD, FINE,20, 0.5,
                                             0.0, 0.0,
                                             0.0, 0.0} ;


  /* 2nd and 3rd params should be initialized correctly */
  xsh_localize_obj_param loc_obj = 
     {10, 0.1, 0, 0, LOC_MANUAL_METHOD, 0, 2.0,3,3,FALSE};

 xsh_opt_extract_param opt_extract_par = 
     { 5, 10, 10, 0.01, 10.0, 1., 2, 2, GAUSS_METHOD }; 

 xsh_interpolate_bp_param ipol_par = {30 };
  /* Parameters init */
  opt_extract_par.oversample = 5;
  opt_extract_par.box_hsize = 10;
  opt_extract_par.chunk_size = 50;
  opt_extract_par.lambda_step = 0.02;
  opt_extract_par.clip_kappa = 3;
  opt_extract_par.clip_frac = 0.4;
  opt_extract_par.clip_niter = 2;
  opt_extract_par.niter = 1;
  opt_extract_par.method = GAUSS_METHOD;

  /* Reset library state */
  xsh_init();

  /* Check input */
  assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin");

  /* Get the recipe out of the plugin */
  assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
          CPL_ERROR_TYPE_MISMATCH,
          "Plugin is not a recipe");

  recipe = (cpl_recipe *)plugin;

  /* Create the parameter list in the cpl_recipe object */
  recipe->parameters = cpl_parameterlist_new();
  assure( recipe->parameters != NULL,
          CPL_ERROR_ILLEGAL_OUTPUT,
          "Memory allocation failed!");

  /* Set generic parameters (common to all recipes) */
  check( xsh_parameters_generic( RECIPE_ID, recipe->parameters ) ) ;
  xsh_parameters_decode_bp(RECIPE_ID,recipe->parameters,-1);
  check( xsh_parameters_pre_overscan( RECIPE_ID, recipe->parameters ) ) ;


  /* subtract_background_params */
  check(xsh_parameters_background_create(RECIPE_ID,recipe->parameters));

  /* remove_crh_single */
  check(xsh_parameters_remove_crh_single_create(RECIPE_ID,recipe->parameters,
						crh_single )) ;

  /* xsh_rectify */
  check(xsh_parameters_rectify_create(RECIPE_ID,recipe->parameters,
					    rectify )) ;

  /* xsh_localize_object */
  check(xsh_parameters_localize_obj_create(RECIPE_ID,recipe->parameters,
					   loc_obj )) ;

  /* xsh_remove_sky_single */
  check(xsh_parameters_subtract_sky_single_create(RECIPE_ID,recipe->parameters,
						  sky_single )) ;


  check(xsh_parameters_interpolate_bp_create(RECIPE_ID,
               recipe->parameters,ipol_par)) ;

  check( xsh_parameters_new_boolean( recipe->parameters, RECIPE_ID,
    "do-optextract", FALSE, 
    "TRUE if we do the optimal extraction"));

  check( xsh_parameters_opt_extract_create( RECIPE_ID, recipe->parameters,
    opt_extract_par));

  /*
  check( xsh_parameters_new_boolean( recipe->parameters, RECIPE_ID,
    "do-flatfield", TRUE, 
    "TRUE if we do the flatfielding"));
*/
  check( xsh_parameters_new_boolean( recipe->parameters, RECIPE_ID,
    "correct-tellurics", TRUE, 
    "TRUE if during response computation we apply telluric correction"));

 cleanup:
  if ( cpl_error_get_code() != CPL_ERROR_NONE ){
    xsh_error_dump(CPL_MSG_ERROR);
    return 1;
  }
  else {
    return 0;
  }
}

/*----------------------------------------------------------------------------*/
/**
   @brief    Execute the plugin instance given by the interface
   @param    plugin  the plugin
   @return   0 if everything is ok
*/
/*----------------------------------------------------------------------------*/

static int xsh_respon_slit_stare_exec(cpl_plugin *plugin) {
  cpl_recipe *recipe = NULL;

  /* Check parameter */

  assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );

  /* Get the recipe out of the plugin */
  assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
          CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");

  recipe = (cpl_recipe *)plugin;

  /* Check recipe */
  xsh_respon_slit_stare(recipe->parameters, recipe->frames);

 cleanup:
  if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
    xsh_error_dump(CPL_MSG_ERROR);
    xsh_error_reset();
    return 1;
  }
  else {
    return 0;
  }
}

/*----------------------------------------------------------------------------*/
/**
   @brief    Destroy what has been created by the 'create' function
   @param    plugin  the plugin
   @return   0 if everything is ok
*/
/*----------------------------------------------------------------------------*/
static int xsh_respon_slit_stare_destroy(cpl_plugin *plugin)
{
  cpl_recipe *recipe = NULL;

  /* reset error state before detroying recipe */
  xsh_error_reset(); 
  /* Check parameter */
  assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );

  /* Get the recipe out of the plugin */
  assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
	  CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");

  recipe = (cpl_recipe *)plugin;

  xsh_free_parameterlist(&recipe->parameters);

 cleanup:
  if (cpl_error_get_code() != CPL_ERROR_NONE)
    {
      return 1;
    }
  else
    {
      return 0;
    }
}


static cpl_error_code 
xsh_params_monitor(xsh_background_param* backg,
                   xsh_rectify_param * rectify_par,
                   xsh_localize_obj_param * loc_obj_par,
                   xsh_opt_extract_param *opt_extract_par,
                   int sub_sky_nbkpts1,
                   int sub_sky_nbkpts2)
{



  xsh_msg_dbg_low("rectify params: radius=%g bin_lambda=%g bin_space=%g",
	  rectify_par->rectif_radius,rectify_par->rectif_bin_lambda,
	  rectify_par->rectif_bin_space);

  xsh_msg_dbg_low("localize params: chunk_nb=%d nod_step=%g",
	  loc_obj_par->loc_chunk_nb,loc_obj_par->nod_step);

  xsh_msg_dbg_low("opt extract params: chunk_size=%d lambda_step=%g box_hsize=%d",
	  opt_extract_par->chunk_size,opt_extract_par->lambda_step,
	  opt_extract_par->box_hsize);

  xsh_msg_dbg_low("sky params: nbkpts1=%d nbkpts2=%d",
	  sub_sky_nbkpts1,sub_sky_nbkpts2);

  return cpl_error_get_code();

}

/*----------------------------------------------------------------------------*/
/**
   @brief    Interpret the command line options and execute the data processing
   @param    parameters     the parameters list
   @param    frameset   the frames list

   In case of failure the cpl_error_code is set.
*/
/*----------------------------------------------------------------------------*/
static cpl_error_code 
xsh_respon_slit_stare(cpl_parameterlist* parameters,
				  cpl_frameset* frameset)
{
   const char* recipe_tags[2] = {XSH_STD_FLUX_SLIT_STARE,XSH_STD_TELL_SLIT_STARE};
  int recipe_tags_size = 2;

  /* Input frames */
  cpl_frameset* raws = NULL;
  cpl_frameset* calib = NULL;
  /* Beware, do not "free" the following input frames, they are part
     of the input frameset */
  cpl_frame * bpmap = NULL;
  cpl_frame * master_bias = NULL;
  cpl_frame * master_dark = NULL;
  cpl_frame * master_flat = NULL;
  cpl_frame * order_tab_edges = NULL;
  cpl_frame * wave_tab = NULL ;
  cpl_frame * model_config_frame = NULL ;
  cpl_frame * wavemap_frame = NULL ;
  cpl_frame * slitmap_frame = NULL ;
  cpl_frame * disp_tab_frame = NULL;
  cpl_frame * spectralformat_frame = NULL ;
  cpl_frame * fluxcal_1D_frame = NULL ;	
  cpl_frame * fluxcal_2D_frame = NULL ;	
  cpl_frame * fluxcal_rect_1D_frame = NULL ;	
  cpl_frame * fluxcal_rect_2D_frame = NULL ;	

  cpl_frame* sky_list_frame=NULL;
  cpl_frame* qc_sky_frame=NULL;

  /* Parameters */
  xsh_background_param* backg_par = NULL;
  xsh_remove_crh_single_param * crh_single_par = NULL ;
  cpl_frame* high_abs_win=NULL;
  xsh_rectify_param * rectify_par = NULL ;
  xsh_localize_obj_param * loc_obj_par = NULL ;
  int sub_sky_nbkpts1 = SUBTRACT_SKY_SINGLE_NBKPTS ; /**< Nb of breakpoints 
						      for the first call to
						      subtract_sky_single */
  int sub_sky_nbkpts2 = SUBTRACT_SKY_SINGLE_NBKPTS ; /**< Nb of breakpoints 
						      for the second call to
						      subtract_sky_single */

  int do_sub_sky = FALSE;
  int recipe_use_model = 0 ;
  int do_optextract = 0;
  int do_flatfield = 1;
  int do_compute_map = FALSE ;
  int generate_sdp_format = 0;
  // int do_compute_eff = 0 ;
  xsh_extract_param extract_par = {  LOCALIZATION_METHOD};

  //xsh_extract_param *extract_par = NULL ;
  xsh_subtract_sky_single_param *sky_par = NULL;

  xsh_instrument* instrument = NULL;
  int nb_raw_frames ;
  char rec_name[256];

  /* Intermediate frames */
  cpl_frame * std_flux_frame = NULL ;	/**< Output of prepare */

  cpl_frame * rmbias = NULL;	/**< Output of subtract bias */
  cpl_frame * rmdark = NULL;	/**< Output of subtract dark */
  cpl_frame * rmbkg = NULL ;	/**< Output of subtract background */
  cpl_frame * div_frame = NULL ; /**< Output of xsh_divide_flat */
  cpl_frame * sub_sky_frame = NULL ; /**< Output of xsh_subtract_sky_single */
  cpl_frame * sub_sky2_frame = NULL ; /**< Output of xsh_subtract_sky_single
				       Second pass (with localization table) */

  cpl_frame * rect_frame = NULL ; /**< Output of xsh_rectify */
  cpl_frame * loc_table_frame = NULL ; /**< Output of xsh_localize_object */
  cpl_frame * clean_frame = NULL ; /**< Output of remove_crh_single */
  cpl_frame * rect2_frame = NULL ;
  cpl_frame * rect2_frame_eso = NULL ;
  cpl_frame * rect2_frame_tab = NULL ;

  cpl_frame * rect2_sky_frame = NULL ;
  cpl_frame * rect2_sky_frame_eso = NULL ;
  cpl_frame * rect2_sky_frame_tab = NULL ;


  cpl_frame * rect_eff_frame_eso = NULL ; /**< Output of xsh_rectify */
  cpl_frame * rect_frame_tab = NULL ; /**< Output of xsh_rectify */
  cpl_frame * rect_eff_frame_tab = NULL ; /**< Output of xsh_rectify */

  cpl_frame * div_clean_frame = NULL ;
  cpl_frame * tell_frame = NULL ; /**< output of xsh_mark_tell */
  cpl_frame * res_1D_frame = NULL ; /**< Output of merge_ord */

  /* Output Frames (results) */
  cpl_frame * sky_frame = NULL ; /**< Sky spectrum (REC) */
  cpl_frame * sky_frame_eso = NULL ; /**< Sky spectrum (REC) */

  cpl_frame * response_frame = NULL ; /**< computed response frame */
  cpl_frame * mresponse_frame = NULL ; /**< computed response frame */
  cpl_frame * response_ord_frame = NULL ; /**< computed response frame */
  cpl_frame* sky_frame_ima=NULL;
  cpl_frame* clean_obj=NULL;

  cpl_frame * ext_frame = NULL ;
  cpl_frame * ext_frame_eso = NULL ;

  cpl_frame *orderext1d_frame = NULL;
  cpl_frame *orderoxt1d_frame = NULL;
  cpl_frame *orderoxt1d_eso_frame = NULL;

  cpl_frame *mergeoxt1d_frame = NULL;
//  cpl_frame *mergeoxt1d_frame = NULL;

  /* Miscelleanious */
  char file_name[256];
  char file_tag[256];
  char arm_str[8] ;

  char prefix[256];
  double exptime = 1. ;
  cpl_frame* grid_backg=NULL;
  cpl_frame* frame_backg=NULL;
  cpl_frame* res_2D_frame=NULL;
  cpl_frame* res_2D_sky_frame=NULL;

  char* rec_prefix=NULL;
  char sky_prefix[256];

  cpl_frame* frm_atmext=NULL;
  cpl_frame* frm_std_cat=NULL;
  cpl_frame* frm_eff=NULL;


  cpl_frame* eff_frame=NULL;
  cpl_frame* rect_eff_frame=NULL;
  cpl_frame* ext_eff_frame=NULL;
  cpl_frame* ext_eff_frame2=NULL;
  int pre_overscan_corr=0;
  cpl_frame* single_frame_sky_sub_tab_frame=NULL;
  xsh_opt_extract_param *opt_extract_par = NULL;
  cpl_frame *fluxcal_rect_opt1D_frame = NULL;
  cpl_frame *fluxcal_merg_opt1D_frame = NULL;
  cpl_frame *qc_subex_frame = NULL;
  cpl_frame *qc_s2ddiv1d_frame = NULL;
  cpl_frame *qc_model_frame = NULL;
  cpl_frame *qc_weight_frame = NULL;
  cpl_frame* tell_mod_cat=NULL;
  cpl_frame* rm_crh = NULL;
  cpl_frame* frame_ord_by_ord=NULL;
  cpl_frame* frame_merged=NULL;
  cpl_frame* resp_fit_points_cat_frame=NULL;
  cpl_frame* ext_sky_frame=NULL;
  cpl_frame* res_1D_sky_frame=NULL;

  char ftag[256];
  char fname[256];

  int merge_par=0;
  xsh_interpolate_bp_param *ipol_bp=NULL;
  int corr_tell=0;
  cpl_frame* sky_orders_chunks =NULL;
  /**************************************************************************/
  /* DFS management */
  /**************************************************************************/
  check( xsh_begin( frameset, parameters, &instrument, &raws, &calib,
                    recipe_tags, recipe_tags_size,
                    RECIPE_ID, XSH_BINARY_VERSION,
                    xsh_respon_slit_stare_description_short ) ) ;



  XSH_ASSURE_NOT_NULL( instrument);
  assure( instrument->mode == XSH_MODE_SLIT, CPL_ERROR_ILLEGAL_INPUT,
	  "Instrument NOT in Slit Mode" ) ;

  xsh_recipe_params_check(parameters,instrument,RECIPE_ID);
  if(instrument->arm == XSH_ARM_NIR) {
    xsh_calib_nir_corr_if_JH(calib,instrument,RECIPE_ID);
    xsh_instrument_nir_corr_if_JH(raws,instrument);
    xsh_calib_nir_respon_corr_if_JH(calib,instrument);
  }
  sprintf( arm_str, "%s",  xsh_instrument_arm_tostring(instrument) ) ;
  


  /**************************************************************************/
  /* Recipe parameters */
  /**************************************************************************/
  check(xsh_slit_stare_get_params(parameters,RECIPE_ID, &pre_overscan_corr,
                                  &backg_par,&loc_obj_par,
                                  &rectify_par,&crh_single_par,&sub_sky_nbkpts1,
                                  &do_flatfield,&sub_sky_nbkpts2,&sky_par,
                                  &do_optextract,
                                  &opt_extract_par,
                                  &generate_sdp_format));
  /* TODO: we should remove this internal parameter that actually confuses the code */
  rectify_par->conserve_flux=FALSE;
  backg_par->method=TRUE;
  check(ipol_bp = xsh_parameters_interpolate_bp_get(RECIPE_ID,parameters));

  check(xsh_rectify_params_set_defaults(parameters,RECIPE_ID,instrument,rectify_par));

  check( do_sub_sky = xsh_parameters_subtract_sky_single_get_true( RECIPE_ID,
    parameters));

  if ( do_sub_sky == 1   && (wavemap_frame == NULL || slitmap_frame == NULL) ) {
       xsh_msg_warning( "sky-subtract is true but wave,slits maps missing create them");
    do_compute_map = TRUE;

       }


  /* adjust relevant parameter to binning */
  if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR) {
     check(xsh_stare_params_bin_scale(raws,backg_par,
                                opt_extract_par,
                                &sub_sky_nbkpts1,&sub_sky_nbkpts2));
  }


  check(xsh_params_monitor(backg_par,rectify_par,loc_obj_par,opt_extract_par,
         sub_sky_nbkpts1,sub_sky_nbkpts2));

  check( pre_overscan_corr = xsh_parameters_get_int( parameters, RECIPE_ID,
                                                        "pre-overscan-corr"));


  check( corr_tell = xsh_parameters_get_boolean( parameters, RECIPE_ID,
                                                       "correct-tellurics"));


  /**************************************************************************/
  /* Recipe frames */
  /**************************************************************************/
  /* only one RAW frames: AMO in scired we allow also more than one frame */
  check( nb_raw_frames = cpl_frameset_get_size( raws));
  xsh_msg_dbg_low("nb_raw_frames=%d",nb_raw_frames);

  XSH_ASSURE_NOT_ILLEGAL_MSG( nb_raw_frames == 1,
                              "Pls provide a STD FLUX frame in input");



  /* prepare RAW frames in XSH format: NB we moved this piece of REDUCTION here
   * because we need to have the calib frameset with input frames already with correct binning
   * that is done by xsh_set_recipe_file_prefix (which needs frames in PRE format)
   */
  xsh_msg( "Calling xsh_prepare" ) ;
  check( xsh_prepare( raws, bpmap, master_bias, XSH_STD_FLUX_SLIT_STARE,
          instrument,pre_overscan_corr,CPL_TRUE));

  check(rec_prefix = xsh_set_recipe_file_prefix(raws,
                                                "xsh_respon_slit_stare"));
  /* in case the input master flat/bias do not match in bin size with the raw data,
   * correct the binning so that :
   *
   * 1x1 std 2x2 mflat,mbias --> correct bin of std
   * 2x2 std 1x1 mflat,mbias --> correct bin of mflat,mbias
   *
   */
  check(xsh_frameset_uniform_bin(&raws, &calib,instrument));


  check(xsh_slit_stare_get_calibs(calib,instrument, &spectralformat_frame,
                                  &master_bias,&master_dark,&master_flat,
                                  &order_tab_edges,&model_config_frame,
                                  &wave_tab,&sky_list_frame,&sky_orders_chunks,&qc_sky_frame,
                                  &bpmap,&single_frame_sky_sub_tab_frame,
                                  &wavemap_frame,&slitmap_frame,RECIPE_ID,
                                  &recipe_use_model,pre_overscan_corr));
  /* QC extra frames */
  if((mresponse_frame=xsh_find_frame_with_tag(calib,XSH_MRESPONSE_MERGE1D_SLIT,
                                             instrument)) != NULL ) {
     xsh_msg("Using the master response curve to flux calibrate the spectrum");
  }

  resp_fit_points_cat_frame=xsh_find_frame_with_tag(calib,XSH_RESP_FIT_POINTS_CAT,instrument);
  if(resp_fit_points_cat_frame==NULL) {
     xsh_msg_warning("Missing input %s_%s response will not be computed",
                     XSH_RESP_FIT_POINTS_CAT,
                     xsh_instrument_arm_tostring( instrument ));
     xsh_msg_warning("and data will not be flux calibrated");
  }
  /* response extra frames */
  frm_atmext=xsh_find_frame_with_tag(calib,XSH_ATMOS_EXT,instrument);
  if(frm_atmext==NULL) {
    xsh_msg_error("Provide atmospheric extinction frame");
    return CPL_ERROR_DATA_NOT_FOUND;
  }

  frm_std_cat=xsh_find_frame_with_tag(calib,XSH_FLUX_STD_CAT,instrument);
  if(frm_std_cat==NULL) {
     xsh_msg_error("Provide std star catalog frame");
     return CPL_ERROR_DATA_NOT_FOUND;
  }
  //high_abs_win=xsh_find_frame_with_tag(calib,XSH_HIGH_ABS_WIN,instrument);
  tell_mod_cat=xsh_find_frame_with_tag(calib,XSH_TELL_MOD_CAT,instrument);

  /* to compute efficiency */
  if(NULL == (disp_tab_frame = xsh_find_disp_tab( calib, instrument))) {
     xsh_msg("To compute efficiency, you must provide a DISP_TAB_ARM input");
  }


  /* 
  - A telluric mask (Tag = TELL_MASK_arm Type = LIN)\n\
  - A standard star fluxes table (Tag = STD_STAR_FLUX_arm Type = FLX)\n\
  - A master response (Tag = RESPONSE_mode_arm Type = RES)\n\
  - An atmospheric extinction table (Tag = Type = ATM)\n\
  */


  
  /* parameters dependent input */
  if ( do_compute_map && recipe_use_model == FALSE){
    check( disp_tab_frame = xsh_find_disp_tab( calib, instrument));
  }


  /**************************************************************************/
  /* Recipe code */
  /**************************************************************************/



  xsh_msg( "Calling xsh_find_std_flux" ) ;
  check_msg( std_flux_frame = xsh_find_std_flux( raws ),
             "Pls provide a STD FLUX telluric" ) ;
  /* Get Exptime */
  {
    xsh_pre * xpre = NULL ;
    check( xpre = xsh_pre_load( std_flux_frame, instrument ) ) ;
    exptime = xpre->exptime ;
    xsh_msg_dbg_medium( "EXPTIME: %lf", exptime ) ;

    xsh_pre_free( &xpre ) ;
  }

  check(xsh_slit_stare_get_maps(calib,
                                do_compute_map,recipe_use_model,rec_prefix,
                                instrument,model_config_frame,std_flux_frame,
                                disp_tab_frame,order_tab_edges,
                                &wavemap_frame, &slitmap_frame));
  sprintf(prefix,"%s",rec_prefix);
  /* Subtract bias if necessary */
  check( rmbias = xsh_check_subtract_bias( std_flux_frame, master_bias, 
					    instrument, "STD_FLUX_",pre_overscan_corr,1));


  /* Subtract Dark if necessary */
  check( rmdark = xsh_check_subtract_dark( rmbias, master_dark,
                                           instrument, "STD_FLUX_STARE_DARK"));



  sprintf(ftag,"%s_STD_NO_CRH_%s",rec_prefix,xsh_instrument_arm_tostring(instrument));
  sprintf(fname,"%s.fits",ftag) ;
  rm_crh = xsh_remove_crh_single(rmdark,instrument,NULL,crh_single_par,ftag) ;
  xsh_add_temporary_file(fname);

  //xsh_add_temporary_file(cpl_frame_get_filename( rmbias));
  /* subtract inter-order background */
  xsh_msg("Subtract inter-order background");
  check( rmbkg = xsh_subtract_background( rm_crh,
					  order_tab_edges, 
                                          backg_par,instrument,rec_prefix,
                                          &grid_backg,&frame_backg,0,0,0));

  /* In case CRH single or localize auto do preliminar sky subtraction */
  /* CHECK LEAKS: next call creates small leack */
  check(xsh_slit_stare_correct_crh_and_sky(loc_obj_par,crh_single_par,
                                           rectify_par,
                                           do_sub_sky,rec_prefix,rmbkg,
                                           order_tab_edges, slitmap_frame,
                                           wavemap_frame,model_config_frame,
                                           single_frame_sky_sub_tab_frame,
                                           instrument,sub_sky_nbkpts1, sky_par,
                                           sky_list_frame,
                                           sky_orders_chunks,
                                           &sky_frame,&sky_frame_eso,
                                           &sky_frame_ima,
                                           wave_tab,disp_tab_frame,
                                           spectralformat_frame,nb_raw_frames,
                                           &loc_table_frame,&clean_frame,
                                           &clean_obj,1
));

  xsh_free_frame(&rmbkg);
  /* now we divide by the flat for proper sky subtraction */
  check( div_frame = xsh_check_divide_flat( do_flatfield, clean_obj,
    master_flat, instrument, prefix));
  xsh_add_temporary_file(cpl_frame_get_filename(div_frame));

  check( sub_sky2_frame = xsh_check_subtract_sky_single( do_sub_sky,
                                                         div_frame,
                                                         order_tab_edges,
                                                         slitmap_frame,
                                                         wavemap_frame,
                                                         loc_table_frame,
                                                         single_frame_sky_sub_tab_frame,
                                                         instrument,
                                                         sub_sky_nbkpts2,
                                                         sky_par,
                                                         sky_list_frame,
                                                         sky_orders_chunks,
                                                         &sky_frame,
                                                         &sky_frame_eso,
                                                         &sky_frame_ima,
                                                         rec_prefix,
                                                         1));

  if(slitmap_frame) {
      xsh_add_temporary_file(cpl_frame_get_filename(slitmap_frame));
  }

  if(wavemap_frame) {
      xsh_add_temporary_file(cpl_frame_get_filename(wavemap_frame));
  }

  xsh_add_temporary_file(cpl_frame_get_filename(sub_sky2_frame));


  if(do_sub_sky) {
     xsh_add_temporary_file(cpl_frame_get_filename(sky_frame_ima));
  }


  check( div_clean_frame = cpl_frame_duplicate( sub_sky2_frame ) ) ;

  xsh_msg( "Prepare S2D products" ) ; 
  xsh_msg( "Rectify") ;
  sprintf(rec_name,"%s_%s_%s.fits",rec_prefix,XSH_ORDER2D,
	  xsh_instrument_arm_tostring( instrument));

  check( rect2_frame = xsh_rectify( sub_sky2_frame, order_tab_edges,
                                    wave_tab, model_config_frame, instrument, 
                                    rectify_par,spectralformat_frame, 
                                    disp_tab_frame,rec_name, 
                                    &rect2_frame_eso,&rect2_frame_tab,rec_prefix));

  if(sky_frame_ima) {
    /* rectify sky frame for QC */
    sprintf(sky_prefix,xsh_set_recipe_sky_file_prefix(rec_prefix));
    sprintf(rec_name,"%s_%s_%s.fits",sky_prefix,XSH_ORDER2D,
	    xsh_instrument_arm_tostring( instrument));

    check( rect2_sky_frame = xsh_rectify( sky_frame_ima, order_tab_edges,
                                    wave_tab, model_config_frame, instrument, 
                                    rectify_par,spectralformat_frame, 
                                    disp_tab_frame,rec_name, 
                                    &rect2_sky_frame_eso,&rect2_sky_frame_tab,
				    sky_prefix));
    xsh_add_temporary_file(cpl_frame_get_filename(rect2_sky_frame_eso));
    xsh_msg("rec2=%p loc=%p rec2_eso=%p",rect2_sky_frame,loc_table_frame,rect2_sky_frame_eso);
    /* the following frame is recreated by next function: we need to deallocate
     * it first */
    xsh_free_frame(&rect2_sky_frame_eso);
    check(ext_sky_frame = xsh_extract_clean(rect2_sky_frame, loc_table_frame,
					     instrument, &extract_par,ipol_bp,
					     &rect2_sky_frame_eso,rec_prefix )) ;
   
    check( res_1D_sky_frame = xsh_merge_ord( ext_sky_frame, instrument,
					      merge_par,sky_prefix));
    xsh_free_frame(&ext_sky_frame);
  }
  xsh_msg( "Extract" ) ;
  check(ext_frame=xsh_extract_clean(rect2_frame, loc_table_frame,
			      instrument, &extract_par,ipol_bp,&ext_frame_eso,
			      rec_prefix)) ;

  xsh_msg( "Merge orders with 1D frame" ) ;
  check( res_1D_frame = xsh_merge_ord( ext_frame, instrument,
				       merge_par,rec_prefix));
  check(xsh_monitor_spectrum1D_flux(res_1D_frame,instrument));


  xsh_msg( "Calling xsh_merge_ord with 2D frame" ) ;
  check( res_2D_frame = xsh_merge_ord( rect2_frame, instrument,
				       merge_par,rec_prefix));
  if(rect2_sky_frame) {
  check( res_2D_sky_frame = xsh_merge_ord( rect2_sky_frame, instrument,
				       merge_par,sky_prefix));
  }
  xsh_msg("Prepare S1D products" ) ;
  /* doing optimal extraction */

  if ( do_optextract){
    xsh_msg( "Optimal extraction");
    check( xsh_opt_extract( sub_sky2_frame, order_tab_edges,
			    wave_tab, model_config_frame, wavemap_frame, 
			    slitmap_frame, loc_table_frame, 
			    spectralformat_frame, master_flat, instrument,
			    opt_extract_par, rec_prefix,
			    &orderext1d_frame, &orderoxt1d_frame,
                            &orderoxt1d_eso_frame,
			    &qc_subex_frame,
			    &qc_s2ddiv1d_frame,
			    &qc_model_frame,
			    &qc_weight_frame));
/*
    check( mergeext1d_frame = xsh_merge_ord( orderext1d_frame, instrument,
 					     merge_par,rec_prefix));
*/
    check( mergeoxt1d_frame = xsh_merge_ord( orderoxt1d_frame, instrument,
					     merge_par,rec_prefix));
  }

 
  /* Telluric correction */
  xsh_msg( "Calling xsh_mark_tell (TBW)" ) ;
  //check( tell_frame = xsh_mark_tell(ext_frame, tell_mask, tell_params )) ;
  check( tell_frame = cpl_frame_duplicate( ext_frame ) ) ;

  /* Response computation */
  if(frm_std_cat!=NULL && frm_atmext!=NULL && 
     resp_fit_points_cat_frame != NULL) {
     xsh_msg( "Calling xsh_compute_response" ) ;


     if ( do_optextract){
        frame_ord_by_ord=orderoxt1d_eso_frame;
        frame_merged= mergeoxt1d_frame;
     } else {
        frame_ord_by_ord=ext_frame_eso;
        frame_merged=res_1D_frame;
     }
     if( (response_ord_frame = xsh_compute_response_ord(frame_ord_by_ord,
                                                        frm_std_cat,
                                                        frm_atmext,
                                                        high_abs_win,
                                                        instrument,
                                                        exptime )) == NULL) {
       xsh_msg_warning("Some error occurred computing response frame. Recover from it.");
       xsh_print_rec_status(0);
        cpl_error_reset();
     } 

     if( (response_frame = xsh_compute_response2(frame_merged,
                                                frm_std_cat,
                                                frm_atmext,
                                                high_abs_win,
                                                resp_fit_points_cat_frame,
                                                tell_mod_cat,
                                                instrument,
						exptime,corr_tell )) == NULL) {
       xsh_msg_warning("Some error occurred computing response frame. Recover from it.");
       xsh_print_rec_status(0);
       cpl_error_reset();
     } else {

        check(xsh_frame_table_monitor_flux_qc(response_frame,"LAMBDA",
                                              "RESPONSE","RESP",instrument));
     }
  }
  if(mresponse_frame != NULL) {
    check(xsh_flux_calibrate(rect2_frame_eso,ext_frame_eso,frm_atmext,
			     mresponse_frame,merge_par,instrument,rec_prefix,
			     &fluxcal_rect_2D_frame,&fluxcal_rect_1D_frame,
			     &fluxcal_2D_frame,&fluxcal_1D_frame));

    if ( do_optextract){

    check(xsh_flux_calibrate1D(orderoxt1d_eso_frame,frm_atmext,
			     mresponse_frame,merge_par,instrument,rec_prefix,
			     &fluxcal_rect_opt1D_frame,
                             &fluxcal_merg_opt1D_frame));

    }

  }
  else if(mresponse_frame == NULL && response_frame != NULL) {

    check(xsh_flux_calibrate(rect2_frame_eso,ext_frame_eso,frm_atmext,
			     response_frame,merge_par,instrument,rec_prefix,
			     &fluxcal_rect_2D_frame,&fluxcal_rect_1D_frame,
			     &fluxcal_2D_frame,&fluxcal_1D_frame));

   if ( do_optextract){

    check(xsh_flux_calibrate1D(orderoxt1d_eso_frame,frm_atmext,
			     response_frame,merge_par,instrument,rec_prefix,
			     &fluxcal_rect_opt1D_frame,
                             &fluxcal_merg_opt1D_frame));

    }
  }

  /* efficiency part */
  if(response_ord_frame != NULL && disp_tab_frame != NULL) {
     int conserve_flux=rectify_par->conserve_flux;
     xsh_msg( "Calling xsh_multiply_flat" ) ;
     sprintf(file_tag,"SLIT_STARE_NOCRH_NOT_FF_%s",arm_str) ;
     if(do_flatfield) {
        check( eff_frame = xsh_multiply_flat( div_clean_frame, master_flat, 
                                              file_tag, instrument ) ) ;
     } else {
        check(eff_frame=cpl_frame_duplicate(div_clean_frame));
     }
     sprintf(file_name,"%s_EFF_%s_%s.fits",rec_prefix,XSH_ORDER2D,
             xsh_instrument_arm_tostring(instrument));
     rectify_par->conserve_flux=1;  
     xsh_add_temporary_file(file_name);
     check( rect_eff_frame = xsh_rectify( eff_frame, 
                                          order_tab_edges,
                                          wave_tab,
                                          model_config_frame,
                                          instrument,
                                          rectify_par, 
                                          spectralformat_frame,
                                          disp_tab_frame,
                                          file_name,
                                          &rect_eff_frame_eso,
                                          &rect_eff_frame_tab,
                                          rec_prefix));
      xsh_msg( "Calling xsh_extract" ) ;
     check( ext_eff_frame = xsh_extract_clean(rect_eff_frame,loc_table_frame, 
                                        instrument,&extract_par, ipol_bp,
                                        &ext_eff_frame2,rec_prefix)) ;
     xsh_msg("name %s",cpl_frame_get_filename(ext_eff_frame2));
    
     frm_eff=xsh_compute_efficiency(ext_eff_frame2,frm_std_cat,
					 frm_atmext,high_abs_win,instrument);
     rectify_par->conserve_flux=conserve_flux;  

  }

  if(model_config_frame!=NULL && wavemap_frame != NULL&& slitmap_frame != NULL) {

     check(xsh_compute_resampling_accuracy(wavemap_frame,slitmap_frame,order_tab_edges,model_config_frame,res_2D_frame,instrument));
     check(xsh_compute_resampling_accuracy(wavemap_frame,slitmap_frame,order_tab_edges,model_config_frame,rect2_frame_eso,instrument));

     check(xsh_compute_wavelength_resampling_accuracy(wavemap_frame,order_tab_edges,model_config_frame,res_1D_frame,instrument));
     check(xsh_compute_wavelength_resampling_accuracy(wavemap_frame,order_tab_edges,model_config_frame,ext_frame_eso,instrument));

     xsh_add_afc_info(model_config_frame,wavemap_frame);
     xsh_add_afc_info(model_config_frame,slitmap_frame);

     if(fluxcal_rect_2D_frame != NULL) {

        check(xsh_compute_resampling_accuracy(wavemap_frame,slitmap_frame,order_tab_edges,model_config_frame,fluxcal_rect_2D_frame,instrument));
        check(xsh_compute_resampling_accuracy(wavemap_frame,slitmap_frame,order_tab_edges,model_config_frame,fluxcal_2D_frame,instrument));

        check(xsh_compute_wavelength_resampling_accuracy(wavemap_frame,order_tab_edges,model_config_frame,fluxcal_rect_1D_frame,instrument));
        check(xsh_compute_wavelength_resampling_accuracy(wavemap_frame,order_tab_edges,model_config_frame,fluxcal_1D_frame,instrument));

     }

     if(res_2D_sky_frame) {
       check(xsh_compute_resampling_accuracy(wavemap_frame,slitmap_frame,order_tab_edges,model_config_frame,res_2D_sky_frame,instrument));
     }

     if ( do_sub_sky == 1 ) {
       check(xsh_compute_wavelength_resampling_accuracy(wavemap_frame,order_tab_edges,model_config_frame,sky_frame_eso,instrument));
     }
  }



  xsh_msg( "Save products.");
  if(response_ord_frame!=NULL) {
    check( xsh_add_product_table(response_ord_frame,frameset,parameters,
				       RECIPE_ID,instrument,NULL));
  }

  if(response_frame!=NULL) {
    check( xsh_add_product_table(response_frame,frameset,parameters,
                                 RECIPE_ID,instrument,NULL));
  }

  check( xsh_add_product_image(rect2_frame_eso, frameset, parameters,
			       RECIPE_ID, instrument,NULL));

  check( xsh_add_product_image(ext_frame_eso, frameset, parameters,
			       RECIPE_ID, instrument,NULL));

  check( xsh_add_product_spectrum(res_2D_frame, frameset, parameters, 
                                  RECIPE_ID, instrument, NULL));

  check( xsh_add_product_spectrum(res_1D_frame, frameset, parameters, 
                                  RECIPE_ID, instrument, NULL));

  if(res_2D_sky_frame) {
    check( xsh_add_product_spectrum( res_2D_sky_frame, frameset, parameters, 
				     RECIPE_ID, instrument, NULL));
    check( xsh_add_product_spectrum( res_1D_sky_frame, frameset, parameters,
				      RECIPE_ID, instrument, NULL));
  }
  if(fluxcal_2D_frame != NULL) {


     check( xsh_add_product_image( fluxcal_rect_2D_frame, frameset, parameters, 
                                   RECIPE_ID, instrument,NULL));
 
    check( xsh_add_product_image( fluxcal_rect_1D_frame, frameset, parameters, 
                                  RECIPE_ID, instrument,NULL));

     check( xsh_add_product_spectrum( fluxcal_2D_frame, frameset, parameters, 
                                      RECIPE_ID, instrument, NULL));
 
    check( xsh_add_product_spectrum( fluxcal_1D_frame, frameset, parameters, 
                                      RECIPE_ID, instrument, NULL));

     if ( do_optextract){

        check( xsh_add_product_image( fluxcal_rect_opt1D_frame, frameset,
                                      parameters, RECIPE_ID, instrument,NULL));

        check( xsh_add_product_spectrum( fluxcal_merg_opt1D_frame, frameset, 
                                         parameters, RECIPE_ID, instrument, NULL));
	check( xsh_add_product_image( qc_subex_frame, frameset, parameters, 
				    RECIPE_ID, instrument,
				    cpl_frame_get_tag(qc_subex_frame)));
        check( xsh_add_product_image( qc_s2ddiv1d_frame, frameset, parameters, 
				    RECIPE_ID, instrument,
				    cpl_frame_get_tag(qc_s2ddiv1d_frame)));
        check( xsh_add_product_image( qc_model_frame, frameset, parameters, 
				    RECIPE_ID, instrument,
				    cpl_frame_get_tag(qc_model_frame)));
        check( xsh_add_product_image( qc_weight_frame, frameset, parameters, 
				    RECIPE_ID, instrument,
				    cpl_frame_get_tag(qc_weight_frame)));

     }

   }

  if(frm_eff!=NULL) {
     check(xsh_add_product_table(frm_eff, frameset,parameters, 
                                       RECIPE_ID, instrument,NULL));
  }

cleanup:
  
  xsh_end( RECIPE_ID, frameset, parameters );
  XSH_FREE(rec_prefix);
  XSH_FREE(ipol_bp);
  XSH_FREE( backg_par ) ;
  XSH_FREE( crh_single_par ) ;
  XSH_FREE( rectify_par ) ;
  XSH_FREE( loc_obj_par ) ;
  XSH_FREE( sky_par ) ;
  XSH_FREE( opt_extract_par ) ;
  xsh_instrument_free(&instrument );

  xsh_free_frameset( &raws);
  xsh_free_frameset( &calib);
  xsh_free_frame( &rmbias);
  xsh_free_frame( &rmdark);
  xsh_free_frame( &rmbkg);

  xsh_free_frame( &rm_crh);
  xsh_free_frame( &bpmap);
  xsh_free_frame( &div_frame);
  xsh_free_frame( &wavemap_frame);
  xsh_free_frame( &slitmap_frame);
  xsh_free_frame( &sky_frame);
  xsh_free_frame( &sky_frame_eso);
  xsh_free_frame( &sky_frame_ima);

  xsh_free_frame( &sub_sky_frame);
  xsh_free_frame( &sub_sky2_frame);
  xsh_free_frame( &rect_frame_tab) ;
  xsh_free_frame( &rect_frame) ;

  xsh_free_frame(&rect2_frame) ;
  xsh_free_frame(&rect2_frame_eso) ;
  xsh_free_frame(&rect2_frame_tab) ;

  xsh_free_frame(&rect2_sky_frame) ;
  xsh_free_frame(&rect2_sky_frame_eso) ;
  xsh_free_frame(&rect2_sky_frame_tab) ;


  xsh_free_frame( &loc_table_frame) ;
  xsh_free_frame( &response_frame) ;
  xsh_free_frame( &response_ord_frame) ;

  xsh_free_frame(& eff_frame);
  xsh_free_frame(& rect_eff_frame);
  xsh_free_frame(& rect_eff_frame_eso);
  xsh_free_frame(& rect_eff_frame_tab);
  xsh_free_frame(& ext_eff_frame);
  xsh_free_frame(& ext_eff_frame2);
  xsh_free_frame(&fluxcal_rect_1D_frame) ;
  xsh_free_frame(&fluxcal_rect_2D_frame) ;
  xsh_free_frame(&fluxcal_1D_frame) ;
  xsh_free_frame(&fluxcal_2D_frame) ;

  xsh_free_frame( &ext_frame ) ;
  xsh_free_frame( &frm_eff ) ;
  xsh_free_frame( &ext_frame_eso ) ;
  xsh_free_frame( &clean_frame) ;
  xsh_free_frame( &div_clean_frame) ;
  xsh_free_frame( &clean_obj) ;
  xsh_free_frame( &res_1D_frame) ;
  xsh_free_frame( &res_2D_frame) ;
  xsh_free_frame(&res_2D_sky_frame) ;
  xsh_free_frame(&res_1D_sky_frame) ;

  xsh_free_frame( &tell_frame ) ;
  xsh_free_frame( &grid_backg ) ;
  xsh_free_frame( &frame_backg ) ;
  xsh_free_frame( &qc_subex_frame);
  xsh_free_frame(&qc_s2ddiv1d_frame);
  xsh_free_frame(&qc_model_frame);
  xsh_free_frame(&qc_weight_frame);
  
  /*
  xsh_free_frame( &spectralformat_frame ) ;
  */
  return CPL_ERROR_NONE;
}

/**@}*/
