/* initialize check-image. */ checkstruct *initcheck(char *filename, checkenum check_type, int next) { catstruct *fitscat; checkstruct *check; QCALLOC(check, checkstruct, 1); strcpy(check->filename, filename); check->type = check_type; if (next>1) /*-- Create a "pure" primary HDU */ { fitscat = new_cat(1); init_cat(fitscat); strcpy(fitscat->filename, filename); fitsadd(fitscat->tab->headbuf, "NEXTEND ", "Number of extensions"); fitswrite(fitscat->tab->headbuf, "NEXTEND ", &next, H_INT, T_LONG); if (open_cat(fitscat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE,"*Error*: cannot open for writing ", filename); save_tab(fitscat, fitscat->tab); check->file = fitscat->file; fitscat->file = NULL; free_cat(&fitscat, 1); } else if (!(check->file = fopen(check->filename, "wb"))) error(EXIT_FAILURE, "*Error*: Cannot open for output ", check->filename); return check; }
/****** context_init ********************************************************* PROTO contextstruct *context_init(char **names, int *group, int ndim, int *degree, int ngroup, int pcexflag) PURPOSE Allocate and initialize a context structure. INPUT Pointer to an array of context names, Pointer to an array of group indices, Number of dependency parameters, Pointer to an array of group degrees, Number of groups, Principal Component exclusion flag. OUTPUT Pointer to an allocated context structure. NOTES See prefs.h. AUTHOR E. Bertin (IAP) VERSION 13/02/2009 */ contextstruct *context_init(char **names, int *group, int ndim, int *degree, int ngroup, int pcexflag) { contextstruct *context; int *groupflag, d,d2,g,g2, pcflag; QCALLOC(context, contextstruct, 1); QCALLOC(context->name, char *, ndim); QCALLOC(context->group, int, ndim); QCALLOC(context->degree, int, ndim); QCALLOC(context->pcflag, int, ndim); QCALLOC(groupflag, int, ndim); /* Copy context names and group indices ...*/ /* ... and remove Principal Components if asked to */ d2=0; for (d=0; d<ndim; d++) { if ((pcflag = !wstrncmp(names[d], "HIDDEN?", 80))) { context->npc++; if (!pcexflag) context->pcflag[d] = 1; } if (!pcexflag || !pcflag) { QMALLOC(context->name[d2], char, 80); strncpy(context->name[d2], names[d], 80); context->group[d2] = group[d]; groupflag[group[d]-1]++; d2++; } }
/****************************** 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 {
/********************************* 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; }
/* Read an assoc-list, and returns a pointer to the new assoc struct (or NULL if no list was found). */ assocstruct *load_assoc(char *filename, wcsstruct *wcs) { assocstruct *assoc; FILE *file; double *list, val; char str[MAXCHARL], str2[MAXCHARL], *sstr; int *data, i,ispoon,j,k,l, ncol, ndata, nlist, size,spoonsize, xindex,yindex,mindex; if (!(file = fopen(filename, "r"))) return NULL; QCALLOC(assoc, assocstruct, 1); list = NULL; /* To avoid gcc -Wall warnings */ data = NULL; /* To avoid gcc -Wall warnings */ ispoon = ncol = ndata = nlist = size = spoonsize = xindex = yindex = mindex = 0; NFPRINTF(OUTPUT, "Reading ASSOC input-list..."); for (i=0; fgets(str, MAXCHARL, file);) { /*-- Examine current input line (discard empty and comment lines) */ if (!*str || strchr("#\t\n",*str)) continue; if (!i) { strcpy(str2, str); /*---- Let's count the number of columns in the first line */ for (ncol=0; strtok(ncol?NULL:str2, " \t\v\n\r\f"); ncol++); if (!ncol) error(EXIT_FAILURE, "*Error*: empty line in ", filename); /*---- Build a look-up table containing the ordering of column data */ QCALLOC(data, int, ncol); k = 1; for (j=0; j<prefs.nassoc_data && k<=prefs.assoc_size; j++) if ((l=prefs.assoc_data[j]) && --l<ncol) data[l] = k++; ndata = k-1; if (!ndata) { ndata = ncol; if (prefs.assoc_size<ndata) ndata = prefs.assoc_size; for (j=0; j<ndata; j++) data[j] = j+1; } if (ndata<prefs.assoc_size) { sprintf(gstr, "no more than %d ASSOC parameters available: ", ncol); warning("VECTOR_ASSOC redimensioned: ", gstr); prefs.assoc_size = ndata; } if ((xindex = prefs.assoc_param[0]-1) >= ncol) error(EXIT_FAILURE, "*Error*: ASSOC_PARAMS #1 exceeds the number of ", "fields in the ASSOC file"); if ((yindex = prefs.assoc_param[1]-1) >= ncol) error(EXIT_FAILURE, "*Error*: ASSOC_PARAMS #2 exceeds the number of ", "fields in the ASSOC file"); if (prefs.nassoc_param>2) { if ((mindex = prefs.assoc_param[2]-1) >= ncol) error(EXIT_FAILURE,"*Error*: ASSOC_PARAMS #3 exceeds the number of ", "fields in the ASSOC file"); } else { mindex = -1; if (prefs.assoc_type == ASSOC_MEAN || prefs.assoc_type == ASSOC_MAGMEAN || prefs.assoc_type == ASSOC_MIN || prefs.assoc_type == ASSOC_MAX) { warning("ASSOC_PARAMS #3 missing,", " reverting to ASSOC_TYPE FIRST"); prefs.assoc_type = ASSOC_FIRST; } } nlist = ndata+3; /*---- Allocate memory for the filtered list */ ispoon = ASSOC_BUFINC/(nlist*sizeof(double)); spoonsize = ispoon*nlist; QMALLOC(assoc->list, double, size = spoonsize); list = assoc->list; } else if (!(i%ispoon))