/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 European Southern Observatory
 *
 * This program 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
 */
/*----------------------------------------------------------------------------
 
   File name    :       sinfo_new_wave_cal_slit2.c
   Author       :    A. Modigliani
   Created on   :    Sep 17, 2003
   Description  : 

 ---------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*----------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include "sinfo_new_wave_cal_slit2.h"
#include "sinfo_pro_save.h"
#include "sinfo_pro_types.h"
#include "sinfo_wavecal_ini_by_cpl.h"
#include "sinfo_wcal_functions.h"
#include "sinfo_absolute.h"
#include "sinfo_wave_calibration.h"
#include "sinfo_wavecal.h"
#include "sinfo_globals.h"
#include "sinfo_hidden.h"

#include "sinfo_utilities.h"
#include "sinfo_utils_wrappers.h"
#include "sinfo_error.h"


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

/*----------------------------------------------------------------------------
                             Function Definitions
 ---------------------------------------------------------------------------*/
static cpl_error_code
sinfo_image_resample(const char* plugin_id,
                     cpl_parameterlist* config,
                     cpl_frameset* sof,
                     cpl_frameset* ref_set);

/**@{*/
/**
 * @addtogroup sinfo_rec_wavecal wavelength calibration 
 *
 * TBD
 */

/*----------------------------------------------------------------------------
   Function     :       sinfo_wave_cal_slit()
   In           :       ini_file: file name of according .ini file
   Out          :       integer (0 if it worked, -1 if it doesn't) 
   Job          :


  Normal method:

  does the wavelength calibration and the fitting of the slitlet sinfo_edge 
  positions (ASCII file 32 x 2 values) if wished
  produces an array of the bcoefs and of the fit parameters if wished and a 
  wavelength calibration map input is an emission line frame and a line list


  o searching for lines by cross sinfo_correlation with a line list
  o Gaussian fitting of emission lines in each column->positions of the lines->
    resulting fit parameters can be stored in an ASCII file
  o Fitting of a polynomial to the line positions for each column
  o Smoothing: fitting of each polynomial coefficient by another polynomial
    across the whole frame -> resulting polynomial coefficients can be stored 
    in an ASCII file.
  o Wavelength calibration map (micron value for each frame pixel) can be
    produced by using these coefficients and a cross sinfo_correlation to the
    original frame

  o The slitlet sinfo_edge positions can be fitted:
    1) Automatically (not really stable) or by using guess sinfo_edge positions
    2) By using a Boltzmann or a linear slope function

  Slit method:

  does the wavelength calibration and the fitting of the slitlet sinfo_edge 
  positions (ASCII file 32 x 2 values) if wished produces a list of the fit 
  parameters and of the smoothed coefficients if wished and a wavelength 
  calibration map input is an emission line frame and a line list

  o Does the same as other method but smoothes the found polynomial 
    coefficients within each slitlet and not over the whole frame.

  o Produces always a wavelength calibration map and does not crosscorrelate.

 ---------------------------------------------------------------------------*/


