IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 17612


Ignore:
Timestamp:
May 9, 2008, 11:34:42 AM (18 years ago)
Author:
eugene
Message:

fixed error with cumulative histogram: values correspond to UPPER BOUNDS for input histogram

File:
1 edited

Legend:

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

    r17447 r17612  
    1313 * use ->min and ->max (PS_STAT_USE_RANGE)
    1414 *
    15  *  @version $Revision: 1.222 $ $Name: not supported by cvs2svn $
    16  *  @date $Date: 2008-04-17 23:43:02 $
     15 *  @version $Revision: 1.223 $ $Name: not supported by cvs2svn $
     16 *  @date $Date: 2008-05-09 21:34:42 $
    1717 *
    1818 *  Copyright 2006 IfA, University of Hawaii
     
    152152// static prototypes:
    153153static 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);
     155static psF32 fitQuadraticSearchForYThenReturnXusingValues(const psVector *xVec, psVector *yVec, psS32 binNum, psF32 yVal);
    156156
    157157/******************************************************************************
     
    817817
    818818        // 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])
    819820        cumulative = psHistogramAlloc(min, max, numBins);
    820821        cumulative->nums->data.F32[0] = histogram->nums->data.F32[0];
    821822        for (long i = 1; i < histogram->nums->n; i++) {
    822823            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];
    823825        }
    824826        if (psTraceGetLevel("psLib.math") >= 8) {
     
    831833        psTrace(TRACE, 6, "Total data points is %ld\n", totalDataPoints);
    832834
     835        // find bin which is the lower bound of median (value[binMedian] < median < value[binMedian+1]
    833836        PS_BIN_FOR_VALUE(binMedian, cumulative->nums, totalDataPoints/2.0, 0);
     837
    834838        psTrace(TRACE, 6, "The median bin is %ld (%.2f to %.2f)\n", binMedian,
    835839                cumulative->bounds->data.F32[binMedian], cumulative->bounds->data.F32[binMedian+1]);
    836840
    837841        // 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);
    840843        if (isnan(stats->robustMedian)) {
    841844            psError(PS_ERR_UNKNOWN, false,
     
    911914        sigma = PS_MIN (sigma1, PS_MIN (sigma2, sigma4));
    912915
    913         psTrace(TRACE, 6, "The 2x sigma is %f.\n", sigma1);
     916        psTrace(TRACE, 6, "The 1x sigma is %f.\n", sigma1);
    914917        psTrace(TRACE, 6, "The 2x sigma is %f.\n", sigma2);
    915918        psTrace(TRACE, 6, "The 4x sigma is %f.\n", sigma4);
     
    920923        // ADD step 6: If the measured SIGMA is less than 2 times the bin size, exclude points which are more
    921924        // 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)) {
    923926            psTrace(TRACE, 6, "*************: Do another iteration (%f %f).\n", sigma, binSize);
    924927            long maskLo = PS_MAX(0, (binMedian - 25)); // Low index for masking region
     
    963966    // ADD step 8: Interpolate to find these two positions exactly: these are the upper and lower quartile
    964967    // 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);
    969970    if (isnan(binLo25F32) || isnan(binHi25F32)) {
    970971        psError(PS_ERR_UNKNOWN, false,
     
    25882589}
    25892590
    2590 
     2591# if (0)
    25912592/******************************************************************************
    25922593fitQuadraticSearchForYThenReturnX(*xVec, *yVec, binNum, yVal): A general
     
    26962697        if (binNum == 0) {
    26972698            // 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/******************************************************************************
     2722fitQuadraticSearchForYThenReturnXusingValues(*xVec, *yVec, binNum, yVal): A general routine
     2723which fits a quadratic to three points and returns the x-value corresponding to the input
     2724y-value.  This routine takes psVectors of x/y pairs as input, and fits a quadratic to the 3
     2725points surrounding element binNum in the vectors.  This version uses the values of x[i] for the
     2726x coordinates (not the midpoints).  This is appropriate for a cumulative histogram.  It then
     2727determines for what value x does that quadratic f(x) = yVal (the input parameter).
     2728
     2729*****************************************************************************/
     2730static 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
    26982827            tmpFloat = 0.5 * (xVec->data.F32[binNum] +
    26992828                              xVec->data.F32[binNum + 1]);
Note: See TracChangeset for help on using the changeset viewer.