/*                                                                            *
 *   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: 2013-03-07 17:57:32 $
 * $Revision: 1.2 $
 * $Name: not supported by cvs2svn $
 */

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

/*----------------------------------------------------------------------------
                                 Includes
 ----------------------------------------------------------------------------*/
#include "xsh_utils_vector.h"
#include "xsh_utils_wrappers.h"
#include "xsh_utils.h"
#include "xsh_msg.h"
/**@{*/


/*
  @brief extract subvector centered at a given element with a given half size
  @param vin input data
  @param pos center position
  @param hsize hal vector size

  @return extracted vector
 * */

cpl_vector*
xsh_vector_extract_range(cpl_vector* vin,const cpl_size pos, const int hsize)
{
  cpl_vector* result;
  int i=0;
  int k=0;
  int size_i=0;
  int size_o=2*hsize+1;
  int ref=(int)pos;
  double* data_i=NULL;
  double* data_o=NULL;

  cpl_ensure(vin != NULL, CPL_ERROR_NULL_INPUT,NULL);
  cpl_ensure(hsize > 0, CPL_ERROR_ILLEGAL_INPUT,NULL);
  cpl_ensure(pos>hsize, CPL_ERROR_ILLEGAL_INPUT,NULL);
  cpl_ensure(hsize > 0, CPL_ERROR_ILLEGAL_INPUT,NULL);
  size_i=cpl_vector_get_size(vin);
  cpl_ensure(pos+hsize < size_i, CPL_ERROR_ILLEGAL_INPUT,NULL);

  result=cpl_vector_new(size_o);

  data_i=cpl_vector_get_data(vin);
  data_o=cpl_vector_get_data(result);

  for(i=-hsize;i<=hsize;i++){
    data_o[k]=data_i[ref+i];
    k++;
  }
  return result;
}
/*
  @brief generates a vector with factor times elements making local linear interpolation
  @param vin data
  @param factor upsampling factor

  @return upsampled vector
 * */
cpl_vector*
xsh_vector_upsample(cpl_vector* vin,const int factor)
{
  cpl_vector* result;
  int i=0;
  int j=0;
  int size_i=0;
  int size_o=0;
  double* data_i=NULL;
  double* data_o=NULL;
  double y1=0;
  double y2=0;
  /*
  double x1=0;
  double x2=0;
  */
  double m=0;

  cpl_ensure(vin != NULL, CPL_ERROR_NULL_INPUT,NULL);
  cpl_ensure(factor > 0, CPL_ERROR_ILLEGAL_INPUT,NULL);

  size_i=cpl_vector_get_size(vin);
  size_o=(size_i-1)*factor+1;

  result=cpl_vector_new(size_o);

  data_i=cpl_vector_get_data(vin);
  data_o=cpl_vector_get_data(result);
  /* here we make a linear interpolation between data points */
  for(i=0;i<size_i-1;i++){
    y1=data_i[i];
    y2=data_i[i+1];
    //x1=i;
    //x2=i+1;
    m=(y2-y1)/factor;
    for(j=0;j<factor;j++){
       data_o[i*factor+j]= y1 + m * j;
    }
  }
  data_o[size_o-1]=data_i[size_i-1];

  return result;
}

/*
  @brief generates a vector of values defined at each input wave pos that is a linear fit of values in range
         (wave[0],wmin_max)---(wmax_min,wave[max])
  @param vec_wave wave data
  @param vec_flux flux data
  @param wmin_max max value of start wave range up to which use data for fit of continuum
  @param wmax_min min value of final wave range from which use data for fit of continuum
  @return fit of continuum data vector
 * */
cpl_vector*
xsh_vector_fit_slope(cpl_vector* vec_wave,cpl_vector* vec_flux,const double wmin_max,const double wmax_min,const int degree)
{
  cpl_vector* vec_slope=NULL;
  int i=0;
  int size=0;
  int k=0;
  double* pwave=NULL;
  double* pflux=NULL;
  double* pslope=NULL;
  double* pvec_x=NULL;
  double* pvec_y=NULL;
  double mse=0;
  cpl_polynomial* pfit=NULL;

  cpl_vector* vec_x=NULL;
  cpl_vector* vec_y=NULL;

  /* input parameters consistency checks */
  cpl_ensure(vec_wave,CPL_ERROR_NULL_INPUT,NULL);
  cpl_ensure(vec_flux,CPL_ERROR_NULL_INPUT,NULL);
  cpl_ensure(wmin_max<wmax_min,CPL_ERROR_INCOMPATIBLE_INPUT,NULL);
  cpl_ensure(degree>0 && degree < 3,CPL_ERROR_INCOMPATIBLE_INPUT,NULL);

  /* extract from vector values that are supposed to follow linear relation */
  size=cpl_vector_get_size(vec_flux);
  vec_x=cpl_vector_new(size);
  vec_y=cpl_vector_new(size);
  pwave=cpl_vector_get_data(vec_wave);
  pflux=cpl_vector_get_data(vec_flux);
  pvec_x=cpl_vector_get_data(vec_x);
  pvec_y=cpl_vector_get_data(vec_y);

  for(i=0;i<size;i++) {
    if( pwave[i] <= wmin_max || pwave[i] >= wmax_min ) {
      pvec_x[k]=pwave[i];
      pvec_y[k]=pflux[i];
      k++;
    }
  }

  cpl_vector_set_size(vec_x,k);
  cpl_vector_set_size(vec_y,k);

  /* makes linear fit */
  pfit=xsh_polynomial_fit_1d_create(vec_x,vec_y,degree,&mse);

  /* define results */
  vec_slope=cpl_vector_new(size);
  pslope=cpl_vector_get_data(vec_slope);
  for(i=0;i<size;i++) {
    pslope[i] = cpl_polynomial_eval_1d( pfit, pwave[i], NULL);
  }
 xsh_free_vector(&vec_x);
 xsh_free_vector(&vec_y);
 xsh_free_polynomial(&pfit);
 return vec_slope;
}


/**@}*/
