Changeset 17612
- Timestamp:
- May 9, 2008, 11:34:42 AM (18 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psStats.c (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psStats.c
r17447 r17612 13 13 * use ->min and ->max (PS_STAT_USE_RANGE) 14 14 * 15 * @version $Revision: 1.22 2$ $Name: not supported by cvs2svn $16 * @date $Date: 2008-0 4-17 23:43:02 $15 * @version $Revision: 1.223 $ $Name: not supported by cvs2svn $ 16 * @date $Date: 2008-05-09 21:34:42 $ 17 17 * 18 18 * Copyright 2006 IfA, University of Hawaii … … 152 152 // static prototypes: 153 153 static psF32 minimizeLMChi2Gauss1D(psVector *deriv, const psVector *params, const psVector *coords); 154 static psF32 fitQuadraticSearchForYThenReturnX(const psVector *xVec, psVector *yVec, psS32 binNum, 155 psF32 yVal);154 // static psF32 fitQuadraticSearchForYThenReturnX(const psVector *xVec, psVector *yVec, psS32 binNum, psF32 yVal); 155 static psF32 fitQuadraticSearchForYThenReturnXusingValues(const psVector *xVec, psVector *yVec, psS32 binNum, psF32 yVal); 156 156 157 157 /****************************************************************************** … … 817 817 818 818 // ADD step 1: Convert the specific histogram to a cumulative histogram 819 // The cumulative histogram data points correspond to the UPPER bound value (N < Bin[i+1]) 819 820 cumulative = psHistogramAlloc(min, max, numBins); 820 821 cumulative->nums->data.F32[0] = histogram->nums->data.F32[0]; 821 822 for (long i = 1; i < histogram->nums->n; i++) { 822 823 cumulative->nums->data.F32[i] = cumulative->nums->data.F32[i-1] + histogram->nums->data.F32[i]; 824 cumulative->bounds->data.F32[i-1] = histogram->bounds->data.F32[i]; 823 825 } 824 826 if (psTraceGetLevel("psLib.math") >= 8) { … … 831 833 psTrace(TRACE, 6, "Total data points is %ld\n", totalDataPoints); 832 834 835 // find bin which is the lower bound of median (value[binMedian] < median < value[binMedian+1] 833 836 PS_BIN_FOR_VALUE(binMedian, cumulative->nums, totalDataPoints/2.0, 0); 837 834 838 psTrace(TRACE, 6, "The median bin is %ld (%.2f to %.2f)\n", binMedian, 835 839 cumulative->bounds->data.F32[binMedian], cumulative->bounds->data.F32[binMedian+1]); 836 840 837 841 // ADD step 3: Interpolate to the exact 50% position: this is the robust histogram median. 838 stats->robustMedian = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 839 binMedian, totalDataPoints/2.0); 842 stats->robustMedian = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binMedian, totalDataPoints/2.0); 840 843 if (isnan(stats->robustMedian)) { 841 844 psError(PS_ERR_UNKNOWN, false, … … 911 914 sigma = PS_MIN (sigma1, PS_MIN (sigma2, sigma4)); 912 915 913 psTrace(TRACE, 6, "The 2x sigma is %f.\n", sigma1);916 psTrace(TRACE, 6, "The 1x sigma is %f.\n", sigma1); 914 917 psTrace(TRACE, 6, "The 2x sigma is %f.\n", sigma2); 915 918 psTrace(TRACE, 6, "The 4x sigma is %f.\n", sigma4); … … 920 923 // ADD step 6: If the measured SIGMA is less than 2 times the bin size, exclude points which are more 921 924 // than 25 bins from the median, recalculate the bin size, and perform the algorithm again. 922 if (sigma < ( 2* binSize)) {925 if (sigma < (3.0 * binSize)) { 923 926 psTrace(TRACE, 6, "*************: Do another iteration (%f %f).\n", sigma, binSize); 924 927 long maskLo = PS_MAX(0, (binMedian - 25)); // Low index for masking region … … 963 966 // ADD step 8: Interpolate to find these two positions exactly: these are the upper and lower quartile 964 967 // positions. 965 psF32 binLo25F32 = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 966 binLo25, totalDataPoints * 0.25f); 967 psF32 binHi25F32 = fitQuadraticSearchForYThenReturnX(cumulative->bounds, cumulative->nums, 968 binHi25, totalDataPoints * 0.75f); 968 psF32 binLo25F32 = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binLo25, totalDataPoints * 0.25f); 969 psF32 binHi25F32 = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binHi25, totalDataPoints * 0.75f); 969 970 if (isnan(binLo25F32) || isnan(binHi25F32)) { 970 971 psError(PS_ERR_UNKNOWN, false, … … 2588 2589 } 2589 2590 2590 2591 # if (0) 2591 2592 /****************************************************************************** 2592 2593 fitQuadraticSearchForYThenReturnX(*xVec, *yVec, binNum, yVal): A general … … 2696 2697 if (binNum == 0) { 2697 2698 // We have two points only at the beginning of the vectors x and y. 2699 tmpFloat = 0.5 * (xVec->data.F32[binNum] + 2700 xVec->data.F32[binNum + 1]); 2701 } else if (binNum == (xVec->n - 1)) { 2702 // The special case where we have two points only at the end of 2703 // the vectors x and y. 2704 // XXX: Is this right? 2705 tmpFloat = xVec->data.F32[binNum]; 2706 } else if (binNum == (xVec->n - 2)) { 2707 // XXX: Is this right? 2708 tmpFloat = 0.5 * (xVec->data.F32[binNum] + xVec->data.F32[binNum + 1]); 2709 } 2710 } 2711 2712 psTrace(TRACE, 6, "FIT: return %f\n", tmpFloat); 2713 psFree(x); 2714 psFree(y); 2715 2716 psTrace(TRACE, 5, "---- %s(%f) end ----\n", __func__, tmpFloat); 2717 return tmpFloat; 2718 } 2719 # endif 2720 2721 /****************************************************************************** 2722 fitQuadraticSearchForYThenReturnXusingValues(*xVec, *yVec, binNum, yVal): A general routine 2723 which fits a quadratic to three points and returns the x-value corresponding to the input 2724 y-value. This routine takes psVectors of x/y pairs as input, and fits a quadratic to the 3 2725 points surrounding element binNum in the vectors. This version uses the values of x[i] for the 2726 x coordinates (not the midpoints). This is appropriate for a cumulative histogram. It then 2727 determines for what value x does that quadratic f(x) = yVal (the input parameter). 2728 2729 *****************************************************************************/ 2730 static psF32 fitQuadraticSearchForYThenReturnXusingValues(const psVector *xVec, 2731 psVector *yVec, 2732 psS32 binNum, 2733 psF32 yVal 2734 ) 2735 { 2736 psTrace(TRACE, 4, "---- %s() begin ----\n", __func__); 2737 psTrace(TRACE, 5, "binNum, yVal is (%d, %f)\n", binNum, yVal); 2738 if (psTraceGetLevel("psLib.math") >= 8) { 2739 PS_VECTOR_PRINT_F32(xVec); 2740 PS_VECTOR_PRINT_F32(yVec); 2741 } 2742 2743 PS_ASSERT_VECTOR_NON_NULL(xVec, NAN); 2744 PS_ASSERT_VECTOR_NON_NULL(yVec, NAN); 2745 PS_ASSERT_VECTOR_TYPE(xVec, PS_TYPE_F32, NAN); 2746 PS_ASSERT_VECTOR_TYPE(yVec, PS_TYPE_F32, NAN); 2747 PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(xVec->n - 1), NAN); 2748 PS_ASSERT_INT_WITHIN_RANGE(binNum, 0, (int)(yVec->n - 1), NAN); 2749 2750 psVector *x = psVectorAlloc(3, PS_TYPE_F64); 2751 psVector *y = psVectorAlloc(3, PS_TYPE_F64); 2752 psF32 tmpFloat = 0.0f; 2753 2754 if ((binNum >= 1) && (binNum < (yVec->n - 2)) && (binNum < (xVec->n - 2))) { 2755 // The general case. We have all three points. 2756 x->data.F64[0] = xVec->data.F32[binNum - 1]; 2757 x->data.F64[1] = xVec->data.F32[binNum]; 2758 x->data.F64[2] = xVec->data.F32[binNum+1]; 2759 y->data.F64[0] = yVec->data.F32[binNum - 1]; 2760 y->data.F64[1] = yVec->data.F32[binNum]; 2761 y->data.F64[2] = yVec->data.F32[binNum + 1]; 2762 psTrace(TRACE, 6, "x vec (orig) is (%f %f %f %f)\n", xVec->data.F32[binNum - 1], 2763 xVec->data.F32[binNum], xVec->data.F32[binNum+1], xVec->data.F32[binNum+2]); 2764 psTrace(TRACE, 6, "x data is (%f %f %f)\n", x->data.F64[0], x->data.F64[1], x->data.F64[2]); 2765 psTrace(TRACE, 6, "y data is (%f %f %f)\n", y->data.F64[0], y->data.F64[1], y->data.F64[2]); 2766 2767 // 2768 // Ensure that the y value lies within range of the y values. 2769 // 2770 if (! (((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2])) || 2771 ((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) ) { 2772 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 2773 _("Specified yVal, %g, is not within y-range, %g to %g."), 2774 (psF64)yVal, y->data.F64[0], y->data.F64[2]); 2775 } 2776 2777 // 2778 // Ensure that the y values are monotonic. 2779 // 2780 if (((y->data.F64[0] < y->data.F64[1]) && !(y->data.F64[1] <= y->data.F64[2])) || 2781 ((y->data.F64[0] > y->data.F64[1]) && !(y->data.F64[1] >= y->data.F64[2]))) { 2782 psError(PS_ERR_UNKNOWN, true, 2783 "This routine must be called with monotonically increasing or decreasing data points.\n"); 2784 psFree(x); 2785 psFree(y); 2786 psTrace(TRACE, 5, "---- %s() end ----\n", __func__); 2787 return NAN; 2788 } 2789 2790 // Determine the coefficients of the polynomial. 2791 psPolynomial1D *myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2); 2792 if (!psVectorFitPolynomial1D(myPoly, NULL, 0, y, NULL, x)) { 2793 psError(PS_ERR_UNEXPECTED_NULL, false, 2794 _("Failed to fit a 1-dimensional polynomial to the three specified data points. " 2795 "Returning NAN.")); 2796 psFree(x); 2797 psFree(y); 2798 psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__); 2799 return NAN; 2800 } 2801 psTrace(TRACE, 6, "myPoly->coeff[0] is %f\n", myPoly->coeff[0]); 2802 psTrace(TRACE, 6, "myPoly->coeff[1] is %f\n", myPoly->coeff[1]); 2803 psTrace(TRACE, 6, "myPoly->coeff[2] is %f\n", myPoly->coeff[2]); 2804 psTrace(TRACE, 6, "Fitted y vec is (%f %f %f)\n", 2805 (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[0]), 2806 (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[1]), 2807 (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[2])); 2808 2809 psTrace(TRACE, 6, "We fit the polynomial, now find x such that f(x) equals %f\n", yVal); 2810 tmpFloat = QuadraticInverse(myPoly->coeff[2], myPoly->coeff[1], myPoly->coeff[0], yVal, 2811 x->data.F64[0], x->data.F64[2]); 2812 psFree(myPoly); 2813 2814 if (isnan(tmpFloat)) { 2815 psError(PS_ERR_UNEXPECTED_NULL, 2816 false, _("Failed to determine the median of the fitted polynomial. Returning NAN.")); 2817 psFree(x); 2818 psFree(y); 2819 psTrace(TRACE, 5, "---- %s(NAN) end ----\n", __func__); 2820 return(NAN); 2821 } 2822 } else { 2823 // These are special cases where the bin is at the beginning or end of the vector. 2824 if (binNum == 0) { 2825 // We have two points only at the beginning of the vectors x and y. 2826 // XXX this does not seem to be doing the linear interpolation / extrapolation 2698 2827 tmpFloat = 0.5 * (xVec->data.F32[binNum] + 2699 2828 xVec->data.F32[binNum + 1]);
Note:
See TracChangeset
for help on using the changeset viewer.
