/* $Id: flames_get_flat_size.c,v 1.21 2013-07-25 13:06:44 amodigli Exp $ */

/*===========================================================================
  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_get_flat_size Get size of flat part of FF and offset of its center with respect to order trace
 *
 */
/*-------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
  Includes
  --------------------------------------------------------------------------*/



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

/* include standard definitions */
#include <flames_get_flat_size.h>      
#include <flames_midas_def.h>      
#include <flames_def_drs_par.h>      
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#include <flames_uves.h>
#include <flames_newmatrix.h>
#define MY_FEPSILON 1e-6   /*1e-6*/
#define FILE_LEN 80                          /* max length of in files */
#define MESS_LEN 80                          /* max length of messages */
#define KEYW_LEN 80                          /* max length of keywords */
#define LABEL_LEN 20                         /* max length of a label  */
//#define BUF_SIZE 12                          /* max size of ima buffer */
#define MAX_STRING_SZ 200                     /* min machine precision */


const char prgName[FILE_LEN] = "flames_get_flat_size";   /* program name */


void
clip_hw_small(double* val,
	      int* mask,
	      int min,
	      int max,
	      int DRS_SFF_HW_MIN);

void
update_delta(double* val,
             float  med,
             int    min,
             int    max,
             double* del);

void  
update_mask(double* del,
            float rms,
            int*   mask,
            int   min,
            int   max);

float 
get_y_min(int     xcPix, 
          int     ycTracePix,
          double   int_min,
          float** mInImaF,
          int LOC_SAV_BORD_SZ);

float 
get_y_max(int     xcPix, 
          int     ycTracePix,
          double   int_min,
          float** mInImaF,
          int     LOC_SAV_BORD_SZ);

void
find_mid_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double   int_min,
                   float** mInImaF,
                   double*  yMin,
                   double*  yMax,
		   int LOC_SAV_BORD_SZ);
void  
find_low_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double   int_min,
                   float** mInImaF,
                   double*  yMin,
                   double*  yMax,
                   int LOC_SAV_BORD_SZ);
void 
find_upp_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double  int_min,
                   float** mInImaF,
                   float*  yMin,
                   float*  yMax,
		   int LOC_SAV_BORD_SZ);
float 
get_avg(double* val,
        int*   mask,
        int    min,
        int    max);
float 
get_med(double* val,
        int*   mask,
        int    min,
        int    max);
  
int 
ima_comp(const void*, const void*);
float **
map2mat(void);              /* map a matrix on a float vector */

void 
clip_hw_new(double* val, int* mask, int* min, int* max);

/**@{*/

/*---------------------------------------------------------------------------
  Implementation
  ---------------------------------------------------------------------------*/
/**
   @name  flames_get_flat_size()  
   @short Get size of flat part of FF and offset of its center with respect to order trace
   @author G. Mulas  -  ITAL_FLAMES Consortium. Ported to CPL by A. Modigliani

   @param IN_A
   @param IN_B
   @param SLIT
   @param ORD_MIN
   @param ORD_MAX
   @param DEFPOL
   @param SAV_BORD_SZ
   @param DRS_SFF_HW_MIN
   @param X_WIND_SIZE
   @param Y_WIND_SIZE
   @param Y_SEARCH_WIND
   @param ORD_TRESH
   @param N_CLIP_MED
   @param N_CLIP_AVG
   @param INT_TRESH

   @return success or failure code

   DRS Functions called:          
   none                                         
                                                                         
   Pseudocode:                                                             

   Finds at central X Xc for central order Mc, Ymin and Ymax 
   such that I[(Ymin(Xc,Mc)]=I[(Ymax(Xc,Mc)]=0.8*I[Yt(Xc,Mc)] were
   Yt(Xc,Mc) is the position of the central trace.
   Ymin, and Ymax are determined with a linear interpolation.
   HALFSIZE=[(Ymax-Yo)-(Ymin-Yo)]/2 were Yo=3pix
   YSHIFT=Yt-Yc(Xc,Mc), with Yc the position of the FF center.

   @note
*/

int 
flames_get_flat_size(
		     const char *IN_A,
		     const char *IN_B,
		     const float *SLIT,
		     const int *ORD_MIN,
		     const int *ORD_MAX,
		     const int *DEFPOL,
		     const  int SAV_BORD_SZ,
		     const  int DRS_SFF_HW_MIN,
		     const  int X_WIND_SIZE,
		     const  int Y_WIND_SIZE,
		     const  int Y_SEARCH_WIND,
		     const  int ORD_TRESH,
		     const  int N_CLIP_MED,
		     const  int N_CLIP_AVG,
		     const  float INT_TRESH)

