/* Create pixel-index submap for deblending. */ int *createsubmap(objliststruct *objlistin, int no, int *subx, int *suby, int *subw, int *subh) { objstruct *obj; pliststruct *pixel, *pixt; int i, n, xmin,ymin, w, *pix, *pt, *submap; obj = objlistin->obj+no; pixel = objlistin->plist; *subx = xmin = obj->xmin; *suby = ymin = obj->ymin; *subw = w = obj->xmax - xmin + 1; *subh = obj->ymax - ymin + 1; n = w**subh; if (!(submap = pix = (int *)malloc(n*sizeof(int)))) return NULL; pt = pix; for (i=n; i--;) *(pt++) = -1; for (i=obj->firstpix; i!=-1; i=PLIST(pixt,nextpix)) { pixt = pixel+i; *(pix+(PLIST(pixt,x)-xmin) + (PLIST(pixt,y)-ymin)*w) = i; } return submap; }
static void flag_satur(objstruct *obj, pliststruct *pixel) { int x,y; pliststruct *pixt; if (!prefs.user_ana2 || (obj->peak+obj->bkg < prefs.satur_level)) return; for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) { x = PLIST(pixt,x); y = PLIST(pixt,y); prefs.user_ana2(x,y); } }
int belong(int corenb, objliststruct *coreobjlist, int shellnb, objliststruct *shellobjlist) { objstruct *cobj = &(coreobjlist->obj[corenb]), *sobj = &(shellobjlist->obj[shellnb]); pliststruct *cpl = coreobjlist->plist, *spl = shellobjlist->plist, *pixt; int xc=PLIST(cpl+cobj->firstpix,x), yc=PLIST(cpl+cobj->firstpix,y); for (pixt = spl+sobj->firstpix; pixt>=spl; pixt = spl+PLIST(pixt,nextpix)) if ((PLIST(pixt,x) == xc) && (PLIST(pixt,y) == yc)) return 1; return 0; }
void inverter_realloc(Inverter_t * v, uint32_t i) { uint32_t p1 = 1 + (100 * (v->ppool - v->pool)) / v->maxpool; uint32_t p2 = 1 + (100 * v->count) / MAX_COUNT; uint32_t oldsize = (char *) PLIST(v->record[i]) - v->record[i]; uint32_t newsize = (150 * oldsize) / MAX(p1, p2); char *p = v->ppool + 2 * sizeof(uint32_t *); v->ppool = p + newsize; memcpy(p, v->record[i], oldsize); PLIST(p) = (uint32_t *) (p + oldsize); PEND(p) = (uint32_t *) (p + newsize); v->record[i] = p; }
int inverter_write(Inverter_t * v, FILE * fp) { uint32_t i, size; inverter_compact(v); radixsort(v->record, 0, v->count - 1, 0); for (i = 0; i < v->count; i++) { *PLIST(v->record[i])++ = EMPTY; size = (char *) PLIST(v->record[i]) - v->record[i]; if (fwrite(&size, sizeof(uint32_t), 1, fp) != 1) return 0; /* can't write */ if (fwrite(v->record[i], size, 1, fp) != 1) return 0; /* can't write */ } inverter_clear(v); return 1; }
/* insert term/docid pair into inverter */ void inverter_insert(Inverter_t * v, const char *term, uint32_t docid) { uint32_t i; if (v->record == NULL) inverter_alloc(v); i = inverter_lookup(v, term); if (v->record[i] == NULL) { alloc(v, i, term); *PLIST(v->record[i])++ = docid; v->count++; return; } if (docid > PLIST(v->record[i])[-1]) { if (PLIST(v->record[i]) >= PEND(v->record[i]) - 1) inverter_realloc(v, i); *PLIST(v->record[i])++ = docid; } }
void alloc(Inverter_t * v, uint32_t i, const char *term) { char *p = v->ppool + 2 * sizeof(uint32_t *); char *pterm = p; while (*pterm++ = *term++); v->ppool = pterm + INITIAL_SIZE; PLIST(p) = (uint32_t *) pterm; PEND(p) = (uint32_t *) v->ppool; v->record[i] = p; }
/* 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; }
/****************************** 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; }
/****************************** 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 {
/********************************* getflags ********************************* PROTO void getflags(objstruct *obj, pliststruct *pixel) PURPOSE Return the composited flags extracted from the flag-maps. INPUT obj structure, pixel list. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden & ESO) VERSION 18/11/98 ***/ void getflags(objstruct *obj, pliststruct *pixel) { pliststruct *pixt; FLAGTYPE imaflag,cimaflag, *flagstack, *fs; int i,n,nmax,nc,nflag,nflag0, *nflagstack, *nfs; for (i=0; i<prefs.nimaisoflag; i++) { nmax = 0; imaflag = 0; switch(prefs.flag_type[i]) { case FLAG_OR: for (pixt=pixel+obj->firstpix;pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) if ((cimaflag = PLISTFLAG(pixt,flag[i]))) { imaflag |= cimaflag; nmax++; } break; case FLAG_AND: for (pixt=pixel+obj->firstpix;pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) if ((cimaflag = PLISTFLAG(pixt,flag[i]))) { imaflag &= cimaflag; nmax++; } break; case FLAG_MIN: imaflag = UINT_MAX; for (pixt=pixel+obj->firstpix;pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) if ((cimaflag = PLISTFLAG(pixt,flag[i]))) { if (cimaflag<imaflag) { imaflag = cimaflag; nmax = 1; } else if (cimaflag==imaflag) nmax++; } if (!nmax) imaflag = 0; break; case FLAG_MAX: imaflag = 0; for (pixt=pixel+obj->firstpix;pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) if ((cimaflag = PLISTFLAG(pixt,flag[i]))) { if (cimaflag>imaflag) { imaflag = cimaflag; nmax = 1; } else if (cimaflag==imaflag) nmax++; } if (!nmax) imaflag = 0; break; case FLAG_MOST: /*------ Allocate memory for the buffers */ nflag = FLAG_BUFSIZE; QCALLOC(flagstack, FLAGTYPE, nflag); QCALLOC(nflagstack, int, nflag); /*------ Count flag values */ for (pixt=pixel+obj->firstpix;pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix)) if ((cimaflag = PLISTFLAG(pixt,flag[i]))) { for (n=nflag, fs=flagstack, nfs=nflagstack; n-- && *nfs; nfs++) if (*(fs++) == cimaflag) { (*nfs)++; break; } if (n<0) { nflag0 = nflag; nflag += FLAG_BUFSIZE; QREALLOC(flagstack, FLAGTYPE, nflag) fs = flagstack + nflag0; memset(fs, 0, (size_t)FLAG_BUFSIZE*sizeof(FLAGTYPE)); QREALLOC(nflagstack, int, nflag) nfs = nflagstack + nflag0; memset(nfs, 0, (size_t)FLAG_BUFSIZE*sizeof(int)); } if (!*nfs) { *fs = cimaflag; *nfs = 1; } } /*------ Explore the list we have built and search for most frequent flags */ for (n=nflag, fs=flagstack, nfs=nflagstack; n-- && *nfs; fs++) if ((nc=*(nfs++))>nmax) { nmax = nc; imaflag = *fs; } /*------ Free memory allocated for the buffers */ free(flagstack); free(nflagstack); break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown FLAG_TYPE",""); } if (i<prefs.imaflag_size) obj->imaflag[i] = imaflag; if (i<prefs.imanflag_size) obj->imanflag[i] = nmax; }
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; }
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; }
void preanalyse(int no, objliststruct *objlist) { objstruct *obj = &objlist->obj[no]; pliststruct *pixel = objlist->plist, *pixt; PIXTYPE peak, cpeak, val, cval; double rv; int x, y, xmin,xmax, ymin,ymax, fdnpix; int xpeak, ypeak, xcpeak, ycpeak; /*----- initialize stacks and bounds */ fdnpix = 0; rv = 0.0; peak = cpeak = -BIG; ymin = xmin = 2*MAXPICSIZE; /* to be really sure!! */ ymax = xmax = 0; xpeak = ypeak = xcpeak = ycpeak = 0; /* avoid -Wall warnings */ /*----- 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, value); cval = PLISTPIX(pixt, cdvalue); if (peak < val) { peak = val; xpeak = x; ypeak = y; } if (cpeak < cval) { cpeak = cval; xcpeak = x; ycpeak = y; } rv += cval; if (xmin > x) xmin = x; if (xmax < x) xmax = x; if (ymin > y) ymin = y; if (ymax < y) ymax = y; fdnpix++; } obj->fdnpix = (LONG)fdnpix; obj->fdflux = (float)rv; obj->fdpeak = cpeak; obj->dpeak = peak; obj->xpeak = xpeak; obj->ypeak = ypeak; obj->xcpeak = xcpeak; obj->ycpeak = ycpeak; obj->xmin = xmin; obj->xmax = xmax; obj->ymin = ymin; obj->ymax = ymax; return; }
/* 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; }
/* C implementation of R.K LUTZ' algorithm for the extraction of 8-connected pi- xels in an image */ int lutz(objliststruct *objlistroot, int nroot, objstruct *objparent, objliststruct *objlist) { static infostruct curpixinfo,initinfo; objstruct *obj, *objroot; pliststruct *plist,*pixel, *plistin, *plistint; char newmarker; int cn, co, luflag, objnb, pstop, xl,xl2,yl, out, minarea, stx,sty,enx,eny, step, nobjm = NOBJ, inewsymbol, *iscan; short trunflag; PIXTYPE thresh; status cs, ps; out = RETURN_OK; minarea = prefs.deb_maxarea; plistint = plistin = objlistroot->plist; objroot = &objlistroot->obj[nroot]; stx = objparent->xmin; sty = objparent->ymin; enx = objparent->xmax; eny = objparent->ymax; thresh = objlist->dthresh; initinfo.pixnb = 0; initinfo.flag = 0; initinfo.firstpix = initinfo.lastpix = -1; cn = 0; iscan = objroot->submap + (sty-objroot->suby)*objroot->subw + (stx-objroot->subx); /* As we only analyse a fraction of the map, a step occurs between lines */ step = objroot->subw - (++enx-stx); eny++; /*------Allocate memory to store object data */ free(objlist->obj); if (!(obj=objlist->obj=(objstruct *)malloc(nobjm*sizeof(objstruct)))) { out = RETURN_FATAL_ERROR; plist = NULL; /* To avoid gcc -Wall warnings */ goto exit_lutz; } /*------Allocate memory for the pixel list */ free(objlist->plist); if (!(objlist->plist = (pliststruct *)malloc((eny-sty)*(enx-stx)*plistsize))) { out = RETURN_FATAL_ERROR; plist = NULL; /* To avoid gcc -Wall warnings */ goto exit_lutz; } pixel = plist = objlist->plist; /*----------------------------------------*/ for (xl=stx; xl<=enx; xl++) marker[xl] = 0 ; objnb = objlist->nobj = 0; co = pstop = 0; curpixinfo.pixnb = 1; for (yl=sty; yl<=eny; yl++, iscan += step) { ps = COMPLETE; cs = NONOBJECT; trunflag = (yl==0 || yl==ymax) ? OBJ_TRUNC : 0; if (yl==eny) iscan = discan; for (xl=stx; xl<=enx; xl++) { newmarker = marker[xl]; marker[xl] = 0; if ((inewsymbol = (xl!=enx)?*(iscan++):-1) < 0) luflag = 0; else { curpixinfo.flag = trunflag; plistint = plistin+inewsymbol; luflag = (PLISTPIX(plistint, cdvalue) > thresh?1:0); } if (luflag) { if (xl==0 || xl==xmax) curpixinfo.flag |= OBJ_TRUNC; memcpy(pixel, plistint, (size_t)plistsize); PLIST(pixel, nextpix) = -1; curpixinfo.lastpix = curpixinfo.firstpix = cn; cn += plistsize; pixel += plistsize; 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], plist); ps = OBJECT; } else if (newmarker == 's') { if ((cs == OBJECT) && (ps == COMPLETE)) { pstop--; xl2 = start[co]; update (&info[co-1],&info[co], plist); 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) { if (objlist->nobj>=nobjm) if (!(obj = objlist->obj = (objstruct *) realloc(obj, (nobjm+=nobjm/2)* sizeof(objstruct)))) { out = RETURN_FATAL_ERROR; goto exit_lutz; } lutzsort(&info[co], objlist); } } else { marker[end[co]] = 'F'; store[start[co]] = info[co]; } co--; ps = psstack[--pstop]; } } } /*---------------------------------------------------------------------------*/ if (luflag) update (&info[co],&curpixinfo, plist); 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--; } } } /*---------------------------------------------------------------------------*/ } } exit_lutz: if (objlist->nobj && out == RETURN_OK) { if (!(objlist->obj=(objstruct *)realloc(obj, objlist->nobj*sizeof(objstruct)))) error(EXIT_FAILURE,"problem with mem. realloc. in lutz()",""); } else { free(obj); objlist->obj = NULL; } if (cn && out == RETURN_OK) { if (!(objlist->plist=(pliststruct *)realloc(plist,cn))) error(EXIT_FAILURE,"problem with mem. realloc. in lutz()",""); } else { free(objlist->plist); objlist->plist = NULL; } return out; }
/******************************** 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; }
/* Collect faint remaining pixels and allocate them to their most probable progenitor. */ int gatherup(objliststruct *objlistin, objliststruct *objlistout) { char *bmp; float *amp, *p, dx,dy, drand, dist, distmin; objstruct *objin = objlistin->obj, *objout, *objt; pliststruct *pixelin = objlistin->plist, *pixelout, *pixt,*pixt2; int i,k,l, *n, iclst, npix, bmwidth, nobj = objlistin->nobj, xs,ys, x,y, status; bmp = NULL; amp = p = NULL; n = NULL; status = RETURN_OK; objlistout->thresh = objlistin->thresh; QMALLOC(amp, float, nobj, status); QMALLOC(p, float, nobj, status); QMALLOC(n, int, nobj, status); for (i=1; i<nobj; i++) analyse(i, objlistin, 0); p[0] = 0.0; bmwidth = objin->xmax - (xs=objin->xmin) + 1; npix = bmwidth * (objin->ymax - (ys=objin->ymin) + 1); if (!(bmp = (char *)calloc(1, npix*sizeof(char)))) { bmp = NULL; status = MEMORY_ALLOC_ERROR; goto exit; } for (objt = objin+(i=1); i<nobj; i++, objt++) { /*-- Now we have passed the deblending section, reset threshold */ objt->thresh = objlistin->thresh; /* ------------ flag pixels which are already allocated */ for (pixt=pixelin+objin[i].firstpix; pixt>=pixelin; pixt=pixelin+PLIST(pixt,nextpix)) bmp[(PLIST(pixt,x)-xs) + (PLIST(pixt,y)-ys)*bmwidth] = '\1'; status = addobjdeep(i, objlistin, objlistout); if (status != RETURN_OK) goto exit; n[i] = objlistout->nobj - 1; dist = objt->fdnpix/(2*PI*objt->abcor*objt->a*objt->b); amp[i] = dist<70.0? objt->thresh * expf(dist) : 4.0*objt->fdpeak; /* ------------ limitate expansion ! */ if (amp[i]>4.0*objt->fdpeak) amp[i] = 4.0*objt->fdpeak; } objout = objlistout->obj; /* DO NOT MOVE !!! */ if (!(pixelout=(pliststruct *)realloc(objlistout->plist, (objlistout->npix + npix)*plistsize))) { status = MEMORY_ALLOC_ERROR; goto exit; } objlistout->plist = pixelout; k = objlistout->npix; iclst = 0; /* To avoid gcc -Wall warnings */ for (pixt=pixelin+objin->firstpix; pixt>=pixelin; pixt=pixelin+PLIST(pixt,nextpix)) { x = PLIST(pixt,x); y = PLIST(pixt,y); if (!bmp[(x-xs) + (y-ys)*bmwidth]) { pixt2 = pixelout + (l=(k++*plistsize)); memcpy(pixt2, pixt, (size_t)plistsize); PLIST(pixt2, nextpix) = -1; distmin = 1e+31; for (objt = objin+(i=1); i<nobj; i++, objt++) { dx = x - objt->mx; dy = y - objt->my; dist=0.5*(objt->cxx*dx*dx+objt->cyy*dy*dy+objt->cxy*dx*dy)/objt->abcor; p[i] = p[i-1] + (dist<70.0?amp[i]*expf(-dist) : 0.0); if (dist<distmin) { distmin = dist; iclst = i; } } if (p[nobj-1] > 1.0e-31) { drand = p[nobj-1]*rand()/RAND_MAX; for (i=1; i<nobj && p[i]<drand; i++); if (i==nobj) i=iclst; } else i = iclst; objout[n[i]].lastpix=PLIST(pixelout+objout[n[i]].lastpix,nextpix)=l; } } objlistout->npix = k; if (!(objlistout->plist = (pliststruct *)realloc(pixelout, objlistout->npix*plistsize))) status = MEMORY_ALLOC_ERROR; exit: free(bmp); free(amp); free(p); free(n); return status; }