Exemple #1
0
/******************************** preanalyse *********************************
PROTO   void preanalyse(int no, objliststruct *objlist, int analyse_type)
PURPOSE Compute basic image parameters from the pixel-list for each detection.
INPUT   objlist number,
        objlist pointer,
        analysis switch flag.
OUTPUT  -.
NOTES   -.
AUTHOR  E. Bertin (IAP & Leiden & ESO)
VERSION 28/11/2003
 ***/
void  preanalyse(int no, objliststruct *objlist, int analyse_type)

  {
   objstruct	*obj = &objlist->obj[no];
   pliststruct	*pixel = objlist->plist, *pixt;
   PIXTYPE	peak, cpeak, val, cval, minthresh, thresht;
   double	thresh,thresh2, t1t2,darea,
		mx,my, mx2,my2,mxy, rv, tv,
		xm,ym, xm2,ym2,xym,
		temp,temp2, theta,pmx2,pmy2;
   int		x, y, xmin,xmax, ymin,ymax,area2, fdnpix, dnpix;


/*-----  initialize stacks and bounds */
  thresh = obj->dthresh;
  if (PLISTEXIST(dthresh))
    minthresh = BIG;
  else
    minthresh = 0.0;
  fdnpix = dnpix = 0;
  rv = 0.0;
  peak = cpeak = -BIG;
  ymin = xmin = 2*MAXPICSIZE;    /* to be really sure!! */
  ymax = xmax = 0;

/*-----  integrate results */
  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
    {
    x = PLIST(pixt, x);
    y = PLIST(pixt, y);
    val=PLISTPIX(pixt, dvalue);
    if (cpeak < (cval=PLISTPIX(pixt, cdvalue)))
      cpeak = cval;
    if (PLISTEXIST(dthresh) && (thresht=PLISTPIX(pixt, dthresh))<minthresh)
      minthresh = thresht;
    if (peak < val)
      peak = val;
    rv += cval;
    if (xmin > x)
      xmin = x;
    if (xmax < x)
      xmax = x;
    if (ymin > y)
      ymin = y;
    if (ymax < y)
      ymax = y;
    fdnpix++;
    }

  if (PLISTEXIST(dthresh))
    obj->dthresh = thresh = minthresh;

/* copy some data to "obj" structure */

  obj->fdnpix = (LONG)fdnpix;
  obj->fdflux = (float)rv;
  obj->fdpeak = cpeak;
  obj->dpeak = peak;
  obj->xmin = xmin;
  obj->xmax = xmax;
  obj->ymin = ymin;
  obj->ymax = ymax;

  if (analyse_type & ANALYSE_FULL)
    {
    mx = my = tv = 0.0;
    mx2 = my2 = mxy = 0.0;
    thresh2 = (thresh + peak)/2.0;
    area2 = 0;
    for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
      {
      x = PLIST(pixt,x)-xmin;	/* avoid roundoff errors on big images */
      y = PLIST(pixt,y)-ymin;	/* avoid roundoff errors on big images */
      cval = PLISTPIX(pixt, cdvalue);
      tv += (val = PLISTPIX(pixt, dvalue));
      if (val>thresh)
        dnpix++;
      if (val > thresh2)
        area2++;
      mx += cval * x;
      my += cval * y;
      mx2 += cval * x*x;
      my2 += cval * y*y;
      mxy += cval * x*y;
      }

/*----- compute object's properties */
    xm = mx / rv;			/* mean x */
    ym = my / rv;			/* mean y */

/*-- In case of blending, use previous barycenters */
    if ((analyse_type&ANALYSE_ROBUST) && (obj->flag&OBJ_MERGED))
      {
       double	xn,yn;

      xn = obj->mx-xmin;
      yn = obj->my-ymin;
      xm2 = mx2 / rv + xn*xn - 2*xm*xn;
      ym2 = my2 / rv + yn*yn - 2*ym*yn;
      xym = mxy / rv + xn*yn - xm*yn - xn*ym;
      xm = xn;
      ym = yn;
      }
    else
      {
      xm2 = mx2 / rv - xm * xm;	/* variance of x */
      ym2 = my2 / rv - ym * ym;	/* variance of y */
      xym = mxy / rv - xm * ym;	/* covariance */
      }

/* Handle fully correlated x/y (which cause a singularity...) */
    if ((temp2=xm2*ym2-xym*xym)<0.00694)
      {
      xm2 += 0.0833333;
      ym2 += 0.0833333;
      temp2 = xm2*ym2-xym*xym;
      obj->singuflag = 1;
      }
    else
      obj->singuflag = 0;

    if ((fabs(temp=xm2-ym2)) > 0.0)
      theta = atan2(2.0 * xym,temp) / 2.0;
    else
      theta = PI/4.0;

    temp = sqrt(0.25*temp*temp+xym*xym);
    pmy2 = pmx2 = 0.5*(xm2+ym2);
    pmx2+=temp;
    pmy2-=temp;

    obj->dnpix = (obj->flag & OBJ_OVERFLOW)? obj->fdnpix:(LONG)dnpix;
    obj->dflux = tv;
    obj->mx = xm+xmin;	/* add back xmin */
    obj->my = ym+ymin;	/* add back ymin */
    obj->mx2 = xm2;
    obj->my2 = ym2;
    obj->mxy = xym;
    obj->a = (float)sqrt(pmx2);
    obj->b = (float)sqrt(pmy2);
    obj->theta = theta*180.0/PI;

    obj->cxx = (float)(ym2/temp2);
    obj->cyy = (float)(xm2/temp2);
    obj->cxy = (float)(-2*xym/temp2);

    darea = (double)area2 - dnpix;
    t1t2 = thresh/thresh2;
    if (t1t2>0.0 && !prefs.dweight_flag)
      {
      obj->abcor = (darea<0.0?darea:-1.0)/(2*PI*log(t1t2<1.0?t1t2:0.99)
	*obj->a*obj->b);
      if (obj->abcor>1.0)
        obj->abcor = 1.0;
      }
    else
      obj->abcor = 1.0;
    }

  return;
  }
Exemple #2
0
/****************************** scanimage ************************************
PROTO   void scanimage(picstruct *field, picstruct *dfield, picstruct *ffield,
        picstruct *wfield, picstruct *dwfield)
PURPOSE Scan of the large pixmap(s). Main loop and heart of the program.
INPUT   Measurement field pointer,
        Detection field pointer,
        Flag field pointer,
        Measurement weight-map field pointer,
        Detection weight-map field pointer,
OUTPUT  -.
NOTES   -.
AUTHOR  E. Bertin (IAP)
VERSION 21/12/2011
 ***/
