Changeset 32347 for trunk/psModules/src/objects/pmSourceMoments.c
- Timestamp:
- Sep 6, 2011, 1:02:53 PM (15 years ago)
- Location:
- trunk/psModules/src/objects
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
pmSourceMoments.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects
- Property svn:ignore
-
old new 5 5 *.la 6 6 *.lo 7 pmSourceIO_CMF_PS1_V1.c 8 pmSourceIO_CMF_PS1_V2.c 9 pmSourceIO_CMF_PS1_V3.c
-
- Property svn:ignore
-
trunk/psModules/src/objects/pmSourceMoments.c
r31670 r32347 96 96 // (int) so they can be used in the image index below. 97 97 98 // do 2 passes : the first pass should use a somewhat smaller radius and no sigma window to 99 // get an unbiased (but probably noisy) centroid 100 if (!pmSourceMomentsGetCentroid (source, 0.75*radius, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) { 101 return false; 102 } 103 // second pass applies the Gaussian window and uses the centroid from the first pass 104 if (!pmSourceMomentsGetCentroid (source, radius, sigma, minSN, maskVal, source->moments->Mx, source->moments->My)) { 98 // XXX // do 2 passes : the first pass should use a somewhat smaller radius and no sigma window to 99 // XXX // get an unbiased (but probably noisy) centroid 100 // XXX if (!pmSourceMomentsGetCentroid (source, 0.75*radius, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) { 101 // XXX return false; 102 // XXX } 103 // XXX // second pass applies the Gaussian window and uses the centroid from the first pass 104 // XXX if (!pmSourceMomentsGetCentroid (source, radius, sigma, minSN, maskVal, source->moments->Mx, source->moments->My)) { 105 // XXX return false; 106 // XXX } 107 108 // If we use a large radius for the centroid, it will be biased by any neighbors. The flux 109 // of any object drops pretty quickly outside 1-2 sigmas. (The exception is bright 110 // saturated stars, for which we need to use a very large radius here) 111 if (!pmSourceMomentsGetCentroid (source, 1.5*sigma, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) { 105 112 return false; 106 113 } … … 108 115 // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates 109 116 // Xn = SUM (x - xc)^n * (z - sky) 110 111 float RFW = 0.0;112 float RHW = 0.0;113 114 float RF = 0.0;115 float RH = 0.0;116 float RS = 0.0;117 117 float XX = 0.0; 118 118 float XY = 0.0; … … 143 143 float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 144 144 145 // calculate the higher-order moments using Xo,Yo 145 146 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 146 147 … … 194 195 Sum += pDiff; 195 196 196 // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)197 197 float r = sqrt(r2); 198 float rf = r * fDiff;199 float rh = sqrt(r) * fDiff;200 float rs = fDiff;201 202 float rfw = r * pDiff;203 float rhw = sqrt(r) * pDiff;204 198 205 199 float x = xDiff * pDiff; … … 221 215 float yyyy = yDiff * yyy / r2; 222 216 223 RF += rf;224 RH += rh;225 RS += rs;226 227 RFW += rfw;228 RHW += rhw;229 230 217 XX += xx; 231 218 XY += xy; … … 242 229 XYYY += xyyy; 243 230 YYYY += yyyy; 231 232 // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?) 233 // XXX float r = sqrt(r2); 234 // XXX float rf = r * fDiff; 235 // XXX float rh = sqrt(r) * fDiff; 236 // XXX float rs = fDiff; 237 // XXX 238 // XXX float rfw = r * pDiff; 239 // XXX float rhw = sqrt(r) * pDiff; 240 // XXX 241 // XXX RF += rf; 242 // XXX RH += rh; 243 // XXX RS += rs; 244 // XXX 245 // XXX RFW += rfw; 246 // XXX RHW += rhw; 244 247 } 245 248 } 246 247 source->moments->Mrf = RF/RS;248 source->moments->Mrh = RH/RS;249 250 249 source->moments->Mxx = XX/Sum; 251 250 source->moments->Mxy = XY/Sum; … … 262 261 source->moments->Mxyyy = XYYY/Sum; 263 262 source->moments->Myyyy = YYYY/Sum; 263 264 // *** now calculate the 1st radial moment (for kron flux) -- symmetrical averaging 265 266 float **vPix = source->pixels->data.F32; 267 float **vWgt = source->variance->data.F32; 268 psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 269 270 float RF = 0.0; 271 float RH = 0.0; 272 float RS = 0.0; 273 274 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 275 276 float yDiff = row - yCM; 277 if (fabs(yDiff) > radius) continue; 278 279 // coordinate of mirror pixel 280 int yFlip = yCM - yDiff; 281 if (yFlip < 0) continue; 282 if (yFlip >= source->pixels->numRows) continue; 283 284 for (psS32 col = 0; col < source->pixels->numCols ; col++) { 285 // check mask and value for this pixel 286 if (vMsk && (vMsk[row][col] & maskVal)) continue; 287 if (isnan(vPix[row][col])) continue; 288 289 float xDiff = col - xCM; 290 if (fabs(xDiff) > radius) continue; 291 292 // coordinate of mirror pixel 293 int xFlip = xCM - xDiff; 294 if (xFlip < 0) continue; 295 if (xFlip >= source->pixels->numCols) continue; 296 297 // check mask and value for mirror pixel 298 if (vMsk && (vMsk[yFlip][xFlip] & maskVal)) continue; 299 if (isnan(vPix[yFlip][xFlip])) continue; 300 301 // radius is just a function of (xDiff, yDiff) 302 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 303 if (r2 > R2) continue; 304 305 float fDiff1 = vPix[row][col] - sky; 306 float fDiff2 = vPix[yFlip][xFlip] - sky; 307 float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2)); 308 309 // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?) 310 float r = sqrt(r2); 311 float rf = r * pDiff; 312 float rh = sqrt(r) * pDiff; 313 float rs = 0.5 * (fDiff1 + fDiff2); 314 315 RF += rf; 316 RH += rh; 317 RS += rs; 318 } 319 } 320 321 source->moments->Mrf = RF/RS; 322 source->moments->Mrh = RH/RS; 264 323 265 324 // if Mrf (first radial moment) is very small, we are getting into low-significance … … 270 329 kronRefRadius = MIN(radius, kronRefRadius); 271 330 } 331 332 // *** now calculate the kron flux values using the 1st radial moment 272 333 273 334 float radKinner = 1.0*kronRefRadius; … … 283 344 float SumOuter = 0.0; 284 345 346 // calculate the Kron flux, and related fluxes (NO symmetrical averaging) 285 347 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 286 348 287 349 float yDiff = row - yCM; 288 350 if (fabs(yDiff) > radKouter) continue; 351 352 for (psS32 col = 0; col < source->pixels->numCols ; col++) { 353 // check mask and value for this pixel 354 if (vMsk && (vMsk[row][col] & maskVal)) continue; 355 if (isnan(vPix[row][col])) continue; 356 357 float xDiff = col - xCM; 358 if (fabs(xDiff) > radKouter) continue; 359 360 // radKron is just a function of (xDiff, yDiff) 361 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 362 363 float fDiff1 = vPix[row][col] - sky; 364 float pDiff = fDiff1; 365 float wDiff = vWgt[row][col]; 366 367 // skip pixels below specified significance level. this is allowed, but should be 368 // avoided -- the over-weights the wings of bright stars compared to those of faint 369 // stars. 370 if (PS_SQR(pDiff) < minSN2*wDiff) continue; 371 372 float r = sqrt(r2); 373 if (r < radKron) { 374 Sum += pDiff; 375 Var += wDiff; 376 nKronPix ++; 377 // if (beVerbose) fprintf (stderr, "mome: %d %d %f %f %f\n", col, row, sky, *vPix, Sum); 378 } 379 380 // use sigma (fixed by psf) not a radKron based value 381 if (r < sigma) { 382 SumCore += pDiff; 383 VarCore += wDiff; 384 nCorePix ++; 385 } 386 387 if ((r > radKinner) && (r < radKron)) { 388 SumInner += pDiff; 389 nInner ++; 390 } 391 if ((r > radKron) && (r < radKouter)) { 392 SumOuter += pDiff; 393 nOuter ++; 394 } 395 } 396 } 397 // *** should I rescale these fluxes by pi R^2 / nNpix? 398 // XXX source->moments->KronCore = SumCore * M_PI * PS_SQR(sigma) / nCorePix; 399 // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix; 400 // XXX source->moments->KronFlux = Sum * M_PI * PS_SQR(radKron) / nKronPix; 401 // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix; 402 // XXX source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron) - PS_SQR(radKinner)) / nInner; 403 // XXX source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) - PS_SQR(radKron)) / nOuter; 404 405 source->moments->KronCore = SumCore; 406 source->moments->KronCoreErr = sqrt(VarCore); 407 source->moments->KronFlux = Sum; 408 source->moments->KronFluxErr = sqrt(Var); 409 source->moments->KronFinner = SumInner; 410 source->moments->KronFouter = SumOuter; 411 412 // XXX not sure I should save this here... 413 source->moments->KronFluxPSF = source->moments->KronFlux; 414 source->moments->KronFluxPSFErr = source->moments->KronFluxErr; 415 source->moments->KronRadiusPSF = source->moments->Mrf; 416 417 psTrace ("psModules.objects", 4, "Mrf: %f KronFlux: %f Mxx: %f Mxy: %f Myy: %f Mxxx: %f Mxxy: %f Mxyy: %f Myyy: %f Mxxxx: %f Mxxxy: %f Mxxyy: %f Mxyyy: %f Mxyyy: %f\n", 418 source->moments->Mrf, source->moments->KronFlux, 419 source->moments->Mxx, source->moments->Mxy, source->moments->Myy, 420 source->moments->Mxxx, source->moments->Mxxy, source->moments->Mxyy, source->moments->Myyy, 421 source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy); 422 423 psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f My: %f Sum: %f Mxx: %f Mxy: %f Myy: %f sky: %f Npix: %d\n", 424 source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx, source->moments->My, Sum, source->moments->Mxx, source->moments->Mxy, source->moments->Myy, sky, source->moments->nPixels); 425 426 return(true); 427 } 428 429 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) { 430 431 // First Pass: calculate the first moments (these are subtracted from the coordinates below) 432 // Sum = SUM (z - sky) 433 // X1 = SUM (x - xc)*(z - sky) 434 // .. etc 435 436 float sky = 0.0; 437 438 float peakPixel = -PS_MAX_F32; 439 psS32 numPixels = 0; 440 float Sum = 0.0; 441 float Var = 0.0; 442 float X1 = 0.0; 443 float Y1 = 0.0; 444 float R2 = PS_SQR(radius); 445 float minSN2 = PS_SQR(minSN); 446 float rsigma2 = 0.5 / PS_SQR(sigma); 447 448 float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage 449 float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage 450 451 // we are guaranteed to have a valid pixel and variance at this location (right? right?) 452 // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]); 453 // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); 454 // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); 455 // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel"); 456 457 // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should 458 // not depend on the fractional pixel location of the source. However, the aperture 459 // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel 460 // position of the expected centroid 461 462 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 463 464 float yDiff = row + 0.5 - yPeak; 465 if (fabs(yDiff) > radius) continue; 289 466 290 467 float *vPix = source->pixels->data.F32[row]; 291 468 float *vWgt = source->variance->data.F32[row]; 292 469 293 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];294 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];470 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; 471 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row]; 295 472 296 473 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) { … … 304 481 if (isnan(*vPix)) continue; 305 482 306 float xDiff = col - xCM;307 if (fabs(xDiff) > radKouter) continue;308 309 // radKron is just a function of (xDiff, yDiff)310 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff);311 312 float pDiff = *vPix - sky;313 float wDiff = *vWgt;314 315 // skip pixels below specified significance level. this is allowed, but should be316 // avoided -- the over-weights the wings of bright stars compared to those of faint317 // stars.318 if (PS_SQR(pDiff) < minSN2*wDiff) continue;319 320 float r = sqrt(r2);321 if (r < radKron) {322 Sum += pDiff;323 Var += wDiff;324 nKronPix ++;325 // if (beVerbose) fprintf (stderr, "mome: %d %d %f %f %f\n", col, row, sky, *vPix, Sum);326 }327 328 // use sigma (fixed by psf) not a radKron based value329 if (r < sigma) {330 SumCore += pDiff;331 VarCore += wDiff;332 nCorePix ++;333 }334 335 if ((r > radKinner) && (r < radKron)) {336 SumInner += pDiff;337 nInner ++;338 }339 if ((r > radKron) && (r < radKouter)) {340 SumOuter += pDiff;341 nOuter ++;342 }343 }344 }345 // *** should I rescale these fluxes by pi R^2 / nNpix?346 source->moments->KronCore = SumCore * M_PI * PS_SQR(sigma) / nCorePix;347 source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;348 source->moments->KronFlux = Sum * M_PI * PS_SQR(radKron) / nKronPix;349 source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;350 source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron) - PS_SQR(radKinner)) / nInner;351 source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) - PS_SQR(radKron)) / nOuter;352 353 psTrace ("psModules.objects", 4, "Mrf: %f KronFlux: %f Mxx: %f Mxy: %f Myy: %f Mxxx: %f Mxxy: %f Mxyy: %f Myyy: %f Mxxxx: %f Mxxxy: %f Mxxyy: %f Mxyyy: %f Mxyyy: %f\n",354 source->moments->Mrf, source->moments->KronFlux,355 source->moments->Mxx, source->moments->Mxy, source->moments->Myy,356 source->moments->Mxxx, source->moments->Mxxy, source->moments->Mxyy, source->moments->Myyy,357 source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);358 359 psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f My: %f Sum: %f Mxx: %f Mxy: %f Myy: %f sky: %f Npix: %d\n",360 source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx, source->moments->My, Sum, source->moments->Mxx, source->moments->Mxy, source->moments->Myy, sky, source->moments->nPixels);361 362 return(true);363 }364 365 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {366 367 // First Pass: calculate the first moments (these are subtracted from the coordinates below)368 // Sum = SUM (z - sky)369 // X1 = SUM (x - xc)*(z - sky)370 // .. etc371 372 float sky = 0.0;373 374 float peakPixel = -PS_MAX_F32;375 psS32 numPixels = 0;376 float Sum = 0.0;377 float Var = 0.0;378 float X1 = 0.0;379 float Y1 = 0.0;380 float R2 = PS_SQR(radius);381 float minSN2 = PS_SQR(minSN);382 float rsigma2 = 0.5 / PS_SQR(sigma);383 384 float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage385 float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage386 387 // we are guaranteed to have a valid pixel and variance at this location (right? right?)388 // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);389 // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");390 // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");391 // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");392 393 // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should394 // not depend on the fractional pixel location of the source. However, the aperture395 // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel396 // position of the expected centroid397 398 for (psS32 row = 0; row < source->pixels->numRows ; row++) {399 400 float yDiff = row + 0.5 - yPeak;401 if (fabs(yDiff) > radius) continue;402 403 float *vPix = source->pixels->data.F32[row];404 float *vWgt = source->variance->data.F32[row];405 406 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];407 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];408 409 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {410 if (vMsk) {411 if (*vMsk & maskVal) {412 vMsk++;413 continue;414 }415 vMsk++;416 }417 if (isnan(*vPix)) continue;418 419 483 float xDiff = col + 0.5 - xPeak; 420 484 if (fabs(xDiff) > radius) continue;
Note:
See TracChangeset
for help on using the changeset viewer.