{
  char* bufData;
  char inIma[FILE_LEN];               /* input File */
  char inTable[FILE_LEN];             /* input Table */
  const int max_pol_ordXY=200;        /* max polynomial order: orderX * orderY */

  //  int  messLevel = 0;                 /* message level */

  int  nPix[2];                       /* tmp variable for pixel data */
  int  nVal = 0;                      /* max no of returned chars */

  int  stat = 0;                      /* status */

  int  inImaId = 0;                   /* Id of input ima frame */
  int  inTabId = 0;                   /* Id of in ima frame */

  int  nCol = 0;                      /* No of columns */
  int  nRow = 0;                      /* No of rows */

  int  unit = 0;                      /* address of unit pointer */
  int  null = 0;                      /* No of null values in data */

  
  int  imaSizeX = 0;                  /* size of ima along X in pix */
  int  imaSizeY = 0;                  /* size of ima along Y in pix */
  int  imaSizeT = 0;                  /* total ima size */
  int  n_pos_y_shift = 0;             /* No of pos y shift */
  int  n_neg_y_shift = 0;             /* No of neg y shift */
  int  success=0;

  float *pInImaF;                     /* image frame */
  float **mInImaF;                    /* matrix represent. */
   

  double dbl_aux=0;                   /* aux double variable */
  double ycTrace =0;                  /* position given from order trace */
  float inSlit=0;                     /* input slit size */
  double coeffd[max_pol_ordXY];                  /* coeffd descriptor */
  int nCoeffd = max_pol_ordXY;                   /* No of coeffd */
  int ordMin=0;                       /* ord min */
  int ordMax=0;                       /* ord max */
  int defPol[2];                      /* bivariate polinomial degree */
  int xcPix = 0;                      /* central pixel */
  int cOrd = 0;                       /* central order */
  int index =0;                       /* auxilliary variable */
  int slitPix=0;                      /* slit dimension in pixel */
  float refInt=0;                     /* Image reference pos in pixel */ 

  double yMin=0;                       /* aux var for min Y limit of flat FF */
  double yMax=0;                       /* aux var for max Y limit of flat FF */
  double y_low_min =0;
  double y_low_max =0;
  float y_upp_min =0;
  float y_upp_max =0;

  int ycTracePix=0;                   /* central Y pos of trace Yc(Xc,Mc) */
  double tmp=0;                       /* tmp variable */
  double int_max=0;                    /* tmp var used as upper thresh on I */
  double int_min=0;                    /* tmp var used as lower thresh on I */
  double tmpFct=0;                     /* tmp variable */
  double ycSlitPix=0;                  /* size of slit in pix at (Xc,Mc) */
  double disTraceYmin=0;               /* Y distance order trace-Ymin */
  double disTraceYmax=0;               /* Y distance order trace-Ymax */
  double yShift=0;                     /* shift of order trace respect to Yc */
  double halfWidth=0;                  /* half width of flat FF in pix */
  int SF = 0;                         /* alias for short float */
  int i  = 0;                         /* loop index */
  int j  = 0;                         /* loop index */
  int ord = 0; 
 
  int k=0;
  int m =0;

  float *frame_buf;
  float *i_median;
  double *sto_y_shift;
  double *sto_half_width;
  double *buf_pos_y_shift;
  double *buf_neg_y_shift;
  double *sto_pos_y_shift;
  double *sto_neg_y_shift;


  double *del_y_shift;
  double *del_pos_y_shift;
  double *del_neg_y_shift;

  double *del_half_width;
  double *buf_y_shift;
  double *buf_half_width;
  int   *sto_mask;
  int   *pos_mask;
  int   *neg_mask;

  float med_y_shift =0.;
  float med_half_width =0.;
  float avg_y_shift =0.;
  float avg_half_width =0.;
  float rms_y_shift =0.;
  float rms_half_width =0.;



  float med_pos_y_shift =0.;
  float avg_pos_y_shift =0.;
  float rms_pos_y_shift =0.;


  float med_neg_y_shift =0.;
  float avg_neg_y_shift =0.;
  float rms_neg_y_shift =0.;


  int i_bound_min = 0;
  int i_bound_max = 0;

  int j_bound_min = 0;
  int j_bound_max = 0;
  int nk = 0;
  int no = 0;
  float i_max = 0;
  int ord_min =0;
  int ord_max=0;
  int i_clip=0;
  char output[MAX_STRING_SZ];

  int actvals=0;
  char drs_verbosity[10];
  int status=0;
  int LOC_SAV_BORD_SZ=3;
 

  SCSPRO(prgName);                    /* assign program name */

  //jmlarsen: not used:
  //SCKRDI(MESS_LEVEL,1,1,&nVal,&messLevel,&unit,&null); /* read keyword */
 
  memset(drs_verbosity, 0, 10);
  if ((status=SCKGETC(DRS_VERBOSITY, 1, 3, &actvals, drs_verbosity))
      != 0) {
    /* the keyword seems undefined, protest... */
    return(MAREMMA);
  }


  stat = SCKGETC(IN_A, 1,FILE_LEN,&nVal,inIma);   /* get input frame */
  stat = SCKGETC(IN_B, 1,FILE_LEN,&nVal,inTable); /* get input table */
  stat = SCKRDR(SLIT, 1,1,&nVal,&inSlit, &unit,&null); /* get slit value */
  stat = SCKRDI(ORD_MIN, 1,1,&nVal,&ordMin,&unit,&null); /* get ord min */
  stat = SCKRDI(ORD_MAX, 1,1,&nVal,&ordMax,&unit,&null); /* get ord max */
  stat = SCKRDI(DEFPOL, 1,2,&nVal,defPol,&unit,&null); /* get ord max */
  slitPix = (int) rint(inSlit);

  /*
    printf("Sav Bord Siz=%i\n",SAV_BORD_SZ);
    printf("X_WIND_SIZE=%i\n",X_WIND_SIZE);
    printf("Y_WIND_SIZE=%i\n",Y_WIND_SIZE);
    printf("Y_SEARCH_WIND=%i\n",Y_SEARCH_WIND);
    printf("ORD_TRESH=%i\n",ORD_TRESH);
    printf("N_CLIP_MED=%i\n",N_CLIP_MED);
    printf("INT_TRESH=%f\n",INT_TRESH);
  */

  printf("polx=%i,poly=%i\n",defPol[0],defPol[1]);

  nCoeffd = (defPol[0]+1)*(defPol[1]+1);
  if (nCoeffd>max_pol_ordXY) {
      return(MAREMMA);
  }
  //jmlarsen:
  //         there is no reason to open this table first with SCFOPN, then with TCTOPN.
  //         to avoid having to implement F_TBL_TYPE support in SCFOPN, just open
  //         the table with TCTOPN

  //before:  SCFOPN(inTable,D_R4_FORMAT,0,F_TBL_TYPE,&inTabId);   /* open input frame */
  //now:
  TCTOPN(inTable,F_I_MODE,&inTabId);
  SCDRDD(inTabId,"COEFFD",1,nCoeffd,&nVal,coeffd,&unit,&null); /* get COEFFD  */

  /*
    for(i=0;i<nCoeffd;i++){

    printf("coeff[%i]=%g\t",i,coeffd[i]);
    }
  */


  SCFOPN(inIma,D_R4_FORMAT,0,F_IMA_TYPE,&inImaId);   /* open input frame */
  SCDRDI(inImaId,"NPIX",1,2,&nVal,nPix,&unit,&null); /* get NPIX descript. */

  imaSizeX = nPix[0];
  imaSizeY = nPix[1];
  imaSizeT = imaSizeX*imaSizeY;

  dbl_aux = (double)(1+nPix[0])/2;
  xcPix = (int) rint(dbl_aux);

  dbl_aux = (double)(ordMin+ordMax)/2;
  cOrd = (int) rint(dbl_aux);

  /*
    printf("central Pixel:%i\n", xcPix);
    printf("central Order:%i\n", cOrd);
  */

  SF = (int) sizeof(float);

  /* do the mapping */

  pInImaF = (float*) malloc((size_t) imaSizeT*SF);
  if (pInImaF == NULL) SCTPUT("No memory for pInImaF");
  bufData = (char*) pInImaF;
  SCFGET(inImaId,1,imaSizeT,&nVal,bufData);    /* read the whole frame */

  /* map data for matrix access */
  /*   mInImaF = map2mat(pInImaF,imaSizeX,imaSizeY,1,1); */

  mInImaF = convert_matrix(pInImaF,1, (int32_t) imaSizeY, 1, (int32_t) imaSizeX);

  /* SCFMAP(inImaId,F_I_MODE,1,imaSizeT,&nVal,&mInImaF); */
  /* get input table data */

  //jmlarsen: this tale was already opened. Do not open again
  //  TCTOPN(inTable,F_I_MODE,&inTabId);
  TCIGET(inTabId, &nCol, &nRow);



  /* Prepare vectors to hold tmp results */
  buf_y_shift     = dvector(0,(ordMax-ordMin)); 
  buf_pos_y_shift = dvector(0,(ordMax-ordMin)); 
  buf_neg_y_shift = dvector(0,(ordMax-ordMin)); 

  del_y_shift     = dvector(0,(ordMax-ordMin)); 
  del_pos_y_shift = dvector(0,(ordMax-ordMin)); 
  del_neg_y_shift = dvector(0,(ordMax-ordMin)); 


  sto_y_shift     = dvector(0,(ordMax-ordMin)); 
  sto_pos_y_shift = dvector(0,(ordMax-ordMin)); 
  sto_neg_y_shift = dvector(0,(ordMax-ordMin)); 

  buf_half_width  = dvector(0,(ordMax-ordMin));
  del_half_width  = dvector(0,(ordMax-ordMin));
  sto_half_width  = dvector(0,(ordMax-ordMin)); 

  sto_mask        = ivector(0,(ordMax-ordMin));
  pos_mask        = ivector(0,(ordMax-ordMin));
  neg_mask        = ivector(0,(ordMax-ordMin));

   
  ord_min=(int)(ordMin+ORD_TRESH);
  ord_max=(int)(ordMax-ORD_TRESH);

  /*
    printf("ordmin=%d,ordmax=%d\n",ord_min,ord_max);
  */

  /* loop over orders (cutting ORD_TRESH) orders upp and down */
  for (ord=ord_min;ord<ord_max; ord++){
    cOrd=ord;
    /* printf("current Order:%i\n", cOrd); */


    /* get Y position of trace at central X pix */
    ycTrace=0;
    index=0;
    for(j=0;j<=defPol[1];j++){
      tmpFct = pow(cOrd,j);
      /* printf("\nj=%i,tmpFct=%g\t",j,tmpFct); */ 
      for(i=0;i<=defPol[0];i++){
	/* printf("i=%i, %g\t",i,coeffd[index]); */
           
	ycTrace += coeffd[index]*pow(xcPix,i)*tmpFct;
	++index;
      }
    }

    /*
      printf("%f\n",ycTrace); 
    */
    tmp =  rint(ycTrace);
    ycTracePix = (int) tmp;

    /*
      printf("ycTracePix=%i\n",ycTracePix);
      printf("ycTrace=%f\n",ycTrace); 
      printf("tmp=%f\n",tmp); 
    */
    refInt = mInImaF[ycTracePix][xcPix];
 

    /*
       
    printf("Reference Intensity %f\n",refInt); 
      
    */
    /* 
       =====================================================
       Here we take the median of the intensity values as 
       better intensity reference value for the flat FF
       =====================================================
    */


    i_bound_min=xcPix-X_WIND_SIZE;
    i_bound_max=xcPix+X_WIND_SIZE;

    i_median = vector(0,2*Y_SEARCH_WIND);
    frame_buf = vector(0,imaSizeY*3-1);

    if (i_bound_min < 0)        i_bound_min = 0;
    if (i_bound_max > imaSizeX) i_bound_max = imaSizeX;
    i_max = 0;


    /*
      printf("ycTrace=%f,Y_SEARCH_WIND=%i\n",ycTrace,Y_SEARCH_WIND);
    */


    for(m=ycTracePix-Y_SEARCH_WIND;m<=ycTracePix+Y_SEARCH_WIND; m++)
      {
	j_bound_min = m-Y_WIND_SIZE;
	j_bound_max = m+Y_WIND_SIZE;

	if (j_bound_min < 0)        j_bound_min = 0;
	if (j_bound_max > imaSizeY) j_bound_max = imaSizeY;


	k=0;
	for(j=j_bound_min;j<=j_bound_max; j++)
	  {
	    for(i=i_bound_min ;i<=i_bound_max; i++)
	      {
		frame_buf[k]=mInImaF[j][i];
		k++;
	      }
	  }
    
	nk=k;
	nk/=2;
	if(nk > imaSizeY*3) printf("Something strage ocxcurred\n");

	qsort(frame_buf, (size_t) nk, sizeof(float), ima_comp);
	i_median[m-ycTracePix+Y_SEARCH_WIND]=frame_buf[nk];

	/* Loop moved outside */
	/*
          if (i_median[m] > i_max) {
	  i_max = i_median[m];
	  }
	*/
      }

       
    for(m=0;m<=2*Y_SEARCH_WIND; m++)
      {
	if (i_median[m] > i_max) {
	  i_max = i_median[m];
	  /* printf("Max Int=%f m=%i\n",i_max,m); */

	}
      }
       
    if (i_max <= 0) {
      SCTPUT("Max Intensity <= 0! Something should be wrong we exit!");
      return 0;
    }

    /* 
       printf("Max Int=%f \n",i_max);
       printf("Discrepancy (Max-Ref)/Max=%f\n",(i_max-refInt)/i_max);
    */

    /* 
       =====================================================
       Now we search for FF borders
       =====================================================

    */

    /*
      printf("ycTrace=%f\n",ycTrace); 
      printf("ycTracePix=%i\n",ycTracePix); 
    */
    /*  
	This was the original setting 
	int_max=(1.0+INT_TRESH)*refInt;
	int_min=(1.0-INT_TRESH)*refInt;

    */
    /*
      printf("i_max=%f cut%f\n",i_max, INT_TRESH);
    */
       
    int_max=(1.0+INT_TRESH)*i_max;
    int_min=(1.0-INT_TRESH)*i_max;

    /*
      printf("int_min=%f\n",int_min);
      printf("int_max=%f\n",int_max);
      printf("xcPix=%i\n",xcPix);

      printf("Int Ima=%f\n",mInImaF[ycTracePix][xcPix]);
    */

    if (mInImaF[ycTracePix][xcPix] >= int_min){
      /* we are near the max of the FF */
      /* printf("Inside the flat part of FF\n"); */

      /*
	yMin = get_y_min(xcPix,ycTracePix,int_min,mInImaF,LOC_SAV_BORD_SZ);
	yMax = get_y_max(xcPix,ycTracePix,int_min,mInImaF,LOC_SAV_BORD_SZ);

      */

      /* printf("Before\n"); */
      find_mid_y_min_max(xcPix,
			 ycTracePix,
			 int_min,
			 mInImaF,
			 &yMin,
			 &yMax,
			 LOC_SAV_BORD_SZ);
      /*
	printf("After\n");
      */
    }
    else{
      /* we are in the interorder region */
      /* printf("near the border\n"); */

      /*

      printf("xcPix=%i, ycTracePix=%i, int_min=%f \n",
      xcPix,    ycTracePix,    int_min);
      */


      /*AM: here a critical point of robustness */
      find_low_y_min_max(xcPix,
			 ycTracePix,
			 int_min,
			 mInImaF,
			 &y_low_min,
			 &y_low_max,
			 LOC_SAV_BORD_SZ);


      find_upp_y_min_max(xcPix,
			 ycTracePix,
			 int_min,
			 mInImaF,
			 &y_upp_min,
			 &y_upp_max,
			 LOC_SAV_BORD_SZ);

      /*
      
      printf("ycTrace=%f\n",ycTrace);
      printf("y_low_min=%f\n",y_low_min);
      printf("y_low_max=%f\n",y_low_max);

      printf("y_upp_min=%f\n",y_upp_min);
      printf("y_upp_max=%f\n",y_upp_max);
      */

      if( (ycTrace-y_low_max) <= (y_upp_min-ycTrace) ){
	/* The distance of the trace from the FF upper border 
	   below the Trace is less than the distance of the trace
	   from the FF lower border */

	yMin = y_low_min;
	yMax = y_low_max;
	/* printf("lower\n"); */
      }
      else{
	yMin = y_upp_min;
	yMax = y_upp_max;
	/* printf("upper\n"); */

      }

    }

    /*
      printf("yMin=%f\n",yMin);
      printf("yMax=%f\n",yMax);
    */
    ycSlitPix=(yMin+yMax)/2.;
    disTraceYmin=(ycTrace-yMin);
    disTraceYmax=(yMax-ycTrace);
    yShift=-(ycTrace-ycSlitPix);
    halfWidth=(yMax-yMin)/2.;

    sto_y_shift[ord]=yShift;
    sto_half_width[ord]=halfWidth;
    sto_mask[ord]=1;

    free_vector(frame_buf,0,imaSizeY*3-1);
    free_vector(i_median,0,2*Y_SEARCH_WIND);


  
/*
	printf("ycSlitPix=%f,disTraceYmin=%f,disTraceYmax=%f\n",
	ycSlitPix,   disTraceYmin,   disTraceYmax);
   


	printf("ord=%i, ycSlitPix=%f yShift=%f halfWidth=%f\n",
	ord,    ycSlitPix,   yShift,   halfWidth);
  
  */
   

  } /* end of loop over ord */


  free_convert_matrix(mInImaF,1,(int32_t) imaSizeY,1,(int32_t) imaSizeX);

  /*
    ====================================================
    Now we divide positive from negative Yshifts
    ====================================================
  */

  for (ord = ord_min; ord < ord_max; ord++){

    if (sto_y_shift[ord] >= 0.) {
      sto_pos_y_shift[ord] = sto_y_shift[ord];
      pos_mask[ord] = 1;
      neg_mask[ord] = 0;
      n_pos_y_shift++;
    }
    else {
      sto_neg_y_shift[ord] = sto_y_shift[ord];
      neg_mask[ord] = 1;
      pos_mask[ord] = 0;
      n_neg_y_shift++;
    }

  }


  /*
    ====================================================
    Now we do a k-s clipping
    ====================================================
  */
  /* printf("Now we do a k-s clipping\n"); */
  clip_hw_small(sto_half_width,
		sto_mask,
		ord_min,
		ord_max,
		DRS_SFF_HW_MIN);

  update_mask(del_half_width,
	      rms_half_width,
	      sto_mask,
	      ord_min,
	      ord_max);


  /*
    ====================================================
    we 1st calculate starting points for med,rms,delta
    ====================================================
  */
  /* printf("we 1st calculate starting points for med,rms,delta\n"); */
    

  avg_pos_y_shift = get_avg(sto_pos_y_shift,
			    pos_mask,
			    ord_min,
			    ord_max);


  avg_neg_y_shift = get_avg(sto_neg_y_shift,
			    neg_mask,
			    ord_min,
			    ord_max);

 
  avg_y_shift = get_avg(sto_y_shift,
			sto_mask,
			ord_min,
			ord_max);

  avg_half_width = get_avg(sto_half_width,
			   sto_mask,
			   ord_min,
			   ord_max);



/*
       printf("Average yshift=%f\n",avg_y_shift);
       printf("Average pos yshift=%f\n",avg_pos_y_shift);
       printf("Average neg yshift=%f\n",avg_neg_y_shift);
       printf("Average halfWidth=%f\n",avg_half_width);
    
       printf("ord_min=%d\n",ord_min);
       printf("ord_max=%d\n",ord_max);

*/

  /* 
   * ----------------------------------------------------------- 
   * Standard data
   * -----------------------------------------------------------
   */

  /* printf("Standard data\n"); */

  no=0;
  for(ord=ord_min;ord<ord_max; ord++){
    del_y_shift[ord]=fabs(sto_y_shift[ord]-avg_y_shift);
    del_half_width[ord]=fabs(sto_half_width[ord]-avg_half_width);
    buf_y_shift[no] = sto_y_shift[ord];
    buf_half_width[no] = sto_half_width[ord];
    no++;
  }
  no/=2.;
  rms_y_shift = get_avg(del_y_shift,
			sto_mask,
			ord_min,
			ord_max);

  rms_half_width = get_avg(del_half_width,
			   sto_mask,
			   ord_min,
			   ord_max);


/*
    printf("RMS yshift=%f\n",rms_y_shift);
    printf("RMS halfWidth=%f\n",rms_half_width);
*/

  if(no > imaSizeY*3) printf("Something strage ocxcurred\n");

  qsort(buf_y_shift, (size_t) no, sizeof(float), ima_comp);
  med_y_shift=(float)buf_y_shift[no];
  qsort(buf_half_width, (size_t) no, sizeof(float), ima_comp);
  med_half_width=(float)buf_half_width[no];

  /*
    printf("no=%d\n",no);
    printf("buf=%f\n",buf_y_shift[no]);
    printf("buf=%f\n",buf_half_width[no]);
    printf("Median yshift=%f\n",med_y_shift);
    printf("Median halfWidth=%f\n",med_half_width);
  */ 


  /* 
   * ----------------------------------------------------------- 
   * Positive data
   * -----------------------------------------------------------
   */

  /* printf("Positive data\n"); */

  no=0;
  for(ord=ord_min;ord<ord_max; ord++){
    del_pos_y_shift[ord]= fabs(sto_pos_y_shift[ord]-avg_pos_y_shift);
    buf_pos_y_shift[no] = sto_pos_y_shift[ord];
    no++;
  }
  no/=2.;
  rms_pos_y_shift = get_avg(del_pos_y_shift,
			    pos_mask,
			    ord_min,
			    ord_max);

  if(no > imaSizeY*3) printf("Something strage ocxcurred\n");

  qsort(buf_pos_y_shift, (size_t) no, sizeof(float), ima_comp);
  med_pos_y_shift=(float)buf_pos_y_shift[no];


  /* 
   * ----------------------------------------------------------- 
   * Negative data
   * -----------------------------------------------------------
   */

  /* printf("Negative data\n"); */

  no=0;
  for(ord=ord_min;ord<ord_max; ord++){
    del_neg_y_shift[ord]= fabs(sto_neg_y_shift[ord]-avg_neg_y_shift);
    buf_neg_y_shift[no] = sto_neg_y_shift[ord];
    no++;
  }
  no/=2.;
  rms_neg_y_shift = get_avg(del_neg_y_shift,
			    neg_mask,
			    ord_min,
			    ord_max);

  if(no > imaSizeY*3) printf("Something strage ocxcurred\n");

  qsort(buf_neg_y_shift, (size_t) no, sizeof(float), ima_comp);
  med_neg_y_shift=(float)buf_neg_y_shift[no];



  /*
    for (ord=ord_max;ord<ord_min; ord++){
    if ( (del_half_width[ord] > rms_half_width) ||
    (del_y_shift[ord]    > rms_y_shift)    ) {
    sto_mask[ord]=0;
    }
    }


    printf("min=%i\n",ord_min);
    printf("max=%i\n",ord_max);
    printf("med=%f\n",avg_y_shift);

  */


  /*
    ====================================================
    Next we start the k-s clipping
    ====================================================
  */

  for(i_clip=0;i_clip<N_CLIP_MED;i_clip++){

    
    /* printf (">>>>>>Median Clipping iter %i<<<<<<\n",i_clip); */
     

    clip_hw_new(sto_half_width,
		sto_mask,
		&ord_min,
		&ord_max);



    /* y shift */

    update_delta(sto_y_shift,
		 med_y_shift,
		 ord_min,
		 ord_max,
		 del_y_shift);


    update_delta(sto_pos_y_shift,
		 med_pos_y_shift,
		 ord_min,
		 ord_max,
		 del_pos_y_shift);


    update_delta(sto_neg_y_shift,
		 med_neg_y_shift,
		 ord_min,
		 ord_max,
		 del_neg_y_shift);


    /* half width */


    update_delta(sto_half_width,
		 med_half_width,
		 ord_min,
		 ord_max, 
		 del_half_width);

    /* mask */


    update_mask(del_half_width,
		rms_half_width,
		sto_mask,
		ord_min,
		ord_max);


    update_mask(del_y_shift,
		rms_y_shift,
		sto_mask,
		ord_min,
		ord_max);

    update_mask(del_pos_y_shift,
		rms_pos_y_shift,
		pos_mask,
		ord_min,
		ord_max);

    update_mask(del_neg_y_shift,
		rms_neg_y_shift,
		neg_mask,
		ord_min,
		ord_max);





    if (rms_half_width > 5 ) {
      /* printf("RMS HW=%f\n",rms_half_width); */
      rms_half_width=5;
    }
    else {
      /* printf("RMS HW=%f\n",rms_half_width); */
    }


    if (rms_y_shift > 5) {
      /* printf("RMS Y=%f\n",rms_y_shift); */
      rms_y_shift=5;
    }
    else {
      /* printf("RMS Y=%f\n",rms_y_shift); */
    }


    update_mask(del_half_width,
		rms_half_width,
		sto_mask,
		ord_min,
		ord_max);


    update_mask(del_y_shift,
		rms_y_shift,
		sto_mask,
		ord_min,
		ord_max);



    update_mask(del_pos_y_shift,
		rms_pos_y_shift,
		pos_mask,
		ord_min,
		ord_max);

    update_mask(del_neg_y_shift,
		rms_neg_y_shift,
		neg_mask,
		ord_min,
		ord_max);


    med_y_shift = get_med(sto_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);


    med_pos_y_shift = get_med(sto_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);


    med_neg_y_shift = get_med(sto_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);

   
    med_half_width = get_med(sto_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);

    /*
      printf("Median yshift=%f\n",med_y_shift);
      printf("Median halfWidth=%f\n",med_half_width);
    */



    rms_y_shift = get_avg(del_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);


    rms_pos_y_shift = get_avg(del_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);
 
    rms_neg_y_shift = get_avg(del_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);

    rms_half_width = get_avg(del_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);


    /*
      printf("RMS yshift=%f\n",rms_y_shift);
      printf("RMS halfWidth=%f\n",rms_half_width);
    */

    avg_y_shift = get_avg(sto_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);


    avg_pos_y_shift = get_avg(sto_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);

    avg_neg_y_shift = get_avg(sto_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);

    avg_half_width = get_avg(sto_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);

    /*
      printf("Average yshift=%f\n",avg_y_shift);
      printf("Average halfWidth=%f\n",avg_half_width);
    */



  }





  for(i_clip=0;i_clip<N_CLIP_AVG;i_clip++){
     
    /*     printf (">>>>>>>Average Clipping iter %i<<<<<<<\n",i_clip); */
     
    clip_hw_new(sto_half_width,
		sto_mask,
		&ord_min,
		&ord_max);


    update_delta(sto_y_shift,
		 avg_y_shift,
		 ord_min,
		 ord_max,
		 del_y_shift);



    update_delta(sto_pos_y_shift,
		 avg_pos_y_shift,
		 ord_min,
		 ord_max,
		 del_pos_y_shift);


    update_delta(sto_neg_y_shift,
		 avg_neg_y_shift,
		 ord_min,
		 ord_max,
		 del_neg_y_shift);



    update_delta(sto_half_width,
		 avg_half_width,
		 ord_min,
		 ord_max, 
		 del_half_width);


    update_mask(del_half_width,
		rms_half_width,
		sto_mask,
		ord_min,
		ord_max);


    update_mask(del_y_shift,
		rms_y_shift,
		sto_mask,
		ord_min,
		ord_max);

    update_mask(del_pos_y_shift,
		rms_pos_y_shift,
		pos_mask,
		ord_min,
		ord_max);

    update_mask(del_neg_y_shift,
		rms_neg_y_shift,
		neg_mask,
		ord_min,
		ord_max);

    avg_y_shift = get_avg(sto_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);


    avg_pos_y_shift = get_avg(sto_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);

    avg_neg_y_shift = get_avg(sto_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);


    avg_half_width = get_avg(sto_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);
     

    rms_y_shift = get_avg(del_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);


    rms_pos_y_shift = get_avg(del_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);

    rms_neg_y_shift = get_avg(del_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);



    rms_half_width = get_avg(del_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);



    /*      
	    printf("RMS yshift=%f\n",rms_y_shift);
	    printf("RMS halfWidth=%f\n",rms_half_width);
    */

    med_y_shift = get_med(sto_y_shift,
			  sto_mask,
			  ord_min,
			  ord_max);



    med_pos_y_shift = get_med(sto_pos_y_shift,
			      pos_mask,
			      ord_min,
			      ord_max);

    med_neg_y_shift = get_med(sto_neg_y_shift,
			      neg_mask,
			      ord_min,
			      ord_max);


    med_half_width = get_med(sto_half_width,
			     sto_mask,
			     ord_min,
			     ord_max);

     
    /*
      printf("Median yshift=%f\n",med_y_shift);
      printf("Median halfWidth=%f\n",med_half_width);
    */

  }
  if ( strcmp(drs_verbosity,"LOW") == 0 ) {
  } else {
     
    success=snprintf(output,MAX_STRING_SZ,"Median yshift=%f\n",med_y_shift);
    SCTPUT(output);
    success=snprintf(output,MAX_STRING_SZ,"Median halfWidth=%f\n",med_half_width);
    SCTPUT(output);

    success=snprintf(output,MAX_STRING_SZ,"Median yshift=%f\n",med_y_shift);
    SCTPUT(output);
    success=snprintf(output,MAX_STRING_SZ,"Median halfWidth=%f\n",med_half_width);
    SCTPUT(output);

    success=snprintf(output,MAX_STRING_SZ,"Median Positive yshift=%f\n",med_pos_y_shift);
    SCTPUT(output);

    success=snprintf(output,MAX_STRING_SZ,"Median Negative yshift=%f\n",med_neg_y_shift);
    SCTPUT(output);

    success=snprintf(output,MAX_STRING_SZ,"RMS Median Positive yshift=%f\n",rms_pos_y_shift);
    SCTPUT(output);

    success=snprintf(output,MAX_STRING_SZ,"RMS Median Negative yshift=%f\n",rms_neg_y_shift);
    SCTPUT(output);


  }



  if (n_neg_y_shift <= 1){
    SCDWRR(inImaId,"YSHIFT", &avg_y_shift,1,1,&unit); 
    SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_y_shift,1,1,&unit); 
  }
  else if (n_pos_y_shift <= 1){
    SCDWRR(inImaId,"YSHIFT", &avg_y_shift,1,1,&unit); 
    SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_y_shift,1,1,&unit); 
  }
  else{
    /* 
       printf("RMS pos =%f RMS neg =%16.14f epsilon=%16.14f \n",
       rms_pos_y_shift,rms_neg_y_shift,MY_FEPSILON);
    */
    if ( (fabs(rms_pos_y_shift) >  MY_FEPSILON) && 
	 (fabs(rms_neg_y_shift) >  MY_FEPSILON) ){
      if (rms_pos_y_shift <= rms_neg_y_shift){
	SCDWRR(inImaId,"YSHIFT", &avg_pos_y_shift,1,1,&unit); 
	SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_pos_y_shift,1,1,&unit); 
      }
      else{
	SCDWRR(inImaId,"YSHIFT", &avg_neg_y_shift,1,1,&unit); 
	SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_neg_y_shift,1,1,&unit); 
      }
    }
    else if (fabs(rms_pos_y_shift) < MY_FEPSILON){ 
      SCDWRR(inImaId,"YSHIFT", &avg_neg_y_shift,1,1,&unit); 
      SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_neg_y_shift,1,1,&unit); 
    }
    else {
      SCDWRR(inImaId,"YSHIFT", &avg_pos_y_shift,1,1,&unit); 
      SCDWRR(inImaId,"ESO QC YSHIFT RMS", &rms_pos_y_shift,1,1,&unit); 
    }
  }

  avg_half_width=avg_half_width+LOC_SAV_BORD_SZ-SAV_BORD_SZ;
  SCDWRR(inImaId,"HALFWIDTH", &avg_half_width,1,1,&unit); 
  SCDWRR(inImaId,"ESO QC HALFWIDTH RMS", &rms_half_width,1,1,&unit); 

  /* free residual allocated memory */
  free_dvector(sto_half_width,0,(ordMax-ordMin)); 
  free_dvector(del_half_width,0,(ordMax-ordMin));
  free_dvector(buf_half_width,0,(ordMax-ordMin));

  free_dvector(sto_y_shift,0,(ordMax-ordMin)); 
  free_dvector(sto_pos_y_shift,0,(ordMax-ordMin)); 
  free_dvector(sto_neg_y_shift,0,(ordMax-ordMin)); 


  free_dvector(buf_y_shift,0,(ordMax-ordMin)); 
  free_dvector(buf_pos_y_shift,0,(ordMax-ordMin));
  free_dvector(buf_neg_y_shift,0,(ordMax-ordMin));

  free_dvector(del_y_shift,0,(ordMax-ordMin)); 
  free_dvector(del_pos_y_shift,0,(ordMax-ordMin)); 
  free_dvector(del_neg_y_shift,0,(ordMax-ordMin)); 

  free_ivector(sto_mask,0,(ordMax-ordMin));
  free_ivector(pos_mask,0,(ordMax-ordMin));
  free_ivector(neg_mask,0,(ordMax-ordMin));

  /* close */
  SCFCLO(inTabId);
  SCFCLO(inImaId);
  SCSEPI();

  return 0;

}

