Changeset 30973
- Timestamp:
- Mar 18, 2011, 2:05:06 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20110213/psModules/src/objects/pmFootprintCullPeaks.c
r30902 r30973 40 40 const float min_threshold, // minimum permitted coll height 41 41 const float max_threshold, 42 const bool isWeightVar42 const bool useSmoothedImage 43 43 ) { // maximum permitted coll height 44 44 assert (img != NULL); assert (img->type.type == PS_TYPE_F32); … … 47 47 assert (fp != NULL); 48 48 49 if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do49 if (fp->peaks == NULL || fp->peaks->n < 2) { // nothing to do 50 50 return PS_ERR_NONE; 51 51 } … … 56 56 57 57 psImage *subImg = psImageSubset((psImage *)img, subRegion); 58 psImage *subWt = psImageSubset((psImage *)weight, subRegion); 59 assert (subImg != NULL && subWt != NULL); 58 psAssert (subImg, "trouble making local subimage"); 60 59 61 60 psImage *idImg = psImageAlloc(subImg->numCols, subImg->numRows, PS_TYPE_S32); … … 86 85 psImage *subMask = psImageCopy(NULL, subImg, PS_TYPE_IMAGE_MASK); 87 86 88 // The brightest peak is always safe; go through other peaks trying to cull them 89 for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop 90 const pmPeak *peak = fp->peaks->data[i]; 91 int x = peak->x - subImg->col0; 92 int y = peak->y - subImg->row0; 93 // 94 // Find the level nsigma below the peak that must separate the peak 95 // from any of its friends 96 // 97 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows); 98 99 // const float stdev = sqrt(subWt->data.F32[y][x]); 100 // float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev; 101 102 float stdev = 0.0; 103 float flux = 0.0; 104 if (isWeightVar) { 105 flux = subImg->data.F32[y][x]; 106 stdev = sqrt(subWt->data.F32[y][x]); 107 } else { 108 flux = subImg->data.F32[y][x]; 109 stdev = flux / sqrt(subWt->data.F32[y][x]); // should be 1/sqrt(subWT) 110 } 111 const float fStdev = fabs(stdev/flux); 112 const float stdev_pad = fabs(flux * hypot(fStdev, fPadding)); 113 114 // if flux is negative, careful with fStdev 115 116 float threshold = flux - nsigma_delta*stdev_pad; 117 118 if (isnan(threshold)) { 119 // min_threshold is assumed to be below the detection threshold, 120 // so all the peaks are pmFootprint, and this isn't the brightest 121 continue; 122 } 123 124 // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true? 125 if (threshold > subImg->data.F32[y][x]) { 126 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; 127 } 128 129 if (threshold < min_threshold) { 130 threshold = min_threshold; 131 } 132 if (threshold > max_threshold) { 133 threshold = max_threshold; 134 } 135 136 // XXX can we / should we use pmFootprintsFind() if the starting footprint is too large? 137 // init peakFootprint here? 138 pmFootprintsFindAtPoint(peakFootprint, peakFPSpans, subImg, subMask, threshold, brightPeaks, peak->y, peak->x); 139 if (peakFPSpans->nStartSpans > 2000) { 140 // dumpfootprints(peakFootprint, peakFPSpans); 141 // fprintf (stderr, "big footprint %d : %d\n", peakFootprint->nspans, peakFPSpans->nStartSpans); 142 fprintf (stderr, "big test footprint: %f %f to %f %f (%d pix)\n", peakFootprint->bbox.x0, peakFootprint->bbox.y0, peakFootprint->bbox.x1, peakFootprint->bbox.y1, peakFootprint->npix); 143 } 144 145 // at this point brightPeaks only has the peaks brighter than the current 146 147 // we set the IDs to either 1 (in peak) or 0 (not in peak) 148 pmSetFootprintID (idImg, peakFootprint, IN_PEAK); 149 150 // If this peak has not already been assigned to a source, then we can look for any 151 // brighter peaks within its footprint. Check if any of the previous (brighter) peaks 152 // are within the footprint of this peak If so, the current peak is bogus; drop it. 153 bool keep = true; 154 for (int j = 0; keep && !peak->assigned && (j < brightPeaks->n); j++) { 155 // const pmPeak *peak2 = fp->peaks->data[j]; XXX isn't this an error? we only care about the kept brighter peak, right? 156 const pmPeak *peak2 = brightPeaks->data[j]; 157 int x2 = peak2->x - subImg->col0; 158 int y2 = peak2->y - subImg->row0; 159 if (idImg->data.S32[y2][x2] == IN_PEAK) { 160 // There's a brighter peak within the footprint above threshold; so cull our initial peak 161 keep = false; 162 } 163 } 164 if (!keep) { 165 psAssert (!peak->assigned, "logic error: trying to drop a previously-assigned peak"); // we should not drop any already assigned peaks. 166 continue; 167 } 168 psArrayAdd (brightPeaks, 128, fp->peaks->data[i]); 87 // if we have many peaks in a large footprint, we waste a lot of time generating nearly identical footprints 88 // here we attempt to cull peaks drawing a single footprint for all peaks in some threshold range 89 fprintf (stderr, "footprint: %d x %d : %d pix, %d peaks\n", subImg->numCols, subImg->numRows, fp->npix, (int) fp->peaks->n); 90 if ((fp->npix > 30000) && (fp->peaks->n > 10)) { 91 92 // max flux is above threshold for brightest peak 93 pmPeak *maxPeak = fp->peaks->data[0]; 94 float maxFlux = useSmoothedImage ? maxPeak->smoothFlux : maxPeak->rawFlux; 95 96 // we have a relationship between the bin and the threshold of: 97 // threshold = 0.25 beta^2 bin^2 + minThreshold 98 // thus, the max bin is: sqrt(4.0*(maxThreshold - minThreshold)/ALPHA^2) 99 100 # define ALPHA 0.1 101 102 float beta = nsigma_delta * ALPHA; 103 float beta2 = PS_SQR(beta); 104 int nBins = sqrt(4.0*(maxFlux - min_threshold)/beta2) + 10; // let's be extra generous 105 106 // create a vector to store the threshold bins used for each peak 107 psVector *threshbins = psVectorAlloc(fp->peaks->n, PS_TYPE_S32); 108 threshbins->data.S32[0] = -1; // we skip the first peak 109 110 /// create a vector to track if a peak has been tried or not: 111 psVector *peaktried = psVectorAlloc(fp->peaks->n, PS_TYPE_U8); 112 psVectorInit(peaktried, 0); 113 peaktried->data.U8[0] = true; // we skip the first peak 114 115 psVector *threshbounds = psVectorAlloc(nBins, PS_TYPE_F32); 116 for (int i = 0; i < nBins; i++) { 117 threshbounds->data.F32[i] = 0.25*beta2*PS_SQR(i) + min_threshold; 118 } 119 psAssert(threshbounds->data.F32[threshbounds->n-1] > maxFlux, "upper limit does not include max flux"); 120 121 psHistogram *threshist = psHistogramAllocGeneric(threshbounds); 122 123 // assign the peaks to the histogram bins based on their nominal thresholsd 124 for (int i = 1; i < fp->peaks->n; i++) { 125 const pmPeak *peak = fp->peaks->data[i]; 126 float flux = useSmoothedImage ? peak->smoothFlux : peak->rawFlux; 127 float stdev = useSmoothedImage ? peak->smoothFluxStdev : peak->rawFluxStdev; 128 129 // if flux is negative, careful with fStdev 130 const float fStdev = fabs(stdev/flux); 131 const float stdev_pad = fabs(flux * hypot(fStdev, fPadding)); 132 133 float threshold = flux - nsigma_delta*stdev_pad; 134 psAssert(!isnan(threshold), "impossible"); 135 136 if (threshold <= min_threshold) { 137 threshist->nums->data.F32[0] += 1.0; 138 threshbins->data.S32[i] = 0; 139 continue; 140 } 141 int bin = sqrt(4.0*(threshold - min_threshold)/beta2); 142 psAssert(bin >= 0, "impossible bin"); 143 144 bin = PS_MIN(bin, threshist->nums->n - 1); 145 threshist->nums->data.F32[bin] += 1.0; 146 147 // record the bin selected for this peak 148 threshbins->data.S32[i] = bin; 149 } 150 151 // XXX TEST: did we assign correctly 152 # if (0) 153 int nPeaks = 1; // we don't put the brightest in the histogram 154 for (int i = 0; i < threshist->nums->n; i++) { 155 if (threshist->nums->data.F32[i] > 0) { 156 fprintf (stderr, "%f : %f : %d\n", threshist->bounds->data.F32[i], threshist->bounds->data.F32[i+1], (int)threshist->nums->data.F32[i]); 157 nPeaks += threshist->nums->data.F32[i]; 158 } 159 } 160 fprintf (stderr, "%d peaks vs %d in histogram\n", (int) fp->peaks->n, nPeaks); 161 # endif 162 163 // XXX for the moment, we will use the alternate cull for all peaks -- it might be 164 // faster to use the standard process for the peaks for which the threshold bin 165 // contains < N sources (N ~ 5-10?) 166 167 // loop over the threshold bins from brightest to faintest 168 for (int i = threshist->nums->n - 1; i >= 0; i--) { 169 if (threshist->nums->data.F32[i] == 0) continue; 170 171 // we are going to examine the footprints at this threshold 172 float threshold = 0.5*(threshist->bounds->data.F32[i] + threshist->bounds->data.F32[i+1]); 173 174 // generate all footprints corresponding to this threshold 175 psArray *myFP = pmFootprintsFind(subImg, threshold, 5); 176 if (!myFP) { 177 psWarning ("missing footprint?"); 178 continue; 179 } 180 if (!myFP->n) { 181 psWarning ("empty footprint?"); 182 continue; 183 } 184 185 // an array to track if the footprint has a brighter peak or not 186 psVector *found = psVectorAlloc(myFP->n + 1, PS_TYPE_U8); 187 psVectorInit(found, 0); 188 int nFound = 0; 189 190 // set IDs to distinguish the footprints 191 psImageInit(idImg, 0); 192 pmSetFootprintArrayIDsForImage(idImg, myFP, true); 193 194 // check which footprints contain already-accepted (brighter) peaks 195 // (we can give up if/when we found a peak for all footprints) 196 for (int j = 0; (j < brightPeaks->n) && (nFound < found->n); j++) { 197 const pmPeak *peak = brightPeaks->data[j]; 198 int x = peak->x - subImg->col0; 199 int y = peak->y - subImg->row0; 200 int myID = idImg->data.S32[y][x]; 201 psAssert(myID >= 0, "impossible"); 202 psAssert(myID < found->n, "impossible"); 203 204 if (myID == 0) continue; // bright peak is not in a footprint 205 if (found->data.U8[myID]) continue; // we already know this footprint contains a peak 206 found->data.U8[myID] = true; 207 nFound ++; 208 } 209 210 // check the peaks from this threshold bin: if they land in a footprint which has 211 // been found, we should drop that peak. otherwise, keep it 212 for (int j = 0; j < fp->peaks->n; j++) { 213 pmPeak *peak = fp->peaks->data[j]; 214 if (peak->assigned) continue; // peak is already claimed by a source -- don't cull 215 216 // skip peaks if we've already tried them 217 if (peaktried->data.U8[j]) continue; 218 219 // is this peak in the threshold bin of interest? 220 if (threshbins->data.S32[j] != i) continue; 221 222 // do not try this peak again 223 peaktried->data.U8[j] = true; 224 225 int x = peak->x - subImg->col0; 226 int y = peak->y - subImg->row0; 227 int myID = idImg->data.S32[y][x]; 228 229 // a peak in this threshold bin must be in a valid footprint, right? 230 psAssert(myID > 0, "impossible"); 231 psAssert(myID < found->n, "impossible"); 232 233 // keep this peak if found->data.U8[myID] == false (no brighter peak in the footprint) 234 if (!found->data.U8[myID]) { 235 // fprintf (stderr, "keeping %d: %d,%d\n", j, peak->x, peak->y); 236 psArrayAdd (brightPeaks, 128, peak); 237 continue; 238 } 239 // fprintf (stderr, "skipping %d: %d,%d\n", j, peak->x, peak->y); 240 } 241 psFree (myFP); 242 psFree (found); 243 } 244 psFree (threshist); 245 psFree (threshbounds); 246 psFree (threshbins); 247 psFree (peaktried); 248 249 } else { 250 251 // The brightest peak is always safe; go through other peaks trying to cull them 252 for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop 253 const pmPeak *peak = fp->peaks->data[i]; 254 255 float flux = useSmoothedImage ? peak->smoothFlux : peak->rawFlux; 256 float stdev = useSmoothedImage ? peak->smoothFluxStdev : peak->rawFluxStdev; 257 258 // if flux is negative, careful with fStdev 259 const float fStdev = fabs(stdev/flux); 260 const float stdev_pad = fabs(flux * hypot(fStdev, fPadding)); 261 262 float threshold = flux - nsigma_delta*stdev_pad; 263 264 if (isnan(threshold)) { 265 // min_threshold is assumed to be below the detection threshold, 266 // so all the peaks are pmFootprint, and this isn't the brightest 267 continue; 268 } 269 270 // just in case, force the threshold below the peak source flux 271 if (threshold > flux) { 272 threshold = flux - 10*FLT_EPSILON; 273 } 274 275 if (threshold < min_threshold) { 276 threshold = min_threshold; 277 } 278 if (threshold > max_threshold) { 279 threshold = max_threshold; 280 } 281 282 pmFootprintsFindAtPoint(peakFootprint, peakFPSpans, subImg, subMask, threshold, brightPeaks, peak->y, peak->x); 283 if (peakFPSpans->nStartSpans > 2000) { 284 // dumpfootprints(peakFootprint, peakFPSpans); 285 // fprintf (stderr, "big footprint %d : %d\n", peakFootprint->nspans, peakFPSpans->nStartSpans); 286 fprintf (stderr, "big test footprint: %f %f to %f %f (%d pix)\n", peakFootprint->bbox.x0, peakFootprint->bbox.y0, peakFootprint->bbox.x1, peakFootprint->bbox.y1, peakFootprint->npix); 287 } 288 289 // at this point brightPeaks only has the peaks brighter than the current 290 291 // we set the IDs to either 1 (in peak) or 0 (not in peak) 292 pmSetFootprintID (idImg, peakFootprint, IN_PEAK); 293 294 // If this peak has not already been assigned to a source, then we can look for any 295 // brighter peaks within its footprint. Check if any of the previous (brighter) peaks 296 // are within the footprint of this peak If so, the current peak is bogus; drop it. 297 bool keep = true; 298 for (int j = 0; keep && !peak->assigned && (j < brightPeaks->n); j++) { 299 // const pmPeak *peak2 = fp->peaks->data[j]; XXX isn't this an error? we only care about the kept brighter peak, right? 300 const pmPeak *peak2 = brightPeaks->data[j]; 301 int x2 = peak2->x - subImg->col0; 302 int y2 = peak2->y - subImg->row0; 303 if (idImg->data.S32[y2][x2] == IN_PEAK) { 304 // There's a brighter peak within the footprint above threshold; so cull our initial peak 305 keep = false; 306 } 307 } 308 if (!keep) { 309 psAssert (!peak->assigned, "logic error: trying to drop a previously-assigned peak"); // we should not drop any already assigned peaks. 310 continue; 311 } 312 psArrayAdd (brightPeaks, 128, fp->peaks->data[i]); 313 } 169 314 } 170 315 … … 174 319 psFree(idImg); 175 320 psFree(subImg); 176 psFree(subWt);177 321 psFree(subMask); 178 322 psFree(peakFootprint);
Note:
See TracChangeset
for help on using the changeset viewer.
