Index: trunk/psLib/src/math/psStats.c
===================================================================
--- trunk/psLib/src/math/psStats.c	(revision 23416)
+++ trunk/psLib/src/math/psStats.c	(revision 23988)
@@ -24,6 +24,13 @@
 // unity, even though the standard deviation is not defined in that case (NAN).
 
+// reworking the return values and failure conditions: it should only be an error if the
+// inputs imply a programming error: eg, NULL data vectors, non-sensical input
+// parameters.  If the statistic cannot be calculated (0 length vector, 0 range, no
+// unmasked data values), the statistic should be reported as NAN, but an error should not
+// be raised.  (TBD: do we need to have a unique field in psStats or a return parameter
+// that can be checked for an invalid result?)
+
 #ifdef HAVE_CONFIG_H
-# include "config.h"
+#include "config.h"
 #endif
 
@@ -42,5 +49,4 @@
 #include "psMemory.h"
 #include "psAbort.h"
-//#include "psImage.h"
 #include "psVector.h"
 #include "psTrace.h"
@@ -69,4 +75,6 @@
 #define PS_POLY_MEDIAN_MAX_ITERATIONS 30
 
+#define TRACE "psLib.math"
+
 #define MASK_MARK 0x80   // XXX : can we change this? bit to use internally to mark data as bad
 #define PS_ROBUST_MAX_ITERATIONS 20     // Maximum number of iterations for robust statistics
@@ -87,5 +95,5 @@
             break; \
           case PS_BINARY_DISECT_OUTSIDE_RANGE: \
-            psTrace ("psLib.math", 6, "selected bin outside range"); \
+            psTrace(TRACE, 6, "selected bin outside range"); \
             if (USE_END == -1) { RESULT = 0; } \
             if (USE_END == +1) { RESULT = VECTOR->n - 1; } \
@@ -116,9 +124,7 @@
         } \
         Xt = PS_MIN (BOUNDS->data.F32[BIN+1], PS_MAX(BOUNDS->data.F32[BIN], Xt)); \
-        psTrace("psLib.math", 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \
+        psTrace(TRACE, 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \
                 Xo, Yo, dX, dY, Xt, VALUE); \
         RESULT = Xt; }
-
-#define TRACE "psLib.math"
 
 /*****************************************************************************/
@@ -182,6 +188,4 @@
                                  psStats* stats)
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
-
     long count = 0;                     // Number of points contributing to this mean
     psF32 mean = 0.0;                   // The mean
@@ -222,12 +226,8 @@
     }
     stats->sampleMean = mean;
-    if (isnan(mean)) {
-        // XXX raise an error here?
-        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
-        return true;
-    }
-
-    stats->results |= PS_STAT_SAMPLE_MEAN;
-    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
+
+    if (!isnan(mean)) {
+	stats->results |= PS_STAT_SAMPLE_MEAN;
+    }
     return true;
 }
@@ -252,5 +252,4 @@
         )
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
     psF32 max = -PS_MAX_F32;            // The calculated maximum
     psF32 min = PS_MAX_F32;             // The calculated minimum
@@ -289,5 +288,4 @@
         stats->results |= PS_STAT_MAX;
     }
-    psTrace(TRACE, 4, "---- %s(%d) end ----\n", __func__, numValid);
     return numValid;
 }
@@ -303,6 +301,4 @@
                                psStats* stats)
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
-
     bool useRange = stats->options & PS_STAT_USE_RANGE;
     psVectorMaskType *maskData = (maskVector == NULL) ? NULL : maskVector->data.PS_TYPE_VECTOR_MASK_DATA; // Dereference the vector
@@ -334,5 +330,5 @@
 
     if (count == 0) {
-        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "No valid data in input vector.\n");
+        psLogMsg(TRACE, PS_LOG_DETAIL, "No valid data in input vector.\n");
         stats->sampleUQ = NAN;
         stats->sampleLQ = NAN;
@@ -343,4 +339,5 @@
     // Sort the temporary vector.
     if (!psVectorSort(outVector, outVector)) { // Sort in-place (since it's a copy, it's OK)
+	// an error in psVectorSort is a serious error
         psError(PS_ERR_UNEXPECTED_NULL, false, _("Failed to sort input data."));
         stats->sampleUQ = NAN;
@@ -364,6 +361,4 @@
     stats->results |= PS_STAT_SAMPLE_QUARTILE;
 
-    // Return "true" on success.
-    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
     return true;
 }