/*=========================================================================*/






int 
ima_comp(const void *arg1, 
         const void *arg2)
{
  float *pixel1= (float *)arg1;
  float *pixel2= (float *)arg2;


  if (fabs((*pixel1)- (*pixel2)) < FEPSILON) {
    return 0;
  }
  else if (*pixel1 > *pixel2) {
    return -1;
  }
  else if (*pixel1 < *pixel2) {
    return 1;
  }
  else return 0;
}


float 
get_y_min(int     xcPix, 
          int     ycTracePix,
          double   int_min,
          float** mInImaF,
          int LOC_SAV_BORD_SZ)
{


  int i = 0;
  int y1 =0;
  int  y2 =0;
  float int1 =0;
  float int2 =0;
  float yMin =0;
    
  yMin=0;

  /* printf("ycTracePix=%i\n",ycTracePix); */

  i= ycTracePix;

  while(mInImaF[i][xcPix]>int_min){
    --i;
  }
  y1=i;
  y2=i+1;


  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
  yMin=(float)(y1+(y2-y1)/(int2-int1)*(int_min-int1));
  yMin+=LOC_SAV_BORD_SZ;

  return yMin;

}  





float 
get_y_max(int     xcPix, 
          int     ycTracePix,
          double   int_min,
          float** mInImaF,
          int     LOC_SAV_BORD_SZ)
{
  int i = 0;
  int y1 =0;
  int  y2 =0;
  float int1 =0;
  float int2 =0;
  float yMax =0;
    
  /* printf("ycTracePix=%i\n",ycTracePix); */
  
  yMax=0;
  i=ycTracePix;
  while(mInImaF[i][xcPix]>int_min){
    ++i;
  }
  y1=i-1;
  y2=i;
  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
  yMax=(float)(y1+(y2-y1)/(int2-int1)*(int_min-int1));
  yMax-=LOC_SAV_BORD_SZ;

  return yMax;
}




