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

#ifndef FLAMES_DEF_DRS_PAR_H
#define FLAMES_DEF_DRS_PAR_H

#include <stdbool.h>
#include <cpl.h>

extern int BKGPOL[2];


// To display (Y) or not (N) images or plots
//#define NICE_CREA  "N"

// How large must the SNR on a fibre be in a calibration frame, at a given
// order and x, for that slice to be considered "good"? Give a reasonable
// default value here */
//#define DECENTSNR   10.  
extern double DECENTSNR;

// How close should a detected fibre be to the position predicted by the 
// 0 order approximation, for it to be recognised and labeled in 
// matchorders() */
extern double MATCHTHRES;

// Half fibre width on the detector: 520,580 6.5, 860 7.0
// This is updated on the fly during data reduction
extern double HALFIBREWIDTH;

//Maximum number of fibres
extern int MAXFIBRES;

//SlitFF size & Y shift keywords
//===========================START========================
//Amount of pix from 50% limit of SlitFF flat part discarded
//to be sure to be in the flat part of the SlitFF
//good default value is 3 pix
//#define FLAMES_SAV_BORD_SZ 3
extern int FLAMES_SAV_BORD_SZ;


//half X window size for median filter. Good default: 3
//#define FLAMES_X_WIND_SIZE 3
extern int FLAMES_X_WIND_SIZE;

//half Y window size for median filter. Good defauld: 5
//#define FLAMES_Y_WIND_SIZE 5
extern int FLAMES_Y_WIND_SIZE;

//search window size to filter image. Good default: 100
//#define FLAMES_Y_SEARCH_WIND 100
extern int FLAMES_Y_SEARCH_WIND;


//number of order cut upper and lower. Good default: 2
//#define FLAMES_ORD_TRESH 2
extern int FLAMES_ORD_TRESH;

//k-s clipping iterations over median. Good default: 4
//#define FLAMES_N_CLIP_MED 4
extern int FLAMES_N_CLIP_MED;

//k-s clipping iterations over average. Good default: 2
//#define FLAMES_N_CLIP_AVG 2
extern int FLAMES_N_CLIP_AVG;

//signal fraction to set upp and low cut. Good default: 0.5
//Note by AM: 0.5 is small but more trustable to detect the
//real end of a SlitFF. With a small value one could always
//take FLAMES_SAV_BORD_SIZE slightly wider (3 pix instead of 2)
//#define FLAMES_INT_TRESH 0.5
extern double FLAMES_INT_TRESH;


//SlitFF size & Y shift keywords


// Number of traces (orders times fibres)
//extern int NBTRACES;

// Minimum fibre fraction coverage for extraction
extern double MINFIBREFRAC;

// Inline background fitting
extern const char* BKGFITINLINE;

// Background fitting method:
extern const char* BKGFITMETHOD;

// Background table bad pixel frame scanning switch
// Values:none, fraction, absolute
// Default: none
extern const char* BKGBADSCAN;

// Background table bad pixel frame scanning window size BKGBADWIN 50,50
extern int BKGBADWIN[2];
extern int BKGBADWINX;
extern int BKGBADWINY;

// Background table bad pixel frame scanning threshold fraction
extern double BKGBADMAXFRAC;

// Background table bad pixel frame scanning threshold number
extern int BKGBADMAXTOT;

// Background window number in each full inter order
extern int BKG_MAX_IO_WIN;

// Polinomial degree used for BKG fit  order  DRS_BKG_FIT_POL 2,2
extern int DRS_BKG_FIT_POL[2];
extern int DRS_BKG_FIT_POL_X;
extern int DRS_BKG_FIT_POL_Y;


// x,y maximum size of each background window: BKG_XY_WIN_SZ 6,2
extern double BKG_XY_WIN_SZ[2];

// XHALFWINDOW,YHALFWINDOW  window: 2,1    DRS_FILT_HW_XY 2,1
extern int DRS_FILT_HW[2];
extern int DRS_FILT_HW_X;
extern int DRS_FILT_HW_Y;

// maximum filtering iterations in frame preparation 300
extern int DRS_FILT_IMAX;

// maximum filtering iterations in frame preparation 10
extern int DRS_FILT_KS;

// Do you want mask saturated pixels in frame preparation ([YES]/NO)? 
extern const char* DRS_FILT_SAT_SW;