@@ -390,6 +385,4 @@
                               psStats* stats)
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
-
     // This procedure requires the mean.  If it has not been already
     // calculated, then call vectorSampleMean()
@@ -400,6 +393,5 @@
     // If the mean is NAN, then generate a warning and set the stdev to NAN.
     if (isnan(stats->sampleMean)) {
-        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): sample mean is NAN.  "
-                "Setting stats->sampleStdev = NAN.\n");
+        psLogMsg(TRACE, PS_LOG_DETAIL, "WARNING: vectorSampleStdev(): sample mean is NAN. Setting stats->sampleStdev = NAN.\n");
         stats->sampleStdev = NAN;
         return true;
@@ -445,11 +437,10 @@
         // Assume that the user knows what he's doing when he masks out everything --> no error.
         stats->sampleStdev = NAN;
-        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): no valid psVector elements (%ld).  "
-                "Setting stats->sampleStdev = NAN.\n", count);
+        psLogMsg(TRACE, PS_LOG_DETAIL, "WARNING: vectorSampleStdev(): no valid psVector elements (%ld). Setting stats->sampleStdev = NAN.\n", count);
         return true;
     }
     if (count == 1) {
         stats->sampleStdev = 0.0;
-        psTrace(TRACE, 5, "WARNING: vectorSampleStdev(): only one valid psVector elements (%ld).  "
+        psLogMsg(TRACE, PS_LOG_DETAIL, "WARNING: vectorSampleStdev(): only one valid psVector elements (%ld).  "
                 "Setting stats->sampleStdev = 0.0.\n", count);
         return true;
@@ -462,6 +453,4 @@
     }
     stats->results |= PS_STAT_SAMPLE_STDEV;
-
-    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
 
     return true;
@@ -473,6 +462,4 @@
                                 psStats* stats)
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
-
     // This procedure requires the mean and standard deviation
     if (!(stats->results & PS_STAT_SAMPLE_MEAN)) {
@@ -480,5 +467,5 @@
     }
     if (isnan(stats->sampleMean)) {
-        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample mean is NAN.\n");
+        psLogMsg(TRACE, PS_LOG_DETAIL, "WARNING: vectorSampleMoments(): sample mean is NAN.\n");
         goto SAMPLE_MOMENTS_BAD;
     }
@@ -487,5 +474,5 @@
     }
     if (isnan(stats->sampleStdev) || stats->sampleStdev == 0.0) {
-        psTrace(TRACE, 5, "WARNING: vectorSampleMoments(): sample stdev is NAN or 0.\n");
+        psLogMsg(TRACE, PS_LOG_DETAIL, "WARNING: vectorSampleMoments(): sample stdev is NAN or 0.\n");
         goto SAMPLE_MOMENTS_BAD;
     }
@@ -534,6 +521,4 @@
     stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
 
-    psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
-
     return true;
 
@@ -542,5 +527,4 @@
     stats->sampleSkewness = NAN;
     stats->sampleKurtosis = NAN;
-    stats->results |= PS_STAT_SAMPLE_SKEWNESS | PS_STAT_SAMPLE_KURTOSIS;
     return true;
 }
