IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 17516


Ignore:
Timestamp:
May 4, 2008, 2:10:40 PM (18 years ago)
Author:
eugene
Message:

some efficiency improvements and cleanups to the footprint code

Location:
trunk/psphot/src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/pmFootprint.h

    r17443 r17516  
    4747
    4848psImage *pmSetFootprintArrayIDs(const psArray *footprints, const bool relativeIDs);
    49 psImage *pmSetFootprintID(const pmFootprint *fp, const int id);
     49psImage *pmSetFootprintID(psImage *idImage, const pmFootprint *fp, const int id);
    5050void pmSetFootprintArrayIDsForImage(psImage *idImage,
    5151                                    const psArray *footprints, // the footprints to insert
  • trunk/psphot/src/pmFootprintArrayGrow.c

    r17443 r17516  
    88    assert (footprints->n == 0 || pmFootprintTest(footprints->data[0]));
    99
     10    psTimerStart ("grow");
     11
    1012    if (footprints->n == 0) {           // we don't know the size of the footprint's region
    1113        return psArrayAlloc(0);
     
    1618     */
    1719    psImage *idImage = pmSetFootprintArrayIDs(footprints, true);
     20    psLogMsg ("psphot", PS_LOG_DETAIL, "set footprint array IDs: %f sec\n", psTimerMark ("grow"));
     21
    1822    if (r <= 0) {
    1923        r = 1;                          // r == 1 => no grow
     
    3236    }
    3337
     38# if (1)   
     39    psImage *f32ImageIn = psImageCopy (NULL, idImage, PS_TYPE_F32);
     40    psImage *f32ImageOut = psImageConvolveFFT(NULL, f32ImageIn, NULL, 0, circle);
     41    psImage *grownIdImage = psImageCopy (NULL, f32ImageOut, PS_TYPE_S32);
     42    psFree (f32ImageIn);
     43    psFree (f32ImageOut);
     44# else
    3445    psImage *grownIdImage = psImageConvolveDirect(NULL, idImage, circle); // Here's the actual grow step
     46# endif
     47
     48    psLogMsg ("psphot", PS_LOG_DETAIL, "convolved with grow disc: %f sec\n", psTimerMark ("grow"));
    3549    psFree(circle);     
    3650
    3751    psArray *grown = pmFootprintsFind(grownIdImage, 0.5, 1); // and here we rebuild the grown footprints
     52    psLogMsg ("psphot", PS_LOG_DETAIL, "found grown footprints: %f sec\n", psTimerMark ("grow"));
     53
    3854    assert (grown != NULL);
    3955    psFree(idImage); psFree(grownIdImage);
     
    4662    psFree((psArray *)peaks);
    4763
     64    psLogMsg ("psphot", PS_LOG_DETAIL, "finished grow: %f sec\n", psTimerMark ("grow"));
     65
    4866    return grown;
    4967   
  • trunk/psphot/src/pmFootprintIDs.c

    r17443 r17516  
    7474 * Set an image to the value of footprint's ID whever they may fall
    7575 */
    76 psImage *pmSetFootprintID(const pmFootprint *fp, // the footprint to insert
     76psImage *pmSetFootprintID(psImage *idImage,
     77                          const pmFootprint *fp, // the footprint to insert
    7778                          const int id) {       // the desired ID
    7879   assert(fp != NULL && pmFootprintTest((const psPtr)fp));
     
    8384   assert (numCols >= 0 && numRows >= 0);
    8485   
    85    psImage *idImage = psImageAlloc(numCols, numRows, PS_TYPE_S32);
     86   if (idImage == NULL) {
     87       idImage = psImageAlloc(numCols, numRows, PS_TYPE_S32);
     88   } else {
     89       assert (idImage->numCols == numCols);
     90       assert (idImage->numRows == numRows);
     91       // XXX assert on type (S32)
     92   }
    8693   P_PSIMAGE_SET_ROW0(idImage, row0);
    8794   P_PSIMAGE_SET_COL0(idImage, col0);
  • trunk/psphot/src/pmFootprintsAssignPeaks.c

    r17443 r17516  
    88psErrorCode
    99pmFootprintsAssignPeaks(psArray *footprints,    // the pmFootprints
    10                           const psArray *peaks) { // the pmPeaks
     10                        const psArray *peaks) { // the pmPeaks
    1111    assert (footprints != NULL);
    1212    assert (footprints->n == 0 || pmFootprintTest(footprints->data[0]));
     
    5454   
    5555    psFree(ids);
    56     //
     56
    5757    // Make sure that peaks within each footprint are sorted and unique
    58     //
    5958    for (int i = 0; i < footprints->n; i++) {
     59       
    6060        pmFootprint *fp = footprints->data[i];
     61
     62        // XXX are we allowed to have peak-less footprints??
     63        if (!fp->peaks->n) continue;
     64
    6165        fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
    6266
    63         for (int j = 1; j < fp->peaks->n; j++) { // check for duplicates
    64             if (fp->peaks->data[j] == fp->peaks->data[j-1]) {
    65                 (void)psArrayRemoveIndex(fp->peaks, j);
    66                 j--;                    // we moved everything down one
     67        // XXX EAM : the algorithm below should be much faster than using psArrayRemove if
     68        // the number of peaks in the footprint is large, or if there are no duplicates.
     69        // if we have a lot of small-number peak arrays with duplicates, this may be
     70        // slower.
     71
     72        // track the number of good peaks in the footprint
     73        int nGood = 1;
     74
     75        // check for duplicates
     76        // on first pass, we set the index to NULL if peak is a duplicate
     77        // XXX EAM : this can leave behind duplicates of the same S/N
     78        // (if sorted list has A, B, A, B ...)
     79        for (int j = 1; j < fp->peaks->n; j++) {
     80            if (fp->peaks->data[j] == fp->peaks->data[nGood]) {
     81                // everything on the array has its own mem reference; free and drop this one
     82                psFree (fp->peaks->data[j]);
     83                fp->peaks->data[j] = NULL;
     84            } else {
     85                nGood ++;
    6786            }
    6887        }
     88
     89        // no deleted peaks, go to next footprint
     90        if (nGood == fp->peaks->n) continue;
     91
     92        int nKeep = 0;
     93
     94        psArray *goodPeaks = psArrayAlloc (nGood);
     95        // on second pass, save the good peaks
     96        for (int j = 0; j < fp->peaks->n; j++) { // check for duplicates
     97            if (fp->peaks->data[j] == NULL) continue;
     98            // transfer the data (NULL to avoid double free)
     99            // this is only slightly sleazy
     100            goodPeaks->data[nKeep] = fp->peaks->data[j];
     101            fp->peaks->data[j] = NULL;
     102            nKeep ++;
     103        }
     104        psAssert (nGood == nKeep, "mis-counted nKeep or nGood");
     105
     106        // free the old (now NULL-filled) array
     107        psFree (fp->peaks);
     108        fp->peaks = goodPeaks;
    69109    }
     110
     111    // (void)psArrayRemoveIndex(fp->peaks, j);
     112
    70113
    71114    return PS_ERR_NONE;
  • trunk/psphot/src/psphotCullPeaks.c

    r17443 r17516  
    5252  * starting point, discard the peak.
    5353  */
    54 psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint
     54psErrorCode pmFootprintCullPeaks_OLD(const psImage *img, // the image wherein lives the footprint
    5555                                 const psImage *weight, // corresponding variance image
    5656                                 pmFootprint *fp, // Footprint containing mortal peaks
     
    125125        pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
    126126        brightPeaks->n = 0;             // don't double free
    127         psImage *idImg = pmSetFootprintID(peakFootprint, peak_id);
     127        psImage *idImg = pmSetFootprintID(NULL, peakFootprint, peak_id);
    128128        psFree(peakFootprint);
    129129
     
    158158}
    159159
     160 /*
     161  * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently
     162  * isolated.  More precisely, for each peak find the highest coll that you'd have to traverse
     163  * to reach a still higher peak --- and if that coll's more than nsigma DN below your
     164  * starting point, discard the peak.
     165  */
     166
     167# define IN_PEAK 1
     168psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint
     169                                 const psImage *weight, // corresponding variance image
     170                                 pmFootprint *fp, // Footprint containing mortal peaks
     171                                 const float nsigma_delta, // how many sigma above local background a peak
     172                                 // needs to be to survive
     173                                 const float min_threshold) { // minimum permitted coll height
     174    assert (img != NULL); assert (img->type.type == PS_TYPE_F32);
     175    assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32);
     176    assert (img->row0 == weight->row0 && img->col0 == weight->col0);
     177    assert (fp != NULL);
     178
     179    if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do
     180        return PS_ERR_NONE;
     181    }
     182
     183    psRegion subRegion;                 // desired subregion; 1 larger than bounding box (grr)
     184    subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1;
     185    subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1;
     186
     187    psImage *subImg = psImageSubset((psImage *)img, subRegion);
     188    psImage *subWt = psImageSubset((psImage *)weight, subRegion);
     189    assert (subImg != NULL && subWt != NULL);
     190
     191    psImage *idImg = psImageAlloc(subImg->numCols, subImg->numRows, PS_TYPE_S32);
     192
     193    // We need a psArray of peaks brighter than the current peak. 
     194    // We reject peaks which either:
     195    // 1) are below the local threshold
     196    // 2) have a brighter peak within their threshold
     197
     198    // allocate the full-sized array.  if the final array is much smaller, we can realloc
     199    // at that point.
     200    psArray *brightPeaks = psArrayAllocEmpty(fp->peaks->n);
     201    psArrayAdd (brightPeaks, 128, fp->peaks->data[0]);
     202
     203    // The brightest peak is always safe; go through other peaks trying to cull them
     204    for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
     205        const pmPeak *peak = fp->peaks->data[i];
     206        int x = peak->x - subImg->col0;
     207        int y = peak->y - subImg->row0;
     208        //
     209        // Find the level nsigma below the peak that must separate the peak
     210        // from any of its friends
     211        //
     212        assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
     213        const float stdev = sqrt(subWt->data.F32[y][x]);
     214        float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev;
     215        if (isnan(threshold) || threshold < min_threshold) {
     216            // min_threshold is assumed to be below the detection threshold,
     217            // so all the peaks are pmFootprint, and this isn't the brightest
     218            continue;
     219        }
     220
     221        // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?
     222        if (threshold > subImg->data.F32[y][x]) {
     223            threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;
     224        }
     225
     226        // XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint
     227        // perhaps this should alloc a single ID image above and pass it in to be set.
     228
     229        // XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31)
     230
     231        // at this point brightPeaks only has the peaks brighter than the current
     232        pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);
     233
     234        // XXX need to supply the image here
     235        // we set the IDs to either 1 (in peak) or 0 (not in peak)
     236        pmSetFootprintID (idImg, peakFootprint, IN_PEAK);
     237        psFree(peakFootprint);
     238
     239        // Check if any of the previous (brighter) peaks are within the footprint of this peak
     240        // If so, the current peak is bogus; drop it.
     241        bool keep = true;
     242        for (int j = 0; keep && (j < brightPeaks->n); j++) {
     243            const pmPeak *peak2 = fp->peaks->data[j];
     244            int x2 = peak2->x - subImg->col0;
     245            int y2 = peak2->y - subImg->row0;
     246            if (idImg->data.S32[y2][x2] == IN_PEAK)
     247                // There's a brighter peak within the footprint above threshold; so cull our initial peak
     248                keep = false;
     249        }
     250        if (!keep) continue;
     251
     252        psArrayAdd (brightPeaks, 128, fp->peaks->data[i]);
     253    }
     254
     255    psFree (fp->peaks);
     256    fp->peaks = brightPeaks;
     257
     258    psFree(idImg);
     259    psFree(subImg);
     260    psFree(subWt);
     261
     262    return PS_ERR_NONE;
     263}
     264
  • trunk/psphot/src/psphotFindFootprints.c

    r17443 r17516  
    11# include "psphotInternal.h"
    2 
    3 // N.b. We're not culling this list; call pmFootprintCullPeaks if you
    4 // want to do that
    52
    63bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psMaskType maskVal) {
  • trunk/psphot/src/psphotFitSourcesLinear.c

    r16820 r17516  
    158158    // set the sky, sky_x, sky_y components of border matrix
    159159    SetBorderMatrixElements (border, readout, fitSources, CONSTANT_PHOTOMETRIC_WEIGHTS, SKY_FIT_ORDER);
     160    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "set border: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
    160161
    161162    psSparseConstraint constraint;
     
    174175        skyfit = NULL;
    175176    }
     177    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "solve matrix: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
    176178
    177179    // adjust I0 for fitSources and subtract
     
    192194        source->mode |= PM_SOURCE_MODE_SUBTRACTED;
    193195    }
     196    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
    194197
    195198    // measure chisq for each source
     
    199202        pmSourceChisq (model, source->pixels, source->maskObj, source->weight, maskVal);
    200203    }
     204    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f (%d elements)\n", psTimerMark ("psphot"), sparse->Nelem);
    201205
    202206    // psFree (index);
     
    212216}
    213217
     218// XXX do we need this?
     219
    214220// Calculate the weight terms for the sky fit component of the matrix.  This function operates
    215221// on the pixels which correspond to all of the sources of interest.  These elements fill in
     
    222228    fullArray = psRegionForImage (readout->mask, fullArray);
    223229    psImageMaskRegion (readout->mask, fullArray, "OR", PM_MASK_MARK);
     230    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 1: %f sec\n", psTimerMark ("psphot"));
    224231
    225232    // turn off MARK for all object pixels
     
    232239        psImageMaskCircle (source->maskView, x, y, model->radiusFit, "AND", PS_NOT_U8(PM_MASK_MARK));
    233240    }
     241    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 2: %f sec\n", psTimerMark ("psphot"));
    234242
    235243    // accumulate the image statistics from the masked regions
     
    268276        }
    269277    }
     278    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 3: %f sec\n", psTimerMark ("psphot"));
    270279
    271280    // turn off MARK for all image pixels
    272281    psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_U8(PM_MASK_MARK));
     282    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 4: %f sec\n", psTimerMark ("psphot"));
    273283
    274284    // set the Border T elements
     
    287297        psSparseBorderElementT (border, 2, 2, y2);
    288298    }
     299    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "step 5: %f sec\n", psTimerMark ("psphot"));
     300
    289301    return true;
    290302}
Note: See TracChangeset for help on using the changeset viewer.