// Do you want a filter/generated badpixel mask: ([NONE]/MEDIAN)? 
extern const char* DRS_FILT_MASK;

// Gaussian pseudofibre HWHM for correlation
extern double GAUSSFIBRESIGMA;



// Gaussian pseudofibre total halfwidth for correlation
extern  double GAUSSHALFWIDTH;

// Half width of the interval to scan for correlation, when determining y shift
extern double MAXYSHIFT;

// This is the maximum number of kappa-sigma clipping iterations which we 
// are willing to perform in background fitting */
extern int MAXBACKITERS;

// This is the maximum fraction of windows/pixels which we are willing to 
// discard by kappa-sigma clipping in each iteration of the background 
// fitting loop */
extern double MAXDISCARDFRACT;

// This is the maximum number of iterations which we 
// are willing to perform in correlation */
extern int MAXCORRITERS;

// This is the absolute accuracy with which we require in the correlation 
// to determine the y shift */
extern double CORRELTOL;

// This is the x step to use while computing the correlation: it must be 
// a positive integer, 1 means "use all pixels", 2 means 
// "use every other pixel", 3 means "use one every three" etc. */
extern int CORRELXSTEP;

// This is the scaling factor with which we define the gaussian width of
// synthetic fibres in correlation */
extern double GAUSSCORRELSCL;

// This is the scaling factor with which we define window out of which the 
// gaussian synthetic fibres are considered negligible in correlation */
extern double GAUSSCORRELWND;

// This is the maximum number of cleaning iterations to be tried on a given
// slice in flames_prep_fibre, before 
// giving up on its normalisability and falling
// back to the second cleaning strategy */
extern int MAXCLEANITERS;

// this is the maximum acceptable fraction of the flux in a given slices in
// one single pixel; a higher fraction than this means that there was some 
// numerical instability and/or unmasked bad pixel, and that it must be 
// discarded */
extern double MAXSINGLEPXFRC;

// This is the maximum number of iterations which we are willing to
// perform in optimal extraction */
extern int MAXOPTITERSINT;

// This is the minimum number of iterations which we are willing to
// perform in optimal extraction */
extern int MINOPTITERSINT;

// When performing sigma-clipping in the optimal extraction, how many
// other adjacent pixels in the x and/or y direction(s) should be 
// discarded along with the one exceeding the threshold? A cosmic or 
// cosmetic problem is likely to affect a spot larger than 1 pixel */
extern int XKILLSIZE;
extern int YKILLSIZE;

// In flames_tracing, a few arrays are statically defined, and need to be
// large enough to contain all the orders which could be possibly found;
// We define it to a hefty one thousend */
extern int MAXORDER;

// Width of the y half-window to use when performing order/fibre labelling */
//#define DYRANGE 300
extern int DYRANGE;
// Step of the scan in y while performing order/fibre labelling */
//#define DYSTEP .1
extern double DYSTEP;

// MASKTHRES defines the minimum value a rebinned mask must have in order
// to consider the corresponding pixel of the rebinned spectrum "good".
// Since a pixel in the rebinned frame may be computed using also bad pixels, 
// we want to throw out pixels which contain even a very small fraction of 
// "badness" 
extern double MASKTHRES;

// FRACSLICESTHRES defines the minimum fraction of slices that must be good, 
// for a fibre to be considered covered enough at the end of fillholes, in 
// flames_prep_fibreff, to avoid stupid instabilities in gaussselfcorrel
//  if a fibre is only very barely covered by the slit FF frames 
//#define FRACSLICESTHRES .3
extern double FRACSLICESTHRES;

// The maximum permitted sizes for the order tables created by the DRS */
extern int MAXROWS;
extern int MAXCOLS;

// ============================================
// Procedures default input parameter settings
// ============================================
// The following settings may be modified 
// (at user wish and own risk) to adjust extraction
// -------------------------------------------

// threshold value for maximum pixel saturation: good: 50000-60000
extern int DRS_PTHRE_MAX;

// threshold value for maximum pixel saturation: good: -20
extern int DRS_PTHRE_MIN;

// extraction method: opt/sta/fop/fst/qopt
extern const  char* DRS_EXT_MTD;

// K-S THRESHOLD good: 10
extern double  DRS_K_S_THRE;

// K-S THRESHOLD good: 10
extern int  DRS_KSIGMA_THRE;


// Integration window size good:  10 (if fibre deconvolution works fine)
extern double  DRS_EXT_W_SIZ;

