- Timestamp:
- Dec 6, 2012, 6:32:19 PM (14 years ago)
- Location:
- branches/czw_branch/20120906/psphot
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/czw_branch/20120906/psphot
- Property svn:mergeinfo changed
/branches/eam_branches/ipp-20120905/psphot (added) merged: 34408-34409,34415-34416,34428,34466,34565,34570,34575,34735,34747
- Property svn:mergeinfo changed
-
branches/czw_branch/20120906/psphot/src
- Property svn:mergeinfo changed
-
branches/czw_branch/20120906/psphot/src/psphotKronIterate.c
r34404 r34772 1 1 # include "psphotInternal.h" 2 2 3 bool psphotKronWindowSetSource(pmSource *source, psImage *kronWindow, bool useKronRadius, bool insert, bool oldWindow); 4 bool psphotKronWindowMag (pmSource *source, psImage *kronWindow, float radius, float minKronRadius, psImageMaskType maskVal, bool applyWeight, psImage *smoothedPixels); 5 6 7 bool psphotKronIterate (pmConfig *config, const pmFPAview *view, const char *filerule, int pass) 8 { 3 bool psphotKronRadiusMeasure (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal, psImage *smoothedPixels); 4 bool psphotKronFluxMeasure (pmSource *source, psImageMaskType maskVal); 5 6 7 bool psphotKronIterate (pmConfig *config, const pmFPAview *view, const char *filerule, int pass) { 9 8 bool status = true; 10 9 … … 98 97 } 99 98 100 bool KRON_APPLY_WEIGHT = psMetadataLookupBool (&status, recipe, "KRON_APPLY_WEIGHT");101 if (!status) {102 KRON_APPLY_WEIGHT = true;103 }104 105 bool KRON_APPLY_WINDOW = psMetadataLookupBool (&status, recipe, "KRON_APPLY_WINDOW");106 if (!status) {107 KRON_APPLY_WINDOW = false;108 }109 99 bool KRON_SMOOTH = psMetadataLookupBool (&status, recipe, "KRON_SMOOTH"); 110 100 if (!status) { … … 170 160 } 171 161 172 // generate the window image: multiply the flux by this to downweight neighbors 173 // XXX: we don't need this image if we aren't going to apply the window 174 psImage *kronWindow = psImageAlloc (readout->image->numCols, readout->image->numRows, PS_TYPE_F32); 175 psImageInit (kronWindow, 1.0); 176 177 // start with the currently known moments (Mxx, Myy, Mxy) and generate a window image 178 for (int i = 0; i < sources->n; i++) { 179 180 pmSource *source = sources->data[i]; 181 182 // set a window function for each source based on the moments 183 // (this skips really bad sources (no peak, no moments, DEFECT) 184 psphotKronWindowSetSource (source, kronWindow, false, true, KRON_APPLY_WINDOW); 162 // pass 3 we only measure fluxes for matched sources so we don't need smooth pixels or multiple iterations 163 if (pass == 3) { 164 KRON_SMOOTH = false; 165 KRON_ITERATIONS = 1; 185 166 } 186 167 … … 235 216 236 217 psArrayAdd(job->args, 1, readout); 237 psArrayAdd(job->args, 1, kronWindow);238 218 psArrayAdd(job->args, 1, cells->data[j]); // sources 239 219 psArrayAdd(job->args, 1, smoothedImage); … … 243 223 PS_ARRAY_ADD_SCALAR(job->args, MIN_KRON_RADIUS, PS_TYPE_F32); 244 224 PS_ARRAY_ADD_SCALAR(job->args, KRON_ITERATIONS, PS_TYPE_S32); 245 PS_ARRAY_ADD_SCALAR(job->args, (psS32) KRON_APPLY_WEIGHT, PS_TYPE_S32);246 PS_ARRAY_ADD_SCALAR(job->args, (psS32) KRON_APPLY_WINDOW, PS_TYPE_S32);247 225 PS_ARRAY_ADD_SCALAR(job->args, KRON_SMOOTH_SIGMA, PS_TYPE_F32); 248 226 PS_ARRAY_ADD_SCALAR(job->args, KRON_SB_MIN_DIVISOR,PS_TYPE_F32); … … 281 259 } 282 260 psFree (cellGroups); 283 psFree (kronWindow);284 261 if (KRON_SMOOTH) { 285 262 for (int i = 0; i < sources->n; i++) { … … 298 275 299 276 pmReadout *readout = job->args->data[0]; 300 psImage *kronWindow = job->args->data[1]; 301 psArray *sources = job->args->data[2]; 302 psImage *smoothedImage = job->args->data[3]; 303 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 304 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA); 305 float RADIUS = PS_SCALAR_VALUE(job->args->data[6],F32); 306 float MIN_KRON_RADIUS = PS_SCALAR_VALUE(job->args->data[7],F32); 307 int KRON_ITERATIONS = PS_SCALAR_VALUE(job->args->data[8],S32); 308 bool KRON_APPLY_WEIGHT = PS_SCALAR_VALUE(job->args->data[9],S32); 309 bool KRON_APPLY_WINDOW = PS_SCALAR_VALUE(job->args->data[10],S32); 310 float KRON_SMOOTH_SIGMA = PS_SCALAR_VALUE(job->args->data[11],F32); 311 float KRON_SB_MIN_DIVISOR = PS_SCALAR_VALUE(job->args->data[12],F32); 312 int pass = PS_SCALAR_VALUE(job->args->data[13],S32); 313 #ifndef REVERT_ON_BAD_MEASUREMENT 314 (void) pass; 315 #endif 277 psArray *sources = job->args->data[1]; 278 psImage *smoothedImage = job->args->data[2]; 279 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 280 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 281 float RADIUS = PS_SCALAR_VALUE(job->args->data[5],F32); 282 float MIN_KRON_RADIUS = PS_SCALAR_VALUE(job->args->data[6],F32); 283 int KRON_ITERATIONS = PS_SCALAR_VALUE(job->args->data[7],S32); 284 float KRON_SMOOTH_SIGMA = PS_SCALAR_VALUE(job->args->data[8],F32); 285 float KRON_SB_MIN_DIVISOR = PS_SCALAR_VALUE(job->args->data[9],F32); 286 int pass = PS_SCALAR_VALUE(job->args->data[10],S32); 287 288 bool measureRadius = true; 289 if (pass == 3) { 290 measureRadius = false; 291 } 316 292 317 293 for (int j = 0; j < KRON_ITERATIONS; j++) { … … 320 296 pmSource *source = sources->data[i]; 321 297 if (!source->peak) continue; // XXX how can we have a peak-less source? 322 323 // check status of this source's moments 324 if (!source->moments) continue; 325 if (!(source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED)) continue; 326 if (source->mode & PM_SOURCE_MODE_MOMENTS_FAILURE) continue; 298 if (!source->moments) continue; 299 if (source->type == PM_SOURCE_TYPE_DEFECT) continue; 300 if (source->type == PM_SOURCE_TYPE_SATURATED) continue; 301 // skip saturated stars modeled with a radial profile 302 if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue; 303 304 // in pass 3 we only measure the flux for matched sources 305 if ((pass == 3) && !(source->mode2 & PM_SOURCE_MODE2_MATCHED)) continue; 306 307 # if (0) 308 # define TEST_X 653 309 # define TEST_Y 466 310 if ((fabs(source->peak->xf - TEST_X) < 5) && (fabs(source->peak->yf - TEST_Y) < 5)) { 311 fprintf (stderr, "test object\n"); 312 } 313 # undef TEST_X 314 # undef TEST_Y 315 # endif 316 317 if (measureRadius) { 318 // check status of this source's moments 319 // XXX: I don't think that we have to apply these restrictions since we dropped the window function 320 if (!(source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED)) continue; 321 if (source->mode & PM_SOURCE_MODE_MOMENTS_FAILURE) continue; 322 } 323 327 324 if (!isfinite(source->moments->Mrf)) { 328 325 // Once we save a bad Mrf measurement we give up on this source 329 // checking here allows us to avoid adding and subtracting the model326 // XXX: is this the right thing to do? 330 327 continue; 331 328 } 332 333 // skip saturated stars modeled with a radial profile334 if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue;335 329 336 330 // replace object in image … … 348 342 // On first iteration set window radius to sky radius (if valid). We also use this on subsequent 349 343 // iterations if we cannot find a better limit 350 float maxWindow = isfinite(source->skyRadius) ? source->skyRadius : RADIUS; 344 float maxWindow; 345 if (measureRadius) { 346 maxWindow = isfinite(source->skyRadius) ? source->skyRadius : RADIUS; 347 } else { 348 maxWindow = source->moments->Mrf; 349 } 351 350 if (j > 0) { 352 351 // on subsequent iterations we use a factor times the previous radial moment value … … 370 369 float windowRadius = PS_MAX(RADIUS, maxWindow); 371 370 372 #ifdef REVERT_ON_BAD_MEASURMENT373 // save previous measurements. We might revert back to them if this round fails374 float MrfPrior = source->moments->Mrf;375 float KronFluxPrior = source->moments->KronFlux;376 float KronFluxErrPrior = source->moments->KronFluxErr;377 #endif378 379 371 // re-allocate image, weight, mask arrays for each peak with box big enough to fit BIG_RADIUS 380 372 bool extend = pmSourceRedefinePixels (source, readout, source->peak->x, source->peak->y, windowRadius + 2); 381 psAssert (source->pixels, " WTF?");373 psAssert (source->pixels, "redefine pixels failed?"); 382 374 if (extend && smoothedPixels) { 383 375 psFree(source->tmpPtr); 384 376 smoothedPixels = psImageSubset(smoothedImage, source->region); 385 psAssert (smoothedPixels, " WTF?");377 psAssert (smoothedPixels, "redefine smoothed pixels failed?"); 386 378 source->tmpPtr = (psPtr) smoothedPixels ; 387 379 } 388 380 389 390 // clear the window function for this source based on the moments 391 // Note: this function also applies cuts on the source and returns false if it 392 // does not meet the requirements for measuring the Kron Radius or Magnitude. 393 // Note: that it performs the cuts even if KRON_APPLY_WINDOW is false 394 if (psphotKronWindowSetSource (source, kronWindow, (j > 0), false, KRON_APPLY_WINDOW)) { 395 396 // this function populates moments->Mrf,KronFlux,KronFluxErr 397 psphotKronWindowMag (source, kronWindow, windowRadius, MIN_KRON_RADIUS, maskVal, KRON_APPLY_WEIGHT, smoothedPixels); 398 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 399 400 // set a window function for each source based on the moments 401 psphotKronWindowSetSource (source, kronWindow, true, true, KRON_APPLY_WINDOW); 402 } 403 404 #ifdef REVERT_ON_BAD_MEASUREMENT 405 // on pass 2 if we get an invalid measurement on a pass 1 source where we had a good one previously 406 // in pass 1 keep that measurement 407 bool reverted = false; 408 if (pass > 1 && !isfinite(source->moments->Mrf) && (source->mode2 & PM_SOURCE_MODE2_PASS1_SRC)) { 409 source->moments->Mrf = MrfPrior; // This is finite otherwise we wouldn't have gotten here 410 source->moments->KronFlux = KronFluxPrior; 411 source->moments->KronFluxErr = KronFluxErrPrior; 412 reverted = true; 413 } 414 #endif 381 bool measureFlux = true; 382 if (measureRadius) { 383 measureFlux = psphotKronRadiusMeasure (source, windowRadius, MIN_KRON_RADIUS, maskVal, smoothedPixels); 384 } 385 386 if (measureFlux) { 387 // Make sure the sources images are large enough for the measured Kron Radius 388 bool extend = pmSourceRedefinePixels (source, readout, source->peak->x, source->peak->y, 389 2.5 * source->moments->Mrf + 2); 390 391 psAssert (source->pixels, "redefine pixels failed?"); 392 if (extend && smoothedPixels) { 393 psFree(source->tmpPtr); 394 smoothedPixels = psImageSubset(smoothedImage, source->region); 395 psAssert (smoothedPixels, "redefine smoothed pixels failed?"); 396 source->tmpPtr = (psPtr) smoothedPixels ; 397 } 398 399 // this function populates moments->Mrf,KronFlux,KronFluxErr, KronFinner, and KronFouter 400 psphotKronFluxMeasure (source, maskVal); 401 } 402 403 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 404 415 405 #ifdef DUMP_KRS 416 #ifndef REVERT_ON_BAD_MEASUREMENT 417 bool reverted = false; 418 #endif 419 fprintf(dumpFile, "%7d %1d %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f %2d\n", source->id, reverted, source->moments->Mrf, MrfPrior, maxWindow, windowRadius, source->peak->xf, source->peak->yf, source->imageID); 406 fprintf(dumpFile, "%7d %6.1f %6.1f %6.1f %6.1f %6.1f %6.1f %2d\n", source->id, source->moments->Mrf, MrfPrior, maxWindow, windowRadius, source->peak->xf, source->peak->yf, source->imageID); 420 407 #endif 421 408 … … 433 420 } 434 421 435 bool psphotKron WindowMag (pmSource *source, psImage *kronWindow, float radius, float minKronRadius, psImageMaskType maskVal,436 bool applyWeight,psImage *smoothedPixels) {422 bool psphotKronRadiusMeasure (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal, 423 psImage *smoothedPixels) { 437 424 438 425 PS_ASSERT_PTR_NON_NULL(source, false); … … 442 429 443 430 psF32 R2 = PS_SQR(radius); 444 float rsigma2 = applyWeight ? 0.5 / R2 : 0;445 431 446 432 // a note about coordinates: coordinates of objects throughout psphot refer to the primary … … 455 441 // Xn = SUM (x - xc)^n * (z - sky) 456 442 457 458 443 psF32 RF = 0.0; 459 444 psF32 RS = 0.0; … … 471 456 psF32 yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 472 457 473 int Xwo = source->pixels->col0;474 int Ywo = source->pixels->row0;475 476 458 psF32 **vPix; 477 459 if (smoothedPixels) { … … 480 462 vPix = source->pixels->data.F32; 481 463 } 482 psF32 **vWin = kronWindow->data.F32; 464 465 psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 466 467 { 468 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 469 470 psF32 yDiff = row - yCM; 471 if (fabs(yDiff) > radius) continue; 472 473 // coordinate of mirror pixel 474 int yFlip = yCM - yDiff; 475 if (yFlip < 0) continue; 476 if (yFlip >= source->pixels->numRows) continue; 477 478 for (psS32 col = 0; col < source->pixels->numCols ; col++) { 479 // check mask and value for this pixel 480 if (vMsk && (vMsk[row][col] & maskVal)) continue; 481 if (isnan(vPix[row][col])) continue; 482 483 psF32 xDiff = col - xCM; 484 if (fabs(xDiff) > radius) continue; 485 486 // coordinate of mirror pixel 487 int xFlip = xCM - xDiff; 488 if (xFlip < 0) continue; 489 if (xFlip >= source->pixels->numCols) continue; 490 491 // check mask and value for mirror pixel 492 if (vMsk && (vMsk[yFlip][xFlip] & maskVal)) continue; 493 if (isnan(vPix[yFlip][xFlip])) continue; 494 495 // radius is just a function of (xDiff, yDiff) 496 psF32 r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 497 if (r2 > R2) continue; 498 499 float fDiff1 = vPix[row][col]; 500 float fDiff2 = vPix[yFlip][xFlip]; 501 502 float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2)); 503 504 // Kron Flux uses the 1st radial moment 505 psF32 rf = pDiff * sqrt(r2); 506 psF32 rs = 0.5 * (fDiff1 + fDiff2); 507 508 RF += rf; 509 RS += rs; 510 } 511 } 512 513 float MrfTry = RF/RS; 514 if (RF <= 0. || RS <= 0 || !isfinite(MrfTry)) { 515 // We did not get a good measurement 516 source->moments->Mrf = NAN; 517 source->moments->KronFlux = NAN; 518 source->moments->KronFluxErr = NAN; 519 return false; 520 } 521 522 float Mrf = MAX(minKronRadius, MrfTry); 523 // Saturate the 1st radial moment 524 if (sqrt(source->peak->detValue) < 10.0) { 525 Mrf = MIN (radius, Mrf); 526 } 527 source->moments->Mrf = Mrf; 528 } 529 return true; 530 } 531 532 bool psphotKronFluxMeasure(pmSource *source, psImageMaskType maskVal) { 533 534 PS_ASSERT_PTR_NON_NULL(source, false); 535 PS_ASSERT_PTR_NON_NULL(source->peak, false); 536 PS_ASSERT_PTR_NON_NULL(source->pixels, false); 537 538 // a note about coordinates: coordinates of objects throughout psphot refer to the primary 539 // image coordinates. the source->pixels image has an offset relative to its parent of 540 // col0,row0: a pixel (x,y) in the primary image has coordinates of (x-col0, y-row0) in 541 // this subimage. we subtract off the peak coordinates, adjusted to this subimage, to have 542 // minimal round-off error in the sums. since these values are subtracted just to minimize 543 // the dynamic range and are added back below, the exact value does not matter. these are 544 // (int) so they can be used in the image index below. 545 546 // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates 547 // Xn = SUM (x - xc)^n * (z - sky) 548 549 // the peak position is less accurate but less subject to extreme deviations 550 float dX = source->moments->Mx - source->peak->xf; 551 float dY = source->moments->My - source->peak->yf; 552 float dR = hypot(dX, dY); 553 float Xo = (dR < 2.0) ? source->moments->Mx : source->peak->xf; 554 float Yo = (dR < 2.0) ? source->moments->My : source->peak->yf; 555 556 // center of mass in subimage. Note: the calculation below uses pixel index, so we correct 557 // xCM, yCM from pixel coords to pixel index here. 558 psF32 xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage 559 psF32 yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 560 561 psF32 **vPix = source->pixels->data.F32; 483 562 psF32 **vWgt = source->variance->data.F32; 484 563 485 564 psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 486 565 566 source->moments->KronFlux = NAN; 567 source->moments->KronFluxErr = NAN; 568 source->moments->KronFinner = NAN; 569 source->moments->KronFouter = NAN; 570 571 // Calculate the Kron fluxes 572 float radKinner = 1.0 * source->moments->Mrf; 573 float radKron = 2.5 * source->moments->Mrf; 574 float radKouter = 4.0 * source->moments->Mrf; 575 576 float limitRadius = MIN (radKouter, source->windowRadius); 577 if (radKouter > source->windowRadius) { 578 // This happens but the measurement isn't important enough to allocate the extra pixels 579 // psWarning ("outer kron radius: %f is larger than windowRadius: %f for %d\n", 580 // radKouter, source->windowRadius, source->id); 581 limitRadius = MIN (radKron, source->windowRadius); 582 } 583 if (radKron > source->windowRadius) { 584 // caller should have prevented this from happening 585 psWarning ("kron radius: %f is larger than windowRadius: %f for %d\n", 586 radKron, source->windowRadius, source->id); 587 return false; 588 } 589 590 float Sum = 0.0; 591 float Var = 0.0; 592 float SumInner = 0.0; 593 float SumOuter = 0.0; 594 595 // set vPix to the source pixels (it may have been set to the smoothed image above) 596 vPix = source->pixels->data.F32; 597 487 598 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 488 599 489 600 psF32 yDiff = row - yCM; 490 if (fabs(yDiff) > radius) continue; 491 492 // coordinate of mirror pixel 493 int yFlip = yCM - yDiff; 494 if (yFlip < 0) continue; 495 if (yFlip >= source->pixels->numRows) continue; 601 if (fabs(yDiff) > limitRadius) continue; 496 602 497 603 for (psS32 col = 0; col < source->pixels->numCols ; col++) { … … 501 607 502 608 psF32 xDiff = col - xCM; 503 if (fabs(xDiff) > radius) continue; 504 505 // coordinate of mirror pixel 506 int xFlip = xCM - xDiff; 507 if (xFlip < 0) continue; 508 if (xFlip >= source->pixels->numCols) continue; 509 510 // check mask and value for mirror pixel 511 if (vMsk && (vMsk[yFlip][xFlip] & maskVal)) continue; 512 if (isnan(vPix[yFlip][xFlip])) continue; 513 514 // radius is just a function of (xDiff, yDiff) 609 if (fabs(xDiff) > limitRadius) continue; 610 515 611 psF32 r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 516 if (r2 > R2) continue; 517 518 // flux * window 519 float z = r2 * rsigma2; 520 assert (z >= 0.0); 521 522 // weight by window image and wide Gaussian 523 float weight1 = vWin[row+Ywo][col+Xwo]*exp(-z); 524 float weight2 = vWin[yFlip+Ywo][xFlip+Xwo]*exp(-z); 525 526 float fDiff1 = vPix[row][col]*weight1; 527 float fDiff2 = vPix[yFlip][xFlip]*weight2; 528 529 float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2)); 530 531 // Kron Flux uses the 1st radial moment (maybe Gaussian windowed?) 532 psF32 rf = pDiff * sqrt(r2); 533 psF32 rs = 0.5 * (fDiff1 + fDiff2); 534 535 RF += rf; 536 RS += rs; 612 psF32 r = sqrt(r2); 613 614 float pDiff = vPix[row][col]; 615 psF32 wDiff = vWgt[row][col]; 616 617 if (r > radKinner && r < radKron) { 618 SumInner += pDiff; 619 } 620 if (r < radKron) { 621 Sum += pDiff; 622 Var += wDiff; 623 } 624 if (r > radKron && r < radKouter) { 625 SumOuter += pDiff; 626 } 537 627 } 538 628 } 539 629 540 float MrfTry = RF/RS;541 if (RF <= 0. || RS <= 0 || !isfinite(MrfTry)) {542 // We did not get a good measurement543 source->moments->Mrf = NAN;544 source->moments->KronFlux = NAN;545 source->moments->KronFluxErr = NAN;546 return false;547 }548 549 float Mrf = MAX(minKronRadius, MrfTry);550 // Saturate the 1st radial moment551 if (sqrt(source->peak->detValue) < 10.0) {552 Mrf = MIN (radius, Mrf);553 }554 555 // Calculate the Kron magnitude (make this block optional?)556 float radKron = 2.5*Mrf;557 float radKron2 = radKron*radKron;558 559 int nKronPix = 0;560 float Sum = 0.0;561 float Var = 0.0;562 float Win = 0.0;563 564 // set vPix to the source pixels (it may have been set to the565 // smoothed image above)566 vPix = source->pixels->data.F32;567 568 569 for (psS32 row = 0; row < source->pixels->numRows ; row++) {570 571 psF32 yDiff = row - yCM;572 if (fabs(yDiff) > radKron) continue;573 574 for (psS32 col = 0; col < source->pixels->numCols ; col++) {575 // check mask and value for this pixel576 if (vMsk && (vMsk[row][col] & maskVal)) continue;577 if (isnan(vPix[row][col])) continue;578 579 psF32 xDiff = col - xCM;580 if (fabs(xDiff) > radKron) continue;581 582 // radKron is just a function of (xDiff, yDiff)583 psF32 r2 = PS_SQR(xDiff) + PS_SQR(yDiff);584 if (r2 > radKron2) continue;585 586 float weight1 = vWin[row+Ywo][col+Xwo];587 float fDiff1 = vPix[row][col]*weight1;588 589 float pDiff = fDiff1;590 psF32 wDiff = vWgt[row][col] * weight1;591 592 Sum += pDiff;593 Var += wDiff;594 Win += weight1;595 nKronPix ++;596 }597 }598 599 source->moments->Mrf = Mrf;600 630 source->moments->KronFlux = Sum; 601 631 source->moments->KronFluxErr = sqrt(Var); 632 source->moments->KronFinner = SumInner; 633 634 // only save radKouter if the radius is inside the integration radius limit 635 if (radKouter <= limitRadius) { 636 source->moments->KronFouter = SumOuter; 637 } 602 638 603 639 return true; 604 640 } 605 606 bool psphotKronWindowSetSource(pmSource *source, psImage *kronWindow, bool useKronRadius, bool insert, bool applyWindow) {607 608 if (!source) return false;609 if (!source->peak) return false; // XXX how can we have a peak-less source?610 if (!source->moments) return false;611 if (source->type == PM_SOURCE_TYPE_DEFECT) return false;612 if (source->type == PM_SOURCE_TYPE_SATURATED) return false;613 if (!(source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED)) return false;614 if (source->mode & PM_SOURCE_MODE_MOMENTS_FAILURE) return false;615 psAssert(kronWindow, "need a window");616 617 // XXX: If we are not applying the window then we don't need to check for valid Mrf here.618 // We should give the this module a chance to measure a good value.619 // However experiments show that it hardly ever succeeds in getting a better value620 if (!isfinite(source->moments->Mrf) || source->moments->Mrf < 0 ) return false;621 622 if (!applyWindow) {623 return true;624 }625 626 // we have a source with moments Mx, My, Mxx, Mxy, Myy. we just need to define a Gaussian that has627 // these values (and peak of 1.0)628 629 int Nx = kronWindow->numCols;630 int Ny = kronWindow->numRows;631 632 float Xo = source->moments->Mx;633 float Yo = source->moments->My;634 635 psEllipseMoments moments;636 moments.x2 = source->moments->Mxx;637 moments.y2 = source->moments->Myy;638 moments.xy = source->moments->Mxy;639 640 psEllipseAxes axes = psEllipseMomentsToAxes(moments, 20.0);641 if (! (isfinite(axes.major) && isfinite(axes.minor) && isfinite(axes.theta)) ) {642 // Shall we log a proper warning? This happens often with matched sources (forced photometry)643 // fprintf(dump, "invalid axes found id: %4d major: %f minor: %f theta: %f\n", source->id, axes.major, axes.minor, axes.theta);644 return false;645 }646 647 // Why this factor of 0.5 ?648 float scale = 0.5 * source->moments->Mrf / axes.major;649 axes.major *= scale;650 axes.minor *= scale;651 652 psEllipseShape shape = psEllipseAxesToShape(axes);653 if (! (isfinite(shape.sx) && isfinite(shape.sy) && isfinite(shape.sxy)) ) {654 // Shall we log a proper warning? This happens often with matched sources (forced photometry)655 // fprintf(dump, "invalid shape found id: %d sx: %f sy %f sxy: %f\n", source->id, shape.sx, shape.sy, shape.sxy);656 return false;657 }658 659 float Smajor = axes.major;660 661 int minX = PS_MIN(PS_MAX(Xo - 5*Smajor, 0), Nx - 1);662 int maxX = PS_MIN(PS_MAX(Xo + 5*Smajor, 0), Nx - 1);663 int minY = PS_MIN(PS_MAX(Yo - 5*Smajor, 0), Ny - 1);664 int maxY = PS_MIN(PS_MAX(Yo + 5*Smajor, 0), Ny - 1);665 666 float rMxx = 0.5 / PS_SQR(shape.sx);667 float rMyy = 0.5 / PS_SQR(shape.sy);668 float Sxy = -1. * shape.sxy; // factor of -1 is included to match the previous window function669 // implementation. XXX: Is this correct?670 671 for (int iy = minY; iy < maxY; iy++) {672 for (int ix = minX; ix < maxX; ix++) {673 674 float dX = (ix + 0.5 - Xo);675 float dY = (iy + 0.5 - Yo);676 677 float z = rMxx * PS_SQR(dX) + rMyy * PS_SQR(dY) + Sxy*dX*dY;678 679 float f = insert ? 1.001 - exp(-z) : 1.0 / (1.001 - exp(-z));680 681 kronWindow->data.F32[iy][ix] *= f;682 }683 }684 685 return true;686 }
Note:
See TracChangeset
for help on using the changeset viewer.
