/******************************* initclean ********************************** PROTO void initclean(void) PURPOSE Initialize things for CLEANing. INPUT -. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden & ESO) VERSION 03/07/97 ***/ void initclean(void) { if (prefs.clean_flag) QMALLOC(cleanvictim, LONG, prefs.clean_stacksize); QMALLOC(cleanobjlist, objliststruct, 1); cleanobjlist->obj = NULL; cleanobjlist->plist = NULL; cleanobjlist->nobj = cleanobjlist->npix = 0; return; }
/* Allocate memory and stuff for the PSF-fitting. */ void psf_init(void) { QMALLOC(thepsfit, psfitstruct, 1); QMALLOC(thepsfit->x, double, prefs.psf_npsfmax); QMALLOC(thepsfit->y, double, prefs.psf_npsfmax); QMALLOC(thepsfit->flux, float, prefs.psf_npsfmax); QMALLOC(thepsfit->fluxerr, float, prefs.psf_npsfmax); if (prefs.dpsf_flag) { QMALLOC(thedpsfit, psfitstruct, 1); QMALLOC(thedpsfit->x, double, prefs.psf_npsfmax); QMALLOC(thedpsfit->y, double, prefs.psf_npsfmax); QMALLOC(thedpsfit->flux, float, prefs.psf_npsfmax); QMALLOC(thedpsfit->fluxerr, float, prefs.psf_npsfmax); }
/****** init_xml ************************************************************ PROTO int init_xml(void) PURPOSE Initialize a set of meta-data kept in memory before being written to the XML file INPUT Number of image extensions. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 03/07/2006 ***/ int init_xml(int next) { QMALLOC(xmlstack, xmlstruct, next); nxml = 0; nxmlmax = next; return EXIT_SUCCESS; }
/* Init resources required for data interpolation. */ void init_interpolate(picstruct *field, int xtimeout, int ytimeout) { QMALLOC(field->interp_backup, PIXTYPE, field->width); /* ytimeout < 0 means we don't need a timeout buffer (it won't be used) */ if (ytimeout>=0) { QMALLOC(field->interp_ytimeoutbuf, int, field->width); memset(field->interp_ytimeoutbuf, 0, (size_t)(field->width*sizeof(int))); }
/* Allocate once for all memory space for buffers used by lutz(). */ void lutzalloc(int width, int height) { int *discant, stacksize, i; stacksize = width+1; xmin = ymin = 0; xmax = width-1; ymax = height-1; QMALLOC(info, infostruct, stacksize); QMALLOC(store, infostruct, stacksize); QMALLOC(marker, char, stacksize); QMALLOC(psstack, status, stacksize); QMALLOC(start, int, stacksize); QMALLOC(end, int, stacksize); QMALLOC(discan, int, stacksize); discant = discan; for (i=stacksize; i--;) *(discant++) = -1; 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; }
/* initialize check-image (for subsequent writing). */ void reinitcheck(picstruct *field, checkstruct *check) { wcsstruct *wcs; char *buf; int i, ival; size_t padsize; double dval; ULONG *ptri; PIXTYPE *ptrf; /* Inherit the field FITS header */ check->fitsheadsize = field->tab->headnblock*FBSIZE; QMEMCPY(field->tab->headbuf, check->fitshead, char, check->fitsheadsize); check->y = 0; /* Neutralize possible scaling factors */ dval = 1.0;fitswrite(check->fitshead, "BSCALE ", &dval, H_FLOAT, T_DOUBLE); dval = 0.0;fitswrite(check->fitshead, "BZERO ", &dval, H_FLOAT, T_DOUBLE); ival = 1;fitswrite(check->fitshead, "BITSGN ", &ival, H_INT, T_LONG); if (field->tab->compress_type != COMPRESS_NONE) fitswrite(check->fitshead, "IMAGECOD", (void*)"NONE", H_STRING, T_STRING); fitswrite(check->fitshead, "ORIGIN ", (void*)BANNER, H_STRING, T_STRING); switch(check->type) { case CHECK_IDENTICAL: case CHECK_BACKGROUND: case CHECK_FILTERED: case CHECK_SUBTRACTED: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; QMALLOC(ptrf, PIXTYPE, check->width); check->pix = (void *)ptrf; QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); break; case CHECK_BACKRMS: case CHECK_SUBOBJECTS: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; QMALLOC(ptrf, PIXTYPE, check->width); check->pix = (void *)ptrf; QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); /*---- Allocate memory for replacing the blanked pixels by 0 */ if (!check->line) QMALLOC(check->line, PIXTYPE, field->width); break; case CHECK_OBJECTS: case CHECK_APERTURES: case CHECK_SUBPSFPROTOS: case CHECK_PSFPROTOS: case CHECK_SUBPCPROTOS: case CHECK_PCPROTOS: case CHECK_PCOPROTOS: case CHECK_SUBPROFILES: case CHECK_PROFILES: case CHECK_PATTERNS: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; check->overlay = 30*field->backsig; QCALLOC(ptrf, PIXTYPE, check->npix); check->pix = (void *)ptrf; QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); break; case CHECK_SEGMENTATION: ival = 32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; QCALLOC(ptri, ULONG, check->npix); check->pix = (void *)ptri; QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); break; case CHECK_ASSOC: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; QMALLOC(ptrf, PIXTYPE, check->npix); check->pix = (void *)ptrf; /*---- Initialize the pixmap to IEEE NaN */ memset(ptrf, 0xFF, check->npix*sizeof(LONG)); QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); break; case CHECK_MINIBACKGROUND: case CHECK_MINIBACKRMS: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->nbackx; fitswrite(check->fitshead, "NAXIS1 ", &check->width, H_INT, T_LONG); check->height = field->nbacky; fitswrite(check->fitshead, "NAXIS2 ", &check->height, H_INT, T_LONG); /*---- Scale the WCS information if present */ if ((wcs=field->wcs)) { dval = wcs->cdelt[0]*field->backw; fitswrite(check->fitshead, "CDELT1 ", &dval, H_EXPO, T_DOUBLE); dval = wcs->cdelt[1]*field->backh; fitswrite(check->fitshead, "CDELT2 ", &dval, H_EXPO, T_DOUBLE); dval = (wcs->crpix[0]-0.5)/field->backw + 0.5; fitswrite(check->fitshead, "CRPIX1 ", &dval, H_EXPO, T_DOUBLE); dval = (wcs->crpix[1]-0.5)/field->backh + 0.5; fitswrite(check->fitshead, "CRPIX2 ", &dval, H_EXPO, T_DOUBLE); dval = wcs->cd[0]*field->backw; fitswrite(check->fitshead, "CD1_1 ", &dval, H_EXPO, T_DOUBLE); dval = wcs->cd[1]*field->backh; fitswrite(check->fitshead, "CD1_2 ", &dval, H_EXPO, T_DOUBLE); dval = wcs->cd[wcs->naxis]*field->backw; fitswrite(check->fitshead, "CD2_1 ", &dval, H_EXPO, T_DOUBLE); dval = wcs->cd[wcs->naxis+1]*field->backh; fitswrite(check->fitshead, "CD2_2 ", &dval, H_EXPO, T_DOUBLE); } check->npix = check->width*check->height; QMALLOC(ptrf, PIXTYPE, check->npix); check->pix = (void *)ptrf; if (check->type==CHECK_MINIBACKRMS) memcpy(check->pix, field->sigma, check->npix*sizeof(float)); else memcpy(check->pix, field->back, check->npix*sizeof(float)); QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); if (bswapflag) swapbytes(check->pix, sizeof(float), (int)check->npix); QFWRITE(check->pix,check->npix*sizeof(float),check->file, check->filename); /*---- Put the buffer back to its original state */ if (bswapflag) swapbytes(check->pix, sizeof(float), (int)check->npix); free(check->pix); QCALLOC(buf, char, FBSIZE); padsize = (FBSIZE -((check->npix*sizeof(PIXTYPE))%FBSIZE))% FBSIZE; if (padsize) QFWRITE (buf, padsize, check->file, check->filename); free(buf); break; case CHECK_MAPSOM: ival = -32; fitswrite(check->fitshead, "BITPIX ", &ival, H_INT, T_LONG); check->width = field->width; check->height = field->height; check->npix = field->npix; QMALLOC(ptrf, PIXTYPE, check->npix); check->pix = (void *)ptrf; for (i=check->npix; i--;) *(ptrf++) = -10.0; QFWRITE(check->fitshead,check->fitsheadsize,check->file,check->filename); free(check->fitshead); break; default: error(EXIT_FAILURE, "*Internal Error* in ", "reinitcheck()!"); } 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 {
/* Background maps are established from the images themselves; thus we need to make at least one first pass through the data. */ void makeback(picstruct *field, picstruct *wfield, int wscale_flag) { backstruct *backmesh,*wbackmesh, *bm,*wbm; PIXTYPE *buf,*wbuf, *buft,*wbuft; OFF_T fcurpos,wfcurpos, wfcurpos2,fcurpos2, bufshift, jumpsize; size_t bufsize, bufsize2, size,meshsize; int i,j,k,m,n, step, nlines, w,bw, bh, nx,ny,nb, lflag, nr; float *ratio,*ratiop, *weight, *sigma, sratio, sigfac; /* If the weight-map is not an external one, no stats are needed for it */ if (wfield && wfield->flags&(INTERP_FIELD|BACKRMS_FIELD)) wfield= NULL; w = field->width; bw = field->backw; bh = field->backh; nx = field->nbackx; ny = field->nbacky; nb = field->nback; NFPRINTF(OUTPUT, "Setting up background maps"); /* Decide if it is worth displaying progress each 16 lines */ lflag = (field->width*field->backh >= (size_t)65536); /* Save current positions in files */ wfcurpos = wfcurpos2 = 0; /* to avoid gcc -Wall warnings */ NDFQFTELL(field->file, fcurpos, field->filename); if (wfield) NDFQFTELL(wfield->file, wfcurpos, wfield->filename); /* Allocate a correct amount of memory to store pixels */ bufsize = (OFF_T)w*bh; meshsize = (size_t)bufsize; nlines = 0; if (bufsize > (size_t)BACK_BUFSIZE) { nlines = BACK_BUFSIZE/w; step = (field->backh-1)/nlines+1; bufsize = (size_t)(nlines = field->backh/step)*w; bufshift = (step/2)*(OFF_T)w; jumpsize = (step-1)*(OFF_T)w; } else bufshift = jumpsize = 0; /* to avoid gcc -Wall warnings */ /* Allocate some memory */ QMALLOC(backmesh, backstruct, nx); /* background information */ QMALLOC(buf, PIXTYPE, bufsize); /* pixel buffer */ free(field->back); QMALLOC(field->back, float, nb); /* background map */ free(field->backline); QMALLOC(field->backline, PIXTYPE, w); /* current background line */ free(field->sigma); QMALLOC(field->sigma, float, nb); /* sigma map */ if (wfield) { QMALLOC(wbackmesh, backstruct, nx); /* background information */ QMALLOC(wbuf, PIXTYPE, bufsize); /* pixel buffer */ free(wfield->back); QMALLOC(wfield->back, float, nb); /* background map */ free(wfield->backline); QMALLOC(wfield->backline, PIXTYPE, w); /* current background line */ free(wfield->sigma); QMALLOC(wfield->sigma, float, nb); /* sigma map */ wfield->sigfac = 1.0; } else {