void
find_mid_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double   int_min,
                   float** mInImaF,
                   double*  yMin,
                   double*  yMax,
                   int LOC_SAV_BORD_SZ)
{


  int i = 0;
  int y1 =0;
  int  y2 =0;
  float int1 =0;
  float int2 =0;

  i= ycTracePix;
   
  /* printf("mid ycTracePix=%i\n",ycTracePix); */
   
  while( (mInImaF[i][xcPix] > FEPSILON) && 
	 ((mInImaF[i][xcPix]>int_min) || 
          (mInImaF[i][xcPix]<0.05*int_min)) ){

    /* printf("i=%d %f %f\n",i,mInImaF[i][xcPix],int_min); */
    --i;
  }
  y1=i;
  y2=i+1;



  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
 
  (*yMin)=(float)(y1+(y2-y1)/(int2-int1)*(int_min-int1));
  (*yMin)+=LOC_SAV_BORD_SZ;


 
  
  i=ycTracePix;
  while( (mInImaF[i][xcPix] > FEPSILON) &&
	 ((mInImaF[i][xcPix]>int_min) ||
          (mInImaF[i][xcPix]<0.05*int_min)) ){
    ++i;
  }
  y1=i-1;
  y2=i;


  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];

  (*yMax)=(float)(y1+(y2-y1)/(int2-int1)*(int_min-int1));
  (*yMax)-=LOC_SAV_BORD_SZ;
  
}  