@@ -565,7 +549,4 @@
     )
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
-    psTrace(TRACE, 4, "Trace level is %d\n", psTraceGetLevel("psLib.math"));
-
     // Ensure that stats->clipIter is within the proper range.
     PS_ASSERT_INT_WITHIN_RANGE(stats->clipIter,
@@ -601,7 +582,6 @@
     vectorSampleMedian(myVector, tmpMask, maskVal, stats);
     if (isnan(stats->sampleMedian)) {
-        psTrace(TRACE, 5, "Call to vectorSampleMedian returned NAN\n");
-        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
-        return false;
+        psLogMsg(TRACE, PS_LOG_DETAIL, "Call to vectorSampleMedian returned NAN\n");
+        return true;
     }
     psTrace(TRACE, 6, "The initial sample median is %f\n", stats->sampleMedian);
@@ -610,7 +590,6 @@
     vectorSampleStdev(myVector, errors, tmpMask, maskVal, stats);
     if (isnan(stats->sampleStdev)) {
-        psTrace(TRACE, 5, "Call to vectorSampleStdev returned NAN\n");
-        psTrace(TRACE, 4, "---- %s(false) end ----\n", __func__);
-        return false;
+        psLogMsg(TRACE, PS_LOG_DETAIL, "Call to vectorSampleStdev returned NAN\n");
+        return true;
     }
     psTrace(TRACE, 6, "The initial sample stdev is %f\n", stats->sampleStdev);
@@ -669,6 +648,8 @@
         if (isnan(stats->sampleMean) || isnan(stats->sampleStdev)) {
             iter = stats->clipIter;
-            psError(PS_ERR_UNKNOWN, true, "vectorSampleMean() or vectorSampleStdev() returned a NAN.\n");
-            return false;
+            psLogMsg(TRACE, PS_LOG_DETAIL, "vectorSampleMean() or vectorSampleStdev() returned a NAN.\n");
+            clippedMean = NAN;
+            clippedStdev = NAN;
+            return true;
         } else {
             clippedMean = stats->sampleMean;
@@ -693,5 +674,4 @@
     psTrace(TRACE, 6, "The final clipped stdev is %f\n", clippedStdev);
 
-    psTrace(TRACE, 4, "---- %s(true) end ----\n", __func__);
     return true;
 }
@@ -722,5 +702,4 @@
                               psStats* stats)
 {
-    psTrace(TRACE, 4, "---- %s() begin ----\n", __func__);
     if (psTraceGetLevel("psLib.math") >= 8) {
         PS_VECTOR_PRINT_F32(myVector);
@@ -767,5 +746,5 @@
         if (numValid == 0 || isnan(min) || isnan(max)) {
             // Data range calculation failed
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             goto escape;
         }
@@ -779,9 +758,9 @@
             stats->robustLQ = min;
             stats->robustN50 = numValid;
+	    // XXX this is sort of an invalid / out-of-bounds result: to set or not to set these bits:
             stats->results |= PS_STAT_ROBUST_MEDIAN;
             stats->results |= PS_STAT_ROBUST_STDEV;
             stats->results |= PS_STAT_ROBUST_QUARTILE;
-            psTrace(TRACE, 5, "All data points have the same value: %f.\n", min);
-            psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
+            psLogMsg(TRACE, PS_LOG_DETAIL, "All data points have the same value: %f.\n", min);
             psFree(mask);
             psFree(statsMinMax);
@@ -809,6 +788,12 @@
         // XXXXX we need to consider this step if errors -> variance
         if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+	    // if psVectorHistogram returns false, we have a programming error
             psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for robust statistics.\n");
-            goto escape;
+	    psFree(histogram);
+	    psFree(cumulative);
+	    psFree(statsMinMax);
+	    psFree(mask);
+
+	    return false;
         }
         if (psTraceGetLevel("psLib.math") >= 8) {
@@ -843,6 +828,5 @@
         stats->robustMedian = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binMedian, totalDataPoints/2.0);
         if (isnan(stats->robustMedian)) {
-            psError(PS_ERR_UNKNOWN, false,
-                    "Failed to fit a quadratic and calculate the 50-percent position.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to fit a quadratic and calculate the 50-percent position.\n");
             goto escape;
         }
@@ -866,5 +850,5 @@
 
         if ((binLo < 0) || (binHi < 0)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the 15.8655%% and 84.1345%% data points.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the 15.8655%% and 84.1345%% data points.\n");
             goto escape;
         }
@@ -962,9 +946,8 @@
                 stats->results |= PS_STAT_ROBUST_STDEV;
                 stats->results |= PS_STAT_ROBUST_QUARTILE;
-                psTrace(TRACE, 5, "Maximum number of iterations (%d) exceeded.", PS_ROBUST_MAX_ITERATIONS);
-                psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
+                psLogMsg(TRACE, PS_LOG_DETAIL, "Maximum number of iterations (%d) exceeded.", PS_ROBUST_MAX_ITERATIONS);
                 psFree(mask);
                 psFree(statsMinMax);
-                return false;
+                return true;
             }
         } else {
@@ -991,6 +974,5 @@
     psF32 binHi25F32 = fitQuadraticSearchForYThenReturnXusingValues(cumulative->bounds, cumulative->nums, binHi25, totalDataPoints * 0.75f);
     if (isnan(binLo25F32) || isnan(binHi25F32)) {
-        psError(PS_ERR_UNKNOWN, false,
-                "could not determine the robustUQ: fitQuadraticSearchForYThenReturnX() returned a NAN.\n");
+        psLogMsg(TRACE, PS_LOG_DETAIL, "could not determine the robustUQ: fitQuadraticSearchForYThenReturnX() returned a NAN.\n");
         goto escape;
     }
@@ -1020,5 +1002,4 @@
     stats->results |= PS_STAT_ROBUST_QUARTILE;
 
-    psTrace(TRACE, 4, "---- %s(0) end  ----\n", __func__);
     return true;
 
@@ -1033,6 +1014,4 @@
     stats->results |= PS_STAT_ROBUST_QUARTILE;
 
-    psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-
     psFree(histogram);
     psFree(cumulative);
@@ -1040,5 +1019,5 @@
     psFree(mask);
 
-    return false;
+    return true;
 }
 
