Changeset 729 for trunk/psLib/src/math/psStats.c
- Timestamp:
- May 18, 2004, 3:50:57 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psStats.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psStats.c
r724 r729 14 14 #include "psSort.h" 15 15 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 16 27 17 28 /****************************************************************************** … … 78 89 newHist->minNum = 0; 79 90 newHist->maxNum = 0; 80 91 newHist->numBins = numBins; 81 92 return(newHist); 82 93 } … … 156 167 } 157 168 169 void 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 158 185 /****************************************************************************** 159 186 MISC STATISTICAL FUNCTIONS … … 262 289 263 290 264 #define MEDIAN_SIZE_THRESHOLD 10000265 291 void p_psArraySampleMedian(const psVector *restrict myVector, 266 292 const psVector *restrict maskVector, … … 278 304 } 279 305 unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues); 306 unsortedVector->n = unsortedVector->nalloc; 280 307 sortedVector = psVectorAlloc(PS_TYPE_FLOAT, newStruct->nValues); 308 sortedVector->n = sortedVector->nalloc; 281 309 282 310 if (maskVector != NULL) { 283 311 for (i=0;i<myVector->n;i++) { 284 312 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 286 315 } 287 316 } … … 303 332 } 304 333 305 void p_psArrayRobustMedian(const psVector *restrict myVector, 306 const psVector *restrict maskVector, 307 unsigned int maskVal, 308 psStats *newStruct) 334 void 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 *****************************************************************************/ 384 void 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 *****************************************************************************/ 454 void p_psArrayRobustStats(const psVector *restrict myVector, 455 const psVector *restrict maskVector, 456 unsigned int maskVal, 457 psStats *newStruct) 309 458 { 310 459 psHistogram *robustHistogram = NULL; 311 460 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. 319 504 robustHistogram = psHistogramAlloc(newStruct->min, 320 505 newStruct->max, 321 506 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 336 539 // Fit a Gaussian to the bins in the range MODE-dL to Mode+dL 540 // What algorithm should I use to do this? 541 337 542 // 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 } 347 572 } 348 573 … … 385 610 } 386 611 countFloat = (float) countInt; 612 387 613 #ifdef DARWIN 388 614 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 624 void 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 *****************************************************************************/ 718 psStats *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.