void 
find_upp_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double  int_min,
                   float** mInImaF,
                   float*  yMin,
                   float*  yMax,
                   int LOC_SAV_BORD_SZ)
{


  int i = 0;
  int y1 =0;
  int  y2 =0;
  double int1 =0;
  double int2 =0;
  //int j =0; /*for debugging purposes */

  i= ycTracePix;


  /* For debugging purposes
     printf("i=%i,xcPix=%i,int_min=%f,ima=%f ref%f \n",
     i    ,xcPix   ,(int_min), mInImaF[i][xcPix],(0.05*(int_min)) );
 
    
     for(j=i-10; j< (i+150);j++){
     printf("i=%i, ima=%f\n",j,mInImaF[j][xcPix]);
     }
  */

    
  while( (mInImaF[i][xcPix]<int_min) || 
	 (mInImaF[i][xcPix]<0.05*int_min) ){
    ++i;

    if (i >= 2048) 
      {

	y1=2047;
	y2=2048;
	goto upp_end;
      }
   

    /* For debugging purposes*/

    /*     
	   printf("i=%i, ima=%f int_min=%f ref_min=%f\n",
	   i,mInImaF[i][xcPix],(int_min),(0.05*(int_min)));
    */
  }
  y1=i;
  y2=i+1;


  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
 
  (*yMin)=(float)(y1+((double)(y2-y1))/(int2-int1)*((int_min)-int1));
  (*yMin)+=LOC_SAV_BORD_SZ;

  /*
    printf("Y1=%d Y2=%d int1=%f int2=%f Imin=%f yMin=%f\n",
    y1,y2,int1,int2,int_min,*yMin);
  */
  i=(int)(*yMin);
  while( (mInImaF[i][xcPix]>int_min) || 
	 (mInImaF[i][xcPix]<0.05*(int_min)) ){
    ++i;

    if (i >= 2048) 
      {

	y1=2047;
	y2=2048;
	goto upp_end;
      }
    /* For debugging purposes*/
    /*
      printf("i=%i, ima=%f int_min=%f ref_min=%f\n",
      i,mInImaF[i][xcPix],(int_min),(0.05*(int_min)));
    */
  }



  y1=i-1;
  y2=i;

 upp_end:
  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
  (*yMax)=(float)(y1+(float)(y2-y1)/(int2-int1)*((int_min)-int1));
  (*yMax)-=LOC_SAV_BORD_SZ;
  /*
    printf("Y1=%d Y2=%d int1=%f int2=%f Imin=%f yMax=%f\n",
    y1,y2,int1,int2,int_min,*yMax);
  */


}  



