/*                                                                              *
 *   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:07 $
 * $Revision: 1.13 $
 * $Name: not supported by cvs2svn $
 * $Log: not supported by cvs2svn $
 * Revision 1.11  2010/06/08 09:45:58  amodigli
 * removed XMODREG_X_RES YMODREG_YNEW_RES columns from result of selplot=1 selection
 *
 * Revision 1.10  2010/06/07 16:49:56  amodigli
 * added columns XMODREG_X_RES,YMODREG_YNEW_RES and now the XDIF,YDIF are computed for any of the points that do not satisfy the SELPLOT=1 condition
 *
 * Revision 1.9  2010/06/02 15:04:10  amodigli
 * fixed bug in cross correlating line and model predicted tables
 *
 * Revision 1.8  2010/06/01 13:28:57  amodigli
 * added column units to line table columns
 *
 * Revision 1.7  2008/09/29 06:55:33  amodigli
 * add #include <string.h>
 *
 * Revision 1.6  2007/06/06 08:17:33  amodigli
 * replace tab with 4 spaces
 *
 * Revision 1.5  2006/11/06 15:19:41  jmlarsen
 * Removed unused include directives
 *
 * Revision 1.4  2006/10/05 11:17:49  jmlarsen
 * Removed debugging call of uves_error_dump
 *
 * Revision 1.3  2006/06/20 10:56:56  amodigli
 * cleaned output, added units
 *
 * Revision 1.2  2006/03/08 08:55:37  amodigli
 * fixed garbage in SELPLOT column of line table
 *
 * Revision 1.1  2006/02/03 07:46:30  jmlarsen
 * Moved recipe implementations to ./uves directory
 *
 * Revision 1.7  2006/01/19 08:47:24  jmlarsen
 * Inserted missing doxygen end tag
 *
 * Revision 1.6  2006/01/16 08:01:57  amodigli
 *
 * Added stability check
 *
 * Revision 1.5  2006/01/05 14:29:59  jmlarsen
 * Removed newline characters from output strings
 *
 * Revision 1.4  2006/01/05 09:30:48  amodigli
 * Col SELPLOT initialized to NULL
 *
 * Revision 1.3  2005/12/19 16:17:55  jmlarsen
 * Replaced bool -> int
 *
 */

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

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

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

#include <uves_error.h>
#include <uves_msg.h>
#include <string.h>
/*-----------------------------------------------------------------------------
                                Defines
 -----------------------------------------------------------------------------*/
#define FILESIZE 200
/*-----------------------------------------------------------------------------
                            Functions prototypes
 ----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
                            Static variables
 -----------------------------------------------------------------------------*/

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

/*----------------------------------------------------------------------------*/
/**
  @brief    To be written
  @param    rline_tbl    The input line table. 
  @param    lin_tbl      The input line table. 

  @return   0 if everything is ok, -1 otherwise

 */
