IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 18, 2004, 3:50:57 PM (22 years ago)
Author:
gusciora
Message:

...

File:
1 edited

Legend:

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

    r724 r729  
    1414#include "psSort.h"
    1515
     16#include "float.h"
     17#include <math.h>
     18#define ROBUST_SIZE_THRESHOLD 10000   // Vectors that are large than this
     19// will use robust statistical methods.
     20#define GAUSS_WIDTH 20                  // The width of the Gaussian or boxcar
     21// smoothing.
     22#define PI 3.141592653
     23#define CLIPPED_NUM_ITER_LB 1
     24#define CLIPPED_NUM_ITER_UB 10
     25#define CLIPPED_SIGMA_LB 1.0
     26#define CLIPPED_SIGMA_UB 10.0
    1627
    1728/******************************************************************************
     
    7889    newHist->minNum = 0;
    7990    newHist->maxNum = 0;
    80 
     91    newHist->numBins = numBins;
    8192    return(newHist);
    8293}
     
    156167}
    157168
     169void p_printVector(psVector *myVector,
     170                   psVector *maskVector,
     171                   unsigned int maskVal,
     172                   psStats *newStruct)
     173{
     174    int i = 0;
     175
     176    for (i=0;i<myVector->n;i++) {
     177        if (maskVector != NULL)
     178            printf("Element %d is %f (mask is %d)\n", i, myVector->vec.f[i], maskVector->vec.ui8[i]);
     179        else
     180            printf("Element %d is %f\n", i, myVector->vec.f[i]);
     181    }
     182}
     183
     184
    158185/******************************************************************************
    159186    MISC STATISTICAL FUNCTIONS
     
    262289
    263290
    264 #define MEDIAN_SIZE_THRESHOLD 10000
    265291void p_psArraySampleMedian(const psVector *restrict myVector,
    266292                           const psVector *restrict maskVector,
     
    278304    }
    279305    unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
     306    unsortedVector->n = unsortedVector->nalloc;
    280307    sortedVector   = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
     308    sortedVector->n = sortedVector->nalloc;
    281309
    282310    if (maskVector != NULL) {
    283311        for (i=0;i<myVector->n;i++) {
    284312            if (!(maskVal & maskVector->vec.ui8[i])) {
    285                 unsortedVector->vec.f[count++] = maskVector->vec.f[i];
     313                unsortedVector->vec.f[count++] = myVector->vec.f[i];
     314
    286315            }
    287316        }
     
    303332}
    304333
    305 void p_psArrayRobustMedian(const psVector *restrict myVector,
    306                            const psVector *restrict maskVector,
    307                            unsigned int maskVal,
    308                            psStats *newStruct)
     334void p_psArraysmoothHistGaussian(psHistogram *robustHistogram,
     335                                 float sigma)
     336{
     337    int i = 0;
     338    int j = 0;
     339    float tmpf = 0.0;
     340    float gaussianCoefs[1 + (2 * GAUSS_WIDTH)];
     341    // The coefficients used in the histogram
     342    // smoothing calculation.
     343
     344    for(i=0;i<(1 + (2 * GAUSS_WIDTH));i++) {
     345        if (fabs(sigma) <= FLT_EPSILON) {
     346            // If sigma does not equal zero, then we use Gaussian smoothing.
     347            #ifdef  DARWIN
     348            tmpf = (float) sqrt(2.0f * PI * sigma * sigma);
     349            #else
     350
     351            tmpf = sqrtf(2.0f * PI * sigma * sigma);
     352            #endif
     353
     354            gaussianCoefs[i] = (float) exp( (-((float) (i-GAUSS_WIDTH)) *
     355                                             ((float) (i-GAUSS_WIDTH))) /
     356                                            (2.0f * sigma * sigma)) /
     357                               tmpf;
     358        } else {
     359            /* If sigma equals zero (all pixels have the same value)
     360             * the above code will divide by zero.  Therefore, we instead
     361             * use boxcar smoothing.
     362             */
     363            gaussianCoefs[i] = 1.0f / (1.0f + (2.0f * (float) GAUSS_WIDTH));
     364        }
     365    }
     366
     367    for(i=0;i<robustHistogram->numBins;i++) {
     368        for (j=-GAUSS_WIDTH;j<=+GAUSS_WIDTH;j++) {
     369            if (((j+i) >= 0) && ((j+i) < robustHistogram->numBins)) {
     370                robustHistogram->nums->vec.i32[j+i]+=
     371                    (gaussianCoefs[j+GAUSS_WIDTH] *
     372                     (float) robustHistogram->nums->vec.i32[j+i]);
     373            }
     374        }
     375    }
     376}
     377
     378/******************************************************************************
     379    p_psArraySampleQuartiles()
     380 This procedure calculates the upper and/or lower quartiles of the
     381 data set.  It is assumed that the data set is small enough that we
     382 can sort all the data points and calculate the quartiles exactly.
     383 *****************************************************************************/
     384void p_psArraySampleQuartiles(const psVector *restrict myVector,
     385                              const psVector *restrict maskVector,
     386                              unsigned int maskVal,
     387                              psStats *newStruct)
     388{
     389    psVector *unsortedVector = NULL;
     390    psVector *sortedVector = NULL;
     391    int count = 0;
     392    int ind = 0;
     393    int i = 0;
     394
     395    // return is we have already calculated both quartile points.
     396    if ((!isnan(newStruct->sampleLQ)) &&
     397            (!isnan(newStruct->sampleUQ))) {
     398        return;
     399    }
     400
     401    if (-1 == newStruct->nValues) {
     402        p_psArrayNValues(myVector, maskVector, maskVal, newStruct);
     403    }
     404
     405
     406    unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
     407    sortedVector   = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
     408
     409    count = 0;
     410    if (maskVector != NULL) {
     411        for (i=0;i<myVector->n;i++) {
     412            if (!(maskVal & maskVector->vec.ui8[i])) {
     413                unsortedVector->vec.f[count++] = maskVector->vec.f[i];
     414            }
     415        }
     416        psSort(sortedVector, unsortedVector);
     417    } else {
     418        psSort(sortedVector, myVector);
     419    }
     420
     421    if (newStruct->options & PS_STAT_SAMPLE_LQ) {
     422        ind = 3 * (newStruct->nValues / 4);
     423        newStruct->sampleUQ = sortedVector->vec.f[ind];
     424    }
     425
     426    if (newStruct->options & PS_STAT_SAMPLE_UQ) {
     427        ind = (newStruct->nValues / 4);
     428        newStruct->sampleLQ = sortedVector->vec.f[ind];
     429    }
     430
     431    psVectorFree(unsortedVector);
     432    psVectorFree(sortedVector);
     433}
     434
     435
     436/******************************************************************************
     437    p_psArrayRobustStats(): this procedure calcualtes a variety of robust
     438    stat measures:
     439 PS_STAT_ROBUST_MEAN
     440        PS_STAT_ROBUST_MEAN_NVALUES
     441        PS_STAT_ROBUST_MEDIAN
     442        PS_STAT_ROBUST_MEDIAN_NVALUES
     443        PS_STAT_ROBUST_MODE
     444        PS_STAT_ROBUST_MODE_NVALUES
     445        PS_STAT_ROBUST_STDEV
     446    I have included all that computation in a single function, as opposed to
     447    breaking it across several functions for one primary reason: the all
     448    require the same basic initial processing steps (calculate the histogram,
     449    etc.) however there is no currently defined means, in the SDRS, to
     450    specify this computation as a separate step.  If the above robust stat
     451    measures were calcualted in separate functiosn, then much of the initial
     452    processing would be duplicated.
     453 *****************************************************************************/
     454void p_psArrayRobustStats(const psVector *restrict myVector,
     455                          const psVector *restrict maskVector,
     456                          unsigned int maskVal,
     457                          psStats *newStruct)
    309458{
    310459    psHistogram *robustHistogram = NULL;
    311460    float binSize = 0.0;
    312 
    313     //    if (isnan(myVector->robustLQ) ||
    314     //        isnan(myVector->robustUQ)) {
    315     //        p_psArrayRobustQuartiles(myVector, maskVector, maskVal, newStruct);
    316     //    }
    317     //    binSize = ((myVector->robustUQ - myVector->robustLQ) / 1.34) / 10.0;
    318 
     461    float sigmaE = 0.0;
     462    int LQBinNum = -1;
     463    int UQBinNum = -1;
     464    int i = 0;    // Loop index variable.
     465    int maxBinNum = 0;
     466    int maxBinCount = 0;
     467    float dL = 0.0;
     468
     469    // NOTE: The SDRS states that the sample quartiles must be used to
     470    // determine the initial bin sizes.  However, the sample quartiles are
     471    // calculated based on a full sort of the data set, regardless of the
     472    // size of the data set.  We should consult with IfA to ensure that this
     473    // is really required.
     474
     475    if (0.0 == newStruct->sampleUQ) {
     476        newStruct->options = newStruct->options | PS_STAT_SAMPLE_UQ;
     477        p_psArraySampleQuartiles(myVector,
     478                                 maskVector,
     479                                 maskVal,
     480                                 newStruct);
     481    }
     482
     483    if (isnan(newStruct->sampleLQ)) {
     484        newStruct->options = newStruct->options | PS_STAT_SAMPLE_LQ;
     485        p_psArraySampleQuartiles(myVector,
     486                                 maskVector,
     487                                 maskVal,
     488                                 newStruct);
     489    }
     490
     491    // Compute the initial bin size of the robust histogram.
     492    sigmaE = (newStruct->sampleUQ - newStruct->sampleLQ) / 1.34f;
     493    binSize = sigmaE / 10.0f;
     494
     495    // Detemine minimum and maximum values in the data vector.
     496    if (isnan(newStruct->min)) {
     497        p_psArrayMin(myVector, maskVector, maskVal, newStruct);
     498    }
     499    if (isnan(newStruct->max)) {
     500        p_psArrayMax(myVector, maskVector, maskVal, newStruct);
     501    }
     502
     503    // Create the histogram structure.
    319504    robustHistogram = psHistogramAlloc(newStruct->min,
    320505                                       newStruct->max,
    321506                                       binSize);
    322     //    p_psArrayNValues(myVector, maskVector, maskVal, newStruct);
    323     //    robustHistogram = psGetArrayHistogram(robustHistogram, myVector);
    324     //    p_psArraySmooth(robustHistogram, (binSize / 4.0));
    325     //    dL = (myVector->robustUQ - myVector->robustLQ) / 8.0;
    326 
    327 
    328     // BROAD: Calculate the Robust Median
    329     // Determine the LQ of the distribution.
    330     // Determine the UQ of the distribution.
    331     // Histogram the data with bin size (sigma_e = (UQ - LQ) / 1.34) / 10.0.
    332     // Smooth the histogram with a Gaussian with sigma_s = sigma_e / 4
    333 
    334     // Find the bin with the peak value between LQ and UQ (the MODE)
    335     // dL = (UQ - LQ) / 8
     507    // Populate the histogram arrat.
     508    robustHistogram = psGetArrayHistogram(robustHistogram, myVector);
     509
     510    // Smooth the histogram.
     511    p_psArraysmoothHistGaussian(robustHistogram, sigmaE/4.0f);
     512
     513    LQBinNum = -1;
     514    UQBinNum = -1;
     515    for (i=0;i<robustHistogram->numBins;i++) {
     516        if ((robustHistogram->nums->vec.i32[i] <= newStruct->sampleLQ) &&
     517                (newStruct->sampleLQ <= robustHistogram->nums->vec.i32[i])) {
     518            LQBinNum = i;
     519        }
     520
     521        if ((robustHistogram->nums->vec.i32[i] <= newStruct->sampleUQ) &&
     522                (newStruct->sampleUQ <= robustHistogram->nums->vec.i32[i])) {
     523            UQBinNum = i;
     524        }
     525    }
     526
     527    // Determine the bin with the peak value in the range LQ to UQ.
     528    maxBinNum = LQBinNum;
     529    maxBinCount = robustHistogram->nums->vec.i32[maxBinNum];
     530    for (i=LQBinNum;i<=UQBinNum;i++) {
     531        if (robustHistogram->nums->vec.i32[i] > maxBinCount) {
     532            maxBinNum = i;
     533            maxBinCount = robustHistogram->nums->vec.i32[i];
     534        }
     535    }
     536
     537    dL = (newStruct->robustUQ - newStruct->robustLQ) / 8.0;
     538
    336539    // Fit a Gaussian to the bins in the range MODE-dL to Mode+dL
     540    // What algorithm should I use to do this?
     541
    337542    // The resulting fit parameters are the robust mean, mean_r, and sigma
    338 }
    339 
    340 
    341 float p_psArrayXXX(const psVector *restrict myVector,
    342                    const psVector *restrict maskVector,
    343                    unsigned int maskVal)
    344 {
    345     printf("ERROR: Don't call me: p_psArrayXXX()\n");
    346     exit(1);
     543    // What is the mean_r?
     544
     545    if (newStruct->options & PS_STAT_ROBUST_MEAN) {
     546        newStruct->robustMean = 0.0;
     547    }
     548    if  (newStruct->options & PS_STAT_ROBUST_MEAN_NVALUES) {
     549        newStruct->robustMeanNvalues = 0.0;
     550    }
     551    if  (newStruct->options & PS_STAT_ROBUST_MEDIAN) {
     552        newStruct->robustMedian = 0.0;
     553    }
     554    if  (newStruct->options & PS_STAT_ROBUST_MEDIAN_NVALUES) {
     555        newStruct->robustMedianNvalues = 0.0;
     556    }
     557    if  (newStruct->options & PS_STAT_ROBUST_MODE) {
     558        newStruct->robustMode = maxBinNum;
     559    }
     560    if  (newStruct->options & PS_STAT_ROBUST_MODE_NVALUES) {
     561        newStruct->robustModeNvalues = 0.0;
     562    }
     563    if  (newStruct->options & PS_STAT_ROBUST_STDEV) {
     564        newStruct->robustStdev = 0.0;
     565    }
     566    if  (newStruct->options & PS_STAT_ROBUST_UQ) {
     567        newStruct->robustUQ = 0.0;
     568    }
     569    if  (newStruct->options & PS_STAT_ROBUST_LQ) {
     570        newStruct->robustLQ = 0.0;
     571    }
    347572}
    348573
     
    385610    }
    386611    countFloat = (float) countInt;
     612
    387613    #ifdef DARWIN
    388614
    389     newStruct->sampleStdev = sqrt(
    390                                  #else
    391                                  newStruct->sampleStdev = sqrtf(
    392                                                               #endif
    393                                                               (sumSquares-(sumDiffs * sumDiffs/countFloat))/ (countFloat-1));
    394                              }
    395 
    396                              /******************************************************************************
    397                               *****************************************************************************/
    398                              void p_psArraySampleQuartiles(const psVector *restrict myVector,
    399                                                            const psVector *restrict maskVector,
    400                                                            unsigned int maskVal,
    401                                                            psStats *newStruct)
    402                              {
    403                                  psVector *unsortedVector = NULL;
    404                                  psVector *sortedVector = NULL;
    405                                  int count = 0;
    406                                  int ind = 0;
    407                                  int i = 0;
    408 
    409                                  // return is we have already calculated both quartile points.
    410                                  if ((!isnan(newStruct->sampleLQ)) &&
    411                                          (!isnan(newStruct->sampleUQ))) {
    412                                      return;
    413                                  }
    414 
    415                                  if (-1 == newStruct->nValues) {
    416                                      p_psArrayNValues(myVector, maskVector, maskVal, newStruct);
    417                                  }
    418 
    419 
    420                                  unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
    421                                  sortedVector   = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues);
    422 
    423                                  count = 0;
    424                                  if (maskVector != NULL) {
    425                                      for (i=0;i<myVector->n;i++) {
    426                                          if (!(maskVal & maskVector->vec.ui8[i])) {
    427                                              unsortedVector->vec.f[count++] = maskVector->vec.f[i];
    428                                          }
    429                                      }
    430                                      psSort(sortedVector, unsortedVector);
    431                                  } else {
    432                                      psSort(sortedVector, myVector);
    433                                  }
    434 
    435                                  ind = 3 * (newStruct->nValues / 4);
    436                                  newStruct->sampleUQ = sortedVector->vec.f[ind];
    437                                  ind = (newStruct->nValues / 4);
    438                                  newStruct->sampleLQ = sortedVector->vec.f[ind];
    439 
    440                                  psVectorFree(unsortedVector);
    441                                  psVectorFree(sortedVector);
    442                              }
    443 
    444                              /******************************************************************************
    445                              
    446                                  NOTE: The current strategy is to implement everything assuming that all
    447                                  input data is of type PS_TYPE_FLOAT.  Once the basic code is in place,
    448                                  we will macro-ize everything and add PS_TYPE_UINT16 and PS_TYPE_DOUBLE.
    449                              
    450                               *****************************************************************************/
    451                              psStats *psArrayStats(const psVector *restrict myVector,
    452                                                    const psVector *restrict maskVector,
    453                                                    unsigned int maskVal,
    454                                                    psStats *stats)
    455                              {
    456                                  psStats *newStruct = NULL;
    457 
    458                                  if (myVector == NULL) {
    459                                      psAbort(__func__,
    460                                              "Input data array (myVector) was NULL.");
    461                                  }
    462 
    463                                  if (myVector->type.type != PS_TYPE_FLOAT) {
    464                                      psAbort(__func__,
    465                                              "Only data type PS_TYPE_FLOAT is currently supported.");
    466                                  }
    467 
    468                                  if (maskVector != NULL) {
    469                                      if (myVector->n != maskVector->n) {
    470                                          psAbort(__func__,
    471                                                  "Vector data and vector mask are of different sizes.");
    472                                      }
    473                                      if (maskVector->type.type != PS_TYPE_UINT8) {
    474                                          psAbort(__func__,
    475                                                  "Vector mask must be type PS_TYPE_UINT8");
    476                                      }
    477                                  }
    478                                  newStruct = psStatsAlloc(stats->options);
    479 
    480                                  // ************************************************************************
    481                                  if (stats->options & PS_STAT_SAMPLE_MEAN) {
    482                                      p_psArraySampleMean(myVector, maskVector, maskVal, newStruct);
    483                                  }
    484 
    485                                  // ************************************************************************
    486                                  if (stats->options & PS_STAT_MAX) {
    487                                      p_psArrayMax(myVector, maskVector, maskVal, newStruct);
    488                                  }
    489 
    490                                  // ************************************************************************
    491                                  if (stats->options & PS_STAT_MIN) {
    492                                      p_psArrayMin(myVector, maskVector, maskVal, newStruct);
    493                                  }
    494 
    495                                  // ************************************************************************
    496                                  if (stats->options & PS_STAT_NVALUES) {
    497                                      p_psArrayNValues(myVector, maskVector, maskVal, newStruct);
    498                                  }
    499 
    500                                  // ************************************************************************
    501                                  if (stats->options & PS_STAT_SAMPLE_MEDIAN) {
    502                                      p_psArraySampleMedian(myVector, maskVector, maskVal, newStruct);
    503                                  }
    504 
    505                                  // ************************************************************************
    506                                  if (stats->options & PS_STAT_SAMPLE_STDEV) {
    507                                      p_psArraySampleStdev(myVector, maskVector, maskVal, newStruct);
    508                                  }
    509 
    510                                  // ************************************************************************
    511                                  if ((stats->options & PS_STAT_SAMPLE_UQ) ||
    512                                          (stats->options & PS_STAT_SAMPLE_LQ)) {
    513                                      p_psArraySampleQuartiles(myVector, maskVector, maskVal, newStruct);
    514                                  }
    515 
    516 
    517 
    518 
    519                                  if (stats->options & PS_STAT_ROBUST_MEAN) {
    520                                      newStruct->robustMean = p_psArrayXXX(myVector, maskVector, maskVal);
    521                                  }
    522 
    523                                  if (stats->options & PS_STAT_ROBUST_MEAN_NVALUES) {
    524                                      newStruct->robustMeanNvalues = p_psArrayXXX(myVector, maskVector, maskVal);
    525                                  }
    526 
    527                                  if (stats->options & PS_STAT_ROBUST_MEDIAN) {
    528                                      newStruct->robustMedian = p_psArrayXXX(myVector, maskVector, maskVal);
    529                                  }
    530 
    531                                  if (stats->options & PS_STAT_ROBUST_MEDIAN_NVALUES) {
    532                                      newStruct->robustMedianNvalues = p_psArrayXXX(myVector, maskVector, maskVal);
    533                                  }
    534 
    535                                  if (stats->options & PS_STAT_ROBUST_MODE) {
    536                                      newStruct->robustMode = p_psArrayXXX(myVector, maskVector, maskVal);
    537                                  }
    538 
    539                                  if (stats->options & PS_STAT_ROBUST_MODE_NVALUES) {
    540                                      newStruct->robustModeNvalues = p_psArrayXXX(myVector, maskVector, maskVal);
    541                                  }
    542 
    543                                  if (stats->options & PS_STAT_ROBUST_STDEV) {
    544                                      newStruct->robustStdev = p_psArrayXXX(myVector, maskVector, maskVal);
    545                                  }
    546 
    547                                  if ((stats->options & PS_STAT_ROBUST_UQ) ||
    548                                          (stats->options & PS_STAT_ROBUST_LQ)) {
    549                                      newStruct->robustLQ = p_psArrayXXX(myVector, maskVector, maskVal);
    550                                  }
    551 
    552                                  if (stats->options & PS_STAT_CLIPPED_MEAN) {
    553                                      newStruct->clippedMean = p_psArrayXXX(myVector, maskVector, maskVal);
    554                                  }
    555 
    556                                  if (stats->options & PS_STAT_CLIPPED_MEAN_NVALUES) {
    557                                      newStruct->clippedMeanNvalues = p_psArrayXXX(myVector, maskVector, maskVal);
    558                                  }
    559 
    560                                  if (stats->options & PS_STAT_CLIPPED_MEAN_NSIGMA) {
    561                                      newStruct->clipSigma = p_psArrayXXX(myVector, maskVector, maskVal);
    562                                  }
    563 
    564                                  if (stats->options & PS_STAT_CLIPPED_STDEV) {
    565                                      newStruct->clippedStdev = p_psArrayXXX(myVector, maskVector, maskVal);
    566                                  }
    567 
    568 
    569                                  //    OLD CODE: Should we check for an unknown option?
    570                                  //    default:
    571                                  //        psAbort(__func__, "Unknown options 0x%x.\n", stats->options);
    572 
    573                                  return(newStruct);
    574                              }
     615    newStruct->sampleStdev = (float) sqrt( (sumSquares-(sumDiffs *
     616                                            sumDiffs/countFloat))/ (countFloat-1));
     617    #else
     618
     619    newStruct->sampleStdev = sqrtf( (sumSquares-(sumDiffs *
     620                                     sumDiffs/countFloat))/ (countFloat-1));
     621    #endif
     622}
     623
     624void p_psArrayClippedStats(const psVector *restrict myVector,
     625                           const psVector *restrict maskVector,
     626                           unsigned int maskVal,
     627                           psStats *newStruct)
     628{
     629    int i = 0;
     630    int j = 0;
     631    float clippedMean = 0.0;
     632    float clippedStdev = 0.0;
     633    psVector *tmpMask = NULL;
     634
     635    if (!((CLIPPED_NUM_ITER_LB <= newStruct->clipIter ) &&
     636            (newStruct->clipIter <= CLIPPED_NUM_ITER_UB))) {
     637        psAbort(__func__, "Unallowed value for clipIter (%d).\n",
     638                newStruct->clipIter);
     639    }
     640
     641    if (!((CLIPPED_SIGMA_LB <= newStruct->clipSigma ) &&
     642            (newStruct->clipSigma <= CLIPPED_SIGMA_UB))) {
     643        psAbort(__func__, "Unallowed value for clipSigma (%f).\n",
     644                newStruct->clipSigma);
     645    }
     646
     647    tmpMask = psVectorAlloc(maskVector->type.type, myVector->nalloc);
     648
     649    tmpMask->n = maskVector->n;
     650    for (i=0;i<tmpMask->n;i++) {
     651        tmpMask->vec.ui8[i] = maskVector->vec.ui8[i];
     652    }
     653
     654    // 1. Compute the sample median.
     655    p_psArraySampleMedian(myVector, maskVector, maskVal, newStruct);
     656
     657    // 2. Compute the sample standard deviation.
     658    p_psArraySampleStdev(myVector, maskVector, maskVal, newStruct);
     659
     660    // 3. Use the sample median as the first estimator of the mean X.
     661    clippedMean = newStruct->sampleMean;
     662
     663    // 4. Use the sample stdev as the first estimator of the mean stdev.
     664    clippedStdev = newStruct->sampleStdev;
     665
     666    // 5. Repeat N times:
     667
     668    for (i=0;i<newStruct->clipIter;i++) {
     669        for (j=0;j<myVector->n;j++) {
     670            // a) Exclude all values x_i for which |x_i - x| > K * stdev
     671            if ( fabs(myVector->vec.f[j] - clippedMean) >
     672                    (newStruct->clipSigma * clippedStdev)) {
     673                tmpMask->vec.ui8[i] = 0xff;
     674            }
     675            // b) compute new mean and stdev
     676            // GUS: I should probably create a new struct here since the
     677            // following calls will overwrite any old values in sampleMean.
     678            p_psArraySampleMedian(myVector, tmpMask, maskVal, newStruct);
     679            p_psArraySampleStdev(myVector, tmpMask, maskVal, newStruct);
     680
     681            // c) Use the new mean for x
     682            clippedMean = newStruct->sampleMean;
     683
     684            // d) Use the new stdev for stdev
     685            clippedStdev = newStruct->sampleStdev;
     686        }
     687    }
     688
     689    // 7. The last calcuated value of x is the cliped mean.
     690    if (newStruct->options & PS_STAT_CLIPPED_MEAN) {
     691        newStruct->clippedMean = clippedMean;
     692    }
     693
     694    // 8. The last calcuated value of stdev is the cliped stdev.
     695    if (newStruct->options & PS_STAT_CLIPPED_STDEV) {
     696        newStruct->clippedStdev = clippedStdev;
     697    }
     698
     699    if (newStruct->options & PS_STAT_CLIPPED_MEAN_NVALUES) {
     700        p_psArrayNValues(myVector, tmpMask, maskVal, newStruct);
     701    }
     702
     703    if (newStruct->options & PS_STAT_CLIPPED_MEAN_NSIGMA) {
     704        // GUS: What to do here?
     705    }
     706
     707    psVectorFree(tmpMask);
     708}
     709
     710
     711/******************************************************************************
     712 
     713    NOTE: The current strategy is to implement everything assuming that all
     714    input data is of type PS_TYPE_FLOAT.  Once the basic code is in place,
     715    we will macro-ize everything and add PS_TYPE_UINT16 and PS_TYPE_DOUBLE.
     716 
     717 *****************************************************************************/
     718psStats *psArrayStats(const psVector *restrict myVector,
     719                      const psVector *restrict maskVector,
     720                      unsigned int maskVal,
     721                      psStats *stats)
     722{
     723    psStats *newStruct = NULL;
     724
     725    if (myVector == NULL) {
     726        psAbort(__func__,
     727                "Input data array (myVector) was NULL.");
     728    }
     729
     730    if (myVector->type.type != PS_TYPE_FLOAT) {
     731        psAbort(__func__,
     732                "Only data type PS_TYPE_FLOAT is currently supported.");
     733    }
     734    if (maskVector != NULL) {
     735        if (myVector->n != maskVector->n) {
     736            psAbort(__func__,
     737                    "Vector data and vector mask are of different sizes.");
     738        }
     739        if (maskVector->type.type != PS_TYPE_UINT8) {
     740            psAbort(__func__,
     741                    "Vector mask must be type PS_TYPE_UINT8");
     742        }
     743    }
     744    newStruct = psStatsAlloc(stats->options);
     745
     746    // ************************************************************************
     747    if (stats->options & PS_STAT_SAMPLE_MEAN) {
     748        p_psArraySampleMean(myVector, maskVector, maskVal, newStruct);
     749    }
     750
     751    // ************************************************************************
     752    if (stats->options & PS_STAT_MAX) {
     753        p_psArrayMax(myVector, maskVector, maskVal, newStruct);
     754    }
     755
     756    // ************************************************************************
     757    if (stats->options & PS_STAT_MIN) {
     758        p_psArrayMin(myVector, maskVector, maskVal, newStruct);
     759    }
     760
     761    // ************************************************************************
     762    if (stats->options & PS_STAT_NVALUES) {
     763        p_psArrayNValues(myVector, maskVector, maskVal, newStruct);
     764    }
     765
     766    // ************************************************************************
     767    if (stats->options & PS_STAT_SAMPLE_MEDIAN) {
     768        p_psArraySampleMedian(myVector, maskVector, maskVal, newStruct);
     769    }
     770
     771    // ************************************************************************
     772    if (stats->options & PS_STAT_SAMPLE_STDEV) {
     773        p_psArraySampleStdev(myVector, maskVector, maskVal, newStruct);
     774    }
     775
     776    // ************************************************************************
     777    if ((stats->options & PS_STAT_SAMPLE_UQ) ||
     778            (stats->options & PS_STAT_SAMPLE_LQ)) {
     779        p_psArraySampleQuartiles(myVector, maskVector, maskVal, newStruct);
     780    }
     781
     782    if ((stats->options & PS_STAT_ROBUST_MEAN) ||
     783            (stats->options & PS_STAT_ROBUST_MEAN_NVALUES) ||
     784            (stats->options & PS_STAT_ROBUST_MEDIAN) ||
     785            (stats->options & PS_STAT_ROBUST_MEDIAN_NVALUES) ||
     786            (stats->options & PS_STAT_ROBUST_MODE) ||
     787            (stats->options & PS_STAT_ROBUST_MODE_NVALUES) ||
     788            (stats->options & PS_STAT_ROBUST_STDEV) ||
     789            (stats->options & PS_STAT_ROBUST_UQ) ||
     790            (stats->options & PS_STAT_ROBUST_LQ)) {
     791        p_psArrayClippedStats(myVector, maskVector, maskVal, newStruct);
     792    }
     793
     794    if ((stats->options & PS_STAT_CLIPPED_MEAN) ||
     795            (stats->options & PS_STAT_CLIPPED_MEAN_NVALUES) ||
     796            (stats->options & PS_STAT_CLIPPED_MEAN_NSIGMA) ||
     797            (stats->options & PS_STAT_CLIPPED_STDEV)) {
     798        p_psArrayClippedStats(myVector, maskVector, maskVal, newStruct);
     799    }
     800
     801    //    OLD CODE: Should we check for an unknown option?
     802    //    default:
     803    //        psAbort(__func__, "Unknown options 0x%x.\n", stats->options);
     804
     805    return(newStruct);
     806}
Note: See TracChangeset for help on using the changeset viewer.