/*===========================================================================
  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
===========================================================================*/
/* Program  : locatefibre.c                                              */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : locate each fibre? Missing                                   */
/*                                                                         */
/*                                                                         */
/* Input:  see interface                                                   */ 
/*                                                                      */
/* Output:                                                              */
/*                                                                         */
/* DRS Functions called:                                                   */
/* none                                                                    */ 
/*                                                                         */ 
/* Pseudocode:                                                             */
/* Missing                                                                 */ 
/*                                                                         */ 
/* Version  :                                                              */
/* Last modification date: 2002/08/05                                      */
/* Who     When        Why                Where                            */
/* AMo     02-08-05   Add header         header                            */
/*-------------------------------------------------------------------------*/

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

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <flames_midas_def.h>
#include <flames_uves.h>
#include <flames_newmatrix.h>
#include <flames_shiftcommon.h>
#include <flames_shiftall.h>


flames_err locatefibre(allflats *allflatsin, allflats *allflatsout, 
               orderpos* ordpos, shiftstruct *shiftdata,
               int32_t iorder, int32_t ifibre, 
               int32_t ix, double yshift)
{
  double fibrecentre=0;
  double yup=0;
  double ydown=0;
  double pyup=0;
  double pydown=0;
  double fibrefrac=0;
  int32_t iorderifibreindex=0;
  int32_t iorderifibreixindex=0;
  int32_t *lvecbuf1=0;
  int32_t *lvecbuf2=0;
  frame_mask *fmvecbuf1=0;

  iorderifibreindex = (iorder*allflatsin->maxfibres)+ifibre;
  iorderifibreixindex = (iorderifibreindex*allflatsin->subcols)+ix;

/* if not allocated allocate ! */  
  if(!(allflatsout->lowfibrebounds)) {
    if(!(allflatsout->lowfibrebounds = 
     l3tensor(0, allflatsout->lastorder-allflatsout->firstorder, 
           0, allflatsout->maxfibres-1, 0, allflatsout->subcols-1))) {
      SCTPUT("Allocation error");
      return flames_midas_fail();
    }   
  }
  lvecbuf1 = allflatsout->lowfibrebounds[0][0]+iorderifibreixindex;

  if(!(allflatsout->highfibrebounds)) {
    if(!(allflatsout->highfibrebounds = 
     l3tensor(0, allflatsout->lastorder-allflatsout->firstorder, 
           0, allflatsout->maxfibres-1, 0, allflatsout->subcols-1))) {
      SCTPUT("Allocation error");
      return flames_midas_fail();
    }
  }
  lvecbuf2 = allflatsout->highfibrebounds[0][0]+iorderifibreixindex;

  fmvecbuf1 = allflatsout->goodfibres[0][0]+iorderifibreixindex;

  /* find the y central position of this fibre at this x */ 
  fibrecentre = (shiftdata[ix]).ordercentre+(ordpos->fibrepos)[ifibre]+yshift;
  /* now determine the y limits of this fibre */
  yup = fibrecentre+allflatsin->halfibrewidth;
  ydown = fibrecentre-allflatsin->halfibrewidth;
  /* translate to pixel coordinates, remembering that pixel numbering starts 
     at 0 and taking into account the pixel size */
  pyup = (yup-allflatsin->substarty)/allflatsin->substepy-0.5;
  pydown = (ydown-allflatsin->substarty)/allflatsin->substepy+0.5;
  /* check boundaries and truncate to integer appropriately */
  /* is the whole interval out of the boundaries? */
  if ((pyup <= -1) || (pydown >= (double)(allflatsin->subrows))) {
    /* the y loop must be skipped */
    *lvecbuf1=1;
    *lvecbuf2=0; 
    *fmvecbuf1=BADSLICE;
  }
  else {
    /* is the upper limit above the upper boundary? */
    if (pyup >= (double) (allflatsin->subrows-1)) {
      pyup = (double) (allflatsin->subrows-1);
      *lvecbuf2 = allflatsin->subrows-1;
    }
    /* truncate the upper limit to the smallest larger integer */
    else {
      *lvecbuf2 = (int32_t) ceil(pyup);
    }
    /* is the lower limit below the lower boundary? */
    if (pydown <= 0) {
      pydown = 0;
      *lvecbuf1 = 0;
    }
    else {
      *lvecbuf1 = (int32_t) floor(pydown);
    }
    fibrefrac = (pyup-pydown+1)*((double)(allflatsin->substepy))/
      (2*allflatsin->halfibrewidth);
    if (fibrefrac < allflatsin->minfibrefrac) {
      /* skip this fibre */
      *lvecbuf1 = 1;
      *lvecbuf2 = 0; 
      *fmvecbuf1=BADSLICE;
    }
  }
  return(NOERR);
}
