/*                                                                            *
 *   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 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     *
 *                  nod_step                                                          */
/*
 * $Author: amodigli $
 * $Date: 2013-10-02 15:48:49 $
 * $Revision: 1.269 $
 * $Name: not supported by cvs2svn $
 */

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

/*----------------------------------------------------------------------------
                                 Includes
 ----------------------------------------------------------------------------*/
#include <xsh_parameters.h>
#include <xsh_model_arm_constants.h>
#include <xsh_badpixelmap.h>
#include <xsh_msg.h>
#include <xsh_error.h>
#include <xsh_drl.h>
#include <strings.h>

/**
 * @defgroup xsh_parameters  Recipe Parameters
 * @ingroup xsh_tools
 */

/*----------------------------------------------------------------------------
                                 Prototypes
 ---------------------------------------------------------------------------*/

void xsh_parameters_new_int( cpl_parameterlist* list,
  const char* recipe_id, const char* name,int value, const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL"); 

  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_INT,comment,
    recipename,value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}


void xsh_parameters_new_boolean( cpl_parameterlist* list,
  const char* recipe_id, const char* name,int value, const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;
                                                                                                                                                             
                                                                                                                                                             
  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  XSH_ASSURE_NOT_NULL(list);                                                                                                                                                             
  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_BOOL,comment,
    recipename,value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));
                                                                                                                                                             
  cleanup:
    return;
}

static void xsh_parameters_new_string( cpl_parameterlist* list,
				       const char* recipe_id,
				       const char* name,
				       const char* value,
				       const char* comment)
{
  char * paramname = NULL ;
  char * recipename = NULL ;
  cpl_parameter* p =NULL;

  recipename = xsh_stringcat_any( "xsh.", recipe_id, (void*)NULL );
  paramname = xsh_stringcat_any( recipename, ".", name, (void*)NULL );

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL"); 

  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_STRING, comment,
				    recipename, value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

 cleanup:
  XSH_FREE(recipename);
  XSH_FREE(paramname);
  return;
}

void xsh_parameters_new_double( cpl_parameterlist* list,
  const char* recipe_id,const char* name,double value, const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_DOUBLE,comment,
    recipename,value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}

static void 
xsh_parameters_new_bool( cpl_parameterlist* list,
  const char* recipe_id,const char* name,bool value, const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_BOOL,comment,
    recipename,value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}

static void 
xsh_parameters_new_float( cpl_parameterlist* list,
  const char* recipe_id,const char* name,float value, const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(p = cpl_parameter_new_value(paramname,CPL_TYPE_FLOAT,comment,
    recipename,value));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}

static void xsh_parameters_new_range_int( cpl_parameterlist* list,
					  const char* recipe_id,
					  const char* name,
					  int def, int min, int max,
					  const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(p = cpl_parameter_new_range( paramname,CPL_TYPE_INT, comment,
    recipename, def, min, max ));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}



static void xsh_parameters_new_range_double( cpl_parameterlist* list,
					  const char* recipe_id,
					  const char* name,
					  double def, double min, double max,
					  const char* comment)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;


  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(p = cpl_parameter_new_range( paramname,CPL_TYPE_DOUBLE, comment,
    recipename, def, min, max ));
  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,name));
  check(cpl_parameterlist_append(list,p));

  cleanup:
    return;
}



char * xsh_parameters_get_string( const cpl_parameterlist* list,
  const char* recipe_id, const char* name)
{
  char paramname[256];
  cpl_parameter * p =NULL;
  char * result = NULL ;

  sprintf(paramname,"xsh.%s.%s",recipe_id, name);

  p = cpl_parameterlist_find( (cpl_parameterlist *)list, paramname);
  if ( p == NULL ) goto cleanup ;
  result = (char *)cpl_parameter_get_string(p) ;

  cleanup:
    return result;
}


int xsh_parameters_get_boolean( const cpl_parameterlist * list,
				const char* recipe_id, const char* name)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;
  int result = 0;
                                                                                                                                                             
  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);
                                
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");
         
  check(p = cpl_parameterlist_find( (cpl_parameterlist *)list,paramname));
  check(result = cpl_parameter_get_bool( p));

  cleanup:
    return result;
}


int xsh_parameters_get_int(const cpl_parameterlist* list,
  const char* recipe_id, const char* name)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;
  int result = 0;
  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");
  check(p = cpl_parameterlist_find( (cpl_parameterlist *)list,paramname));
  check(result = cpl_parameter_get_int(p));

  cleanup:
    return result;
}

double xsh_parameters_get_double(const cpl_parameterlist* list,
  const char* recipe_id, const char* name)
{
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;
  double result = 0.0;

  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,name);

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");
  
  check(p = cpl_parameterlist_find(list,paramname));
  check(result = cpl_parameter_get_double(p));

  cleanup:
    return result;
} 

/**@{*/


/*---------------------------------------------------------------------------*/
/**
  @brief find a parameter

  @param list the parameters list to search in
  @param recipe_id the current recipe in use
  @param name the parameter name
  @return the parameter
*/
/*---------------------------------------------------------------------------*/

cpl_parameter* xsh_parameters_find( cpl_parameterlist* list,
  const char* recipe_id, const char* name)
{

  char paramname[256];
  cpl_parameter * result = NULL ;
 
  sprintf(paramname,"xsh.%s.%s",recipe_id, name);
  check(result = cpl_parameterlist_find( (cpl_parameterlist *)list, paramname));
 
  cleanup:
    return result;

}


void xsh_parameters_pre_overscan( const char *recipe_id,
			     cpl_parameterlist * plist )
{
  cpl_parameter* p=NULL;
  char paramname[256];
  char recipename[256];

  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

				
  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,"pre-overscan-corr");

  check(p = cpl_parameter_new_enum(paramname,CPL_TYPE_INT,
				   "pre-overscan correction."
                                   "0: no correction"
                                   "1: mean overscan correction"
                                   "2: mean prescan correction"
                                   "3: (mean pre+mean overscan)/2 correction"
				   // "4: ima raw based on overscan"
                                   // "5: ima raw based on prescan"
                                   // "6: ima raw based on pre and overscan"
				   ,recipename,1,
                                   4,0,1,2,3));

  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
				"pre-overscan-corr"));
  check(cpl_parameterlist_append(plist,p));

 cleanup:
  return ;
}

void xsh_parameters_generic( const char *recipe_id,
			     cpl_parameterlist * plist )
{
  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  check( xsh_parameters_new_string( plist, recipe_id, "keep-temp", "no",
	 "If 'no', temporary files are deleted." ) ) ;
  check( xsh_parameters_new_string( plist, recipe_id, "debug-level",
				    "none",
  "Additional xshooter debug level. One of 'none', 'low', 'medium', 'high'"));
  /*
  check( xsh_parameters_new_string( plist, recipe_id, "test",
				    "none",
  "Can be any string, usage depends on recipe. Used during development phases" ) ) ;
  */
  check( xsh_parameters_new_boolean(plist,recipe_id, "time-stamp",
				    FALSE,
				    "Add timestamp to product file name." )) ;

 cleanup:
  return ;
}

cpl_error_code
xsh_parameters_decode_bp( const char *recipe_id,
                          cpl_parameterlist * plist,const int ival )
{
    XSH_ASSURE_NOT_NULL( recipe_id ) ;
    XSH_ASSURE_NOT_NULL( plist ) ;
    int mval=DECODE_BP_FLAG_MAX;
    int val=0;
    if(ival<0) {
        val=DECODE_BP_FLAG_DEF;
    } else {
        val=ival;
    }
    check(xsh_parameters_new_range_int( plist, recipe_id,"decode-bp",
                    val, 0,mval,"Integer representation of the bits to be considered bad when decoding the bad pixel mask pixel values. \n\
 Most frequent codes relevant for the user: \n\
 0: good pixel, \n\
 8: pick-up noise, \n\
 16: cosmic-ray removed, \n\
 32: cosmic-ray unremoved, \n\
 128: calibration file defect, \n\
 256: hot pixel, \n\
 512: dark pixel, \n\
 4096: A/D converted saturation, \n\
 32768: non linear pixel, \n\
 1048576: extrapolated flux in NIR, \n\
 4194304: Interpolated flux during extraction."));
    cleanup:
    return cpl_error_get_code();
}

cpl_error_code
xsh_parameters_decode_bp_set( const char *rec_id,cpl_parameterlist * parameters,const int ival)
{

  cpl_parameter* p = NULL;
  const char* pname = "decode-bp";
  p = xsh_parameters_find(parameters, rec_id, pname);
  cpl_parameter_set_int(p, ival);

  return cpl_error_get_code();
}

int xsh_parameters_get_temporary( const char * recipe_id,
				  const cpl_parameterlist * list )
{
  char * result = NULL ;

  result = xsh_parameters_get_string( list, recipe_id,
				      "keep-temp" ) ;
  if ( result == NULL ) {
    xsh_msg( "Cant get parameter 'keep-temp'" ) ;
    return 1 ;
  }
  else if ( strcasecmp( result, "yes" ) == 0 ) return 1 ;
  else return 0 ;

}

int xsh_parameters_debug_level_get( const char * recipe_id,
				    const cpl_parameterlist * list )
{
  char * slevel = NULL ;
  int level = XSH_DEBUG_LEVEL_NONE ;

  slevel = xsh_parameters_get_string( list, recipe_id,
				      "debug-level" ) ;
  if ( slevel == NULL ) {
    xsh_msg( "Cant get parameter 'debug-level'" ) ;
  }
  else if ( strcmp( slevel, "low" ) == 0 ) level = XSH_DEBUG_LEVEL_LOW ;
  else if ( strcmp( slevel, "medium" ) == 0 ) level = XSH_DEBUG_LEVEL_MEDIUM ;
  else if ( strcmp( slevel, "high" ) == 0 ) level = XSH_DEBUG_LEVEL_HIGH ;
  else level = XSH_DEBUG_LEVEL_NONE ;

  xsh_debug_level_set( level ) ;
  return level ;
}

char * xsh_parameters_test_mode_get( const char * recipe_id,
				     const cpl_parameterlist * list )
{
  char * stest = NULL ;

  stest = xsh_parameters_get_string( list, recipe_id,
				      "test" ) ;
  return stest ;
}

int xsh_parameters_time_stamp_get( const char * recipe_id,
				   const cpl_parameterlist * list )
{
  int ts = FALSE ;

  ts = xsh_parameters_get_boolean( list, recipe_id, "time-stamp" ) ;

  xsh_time_stamp_set( ts ) ;

  return ts ;
}

int xsh_parameters_cut_uvb_spectrum_get( const char * recipe_id,
				   const cpl_parameterlist * list )
{
  int cut = FALSE ;

  cut = xsh_parameters_get_boolean( list, recipe_id, "cut-uvb-spectrum" ) ;

  return cut ;
}
/*---------------------------------------------------------------------------*/
/**
  @brief create the crh clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p CRH clipping parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_crh_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_clipping_param p)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  /* --crh-clip-kappa 
  check(xsh_parameters_new_double(list,recipe_id,"crh-clip-res-max", p.res_max,
    "Maximum allowed residual (before kappa-sigma clipping)"));
  */
  check(xsh_parameters_new_double(list,recipe_id,"crh-clip-kappa", p.sigma,
    "Kappa value in sigma clipping during CRH rejection using "\
    "multiple frames"));
  /* --crh-clip-niter */
  check(xsh_parameters_new_int(list,recipe_id,"crh-clip-niter", p.niter,
    "Number of iterations in sigma clipping during CRH rejection "\
    "using multiple frames"));
  /* --crh-clip-frac */
  check(xsh_parameters_new_double(list,recipe_id,"crh-clip-frac", p.frac,
    "Minimal ratio of points accepted / total in sigma clipping "\
    "during CRH rejection using multiple frames"));
  
  cleanup:
    return;
}



