/* @(#)locatefillfibre     */
/*===========================================================================
  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  : locatefillfibre.c                                            */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  :                                                              */
/* find the beginning and the end in y of the portion of CCD illuminated   */
/* by a given fibre in a given grating order and at a given x              */
/*                                                                         */
/* Input:                                                       */
/*      allflatsin: a structure which contains the set of fibre FF frames  */
/*                  to be used and related scalars                         */
/*      ordpos:     a structure containing all the data needed for accurate */
/*                  order and fibre positioning on a frame                 */
/*      iorder:     the given order for the function (pixel coordinates)   */
/*      ifibre:     the given fibre for the function (pixel coordinates)   */
/*      ix:         the given x for the function (pixel coordinates)       */
/* Output:                                                       */
/*      allflatsin: the fibre boundaries are, if necessary, reset here     */
/*      shiftdata:  a structure containing the results of this function    */ 
/*                                                                         */
/*                                                                         */
/* 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_fillholes.h>


flames_err locatefillfibre(allflats *allflatsin, orderpos* ordpos, 
                           shiftstruct *shiftdata,
                           int32_t iorder,
                           int32_t ifibre,
                           int32_t ix)
{
    double fibrecentre=0;
    double yup=0;
    double ydown=0;
    double pyup=0;
    double pydown=0;

    int32_t iy=0;
    int32_t iyixindex=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;
    lvecbuf1 = allflatsin->lowfibrebounds[0][0]+iorderifibreixindex;
    lvecbuf2 = allflatsin->highfibrebounds[0][0]+iorderifibreixindex;
    fmvecbuf1 = allflatsin->goodfibres[0][0]+iorderifibreixindex;

    /* mark the fibre as good and normalisable, unless otherwise set hereafter */
    *fmvecbuf1 = GOODSLICE;
    /* find the y central position of this fibre at this x */
    fibrecentre = (shiftdata[ix]).ordercentre+(ordpos->fibrepos)[ifibre];
    /* 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 >= 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;
            /* this slice is not normalisable, mark it bad */
            *fmvecbuf1 = BADSLICE;
        }
        /* 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;
            /* this slice is not normalisable, mark it bad */
            *fmvecbuf1 = BADSLICE;
        }
        else {
            *lvecbuf1 = (int32_t) floor(pydown);
        }
        double fibrefrac = (pyup-pydown+1)*(allflatsin->substepy)/
                        (2*allflatsin->halfibrewidth);
        if (fibrefrac < allflatsin->minfibrefrac) {
            /* skip this fibre */
            *lvecbuf1 = 1;
            *lvecbuf2 = 0;
            /* this slice is not normalisable, mark it bad */
            *fmvecbuf1 = BADSLICE;
        }
        if (*fmvecbuf1==BADSLICE) {
            int iframe = allflatsin->fibre2frame[ifibre];
            frame_mask* fmvecbuf2 = allflatsin->flatdata[iframe].badpixel[0];
            for (iy=*lvecbuf1; iy<=*lvecbuf2; iy++) {
                iyixindex = (iy*allflatsin->subcols)+ix;
                fmvecbuf2[iyixindex] = 1;
            }
        }
    }
    return(NOERR);
}


