#ifndef SINFO_FOCUS_H
#define SINFO_FOCUS_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_focus.h,v 1.3 2007/06/06 07:10:45 amodigli Exp $"
*
* who       when      what
* --------  --------  ----------------------------------------------
* schreib  04/02/02  created
*/

/************************************************************************
 * sinfo_focus.h
 * some functions to fit a 2-D Gaussian for focus finding
 *----------------------------------------------------------------------
 */

/*
 * header files
 */

#include <cpl.h>
#include "sinfo_utilities.h"
#include "sinfo_new_cube_ops.h"
/*----------------------------------------------------------------------------
 *                        Function ANSI C prototypes
 *--------------------------------------------------------------------------*/
/**
  @name     sinfo_new_gaussian_ellipse()
  @param    parlist(0)     center of Gaussian in x direction
  @param    parlist(1)     center of Gaussian in y direction
  @param    parlist(2)     Amplitude of the 2d Gaussian
  @param    parlist(3)     Background level
  @param    parlist(4)     FWHMx, fwhm of the axis of the ellipse 
                           near the x-axis
  @param    parlist(5)     FWHMy, fwhm of the axis of the ellipse 
                           near the y-axis
  @param    parlist(6)     theta, position angle of the fwhmx line 
                            (-PI/4 to PI/4)

  @result   double value of the 2d Gaussian at position xdat.

  @doc      Compute the value of a 2d Gaussian function at a given point.
            The ellptical 2D Gaussian is:
  F(x,y) = par(2) * EXP( -4.0*log(2.0)*[(xr/par(4))^2+(yr/par(5))^2]) + par(3),
  where: xr = xo * cos(par(6)) + yo * sin(par(6))
         yr = -xo * sin(par(6)) + yo * cos(par(6))
  and:   x0 = x - par(0)
         y0 = y - par(1)
 */


double 
sinfo_new_gaussian_ellipse(double * xdat, double * parlist) ;

/**
   @name                     sinfo_new_gaussian_ellipse_deriv()
   @memo calculates the partial derivatives for a 2d Gaussian function with
         parameters parlist at position xdat
   @param xdat           position array, 
   @param parlist        parameter list 
                        The parameters are:
                      #  parlist(0): center of Gaussian in x direction
                      #  parlist(1): center of Gaussian in y direction
                      #  parlist(2): Amplitude of 2d Gaussian
                      #  parlist(3): Background level
                      #  parlist(4): FWHMx
                      #  parlist(5): FWHMy
                      #  parlist(6): theta
   @param dervs   derivative value of a 2d Gaussian function at position xdat
                      #  dervs[0]: partial derivative by center x
                      #  dervs[1]: partial derivative by center y
                      #  dervs[2]: partial derivative by the amplitude
                      #  dervs[3]: partial derivative by the background
                      #  dervs[4]: partial derivative by FWHMx
                      #  dervs[5]: partial derivative by FWHMy
                      #  dervs[6]: partial derivative by theta
   @return void
*/

void 
sinfo_new_gaussian_ellipse_deriv( double * xdat, 
                                  double * parlist, 
                                  double * dervs ) ;

