Index: trunk/tests/test_HistoND.cc =================================================================== --- trunk/tests/test_HistoND.cc (revision 615) +++ trunk/tests/test_HistoND.cc (revision 616) @@ -1,791 +1,816 @@ #include #include #include #include "UnitTest++.h" #include "test_utils.hh" #include "npstat/stat/HistoNDCdf.hh" #include "npstat/stat/arrayStats.hh" #include "npstat/stat/histoStats.hh" #include "npstat/stat/StatAccumulator.hh" #include "npstat/stat/interpolateHistoND.hh" #include "npstat/nm/SimpleFunctors.hh" #include "npstat/stat/ArrayProjectors.hh" #include "npstat/stat/NUHistoAxis.hh" #include "npstat/stat/DualHistoAxis.hh" #include "npstat/nm/EquidistantSequence.hh" #include "rk/geom3.hh" #include "geners/CPP11_array.hh" using namespace npstat; using namespace std; namespace { template struct pluseq_left_ptr { inline T1& operator()(T1*& left, const T2& right) const {return *left += right;} }; TEST(HistoAxis) { const unsigned nsteps = 331; const HistoAxis axis(10, 1.0, 5.0); const double step = 4.0/nsteps; const LinearMapper1d mapper(axis.binNumberMapper()); const LinearMapper1d mapper2(axis.binNumberMapper(false)); const double halfbin = axis.binWidth()/2.0; for (unsigned i=0; i(mapper(x))); CHECK_EQUAL(ibin, static_cast(mapper2(x + halfbin))); } } TEST(HistoND) { HistoND h1d(std::vector(1, HistoAxis(10,0.0,5.0))); HistoND h1d_fcn(h1d); HistoND h1d_ptr(h1d.axes()); HistoND h1d_base(h1d); HistoND h1dcop(HistoAxis(10,0.0,5.0)); CHECK(h1dcop == h1d); for (unsigned i=0; i(&h1d_base.binContents()(i))); double one = 1.0; pluseq_left fcn; pluseq_left_ptr fcn2; for (unsigned i=0; i<1000; ++i) { const double x = test_rng()*5.0; h1d.fill(x, 1.0); h1d_fcn.dispatch(x, one, fcn); h1d_ptr.dispatch(x, one, fcn2); } h1d_fcn.recalculateNFillsFromData(); h1d_base.recalculateNFillsFromData(); CHECK(h1d == h1d_fcn); CHECK(h1d == h1d_base); CPP11_auto_ptr dens1 = histoDensity1D(h1d); const double xinter = 1.12; CHECK_EQUAL(interpolateHistoND(h1d, xinter, 1U), interpolateHistoND(h1d, &xinter, 1U, 1U)); std::vector axes; axes.push_back(HistoAxis(10, 0.0, 5.0)); axes.push_back(HistoAxis(15, 0.0, 3.0)); const double xmin = axes[0].min(); const double bwx = axes[0].binWidth(); const unsigned nx = axes[0].nBins(); const double ymin = axes[1].min(); const double bwy = axes[1].binWidth(); const unsigned ny = axes[1].nBins(); HistoND hu1(axes); HistoND hu1_cop(HistoAxis(10, 0.0, 5.0), HistoAxis(15, 0.0, 3.0)); CHECK(hu1 == hu1_cop); std::vector moreAxes(axes); moreAxes.push_back(HistoAxis(20, -1.0, 4.0, "haha")); HistoND hu33(moreAxes); HistoND hu33_3(HistoAxis(10, 0.0, 5.0), HistoAxis(15, 0.0, 3.0), HistoAxis(20, -1.0, 4.0, "haha")); CHECK(hu33 == hu33_3); moreAxes.push_back(HistoAxis(2, -10.0, -1.0, "hoho")); HistoND hu44(moreAxes); HistoND hu44_4(HistoAxis(10, 0.0, 5.0), HistoAxis(15, 0.0, 3.0), HistoAxis(20, -1.0, 4.0, "haha"), HistoAxis(2, -10.0, -1.0, "hoho")); CHECK(hu44 == hu44_4); hu1.fill(2.0, 1.0, 1); hu1.fill(2.0, 1.0, 1); CHECK_EQUAL(2U, hu1.examine(2.0, 1.0)); CHECK_EQUAL(2U, hu1.closestBin(2.0, 1.0)); const double dindex[2] = {2.0, 1.0}; CHECK_EQUAL(2U, hu1.examine(dindex, 2U)); CHECK_EQUAL(2U, hu1.closestBin(dindex, 2U)); CHECK_CLOSE(5.0*3.0/150, hu1.binVolume(), 1.e-15); CHECK_EQUAL(5.0*3.0, hu1.volume()); HistoND hu2(hu1); CHECK(hu1 == hu2); hu2 += hu1; hu2 -= hu1; CHECK(hu1.isSameData(hu2)); hu2 *= 7; CHECK(!hu1.isSameData(hu2)); hu2 /= 7; CHECK(hu1.isSameData(hu2)); HistoND hu3(axes); double coords[2] = {2.0, 1.0}; hu3.fill(coords, 2, 1); hu3.fill(coords, 2, 1); CHECK(hu1 == hu3); // HistoND hu4(axes); HistoND hu4(axes); hu4.fillC(2.0, 1.0, 5.0); HistoND hu5(axes); for (unsigned ix=0; ix cov1(2, 2); Matrix cov2(2, 2); arrayCoordCovariance(hu4.binContents(), hu4.boundingBox(), &cov1); histoCovariance(hu4, &cov2); for (unsigned i=0; i<2; ++i) for (unsigned j=0; j<2; ++j) CHECK_CLOSE(cov1[i][j], cov2[i][j], 1.0e-15); CPP11_auto_ptr dens = histoDensityND(hu4); ostringstream os; CHECK(hu4.classId().write(os)); CHECK(hu4.write(os)); HistoND hvec(axes); hvec.fill(1.0, 1.0, geom3::Vector3(1.0, 2.0, 3.0)); hvec.fill(2.0, 1.5, geom3::Vector3(1.1, 2.3, 4.0)); const geom3::Vector3& bin = hvec.closestBin(1.0, 1.5); bin.x(); HistoND hs1(axes); hs1.fill(2.0, 2.0, "abc"); hs1.fill(1.0, 1.0, "hook"); hs1.fill(1.0, 1.0, "cat"); hs1.fill(100.0, 199.0, "baba"); gs::write_item(os, hs1, false); HistoND hs2(hs1); hs2.addToBinContents("gqlosc"); HistoND hs3(hs1); for (unsigned ix=0; ix* hu4_restored = HistoND::read(hid, is); CHECK(hu4_restored); CHECK(hu4 == *hu4_restored); delete hu4_restored; HistoND* hs1_restored = HistoND::read( gs::ClassId::makeId >(), is); CHECK(hs1_restored); CHECK(hs1 == *hs1_restored); delete hs1_restored; // Check the code which gets the bin centers std::vector > binCenters; hu1.allBinCenters(&binCenters); unsigned ibin = 0; for (unsigned ix=0; ix hacc(axes); hacc.fill(2.0, 1.0, 1); HistoND hd(axes); for (unsigned i=0; i<1000; ++i) hd.fill(test_rng()*5.0, test_rng()*3.0, 1.0); CHECK(hd.nFillsTotal() == 1000); ArrayND arrhd(hd.binContents()); hd.scaleBinContents(hu4.binContents().data(), hu4.nBins()); arrhd.inPlaceMul(hu4.binContents()); const unsigned long lenb = hu4.nBins(); for (unsigned long i=0; i hacc2(hd.axes()); hacc2 += hd; hacc2 += hd; HistoND hmeanh(hacc2, mem_fun_ref(&StatAccumulator::mean)); HistoND fmean(hmeanh, SameRef()); hd.setBinsToConst(1.0f); hd.setOverflowsToConst(1U); hacc2 /= -2; hacc2 *= -2; } TEST(HistoND_dual) { HistoND h1d(DualHistoAxis(10,0.0,5.0)); HistoND h1d_fcn(h1d); HistoND h1d_ptr(h1d.axes()); HistoND h1d_base(h1d); HistoND h1dcop(DualHistoAxis(10,0.0,5.0)); CHECK(h1dcop == h1d); for (unsigned i=0; i(&h1d_base.binContents()(i))); double one = 1.0; pluseq_left fcn; pluseq_left_ptr fcn2; for (unsigned i=0; i<1000; ++i) { const double x = test_rng()*5.0; h1d.fill(x, 1.0); h1d_fcn.dispatch(x, one, fcn); h1d_ptr.dispatch(x, one, fcn2); } h1d_fcn.recalculateNFillsFromData(); h1d_base.recalculateNFillsFromData(); CHECK(h1d == h1d_fcn); CHECK(h1d == h1d_base); CPP11_auto_ptr dens1 = histoDensity1D(h1d); const unsigned nCdf = 1000; std::vector cdf(nCdf); std::vector quantiles(nCdf); for (unsigned i=0; iquantile(r); } histoQuantiles(h1d, 0, &cdf[0], &cdf[0], nCdf); for (unsigned i=0; i axes; axes.push_back(DualHistoAxis(10, 0.0, 5.0)); axes.push_back(DualHistoAxis(15, 0.0, 3.0)); const double xmin = axes[0].min(); const double bwx = axes[0].binWidth(0); const unsigned nx = axes[0].nBins(); const double ymin = axes[1].min(); const double bwy = axes[1].binWidth(0); const unsigned ny = axes[1].nBins(); HistoND hu1(axes); HistoND hu1_cop(DualHistoAxis(10, 0.0, 5.0), DualHistoAxis(15, 0.0, 3.0)); CHECK(hu1 == hu1_cop); std::vector moreAxes(axes); moreAxes.push_back(DualHistoAxis(20, -1.0, 4.0, "haha")); HistoND hu33(moreAxes); HistoND hu33_3(DualHistoAxis(10, 0.0, 5.0), DualHistoAxis(15, 0.0, 3.0), DualHistoAxis(20, -1.0, 4.0, "haha")); CHECK(hu33 == hu33_3); moreAxes.push_back(DualHistoAxis(2, -10.0, -1.0, "hoho")); HistoND hu44(moreAxes); HistoND hu44_4(DualHistoAxis(10, 0.0, 5.0), DualHistoAxis(15, 0.0, 3.0), DualHistoAxis(20, -1.0, 4.0, "haha"), DualHistoAxis(2, -10.0, -1.0, "hoho")); CHECK(hu44 == hu44_4); hu1.fill(2.0, 1.0, 1); hu1.fill(2.0, 1.0, 1); CHECK_EQUAL(2U, hu1.examine(2.0, 1.0)); CHECK_EQUAL(2U, hu1.closestBin(2.0, 1.0)); const double dindex[2] = {2.0, 1.0}; CHECK_EQUAL(2U, hu1.examine(dindex, 2U)); CHECK_EQUAL(2U, hu1.closestBin(dindex, 2U)); CHECK_CLOSE(5.0*3.0/150, hu1.binVolume(), 1.e-15); CHECK_EQUAL(5.0*3.0, hu1.volume()); HistoND hu2(hu1); CHECK(hu1 == hu2); hu2 += hu1; hu2 -= hu1; CHECK(hu1.isSameData(hu2)); hu2 *= 7; CHECK(!hu1.isSameData(hu2)); hu2 /= 7; CHECK(hu1.isSameData(hu2)); HistoND hu3(axes); double coords[2] = {2.0, 1.0}; hu3.fill(coords, 2, 1); hu3.fill(coords, 2, 1); CHECK(hu1 == hu3); // HistoND hu4(axes); HistoND hu4(axes); hu4.fill(0.75, 0.3, 5.0); HistoND hu5(axes); for (unsigned ix=0; ix cov1(2, 2); Matrix cov2(2, 2); arrayCoordCovariance(hu4.binContents(), hu4.boundingBox(), &cov1); histoCovariance(hu4, &cov2); for (unsigned i=0; i<2; ++i) for (unsigned j=0; j<2; ++j) CHECK_CLOSE(cov1[i][j], cov2[i][j], 1.0e-15); CPP11_auto_ptr dens = histoDensityND(hu4); ostringstream os; CHECK(hu4.classId().write(os)); CHECK(hu4.write(os)); HistoND hvec(axes); hvec.fill(1.0, 1.0, geom3::Vector3(1.0, 2.0, 3.0)); hvec.fill(2.0, 1.5, geom3::Vector3(1.1, 2.3, 4.0)); const geom3::Vector3& bin = hvec.closestBin(1.0, 1.5); bin.x(); HistoND hs1(axes); hs1.fill(2.0, 2.0, "abc"); hs1.fill(1.0, 1.0, "hook"); hs1.fill(1.0, 1.0, "cat"); hs1.fill(100.0, 199.0, "baba"); gs::write_item(os, hs1, false); HistoND hs2(hs1); hs2.addToBinContents("gqlosc"); HistoND hs3(hs1); for (unsigned ix=0; ix* hu4_restored = HistoND::read(hid, is); CHECK(hu4_restored); CHECK(hu4 == *hu4_restored); delete hu4_restored; HistoND* hs1_restored = HistoND::read( gs::ClassId::makeId >(), is); CHECK(hs1_restored); CHECK(hs1 == *hs1_restored); delete hs1_restored; // Check the code which gets the bin centers std::vector > binCenters; hu1.allBinCenters(&binCenters); unsigned ibin = 0; for (unsigned ix=0; ix hacc(axes); hacc.fill(2.0, 1.0, 1); HistoND hd(axes); for (unsigned i=0; i<1000; ++i) hd.fill(test_rng()*5.0, test_rng()*3.0, 1.0); CHECK(hd.nFillsTotal() == 1000); ArrayND arrhd(hd.binContents()); hd.scaleBinContents(hu4.binContents().data(), hu4.nBins()); arrhd.inPlaceMul(hu4.binContents()); const unsigned long lenb = hu4.nBins(); for (unsigned long i=0; i hacc2(hd.axes()); hacc2 += hd; hacc2 += hd; HistoND hmeanh(hacc2, mem_fun_ref(&StatAccumulator::mean)); HistoND fmean(hmeanh, SameRef()); hd.setBinsToConst(1.0f); hd.setOverflowsToConst(1U); hacc2 /= -2; hacc2 *= -2; } TEST(HistoND_2) { HistoND h1(std::vector(1, HistoAxis(10,0.0,5.0))); EquidistantInLinearSpace bins(0.0,5.0,11); HistoND h2(std::vector(1, bins)); for (unsigned i=0; i<10000; ++i) { const double x = test_rng()*12 - 1.0; h1.fill(x, 1.0); h2.fill(x, 1.0); } CHECK_CLOSE(h1.integral(), 0.5*h1.nFillsInRange(), 1.0e-12); CHECK_CLOSE(h2.integral(), 0.5*h2.nFillsInRange(), 1.0e-12); CHECK_EQUAL(h1.nBins(), h2.nBins()); const ArrayND& a1 = h1.binContents(); const ArrayND& a2 = h2.binContents(); for (unsigned i=0; i& o1 = h1.overflows(); const ArrayND& o2 = h2.overflows(); for (unsigned i=0; i* h2_restored = HistoND::read(hid, is); CHECK(h2_restored); CHECK(h2 == *h2_restored); delete h2_restored; } TEST(HistoND_2_dual) { HistoND h1(std::vector(1, HistoAxis(10,0.0,5.0))); EquidistantInLinearSpace bins(0.0,5.0,11); HistoND h2(std::vector(1, bins)); for (unsigned i=0; i<10000; ++i) { const double x = test_rng()*12 - 1.0; h1.fill(x, 1.0); h2.fill(x, 1.0); } CHECK_CLOSE(h1.integral(), 0.5*h1.nFillsInRange(), 1.0e-12); CHECK_CLOSE(h2.integral(), 0.5*h2.nFillsInRange(), 1.0e-12); CHECK_EQUAL(h1.nBins(), h2.nBins()); const ArrayND& a1 = h1.binContents(); const ArrayND& a2 = h2.binContents(); for (unsigned i=0; i& o1 = h1.overflows(); const ArrayND& o2 = h2.overflows(); for (unsigned i=0; i* h2_restored = HistoND::read(hid, is); CHECK(h2_restored); CHECK(h2 == *h2_restored); delete h2_restored; } TEST(accumulateBinsInBox) { const double eps = 1.0e-14; const double eps2 = 1.0e-10; std::vector axes; axes.push_back(HistoAxis(2, 0.0, 2.0)); axes.push_back(HistoAxis(2, 0.0, 2.0)); HistoND hd(axes); hd.setBin(0U, 0U, 1.0); hd.setBin(0U, 1U, 2.0); hd.setBin(1U, 0U, 4.0); hd.setBin(1U, 1U, 8.0); BoxND box; box.push_back(Interval(0.3, 1.3)); box.push_back(Interval(0.6, 1.6)); const double expect = 0.7*0.4*1 + 0.7*0.6*2 + 0.3*0.4*4 + 0.3*0.6*8; double sum0 = 0.0; for (unsigned i=0; i<2; ++i) { for (unsigned j=0; j<2; ++j) { BoxND bin; bin.push_back(hd.axis(0).binInterval(i)); bin.push_back(hd.axis(1).binInterval(j)); const double over = bin.overlapFraction(box); sum0 += over*hd.binContents()(i, j); } } CHECK_CLOSE(expect, sum0, eps); long double sum = 0.0; hd.accumulateBinsInBox(box, &sum); CHECK_CLOSE(expect, static_cast(sum), eps); double center[2]; center[0] = hd.axis(0).fltBinNumber(box[0].midpoint(), false); center[1] = hd.axis(1).fltBinNumber(box[1].midpoint(), false); const double v1 = hd.binContents().interpolate1(center, 2); CHECK_CLOSE(expect, v1, eps); double scales[2] = {10.0, 10.0}; HistoNDCdf hcdf(hd, scales, 2); const double nall = hd.binContents().sum(); const double coverage = hcdf.boxCoverage(box); CHECK_CLOSE(expect, nall*coverage, eps); center[0] = box[0].midpoint(); center[1] = box[1].midpoint(); BoxND cobox; hcdf.coveringBox(coverage, center, 2, &cobox); for (unsigned i=0; i<2; ++i) { CHECK_CLOSE(box[i].min(), cobox[i].min(), eps2); CHECK_CLOSE(box[i].max(), cobox[i].max(), eps2); } } TEST(HistoNDCdf) { const unsigned npoints = 1000; const double eps = 1.0e-11; for (unsigned dim = 1; dim < 4; ++dim) { std::vector axes; axes.push_back(HistoAxis(5, -2.0, 5.0)); if (dim > 1) axes.push_back(HistoAxis(10, -4.0, 8.0)); if (dim > 2) axes.push_back(HistoAxis(7, -1.0, 2.0)); HistoND hd(axes); for (unsigned icycle=0; icycle<100; ++icycle) { hd.clear(); for (unsigned i=0; i(); CHECK(nInside > 0.0); double scales[3]; scales[0] = 3.5*test_rng() + 0.1; scales[1] = 6.0*test_rng() + 0.1; scales[2] = 1.5*test_rng() + 0.1; HistoNDCdf hcdf(hd, scales, dim); BoxND box(BoxND::sizeTwoBox(dim)); double shift[3]; shift[0] = test_rng()*7.0-2.0; shift[1] = test_rng()*12.0-4.0; shift[2] = test_rng()*3.0-1.0; box.shift(shift, dim); box.expand(scales, dim); long double sum = 0.0L; hd.accumulateBinsInBox(box, &sum); const double expectedCover = sum/nInside; const double cover1 = hcdf.boxCoverage(box); CHECK_CLOSE(expectedCover, cover1, eps); BoxND cobox; hcdf.coveringBox(cover1, shift, dim, &cobox); for (unsigned i=0; i axes; axes.push_back(HistoAxis(5, 0, 10, "X")); axes.push_back(HistoAxis(10, -5, 5, "Y")); HistoND expected(axes, "Some Title", "V"); axes.push_back(HistoAxis(7, 0, 7, "Z")); HistoND hd(axes, "Dummy", "V"); HistoND marg0(axes[0]); HistoND marg1(axes[1]); HistoND marg2(axes[2]); for (unsigned i=0; i proj(hd, &exclude, 1U, "Some Title"); ArraySumProjector summer; hd.addToProjection(&proj, summer, &exclude, 1U); proj.recalculateNFillsFromData(); CHECK(expected == proj); const double qvalues[3] = {0.25, 0.5, 0.75}; double quantiles[3], quantComp[3]; histoQuantiles(hd, 0, qvalues, quantiles, 3); histoQuantiles(marg0, 0, qvalues, quantComp, 3); for (unsigned i=0; i<3; ++i) CHECK_CLOSE(quantComp[i], quantiles[i], eps); histoQuantiles(hd, 1, qvalues, quantiles, 3); histoQuantiles(marg1, 0, qvalues, quantComp, 3); for (unsigned i=0; i<3; ++i) CHECK_CLOSE(quantComp[i], quantiles[i], eps); histoQuantiles(hd, 2, qvalues, quantiles, 3); histoQuantiles(marg2, 0, qvalues, quantComp, 3); for (unsigned i=0; i<3; ++i) CHECK_CLOSE(quantComp[i], quantiles[i], eps); } + + TEST(histoQuantiles) + { + HistoND h1(HistoAxis(100,0.0,5.0)); + for (unsigned i=0; i<10; ++i) + { + const double x = test_rng()*5.0; + h1.fill(x, 1.0); + } + CPP11_auto_ptr dens1 = histoDensity1D(h1); + + const unsigned nCdf = 1000; + std::vector cdf(nCdf); + std::vector quantiles(nCdf); + for (unsigned i=0; iquantile(r); + } + histoQuantiles(h1, 0, &cdf[0], &cdf[0], nCdf); + + for (unsigned i=0; i