/*---------------------------------------------------------------------------*/
/**
  @brief create the crh clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p hot-cold pix detection parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_hot_cold_pix_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_hot_cold_pix_param p)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");


  check( xsh_parameters_new_boolean( list, recipe_id,
    "hot-cold-pix-search",
    p.hot_cold_pix_search,
    "If true hot and cold pixels are searched"));

  xsh_parameters_new_double(list,recipe_id,"cold-pix-kappa",p.cold_pix_kappa,
                           "Kappa sigma value to clip low intensity pixels");


  check(xsh_parameters_new_range_int( list, recipe_id,"cold-pix-niter",
				      p.cold_pix_niter, 1, 999,
	  "Number of kappa-sigma clip iterations (cold pixels search)."));


  xsh_parameters_new_double(list,recipe_id,"hot-pix-kappa",p.hot_pix_kappa,
                           "Kappa sigma value to clip high intensity pixels");

  check(xsh_parameters_new_range_int( list, recipe_id,"hot-pix-niter",
				      p.hot_pix_niter, 1, 999,
	  "Number of kappa-sigma clip iterations (hot pixels search)."));
  
  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief create the structX/Y region definition parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p reference region parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_struct_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_struct_param p)
{

   xsh_parameters_new_int(list,recipe_id,"struct_refx",p.ref_x,
                          "Reference X value to compute structure");

   xsh_parameters_new_int(list,recipe_id,"struct_refy",p.ref_y,
                          "Reference Y value to compute structure");
}



/*---------------------------------------------------------------------------*/
/**
  @brief create the reference region definition parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p reference region parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_ref1_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_ref_param p)
{

   xsh_parameters_new_int(list,recipe_id,"ref1_llx",p.ref_llx,
                          "Lower left X of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref1_lly",p.ref_lly,
                          "Lower left Y of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref1_urx",p.ref_urx,
                          "Upper right X of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref1_ury",p.ref_ury,
                          "Upper right Y of reference region");

}


/*---------------------------------------------------------------------------*/
/**
  @brief create the reference region definition parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p reference region parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_ref2_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_ref_param p)
{

   xsh_parameters_new_int(list,recipe_id,"ref2_llx",p.ref_llx,
                          "Lower left X of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref2_lly",p.ref_lly,
                          "Lower left Y of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref2_urx",p.ref_urx,
                          "Upper right X of reference region");

   xsh_parameters_new_int(list,recipe_id,"ref2_ury",p.ref_ury,
                          "Upper right Y of reference region");

}


/*---------------------------------------------------------------------------*/
/**
  @brief create the RON determination parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p RON parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_ron_dark_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_ron_dark_param p)
{

   xsh_parameters_new_int(list,recipe_id,"ron_llx",p.ron_llx,
                          "Lower left X of reference region to measure RON");

   xsh_parameters_new_int(list,recipe_id,"ron_lly",p.ron_lly,
                          "Lower left Y of reference region to measure RON");

   xsh_parameters_new_int(list,recipe_id,"ron_urx",p.ron_urx,
                          "Upper right X of reference region to measure RON");

   xsh_parameters_new_int(list,recipe_id,"ron_ury",p.ron_ury,
                          "Upper right Y of reference region to measure RON");

  xsh_parameters_new_int(list,recipe_id,"ron_hsize",p.ron_hsize,
                          "Sampling area size");
                             

  xsh_parameters_new_int(list,recipe_id,"ron_nsamples",p.ron_nsamp,
                          "Number of random samples");
                              
 

}


/*---------------------------------------------------------------------------*/
/**
  @brief create the RON determination parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p RON parameters structure
*/
/*---------------------------------------------------------------------------*/
void 
xsh_parameters_stack_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_stack_param sp)
{

  char * paramname = NULL ;
  char * recipename = NULL ;
  const char* aliasname="stack-method";
  cpl_parameter* p =NULL;

  recipename = xsh_stringcat_any( "xsh.", recipe_id, (void*)NULL );
  paramname = xsh_stringcat_any( recipename, ".", aliasname, (void*)NULL );

  p = cpl_parameter_new_enum(paramname,CPL_TYPE_STRING,
			     "Method used to build master frame.",
			     recipe_id,"median",
			     2,"median","mean");

  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
			  aliasname);
  cpl_parameterlist_append(list,p);

  xsh_parameters_new_double(list,recipe_id,"klow",sp.klow,
			 "Kappa used to clip low level values, when method is set to 'mean'");

  xsh_parameters_new_double(list,recipe_id,"khigh",sp.khigh,
			 "Kappa used to clip high level values, when method is set to 'mean'");

  XSH_FREE(recipename);
  XSH_FREE(paramname);

}
/*---------------------------------------------------------------------------*/
/**
  @brief create the RON determination parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p RON parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_ron_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_ron_param p)
{


   xsh_ref_param ref_params = {p.ron_ref_llx,p.ron_ref_lly,
                              p.ron_ref_urx,p.ron_ref_ury};


   xsh_parameters_new_string(list,recipe_id,"ron_method",p.ron_method,
                             "RON computation method");

   xsh_parameters_new_int(list,recipe_id,"random_sizex",p.ron_random_sizex,
                          "Region X size for random computation");

   xsh_parameters_new_int(list,recipe_id,"random_nsamples",p.ron_random_nsamples,
                          "Number of random samples");


   xsh_parameters_ref1_create(recipe_id,list,ref_params);
   xsh_parameters_ref2_create(recipe_id,list,ref_params);


   xsh_parameters_new_int(list,recipe_id,"stacking_ks_low",p.stacking_ks_low,
                          "Lower value of kappa-sigma clip in stacking");

   xsh_parameters_new_int(list,recipe_id,"stacking_ks_iter",p.stacking_ks_iter,
                          "Number of iterations in kappa-sigma clip in stacking");


}



/*---------------------------------------------------------------------------*/
/**
  @brief create the FPN parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p Fixed Pattern Noise parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_fpn_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_fpn_param p)
{

   xsh_parameters_new_int(list,recipe_id,"fpn_llx",p.fpn_llx,
			  "Lower left reference area X coordinate for "
                          "Fixed Pattern Noise computation");

   xsh_parameters_new_int(list,recipe_id,"fpn_lly",p.fpn_lly,
			  "Lower left reference area Y coordinate for "
                          "Fixed Pattern Noise computation");

   xsh_parameters_new_int(list,recipe_id,"fpn_urx",p.fpn_urx,
			  "Upper right reference area X coordinate for "
                          "Fixed Pattern Noise computation");

   xsh_parameters_new_int(list,recipe_id,"fpn_ury",p.fpn_ury,
			  "Upper right reference area Y coordinate for "
                          "Fixed Pattern Noise computation");

   xsh_parameters_new_int(list,recipe_id,"fpn_hsize",p.fpn_hsize,
			      "Sample size for "
                          "Fixed Pattern Noise computation");


   xsh_parameters_new_int(list,recipe_id,"fpn_nsamples",p.fpn_nsamples,
			  "Number of sampling points for "
                          "Fixed Pattern Noise computation");

}

/*---------------------------------------------------------------------------*/
/**
  @brief get the crh clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param* xsh_parameters_clipping_crh_get(const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_clipping_param*)(cpl_malloc(sizeof(xsh_clipping_param)))
    );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
    "Memory allocation failed!");
 
 /* Fill the structure */
  /*
  check(result->res_max = xsh_parameters_get_double(list,recipe_id,
    "crh-clip-res-max"));
  */
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "crh-clip-kappa"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "crh-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "crh-clip-frac"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}
/****************** detect continuum **************/
/*---------------------------------------------------------------------------*/
/**
  @brief create the crh noise clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param noise_param structure describing noise params
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_noise_create(const char* recipe_id,
					  cpl_parameterlist* list,
					  xsh_clipping_param noise_param)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  /* --noise-clip-kappa */
  check(xsh_parameters_new_double(list,recipe_id,"noise-clip-kappa",
				  noise_param.sigma,
				  "Multiple of sigma in sigma clipping"));
  /* --noise-clip-niter */
  check(xsh_parameters_new_int(list,recipe_id,"noise-clip-niter",
			       noise_param.niter,
			       "Number of iterations in sigma clipping"));
  /* --noise-clip-frac */
  check(xsh_parameters_new_double(list,recipe_id,"noise-clip-frac",
				  noise_param.frac,
				  "Minimal fractions of bad pixel allowed"));
  /* --noise-clip-diff */
  check(xsh_parameters_new_double(list,recipe_id,"noise-clip-diff",
				  noise_param.diff,
				  "Minimum relative change in sigma for sigma clipping"));
  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief get the noise clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param* xsh_parameters_clipping_noise_get(const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_clipping_param*)(cpl_malloc(sizeof(xsh_clipping_param)))
    );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
    "Memory allocation failed!");

 /* Fill the structure */
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "noise-clip-kappa"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "noise-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "noise-clip-frac"));
  check(result->diff = xsh_parameters_get_double(list,recipe_id,
    "noise-clip-diff"));
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Create the detect order parameters in a parameters list

  @param[in] recipe_id
    The current recipe in use
  @param list
    The parameters list to update 
*/
/*---------------------------------------------------------------------------*/

void xsh_parameters_detect_order_create(const char* recipe_id,
  cpl_parameterlist* list)
{

  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  /* --detectorder-search-window-half-size */
  check( xsh_parameters_new_int( list, recipe_id, 
    "detectorder-edges-search-win-hsize",
    50,
    "Half window size in pixels for the search for order edges"));

  /* --detectorder-edges-threshold-factor */
  check( xsh_parameters_new_double( list, recipe_id,
    "detectorder-edges-flux-thresh",
    0.4,
    "Threshold in relative flux (compared to the central flux) "\
    "below which the order edges are defined"));
  /* --detectorder-min-sn */
  check( xsh_parameters_new_double( list, recipe_id,
    "detectorder-min-sn",
    -1,
    "Minimum signal-to-noise ratio at the centroid of the orders (60 for SLIT-UVB,VIS,NIR, 20 for IFU-UVB,VIS, 4 for IFU-NIR"));
  /* --detectorder-min-order-size-x */
  check( xsh_parameters_new_int( list, recipe_id,
    "detectorder-min-order-size-x",
    -1,
    "Minimum order size in pixels along X direction [60 for UVB,VIS, 40 for NIR]"));
  check( xsh_parameters_new_int( list, recipe_id,
    "detectorder-chunk-half-size",
    1,
    "Half size in pixels of the chunks in Y direction"));

  /* --detectorder-slitlet-low-factor */
  check( xsh_parameters_new_double( list, recipe_id,
    "detectorder-slitlet-low-factor",
    1.0,
    "Factor for slitlet on lower edge slitlet (IFU)"));
  /* --detectorder-slitlet-up-factor */
  check( xsh_parameters_new_double( list, recipe_id,
    "detectorder-slitlet-up-factor",
    1.0,
    "Factor for slitlet on upper edge (IFU)"));
  check( xsh_parameters_new_boolean( list, recipe_id,
    "detectorder-fixed-slice",
    CPL_TRUE,
    "If true the size of slitlet is fixed (IFU)"));



  sprintf(recipename,"xsh.%s",recipe_id);
  sprintf(paramname,"%s.%s",recipename,"detectorder-slice-trace-method");

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL"); 

  check(p = cpl_parameter_new_enum(paramname,CPL_TYPE_STRING,
				   "method adopted for IFU slice tracing ('fixed' for SLIT and 'sobel' for IFU):",
				   recipename,"auto",
                                   4,"auto","fixed","sobel","scharr"));

  check(cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
				"detectorder-slice-trace-method"));
  check(cpl_parameterlist_append(list,p));

  check( xsh_parameters_new_boolean( list, recipe_id,
    "detectorder-qc-mode",
    CPL_FALSE,
    "If true allows one to skip edge detection on orders below detectorder-min-sn (oly for QC mode, not to be set by normal users)"));

  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the detect orders parameters in a parameters list

  @param recipe_id
    The current recipe in use
  @param list
    The parameters list to search
  @return 
    A NEWLY allocated structure of detect orders parameters
*/
/*---------------------------------------------------------------------------*/

xsh_detect_order_param* xsh_parameters_detect_order_get(const char* recipe_id,
  cpl_parameterlist* list,cpl_parameterlist* drs)
{
  xsh_detect_order_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_detect_order_param, 1);

 /* Fill the structure */
  check( result->search_window_hsize = xsh_parameters_get_int( list, recipe_id,
    "detectorder-edges-search-win-hsize"));
  check( result->flux_thresh = xsh_parameters_get_double( list, recipe_id,
    "detectorder-edges-flux-thresh"));
  check( result->min_sn = xsh_parameters_get_double( list, recipe_id,
    "detectorder-min-sn"));
  check( result->min_order_size_x = xsh_parameters_get_int( list, recipe_id,
    "detectorder-min-order-size-x"));
  check( result->chunk_hsize = xsh_parameters_get_int( list, recipe_id,
    "detectorder-chunk-half-size"));
  check( result->slitlet_low_factor = xsh_parameters_get_double( list,recipe_id,
    "detectorder-slitlet-low-factor"));
  check( result->slitlet_up_factor = xsh_parameters_get_double( list,recipe_id,
    "detectorder-slitlet-up-factor"));
  check( result->fixed_slice = xsh_parameters_get_boolean( list,recipe_id,
    "detectorder-fixed-slice"));

  check( result->method = xsh_parameters_get_string( list,recipe_id,
    "detectorder-slice-trace-method"));
  if(drs==NULL) {
    result->qc_mode= false;
  } else {
  check( result->qc_mode = xsh_parameters_get_boolean( drs,recipe_id,
    "detectorder-qc-mode"));
  }
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
}
/*---------------------------------------------------------------------------*/
/**
  @brief
    Create the d2 detect order parameters in a parameters list

  @param[in] recipe_id
    The current recipe in use
  @param list
    The parameters list to update 
*/
/*---------------------------------------------------------------------------*/

void xsh_parameters_d2_detect_order_create(const char* recipe_id,
  cpl_parameterlist* list)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */

  /* --detectorder-d2-min-sn */
  check( xsh_parameters_new_range_double( list, recipe_id,
    "detectorder-d2-min-sn",
                                          60.,0,150,
    "minimum signal noise ratio in D2 lamp frame in order"));
  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the d2 detect orders parameters in a parameters list

  @param recipe_id
    The current recipe in use
  @param list
    The parameters list to search
  @return 
    A NEWLY allocated structure of d2 detect orders parameters
*/
/*---------------------------------------------------------------------------*/

xsh_d2_detect_order_param* xsh_parameters_d2_detect_order_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_d2_detect_order_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_d2_detect_order_param, 1);

 /* Fill the structure */
  check( result->min_sn = xsh_parameters_get_double( list, recipe_id,
    "detectorder-d2-min-sn"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
}

/*---------------------------------------------------------------------------*/
/**
  @brief create the subtract background parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_background_create( const char* recipe_id,
  cpl_parameterlist* list)
{
  /*
  char paramname[256];
  char recipename[256];
  cpl_parameter* p =NULL;
  */
  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);


  /* Fill the parameter list */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL"); 

  check( xsh_parameters_new_range_int( list, recipe_id,
      "background-edges-margin",
      1,0,15,
      "X margin to order edge to define background sampling points"));

  check( xsh_parameters_new_range_int( list, recipe_id,
     "background-poly-deg-y",
                                       9,0,15,
     "Poly mode fit deg along Y."));

  check( xsh_parameters_new_range_int( list, recipe_id,
      "background-poly-deg-x",
                                 9,0,15,
      "Poly mode fit deg along X."));

  check( xsh_parameters_new_range_double( list, recipe_id,
       "background-poly-kappa",
                                    10.0,0,100,
       "Poly mode kappa value of kappa-sigma-clip outliers removal."));

  /*
  check( xsh_parameters_new_boolean( list, recipe_id,
    "background-debug",
    CPL_TRUE, 
   "Generate a table containing the background sampling grid points"));
  */
  cleanup:
    return;
}
/*---------------------------------------------------------------------------*/
/**
  @brief get the background parameters in a parameters list
    
  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of background parameters
*/
/*---------------------------------------------------------------------------*/

xsh_background_param* xsh_parameters_background_get(const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_background_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list );

  /* allocate the structure */
  XSH_MALLOC( result, xsh_background_param, 1); 
  memset(result, 0x0, sizeof(*result));

 /* Fill the structure */
  check(result->edges_margin = xsh_parameters_get_int(list,recipe_id,
      "background-edges-margin"));

  check(result->poly_deg_x = xsh_parameters_get_int(list,recipe_id,
    "background-poly-deg-x"));

  check(result->poly_deg_y = xsh_parameters_get_int(list,recipe_id,
    "background-poly-deg-y"));

  check(result->poly_kappa = xsh_parameters_get_double(list,recipe_id,
    "background-poly-kappa"));

  /*
  check(result->debug = xsh_parameters_get_boolean(list,recipe_id,
    "background-debug"));
  */
  result->debug=true;

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
}

