Changeset 797 for trunk/psLib/src/math/psStats.c
- Timestamp:
- May 27, 2004, 4:45:31 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psStats.c (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psStats.c
r796 r797 15 15 16 16 #include "float.h" 17 #define ROBUST_SIZE_THRESHOLD 10000 // Vectors that are large than this17 #define ROBUST_SIZE_THRESHOLD 30000 // Vectors that are large than this 18 18 // will use robust statistical methods. 19 19 #define GAUSS_WIDTH 20 // The width of the Gaussian or boxcar … … 27 27 #define false 0 28 28 #define MYMAXFLOAT 1e99 29 30 void p_psVectorRobustStats(const psVector *restrict myVector, 31 const psVector *restrict maskVector, 32 unsigned int maskVal, 33 psStats *stats); 29 34 /****************************************************************************** 30 35 psStatsAlloc(): This routine must create a new psStats data structure. … … 40 45 newStruct->sampleUQ = NAN; 41 46 newStruct->sampleLQ = NAN; 42 newStruct->sampleLimit = NAN;47 newStruct->sampleLimit = ROBUST_SIZE_THRESHOLD; 43 48 newStruct->robustMean = NAN; 44 49 newStruct->robustMedian = NAN; … … 51 56 newStruct->clippedMean = NAN; 52 57 newStruct->clippedStdev = NAN; 53 newStruct->clipSigma = NAN;54 newStruct->clipIter = -1;58 newStruct->clipSigma = 3.0; 59 newStruct->clipIter = 3.0; 55 60 newStruct->min = NAN; 56 61 newStruct->max = NAN; … … 187 192 psVector *maskVector, 188 193 unsigned int maskVal, 189 psStats * newStruct)194 psStats *stats) 190 195 { 191 196 int i = 0; … … 207 212 ****************************************************************************** 208 213 *****************************************************************************/ 214 215 216 /****************************************************************************** 217 ASSUMPTION: the mean is always calculated exactly. Robust means are never 218 calculated in this routine. 219 *****************************************************************************/ 209 220 void p_psVectorSampleMean(const psVector *restrict myVector, 210 221 const psVector *restrict maskVector, … … 368 379 369 380 /****************************************************************************** 370 This routine calculates the number of non-masked pixels in the vector. 381 This routine calculates the number of non-masked pixels in the vector. 382 that fall within the min/max range, if given. 371 383 *****************************************************************************/ 372 384 int p_psVectorNValues(const psVector *restrict myVector, 373 385 const psVector *restrict maskVector, 374 386 unsigned int maskVal, 375 psStats * newStruct)387 psStats *stats) 376 388 { 377 389 int i = 0; 378 390 int numData = 0; 379 380 if (maskVector != NULL) { 381 for (i=0;i<myVector->n;i++) { 382 if (!(maskVal & maskVector->vec.ui8[i])) { 383 numData++; 391 float rangeMin = 0.0; 392 float rangeMax = 0.0; 393 394 if (stats->options & PS_STAT_USE_RANGE) { 395 rangeMin = stats->min; 396 rangeMax = stats->max; 397 if (maskVector != NULL) { 398 for (i=0;i<myVector->n;i++) { 399 if (!(maskVal & maskVector->vec.ui8[i]) && 400 (rangeMin <= myVector->vec.f[i]) && 401 (myVector->vec.f[i] <= rangeMax)) { 402 numData++; 403 } 404 } 405 } else { 406 for (i=0;i<myVector->n;i++) { 407 if ((rangeMin <= myVector->vec.f[i]) && 408 (myVector->vec.f[i] <= rangeMax)) { 409 numData++; 410 } 384 411 } 385 412 } 386 413 } else { 387 numData = myVector->n; 414 rangeMin = stats->min; 415 rangeMax = stats->max; 416 if (maskVector != NULL) { 417 for (i=0;i<myVector->n;i++) { 418 if (!(maskVal & maskVector->vec.ui8[i])) { 419 numData++; 420 } 421 } 422 } else { 423 numData = myVector->n; 424 } 388 425 } 389 426 return(numData); … … 395 432 const psVector *restrict maskVector, 396 433 unsigned int maskVal, 397 psStats * newStruct)434 psStats *stats) 398 435 { 399 436 psVector *unsortedVector = NULL; … … 401 438 int count = 0; 402 439 int i = 0; 403 float median = 0.0;404 440 int nValues = 0; 405 406 nValues = p_psVectorNValues(myVector, maskVector, maskVal, newStruct); 441 float rangeMin = 0.0; 442 float rangeMax = 0.0; 443 psStats *stats2 = NULL; 444 445 446 // Determine if the number of data points exceed a threshold which will 447 // cause to generate robust stats, as opposed to exact stats. 448 449 if (myVector->n > stats->sampleLimit) { 450 // Calculate the robust quartiles. 451 stats2 = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 452 p_psVectorRobustStats(myVector, maskVector, maskVal, stats2); 453 454 // Store the robust quartiles into the sample quartile members. 455 stats->sampleMedian = stats2->robustMedian; 456 457 // Free temporary data buffers. 458 psStatsFree(stats2); 459 460 // Set the PS_STAT_ROBUST_FOR_SAMPLE bit in the stats structure. 461 stats->options = stats->options | PS_STAT_ROBUST_FOR_SAMPLE; 462 463 return; 464 } 465 466 // Determine how many data points fit inside this min/max range 467 // and are not maxed, IF the maskVector is not NULL> 468 nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats); 469 470 // Allocate temporary vectors for the data. 407 471 unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, nValues); 408 472 unsortedVector->n = unsortedVector->nalloc; … … 410 474 sortedVector->n = sortedVector->nalloc; 411 475 412 if (maskVector != NULL) { 413 for (i=0;i<myVector->n;i++) { 414 if (!(maskVal & maskVector->vec.ui8[i])) { 415 unsortedVector->vec.f[count++] = myVector->vec.f[i]; 416 417 } 418 } 419 psSort(sortedVector, unsortedVector); 476 // Determine if we must only use data points within a min/max range. 477 if (stats->options & PS_STAT_USE_RANGE) { 478 rangeMin = stats->min; 479 rangeMax = stats->max; 480 481 // Store all non-masked data points within the min/max range 482 // into the temporary vectors. 483 count = 0; 484 if (maskVector != NULL) { 485 for (i=0;i<myVector->n;i++) { 486 if (!(maskVal & maskVector->vec.ui8[i]) && 487 (rangeMin <= myVector->vec.f[i]) && 488 (myVector->vec.f[i] <= rangeMax)) { 489 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 490 } 491 } 492 } else { 493 for (i=0;i<myVector->n;i++) { 494 if ((rangeMin <= myVector->vec.f[i]) && 495 (myVector->vec.f[i] <= rangeMax)) { 496 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 497 } 498 } 499 } 420 500 } else { 421 psSort(sortedVector, myVector); 422 } 423 501 // Store all non-masked data points into the temporary vectors. 502 count = 0; 503 if (maskVector != NULL) { 504 for (i=0;i<myVector->n;i++) { 505 if (!(maskVal & maskVector->vec.ui8[i])) { 506 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 507 } 508 } 509 } else { 510 for (i=0;i<myVector->n;i++) { 511 unsortedVector->vec.f[i] = maskVector->vec.f[i]; 512 } 513 } 514 } 515 // Sort the temporary vectors. 516 psSort(sortedVector, unsortedVector); 517 518 // Calculate the median exactly. 424 519 if (0 == (nValues % 2)) { 425 median = 0.5 * (sortedVector->vec.f[(nValues/2)-1] +426 sortedVector->vec.f[nValues/2]);520 stats->sampleMedian = 0.5 * (sortedVector->vec.f[(nValues/2)-1] + 521 sortedVector->vec.f[nValues/2]); 427 522 } else { 428 median = sortedVector->vec.f[nValues/2]; 429 } 430 523 stats->sampleMedian = sortedVector->vec.f[nValues/2]; 524 } 525 526 // Free the temporary data structures. 431 527 psVectorFree(unsortedVector); 432 528 psVectorFree(sortedVector); 433 newStruct->sampleMedian = median; 434 } 435 529 } 530 531 /****************************************************************************** 532 This routine smoothes the data in the input robustHistogram with a 533 Gaussian of width sigma. 534 *****************************************************************************/ 436 535 void p_psVectorsmoothHistGaussian(psHistogram *robustHistogram, 437 536 float sigma) … … 481 580 p_psVectorSampleQuartiles() 482 581 This procedure calculates the upper and/or lower quartiles of the 483 data set. It is assumed that the data set is small enough that we484 can sort all the data points and calculate the quartiles exactly.582 data set. 583 485 584 *****************************************************************************/ 486 585 void p_psVectorSampleQuartiles(const psVector *restrict myVector, 487 586 const psVector *restrict maskVector, 488 587 unsigned int maskVal, 489 psStats * newStruct)588 psStats *stats) 490 589 { 491 590 psVector *unsortedVector = NULL; … … 495 594 int i = 0; 496 595 int nValues = 0; 497 498 // return is we have already calculated both quartile points. 499 if ((!isnan(newStruct->sampleLQ)) && 500 (!isnan(newStruct->sampleUQ))) { 596 float rangeMin = 0.0; 597 float rangeMax = 0.0; 598 psStats *stats2 = NULL; 599 600 // Determine if the number of data points exceed a threshold which will 601 // cause to generate robust stats, as opposed to exact stats. 602 if (myVector->n > stats->sampleLimit) { 603 // Calculate the robust quartiles. 604 stats2 = psStatsAlloc(PS_STAT_ROBUST_QUARTILE); 605 p_psVectorRobustStats(myVector, maskVector, maskVal, stats2); 606 607 // Store the robust quartiles into the sample quartile members. 608 stats->sampleUQ = stats2->robustUQ; 609 stats->sampleLQ = stats2->robustLQ; 610 611 // Free temporary data buffers. 612 psStatsFree(stats2); 613 614 // Set the PS_STAT_ROBUST_FOR_SAMPLE bit in the stats structure. 615 stats->options = stats->options | PS_STAT_ROBUST_FOR_SAMPLE; 616 501 617 return; 502 618 } 503 619 504 nValues = p_psVectorNValues(myVector, maskVector, maskVal, newStruct); 505 620 // Determine how many data points fit inside this min/max range 621 // and are not maxed, IF the maskVector is not NULL> 622 nValues = p_psVectorNValues(myVector, maskVector, maskVal, stats); 623 624 // Allocate temporary vectors for the data. 506 625 unsortedVector = psVectorAlloc(PS_TYPE_FLOAT, nValues); 626 unsortedVector->n = unsortedVector->nalloc; 507 627 sortedVector = psVectorAlloc(PS_TYPE_FLOAT, nValues); 508 509 count = 0; 510 if (maskVector != NULL) { 511 for (i=0;i<myVector->n;i++) { 512 if (!(maskVal & maskVector->vec.ui8[i])) { 513 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 514 } 515 } 516 psSort(sortedVector, unsortedVector); 628 sortedVector->n = sortedVector->nalloc; 629 630 // Determine if we must only use data points within a min/max range. 631 if (stats->options & PS_STAT_USE_RANGE) { 632 rangeMin = stats->min; 633 rangeMax = stats->max; 634 // Store all non-masked data points within the min/max range 635 // into the temporary vectors. 636 count = 0; 637 if (maskVector != NULL) { 638 for (i=0;i<myVector->n;i++) { 639 if (!(maskVal & maskVector->vec.ui8[i]) && 640 (rangeMin <= myVector->vec.f[i]) && 641 (myVector->vec.f[i] <= rangeMax)) { 642 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 643 } 644 } 645 } else { 646 for (i=0;i<myVector->n;i++) { 647 if ((rangeMin <= myVector->vec.f[i]) && 648 (myVector->vec.f[i] <= rangeMax)) { 649 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 650 } 651 } 652 } 517 653 } else { 518 psSort(sortedVector, myVector); 519 } 520 654 // Store all non-masked data points into the temporary vectors. 655 count = 0; 656 if (maskVector != NULL) { 657 for (i=0;i<myVector->n;i++) { 658 if (!(maskVal & maskVector->vec.ui8[i])) { 659 unsortedVector->vec.f[count++] = maskVector->vec.f[i]; 660 } 661 } 662 } else { 663 for (i=0;i<myVector->n;i++) { 664 unsortedVector->vec.f[i] = maskVector->vec.f[i]; 665 } 666 } 667 } 668 669 // Sort the temporary vectors. 670 psSort(sortedVector, unsortedVector); 671 672 // Calculate the quartile points exactly. 521 673 ind = 3 * (nValues / 4); 522 newStruct->sampleUQ = sortedVector->vec.f[ind];674 stats->sampleUQ = sortedVector->vec.f[ind]; 523 675 ind = (nValues / 4); 524 newStruct->sampleLQ = sortedVector->vec.f[ind]; 525 676 stats->sampleLQ = sortedVector->vec.f[ind]; 677 678 // Free the temporary data structures. 526 679 psVectorFree(unsortedVector); 527 680 psVectorFree(sortedVector); … … 530 683 531 684 /****************************************************************************** 532 p_psVectorRobustStats(): this procedure calcu altes a variety of robust685 p_psVectorRobustStats(): this procedure calculates a variety of robust 533 686 stat measures: 534 PS_STAT_ROBUST_MEAN687 PS_STAT_ROBUST_MEAN 535 688 PS_STAT_ROBUST_MEDIAN 536 689 PS_STAT_ROBUST_MODE 537 690 PS_STAT_ROBUST_STDEV 691 PS_STAT_ROBUST_QUARTILE 538 692 I have included all that computation in a single function, as opposed to 539 693 breaking it across several functions for one primary reason: the all … … 547 701 const psVector *restrict maskVector, 548 702 unsigned int maskVal, 549 psStats * newStruct)703 psStats *stats) 550 704 { 551 705 psHistogram *robustHistogram = NULL; … … 565 719 // is really required. 566 720 567 if (0.0 == newStruct->sampleUQ) { 721 if (0.0 == stats->sampleUQ) { 722 568 723 // GUS: fix this 569 // newStruct->options = newStruct->options | PS_STAT_SAMPLE_UQ;724 // stats->options = stats->options | PS_STAT_SAMPLE_UQ; 570 725 p_psVectorSampleQuartiles(myVector, 571 726 maskVector, 572 727 maskVal, 573 newStruct);574 } 575 576 if (isnan( newStruct->sampleLQ)) {728 stats); 729 } 730 731 if (isnan(stats->sampleLQ)) { 577 732 // GUS: fix this 578 // newStruct->options = newStruct->options | PS_STAT_SAMPLE_LQ;733 // stats->options = stats->options | PS_STAT_SAMPLE_LQ; 579 734 p_psVectorSampleQuartiles(myVector, 580 735 maskVector, 581 736 maskVal, 582 newStruct);737 stats); 583 738 } 584 739 585 740 // Compute the initial bin size of the robust histogram. 586 sigmaE = ( newStruct->sampleUQ - newStruct->sampleLQ) / 1.34f;741 sigmaE = (stats->sampleUQ - stats->sampleLQ) / 1.34f; 587 742 binSize = sigmaE / 10.0f; 588 743 589 744 // Detemine minimum and maximum values in the data vector. 590 if (isnan( newStruct->min)) {591 p_psVectorMin(myVector, maskVector, maskVal, newStruct);592 } 593 if (isnan( newStruct->max)) {594 p_psVectorMax(myVector, maskVector, maskVal, newStruct);745 if (isnan(stats->min)) { 746 p_psVectorMin(myVector, maskVector, maskVal, stats); 747 } 748 if (isnan(stats->max)) { 749 p_psVectorMax(myVector, maskVector, maskVal, stats); 595 750 } 596 751 597 752 // Create the histogram structure. 598 robustHistogram = psHistogramAlloc( newStruct->min,599 newStruct->max,753 robustHistogram = psHistogramAlloc(stats->min, 754 stats->max, 600 755 binSize); 601 756 // Populate the histogram arrat. … … 610 765 UQBinNum = -1; 611 766 for (i=0;i<robustHistogram->nums->n;i++) { 612 if ((robustHistogram->nums->vec.i32[i] <= newStruct->sampleLQ) &&613 ( newStruct->sampleLQ <= robustHistogram->nums->vec.i32[i])) {767 if ((robustHistogram->nums->vec.i32[i] <= stats->sampleLQ) && 768 (stats->sampleLQ <= robustHistogram->nums->vec.i32[i])) { 614 769 LQBinNum = i; 615 770 } 616 771 617 if ((robustHistogram->nums->vec.i32[i] <= newStruct->sampleUQ) &&618 ( newStruct->sampleUQ <= robustHistogram->nums->vec.i32[i])) {772 if ((robustHistogram->nums->vec.i32[i] <= stats->sampleUQ) && 773 (stats->sampleUQ <= robustHistogram->nums->vec.i32[i])) { 619 774 UQBinNum = i; 620 775 } … … 631 786 } 632 787 633 dL = ( newStruct->robustUQ - newStruct->robustLQ) / 8.0;788 dL = (stats->robustUQ - stats->robustLQ) / 8.0; 634 789 635 790 // Fit a Gaussian to the bins in the range MODE-dL to Mode+dL … … 639 794 // What is the mean_r? 640 795 641 if ( newStruct->options & PS_STAT_ROBUST_MEAN) {642 newStruct->robustMean = 0.0;643 } 644 645 if ( newStruct->options & PS_STAT_ROBUST_MEDIAN) {646 newStruct->robustMedian = 0.0;647 } 648 if ( newStruct->options & PS_STAT_ROBUST_MODE) {649 newStruct->robustMode = maxBinNum;650 } 651 if ( newStruct->options & PS_STAT_ROBUST_STDEV) {652 newStruct->robustStdev = 0.0;653 } 654 if ( newStruct->options & PS_STAT_ROBUST_QUARTILE) {655 newStruct->robustUQ = 0.0;656 newStruct->robustLQ = 0.0;796 if (stats->options & PS_STAT_ROBUST_MEAN) { 797 stats->robustMean = 0.0; 798 } 799 800 if (stats->options & PS_STAT_ROBUST_MEDIAN) { 801 stats->robustMedian = 0.0; 802 } 803 if (stats->options & PS_STAT_ROBUST_MODE) { 804 stats->robustMode = maxBinNum; 805 } 806 if (stats->options & PS_STAT_ROBUST_STDEV) { 807 stats->robustStdev = 0.0; 808 } 809 if (stats->options & PS_STAT_ROBUST_QUARTILE) { 810 stats->robustUQ = 0.0; 811 stats->robustLQ = 0.0; 657 812 } 658 813 } … … 661 816 NOTE: This function assumes that p_psVectorMean() has already been called 662 817 and the correct value is stored in stats->sampleMean. 818 819 NOTE: the mean is always calculated exactly. Robust means are never 820 calculated in this routine. 663 821 *****************************************************************************/ 664 822 void p_psVectorSampleStdev(const psVector *restrict myVector, … … 742 900 const psVector *restrict maskVector, 743 901 unsigned int maskVal, 744 psStats * newStruct)902 psStats *stats) 745 903 { 746 904 int i = 0; … … 750 908 psVector *tmpMask = NULL; 751 909 752 if (!((CLIPPED_NUM_ITER_LB <= newStruct->clipIter ) &&753 ( newStruct->clipIter <= CLIPPED_NUM_ITER_UB))) {910 if (!((CLIPPED_NUM_ITER_LB <= stats->clipIter ) && 911 (stats->clipIter <= CLIPPED_NUM_ITER_UB))) { 754 912 psAbort(__func__, "Unallowed value for clipIter (%d).\n", 755 newStruct->clipIter);756 } 757 758 if (!((CLIPPED_SIGMA_LB <= newStruct->clipSigma ) &&759 ( newStruct->clipSigma <= CLIPPED_SIGMA_UB))) {913 stats->clipIter); 914 } 915 916 if (!((CLIPPED_SIGMA_LB <= stats->clipSigma ) && 917 (stats->clipSigma <= CLIPPED_SIGMA_UB))) { 760 918 psAbort(__func__, "Unallowed value for clipSigma (%f).\n", 761 newStruct->clipSigma);919 stats->clipSigma); 762 920 } 763 921 … … 770 928 771 929 // 1. Compute the sample median. 772 p_psVectorSampleMedian(myVector, maskVector, maskVal, newStruct);930 p_psVectorSampleMedian(myVector, maskVector, maskVal, stats); 773 931 774 932 // 2. Compute the sample standard deviation. 775 p_psVectorSampleStdev(myVector, maskVector, maskVal, newStruct);933 p_psVectorSampleStdev(myVector, maskVector, maskVal, stats); 776 934 777 935 // 3. Use the sample median as the first estimator of the mean X. 778 clippedMean = newStruct->sampleMean;936 clippedMean = stats->sampleMean; 779 937 780 938 // 4. Use the sample stdev as the first estimator of the mean stdev. 781 clippedStdev = newStruct->sampleStdev;939 clippedStdev = stats->sampleStdev; 782 940 783 941 // 5. Repeat N times: 784 942 785 for (i=0;i< newStruct->clipIter;i++) {943 for (i=0;i<stats->clipIter;i++) { 786 944 for (j=0;j<myVector->n;j++) { 787 945 // a) Exclude all values x_i for which |x_i - x| > K * stdev 788 946 if ( fabs(myVector->vec.f[j] - clippedMean) > 789 ( newStruct->clipSigma * clippedStdev)) {947 (stats->clipSigma * clippedStdev)) { 790 948 tmpMask->vec.ui8[i] = 0xff; 791 949 } … … 793 951 // GUS: I should probably create a new struct here since the 794 952 // following calls will overwrite any old values in sampleMean. 795 p_psVectorSampleMedian(myVector, tmpMask, maskVal, newStruct);796 p_psVectorSampleStdev(myVector, tmpMask, maskVal, newStruct);953 p_psVectorSampleMedian(myVector, tmpMask, maskVal, stats); 954 p_psVectorSampleStdev(myVector, tmpMask, maskVal, stats); 797 955 798 956 // c) Use the new mean for x 799 clippedMean = newStruct->sampleMean;957 clippedMean = stats->sampleMean; 800 958 801 959 // d) Use the new stdev for stdev 802 clippedStdev = newStruct->sampleStdev;960 clippedStdev = stats->sampleStdev; 803 961 } 804 962 } 805 963 806 964 // 7. The last calcuated value of x is the cliped mean. 807 if ( newStruct->options & PS_STAT_CLIPPED_MEAN) {808 newStruct->clippedMean = clippedMean;965 if (stats->options & PS_STAT_CLIPPED_MEAN) { 966 stats->clippedMean = clippedMean; 809 967 } 810 968 811 969 // 8. The last calcuated value of stdev is the cliped stdev. 812 if ( newStruct->options & PS_STAT_CLIPPED_STDEV) {813 newStruct->clippedStdev = clippedStdev;970 if (stats->options & PS_STAT_CLIPPED_STDEV) { 971 stats->clippedStdev = clippedStdev; 814 972 } 815 973
Note:
See TracChangeset
for help on using the changeset viewer.
