/*                                                                          *
 *   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-09-14 07:16:32 $
 * $Revision: 1.2 $
 */

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

/*-------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_bspline  Test Object extraction
 * @ingroup unit_tests
 * 
 */
/*-------------------------------------------------------------------------*/
/**@{*/

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

#include <tests.h>

#include <xsh_error.h>
#include <xsh_msg.h>

/*
#include <xsh_data_pre.h>
#include <xsh_data_instrument.h>
#include <xsh_data_rec.h>
#include <xsh_data_localization.h>
#include <xsh_drl.h>
#include <xsh_pfits.h>

#include <xsh_badpixelmap.h>
#include <getopt.h>
*/
#include <cpl.h>


#include <stdio.h> 
#include <stdlib.h>
#include <math.h>
#include <gsl/gsl_bspline.h>
#include <gsl/gsl_multifit.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_statistics.h>

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

#define MODULE_ID "XSH_BSPLINE"

/* number of data points to fit */
#define N 200

/* number of fit coefficients */
#define NCOEFFS 12

/* nbreak = ncoeffs +2 -k = ncoeffs -2 since k = 4 */
#define NBREAK (NCOEFFS -2)


int
test_gsl_table(const char* fname) {

   cpl_table* t=NULL;
   double* w=NULL;
   double* f=NULL;
   double* e=NULL;

   t=cpl_table_load(fname,1,0);

   w=cpl_table_get_data_double(t,"WAVE");
   f=cpl_table_get_data_double(t,"FLUX");
   e=cpl_table_get_data_double(t,"ERR");




}

int test_gsl_example() {

  const size_t n = N;
  const size_t ncoeffs = NCOEFFS;
  const size_t nbreak = NBREAK;
  size_t i, j;
  gsl_bspline_workspace *bw;
  gsl_vector *B;
  double dy;
  gsl_rng *r;
  gsl_vector *c, *w;
  gsl_vector *x, *y;
  gsl_matrix *X, *cov;
  gsl_multifit_linear_workspace *mw;
  double chisq, dof; 
  //double tss, Rsq;


  gsl_rng_env_setup();
  r = gsl_rng_alloc(gsl_rng_default);

  /* allocate a cubic bspline workspace (k = 4) */
  bw = gsl_bspline_alloc(4, nbreak);
  B = gsl_vector_alloc(ncoeffs);

  x = gsl_vector_alloc(n);
  y = gsl_vector_alloc(n);
  X = gsl_matrix_alloc(n, ncoeffs);
  c = gsl_vector_alloc(ncoeffs);
  w = gsl_vector_alloc(n);
  cov = gsl_matrix_alloc(ncoeffs, ncoeffs);

  printf("#m=0,S=0\n");
  /* this is the data to be fitted */
  for (i = 0; i < n; ++i)
    {
      double sigma;
      double xi = (15.0 / (N - 1)) * i;
      double yi = cos(xi) * exp(-0.1 * xi);

      sigma = 0.1 * yi;
      dy = gsl_ran_gaussian(r, sigma);
      yi += dy;

      gsl_vector_set(x, i, xi);
      gsl_vector_set(y, i, yi);
      gsl_vector_set(w, i, 1.0 / (sigma * sigma));

      //printf("%f %f\n", xi, yi);
    }

  /* use uniform breakpoints on [0, 15] */
  gsl_bspline_knots_uniform(0.0, 15.0, bw);

  /* construct the fit matrix X */
  for (i = 0; i < n; ++i)
    {
      double xi = gsl_vector_get(x, i);

      /* compute B_j(xi) for all j */
      gsl_bspline_eval(xi, B, bw);

      /* fill in row i of X */
      for (j = 0; j < ncoeffs; ++j)
        {
          double Bj = gsl_vector_get(B, j);
          gsl_matrix_set(X, i, j, Bj);
        }
    }
  mw = gsl_multifit_linear_alloc(n, ncoeffs);

  /* do the fit */
  printf("ok2 n=%d mw->n=%d\n",n,mw->n);
  mw->n=X->size1;
  printf("ok2 n=%d mw->n=%d\n",n,mw->n);
  printf("ok3 p=%d mw->p=%d\n",ncoeffs,mw->p);
  mw->p=X->size2;
  printf("ok3 p=%d mw->p=%d\n",ncoeffs,mw->p);

  gsl_multifit_wlinear(X, w, y, c, cov, &chisq, mw);


  dof = n - ncoeffs;
  /*
  tss = gsl_stats_wtss(w->data, 1, y->data, 1, y->size);
  Rsq = 1.0 - chisq / tss;

  fprintf(stderr, "chisq/dof = %e, Rsq = %f\n", 
                   chisq / dof, Rsq);
  */
  /* output the smoothed curve */
  {
    double xi, yi, yerr;

    printf("#m=1,S=0\n");
    for (xi = 0.0; xi < 15.0; xi += 0.1)
      {
        gsl_bspline_eval(xi, B, bw);
        gsl_multifit_linear_est(B, c, cov, &yi, &yerr);
        //printf("%f %f\n", xi, yi);
      }
  }

  gsl_rng_free(r);
  gsl_bspline_free(bw);
  gsl_vector_free(B);
  gsl_vector_free(x);
  gsl_vector_free(y);
  gsl_matrix_free(X);
  gsl_vector_free(c);
  gsl_vector_free(w);
  gsl_matrix_free(cov);
  gsl_multifit_linear_free(mw);

}

/**
  @brief
    Unit test of xsh_bspline
  @return
    0 if success

*/
int main(int argc, char * const argv[])
{
    /* Declarations */
    int ret =0;
    const char* file_on = NULL ;
    /* Initialize libraries */
    cpl_test_init("amodigli@eso.org", CPL_MSG_WARNING);

    if (argc == 1)
    {
            test_gsl_example();
    }
    else if(argc == 2)
    {
		file_on = argv[1];

    } else {
		fprintf(stderr, "usage: %s table.fits\n", argv[0]);
		return 0;
    }


    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret= 1;
    }
    cpl_test_end(0);
    return ret ;
}

/**@}*/
