IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Feb 10, 2010, 4:08:49 PM (16 years ago)
Author:
eugene
Message:

updates from trunk (includes fix to robust stats)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/20091201/psLib/src/math/psStats.c

    r25884 r26868  
    749749    // Iterate to get the best bin size; an iteration limit is enforced at the bottom of the loop.
    750750    for (int iterate = 1; iterate > 0; iterate++) {
    751         psTrace(TRACE, 6,
    752                 "-------------------- Iterating on Bin size.  Iteration number %d --------------------\n",
    753                 iterate);
     751        psTrace(TRACE, 6, "-------------------- Iterating on Bin size.  Iteration number %d --------------------\n", iterate);
     752
     753        if (iterate >= PS_ROBUST_MAX_ITERATIONS) {
     754          // This occurs when a large number of the values are identical --- a bin size cannot be found
     755          // that will spread out the distribution.  Therefore, set what we can, and fall over
     756          // gracefully.
     757          COUNT_WARNING(10, 100, "Maximum number of iterations (%d) exceeded.", PS_ROBUST_MAX_ITERATIONS);
     758          goto escape;
     759        }
    754760
    755761        // Get the minimum and maximum values
     
    791797        psTrace(TRACE, 6, "Initial robust bin size is %.2f\n", binSize);
    792798
    793         // ADD step 0: Construct the histogram with the specified bin size.  NOTE: we can not specify the bin
    794         // size precisely since the argument to psHistogramAlloc() is the number of bins, not the binSize.  If
    795         // we get here, we know that binSize != 0.0.
    796         long numBins = (max - min) / binSize; // Number of bins
     799        // ADD step 0: Construct the histogram with the specified bin size.  NOTE: we can
     800        // not specify the bin size precisely since the argument to psHistogramAlloc() is
     801        // the number of bins, not the binSize.  If we get here, we know that binSize !=
     802        // 0.0.  We can also have a floating-point round-off error such that the last bin
     803        // of the histogram does not correspond exactly with the value of 'max'.  Let's be
     804        // a bit generous and extend the histogram by two bins in either direction
     805        long numBins = 4 + (max - min) / binSize; // Number of bins
    797806        psTrace(TRACE, 6, "Numbins is %ld\n", numBins);
    798807        psTrace(TRACE, 6, "Creating a robust histogram from data range (%.2f - %.2f)\n", min, max);
    799808        // Generate the histogram
    800         histogram = psHistogramAlloc(min, max, numBins);
     809        histogram = psHistogramAlloc(min - 2.0*binSize, max + 2.0*binSize, numBins);
    801810        // XXXXX we need to consider this step if errors -> variance
    802811        if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
     
    807816            psFree(statsMinMax);
    808817            psFree(mask);
    809 
    810818            return false;
    811819        }
     
    814822            PS_VECTOR_PRINT_F32(histogram->nums);
    815823        }
     824
     825        // perversity check: if most of the values land in a single bin, then we probably
     826        // have a perverse case (eg, small number of points at extremely large / small
     827        // values; nearly bi-modal distribution).  if so, keep only points within 5? 10?
     828        // bins of that excess bin:
     829        int nMaxBin = 0;
     830        int iMaxBin = 0;
     831        for (long i = 1; i < histogram->nums->n; i++) {
     832            if (histogram->nums->data.F32[i] > nMaxBin) {
     833                nMaxBin = histogram->nums->data.F32[i];
     834                iMaxBin = i;
     835            }
     836        }
     837        if (nMaxBin > numValid / 2) {
     838            float minKeep = histogram->bounds->data.F32[iMaxBin] - 10*binSize;
     839            float maxKeep = histogram->bounds->data.F32[iMaxBin + 1] + 10*binSize;
     840            int nInvalid = 0;
     841            for (long i = 0; i < myVector->n; i++) {
     842                // skip the already-masked values
     843                if (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskVal) continue;
     844                bool invalid = false;
     845                invalid |= (myVector->data.F32[i] <= minKeep);
     846                invalid |= (myVector->data.F32[i] >= maxKeep);
     847                invalid |= (!isfinite(myVector->data.F32[i]));
     848                if (!invalid) continue;
     849                mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = maskVal;
     850                nInvalid ++;
     851            }
     852
     853            if (nInvalid) {
     854              psTrace(TRACE, 6, "data is concentrated in a single bin, masking %d extreme outliers and retrying\n", nInvalid);
     855              psFree(histogram);
     856              psFree(cumulative);
     857              histogram = NULL;
     858              cumulative = NULL;
     859              continue;
     860            }
     861            // if we did not mask anything, give up.
     862        }
    816863
    817864        // ADD step 1: Convert the specific histogram to a cumulative histogram
     
    10071054    stats->robustN50 = N50;
    10081055    psTrace(TRACE, 6, "The robustN50 is %ld.\n", N50);
     1056    psTrace(TRACE, 6, "The robust median and stdev are %f, %f\n", stats->robustMedian, stats->robustStdev);
    10091057
    10101058    // Clean up
Note: See TracChangeset for help on using the changeset viewer.