/*                                                                            *
 *   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,
    "During extraction the local spatial profile (=cross-order) of the spectrum is determined by collapsing the 2-dimensional spectrum along the dispersion axis. This parameter defines the half size of the region across which the spectrum is collapsed. This parameter affects flagged pixels interpolation. In case of spectrum gaps the recommended optimal value is: (size_of_gap [nm]/(2*size_of_pixel [nm])+1)"));

  /* --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, 0., 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, BSPLINE1, BSPLINE2 MEDIAN). BSPLINE is equivalent to BSPLINE1"));

  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(BSPLINE_METHOD1), par_method) == 0){
    result->method = BSPLINE_METHOD1;
  }
  else if (strcmp( SKY_METHOD_PRINT(BSPLINE_METHOD2), par_method) == 0){
    result->method = BSPLINE_METHOD2;
  }
  else if (strcmp( SKY_METHOD_PRINT(BSPLINE_METHOD3), par_method) == 0){
      result->method = BSPLINE_METHOD3;
    }
  else if (strcmp( SKY_METHOD_PRINT(BSPLINE_METHOD4), par_method) == 0){
       result->method = BSPLINE_METHOD4;
     }
  else if (strcmp( SKY_METHOD_PRINT(BSPLINE_METHOD5), par_method) == 0){
        result->method = BSPLINE_METHOD5;
      }
  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_crhsingle_nod_check(cpl_parameterlist * parameters, const char* rec_id, XSH_ARM arm)
{

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

  double min_sigma_val=20;
  if (
        (strcmp(rec_id, "xsh_respon_slit_nod") == 0) &&
        (arm == XSH_ARM_NIR )
      ) {
      min_sigma_val=40;
  }

  pname="removecrhsingle-sigmalim";
  cpl_parameter* p=xsh_parameters_find(parameters,rec_id,pname);
  double dval=cpl_parameter_get_default_double(p);
  if(dval< min_sigma_val) {
      cpl_parameter_set_default_double(p,min_sigma_val);
  }
  double uval=cpl_parameter_get_double(p);
  if(uval< min_sigma_val) {
       cpl_parameter_set_double(p,min_sigma_val);
   }
  xsh_params_crhsingle_check(parameters,rec_id);

  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,500,-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_crhsingle_nod_check(parameters, rec_id,arm);
    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();

}


/**@}*/
