#ifndef SINFO_WAVE_CALIBRATION_H
#define SINFO_WAVE_CALIBRATION_H
/*
 * 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
 */
/*******************************************************************************
* E.S.O. - VLT project
*
* "@(#) $Id: sinfo_wave_calibration.h,v 1.5 2008-03-25 08:20:43 amodigli Exp $"
*
* who       when      what
* --------  --------  ----------------------------------------------
* schreib  13/07/00  created
*/

/************************************************************************
 * wave_calibration.h
 * routines needed for wavelength calibration
 *----------------------------------------------------------------------
 */

/*
 * header files
 */

#include <cpl.h>
#include "sinfo_wavecal.h"
/*
 * function prototypes
 */

/**
   @name sinfo_new_fit_params()
   @memo allocates memory for a new sinfo_vector of FitParams data structures
   @param n_params number of parameters that will be fitted
   @return allocated sinfo_vector of FitParams data structures
*/

FitParams ** 
sinfo_new_fit_params( int n_params ) ;

/**
   @name      sinfo_new_destroy_fit_params()
   @memo   frees memory of a sinfo_vector of FitParams data structures
   @param     params  fit params to destroy
   @return    void
*/

void 
sinfo_new_destroy_fit_params ( FitParams *** params ) ;

/**
   @name   sinfo_new_dump_fit_params_to_ascii()
   @memo   dumps the fit parameters to an ASCII file
   @param  params fit params to dump
   @param  filename
   @return filled ASCII file
*/

void 
sinfo_new_dump_fit_params_to_ascii ( FitParams ** params, const char * filename ) ;

/**
   @name   sinfo_new_dump_ascii_to_fit_params()
   @memo   dumps ASCII information to an allocated FitParams data structure
   @param  params allocated dummy for the fit params
   @param  filename
   @return params: filled FitParams object
*/

void 
sinfo_new_dump_ascii_to_fit_params ( FitParams ** params, char * filename ) ;

/**
   @name  sinfo_new_find_lines()
   @memo determines the pixel shift between the line list and the real image 
         by using the beginning wavelength on the detector and the dispersion 
         estimate.

   @param lineImage merged emission line image,
   @param wave_position wavelength list in Angstroems
   @param wave_intensity corresponding intensity list
   @param n_lines number of lines in list
   @param row_clean resulting list of the row indices but without the
                    lines that are too close to each other for the fit
   @param wavelength_clean corrected wavelength list corresponding to
                           the row_clean array
   @param beginWave beginning wavelength on detector in microns
   @param dispersion dispersion of the grating on the detector
                     (microns per pixel, attention: merged image).
   @param mindiff minimal difference of mean and sinfo_median column
                  intensity to do the sinfo_correlation.
                  This is done to avoid correlations in columns
                  without emission line intensity.
   @param halfWidth   half width of the box where the line must sit,
   @param n_found_lines number of found and correlated
                        emission lines in a column.
   @param sigma sigma of Gaussian that is convolved with the artificial 
          spectrum
   @return 0 if all went o.k.
   @param row resulting list of the row indices of the line positions
   @param row_clean resulting list of the row indices but without the
                    lines that are too close to each other for the fit
   @param wavelength wavelength from the list corresponding to the
                     found row positions
   @param wavelength_clean corrected wavelength list corresponding to
                           the row_clean array
   @param n_found_lines number of found and correlated
                        emission lines in a column.
   @param sum_lines total sum of found and correlated emission lines
                    INT32_MAX = 2^32/2 if something has gone wrong

*/
int 
sinfo_new_find_lines(cpl_image * lineImage,
               float    * wave_position,
               float    * wave_intensity,
               int        n_lines,
               int     ** row_clean,
               float   ** wavelength_clean,
               float      beginWave,
               float      dispersion1,
               float      dispersion2,
               float      mindiff,
               int        halfWidth,
               int      * n_found_lines,
               float      sigma,
               int      * sum_lines ) ;

/**
   @name   sinfo_new_read_list()
   @memo   reads the line data  of the calibration lamps
   @param  listname name of the list file, arrays to store the wavelength
                    and the intensities of the emission lines
   @return number of lines in file
*/

int 
sinfo_new_read_list( char * listname, 
                     float * lineCenter, 
                     float * lineIntensity ) ;

/**
   @name    sinfo_new_line_fit()
   @param   mergedImage image of a calibration emission lamp,
   @param   par         dummys for the resulting fitting parameters,
   @param   fwhm:        guess for full width of half maximum of Gaussian
   @param   lineInd     index of the emission line,
   @param   column      present index of the image column,
   @param   halfWidth   half width of the box where the line must sit,
   @param   lineRow     row index where the line is expected,
   @param   min_amplitude minimum amplitude of the Gaussian with
                          respect to the background to do the fit
   @return  the fitting parameter data structure containing the resulting 
         parameters. integers: number of iterations if all was ok,
                   #    -8   if no input image was given,
                   #    -9   if no dummy for the fit parameters is given,
                   #    -10  if the wrong column index was given,
                   #    -11  if the wrong box width was given,
                   #    -12  if the wrong row index was given,
                   #    -13  if a wrong minimum amplitude factor was given
                   #    -14  if the spectral sinfo_vector data structure memory
                             could not be allocated
                   #     -15  wrong row index or box width was given,
                   #     -16  negative peak or signal too low to fit
                   #     -17 least squares fit failed
   @doc   fits a Gaussian to a 1-dimensional slice of an image,
          this routine uses the routine sinfo_lsqfit_c as a non-linear
          least square fit method (Levenberg-Marquardt).
*/

