/*===========================================================================
  Copyright (C) 1995-2009 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 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence 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
===========================================================================*/

/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* .IDENT       necoffset.c                                */
/* .AUTHOR      Pascal Ballester (ESO/Garching)            */
/* .KEYWORDS    Spectroscopy, Echelle, Offset              */
/* .PURPOSE     Determines the slit offset of an exposure  */
/* .VERSION     1.0  Creation  16-MAR-1995                 */
/*                                                         */
/*  090723	last modif				   */
/*
   .INPUT/OUTPUT:
    IN_A         :  Image name 
    IN_B         :  Order table name
    INPUTC(11:10):  Coefficients descriptor generic name
    INPUTI/I/1/4 :  range, nb_positions, order nb min and max
    INPUTI/I/9/1 :  Seed for random number generator
    INPUTI(10)   :  Debug level (0,1)
---------------------------------------------------------- */

#include <math.h>
#include <stdlib.h>
#include <tbldef.h>
#include <midas_def.h>
#include <mutil.h> 

#define  ipos(col,row,siz)   row * siz + col  /* Pointer value */
#define  nint(f)             (int) (f + 0.5)  /* Nearest integer */

#ifndef RAND_MAX
#define RAND_MAX 32767
#endif

int  rand_nb();
double   position();

int main()
{
      char         frame[61], ordtab[61], coeff[11], descr[12];
      int          range, nb_positions, order_min, order_max, parami[4];
      int          dbx, nd, kmax, lmax;
      double       coeffd[100], x, y;
      int          coeffi[10];
      unsigned int seed;
      float        *pntra, p_mean;

      int          imnoa, naxis, npix[2], knul, kun;
      int          iav, actvals, tid;
      int          ncol, nrow, nsort, allcol, allrow;
      double       start[2], step[2];
      char         ident[TEXT_LEN+1], cunit[16*3+1];
      int          np, npts, sample, pos[2], x_pix, y_pix, p_max;
      int          offs, pixel, *list;
      double       incr, value;

      SCSPRO("offset");

      value = 0.0;
      p_max = 0;

      SCKGETC ("IN_A", 1, 60,  &actvals, frame);
      SCKGETC ("IN_B", 1, 60,  &actvals, ordtab);
      SCKGETC ("INPUTC",11, 10,&actvals, coeff);

      SCKRDI ("INPUTI", 1, 4, &actvals, parami,    &kun, &knul);
      range=parami[0], nb_positions=parami[1];
      order_min=parami[2], order_max=parami[3];
      SCKRDI ("INPUTI", 9, 2, &actvals, parami,    &kun, &knul);
      seed = 2*parami[0]+1, dbx = parami[1];
      srand(seed);

      /* Open Input image */
      strcpy(ident, " ");
      strcpy(cunit, " ");
      SCIGET (frame, D_R4_FORMAT, F_I_MODE, F_IMA_TYPE, 2,
              &naxis, npix, start, step, ident, cunit, (char **)&pntra,
              &imnoa);
      nrow  =  npix[1];
      ncol  =  npix[0];

      /* Read Coefficients from order table */
      TCTOPN (ordtab, F_IO_MODE, &tid);
      TCIGET (tid, &ncol, &nrow, &nsort, &allcol, &allrow);
      strcpy(descr,coeff);
      strcat(descr,"I");
      SCDRDI(tid, descr, 4, 4, &iav, coeffi, &kun, &knul);
      kmax = coeffi[2], lmax = coeffi[3];
      nd = (kmax+1)*(lmax+1);
      strcpy(descr,coeff);
      strcat(descr,"D");
      SCDRDD(tid, descr, 1, nd, &iav, coeffd, &kun, &knul); 

      np = (order_max - order_min +1)*npix[0]-1;
      npts = nb_positions;
      incr = (double)np/ (double)npts;
      list = (int *) osmmget((npts+1)*sizeof(int));

      p_mean = 0.;
      for (sample=1; sample<=npts; sample++) {

      /* Pick random column and order number */
      pick:
           pos[0] = rand_nb(order_min, order_max);
           pos[1] = rand_nb(1,npix[0]);
           x = start[0] + (pos[1]-1)*step[0];
           y = position(x,pos[0],kmax,lmax,coeffd);
           y_pix = (y-start[1])/step[1];
           x_pix = pos[1] - 1;
           if ((y_pix-range) < 0) goto pick;
           if ((y_pix+range) > (npix[1]-1)) goto pick;

      /* Determine offset of maximum signal */
           for (offs=(-range); offs<=range; offs++) {
                pixel = ipos(x_pix, (y_pix+offs), npix[0]);
                if (offs == (-range)) 
                    {value = pntra[pixel]; p_max=offs;}
                else if (pntra[pixel] > value) 
                    {value = pntra[pixel]; p_max=offs;}
           }

           list[sample] = p_max;
      }

      hsort(npts,list);

      pos[0] = nint(npts*0.375);
      pos[1] = nint(npts*0.625);
      p_mean = 0.;
      for (sample=pos[0]; sample<=pos[1]; sample++) p_mean += list[sample];
      p_mean /= (double) (pos[1]-pos[0]+1.);

      // printf("Found offset=%f\n",p_mean);
      SCKWRR("OUTPUTR", &p_mean,  1, 1, &kun);

      TCTCLO(tid);
      SCSEPI();
 return 0;
}

int rand_nb(min,max)
    int min,max;
{
    double frac;
    int    result;
    frac = (double)rand()/(double)(RAND_MAX);
    if (frac > 1.) frac -= (int) frac;
    frac *= (max-min);
    result = min + nint(frac);
    return(result);
}

double position(x,m, kmax, lmax, dpar)
  double x;
  int    m, kmax, lmax;
  double dpar[];
{
  int    l, ip = -1, k;
  double dc=1., ww[100], yval=0.;

  for (l=0; l<=lmax; l++) {
       ip += 1, ww[ip] = dc, yval += ww[ip]*dpar[ip];
       for (k=1; k<=kmax; k++) {
            ip += 1, ww[ip] = ww[ip-1]*x;
            yval += ww[ip]*dpar[ip];
	  }
       dc *= m;
     }
  return(yval);
}