@@ -1057,5 +1036,8 @@
     // calculated, then call vectorSampleMean()
     if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
-        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+        if (!vectorRobustStats(myVector, errors, mask, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "failure to measure robust stats\n");
+	    return false;
+	}
     }
 
@@ -1064,6 +1046,5 @@
         stats->fittedStdev = NAN;
         stats->fittedStdev = NAN;
-        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
-        return false;
+        return true;
     }
 
@@ -1096,8 +1077,7 @@
         float max = statsMinMax->max;
         if (numValid == 0 || isnan(min) || isnan(max)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psTrace(TRACE, 5, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
-            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+            return true;
         }
 
@@ -1111,4 +1091,5 @@
         psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
         if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
+	    // if psVectorHistogram returns false, we have a programming error
             psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistics.\n");
             psFree(histogram);
@@ -1175,4 +1156,6 @@
             PS_VECTOR_PRINT_F32(y);
         }
+	
+	// psMinimizeLMChi2 can return false for bad data as well as for serious failures
         if (!psMinimizeLMChi2(minimizer, NULL, params, NULL, x, y, NULL, minimizeLMChi2Gauss1D)) {
             psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
@@ -1183,6 +1166,5 @@
             psFree(histogram);
             psFree(statsMinMax);
-            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+            return true;
         }
         if (psTraceGetLevel("psLib.math") >= 8) {
@@ -1235,5 +1217,8 @@
     // calculated, then call vectorSampleMean()
     if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
-        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+        if (!vectorRobustStats(myVector, errors, mask, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "failure to measure robust stats\n");
+	    return false;
+	}
     }
 
@@ -1243,5 +1228,5 @@
         stats->fittedStdev = NAN;
         psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
-        return false;
+        return true;
     }
 
@@ -1274,8 +1259,8 @@
         float max = statsMinMax->max;
         if (numValid == 0 || isnan(min) || isnan(max)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
             psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+            return true;
         }
 
@@ -1354,4 +1339,5 @@
         // psVectorInit (fitMask, 0);
 
+	// XXX not sure if these should result in errors or not...
         if (!psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x)) {
             psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
@@ -1366,6 +1352,5 @@
 
         if (poly->coeff[2] >= 0.0) {
-            psTrace(TRACE, 6, "Parabolic fit results: %f + %f x + %f x^2\n",
-                    poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+            psTrace(TRACE, 6, "Parabolic fit results: %f + %f x + %f x^2\n", poly->coeff[0], poly->coeff[1], poly->coeff[2]);
             psError(PS_ERR_UNKNOWN, false, "fit did not converge\n");
             psFree(x);
@@ -1429,5 +1414,8 @@
     // calculated, then call vectorSampleMean()
     if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
-        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+        if (!vectorRobustStats(myVector, errors, mask, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "failure to measure robust stats\n");
+	    return false;
+	}
     }
 
@@ -1437,5 +1425,5 @@
         stats->fittedStdev = NAN;
         psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
-        return false;
+        return true;
     }
 
@@ -1468,8 +1456,8 @@
         float max = statsMinMax->max;
         if (numValid == 0 || isnan(min) || isnan(max)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
             psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+            return true;
         }
 
@@ -1516,8 +1504,7 @@
         PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
         if (binMin == binMax) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
-            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+            return true;
         }
 
@@ -1724,5 +1711,8 @@
     // calculated, then call vectorSampleMean()
     if (!(stats->results & PS_STAT_ROBUST_MEDIAN)) {
-        vectorRobustStats(myVector, errors, mask, maskVal, stats);
+        if (!vectorRobustStats(myVector, errors, mask, maskVal, stats)) {
+            psError(PS_ERR_UNKNOWN, false, "failure to measure robust stats\n");
+	    return false;
+	}
     }
 
@@ -1731,6 +1721,5 @@
         stats->fittedStdev = NAN;
         stats->fittedStdev = NAN;
-        psTrace(TRACE, 4, "---- %s() end ----\n", __func__);
-        return false;
+        return true;
     }
 