void
find_low_y_min_max(int     xcPix, 
                   int     ycTracePix,
                   double   int_min,
                   float** mInImaF,
                   double*  yMin,
                   double*  yMax,
                   int LOC_SAV_BORD_SZ)
{


  int i = 0;
  int y1 =0;
  int  y2 =0;
  float int1 =0;
  float int2 =0;

 

  i= ycTracePix;
  while( (mInImaF[i][xcPix]<int_min) || 
	 (mInImaF[i][xcPix]<0.05*int_min) ){

    --i;

    if (i <= 0) 
      {

	y1=2;
	y2=1;
	goto low_end;
      }

  }

  y1=i-1;
  y2=i;

 

  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];

  (*yMax)=y1+(y2-y1)/(int2-int1)*(int_min-int1);

  (*yMax)-=LOC_SAV_BORD_SZ;
 
  
  i=(int) (*yMax);

  if (i < 0) 
    {

      y1=2;
      y2=1;
      goto low_end;
    }


  if (i > 4096) 
  {

     y1=2;
     y2=1;
     goto low_end;
  } 

  while( (mInImaF[i][xcPix]>int_min) || 
	 (mInImaF[i][xcPix]<0.05*int_min) ){
    --i;

    if (i <= 0) 
      {

	y1=2;
	y2=1;
	goto low_end;
      }


  }


  y1=i+1;
  y2=i;

 low_end:
  int1=mInImaF[y1][xcPix];
  int2=mInImaF[y2][xcPix];
  (*yMin)=y1+(y2-y1)/(int2-int1)*(int_min-int1);
  (*yMin)+=LOC_SAV_BORD_SZ;

}  



