Changeset 5113
- Timestamp:
- Sep 23, 2005, 1:01:30 PM (21 years ago)
- Location:
- trunk/psLib
- Files:
-
- 4 edited
-
src/math/psMinimize.c (modified) (6 diffs)
-
src/math/psPolynomial.c (modified) (3 diffs)
-
src/math/psStats.c (modified) (32 diffs)
-
test/math/tst_psStats07.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimize.c
r5090 r5113 10 10 * @author EAM, IfA 11 11 * 12 * @version $Revision: 1.1 39$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-09-2 2 02:47:16$12 * @version $Revision: 1.140 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-09-23 23:01:30 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 204 204 # ifndef PS_NO_TRACE 205 205 // 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 */ 215 217 # endif /* PS_NO_TRACE */ 216 218 … … 226 228 # ifndef PS_NO_TRACE 227 229 // 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 */ 237 241 # endif /* PS_NO_TRACE */ 238 242 … … 249 253 # ifndef PS_NO_TRACE 250 254 // 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 */ 256 262 # endif /* PS_NO_TRACE */ 257 263 … … 271 277 // printf("CONDITIONS: (%f > %f) && (%d < %d)\n", min->lastDelta, min->tol, min->iter, min->maxIter); 272 278 } 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); 274 280 275 281 // construct & return the covariance matrix (if requested) … … 1579 1585 1580 1586 if (psTraceGetLevel (".psLib.dataManip.VectorFitPolynomial1DOrd") >= 5) { 1581 FILE *fp = fdopen((psTraceGetDestination ()), "a+"); 1582 fprintf(fp, "VectorFitPolynomial1D()\n"); 1587 psTrace(__func__, 6, "VectorFitPolynomial1D()\n"); 1583 1588 for (int i = 0; i < f->n; i++) { 1584 fprintf(fp, "(x, f, fErr) is (");1589 psTrace(__func__, 6, "(x, f, fErr) is ("); 1585 1590 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]); 1587 1592 } else { 1588 fprintf(fp, "%f, %f, ", (psF64) i, f->data.F64[i]);1593 psTrace(__func__, 6, "%f, %f, ", (psF64) i, f->data.F64[i]); 1589 1594 } 1590 1595 if (fErr != NULL) { 1591 fprintf(fp, "%f)\n", fErr->data.F64[i]);1596 psTrace(__func__, 6, "%f)\n", fErr->data.F64[i]); 1592 1597 } else { 1593 fprintf(fp, "NULL)\n"); 1594 } 1595 } 1596 fclose(fp); 1598 psTrace(__func__, 6, "NULL)\n"); 1599 } 1600 } 1597 1601 } 1598 1602 -
trunk/psLib/src/math/psPolynomial.c
r5096 r5113 7 7 * polynomials. It also contains a Gaussian functions. 8 8 * 9 * @version $Revision: 1.12 7$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-09-2 2 22:49:29$9 * @version $Revision: 1.128 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-09-23 23:01:30 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 572 572 psF32 tmp = 1.0; 573 573 574 psTrace(".psLib.dataManip.psPolynomial.psGaussian", 4, 575 "---- psGaussian() begin ----\n"); 574 psTrace(__func__, 4, "---- %s() begin ----\n", __func__); 576 575 577 576 if (normal == true) { … … 579 578 } 580 579 581 psTrace(".psLib.dataManip.psPolynomial.psGaussian", 4, 582 "---- psGaussian() end ----\n"); 580 psTrace(__func__, 4, "---- %s() end ----\n", __func__); 583 581 return(tmp * exp(-((x - mean) * (x - mean)) / (2.0 * sigma * sigma))); 584 582 } -
trunk/psLib/src/math/psStats.c
r5090 r5113 7 7 * on those data structures. 8 8 * 9 * @author GLG, MHPCC10 *11 * XXX: The following stats members are never used, or set in this code.12 * stats->robustN5013 * stats->clippedNvalues14 * stats->binsize15 *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 Hawaii23 */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 */ 24 24 25 25 #include <stdlib.h> … … 631 631 psF32 sigma) 632 632 { 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); 633 635 PS_ASSERT_PTR_NON_NULL(histogram, NULL); 634 636 PS_ASSERT_PTR_NON_NULL(histogram->bounds, NULL); … … 666 668 false, 667 669 PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM); 670 psTrace(__func__, 3, "---- %s(NULL) end ----\n", __func__); 668 671 return(NULL); 669 672 } … … 681 684 false, 682 685 PS_ERRORTEXT_psStats_STATS_VECTOR_BIN_DISECT_PROBLEM); 686 psTrace(__func__, 3, "---- %s(NULL) end ----\n", __func__); 683 687 return(NULL); 684 688 } … … 703 707 // We get here if the histogram is uniform. 704 708 // 705 706 709 for (psS32 i = 0; i < numBins; i++) { 707 710 psF32 binSize = histogram->bounds->data.F32[1] - histogram->bounds->data.F32[0]; 708 711 psS32 gaussWidth = (psS32) ((PS_GAUSS_WIDTH * sigma) / binSize); 709 712 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; 710 720 // 711 721 // We determine the bin numbers (jMin:jMax) corresponding to a … … 735 745 } 736 746 747 psTrace(__func__, 3, "---- %s(psVector) end ----\n", __func__); 737 748 return(smooth); 738 749 } 739 /******************************************************************************740 p_psVectorSmoothHistGaussianNEW(): This routine smoothes the data in the input741 robustHistogram with a Gaussian of width sigma. It returns a psVector of the742 smoothed data.743 744 XXX: Only PS_TYPE_F32 is supported.745 746 XXX: Write a general routine which smoothes a psVector. This routine should747 call that. Is that possible?748 749 XXX: This is, or will be, prettier than the previous750 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 a780 // range of data values surrounding iMid. The range is of size:781 // 2*PS_GAUSS_WIDTH*sigma782 //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 a834 // range of data values surrounding iMid. The range is of size:835 // 2*PS_GAUSS_WIDTH*sigma836 //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 862 750 /****************************************************************************** 863 751 p_psVectorSampleQuartiles(myVector, maskVector, maskVal, stats): calculates … … 1435 1323 psF32 fHi = psPolynomial1DEval(myPoly, rangeHigh); 1436 1324 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); 1440 1326 return(NAN); 1441 1327 } … … 1491 1377 psF32 yVal) 1492 1378 { 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 1493 1386 PS_ASSERT_VECTOR_NON_NULL(xVec, NAN); 1494 1387 PS_ASSERT_VECTOR_NON_NULL(yVec, NAN); … … 1502 1395 psVector *y = psVectorAlloc(3, PS_TYPE_F64); 1503 1396 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.1505 1397 psPolynomial1D *myPoly = psPolynomial1DAlloc(2, PS_POLYNOMIAL_ORD); 1506 1398 … … 1515 1407 y->data.F64[1] = yVec->data.F32[binNum]; 1516 1408 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]); 1517 1412 1518 1413 // … … 1529 1424 psFree(y); 1530 1425 psFree(yErr); 1426 psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__); 1531 1427 return(NAN); 1532 1428 } 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]) { 1534 1436 if (!(y->data.F64[1] >= y->data.F64[2])) { 1535 1437 psError(PS_ERR_UNKNOWN, true, "This routine must be called with montically increasing or decreasing data points.\n"); … … 1538 1440 psFree(y); 1539 1441 psFree(yErr); 1442 psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__); 1540 1443 return(NAN); 1541 1444 } 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 1550 1453 yErr->data.F64[0] = 1.0; 1551 1454 yErr->data.F64[1] = 1.0; … … 1553 1456 1554 1457 // Determine the coefficients of the polynomial. 1458 // myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr); 1555 1459 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, y, yErr, x); 1556 1460 if (myPoly == NULL) { … … 1562 1466 psFree(y); 1563 1467 psFree(yErr); 1468 psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__); 1564 1469 return(NAN); 1565 1470 } 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 1566 1478 // Call p_ps1DPolyMedian(), which does a binary search on the 1567 1479 // 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); 1568 1481 tmpFloat = p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2], yVal); 1482 1569 1483 if (isnan(tmpFloat)) { 1570 1484 psError(PS_ERR_UNEXPECTED_NULL, … … 1575 1489 psFree(y); 1576 1490 psFree(yErr); 1491 psTrace(__func__, 3, "---- %s(NAN) end ----\n", __func__); 1577 1492 return(NAN); 1578 1493 } … … 1596 1511 } 1597 1512 1513 psTrace(__func__, 6, "FIT: return %f\n", tmpFloat); 1598 1514 psFree(myPoly); 1599 1515 psFree(x); 1600 1516 psFree(y); 1601 1517 psFree(yErr); 1518 1519 psTrace(__func__, 3, "---- %s(%f) end ----\n", __func__, tmpFloat); 1602 1520 return(tmpFloat); 1603 1521 } 1522 1523 /***************************************************************************** 1524 XXX: Is there a psLib function for this? 1525 *****************************************************************************/ 1526 psVector *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 /****************************************************************************** 1547 XXX: This function need to be written. Actually, it simply needs to be 1548 retrieved from the CVS repository, since it was written earlier, then 1549 discarded. At present, it was deleted from the CVS repository, so we might 1550 have to retrieve it from tape. 1551 *****************************************************************************/ 1552 psVector *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 /****************************************************************************** 1564 XXX: We assume unnormalized gaussians. 1565 *****************************************************************************/ 1566 psF32 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 1598 psF32 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 1614 void 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) \ 1633 memLeaks = currentId; 1634 1604 1635 1605 1636 /****************************************************************************** … … 1625 1656 XXX: Check for errors in psLib routines that we call. 1626 1657 *****************************************************************************/ 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 1962 1659 1963 1660 /****************************************************************************** … … 1984 1681 psStats* stats) 1985 1682 { 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; 1986 1689 psHistogram *robustHistogram = NULL; 1987 1690 psHistogram *cumulativeRobustHistogram = NULL; … … 1991 1694 psS32 totalDataPoints = 0; 1992 1695 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"); 1996 1713 // 1997 1714 // Determine the bin size of the robust histogram. This is done 1998 1715 // by computing the total range of data values and dividing by 1000.0. 1999 1716 // 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); 2003 1719 if ((rc != 0) || isnan(tmpStatsMinMax->min) || isnan(tmpStatsMinMax->max)) { 2004 1720 psError(PS_ERR_UNKNOWN, false, "Failed to calculate the min/max of the input vector.\n"); … … 2006 1722 psFree(tmpMaskVec); 2007 1723 psFree(tmpScalar); 1724 psTrace(__func__, 3, "---- %s(1) end ----\n", __func__); 2008 1725 return(1); 2009 1726 } 1727 psTrace(__func__, 6, "Data min/man is (%.2f, %.2f)\n", tmpStatsMinMax->min, tmpStatsMinMax->max); 2010 1728 psF32 binSize = (tmpStatsMinMax->max - tmpStatsMinMax->min) / 1000.0f; 1729 psTrace(__func__, 6, "Robust bin size is %.2f\n", binSize); 2011 1730 2012 1731 // … … 2015 1734 // 2016 1735 if (fabs(tmpStatsMinMax->max - tmpStatsMinMax->min) <= FLT_EPSILON) { 1736 psTrace(__func__, 5, "All data points have the same value.\n", binSize); 2017 1737 if (stats->options & PS_STAT_ROBUST_MEDIAN) { 2018 1738 stats->robustMedian = tmpStatsMinMax->min; … … 2029 1749 psFree(tmpScalar); 2030 1750 1751 psTrace(__func__, 3, "---- %s(0) end ----\n", __func__); 2031 1752 return(0); 2032 1753 } … … 2041 1762 // 2042 1763 numBins = (psS32)((tmpStatsMinMax->max - tmpStatsMinMax->min) / binSize); 1764 psTrace(__func__, 6, "Numbins is %d\n", numBins); 2043 1765 robustHistogram = psHistogramAlloc(tmpStatsMinMax->min, tmpStatsMinMax->max, numBins); 2044 1766 cumulativeRobustHistogram = psHistogramAlloc(tmpStatsMinMax->min, tmpStatsMinMax->max, numBins); 2045 1767 2046 1768 // 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 } 2049 1774 // 2050 1775 // ADD: Step 1. … … 2056 1781 robustHistogram->nums->data.F32[i]; 2057 1782 } 1783 if (psTraceGetLevel(__func__) >= 8) { 1784 PS_VECTOR_PRINT_F32(cumulativeRobustHistogram->bounds); 1785 PS_VECTOR_PRINT_F32(cumulativeRobustHistogram->nums); 1786 } 2058 1787 2059 1788 // … … 2062 1791 // 2063 1792 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); 2074 1814 2075 1815 // … … 2079 1819 // 2080 1820 stats->robustMedian = fitQuadraticSearchForYThenReturnX( 2081 *(psVector* *)& robustHistogram->bounds,2082 *(psVector* *)& robustHistogram->nums,1821 *(psVector* *)&cumulativeRobustHistogram->bounds, 1822 *(psVector* *)&cumulativeRobustHistogram->nums, 2083 1823 binMedian, 2084 1824 totalDataPoints/2.0); 1825 psTrace(__func__, 6, "Current robust median is %f\n", stats->robustMedian); 2085 1826 2086 1827 // … … 2088 1829 // Find the bins which contains the 15.8655% and 84.1345% data points. 2089 1830 // 1831 psS32 binLo = 0; 1832 psS32 binHi = 0; 2090 1833 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 } 2092 1843 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"); 2096 1859 psFree(tmpStatsMinMax); 2097 1860 psFree(robustHistogram); 2098 1861 psFree(cumulativeRobustHistogram); 2099 1862 psFree(tmpScalar); 1863 psFree(tmpMaskVec); 1864 psTrace(__func__, 3, "---- %s(1) end ----\n", __func__); 2100 1865 return(1); 2101 1866 } … … 2105 1870 // Interpolate Sigma to find these two positions exactly: these are the 1sigma positions. 2106 1871 // 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 } 2117 1912 2118 1913 // … … 2120 1915 // Determine SIGMA as 1/2 of the distance between these positions. 2121 1916 // 2122 psF32 sigma = (binHiF32 - binLoF32) / 2.0; 1917 sigma = (binHiF32 - binLoF32) / 2.0; 1918 psTrace(__func__, 6, "The current sigma is %f.\n", sigma); 2123 1919 2124 1920 // … … 2129 1925 // 2130 1926 if (sigma < (2 * binSize)) { 1927 psTrace(__func__, 6, "*************: Do another iteration (%f %f).\n", sigma, binSize); 2131 1928 psF32 medianLo = robustHistogram->bounds->data.F32[binMedian - 25]; 2132 1929 psF32 medianHi = robustHistogram->bounds->data.F32[binMedian + 25]; 1930 psTrace(__func__, 6, "Masking data outside (%f %f)\n", medianLo, medianHi); 2133 1931 for (psS32 i = 0 ; i < myVector->n ; i++) { 2134 1932 if ((myVector->data.F32[i] < medianLo) || 2135 1933 (myVector->data.F32[i] > medianHi)) { 2136 1934 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 } 2258 1938 psFree(robustHistogram); 2259 1939 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"); 2266 1970 psFree(tmpStatsMinMax); 2267 1971 psFree(robustHistogram); 2268 1972 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); 2271 2217 } 2272 2218 … … 2808 2754 // Since the various robust stats quantities share much computation, they 2809 2755 // are grouped together in a single private function: 2810 // p_psVectorRobustStats ()2756 // p_psVectorRobustStatsNew() 2811 2757 if ((stats->options & PS_STAT_ROBUST_MEAN) || 2812 2758 (stats->options & PS_STAT_ROBUST_MEDIAN) || … … 2814 2760 (stats->options & PS_STAT_ROBUST_STDEV) || 2815 2761 (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)) { 2817 2763 psError(PS_ERR_UNKNOWN, false, 2818 2764 PS_ERRORTEXT_psStats_STATS_FAILED); 2819 2765 // 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); 2820 2770 } 2821 2771 } -
trunk/psLib/test/math/tst_psStats07.c
r4861 r5113 34 34 float realMeanNoMask = MEAN; 35 35 float realMedianNoMask = MEAN; 36 float realModeNoMask = MEAN;37 float realStdevNoMask = STDEV * 0.20;36 // float realModeNoMask = MEAN; 37 float realStdevNoMask = STDEV; 38 38 float realLQNoMask = MEAN - ( 0.6 * STDEV ); 39 39 float realUQNoMask = MEAN + ( 0.6 * STDEV ); 40 40 psS32 realN50NoMask = N / 4; 41 41 psS32 realNfitNoMask = N / 4; 42 43 psTraceSetLevel(".psLib.dataManip", 0);44 42 45 43 /*************************************************************************/ … … 55 53 maskVector->n = N; 56 54 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; 57 58 // Set the mask vector and calculate the expected maximum. 58 59 for ( i = 0;i < N;i++ ) { … … 72 73 73 74 myStats = psVectorStats( myStats, myVector, NULL, NULL, 0 ); 75 if (myStats == NULL) { 76 printf("TEST ERROR: psVectorStats() returned NULL.\n"); 77 return(false); 78 } 74 79 75 80 printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n", … … 105 110 testStatus ); 106 111 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 */ 126 131 127 132 printPositiveTestHeader( stdout, … … 143 148 144 149 145 146 150 printPositiveTestHeader( stdout, 147 151 "psStats functions", … … 161 165 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask", 162 166 testStatus ); 163 164 165 167 166 168 printPositiveTestHeader( stdout, … … 180 182 "PS_STAT_ROBUST_STATS: lower quartile: no vector mask", 181 183 testStatus ); 182 183 184 184 185 185 printPositiveTestHeader( stdout, … … 205 205 testStatus ); 206 206 207 208 209 207 printPositiveTestHeader( stdout, 210 208 "psStats functions", … … 228 226 "PS_STAT_ROBUST_STATS: robust Nfit: no vector mask", 229 227 testStatus ); 230 return(testStatus);231 228 232 229 /*************************************************************************/ … … 252 249 testStatus ); 253 250 254 if (globalTestStatus == false) 255 printf("Returning FALSE\n"); 256 else 257 printf("Returning TRUE\n"); 258 return ( !globalTestStatus ); 251 return ( globalTestStatus ); 259 252 } 260 253 … … 276 269 float realMeanWithMask = MEAN; 277 270 float realMedianWithMask = MEAN; 278 float realModeWithMask = MEAN;279 float realStdevWithMask = STDEV * 0.20;271 // float realModeWithMask = MEAN; 272 float realStdevWithMask = STDEV; 280 273 float realLQWithMask = MEAN; 281 274 float realUQWithMask = MEAN; 282 275 psS32 realN50WithMask = N / 4; 283 276 psS32 realNfitWithMask = N / 4; 284 285 psTraceSetLevel(".psLib.dataManip.psStats", 0);286 287 277 /*************************************************************************/ 288 278 /* Allocate and initialize data structures */ … … 316 306 printf( "Calling psVectorStats() on a vector with elements masked.\n" ); 317 307 myStats = psVectorStats( myStats, myVector, NULL, maskVector, 1 ); 308 if (myStats == NULL) { 309 printf("TEST ERROR: psVectorStats() returned NULL.\n"); 310 return(false); 311 } 318 312 printf( "Called psVectorStats() on a vector with elements masked.\n" ); 319 313 printf( "The expected Mean was %.2f; the calculated Mean was %.2f\n", … … 348 342 349 343 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 */ 368 362 369 363 … … 489 483 testStatus ); 490 484 491 if (globalTestStatus == false) 492 printf("Returning FALSE\n"); 493 else 494 printf("Returning TRUE\n"); 495 496 return ( !globalTestStatus ); 485 return ( globalTestStatus ); 497 486 } 498 487 … … 500 489 { 501 490 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); 506 497 }
Note:
See TracChangeset
for help on using the changeset viewer.
