/*                                                                            *
 *   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-01-16 17:52:47 $
 * $Revision: 1.19 $
 * $Name: not supported by cvs2svn $
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/*--------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_detect_arclines Test Detect Arc Lines
 * @ingroup unit_tests
 *
 */
/*--------------------------------------------------------------------------*/
/**@{*/

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

#include <xsh_data_instrument.h>
#include <xsh_badpixelmap.h>
#include <xsh_pfits.h>
#include <xsh_msg.h>
#include <xsh_utils.h>
#include <tests.h>
#include <cpl.h>
#include <math.h>
#include <stdlib.h>
#include <getopt.h>

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

#define SYNTAX "Test the detect_arclines function\n"\
  "use : ./test_xsh_detect_arclines OPTIONS FMTCHK_FRAME LINE_LIST THEMAP "\
  "[GUESS_WAVE_TAB]\n"\
  "FMTCHK_FRAME  => the frame to detect arclines (PRE format)\n"\
  "LINE_LIST  => the line list\n"\
  "THEMAP     => the theoretical map\n"\
  "GUESS_WAVE_TAB => the guess wave solution\n"\
  "SPECTRAL_FORMAT_TAB => the spectral format table \n"\
  "OPTIONS    => \n"\
  "  --half_window_size : half window size (HWS) in pixel around the"\
  " position to fit the gaussian (total window size = 2*HWS+1)\n"\
  "  --half_window_size_for_max : half window size (HWS) in pixel around the"\
  " theoritical position to find the maximum flux\n"\
  "  --half_window_size_running_median : half window size of running "\
  "median\n"\
  "  --deg_lambda : lambda degree in polynomial wavelength solution fit\n"\
  "  --deg_order :  order degree in polynomial wavelength solution fit\n"\
  "  --deg_slit :  slit degree in polynomial wavelength solution fit\n"\
  "  --poly_degree : Polynomial degree\n"\
  "  --min_sn : minimal S/N allowed\n"\
  "  --clip_sigma : multiple of sigma in sigma clipping\n"\
  "  --clip_niter :  number of iterations in sigma clipping\n"\
  "  --clip_frac : minimal fractions of bad pixel allowed\n"

enum {
  HALF_WINDOW_SIZE_OPT, HALF_WINDOW_SIZE_FOR_MAX_OPT, DEG_LAMBDA_OPT, 
  DEG_ORDER_OPT, DEG_SLIT_OPT, POLY_DEGREE_OPT, MIN_SN_OPT, CLIP_SIGMA_OPT, 
  CLIP_NITER_OPT, CLIP_FRAC_OPT, INITIAL_CENTER_OPT,
  HALF_WINDOW_SIZE_RUNNING_MEDIAN_OPT
} ;