void	scanimage(picstruct *field, picstruct *dfield, picstruct **pffield,
		int nffield, picstruct *wfield, picstruct *dwfield)

  {
   static infostruct	curpixinfo, *info, *store,
			initinfo, freeinfo, *victim;
   picstruct		*ffield;
   checkstruct		*check;
   objliststruct       	objlist;
   objstruct		*cleanobj;
   pliststruct		*pixel, *pixt;
   picstruct		*cfield, *cdwfield;

   char			*marker, newmarker, *blankpad, *bpt,*bpt0;
   int			co, i,j, flag, luflag,pstop, xl,xl2,yl, cn,
			nposize, stacksize, w, h, blankh, maxpixnb,
			varthreshflag, ontotal;
   short	       	trunflag;
   PIXTYPE		thresh, relthresh, cdnewsymbol, cdwthresh,wthresh,
			*scan,*dscan,*cdscan,*dwscan,*dwscanp,*dwscann,
			*cdwscan,*cdwscanp,*cdwscann,*wscand,
			*scant, *wscan,*wscann,*wscanp;
   FLAGTYPE		*pfscan[MAXFLAG];
   status		cs, ps, *psstack;
   int			*start, *end, ymax;

/* Avoid gcc -Wall warnings */
  scan = dscan = cdscan = cdwscan = cdwscann = cdwscanp
	= dwscan = dwscann = dwscanp
	= wscan = wscann = wscanp = NULL;
  victim = NULL;			/* Avoid gcc -Wall warnings */
  blankh = 0;				/* Avoid gcc -Wall warnings */
/*----- Beginning of the main loop: Initialisations  */
  thecat.ntotal = thecat.ndetect = 0;

/* cfield is the detection field in any case */
  cfield = dfield? dfield:field;

/* cdwfield is the detection weight-field if available */
  cdwfield = dwfield? dwfield:(prefs.dweight_flag?wfield:NULL);
  cdwthresh = cdwfield ? cdwfield->weight_thresh : 0.0;
  if (cdwthresh>BIG*WTHRESH_CONVFAC);
    cdwthresh = BIG*WTHRESH_CONVFAC;
  wthresh = wfield? wfield->weight_thresh : 0.0;

/* If WEIGHTing and no absolute thresholding, activate threshold scaling */
  varthreshflag = (cdwfield && prefs.thresh_type[0]!=THRESH_ABSOLUTE);
  relthresh = varthreshflag ? prefs.dthresh[0] : 0.0;/* To avoid gcc warnings*/
  w = cfield->width;
  h = cfield->height;
  objlist.dthresh = cfield->dthresh;
  objlist.thresh = field->thresh;
  cfield->yblank = 1;
  field->y = field->stripy = 0;
  field->ymin = field->stripylim = 0;
  field->stripysclim = 0;
  if (dfield)
    {
    dfield->y = dfield->stripy = 0;
    dfield->ymin = dfield->stripylim = 0;
    dfield->stripysclim = 0;
    }
  if (nffield)
    for (i=0; i<nffield; i++)
      {
      ffield = pffield[i];
      ffield->y = ffield->stripy = 0;
      ffield->ymin = ffield->stripylim = 0;
      ffield->stripysclim = 0;
      }
  if (wfield)
    {
    wfield->y = wfield->stripy = 0;
    wfield->ymin = wfield->stripylim = 0;
    wfield->stripysclim = 0;
    }
  if (dwfield)
    {
    dwfield->y = dwfield->stripy = 0;
    dwfield->ymin = dwfield->stripylim = 0;
    dwfield->stripysclim = 0;
    }

/*Allocate memory for buffers */
  stacksize = w+1;
  QMALLOC(info, infostruct, stacksize);
  QCALLOC(store, infostruct, stacksize);
  QMALLOC(marker, char, stacksize);
  QMALLOC(dumscan, PIXTYPE, stacksize);
  QMALLOC(psstack, status, stacksize);
  QCALLOC(start, int, stacksize);
  QMALLOC(end, int, stacksize);
  blankpad = bpt = NULL;
  lutzalloc(w,h);
  allocparcelout();

/* Some initializations */

  thresh = objlist.dthresh;
  initinfo.pixnb = 0;
  initinfo.flag = 0;
  initinfo.firstpix = initinfo.lastpix = -1;

  for (xl=0; xl<stacksize; xl++)
    {
    marker[xl]  = 0 ;
    dumscan[xl] = -BIG ;
    }

  co = pstop = 0;
  objlist.nobj = 1;
  curpixinfo.pixnb = 1;

/* Init cleaning procedure */
  initclean();

/*----- Allocate memory for the pixel list */
  init_plist();

  if (!(pixel = objlist.plist = malloc(nposize=prefs.mem_pixstack*plistsize)))
    error(EXIT_FAILURE, "Not enough memory to store the pixel stack:\n",
        "           Try to decrease MEMORY_PIXSTACK");

/*----- at the beginning, "free" object fills the whole pixel list */
  freeinfo.firstpix = 0;
  freeinfo.lastpix = nposize-plistsize;
  pixt = pixel;
  for (i=plistsize; i<nposize; i += plistsize, pixt += plistsize)
    PLIST(pixt, nextpix) = i;
  PLIST(pixt, nextpix) = -1;

/* Allocate memory for other buffers */
  if (prefs.filter_flag)
    {
    QMALLOC(cdscan, PIXTYPE, stacksize);
    if (cdwfield)
      {
      QCALLOC(cdwscan, PIXTYPE, stacksize);
      if (PLISTEXIST(wflag))
        {
        QCALLOC(cdwscanp, PIXTYPE, stacksize);
        QCALLOC(cdwscann, PIXTYPE, stacksize);
        }
      }
/*-- One needs a buffer to protect filtering if source-blanking applies */
    if (prefs.blank_flag)
      {
      blankh = thefilter->convh/2+1;
      QMALLOC(blankpad, char, w*blankh);
      cfield->yblank -= blankh;
      if (dfield)
        field->yblank = cfield->yblank;
      bpt = blankpad;
      }
    }

/*----- Here we go */
  for (yl=0; yl<=h;)
    {
    ps = COMPLETE;
    cs = NONOBJECT;
    if (yl==h)
      {
/*---- Need an empty line for Lutz' algorithm to end gracely */
      if (prefs.filter_flag)
        {
        free(cdscan);
        if (cdwfield)
          {
          if (PLISTEXIST(wflag))
            {
            free(cdwscanp);
            free(cdwscann);
            cdwscanp = cdwscan;
            }
          else
            free(cdwscan);
          }
        }
      cdwscan = cdwscann = cdscan = dumscan;
      }
    else
      {
      if (nffield)
        for (i=0; i<nffield; i++)
          {
          ffield = pffield[i];
          pfscan[i] = (ffield->stripy==ffield->stripysclim)?
		  (FLAGTYPE *)loadstrip(ffield, (picstruct *)NULL)
		: &ffield->fstrip[ffield->stripy*ffield->width];
          }
      if (wfield)
        {
/*------ Copy the previous weight line to track bad pixel limits */
        wscan = (wfield->stripy==wfield->stripysclim)?
		  (PIXTYPE *)loadstrip(wfield, (picstruct *)NULL)
		: &wfield->strip[wfield->stripy*wfield->width];
        if (PLISTEXIST(wflag))
          {
          if (yl>0)
            wscanp = &wfield->strip[((yl-1)%wfield->stripheight)*wfield->width];
          if (yl<h-1)
            wscann = &wfield->strip[((yl+1)%wfield->stripheight)*wfield->width];
          }
        }
      scan = (field->stripy==field->stripysclim)?
		  (PIXTYPE *)loadstrip(field, wfield)
		: &field->strip[field->stripy*field->width];
      if (dwfield)
        {
        dwscan = (dwfield->stripy==dwfield->stripysclim)?
		  (PIXTYPE *)loadstrip(dwfield,
				dfield?(picstruct *)NULL:dwfield)
		: &dwfield->strip[dwfield->stripy*dwfield->width];
        if (PLISTEXIST(wflag))
          {
          if (yl>0)
            dwscanp = &dwfield->strip[((yl-1)%dwfield->stripheight)
			*dwfield->width];
          if (yl<h-1)
            dwscann = &dwfield->strip[((yl+1)%dwfield->stripheight)
			*dwfield->width];
          }
        }
      else
        {
        dwscan = wscan;
        if (PLISTEXIST(wflag))
          {
          dwscanp = wscanp;
          dwscann = wscann;
          }
        }
      if (dfield)
        dscan = (dfield->stripy==dfield->stripysclim)?
		  (PIXTYPE *)loadstrip(dfield, dwfield)
		: &dfield->strip[dfield->stripy*dfield->width];
      else
        dscan = scan;

      if (prefs.filter_flag)
        {
        filter(cfield, cdscan, cfield->y);
        if (cdwfield)
          {
          if (PLISTEXIST(wflag))
            {
            if (yl==0)
              filter(cdwfield, cdwscann, yl);
            wscand = cdwscanp;
            cdwscanp = cdwscan;
            cdwscan = cdwscann;
            cdwscann = wscand;
            if (yl < h-1)
              filter(cdwfield, cdwscann, yl + 1);
            }
          else
            filter(cdwfield, cdwscan, yl);
          }
        }
      else
        {
        cdscan = dscan;
        cdwscan = dwscan;
        if (PLISTEXIST(wflag))
          {
          cdwscanp = dwscanp;
          cdwscann = dwscann;
          }
        }

      if ((check=prefs.check[CHECK_FILTERED]))
        writecheck(check, cdscan, w);
      }

    trunflag = (yl==0 || yl==h-1)? OBJ_TRUNC:0;

    for (xl=0; xl<=w; xl++)
      {
      if (xl == w)
        cdnewsymbol = -BIG;
      else
        cdnewsymbol = cdscan[xl];

      newmarker = marker[xl];
      marker[xl] = 0;

      curpixinfo.flag = trunflag;
      if (varthreshflag)
        thresh = relthresh*sqrt((xl==w || yl==h)? 0.0:cdwscan[xl]);
      luflag = cdnewsymbol > thresh?1:0;

      if (luflag)
        {
        if (xl==0 || xl==w-1)
          curpixinfo.flag |= OBJ_TRUNC;
        pixt = pixel + (cn=freeinfo.firstpix);
        freeinfo.firstpix = PLIST(pixt, nextpix);

/*------- Running out of pixels, the largest object becomes a "victim" ------*/

        if (freeinfo.firstpix==freeinfo.lastpix)
          {
          sprintf(gstr, "%d,%d", xl+1, yl+1);
          warning("Pixel stack overflow at position ", gstr);
          maxpixnb = 0;
          for (i=0; i<=w; i++)
            if (store[i].pixnb>maxpixnb)
              if (marker[i]=='S' || (newmarker=='S' && i==xl))
                {
                flag = 0;
                if (i<xl)
                  for (j=0; j<=co; j++)
                    flag |= (start[j]==i);
                if (!flag)
                  maxpixnb = (victim = &store[i])->pixnb;
                }
          for (j=1; j<=co; j++)
            if (info[j].pixnb>maxpixnb)
              maxpixnb = (victim = &info[j])->pixnb;

          if (!maxpixnb)
            error(EXIT_FAILURE, "*Fatal Error*: something is badly bugged in ",
		"scanimage()!");
          if (maxpixnb <= 1)
            error(EXIT_FAILURE, "Pixel stack overflow in ", "scanimage()");
          freeinfo.firstpix = PLIST(pixel+victim->firstpix, nextpix);
          PLIST(pixel+victim->lastpix, nextpix) = freeinfo.lastpix;
          PLIST(pixel+(victim->lastpix=victim->firstpix), nextpix) = -1;
          victim->pixnb = 1;
          victim->flag |= OBJ_OVERFLOW;
          }

/*---------------------------------------------------------------------------*/
        curpixinfo.lastpix = curpixinfo.firstpix = cn;
        PLIST(pixt, nextpix) = -1;
        PLIST(pixt, x) = xl;
        PLIST(pixt, y) = yl;
        PLIST(pixt, value) = scan[xl];
        if (PLISTEXIST(dvalue))
          PLISTPIX(pixt, dvalue) = dscan[xl];
        if (PLISTEXIST(cdvalue))
          PLISTPIX(pixt, cdvalue) = cdnewsymbol;
        if (PLISTEXIST(flag))
          for (i=0; i<nffield; i++)
            PLISTFLAG(pixt, flag[i]) = pfscan[i][xl];
/*--------------------- Detect pixels with a low weight ---------------------*/
        if (PLISTEXIST(wflag) && wscan)
          {
	  PLISTFLAG(pixt, wflag) = 0;
          if (wscan[xl] >= wthresh)
            PLISTFLAG(pixt, wflag) |= OBJ_LOWWEIGHT;
          if (cdwscan[xl] >= cdwthresh)
            PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;

          if (yl>0)
            {
            if (cdwscanp[xl] >= cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            if (xl>0 && cdwscanp[xl-1]>=cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            if (xl<w-1 && cdwscanp[xl+1]>=cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            }
          if (xl>0 && cdwscan[xl-1]>=cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
          if (xl<w-1 && cdwscan[xl+1]>=cdwthresh)
            PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
          if (yl<h-1)
            {
            if (cdwscann[xl] >= cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            if (xl>0 && cdwscann[xl-1]>=cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            if (xl<w-1 && cdwscann[xl+1]>=cdwthresh)
              PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
            }
          }
        if (PLISTEXIST(dthresh))
          PLISTPIX(pixt, dthresh) = thresh;
        if (PLISTEXIST(var))
          PLISTPIX(pixt, var) = wscan[xl];

        if (cs != OBJECT)
/*------------------------------- Start Segment -----------------------------*/

          {
          cs = OBJECT;
          if (ps == OBJECT)
            {
            if (start[co] == UNKNOWN)
              {
              marker[xl] = 'S';
              start[co] = xl;
              }
            else
              marker[xl] = 's';
            }
          else
            {
            psstack[pstop++] = ps;
            marker[xl] = 'S';
            start[++co] = xl;
            ps = COMPLETE;
            info[co] = initinfo;
            }
          }

/*---------------------------------------------------------------------------*/
        }

      if (newmarker)

/*---------------------------- Process New Marker ---------------------------*/

        {
        if (newmarker == 'S')
          {
          psstack[pstop++] = ps;
          if (cs == NONOBJECT)
            {
            psstack[pstop++] = COMPLETE;
            info[++co] = store[xl];
            start[co] = UNKNOWN;
            }
          else
            update (&info[co],&store[xl], pixel);
          ps = OBJECT;
          }
        else if (newmarker == 's')
          {
          if ((cs == OBJECT) && (ps == COMPLETE))
            {
            pstop--;
            xl2 = start[co];
            update (&info[co-1],&info[co], pixel);
            if (start[--co] == UNKNOWN)
              start[co] = xl2;
            else
              marker[xl2] = 's';
            }
          ps = OBJECT;
          }
        else if (newmarker == 'f')
          ps = INCOMPLETE;
        else if (newmarker == 'F')
          {
          ps = psstack[--pstop];
          if ((cs == NONOBJECT) && (ps == COMPLETE))
            {
            if (start[co] == UNKNOWN)
              {
              if ((int)info[co].pixnb >= prefs.ext_minarea)
                {
                sortit(field, dfield, wfield, cdwfield, &info[co], &objlist,
		       cdwscan, wscan);
                }
/* ------------------------------------ free the chain-list */

              PLIST(pixel+info[co].lastpix, nextpix) = freeinfo.firstpix;
              freeinfo.firstpix = info[co].firstpix;
              }
            else
              {
              marker[end[co]] = 'F';
              store[start[co]] = info[co];
              }
            co--;
            ps = psstack[--pstop];
            }
          }
        }
/*---------------------------------------------------------------------------*/

      if (luflag)
        update (&info[co],&curpixinfo, pixel);
      else
        {
        if (cs == OBJECT)
/*-------------------------------- End Segment ------------------------------*/
          {
          cs = NONOBJECT;
          if (ps != COMPLETE)
            {
            marker[xl] = 'f';
            end[co] = xl;
            }
          else
            {
            ps = psstack[--pstop];
            marker[xl] = 'F';
            store[start[co]] = info[co];
            co--;
            }
          }
        }

      if (prefs.blank_flag && xl<w)
        {
        if (prefs.filter_flag)
	  *(bpt++) = (luflag)?1:0;
        else if (luflag)
          dscan[xl] = -BIG;
        if (dfield && luflag)
          scan[xl] = -BIG;
        }
/*--------------------- End of the loop over the x's -----------------------*/
      }

/* Detected pixel removal at the end of each line */
    if (prefs.blank_flag && yl<h)
      {
      if (prefs.filter_flag)
        {
        bpt = bpt0 = blankpad + w*((yl+1)%blankh);
        if (cfield->yblank >= 0)
          {
          scant = &PIX(cfield, 0, cfield->yblank);
          for (i=w; i--; scant++)
            if (*(bpt++))
              *scant = -BIG;
          if (dfield)
            {
            bpt = bpt0;
            scant = &PIX(field, 0, cfield->yblank);
            for (i=w; i--; scant++)
              if (*(bpt++))
                *scant = -BIG;
            }
          bpt = bpt0;
          }
        }
      cfield->yblank++;
      if (dfield)
        field->yblank = cfield->yblank;
      }

/*-- Prepare markers for the next line */
    yl++;
    field->stripy = (field->y=yl)%field->stripheight;
    if (dfield)
      dfield->stripy = (dfield->y=yl)%dfield->stripheight;
    if (nffield)
      for (i=0; i<nffield; i++)
        {
        ffield = pffield[i];
        ffield->stripy = (ffield->y=yl)%ffield->stripheight;
        }
    if (wfield)
      wfield->stripy = (wfield->y=yl)%wfield->stripheight;
    if (dwfield)
      dwfield->stripy = (dwfield->y=yl)%dwfield->stripheight;

/*-- Remove objects close to the ymin limit if ymin is ready to increase */
    if (cfield->stripy==cfield->stripysclim)
      {
      cleanobj = cleanobjlist->obj+cleanobjlist->nobj-1;
      ontotal = 0;
      for (i=cleanobjlist->nobj; i--; cleanobj--)
        {
        if (cleanobj->ycmin <= cfield->ymin)
          {
/*-------- Warn if there is a possibility for any aperture to be truncated */
          if ((ymax=cleanobj->ycmax) > cfield->ymax)
            {
            sprintf(gstr, "Object at position %.0f,%.0f ",
		cleanobj->mx+1, cleanobj->my+1);
            QWARNING(gstr, "may have some apertures truncated:\n"
		"          You might want to increase MEMORY_BUFSIZE");
            }
          else if (ymax>cfield->yblank && prefs.blank_flag)
            {
            sprintf(gstr, "Object at position %.0f,%.0f ",
		cleanobj->mx+1, cleanobj->my+1);
            QWARNING(gstr, "may have some unBLANKed neighbours:\n"
		"          You might want to increase MEMORY_PIXSTACK");
            }
          if ((prefs.prof_flag && !(thecat.ntotal%10)
		&& thecat.ntotal != ontotal)
		|| !(thecat.ntotal%400))
            NPRINTF(OUTPUT, "\33[1M> Line:%5d  "
		"Objects: %8d detected / %8d sextracted\n\33[1A",
		yl>h? h:yl, thecat.ndetect, thecat.ntotal);
          ontotal = thecat.ntotal;
          endobject(field, dfield, wfield, cdwfield, i, cleanobjlist);
          subcleanobj(i);
          cleanobj = cleanobjlist->obj+i;	/* realloc in subcleanobj() */
          }
        }
      }

    if ((prefs.prof_flag && !(thecat.ntotal%10)) || !(yl%25))
      NPRINTF(OUTPUT, "\33[1M> Line:%5d  "
		"Objects: %8d detected / %8d sextracted\n\33[1A",
	yl>h?h:yl, thecat.ndetect, thecat.ntotal);
/*--------------------- End of the loop over the y's -----------------------*/
    }

/* Removal or the remaining pixels */
  if (prefs.blank_flag && prefs.filter_flag && (cfield->yblank >= 0))
    for (j=blankh-1; j--; yl++)
      {
      bpt = bpt0 = blankpad + w*(yl%blankh);
      scant = &PIX(cfield, 0, cfield->yblank);
      for (i=w; i--; scant++)
        if (*(bpt++))
          *scant = -BIG;
      if (dfield)
        {
        bpt = bpt0;
        scant = &PIX(field, 0, cfield->yblank);
        for (i=w; i--; scant++)
          if (*(bpt++))
            *scant = -BIG;
        }
      cfield->yblank++;
      if (dfield)
        field->yblank = cfield->yblank;
      }

/* Now that all "detected" pixels have been removed, analyse detections */
  ontotal = 0;
  for (j=cleanobjlist->nobj; j--;)
    {
    if ((prefs.prof_flag && !(thecat.ntotal%10) && thecat.ntotal != ontotal)
		|| !(thecat.ntotal%400))
      NPRINTF(OUTPUT, "\33[1M> Line:%5d  "
		"Objects: %8d detected / %8d sextracted\n\33[1A",
	h, thecat.ndetect, thecat.ntotal);
    ontotal = thecat.ntotal;
    endobject(field, dfield, wfield, cdwfield, 0, cleanobjlist);
    subcleanobj(0);
    }

  endclean();

/*Free memory */
  if (prefs.filter_flag && cdwfield && PLISTEXIST(wflag))
    free(cdwscanp);
  freeparcelout();
  free(pixel); pixel = NULL;
  lutzfree();
  free(info); info = NULL;
  free(store); store = NULL;
  free(marker); marker = NULL;
  free(dumscan); dumscan = NULL;
  free(psstack); psstack = NULL;
  free(start); start = NULL;
  free(end); end = NULL;
  if (prefs.blank_flag && prefs.filter_flag)
    free(blankpad); blankpad = NULL;

  return;
  }
Exemple #3
0
/****************************** extract **************************************/
int sep_extract(PIXTYPE *im, PIXTYPE *var, int w, int h,
	        PIXTYPE thresh, int minarea,
	        float *conv, int convw, int convh,
		int deblend_nthresh, double deblend_mincont,
		int clean_flag, double clean_param,
		int *nobj, sepobj **objects)
{
  static infostruct	curpixinfo, *info, *store, initinfo, freeinfo, *victim;
  objliststruct       	objlist, *finalobjlist;
  pliststruct		*pixel, *pixt; 
  char			*marker, newmarker;
  int			co, i, j, flag, luflag, pstop, xl, xl2, yl, cn,
			nposize, stacksize, maxpixnb, convn, status;
  short	       	        trunflag;
  PIXTYPE		relthresh, cdnewsymbol;
  PIXTYPE               *scan,*cdscan,*cdwscan,*wscan,*dumscan;
  float                 sum, *convnorm;
  pixstatus		cs, ps, *psstack;
  int			*start, *end, *survives;

  status = RETURN_OK;
  char errtext[80];  /* 80 should be more than enough */
  
  pixel = NULL;
  convnorm = NULL;
  scan = wscan = cdscan = cdwscan = dumscan = NULL;
  victim = NULL;
  info = NULL;
  store = NULL;
  marker = NULL;
  psstack = NULL;
  start = end = NULL;
  finalobjlist = NULL; /* final return value */
  convn = 0;
  sum = 0.0;

  /* var is the image variance to use for thresholding, if available */
  relthresh = var? thresh : 0.0;/* To avoid gcc warnings*/

  objlist.dthresh = thresh;
  objlist.thresh = thresh;

  /*Allocate memory for buffers */
  stacksize = w+1;
  QMALLOC(info, infostruct, stacksize, status);
  QCALLOC(store, infostruct, stacksize, status);
  QMALLOC(marker, char, stacksize, status);
  QMALLOC(dumscan, PIXTYPE, stacksize, status);
  QMALLOC(psstack, pixstatus, stacksize, status);
  QCALLOC(start, int, stacksize, status);
  QMALLOC(end, int, stacksize, status);
  if ((status = lutzalloc(w, h)) != RETURN_OK)
    goto exit;
  if ((status = allocdeblend(deblend_nthresh)) != RETURN_OK)
    goto exit;

  /* More initializations */
  initinfo.pixnb = 0;
  initinfo.flag = 0;
  initinfo.firstpix = initinfo.lastpix = -1;

  for (xl=0; xl<stacksize; xl++)
    {
    marker[xl]  = 0 ;
    dumscan[xl] = -BIG ;
    }

  co = pstop = 0;
  objlist.nobj = 1;
  curpixinfo.pixnb = 1;

  /* Init finalobjlist (the return catalog) */
  QMALLOC(finalobjlist, objliststruct, 1, status);
  finalobjlist->obj = NULL;
  finalobjlist->plist = NULL;
  finalobjlist->nobj = finalobjlist->npix = 0;


  /* Allocate memory for the pixel list */
  plistinit(conv, var);
  if (!(pixel = objlist.plist = malloc(nposize=MEMORY_PIXSTACK*plistsize)))
    {
      status = MEMORY_ALLOC_ERROR;
      goto exit;
    }

  /*----- at the beginning, "free" object fills the whole pixel list */
  freeinfo.firstpix = 0;
  freeinfo.lastpix = nposize-plistsize;
  pixt = pixel;
  for (i=plistsize; i<nposize; i += plistsize, pixt += plistsize)
    PLIST(pixt, nextpix) = i;
  PLIST(pixt, nextpix) = -1;

  if (conv)
    {
      /* allocate memory for convolved buffers */
      QMALLOC(cdscan, PIXTYPE, stacksize, status);
      if (var)
	QCALLOC(cdwscan, PIXTYPE, stacksize, status);

      /* normalize the filter */
      convn = convw * convh;
      QMALLOC(convnorm, PIXTYPE, convn, status);
      for (i=0; i<convn; i++)
	sum += fabs(conv[i]);
      for (i=0; i<convn; i++)
	convnorm[i] = conv[i] / sum;
    }

  /*----- MAIN LOOP ------ */
  for (yl=0; yl<=h; yl++)
    {

      ps = COMPLETE;
      cs = NONOBJECT;
    
      /* Need an empty line for Lutz' algorithm to end gracely */
      if (yl==h)
	{
	  if (conv)
	    {
	      free(cdscan);
	      cdscan = NULL;
	      if (var)
		{
		  free(cdwscan);
		  cdwscan = NULL;
		}
	    }
	  cdwscan = cdscan = dumscan;
	}

      else
	{
	  scan = im + yl*w;
	  if (var)
	    wscan = var + yl*w;

	  /* filter the lines */
	  if (conv)
	    {
	      convolve(im, w, h, yl, convnorm, convw, convh, cdscan);
	      if (var)
		convolve(var, w, h, yl, convnorm, convw, convh, cdwscan);
	    }
	  else
	    {
	      cdscan = scan;
	      cdwscan = wscan;
	    }	  
	}
      
      trunflag = (yl==0 || yl==h-1)? SEP_OBJ_TRUNC:0;
      
      for (xl=0; xl<=w; xl++)
	{
	  if (xl == w)
	    cdnewsymbol = -BIG;
	  else
	    cdnewsymbol = cdscan[xl];

	  newmarker = marker[xl];  /* marker at this pixel */
	  marker[xl] = 0;

	  curpixinfo.flag = trunflag;
	  if (var)
	    thresh = relthresh * sqrt((xl==w || yl==h)? 0.0:cdwscan[xl]);
	  luflag = cdnewsymbol > thresh? 1: 0;  /* is pixel above thresh? */

	  if (luflag)
	    {
	      /* flag the current object if we're near the image bounds */
	      if (xl==0 || xl==w-1)
		curpixinfo.flag |= SEP_OBJ_TRUNC;
	      
	      /* point pixt to first free pixel in pixel list */
	      /* and increment the "first free pixel" */
	      pixt = pixel + (cn=freeinfo.firstpix);
	      freeinfo.firstpix = PLIST(pixt, nextpix);
	      curpixinfo.lastpix = curpixinfo.firstpix = cn;

	      /* set values for the new pixel */ 
	      PLIST(pixt, nextpix) = -1;
	      PLIST(pixt, x) = xl;
	      PLIST(pixt, y) = yl;
	      PLIST(pixt, value) = scan[xl];
	      if (PLISTEXIST(cdvalue))
		PLISTPIX(pixt, cdvalue) = cdnewsymbol;
	      if (PLISTEXIST(var))
		PLISTPIX(pixt, var) = wscan[xl];

	      /* Check if we are running out of free pixels in objlist.plist */
	      /* (previously, the largest object became a "victim") */
	      if (freeinfo.firstpix==freeinfo.lastpix)
		{
		  status = SEP_INTERNAL_ERROR;
		  sprintf(errtext, "Pixel stack overflow at position %d,%d.",
			  xl+1, yl+1);
		  put_errdetail(errtext);
		  goto exit;
		  
		  /* NOTE: The above error was originally just a warning.
		     with the change to an error, the following code in this
		     if block is never executed.
		     TODO: should this just be a warning (or nothing?)
		  */

		  /* loop over pixels in row to find largest object */
		  maxpixnb = 0;
		  for (i=0; i<=w; i++)
		    if (store[i].pixnb>maxpixnb)
		      if (marker[i]=='S' || (newmarker=='S' && i==xl))
			{
			  flag = 0;
			  if (i<xl)
			    for (j=0; j<=co; j++)
			      flag |= (start[j]==i);
			  if (!flag)
			    maxpixnb = (victim = &store[i])->pixnb;
			}
		  for (j=1; j<=co; j++)
		    if (info[j].pixnb>maxpixnb)
		      maxpixnb = (victim = &info[j])->pixnb;
		  
		  if ((!maxpixnb) || (maxpixnb <= 1))
		    {
		      status = SEP_INTERNAL_ERROR;
		      goto exit;
		    }
		  freeinfo.firstpix = PLIST(pixel+victim->firstpix, nextpix);
		  PLIST(pixel+victim->lastpix, nextpix) = freeinfo.lastpix;
		  PLIST(pixel+(victim->lastpix=victim->firstpix), nextpix) = -1;
		  victim->pixnb = 1;
		  victim->flag |= SEP_OBJ_OVERFLOW;
		}
	      /*------------------------------------------------------------*/

	      /* if the current status on this line is not already OBJECT... */
	      /* start segment */
	      if (cs != OBJECT)
		{
		  cs = OBJECT;
		  if (ps == OBJECT)
		    {
		      if (start[co] == UNKNOWN)
			{
			  marker[xl] = 'S';
			  start[co] = xl;
			}
		      else
			marker[xl] = 's';
		    }
		  else
		    {
		      psstack[pstop++] = ps;
		      marker[xl] = 'S';
		      start[++co] = xl;
		      ps = COMPLETE;
		      info[co] = initinfo;
		    }
		}

	    } /* closes if pixel above threshold */

	  /* process new marker ---------------------------------------------*/
	  /* newmarker is marker[ ] at this pixel position before we got to
	     it. We'll only enter this if marker[ ] was set on a previous
	     loop iteration.   */
	  if (newmarker)
	    {
	      if (newmarker == 'S')
		{
		  psstack[pstop++] = ps;
		  if (cs == NONOBJECT)
		    {
		      psstack[pstop++] = COMPLETE;
		      info[++co] = store[xl];
		      start[co] = UNKNOWN;
		    }
		  else
		    update(&info[co], &store[xl], pixel);
		  ps = OBJECT;
		}

	      else if (newmarker == 's')
		{
		  if ((cs == OBJECT) && (ps == COMPLETE))
		    {
		      pstop--;
		      xl2 = start[co];
		      update (&info[co-1],&info[co], pixel);
		      if (start[--co] == UNKNOWN)
			start[co] = xl2;
		      else
			marker[xl2] = 's';
		    }
		  ps = OBJECT;
		}

	      else if (newmarker == 'f')
		ps = INCOMPLETE;

	      else if (newmarker == 'F')
		{
		  ps = psstack[--pstop];
		  if ((cs == NONOBJECT) && (ps == COMPLETE))
		    {
		      if (start[co] == UNKNOWN)
			{
			  if ((int)info[co].pixnb >= minarea)
			    {
			      status = sortit(&info[co], &objlist, minarea,
					      finalobjlist,
					      deblend_nthresh,deblend_mincont);
			      if (status != RETURN_OK)
				goto exit;
			    }

			  /* free the chain-list */
			  PLIST(pixel+info[co].lastpix, nextpix) =
			    freeinfo.firstpix;
			  freeinfo.firstpix = info[co].firstpix;
			}
		      else
			{
			  marker[end[co]] = 'F';
			  store[start[co]] = info[co];
			}
		      co--;
		      ps = psstack[--pstop];
		    }
		}
	    }
	  /* end of if (newmarker) ------------------------------------------*/

	  /* update the info or end segment */
	  if (luflag)
	    {
	      update(&info[co], &curpixinfo, pixel);
	    }
	  else if (cs == OBJECT)
	    {
	      cs = NONOBJECT;
	      if (ps != COMPLETE)
		{
		  marker[xl] = 'f';
		  end[co] = xl;
		}
	      else
		{
		  ps = psstack[--pstop];
		  marker[xl] = 'F';
		  store[start[co]] = info[co];
		  co--;
		}
	    }

	} /*------------ End of the loop over the x's -----------------------*/
    } /*---------------- End of the loop over the y's -----------------------*/

  /* convert `finalobjlist` to an array of `sepobj` structs */
  if (clean_flag)
    {
      /* Calculate mthresh for all objects in the list (needed for cleaning) */
      for (i=0; i<finalobjlist->nobj; i++)
	{
	  status = analysemthresh(i, finalobjlist, minarea, thresh);
	  if (status != RETURN_OK)
	    goto exit;
	}

      QMALLOC(survives, int, finalobjlist->nobj, status);
      clean(finalobjlist, clean_param, survives);

      /* count surviving objects and allocate space accordingly*/
      *nobj = 0;
      for (i=0; i<finalobjlist->nobj; i++)
	*nobj += survives[i];
      QMALLOC(*objects, sepobj, *nobj, status);

      /* fill */
      j=0;
      for (i=0; i<finalobjlist->nobj; i++)
	if (survives[i])
	    convertobj(i, finalobjlist, (*objects) + j++, w);
    }
  else
    {
Exemple #4
0
int analysemthresh(int objnb, objliststruct *objlist, int minarea,
		   PIXTYPE thresh)
{
  objstruct *obj = objlist->obj+objnb;
  pliststruct *pixel = objlist->plist;
  pliststruct *pixt;
  PIXTYPE tpix;
  float     *heap,*heapt,*heapj,*heapk, swap;
  int       j, k, h, status;

  status = RETURN_OK;
  heap = heapt = heapj = heapk = NULL;
  h = minarea;

  if (obj->fdnpix < minarea)
    {
      obj->mthresh = 0.0;
      return status;
    }

  QMALLOC(heap, float, minarea, status);
  heapt = heap;

  /*-- Find the minareath pixel in decreasing intensity for CLEANing */
  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
    {
      /* amount pixel is above threshold */
      tpix = PLISTPIX(pixt, cdvalue) - (PLISTEXIST(thresh)?
					PLISTPIX(pixt, thresh):thresh);
      if (h>0)
        *(heapt++) = (float)tpix;
      else if (h)
        {
	  if ((float)tpix>*heap)
	    {
	      *heap = (float)tpix;
	      for (j=0; (k=(j+1)<<1)<=minarea; j=k)
		{
		  heapk = heap+k;
		  heapj = heap+j;
		  if (k != minarea && *(heapk-1) > *heapk)
		    {
		      heapk++;
		      k++;
		    }
		  if (*heapj <= *(--heapk))
		    break;
		  swap = *heapk;
		  *heapk = *heapj;
		  *heapj = swap;
		}
	    }
        }
      else
        fqmedian(heap, minarea);
      h--;
    }

  obj->mthresh = *heap;

 exit:
  free(heap);
  return status;
}
Exemple #5
0
void  analyse(int no, objliststruct *objlist, int robust, double gain)
{
  objstruct	*obj = &objlist->obj[no];
  pliststruct	*pixel = objlist->plist, *pixt;
  PIXTYPE	peak, val, cval;
  double	thresh,thresh2, t1t2,darea,
                mx,my, mx2,my2,mxy, rv, rv2, tv,
		xm,ym, xm2,ym2,xym,
                temp,temp2, theta,pmx2,pmy2,
                errx2, erry2, errxy, cvar, cvarsum;
  int		x, y, xmin, ymin, area2, dnpix;

  preanalyse(no, objlist);
  
  dnpix = 0;
  mx = my = tv = 0.0;
  mx2 = my2 = mxy = 0.0;
  cvarsum = errx2 = erry2 = errxy = 0.0;
  thresh = obj->thresh;
  peak = obj->dpeak;
  rv = obj->fdflux;
  rv2 = rv * rv;
  thresh2 = (thresh + peak)/2.0;
  area2 = 0;
  
  xmin = obj->xmin;
  ymin = obj->ymin;

  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
    {
      x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
      y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */
      cval = PLISTPIX(pixt, cdvalue);
      tv += (val = PLISTPIX(pixt, value));
      if (val>thresh)
	dnpix++;
      if (val > thresh2)
	area2++;
      mx += cval * x;
      my += cval * y;
      mx2 += cval * x*x;
      my2 += cval * y*y;
      mxy += cval * x*y;

    }

  /* compute object's properties */
  xm = mx / rv;    /* mean x */
  ym = my / rv;    /* mean y */


  /* In case of blending, use previous barycenters */
  if ((robust) && (obj->flag & SEP_OBJ_MERGED))
    {
      double xn, yn;
	  
      xn = obj->mx-xmin;
      yn = obj->my-ymin;
      xm2 = mx2 / rv + xn*xn - 2*xm*xn;
      ym2 = my2 / rv + yn*yn - 2*ym*yn;
      xym = mxy / rv + xn*yn - xm*yn - xn*ym;
      xm = xn;
      ym = yn;
    }
  else
    {
      xm2 = mx2 / rv - xm * xm;	 /* variance of x */
      ym2 = my2 / rv - ym * ym;	 /* variance of y */
      xym = mxy / rv - xm * ym;	 /* covariance */

    }

  /* Calculate the errors on the variances */
  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
    {
      x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
      y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */

      cvar = PLISTEXIST(var)? PLISTPIX(pixt, var): 0.0;
      if (gain > 0.0) {  /* add poisson noise if given */
        cval = PLISTPIX(pixt, cdvalue);
        if (cval > 0.0) cvar += cval / gain;
      }

      /* Note that this works for both blended and non-blended cases
       * because xm is set to xn above for the blended case. */
      cvarsum += cvar;
      errx2 += cvar * (x - xm) * (x - xm);
      erry2 += cvar * (y - ym) * (y - ym);
      errxy += cvar * (x - xm) * (y - ym);
    }
  errx2 /= rv2;
  erry2 /= rv2;
  errxy /= rv2;

  /* Handle fully correlated x/y (which cause a singularity...) */
  if ((temp2=xm2*ym2-xym*xym)<0.00694)
    {
      xm2 += 0.0833333;
      ym2 += 0.0833333;
      temp2 = xm2*ym2-xym*xym;
      obj->flag |= SEP_OBJ_SINGU;

      /* handle it for the error parameters */
      cvarsum *= 0.08333/rv2;
      if (errx2*erry2 - errxy * errxy < cvarsum * cvarsum) {
        errx2 += cvarsum;
        erry2 += cvarsum;
      }
    }

  if ((fabs(temp=xm2-ym2)) > 0.0)
    theta = atan2(2.0 * xym, temp) / 2.0;
  else
    theta = PI/4.0;

  temp = sqrt(0.25*temp*temp+xym*xym);
  pmy2 = pmx2 = 0.5*(xm2+ym2);
  pmx2+=temp;
  pmy2-=temp;
  
  obj->dnpix = (LONG)dnpix;
  obj->dflux = tv;
  obj->mx = xm+xmin;	/* add back xmin */
  obj->my = ym+ymin;	/* add back ymin */
  obj->mx2 = xm2;
  obj->errx2 = errx2;
  obj->my2 = ym2;
  obj->erry2 = erry2;
  obj->mxy = xym;
  obj->errxy = errxy;
  obj->a = (float)sqrt(pmx2);
  obj->b = (float)sqrt(pmy2);
  obj->theta = theta;
  
  obj->cxx = (float)(ym2/temp2);
  obj->cyy = (float)(xm2/temp2);
  obj->cxy = (float)(-2*xym/temp2);
  
  darea = (double)area2 - dnpix;
  t1t2 = thresh/thresh2;

  /* debugging */
  /*if (t1t2>0.0 && !PLISTEXIST(thresh)) */  /* was: prefs.dweight_flag */
  if (t1t2 > 0.0)
    {
      obj->abcor = (darea<0.0?darea:-1.0)/(2*PI*log(t1t2<1.0?t1t2:0.99)
					   *obj->a*obj->b);
      if (obj->abcor>1.0)
	obj->abcor = 1.0;
    }
  else
    {
      obj->abcor = 1.0;
    }

  return;

}
Exemple #6
0
/*
compute some isophotal parameters IN THE MEASUREMENT image.
*/
void  examineiso(picstruct *field, picstruct *dfield, objstruct *obj,
		pliststruct *pixel)

  {
   checkstruct		*check;
   pliststruct		*pixt;
   int			i,j,k,h, photoflag,area,errflag, cleanflag,
			pospeakflag, profflag, minarea, gainflag;
   double		tv,sigtv, ngamma,
			esum, emx2,emy2,emxy, err,gain,backnoise2,dbacknoise2,
			xm,ym, x,y,var,var2, profflux,proffluxvar;
   float		*heap,*heapt,*heapj,*heapk, swap;
   PIXTYPE		pix, cdpix, tpix, peak,cdpeak, thresh,dthresh;
   static PIXTYPE	threshs[NISO];


  if (!dfield)
    dfield = field;

/* Prepare computation of positional error */
  esum = emx2 = emy2 = emxy = 0.0;
  if ((errflag=FLAG(obj.poserr_mx2)))
    {
    dbacknoise2 = dfield->backsig*dfield->backsig;
    xm = obj->mx;
    ym = obj->my;
    }
  else
    xm = ym = dbacknoise2 = 0.0;	/* to avoid gcc -Wall warnings */

  pospeakflag = FLAG(obj.peakx);
  profflag = FLAG(obj.flux_prof);
  gain = prefs.gain;
  ngamma = field->ngamma;
  photoflag = (prefs.detect_type==PHOTO);
  gainflag = PLISTEXIST(var) && prefs.weightgain_flag;

  h = minarea = prefs.ext_minarea;

/* Prepare selection of the heap selection for CLEANing */
  if ((cleanflag = prefs.clean_flag))
    {
    if (obj->fdnpix < minarea)
      {
      obj->mthresh = 0.0;
      cleanflag = 0;
      heapt = heap = NULL;		/* to avoid gcc -Wall warnings */
      }
    else
      {
      QMALLOC(heap, float, minarea);
      heapt = heap;
      }
    }
  else
    {
    obj->mthresh = 0.0;
    heapt = heap = NULL;		/* to avoid gcc -Wall warnings */
    }


/* Measure essential isophotal parameters in the measurement image... */
  tv = sigtv = profflux = proffluxvar = 0.0;
  var = backnoise2 = field->backsig*field->backsig;
  peak = -BIG;
  cdpeak = -BIG;
  thresh = field->thresh;
  dthresh = dfield->dthresh;
  area = 0;
  for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
    {
    pix = PLIST(pixt,value);
    if (pix>peak)
      peak = pix;

    cdpix=PLISTPIX(pixt,cdvalue);
    if (pospeakflag && cdpix>cdpeak)
      {
      cdpeak=cdpix;
      obj->peakx =  PLIST(pixt,x) + 1;
      obj->peaky =  PLIST(pixt,y) + 1;
      }
    if (PLISTEXIST(var))
      var = PLISTPIX(pixt, var);
    if (photoflag)
      {
      pix = exp(pix/ngamma);
      var2 = pix*pix*var;
      }
    else
      var2 = var;

    if (gainflag && pix>0.0 && gain>0.0)
      var2 += pix/gain*var/backnoise2;

    sigtv += var2;

    if (profflag && cdpix>0.0)
      {
      profflux += cdpix*pix;
      proffluxvar += cdpix*var2;
      }

    if (pix>thresh)
      area++;
    tv += pix;
    if (errflag)
      {
      err = dbacknoise2;
      if (gain>0.0 && cdpix>0.0)
        err += cdpix/gain;
      x = PLIST(pixt,x) - xm;
      y = PLIST(pixt,y) - ym;
      esum += err;
      emx2 += err*x*x;
      emy2 += err*y*y;
      emxy += err*x*y;
      }

/*-- Find the minareath pixel in decreasing intensity for CLEANing */
    if (cleanflag)
      {
      tpix = PLISTPIX(pixt, cdvalue) - (PLISTEXIST(dthresh)?
		PLISTPIX(pixt, dthresh):dthresh);
      if (h>0)
        *(heapt++) = (float)tpix;
      else if (h)
        {
        if ((float)tpix>*heap)
          {
          *heap = (float)tpix;
          for (j=0; (k=(j+1)<<1)<=minarea; j=k)
            {
            heapk = heap+k;
            heapj = heap+j;
            if (k != minarea && *(heapk-1) > *heapk)
              {
              heapk++;
              k++;
              }
            if (*heapj <= *(--heapk))
              break;
            swap = *heapk;
            *heapk = *heapj;
            *heapj = swap;
            }
          }
        }
      else
        hmedian(heap, minarea);
      h--;
      }
    }

/* Flagging from the flag-map */
  if (PLISTEXIST(flag))
    getflags(obj, pixel);

  if (cleanflag)
    {
    obj->mthresh = *heap;
    free(heap);
    }

  if (profflag)
    {
    obj->flux_prof = obj->fdflux>0.0? (float)(profflux/obj->fdflux) : 0.0;
    obj->fluxerr_prof = obj->fdflux>0.0? (float)(proffluxvar/obj->fdflux):0.0;
    }

  if (errflag)
    {
     double	flux2;

    flux2 = obj->fdflux*obj->fdflux;
/*-- Estimation of the error ellipse moments: we re-use previous variables */
    emx2 /= flux2;	/* variance of xm */
    emy2 /= flux2;	/* variance of ym */
    emxy /= flux2;	/* covariance */

/*-- Handle fully correlated profiles (which cause a singularity...) */
    esum *= 0.08333/flux2;
    if (obj->singuflag && (emx2*emy2-emxy*emxy) < esum*esum)
      {
      emx2 += esum;
      emy2 += esum;
      }

    obj->poserr_mx2 = emx2;
    obj->poserr_my2 = emy2;
    obj->poserr_mxy = emxy;
    }
 
  if (photoflag)
    {
    tv = ngamma*(tv-obj->fdnpix*exp(obj->dbkg/ngamma));
    sigtv /= ngamma*ngamma;
    }
  else
    {
    tv -= obj->fdnpix*obj->dbkg;
    if (!gainflag && gain > 0.0 && tv>0.0)
      sigtv += tv/gain;
    }

  obj->npix = area;
  obj->flux = tv;
  obj->fluxerr = sigtv;
  obj->peak = peak;

  obj->thresh -= obj->dbkg;
  obj->peak -= obj->dbkg;

/* Initialize isophotal thresholds so as to sample optimally the full profile*/

  if (FLAG(obj.iso[0]))
    {
     int	*iso;
     PIXTYPE	*thresht;

    memset(obj->iso, 0, NISO*sizeof(int));
    if (prefs.detect_type == PHOTO)
      for (i=0; i<NISO; i++)
        threshs[i] = obj->thresh + (obj->peak-obj->thresh)*i/NISO;
    else
      {
      if (obj->peak>0.0 && obj->thresh>0.0)
        for (i=0; i<NISO; i++)
          threshs[i] = obj->thresh*pow(obj->peak/obj->thresh, (double)i/NISO);
      else
        for (i=0; i<NISO; i++)
          threshs[i] = 0.0;
      }
    for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
      for (i=NISO,iso=obj->iso,thresht=threshs;
		i-- && PLIST(pixt,value)>*(thresht++);)
        (*(iso++))++;
    }

/* Put objects in "segmentation check-image" */

  if ((check = prefs.check[CHECK_SEGMENTATION]))
    for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
      ((ULONG *)check->pix)[check->width*PLIST(pixt,y)+PLIST(pixt,x)]
		= (ULONG)obj->number;

  if ((check = prefs.check[CHECK_OBJECTS]))
    for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
      ((PIXTYPE *)check->pix)[check->width*PLIST(pixt,y)+PLIST(pixt,x)]
		= PLIST(pixt,value);

/* Compute the FWHM of the object */
  if (FLAG(obj.fwhm))
    {
     PIXTYPE	thresh0;

    thresh0 = obj->peak/5.0;
    if (thresh0<obj->thresh)
      thresh0 = obj->thresh;
    if (thresh0>0.0)
      {
       double	mx,my, s,sx,sy,sxx,sxy, dx,dy,d2, lpix,pix, b, inverr2, sat,
		dbkg, d, bmax;

      mx = obj->mx;
      my = obj->my;
      dbkg = obj->dbkg;
      sat = (double)(prefs.satur_level - obj->bkg);
      s = sx = sy = sxx = sxy = 0.0;
      for (pixt=pixel+obj->firstpix;pixt>=pixel;pixt=pixel+PLIST(pixt,nextpix))
        {
        pix = PLIST(pixt,value)-dbkg;
        if (pix>thresh0 && pix<sat)
          {
          dx = PLIST(pixt,x) - mx;
          dy = PLIST(pixt,y) - my;
          lpix = log(pix);
          inverr2 = pix*pix;
          s += inverr2;
          d2 = dx*dx+dy*dy;
          sx += d2*inverr2;
          sxx += d2*d2*inverr2;
          sy += lpix*inverr2;
          sxy += lpix*d2*inverr2;
          }        
        }
      d = s*sxx-sx*sx;
      if (fabs(d)>0.0)
        {
        b = -(s*sxy-sx*sy)/d;
        if (b<(bmax = 1/(13*obj->a*obj->b)))	/* to have FWHM # 6 sigma */
          b = bmax;
        obj->fwhm = (float)(1.6651/sqrt(b));
/*----- correction for undersampling effects (established from simulations) */
        if (obj->fwhm>0.0)
          obj->fwhm -= 1/(4*obj->fwhm);
        }
      else
        obj->fwhm = 0.0;
      }
    else
      obj->fwhm = 0.0;
    }

  return;
  }