/*                                                                              *
 *   This file is part of the ESO UVES  Pipeline                                *
 *   Copyright (C) 2004,2005 European Southern Observatory                      *
 *                                                                              *
 *   This library is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by       *
 *   the Free Software Foundation; either version 2 of the License, or          *
 *   (at your option) any later version.                                        *
 *                                                                              *
 *   This program is distributed in the hope that it will be useful,            *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 *   GNU General Public License for more details.                               *
 *                                                                              *
 *   You should have received a copy of the GNU General Public License          *
 *   along with this program; if not, write to the Free Software                *
 *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
 *                                                                              */


/*
 * $Author: amodigli $
 * $Date: 2010-09-24 09:32:06 $
 * $Revision: 1.14 $
 * $Name: not supported by cvs2svn $
 * $Log: not supported by cvs2svn $
 * Revision 1.12  2007/08/21 13:08:26  jmlarsen
 * Removed irplib_access module, largely deprecated by CPL-4
 *
 * Revision 1.11  2007/06/06 08:17:33  amodigli
 * replace tab with 4 spaces
 *
 * Revision 1.10  2007/03/19 13:48:54  jmlarsen
 * Added some error handling
 *
 * Revision 1.9  2006/11/15 15:02:14  jmlarsen
 * Implemented const safe workarounds for CPL functions
 *
 * Revision 1.7  2006/11/15 14:04:08  jmlarsen
 * Removed non-const version of parameterlist_get_first/last/next which is already in CPL, added const-safe wrapper, unwrapper and deallocator functions
 *
 * Revision 1.6  2006/11/06 15:19:41  jmlarsen
 * Removed unused include directives
 *
 * Revision 1.5  2006/08/23 15:41:06  amodigli
 * removed warning from checks on line length
 *
 * Revision 1.4  2006/08/07 11:30:55  jmlarsen
 * Added debugging statments
 *
 * Revision 1.3  2006/06/20 10:56:56  amodigli
 * cleaned output, added units
 *
 * Revision 1.2  2006/02/15 13:19:15  jmlarsen
 * Reduced source code max. line length
 *
 * Revision 1.1  2006/02/03 07:46:30  jmlarsen
 * Moved recipe implementations to ./uves directory
 *
 * Revision 1.8  2006/01/19 08:47:24  jmlarsen
 * Inserted missing doxygen end tag
 *
 * Revision 1.7  2006/01/13 13:43:15  jmlarsen
 * Removed memory leak
 *
 * Revision 1.6  2006/01/13 09:54:42  amodigli
 * Fixed some bugs: improved agreement with MIDAS version
 *
 * Revision 1.5  2006/01/05 14:29:59  jmlarsen
 * Removed newline characters from output strings
 *
 * Revision 1.4  2005/12/20 08:11:44  jmlarsen
 * Added CVS  entry
 *
 */

/*----------------------------------------------------------------------------*/
/**
 * @addtogroup uves_physmod
 */
/*----------------------------------------------------------------------------*/
/**@{*/



#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/*-----------------------------------------------------------------------------
                                Includes
 -----------------------------------------------------------------------------*/
#include <uves_physmod_center_gauss.h>

#include <uves_physmod_cstacen.h>
#include <uves_utils_wrappers.h>
#include <uves_error.h>
#include <uves_msg.h>

#include <cpl.h>