/*---------------------------------------------------------------------------*/
/**
  @brief create the detect arclines parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p Parameters structure

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

void xsh_parameters_detect_arclines_create(const char* recipe_id,
  cpl_parameterlist* list,  xsh_detect_arclines_param p)
{
  const char *method_string = NULL; 
  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* --detectarclines-fit-win-hsize */
  check( xsh_parameters_new_int(list,recipe_id,
    "detectarclines-fit-win-hsize",
    p.fit_window_hsize, 
    "Half window size (HWS) in pixels for the line 2D fitting window"\
    " (total window size = 2*HWS+1)"));
  /* --detectarclines-search-win-hsize */
  check( xsh_parameters_new_int(list,recipe_id,
    "detectarclines-search-win-hsize",
    p.search_window_hsize,
    "Half window size (HWS) in pixels for the line search box around "\
    "the expected position (total window size = 2*HWS+1) [bin units]"));
  /* --detectarclines-running-median-hsize */
  check( xsh_parameters_new_int(list,recipe_id,
    "detectarclines-running-median-hsize",
     p.running_median_hsize,
    "Half window size in pixels (HWS) for the running median box"));
  /* --detectarclines-wavesol-deg-lambda*/
  check( xsh_parameters_new_int( list, recipe_id, 
    "detectarclines-wavesol-deg-lambda",
    p.wavesol_deg_lambda, 
    "Degree in lambda in the polynomial solution "\
    "X=f(lambda,order,slit) and Y=f(lambda,order,slit) (POLY mode)"));
  /* --detectarclines-wavesol-deg-order */
  check( xsh_parameters_new_int( list, recipe_id, 
    "detectarclines-wavesol-deg-order",
    p.wavesol_deg_order, 
    "Degree in order in the polynomial solution "\
    "X=f(lambda,order,slit) and Y=f(lambda,order,slit) (POLY mode)"));
  if( strcmp("xsh_2dmap",recipe_id) == 0 ) {
  /* --detectarclines-wavesol-deg-slit */
  check( xsh_parameters_new_int( list, recipe_id, 
    "detectarclines-wavesol-deg-slit",
    p.wavesol_deg_slit, 
    "Degree in slit in the polynomial solution "\
    "X=f(lambda,order,slit) and Y=f(lambda,order,slit) (POLY mode)"));

  }

  /* --detectarclines-ordertab-deg-y */
  if (strcmp(recipe_id, "xsh_predict") == 0) {
    check(xsh_parameters_new_int(list, recipe_id,
            "detectarclines-ordertab-deg-y",
            p.ordertab_deg_y,
            "Degree in Y in the polynomial order tracing X=f(Y)"));
  }
  /* --detectarclines-min-sn */
  check( xsh_parameters_new_double( list, recipe_id, 
    "detectarclines-min-sn",
    p.min_sn, 
    "Minimum signal-to-noise ratio to filter lines [xsh_predict: UVB,VIS=5,NIR=4; xsh_2dmap: UVB=3, VIS=6, NIR=10]"));
  /* --detectarclines-find-lines-center */
  if (  p.find_center_method == XSH_GAUSSIAN_METHOD){
     method_string= "gaussian";
  }
  else{
    method_string = "barycenter";
  }
  check( xsh_parameters_new_string( list, recipe_id, 
    "detectarclines-find-lines-center", method_string,
    "Method used to find the center of the lines: gaussian, barycenter. Gaussian method applies a Gaussian fit to the line. Barycenter method computes the line centroid." ));
  /*
  check( xsh_parameters_new_boolean( list, recipe_id,
    "detectarclines-mode-iterative", p.mode_iterative,
    "If TRUE the recipe doesn't crash if it doesn't succceeded "\
      "in producing order table."));
  */

  cleanup:
    return;
}


/*---------------------------------------------------------------------------*/
/**
  @brief get the detect arclines parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of detect orders parameters
*/
/*---------------------------------------------------------------------------*/
xsh_stack_param* xsh_stack_frames_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_stack_param* result = NULL;
  //const char *method_string = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);
  
  /* allocate the structure */
  XSH_MALLOC(result,xsh_stack_param,1);

 /* Fill the structure */
  check( result->stack_method = xsh_parameters_get_string( list, recipe_id,
    "stack-method"));

  check( result->klow = xsh_parameters_get_double( list, recipe_id,"klow"));

  check( result->khigh = xsh_parameters_get_double( list, recipe_id,"khigh"));

 cleanup:
  return result;

}

/*---------------------------------------------------------------------------*/
/**
  @brief get the detect arclines parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of detect orders parameters
*/
/*---------------------------------------------------------------------------*/
xsh_detect_arclines_param* xsh_parameters_detect_arclines_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_detect_arclines_param* result = NULL;
  const char *method_string = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);
  
  /* allocate the structure */
  XSH_MALLOC(result,xsh_detect_arclines_param,1);

 /* Fill the structure */
  check( result->fit_window_hsize = xsh_parameters_get_int( list, recipe_id,
    "detectarclines-fit-win-hsize"));
  check( result->search_window_hsize = xsh_parameters_get_int( list, 
    recipe_id, "detectarclines-search-win-hsize"));
  check( result->running_median_hsize = xsh_parameters_get_int( list,
    recipe_id, "detectarclines-running-median-hsize"));
  check( result->wavesol_deg_lambda = xsh_parameters_get_int( list, recipe_id,
    "detectarclines-wavesol-deg-lambda"));
  if (strcmp("xsh_2dmap", recipe_id) == 0) {
    check(
        result->wavesol_deg_slit = xsh_parameters_get_int( list, recipe_id, "detectarclines-wavesol-deg-slit"));
  } else {

    result->wavesol_deg_slit=0;
  }
  check( result->wavesol_deg_order = xsh_parameters_get_int( list, recipe_id,
    "detectarclines-wavesol-deg-order"));
  if (strcmp("xsh_predict", recipe_id) == 0) {
  check( result->ordertab_deg_y = xsh_parameters_get_int( list, recipe_id,
    "detectarclines-ordertab-deg-y"));
  }
  check( result->min_sn = xsh_parameters_get_double( list, recipe_id,
    "detectarclines-min-sn"));
  check( method_string = xsh_parameters_get_string( list, recipe_id,
    "detectarclines-find-lines-center"));
  if ( strcmp( method_string, "gaussian") == 0){
    result->find_center_method = XSH_GAUSSIAN_METHOD;
  }
  else{
    result->find_center_method = XSH_BARYCENTER_METHOD;
  } 
  /*
  check( result->mode_iterative = xsh_parameters_get_boolean( list, recipe_id,
    "detectarclines-mode-iterative"));
  */
  result->mode_iterative=false;
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE(result);
    }
    return result;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Create the arclines clipping parameters in a parameters list

  @param[in] recipe_id
    The current recipe in use
  @param[in] list
    The parameters list to update
  @param[in] p 
    Clipping parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_detect_arclines_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_clipping_param p)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* Fill the parameter list */
  check(xsh_parameters_new_double( list, recipe_id,
    "detectarclines-clip-sigma",
    p.sigma, 
    "Kappa value in sigma clipping during the polynomial solution "\
    "fit (POLY mode)"));
  check( xsh_parameters_new_int( list, recipe_id,
    "detectarclines-clip-niter",
    p.niter, 
    "Number of iterations in sigma clipping during the polynomial "\
    "solution fit (POLY mode)"));
  check( xsh_parameters_new_double( list, recipe_id,
    "detectarclines-clip-frac",
    p.frac, 
    "Minimal fractions of bad pixel allowed in sigma clipping during"\
    "the polynomial solution fit (POLY mode)"));
  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the arclines clipping parameters in a parameters list

  @param[in] recipe_id
    The current recipe in use
  @param[in] list
    The parameters list to search
  @return
    A NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param* xsh_parameters_clipping_detect_arclines_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* allocate the structure */
  XSH_MALLOC(result, xsh_clipping_param, 1);

 /* Fill the structure */
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "detectarclines-clip-sigma"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "detectarclines-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "detectarclines-clip-frac"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE(result);
    }
    return result;
}


/**
  @brief create the DetectContiNuum clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_dcn_create(const char* recipe_id,
  cpl_parameterlist* list)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  /* --dcn-clip-sigma */
  check( xsh_parameters_new_range_double(list,recipe_id,
    "detectcontinuum-clip-res-max", 0.5, -1., 2.,
    "Maximum allowed residual (before kappa-sigma clip)"));

  /* --dcn-clip-sigma */
  check(xsh_parameters_new_double(list,recipe_id,
    "detectcontinuum-clip-sigma", 5,
    "Kappa value in sigma clipping during order trace polynomial fit"));
  /* --dcn-clip-niter */
  check(xsh_parameters_new_int(list,recipe_id,
    "detectcontinuum-clip-niter", 5,
    "Number of iterations in sigma clipping during order trace "\
    "polynomial fit"));
  /* --dcn-clip-frac */
  check(xsh_parameters_new_double(list,recipe_id,
    "detectcontinuum-clip-frac", 0.4,
    "Minimal fractions of points accepted / total in sigma clipping"\
    "during order trace polynomial fit"));
  
  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the detectcontinuum clipping parameters in a parameters list

  @param[in] recipe_id
    The current recipe in use
  @param[in] list
    The parameters list to search
  @return
    A NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param* xsh_parameters_clipping_dcn_get(const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* allocate the structure */
  XSH_MALLOC(result, xsh_clipping_param, 1);
 
 /* Fill the structure */
  check(result->res_max = xsh_parameters_get_double(list,recipe_id,
    "detectcontinuum-clip-res-max"));
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "detectcontinuum-clip-sigma"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "detectcontinuum-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "detectcontinuum-clip-frac"));

  cleanup:
    if( cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}


/**
  @brief create the detect continuum parameter "window" in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param par the structure containing relevant params to be created
*/
void xsh_parameters_detect_continuum_create( const char* recipe_id,
					     cpl_parameterlist* list,
					     xsh_detect_continuum_param par )
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  check( xsh_parameters_new_int( list, recipe_id,
    "detectcontinuum-search-win-hsize",
    par.search_window,
    "Half window size in pixels for the 1D box to search for the "\
    "maximum in the cross-dispersion profile"));

  check( xsh_parameters_new_int( list, recipe_id,
    "detectcontinuum-running-win-hsize",
    par.running_window,
    "Half window size for the running median box during the "\
    "search for the maximum in the cross-dispersion profile"));

  check( xsh_parameters_new_int( list, recipe_id,
    "detectcontinuum-fit-win-hsize", 
    par.fit_window,
    "Half window size for the fit of the cross-dispersion profile"));

  check( xsh_parameters_new_double( list, recipe_id,
    "detectcontinuum-center-thresh-fac",
    par.fit_threshold,
   "Threshold factor applied to check that the flux at the fitted peak is "
    "higher than error."));
  
  check( xsh_parameters_new_int( list, recipe_id,
    "detectcontinuum-ordertab-step-y",
    par.poly_step,
    "Step in Y for order centroid detection"));

  check( xsh_parameters_new_int( list, recipe_id,
    "detectcontinuum-ordertab-deg-y",
    par.poly_degree,
    "Degree in Y in the polynomial order tracing X=f(Y)")) ;

/*
  check( xsh_parameters_new_int( list, recipe_id,
    "recoverformat-search-window-half-size",
    par.fmtchk_window,
    "Half size of window used to follow an order\
   (during creation of the order table)"));

  check( xsh_parameters_new_int( list, recipe_id,
    "recoverformat-search-step-y",
    par.fmtchk_step,
    "Step in Y used to follow an order\
   (during creation of the order table)"));

  check( xsh_parameters_new_double( list, recipe_id,
    "recoverformat-search-min-sn",
    par.fmtchk_search_sn,
    "Signal/Noise ratio used to find orders\
   (during creation of the order table)"));

  check( xsh_parameters_new_double( list, recipe_id,
    "recoverformat-search-min-contrast",
    par.fmtchk_follow_sn,
    "Signal/Bckgrnd ratio used to follow orders\
   (during creation of the order table)"));

  check( xsh_parameters_new_int( list, recipe_id,
    "recoverformat-search-dist-order",
    0,
    "Used to calculate the distance between orders\
   (during creation of the order table)"));
*/
 cleanup:
  return ;
}

/**
  @brief
    Get the detect continuum parameters in a parameters list

  @param recipe_id
    The current recipe in use
  @param list
    The parameters list to search
  @return
    A NEWLY allocated structure of detect continuum parameters
*/
xsh_detect_continuum_param * xsh_parameters_detect_continuum_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_detect_continuum_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);
  
  /* allocate the structure */
  XSH_MALLOC( result, xsh_detect_continuum_param, 1);

 /* Fill the structure */
  check( result->search_window = xsh_parameters_get_int( list, recipe_id,
    "detectcontinuum-search-win-hsize"));
  check( result->fit_window = xsh_parameters_get_int( list, recipe_id,
    "detectcontinuum-fit-win-hsize"));
  check( result->fit_threshold = xsh_parameters_get_double( list, recipe_id,
    "detectcontinuum-center-thresh-fac"));
  check( result->running_window = xsh_parameters_get_int( list, recipe_id,
    "detectcontinuum-running-win-hsize"));
  check( result->poly_degree = xsh_parameters_get_int( list, recipe_id,
    "detectcontinuum-ordertab-deg-y"));
  check( result->poly_step = xsh_parameters_get_int( list, recipe_id,
    "detectcontinuum-ordertab-step-y"));
/*
  check( result->fmtchk_window = xsh_parameters_get_int( list, recipe_id,
    "recoverformat-search-window-half-size"));
  check( result->fmtchk_step = xsh_parameters_get_int( list, recipe_id,
    "recoverformat-search-step-y"));
  check( result->fmtchk_search_sn = xsh_parameters_get_double( list, recipe_id,
    "recoverformat-search-min-sn"));
  check( result->fmtchk_follow_sn = xsh_parameters_get_double( list, recipe_id,
    "recoverformat-search-min-contrast"));
  check( result->dist_order = xsh_parameters_get_int( list, recipe_id,
    "recoverformat-search-dist-order"));
*/
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE(result);
    }
    return result;
}

/**
  @brief create the xsh_wavecal (function follow_arclines) clipping
  parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_tilt_create(const char* recipe_id,
  cpl_parameterlist* list)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( list); 
 
  /* Fill the parameter list */
  check( xsh_parameters_new_double( list, recipe_id,
    "tilt-clip-kappa",
    2.5,
    "Multiple of sigma in sigma clipping for evaluate tilt"));
  check( xsh_parameters_new_int( list, recipe_id,
    "tilt-clip-niter",
    5,
    "Number of iterations in sigma clipping for evaluate tilt"));
  check( xsh_parameters_new_double( list, recipe_id,
    "tilt-clip-frac",
    0.7,
    "Minimal fractions of points accepted / total in sigma clipping for evaluate tilt"));
  
  cleanup:
    return;
}
/*---------------------------------------------------------------------------*/
/**
  @brief get the xsh_wavecal (follow_arclines) clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param * xsh_parameters_clipping_tilt_get(const char* recipe_id,
                                                      cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_clipping_param*)(cpl_malloc(sizeof(xsh_clipping_param)))
    );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
    "Memory allocation failed!");

 /* Fill the structure */
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "tilt-clip-kappa"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "tilt-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "tilt-clip-frac"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}

