/*
* scan.c
*
* Main image scanning routines.
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* This file part of: SExtractor
*
* Copyright: (C) 1993,1998-2010 IAP/CNRS/UPMC
* (C) 1994,1997 ESO
* (C) 1995,1996 Sterrewacht Leiden
*
* Author: Emmanuel Bertin (IAP)
*
* License: GNU General Public License
*
* SExtractor 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 3 of the License, or
* (at your option) any later version.
* SExtractor 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 SExtractor. If not, see .
*
* Last modified: 11/10/2010
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include "define.h"
#include "globals.h"
#include "prefs.h"
#include "back.h"
#include "check.h"
#include "clean.h"
#include "extract.h"
#include "filter.h"
#include "image.h"
#include "plist.h"
#include "weight.h"
/****************************** 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 28/09/2010
***/
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, cdvar,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; iy = 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; xlconvh/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; istripy==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 (ylstrip[((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 (ylstrip[((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(cdvar = ((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 (ipixnb;
}
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= 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=cdwthresh)
PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
}
if (xl>0 && cdwscan[xl-1]>=cdwthresh)
PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
if (xl=cdwthresh)
PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
if (yl= cdwthresh)
PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
if (xl>0 && cdwscann[xl-1]>=cdwthresh)
PLISTFLAG(pixt, wflag) |= OBJ_LOWDWEIGHT;
if (xl=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 && xlyblank >= 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; istripy = (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);
lutzfree();
free(info);
free(store);
free(marker);
free(dumscan);
free(psstack);
free(start);
free(end);
if (prefs.blank_flag && prefs.filter_flag)
free(blankpad);
return;
}
/********************************* update ************************************/
/*
update object's properties each time one of its pixels is scanned by lutz()
*/
void update(infostruct *infoptr1, infostruct *infoptr2, pliststruct *pixel)
{
infoptr1->pixnb += infoptr2->pixnb;
infoptr1->flag |= infoptr2->flag;
if (infoptr1->firstpix == -1)
{
infoptr1->firstpix = infoptr2->firstpix;
infoptr1->lastpix = infoptr2->lastpix;
}
else if (infoptr2->lastpix != -1)
{
PLIST(pixel+infoptr1->lastpix, nextpix) = infoptr2->firstpix;
infoptr1->lastpix = infoptr2->lastpix;
}
return;
}
/********************************* sortit ************************************/
/*
build the object structure.
*/
void sortit(picstruct *field, picstruct *dfield, picstruct *wfield,
picstruct *dwfield, infostruct *info, objliststruct *objlist,
PIXTYPE *cdwscan, PIXTYPE *wscan)
{
picstruct *cfield;
objliststruct objlistout, *objlist2;
static objstruct obj;
objstruct *cobj;
pliststruct *pixel;
int i,j,n;
cfield = dfield? dfield: field;
pixel = objlist->plist;
objlistout.obj = NULL;
objlistout.plist = NULL;
objlistout.nobj = objlistout.npix = 0;
/*----- Allocate memory to store object data */
objlist->obj = &obj;
objlist->nobj = 1;
memset(&obj, 0, (size_t)sizeof(objstruct));
objlist->npix = info->pixnb;
obj.firstpix = info->firstpix;
obj.lastpix = info->lastpix;
obj.flag = info->flag;
obj.dthresh = objlist->dthresh;
obj.thresh = objlist->thresh;
preanalyse(0, objlist, ANALYSE_FAST);
/*----- Check if the current strip contains the lower isophote... */
if ((int)obj.ymin < cfield->ymin)
obj.flag |= OBJ_ISO_PB;
if (!(obj.flag & OBJ_OVERFLOW) && (createsubmap(objlist, 0) == RETURN_OK))
{
if (parcelout(objlist, &objlistout) == RETURN_OK)
objlist2 = &objlistout;
else
{
objlist2 = objlist;
for (i=0; inobj; i++)
objlist2->obj[i].flag |= OBJ_DOVERFLOW;
sprintf(gstr, "%.0f,%.0f", obj.mx+1, obj.my+1);
warning("Deblending overflow for detection at ", gstr);
}
free(obj.submap);
}
else
objlist2 = objlist;
for (i=0; inobj; i++)
{
preanalyse(i, objlist2, ANALYSE_FULL|ANALYSE_ROBUST);
if (prefs.ext_maxarea && objlist2->obj[i].fdnpix > prefs.ext_maxarea)
continue;
analyse(field, dfield, i, objlist2);
cobj = objlist2->obj + i;
if (prefs.blank_flag)
{
if (createblank(objlist2,i) != RETURN_OK)
{
/*------ Not enough mem. for the BLANK vignet: flag the object now */
cobj->flag |= OBJ_OVERFLOW;
cobj->blank = cobj->dblank = NULL;
sprintf(gstr, "%.0f,%.0f", cobj->mx+1, cobj->my+1);
warning("Memory overflow during masking for detection at ", gstr);
}
}
if ((n=cleanobjlist->nobj) >= prefs.clean_stacksize)
{
objstruct *cleanobj;
int ymin, ymax, victim=0;
ymin = 2000000000; /* No image is expected to be that tall ! */
cleanobj = cleanobjlist->obj;
for (j=0; jycmax < ymin)
{
victim = j;
ymin = cleanobj->ycmax;
}
/*---- Warn if there is a possibility for any aperture to be truncated */
if (field->ymax < field->height)
{
cleanobj = &cleanobjlist->obj[victim];
if ((ymax=cleanobj->ycmax) > field->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_OBJSTACK");
}
else if (ymax>field->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_OBJSTACK");
}
}
endobject(field, dfield, wfield, dwfield, victim, cleanobjlist);
subcleanobj(victim);
}
/* Only add the object if it is not swallowed by cleaning */
if (!prefs.clean_flag || clean(field, dfield, i, objlist2))
addcleanobj(cobj);
}
free(objlistout.plist);
free(objlistout.obj);
return;
}
/******************************** 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)) 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;
}