IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 5113


Ignore:
Timestamp:
Sep 23, 2005, 1:01:30 PM (21 years ago)
Author:
gusciora
Message:

The purpose of this check-in is primarily to put the new robusts stats
code and tests into the CVS tree.

Location:
trunk/psLib
Files:
4 edited

Legend:

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

    r5090 r5113  
    1010 *  @author EAM, IfA
    1111 *
    12  *  @version $Revision: 1.139 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-09-22 02:47:16 $
     12 *  @version $Revision: 1.140 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-09-23 23:01:30 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    204204    # ifndef PS_NO_TRACE
    205205    // dump some useful info if trace is defined
    206     if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
    207         p_psImagePrint  (psTraceGetDestination(), alpha, "alpha guess");
    208         p_psVectorPrint (psTraceGetDestination(), beta, "beta guess");
    209         p_psVectorPrint (psTraceGetDestination(), params, "params guess");
    210     }
    211     if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) {
    212         // XXX: Where is this?
    213         // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
    214     }
     206    /* XXX: This code is seg faulting.
     207        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     208            p_psImagePrint  (psTraceGetDestination(), alpha, "alpha guess");
     209            p_psVectorPrint (psTraceGetDestination(), beta, "beta guess");
     210            p_psVectorPrint (psTraceGetDestination(), params, "params guess");
     211        }
     212        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 4) {
     213            // XXX: Where is this?
     214            // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
     215        }
     216    */
    215217    # endif /* PS_NO_TRACE */
    216218
     
    226228        # ifndef PS_NO_TRACE
    227229        // dump some useful info if trace is defined
    228         if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
    229             p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
    230             p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
    231             p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
    232         }
    233         if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) {
    234             // XXX: Where is this?
    235             // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
    236         }
     230        /* XXX: This code is seg faulting.
     231                if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     232                    p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
     233                    p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
     234                    p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
     235                }
     236                if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 4) {
     237                    // XXX: Where is this?
     238                    // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
     239                }
     240        */
    237241        # endif /* PS_NO_TRACE */
    238242
     
    249253        # ifndef PS_NO_TRACE
    250254        // dump some useful info if trace is defined
    251         if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
    252             p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
    253             p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
    254             p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
    255         }
     255        /* XXX: This code is seg faulting.
     256                if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") >= 5) {
     257                    p_psImagePrint  (psTraceGetDestination(), Alpha, "alpha guess");
     258                    p_psVectorPrint (psTraceGetDestination(), Beta, "beta guess");
     259                    p_psVectorPrint (psTraceGetDestination(), Params, "params guess");
     260                }
     261        */
    256262        # endif /* PS_NO_TRACE */
    257263
     
    271277        //        printf("CONDITIONS: (%f > %f) && (%d < %d)\n", min->lastDelta, min->tol, min->iter, min->maxIter);
    272278    }
    273     psTrace (".psLib.dataManip.psMinimizeLMChi2", 3, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
     279    psTrace (".psLib.dataManip.psMinimizeLMChi2", 4, "chisq: %f, last delta: %f, Niter: %d\n", min->value, min->lastDelta, min->iter);
    274280
    275281    // construct & return the covariance matrix (if requested)
     
    15791585
    15801586    if (psTraceGetLevel (".psLib.dataManip.VectorFitPolynomial1DOrd") >= 5) {
    1581         FILE *fp = fdopen((psTraceGetDestination ()), "a+");
    1582         fprintf(fp, "VectorFitPolynomial1D()\n");
     1587        psTrace(__func__, 6, "VectorFitPolynomial1D()\n");
    15831588        for (int i = 0; i < f->n; i++) {
    1584             fprintf(fp, "(x, f, fErr) is (");
     1589            psTrace(__func__, 6, "(x, f, fErr) is (");
    15851590            if (x != NULL) {
    1586                 fprintf(fp, "%f, %f, ", x->data.F64[i], f->data.F64[i]);
     1591                psTrace(__func__, 6, "%f, %f, ", x->data.F64[i], f->data.F64[i]);
    15871592            } else {
    1588                 fprintf(fp, "%f, %f, ", (psF64) i, f->data.F64[i]);
     1593                psTrace(__func__, 6, "%f, %f, ", (psF64) i, f->data.F64[i]);
    15891594            }
    15901595            if (fErr != NULL) {
    1591                 fprintf(fp, "%f)\n", fErr->data.F64[i]);
     1596                psTrace(__func__, 6, "%f)\n", fErr->data.F64[i]);
    15921597            } else {
    1593                 fprintf(fp, "NULL)\n");
    1594             }
    1595         }
    1596         fclose(fp);
     1598                psTrace(__func__, 6, "NULL)\n");
     1599            }
     1600        }
    15971601    }
    15981602
  • trunk/psLib/src/math/psPolynomial.c

    r5096 r5113  
    77*  polynomials.  It also contains a Gaussian functions.
    88*
    9 *  @version $Revision: 1.127 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-09-22 22:49:29 $
     9*  @version $Revision: 1.128 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-09-23 23:01:30 $
    1111*
    1212*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    572572    psF32 tmp = 1.0;
    573573
    574     psTrace(".psLib.dataManip.psPolynomial.psGaussian", 4,
    575             "---- psGaussian() begin ----\n");
     574    psTrace(__func__, 4, "---- %s() begin ----\n", __func__);
    576575
    577576    if (normal == true) {
     
    579578    }
    580579
    581     psTrace(".psLib.dataManip.psPolynomial.psGaussian", 4,
    582             "---- psGaussian() end ----\n");
     580    psTrace(__func__, 4, "---- %s() end ----\n", __func__);
    583581    return(tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma)));
    584582}
  • trunk/psLib/src/math/psStats.c

    r5090 r5113  
    77 *  on those data structures.
    88 *
    9  *  @author GLG, MHPCC
    10  *
    11  *  XXX: The following stats members are never used, or set in this code.
    12  *      stats->robustN50
    13  *      stats->clippedNvalues
    14  *      stats->binsize
    15  *
    16  *
    17  *
    18  *
    19  *  @version $Revision: 1.146 $ $Name: not supported by cvs2svn $
    20  *  @date $Date: 2005-09-22 02:47:16 $
    21  *
    22  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    23  */
     9*  @author GLG, MHPCC
     10*
     11*  XXX: The following stats members are never used, or set in this code.
     12*      stats->robustN50
     13*      stats->clippedNvalues
     14*      stats->binsize
     15*
     16*
     17*
     18*
     19*  @version $Revision: 1.147 $ $Name: not supported by cvs2svn $
     20*  @date $Date: 2005-09-23 23:01:30 $
     21*
     22*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     23*/
    2424
    2525#include <stdlib.h>
     
    631631                                       psF32 sigma)
    632632{
     633    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     634    psTrace(__func__, 6, "(histogram->nums->n, sigma) is (%d, %.2f\n", (int) histogram->nums->n, sigma);
    633635    PS_ASSERT_PTR_NON_NULL(histogram, NULL);
    634636    PS_ASSERT_PTR_NON_NULL(histogram->bounds, NULL);
     
    666668                            false,
    667669                            PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM);
     670                    psTrace(__func__, 3, "---- %s(NULL) end ----\n", __func__);
    668671                    return(NULL);
    669672                }
     
    681684                            false,
    682685                            PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM);
     686                    psTrace(__func__, 3, "---- %s(NULL) end ----\n", __func__);
    683687                    return(NULL);
    684688                }
     
    703707        // We get here if the histogram is uniform.
    704708        //
    705 
    706709        for (psS32 i = 0; i < numBins; i++) {
    707710            psF32 binSize = histogram->bounds->data.F32[1] - histogram->bounds->data.F32[0];
    708711            psS32 gaussWidth = (psS32) ((PS_GAUSS_WIDTH * sigma) / binSize);
    709712
     713            //
     714            // XXX: The following is wrong.  However, in practice, the sigma was too
     715            // large compared to the binSize.  This meant that the smoothing was done
     716            // over 500 bins in the robust stats algorithm.  This mean that the smoothing
     717            // took way too long.
     718            //
     719            gaussWidth = 10;
    710720            //
    711721            // We determine the bin numbers (jMin:jMax) corresponding to a
     
    735745    }
    736746
     747    psTrace(__func__, 3, "---- %s(psVector) end ----\n", __func__);
    737748    return(smooth);
    738749}
    739 /******************************************************************************
    740 p_psVectorSmoothHistGaussianNEW(): This routine smoothes the data in the input
    741 robustHistogram with a Gaussian of width sigma.  It returns a psVector of the
    742 smoothed data.
    743  
    744 XXX: Only PS_TYPE_F32 is supported.
    745  
    746 XXX: Write a general routine which smoothes a psVector.  This routine should
    747 call that.  Is that possible?
    748  
    749 XXX: This is, or will be, prettier than the previous
    750 psVectorSmoothHistGaussian().  However, it is not being used, yet.
    751  *****************************************************************************/
    752 psVector *p_psVectorSmoothHistGaussianNEW(psHistogram *histogram,
    753         psF32 sigma)
    754 {
    755     PS_ASSERT_PTR_NON_NULL(histogram, NULL);
    756     PS_ASSERT_PTR_NON_NULL(histogram->bounds, NULL);
    757     PS_ASSERT_PTR_NON_NULL(histogram->nums, NULL);
    758 
    759     psS32 numBins = histogram->nums->n;
    760     psS32 numBounds = histogram->bounds->n;
    761     psVector *smooth = psVectorAlloc(numBins, PS_TYPE_F32);
    762     psF32 firstBound = histogram->bounds->data.F32[0];
    763     psF32 lastBound = histogram->bounds->data.F32[numBounds-1];
    764     psScalar x;
    765     x.type.type = PS_TYPE_F32;
    766     psS32 jMin = 0;
    767     psS32 jMax = 0;
    768 
    769     if (histogram->uniform == false) {
    770         //
    771         // We get here if the histogram is non-uniform.
    772         //
    773 
    774         for (psS32 i = 0; i < numBins; i++) {
    775             // Determine the midpoint of bin i.
    776             psS32 iMid = PS_BIN_MIDPOINT(histogram, i);
    777 
    778             //
    779             // We determine the bin numbers (jMin:jMax) corresponding to a
    780             // range of data values surrounding iMid.  The range is of size:
    781             // 2*PS_GAUSS_WIDTH*sigma
    782             //
    783             x.data.F32 = iMid - (PS_GAUSS_WIDTH * sigma);
    784             if ((x.data.F32 >= firstBound) && (x.data.F32 <= lastBound)) {
    785                 jMin = p_psVectorBinDisect( *(psVector* *)&histogram->bounds, &x);
    786                 if (jMin < 0) {
    787                     psError(PS_ERR_UNEXPECTED_NULL,
    788                             false,
    789                             PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM);
    790                     return(NULL);
    791                 }
    792             } else if (x.data.F32 <= firstBound) {
    793                 jMin = 0;
    794             } else if (x.data.F32 >= lastBound) {
    795                 jMin = histogram->bounds->n - 1;
    796             }
    797 
    798             x.data.F32 = iMid + (PS_GAUSS_WIDTH * sigma);
    799             if ((x.data.F32 >= firstBound) && (x.data.F32 <= lastBound)) {
    800                 jMax = p_psVectorBinDisect( *(psVector* *)&histogram->bounds, &x);
    801                 if (jMax < 0) {
    802                     psError(PS_ERR_UNEXPECTED_NULL,
    803                             false,
    804                             PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM);
    805                     return(NULL);
    806                 }
    807             } else if (x.data.F32 <= firstBound) {
    808                 jMax = 0;
    809             } else if (x.data.F32 >= lastBound) {
    810                 jMax = histogram->bounds->n - 1;
    811             }
    812 
    813             //
    814             // Loop from jMin to jMax, computing the gaussian of data i.
    815             //
    816             smooth->data.F32[i] = 0.0;
    817             for (psS32 j = jMin ; j <= jMax ; j++) {
    818                 psS32 jMid = PS_BIN_MIDPOINT(histogram, j);
    819                 smooth->data.F32[i] +=
    820                     histogram->nums->data.F32[j] * psGaussian(jMid, iMid, sigma, true);
    821             }
    822         }
    823     } else {
    824         //
    825         // We get here if the histogram is uniform.
    826         //
    827 
    828         for (psS32 i = 0; i < numBins; i++) {
    829             psF32 binSize = histogram->bounds->data.F32[1] - histogram->bounds->data.F32[0];
    830             psS32 gaussWidth = (psS32) ((PS_GAUSS_WIDTH * sigma) / binSize);
    831 
    832             //
    833             // We determine the bin numbers (jMin:jMax) corresponding to a
    834             // range of data values surrounding iMid.  The range is of size:
    835             // 2*PS_GAUSS_WIDTH*sigma
    836             //
    837             psS32 jMin = i - gaussWidth;
    838             if (jMin < 0 ) {
    839                 jMin = 0;
    840             }
    841             psS32 jMax = i + gaussWidth;
    842             if (jMax > (histogram->bounds->n - 1)) {
    843                 jMax = (histogram->bounds->n - 1);
    844             }
    845 
    846             //
    847             // Loop from jMin to jMax, computing the gaussian of data i.
    848             //
    849             smooth->data.F32[i] = 0.0;
    850             psS32 iMid = PS_BIN_MIDPOINT(histogram, i);
    851             for (psS32 j = jMin ; j <= jMax ; j++) {
    852                 psS32 jMid = PS_BIN_MIDPOINT(histogram, j);
    853                 smooth->data.F32[i] +=
    854                     histogram->nums->data.F32[j] * psGaussian(jMid, iMid, sigma, true);
    855             }
    856         }
    857     }
    858 
    859     return(smooth);
    860 }
    861 
    862750/******************************************************************************
    863751p_psVectorSampleQuartiles(myVector, maskVector, maskVal, stats): calculates
     
    14351323    psF32 fHi = psPolynomial1DEval(myPoly, rangeHigh);
    14361324    if (!((fLo <= getThisValue) && (fHi >= getThisValue))) {
    1437         psError(PS_ERR_UNKNOWN,
    1438                 true,
    1439                 PS_ERRORTEXT_psStats_STATS_POLY_MEDIAN_OUT_OF_RANGE);
     1325        psError(PS_ERR_UNKNOWN, true, "The requested y value (%f) does not fall within the specified range (%f to %f)\n", getThisValue, fLo, fHi);
    14401326        return(NAN);
    14411327    }
     
    14911377                                        psF32 yVal)
    14921378{
     1379    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     1380    psTrace(__func__, 6, "binNum, yVal is (%d, %f)\n", binNum, yVal);
     1381    if (psTraceGetLevel(__func__) >= 8) {
     1382        PS_VECTOR_PRINT_F32(xVec);
     1383        PS_VECTOR_PRINT_F32(yVec);
     1384    }
     1385
    14931386    PS_ASSERT_VECTOR_NON_NULL(xVec, NAN);
    14941387    PS_ASSERT_VECTOR_NON_NULL(yVec, NAN);
     
    15021395    psVector *y = psVectorAlloc(3, PS_TYPE_F64);
    15031396    psVector *yErr = psVectorAlloc(3, PS_TYPE_F64);
    1504     // XXX: Why was this 2 when the alloc function specified number of terms?  Note: it's correct now.
    15051397    psPolynomial1D *myPoly = psPolynomial1DAlloc(2, PS_POLYNOMIAL_ORD);
    15061398
     
    15151407        y->data.F64[1] = yVec->data.F32[binNum];
    15161408        y->data.F64[2] = yVec->data.F32[binNum + 1];
     1409        psTrace(__func__, 6, "x vec (orig) is (%f %f %f %f)\n", xVec->data.F32[binNum - 1], xVec->data.F32[binNum], xVec->data.F32[binNum+1], xVec->data.F32[binNum+2]);
     1410        psTrace(__func__, 6, "x vec is (%f %f %f)\n", x->data.F64[0], x->data.F64[1], x->data.F64[2]);
     1411        psTrace(__func__, 6, "y vec is (%f %f %f)\n", y->data.F64[0], y->data.F64[1], y->data.F64[2]);
    15171412
    15181413        //
     
    15291424                psFree(y);
    15301425                psFree(yErr);
     1426                psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__);
    15311427                return(NAN);
    15321428            }
    1533         } else {
     1429            // Ensure that yVal is within the range of the bins we are using.
     1430            if (!((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2]))) {
     1431                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     1432                        PS_ERRORTEXT_psStats_YVAL_OUT_OF_RANGE,
     1433                        (psF64)yVal, y->data.F64[2], y->data.F64[0]);
     1434            }
     1435        } else if (y->data.F64[0] > y->data.F64[1]) {
    15341436            if (!(y->data.F64[1] >= y->data.F64[2])) {
    15351437                psError(PS_ERR_UNKNOWN, true, "This routine must be called with montically increasing or decreasing data points.\n");
     
    15381440                psFree(y);
    15391441                psFree(yErr);
     1442                psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__);
    15401443                return(NAN);
    15411444            }
    1542         }
    1543 
    1544         // Ensure that yVal is within the range of the bins we are using.
    1545         if (!((y->data.F64[0] <= yVal) && (yVal <= y->data.F64[2]))) {
    1546             psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    1547                     PS_ERRORTEXT_psStats_YVAL_OUT_OF_RANGE,
    1548                     (psF64)yVal,y->data.F64[2],y->data.F64[0]);
    1549         }
     1445            // Ensure that yVal is within the range of the bins we are using.
     1446            if (!((y->data.F64[2] <= yVal) && (yVal <= y->data.F64[0]))) {
     1447                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
     1448                        PS_ERRORTEXT_psStats_YVAL_OUT_OF_RANGE,
     1449                        (psF64)yVal, y->data.F64[2], y->data.F64[0]);
     1450            }
     1451        }
     1452
    15501453        yErr->data.F64[0] = 1.0;
    15511454        yErr->data.F64[1] = 1.0;
     
    15531456
    15541457        // Determine the coefficients of the polynomial.
     1458        //        myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
    15551459        myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, y, yErr, x);
    15561460        if (myPoly == NULL) {
     
    15621466            psFree(y);
    15631467            psFree(yErr);
     1468            psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__);
    15641469            return(NAN);
    15651470        }
     1471        psTrace(__func__, 6, "myPoly->coeff[0] is %f\n", myPoly->coeff[0]);
     1472        psTrace(__func__, 6, "myPoly->coeff[1] is %f\n", myPoly->coeff[1]);
     1473        psTrace(__func__, 6, "myPoly->coeff[2] is %f\n", myPoly->coeff[2]);
     1474        psTrace(__func__, 6, "Fitted y vec is (%.2f %.2f %.2f)\n", (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[0]),
     1475                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[1]),
     1476                (psF32) psPolynomial1DEval(myPoly, (psF64) x->data.F64[2]));
     1477
    15661478        // Call p_ps1DPolyMedian(), which does a binary search on the
    15671479        // polynomial, looking for the value x such that f(x) = yVal
     1480        psTrace(__func__, 6, "We fit the polynomial, now find x such that f(x) equals %f\n", yVal);
    15681481        tmpFloat = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], yVal);
     1482
    15691483        if (isnan(tmpFloat)) {
    15701484            psError(PS_ERR_UNEXPECTED_NULL,
     
    15751489            psFree(y);
    15761490            psFree(yErr);
     1491            psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__);
    15771492            return(NAN);
    15781493        }
     
    15961511    }
    15971512
     1513    psTrace(__func__, 6, "FIT: return %f\n", tmpFloat);
    15981514    psFree(myPoly);
    15991515    psFree(x);
    16001516    psFree(y);
    16011517    psFree(yErr);
     1518
     1519    psTrace(__func__, 3, "---- %s(%f) end ----\n", __func__, tmpFloat);
    16021520    return(tmpFloat);
    16031521}
     1522
     1523/*****************************************************************************
     1524XXX: Is there a psLib function for this?
     1525 *****************************************************************************/
     1526psVector *PsVectorDup(psVector *in)
     1527{
     1528    PS_ASSERT_VECTOR_NON_NULL(in, NULL);
     1529    psVector *out = psVectorAlloc(in->n, in->type.type);
     1530
     1531    if (in->type.type == PS_TYPE_F32) {
     1532        for (psS32 i = 0 ; i < in->n ; i++) {
     1533            out->data.F32[i] = in->data.F32[i];
     1534        }
     1535    } else if (in->type.type == PS_TYPE_F64) {
     1536        for (psS32 i = 0 ; i < in->n ; i++) {
     1537            out->data.F64[i] = in->data.F64[i];
     1538        }
     1539    } else {
     1540        psError(PS_ERR_UNKNOWN, true, "Unallowable vector type.\n");
     1541        return(NULL);
     1542    }
     1543    return(out);
     1544}
     1545
     1546/******************************************************************************
     1547XXX: This function need to be written.  Actually, it simply needs to be
     1548retrieved from the CVS repository, since it was written earlier, then
     1549discarded.  At present, it was deleted from the CVS repository, so we might
     1550have to retrieve it from tape.
     1551*****************************************************************************/
     1552psVector *Fit1DGaussian(psVector *x, psVector*y)
     1553{
     1554    psError(PS_ERR_UNKNOWN, true, "This code has not been implemented yet.\n");
     1555    // XXX: This function was previously part of psStats.c, was removed, was
     1556    // purged from CVS, and now needs to be retrieved from tape.
     1557
     1558    return(NULL);
     1559}
     1560
     1561
     1562
     1563/******************************************************************************
     1564XXX: We assume unnormalized gaussians.
     1565 *****************************************************************************/
     1566psF32 psMinimizeLMChi2Gauss1D(psVector *deriv,
     1567                              const psVector *params,
     1568                              const psVector *coords)
     1569{
     1570    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
     1571    PS_ASSERT_VECTOR_SIZE(params, 2, NAN);
     1572    PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, NAN);
     1573    PS_ASSERT_VECTOR_NON_NULL(coords, NAN);
     1574    PS_ASSERT_VECTOR_SIZE(coords, 1, NAN);
     1575    PS_ASSERT_VECTOR_TYPE(coords, PS_TYPE_F32, NAN);
     1576
     1577    psF32 x = coords->data.F32[0];
     1578    psF32 mean = params->data.F32[0];
     1579    psF32 stdev = params->data.F32[1];
     1580
     1581    if (deriv == NULL) {
     1582        deriv = psVectorAlloc(2, PS_TYPE_F32);
     1583    } else {
     1584        PS_ASSERT_VECTOR_SIZE(deriv, 2, NAN);
     1585        PS_ASSERT_VECTOR_TYPE(deriv, PS_TYPE_F32, NAN);
     1586    }
     1587
     1588    psF32 tmp = (x - mean) * psGaussian(x, mean, stdev, false);
     1589    deriv->data.F32[0] = tmp / (stdev * stdev);
     1590    tmp = (x - mean) * (x - mean) * psGaussian(x, mean, stdev, 0);
     1591    deriv->data.F32[1] = tmp / (stdev * stdev * stdev);
     1592
     1593    // printf("f(x, mean, stdev) = f(%.2f %.2f %.2f) is %.2f\n", x, mean, stdev, psGaussian(x, mean, stdev, false));
     1594
     1595    return(psGaussian(x, mean, stdev, false));
     1596}
     1597
     1598psF32 LinInterpolate(psF32 x0,
     1599                     psF32 x1,
     1600                     psF32 y0,
     1601                     psF32 y1,
     1602                     psF32 y)
     1603{
     1604    // printf("HEY: LinInterpolate(%.2f %.2f %.2f %.2f %.2f)\n", x0, x1, y0, y1, y);
     1605    if (y0 == y1) {
     1606        psLogMsg(__func__, PS_LOG_WARN, "WARNING: y0 == y1.  Cannot interpolate.  Returning NaN.\n");
     1607        return(NAN);
     1608    }
     1609    // printf("HMMM: LinInterpolate(%.2f %.2f %.2f %.2f %.2f %.2f)\n", x0, x1, y0, y1, y, 0 + y * (x1 - x0) / (y1 - y0));
     1610
     1611    return(x0 + y * (x1 - x0) / (y1 - y0));
     1612}
     1613
     1614void PRINT_LEAKS()
     1615{
     1616    psScalar *tmpScalar = psScalarAlloc(0.0, PS_TYPE_F32);
     1617    psMemCheckCorruption( 1 );
     1618    psS32 currentId = psMemGetId();
     1619    //    psMemBlock** blks;
     1620    //    psS32 nLeaks = psMemCheckLeaks( currentId, &blks, stderr, false );
     1621    psS32 nLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
     1622    printf("COOL: %d leaks.\n", nLeaks);
     1623    tmpScalar->data.F32 = 0.0;
     1624}
     1625
     1626/*
     1627#define PRINT_MEMLEAKS(NUM) \
     1628    printf("A: ---------------------------------------- (ID: %d)\n", NUM); \
     1629    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false); \
     1630    printf("B: ---------------------------------------- (%d)\n", memLeaks); \
     1631*/
     1632#define PRINT_MEMLEAKS(NUM) \
     1633memLeaks = currentId;
     1634
    16041635
    16051636/******************************************************************************
     
    16251656XXX: Check for errors in psLib routines that we call.
    16261657*****************************************************************************/
    1627 psS32 p_psVectorRobustStats(const psVector* myVector,
    1628                             const psVector* errors,
    1629                             const psVector* maskVector,
    1630                             psU32 maskVal,
    1631                             psStats* stats)
    1632 {
    1633     psHistogram* robustHistogram = NULL;
    1634     psVector* robustHistogramVector = NULL;
    1635     psF32 binSize = 0.0;        // Size of the histogram bins
    1636     psS32 LQBinNum = -1;          // Bin num for lower quartile
    1637     psS32 UQBinNum = -1;          // Bin num for upper quartile
    1638     psS32 medianBinNum = -1;
    1639     psS32 i = 0;                  // Loop index variable
    1640     psS32 modeBinNum = 0;
    1641     psF32 modeBinCount = 0.0;
    1642     psF32 dL = 0.0;
    1643     psS32 numBins = 0;
    1644     psF32 myMean = 0.0;
    1645     psF32 myStdev = 0.0;
    1646     psF32 countFloat = 0.0;
    1647     psF32 diff = 0.0;
    1648     psF32 sumSquares = 0.0;
    1649     psF32 sumDiffs = 0.0;
    1650     psVector* cumulativeRobustSums = NULL;
    1651     psF32 sumRobust = 0.0;
    1652     psF32 sumN50 = 0.0;
    1653     psF32 sumNfit = 0.0;
    1654     psScalar tmpScalar;
    1655     tmpScalar.type.type = PS_TYPE_F32;
    1656     psStats* tmpStats = psStatsAlloc(PS_STAT_CLIPPED_STDEV | PS_STAT_CLIPPED_MEAN);
    1657 
    1658     // Compute the initial bin size of the robust histogram.  This is done
    1659     // by computing the clipped standard deviation of the vector, and dividing
    1660     // that by 10.0;
    1661     //XXX: add errors
    1662     psS32 rc = p_psVectorClippedStats(myVector, NULL, maskVector, maskVal, tmpStats);
    1663     if (rc != 0) {
    1664         psError(PS_ERR_UNEXPECTED_NULL,
    1665                 false,
    1666                 PS_ERRORTEXT_psStats_ROBUST_STATS_CLIPPED_STATS);
    1667         return(1);
    1668     }
    1669     binSize = tmpStats->clippedStdev / 10.0f;
    1670 
    1671     // If stats->clippedStdev == 0.0, then all data elements have the same
    1672     // value.  Therefore, we can set the appropiate results and return.
    1673     if (fabs(binSize) <= FLT_EPSILON) {
    1674         if (stats->options & PS_STAT_ROBUST_MEAN) {
    1675             stats->robustMean = tmpStats->clippedMean;
    1676         }
    1677         if (stats->options & PS_STAT_ROBUST_MEDIAN) {
    1678             stats->robustMedian = tmpStats->clippedMean;
    1679         }
    1680         if (stats->options & PS_STAT_ROBUST_MODE) {
    1681             stats->robustMode = tmpStats->clippedMean;
    1682         }
    1683         if (stats->options & PS_STAT_ROBUST_STDEV) {
    1684             stats->robustStdev = 0.0;
    1685         }
    1686         if (stats->options & PS_STAT_ROBUST_QUARTILE) {
    1687             stats->robustUQ = tmpStats->clippedMean;
    1688             stats->robustLQ = tmpStats->clippedMean;
    1689         }
    1690         // XXX: Set these to the number of unmasked data points?
    1691         stats->robustNfit = 0.0;
    1692         stats->robustN50 = 0.0;
    1693         psFree(tmpStats);
    1694         return(0);
    1695     }
    1696 
    1697     // Determine minimum and maximum values in the data vector.
    1698     // XXX: remove this conditional?
    1699     if (isnan(tmpStats->min)) {
    1700         if (0 != p_psVectorMin(myVector, maskVector, maskVal, tmpStats)) {
    1701             psLogMsg(__func__, PS_LOG_WARN,
    1702                      "WARNING: p_psVectorMin(): p_psVectorMin() reported a NAN mean.\n");
    1703             return(1);
    1704         }
    1705     }
    1706     // XXX: remove this conditional?
    1707     if (isnan(tmpStats->max)) {
    1708         if (0 != p_psVectorMax(myVector, maskVector, maskVal, tmpStats)) {
    1709             psLogMsg(__func__, PS_LOG_WARN,
    1710                      "WARNING: p_psVectorMin(): p_psVectorMax() reported a NAN mean.\n");
    1711             return(1);
    1712         }
    1713     }
    1714 
    1715     // Create the histogram structure.  NOTE: we can not specify the bin size
    1716     // precisely since the argument to psHistogramAlloc() is the number of
    1717     // bins, not the binSize.  Also, if we get here, we know that
    1718     // binSize != 0.0.
    1719     numBins = (psS32)((tmpStats->max - tmpStats->min) / binSize);
    1720     robustHistogram = psHistogramAlloc(tmpStats->min, tmpStats->max, numBins);
    1721 
    1722     // Populate the histogram array.
    1723     psVectorHistogram(robustHistogram, myVector, errors, maskVector, maskVal);
    1724 
    1725     // Smooth the histogram, Gaussian-style.
    1726     robustHistogramVector = p_psVectorSmoothHistGaussian(robustHistogram,
    1727                             tmpStats->clippedStdev / 4.0f);
    1728 
    1729     /**************************************************************************
    1730     Determine the median/lower/upper quartile bin numbers.
    1731 
    1732     We define a vector called "cumulativeRobustSums" where the value at
    1733     index position i is equal to the sum of bins 0:i.  This will be used in
    1734     determining the median and lower/upper quartiles.
    1735     **************************************************************************/
    1736     cumulativeRobustSums = psVectorAlloc(robustHistogramVector->n, PS_TYPE_F32);
    1737     cumulativeRobustSums->data.F32[0] = robustHistogramVector->data.F32[0];
    1738     for (i = 1; i < robustHistogramVector->n; i++) {
    1739         cumulativeRobustSums->data.F32[i] = cumulativeRobustSums->data.F32[i - 1] +
    1740                                             robustHistogramVector->data.F32[i];
    1741     }
    1742     sumRobust = cumulativeRobustSums->data.F32[robustHistogramVector->n - 1];
    1743 
    1744     tmpScalar.data.F32 = sumRobust / 4.0;
    1745     LQBinNum = p_psVectorBinDisect(cumulativeRobustSums, &tmpScalar);
    1746     tmpScalar.data.F32 = 3.0 * sumRobust / 4.0;
    1747     UQBinNum = p_psVectorBinDisect(cumulativeRobustSums, &tmpScalar);
    1748     tmpScalar.data.F32 = sumRobust / 2.0;
    1749     medianBinNum = p_psVectorBinDisect(cumulativeRobustSums, &tmpScalar);
    1750 
    1751     if ((LQBinNum < 0) || (UQBinNum < 0)) {
    1752         psError(PS_ERR_UNKNOWN, true,
    1753                 PS_ERRORTEXT_psStats_ROBUST_QUARTILE_BINS_FAILED);
    1754         return(1);
    1755     }
    1756     if (medianBinNum < 0) {
    1757         psError(PS_ERR_UNKNOWN, true,
    1758                 PS_ERRORTEXT_psStats_ROBUST_QUARTILE_BINS_FAILED);
    1759         return(1);
    1760     }
    1761     /**************************************************************************
    1762     Determine the mode in the range LQ:UQ.
    1763     **************************************************************************/
    1764     // Determine the bin with the peak value in the range LQ to UQ.
    1765     modeBinNum = LQBinNum;
    1766     modeBinCount = robustHistogramVector->data.F32[LQBinNum];
    1767     sumN50 = robustHistogram->nums->data.F32[LQBinNum];
    1768     for (i = LQBinNum + 1; i <= UQBinNum; i++) {
    1769         if (robustHistogramVector->data.F32[i] > modeBinCount) {
    1770             modeBinNum = i;
    1771             modeBinCount = robustHistogramVector->data.F32[i];
    1772         }
    1773         sumN50 += robustHistogram->nums->data.F32[i];
    1774     }
    1775 
    1776     dL = (UQBinNum - LQBinNum) / 4;
    1777     /**************************************************************************
    1778     Determine the mean/stdev for the bins in the range mode-dL to mode+dL
    1779     **************************************************************************/
    1780     // Calculate the mean of the smoothed robust histogram in the range
    1781     // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
    1782     // that bin (this is a non-exact approximation).
    1783     sumNfit = 0.0;
    1784     myMean = 0.0;
    1785     for (i = modeBinNum - dL; i <= modeBinNum + dL; i++) {
    1786         if ((0 <= i) && (i < robustHistogramVector->n)) {
    1787             myMean += (robustHistogramVector->data.F32[i]) * PS_BIN_MIDPOINT(robustHistogram, i);
    1788             countFloat += robustHistogramVector->data.F32[i];
    1789         }
    1790 
    1791         sumNfit += robustHistogram->nums->data.F32[i];
    1792     }
    1793     // XXX: divide by zero?
    1794     myMean /= countFloat;
    1795 
    1796     // Calculate the stdev of the smoothed robust histogram in the range
    1797     // mode-dL to mode+dL.  We use the midpoint of each bin as the mean for
    1798     // that bin.
    1799     for (i = modeBinNum - dL; i <= modeBinNum + dL; i++) {
    1800         if ((0 <= i) && (i < robustHistogramVector->n)) {
    1801             diff = PS_BIN_MIDPOINT(robustHistogram, i) - myMean;
    1802             sumSquares += diff * diff * robustHistogramVector->data.F32[i];
    1803             sumDiffs += diff * robustHistogramVector->data.F32[i];
    1804         }
    1805     }
    1806     myStdev = sqrtf((sumSquares - (sumDiffs * sumDiffs / countFloat)) / (countFloat - 1));
    1807 
    1808     p_psNormalizeVectorRangeF32(robustHistogramVector, 0.0, 1.0);
    1809 
    1810     if ((stats->options & PS_STAT_ROBUST_MEAN) ||
    1811             (stats->options & PS_STAT_ROBUST_STDEV)) {
    1812         // We fit a 1-D polynomial to the data.
    1813         // XXX: I implement the changes requested in bug 366.  However, this
    1814         // code no longer produces sensible results.
    1815         // XXX: Since we are no longer fitting a 1-D Gaussian, we can probably
    1816         // remove some of the above code that calculated the initial estimate
    1817         // for the mean and sigma.
    1818 
    1819         psVector *y = psVectorAlloc(2 * dL + 1, PS_TYPE_F32);
    1820         psVector *x = psVectorAlloc(2 * dL + 1, PS_TYPE_F32);
    1821         for (i = modeBinNum - dL; i <= modeBinNum + dL; i++) {
    1822             int index = i - modeBinNum + dL;
    1823             // XXX: Should this be the natural log?
    1824             //            y->data.F32[index] = robustHistogramVector->data.F32[i];
    1825             y->data.F32[index] = logf(robustHistogramVector->data.F32[i]);
    1826             x->data.F32[index] = (psF32) index;
    1827         }
    1828 
    1829         psPolynomial1D *tmpPoly = psPolynomial1DAlloc(2, PS_POLYNOMIAL_ORD);
    1830         // XXX: What about the NULL x argument?
    1831         tmpPoly = psVectorFitPolynomial1D(tmpPoly, NULL, 0, y, NULL, NULL);
    1832         if (tmpPoly == NULL) {
    1833             psLogMsg(__func__, PS_LOG_WARN,
    1834                      "WARNING: failed fit a 1D polynomial.\n");
    1835         }
    1836         psF32 polyFitSigma = sqrtf(-0.5 / tmpPoly->coeff[2]);
    1837         psF32 polyFitMean = tmpPoly->coeff[1] * PS_SQR(polyFitSigma);
    1838         // psF32 polyFitNorm = exp(tmpPoly->coedd[0] + PS_SQR(polyFitMean) / (2.0 * PS_SQR(polyFitSigma)));
    1839 
    1840         if (stats->options & PS_STAT_ROBUST_MEAN) {
    1841             stats->robustMean = polyFitMean;
    1842         }
    1843 
    1844         if (stats->options & PS_STAT_ROBUST_STDEV) {
    1845             stats->robustStdev = polyFitSigma;
    1846         }
    1847         // For testing only.  This shows that the polynomial fit is successful.
    1848         if (0) {
    1849             printf("--- Results of the 1-D polynomial fit:\n");
    1850             for (i = modeBinNum - dL; i <= modeBinNum + dL; i++) {
    1851                 int index = i - modeBinNum + dL;
    1852                 printf("(x, y, poly(x)) is (%.2f, %.2f, %.2f)\n",
    1853                        x->data.F32[index],
    1854                        y->data.F32[index],
    1855                        psPolynomial1DEval(tmpPoly, x->data.F32[index]));
    1856             }
    1857         }
    1858 
    1859         psFree(x);
    1860         psFree(y);
    1861         psFree(tmpPoly);
    1862     }
    1863 
    1864 
    1865     /**************************************************************************
    1866     Set the appropriate members in the output stats struct.
    1867     **************************************************************************/
    1868 
    1869     if (stats->options & PS_STAT_ROBUST_MODE) {
    1870         stats->robustMode = PS_BIN_MIDPOINT(robustHistogram, modeBinNum);
    1871     }
    1872 
    1873 
    1874     // To determine the median, we fit a quadratic y=f(x) to the three bins
    1875     // surrounding the bin containing the median (x is the midpoint of each
    1876     // bin and y is the value of each bin).  Then we figure out what value
    1877     // of x corresponds to f(x) being the median (half of all points).
    1878     if (stats->options & PS_STAT_ROBUST_MEDIAN) {
    1879         // Take a psVector.  Fit a polynomial y = f(x) to the 3 data elements
    1880         // surrounding medianBinNum, then find the x-value corresponding y = sumRobust/2.0.
    1881 
    1882         //XXX: robustHistogram->bounds and cumulativeRobustSums are of different lengths.
    1883         //Determine id that is okay.
    1884         stats->robustMedian = fitQuadraticSearchForYThenReturnX(
    1885                                   *(psVector* *)&robustHistogram->bounds,
    1886                                   cumulativeRobustSums,
    1887                                   medianBinNum,
    1888                                   sumRobust/2.0);
    1889     }
    1890 
    1891     // To determine the quartiles, we fit a quadratic y=f(x) to the three bins
    1892     // surrounding the bin containing LQ/UQ (x is the midpoint of each
    1893     // bin and y is the value of each bin).  Then we figure out what value
    1894     // of x corresponds to f(x) being the LQ/UQ.
    1895     if (stats->options & PS_STAT_ROBUST_QUARTILE) {
    1896         countFloat = cumulativeRobustSums->data.F32[robustHistogramVector->n - 1];
    1897 
    1898         //XXX: robustHistogram->bounds and cumulativeRobustSums are of different lengths.
    1899         //Determine id that is okay.
    1900         stats->robustLQ = fitQuadraticSearchForYThenReturnX(
    1901                               *(psVector* *)&robustHistogram->bounds,
    1902                               cumulativeRobustSums,
    1903                               LQBinNum,
    1904                               countFloat/4.0);
    1905         //XXX: robustHistogram->bounds and cumulativeRobustSums are of different lengths.
    1906         //Determine id that is okay.
    1907         stats->robustUQ = fitQuadraticSearchForYThenReturnX(
    1908                               *(psVector* *)&robustHistogram->bounds,
    1909                               cumulativeRobustSums,
    1910                               UQBinNum,
    1911                               3.0 * countFloat/4.0);
    1912     }
    1913     // XXX: I think sumNfit == sumN50 here.
    1914     stats->robustNfit = sumNfit;
    1915     stats->robustN50 = sumN50;
    1916 
    1917     psFree(tmpStats);
    1918     psFree(robustHistogram);
    1919     psFree(robustHistogramVector);
    1920     psFree(cumulativeRobustSums);
    1921 
    1922     return(0);
    1923 }
    1924 
    1925 
    1926 /*****************************************************************************
    1927 XXX: Is there a psLib function for this?
    1928  *****************************************************************************/
    1929 psVector *PsVectorDup(psVector *in)
    1930 {
    1931     psVector *out = psVectorAlloc(in->n, in->type.type);
    1932 
    1933     if (in->type.type == PS_TYPE_F32) {
    1934         for (psS32 i = 0 ; i < in->n ; i++) {
    1935             out->data.F32[i] = in->data.F32[i];
    1936         }
    1937     } else if (in->type.type == PS_TYPE_F64) {
    1938         for (psS32 i = 0 ; i < in->n ; i++) {
    1939             out->data.F64[i] = in->data.F64[i];
    1940         }
    1941     } else {
    1942         psError(PS_ERR_UNKNOWN, true, "Unallowable vector type.\n");
    1943         return(NULL);
    1944     }
    1945     return(out);
    1946 }
    1947 
    1948 /******************************************************************************
    1949 XXX: This function need to be written.  Actually, it simply needs to be
    1950 retrieved from the CVS repository, since it was written earlier, then
    1951 discarded.  At present, it was deleted from the CVS repository, so we might
    1952 have to retrieve it from tape.
    1953 *****************************************************************************/
    1954 psVector *Fit1DGaussian(psVector *x, psVector*y)
    1955 {
    1956     psError(PS_ERR_UNKNOWN, true, "This code has not been implemented yet.\n");
    1957     // XXX: This function was previously part of psStats.c, was removed, was
    1958     // purged from CVS, and now needs to be retrieved from tape.
    1959 
    1960     return(NULL);
    1961 }
     1658
    19621659
    19631660/******************************************************************************
     
    19841681                               psStats* stats)
    19851682{
     1683    psTrace(__func__, 3, "---- %s() begin ----\n", __func__);
     1684    if (psTraceGetLevel(__func__) >= 8) {
     1685        PS_VECTOR_PRINT_F32(myVector);
     1686    }
     1687    //    psS32 currentId = psMemGetId();
     1688    //    psS32 memLeaks = 0;
    19861689    psHistogram *robustHistogram = NULL;
    19871690    psHistogram *cumulativeRobustHistogram = NULL;
     
    19911694    psS32 totalDataPoints = 0;
    19921695    psS32 rc = 0;
    1993     psVector *tmpMaskVec = PsVectorDup((psVector *) maskVector);
    1994 
    1995     while (1) {
     1696    psS32 rcBool = false;
     1697    psVector *tmpMaskVec = psVectorAlloc(myVector->n, PS_TYPE_U8);
     1698    if (maskVector != NULL) {
     1699        for (psS32 i = 0 ; i < myVector->n ; i++) {
     1700            tmpMaskVec->data.U8[i] = maskVector->data.U8[i];
     1701        }
     1702    } else {
     1703        for (psS32 i = 0 ; i < myVector->n ; i++) {
     1704            tmpMaskVec->data.U8[i] = 0;
     1705        }
     1706    }
     1707    psBool iterate = true;
     1708    psF32 sigma;
     1709    psStats *tmpStatsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX);
     1710
     1711    while (iterate) {
     1712        psTrace(__func__, 6, "Iterating on Bin size.\n");
    19961713        //
    19971714        // Determine the bin size of the robust histogram.  This is done
    19981715        // by computing the total range of data values and dividing by 1000.0.
    19991716        //
    2000         psStats* tmpStatsMinMax = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX);
    2001         rc = p_psVectorMin(myVector, tmpMaskVec, maskVal, tmpStatsMinMax);
    2002         rc|= p_psVectorMax(myVector, tmpMaskVec, maskVal, tmpStatsMinMax);
     1717        rc = p_psVectorMin(myVector, tmpMaskVec, 1, tmpStatsMinMax);
     1718        rc|= p_psVectorMax(myVector, tmpMaskVec, 1, tmpStatsMinMax);
    20031719        if ((rc != 0) || isnan(tmpStatsMinMax->min) || isnan(tmpStatsMinMax->max)) {
    20041720            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
     
    20061722            psFree(tmpMaskVec);
    20071723            psFree(tmpScalar);
     1724            psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
    20081725            return(1);
    20091726        }
     1727        psTrace(__func__, 6, "Data min/man is (%.2f, %.2f)\n", tmpStatsMinMax->min, tmpStatsMinMax->max);
    20101728        psF32 binSize = (tmpStatsMinMax->max - tmpStatsMinMax->min) / 1000.0f;
     1729        psTrace(__func__, 6, "Robust bin size is %.2f\n", binSize);
    20111730
    20121731        //
     
    20151734        //
    20161735        if (fabs(tmpStatsMinMax->max - tmpStatsMinMax->min) <= FLT_EPSILON) {
     1736            psTrace(__func__, 5, "All data points have the same value.\n", binSize);
    20171737            if (stats->options & PS_STAT_ROBUST_MEDIAN) {
    20181738                stats->robustMedian = tmpStatsMinMax->min;
     
    20291749            psFree(tmpScalar);
    20301750
     1751            psTrace(__func__, 3, "---- %s(0) end  ----\n", __func__);
    20311752            return(0);
    20321753        }
     
    20411762        //
    20421763        numBins = (psS32)((tmpStatsMinMax->max - tmpStatsMinMax->min) / binSize);
     1764        psTrace(__func__, 6, "Numbins is %d\n", numBins);
    20431765        robustHistogram = psHistogramAlloc(tmpStatsMinMax->min, tmpStatsMinMax->max, numBins);
    20441766        cumulativeRobustHistogram = psHistogramAlloc(tmpStatsMinMax->min, tmpStatsMinMax->max, numBins);
    20451767
    20461768        // Populate the histogram array.
    2047         psVectorHistogram(robustHistogram, myVector, errors, tmpMaskVec, maskVal);
    2048 
     1769        robustHistogram = psVectorHistogram(robustHistogram, myVector, errors, tmpMaskVec, maskVal);
     1770        if (psTraceGetLevel(__func__) >= 8) {
     1771            PS_VECTOR_PRINT_F32(robustHistogram->bounds);
     1772            PS_VECTOR_PRINT_F32(robustHistogram->nums);
     1773        }
    20491774        //
    20501775        // ADD: Step 1.
     
    20561781                    robustHistogram->nums->data.F32[i];
    20571782        }
     1783        if (psTraceGetLevel(__func__) >= 8) {
     1784            PS_VECTOR_PRINT_F32(cumulativeRobustHistogram->bounds);
     1785            PS_VECTOR_PRINT_F32(cumulativeRobustHistogram->nums);
     1786        }
    20581787
    20591788        //
     
    20621791        //
    20631792        totalDataPoints = cumulativeRobustHistogram->nums->data.F32[numBins - 1];
    2064         tmpScalar->data.F32 = totalDataPoints/2.0;
    2065         psS32 binMedian = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
    2066         if (binMedian != 0) {
    2067             psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 50% data point.\n");
    2068             psFree(tmpStatsMinMax);
    2069             psFree(robustHistogram);
    2070             psFree(cumulativeRobustHistogram);
    2071             psFree(tmpScalar);
    2072             return(1);
    2073         }
     1793        psTrace(__func__, 6, "Total data points is %d\n", totalDataPoints);
     1794        psS32 binMedian;
     1795        if (totalDataPoints/2.0 < cumulativeRobustHistogram->nums->data.F32[0]) {
     1796            // Special case: the median is in the first bin.  Perhaps we should recode this.
     1797            // XXX: Must try a special case where the median in in the last bin.
     1798            binMedian = 0;
     1799        } else {
     1800            tmpScalar->data.F32 = totalDataPoints/2.0;
     1801            binMedian = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1802            if (binMedian < 0) {
     1803                psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 50 precent data point (%d).\n", binMedian);
     1804                psFree(tmpStatsMinMax);
     1805                psFree(robustHistogram);
     1806                psFree(cumulativeRobustHistogram);
     1807                psFree(tmpScalar);
     1808                psFree(tmpMaskVec);
     1809                psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
     1810                return(1);
     1811            }
     1812        }
     1813        psTrace(__func__, 6, "The median bin is %d\n", binMedian);
    20741814
    20751815        //
     
    20791819        //
    20801820        stats->robustMedian = fitQuadraticSearchForYThenReturnX(
    2081                                   *(psVector* *)&robustHistogram->bounds,
    2082                                   *(psVector* *)&robustHistogram->nums,
     1821                                  *(psVector* *)&cumulativeRobustHistogram->bounds,
     1822                                  *(psVector* *)&cumulativeRobustHistogram->nums,
    20831823                                  binMedian,
    20841824                                  totalDataPoints/2.0);
     1825        psTrace(__func__, 6, "Current robust median is %f\n", stats->robustMedian);
    20851826
    20861827        //
     
    20881829        // Find the bins which contains the 15.8655% and 84.1345% data points.
    20891830        //
     1831        psS32 binLo = 0;
     1832        psS32 binHi = 0;
    20901833        tmpScalar->data.F32 = totalDataPoints * 0.158655f;
    2091         psS32 binLo = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1834        if (tmpScalar->data.F32 <= cumulativeRobustHistogram->nums->data.F32[0]) {
     1835            binLo = 0;
     1836        } else {
     1837            // NOTE: the (+1) here is because of the way p_psVectorBinDisect is defined.
     1838            binLo = 1 + p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1839            if (binLo > cumulativeRobustHistogram->nums->n-1) {
     1840                binLo = cumulativeRobustHistogram->nums->n-1;
     1841            }
     1842        }
    20921843        tmpScalar->data.F32 = totalDataPoints * 0.841345f;
    2093         psS32 binHi = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
    2094         if ((binLo != 0) || (binHi != 0)) {
    2095             psError(PS_ERR_UNKNOWN, false, "Failed to calculate the15.8655% and 84.1345% data point\n");
     1844        if (tmpScalar->data.F32 <= cumulativeRobustHistogram->nums->data.F32[0]) {
     1845            binHi = 0;
     1846        } else {
     1847            // NOTE: the (+1) here is because of the way p_psVectorBinDisect is defined.
     1848            binHi = 1+ p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1849            if (binHi > cumulativeRobustHistogram->nums->n-1) {
     1850                binHi = cumulativeRobustHistogram->nums->n-1;
     1851            }
     1852        }
     1853        psTrace(__func__, 6, "The 15.8655% and 84.1345% data point bins are (%d, %d).\n", binLo, binHi);
     1854        psTrace(__func__, 6, "binLo midpoint is %f\n", PS_BIN_MIDPOINT(cumulativeRobustHistogram, binLo));
     1855        psTrace(__func__, 6, "binHi midpoint is %f\n", PS_BIN_MIDPOINT(cumulativeRobustHistogram, binHi));
     1856
     1857        if ((binLo < 0) || (binHi < 0)) {
     1858            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 15.8655 and 84.1345 percent data point\n");
    20961859            psFree(tmpStatsMinMax);
    20971860            psFree(robustHistogram);
    20981861            psFree(cumulativeRobustHistogram);
    20991862            psFree(tmpScalar);
     1863            psFree(tmpMaskVec);
     1864            psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
    21001865            return(1);
    21011866        }
     
    21051870        // Interpolate Sigma to find these two positions exactly: these are the 1sigma positions.
    21061871        //
    2107         psF32 binLoF32 = fitQuadraticSearchForYThenReturnX(
    2108                              *(psVector* *)&robustHistogram->bounds,
    2109                              *(psVector* *)&robustHistogram->nums,
    2110                              binLo,
    2111                              totalDataPoints * 0.158655f);
    2112         psF32 binHiF32 = fitQuadraticSearchForYThenReturnX(
    2113                              *(psVector* *)&robustHistogram->bounds,
    2114                              *(psVector* *)&robustHistogram->nums,
    2115                              binHi,
    2116                              totalDataPoints * 0.841345f);
     1872        // XXX: I am overriding the ADD for now.  The following code implements
     1873        // the ADD exactly and is having problems fitting a 2nd-order polynomial
     1874        // to data y-values suchs as (1, 1, 100).  Therefore, I commented out the
     1875        // code and am doing simply linear interpolation.
     1876        //
     1877        psF32 binLoF32;
     1878        psF32 binHiF32;
     1879        if (0) {
     1880            binLoF32 = fitQuadraticSearchForYThenReturnX(
     1881                           *(psVector* *)&cumulativeRobustHistogram->bounds,
     1882                           *(psVector* *)&cumulativeRobustHistogram->nums,
     1883                           binLo,
     1884                           totalDataPoints * 0.158655f);
     1885            binHiF32 = fitQuadraticSearchForYThenReturnX(
     1886                           *(psVector* *)&cumulativeRobustHistogram->bounds,
     1887                           *(psVector* *)&cumulativeRobustHistogram->nums,
     1888                           binHi,
     1889                           totalDataPoints * 0.841345f);
     1890            psTrace(__func__, 6, "The exact 15.8655 and 84.1345 percent data point positions are: (%f, %f)\n", binLoF32, binHiF32);
     1891        }
     1892
     1893        if (1) {
     1894            psTrace(__func__, 6, "binLo is %d.  Nums at that bin and the next are (%.2f, %.2f)\n", binLo, cumulativeRobustHistogram->nums->data.F32[binLo], cumulativeRobustHistogram->nums->data.F32[binLo+1]);
     1895            psTrace(__func__, 6, "binHi is %d.  Nums at that bin and the next are (%.2f, %.2f)\n", binHi, cumulativeRobustHistogram->nums->data.F32[binHi], cumulativeRobustHistogram->nums->data.F32[binHi+1]);
     1896            // XXX: Add checks to ensure that these bins are not the first (seg fault).
     1897            binLoF32 = LinInterpolate(
     1898                           cumulativeRobustHistogram->bounds->data.F32[binLo],
     1899                           cumulativeRobustHistogram->bounds->data.F32[binLo+1],
     1900                           cumulativeRobustHistogram->nums->data.F32[binLo-1],
     1901                           cumulativeRobustHistogram->nums->data.F32[binLo],
     1902                           totalDataPoints * 0.158655f);
     1903            binHiF32 = LinInterpolate(
     1904                           cumulativeRobustHistogram->bounds->data.F32[binHi],
     1905                           cumulativeRobustHistogram->bounds->data.F32[binHi+1],
     1906                           cumulativeRobustHistogram->nums->data.F32[binHi-1],
     1907                           cumulativeRobustHistogram->nums->data.F32[binHi],
     1908                           totalDataPoints * 0.841345f);
     1909            // XXX: Check for NANs
     1910            psTrace(__func__, 6, "The exact 15.8655 and 84.1345 percent data point positions are: (%f, %f)\n", binLoF32, binHiF32);
     1911        }
    21171912
    21181913        //
     
    21201915        // Determine SIGMA as 1/2 of the distance between these positions.
    21211916        //
    2122         psF32 sigma = (binHiF32 - binLoF32) / 2.0;
     1917        sigma = (binHiF32 - binLoF32) / 2.0;
     1918        psTrace(__func__, 6, "The current sigma is %f.\n", sigma);
    21231919
    21241920        //
     
    21291925        //
    21301926        if (sigma < (2 * binSize)) {
     1927            psTrace(__func__, 6, "*************: Do another iteration (%f %f).\n", sigma, binSize);
    21311928            psF32 medianLo = robustHistogram->bounds->data.F32[binMedian - 25];
    21321929            psF32 medianHi = robustHistogram->bounds->data.F32[binMedian + 25];
     1930            psTrace(__func__, 6, "Masking data outside (%f %f)\n", medianLo, medianHi);
    21331931            for (psS32 i = 0 ; i < myVector->n ; i++) {
    21341932                if ((myVector->data.F32[i] < medianLo) ||
    21351933                        (myVector->data.F32[i] > medianHi)) {
    21361934                    tmpMaskVec->data.U8[i] = 1;
    2137                 }
    2138             }
    2139         } else {
    2140             //
    2141             // ADD: Step 7.
    2142             // Find the bins which contains the 25% and 75% data points.
    2143             //
    2144             tmpScalar->data.F32 = totalDataPoints * 0.25f;
    2145             psS32 binLo25 = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
    2146             tmpScalar->data.F32 = totalDataPoints * 0.75f;
    2147             psS32 binHi25 = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
    2148             if ((binLo25 != 0) || (binHi25 != 0)) {
    2149                 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 25% and 75% data points\n");
    2150                 psFree(tmpStatsMinMax);
    2151                 psFree(robustHistogram);
    2152                 psFree(cumulativeRobustHistogram);
    2153                 psFree(tmpScalar);
    2154                 return(1);
    2155             }
    2156 
    2157             //
    2158             // ADD: Step 8.
    2159             // Interpolate to find these two positions exactly: these are the upper
    2160             // and lower quartile positions.
    2161             // XXX: Check for errors.
    2162             //
    2163             psF32 binLo25F32 = fitQuadraticSearchForYThenReturnX(
    2164                                    *(psVector* *)&robustHistogram->bounds,
    2165                                    *(psVector* *)&robustHistogram->nums,
    2166                                    binLo25,
    2167                                    totalDataPoints * 0.25f);
    2168             psF32 binHi25F32 = fitQuadraticSearchForYThenReturnX(
    2169                                    *(psVector* *)&robustHistogram->bounds,
    2170                                    *(psVector* *)&robustHistogram->nums,
    2171                                    binHi25,
    2172                                    totalDataPoints * 0.75f);
    2173 
    2174             stats->robustLQ = binLo25F32;
    2175             stats->robustUQ = binHi25F32;
    2176 
    2177             // PS_BIN_MIDPOINT(robustHistogram, modeBinNum);
    2178             // XXX: I think sumNfit == sumN50 here.
    2179             stats->robustNfit = -1;
    2180             stats->robustN50 = -1;
    2181 
    2182             //
    2183             // Perform the Robust Histogram Statistics algorithm above
    2184             //
    2185 
    2186             //
    2187             // Smooth the resulting histogram with a Gaussian with SIGMA_s = 1
    2188             // bin.
    2189             //
    2190             // XXX: SIGMA_s is defined nowhere in the ADD.
    2191             //
    2192             psF32 SIGMA_S = 1.0;
    2193             p_psVectorSmoothHistGaussian(robustHistogram, SIGMA_S);
    2194 
    2195             //
    2196             // Find the bin with the peak value in the range 2 SIGMA of the
    2197             // robust histogram median.
    2198             //
    2199             // XXX: SIGMA is defined nowhere in the ADD.
    2200             //
    2201             psF32 SIGMA = 2.0;
    2202             psS32 binMin = binMedian - (SIGMA * PS_GAUSS_WIDTH);
    2203             if (binMin < 0) {
    2204                 binMin = 0;
    2205             }
    2206             psS32 binMax = binMedian + (2 * PS_GAUSS_WIDTH);
    2207             if (binMin > (robustHistogram->nums->n - 1)) {
    2208                 binMin = (robustHistogram->nums->n - 1);
    2209             }
    2210             psS32 binNum = binNum;
    2211             psF32 binMaxNums = robustHistogram->nums->data.F32[binNum];
    2212             for (psS32 i = binNum+1 ; i <= binMax ; i++) {
    2213                 if (robustHistogram->nums->data.F32[i] > binMaxNums) {
    2214                     binNum = i;
    2215                     binMaxNums = robustHistogram->nums->data.F32[i];
    2216                 }
    2217             }
    2218 
    2219             //
    2220             // Fit a Gaussian to the bins in the range 2 SIGMA of the robust
    2221             // histogram median.
    2222             //
    2223             // XXX: SIGMA is defined nowhere in the ADD.
    2224             //
    2225             psVector *y = psVectorAlloc((1 + (binMax - binMin)), PS_TYPE_F32);
    2226             psVector *x = psVectorAlloc((1 + (binMax - binMin)), PS_TYPE_F32);
    2227             psS32 j = 0;
    2228             for (psS32 i = binNum ; i <= binMax ; i++) {
    2229                 y->data.F32[j] = robustHistogram->nums->data.F32[i];
    2230                 x->data.F32[j] = PS_BIN_MIDPOINT(robustHistogram, i);
    2231             }
    2232             //
    2233             // XXX: This function need to be written.  Actually, it simply
    2234             // needs to be retrieved from the CVS repository, since it was
    2235             // written earlier, then discarded.  At present, it was deleted
    2236             // from the CVS repository, so we might have to retrieve it from
    2237             // tape.
    2238             //
    2239             psVector *params = Fit1DGaussian(x, y);
    2240 
    2241             //
    2242             // The robust mean mean_r is derived directly from the fitted
    2243             // Gaussian mean.
    2244             //
    2245             stats->robustMean = params->data.F32[0];
    2246 
    2247             //
    2248             // The robust standard deviation, SIGMA_r is determined by
    2249             // subtracting the smoothing scale in quadrature: SIGMA_r^2 = SIGMA^2
    2250             // - SIGMA_s^2
    2251             //
    2252             // XXX: SIGMA and SIGMA_s are defined nowhere in the ADD.  We must figure
    2253             // out what they are.
    2254             //
    2255             stats->robustStdev = sqrt(PS_SQR(SIGMA) - PS_SQR(SIGMA_S));
    2256 
    2257             psFree(tmpStatsMinMax);
     1935                    psTrace(__func__, 6, "Masking element %d is %f\n", i, myVector->data.F32[i]);
     1936                }
     1937            }
    22581938            psFree(robustHistogram);
    22591939            psFree(cumulativeRobustHistogram);
    2260             psFree(tmpScalar);
    2261             psFree(params);
    2262 
    2263             return(0);
    2264         }
    2265 
     1940
     1941        } else {
     1942            psTrace(__func__, 6, "*************: No more iteration.  sigma is %f\n", sigma);
     1943            iterate = false;
     1944        }
     1945    }
     1946
     1947    //
     1948    // ADD: Step 7.
     1949    // Find the bins which contains the 25% and 75% data points.
     1950    //
     1951    psS32 binLo25 = 0;
     1952    psS32 binHi25 = 0;
     1953
     1954    tmpScalar->data.F32 = totalDataPoints * 0.25f;
     1955    if (tmpScalar->data.F32 <= cumulativeRobustHistogram->nums->data.F32[0]) {
     1956        // XXX: Special case where its in first bin.  Must code last bin.
     1957        binLo25 = 0;
     1958    } else {
     1959        binLo25 = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1960    }
     1961    tmpScalar->data.F32 = totalDataPoints * 0.75f;
     1962    if (tmpScalar->data.F32 <= cumulativeRobustHistogram->nums->data.F32[0]) {
     1963        // XXX: Special case where its in first bin.  Must code last bin.
     1964        binHi25 = 0;
     1965    } else {
     1966        binHi25 = p_psVectorBinDisect(cumulativeRobustHistogram->nums, tmpScalar);
     1967    }
     1968    if ((binLo25 < 0) || (binHi25 < 0)) {
     1969        psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 25 and 75 percent data points\n");
    22661970        psFree(tmpStatsMinMax);
    22671971        psFree(robustHistogram);
    22681972        psFree(cumulativeRobustHistogram);
    2269     }
    2270     return(1);
     1973        psFree(tmpScalar);
     1974        psFree(tmpMaskVec);
     1975        psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
     1976        return(1);
     1977    }
     1978    psTrace(__func__, 6, "The 25% and 75% data point bins are (%d, %d).\n", binLo25, binHi25);
     1979
     1980    //
     1981    // ADD: Step 8.
     1982    // Interpolate to find these two positions exactly: these are the upper
     1983    // and lower quartile positions.
     1984    // XXX: Check for errors.
     1985    //
     1986    psF32 binLo25F32 = fitQuadraticSearchForYThenReturnX(
     1987                           *(psVector* *)&cumulativeRobustHistogram->bounds,
     1988                           *(psVector* *)&cumulativeRobustHistogram->nums,
     1989                           binLo25,
     1990                           totalDataPoints * 0.25f);
     1991    psF32 binHi25F32 = fitQuadraticSearchForYThenReturnX(
     1992                           *(psVector* *)&cumulativeRobustHistogram->bounds,
     1993                           *(psVector* *)&cumulativeRobustHistogram->nums,
     1994                           binHi25,
     1995                           totalDataPoints * 0.75f);
     1996    stats->robustLQ = binLo25F32;
     1997    stats->robustUQ = binHi25F32;
     1998    psTrace(__func__, 6, "The 25 and 75 percent data point exact positions are (%f, %f).\n", binLo25F32, binHi25F32);
     1999
     2000    //
     2001    //
     2002    // New algorithm for calculated mean and stdev.
     2003    //
     2004    //
     2005    psS32 N50 = 0;
     2006    for (psS32 i = 0 ; i < myVector->n ; i++) {
     2007        if ((0 == tmpMaskVec->data.U8[i]) &&
     2008                (binLo25F32 <= myVector->data.F32[i]) &&
     2009                (binHi25F32 >= myVector->data.F32[i])) {
     2010            N50++;
     2011        }
     2012    }
     2013    stats->robustN50 = N50;
     2014    psTrace(__func__, 6, "The robustN50 is %d.\n", N50);
     2015
     2016    psF32 dN = (psF32) (0.17 * N50);
     2017    if (dN < 1.0) {
     2018        dN = 1.0;
     2019    } else if (dN > 4.0) {
     2020        dN = 4.0;
     2021    }
     2022    psF32 newBinSize = sigma / dN;
     2023
     2024    rc = p_psVectorMin(myVector, tmpMaskVec, 1 | maskVal, tmpStatsMinMax);
     2025    rc|= p_psVectorMax(myVector, tmpMaskVec, 1 | maskVal, tmpStatsMinMax);
     2026    if ((rc != 0) || isnan(tmpStatsMinMax->min) || isnan(tmpStatsMinMax->max)) {
     2027        psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
     2028        psFree(tmpStatsMinMax);
     2029        psFree(robustHistogram);
     2030        psFree(cumulativeRobustHistogram);
     2031        psFree(tmpScalar);
     2032        psFree(tmpMaskVec);
     2033        psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
     2034        return(1);
     2035    }
     2036
     2037    numBins = (psS32)((tmpStatsMinMax->max - tmpStatsMinMax->min) / newBinSize);
     2038    psTrace(__func__, 6, "The new min/max values are (%f, %f).\n", tmpStatsMinMax->min, tmpStatsMinMax->max);
     2039    psTrace(__func__, 6, "The new bin size is %f.\n", newBinSize);
     2040    psTrace(__func__, 6, "The numBins is %d\n", numBins);
     2041
     2042    psHistogram *newHistogram = psHistogramAlloc(tmpStatsMinMax->min, tmpStatsMinMax->max, numBins);
     2043    newHistogram = psVectorHistogram(newHistogram, myVector, errors, tmpMaskVec, maskVal|1);
     2044    if (psTraceGetLevel(__func__) >= 8) {
     2045        PS_VECTOR_PRINT_F32(newHistogram->nums);
     2046    }
     2047
     2048    //
     2049    // Smooth the resulting histogram with a Gaussian with sigma_s = 1
     2050    // bin.
     2051    //
     2052    psF32 sigma_s = newBinSize;
     2053
     2054    psVector *newHistogramSmoothed = p_psVectorSmoothHistGaussian(newHistogram, sigma_s);
     2055    if (psTraceGetLevel(__func__) >= 8) {
     2056        PS_VECTOR_PRINT_F32(newHistogramSmoothed);
     2057    }
     2058
     2059    //
     2060    // Find the bin with the peak value in the range 2 sigma of the
     2061    // robust histogram median.
     2062    //
     2063
     2064    psS32 binMin = 0;
     2065    psS32 binMax = 0;
     2066    tmpScalar->data.F32 = stats->robustMedian - (2.0 * sigma);
     2067    if (tmpScalar->data.F32 <= newHistogram->bounds->data.F32[0]) {
     2068        binMin = 0;
     2069    } else {
     2070        binMin = p_psVectorBinDisect((psVector *) newHistogram->bounds, tmpScalar);
     2071    }
     2072
     2073    tmpScalar->data.F32 = stats->robustMedian + (2.0 + sigma);
     2074    if (tmpScalar->data.F32 >= newHistogram->bounds->data.F32[newHistogram->bounds->n-1]) {
     2075        binMax = newHistogram->bounds->n-1;
     2076    } else {
     2077        binMax = p_psVectorBinDisect((psVector *) newHistogram->bounds, tmpScalar);
     2078    }
     2079    if ((binMin < 0) || (binMax < 0)) {
     2080        psError(PS_ERR_UNKNOWN, false, "Failed to calculate the +- 2.0 * sigma bins\n");
     2081        psFree(tmpMaskVec);
     2082        psFree(robustHistogram);
     2083        psFree(cumulativeRobustHistogram);
     2084        psFree(tmpStatsMinMax);
     2085        psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
     2086        return(1);
     2087    }
     2088
     2089    psS32 binNum = binMin;
     2090    psF32 binMaxNums = newHistogramSmoothed->data.F32[binNum];
     2091    for (psS32 i = binMin+1 ; i <= binMax ; i++) {
     2092        if (newHistogramSmoothed->data.F32[i] > binMaxNums) {
     2093            binNum = i;
     2094            binMaxNums = newHistogramSmoothed->data.F32[i];
     2095        }
     2096    }
     2097    psTrace(__func__, 6, "The peak bin is %d, with %f data.n", binNum, binMaxNums);
     2098
     2099    //
     2100    // Fit a Gaussian to the bins in the range 20 sigma of the robust
     2101    // histogram median.
     2102    //
     2103    tmpScalar->data.F32 = stats->robustMedian - (20.0 * sigma);
     2104    if (tmpScalar->data.F32 < tmpStatsMinMax->min) {
     2105        binMin = 0;
     2106    } else {
     2107        binMin = p_psVectorBinDisect((psVector *) newHistogram->bounds, tmpScalar);
     2108        // XXX: check for errors here.
     2109    }
     2110    tmpScalar->data.F32 = stats->robustMedian + (20.0 * sigma);
     2111    if (tmpScalar->data.F32 > tmpStatsMinMax->max) {
     2112        binMax = newHistogramSmoothed->n - 1;
     2113    } else {
     2114        binMax = p_psVectorBinDisect((psVector *) newHistogram->bounds, tmpScalar);
     2115        // XXX: check for errors here.
     2116    }
     2117    psVector *y = psVectorAlloc((1 + (binMax - binMin)), PS_TYPE_F32);
     2118    psVector *xTmp = psVectorAlloc((1 + (binMax - binMin)), PS_TYPE_F32);
     2119    psArray *x = psArrayAlloc((1 + (binMax - binMin)));
     2120    stats->robustNfit = 0;
     2121    psS32 j = 0;
     2122
     2123    for (psS32 i = binMin ; i <= binMax ; i++) {
     2124        y->data.F32[j] = newHistogramSmoothed->data.F32[i];
     2125        x->data[j] = (psPtr *) psVectorAlloc(1, PS_TYPE_F32);
     2126        ((psVector *) x->data[j])->data.F32[0] = PS_BIN_MIDPOINT(newHistogram, i);
     2127        xTmp->data.F32[j] = PS_BIN_MIDPOINT(newHistogram, i);
     2128
     2129        stats->robustNfit+= newHistogramSmoothed->data.F32[i];
     2130        j++;
     2131    }
     2132    if (psTraceGetLevel(__func__) >= 8) {
     2133        // XXX: Print the x array somehow.
     2134        PS_VECTOR_PRINT_F32(y);
     2135    }
     2136
     2137    // XXX: Use the min/max routines for this
     2138    psF32 minY = FLT_MAX;
     2139    psF32 maxY = -FLT_MAX;
     2140    for (psS32 i = 0 ; i < 1 + (binMax - binMin) ; i++) {
     2141        if (y->data.F32[i] > maxY) {
     2142            maxY = y->data.F32[i];
     2143        }
     2144        if (y->data.F32[i] < minY) {
     2145            minY = y->data.F32[i];
     2146        }
     2147    }
     2148    //
     2149    // Normalize y to [0.0:1.0] (since the psMinimizeLMChi2Gauss1D() functions is [0.0:1.0])
     2150    // XXX: Use the normalize routines for this.
     2151    //
     2152    for (psS32 i = 0 ; i < 1 + (binMax - binMin) ; i++) {
     2153        y->data.F32[i]= (y->data.F32[i] - minY) / (maxY - minY);
     2154    }
     2155
     2156    //
     2157    psMinimization *min = psMinimizationAlloc(100, 0.01);
     2158    psVector *params = psVectorAlloc(2, PS_TYPE_F32);
     2159    // Initial guess for the mean ([0]) and standard dev.
     2160    params->data.F32[0] = stats->robustMedian;
     2161    params->data.F32[1] = sigma;
     2162    if (psTraceGetLevel(__func__) >= 8) {
     2163        PS_VECTOR_PRINT_F32(params);
     2164        PS_VECTOR_PRINT_F32(y);
     2165    }
     2166    psFree(xTmp);
     2167    rcBool = psMinimizeLMChi2(min, NULL, params, NULL, x, y, NULL, psMinimizeLMChi2Gauss1D);
     2168
     2169    if (rcBool != true) {
     2170        psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
     2171        psFree(tmpStatsMinMax);
     2172        psFree(robustHistogram);
     2173        psFree(cumulativeRobustHistogram);
     2174        psFree(tmpScalar);
     2175        psFree(newHistogram);
     2176        psFree(x);
     2177        psFree(y);
     2178        psFree(min);
     2179        psFree(params);
     2180        psFree(tmpMaskVec);
     2181        psTrace(__func__, 3, "---- %s(1) end  ----\n", __func__);
     2182        return(1);
     2183    }
     2184    if (psTraceGetLevel(__func__) >= 8) {
     2185        PS_VECTOR_PRINT_F32(params);
     2186    }
     2187
     2188    //
     2189    // The robust mean mean_r is derived directly from the fitted
     2190    // Gaussian mean.
     2191    //
     2192    stats->robustMean = params->data.F32[0];
     2193    psTrace(__func__, 6, "The robust mean is %f.\n", params->data.F32[0]);
     2194
     2195    //
     2196    // The robust standard deviation, SIGMA_r is determined by
     2197    // subtracting the smoothing scale in quadrature:
     2198    //     SIGMA_r^2 = SIGMA^2 - sigma_s^2
     2199    //
     2200    stats->robustStdev = sqrt(PS_SQR(params->data.F32[1]) - PS_SQR(sigma_s));
     2201    psTrace(__func__, 6, "The robust stdev is %f.\n", stats->robustStdev);
     2202
     2203    psFree(newHistogramSmoothed);
     2204    psFree(tmpStatsMinMax);
     2205    psFree(cumulativeRobustHistogram);
     2206    psFree(tmpScalar);
     2207    psFree(newHistogram);
     2208    psFree(x);
     2209    psFree(y);
     2210    psFree(min);
     2211    psFree(params);
     2212    psFree(tmpMaskVec);
     2213    psFree(robustHistogram);
     2214
     2215    psTrace(__func__, 3, "---- %s(0) end  ----\n", __func__);
     2216    return(0);
    22712217}
    22722218
     
    28082754    // Since the various robust stats quantities share much computation, they
    28092755    // are grouped together in a single private function:
    2810     // p_psVectorRobustStats()
     2756    // p_psVectorRobustStatsNew()
    28112757    if ((stats->options & PS_STAT_ROBUST_MEAN) ||
    28122758            (stats->options & PS_STAT_ROBUST_MEDIAN) ||
     
    28142760            (stats->options & PS_STAT_ROBUST_STDEV) ||
    28152761            (stats->options & PS_STAT_ROBUST_QUARTILE)) {
    2816         if (0 != p_psVectorRobustStats(inF32, errorsF32, mask, maskVal, stats)) {
     2762        if (0 != p_psVectorRobustStatsNew(inF32, errorsF32, mask, maskVal, stats)) {
    28172763            psError(PS_ERR_UNKNOWN, false,
    28182764                    PS_ERRORTEXT_psStats_STATS_FAILED);
    28192765            // XXX: Set to NAN
     2766            // XXX: Is this the right thing to do?
     2767            // XXX: If so, do it for other funcs?
     2768            psFree(stats);
     2769            return(NULL);
    28202770        }
    28212771    }
  • trunk/psLib/test/math/tst_psStats07.c

    r4861 r5113  
    3434    float realMeanNoMask = MEAN;
    3535    float realMedianNoMask = MEAN;
    36     float realModeNoMask = MEAN;
    37     float realStdevNoMask = STDEV * 0.20;
     36    //    float realModeNoMask = MEAN;
     37    float realStdevNoMask = STDEV;
    3838    float realLQNoMask = MEAN - ( 0.6 * STDEV );
    3939    float realUQNoMask = MEAN + ( 0.6 * STDEV );
    4040    psS32 realN50NoMask = N / 4;
    4141    psS32 realNfitNoMask = N / 4;
    42 
    43     psTraceSetLevel(".psLib.dataManip", 0);
    4442
    4543    /*************************************************************************/
     
    5553    maskVector->n = N;
    5654    myVector = p_psGaussianDev( MEAN, STDEV, N );
     55    // Create a full outliers:
     56    myVector->data.F32[N/4] = -1000.0 * MEAN;
     57    myVector->data.F32[N/2] = 1000.0 * MEAN;
    5758    // Set the mask vector and calculate the expected maximum.
    5859    for ( i = 0;i < N;i++ ) {
     
    7273
    7374    myStats = psVectorStats( myStats, myVector, NULL, NULL, 0 );
     75    if (myStats == NULL) {
     76        printf("TEST ERROR: psVectorStats() returned NULL.\n");
     77        return(false);
     78    }
    7479
    7580    printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n",
     
    105110                 testStatus );
    106111
    107     printPositiveTestHeader( stdout,
    108                              "psStats functions",
    109                              "PS_STAT_ROBUST_STATS: robust Mode: no vector mask" );
    110 
    111 
    112     printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
    113             realModeNoMask, myStats->robustMode );
    114     if ( fabs( myStats->robustMode - realModeNoMask ) < ( ERROR_TOLERANCE * realModeNoMask ) ) {
    115         testStatus = true;
    116     } else {
    117         testStatus = false;
    118         globalTestStatus = false;
    119     }
    120     printFooter( stdout,
    121                  "psVector functions",
    122                  "PS_STAT_ROBUST_STATS: robust Mode: no vector mask",
    123                  testStatus );
    124 
    125 
     112    /* XXX: Should we test mode?
     113        printPositiveTestHeader( stdout,
     114                                 "psStats functions",
     115                                 "PS_STAT_ROBUST_STATS: robust Mode: no vector mask" );
     116     
     117     
     118        printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
     119                realModeNoMask, myStats->robustMode );
     120        if ( fabs( myStats->robustMode - realModeNoMask ) < ( ERROR_TOLERANCE * realModeNoMask ) ) {
     121            testStatus = true;
     122        } else {
     123            testStatus = false;
     124            globalTestStatus = false;
     125        }
     126        printFooter( stdout,
     127                     "psVector functions",
     128                     "PS_STAT_ROBUST_STATS: robust Mode: no vector mask",
     129                     testStatus );
     130    */
    126131
    127132    printPositiveTestHeader( stdout,
     
    143148
    144149
    145 
    146150    printPositiveTestHeader( stdout,
    147151                             "psStats functions",
     
    161165                 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask",
    162166                 testStatus );
    163 
    164 
    165167
    166168    printPositiveTestHeader( stdout,
     
    180182                 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask",
    181183                 testStatus );
    182 
    183 
    184184
    185185    printPositiveTestHeader( stdout,
     
    205205                 testStatus );
    206206
    207 
    208 
    209207    printPositiveTestHeader( stdout,
    210208                             "psStats functions",
     
    228226                 "PS_STAT_ROBUST_STATS: robust Nfit: no vector mask",
    229227                 testStatus );
    230     return(testStatus);
    231228
    232229    /*************************************************************************/
     
    252249                 testStatus );
    253250
    254     if (globalTestStatus == false)
    255         printf("Returning FALSE\n");
    256     else
    257         printf("Returning TRUE\n");
    258     return ( !globalTestStatus );
     251    return ( globalTestStatus );
    259252}
    260253
     
    276269    float realMeanWithMask = MEAN;
    277270    float realMedianWithMask = MEAN;
    278     float realModeWithMask = MEAN;
    279     float realStdevWithMask = STDEV * 0.20;
     271    //    float realModeWithMask = MEAN;
     272    float realStdevWithMask = STDEV;
    280273    float realLQWithMask = MEAN;
    281274    float realUQWithMask = MEAN;
    282275    psS32 realN50WithMask = N / 4;
    283276    psS32 realNfitWithMask = N / 4;
    284 
    285     psTraceSetLevel(".psLib.dataManip.psStats", 0);
    286 
    287277    /*************************************************************************/
    288278    /*  Allocate and initialize data structures                              */
     
    316306    printf( "Calling psVectorStats() on a vector with elements masked.\n" );
    317307    myStats = psVectorStats( myStats, myVector, NULL, maskVector, 1 );
     308    if (myStats == NULL) {
     309        printf("TEST ERROR: psVectorStats() returned NULL.\n");
     310        return(false);
     311    }
    318312    printf( "Called psVectorStats() on a vector with elements masked.\n" );
    319313    printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n",
     
    348342
    349343
    350 
    351     printPositiveTestHeader( stdout,
    352                              "psStats functions",
    353                              "PS_STAT_ROBUST_STATS: robust Mode: with vector mask" );
    354 
    355     printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
    356             realModeWithMask, myStats->robustMode );
    357     if ( fabs( myStats->robustMode - realModeWithMask ) < ( ERROR_TOLERANCE * realModeWithMask ) ) {
    358         testStatus = true;
    359     } else {
    360         testStatus = false;
    361         globalTestStatus = false;
    362     }
    363     printFooter( stdout,
    364                  "psVector functions",
    365                  "PS_STAT_ROBUST_STATS: robust Mode: with vector mask",
    366                  testStatus );
    367 
     344    /* XXX: mode is not set?
     345        printPositiveTestHeader( stdout,
     346                                 "psStats functions",
     347                                 "PS_STAT_ROBUST_STATS: robust Mode: with vector mask" );
     348     
     349        printf( "The expected Mode was %.2f; the calculated Mode was %.2f\n",
     350                realModeWithMask, myStats->robustMode );
     351        if ( fabs( myStats->robustMode - realModeWithMask ) < ( ERROR_TOLERANCE * realModeWithMask ) ) {
     352            testStatus = true;
     353        } else {
     354            testStatus = false;
     355            globalTestStatus = false;
     356        }
     357        printFooter( stdout,
     358                     "psVector functions",
     359                     "PS_STAT_ROBUST_STATS: robust Mode: with vector mask",
     360                     testStatus );
     361    */
    368362
    369363
     
    489483                 testStatus );
    490484
    491     if (globalTestStatus == false)
    492         printf("Returning FALSE\n");
    493     else
    494         printf("Returning TRUE\n");
    495 
    496     return ( !globalTestStatus );
     485    return ( globalTestStatus );
    497486}
    498487
     
    500489{
    501490    psLogSetFormat("HLNM");
    502     psBool rc = t00();
    503     rc |= t01();
    504 
    505     return(rc);
     491    psTraceSetLevel(".", 0);
     492    psTraceSetLevel("psGaussian", 0);
     493    psBool rc0 = t00();
     494    psBool rc1 = t01();
     495
     496    return(rc0 & rc1);
    506497}
Note: See TracChangeset for help on using the changeset viewer.