/*                                                                            *
 *   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: 2011-12-02 14:13:14 $
 * $Revision: 1.8 $
 * $Name: not supported by cvs2svn $
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/*--------------------------------------------------------------------------*/
/**
 * @defgroup xsh_test_pre     Test Data Type PRE functions
 * @ingroup unit_tests
 *
 */
/*--------------------------------------------------------------------------*/
/**@{*/

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


#include <xsh_data_pre.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_badpixelmap.h>
#include <xsh_data_instrument.h>
#include <xsh_dfs.h>
#include <xsh_pfits.h>
#include <tests.h>

#include <cpl.h>
#include <math.h>

/*---------------------------------------------------------------------------
                            Defines
 ---------------------------------------------------------------------------*/
#define MODULE_ID "XSH_DATA_PRE"

#define SYNTAX "Test the pre frame\n"\
  "use : ./test_xsh_data_pre PRE \n"\
  "PRE   => the pre frame\n"

/*--------------------------------------------------------------------------*/
/**
  @brief    Unit test of PRE module
  @return   0 if tests passed successfully

  Test the PRE module.
 */
/*--------------------------------------------------------------------------*/
int main( int argc, char** argv)
{
  int ret = 0;
  xsh_instrument * instrument = NULL ;
  char *pre_name = NULL;
  cpl_frame *pre_frame = NULL;
  xsh_pre *pre = NULL;

  cpl_propertylist* header = NULL;
  int naxis1;
  cpl_image *errs_img = NULL;
  cpl_image* qual_img = NULL; 

  int *qual = NULL;
  FILE* pre_file = NULL;
  int i, j;
  double data_mean=0.0, data_stdev=0.0, data_median=0.0;
  int binx;

  /* Initialize libraries */
  TESTS_INIT( MODULE_ID);
  cpl_msg_set_level( CPL_MSG_DEBUG);
  xsh_debug_level_set( XSH_DEBUG_LEVEL_MEDIUM) ;

  /* Analyse parameters */
  if (argc > 1){
    pre_name = argv[1];
  }
  else{
    printf(SYNTAX);
    TEST_END();
    return 0;
  }
  
  XSH_ASSURE_NOT_NULL( pre_name);
  check (header = cpl_propertylist_load( pre_name, 0));
  check ( naxis1 = xsh_pfits_get_naxis1( header));
  check ( binx = xsh_pfits_get_binx( header));

  /* Create instrument structure and fill */
  instrument = xsh_instrument_new() ;
  xsh_instrument_set_mode( instrument, XSH_MODE_IFU);
  if ( naxis1 == (2048/binx) ){
     xsh_instrument_set_arm( instrument, XSH_ARM_UVB);
  }
  else if (naxis1 == (2044/binx) ){
    xsh_instrument_set_arm( instrument, XSH_ARM_VIS);
  }
  else if (naxis1 == (1024/binx) ){
    xsh_instrument_set_arm( instrument, XSH_ARM_NIR);
  }
  else{
    xsh_msg(" Invalid naxis1 size %d", naxis1);
    XSH_ASSURE_NOT_NULL( pre);
  }
  xsh_instrument_set_lamp( instrument, XSH_LAMP_QTH ) ;
  
  /* Create frame */
  pre_frame = cpl_frame_new();
  cpl_frame_set_filename( pre_frame, pre_name) ;
  cpl_frame_set_level( pre_frame, CPL_FRAME_LEVEL_TEMPORARY);
  cpl_frame_set_group( pre_frame, CPL_FRAME_GROUP_RAW );
  cpl_frame_set_tag( pre_frame, "BIAS_UVB");

  check( pre = xsh_pre_load( pre_frame, instrument));

  {
    int a=0, b=0;
  xsh_pre_window_best_median_flux_pos( pre, 1598, 2720,
   3, 1,  &a, &b);
    xsh_msg("find max at %d %d",a,b);
  }
  check( xsh_pre_median_mean_stdev( pre, &data_mean, &data_median, &data_stdev));

  xsh_msg(" Statistics on DATA: median %f mean %f stdev %f",
    data_median, data_mean, data_stdev);

  check( errs_img = xsh_pre_get_errs( pre));
  check( qual_img = xsh_pre_get_qual( pre)); 
  check ( qual = cpl_image_get_data_int( qual_img));
  xsh_msg("Save order tab in BADPIXEL.reg"); 
  pre_file = fopen( "BADPIXEL.reg", "w");
  fprintf( pre_file, "# Region file format: DS9 version 4.0\n"\
    "global color=red font=\"helvetica 4 normal\""\
    "select=1 highlite=1 edit=1 move=1 delete=1 include=1 fixed=0 "\
    "source\nimage\n");
  xsh_msg( "XSH_GOOD_PIXEL_LEVEL %d",XSH_GOOD_PIXEL_LEVEL); 
  for(j=0; j< pre->ny; j++){
    for(i=0; i<pre->nx; i++){
      if ( qual[i+j*pre->nx] > XSH_GOOD_PIXEL_LEVEL){
        fprintf( pre_file, "point(%f,%f) #point=cross color=red font="\
      "\"helvetica 4 normal\"\n", i+1.0, j+1.0);    
      }
      else if ( (qual[i+j*pre->nx] & 16) == 16){
        fprintf( pre_file, "point(%f,%f) #point=cross color=green font="\
         "\"helvetica 4 normal\"\n", i+1.0, j+1.0);
      }
    }
  }
  fclose( pre_file);

  cleanup:
    xsh_free_frame( &pre_frame);
    xsh_pre_free( &pre);
    xsh_instrument_free( &instrument);
    xsh_free_propertylist( &header);

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

#if 0
  /* Create FITS data */
  frame = xsh_test_create_frame(dataname, nx, ny,
    XSH_LINEARITY_UVB,CPL_FRAME_GROUP_RAW, instrument);
  /* TEST 1 Create PRE */
  check(pre1 = xsh_pre_create(frame,NULL,NULL, instrument));
  xsh_msg("Create PRE %s OK",dataname);
 
  /* TEST 2 : Save PRE */
  check(preframe = xsh_pre_save(pre1,pre_name, "PRE_TAG",1 ));
  xsh_msg("Save PRE %s OK",pre_name);

  /* DFS : assign tag and group */
  cpl_frame_set_tag(preframe,XSH_LINEARITY_UVB);
  cpl_frame_set_group(preframe,CPL_FRAME_GROUP_RAW);  

  /* TEST 3 : Load PRE */
  check(pre2 = xsh_pre_load(preframe,instrument));
  xsh_msg("Load PRE %s OK",dataname);

  /* TEST 4 : Check FITS header */
  check_msg(conad = xsh_pfits_get_conad(pre2->data_header),
    "Can't find conad in header");
  check_msg(ron = xsh_pfits_get_ron(pre2->data_header),
    "Can't find ron in header");

  xsh_msg("Header PRE OK");
  
  /* TEST 5 : Check format */
  assure(xsh_pre_get_nx(pre2) == nx,CPL_ERROR_ILLEGAL_OUTPUT,
    "wrong nx in PRE format");
  assure(xsh_pre_get_ny(pre2) == ny,CPL_ERROR_ILLEGAL_OUTPUT,
    "wrong ny in PRE format");   
  assure(xsh_pre_get_group(pre2) == CPL_FRAME_GROUP_RAW,
    CPL_ERROR_ILLEGAL_OUTPUT,"wrong group in PRE format");
  assure(pre2->data != NULL,CPL_ERROR_ILLEGAL_OUTPUT,
    "PRE data is NULL");
  assure(pre2->errs != NULL,CPL_ERROR_ILLEGAL_OUTPUT,
    "PRE errs is NULL");
  assure(pre2->qual != NULL,CPL_ERROR_ILLEGAL_OUTPUT,
    "PRE qual is NULL");

  xsh_msg("Format PRE OK");

  /* TEST 6 : Check data */
  tdata = cpl_image_get_data_float(pre2->data);
  terrs = cpl_image_get_data_float(pre2->errs);
  for(i = 0; i < nx * ny; i++){
    assure((terrs[i] - sqrt(fabs(tdata[i])+ron*ron) < XSH_FLOAT_PRECISION),
      CPL_ERROR_ILLEGAL_OUTPUT,"WRONG errs part");
  }
  xsh_msg("Data PRE OK");

  /* TEST 7 : Subtract two PRE frames */ 
  pre3 = xsh_pre_duplicate(pre2);
  residual = xsh_pre_duplicate(pre2);
  check(xsh_pre_subtract(residual, pre3));
  
  avg_residual = cpl_image_get_stdev(xsh_pre_get_data(residual));
  avg_err = cpl_image_get_stdev(xsh_pre_get_errs(residual));

  xsh_msg("avg residual = %f ; avg uncertainty = %f", 
      avg_residual, avg_err);

  assure(avg_residual <= avg_err, CPL_ERROR_ILLEGAL_OUTPUT,
    "Residual is not zero");

  /* For each pixel, check that the residual is zero (withing
     uncertainty) */
  tdata = cpl_image_get_data_float(residual->data);
  terrs = cpl_image_get_data_float(residual->errs);
  tqual = cpl_image_get_data_int(residual->qual);
  tdata1 = cpl_image_get_data_float(pre2->data);
  terrs1 = cpl_image_get_data_float(pre2->errs);
  tqual1 = cpl_image_get_data_int(pre2->qual);
  tdata2 = cpl_image_get_data_float(pre3->data);
  terrs2 = cpl_image_get_data_float(pre3->errs);
  tqual2 = cpl_image_get_data_int(pre3->qual);
  for (i = 0; i < nx * ny; i++) {
    assure(tdata[i] <= terrs[i],CPL_ERROR_ILLEGAL_OUTPUT,
 	       "Residual is non-zero at %d : ",i);
    assure(terrs[i] -(sqrt(pow(terrs1[i],2)+pow(terrs2[i],2))) < 
      XSH_FLOAT_PRECISION,
      CPL_ERROR_ILLEGAL_OUTPUT,
               "Wrong errs  at %d : ",i);
    assure(tqual[i] == (tqual1[i]+tqual2[i]),CPL_ERROR_ILLEGAL_OUTPUT,
      "Wrong qual part");
  }
  xsh_msg("subtract two PRE OK");

  /* TEST 8 : Add two PRE image */
  check(addtest = xsh_pre_duplicate(pre2));
  check(xsh_pre_add(addtest, pre3));
  tdata = cpl_image_get_data_float(addtest->data);
  terrs = cpl_image_get_data_float(addtest->errs);
  tqual = cpl_image_get_data_int(addtest->qual);
  tdata1 = cpl_image_get_data_float(pre2->data);
  terrs1 = cpl_image_get_data_float(pre2->errs);
  tqual1 = cpl_image_get_data_int(pre2->qual);
  tdata2 = cpl_image_get_data_float(pre3->data);
  terrs2 = cpl_image_get_data_float(pre3->errs);
  tqual2 = cpl_image_get_data_int(pre3->qual);
  
  for (i = 0; i < nx * ny; i++) {
    assure(tdata[i] -(tdata1[i]+tdata2[i]) < XSH_FLOAT_PRECISION,
      CPL_ERROR_ILLEGAL_OUTPUT,
               "Wrong data  at %d : ",i);
    assure(terrs[i] -(sqrt(pow(terrs1[i],2)+pow(terrs2[i],2))) < 
      XSH_FLOAT_PRECISION,
      CPL_ERROR_ILLEGAL_OUTPUT,
               "Wrong errs  at %d : ",i);
    assure(tqual[i] == (tqual1[i]+tqual2[i]),CPL_ERROR_ILLEGAL_OUTPUT,
      "Wrong qual part"); 
  }
  xsh_msg("Add two PRE OK"); 
  
cleanup:
  xsh_instrument_free(&instrument);
  xsh_pre_free(&pre1);
  xsh_pre_free(&pre2);
  xsh_pre_free(&pre3);
  xsh_pre_free(&residual);
  xsh_pre_free(&addtest);
  xsh_free_frame(&frame);
  xsh_free_frame(&preframe);

  if (cpl_error_get_code() != CPL_ERROR_NONE) {
    xsh_error_dump(CPL_MSG_ERROR);
    return 1;
  } else {
    return 0;
  }
#endif
}

/**@}*/