/*-----------------------------------------------------------------------------
                                Defines
 -----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
                            Functions prototypes
 ----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
                            Static variables
 -----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                            Functions code
 -----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/**
  @brief    Fit the image line X and Y distributions with a Gaussian in a box
  @param    raw_image    Input raw image
  @param    m_tbl model table:  Input/Output table with added colums 
                         ICENT,XCEN,YCEN,XFWHM,YFWHM,XSIG,YSIG,XERR,YERR,STATUS
                         with results of a Gaussian marginal fit to the image
                         intensity distributions obtained by collapsing along
                         X and Y the image points within a box centered at 
                         each line

  @return   0 if everything is ok, -1 otherwise

  This function is used to precisely locate each image line within a given
  box by a Gaussian 1d fit of each intensity distribution which can be obtained
  by collapsing the signal within a box centered at each line (routine derived
  from MIDAS one)

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

int
uves_physmod_center_gauss(const cpl_image * raw_image,cpl_table** m_tbl)
{

  /* Derived from MIDAS center.for, only in case input is ima,table and
     method is Gauss
  */
  int nraw=0;
  int i=0;

  double px_start=0;
  double py_start=0;
  double px_end=0;
  double py_end=0;

  int img_llx=0;
  int img_lly=0;
  int img_urx=0;
  int img_ury=0;

  int img_sx=0;
  int img_sy=0;


  double tmp_val=0;

  double* x_mod=NULL;
  double* y_mod=NULL;
  int status=0;
  double* x_cen=NULL;
  double* y_cen=NULL;

  double* x_err=NULL;
  double* y_err=NULL;

  double* x_start=NULL;
  double* y_start=NULL;
  double* x_end=NULL;
  double* y_end=NULL;
  double* icent=0;


  double* x_sig=NULL;
  double* y_sig=NULL;
  double* x_fwhm=NULL;
  double* y_fwhm=NULL;

  int img_ofx=0;
  int img_ofy=0;
  int img_buf1=0;
  int img_buf2=0;
  int img_buf3=0;
  
  int img_szx=0;
  int img_szy=0;

  float xout=0;
  float yout=0;
  float xerr=0;
  float yerr=0;
  float xsig=0;
  float ysig=0;
  float amp=0;
  double xfwhm=0;
  double yfwhm=0;
  double ang=0.;
  double ang_sig=0.;
  double rv=0.;
  int kstat=0;
  int cpix[5]={0,0,0,0,0};
  double STEP[3]={1.0,1.0,1.0};
  int NPIX=0;

  float* sima;
  cpl_image* img_sub=NULL;
  cpl_image* img_cst=NULL;

  int ok=0;
  int nok=0;
  int nf=0;



  check(nraw = cpl_table_get_nrow(*m_tbl), "Error getting nraw");

  cpl_table_new_column(*m_tbl,"XCEN",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"YCEN",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"ICENT",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"XSIG",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"YSIG",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"XFWHM",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"YFWHM",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"XERR",CPL_TYPE_DOUBLE);
  cpl_table_new_column(*m_tbl,"YERR",CPL_TYPE_DOUBLE);


  icent = cpl_table_get_data_double(*m_tbl,"ICENT");

  x_mod = cpl_table_get_data_double(*m_tbl,"XMOD");
  y_mod = cpl_table_get_data_double(*m_tbl,"YMOD");
  x_err = cpl_table_get_data_double(*m_tbl,"XERR");
  y_err = cpl_table_get_data_double(*m_tbl,"YERR");

  x_start = cpl_table_get_data_double(*m_tbl,"XSTART");
  y_start = cpl_table_get_data_double(*m_tbl,"YSTART");
  x_end   = cpl_table_get_data_double(*m_tbl,"XEND");
  y_end   = cpl_table_get_data_double(*m_tbl,"YEND");

  x_cen = cpl_table_get_data_double(*m_tbl,"XCEN");
  y_cen = cpl_table_get_data_double(*m_tbl,"YCEN");
  x_sig = cpl_table_get_data_double(*m_tbl,"XSIG");
  y_sig = cpl_table_get_data_double(*m_tbl,"YSIG");
  x_fwhm = cpl_table_get_data_double(*m_tbl,"XFWHM");
  y_fwhm = cpl_table_get_data_double(*m_tbl,"YFWHM");
  

  cpl_table_new_column(*m_tbl,"STATUS",CPL_TYPE_INT);
  check_nomsg( cpl_table_set_column_invalid(*m_tbl,"STATUS",0,
                                            cpl_table_get_nrow(*m_tbl)));

  cpl_table_set_column_invalid(*m_tbl,"ICENT",0,
                            cpl_table_get_nrow(*m_tbl));

  cpl_table_set_column_invalid(*m_tbl,"XCEN",0,
                            cpl_table_get_nrow(*m_tbl));
  cpl_table_set_column_invalid(*m_tbl,"YCEN",0,
                            cpl_table_get_nrow(*m_tbl));

  cpl_table_set_column_invalid(*m_tbl,"XSIG",0,
                            cpl_table_get_nrow(*m_tbl));
  cpl_table_set_column_invalid(*m_tbl,"YSIG",0,
                            cpl_table_get_nrow(*m_tbl));

  cpl_table_set_column_invalid(*m_tbl,"XFWHM",0,
                            cpl_table_get_nrow(*m_tbl));
  cpl_table_set_column_invalid(*m_tbl,"YFWHM",0,
                            cpl_table_get_nrow(*m_tbl));


  /* We loop over each table raw and get box edges */
  /* one should skip selected raws */
  nf=0;
  for(i=0;i<nraw;i++) { 
    /* get box edges */
    px_start=cpl_table_get_double(*m_tbl,"XSTART",i,&status);
    py_start=cpl_table_get_double(*m_tbl,"YSTART",i,&status);
    px_end=cpl_table_get_double(*m_tbl,"XEND",i,&status);
    py_end=cpl_table_get_double(*m_tbl,"YEND",i,&status);


    img_llx=floor(px_start+0.5);
    img_lly=floor(py_start+0.5);
    img_urx=floor(px_end+0.5);
    img_ury=floor(py_end+0.5);

    img_szx=cpl_image_get_size_x(raw_image);
    img_szy=cpl_image_get_size_y(raw_image);

    /*
    if(i==167 || i==485) {
      uves_msg(">>>>>>>>>>>>>>>>i=%d",i);
    }
    */
    if(img_llx < 1 || img_urx > img_szx || 
       img_lly < 1 || img_ury > img_szy) {
      /* 
     uves_msg("SSSSSSSSSSSSSSSSSSi=%d",i);
      */
      continue;

      }
    /*
    img_llx=( img_llx >= 1 ) ? img_llx : 1;
    img_lly=( img_lly >= 1 ) ? img_lly : 1;
    img_urx=( img_urx <= img_szx ) ? img_urx : img_szx;
    img_ury=( img_ury <= img_szy ) ? img_ury : img_szy;
    */

    img_sx=img_urx-img_llx+1;
    img_sy=img_ury-img_lly+1;
    img_ofx=img_llx-1;
    img_ofy=img_lly-1;
    /* we get NPIX */
    img_buf1=NPIX;
    img_buf2=img_sy;
    img_buf3=1;


    /* initialize centering algorithm */
    cpix[0]=1;
    cpix[1]=img_sx;
    cpix[2]=1;
    cpix[3]=img_sy;


    uves_msg_debug("Box %d %d %d %d %d",nf,img_llx,img_urx,img_lly,img_ury);
    /*
    check(img_sub =cpl_image_extract(raw_image,img_llx,img_lly,img_urx,img_ury);
      img_cst = cpl_image_cast(img_sub,CPL_TYPE_FLOAT),
      sima = cpl_image_get_data_float(img_cst),
    "error img_sub");
    */
    uves_free_image(&img_sub);
    img_sub =cpl_image_extract(raw_image,img_llx,img_lly,img_urx,img_ury);
    uves_free_image(&img_cst);
    img_cst = cpl_image_cast(img_sub,CPL_TYPE_FLOAT);
    sima = cpl_image_get_data_float(img_cst);

      /*
 for(i=0;kk<img_sx*img_sy;kk++) {
    uves_msg("Image[%d]=%f",kk,sima[kk]);
 }
      */
    
    uves_msg_debug("stacen nf=%d cpix=%d %d %d %d",nf,cpix[0],cpix[1],cpix[2],cpix[3]);
    uves_physmod_stacen(sima,img_sx,img_sy,'G',cpix,
            &xout,&yout,&xerr,&yerr,&xsig,&ysig,&amp,&kstat);
    
    uves_msg_debug("nf=%d,xout=%f,yout=%f,xerr=%f,yerr=%f",nf,xout,yout,xerr,yerr);
    uves_msg_debug("xsig=%f,ysig=%f,xfwhm=%f,yfwhm=%f",xsig,ysig,xfwhm,yfwhm);

    uves_msg_debug("amp=%f,kstat=%d",amp,kstat);
    
    rv=0.;
    ang=0.;
    ang_sig=0.;

    
    if (i<0) {
    uves_msg("Min=%f,Max=%f",cpl_image_get_min(img_sub),
                             cpl_image_get_max(img_sub));
    uves_msg("llx=%d,lly=%d,urx=%d,ury=%d",img_llx,img_lly,img_urx,img_ury);
    uves_msg("sx=%d,sy=%d,ofx=%d,ofy=%d",img_sx,img_sy,img_ofx,img_ofy);
    uves_msg("img_sx=%d,img_sy=%d,cpix[0]=%d,cpix[1]=%d,cpix[2]=%d,cpix[3]=%d",
           img_sx,img_sy,cpix[0],cpix[1],cpix[2],cpix[3]);

    uves_msg("i=%d,xout=%f,yout=%f,xerr=%f,yerr=%f",nf,xout,yout,xerr,yerr);
    uves_msg("xsig=%f,ysig=%f,xfwhm=%f,yfwhm=%f,amp=%f,kstat=%d",xsig,ysig,xfwhm,yfwhm,amp,kstat);
   
    }
    
    /* check status */
    if(kstat == 0) {

      xerr=xerr*fabs(STEP[1]);
      xsig=xsig*fabs(STEP[1]);
      xfwhm=xsig*TWOSQRT2LN2;  /* MIDAS: 2.35482 */

      yerr=yerr*fabs(STEP[2]);
      ysig=ysig*fabs(STEP[2]);
      yfwhm=ysig*TWOSQRT2LN2;  /* MIDAS: 2.35482 */
      ok++;
      tmp_val=cpl_table_get_double(*m_tbl,"IDENT",i,&status);
      tmp_val-=1;
      tmp_val/=1000.;

    } else {

      xerr=0.;
      xsig=0.;
      xfwhm=0.;

      yerr=0.;
      ysig=0.;
      yfwhm=0.;
      nok++;
      /* we assume that not using IQUE function kstatus >=0 */
    }


    uves_msg_debug("nf=%d %f %f %f %f %f %d",nf,xout,yout,xsig,ysig,amp,kstat);
    
    /* we write results in table */


    /* we check if FWHM makes sense */
    if( (xfwhm > img_sx *fabs(STEP[1])) || (yfwhm > img_sy *fabs(STEP[2])) ) {
      kstat = 4;
    }
    if ( (xfwhm < 0.0) || (yfwhm < 0.0) ) {
      kstat = 5;
    }


   
    /* to debug: 0-->NN>0 */
    if (i<0) {
    uves_msg("Min=%f,Max=%f",cpl_image_get_min(img_sub),
                             cpl_image_get_max(img_sub));
    uves_msg("llx=%d,lly=%d,urx=%d,ury=%d",img_llx,img_lly,img_urx,img_ury);
    uves_msg("sx=%d,sy=%d,ofx=%d,ofy=%d",img_sx,img_sy,img_ofx,img_ofy);
    uves_msg("img_sx=%d,img_sy=%d,cpix[0]=%d,cpix[1]=%d,cpix[2]=%d,cpix[3]=%d",
           img_sx,img_sy,cpix[0],cpix[1],cpix[2],cpix[3]);

    uves_msg("i=%d,xout=%f,yout=%f,xerr=%f,yerr=%f",i,xout,yout,xerr,yerr);
    uves_msg("xsig=%f,ysig=%f,xfwhm=%f,yfwhm=%f,amp=%f,kstat=%d",xsig,ysig,xfwhm,yfwhm,amp,kstat);
   
    }
    

     cpl_table_set_double(*m_tbl,"IDENT",i,tmp_val);
     cpl_table_set_double(*m_tbl,"ICENT",i,(double)amp);
     cpl_table_set_double(*m_tbl,"XERR",i,(double)xerr);
     cpl_table_set_double(*m_tbl,"YERR",i,(double)yerr);

     cpl_table_set_double(*m_tbl,"XCEN",i,(double)(xout+img_ofx));
     cpl_table_set_double(*m_tbl,"YCEN",i,(double)(yout+img_ofy));
     cpl_table_set_double(*m_tbl,"XSIG",i,(double)xsig);
     cpl_table_set_double(*m_tbl,"YSIG",i,(double)ysig);
     cpl_table_set_double(*m_tbl,"XFWHM",i,(double)xfwhm);
     cpl_table_set_double(*m_tbl,"YFWHM",i,(double)yfwhm);
     cpl_table_set_int   (*m_tbl,"STATUS",i,kstat);
     nf=nf+1;

  }

  if (false)   /* Debugging... */
      {
      cpl_table *dum = cpl_table_new(cpl_table_get_nrow(*m_tbl));
      
      cpl_table_duplicate_column(dum,"STAT",*m_tbl,"STATUS");
      
      uves_msg_warning("xcen = %f", cpl_table_get_column_mean(*m_tbl, "XCEN"));
      uves_msg_warning("ycen = %f", cpl_table_get_column_mean(*m_tbl, "YCEN"));
      uves_msg_warning("xerr = %f", cpl_table_get_column_mean(*m_tbl, "XERR"));
      uves_msg_warning("yerr = %f", cpl_table_get_column_mean(*m_tbl, "YERR"));
      uves_msg_warning("xsig = %f", cpl_table_get_column_mean(*m_tbl, "XSIG"));
      uves_msg_warning("ysig = %f", cpl_table_get_column_mean(*m_tbl, "YSIG"));
      uves_msg_warning("xfwhm = %f", cpl_table_get_column_mean(*m_tbl, "XFWHM"));
      uves_msg_warning("yfwhm = %f", cpl_table_get_column_mean(*m_tbl, "YFWHM"));
      uves_msg_warning("icent = %f", cpl_table_get_column_mean(*m_tbl, "ICENT"));
      uves_msg_warning("status = %f", cpl_table_get_column_mean(*m_tbl, "STATUS"));
      
//    cpl_table_dump(dum, 0, cpl_table_get_nrow(*m_tbl), stdout);
      }

  uves_msg_debug("nok=%d ok=%d",nok,ok);

  cleanup:
  uves_free_image(&img_sub);
  uves_free_image(&img_cst);

  return 0;
}
/**@}*/
