IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 26646


Ignore:
Timestamp:
Jan 20, 2010, 2:49:40 PM (16 years ago)
Author:
eugene
Message:

clean up of CZW code assuming that footprints are not corrupted, but keep it commented out until the size checks can be improved

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/20091201/psphot/src/psphotSourceSize.c

    r26508 r26646  
    1515} psphotSourceSizeOptions;
    1616
     17// local functions:
    1718bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf);
    1819bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options);
     
    2122bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
    2223bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
     24bool psphotMaskCosmicRayCZW (pmReadout *readout, pmSource *source, psImageMaskType maskVal);
     25
     26bool 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}
    2340
    2441// we need to call this function after sources have been fitted to the PSF model and
     
    7087
    7188    // We are using the value psfMag - 2.5*log10(moment.Sum) as a measure of the extendedness
    72     // of and object.  We need to model this distribution for the PSF stars before we can test
     89    // of an object.  We need to model this distribution for the PSF stars before we can test
    7390    // the significance for a specific object
    7491    // XXX move this to the code that generates the PSF?
     
    90107}
    91108
    92 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
     109// This attempt to mask the cosmic rays used the isophotal boundary
     110bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    93111
    94112    // replace the source flux
     
    103121    pmFootprint *footprint = peak->footprint;
    104122    if (!footprint) {
     123      psTrace("psphot.czw",2,"Using isophot CR mask code.");
     124     
    105125        // if we have not footprint, use the old code to mask by isophot
    106126        psphotMaskCosmicRayIsophot (source, maskVal, crMask);
     
    109129
    110130    if (!footprint->spans) {
     131      psTrace("psphot.czw",2,"Using isophot CR mask code.");
     132     
    111133        // if we have no footprint, use the old code to mask by isophot
    112134        psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    113135        return true;
    114136    }
    115 
     137    psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    116138    // 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    } 
    128150    return true;
    129151}
     
    232254        float dMag = source->psfMag - apMag;
    233255
    234         psVectorAppend (Ap, dMag);
    235         psVectorAppend (ApErr, source->errMag);
     256        psVectorAppend (Ap, 100, dMag);
     257        psVectorAppend (ApErr, 100, source->errMag);
    236258    }
    237259
     
    247269    options->ApResid = stats->robustMedian;
    248270    options->ApSysErr = psVectorSystematicError(dAp, ApErr, 0.05);
    249     // XXX this is quite arbitrary...
    250     if (!isfinite(options->ApSysErr)) options->ApSysErr = 0.01;
    251271    psLogMsg ("psphot", PS_LOG_DETAIL, "psf - Sum: %f +/- %f\n", options->ApResid, options->ApSysErr);
    252272
     
    375395        // Anything within this region is a probably PSF-like object. Saturated stars may land
    376396        // 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));
    378400        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;
    381406        }
    382407
     
    385410        // XXX this rule is not great
    386411        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);
    387416            source->mode |= PM_SOURCE_MODE_DEFECT;
    388417            Ncr ++;
     
    393422        // just large saturated regions.
    394423        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         
    395428            Nsat ++;
    396429            continue;
     
    400433        bool isEXT = (nSigma > options->nSigmaApResid) || ((Mxx > psfClump->X) && (Myy > psfClump->Y));
    401434        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         
    402439            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    403440            Next ++;
    404441            continue;
    405442        }
    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       
    407447        psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigma);
    408448        Nmiss ++;
     
    488528}
    489529
     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
    490532bool 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
     584bool 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
     763bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
    491764
    492765    // classify the sources based on the CR test (place this in a function?)
Note: See TracChangeset for help on using the changeset viewer.