/**
  @brief create the xsh_wavecal (function follow_arclines) clipping
  parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_clipping_specres_create(const char* recipe_id,
  cpl_parameterlist* list)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  check( xsh_parameters_new_double( list, recipe_id,
    "specres-clip-kappa",
    2.5,
    "Multiple of sigma in sigma clipping for evaluate spectral resolution"));
  check( xsh_parameters_new_int( list, recipe_id,
    "specres-clip-niter",
    5,
    "Number of iterations in sigma clipping for evaluate spectral resolution"));
  check( xsh_parameters_new_double( list, recipe_id,
    "specres-clip-frac",
    0.7,
    "Minimal fractions of points accepted / total in sigma clipping for evaluate spectral resolution"));

  cleanup:
    return;
}
/*---------------------------------------------------------------------------*/
/**
  @brief get the xsh_wavecal (follow_arclines) clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of clipping parameters
*/
/*---------------------------------------------------------------------------*/
xsh_clipping_param * xsh_parameters_clipping_specres_get(const char* recipe_id,
						      cpl_parameterlist* list)
{
  xsh_clipping_param* result = NULL;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_clipping_param*)(cpl_malloc(sizeof(xsh_clipping_param)))
    );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
    "Memory allocation failed!");
 
 /* Fill the structure */
  check(result->sigma = xsh_parameters_get_double(list,recipe_id,
    "specres-clip-kappa"));
  check(result->niter = xsh_parameters_get_int(list,recipe_id,
    "specres-clip-niter"));
  check(result->frac = xsh_parameters_get_double(list,recipe_id,
    "specres-clip-frac"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}


void xsh_parameters_wavecal_range_create(const char* recipe_id,
						  cpl_parameterlist* list)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  /* --arclines_thresh */
  check(xsh_parameters_new_range_int( list, recipe_id,
				      "followarclines-search-window-half-size",
				      WAVECAL_RANGE_DEFAULT, 1, 4096,
	  "Half window size (HWS) in pixels (Y axis) of search window for each line."
	  ));
  
  cleanup:
    return;
}

int xsh_parameters_wavecal_range_get( const char* recipe_id,
					  cpl_parameterlist* list)
{
  int result = 0;

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check( result = xsh_parameters_get_int( list, recipe_id,
					  "followarclines-search-window-half-size"));

 cleanup:
  return result ; 
}

void xsh_parameters_wavecal_margin_create(const char* recipe_id,
					  cpl_parameterlist* list)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  /* --arclines_thresh */
  check(xsh_parameters_new_range_int( list, recipe_id,
				      "followarclines-order-edges-mask",
				      WAVECAL_MARGIN_DEFAULT, 0, 20,
	  "Nb of pixels suppressed (X) from edges of search window."
	  "" ));
  
  cleanup:
    return;
}

int xsh_parameters_wavecal_margin_get( const char* recipe_id,
				       cpl_parameterlist* list)
{
  int result = 0;

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check( result = xsh_parameters_get_int( list, recipe_id,
					  "followarclines-order-edges-mask"));

 cleanup:
  return result ; 
}

void xsh_parameters_wavecal_s_n_create(const char* recipe_id,
				       cpl_parameterlist* list)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  /* --arclines_thresh */
  check(xsh_parameters_new_double( list, recipe_id,
				   "followarclines-min-sn",
				   -1.,
	  "Minimum Signal over Noise ratio at center to keep the line (6 for IFU, 15 for SLIT)."
	   ));
  
  cleanup:
    return;
}

double xsh_parameters_wavecal_s_n_get( const char* recipe_id,
				       cpl_parameterlist* list)
{
  int result = 0;

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check( result = xsh_parameters_get_double( list, recipe_id,
					     "followarclines-min-sn"));

 cleanup:
  return result ; 
}

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

void xsh_parameters_use_model_create( const char * recipe_id,
				      cpl_parameterlist * plist )
{
  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  check( xsh_parameters_new_string( plist, recipe_id, "use-model", "no",
	 "If 'no', use wavecal solution, otherwise use model. Default is 'no'" ) ) ;
 cleanup:
  return ;
}

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

int xsh_parameters_use_model_get( const char * recipe_id,
				  const cpl_parameterlist * plist )
{
  char * yesno = NULL ;

  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  yesno = xsh_parameters_get_string( plist, recipe_id, "use-model" ) ;

  if ( strcmp( yesno, "yes" ) == 0 ) return 1 ;
  else return 0 ;

 cleanup:
  return 0 ;
}

/*---------------------------------------------------------------------------*/
/*
  xsh_remove_crh_single parameters
*/
void xsh_parameters_remove_crh_single_create( const char * recipe_id,
					      cpl_parameterlist * plist,
					      xsh_remove_crh_single_param p )
{
  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  /*
  check(xsh_parameters_new_double(plist,recipe_id,
				  "removecrhsingle-frac-max",
				  p.crh_frac_max, 
    "Max fraction of bad pixels allowed"));
  */
  check(xsh_parameters_new_double(plist,recipe_id,
				  "removecrhsingle-sigmalim",
				  p.sigma_lim, 
    "Poisson fluctuation threshold to flag CRHs (see van Dokkum, PASP,113,2001,p1420-27)"));
  check(xsh_parameters_new_double(plist,recipe_id,
				  "removecrhsingle-flim",
				  p.f_lim, 
    "Minimum contrast between the Laplacian image and the fine structure image that a point must have to be flagged as CRH. (see van Dokkum, PASP,113,2001,p1420-27)"));
  check(xsh_parameters_new_int(plist,recipe_id,
			       "removecrhsingle-niter",
			       p.nb_iter, 
    "Max number of iterations"));

 cleanup:
  return ;
}

xsh_remove_crh_single_param * xsh_parameters_remove_crh_single_get(
                                        const char* recipe_id,
					cpl_parameterlist* list)
{
  xsh_remove_crh_single_param * result = NULL ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_remove_crh_single_param, 1);
 
 /* Fill the structure */
  /*
  check(result->crh_frac_max = xsh_parameters_get_double(list,recipe_id,
    "removecrhsingle-frac-max"));
  */
  check(result->sigma_lim = xsh_parameters_get_double(list,recipe_id,
    "removecrhsingle-sigmalim"));
  check(result->f_lim = xsh_parameters_get_double(list,recipe_id,
    "removecrhsingle-flim"));
  check(result->nb_iter = xsh_parameters_get_int(list,recipe_id,
    "removecrhsingle-niter"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
 
}

/*---------------------------------------------------------------------------*/
/*
  xsh_rectify parameters
*/
typedef struct {
  const char * name ;
  int type ;
} XSH_KERNEL_TYPE ;

static const XSH_KERNEL_TYPE xsh_ker_type[] = {
  {"tanh", CPL_KERNEL_TANH},
  {"sinc", CPL_KERNEL_SINC},
  {"sinc2", CPL_KERNEL_SINC2},
  {"lanczos", CPL_KERNEL_LANCZOS},
  {"hamming", CPL_KERNEL_HAMMING},
  {"hann", CPL_KERNEL_HANN},
  {NULL, 0}
} ;

static void set_rectify_kernel_type( xsh_rectify_param *recpar )
{
  const XSH_KERNEL_TYPE * pk = xsh_ker_type ;

  for( ; pk->name != NULL ; pk++ )
    if ( strcasecmp( recpar->rectif_kernel, pk->name ) == 0 ) {
      recpar->kernel_type = pk->type ;
      return ;
    }
  recpar->kernel_type = CPL_KERNEL_DEFAULT ;

  return ;
}
/*
static const char * get_ker_default( void )
{
  const XSH_KERNEL_TYPE * pk = xsh_ker_type ;

  for( ; pk->name != NULL ; pk++ )
    if ( pk->type == CPL_KERNEL_DEFAULT ) {
      return pk->name ;
    }
  return "unknown" ;
  
}
*/

void xsh_parameters_rectify_create( const char * recipe_id,
				    cpl_parameterlist * plist,
				    xsh_rectify_param p )
{
  char ker_comment[256];

  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  sprintf( ker_comment,
    "Name of the Interpolation Kernel Used. Possible values are: "\
    " tanh, sinc, sinc2, lanczos, hamming, hann.");

  check(xsh_parameters_new_string(plist,recipe_id,
				  "rectify-kernel",
				  p.rectif_kernel, ker_comment));

  check(xsh_parameters_new_range_double( plist, recipe_id,
				      "rectify-radius",
				      p.rectif_radius, 2., 100.,
	  "Rectify Interpolation radius [bin units]."
	  "" ));

  check(xsh_parameters_new_double(plist,recipe_id,
				  "rectify-bin-lambda",
				  p.rectif_bin_lambda, 
    "Wavelength step in the output spectrum [nm]"));

  check(xsh_parameters_new_double(plist,recipe_id,
				  "rectify-bin-slit",
				  p.rectif_bin_space, 
    "Spatial step along the slit in the output spectrum [arcsec]"));
  /*
  check( xsh_parameters_new_boolean( plist, recipe_id,
				     "rectify-full-slit",
				     p.rectify_full_slit,
				     "Use full slit if TRUE"));
  
  check( xsh_parameters_new_boolean( plist, recipe_id,
    "rectify-conserve-flux", p.conserve_flux,
    "Use flux conservation if TRUE"));
  */
/*
  check( xsh_parameters_new_boolean( plist, recipe_id,
    "rectify-fast", TRUE,
    "Fast if TRUE (Rect[B-A] = -Rect[A-B])"));


  check(xsh_parameters_new_double(plist,recipe_id,
				  "rectify-slit-offset",
				  p.slit_offset, 
    "Rectify Slit Offset"));
*/

/*check( xsh_parameters_new_int( plist, recipe_id,
    "rectify-cut-edges", p.conserve_flux,
    "Cut edges in rectify bin pixel [pix]"));
*/
 cleanup:
  return ;
}

int xsh_parameters_rectify_fast_get( const char* recipe_id,
						cpl_parameterlist* list)
{
  int result = 0 ;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check( result = xsh_parameters_get_boolean( list,
    recipe_id, "rectify-fast"));

 cleanup:
  return result ;
}

xsh_rectify_param * xsh_parameters_rectify_get( const char* recipe_id,
						cpl_parameterlist* list)
{
  xsh_rectify_param * result = NULL ;
  char *p ;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_rectify_param *)(cpl_malloc(
                  sizeof(xsh_rectify_param))) );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
	  "Memory allocation failed!");
 
  /* Fill the structure */
  check(p = xsh_parameters_get_string(list,recipe_id,
    "rectify-kernel"));
  strcpy( result->rectif_kernel, p ) ;
  check(result->rectif_radius = xsh_parameters_get_double(list,recipe_id,
    "rectify-radius"));
  check(result->rectif_bin_lambda = xsh_parameters_get_double(list,recipe_id,
    "rectify-bin-lambda"));
  check(result->rectif_bin_space = xsh_parameters_get_double(list,recipe_id,
    "rectify-bin-slit"));
  /*
  check( result->rectify_full_slit = xsh_parameters_get_boolean( list,
								 recipe_id,
    "rectify-full-slit")) ;
  */
  result->rectify_full_slit=true;
/*

  check( result->conserve_flux = xsh_parameters_get_boolean( list,
    recipe_id, "rectify-conserve-flux"));
  check(result->slit_offset = xsh_parameters_get_double(list,recipe_id,
    "rectify-slit-offset"));
*/
/* check( result->cut_edges = xsh_parameters_get_int( list,
    recipe_id, "rectify-cut-edges"));
*/
  /* Set the kernel type in CPL_KERNEL_XXXXX format */
  set_rectify_kernel_type( result ) ;

 cleanup:
  if(cpl_error_get_code() != CPL_ERROR_NONE){
    cpl_free(result);
    result = NULL;
  }
  return result;
}

void
xsh_parameters_compute_response_create( const char * recipe_id,
					cpl_parameterlist * plist,
					xsh_compute_response_param p )
{
  /* check parameters */
  assure(plist != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  check(xsh_parameters_new_double(plist,recipe_id,
				  "compute-response-lambda-step",
				  p.lambda_bin, 
    "Compute Response Interpolation Lambda Step"));

 cleanup:
  return ;
}

xsh_compute_response_param *
xsh_parameters_compute_response_get( const char * recipe_id,
				     cpl_parameterlist * list)
{
  xsh_compute_response_param * result = NULL ;

  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_compute_response_param *)(cpl_malloc(
                  sizeof(xsh_compute_response_param))) );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
	  "Memory allocation failed!");
 
  /* Fill the structure */
  check(result->lambda_bin =
	xsh_parameters_get_double(list,recipe_id,
				  "compute-response-lambda-step"));

 cleanup:
  if(cpl_error_get_code() != CPL_ERROR_NONE){
    cpl_free(result);
    result = NULL;
  }
  return result;

}
/*---------------------------------------------------------------------------*/
/*
  xsh_localize_obj parameters
*/
void xsh_parameters_localize_obj_create( const char * recipe_id,
  cpl_parameterlist * plist, xsh_localize_obj_param p)
{
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check( xsh_parameters_new_string( plist, recipe_id,
    "localize-method",
    LOCALIZE_METHOD_PRINT(p.method), 
    "Localization method (MANUAL, MAXIMUM, GAUSSIAN) used to detect "\
    "the object centroid and height on the slit"));

  check( xsh_parameters_new_int( plist, recipe_id,
    "localize-chunk-nb",
    p.loc_chunk_nb, 
    "Number of chunks in the full spectrum to localize the object"));
  check( xsh_parameters_new_double( plist, recipe_id,
    "localize-thresh",
    p.loc_thresh, 
    "Threshold relative to the peak intensity below which the edges "\
    "of the object are detected for MAXIMUM localization"));
  check( xsh_parameters_new_int( plist, recipe_id,
    "localize-deg-lambda",
    p.loc_deg_poly, 
    "Degree in lambda in the localization polynomial expression "\
    "slit=f(lambda), used only for MAXIMUM and GAUSSIAN"));

  if (strcmp(recipe_id,"xsh_scired_slit_nod")==0){
    check( xsh_parameters_new_double( plist, recipe_id,
      "localize-slit-position", 
      p.slit_position,
      "Object position on the slit for MANUAL localization [arcsec]. It refers to the object position in the first frame of the nodding sequence"));
  }
  else {
    check( xsh_parameters_new_double( plist, recipe_id,
      "localize-slit-position", 
      p.slit_position,
      "Object position on the slit for MANUAL localization [arcsec]"));
  }
  check( xsh_parameters_new_double( plist, recipe_id,
    "localize-slit-hheight", 
    p.slit_hheight,
    "Object half height on the slit for MANUAL localization [arcsec]"));
  check( xsh_parameters_new_double( plist, recipe_id,
    "localize-kappa", 
    p.kappa,
    "Kappa value for sigma clipping in the localization "\
    "polynomial fit"));
  check( xsh_parameters_new_int( plist, recipe_id,
    "localize-niter", 
    p.niter,
    "Number of iterations for sigma clipping in the localization "\
    "polynomial fit"));

  check(xsh_parameters_new_boolean( plist, recipe_id,
    "localize-use-skymask", p.use_skymask,
    "TRUE if we want to mask sky lines using SKY_LINE_LIST file."));

  cleanup:
    return ;
}