int 
sinfo_new_wave_cal_slit2(const char* plugin_id,
                        cpl_parameterlist* config, 
                        cpl_frameset* sof,cpl_frameset* ref_set)
{
  wave_config * cfg =NULL;
  char col_name[MAX_NAME_SIZE];
  char tbl_name[MAX_NAME_SIZE];
  char tbl_fitpar_name[MAX_NAME_SIZE];
  char tbl_line_list_name[MAX_NAME_SIZE];
  char tbl_slitpos_guess_name[MAX_NAME_SIZE];
  char key_name[MAX_NAME_SIZE];
  char col[MAX_NAME_SIZE];
  int check = 0;
  int lx = 0;
  int ly = 0;
  int n_lines=0;
  int i = 0;
  int j = 0;
  int n = 0;
  int readsum=0;
  int sum=0;
  int fit=0;
  int sw=0;
 
  int* status=NULL;
  int* n_found_lines=NULL;
  int* sum_pointer=NULL;
  int** row_clean=NULL;

  float a=0;
  float shift=0;
  float val_x=0;
  float val_y=0;

  float* wave=NULL;
  float* intens=NULL;

  float** acoefs=NULL;
  float** wavelength_clean=NULL;
  float** sinfo_slit_pos=NULL;

  double fwhm_med=0;
  double fwhm_avg=0;
  double coef_med=0;
  double coef_avg=0;
 
  cpl_image * im=NULL ;

  FitParams** par=NULL;

  cpl_table* tbl_wcal=NULL;
  cpl_table* tbl_spos=NULL;
  cpl_table* tbl_fitpar = NULL;
  cpl_table* tbl_line_list = NULL;
  cpl_table* tbl_slitpos_guess=NULL;
  cpl_table * tbl_fp =NULL;
  cpl_table* qclog_tbl=NULL;

  cpl_image* map_img=NULL;

  cpl_frameset* raw=NULL;
  cpl_parameter* p=NULL;

  qc_wcal* qc=sinfo_qc_wcal_new();
  int pdensity=0;

  /*   -----------------------------------------------------------------
       1) parse the file names and parameters to the ns_config data 
          structure cfg
       -----------------------------------------------------------------
  */

  check_nomsg(p=cpl_parameterlist_find(config,"sinfoni.product.density"));
  check_nomsg(pdensity=cpl_parameter_get_int(p));


  sinfo_msg("Parsing cpl input");
  check_nomsg(raw=cpl_frameset_new());
  cknull(cfg = sinfo_parse_cpl_input_wave(config,sof,&raw),
     "could not parse cpl input!") ;
 
  check_nomsg(p = cpl_parameterlist_find(config,
                                         "sinfoni.wavecal.slitpos_boostrap"));
  check_nomsg(sw=cpl_parameter_get_bool(p));

  if(sw==1) {
     cfg->nslitlets=32;
     cfg->calibIndicator=1;
     cfg->wavemapInd=0;
     cfg->slitposIndicator=1;
     sinfo_msg("***********************************");
     sinfo_msg("parameter setting for %s",PRO_WAVE_SLITPOS_STACKED);
     sinfo_msg("***********************************");
  }

  if(sinfo_is_fits_file(cfg->inFrame) != 1) {
    sinfo_msg_error("Input file cfg->inFrame %s is not FITS",cfg->inFrame);
    goto cleanup;
  }


  if (cfg->slitposIndicator == 1 && cfg->estimateIndicator == 1) {
    if (sinfo_is_fits_file(cfg->slitposGuessName) != 1) {
      sinfo_msg_error("slitlet position guess list not given!");
      goto cleanup;
    }
  }

  if (cfg->calibIndicator == 0 && cfg->wavemapInd == 1) {
    if (sinfo_is_fits_file(cfg->coeffsName) != 1) {
      sinfo_msg_error("coefficients list not given!");
      goto cleanup;
    }
  }

  if (cfg->slitposIndicator == 1) {
    if (cfg->calibIndicator != 1 && cfg->estimateIndicator != 1) {
      if (sinfo_is_fits_file(cfg->paramsList) != 1) {
    sinfo_msg_error("parameter list not given!");
    goto cleanup;
      }
    }
  }
 
  /*---load the emission line frame---*/
  check(im = cpl_image_load(cfg->inFrame,CPL_TYPE_FLOAT,0,0)
        ,"could not load image");
  lx = cpl_image_get_size_x(im);
  ly = cpl_image_get_size_y(im);

  if (cfg->calibIndicator == 1 || cfg->wavemapInd == 1) {
    /*---open the line list and read the number of lines---*/
    strcpy(tbl_line_list_name,cfg->lineList);
    check_nomsg(tbl_line_list = cpl_table_load(tbl_line_list_name,1,0));
    check_nomsg(n = cpl_table_get_nrow(tbl_line_list));
    n_lines = n;

    check_nomsg(wave   = cpl_table_get_data_float(tbl_line_list,"wave"));
    check_nomsg(intens = cpl_table_get_data_float(tbl_line_list,"int"));
  }

  /*
  ----------------------------------------------------------------------
  ---------------------------FINDLINES----------------------------------
  ----------------------------------------------------------------------
  */

  /*if not yet done:
    do the wavelength calibration, that means: 
    find the dispersion relation and parameterize its coefficients
  */
  /*
  sinfo_msg("guessBeginWave=%g",cfg->guessBeginWavelength);
  sinfo_msg("guessDisp1=%g",cfg->guessDispersion1);
  sinfo_msg("guessDisp2=%g",cfg->guessDispersion2);
  */
  if (cfg->calibIndicator == 1 && cfg->wavemapInd == 0) {
    sinfo_msg("Findlines");
    acoefs  = sinfo_new_2Dfloatarray(cfg->nrDispCoefficients, lx);

    /*allocate memory*/
    n_found_lines    = sinfo_new_intarray(lx); 
    row_clean        = sinfo_new_2Dintarray(lx, n_lines);
    wavelength_clean = sinfo_new_2Dfloatarray(lx, n_lines);
    sum_pointer      = sinfo_new_intarray(1) ;

    /*find the emission lines in each image column*/
    sinfo_new_intarray_set_value(sum_pointer, 0, 0);
 
    ck0(check = sinfo_new_find_lines(im, 
                                wave, 
                                intens, 
                                n_lines, 
                                row_clean, 
                                wavelength_clean, 
                                cfg->guessBeginWavelength, 
                        cfg->guessDispersion1, 
                                cfg->guessDispersion2,
                                cfg->mindiff, 
                                cfg->halfWidth, 
                                n_found_lines, 
                                cfg->sigma, 
                                sum_pointer),
    "sinfo_findLines failed!");

    /*---------------------------------------------------------------------
     *-----------------------WAVE_CALIB-------------------------------------
     *---------------------------------------------------------------------
    */
    sinfo_msg("Wave Calibration");
    sum = sinfo_new_intarray_get_value(sum_pointer,0);
    /* allocate memory for the fit parameters */
    cknull(par = sinfo_new_fit_params( sum ),
       "sinfo_newFitParams failed!");

  /*
   fit each line, make a polynomial fit and fit the resulting fit 
   coefficients across the columns of the slitlet
   */
   cknull(map_img = sinfo_new_wave_cal(im, 
                  par, 
                  acoefs,
                  cfg->nslitlets, 
                  row_clean,
                  wavelength_clean,
                  n_found_lines,
                  cfg->guessDispersion1,
                  cfg->halfWidth,
                  cfg->minAmplitude,
                  cfg->maxResidual,
                  cfg->fwhm,
                  cfg->nrDispCoefficients, 
                  cfg->nrCoefCoefficients,
                  cfg->sigmaFactor,
                  cfg->pixeldist,
                  cfg->pixel_tolerance),
      "sinfo_wave_cal failed!");

   sinfo_msg("Check line positions");

   shift=sinfo_new_check_line_positions(im,acoefs,cfg->nrDispCoefficients,
                    cfg->guessDispersion1,par);
   if (FLAG == shift){ 
      sinfo_msg_error("checkForLinePositions failed!\n");
   }


   sinfo_det_ncounts(raw, cfg->qc_thresh_max, qc);

   cknull_nomsg(qclog_tbl = sinfo_qclog_init());
   ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC WAVE ALL",n_lines,
                                 "Number of found lines","%d"));
   ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC WAVE NPIXSAT",qc->nsat,
                                 "Number of saturated pixels","%d"));
   ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC WAVE MAXFLUX",qc->max_di,
                                 "Max int off-lamp subtracted frm","%g"));
   ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC WAVE POSERR",shift,
                                 "Overall positioning error in mum","%g"));

   ck0(sinfo_pro_save_ima(map_img,ref_set,sof,cfg->outName,
              PRO_WAVE_MAP,qclog_tbl,plugin_id,config),
       "cannot save ima %s", cfg->outName);

   sinfo_free_table(&qclog_tbl);
   sinfo_free_image(&map_img);

   /*
    #store the resulting polynomial fit coefficients in an 
     ASCII file if wished
   */

   if (cfg->writeCoeffsInd == 1) {
     check_nomsg(tbl_wcal = cpl_table_new(lx));
     for (i=0; i< cfg->nrDispCoefficients; i++) {
       snprintf(col_name,MAX_NAME_SIZE-1,"%s%d","coeff",i);
       check_nomsg(cpl_table_new_column(tbl_wcal,col_name, CPL_TYPE_DOUBLE));
     }

     cknull_nomsg(qclog_tbl = sinfo_qclog_init());
     ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC WAVE ALL",n_lines,
                                   "Number found lines","%d"));

     for (j=0; j< lx; j++) {
       for (i=0; i< cfg->nrDispCoefficients; i++) {
     snprintf(col_name,MAX_NAME_SIZE-1,"%s%d","coeff",i);
     a = sinfo_new_array2D_get_value(acoefs, i, j);
     /* fprintf(acoefs_file, "%15.13g ", a) ; */
     cpl_table_set_double(tbl_wcal,col_name,j,a);
       }
     }
     for (i=0; i< cfg->nrDispCoefficients; i++) {
       snprintf(col_name,MAX_NAME_SIZE-1,"%s%d","coeff",i);
       check_nomsg(coef_avg=cpl_table_get_column_mean(tbl_wcal,col_name));
       check_nomsg(coef_med=cpl_table_get_column_median(tbl_wcal,col_name));

       snprintf(key_name,MAX_NAME_SIZE-1,"%s%d%s","QC COEF",i," AVG");
       ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,key_name,coef_avg,
                                        "Average wavecal Coef","%g"));

       snprintf(key_name,MAX_NAME_SIZE-1,"%s%d%s","QC COEF",i," MED");
       ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,key_name,coef_med,
                                        "Median wavecal Coef","%g"));

     }
     if(pdensity >1) {
     strcpy(tbl_name,cfg->coeffsName);
     ck0(sinfo_pro_save_tbl(tbl_wcal,ref_set,sof,tbl_name,
                PRO_WAVE_COEF_SLIT,qclog_tbl,plugin_id,config),
     "cannot save tbl %s", tbl_name);
     sinfo_free_table(&tbl_wcal);
     sinfo_free_table(&qclog_tbl);
     }

   }

   /*
    #store the resulting Gaussian fit parameters in an ASCII file if wished
   */
   if (cfg->writeParInd == 1) {
      sinfo_new_dump_fit_params_to_ascii(par,WAVECAL_FIT_PARAMS_OUT_FILEASCII);
 
      cknull(par,"no fit parameters available!") ;
      cknull(cfg->paramsList,"no filename available!") ;
      check_nomsg(tbl_fp = cpl_table_new(par[0] -> n_params));
      check_nomsg(cpl_table_new_column(tbl_fp,"n_params", CPL_TYPE_INT));
      check_nomsg(cpl_table_new_column(tbl_fp,"column", CPL_TYPE_INT));
      check_nomsg(cpl_table_new_column(tbl_fp,"line", CPL_TYPE_INT));
 
      for(j=0;j<4;j++) {
         snprintf(col,MAX_NAME_SIZE-1,"%s%d","fpar",j);
         cpl_table_new_column(tbl_fp,col, CPL_TYPE_DOUBLE);
         snprintf(col,MAX_NAME_SIZE-1,"%s%d","dpar",j);
         cpl_table_new_column(tbl_fp,col, CPL_TYPE_DOUBLE);
      }

      cknull_nomsg(qclog_tbl = sinfo_qclog_init());
      ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC NLINES",n_lines,
                                    "Number of found lines","%d"));

     for ( i = 0 ; i < par[0] -> n_params ; i++ ) {
      
         check_nomsg(cpl_table_set_int(tbl_fp,"n_params",i,par[i]->n_params));
         check_nomsg(cpl_table_set_int(tbl_fp,"column",i,par[i]->column));
         check_nomsg(cpl_table_set_int(tbl_fp,"line",i,par[i]->line));

         for(j=0;j<4;j++) {
       snprintf(col,MAX_NAME_SIZE-1,"%s%d","fpar",j);
       if(isnan(par[i]->fit_par[j])) {
         cpl_table_set_invalid(tbl_fp,col,i);
       } else {
         cpl_table_set_double(tbl_fp,col,i,par[i]->fit_par[j]);
       }
       snprintf(col,MAX_NAME_SIZE-1,"%s%d","dpar",j);
       if(isnan(par[i]->derv_par[j])) {
         cpl_table_set_invalid(tbl_fp,col,i);
       } else {
         cpl_table_set_double(tbl_fp,col,i,par[i]->derv_par[j]);
       }
     }
      }

      check_nomsg(fwhm_avg = cpl_table_get_column_mean(tbl_fp,"fpar1"));
      check_nomsg(fwhm_med = cpl_table_get_column_median(tbl_fp,"fpar1"));
      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM MED",fwhm_med,
                                       "Median FWHM of found lines","%f"));
      ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM AVG",fwhm_avg,
                                       "Average FWHM of found lines","%f"));

      if(pdensity > 1) {
      ck0(sinfo_pro_save_tbl(tbl_fp,ref_set,sof,cfg->paramsList,
                 PRO_WAVE_PAR_LIST,qclog_tbl,plugin_id,config),
      "cannot save tbl %s", cfg->paramsList);
      }

      sinfo_free_table(&qclog_tbl);
      sinfo_free_table(&tbl_fp) ;

   }

   /* free memory */
   sinfo_new_destroy_2Dfloatarray ( &wavelength_clean, lx );
   sinfo_new_destroy_2Dintarray (&row_clean, lx);
   sinfo_new_destroy_intarray(&n_found_lines );
   sinfo_new_destroy_intarray(&sum_pointer );
   sinfo_new_destroy_2Dfloatarray ( &acoefs, cfg->nrDispCoefficients );
   sinfo_free_table(&tbl_line_list);

   /*----------------------------------------------------------------------
    *-------------------WAVEMAP--------------------------------------------
    *----------------------------------------------------------------------
    */

   /*
    #---now do the cross sinfo_correlation and produce a wavelength map---
   */

  } else if (cfg->wavemapInd == 1 && cfg->calibIndicator == 0) { 
    sinfo_msg("Wavemap");
    acoefs = sinfo_new_2Dfloatarray ( cfg->nrDispCoefficients, lx);
    /* #read the parameterized dispersion relation */

    strcpy(tbl_name,cfg->coeffsName);
    check_nomsg(tbl_wcal = cpl_table_load(tbl_name,1,0));

    for (i =0; i < lx; i++) {
      for (j = 0; j< cfg->nrDispCoefficients; j++) {
    snprintf(col_name,MAX_NAME_SIZE-1,"%s%d","coeff",j);
    acoefs[j][i]=cpl_table_get_double(tbl_wcal,col_name,i,status);
      }
    }
    sinfo_free_table(&tbl_wcal);

    cknull(map_img = sinfo_new_create_shifted_slit_wavemap2(im,
                           acoefs,
                           cfg->nrDispCoefficients,
                           wave,
                           intens,
                           n_lines,
                           cfg->magFactor,
                           cfg->guessDispersion1,
                           cfg->pixeldist ),
           "sinfo_createShiftedSlitWavemap2 failed!");

    par = sinfo_new_fit_params(15*n_lines);
    sinfo_msg("Check shifts");

    shift = sinfo_new_check_correlated_line_positions ( im, acoefs, 
                         cfg->nrDispCoefficients, 
                         wave,
                         intens,
                         n_lines,
                         cfg->fwhm,
                         cfg->halfWidth,
                         cfg->minAmplitude,
                         cfg->guessDispersion1,
                         par );

    if (FLAG == shift){
      sinfo_msg_error("sinfo_checkCorrelatedLinePositions failed!\n");
    }

    sinfo_det_ncounts(raw, cfg->qc_thresh_max,qc);
    cknull_nomsg(qclog_tbl = sinfo_qclog_init());

    ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC NLINES",n_lines,
                                  "Number of found lines","%d"));

    check_nomsg(fwhm_avg = cpl_table_get_column_mean(tbl_fp,"fpar1"));
    check_nomsg(fwhm_med = cpl_table_get_column_median(tbl_fp,"fpar1"));

    ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM MED",fwhm_med,
                                  "Median FWHM of found lines","%f"));
    ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHM AVG",fwhm_avg,
                                  "Average FWHM of found lines","%f"));

    ck0(sinfo_pro_save_ima(map_img,ref_set,sof,cfg->outName,
               PRO_WAVE_MAP,qclog_tbl,plugin_id,config),
    "cannot save ima %s", cfg->outName);

    sinfo_free_table(&qclog_tbl);
    sinfo_free_image(&map_img);

    /* # ---free memory--- */
    sinfo_new_destroy_2Dfloatarray ( &acoefs, cfg->nrDispCoefficients );
    /* To fix a memory bug we comment the following. But check! */
    /* cpl_free ( wave ); */
    /* cpl_free ( intens ); */

  } else if (cfg->wavemapInd == 1 && cfg->calibIndicator == 1) {
    sinfo_msg_error("give either wavemapIndicator = yes and calibIndicator");
    sinfo_msg_error("= no or wavemapIndicator = no and calibIndicator = yes") ;
    goto cleanup;
  }

  /*-------------------------------------------------------------------
   *-------------------SLITFITS----------------------------------------
   *-------------------------------------------------------------------
   #--fit the slitlet sinfo_edge positions if desired--
  */
  if (cfg->slitposIndicator == 1) {
  sinfo_msg("fit the slitlet sinfo_edge positions");
  if (cfg->calibIndicator != 1 && cfg->estimateIndicator != 1) {

    /*
      #read the first integer to determine the number of fit 
      parameters to allocate
    */

     if(sinfo_is_fits_file(cfg->paramsList) !=1 ) {
       sinfo_msg_error("cannot read FITS file %s ",cfg->paramsList);
       goto cleanup;
     }
     strcpy(tbl_fitpar_name,cfg->paramsList);
     check_nomsg(tbl_fitpar = cpl_table_load(tbl_fitpar_name,1,0));

     check_nomsg(readsum=cpl_table_get_int(tbl_fitpar,"n_params",1,status));
     sinfo_free_table(&tbl_fitpar);
 
     cknull(sinfo_new_fit_params( readsum ),"sinfo_new_fit_params failed!");

     ck0(sinfo_dumpTblToFitParams(par, cfg->paramsList),
     "reading tbl %s ", cfg->paramsList);
  }

  /* #allocate memory for the slitlet position array */
  sinfo_slit_pos = sinfo_new_2Dfloatarray(32,2);
  /* #now decide which fit model function you want to use by 
     reading a given character
  */
  /*
  sinfo_msg("cfg->fitBoltzIndicator=%d\n",cfg->fitBoltzIndicator);
  sinfo_msg("cfg->estimateIndicator=%d\n",cfg->estimateIndicator);
  sinfo_msg("cfg->fitEdgeIndicator=%d\n",cfg->fitEdgeIndicator);
  */
  if (cfg->fitBoltzIndicator == 1) {
    if (cfg->estimateIndicator == 1) {
      /* #open the ASCII list of the slitlet positions--- */
      /*READ TFITS TABLE*/
      strcpy(tbl_slitpos_guess_name,cfg->slitposGuessName);
      check_nomsg(tbl_slitpos_guess=cpl_table_load(tbl_slitpos_guess_name,1,0));
      check_nomsg(n = cpl_table_get_nrow(tbl_slitpos_guess));

      for (i =0 ; i< 32; i++){
        val_x=cpl_table_get_double(tbl_slitpos_guess,"pos1",i,status);
        val_y=cpl_table_get_double(tbl_slitpos_guess,"pos2",i,status);
    sinfo_new_array2D_set_value(sinfo_slit_pos,val_x,i,0);
    sinfo_new_array2D_set_value(sinfo_slit_pos,val_y,i,1);
      }
      sinfo_free_table(&tbl_slitpos_guess);

      sinfo_msg("sinfo_new_fit_slits_boltz_with_estimate");
      fit = sinfo_new_fit_slits_boltz_with_estimate(im, 
                                            sinfo_slit_pos, 
                                  cfg->boxLength, 
                                            cfg->yBox, 
                                            cfg->diffTol, 
                                            cfg->loPos, 
                                            cfg->hiPos );
      if (fit < 0){
    sinfo_msg_error("sinfo_new_fit_slits_boltz_with_estimate failed" );
    goto cleanup;
      }
    } else {
    sinfo_msg("sinfo_new_fit_slits_boltz");
    fit = sinfo_new_fit_slits_boltz(im, 
                                  par, 
                                  sinfo_slit_pos, 
                                  cfg->boxLength, 
                                  cfg->yBox, 
                                  cfg->diffTol );

    if (fit < 0) {
      sinfo_msg_error ( "sinfo_new_fit_slits_boltz failed" );
      goto cleanup;
    }
    }
  } else if (cfg->fitEdgeIndicator == 1) {

    if (cfg->estimateIndicator == 1){
      /*READ TFITS TABLE*/
      strcpy(tbl_slitpos_guess_name,cfg->slitposGuessName);
      check_nomsg(tbl_slitpos_guess=cpl_table_load(tbl_slitpos_guess_name,1,0));
      check_nomsg(n = cpl_table_get_nrow(tbl_slitpos_guess));

      for (i =0 ; i< 32; i++){
    val_x=cpl_table_get_double(tbl_slitpos_guess,"pos1",i,status);
    val_y=cpl_table_get_double(tbl_slitpos_guess,"pos2",i,status);
    sinfo_new_array2D_set_value(sinfo_slit_pos,val_x,i,0);
    sinfo_new_array2D_set_value(sinfo_slit_pos,val_y,i,1);
      }
      cpl_table_delete(tbl_slitpos_guess);

      sinfo_msg("sinfo_new_fit_slits_edge_with_estimate");
      fit = sinfo_new_fit_slits_edge_with_estimate(im, 
                                           sinfo_slit_pos,
                                           cfg->boxLength, 
                                           cfg->yBox, 
                                           cfg->diffTol, 
                                           cfg->loPos, 
                                 cfg->hiPos );
      if (fit < 0) {
     sinfo_msg_error( "sinfo_new_fit_slits_boltz failed" );
         goto cleanup;
      }
    } else {
      sinfo_msg("sinfo_new_fit_slits_edge");
      fit = sinfo_new_fit_slits_edge(im, 
                               par, 
                               sinfo_slit_pos, 
                               cfg->boxLength, 
                               cfg->yBox, 
                               cfg->diffTol );
      if (fit < 0) {
    sinfo_msg_error("sinfo_new_fit_slits_edge failed" );
        goto cleanup;
      }
    }
  } else {
    sinfo_msg_error("no indication of desired fit function given" );
    goto cleanup;
  }
  sinfo_free_image(&im);

  /* #store the resulting sitlet positions in an TFITS table */
  check_nomsg(tbl_spos = cpl_table_new(32));
  check_nomsg(cpl_table_new_column(tbl_spos,"pos1", CPL_TYPE_DOUBLE));
  check_nomsg(cpl_table_new_column(tbl_spos,"pos2", CPL_TYPE_DOUBLE));
  check_nomsg(cpl_table_set_column_format(tbl_spos,"pos1", "15.9f"));
  check_nomsg(cpl_table_set_column_format(tbl_spos,"pos2", "15.9f"));

  for (i =0; i< 32; i++) {
    cpl_table_set_double(tbl_spos,"pos1",i,
                         sinfo_new_array2D_get_value(sinfo_slit_pos,i,0));
    cpl_table_set_double(tbl_spos,"pos2",i,
                         sinfo_new_array2D_get_value(sinfo_slit_pos,i,1));
     
  }
  if(sw == 1) {
    strcpy(tbl_name,"out_slitpos_guess.fits");
    ck0(sinfo_pro_save_tbl(tbl_spos,ref_set,sof,tbl_name,
               PRO_SLIT_POS_GUESS,NULL,plugin_id,config),
    "cannot save tbl %s", tbl_name);
  } else {
    strcpy(tbl_name,cfg->slitposName);
    ck0(sinfo_pro_save_tbl(tbl_spos,ref_set,sof,tbl_name,
               PRO_SLIT_POS,NULL,plugin_id,config),
    "cannot save tbl %s", tbl_name);
  }
  sinfo_free_table(&tbl_spos);
  sinfo_new_destroy_2Dfloatarray ( &sinfo_slit_pos, 32 );
  }

  if ( (cfg->slitposIndicator == 1 && cfg->estimateIndicator != 1) || 
       (cfg->calibIndicator == 1)  || (cfg->wavemapInd == 1) ){
    sinfo_new_destroy_fit_params(&par);
  }





  if(pdensity > 1) {
     check_nomsg(sinfo_image_resample(plugin_id,config,sof,ref_set));


/**
  //RESAMPLE ThAr frame for QC
  double dis=0;
  float mi=0;
  float ma=0;
  double cwav=0;
  int cpix=0;
  const cpl_frame* frm=NULL;
  char wstk_name[80];
  char map_name[80];
  cpl_image* res_ima=NULL;
  int ncoeffs=3;
  int nrows=SINFO_RESAMP_NROWS;

  check_nomsg(p = cpl_parameterlist_find(config,
                                         "sinfoni.wavecal.n_coeffs"));

  check_nomsg(ncoeffs=cpl_parameter_get_int(p));

  check_nomsg(frm=cpl_frameset_find_const(sof,PRO_WAVE_LAMP_STACKED));
  check_nomsg(strcpy(wstk_name,cpl_frame_get_filename(frm)));
  check_nomsg(wstk_img=cpl_image_load(wstk_name,CPL_TYPE_FLOAT,0,0));



  check_nomsg(frm=cpl_frameset_find_const(sof,PRO_WAVE_MAP));
  check_nomsg(strcpy(map_name,cpl_frame_get_filename(frm)));
  check_nomsg(map_img=cpl_image_load(map_name,CPL_TYPE_FLOAT,0,0));



  cknull(res_ima = sinfo_new_defined_resampling(wstk_img, 
						map_img, 
						ncoeffs,
						&nrows,
						&dis,
						&mi,
						&ma,
						&cwav,
						&cpix),
	 " sinfo_definedResampling() failed" ) ;



  ck0(sinfo_pro_save_ima(res_ima,ref_set,sof,WAVECAL_RESAMPLED_OUT_FILENAME,
			 PRO_RESAMPLED_WAVE,NULL,plugin_id,config),
      "cannot save ima %s",WAVECAL_RESAMPLED_OUT_FILENAME);


  sinfo_free_image(&map_img);
  sinfo_free_image(&res_ima);
  sinfo_free_image(&wstk_img);

  sinfo_qc_wcal_delete(&qc);
*/
  }
  sinfo_free_frameset(&raw);
  sinfo_qc_wcal_delete(&qc);
  sinfo_wavecal_free(&cfg);

  return 0;

  cleanup:
  sinfo_free_image(&map_img);
  //sinfo_free_image(&wstk_img);
  sinfo_free_table(&tbl_spos);
  sinfo_free_table(&tbl_fitpar);
  sinfo_free_image(&map_img);
  sinfo_free_table(&tbl_wcal);
  sinfo_free_table(&tbl_fp) ;
  sinfo_free_table(&tbl_line_list);
  sinfo_free_table(&tbl_wcal);
  sinfo_free_table(&qclog_tbl);
  sinfo_free_image(&map_img);
  sinfo_new_destroy_fit_params(&par);
  sinfo_new_destroy_2Dfloatarray ( &sinfo_slit_pos, 32 );
  sinfo_new_destroy_2Dfloatarray ( &wavelength_clean, lx );
  sinfo_new_destroy_2Dintarray (&row_clean, lx);
  sinfo_new_destroy_intarray(&n_found_lines );
  sinfo_new_destroy_intarray(&sum_pointer );
  if(acoefs!=NULL) {
     sinfo_new_destroy_2Dfloatarray(&acoefs,cfg->nrDispCoefficients);
  }
  sinfo_free_table(&tbl_line_list);
  sinfo_free_image(&im);
  sinfo_wavecal_free(&cfg);
  sinfo_free_frameset(&raw);
  sinfo_qc_wcal_delete(&qc);
  return -1 ;

}