// MIDAS to FITS conersion: Y/N
extern const char*  DRS_MIDAS2FITS;

// BIAS Subtraction method: M/<num>/N
// M:     Master bias subtraction
// <num>: constant value subtraction
// N:     no subtraction
extern const char*  DRS_BIAS_MTD;

// filter switch
extern const char* DRS_FILT_SW;

// slitff-fibreff frames preparation: [Y]/N
// Y: yes, slower, for DFO
// N: no, faster, for PSO once the CDB is ready
//#define  DRS_SFF_FIBFF "Y"

// crea Bad Pix table
//#define  DRS_CREA_BP_TAB "N"

// Physical model auto recover switch
// Y: yes, the physical model auto recovers
// N: no, the physical model does not auto recover
//#define  DRS_PHYSMOD_REC "Y"


// What merging method are we using: 
// FLAMES one or the standard ECHELLE? ECHELLE is more robust
//#define DRS_MER_MTD "ECHELLE"


// Produce or not raw science data
//#define DRS_SCI_RAW "Y"


// DRS MIDAS VERBOSITY
extern const char* DRS_VERBOSITY;

// DRS MIDAS MESSAGE LEVEL
//      if "{DRS_VERBOSITY}" .eq. "LOW" then
//     #define DRS_MES_LEV/i/1/1 4
// else if "{DRS_VERBOSITY}" .eq. "NORM" then
//     #define DRS_MES_LEV/i/1/1 3
// else if "{DRS_VERBOSITY}" .eq. "HIGH" then
//     #define DRS_MES_LEV/i/1/1 3
// else
//     #define DRS_MES_LEV/i/1/1 3
// endif
//#define DRS_MES_LEV 4


// DRS CUBIFY SWITCH 
extern const char* DRS_CUBIFY;

// DRS QC key holder  
//#define DRS_BKG_PIX 0
extern int DRS_BKG_PIX;

// DRS strenghtened correlation shape definition 
// and pre search of maximum switch:
// Y do pre search of correlation's maximum.
// N don't do it (do only search of max with modified Brent method
//  on points -3,0,+3)
extern const char* DRS_COR_MAX_FND;

// DRS Correlation function's range: [-DRS_COR_DEF_RNG,+DRS_COR_DEF_RNG] pix
extern float DRS_COR_DEF_RNG;

// DRS Correlation function's No of definition points
//  Effective No of points is 2*DRS_COR_DEF_PNT+1
extern int DRS_COR_DEF_PNT;

// DRS Correlation function's offset to range center
extern float DRS_COR_DEF_OFF;


//  Effective No of points is 2*DRS_COR_DEF_PNT+1
//#define DRS_WAVE_QC_LOG 0

// DRS QC key holder  
//#define DRS_CHI2_RED 0.
extern double DRS_CHI2_RED;

// DRS QC key holder  
//#define DRS_Y_SHIFT 0.

// DRS N LIT  FIBRES
//#define DRS_NLIT_FIBRES 0
extern int DRS_NLIT_FIBRES;


// DRS Wavecal linear fit mode:  
//#define DRS_WCAL_MODE "AUTO"

// DRS Wavecal Resolution Plots generation:  
//#define DRS_WCAL_RPLT "Y"

// DRS Wavecal FITS output tables:  
//#define DRS_WCAL_FITS "N"

// DRS Wavecal FITS output tables:  
extern const char* DRS_BASE_NAME;

// DRS Wavecal FITS output tables:  
//#define DRS_SCI_CUBE "N"

// DRS Wavecal polynomial solution degree:  originally 5, 4 is more robust
//#define DRS_WCAL_DC 4

// DRS Wavecal polynomial solution tolerance:  0.6
//#define DRS_WCAL_TOL 0.6


// DRS Wavecal parameters:  
//#define DRS_WCAL_PAR {DRS_WCAL_MODE}, {DRS_WCAL_RPLT}, {DRS_WCAL_FITS}, {DRS_WCAL_DC}, {DRS_WCAL_TOL}


// DRS Multiple parameter: 
//#define DRS_SCI_PAR1 {DRS_EXT_MTD}, {DRS_COR_MAX_FND}, {DRS_COR_DEF_RNG},  {DRS_COR_DEF_PNT}, {DRS_COR_DEF_OFF}