float 
get_avg(double* val,
        int*   mask,
        int    min,
        int    max)
{
  /* this calculates the mean (average) of a distribution */
  int cnt=0;
  int i=0;
  float avg=0;
    

  for (i=min;i<max; i++)
    {
      if (mask[i] == 1) {
	/* printf("i=%i val=%f,med=%f,mask=%i\n",i,val[i],med,mask[i]); */
	avg+=val[i];
	cnt++;
      }
    }
  if (cnt) avg/=cnt;

  return avg;
}


float 
get_med(double* val,
        int*   mask,
        int    min,
        int    max)
{
  /* this calculates the mean (average) of a distribution */
  int cnt=0;
  int i=0;
  int nk=0;
  double med=0;
  double* buf;
  int buf_siz =0;

  for (i=min;i<max; i++)
    {
      if (mask[i] == 1) {
	/* printf("i=%i val=%f,med=%f,mask=%i\n",i,val[i],med,mask[i]); */ 
	cnt++;
      }
    }
  
  buf_siz=cnt;
  buf = dvector(0,buf_siz);

  cnt=0;
  for (i=min;i<max; i++)
    {
      if (mask[i] == 1) {
	/* printf("i=%i val=%f,med=%f,mask=%i\n",i,val[i],med,mask[i]); */
        
	buf[cnt++]=val[i];

      }
    }

  /*nk=(int)rint(cnt/2.); */
  nk=cnt/2.;
  
  if(nk > buf_siz) printf("Something strage ocxcurred\n");

  qsort(buf, (size_t) nk, sizeof(float), ima_comp);
  med=buf[nk];
  free_dvector(buf,0,buf_siz);

  return (float) med;
}



