/*===========================================================================
  Copyright (C) 2001 European Southern Observatory (ESO)
 
  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, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
  Internet e-mail: midas@eso.org
  Postal address: European Southern Observatory
  Data Management Division 
  Karl-Schwarzschild-Strasse 2
  D 85748 Garching bei Muenchen 
  GERMANY
  ===========================================================================*/
/*-------------------------------------------------------------------------*/
/**
 * @defgroup flames_doptimal  
 *
 */
/*---------------------------------------------------------------------------
  Includes
  --------------------------------------------------------------------------*/

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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <flames_midas_def.h>
#include <flames_optimal.h>
#include <flames_def_drs_par.h>
#include <flames_uves.h>
#include <flames_ordselect.h>
#include <flames_doptimal.h>
#include <flames_newmatrix.h>
/**@{*/

/*---------------------------------------------------------------------------
  Implementation
  ---------------------------------------------------------------------------*/
/**
   @name  flames_doptimal()  
   @short this function performs the actual optimal extraction on a frame
   @author G. Mulas  -  ITAL_FLAMES Consortium. Ported to CPL by A. Modigliani

   @param ScienceFrame   all fibre frame to be optimally extracted
   @param Order          fibre-order position table
   @param Shifted_FF     shifted flat field structure
   @param kappa2         square of kappa to be used in kappa-sigma clip
   @param mask           bad pixel mask frame
   @param backframe      inter-order background frame
   @param normcover      array to hold fibre normalization factors
   @param orderoffset    offset between Slit_FF order tab and fibre-order tab;
   @param realfirstorder first order (from fibre-order table) to be extracted
   @param reallastorder  last order (from fibre-order table) to be extracted
   @param minoptitersint minimum number of optimal extraction iterations
   @param maxoptitersint maximum number of optimal extraction iterations
   @param xkillsize      When performing sigma-clipping in the optimal extraction, how many
                         other adjacent pixels in the x and/or y direction(s) should be
                         discarded along with the one exceeding the threshold? A cosmic or
                         cosmetic problem is likely to affect a spot larger than 1 pixel
   @param ykillsize      see above

   @doc                  loop over orders and the call optimal() function

   @return success or failure code

   DRS Functions called:          
   none                                         
                                                                         
   Pseudocode:                                                             


   @note
*/

flames_err 
doptimal(
         flames_frame *ScienceFrame, 
         orderpos *Order, 
         allflats *Shifted_FF, 
         double kappa2, 
         frame_mask **mask, 
         frame_data **backframe, 
         frame_data **normcover, 
         int32_t orderoffset, 
         int32_t realfirstorder, 
         int32_t reallastorder, 
         int32_t minoptitersint, 
         int32_t maxoptitersint, 
         int32_t xkillsize, 
         int32_t ykillsize)
{

  int32_t ordsta=0, ordend=0, i=0, xysize=0;
  char output[100];

  int actvals=0;
  char drs_verbosity[10];


  frame_mask **newmask=0;
  frame_mask *fmvecbuf1=0;

  memset(drs_verbosity, 0, 10);
  if ( SCKGETC(DRS_VERBOSITY, 1, 3, &actvals, drs_verbosity) != 0 ) {
    /* the keyword seems undefined, protest... */
    return(MAREMMA);
  }


  newmask=fmmatrix(0,ScienceFrame->subrows-1,0,ScienceFrame->subcols-1);
  fmvecbuf1 = newmask[0];
  xysize = (ScienceFrame->subrows*ScienceFrame->subcols)-1;
  for (i=0; i<=xysize; i++) fmvecbuf1[i] = 0;

  for (ordsta=ordend=realfirstorder; ordsta<=reallastorder; 
       ordsta=++ordend) 
    {
      /* at least we extract from ordsta to ordend */
      /* select a set of orders which is disjoint from other orders */
      if (ordselect(Order, ScienceFrame, Shifted_FF, &ordend)!=NOERR) 
	{
	  SCTPUT("Error selecting an order subset to estract\n");
	  return flames_midas_error(MAREMMA);
	}

      /* A little bit of advertising */
      sprintf(output, "Extracting orders from nr. %d to nr. %d....", 
	      ordsta, ordend);
      SCTPUT(output);

      /* let's make the optimal extraction */  
      switch(optimal(ScienceFrame, Shifted_FF, Order, ordsta, ordend, kappa2, 
		     mask, newmask, backframe, normcover, orderoffset, 
		     minoptitersint, maxoptitersint, xkillsize, ykillsize)) {
      case 0:
	if ( strcmp(drs_verbosity,"LOW") == 0 ){
	} else {
	  sprintf(output, "Optimal extraction for orders from nr. %d to %d completed\n", ordsta, ordend);
	  SCTPUT(output);
	}
	break;
      case 1:
	sprintf(output, "Error in optimal extraction\n");
	SCTPUT(output);
	return flames_midas_error(MAREMMA);
	break;
      case 2:
	sprintf(output, "Error in sigma clipping\n");
	SCTPUT(output);
	return flames_midas_error(MAREMMA);
	break;
      case 3:
	sprintf(output, "Error in covariance calculation\n");
	SCTPUT(output);
	return flames_midas_error(MAREMMA);
	break;
      case 4:
	sprintf(output, "Error in cross-correlation\n");
	SCTPUT(output);
	return flames_midas_error(MAREMMA);
	break;
      default :
	sprintf(output, "Unknown error\n");
	SCTPUT(output);
	return flames_midas_error(MAREMMA);
	break;
      }
    }

  free_fmmatrix(newmask, 0,ScienceFrame->subrows-1,0,ScienceFrame->subcols-1);

  return NOERR;

}
/**@}*/