// DRS Wavecal polynomial solution tolerance:  
//#define DRS_SCI_PAR2 {DRS_BIAS_MTD},{DRS_FILT_SW},{DRS_PTHRE_MAX}


// First component of P8 for the 3 settings:
// Sometime in 520 setting one may have less problems
// using a higher value of DRS_P8_OFPOS_S1, like 0.2
// Reasonable values are:
// 520: .05
// 580: .10
// 860: .10 

// DRS Parameter P8 for hough/echelle: Note flames_ofpos (OFPOS/FLAMES)
// Uses values: 
// DRS_P8_OFPOS="{DRS_P8_OFPOS_S1(i)},-.1,.1,.005,1."   i=1,2,3

extern double DRS_P8_OFPOS_S1_1;
extern double DRS_P8_OFPOS_S1_2;
extern double DRS_P8_OFPOS_S1_3;



// Chopped part in CCD in doing hough/echelle
// same meaning of parameter SCAN of hough/echelle 
// DRS_SCAN_MIN: lower part of CCD
// DRS_SCAN_MAX: upper part of CCD
// Those aliases are hardcoded in OFPOS/FLAMES

//#define DRS_SCAN_MIN 55,73,73 // 520: 55
                                          // 580: 73
                                          // 860: 73 
//#define DRS_SCAN_MAX 1993,1975,1975 // 520: 1993 (1993=2048-55)
                                                // 580: 1975 (1975=2048-73)
                                                // 860: 1975 
extern int DRS_SCAN_MIN_1;
extern int DRS_SCAN_MIN_2;
extern int DRS_SCAN_MIN_3;

extern int DRS_SCAN_MAX_1;
extern int DRS_SCAN_MAX_2;
extern int DRS_SCAN_MAX_3;

// To easily temporally test data reduction
//#define DRS_DIR_SPFMT /new_format/with_extensions

//#define DRS_MER_DELTA "5,5"
extern const char* DRS_DEL_SW;


//#define DRS_WCHAR_DEG 4
//#define DRS_WCHAR_WID 4.

// Simultaneous fibre data reduction
//#define DRS_SCI_SIM Y
//#define DRS_CVEL_SWITCH "Y"

// Simultaneous fibre data reduction
//#define FLAMES_DRS_SFF_HW_MIN 10
extern int FLAMES_DRS_SFF_HW_MIN;

// SWITCH FOR generating not blaze corrected extracted frames.
//#define DRS_BLAZE_SW "Y"
extern bool DRS_BLAZE_SW;


cpl_error_code
flames_update_drs_par(cpl_propertylist* plist);

cpl_error_code
flames_save_drs_par(cpl_propertylist* plist);

cpl_error_code
flames_def_drs_par(cpl_parameterlist* list, const char* recipe_id);



void uves_parameters_new_int( cpl_parameterlist* list,
			      const char* recipe_id, const char* name,int value, const char* comment);


void uves_parameters_new_boolean( cpl_parameterlist* list,
				  const char* recipe_id, const char* name,int value, const char* comment);

void uves_parameters_new_string( cpl_parameterlist* list,
				       const char* recipe_id,
				       const char* name,
				       const char *value,
				 const char* comment);


void uves_parameters_new_float( cpl_parameterlist* list,
				const char* recipe_id,const char* name,float value, const char* comment);

void uves_parameters_new_double( cpl_parameterlist* list,
				 const char* recipe_id,const char* name,double value, const char* comment);


void uves_parameters_new_range_int( cpl_parameterlist* list,
					  const char* recipe_id,
					  const char* name,
					  int def, int min, int max,
				    const char* comment);


void uves_parameters_new_range_float( cpl_parameterlist* list,
					  const char* recipe_id,
					  const char* name,
					  float def, float min, float max,
				      const char* comment);

void uves_parameters_new_range_double( cpl_parameterlist* list,
					  const char* recipe_id,
					  const char* name,
				       double def, double min, double max,					  const char* comment);


char * uves_parameters_get_string( const cpl_parameterlist* list,
				   const char* recipe_id, const char* name);

int uves_parameters_get_boolean( const cpl_parameterlist * list,
				 const char* recipe_id, const char* name);



int uves_parameters_get_int( cpl_parameterlist* list,
			     const char* recipe_id, const char* name);

double uves_parameters_get_double( cpl_parameterlist* list,
				   const char* recipe_id, const char* name);

#endif