void
update_mask(double* del,
            float rms,
            int*   mask,
            int   min,
            int   max)
{
  /* 
     this routine catch the point which have maximum distance from the mean,
     and greater that the rms of distances respect to the mean and mask it out
  */
  int i=0;
  int i_max=-1;
  float tresh=rms;
  int n_msk=0;
  for (i=min;i<max; i++)
    {
      if (mask[i] == 1) {
	/* if ((del[i] > tresh) || (del[i] > 5)) {*/
	if (del[i] > tresh) {
	  /*
	    printf("Tresh %f\n",tresh);
	    printf("Value %f pos %i mask %i\n",del[i],i,mask[i]);
	  */
	  i_max=i;
	  tresh=(float) del[i];
        }
	n_msk++;
      }
    }
  if ((i_max >= 0) && n_msk >1) { /*We need to have at least one left point */
    /*
      printf("Maskera %i\n",i_max);
      printf("Value %f\n",del[i_max]);
    */
    mask[i_max]=0;
  }
}



void
update_delta(double* val,
             float  med,
             int    min,
             int    max,
             double* del)
{
  /* this routine update distances of values from a given mean */
  int i=0;

  for (i= min;i<max; i++)
    {
      del[i]=(float)fabs(val[i]-med);
    }
}



void
clip_hw_new(double* val,
            int* mask,
            int* min,
	    int* max)
{
  /* this routine mask out negative half width values */
  int i=0;
  for (i= (*min);i<(*max); i++)
    {
      if (val[i] <= 0)  mask[i]=0;
    }
}


void
clip_hw_small(double* val,
	      int* mask,
	      int min,
	      int max,
	      int DRS_SFF_HW_MIN)
{
  /* this routine mask out negative half width values */
  int i=0;
  for (i= min;i<max; i++)
    {
      if (val[i] < DRS_SFF_HW_MIN)  mask[i]=0;
    }
}

/**@}*/
















