/* 
   
   Otmar Stahl, Anton Malina

   extract_profiles.c

   select spatial profiles with given fractional distance
   fit spatial profiles with polynomials (a la Horne)
   output all fit coefficients (fit_deg x width x norder) to table

.VERSION
 090728		last modif
*/

/* system includes */

#include <math.h>
#include <stdio.h>

/* general Midas includes */

#include <midas_def.h>

/* FEROS specific includes */

#include <nrutil.h>
#include <echelle.h>
#include <misc.h>

int extract_profiles
#ifdef __STDC__
(
 int straight, int xposfile, int dyfile,
 int nact, int nlines, int npts, int *npoints,
 float v0, float gain, float thres,
 int tid1, int icol[], int fit_deg
 )
#else
(
 straight, xposfile, dyfile,
 nact, nlines, npts, npoints,
 v0, gain, thres,
 tid1, icol, fit_deg)

     float v0, gain, thres;
     int straight, tid1, nact, fit_deg, nlines, npts, xposfile, dyfile;
     int icol[];
     int *npoints;
#endif

{
  float *xpos, *ypos1;
  float *mask, *profile, *variance, *outframe, *varframe, *sky, *raw;
  float *x, *z, *x_2, *z_2, *x_3, *z_3, *y;
  float **buffer1;
  double start[2], step[2];
  double **p_coeff;
  int actvals, i, j, jj, k, offset;
  int imno_var, imno_varf, imno_mask, imno_prof, imno_out;
  int niter, rawoffset;
  int npixo[2];
  int *number1;
  char line[80];


  /* allocate memory */

  number1 = ivector(1, data_per_pixel);
  raw = vector(0, npts * nlines);
  sky = vector(0, npts * nlines);
  x = vector(0, npts);
  x_2 = vector(0, npts);
  x_3 = vector(0, npts);
  y = vector(0, npts);
  z = vector(0, npts);
  z_2 = vector(0, npts);
  z_3 = vector(0, npts);
  xpos = vector(0, npts);
  ypos1 = vector(0, npts);
  buffer1 = matrix(1, data_per_pixel, 0, npts * nlines);
  p_coeff = dmatrix(1, data_per_pixel, 1, fit_deg * nlines);

  /* initialize variables */

  npixo[0] = npts; npixo[1] = nlines;
  start[0] = start[1] = step[0] = step[1] = 1.0;
  niter = 3;
  for (i = 0; i < npixo[0] * npixo[1]; i++)
    sky[i] = 0.0;

  /* create images */
  
  
  SCIPUT ("mask", D_R4_FORMAT, F_O_MODE, F_IMA_TYPE,
	  2, npixo, start, step, "test", "test", 
	  (char **) &mask, &imno_mask);
  SCIPUT ("profile", D_R4_FORMAT, F_O_MODE, F_IMA_TYPE,
	  2, npixo, start, step, "test", "test", 
	  (char **) &profile, &imno_prof);
  SCIPUT ("variance", D_R4_FORMAT, F_O_MODE, F_IMA_TYPE,
	  2, npixo, start, step, "test", "test",
	  (char **) &variance, &imno_var);
  SCIPUT ("outframe", D_R4_FORMAT, F_O_MODE, F_IMA_TYPE,
	  1, npixo, start, step, "test", "test", 
	  (char **) &outframe, &imno_out);
  SCIPUT ("varframe", D_R4_FORMAT, F_O_MODE, F_IMA_TYPE,
	  1, npixo, start, step, "test", "test", 
	  (char **) &varframe, &imno_varf);
  
  /* determine spatial profile */


      offset = -npts+1;
      
      for (i = 1; i <= nact; i++)                   /* for each order */
	
	{
	  
      /* read frame into mem at *raw */

      rawoffset = npts * nlines * (i - 1) + 1;
      
      SCFGET(straight, rawoffset, npts * nlines, &actvals, (char *) raw);

      for(k = 1; k <= data_per_pixel; k++)
	 number1[k] = 0;                              /* initialize  array */

      offset += npts;

          /* position in dispersion direction */
	  /* read xpos from file */

      SCFGET(xposfile, offset, npoints[i], &actvals, (char *) xpos);

	  /* read ypos1 from file */

      SCFGET(dyfile, offset, npoints[i], &actvals, (char *) ypos1);

      for(k = 0; k < npoints[i]; k++)              /* for each row */
	{

          /* deviation from pixel center */

	  /* ypos1 lies between -0.5 and +0.5 */

	  if (fabs(ypos1[k]) < 0.05)
	    {
	      for (jj = 0 ; jj < nlines; jj++)
		{
		  buffer1[2][jj * npts + number1[2]] = raw[jj * npts + k];
		}
	      x_2[number1[2]] = xpos[k];
	      number1[2]++;
	    }

	  /*(fabs(ypos1 - 0.33) < 0.05)*/

	  else if  (ypos1[k] > 0.28 && ypos1[k] < 0.38)
	    {
	      for (jj = 0 ; jj < nlines; jj++)
		{
		  buffer1[3][jj * npts + number1[3]] = raw[jj * npts + k];
		}
	      x_3[number1[3]] = xpos[k];
	      number1[3]++;
	    }

	  /*(fabs(ypos1 + 0.33) < 0.05)*/
	  
	  else if (ypos1[k] > -0.38 && ypos1[k] < -0.28)
	    {
	      for (jj = 0 ; jj < nlines; jj++)
		{
		  buffer1[1][jj * npts + number1[1]] = raw[jj * npts + k];
		}
	      x[number1[1]] = xpos[k];
	      number1[1]++;
	    }
	} /* end for k */
      
      sprintf(line, "compute profile %d of %d", i, nact);
      SCTPUT(line);

      /* calculate polynomial coefficients */

      spatial_profile(buffer1[1], sky, outframe,
		      varframe, mask, profile, variance,
		      x, y, z, nlines, npts,
		      number1[1], niter, fit_deg,
		      v0, gain, thres, p_coeff[1]);
      spatial_profile(buffer1[2], sky, outframe,
		      varframe, mask, profile, variance,
		      x_2, y, z_2, nlines, npts,
		      number1[2], niter, fit_deg,
		      v0, gain, thres, p_coeff[2]);
      spatial_profile(buffer1[3], sky, outframe,
		      varframe, mask, profile, variance,
		      x_3, y, z_3, nlines, npts,
		      number1[3], niter, fit_deg,
		      v0, gain, thres, p_coeff[3]);

      /* write coefficients to table */

      for(j = 1; j <= nlines; j++)
	{
	  TCRWRD (tid1, (i-1) * nlines + j, fit_deg, icol, 
		  &p_coeff[1][(j-1) * fit_deg + 1]);
	  TCRWRD (tid1, (i-1) * nlines + j, fit_deg, &icol[fit_deg], 
		  &p_coeff[2][(j-1) * fit_deg + 1]);
	  TCRWRD (tid1, (i-1) * nlines + j, fit_deg, &icol[2 * fit_deg], 
		  &p_coeff[3][(j-1) * fit_deg + 1]);
	}
    } /* end for i */

  /* release memory */

      
  free_ivector(number1, 1, data_per_pixel);
  free_vector(raw, 0, npts * nlines);
  free_vector(sky, 0, npts * nlines);
  free_vector(x, 0, npts);
  free_vector(x_2, 0, npts);
  free_vector(x_3, 0, npts);
  free_vector(y, 0, npts);
  free_vector(z, 0, npts);
  free_vector(z_2, 0, npts);
  free_vector(z_3, 0, npts);
  free_vector(xpos, 0, npts);
  free_vector(ypos1, 0, npts);

  free_matrix(buffer1, 1, data_per_pixel, 0, npts * nlines);
  free_dmatrix(p_coeff, 1, data_per_pixel, 1, fit_deg * nlines);

  SCFCLO (imno_mask);
  SCFCLO (imno_prof);
  SCFCLO (imno_var);
  SCFCLO (imno_out);
  SCFCLO (imno_varf);

  return 0;
}