xsh_localize_obj_param* xsh_parameters_localize_obj_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_localize_obj_param * result = NULL ;
  const char* par_method = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list); 

  /* allocate the structure */
   XSH_MALLOC( result, xsh_localize_obj_param, 1);
 
  /* Fill the structure */
  check( result->loc_chunk_nb = xsh_parameters_get_int( list,recipe_id,
    "localize-chunk-nb"));
  check( result->loc_thresh = xsh_parameters_get_double( list,recipe_id,
    "localize-thresh"));
  check( result->loc_deg_poly = xsh_parameters_get_int( list,recipe_id,
    "localize-deg-lambda"));
  check( par_method = xsh_parameters_get_string( list, recipe_id,
    "localize-method"));
  if ( strcmp( LOCALIZE_METHOD_PRINT(LOC_MANUAL_METHOD), par_method) == 0){
    result->method = LOC_MANUAL_METHOD;
  }
  else if (strcmp( LOCALIZE_METHOD_PRINT(LOC_MAXIMUM_METHOD), par_method) == 0){
    result->method = LOC_MAXIMUM_METHOD;
  }
  else if (strcmp( LOCALIZE_METHOD_PRINT(LOC_GAUSSIAN_METHOD), par_method) == 0){
    result->method = LOC_GAUSSIAN_METHOD;
  }
  else {
    xsh_error_msg("WRONG parameter localize-method %s",par_method);
  }
  check( result->slit_position = xsh_parameters_get_double( list, recipe_id,
    "localize-slit-position"));
  check( result->slit_hheight = xsh_parameters_get_double( list, recipe_id,
    "localize-slit-hheight"));
  check( result->kappa = xsh_parameters_get_double( list, recipe_id,
    "localize-kappa"));
  check( result->niter = xsh_parameters_get_int( list, recipe_id,
    "localize-niter"));
  check( result->use_skymask = xsh_parameters_get_boolean( list, recipe_id,
    "localize-use-skymask")); 

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
  
}

