/*                                                                           *
 *   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    *
 *                                                                           */

/*
 * $Author: amodigli $
 * $Date: 2012-06-19 07:45:26 $
 * $Revision: 1.23 $
 * $Name: not supported by cvs2svn $
 */
#ifndef XSH_DATA_RESID_TAB_H
#define XSH_DATA_RESID_TAB_H

#include <cpl.h>
#include <xsh_data_wavesol.h>

#define XSH_RESID_TAB_TABLE_NB_COL 20

#define XSH_RESID_TAB_TABLE_COLNAME_WAVELENGTH "Wavelength"
#define XSH_RESID_TAB_TABLE_UNIT_WAVELENGTH "nm"

#define XSH_RESID_TAB_TABLE_COLNAME_SN "SN"
#define XSH_RESID_TAB_TABLE_UNIT_SN "none"

#define XSH_RESID_TAB_TABLE_COLNAME_ORDER "Order"
#define XSH_RESID_TAB_TABLE_UNIT_ORDER "none"

#define XSH_RESID_TAB_TABLE_COLNAME_SLITPOSITION "Slit_position"
#define XSH_RESID_TAB_TABLE_UNIT_SLITPOSITION "arcsec"

#define XSH_RESID_TAB_TABLE_COLNAME_SLITINDEX "Slit_index"
#define XSH_RESID_TAB_TABLE_UNIT_SLITINDEX "none"

#define XSH_RESID_TAB_TABLE_COLNAME_XTHPRE "Xthpre"
#define XSH_RESID_TAB_TABLE_UNIT_XTHPRE "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_YTHPRE "Ythpre"
#define XSH_RESID_TAB_TABLE_UNIT_YTHPRE "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_XTHCOR "Xthcor"
#define XSH_RESID_TAB_TABLE_UNIT_XTHCOR "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_YTHCOR "Ythcor"
#define XSH_RESID_TAB_TABLE_UNIT_YTHCOR "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_XGAUSS "XGauss"
#define XSH_RESID_TAB_TABLE_UNIT_XGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_YGAUSS "YGauss"
#define XSH_RESID_TAB_TABLE_UNIT_YGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_SIGMAXGAUSS "SigmaXGauss"
#define XSH_RESID_TAB_TABLE_UNIT_SIGMAXGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_SIGMAYGAUSS "SigmaYGauss"
#define XSH_RESID_TAB_TABLE_UNIT_SIGMAYGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_FWHMXGAUSS "FwhmXGauss"
#define XSH_RESID_TAB_TABLE_UNIT_FWHMXGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_FWHMYGAUSS "FwhmYGauss"
#define XSH_RESID_TAB_TABLE_UNIT_FWHMYGAUSS "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_NORMGAUSS "NormGauss"
#define XSH_RESID_TAB_TABLE_UNIT_NORMGAUSS "ADU"

#define XSH_RESID_TAB_TABLE_COLNAME_XPOLY "Xpoly"
#define XSH_RESID_TAB_TABLE_UNIT_XPOLY "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_YPOLY "Ypoly"
#define XSH_RESID_TAB_TABLE_UNIT_YPOLY "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_XTHANNEAL "Xthanneal"
#define XSH_RESID_TAB_TABLE_UNIT_XTHANNEAL "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_YTHANNEAL "Ythanneal"
#define XSH_RESID_TAB_TABLE_UNIT_YTHANNEAL "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_RESIDXPOLY "ResidXpoly"
#define XSH_RESID_TAB_TABLE_UNIT_RESIDXPOLY "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_RESIDYPOLY "ResidYpoly"
#define XSH_RESID_TAB_TABLE_UNIT_RESIDYPOLY "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_RESIDXMODEL "ResidXmodel"
#define XSH_RESID_TAB_TABLE_UNIT_RESIDXMODEL "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_RESIDYMODEL "ResidYmodel"
#define XSH_RESID_TAB_TABLE_UNIT_RESIDYMODEL "pixel"

#define XSH_RESID_TAB_TABLE_COLNAME_FLAG "Flag"
#define XSH_RESID_TAB_TABLE_UNIT_FLAG "none"

/* get property  PROPERTY of type TYPE from OBJECT */
#define PROPERTY_GET( OBJECT, PROPERTY, TYPE, DEFAULT)\
TYPE OBJECT##_get_##PROPERTY( OBJECT* obj)\
{\
  TYPE result = DEFAULT;\
\
  XSH_ASSURE_NOT_NULL( obj);\
  result = obj->PROPERTY;\
\
  cleanup:\
    return result;\
}

/* get property  PROPERTY of type TYPE from resid_tab */
#define RESID_TAB_PROPERTY_GET( PROPERTY, TYPE, DEFAULT)\
  PROPERTY_GET( xsh_resid_tab, PROPERTY, TYPE, DEFAULT)