static struct option long_options[] = {
  {"half_window_size", required_argument, 0,  HALF_WINDOW_SIZE_OPT},
  {"half_window_size_for_max", required_argument, 0,  
    HALF_WINDOW_SIZE_FOR_MAX_OPT},
  {"half_window_size_running_median", required_argument, 0,
    HALF_WINDOW_SIZE_RUNNING_MEDIAN_OPT},
  {"deg_lambda", required_argument, 0,  DEG_LAMBDA_OPT},
  {"deg_order", required_argument, 0,  DEG_ORDER_OPT},
  {"deg_slit", required_argument, 0,  DEG_SLIT_OPT},
  {"poly_degree", required_argument, 0,  POLY_DEGREE_OPT},
  {"min_sn", required_argument, 0,  MIN_SN_OPT},
  {"clip_sigma", required_argument, 0,  CLIP_SIGMA_OPT},
  {"clip_niter", required_argument, 0,  CLIP_NITER_OPT},
  {"clip_frac", required_argument, 0,  CLIP_FRAC_OPT},
  {0, 0, 0, 0}
};

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

  /* Default parameters */
  det_arc_par->fit_window_hsize = 10;
  det_arc_par->search_window_hsize = 30;
  det_arc_par->running_median_hsize = 1;
  det_arc_par->wavesol_deg_lambda = 2;
  det_arc_par->wavesol_deg_order = 2;
  det_arc_par->wavesol_deg_slit = 0;
  det_arc_par->ordertab_deg_y = 2;
  det_arc_par->min_sn = 0.2;
  clip_par->sigma = 1.0;
  clip_par->niter = 5;
  clip_par->frac = 0.7; 
 
  /* Handle options */
  while (( opt = getopt_long (argc, argv, "half_window_size:deg_lambda:"\
    "deg_order:deg_slit:poly_degree:min_sn:"\
    "clip_sigma:clip_niter:clip_frac:half_window_size_for_max:"\
    "half_window_size_running_median",
    long_options, &option_index)) != EOF ){

    switch ( opt ) {
    case  HALF_WINDOW_SIZE_OPT :
      det_arc_par->fit_window_hsize = atoi(optarg);
      break ;
    case  HALF_WINDOW_SIZE_FOR_MAX_OPT :
      det_arc_par->search_window_hsize = atoi(optarg);
      break;
    case HALF_WINDOW_SIZE_RUNNING_MEDIAN_OPT :
      det_arc_par->running_median_hsize = atoi(optarg);
      break;
    case DEG_LAMBDA_OPT:
      det_arc_par->wavesol_deg_lambda = atoi(optarg);
      break;
    case DEG_ORDER_OPT:
      det_arc_par->wavesol_deg_order = atoi(optarg);
      break;
    case DEG_SLIT_OPT:
      det_arc_par->wavesol_deg_slit = atoi(optarg);
      break;
    case POLY_DEGREE_OPT:
      det_arc_par->ordertab_deg_y = atoi(optarg);
      break;
    case MIN_SN_OPT:
      det_arc_par->min_sn = atof(optarg); 
      break;
    case CLIP_SIGMA_OPT:
      clip_par->sigma = atof(optarg);
      break;
    case CLIP_NITER_OPT:
      clip_par->niter = atoi(optarg);
      break;
    case CLIP_FRAC_OPT:
      clip_par->frac = atof(optarg);
      break;
    default:
      printf(SYNTAX);
      exit(0);
    }
  }
  return;
}
/*---------------------------------------------------------------------------
                         Functions prototypes
 ---------------------------------------------------------------------------*/

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

  Test the Data Reduction Library function XSH_DETECT_ARCLINES
 */
/*--------------------------------------------------------------------------*/