/*---------------------------------------------------------------------------*/
/*
  xsh_localize_ifu parameters
*/
void xsh_parameters_localize_ifu_create( const char * recipe_id,
  cpl_parameterlist * plist, xsh_localize_ifu_param p)
{
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check( xsh_parameters_new_int( plist, recipe_id,
    "localizeifu-bckg-deg",
    p.bckg_deg,
    "Degree (<=2) of the polynomial component in the cross-dispersion profile fit"));
    
  check( xsh_parameters_new_int( plist, recipe_id,
    "localizeifu-smooth-hsize",
    p.smooth_hsize,
    "Half-size of the median filter for smoothing the cross-dispersion profile prior to localization"));

  check( xsh_parameters_new_int( plist, recipe_id,
    "localizeifu-wavelet-nscales",
    p.nscales,
    "Number of scales used for wavelet a trous algorithm"));

  check( xsh_parameters_new_int( plist, recipe_id,
    "localizeifu-wavelet-hf-skip",
    p.HF_skip,
    "Number of high frequency scales skipped from the wavelet decomposition")); 

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-sigma-low",
    p.cut_sigma_low,
    "Gaussian fits of the cross-dispersion profile whose FWHM is lower than this value are rejected"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-sigma-up",
    p.cut_sigma_up,
    "Gaussian fits of the cross-dispersion profile whose FWHM is larger than this value are rejected"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-snr-low",
    p.cut_snr_low,
    "Gaussian fits of the cross-dispersion profile whose SNR is lower than this value are rejected"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-snr-up",
    p.cut_snr_up,
    "Gaussian fits of the cross-dispersion profile whose SNR is larger than this value are rejected"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-slitlow-edges-mask",
    p.slitlow_edges_mask,
    "in arsec"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "localizeifu-slitup-edges-mask",
    p.slitup_edges_mask,
    "in arsec"));

  check(xsh_parameters_new_boolean( plist, recipe_id,
    "localizeifu-use-skymask", p.use_skymask,
    "TRUE if we want to mask sky lines using SKY_LINE_LIST file."));

  check(xsh_parameters_new_int( plist, recipe_id,
    "localizeifu-chunk-hsize", p.box_hsize,
    "Half size of chunk [bin]"));
        
  cleanup:
    return;
}
xsh_localize_ifu_param * xsh_parameters_localize_ifu_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_localize_ifu_param *result = NULL ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_localize_ifu_param, 1);

  check( result->bckg_deg = xsh_parameters_get_int( list, recipe_id,
    "localizeifu-bckg-deg"));
  check( result->smooth_hsize = xsh_parameters_get_int( list, recipe_id,
    "localizeifu-smooth-hsize"));

  check( result->nscales = xsh_parameters_get_int( list, recipe_id,
    "localizeifu-wavelet-nscales"));

  check( result->HF_skip = xsh_parameters_get_int( list, recipe_id,
    "localizeifu-wavelet-hf-skip"));

  check( result->cut_sigma_low = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-sigma-low"));
  check( result->cut_sigma_up = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-sigma-up"));

  check( result->cut_snr_low = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-snr-low"));
  check( result->cut_snr_up = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-snr-up"));

  check( result->slitlow_edges_mask = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-slitlow-edges-mask"));
  check( result->slitup_edges_mask = xsh_parameters_get_double( list, recipe_id,
    "localizeifu-slitup-edges-mask"));

  check( result->use_skymask = xsh_parameters_get_boolean( list, recipe_id,
    "localizeifu-use-skymask"));
    
  check( result->box_hsize = xsh_parameters_get_int( list, recipe_id,
    "localizeifu-chunk-hsize"));
    
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
}
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*
 *   xsh_extract parameters
*/

void xsh_parameters_extract_create( const char * recipe_id,
                                    cpl_parameterlist * plist, 
                                    xsh_extract_param p,
                                    enum extract_method method)
{
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check( xsh_parameters_new_string( plist, recipe_id,
    "extract-method", EXTRACT_METHOD_PRINT(method),
    "Method used for extraction (LOCALIZATION, NOD)"));

  cleanup:
    return ;
}

void xsh_parameters_interpolate_bp_create( const char * recipe_id,
                                    cpl_parameterlist * plist,
                                    xsh_interpolate_bp_param p)
{
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check( xsh_parameters_new_int( plist, recipe_id,
    "stdextract-interp-hsize",
    p.mask_hsize,
    "Half size of mask used to define object cross order profile"));

  cleanup:
    return ;
}

xsh_extract_param * xsh_parameters_extract_get( 
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_extract_param *result = NULL ;
  const char *par_method = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_extract_param, 1);
 
  /* Fill the structure */
  if(strstr(recipe_id,"offset")!= NULL) {
    result->method = LOCALIZATION_METHOD;
  } else {
    check( par_method = xsh_parameters_get_string( list, recipe_id,
        "extract-method"));
    if ( strcmp( EXTRACT_METHOD_PRINT(LOCALIZATION_METHOD), par_method) == 0){
      result->method = LOCALIZATION_METHOD;
    }
    else if (strcmp( EXTRACT_METHOD_PRINT(FULL_METHOD), par_method) == 0){
      result->method = FULL_METHOD;
    }
    else if (strcmp( EXTRACT_METHOD_PRINT(NOD_METHOD), par_method) == 0){
      result->method = NOD_METHOD;
    }
    else if (strcmp( EXTRACT_METHOD_PRINT(CLEAN_METHOD), par_method) == 0){
      result->method = CLEAN_METHOD;
    }
    else {
      xsh_error_msg("WRONG parameter extract-method %s",par_method);
      xsh_error_msg("Only %s, %s or %s are allowed",EXTRACT_METHOD_PRINT(LOCALIZATION_METHOD),EXTRACT_METHOD_PRINT(NOD_METHOD),EXTRACT_METHOD_PRINT(CLEAN_METHOD));
    }
  }
  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}

xsh_interpolate_bp_param * xsh_parameters_interpolate_bp_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_interpolate_bp_param *result = NULL ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_interpolate_bp_param, 1);

  /* Fill the structure */

  check( result->mask_hsize = xsh_parameters_get_int( list, recipe_id,
     "stdextract-interp-hsize"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}

/*---------------------------------------------------------------------------*/
/*
  xsh_remove_sky_single parameters
*/
void xsh_parameters_subtract_sky_single_create( const char * recipe_id,
						cpl_parameterlist * plist,
					 xsh_subtract_sky_single_param p )
{
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check(xsh_parameters_new_boolean( plist, recipe_id,
    "sky-subtract", TRUE,
    "TRUE to use subtract sky single."));

  check( xsh_parameters_new_int( plist, recipe_id,
    "sky-bspline-nbkpts-first",
    p.nbkpts1, 
    "Nb of break points for Bezier curve fitting (without localization)"));
  check( xsh_parameters_new_int( plist,recipe_id,
    "sky-bspline-nbkpts-second",
    p.nbkpts2, 
    "Nb of break points for Bezier curve fitting (with localization)"));

  check( xsh_parameters_new_int( plist, recipe_id,
    "sky-bspline-order",
    p.bezier_spline_order, 
    "Bezier spline order"));

  check( xsh_parameters_new_int( plist, recipe_id,
    "sky-bspline-niter",
    p.niter, 
    "Nb of iterations"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-bspline-kappa",
    p.kappa, 
    "Kappa value used to kappa-sigma-clip object"));

  check( xsh_parameters_new_string( plist, recipe_id, 
     "sky-method",
     SKY_METHOD_PRINT(p.method), "Sky subtract Method (BSPLINE, MEDIAN)"));

  check( xsh_parameters_new_string( plist, recipe_id, 
     "bspline-sampling",
     BSPLINE_SAMPLING_PRINT(p.bspline_sampling), "BSPLINE sampling. UNIFORM-uses the user defined nbkpts value, corrected for binning, for all orders. FINE: multiplies the user defined nbkpts value, corrected for binning, by a hard coded coefficient optimized on each arm-order)"));

  check(xsh_parameters_new_range_int( plist, recipe_id,
				      "sky-median-hsize",
				      p.median_hsize, 0, 2000,
	  "Half size of the running median. If sky-method=MEDIAN ."
	  ));


  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-slit-edges-mask",
    p.slit_edges_mask,
    "Size of edges mask in arcsec"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-position1",
    p.pos1,
    "Central position of the sky window #1 [arcsec]"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-hheight1",
    p.hheight1,
    "Half size of sky window #1 [arcsec]"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-position2",
    p.pos2,
    "Central position of the sky window #2 [arcsec]"));

  check( xsh_parameters_new_double( plist, recipe_id,
    "sky-hheight2",
    p.hheight2,
    "Half size of the sky window #2 [arcsec]"));

  cleanup:
    return ;
}

xsh_subtract_sky_single_param* xsh_parameters_subtract_sky_single_get(
  const char* recipe_id, cpl_parameterlist* list)
{
  xsh_subtract_sky_single_param *result = NULL ;
  const char* par_method = NULL;
  const char* bspline_sampling = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_subtract_sky_single_param, 1);

  /* Fill the structure */
  check( result->nbkpts1 = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-nbkpts-first"));
  check( result->nbkpts2 = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-nbkpts-second"));
  check( result->bezier_spline_order = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-order"));
  check( result->niter = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-niter"));
  check( result->kappa =  xsh_parameters_get_double( list, recipe_id,
    "sky-bspline-kappa"));


  check( par_method = xsh_string_toupper(xsh_parameters_get_string(list, 
                                                                   recipe_id,
                                                                   "sky-method")
            ));

 
  if ( strcmp( SKY_METHOD_PRINT(BSPLINE_METHOD), par_method) == 0){
    result->method = BSPLINE_METHOD;
  }
  else if (strcmp( SKY_METHOD_PRINT(MEDIAN_METHOD), par_method) == 0){ 
    result->method = MEDIAN_METHOD;
  }
  else {
    xsh_error_msg("WRONG parameter sky_method %s",par_method);
  }

  check( bspline_sampling = xsh_parameters_get_string( list, recipe_id,
    "bspline-sampling"));
  if ( strcmp( BSPLINE_SAMPLING_PRINT(UNIFORM), bspline_sampling) == 0){
    result->bspline_sampling = BSPLINE_METHOD;
  }
  else if (strcmp( BSPLINE_SAMPLING_PRINT(FINE), bspline_sampling) == 0){ 
    result->bspline_sampling = FINE;
  }
  else {
    xsh_error_msg("WRONG parameter bspline-sampling %s",bspline_sampling);
  }



  check( result->median_hsize =  xsh_parameters_get_int( list, recipe_id,
    "sky-median-hsize"));
  check( result->slit_edges_mask =  xsh_parameters_get_double( list, 
    recipe_id,
    "sky-slit-edges-mask"));

  check( result->pos1 =  xsh_parameters_get_double( list,
    recipe_id,
    "sky-position1"));
  check( result->hheight1 =  xsh_parameters_get_double( list,
    recipe_id,
    "sky-hheight1"));
  check( result->pos2 =  xsh_parameters_get_double( list,
    recipe_id,
    "sky-position2"));
  check( result->hheight2 =  xsh_parameters_get_double( list,
    recipe_id,
    "sky-hheight2"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}

int xsh_parameters_subtract_sky_single_get_true( const char* recipe_id,
						 cpl_parameterlist* list)
{
  bool result = FALSE;

  check( result = xsh_parameters_get_boolean( list, recipe_id, 
    "sky-subtract"));

  cleanup:
    return result ;
}


void xsh_parameters_dosky_domap_get( const char *recipe_id,
                                     cpl_parameterlist *list, 
                                     cpl_frame* wavemap_frame, 
                                     cpl_frame* slitmap_frame, 
                                     int *dosky, int *domap)
{
  bool sub_sky=FALSE;
  bool computemap=FALSE;

  XSH_ASSURE_NOT_NULL( dosky);
  XSH_ASSURE_NOT_NULL( domap);

  check( sub_sky = xsh_parameters_subtract_sky_single_get_true( recipe_id,
    list));
  check( computemap = xsh_parameters_get_boolean( list, recipe_id,
    "compute-map"));

/* This check is made more robust as it may be useful for debugging purpose 
   to switch off the wavemap generation if the wavemaps and slit maps are 
   provided in input-assuming the user have provided  proper values).
*/
  if ( (sub_sky && !computemap) && 
       (wavemap_frame == NULL || slitmap_frame == NULL)  
     ){
    xsh_msg_warning( "Parameters sky-subtract and compute-map are not compatible, compute-map has been forced to TRUE");
    computemap = TRUE;
  }

  *dosky = sub_sky;
  *domap = computemap;

  cleanup:
    return;
}


int xsh_parameters_subtract_sky_single_get_first( const char* recipe_id,
						  cpl_parameterlist* list)
{
  int result = 0 ;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the structure */
  check(result = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-nbkpts-first"));

  cleanup:
    return result;
  
}

int xsh_parameters_subtract_sky_single_get_second( const char* recipe_id,
						   cpl_parameterlist* list)
{
  int result = 0 ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the structure */
  check(result = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-nbkpts-second"));

  cleanup:
    return result;
}


int xsh_parameters_subtract_sky_single_get_niter( const char* recipe_id,
						   cpl_parameterlist* list)
{
  int result = 0 ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the structure */
  check(result = xsh_parameters_get_int( list, recipe_id,
    "sky-bspline-niter"));

  cleanup:
    return result;
}



double xsh_parameters_subtract_sky_single_get_kappa( const char* recipe_id,
						   cpl_parameterlist* list)
{
  double result = 0 ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the structure */
  check(result = xsh_parameters_get_double( list, recipe_id,
    "sky-bspline-kappa"));

  cleanup:
    return result;
}

/*---------------------------------------------------------------------------*/
/*
  xsh_merge_ord parameter
*/
void xsh_parameters_merge_ord_create( const char * recipe_id,
				      cpl_parameterlist * plist,
				      int p )
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( plist);

  check(xsh_parameters_new_int( plist, recipe_id, "mergeord-method",
    p, "Method for combining overlapping orders "\
    "(0 = WEIGHTED with the errors, 1 = MEAN)"));

  cleanup:
    return;
}

xsh_merge_param* xsh_parameters_merge_ord_get( const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_merge_param *result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* allocate the structure */
  XSH_MALLOC( result, xsh_merge_param, 1);

  /* Fill the structure */
  check( result->method = xsh_parameters_get_int( list, recipe_id,
    "mergeord-method"));

 cleanup:
  if(cpl_error_get_code() != CPL_ERROR_NONE){
    XSH_FREE( result);
  }
  return result;
}

/*---------------------------------------------------------------------------*/
/*
  xsh_optimal_extract parameter
*/
void xsh_parameters_optimal_extract_create( const char * recipe_id,
					    cpl_parameterlist * plist,
					    int p )
{
  XSH_ASSURE_NOT_NULL( recipe_id ) ;
  XSH_ASSURE_NOT_NULL( plist ) ;

  check(xsh_parameters_new_double(plist,recipe_id,
			       "optimal_extract_kappa",
			       p,
    "Pixels with values > kappa*RMS are ignored. If negative no rejection."));

 cleanup:
  return ;
}

double xsh_parameters_optimal_extract_get_kappa( const char* recipe_id,
					cpl_parameterlist* list)
{
  double result = 0 ;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the structure */
  check(result = xsh_parameters_get_double(list,recipe_id,
					"optimal_extract_kappa"));

 cleanup:
  return result;
  
}

/*---------------------------------------------------------------------------*/
/**
  @brief 
    Create the dispersol compute parameters in a parameters list
  @param recipe_id 
    The current recipe in use
  @param list 
    The parameters list to update
  @param p 
    The dispersol parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_dispersol_create(const char* recipe_id,
  cpl_parameterlist* list, xsh_dispersol_param p)
{
  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* Fill the parameter list */
  /* --wavemap_x_degree */
  check(xsh_parameters_new_int(list,recipe_id,"dispersol-deg-x",
    p.deg_x, "Degree in X in the polynomial dispersion solution "\
    "lambda=f(X,Y) and slit=f(X,Y)"));
  /* --wavemap_y_degree */
  check(xsh_parameters_new_int(list,recipe_id,"dispersol-deg-y",
    p.deg_y, "Degree in Y in the polynomial dispersion solution "\
    "lambda=f(X,Y) and slit=f(X,Y)"));

  cleanup:
    return;
}
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the dispersion solution compute parameters in a parameters list

  @param recipe_id 
    The current recipe in use
  @param list 
    The parameters list to search
  @return a NEWLY allocated structure of wavemap parameters
*/
/*---------------------------------------------------------------------------*/
xsh_dispersol_param* xsh_parameters_dispersol_get( const char* recipe_id,
  cpl_parameterlist* list)
{
  xsh_dispersol_param* result = NULL;

  /* check parameters */
  XSH_ASSURE_NOT_NULL(list);

  /* allocate the structure */
  XSH_MALLOC(result, xsh_dispersol_param, 1);

 /* Fill the structure */
  check(result->deg_x = xsh_parameters_get_int(list, recipe_id,
    "dispersol-deg-x"));
  check(result->deg_y = xsh_parameters_get_int(list, recipe_id,
    "dispersol-deg-y"));

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE(result);
    }
    return result;
}
/*---------------------------------------------------------------------------*/

/**
  @brief create the crh clipping parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to update
  @param p combine nod parameters structure
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_combine_nod_create(const char * recipe_id,
				       cpl_parameterlist * list,
				       xsh_combine_nod_param p)
{
  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* Fill the parameter list */
  if (strstr(recipe_id, "nod") != NULL) {
    /*
    check(
        xsh_parameters_new_int(list,recipe_id,"combinenod-min", p.nod_min, "minimum NS size of resulting frame  in pixels"));
    check(xsh_parameters_new_boolean(list,recipe_id,"combinenod-clip",
            p.nod_clip,
            "TRUE if do sigma clipping"));
    // --nod-clip-sigma
    check(
        xsh_parameters_new_double(list,recipe_id,"combinenod-clip-sigma", p.nod_clip_sigma, "Kappa value in sigma clipping for combining nodded frames"));
    // --crh-clip-niter
    check(
        xsh_parameters_new_int(list,recipe_id,"combinenod-clip-niter", p.nod_clip_niter, "Number of iterations in sigma clipping for combining nodded frames"));
    // --crh-clip-frac
    check(
        xsh_parameters_new_double(list,recipe_id,"combinenod-clip-diff", p.nod_clip_diff, "Minimal change in sigma in sigma clipping for combining nodded frames"));
*/
    check(
        xsh_parameters_new_string( list, recipe_id, "combinenod-throwlist", p.throwname, "Name of ascii file containing the list of throw shifts with respect to the first exposure"));
  }

  check( xsh_parameters_new_string( list, recipe_id,
    "combinenod-method", COMBINE_METHOD_PRINT( p.method),
    "Combination method for nodded frames (MEDIAN, MEAN)")); 

  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief get the combine nod parameters in a parameters list

  @param recipe_id the current recipe in use
  @param list the parameters list to search
  @return a NEWLY allocated structure of combine nod parameters
*/
/*---------------------------------------------------------------------------*/
xsh_combine_nod_param * xsh_parameters_combine_nod_get(const char* recipe_id,
						       cpl_parameterlist* list)
{
  xsh_combine_nod_param* result = NULL;
  const char *par_method = NULL;

  /* check parameters */
  assure(list != NULL,CPL_ERROR_NULL_INPUT,"parameters list is NULL");

  /* allocate the structure */
  check(result = (xsh_combine_nod_param *)(cpl_malloc(sizeof(xsh_combine_nod_param)))
    );
  assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
    "Memory allocation failed!");
 
 /* Fill the structure */
  if( strstr(recipe_id,"nod") != NULL) {
    /*
    check(result->nod_min = xsh_parameters_get_int(list,recipe_id,
						   "combinenod-min"));
    check(result->nod_clip = xsh_parameters_get_boolean(list,recipe_id,
							"combinenod-clip"));
    check(result->nod_clip_sigma = xsh_parameters_get_double(list,recipe_id,
							     "combinenod-clip-sigma"));
    check(result->nod_clip_niter = xsh_parameters_get_int(list,recipe_id,
							  "combinenod-clip-niter"));
    check(result->nod_clip_diff = xsh_parameters_get_double(list,recipe_id,
							    "combinenod-clip-diff"));
							    */
    check(result->throwname = xsh_parameters_get_string(list,recipe_id,
							"combinenod-throwlist"));
  }
 check( par_method = xsh_parameters_get_string( list, recipe_id,
    "combinenod-method"));
  if ( strcmp( COMBINE_METHOD_PRINT( COMBINE_MEAN_METHOD), par_method) == 0){
    result->method = COMBINE_MEAN_METHOD;
  }
  else if (strcmp( COMBINE_METHOD_PRINT( COMBINE_MEDIAN_METHOD), par_method) == 0){
    result->method = COMBINE_MEDIAN_METHOD;
  }
  else {
    xsh_error_msg("WRONG parameter combinenod-method %s",par_method);
  }


  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      cpl_free(result);
      result = NULL;
    }
    return result;
}
/*---------------------------------------------------------------------------*/
/**
  @brief
    Create the optimal extraction parameters in a parameters list
  @param[in] recipe_id
    The current recipe in use
  @param[in,out] list
    The parameters list to update
  @param[in] p
    The default value for the parameter
*/
/*---------------------------------------------------------------------------*/
void xsh_parameters_opt_extract_create( const char * recipe_id,
  cpl_parameterlist* list, xsh_opt_extract_param p)
{
  /* Check input parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  check( xsh_parameters_new_int( list, recipe_id,
    "optextract-oversample", p.oversample,
    "Oversample factor for the science image"));
  check( xsh_parameters_new_int( list, recipe_id,
    "optextract-box-half-size", p.box_hsize,
    "Extraction box [pixel]"));
  check( xsh_parameters_new_int( list, recipe_id,
    "optextract-chunk-size", p.chunk_size,
    "Chunk size [bin]"));
  check( xsh_parameters_new_double( list, recipe_id,
    "optextract-step-lambda", p.lambda_step,
    "Lambda step [nm]"));
  check( xsh_parameters_new_double( list, recipe_id,
    "optextract-clip-kappa", p.clip_kappa,
    "Kappa for cosmics ray hits rejection" ) ) ;
  check( xsh_parameters_new_double( list, recipe_id,
    "optextract-clip-frac", p.clip_frac,
    "Maximum bad pixels fraction for cosmics ray hits rejection"));
  check( xsh_parameters_new_int( list, recipe_id,
    "optextract-clip-niter", p.clip_niter,
    "Maximum number of iterations for cosmics ray hits rejection"));
  check( xsh_parameters_new_int( list, recipe_id,
    "optextract-niter", p.niter,
    "Number of iterations" ) ) ;
  check( xsh_parameters_new_string( list, recipe_id,
    "optextract-method", OPTEXTRACT_METHOD_PRINT(p.method),
    "Extraction method GAUSSIAN | GENERAL"));

  cleanup:
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief
    Get the optimal extraction parameters in a parameters list
  @param[in] recipe_id 
    The current recipe in use
  @param[in] list
    The parameters list to search
  @return 
    A NEWLY allocated structure for parameters
*/
/*---------------------------------------------------------------------------*/
xsh_opt_extract_param* xsh_parameters_opt_extract_get( const char* recipe_id,
						       cpl_parameterlist* list)
{
  xsh_opt_extract_param* result = NULL;
  const char *par_method = NULL;


  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);
  /* Allocate structure */
  XSH_MALLOC( result, xsh_opt_extract_param, 1);

 /* Fill the structure */
  check( result->oversample = xsh_parameters_get_int( list,recipe_id,
    "optextract-oversample"));
  check( result->box_hsize = xsh_parameters_get_int( list,recipe_id,
    "optextract-box-half-size"));
  check( result->chunk_size = xsh_parameters_get_int( list,recipe_id,
    "optextract-chunk-size"));
  check( result->lambda_step = xsh_parameters_get_double( list,recipe_id,
    "optextract-step-lambda"));
  check( result->clip_kappa = xsh_parameters_get_double( list, recipe_id,
						    "optextract-clip-kappa"));
  check( result->clip_frac = xsh_parameters_get_double( list, recipe_id,
                                                    "optextract-clip-frac"));
  check( result->clip_niter = xsh_parameters_get_int( list, recipe_id,
                                                    "optextract-clip-niter"));
  check( result->niter = xsh_parameters_get_int( list, recipe_id,
                                                    "optextract-niter"));
  check( par_method = xsh_parameters_get_string( list, recipe_id,
    "optextract-method"));
  if ( strcmp( OPTEXTRACT_METHOD_PRINT(GAUSS_METHOD), par_method) == 0){
    result->method = GAUSS_METHOD;
  }
  else if (strcmp( OPTEXTRACT_METHOD_PRINT(GENERAL_METHOD), par_method) == 0){
    result->method = GENERAL_METHOD;
  }
  else {
    xsh_error_msg("WRONG parameter optextract-method %s",par_method);
  }

  cleanup:
    if(cpl_error_get_code() != CPL_ERROR_NONE){
      XSH_FREE( result);
    }
    return result;
}

void xsh_parameters_slit_limit_create( const char* recipe_id,
				       cpl_parameterlist* list,
				       xsh_slit_limit_param p )
{
  /* Check input parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  /* Fill the parameter list */
  check( xsh_parameters_new_double( list, recipe_id,
    "max-slit", p.max_slit,
    "Lower Slit Limit (localize and extract"));
  check( xsh_parameters_new_double( list, recipe_id,
    "min-slit", p.min_slit,
    "Upper Slit Limit (localize and extract"));

 cleanup:
  return ;
}

xsh_slit_limit_param * xsh_parameters_slit_limit_get( const char * recipe_id,
						      cpl_parameterlist* list )
{
  xsh_slit_limit_param * result = NULL ;

  /* check parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);
  /* Allocate structure */
  XSH_MALLOC( result, xsh_slit_limit_param, 1);

 /* Fill the structure */
  check( result->min_slit = xsh_parameters_get_double( list,recipe_id,
						      "min-slit"));
  check( result->max_slit = xsh_parameters_get_double( list,recipe_id,
						      "max-slit"));
 cleanup:
  if(cpl_error_get_code() != CPL_ERROR_NONE){
    XSH_FREE( result);
  }
  return result;
}

void xsh_parameters_geom_ifu_mode_create( const char* recipe_id,
					  cpl_parameterlist* list )
{
  /* Check input parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);

  check(xsh_parameters_new_boolean(list,recipe_id,
				   "geom-ifu-localize-single",
				   TRUE,
    "Use a concatenation of rectified to localize."));
 cleanup:
  return ;
}

int xsh_parameters_geom_ifu_mode_get( const char * recipe_id,
				      cpl_parameterlist* list)
{
  int ts = FALSE ;

  /* Check input parameters */
  XSH_ASSURE_NOT_NULL( recipe_id);
  XSH_ASSURE_NOT_NULL( list);
  ts = xsh_parameters_get_boolean( list, recipe_id,
				   "geom-ifu-localize-single" ) ;

 cleanup:
  return ts ;
}


cpl_parameterlist*
xsh_parameters_create_from_drs_table(const cpl_table* tab)
{

   cpl_parameterlist* result=NULL;
   int nrow=0;
   int i=0;
   const char*  svalue=NULL;
   int    ivalue=0;
   float  fvalue=0;
   double dvalue=0;
   bool bvalue=0;

   const char* rec_id=NULL;
   const char* pname=NULL;
   const char* ptype=NULL;
   const char* phelp=NULL;


   XSH_ASSURE_NOT_NULL_MSG(tab,"Null input DRS tab");
   nrow=cpl_table_get_nrow(tab);
   result=cpl_parameterlist_new();
   for(i=0;i<nrow;i++) {
      check(rec_id=cpl_table_get_string(tab,"recipe",i));
      check(pname=cpl_table_get_string(tab,"param_name",i));
      check(ptype=cpl_table_get_string(tab,"param_type",i));
      check(phelp=cpl_table_get_string(tab,"param_help",i));
      //xsh_msg("pname=%s ptype=%s",pname,ptype);
     if (strcmp(ptype,"int") == 0) {
       check(ivalue=atoi(cpl_table_get_string(tab,"param_value",i)));
         check(xsh_parameters_new_int(result,rec_id,pname,ivalue,phelp));
      }
      else if (strcmp(ptype,"float") == 0) {
	fvalue=atof(cpl_table_get_string(tab,"param_value",i));
         xsh_parameters_new_float(result,rec_id,pname,fvalue,phelp);
      }
      else if (strcmp(ptype,"double") == 0) {
	dvalue=atof(cpl_table_get_string(tab,"param_value",i));
         xsh_parameters_new_double(result,rec_id,pname,dvalue,phelp);
      }
      else if (strcmp(ptype,"string") == 0) {
         svalue=cpl_table_get_string(tab,"param_value",i);
         xsh_parameters_new_string(result,rec_id,pname,svalue,phelp);
      }
      else if (strcmp(ptype,"bool") == 0) {
	bvalue=atoi(cpl_table_get_string(tab,"param_value",i));
         xsh_parameters_new_bool(result,rec_id,pname,bvalue,phelp);
      }
      else {
         xsh_msg_error("DRS table parameter type %s not supported!",ptype);
         return NULL;
      }
   }
   //cpl_parameterlist_dump(result,stdout);
  cleanup:
   return result;
}



static cpl_error_code
xsh_params_overscan_nir_check(cpl_parameterlist * parameters,const char* rec_id)
{

  cpl_parameter* p=NULL;
  const char* pname=NULL;
  pname="pre-overscan-corr";
  p=xsh_parameters_find(parameters,rec_id,pname);
  cpl_parameter_set_int(p,0);

  return cpl_error_get_code();

}



static cpl_error_code 
xsh_parameter_check_int(cpl_parameterlist* parameters,const char* rec_id,const char* pname,const int min,const int max,const int skip_val, const char* spec)
{
  int ival=0;
  int uval=0;
  cpl_parameter* p=NULL;


  check(uval=xsh_parameters_get_int(parameters,rec_id,pname));
  if(skip_val == -1) {
    if( (uval != skip_val && uval < min ) || uval > max ) {
      xsh_msg_warning("%s (%d) < %d or > %s (%d). Switch to defaults",
		      pname,uval,min,spec,max);
      check(p=xsh_parameters_find(parameters,rec_id,pname));
      ival=cpl_parameter_get_default_int(p);
      cpl_parameter_set_int(p,ival);
    }
  } else {
    if( uval < min  || uval > max ) {
      xsh_msg_warning("%s (%d) < %d or > %s (%d). Switch to defaults",
		      pname,uval,min,spec,max);
      check(p=xsh_parameters_find(parameters,rec_id,pname));
      ival=cpl_parameter_get_default_int(p);
      cpl_parameter_set_int(p,ival);
    }
  }

  cleanup:
  return cpl_error_get_code();

}

static cpl_error_code 
xsh_parameter_check_double(cpl_parameterlist* parameters,const char* rec_id,const char* pname,const double min,const double max,const double skip_val, const char* spec)
{
  double dval=0;
  double uval=0;
  cpl_parameter* p=NULL;

  check(uval=xsh_parameters_get_double(parameters,rec_id,pname));
  if(skip_val == -1) {
    if( (uval != skip_val && uval < min ) || uval > max ) {
      xsh_msg_warning("%s (%g) < %g or > %s (%g). Switch to defaults",
		      pname,uval,min,spec,max);
      check(p=xsh_parameters_find(parameters,rec_id,pname));
      dval=cpl_parameter_get_default_double(p);
      cpl_parameter_set_double(p,dval);
    }
  } else {
    if( uval < min  || uval > max ) {
      xsh_msg_warning("%s (%g) < %g or > %s (%g). Switch to defaults",
		      pname,uval,min,spec,max);
      check(p=xsh_parameters_find(parameters,rec_id,pname));
      dval=cpl_parameter_get_default_double(p);
      cpl_parameter_set_double(p,dval);
    }
  }

 cleanup:
  return cpl_error_get_code();
}


static cpl_error_code
xsh_params_crhclip_check(cpl_parameterlist * parameters, const char* rec_id)
{

  const char* pname=NULL;

  pname="crh-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="crh-clip-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="crh-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_noise_clip_check(cpl_parameterlist * parameters, const char* rec_id)
{

  const char* pname=NULL;

  pname="noise-clip-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="noise-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-9,"");

  pname="noise-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="noise-clip-diff";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="noise-lower-rejection";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="noise-higher-rejection";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");
 
  return cpl_error_get_code();

}



static cpl_error_code
xsh_params_crhsingle_check(cpl_parameterlist * parameters, const char* rec_id)
{

  const char* pname=NULL;
  /*
  pname="removecrhsingle-frac-max";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");
  */

  pname="removecrhsingle-sigmalim";
  xsh_parameter_check_double(parameters,rec_id,pname,0,200,-9,"");

  pname="removecrhsingle-flim";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="removecrhsingle-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,1000,-9,"");

  return cpl_error_get_code();


}

/*
static cpl_error_code
xsh_params_combinenod_check(cpl_parameterlist * parameters,const char* rec_id)
{

  
  const char* pname=NULL;
  pname="combinenod-min";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  pname="combinenod-clip-sigma";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="combinenod-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-9,"");

  pname="combinenod-clip-diff";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");
  
  return cpl_error_get_code();

}
*/
static cpl_error_code
xsh_params_optextract_check(cpl_parameterlist * parameters,const char* rec_id,
			    const int sizey)
{

  const char* pname=NULL;

  pname="optextract-oversample";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-9,"");

  pname="optextract-box-half-size";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-9,"");

  pname="optextract-chunk-size";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-9,"");

  pname="optextract-step-lambda";
  xsh_parameter_check_double(parameters,rec_id,pname,0,210,-9,"nm");

  pname="optextract-clip-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="optextract-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="optextract-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,1,200,-9,"");

  pname="optextract-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,1,200,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_follow_arclines_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="followarclines-search-window-half-size";
  xsh_parameter_check_int(parameters,rec_id,pname,1,60,-9,"");

  pname="followarclines-order-edges-mask";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="followarclines-min-sn";
  xsh_parameter_check_double(parameters,rec_id,pname,0,200,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_extract_mask_size_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="stdextract-interp-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,1000,-9,"");



  return cpl_error_get_code();

}


