Changeset 26646
- Timestamp:
- Jan 20, 2010, 2:49:40 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20091201/psphot/src/psphotSourceSize.c
r26508 r26646 15 15 } psphotSourceSizeOptions; 16 16 17 // local functions: 17 18 bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf); 18 19 bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options); … … 21 22 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 22 23 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 24 bool psphotMaskCosmicRayCZW (pmReadout *readout, pmSource *source, psImageMaskType maskVal); 25 26 bool psphotMaskCosmicRayFootprintCheck (psArray *sources) { 27 28 for (int i = 0; i < sources->n; i++) { 29 pmSource *source = sources->data[i]; 30 pmPeak *peak = source->peak; 31 pmFootprint *footprint = peak->footprint; 32 if (!footprint) continue; 33 for (int j = 0; j < footprint->spans->n; j++) { 34 pmSpan *sp = footprint->spans->data[j]; 35 psAssert (sp, "missing span"); 36 } 37 } 38 return true; 39 } 23 40 24 41 // we need to call this function after sources have been fitted to the PSF model and … … 70 87 71 88 // We are using the value psfMag - 2.5*log10(moment.Sum) as a measure of the extendedness 72 // of an dobject. We need to model this distribution for the PSF stars before we can test89 // of an object. We need to model this distribution for the PSF stars before we can test 73 90 // the significance for a specific object 74 91 // XXX move this to the code that generates the PSF? … … 90 107 } 91 108 92 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 109 // This attempt to mask the cosmic rays used the isophotal boundary 110 bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 93 111 94 112 // replace the source flux … … 103 121 pmFootprint *footprint = peak->footprint; 104 122 if (!footprint) { 123 psTrace("psphot.czw",2,"Using isophot CR mask code."); 124 105 125 // if we have not footprint, use the old code to mask by isophot 106 126 psphotMaskCosmicRayIsophot (source, maskVal, crMask); … … 109 129 110 130 if (!footprint->spans) { 131 psTrace("psphot.czw",2,"Using isophot CR mask code."); 132 111 133 // if we have no footprint, use the old code to mask by isophot 112 134 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 113 135 return true; 114 136 } 115 137 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 116 138 // mask all of the pixels covered by the spans of the footprint 117 for (int j = 1; j < footprint->spans->n; j++) { 118 pmSpan *span1 = footprint->spans->data[j]; 119 120 int iy = span1->y; 121 int xs = span1->x0; 122 int xe = span1->x1; 123 124 for (int ix = xs; ix < xe; ix++) { 125 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 126 } 127 } 139 for (int j = 1; j < footprint->spans->n; j++) { 140 pmSpan *span1 = footprint->spans->data[j]; 141 142 int iy = span1->y; 143 int xs = span1->x0; 144 int xe = span1->x1; 145 146 for (int ix = xs; ix < xe; ix++) { 147 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 148 } 149 } 128 150 return true; 129 151 } … … 232 254 float dMag = source->psfMag - apMag; 233 255 234 psVectorAppend (Ap, dMag);235 psVectorAppend (ApErr, source->errMag);256 psVectorAppend (Ap, 100, dMag); 257 psVectorAppend (ApErr, 100, source->errMag); 236 258 } 237 259 … … 247 269 options->ApResid = stats->robustMedian; 248 270 options->ApSysErr = psVectorSystematicError(dAp, ApErr, 0.05); 249 // XXX this is quite arbitrary...250 if (!isfinite(options->ApSysErr)) options->ApSysErr = 0.01;251 271 psLogMsg ("psphot", PS_LOG_DETAIL, "psf - Sum: %f +/- %f\n", options->ApResid, options->ApSysErr); 252 272 … … 375 395 // Anything within this region is a probably PSF-like object. Saturated stars may land 376 396 // in this region, but are detected elsewhere on the basis of their peak value. 377 bool isPSF = (fabs(nSigma) < options->nSigmaApResid) && (fabs(Mxx - psfClump->X) < options->nSigmaMoments*psfClump->dX) && (fabs(Myy - psfClump->Y) < options->nSigmaMoments*psfClump->dY); 397 bool isPSF = ((fabs(nSigma) < options->nSigmaApResid) && 398 (fabs(Mxx - psfClump->X) < options->nSigmaMoments*psfClump->dX) && 399 (fabs(Myy - psfClump->Y) < options->nSigmaMoments*psfClump->dY)); 378 400 if (isPSF) { 379 Npsf ++; 380 continue; 401 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g PSF\t%g %g\n", 402 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 403 options->nSigmaApResid,options->nSigmaMoments); 404 Npsf ++; 405 continue; 381 406 } 382 407 … … 385 410 // XXX this rule is not great 386 411 if ((Mxx < psfClump->X) || (Myy < psfClump->Y)) { 412 413 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g CR\t%g %g\n", 414 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 415 options->nSigmaApResid,options->nSigmaMoments); 387 416 source->mode |= PM_SOURCE_MODE_DEFECT; 388 417 Ncr ++; … … 393 422 // just large saturated regions. 394 423 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 424 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g SAT\t%g %g\n", 425 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 426 options->nSigmaApResid,options->nSigmaMoments); 427 395 428 Nsat ++; 396 429 continue; … … 400 433 bool isEXT = (nSigma > options->nSigmaApResid) || ((Mxx > psfClump->X) && (Myy > psfClump->Y)); 401 434 if (isEXT) { 435 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Ext\t%g %g\n", 436 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 437 options->nSigmaApResid,options->nSigmaMoments); 438 402 439 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 403 440 Next ++; 404 441 continue; 405 442 } 406 443 psTrace("psphot.czw",4,"CLASS: %g %g\t%g %g %g %g %g %g\t%g %g\t%g Unk\t%g %g\n", 444 source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigma, 445 options->nSigmaApResid,options->nSigmaMoments); 446 407 447 psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigma); 408 448 Nmiss ++; … … 488 528 } 489 529 530 // given an object suspected to be a defect, generate a pixel mask using the Lapacian transform 531 // if enough of the object is detected as 'sharp', consider the object a cosmic ray 490 532 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) { 533 534 for (int i = 0; i < sources->n; i++) { 535 pmSource *source = sources->data[i]; 536 537 // Integer position of peak 538 int xPeak = source->peak->xf - source->pixels->col0 + 0.5; 539 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; 540 541 // Skip sources which are too close to a boundary. These are mostly caught as DEFECT 542 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 543 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 544 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 545 // psTrace("psphot.czw", 2, "Not calculating crNsigma due to edge\n"); 546 continue; 547 } 548 549 // this source is thought to be a cosmic ray. flag the detection and mask the pixels 550 if (source->mode & PM_SOURCE_MODE_DEFECT) { 551 // XXX this is running slowly and is too agressive, but it more-or-less works 552 // psphotMaskCosmicRayCZW(readout, source, options->crMask); 553 554 // XXX these are the old versions which we are not using 555 // psphotMaskCosmicRay (readout->mask, source, maskVal, crMask); 556 // psphotMaskCosmicRay_Old (source, maskVal, crMask); 557 } 558 } 559 560 // now that we have masked pixels associated with CRs, we can grow the mask 561 if (options->grow > 0) { 562 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask 563 psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow); 564 psImageConvolveSetThreads(oldThreads); 565 if (!newMask) { 566 psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask"); 567 return false; 568 } 569 psFree(readout->mask); 570 readout->mask = newMask; 571 } 572 573 // XXX test : save the mask image 574 if (0) { 575 psphotSaveImage (NULL, readout->mask, "mask.fits"); 576 } 577 return true; 578 } 579 580 // Comments by CZW 20091209 : Mechanics of how to identify CR pixels taken from "Cosmic-Ray 581 // Rejection by Laplacian Edge Detection" by Pieter van Dokkum, arXiv:astro-ph/0108003. This 582 // does no repair or recovery of the CR pixels, it only masks them out. My test code can be 583 // found at /data/ipp031.0/watersc1/psphot.20091209/algo_check.c 584 bool psphotMaskCosmicRayCZW (pmReadout *readout, pmSource *source, psImageMaskType maskVal) { 585 586 // Get the actual images and information about the peak. 587 psImage *mask = readout->mask; 588 pmPeak *peak = source->peak; 589 pmFootprint *footprint = peak->footprint; 590 591 int xm = footprint->bbox.x0; 592 int xM = footprint->bbox.x1; 593 int ym = footprint->bbox.y0; 594 int yM = footprint->bbox.y1; 595 596 if (xm < 0) { xm = 0; } 597 if (ym < 0) { ym = 0; } 598 if (xM > mask->numCols) { xM = mask->numCols; } 599 if (yM > mask->numRows) { yM = mask->numRows; } 600 int dx = xM - xm; 601 int dy = yM - ym; 602 603 // Bounding boxes are inclusive of final pixel 604 // XXX ensure dx,dy do not become too large here 605 dx++; 606 dy++; 607 608 psImage *image= readout->image; 609 psImage *variance = readout->variance; 610 611 int binning = 1; 612 float sigma_thresh = 2.0; 613 int iteration = 0; 614 int max_iter = 5; 615 float noise_factor = 5.0 / 4.0; // Intrinsic to the Laplacian making noise spikes spikier. 616 617 // Temporary images. 618 psImage *mypix = psImageAlloc(dx,dy,image->type.type); 619 psImage *myvar = psImageAlloc(dx,dy,image->type.type); 620 psImage *binned = psImageAlloc(dx * binning,dy * binning,image->type.type); 621 psImage *conved = psImageAlloc(dx * binning,dy * binning,image->type.type); 622 psImage *edges = psImageAlloc(dx,dy,image->type.type); 623 psImage *mymask = psImageAlloc(dx,dy,PS_TYPE_IMAGE_MASK); 624 625 int x,y; 626 // Load my copy of things. 627 for (x = 0; x < dx; x++) { 628 for (y = 0; y < dy; y++) { 629 psImageSet(mypix,x,y,psImageGet(image,x+xm,y+ym)); 630 psImageSet(myvar,x,y,psImageGet(variance,x+xm,y+ym)); 631 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0x00; 632 } 633 } 634 // Mask so I can see on the output image where the footprint is. 635 for (int i = 0; i < footprint->spans->n; i++) { 636 pmSpan *sp = footprint->spans->data[i]; 637 for (int j = sp->x0; j <= sp->x1; j++) { 638 y = sp->y - ym; 639 x = j - xm; 640 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x01; 641 } 642 } 643 644 int CRpix_count = 0; 645 do { 646 CRpix_count = 0; 647 // Zero out my temp images. 648 for (x = 0; x < binning * dx; x++) { 649 for (y = 0; y < binning * dy; y++) { 650 psImageSet(binned,x,y,0.0); 651 psImageSet(conved,x,y,0.0); 652 psImageSet(edges,x/binning,y/ binning,0.0); 653 } 654 } 655 // Make subsampled image. Maybe this should be called "unbinned" or something 656 for (x = 0; x < binning * dx; x++) { 657 for (y = 0; y < binning * dy; y++) { 658 psImageSet(binned,x,y,psImageGet(mypix,x / binning,y / binning)); 659 } 660 } 661 // Apply Laplace transform (kernel = [[0 -0.25 0][-0.25 1 -0.25][0 -0.25 0]]), clipping at zero 662 for (x = 1; x < dx - 1; x++) { 663 for (y = 1; y < dy - 1; y++) { 664 psImageSet(conved,x,y,psImageGet(binned,x,y) - 0.25 * 665 (psImageGet(binned,x-1,y) + psImageGet(binned,x+1,y) + 666 psImageGet(binned,x,y-1) + psImageGet(binned,x,y+1))); 667 if (psImageGet(conved,x,y) < 0.0) { 668 psImageSet(conved,x,y,0.0); 669 } 670 } 671 } 672 // Create an edge map by rebinning 673 for (x = 0; x < binning * dx; x++) { 674 for (y = 0; y < binning * dy; y++) { 675 psImageSet(edges,x / binning, y / binning, 676 psImageGet(edges, x / binning, y / binning) + 677 psImageGet(conved,x,y)); 678 } 679 } 680 // Modify my mask if we're above the significance threshold 681 for (x = 0; x < dx; x++) { 682 for (y = 0; y < dy; y++) { 683 if ( psImageGet(edges,x,y) / (binning * sqrt(noise_factor * psImageGet(myvar,x,y))) > sigma_thresh ) { 684 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x01) { 685 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x40; 686 CRpix_count++; 687 } 688 } 689 } 690 } 691 692 // "Repair" Masked pixels for the next round. 693 for (x = 1; x < dx - 1; x++) { 694 for (y = 1; y < dy - 1; y++) { 695 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 696 psImageSet(mypix,x,y,0.25 * 697 (psImageGet(mypix,x-1,y) + psImageGet(mypix,x+1,y) + 698 psImageGet(mypix,x,y-1) + psImageGet(mypix,x,y+1))); 699 } 700 } 701 } 702 703 # if 0 704 if ((psTraceGetLevel("psphot.czw") >= 2)&&(abs(xm - 2770) < 5)&&(abs(ym - 2581) < 5)&&(iteration == 0)) { 705 psTrace("psphot.czw",2,"TRACEMOTRON %d %d %d %d %d\n",xm,ym,dx,dy,iteration); 706 psphotSaveImage (NULL, mypix, "czw.pix.fits"); 707 psphotSaveImage (NULL, myvar, "czw.var.fits"); 708 psphotSaveImage (NULL, binned, "czw.binn.fits"); 709 psphotSaveImage (NULL, conved, "czw.conv.fits"); 710 psphotSaveImage (NULL, edges, "czw.edge.fits"); 711 psphotSaveImage (NULL, mymask, "czw.mask.fits"); 712 } 713 # endif 714 715 psTrace("psphot.czw",2,"Iter: %d Count: %d",iteration,CRpix_count); 716 iteration++; 717 } while ((iteration < max_iter)&&(CRpix_count > 0)); 718 719 // A solitary masked pixel is likely a lie. Remove those. 720 for (x = 0; x < dx; x++) { 721 for (y = 0; y < dy; y++) { 722 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 723 if ((x-1 >= 0)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x-1] & 0x40)) { 724 continue; 725 } 726 if ((y-1 >= 0)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y-1][x] & 0x40)) { 727 continue; 728 } 729 if ((x+1 < dx)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x+1] & 0x40)) { 730 continue; 731 } 732 if ((y+1 < dy)&&(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y+1][x] & 0x40)) { 733 continue; 734 } 735 mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] ^= 0x40; 736 } 737 } 738 } 739 740 // transfer temporary mask to real mask 741 for (x = 0; x < dx; x++) { 742 for (y = 0; y < dy; y++) { 743 if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) { 744 mask->data.PS_TYPE_IMAGE_MASK_DATA[y+ym+mask->row0][x+xm+mask->col0] |= maskVal; 745 } 746 } 747 } 748 749 // XXX if we decide this REALLY is a cosmic ray, set the CR_LIMIT bit 750 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 751 752 psFree(mypix); 753 psFree(myvar); 754 psFree(binned); 755 psFree(conved); 756 psFree(edges); 757 psFree(mymask); 758 759 return true; 760 } 761 762 // this was an old attempt to identify cosmic rays based on the peak curvature 763 bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) { 491 764 492 765 // classify the sources based on the CR test (place this in a function?)
Note:
See TracChangeset
for help on using the changeset viewer.
