Changeset 34377
- Timestamp:
- Sep 2, 2012, 12:41:50 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20120805/psphot/src/psphotDeblendSatstars.c
r34369 r34377 10 10 11 11 bool psImageQuickStats (QuickStats *stats, psImage *image, psRegion region); 12 13 bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logFlux, psVector *logRad, float Rmax);14 bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal);15 bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal);16 12 float InterpolateValues (float X0, float Y0, float X1, float Y1, float X); 17 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel);13 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, float factor, int channel); 18 14 19 15 // for now, let's store the detections on the readout->analysis for each readout … … 46 42 TBD: 47 43 48 1) carry the radial profile out of this function (element of pmSource) 49 2) function to replace the radial profile for a source 50 3) recenter the profile (based) 44 * function to replace the radial profile for a source 45 * recenter the profile (based on cross-correlation / convolution with 1D profile) 46 47 * raise a bit somewhere for these super saturated stars (if they were so modeled) 48 * consider the subtraction bit : when to raise it? 51 49 52 50 **/ … … 171 169 source->mode |= PM_SOURCE_MODE_BIG_RADIUS; 172 170 171 if (!psphotSatstarProfileModel (source, maskVal)) continue; 172 173 source->mode |= PM_SOURCE_MODE_SATSTAR; // yes, this source IS saturated 174 source->mode2 |= PM_SOURCE_MODE2_SATSTAR_PROFILE; // and we have in fact subtracted the profile 175 173 176 // XXX visualize, model, and subtract 174 if (!psphotVisualRadialProfileSatstar (source, maskVal)) {175 break;176 }177 // if (!psphotVisualRadialProfileSatstar (source, maskVal)) { 178 // break; 179 // } 177 180 178 181 // generate radial profile, store on the source structure … … 392 395 } 393 396 397 // create a model for the radial profile of a saturated star (is this actually more generic?) 398 bool psphotSatstarProfileModel (pmSource *source, psImageMaskType maskVal) { 399 400 // XXX user define somewhere? 401 float Rmax = 320.0; 402 403 // XXX is this ever the case?? 404 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 405 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 406 407 int nPts = source->pixels->numRows * source->pixels->numCols; 408 psVector *logR = psVectorAllocEmpty (nPts, PS_TYPE_F32); 409 psVector *flux = psVectorAllocEmpty (nPts, PS_TYPE_F32); 410 411 int ng = 0; 412 413 // choose the best center for this profile 414 float Xo = NAN; 415 float Yo = NAN; 416 417 if (source->modelPSF) { 418 // XXX do we ever have a PSF model for a SATSTAR? 419 Xo = source->modelPSF->params->data.F32[PM_PAR_XPOS]; 420 Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS]; 421 } else { 422 Xo = source->moments->Mx; 423 Yo = source->moments->My; 424 } 425 426 float Xc = Xo - source->pixels->col0 - 0.5; 427 float Yc = Yo - source->pixels->row0 - 0.5; 428 429 for (int iy = 0; iy < source->pixels->numRows; iy++) { 430 for (int ix = 0; ix < source->pixels->numCols; ix++) { 431 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue; 432 // XXX do this faster by generating R^2 and returning 0.5*log10(R^2)? 433 logR->data.F32[ng] = log10(hypot (ix - Xc, iy - Yc)); 434 flux->data.F32[ng] = source->pixels->data.F32[iy][ix]; 435 ng++; 436 } 437 } 438 logR->n = ng; 439 flux->n = ng; 440 441 // XXX do something sensible here if there are no pixels 442 443 // measure the radial profile 444 psVector *logFmodel = NULL; 445 psVector *logRmodel = NULL; 446 psphotSatstarProfileCreate (source, &logRmodel, &logFmodel, logR, flux, Rmax); 447 448 // XXX do something sensible here if the profile is crap 449 450 source->satstar = pmSourceSatstarAlloc(); 451 source->satstar->Xo = Xo; 452 source->satstar->Yo = Yo; 453 source->satstar->Rmax = Rmax; 454 source->satstar->logFmodel = logFmodel; 455 source->satstar->logRmodel = logRmodel; 456 457 // subtract the profile (false => subtract) 458 psphotSatstarProfileOp (source, maskVal, 1.0, 0, false); 459 460 psFree (logR); 461 psFree (flux); 462 463 return true; 464 } 465 466 // Take logR + flux and generate radial bins logRmodelOut, logFmodelOut 467 bool psphotSatstarProfileCreate (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logR, psVector *flux, float Rmax) { 468 469 // we have log(radius) & log(flux). find the median flux in log radial bins 470 471 float logRmax = log10(Rmax); 472 float logRdel = 0.1; // XXX user-define? 473 474 psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 475 psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 476 477 pmSourceRadialProfileSortPair (logR, flux); 478 479 psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 480 psVector *fluxVals = psVectorAllocEmpty (100, PS_TYPE_F32); 481 482 int bin = 0; 483 for (int i = 0; i < logRmodel->n; i++) { 484 485 // bin (i) has log radius range (i*logRdel : (i+1)*logRdel) 486 float lRmin = logRdel*(i + 0); 487 float lRmax = logRdel*(i + 1); 488 489 // reset the flux vector 490 fluxVals->n = 0; 491 psStatsInit (fluxStats); 492 493 while (logR->data.F32[bin] < lRmax) { 494 if (isfinite(flux->data.F32[bin])) { 495 psVectorAppend (fluxVals, flux->data.F32[bin]); 496 } 497 bin ++; 498 } 499 500 // we have the set of fluxes for this bin; find the median values 501 502 float Rmin = pow(10.0, lRmin); 503 float Rmax = pow(10.0, lRmax); 504 505 float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin)); 506 logRmodel->data.F32[i] = log10(Rmean); 507 508 float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin)); 509 if (fluxVals->n < 0.25*Area) { 510 logFmodel->data.F32[i] = NAN; 511 continue; 512 } 513 514 psVectorStats (fluxStats, fluxVals, NULL, NULL, 0); 515 if (fluxStats->robustMedian > 0.0) { 516 logFmodel->data.F32[i] = log10(fluxStats->robustMedian); 517 } else { 518 logFmodel->data.F32[i] = -3.0; 519 } 520 // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev); 521 } 522 523 // now how do i use this to subtract a model?? 524 *logRmodelOut = logRmodel; 525 *logFmodelOut = logFmodel; 526 527 // need to free stuff 528 psFree (fluxStats); 529 psFree (fluxVals); 530 531 return true; 532 } 533 534 bool psphotSatstarProfileOp (pmSource *source, psImageMaskType maskVal, float FACTOR, pmModelOpMode mode, bool add) { 535 536 int alt; 537 float logRdel = 0.1; 538 539 float Xc = source->satstar->Xo - source->pixels->col0 - 0.5; 540 float Yc = source->satstar->Yo - source->pixels->row0 - 0.5; 541 psVector *logRmodel = source->satstar->logRmodel; 542 psVector *logFmodel = source->satstar->logFmodel; 543 544 for (int iy = 0; iy < source->pixels->numRows; iy++) { 545 for (int ix = 0; ix < source->pixels->numCols; ix++) { 546 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue; 547 548 float radius = hypot (ix - Xc, iy - Yc) ; 549 float logR = log10(radius); 550 551 int bin = (int)(logR / logRdel); 552 553 // we are going to interpolate if possible, or extrapolate if necessary 554 if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1; 555 if (bin < 0) bin = 0; 556 557 // interpolate to the current radial position 558 // XXX BIG HACK : skip nan bins for now 559 560 float logF0 = logFmodel->data.F32[bin]; 561 float logR0 = logRmodel->data.F32[bin]; 562 if (!isfinite(logF0)) continue; 563 564 // interpolate between closest two bins if possible, extrapolate on ends 565 if (logR < logR0) { 566 alt = (bin > 0) ? bin - 1 : bin + 1; 567 } else { 568 alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1; 569 } 570 571 float logF1 = logFmodel->data.F32[alt]; 572 float logR1 = logRmodel->data.F32[alt]; 573 if (!isfinite(logF1)) continue; 574 575 // XXX use linear flux, not logFlux 576 float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR); 577 float flux = pow (10.0, logF); 578 579 if (mode & PM_MODEL_OP_NOISE) { 580 if (add) { 581 source->variance->data.F32[iy][ix] += FACTOR * flux; 582 } else { 583 source->variance->data.F32[iy][ix] -= FACTOR * flux; 584 } 585 } else { 586 if (add) { 587 source->pixels->data.F32[iy][ix] += flux; 588 } else { 589 source->pixels->data.F32[iy][ix] -= flux; 590 } 591 } 592 } 593 } 594 return true; 595 } 596 597 // Take logR + flux and generate radial bins logRmodelOut, logFmodelOut 598 bool psphotSatstarPhotometry (pmSource *source) { 599 600 if (!source->satstar) return false; 601 602 psVector *logRmodel = source->satstar->logRmodel; 603 psVector *logFmodel = source->satstar->logFmodel; 604 605 float fluxTotal = 0.0; 606 float logRdel = 0.1; // XXX user-define (or carry in satstar) 607 608 // integrate flux in radial bins 609 for (int i = 0; i < logRmodel->n; i++) { 610 // just add up the mean flux in each bin and multiply by the area of the bin 611 612 float logF = logFmodel->data.F32[i]; 613 if (!isfinite(logF)) continue; 614 float flux = pow(10.0, logF); // this is the mean flux per pixel (ie, surface brightness) 615 616 // bin (i) has log radius range (i*logRdel : (i+1)*logRdel) 617 float lRmin = logRdel*(i + 0); 618 float lRmax = logRdel*(i + 1); 619 620 float Rmin = pow(10.0, lRmin); 621 float Rmax = pow(10.0, lRmax); 622 623 float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin)); 624 625 fluxTotal += flux * Area; 626 } 627 628 source->psfMag = -2.5*log10(fluxTotal); 629 source->psfMagErr = 0.05; 630 631 // XXX I have no idea of a realistic error on the photometry here. the bottom line is that 632 // the error is totally dominated by the loss of charge due to saturation. I am not 633 // modeling the profile in any real detail other than to follow the radial bins. 634 635 source->extMag = NAN; 636 source->apMag = NAN; 637 source->apMagRaw = NAN; 638 source->apFlux = fluxTotal; 639 source->apFluxErr = 0.05*fluxTotal; 640 641 return true; 642 } 643 644 # if (0) 394 645 static bool skipDisplay = false; 395 646 bool psphotVisualRadialProfileSatstar (pmSource *source, psImageMaskType maskVal) { … … 743 994 return true; 744 995 } 745 746 bool psphotTestRadialModel (pmSource *source, psVector **logRmodelOut, psVector **logFmodelOut, psVector *logRad, psVector *logFlux, float Rmax) { 747 748 // we have log(radius) & log(flux). find the median flux in log radial bins 749 750 float logRmax = log10(Rmax); 751 float logRdel = 0.1; 752 753 psVector *logRmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 754 psVector *logFmodel = psVectorAlloc (1 + (int) (logRmax / logRdel), PS_TYPE_F32); 755 756 pmSourceRadialProfileSortPair (logRad, logFlux); 757 758 psStats *fluxStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 759 psVector *flux = psVectorAllocEmpty (100, PS_TYPE_F32); 760 761 int bin = 0; 762 for (int i = 0; i < logRmodel->n; i++) { 763 764 // bin (i) has log radius range (i*logRdel : (i+1)*logRdel) 765 float lRmin = logRdel*(i + 0); 766 float lRmax = logRdel*(i + 1); 767 768 // reset the flux vector 769 flux->n = 0; 770 psStatsInit (fluxStats); 771 772 while (logRad->data.F32[bin] < lRmax) { 773 if (isfinite(logFlux->data.F32[bin])) { 774 psVectorAppend (flux, logFlux->data.F32[bin]); 775 } 776 bin ++; 777 } 778 779 // we have the set of fluxes for this bin; find the median values 780 781 float Rmin = pow(10.0, lRmin); 782 float Rmax = pow(10.0, lRmax); 783 784 float Rmean = (2.0/3.0) * (pow(Rmax, 3.0) - pow(Rmin, 3.0)) / (PS_SQR(Rmax) - PS_SQR(Rmin)); 785 logRmodel->data.F32[i] = log10(Rmean); 786 787 float Area = M_PI * (PS_SQR(Rmax) - PS_SQR(Rmin)); 788 if (flux->n < 0.25*Area) { 789 logFmodel->data.F32[i] = NAN; 790 continue; 791 } 792 793 psVectorStats (fluxStats, flux, NULL, NULL, 0); 794 if (fluxStats->robustMedian > 0.0) { 795 logFmodel->data.F32[i] = log10(fluxStats->robustMedian); 796 } else { 797 logFmodel->data.F32[i] = -3.0; 798 } 799 // fprintf (stderr, "R: %f, F: %f +/- %f\n", Rmean, fluxStats->robustMedian, fluxStats->robustStdev); 800 } 801 802 // now how do i use this to subtract a model?? 803 *logRmodelOut = logRmodel; 804 *logFmodelOut = logFmodel; 805 806 // need to free stuff 807 psFree (fluxStats); 808 psFree (flux); 809 810 return true; 811 } 812 813 bool psphotTestRadialModelSub (pmSource *source, psVector *logRmodel, psVector *logFmodel, float Xo, float Yo, float Rmax, psImageMaskType maskVal) { 814 815 int alt; 816 float logRdel = 0.1; 817 818 for (int iy = 0; iy < source->pixels->numRows; iy++) { 819 for (int ix = 0; ix < source->pixels->numCols; ix++) { 820 if ((source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal)) continue; 821 822 float radius = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 823 float logR = log10(radius); 824 825 int bin = (int)(logR / logRdel); 826 827 // we are going to interpolate if possible, or extrapolate if necessary 828 if (bin >= logRmodel->n - 1) bin = logRmodel->n - 1; 829 if (bin < 0) bin = 0; 830 831 // interpolate to the current radial position 832 // XXX BIG HACK : skip nan bins for now 833 834 float logF0 = logFmodel->data.F32[bin]; 835 float logR0 = logRmodel->data.F32[bin]; 836 if (!isfinite(logF0)) continue; 837 838 // interpolate between closest two bins if possible, extrapolate on ends 839 if (logR < logR0) { 840 alt = (bin > 0) ? bin - 1 : bin + 1; 841 } else { 842 alt = (bin < logRmodel->n - 1) ? bin + 1 : bin - 1; 843 } 844 845 float logF1 = logFmodel->data.F32[alt]; 846 float logR1 = logRmodel->data.F32[alt]; 847 if (!isfinite(logF1)) continue; 848 849 // XXX use linear flux, not logFlux 850 float logF = InterpolateValues (logR0, logF0, logR1, logF1, logR); 851 float flux = pow (10.0, logF); 852 853 // float flux = InterpolateValues (logR0, logF0, logR1, logF1, logR); 854 source->pixels->data.F32[iy][ix] -= flux; 855 } 856 } 857 return true; 858 } 996 # endif 859 997 860 998 // only valid for F32 … … 902 1040 return true; 903 1041 } 1042 1043 bool psphotAddOrSubSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int fileIndex, psMetadata *recipe, bool add) { 1044 1045 bool status; 1046 1047 psTimerStart ("psphot.deblend.sat"); 1048 1049 // find the currently selected readout 1050 pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, fileIndex); // File of interest 1051 psAssert (file, "missing file?"); 1052 1053 pmReadout *readout = pmFPAviewThisReadout(view, file->fpa); 1054 psAssert (readout, "missing readout?"); 1055 1056 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 1057 psAssert (detections, "missing detections?"); 1058 1059 psArray *sources = detections->allSources; 1060 psAssert (sources, "missing sources?"); 1061 1062 if (!sources->n) { 1063 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend"); 1064 return true; 1065 } 1066 1067 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 1068 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 1069 assert (maskVal); 1070 1071 // examine sources in decreasing SN order 1072 for (int i = 0; i < sources->n; i++) { 1073 pmSource *source = sources->data[i]; 1074 1075 if (!(source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE)) continue; 1076 1077 if (!psphotSatstarProfileOp (source, maskVal, 1.0, 0, add)) continue; 1078 } 1079 1080 psLogMsg ("psphot", PS_LOG_DETAIL, "satstar op: %f sec\n", psTimerMark ("psphot.deblend.sat")); 1081 return true; 1082 } 1083
Note:
See TracChangeset
for help on using the changeset viewer.