typedef struct{
  /* solution type */
  int solution_type;
  /* Lambda lines */
  double *lambda;
  /* order lines */
  double *order;
  /* slit lines */
  double *slit;
  double *sn;
  /* slit index */
  int* slit_index;
  double *thpre_x;		/**< theoretical X lines position in Pre */
  double *thpre_y;		/**< theoretical Y lines position in Pre */
  double *thcor_x;		/**< Corrected X position */
  double *thcor_y;		/**< Corrected Y position */
  double *xgauss;  /**< Gaussian fit X position */
  double *ygauss; /**< Gaussian fit Y position */
  double *sig_xgauss; /**< Sigma of Gaussian fit X position */
  double *sig_ygauss; /**< Sigma of Gaussian fit Y position */
  double *fwhm_xgauss; /**< FWHM of Gaussian fit X position */
  double *fwhm_ygauss; /**< FWHM of Gaussian fit Y position */
  double *norm_gauss; /**< Norm of Gaussian fit */
  double *xpoly; /**< Polynomial fit X position */
  double *ypoly; /**< Polynomial fit Y position */
  double *thanneal_x; /**< Anneal new X position */
  double *thanneal_y; /**< Anneal new Y position */
  int* flag; /* to indicate if a line has been detected. If not why */
  /* size of the residual map */
  int size;
  /* median of difference between theoretical and polynomial fit in x */
  double median_diff_poly_fit_x;
  /* median of difference between theoretical and polynomial fit in y */
  double median_diff_poly_fit_y;
  /* mean of difference between theoretical and polynomial fit in x */
  double mean_diff_poly_fit_x;
  /* mean of difference between theoretical and polynomial fit in y */
  double mean_diff_poly_fit_y;
  /* stdev of difference between theoretical and polynomial fit in x */
  double stdev_diff_poly_fit_x;
  /* stdev of difference between theoretical and polynomial fit in y */
  double stdev_diff_poly_fit_y;


  /* header fits */
  cpl_propertylist* header;
}xsh_resid_tab;

xsh_resid_tab* 
xsh_resid_tab_create(int size, double *lambda, double *order,
                     double *slit, double* sn, int *slit_index,
                     double *thpre_x, double *thpre_y, 
                     double*corr_x, double* corr_y,
                     double *gaussian_norm, 
                     double *gaussian_fit_x, double *gaussian_fit_y,
                     double *gaussian_sigma_x, double *gaussian_sigma_y, 
                     double *gaussian_fwhm_x, double *gaussian_fwhm_y, int* flag,
                     xsh_wavesol *wavesol, int wavesol_type);


xsh_resid_tab* 
xsh_resid_tab_create_not_flagged(int size, double *lambda, double *order,
                     double *slit, double* sn, int *slit_index,
                     double *thpre_x, double *thpre_y, 
                     double*corr_x, double* corr_y,
                     double *gaussian_norm, 
                     double *gaussian_fit_x, double *gaussian_fit_y,
                     double *gaussian_sigma_x, double *gaussian_sigma_y, 
                     double *gaussian_fwhm_x, double *gaussian_fwhm_y, int* flag,
                     xsh_wavesol *wavesol, int wavesol_type);

xsh_resid_tab* xsh_resid_tab_load( cpl_frame* resid_tab_frame);
int xsh_resid_tab_get_size( xsh_resid_tab *resid);
double * xsh_resid_tab_get_lambda_data(xsh_resid_tab *resid) ;
double * xsh_resid_tab_get_order_data(xsh_resid_tab *resid) ;
double * xsh_resid_tab_get_slitpos_data(xsh_resid_tab *resid) ;
int* xsh_resid_tab_get_slit_index( xsh_resid_tab *resid);
double * xsh_resid_tab_get_thpre_x_data(xsh_resid_tab *resid) ;
double * xsh_resid_tab_get_thpre_y_data(xsh_resid_tab *resid) ;
double * xsh_resid_tab_get_xgauss_data(xsh_resid_tab *resid) ;
double * xsh_resid_tab_get_ygauss_data(xsh_resid_tab *resid) ;

void xsh_resid_tab_free( xsh_resid_tab **resid);
cpl_frame* xsh_resid_tab_save( xsh_resid_tab *resid, const char *filename,
			       xsh_instrument* instr,const char* tag);
void xsh_resid_tab_log( xsh_resid_tab* resid, const char *filename) ;
cpl_frame* xsh_resid_tab_erase_flagged( cpl_frame* resid,const char* name);

cpl_error_code
xsh_frame_table_resid_merge(cpl_frame* self, cpl_frame* right,
			    const int solution_type);

#endif  /* XSH_DATA_RESID_TAB_H */