static cpl_error_code
xsh_params_tilt_clip_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="tilt-clip-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="tilt-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  pname="tilt-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,200,-9,"");

  return cpl_error_get_code();

}


static cpl_error_code
xsh_params_spec_res_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="specres-clip-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="specres-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  pname="specres-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,200,-9,"");

  return cpl_error_get_code();

}


static cpl_error_code
xsh_params_background_check(cpl_parameterlist * parameters,const char* rec_id,
			    const int sizex,const int sizey, const int norder)
{
  //int nb_y_max=0;
  //int radius_y=0;

  const char* pname=NULL;

  pname="background-poly-deg-x";
  xsh_parameter_check_int(parameters,rec_id,pname,0,15,-9,"");

  pname="background-poly-deg-y";
  xsh_parameter_check_int(parameters,rec_id,pname,0,15,-9,"");


  pname="background-poly-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  //cleanup:
  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_rectify_check(cpl_parameterlist * parameters, const char* rec_id)
{

  const char* pname=NULL;

  pname="rectify-radius";
  xsh_parameter_check_double(parameters,rec_id,pname,1,100,-9,"");

  pname="rectify-bin-slit";
  xsh_parameter_check_double(parameters,rec_id,pname,0,6,-1,"arcsec");

  pname="rectify-bin-lambda";
  xsh_parameter_check_double(parameters,rec_id,pname,0,210,-1,"nm");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_localize_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="localize-chunk-nb";
  xsh_parameter_check_int(parameters,rec_id,pname,1,1000,-9,"");

  pname="localize-thresh";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localize-deg-lambda";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="localize-slit-position";
  xsh_parameter_check_double(parameters,rec_id,pname,-7,7,-9,"");

  pname="localize-slit-hheight";
  xsh_parameter_check_double(parameters,rec_id,pname,0,7,-9,"");

  /* FIXME: different default on respon_slit_nod and stare/offset */
  pname="localize-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="localize-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  return cpl_error_get_code();


}


static cpl_error_code
xsh_params_sky_bspline_check(cpl_parameterlist * parameters,const char* rec_id,
			     const int biny)
{

  int nbkpts_max=20000/(0.75 *biny);
  int niter_max=100;
  const char* pname=NULL;

  pname="sky-bspline-nbkpts-first";
  xsh_parameter_check_int(parameters,rec_id,pname,1,nbkpts_max,-1,"");

  pname="sky-bspline-nbkpts-second";
  xsh_parameter_check_int(parameters,rec_id,pname,1,nbkpts_max,-1,"");

  pname="sky-bspline-order";
  xsh_parameter_check_int(parameters,rec_id,pname,0,12,-9,"");

  pname="sky-bspline-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,1,niter_max,-9,"");

  pname="sky-bspline-kappa";
  xsh_parameter_check_double(parameters,rec_id,pname,1,10,-9,"");

  pname="sky-slit-edges-mask";
  xsh_parameter_check_double(parameters,rec_id,pname,0,7,-9,"");

  pname="sky-hheight1";
  xsh_parameter_check_double(parameters,rec_id,pname,0,7,-9,"");

  pname="sky-hheight2";
  xsh_parameter_check_double(parameters,rec_id,pname,0,7,-9,"");

  return cpl_error_get_code();

}



static cpl_error_code
xsh_params_model_anneal_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="model-anneal-factor";
  xsh_parameter_check_double(parameters,rec_id,pname,0,10,-9,"");

  pname="model-scenario";
  xsh_parameter_check_int(parameters,rec_id,pname,0,8,-9,"");

  pname="model-maxit";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100000,-9,"");

   return cpl_error_get_code();

}

static cpl_error_code
xsh_params_overscan_check(cpl_parameterlist * parameters,const char* rec_id)
{

   const char* pname=NULL;

   pname="pre-overscan-corr";
   xsh_parameter_check_int(parameters,rec_id,pname,0,6,-1,"");

   return cpl_error_get_code();



}