@@ -1763,8 +1752,9 @@
         float max = statsMinMax->max;
         if (numValid == 0 || isnan(min) || isnan(max)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
-            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+	    stats->fittedStdev = NAN;
+	    stats->fittedStdev = NAN;
+            return true;
         }
 
@@ -1780,8 +1770,10 @@
         psHistogram *histogram = psHistogramAlloc(min, max, numBins); // A new histogram (without outliers)
         if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for fitted statistics v4.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Unable to generate histogram for fitted statistics v4.\n");
             psFree(histogram);
             psFree(statsMinMax);
-            return false;
+	    stats->fittedStdev = NAN;
+	    stats->fittedStdev = NAN;
+            return true;
         }
         if (psTraceGetLevel("psLib.math") >= 8) {
@@ -1813,8 +1805,9 @@
         PS_BIN_FOR_VALUE (binMax, histogram->bounds, guessMean + maxFitSigma*guessStdev, 0);
         if (binMin == binMax) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n");
+            psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to calculate the min/max of the input vector.\n");
             psFree(statsMinMax);
-            psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-            return false;
+	    stats->fittedStdev = NAN;
+	    stats->fittedStdev = NAN;
+            return true;
         }
 
@@ -1877,4 +1870,6 @@
 
             // fit 2nd order polynomial to ln(y) = -(x-xo)^2/2sigma^2
+	    // XXX this fit may fail with an error for an ill-conditioned matrix (bad data)
+	    // we probably should be able to handle the data errors gracefully
             psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, 2);
             bool status = psVectorFitPolynomial1D (poly, NULL, 0, y, NULL, x);
@@ -1883,15 +1878,15 @@
 
             if (!status) {
-                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to fit a gaussian to the robust histogram.\n");
                 psFree(poly);
                 psFree(histogram);
                 psFree(statsMinMax);
-                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-                return false;
+		stats->fittedStdev = NAN;
+		stats->fittedStdev = NAN;
+                return true;
             }
 
             if (poly->coeff[2] >= 0.0) {
-                psTrace(TRACE, 6, "Failed parabolic fit: %f + %f x + %f x^2\n",
-                        poly->coeff[0], poly->coeff[1], poly->coeff[2]);
+                psLogMsg(TRACE, PS_LOG_MINUTIA, "Failed parabolic fit: %f + %f x + %f x^2\n", poly->coeff[0], poly->coeff[1], poly->coeff[2]);
                 psFree(poly);
                 psFree(histogram);
@@ -1907,7 +1902,8 @@
                 }
 
-                psError(PS_ERR_UNKNOWN, false, "fit did not converge\n");
-                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-                return false;
+                psLogMsg(TRACE, PS_LOG_DETAIL, "fit did not converge\n");
+		stats->fittedStdev = NAN;
+		stats->fittedStdev = NAN;
+                return true;
             }
 
@@ -1975,10 +1971,11 @@
 
             if (!status) {
-                psError(PS_ERR_UNKNOWN, false, "Failed to fit a gaussian to the robust histogram.\n");
+                psLogMsg(TRACE, PS_LOG_DETAIL, "Failed to fit a gaussian to the robust histogram.\n");
                 psFree(poly);
                 psFree(histogram);
                 psFree(statsMinMax);
-                psTrace(TRACE, 4, "---- %s(false) end  ----\n", __func__);
-                return false;
+		stats->fittedStdev = NAN;
+		stats->fittedStdev = NAN;
+                return true;
             }
 
@@ -2155,6 +2152,4 @@
 psStats* p_psStatsAlloc(const char *file, unsigned int lineno, const char *func, psStatsOptions options)
 {
-    psTrace(TRACE, 3,"---- %s() begin  ----\n", __func__);
-
     psStats *stats = p_psAlloc(file, lineno, func, sizeof(psStats));
     psMemSetDeallocator(stats, (psFreeFunc)statsFree);
@@ -2172,5 +2167,4 @@
     stats->tmpMask = NULL;
 
-    psTrace(TRACE, 3, "---- %s() end  ----\n", __func__);
     return stats;
 }
@@ -2231,5 +2225,4 @@
                    psVectorMaskType maskVal)
 {
-    psTrace(TRACE, 3,"---- %s() begin  ----\n", __func__);
     PS_ASSERT_PTR_NON_NULL(stats, false);
     PS_ASSERT_VECTOR_NON_NULL(in, false);
@@ -2380,5 +2373,4 @@
     psFree(errorsF32);
     psFree(maskVector);
-    psTrace(TRACE, 3,"---- %s() end  ----\n", __func__);
     return status;
 }