/**
   @name    sinfo_new_lsqfitd()
   @param   xdat  position, coordinates of data points.
                  xdat is 2 dimensional: XDAT ( XDIM, NDAT )
   @param   xdim  dimension of fit
   @param   ydat  data points
   @param   wdat  weights for data points
   @param   ndat  number of data points
   @param   fpar  on input contains initial estimates of the
                  parameters for non-linear fits, on output the
                  fitted parameters.
   @param   epar  contains estimates of the errors in fitted parameters
   @param   mpar  logical mask telling which parameters are free (non-zero)
                  and which parameters are fixed (0)
   @param   npar number of function parameters ( free + fixed )
   @param   tol  relative tolerance. lsqfit stops when successive iterations
                 fail to produce a decrement in reduced chi-squared less
                 than tol. If tol is less than the minimum tolerance
                 possible, tol will be set to this value. This means
                 that maximum accuracy can be obtained by setting tol = 0.0.
   @param   its  maximum number of iterations
   @param   lab  mixing parameter, lab determines the initial weight
                 of steepest descent method relative to the Taylor method
                 lab should be a small value (i.e. 0.01). lab can only
                 be zero when the partial derivatives are independent
                 of the parameters. In fact in this case lab should be
                 exactly equal to zero.
   @param   returns number of iterations needed to achieve convergence
            according to tol. When this number is negative, the fitting
            was not continued because a fatal error occurred:
                     #   -1 too many free parameters, maximum is 32
                     #   -2 no free parameters
                     #   -3 not enough degrees of freedom
                     #   -4 maximum number of iterations too small to obtain
                           a solution which satisfies tol.
                     #   -5 diagonal of sinfo_matrix contains elements 
                            which are zero
                     #   -6 determinant of the coefficient sinfo_matrix is zero
                     #   -7 square root of a negative number
   @doc     this is a routine for making a least-squares fit of a
            function to a set of data points. The method used is
            described in: Marquardt, J.Soc.Ind.Appl.Math. 11. 431 (1963).
            This method is a mixture of the steepest descent method
            and the Taylor method.
*/
int 
sinfo_new_lsqfitd ( double * xdat,
              int    * xdim,
              double * ydat,
              double * wdat,
              int    * ndat,
              double * fpar,
              double * epar,
              int    * mpar,
              int    * npar,
              double * tol ,
              int    * its ,
              double * lab  ) ;

/**
   @name  sinfo_new_fit_2d_gaussian()
   @param image      reconstructed image of a point source
   @param fit_par    array of 7 free fit parameters of a 2D-Gauss
   @param derv_par   derivatives of the fit_par array
   @param mpar       mask to set free parameters, 1: free, 0: fixed.
   @param lleftx
   @param llefty     lower left starting point of the box in which the fit 
                     is carried through to find the maximum of point source 
                     image
   @param halfbox_x  half box length in x-direction in pixels inside which the 
                     fit is carried through
   @param halfbox_y  half box length in y-direction in pixels inside which the 
                     fit is carried through
   @return number of needed iterations -1 if an error occurred.
   @doc fits the image of a point source by using a 2-D Gaussian fit.
        Remark on the fit results for the fit parameters (fwhmx and fwhmy and 
        theta): theta will always be between -PI/4 and +PI/4, exchange of the 
        fwhmx and fwhmy values corresponds to a shift of theta by PI/2.
        Consequently, an expected theta > |PI/4| will result
        in an exchange of the fwhm values and a shift of theta by
        PI/2 to a value < |PI/4| what yields exactly the same image.
*/

int 
sinfo_new_fit_2d_gaussian ( cpl_image   * image,
                    double     * fit_par,
                    double     * derv_par,
                    int        * mpar,
                    int          lleftx,
                    int          llefty,
                    int          halfbox_x,
                    int          halfbox_y, int* check ) ;

/**
   @name   sinfo_new_plot_gaussian()
   @memo    plots an image of a given 2D-Gaussian
   @param  image: image which should be fitted
   @param  parlist: parameters of 2D-Gaussian
   @return image of the 2D-Gaussian
*/

cpl_image * 
sinfo_new_plot_gaussian ( cpl_image   * image,
                          double     * parlist ) ;

/**
   @name      sinfo_new_determine_conversion_factor()
   @param     cube reduced data cube of a standard star
   @param     mag  brightness of the standard star
   @param     exptime exposure time read from the fits header
   @param     llx
   @param     lly lower left point of fitting box
   @param     halfbox_x
   @param     halfbox_y half width of a box inside which
                        a 2D-Gauss fit is carried out
   @return    intensity conversion value: magnitude per counts/s
              -FLT_MAX if error occurred.
   @return    determines an intensity conversion factor for the instrument
              by fitting a 2D-Gaussian to an collapsed image of a standard star
              with known brightness (only for non-AO observations).
              Then the resulting Gaussian is integrated and the counts
              are divided by the exposure time (Fits header information)
*/
float 
sinfo_new_determine_conversion_factor ( cpl_imagelist * cube,
                                  float     mag,
                                  float     exptime,
                                  int       llx,
                                  int       lly,
                                  int       halfbox_x,
                                  int       halfbox_y, int* check ) ;

#endif /*!SINFO_FOCUS_H*/