/*----------------------------------------------------------------------------*/
int uves_physmod_qc1pmtbl(cpl_table** rline_tbl,cpl_table** lin_tbl)
{

  int nCol   = 0;            /* No of columns in tbl */
  int rlineRowNumber=0;      /* number of rows in rline table */
  int lineRowNo=0;           /* number of Rows in line table */
  int null=0;                /* number of null values in keyword */
  int i=0;                   /* loop variable */
  int l=0;                   /* loop variable */


  int    selIdx=0;           /* actual value */
  
  char   lineTbl[FILESIZE];  /* buffer for data values */
  char   rLineTbl[FILESIZE]; /* buffer for data values */
  char   aHeading[FILESIZE]; /* column reference */
  char   tmps[FILESIZE];     /* for messout */
   
  
  
  double  xDif=0.0;          /* actual value */
  double  yDif=0.0;          /* actual value */
  double  xModReg=0.0;       /* actual value */
  double  yModReg=0.0;       /* actual value */
  double  xPred=0.0;         /* actual value */
  double  yPred=0.0;         /* actual value */
  double  x=0.0;             /* actual value */
  double  yNew=0.0;          /* actual value */
  double  diffX=0.0;         /* difference between x and y */
  double  diffY=0.0;         /* difference between x and y */
                             /* (rounding error threshold) */
  double waveReg=0.0;
  double wavec=0.0;
  int match=1;
  int order=0;
  int orderReg=0;


/* initializes chars */
  memset(lineTbl,  0, FILESIZE);    
  memset(rLineTbl, 0, FILESIZE);    
  memset(aHeading, 0, FILESIZE);    
  memset(tmps,     0, FILESIZE);        


  uves_msg_debug("start %s",__func__);

  check(nCol=cpl_table_get_ncol(*rline_tbl),"Error getting ncol");
  rlineRowNumber=cpl_table_get_nrow(*rline_tbl);
  uves_msg_debug("Opened table %s nCol=%d nrow=%d",
                     "rline.tbl" ,nCol,rlineRowNumber);

  nCol=cpl_table_get_ncol(*lin_tbl);
  lineRowNo=cpl_table_get_nrow(*lin_tbl);
  
  uves_msg_debug("Opened table %s nCol=%d nrow=%d",
                      lineTbl ,nCol,lineRowNo); 

 
  if(cpl_table_has_column(*lin_tbl,"XDIF")){
    cpl_table_erase_column(*lin_tbl,"XDIF"); 
    uves_msg_debug("removed column XDIF");
  }

  if(cpl_table_has_column(*lin_tbl,"YDIF")){
    cpl_table_erase_column(*lin_tbl,"YDIF"); 
    uves_msg_debug("removed column YDIF");
  }

  if(cpl_table_has_column(*lin_tbl,"SELPLOT")){
    cpl_table_erase_column(*lin_tbl,"SELPLOT"); 
    uves_msg_debug("removed column SELPLOT");
  }

  if(cpl_table_has_column(*lin_tbl,"XPRED")){
    cpl_table_erase_column(*lin_tbl,"XPRED"); 
    uves_msg_debug("removed column XPRED");
  }

  if(cpl_table_has_column(*lin_tbl,"YPRED")){
    cpl_table_erase_column(*lin_tbl,"YPRED"); 
    uves_msg_debug("removed column YPRED");
  }

  /* Then add those columns */

  cpl_table_new_column(*lin_tbl,"XPRED",CPL_TYPE_DOUBLE);
  cpl_table_set_column_unit(*lin_tbl,"XPRED","pix");

  cpl_table_new_column(*lin_tbl,"YPRED",CPL_TYPE_DOUBLE);
  cpl_table_set_column_unit(*lin_tbl,"YPRED","pix");

  cpl_table_new_column(*lin_tbl,"XDIF",CPL_TYPE_DOUBLE);
  cpl_table_set_column_unit(*lin_tbl,"XDIF","pix");

  cpl_table_new_column(*lin_tbl,"YDIF",CPL_TYPE_DOUBLE);
  cpl_table_set_column_unit(*lin_tbl,"YDIF","pix");

  cpl_table_new_column(*lin_tbl,"SELPLOT",CPL_TYPE_INT);
  cpl_table_set_column_unit(*lin_tbl,"YDIF","pix");


/*
 ***************************************************************************
 * Now does the actual ordering of the elements writing in the right place *
 ***************************************************************************
 */
 
  cpl_table_set_column_invalid(*lin_tbl,"SELPLOT",0,
                               cpl_table_get_nrow(*lin_tbl));


/*
  uves_msg("rlineRowNumber=%d",rlineRowNumber);
  cpl_table_dump(*rline_tbl,1,2,stdout);
  cpl_table_dump(*lin_tbl,1,2,stdout);
*/
  for (l=0; l< rlineRowNumber; l++) {

 
    xModReg=cpl_table_get_double(*rline_tbl,"XMODREG",l,&null);
    yModReg=cpl_table_get_double(*rline_tbl,"YMODREG",l,&null);
    xDif=cpl_table_get_double(*rline_tbl,"XDIF",l,&null);
    yDif=cpl_table_get_double(*rline_tbl,"YDIF",l,&null);
    xPred=cpl_table_get_double(*rline_tbl,"XMOD",l,&null);
    yPred=cpl_table_get_double(*rline_tbl,"YMOD",l,&null);
    waveReg=cpl_table_get_double(*rline_tbl,"WAVE",l,&null);
    check_nomsg(orderReg=cpl_table_get_int(*rline_tbl,"ORDER",l,&null));
    //uves_msg("i=%d xDif=%f yDif=%f lineRowNo=%d",i,xDif,yDif,lineRowNo);

    selIdx = 1;
    match=0;
    for (i=0; i< lineRowNo; i++) {
       //uves_msg("i=%d",i);
        x=cpl_table_get_double(*lin_tbl,"X",i,&null);
        yNew=cpl_table_get_double(*lin_tbl,"YNEW",i,&null);
        wavec=cpl_table_get_double(*lin_tbl,"WAVEC",i,&null);
        check_nomsg(order=cpl_table_get_int(*lin_tbl,"Order",i,&null));
        diffX=fabs(x-xModReg);
        diffY=fabs(yNew-yModReg);
/*
        uves_msg("waveReg=%f wavec=%f diff=%f",
                 10.*waveReg, wavec, fabs(waveReg - wavec));
*/  
        if ( (fabs(10.*waveReg - wavec)  <= 0.01) && 
              match == 0 && 
             (fabs(orderReg-order)<0.1) ) {
           //uves_msg("match wave l=%d i=%d order=%d",l,i,order);
          cpl_table_set_double(*lin_tbl,"XPRED",i,xPred);
          cpl_table_set_double(*lin_tbl,"YPRED",i,yPred);
          cpl_table_set_double(*lin_tbl,"XDIF",i,xDif);
          cpl_table_set_double(*lin_tbl,"YDIF",i,yDif);
        }    
        if ((diffX <= 0.001) && (diffY <= 0.001)) {
           match=1;
          cpl_table_set_double(*lin_tbl,"XPRED",i,xPred);
          cpl_table_set_double(*lin_tbl,"YPRED",i,yPred);
          cpl_table_set_double(*lin_tbl,"XDIF",i,xDif);
          cpl_table_set_double(*lin_tbl,"YDIF",i,yDif);

          cpl_table_set_int(*lin_tbl,"SELPLOT",i,selIdx);

           break;   
        }
    }
  }


  /* second check to add only those lines that are not matching selplot=1
     criterium */

  for (l=0; l< rlineRowNumber; l++) { 
    xModReg=cpl_table_get_double(*rline_tbl,"XMODREG",l,&null);
    yModReg=cpl_table_get_double(*rline_tbl,"YMODREG",l,&null);
    xDif=cpl_table_get_double(*rline_tbl,"XDIF",l,&null);
    yDif=cpl_table_get_double(*rline_tbl,"YDIF",l,&null);
    xPred=cpl_table_get_double(*rline_tbl,"XMOD",l,&null);
    yPred=cpl_table_get_double(*rline_tbl,"YMOD",l,&null);
    waveReg=cpl_table_get_double(*rline_tbl,"WAVE",l,&null);
    check_nomsg(orderReg=cpl_table_get_int(*rline_tbl,"ORDER",l,&null));
    //uves_msg("i=%d xDif=%f yDif=%f lineRowNo=%d",i,xDif,yDif,lineRowNo);
    
    for (i=0; i< lineRowNo; i++) {
       //uves_msg("i=%d",i);
        x=cpl_table_get_double(*lin_tbl,"X",i,&null);
        yNew=cpl_table_get_double(*lin_tbl,"YNEW",i,&null);
        wavec=cpl_table_get_double(*lin_tbl,"WAVEC",i,&null);
        check_nomsg(order=cpl_table_get_int(*lin_tbl,"Order",i,&null));
        check_nomsg(selIdx=cpl_table_get_int(*lin_tbl,"SELPLOT",i,&null));
        diffX=fabs(x-xModReg);
        diffY=fabs(yNew-yModReg);

        if ( selIdx != 1 && 
             (fabs(orderReg-order)<0.1) ) {
          cpl_table_set_double(*lin_tbl,"XPRED",i,xPred);
          cpl_table_set_double(*lin_tbl,"YPRED",i,yPred);
          cpl_table_set_double(*lin_tbl,"XDIF",i,xDif);
          cpl_table_set_double(*lin_tbl,"YDIF",i,yDif);
           break;   
        }    
    }
  }




  /*
  cpl_table_dump(*lin_tbl,0,20,stdout);
  */
  uves_msg_debug("end %s",__func__);
  cpl_table_fill_invalid_int(*lin_tbl,"SELPLOT",-1);

  cleanup:
  return 0;

}
/**@}*/