static cpl_error_code
xsh_params_detect_arclines_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;
  int deg_slit_min=0;
  int deg_slit_max=0;

  pname="detectarclines-fit-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,60,-1,"");

  pname="detectarclines-search-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,60,-9,"");

  pname="detectarclines-running-median-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,1,60,-9,"");

  pname="detectarclines-wavesol-deg-lambda";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="detectarclines-wavesol-deg-order";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  if(strcmp(rec_id,"xsh_predict") == 0) {
    deg_slit_max=0;
    deg_slit_min=0;
  } else {
    deg_slit_max=0;
    deg_slit_min=10;
  }

  if (strcmp("xsh_2dmap", rec_id) == 0) {
    pname = "detectarclines-wavesol-deg-slit";
    xsh_parameter_check_int(parameters,rec_id,pname,deg_slit_min,deg_slit_max,-9,"");

  }

  if(strcmp(rec_id,"xsh_predict") == 0) {
    pname="detectarclines-ordertab-deg-y";
    xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");
  }
  pname="detectarclines-min-sn";
  xsh_parameter_check_double(parameters,rec_id,pname,0,200,-1,"");

  pname="detectarclines-clip-sigma";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="detectarclines-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,200,-9,"");

  pname="detectarclines-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_detect_continuum_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="detectcontinuum-search-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-1,"");

  pname="detectcontinuum-running-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,1,100,-1,"");

  pname="detectcontinuum-fit-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  pname="detectcontinuum-center-thresh-fac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectcontinuum-ordertab-step-y";
  xsh_parameter_check_int(parameters,rec_id,pname,1,20,-9,"");

  pname="detectcontinuum-ordertab-deg-y";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="detectcontinuum-clip-sigma";
  xsh_parameter_check_double(parameters,rec_id,pname,0,20,-9,"");

  pname="detectcontinuum-clip-frac";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectcontinuum-clip-res-max";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectcontinuum-clip-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_detectorder_check(cpl_parameterlist * parameters, 
			      const char* rec_id,const int sizex,
			      const int sizey,const int norders)
{

  const char* pname=NULL;

  pname="detectorder-edges-flux-thresh";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectorder-edges-search-win-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,sizex/norders/4,sizex/norders,-1,"");

  pname="detectorder-min-order-size-x";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex/norders,-1,"");

  pname="detectorder-chunk-half-size";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-9,"");

  pname="detectorder-slitlet-low-factor";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectorder-slitlet-up-factor";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="detectorder-chunk-half-size";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-9,"");

  pname="detectorder-min-sn";
  xsh_parameter_check_double(parameters,rec_id,pname,0,150,-9,"");

  pname="detectorder-d2-min-sn";
  xsh_parameter_check_double(parameters,rec_id,pname,0,150,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_dispersol_check(cpl_parameterlist * parameters,const char* rec_id)
{

  const char* pname=NULL;

  pname="dispersol-deg-x";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="dispersol-deg-y";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_compute_fpn_check(cpl_parameterlist * parameters,const char* rec_id, const int sizex, const int sizey)
{

  int hsize=0;
  int nsamples=0;

  cpl_parameter* p=NULL;
  const char* pname=NULL;
  int ival=0;

  pname="fpn_llx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="fpn_urx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="fpn_lly";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="fpn_ury";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="fpn_nsamples";
  check(nsamples=xsh_parameters_get_int(parameters,rec_id,pname));


  if( nsamples<1 || nsamples > sizex || nsamples > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size. Switch to defaults",pname,nsamples,sizex);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

  pname="fpn_hsize";
  check(hsize=xsh_parameters_get_int(parameters,rec_id,pname));
  if( hsize<1 || hsize > sizex || hsize > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size (%d). Switch to defaults",pname,hsize,sizex,sizey);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

cleanup:
  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_stacking_check(cpl_parameterlist * parameters,
				   const char* rec_id)
{

  const char* pname=NULL;

  pname="stacking_ks_low";
  xsh_parameter_check_int(parameters,rec_id,pname,0,20,-9,"");

  pname="stacking_ks_iter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,200,-9,"");

  return cpl_error_get_code();
}



static cpl_error_code
xsh_params_stack_check(cpl_parameterlist * parameters,
				   const char* rec_id)
{

  const char* pname=NULL;

  pname="klow";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");

  pname="khigh";
  xsh_parameter_check_double(parameters,rec_id,pname,0,100,-9,"");


  return cpl_error_get_code();
}


static cpl_error_code
xsh_params_compute_ron_region1_check(cpl_parameterlist * parameters,
				   const char* rec_id,
				   const int sizex,const int sizey)

{

  const char* pname=NULL;

  pname="ref1_llx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ref1_urx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ref1_lly";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="ref1_ury";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  return cpl_error_get_code();

}

static cpl_error_code
xsh_params_compute_ron_region2_check(cpl_parameterlist * parameters,
				   const char* rec_id,
				   const int sizex,const int sizey)

{
  const char* pname=NULL;
 
  pname="ref2_llx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ref2_urx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ref2_lly";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="ref2_ury";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  return cpl_error_get_code();


}

static cpl_error_code
xsh_params_compute_ron_mbias_set3_check(cpl_parameterlist * parameters,
				   const char* rec_id,
				   const int sizex,const int sizey)

{

  const char* pname=NULL;
  cpl_parameter* p=NULL;
  int nsamples=0;
  int hsize=0;
  int ival=0;

  pname="random_nsamples";
  check(nsamples=xsh_parameters_get_int(parameters,rec_id,pname));


  if( nsamples<1 || nsamples > sizex || nsamples > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size. Switch to defaults",pname,nsamples,sizex);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

  pname="random_sizex";
  check(hsize=xsh_parameters_get_int(parameters,rec_id,pname));
  if( hsize<1 || hsize > sizex || hsize > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size (%d). Switch to defaults",pname,hsize,sizex,sizey);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

cleanup:
  return cpl_error_get_code();


}

static cpl_error_code
xsh_params_compute_ron_mdark_check(cpl_parameterlist * parameters,
				   const char* rec_id,
				   const int sizex,const int sizey)

{
  int hsize=0;
  int nsamples=0;

  cpl_parameter* p=NULL;
  const char* pname=NULL;
  int ival=0;

  pname="ron_llx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ron_urx";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizex,-1,"detector X size");

  pname="ron_lly";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="ron_ury";
  xsh_parameter_check_int(parameters,rec_id,pname,1,sizey,-1,"detector Y size");

  pname="ron_nsamples";
  check(nsamples=xsh_parameters_get_int(parameters,rec_id,pname));

  if( nsamples<1 || nsamples > sizex || nsamples > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size. Switch to defaults",pname,nsamples,sizex);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

  pname="ron_hsize";
  check(hsize=xsh_parameters_get_int(parameters,rec_id,pname));
  if( hsize<1 || hsize > sizex || hsize > sizey ) {
    xsh_msg_warning("%s (%d) < 1 or > detector X size (%d) or > detector Y size (%d). Switch to defaults",pname,hsize,sizex,sizey);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_int(p);
    cpl_parameter_set_int(p,ival);
  }

cleanup:
  return cpl_error_get_code();


}


static cpl_error_code
xsh_params_compute_ron_check(cpl_parameterlist * parameters,
				   const char* rec_id,
				   const int sizex,const int sizey)
{

   if(strcmp(rec_id,"xsh_mbias") ==0 ) {
      check(xsh_params_compute_ron_region1_check(parameters,rec_id,sizex,sizey));
      xsh_params_compute_ron_region2_check(parameters,rec_id,sizex,sizey);
      xsh_params_compute_ron_mbias_set3_check(parameters,rec_id,sizex,sizey);
   } else if(strcmp(rec_id,"xsh_mdark") ==0 ) {
      xsh_params_compute_ron_region1_check(parameters,rec_id,sizex,sizey);
      xsh_params_compute_ron_mdark_check(parameters,rec_id,sizex,sizey);
   }

cleanup:
  return cpl_error_get_code();

}


static cpl_error_code 
xsh_params_localizeifu_check(cpl_parameterlist* parameters, const char* rec_id){

  int use_skymask=0;
  cpl_parameter* p=NULL;
  const char* pname=NULL;
  int ival=0;
  
  pname="localizeifu-bckg-deg";
  xsh_parameter_check_int(parameters,rec_id,pname,0,100,-9,"");

  pname="localizeifu-smooth-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="localizeifu-wavelet-nscales";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="localizeifu-wavelet-hf-skip";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="localizeifu-sigma-low";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-sigma-up";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-snr-low";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-snr-up";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-slitlow-edges-mask";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-slitup-edges-mask";
  xsh_parameter_check_double(parameters,rec_id,pname,0,1,-9,"");

  pname="localizeifu-use-skymask";
  check(use_skymask=xsh_parameters_get_boolean(parameters,rec_id,pname));
  if( (use_skymask < 0) || use_skymask > 10 ) {
    xsh_msg_warning("%s (%d) < 0 or > 10. Switch to defaults",
                    pname,use_skymask);
    check(p=xsh_parameters_find(parameters,rec_id,pname));
    ival=cpl_parameter_get_default_bool(p);
    cpl_parameter_set_bool(p,ival);
  }


  pname="localizeifu-chunk-hsize";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  cleanup:
  return cpl_error_get_code();

}

static cpl_error_code 
xsh_params_correctifu_check(cpl_parameterlist* parameters, const char* rec_id){


  const char* pname=NULL;

  pname="correctifu-niter";
  xsh_parameter_check_int(parameters,rec_id,pname,0,10,-9,"");

  pname="correctifu-lambdaref";
  xsh_parameter_check_double(parameters,rec_id,pname,300,1500,-1,"");

  pname="correctifu-lambdaref-hsize";
  xsh_parameter_check_double(parameters,rec_id,pname,0,10,-9,"");

  return cpl_error_get_code();

}

cpl_error_code
xsh_recipe_params_check(cpl_parameterlist * parameters,xsh_instrument* instrument,const char* rec_id)
{
  XSH_ARM arm;
  int binx=1;
  int biny=1;
  int sizex=0;
  int sizey=0;
  int norders=0;

  check(arm =xsh_instrument_get_arm(instrument));

  if ( arm == XSH_ARM_UVB ) {
    binx=xsh_instrument_get_binx( instrument ) ;
    biny=xsh_instrument_get_biny( instrument ) ;

    sizex=UVB_ASIZE;
    sizex/=binx;
    sizey=UVB_BSIZE;
    sizey/=biny;
    norders=UVB_morder;
  } else if ( arm == XSH_ARM_AGC ) {
    binx=xsh_instrument_get_binx( instrument ) ;
    biny=xsh_instrument_get_biny( instrument ) ;

    sizex=UVB_ASIZE;
    sizex/=binx;
    sizey=UVB_BSIZE;
    sizey/=biny;
    norders=UVB_morder;
  } else if ( arm == XSH_ARM_VIS ) {
    binx=xsh_instrument_get_binx( instrument ) ;
    biny=xsh_instrument_get_biny( instrument ) ;

    sizex=VIS_ASIZE;
    sizex/=binx;
    sizey=VIS_BSIZE;
    sizey/=biny;
    norders=VIS_morder;

  } else if ( arm == XSH_ARM_NIR ) {

    sizex=NIR_ASIZE;
    sizey=NIR_BSIZE;
    norders=NIR_morder;

  } else {
    xsh_msg_error("arm not supported");
    return CPL_ERROR_ILLEGAL_INPUT;
  }

  if (strcmp(rec_id, "xsh_cfg_recover") == 0) {

  } else if (strcmp(rec_id, "xsh_mbias") == 0) {
    xsh_params_compute_fpn_check(parameters,rec_id,sizex,sizey);
    xsh_params_compute_ron_check(parameters,rec_id,sizex,sizey);
    xsh_params_stack_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_mdark") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    xsh_params_stack_check(parameters, rec_id);
    xsh_params_crhclip_check(parameters, rec_id);
    xsh_params_noise_clip_check(parameters,rec_id);
    xsh_params_compute_ron_check(parameters,rec_id,sizex,sizey);
    check(xsh_params_compute_fpn_check(parameters,rec_id,sizex,sizey));

  } else if (strcmp(rec_id, "xsh_mflat") == 0) {
    xsh_params_detectorder_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
  } else if (strcmp(rec_id, "xsh_predict") == 0) {
    xsh_params_detect_arclines_check(parameters, rec_id);
    xsh_params_model_anneal_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_orderpos") == 0) {
    xsh_params_detect_continuum_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_2dmap") == 0) {
    xsh_params_detect_arclines_check(parameters, rec_id);
    xsh_params_dispersol_check(parameters, rec_id);
    xsh_params_model_anneal_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_flexcomp") == 0) {
    xsh_params_detect_arclines_check(parameters, rec_id);
    xsh_params_dispersol_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_wavecal") == 0) {
    xsh_params_follow_arclines_check(parameters, rec_id);
    xsh_params_tilt_clip_check(parameters, rec_id);
    xsh_params_spec_res_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_respon_slit_stare") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    check(xsh_params_sky_bspline_check(parameters, rec_id, biny));
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_optextract_check(parameters, rec_id, sizey);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_respon_slit_offset") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_respon_slit_nod") == 0) {
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_scired_slit_stare") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    xsh_params_sky_bspline_check(parameters, rec_id, biny);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_optextract_check(parameters, rec_id, sizey);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_scired_slit_offset") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_scired_slit_nod") == 0) {
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_scired_ifu_offset") == 0) {
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    //xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
  } else if (strcmp(rec_id, "xsh_scired_ifu_stare") == 0) {
    xsh_params_overscan_check(parameters,rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
  } else if (strcmp(rec_id, "xsh_absorp") == 0) {
    xsh_params_overscan_check(parameters, rec_id);
    xsh_params_stack_check(parameters, rec_id);
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);

    xsh_params_sky_bspline_check(parameters, rec_id, biny);
    xsh_params_optextract_check(parameters, rec_id, sizey);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_geom_ifu") == 0) {
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localizeifu_check(parameters, rec_id);
    check(xsh_params_correctifu_check(parameters, rec_id));
  } else if (strcmp(rec_id, "xsh_scired_ifu_stare_drl") == 0) {
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else if (strcmp(rec_id, "xsh_scired_ifu_offset_drl") == 0) {
    xsh_params_background_check(parameters, rec_id, sizex, sizey, norders);
    xsh_params_crhsingle_check(parameters, rec_id);
    xsh_params_rectify_check(parameters, rec_id);
    xsh_params_localize_check(parameters, rec_id);
    xsh_params_extract_mask_size_check(parameters,rec_id);
  } else {

    xsh_msg_error("Parameter checking for recipe %s not supported", rec_id);

  }

  if ( arm == XSH_ARM_NIR ) {
     xsh_params_overscan_nir_check(parameters, rec_id);
  }

 cleanup:
  return cpl_error_get_code();

}


cpl_error_code
xsh_recipe_params_drs_check(cpl_parameterlist * parameters,xsh_instrument* instrument,const char* rec_id)
{
  XSH_ARM arm;
  int binx=1;
  int biny=1;
  int sizex=0;
  int sizey=0;
  //int norders=0;

  check(arm =xsh_instrument_get_arm(instrument));

  if ( arm == XSH_ARM_UVB ) {
    binx=xsh_instrument_get_binx( instrument ) ;
    biny=xsh_instrument_get_biny( instrument ) ;

    sizex=UVB_ASIZE;
    sizex/=binx;
    sizey=UVB_BSIZE;
    sizey/=biny;
    //norders=UVB_morder;
  } else if ( arm == XSH_ARM_AGC ) {
      binx=xsh_instrument_get_binx( instrument ) ;
      biny=xsh_instrument_get_biny( instrument ) ;

      sizex=UVB_ASIZE;
      sizex/=binx;
      sizey=UVB_BSIZE;
      sizey/=biny;
      //norders=UVB_morder;
  } else if ( arm == XSH_ARM_VIS ) {
    binx=xsh_instrument_get_binx( instrument ) ;
    biny=xsh_instrument_get_biny( instrument ) ;

    sizex=VIS_ASIZE;
    sizex/=binx;
    sizey=VIS_BSIZE;
    sizey/=biny;
    //norders=VIS_morder;

  } else if ( arm == XSH_ARM_NIR ) {

    sizex=NIR_ASIZE;
    sizey=NIR_BSIZE;
    //norders=NIR_morder;

  } else {
    xsh_msg_error("arm not supported");
    return CPL_ERROR_ILLEGAL_INPUT;
  }

  if (strcmp(rec_id, "xsh_cfg_recover") == 0) {

  } else if (strcmp(rec_id, "xsh_mbias") == 0) {
    xsh_params_stacking_check(parameters, rec_id);
    xsh_params_compute_ron_check(parameters, rec_id, sizex, sizey);
  } else if (strcmp(rec_id, "xsh_mdark") == 0) {
    check(xsh_params_crhclip_check(parameters, rec_id));
    check(xsh_params_noise_clip_check(parameters, rec_id));
    check(xsh_params_compute_ron_check(parameters, rec_id, sizex, sizey));
    xsh_params_compute_fpn_check(parameters, rec_id, sizex, sizey);
  } else if (strcmp(rec_id, "xsh_mflat") == 0) {
  } else if (strcmp(rec_id, "xsh_predict") == 0) {
  } else if (strcmp(rec_id, "xsh_orderpos") == 0) {
  } else if (strcmp(rec_id, "xsh_2dmap") == 0) {
  } else if (strcmp(rec_id, "xsh_geom_ifu") == 0) {
  } else if (strcmp(rec_id, "xsh_flexcomp") == 0) {
  } else if (strcmp(rec_id, "xsh_wavecal") == 0) {
  } else if (strcmp(rec_id, "xsh_respon_slit_stare") == 0) {
  } else if (strcmp(rec_id, "xsh_respon_slit_offset") == 0) {
  } else if (strcmp(rec_id, "xsh_respon_slit_nod") == 0) {
  } else if (strcmp(rec_id, "xsh_scired_slit_stare") == 0) {
  } else if (strcmp(rec_id, "xsh_scired_slit_offset") == 0) {
  } else if (strcmp(rec_id, "xsh_scired_slit_nod") == 0) {
  } else if (strcmp(rec_id, "xsh_scired_ifu_offset") == 0) {
  } else if (strcmp(rec_id, "xsh_scired_ifu_stare") == 0) {
  } else {

    xsh_msg_error("Parameter checking for recipe %s not supported", rec_id);

  }

 cleanup:
  return cpl_error_get_code();

}


/**@}*/
