/*
 * 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_boltzmann.h"
#include "sinfo_wave_calibration.h"
#include "sinfo_wavecal.h"
#include "sinfo_globals.h"
#include "sinfo_hidden.h"

#include "sinfo_utilities.h"
#include "sinfo_utilities_scired.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;
    /* not used later
     * 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"));
        cpl_type type=cpl_table_get_column_type(tbl_line_list,"int");
        if(type==CPL_TYPE_INT) {
            check_nomsg(cpl_table_cast_column(tbl_line_list,"int", "fint",CPL_TYPE_FLOAT));
            check_nomsg(intens = cpl_table_get_data_float(tbl_line_list,"fint"));
        } else {
            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;
    int x_cen=0;

    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" ) ;


    x_cen=0.5*cpl_image_get_size_x(wstk_img);
    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_set_wcs_cal_image(res_ima,WAVECAL_RESAMPLED_OUT_FILENAME,
                            (double)x_cen,(double)x_cen,1.,(double)cpix,cwav,dis);

    cleanup:

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


}
/**@}*/