static cpl_error_code
sinfo_image_resample(const char* plugin_id,
                     cpl_parameterlist* config,
                     cpl_frameset* sof,
                     cpl_frameset* ref_set)
{
  //RESAMPLE ThAr frame for QC
  double dis=0;
  float mi=0;
  float ma=0;
  double cwav=0;
  int cpix=0;
  const cpl_frame* frm=NULL;
  char wstk_name[80];
  char map_name[80];
  cpl_image* res_ima=NULL;
  int ncoeffs=3;
  int nrows=SINFO_RESAMP_NROWS;
  cpl_parameter* p=NULL;
  cpl_image* wstk_img=NULL;
  cpl_image* map_img=NULL;

  check_nomsg(p = cpl_parameterlist_find(config,
                                         "sinfoni.wavecal.n_coeffs"));

  check_nomsg(ncoeffs=cpl_parameter_get_int(p));

  check_nomsg(frm=cpl_frameset_find_const(sof,PRO_WAVE_LAMP_STACKED));
  check_nomsg(strcpy(wstk_name,cpl_frame_get_filename(frm)));
  check_nomsg(wstk_img=cpl_image_load(wstk_name,CPL_TYPE_FLOAT,0,0));



  check_nomsg(frm=cpl_frameset_find_const(sof,PRO_WAVE_MAP));
  check_nomsg(strcpy(map_name,cpl_frame_get_filename(frm)));
  check_nomsg(map_img=cpl_image_load(map_name,CPL_TYPE_FLOAT,0,0));



  cknull(res_ima = sinfo_new_defined_resampling(wstk_img, 
						map_img, 
						ncoeffs,
						&nrows,
						&dis,
						&mi,
						&ma,
						&cwav,
						&cpix),
	 " sinfo_definedResampling() failed" ) ;



  ck0(sinfo_pro_save_ima(res_ima,ref_set,sof,WAVECAL_RESAMPLED_OUT_FILENAME,
			 PRO_RESAMPLED_WAVE,NULL,plugin_id,config),
      "cannot save ima %s",WAVECAL_RESAMPLED_OUT_FILENAME);


  cleanup:

  sinfo_free_image(&map_img);
  sinfo_free_image(&res_ima);
  sinfo_free_image(&wstk_img);
  return cpl_error_get_code();


}
/**@}*/
