IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 14428


Ignore:
Timestamp:
Aug 8, 2007, 9:34:58 AM (19 years ago)
Author:
Paul Price
Message:

Adding higher-order moments (skewness and kurtosis).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psStats.c

    r13991 r14428  
    1313 * use ->min and ->max (PS_STAT_USE_RANGE)
    1414 *
    15  *  @version $Revision: 1.213 $ $Name: not supported by cvs2svn $
    16  *  @date $Date: 2007-06-30 00:35:38 $
     15 *  @version $Revision: 1.214 $ $Name: not supported by cvs2svn $
     16 *  @date $Date: 2007-08-08 19:34:58 $
    1717 *
    1818 *  Copyright 2006 IfA, University of Hawaii
     
    382382
    383383using the method below, with a single loop for various options costs only a small amount and is
    384 much easier to debug. running 10000 tests of 1000 point vectors for the two methods gives:
    385 
    386                      single
    387 (mask: 0, range: 0): 0.193 sec
    388 (mask: 1, range: 0): 0.257 sec
    389 (mask: 0, range: 0): 0.349 sec
    390 (mask: 1, range: 0): 0.401 sec
    391 
     384much easier to debug.
    392385*****************************************************************************/
    393     static bool vectorSampleStdev(const psVector* myVector,
    394                                   const psVector* errors,
    395                                   const psVector* maskVector,
    396                                   psMaskType maskVal,
    397                                   psStats* stats)
     386
     387static bool vectorSampleStdev(const psVector* myVector,
     388                              const psVector* errors,
     389                              const psVector* maskVector,
     390                              psMaskType maskVal,
     391                              psStats* stats)
    398392{
    399393    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
     
    467461    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
    468462
     463    return true;
     464}
     465
     466static bool vectorSampleMoments(const psVector* myVector,
     467                                const psVector* maskVector,
     468                                psMaskType maskVal,
     469                                psStats* stats)
     470{
     471    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
     472
     473    // This procedure requires the mean and standard deviation
     474    if (!(stats->results & PS_STAT_SAMPLE_MEAN)) {
     475        vectorSampleMean(myVector, NULL, maskVector, maskVal, stats);
     476    }
     477    if (isnan(stats->sampleMean)) {
     478        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample mean is NAN.\n");
     479        goto SAMPLE_MOMENTS_BAD;
     480    }
     481    if (!(stats->results & PS_STAT_SAMPLE_STDEV)) {
     482        vectorSampleMean(myVector, NULL, maskVector, maskVal, stats);
     483    }
     484    if (isnan(stats->sampleStdev) || stats->sampleStdev == 0.0) {
     485        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample mean is NAN or 0.\n");
     486        goto SAMPLE_MOMENTS_BAD;
     487    }
     488
     489    psF32 *data = myVector->data.F32;   // Dereference
     490    psU8 *maskData = (maskVector == NULL) ? NULL : maskVector->data.U8;
     491    bool useRange = stats->options & PS_STAT_USE_RANGE;
     492
     493    // Accumulate the sums
     494    double mean = stats->sampleMean;    // The mean
     495    double sum3 = 0.0;                  // Sum of the cubes of the differences
     496    double sum4 = 0.0;                  // Sum of the fourth powers of the differences
     497    long count = 0;                     // Number of data points being used
     498    for (long i = 0; i < myVector->n; i++) {
     499        // Check if the data is with the specified range
     500        if (useRange && (data[i] < stats->min)) {
     501            continue;
     502        }
     503        if (useRange && (data[i] > stats->max)) {
     504            continue;
     505        }
     506        if (maskData && (maskData[i] & maskVal)) {
     507            continue;
     508        }
     509
     510        double diff = data[i] - mean;   // Difference from the mean
     511        double temp;                    // Temporary variable for accumulating
     512
     513        sum3 += temp = PS_SQR(diff);
     514        sum4 += temp * diff;
     515
     516        count++;
     517    }
     518
     519    assert(count > 1);                  // It should be, because we have a mean and standard deviation
     520
     521    double stdev = stats->sampleStdev;  // Standard deviation
     522    double variance = PS_SQR(stdev);    // Variance
     523
     524    // Formula for skewness and kurtosis from Numerical Recipes in C, p 613.
     525    // Note that we are defining the kurtosis relative to a normal distribution (hence the -3.0).
     526    stats->sampleSkewness = sum3 / (count * variance * stdev);
     527    stats->sampleKurtosis = sum4 / (count * PS_SQR(variance)) - 3.0;
     528    stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
     529
     530    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
     531
     532    return true;
     533
     534 SAMPLE_MOMENTS_BAD:
     535    // stats->sampleStdev has already been set
     536    stats->sampleSkewness = NAN;
     537    stats->sampleKurtosis = NAN;
     538    stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
    469539    return true;
    470540}
     
    16831753    stats->sampleUQ = NAN;
    16841754    stats->sampleLQ = NAN;
     1755    stats->sampleSkewness = NAN;
     1756    stats->sampleKurtosis = NAN;
    16851757    stats->robustMedian = NAN;
    16861758    stats->robustStdev = NAN;
     
    18081880    }
    18091881
     1882    if (stats->options & (PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS)) {
     1883        if (!vectorSampleMoments(inF32, maskU8, maskVal, stats)) {
     1884            psError(PS_ERR_UNKNOWN, false, "Failed to calculate sample moments");
     1885            status &= false;
     1886        }
     1887    }
     1888
    18101889    // ************************************************************************
    18111890    if (stats->options & (PS_STAT_MAX | PS_STAT_MIN)) {
     
    18781957    READ_STAT("MEAN",       PS_STAT_SAMPLE_MEAN);
    18791958    READ_STAT("STDEV",      PS_STAT_SAMPLE_STDEV);
     1959    READ_STAT("SKEWNESS",   PS_STAT_SAMPLE_SKEWNESS);
     1960    READ_STAT("KURTOSIS",   PS_STAT_SAMPLE_KURTOSIS);
    18801961    READ_STAT("MEDIAN",     PS_STAT_SAMPLE_MEDIAN);
    18811962    READ_STAT("QUARTILE",   PS_STAT_SAMPLE_QUARTILE);
     
    18841965    READ_STAT("SAMPLE_MEDIAN",   PS_STAT_SAMPLE_MEDIAN);
    18851966    READ_STAT("SAMPLE_QUARTILE", PS_STAT_SAMPLE_QUARTILE);
     1967    READ_STAT("SAMPLE_SKEWNESS", PS_STAT_SAMPLE_SKEWNESS);
     1968    READ_STAT("SAMPLE_KURTOSIS", PS_STAT_SAMPLE_KURTOSIS);
    18861969    READ_STAT("ROBUST",          PS_STAT_ROBUST_MEDIAN);
    18871970    READ_STAT("ROBUST_MEDIAN",   PS_STAT_ROBUST_MEDIAN);
     
    19192002    WRITE_STAT("SAMPLE_MEDIAN",   PS_STAT_SAMPLE_MEDIAN);
    19202003    WRITE_STAT("SAMPLE_QUARTILE", PS_STAT_SAMPLE_QUARTILE);
     2004    WRITE_STAT("SAMPLE_SKEWNESS", PS_STAT_SAMPLE_SKEWNESS);
     2005    WRITE_STAT("SAMPLE_KURTOSIS", PS_STAT_SAMPLE_KURTOSIS);
    19212006    WRITE_STAT("ROBUST_MEDIAN",   PS_STAT_ROBUST_MEDIAN);
    19222007    WRITE_STAT("ROBUST_STDEV",    PS_STAT_ROBUST_STDEV);
     
    19712056      case PS_STAT_SAMPLE_STDEV:
    19722057      case PS_STAT_SAMPLE_QUARTILE:
     2058      case PS_STAT_SAMPLE_SKEWNESS:
     2059      case PS_STAT_SAMPLE_KURTOSIS:
    19732060      case PS_STAT_ROBUST_MEDIAN:
    19742061      case PS_STAT_ROBUST_STDEV:
     
    20022089      case PS_STAT_SAMPLE_STDEV:
    20032090        return stats->sampleStdev;
     2091      case PS_STAT_SAMPLE_SKEWNESS:
     2092        return stats->sampleSkewness;
     2093      case PS_STAT_SAMPLE_KURTOSIS:
     2094        return stats->sampleKurtosis;
    20042095      case PS_STAT_ROBUST_MEDIAN:
    20052096        return stats->robustMedian;
Note: See TracChangeset for help on using the changeset viewer.