int main(int argc, char** argv)
{
  /* Initialize libraries */
  cpl_frame* predict = NULL;
  cpl_frame* theoretical_map = NULL;
  cpl_frame* arclines = NULL;
  cpl_frame* clean_arclines = NULL;
  //cpl_frame * guess_order_table = NULL ;
  cpl_frame* resid_tab_orders=NULL;
  cpl_frame* guess_tab = NULL;
  cpl_frame* wave_sol = NULL;
  cpl_frame* twodmap_resid = NULL;
  cpl_frame* spectral_format = NULL;
  xsh_instrument* instrument = NULL;
  xsh_detect_arclines_param da ;
  xsh_clipping_param dac ;
  char *fmtchk_name = NULL;
  char *linelist_name = NULL;
  char *themap_name = NULL;
  char *guess_tab_name = NULL;
  char *spectral_format_name = NULL;
  int nb_frames = 0;
  int decode_bp=QFLAG_OUTSIDE_DATA_RANGE;

  TESTS_INIT(MODULE_ID);

  cpl_msg_set_level(CPL_MSG_DEBUG);
  xsh_debug_level_set(XSH_DEBUG_LEVEL_MEDIUM);

  /* Analyse parameters */
  HandleOptions( argc, argv, &da, &dac);

  nb_frames = argc - optind;
  if ( nb_frames > 2 ) {
    fmtchk_name = argv[optind];
    linelist_name = argv[optind+1];
    themap_name = argv[optind+2];
    if ( nb_frames > 3){
      guess_tab_name = argv[optind+3];
      TESTS_XSH_FRAME_CREATE( guess_tab, "GUESS_WAVE_TAB_UVB",
        guess_tab_name);
      if ( nb_frames > 4){
         spectral_format_name = argv[optind+4];
         TESTS_XSH_FRAME_CREATE( spectral_format, "SPECTRAL_FORMAT_TAB_UVB",
                                 spectral_format_name);

      }
    }
  }
  else{
    xsh_msg( "********** NOT ENOUGH INPUT FRAMES **********" ) ;
    printf(SYNTAX);
    exit(0);
  }
  TESTS_XSH_INSTRUMENT_CREATE( instrument, XSH_MODE_IFU, 
    XSH_ARM_UVB, XSH_LAMP_QTH, "xsh_predict");

  TESTS_XSH_FRAME_CREATE( predict, "FMTCHK_UVB", fmtchk_name);
  TESTS_XSH_FRAME_CREATE( theoretical_map, "THEORETICAL_MAP_SLIT_UVB",
    themap_name);
  TESTS_XSH_FRAME_CREATE( arclines, "ARC_LINE_LIST_UVB", 
    linelist_name);
  /* Function Parameters Output */
  xsh_msg("--------------------------------------------------------");
  xsh_msg("PARAMETERS");
  xsh_msg("--------------------------------------------------------");
  xsh_msg("  fit window half size         : %d", da.fit_window_hsize);
  xsh_msg("  search window half size      : %d", da.search_window_hsize);
  xsh_msg("  running median half size     : %d", da.running_median_hsize);
  xsh_msg("  wave solution order degree   : %d", da.wavesol_deg_order);
  xsh_msg("  wave solution lambda degree  : %d", da.wavesol_deg_lambda);
  xsh_msg("  wave solution slit degree    : %d", da.wavesol_deg_slit);
  xsh_msg("  order tab y degree           : %d", da.ordertab_deg_y);
  xsh_msg("  min S/N                      : %f", da.min_sn);
  xsh_msg("  clip sigma                   : %f", dac.sigma);
  xsh_msg("  clip niter                   : %d", dac.niter);
  xsh_msg("  clip frac                    : %f", dac.frac);
  xsh_msg("--------------------------------------------------------");
  xsh_msg("FRAMES");
  xsh_msg("--------------------------------------------------------");
  xsh_msg("  FMTCHK frame     : %s", fmtchk_name);
  xsh_msg("  LINE_LIST frame  : %s", linelist_name);
  xsh_msg("  THEMAP frame     : %s", themap_name);
  if (guess_tab_name != NULL){
    xsh_msg("  GUESS_TAB frame     : %s", guess_tab_name);
  }
  if (spectral_format_name != NULL){
    xsh_msg("  SPECTRAL FORMAT TAB frame     : %s", spectral_format_name);
  }
  xsh_msg("--------------------------------------------------------");
  xsh_msg("Function call");
  xsh_msg("--------------------------------------------------------");
  /* Start the function */
  check( xsh_detect_arclines ( predict, 
                               theoretical_map,
			       arclines, 
                               guess_tab, 
                               NULL,  /* order tab recover frame */
                               NULL,  /* model cfg frame */ 
			       spectral_format,  
                               &resid_tab_orders, &clean_arclines, 
			       &wave_sol, &twodmap_resid, 
                               XSH_SOLUTION_RELATIVE,
                               &da, &dac,
			       instrument,
			       "xsh_predict",decode_bp,0)); 
//added "xsh_predict" to fix API change

  xsh_msg("--------------------------------------------------------");
  xsh_msg("CLEANUP");
  xsh_msg("--------------------------------------------------------");
  cleanup:
    cpl_frame_delete(predict);
    cpl_frame_delete(theoretical_map);
    cpl_frame_delete(arclines);
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      return 1;
    } 
    else {
      return 0;
    }
}

/**@}*/
