/* build the object structure. */ void sortit(picstruct *field, picstruct *dfield, picstruct *wfield, picstruct *dwfield, infostruct *info, objliststruct *objlist, PIXTYPE *cdwscan, PIXTYPE *wscan) { picstruct *cfield; objliststruct objlistout, *objlist2; static objstruct obj; objstruct *cobj; pliststruct *pixel; int i,j,n; cfield = dfield? dfield: field; pixel = objlist->plist; objlistout.obj = NULL; objlistout.plist = NULL; objlistout.nobj = objlistout.npix = 0; /*----- Allocate memory to store object data */ objlist->obj = &obj; objlist->nobj = 1; memset(&obj, 0, (size_t)sizeof(objstruct)); objlist->npix = info->pixnb; obj.firstpix = info->firstpix; obj.lastpix = info->lastpix; obj.flag = info->flag; obj.dthresh = objlist->dthresh; obj.thresh = objlist->thresh; preanalyse(0, objlist, ANALYSE_FAST); /*----- Check if the current strip contains the lower isophote... */ if ((int)obj.ymin < cfield->ymin) obj.flag |= OBJ_ISO_PB; if (!(obj.flag & OBJ_OVERFLOW) && (createsubmap(objlist, 0) == RETURN_OK)) { if (parcelout(objlist, &objlistout) == RETURN_OK) objlist2 = &objlistout; else { objlist2 = objlist; for (i=0; i<objlist2->nobj; i++) objlist2->obj[i].flag |= OBJ_DOVERFLOW; sprintf(gstr, "%.0f,%.0f", obj.mx+1, obj.my+1); warning("Deblending overflow for detection at ", gstr); } free(obj.submap); } else objlist2 = objlist; for (i=0; i<objlist2->nobj; i++) { preanalyse(i, objlist2, ANALYSE_FULL|ANALYSE_ROBUST); if (prefs.ext_maxarea && objlist2->obj[i].fdnpix > prefs.ext_maxarea) continue; analyse(field, dfield, i, objlist2); cobj = objlist2->obj + i; if (prefs.blank_flag) { if (createblank(objlist2,i) != RETURN_OK) { /*------ Not enough mem. for the BLANK vignet: flag the object now */ cobj->flag |= OBJ_OVERFLOW; cobj->blank = cobj->dblank = NULL; sprintf(gstr, "%.0f,%.0f", cobj->mx+1, cobj->my+1); warning("Memory overflow during masking for detection at ", gstr); } } if ((n=cleanobjlist->nobj) >= prefs.clean_stacksize) { objstruct *cleanobj; int ymin, ymax, victim=0; ymin = 2000000000; /* No image is expected to be that tall ! */ cleanobj = cleanobjlist->obj; for (j=0; j<n; j++, cleanobj++) if (cleanobj->ycmax < ymin) { victim = j; ymin = cleanobj->ycmax; } /*---- Warn if there is a possibility for any aperture to be truncated */ if (field->ymax < field->height) { cleanobj = &cleanobjlist->obj[victim]; if ((ymax=cleanobj->ycmax) > field->ymax) { sprintf(gstr, "Object at position %.0f,%.0f ", cleanobj->mx+1, cleanobj->my+1); QWARNING(gstr, "may have some apertures truncated:\n" " You might want to increase MEMORY_OBJSTACK"); } else if (ymax>field->yblank && prefs.blank_flag) { sprintf(gstr, "Object at position %.0f,%.0f ", cleanobj->mx+1, cleanobj->my+1); QWARNING(gstr, "may have some unBLANKed neighbours\n" " You might want to increase MEMORY_OBJSTACK"); } } endobject(field, dfield, wfield, dwfield, victim, cleanobjlist); subcleanobj(victim); } /* Only add the object if it is not swallowed by cleaning */ if (!prefs.clean_flag || clean(field, dfield, i, objlist2)) addcleanobj(cobj); } free(objlistout.plist); free(objlistout.obj); return; }
/* Divide a list of isophotal detections in several parts (deblending). NOTE: Even if the object is not deblended, the output objlist threshold is recomputed if a variable threshold is used. This can return two error codes: DEBLEND_OVERFLOW or MEMORY_ALLOC_ERROR */ int deblend(objliststruct *objlistin, int l, objliststruct *objlistout, int deblend_nthresh, double deblend_mincont, int minarea) { objstruct *obj; static objliststruct debobjlist, debobjlist2; double thresh, thresh0, value0; int h,i,j,k,m,subx,suby,subh,subw, xn, nbm = NBRANCH, status; int *submap; submap = NULL; status = RETURN_OK; xn = deblend_nthresh; /* reset global static objlist for deblending */ memset(objlist, 0, (size_t)xn*sizeof(objliststruct)); /* initialize local object lists */ debobjlist.obj = debobjlist2.obj = NULL; debobjlist.plist = debobjlist2.plist = NULL; debobjlist.nobj = debobjlist2.nobj = 0; debobjlist.npix = debobjlist2.npix = 0; /* Create the submap for the object. * The submap is used in lutz(). We create it here because we may call * lutz multiple times below, and we only want to create it once. */ submap = createsubmap(objlistin, l, &subx, &suby, &subw, &subh); if (!submap) { status = MEMORY_ALLOC_ERROR; goto exit; } /* set thresholds of object lists based on object threshold */ thresh0 = objlistin->obj[l].thresh; objlistout->thresh = debobjlist2.thresh = thresh0; /* add input object to global deblending objlist and one local objlist */ if ((status = addobjdeep(l, objlistin, &objlist[0])) != RETURN_OK) goto exit; if ((status = addobjdeep(l, objlistin, &debobjlist2)) != RETURN_OK) goto exit; value0 = objlist[0].obj[0].fdflux*deblend_mincont; ok[0] = (short)1; for (k=1; k<xn; k++) { /*------ Calculate threshold */ thresh = objlistin->obj[l].fdpeak; debobjlist.thresh = thresh > 0.0? thresh0*pow(thresh/thresh0,(double)k/xn) : thresh0; /*--------- Build tree (bottom->up) */ if (objlist[k-1].nobj>=NSONMAX) { status = DEBLEND_OVERFLOW; goto exit; } for (i=0; i<objlist[k-1].nobj; i++) { status = lutz(objlistin->plist, submap, subx, suby, subw, &objlist[k-1].obj[i], &debobjlist, minarea); if (status != RETURN_OK) goto exit; for (j=h=0; j<debobjlist.nobj; j++) if (belong(j, &debobjlist, i, &objlist[k-1])) { debobjlist.obj[j].thresh = debobjlist.thresh; if ((status = addobjdeep(j, &debobjlist, &objlist[k])) != RETURN_OK) goto exit; m = objlist[k].nobj - 1; if (m>=NSONMAX) { status = DEBLEND_OVERFLOW; goto exit; } if (h>=nbm-1) if (!(son = (short *) realloc(son,xn*NSONMAX*(nbm+=16)*sizeof(short)))) { status = MEMORY_ALLOC_ERROR; goto exit; } son[k-1+xn*(i+NSONMAX*(h++))] = (short)m; ok[k+xn*m] = (short)1; } son[k-1+xn*(i+NSONMAX*h)] = (short)-1; } } /*------- cut the right branches (top->down) */ for (k = xn-2; k>=0; k--) { obj = objlist[k+1].obj; for (i=0; i<objlist[k].nobj; i++) { for (m=h=0; (j=(int)son[k+xn*(i+NSONMAX*h)])!=-1; h++) { if (obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0) m++; ok[k+xn*i] &= ok[k+1+xn*j]; } if (m>1) { for (h=0; (j=(int)son[k+xn*(i+NSONMAX*h)])!=-1; h++) if (ok[k+1+xn*j] && obj[j].fdflux - obj[j].thresh * obj[j].fdnpix > value0) { objlist[k+1].obj[j].flag |= SEP_OBJ_MERGED; status = addobjdeep(j, &objlist[k+1], &debobjlist2); if (status != RETURN_OK) goto exit; } ok[k+xn*i] = (short)0; } } } if (ok[0]) status = addobjdeep(0, &debobjlist2, objlistout); else status = gatherup(&debobjlist2, objlistout); exit: if (status == DEBLEND_OVERFLOW) put_errdetail("limit of " NSONMAX_STR " sub-objects reached while " "deblending. Decrease number of deblending thresholds " "or increase the detection threshold."); free(submap); submap = NULL; free(debobjlist2.obj); free(debobjlist2.plist); for (k=0; k<xn; k++) { free(objlist[k].obj); free(objlist[k].plist); } free(debobjlist.obj); free(debobjlist.plist); return status; }