int 
sinfo_new_line_fit (cpl_image  * mergedImage,
              FitParams * par,
              float       fwhm,
              int         lineInd,
              int         column,
              int         halfWidth,
              int         lineRow,
              float       min_amplitude,
          Vector    *  line,
          int       *  mpar,
          float     *  xdat,
          float     *  wdat ) ;

/**
   @name    sinfo_new_fit_lines
   @param   line_image merged image of a calibration lamp ,
   @param   allParams  allocated sinfo_vector of FitParams data structures,
   @param   fwhm       guess for full width of half maximum of Gaussian,
   @param   n_lines  number of neon lines that will be fitted in one column,
   @param   row        list of the rows of the fitted lines
   @param   wavelength list of wavelength corresponding to the found line rows
   @param   width      list of the half widths
                       around the corresponding rows to find line
   @param   min_amplitude minimal amplitude of the Gaussian beyond which 
              the fit is carried through.
   @return filled FitParams data structure sinfo_vector, number of successfully
           fitted lines, errors: negative integers resulting from the 
           sinfo_linefit routine and:
           # -18: no image given,
           # -19: number of emission lines or number of slitlets is wrong,
           # -20: sinfo_vector of the slitlet boundaries or of the line rows or
                  of the half width are empty.
           # -21: no wavelength array given.
   @memo   calculates and stores the fit parameters of the neon
           emission lines of a neon frame by using the sinfo_linefit routine.
*/

int 
sinfo_new_fit_lines (cpl_image  *  line_image,
               FitParams ** allParams,
               float        fwhm,
               int       *  n_lines,
               int       ** row,
               float     ** wavelength,
               int          width,
               float        min_amplitude ) ;

/**
   @name      sinfo_new_polyfit()
   @memo    fits a second order polynom
            lambda[i] = a1 + a2*pos[i] + a3*pos[i]^2
            to determine the connection between the listed wavelength values 
            and the gauss-fitted positions for each image column using the 
            singular value decomposition method.

   @param     par          filled array of fit parameter structure
   @param     column       image column index
   @param     n_lines      number of lines found in column
   @param     n_rows       number of image rows
   @param     dispersion   microns per pixel
   @param     max_residual maximum residual value, beyond that value
                           the fit is rejected.
   @param     acoefs       array of the 3 coefficients of the fitted parabola
   @param     dacoefs      variances of parabola coefficients  
   @param     n_reject     rejected number of fits due to high residuals
   @param     n_fitcoefs   number of polynomial coefficients to fit
   @return   chisq        chi2 of polyfit
*/

float 
sinfo_new_polyfit( FitParams ** par,
               int          column,
               int          n_lines,
               int          n_rows,
               float        dispersion,
               float        max_residual,
               float *      acoefs,
               float *      dacoefs,
               int   *      n_reject,
               int          n_fitcoefs ) ;

/**
   @name     sinfo_new_coefs_cross_fit()
   @param    n_columns    number of image columns
   @param    acoefs       coeffs fitted in sinfo_polyfit
   @param    dacoefs      fit errors of the corresponding acoefs
   @param    bcoefs       the fitted coefs
   @param    n_fitcoefs   number of fit coefficients
   @param    sigma_factor factor of sigma beyond which the
                          column coefficients are discarded for the fit

   @return   chisq, the found fit coefficients
   @doc      Fits the each single parameter of the three fit parameters
             acoefs from sinfo_polyfit through the image columns
   @note this is a vector of coefficients with the same index for all columns
*/

float 
sinfo_new_coefs_cross_fit ( int      n_columns,
                      float *  acoefs,
                      float *  dacoefs,
                      float *  bcoefs,
                      int      n_fitcoefs,
                      float    sigma_factor ) ;

/**
   @name   sinfo_new_wave_map()
   @param  lineImage    image from a calibration emission lamp,
   @param  bcoefs       transformed fit coefficients
   @param  n_a_fitcoefs number of fit coefficients for the single
                        column fits lambda-position
   @param  n_b_fitcoefs number of fit coefficients for the fits of
                        the single a coefficients across the columns
   @param  wavelength   wavelength list from lamp file
   @param  intensity    corresponding line intensity from line list
   @param  n_lines      number of lines in the list
   @param  magFactor    magnifying factor of the image for FFT
   @return wavelength calibration map image.
   @memo   determines a wavelength calibration map frame associating a 
           wavelength value to each pixel by using the fit coefficients 
           determined before.
*/

