/*===========================================================================
  Copyright (C) 1988-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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT       (c)  1988  European Southern Observatory
.LANGUAGE        C
.IDENTIFICATION  slslv
.AUTHOR          Preben Grosbol  (ESO-IPG)
.KEYWORDS        Object search, single line, level detection
.ENVIRONMENT     MIDAS
.COMMENTS        Routines used for Measuring Machine facility.
		 Only positive peaks will be detected.
.PURPOSE         Fast search of objects in a single scan line
                 using a level detection.
.RETURN          no. of objects found, <0 error
.VERSION         1.0   1988-Oct-08 :   Creation,     PJG

 090728		last modif
------------------------------------------------------------------------*/

#include   <mmfsrch.h>          /* definitions of search structures etc.*/

int slslv(buf,np,obj,mm,lev)
int      *buf;                  /* pointer to scan line to be searched  */
int        np;                  /* no. of pixels in scan line           */
OBJ      *obj;                  /* pointer to structure with objects    */
int        mm;                  /* size of moving mean filter           */
int       lev;                  /* detection level                      */
{
  int    *buff;
  int    nobj,nobg,bg,isg,n,ka,kf;
  int    kaf,kmg,nss,kzn,kax,i;
  int    n0,n1,n2;
  float  gkm,axk,pm;
  float  ak,an,den,xs,xxs;


  nobj = 0; i = 0; nobg = 0;       /* initiate search parameters        */
  n = 0; nss = 0; isg = -1;
  kmg = 0; kax = 0; bg = *buf;
  den = 0.0; xs = 0.0; xxs = 0.0;

  if (mm<1) mm = 1; else if (np<=mm) return -1;
  lev *= mm; kzn = KZN * mm; pm = mm;

  n1 = 0; buff = buf;              /* initiate moving mean filter      */
  while (mm--) { n1 += *buf++; np--; }
  n2 = n1 + (*buf++) - (*buff++);

  bg = n1;                             /* first pixel is background    */
  while (np--) {                       /* start search pixel by pixel  */
    i++;
    n0 = n1; n1 = n2;
    n2 += (*buf++) - (*buff++);        /* compute new moving mean      */
 
    if (nobg || n2>lev) {              /* pixel in object              */
       nobg = (n2>lev);
       if (nobg) { 	               /* new object found             */
          n++;
          ka = n1 - bg;
          kf = n2 - n0;
          if (isg*kf < kzn) {          /* sign changes in gradient     */
             nss++;
             isg = (0<kf) ? 1 : -1;
          }
          ak = ka; an = n;
          den += ak;
	  ak  *= an;
          xs  += ak;
          xxs += ak*an;
          if (ka>kax) kax = ka;        /* max. density of object       */
          kaf = (kf<0) ? -kf : kf;     /* max. absolute gradient       */
	  if (kaf>kmg) kmg = kaf;
          if (np) continue;
       }
       if (n>MPIX && nss>1) {          /* object has terminated        */
          gkm = kmg; axk = kax;
          obj->x = xs/den;
          obj->y = den/pm;
          obj->xs = xxs/pm;
          obj->ys = den/pm;
          obj->xy = xs/pm;
          obj->den = den/pm;
          obj->max = axk/pm;
          obj->bg  = bg/pm;
          obj->grad = 0.5*gkm/pm;
          obj->ix = i - n;
          obj->iy = 0;
	  obj->npix = n;
          obj->nline = 1;
	  obj++; nobj++;
       }
       nobg = 0;                       /* reset counters for new obj.  */
       n = 0; nss = 0; isg = -1;
       kmg = 0; kax = 0;
       den = 0.0; xs = 0.0; xxs = 0.0;
    }
    bg = n0;
  }
  return nobj;
}
