Changeset 12437 for trunk/psLib/src/math/psStats.c
- Timestamp:
- Mar 13, 2007, 4:43:47 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psStats.c (modified) (49 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psStats.c
r11760 r12437 13 13 * use ->min and ->max (PS_STAT_USE_RANGE) 14 14 * 15 * @version $Revision: 1.20 1$ $Name: not supported by cvs2svn $16 * @date $Date: 2007-0 2-13 03:08:17 $15 * @version $Revision: 1.202 $ $Name: not supported by cvs2svn $ 16 * @date $Date: 2007-03-14 02:43:47 $ 17 17 * 18 18 * Copyright 2006 IfA, University of Hawaii … … 67 67 (0.5 * (HISTOGRAM->bounds->data.F32[(BIN_NUM)] + HISTOGRAM->bounds->data.F32[(BIN_NUM)+1])) 68 68 69 // set the bin closest to the corresponding value. if USE_END is +/- 1, 70 // out-of-range saturates on lower/upper bin REGARDLESS of actual value 71 #define PS_BIN_FOR_VALUE(RESULT, VECTOR, VALUE, USE_END) \ 72 tmpScalar.data.F32 = (VALUE); \ 73 RESULT = psVectorBinaryDisect (&result, VECTOR, &tmpScalar); \ 74 switch (result) { \ 75 case PS_BINARY_DISECT_PASS: \ 76 break; \ 77 case PS_BINARY_DISECT_OUTSIDE_RANGE: \ 78 psTrace ("psLib.math", 6, "selected bin outside range"); \ 79 if (USE_END == -1) { RESULT = 0; } \ 80 if (USE_END == +1) { RESULT = VECTOR->n - 1; } \ 81 break; \ 82 case PS_BINARY_DISECT_INVALID_INPUT: \ 83 case PS_BINARY_DISECT_INVALID_TYPE: \ 84 psAbort ("programming error"); \ 85 break; \ 86 } 87 88 # define PS_BIN_INTERPOLATE(RESULT, VECTOR, BOUNDS, BIN, VALUE) { \ 89 float dX, dY, Xo, Yo, Xt; \ 90 if (BIN == BOUNDS->n - 1) { \ 91 dX = 0.5*(BOUNDS->data.F32[BIN+1] - BOUNDS->data.F32[BIN-1]); \ 92 dY = VECTOR->data.F32[BIN] - VECTOR->data.F32[BIN-1]; \ 93 Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \ 94 Yo = VECTOR->data.F32[BIN]; \ 95 } else { \ 96 dX = 0.5*(BOUNDS->data.F32[BIN+2] - BOUNDS->data.F32[BIN]); \ 97 dY = VECTOR->data.F32[BIN+1] - VECTOR->data.F32[BIN]; \ 98 Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \ 99 Yo = VECTOR->data.F32[BIN]; \ 100 } \ 101 if (dY != 0) { \ 102 Xt = (VALUE - Yo)*dX/dY + Xo; \ 103 } else { \ 104 Xt = Xo; \ 105 } \ 106 Xt = PS_MIN (BOUNDS->data.F32[BIN+1], PS_MAX(BOUNDS->data.F32[BIN], Xt)); \ 107 psTrace("psLib.math", 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \ 108 Xo, Yo, dX, dY, Xt, VALUE); \ 109 RESULT = Xt; } 110 69 111 /*****************************************************************************/ 70 112 /* TYPE DEFINITIONS */ … … 120 162 To optmize this, use a macro and ifdef in or out the three states (errors, mask, range) 121 163 *****************************************************************************/ 122 static bool vectorSampleMean(const psVector* myVector,123 const psVector* errors,124 const psVector* maskVector,125 psMaskType maskVal,126 psStats* stats)164 static bool vectorSampleMean(const psVector* myVector, 165 const psVector* errors, 166 const psVector* maskVector, 167 psMaskType maskVal, 168 psStats* stats) 127 169 { 128 170 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); … … 188 230 (mask: 1, range: 0): 0.200 sec 0.244 sec 189 231 *****************************************************************************/ 190 static long vectorMinMax(const psVector* myVector,191 const psVector* maskVector,192 psMaskType maskVal,193 psStats* stats194 )232 static long vectorMinMax(const psVector* myVector, 233 const psVector* maskVector, 234 psMaskType maskVal, 235 psStats* stats 236 ) 195 237 { 196 238 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); … … 331 373 332 374 *****************************************************************************/ 333 static bool vectorSampleStdev(const psVector* myVector,334 const psVector* errors,335 const psVector* maskVector,336 psMaskType maskVal,337 psStats* stats)375 static bool vectorSampleStdev(const psVector* myVector, 376 const psVector* errors, 377 const psVector* maskVector, 378 psMaskType maskVal, 379 psStats* stats) 338 380 { 339 381 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); … … 422 464 psMaskType maskValInput, 423 465 psStats* stats 424 )466 ) 425 467 { 426 468 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); … … 491 533 for (long j = 0; j < myVector->n; j++) { 492 534 if (!tmpMask->data.U8[j] && 493 fabsf(myVector->data.F32[j] - clippedMean) > stats->clipSigma * errors->data.F32[j]) {535 fabsf(myVector->data.F32[j] - clippedMean) > stats->clipSigma * errors->data.F32[j]) { 494 536 tmpMask->data.U8[j] = 0xff; 495 537 psTrace("psLib.math", 10, "Clipped %ld: %f +/- %f\n", j, … … 502 544 for (long j = 0; j < myVector->n; j++) { 503 545 if (!tmpMask->data.U8[j] && 504 fabsf(myVector->data.F32[j] - clippedMean) > (stats->clipSigma * clippedStdev)) {546 fabsf(myVector->data.F32[j] - clippedMean) > (stats->clipSigma * clippedStdev)) { 505 547 tmpMask->data.U8[j] = 0xff; 506 548 psTrace("psLib.math", 10, "Clipped %ld: %f\n", j, myVector->data.F32[j]); … … 584 626 } 585 627 586 psScalar tmpScalar; // Temporary scalar variable, for p_psVectorBinDisect 628 psVectorBinaryDisectResult result; 629 psScalar tmpScalar; // Temporary scalar variable, for psVectorBinaryDisect 587 630 tmpScalar.type.type = PS_TYPE_F32; 588 631 … … 609 652 long totalDataPoints = 0; // Total number of (unmasked) data points 610 653 654 float binSize = 0.0; // Size of bins for histogram 655 long binLo, binHi; 656 long binL2, binH2; 657 long binMedian; 658 611 659 // Iterate to get the best bin size 612 660 for (int iterate = 1; iterate > 0; iterate++) { … … 620 668 // Data range calculation failed 621 669 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n"); 622 psFree(statsMinMax); 623 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 624 psFree(mask); 625 return false; 670 goto escape; 626 671 } 627 672 psTrace("psLib.math", 6, "Data min/max is (%.2f, %.2f)\n", min, max); … … 629 674 // If all data points have the same value, then we set the appropriate members of stats and return. 630 675 if (fabs(max - min) <= FLT_EPSILON) { 631 psTrace("psLib.math", 5, "All data points have the same value: %f.\n", min);632 676 stats->robustMedian = min; 633 677 stats->robustStdev = 0.0; … … 635 679 stats->robustLQ = min; 636 680 stats->robustN50 = numValid; 637 psFree(statsMinMax);638 639 681 stats->results |= PS_STAT_ROBUST_MEDIAN; 640 682 stats->results |= PS_STAT_ROBUST_STDEV; 641 683 stats->results |= PS_STAT_ROBUST_QUARTILE; 642 684 psTrace("psLib.math", 5, "All data points have the same value: %f.\n", min); 643 685 psTrace("psLib.math", 4, "---- %s(0) end ----\n", __func__); 644 686 psFree(mask); 687 psFree(statsMinMax); 645 688 return true; 646 689 } 647 690 648 float binSize = 0.0; // Size of bins for histogram649 691 if ((iterate == 1) && (stats->options & PS_STAT_USE_BINSIZE)) { 650 692 // Set initial bin size to the specified value. … … 668 710 if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) { 669 711 psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for robust statistics.\n"); 670 psFree(histogram); 671 psFree(statsMinMax); 672 return false; 712 goto escape; 673 713 } 674 714 if (psTraceGetLevel("psLib.math") >= 8) { … … 691 731 totalDataPoints = cumulative->nums->data.F32[numBins - 1]; 692 732 psTrace("psLib.math", 6, "Total data points is %ld\n", totalDataPoints); 693 long binMedian; 694 if (totalDataPoints/2.0 < cumulative->nums->data.F32[0]) { 695 // Special case: the median is in the first bin. Perhaps we should recode this. 696 // XXX: Must try a special case where the median in in the last bin. 697 binMedian = 0; 698 } else { 699 tmpScalar.data.F32 = totalDataPoints/2.0; 700 binMedian = 1 + p_psVectorBinDisect(cumulative->nums, &tmpScalar); 701 if (binMedian < 0) { 702 psError(PS_ERR_UNKNOWN, false, 703 "Failed to calculate the 50 precent data point (%ld).\n", binMedian); 704 psFree(statsMinMax); 705 psFree(histogram); 706 psFree(cumulative); 707 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 708 psFree(mask); 709 return false; 710 } 711 } 733 734 PS_BIN_FOR_VALUE(binMedian, cumulative->nums, totalDataPoints/2.0, 0); 712 735 psTrace("psLib.math", 6, "The median bin is %ld (%.2f to %.2f)\n", binMedian, 713 736 cumulative->bounds->data.F32[binMedian], cumulative->bounds->data.F32[binMedian+1]); … … 715 738 // ADD step 3: Interpolate to the exact 50% position: this is the robust histogram median. 716 739 stats->robustMedian = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 717 binMedian, totalDataPoints/2.0);740 binMedian, totalDataPoints/2.0); 718 741 if (isnan(stats->robustMedian)) { 719 psError(PS_ERR_UNKNOWN, false, 720 "Failed to fit a quadratic and calculate the 50-percent position.\n"); 721 psFree(statsMinMax); 722 psFree(histogram); 723 psFree(cumulative); 724 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 725 psFree(mask); 726 return false; 742 psError(PS_ERR_UNKNOWN, false, "Failed to fit a quadratic and calculate the 50-percent position.\n"); 743 goto escape; 727 744 } 728 745 psTrace("psLib.math", 6, "Current robust median is %f\n", stats->robustMedian); 729 746 730 // ADD step 4: Find the bins which contains the 15.8655% and 84.1345% data points. 731 long binLo = 0; // Bin containing the 15.8655% mark 732 tmpScalar.data.F32 = totalDataPoints * 0.158655f; 733 if (tmpScalar.data.F32 > cumulative->nums->data.F32[0]) { 734 // NOTE: the (+1) here is because of the way p_psVectorBinDisect is defined. 735 binLo = 1 + p_psVectorBinDisect(cumulative->nums, &tmpScalar); 736 if (binLo > cumulative->nums->n-1) { 737 binLo = cumulative->nums->n-1; 738 } 739 } 740 741 long binHi = 0; // Bin containing the 84.1345% mark 742 tmpScalar.data.F32 = totalDataPoints * 0.841345f; 743 if (tmpScalar.data.F32 > cumulative->nums->data.F32[0]) { 744 // NOTE: the (+1) here is because of the way p_psVectorBinDisect is defined. 745 binHi = 1 + p_psVectorBinDisect(cumulative->nums, &tmpScalar); 746 if (binHi > cumulative->nums->n-1) { 747 binHi = cumulative->nums->n-1; 748 } 749 } 747 // ADD step 4: Find the bins which contains the 15.8655% (-1 sigma) and 84.1345% (+1 sigma) data points 748 // also find the 30.8538% (-0.5 sigma) and 69.1462% (+0.5 sigma) points 749 PS_BIN_FOR_VALUE(binLo, cumulative->nums, totalDataPoints * 0.158655f, -1); 750 PS_BIN_FOR_VALUE(binHi, cumulative->nums, totalDataPoints * 0.841345f, +1); 751 752 PS_BIN_FOR_VALUE(binL2, cumulative->nums, totalDataPoints * 0.308538f, -1); 753 PS_BIN_FOR_VALUE(binH2, cumulative->nums, totalDataPoints * 0.691462f, +1); 754 750 755 psTrace("psLib.math", 6, "The 15.8655%% and 84.1345%% data point bins are (%ld, %ld).\n", 751 756 binLo, binHi); … … 755 760 if ((binLo < 0) || (binHi < 0)) { 756 761 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 15.8655%% and 84.1345%% data points.\n"); 757 psFree(statsMinMax); 758 psFree(histogram); 759 psFree(cumulative); 760 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 761 psFree(mask); 762 return false; 762 goto escape; 763 763 } 764 764 … … 769 769 binHi, cumulative->nums->data.F32[binHi], cumulative->nums->data.F32[binHi+1]); 770 770 771 float deltaBounds, deltaNums, prevPixels; 772 float percentNums, base, binLoF32; 773 774 // find the -1 sigma points with linear interpolation 775 deltaBounds = cumulative->bounds->data.F32[binLo+1] - cumulative->bounds->data.F32[binLo]; 776 if (binLo == 0) { 777 deltaNums = cumulative->nums->data.F32[0]; 778 prevPixels = 0; 779 } else { 780 deltaNums = cumulative->nums->data.F32[binLo] - cumulative->nums->data.F32[binLo-1]; 781 prevPixels = cumulative->nums->data.F32[binLo-1]; 782 } 783 percentNums = (totalDataPoints * 0.158655f) - prevPixels; 784 base = cumulative->bounds->data.F32[binLo]; 785 binLoF32 = base + (deltaBounds / deltaNums) * percentNums; // Value for the 15.8655% mark 786 psTrace("psLib.math", 6, 787 "(base, deltaBounds, deltaNums, prevPixels, percentNums) is (%.2f %.2f %.2f %.2f %.2f)\n", 788 base, deltaBounds, deltaNums, prevPixels, percentNums); 789 790 // find the +1 sigma points with linear interpolation 791 deltaBounds = cumulative->bounds->data.F32[binHi+1] - cumulative->bounds->data.F32[binHi]; 792 if (binHi == 0) { 793 deltaNums = cumulative->nums->data.F32[0]; 794 prevPixels = 0; 795 } else { 796 deltaNums = cumulative->nums->data.F32[binHi] - cumulative->nums->data.F32[binHi-1]; 797 prevPixels = cumulative->nums->data.F32[binHi-1]; 798 } 799 percentNums = (totalDataPoints * 0.841345f) - prevPixels; 800 base = cumulative->bounds->data.F32[binHi]; 801 float binHiF32 = base + (deltaBounds / deltaNums) * percentNums; // Value for the 84.1345% mark 802 psTrace("psLib.math", 6, 803 "(base, deltaBounds, deltaNums, prevPixels, percentNums) is (%.2f %.2f %.2f %.2f %.2f)\n", 804 base, deltaBounds, deltaNums, prevPixels, percentNums); 771 // find the +0.5 and -0.5 sigma points with linear interpolation. binLo and binHi are the bins 772 // containing the value of interest. constrain the answer to be within the current bin. 773 // (extrapolation should not be needed and will result in errors) 774 float binLoF32, binHiF32, binL2F32, binH2F32; 775 PS_BIN_INTERPOLATE (binLoF32, cumulative->nums, cumulative->bounds, binL2, totalDataPoints * 0.158655f); 776 PS_BIN_INTERPOLATE (binHiF32, cumulative->nums, cumulative->bounds, binH2, totalDataPoints * 0.841345f); 777 PS_BIN_INTERPOLATE (binL2F32, cumulative->nums, cumulative->bounds, binL2, totalDataPoints * 0.308538f); 778 PS_BIN_INTERPOLATE (binH2F32, cumulative->nums, cumulative->bounds, binH2, totalDataPoints * 0.691462f); 805 779 806 780 // report +/- 1 sigma points … … 809 783 binLoF32, binHiF32); 810 784 811 // ADD step 5: Determine SIGMA as 1/2 of the distance between these positions. 812 sigma = (binHiF32 - binLoF32) / 2.0; 785 // ADD step 5: Determine SIGMA as (1/2 of) the distance between these positions. 786 // sigma = (binHiF32 - binLoF32) / 2.0; 787 sigma = (binH2F32 - binL2F32); 788 813 789 psTrace("psLib.math", 6, "The current sigma is %f.\n", sigma); 814 790 stats->robustStdev = sigma; … … 835 811 // Free the histograms; they will be recreated on the next iteration, with new bounds 836 812 psFree(histogram); 813 histogram = NULL; 814 837 815 psFree(cumulative); 816 cumulative = NULL; 838 817 } else { 839 818 // We've got the bin size correct now … … 842 821 } 843 822 } 844 psFree(histogram); 823 824 // XXX test lines while studying algorithm errors 825 // fprintf (stderr, "robust stats test %7.1f +/- %7.1f : %4ld %4ld %4ld %4ld %4ld : %f %f %f\n", 826 // stats->robustMedian, stats->robustStdev, 827 // binLo, binL2, binMedian, binH2, binHi, binSize, max, min); 845 828 846 829 // ADD step 7: Find the bins which contains the 25% and 75% data points. 847 long binLo25 = 0; // Bin containing the 25% value 848 long binHi25 = 0; // Bin containing the 75% value 849 850 tmpScalar.data.F32 = totalDataPoints * 0.25f; 851 if (tmpScalar.data.F32 <= cumulative->nums->data.F32[0]) { 852 // Special case where its in first bin. The last bin should be handled automatically. 853 binLo25 = 0; 854 } else { 855 binLo25 = 1 + p_psVectorBinDisect(cumulative->nums, &tmpScalar); 856 } 857 tmpScalar.data.F32 = totalDataPoints * 0.75f; 858 if (tmpScalar.data.F32 <= cumulative->nums->data.F32[0]) { 859 // Special case where its in first bin. The last bin should be handled automatically. 860 binHi25 = 0; 861 } else { 862 binHi25 = 1 + p_psVectorBinDisect(cumulative->nums, &tmpScalar); 863 } 864 if ((binLo25 < 0) || (binHi25 < 0)) { 865 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 25 and 75 percent data points\n"); 866 psFree(statsMinMax); 867 psFree(cumulative); 868 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 869 psFree(mask); 870 return false; 871 } 830 long binLo25, binHi25; 831 PS_BIN_FOR_VALUE (binLo25, cumulative->nums, totalDataPoints * 0.25f, 0); 832 PS_BIN_FOR_VALUE (binHi25, cumulative->nums, totalDataPoints * 0.75f, 0); 872 833 psTrace("psLib.math", 6, "The 25-percent and 75-precent data point bins are (%ld, %ld).\n", binLo25, binHi25); 873 834 … … 875 836 // positions. 876 837 psF32 binLo25F32 = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 877 binLo25, totalDataPoints * 0.25f);838 binLo25, totalDataPoints * 0.25f); 878 839 psF32 binHi25F32 = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 879 binHi25, totalDataPoints * 0.75f); 880 psFree(cumulative); 881 840 binHi25, totalDataPoints * 0.75f); 882 841 if (isnan(binLo25F32) || isnan(binHi25F32)) { 883 842 psError(PS_ERR_UNKNOWN, false, 884 843 "could not determine the robustUQ: fitQuadraticSearchForYThenReturnX() returned a NAN.\n"); 885 psFree(statsMinMax); 886 psTrace("psLib.math", 4, "---- %s(1) end ----\n", __func__); 887 psFree(mask); 888 return false; 889 } 890 891 stats->results |= PS_STAT_ROBUST_QUARTILE; 844 goto escape; 845 } 846 892 847 stats->robustLQ = binLo25F32; 893 848 stats->robustUQ = binHi25F32; … … 897 852 for (long i = 0 ; i < myVector->n ; i++) { 898 853 if (!mask->data.U8[i] && 899 (binLo25F32 <= myVector->data.F32[i]) && (binHi25F32 >= myVector->data.F32[i])) {854 (binLo25F32 <= myVector->data.F32[i]) && (binHi25F32 >= myVector->data.F32[i])) { 900 855 N50++; 901 856 } … … 905 860 906 861 // Clean up 862 psFree(histogram); 863 psFree(cumulative); 907 864 psFree(statsMinMax); 908 865 psFree(mask); … … 910 867 stats->results |= PS_STAT_ROBUST_MEDIAN; 911 868 stats->results |= PS_STAT_ROBUST_STDEV; 869 stats->results |= PS_STAT_ROBUST_QUARTILE; 912 870 913 871 psTrace("psLib.math", 4, "---- %s(0) end ----\n", __func__); 914 872 return true; 873 874 escape: 875 stats->robustMedian = NAN; 876 stats->robustStdev = NAN; 877 stats->robustUQ = NAN; 878 stats->robustLQ = NAN; 879 stats->robustN50 = 0; 880 stats->results |= PS_STAT_ROBUST_MEDIAN; 881 stats->results |= PS_STAT_ROBUST_STDEV; 882 stats->results |= PS_STAT_ROBUST_QUARTILE; 883 884 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 885 886 psFree(histogram); 887 psFree(cumulative); 888 psFree(statsMinMax); 889 psFree(mask); 890 891 return false; 915 892 } 916 893 … … 943 920 float guessMean = stats->robustMedian; // pass the guess mean 944 921 922 psVectorBinaryDisectResult result; 923 945 924 psTrace("psLib.math", 6, "The guess mean is %f.\n", guessMean); 946 925 psTrace("psLib.math", 6, "The guess stdev is %f.\n", guessStdev); … … 950 929 psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max 951 930 952 psScalar tmpScalar; // Temporary scalar variable, for p _psVectorBinDisect931 psScalar tmpScalar; // Temporary scalar variable, for psVectorBinaryDisect 953 932 tmpScalar.type.type = PS_TYPE_F32; 954 933 … … 995 974 } 996 975 997 long binMin = 0; // Low bin to check998 long binMax = 0; // High bin to check999 1000 976 // Fit a Gaussian to the bins in the requested range about the guess mean 1001 977 // min,max overrides clipSigma … … 1016 992 } 1017 993 1018 tmpScalar.data.F32 = guessMean - minFitSigma*guessStdev; 1019 if (tmpScalar.data.F32 < min) { 1020 binMin = 0; 1021 } else { 1022 binMin = p_psVectorBinDisect(histogram->bounds, &tmpScalar); 1023 } 1024 tmpScalar.data.F32 = guessMean + maxFitSigma*guessStdev; 1025 if (tmpScalar.data.F32 > max) { 1026 binMax = histogram->bounds->n - 1; 1027 } else { 1028 binMax = p_psVectorBinDisect(histogram->bounds, &tmpScalar); 1029 } 1030 if (binMin < 0 || binMax < 0) { 1031 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the -%f sigma : +%f sigma bins\n", minFitSigma, maxFitSigma); 1032 psFree(statsMinMax); 1033 psFree(histogram); 1034 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 1035 return false; 1036 } 994 // select the min and max bins, saturating on the lower and upper end-points 995 long binMin, binMax; 996 PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, -1); 997 PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, +1); 1037 998 1038 999 // Generate the variables that will be used in the Gaussian fitting … … 1142 1103 float guessMean = stats->robustMedian; // pass the guess mean 1143 1104 1105 psVectorBinaryDisectResult result; 1144 1106 psTrace("psLib.math", 6, "The ** starting ** guess mean is %f.\n", guessMean); 1145 1107 psTrace("psLib.math", 6, "The ** starting ** guess stdev is %f.\n", guessStdev); … … 1149 1111 psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max 1150 1112 1151 psScalar tmpScalar; // Temporary scalar variable, for p _psVectorBinDisect1113 psScalar tmpScalar; // Temporary scalar variable, for psVectorBinaryDisect 1152 1114 tmpScalar.type.type = PS_TYPE_F32; 1153 1115 … … 1194 1156 } 1195 1157 1196 long binMin = 0; // Low bin to check1197 long binMax = 0; // High bin to check1198 1199 1158 // Fit a Gaussian to the bins in the requested range about the guess mean 1200 1159 // min,max overrides clipSigma … … 1215 1174 } 1216 1175 1217 tmpScalar.data.F32 = guessMean - minFitSigma*guessStdev; 1218 if (tmpScalar.data.F32 < min) { 1219 binMin = 0; 1220 } else { 1221 binMin = p_psVectorBinDisect(histogram->bounds, &tmpScalar); 1222 } 1223 tmpScalar.data.F32 = guessMean + maxFitSigma*guessStdev; 1224 if (tmpScalar.data.F32 > max) { 1225 binMax = histogram->bounds->n - 1; 1226 } else { 1227 binMax = p_psVectorBinDisect(histogram->bounds, &tmpScalar); 1228 } 1229 if (binMin < 0 || binMax < 0) { 1230 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the -%f sigma : +%f sigma bins\n", minFitSigma, maxFitSigma); 1231 psFree(statsMinMax); 1232 psFree(histogram); 1233 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 1234 return false; 1235 } 1176 // select the min and max bins, saturating on the lower and upper end-points 1177 long binMin, binMax; 1178 PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, -1); 1179 PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, +1); 1236 1180 1237 1181 // Generate the variables that will be used in the Gaussian fitting … … 1355 1299 float guessMean = stats->robustMedian; // pass the guess mean 1356 1300 1301 psVectorBinaryDisectResult result; 1357 1302 psTrace("psLib.math", 6, "The ** starting ** guess mean is %f.\n", guessMean); 1358 1303 psTrace("psLib.math", 6, "The ** starting ** guess stdev is %f.\n", guessStdev); … … 1362 1307 psStats *statsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max 1363 1308 1364 psScalar tmpScalar; // Temporary scalar variable, for p _psVectorBinDisect1309 psScalar tmpScalar; // Temporary scalar variable, for psVectorBinaryDisect 1365 1310 tmpScalar.type.type = PS_TYPE_F32; 1366 1311 … … 1409 1354 // now fit a Gaussian to the upper and lower halves about the peak independently 1410 1355 1411 long binMin, binMax;1412 float upperMean, upperStdev;1413 1414 1356 // set the full-range upper and lower limits 1415 1357 psF32 maxFitSigma = 2.0; … … 1429 1371 } 1430 1372 1431 tmpScalar.data.F32 = guessMean - minFitSigma*guessStdev; 1432 if (tmpScalar.data.F32 < min) { 1433 binMin = 0; 1434 } else { 1435 binMin = p_psVectorBinDisect(histogram->bounds, &tmpScalar); 1436 } 1437 tmpScalar.data.F32 = guessMean + maxFitSigma*guessStdev; 1438 if (tmpScalar.data.F32 > max) { 1439 binMax = histogram->bounds->n; 1440 } else { 1441 binMax = p_psVectorBinDisect(histogram->bounds, &tmpScalar) + 1; 1442 } 1443 if (binMin < 0 || binMax < 0) { 1444 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the -%f sigma : +%f sigma bins\n", minFitSigma, maxFitSigma); 1445 psFree(statsMinMax); 1446 psFree(histogram); 1447 psTrace("psLib.math", 4, "---- %s(false) end ----\n", __func__); 1448 return false; 1449 } 1373 // select the min and max bins, saturating on the lower and upper end-points 1374 long binMin, binMax; 1375 PS_BIN_FOR_VALUE (binMin, histogram->bounds, guessMean - minFitSigma*guessStdev, -1); 1376 PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, +1); 1450 1377 1451 1378 // search for mode (peak of histogram within range mean-2sigma - mean+2sigma … … 1463 1390 psTrace("psLib.math", 6, "The clipped numBins is %ld\n", binMax - binMin); 1464 1391 psTrace("psLib.math", 6, "The clipped min is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMin), binMin); 1465 psTrace("psLib.math", 6, "The clipped max is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMax ), binMax);1392 psTrace("psLib.math", 6, "The clipped max is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binMax - 1), binMax - 1); 1466 1393 psTrace("psLib.math", 6, "The clipped peak is %f (%ld)\n", PS_BIN_MIDPOINT(histogram, binPeak), binPeak); 1467 1394 … … 1581 1508 1582 1509 // calculate upper mean & stdev from parabolic fit -- use this as the result 1583 upperStdev = sqrt(-0.5/poly->coeff[2]);1584 upperMean = poly->coeff[1]*PS_SQR(upperStdev);1510 float upperStdev = sqrt(-0.5/poly->coeff[2]); 1511 float upperMean = poly->coeff[1]*PS_SQR(upperStdev); 1585 1512 psTrace("psLib.math", 6, "Parabolic Upper fit results: %f + %f x + %f x^2\n", poly->coeff[0], poly->coeff[1], poly->coeff[2]); 1586 1513 psTrace("psLib.math", 6, "The upper mean is %f.\n", upperMean); … … 1680 1607 // took way too long. 1681 1608 // 1682 #if 01609 #if 0 1683 1610 1684 1611 gaussWidth = 10; 1685 #endif1612 #endif 1686 1613 // 1687 1614 // We determine the bin numbers (jMin:jMax) corresponding to a … … 1926 1853 psStatsOptions psStatsOptionFromString(const char *string) 1927 1854 { 1928 #define READ_STAT(NAME, SYMBOL) \1855 #define READ_STAT(NAME, SYMBOL) \ 1929 1856 if (strcasecmp(string, NAME) == 0) { \ 1930 1857 return SYMBOL; \ … … 1964 1891 psString string = NULL; // String to return 1965 1892 1966 #define WRITE_STAT(NAME, SYMBOL) \1893 #define WRITE_STAT(NAME, SYMBOL) \ 1967 1894 if (option & SYMBOL) { \ 1968 1895 psStringAppend(&string, "%s ", NAME); \ … … 2023 1950 { 2024 1951 switch (option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE)) { 2025 case PS_STAT_SAMPLE_MEAN:2026 case PS_STAT_SAMPLE_MEDIAN:2027 case PS_STAT_SAMPLE_STDEV:2028 case PS_STAT_SAMPLE_QUARTILE:2029 case PS_STAT_ROBUST_MEDIAN:2030 case PS_STAT_ROBUST_STDEV:2031 case PS_STAT_ROBUST_QUARTILE:2032 case PS_STAT_FITTED_MEAN:2033 case PS_STAT_FITTED_STDEV:2034 case PS_STAT_FITTED_MEAN_V2:2035 case PS_STAT_FITTED_STDEV_V2:2036 case PS_STAT_FITTED_MEAN_V3:2037 case PS_STAT_FITTED_STDEV_V3:2038 case PS_STAT_CLIPPED_MEAN:2039 case PS_STAT_CLIPPED_STDEV:2040 case PS_STAT_MAX:2041 case PS_STAT_MIN:1952 case PS_STAT_SAMPLE_MEAN: 1953 case PS_STAT_SAMPLE_MEDIAN: 1954 case PS_STAT_SAMPLE_STDEV: 1955 case PS_STAT_SAMPLE_QUARTILE: 1956 case PS_STAT_ROBUST_MEDIAN: 1957 case PS_STAT_ROBUST_STDEV: 1958 case PS_STAT_ROBUST_QUARTILE: 1959 case PS_STAT_FITTED_MEAN: 1960 case PS_STAT_FITTED_STDEV: 1961 case PS_STAT_FITTED_MEAN_V2: 1962 case PS_STAT_FITTED_STDEV_V2: 1963 case PS_STAT_FITTED_MEAN_V3: 1964 case PS_STAT_FITTED_STDEV_V3: 1965 case PS_STAT_CLIPPED_MEAN: 1966 case PS_STAT_CLIPPED_STDEV: 1967 case PS_STAT_MAX: 1968 case PS_STAT_MIN: 2042 1969 return option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE); 2043 default:1970 default: 2044 1971 return 0; 2045 1972 } … … 2052 1979 // We could call psStatsSingle to check, but it would be a waste since we effectively do it anyway 2053 1980 switch (option & ~(PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE)) { 2054 case PS_STAT_SAMPLE_MEAN:1981 case PS_STAT_SAMPLE_MEAN: 2055 1982 return stats->sampleMean; 2056 case PS_STAT_SAMPLE_MEDIAN:1983 case PS_STAT_SAMPLE_MEDIAN: 2057 1984 return stats->sampleMedian; 2058 case PS_STAT_SAMPLE_STDEV:1985 case PS_STAT_SAMPLE_STDEV: 2059 1986 return stats->sampleStdev; 2060 case PS_STAT_ROBUST_MEDIAN:1987 case PS_STAT_ROBUST_MEDIAN: 2061 1988 return stats->robustMedian; 2062 case PS_STAT_ROBUST_STDEV:1989 case PS_STAT_ROBUST_STDEV: 2063 1990 return stats->robustStdev; 2064 case PS_STAT_FITTED_MEAN:1991 case PS_STAT_FITTED_MEAN: 2065 1992 return stats->fittedMean; 2066 case PS_STAT_FITTED_STDEV:1993 case PS_STAT_FITTED_STDEV: 2067 1994 return stats->fittedStdev; 2068 case PS_STAT_FITTED_MEAN_V2:1995 case PS_STAT_FITTED_MEAN_V2: 2069 1996 return stats->fittedMean; 2070 case PS_STAT_FITTED_STDEV_V2:1997 case PS_STAT_FITTED_STDEV_V2: 2071 1998 return stats->fittedStdev; 2072 case PS_STAT_FITTED_MEAN_V3:1999 case PS_STAT_FITTED_MEAN_V3: 2073 2000 return stats->fittedMean; 2074 case PS_STAT_FITTED_STDEV_V3:2001 case PS_STAT_FITTED_STDEV_V3: 2075 2002 return stats->fittedStdev; 2076 case PS_STAT_CLIPPED_MEAN:2003 case PS_STAT_CLIPPED_MEAN: 2077 2004 return stats->clippedMean; 2078 case PS_STAT_CLIPPED_STDEV:2005 case PS_STAT_CLIPPED_STDEV: 2079 2006 return stats->clippedStdev; 2080 case PS_STAT_MAX:2007 case PS_STAT_MAX: 2081 2008 return stats->max; 2082 case PS_STAT_MIN:2009 case PS_STAT_MIN: 2083 2010 return stats->min; 2084 case PS_STAT_SAMPLE_QUARTILE:2085 case PS_STAT_ROBUST_QUARTILE:2011 case PS_STAT_SAMPLE_QUARTILE: 2012 case PS_STAT_ROBUST_QUARTILE: 2086 2013 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot return a single quartile value; " 2087 2014 "get them yourself.\n"); 2088 2015 return NAN; 2089 default:2016 default: 2090 2017 return NAN; 2091 2018 } … … 2102 2029 psF32 xLo, 2103 2030 psF32 xHi 2104 )2031 ) 2105 2032 { 2106 2033 psF64 tmp = sqrt((y - c)/a + (b*b)/(4.0 * a * a)); … … 2130 2057 *****************************************************************************/ 2131 2058 static psF32 fitQuadraticSearchForYThenReturnX(const psVector *xVec, 2132 psVector *yVec,2133 psS32 binNum,2134 psF32 yVal2135 )2059 psVector *yVec, 2060 psS32 binNum, 2061 psF32 yVal 2062 ) 2136 2063 { 2137 2064 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); … … 2171 2098 // 2172 2099 if (! (((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2])) || 2173 ((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) ) {2100 ((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) ) { 2174 2101 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 2175 2102 _("Specified yVal, %g, is not within y-range, %g to %g."), … … 2181 2108 // 2182 2109 if (((y->data.F64[0] < y->data.F64[1]) && !(y->data.F64[1] <= y->data.F64[2])) || 2183 ((y->data.F64[0] > y->data.F64[1]) && !(y->data.F64[1] >= y->data.F64[2]))) {2110 ((y->data.F64[0] > y->data.F64[1]) && !(y->data.F64[1] >= y->data.F64[2]))) { 2184 2111 psError(PS_ERR_UNKNOWN, true, 2185 2112 "This routine must be called with monotonically increasing or decreasing data points.\n"); … … 2252 2179 const psVector *params, 2253 2180 const psVector *coords 2254 )2181 ) 2255 2182 { 2256 2183 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
Note:
See TracChangeset
for help on using the changeset viewer.