cpl_image * 
sinfo_new_wave_map(cpl_image * lineImage,
                    float   ** bcoefs,
                    int        n_a_fitcoefs,
                    int        n_b_fitcoefs,
                    float    * wavelength,
                    float    * intensity,
                    int        n_lines,
                    int        magFactor) ;

/**
   @name  sinfo_new_wavelength_calibration()
   @memo  takes an image from a calibration emission lamp and delivers the fit 
          coefficients of a polynomial fit across the columns of the 
          coefficients of the polynomial line position fits as output. 
          Furthermore it delivers an array of the fit parameters as output. 
          This routine expects Nyquist sampled spectra (either an interleaved 
          image or an image convolved with an appropriate function in spectral 
          direction).

   @param image merged image from a calibration emission lamp,
   @param  par array of the resulting FitParams data structure
   @param  bcoefs array of cooefficients of the polynomial fit 
           across the columns.
   @param wave  wavelength array read from the wavelength list
   @param n_lines  number of lines in the wavelength list
   @param row_clean resulting list of the row indices but without the
                    lines that are too close to each other for the fit
                    output of sinfo_findLines()
   @param wavelength_clean corrected wavelength list corresponding to
                           the row_clean array output of sinfo_findLines()
   @param n_found_lines output of sinfo_findLines(): total number of 
                        found emission lines
   @param dispersion   dispersion of spectrum: micron per pixel
   @param halfWidth    half width of the box where the line must sit
   @param minAmplitude minimum amplitude of the Gaussian beyond which
                       the fit is carried out
   @param max_residual maximum residual value, beyond that value
                       the polynomial lambda-position fit is rejected.
   @param fwhm         first guess for the full width of half maximum
                       of the sinfo_gaussian line fit
   @param n_a_fitcoefs number of fit coefficients for the single
                       column fits: lambda-position
   @param n_b_fitcoefs number of fit coefficients for the fits of
                       the single a coefficients across the columns
   @param sigmaFactor  factor of the standard deviation of the determined
                       polynomial coefficients of the columns beyond
                       which these coefficients are not used to carry out
                       the polynomial fit across the columns.
   @param pixel_tolerance maximum tolerated difference between estimated
                          and fitted line positions.
   @return  0 if all went o.k., -1 if something went wrong.
  */

int 
sinfo_new_wavelength_calibration(cpl_image   * image,
                           FitParams ** par ,
                           float     ** bcoefs,
                           float      * wave,
                           int          n_lines,
                           int       ** row_clean,
                           float     ** wavelength_clean,
                           int        * n_found_lines,
                           float        dispersion,
                           int          halfWidth,
                           float        minAmplitude,
                           float        max_residual,
                           float        fwhm,
                           int          n_a_fitcoefs,
                           int          n_b_fitcoefs,
                           float        sigmaFactor,
               float        pixel_tolerance ) ;

/**
   @name     sinfo_new_convolve_image_by_gauss()
   @param    lineImage  emission line image
   @param    hw         kernel half width of the sinfo_gaussian
                        response function
   @return   emission line image convolved with a sinfo_gaussian
   @doc convolves an emission line image with a Gaussian with user given 
        integer half width by using the eclipse routine 
        sinfo_function1d_filter_lowpass().
*/

cpl_image * 
sinfo_new_convolve_image_by_gauss(cpl_image * lineImage,
                                 int        hw ) ;

/**
   @name    sinfo_new_defined_resampling()
   @param   image      source image to be calibrated
   @param   calimage   wavelength map image
   @param   n_params   number of fit parameters for polynomial interpolation
                       standard should be 3 that means order of polynom + 1
   @param   n_rows     desired number of rows for the final image, this will be
                       the final number of spectral pixels in the final data 
                       cube.
   @param dispersion   resulting spectral dispersion (microns/pixel)
                       is chosen as the minimum dispersion found in
                       the wavelength map - 2% of this value
   @param minval       minimal wavelength value,
   @param maxval       maximal wavelength value
   @param centralLambda final central wavelength value
   @param  centralpix    row of central wavelength (in image coordinates!)

   @return wavelength   calibrated source image,

   @doc   Given a source image and a corresponding wavelength
          calibration file this routine produces an image
          in which elements in a given row are associated
          with a single wavelength. It thus corrects for
          the wavelength shifts between adjacent elements
          in the rows of the input image. The output image
          is larger in the wavelength domain than the input
          image with pixels in each column corresponding to
          undefined (blank, ZERO) values. The distribution
          of these undefined values varies from column to
          column. The input image is resampled at discrete
          wavelength intervals using the polynomial interpolation
          routine.
          The wavelength intervals (dispersion) and the
          central wavelength are defined and stable for each
          used grating. Thus, each row has a defined wavelength
          for each grating. Only the number of rows can be
          changed by the user.
*/

cpl_image * 
sinfo_new_defined_resampling(cpl_image * image,
                              cpl_image * calimage,
                              int        n_params,
                              int*        n_rows,
                              double   * dispersion,
                              float    * minval,
                              float    * maxval,
                              double   * centralLambda,
                              int    * centralpix ) ;


#endif /*!SINFO_WAVE_CALIBRATION_H*/
