/*                                                                          *
 *   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-04-27 17:35:03 $
 * $Revision: 1.5 $
 */

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

/*-------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_remove_crh_single  Test Remove Crh Multi function(s)
 * @ingroup unit_tests
 * 
 */
/*-------------------------------------------------------------------------*/
/**@{*/

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

#include <tests.h>
#include <stdlib.h>
#include <stdio.h>


#include <xsh_data_pre.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_data_instrument.h>
#include <xsh_data_spectrum.h>
#include <xsh_data_localization.h>
#include <xsh_drl.h>
#include <xsh_pfits.h>
#include <xsh_parameters.h>
#include <xsh_badpixelmap.h>
#include <xsh_utils_ifu.h>
#include <xsh_utils.h>
#include <cpl.h>
#include <math.h>

#include <string.h>
#include <getopt.h>

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

#define MODULE_ID "XSH_GAUSSIAN_FIT"

enum {
  HELP_OPT
} ;

static struct option long_options[] = {
  {"help", 0, 0, HELP_OPT},
  {0, 0, 0, 0}
};

static void Help( void )
{
  puts( "Unitary test of xsh_gaussian_fit");
  puts( "Usage: test_xsh_gaussian_fit [options] DATA_FILE");

  puts( "Options" ) ;
  puts( " --help             : What you see" ) ;
  puts( "\nInput Files" ) ;
  puts( "DATA_FILE           :ASCII x,y file y column is use for decomposition");
  TEST_END();
}


static void HandleOptions( int argc, char **argv)
{
  int opt ;
  int option_index = 0;

  while (( opt = getopt_long (argc, argv, 
    "help",
    long_options, &option_index)) != EOF ){
  
    switch ( opt ) {
    default: 
      Help(); exit(-1);
    }
  }
  return;
}


int main( int argc, char **argv)
{
  /* Declarations */
  int ret = 0 ;
  const char *file_name = NULL;
  FILE* file = NULL;
  char line[200];
  double xpos[10000];
  double ypos[10000];
  int i, size=0;
  int max = 10000;
  char res_name[256];
  
  /* gsl */
  double cpl_area=0, cpl_sigma=0, cpl_x0=0, cpl_offset=0;
  int status;

  cpl_vector *pos_vect = NULL;
  cpl_vector *data_vect = NULL;
  
  
  double init_par[6];
  double errs_par[6];

  /* Initialize libraries */
  TESTS_INIT(MODULE_ID);

  cpl_msg_set_level(CPL_MSG_DEBUG);
  xsh_debug_level_set(XSH_DEBUG_LEVEL_MEDIUM);

  /* Analyse parameters */
  HandleOptions( argc, argv);

  if ( (argc - optind) > 0 ) {
    file_name = argv[optind];
  }
  else {
    Help();
    exit( 0);
  }
  
  xsh_msg("---Input Files");
  xsh_msg("File    : %s ", file_name);

  /* READ data */
  file = fopen( file_name, "r");
  if (file != NULL){
    size=0;
    while ( size < max && fgets( line, 200, file)){
      char col1[20];
      char col2[20];

      if ( line[0] != '#'){
        /* Note: update the string format (the %__s) if col1(2) changes size.
         * Remember: field width must equal 1 less than sizeof(col1(2)). */
        sscanf(line,"%19s %19s", col1, col2);
        xpos[size] = atof(col1);
        ypos[size] = atof(col2);
        size++; 
      }
    }
  }
  if(file != NULL) {
    fclose(file);
  }

  check( pos_vect = cpl_vector_wrap( size, xpos)); 
  check( data_vect = cpl_vector_wrap( size, ypos));

  cpl_vector_fit_gaussian( pos_vect, NULL, data_vect, 
    NULL,CPL_FIT_ALL,&cpl_x0,&cpl_sigma,&cpl_area,&cpl_offset,NULL,NULL,NULL);

  printf( "CPL FIT area %f x0 %f sigma %f offset %f\n", cpl_area, cpl_x0, cpl_sigma, cpl_offset);

  xsh_gsl_init_gaussian_fit( pos_vect, data_vect, init_par);  
  check( xsh_gsl_fit_gaussian( pos_vect, data_vect, 0, init_par, errs_par, &status));


  printf ("area   = %.5f +/- %.5f\n", init_par[0], errs_par[0]);
  printf ("a      = %.5f +/- %.5f\n", init_par[1], errs_par[1]);
  printf ("b      = %.5f +/- %.5f\n", init_par[2], errs_par[2]);
  printf ("c      = %.5f +/- %.5f\n", init_par[3], errs_par[3]);
  printf ("x0     = %.5f +/- %.5f\n", init_par[4], errs_par[4]);	 
  printf ("sigma  = %.5f +/- %.5f\n", init_par[5], errs_par[5]);
        
  sprintf( res_name, "GSL_FIT_%s.dat", file_name);

  file = fopen( res_name, "w+");
  fprintf( file, "#x y\n");
  
  for( i=0; i< size; i++){
    double step = xpos[1]-xpos[0];
    double j;
    
    for (j=0; j< step; j+=step/10.){
      double t = xpos[i]+j;
      
      double area = init_par[0];
      double a = init_par[1];
      double b = init_par[2];
      double c = init_par[3];
      double x0 = init_par[4];
      double sigma =init_par[5];
      double height = area/sqrt(2*M_PI*sigma*sigma);
    
      double W = ((t-x0)*(t-x0))/(2*sigma*sigma);
      
      double Yi = height*exp(-W)+a+b*t+c*t*t;


      fprintf( file, "%f %f\n", t, Yi);
    }
  }
  fclose(file);

  sprintf( res_name, "CPL_FIT_%s.dat", file_name);

  file = fopen( res_name, "w+");
  fprintf( file, "#x y\n");
  
  for( i=0; i< size; i++){
    double step = xpos[1]-xpos[0];
    double j;
    
    for (j=0; j< step; j+=step/10.){
      double t = xpos[i]+j;
      
      double area = cpl_area;
      double a = cpl_offset;
      double b = 0;
      double c = 0;
      double x0 = cpl_x0;
      double sigma = cpl_sigma;
      double height = area/sqrt(2*M_PI*sigma*sigma);
    
      double W = ((t-x0)*(t-x0))/(2*sigma*sigma);
      
      double Yi = height*exp(-W)+a+b*t+c*t*t;


      fprintf( file, "%f %f\n", t, Yi);
    }
  }
  fclose(file);



  
  cleanup:
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret=1;
    }
    xsh_unwrap_vector( &pos_vect);
    xsh_unwrap_vector( &data_vect);
    TEST_END();
    return ret ;
}

/**@}*/
