Skip to content

Commit 8bb1c23

Browse files
committed
[hist] Implement weighted filling in RHistAutoAxisFiller
1 parent 59594e2 commit 8bb1c23

File tree

2 files changed

+85
-10
lines changed

2 files changed

+85
-10
lines changed

hist/histv7/inc/ROOT/RHistAutoAxisFiller.hxx

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define ROOT_RHistAutoAxisFiller
77

88
#include "RHist.hxx"
9+
#include "RHistEngine.hxx"
10+
#include "RWeight.hxx"
911

1012
#include <algorithm>
1113
#include <cmath>
@@ -43,6 +45,10 @@ Feedback is welcome!
4345
*/
4446
template <typename BinContentType>
4547
class RHistAutoAxisFiller final {
48+
public:
49+
static constexpr bool SupportsWeightedFilling = RHistEngine<BinContentType>::SupportsWeightedFilling;
50+
51+
private:
4652
/// The filled histogram, after it has been constructed
4753
std::optional<RHist<BinContentType>> fHist;
4854

@@ -51,9 +57,10 @@ class RHistAutoAxisFiller final {
5157
/// The maximum buffer size until Flush() is automatically called
5258
std::size_t fMaxBufferSize;
5359

60+
using BufferElement = std::conditional_t<SupportsWeightedFilling, std::pair<double, RWeight>, double>;
61+
5462
/// The buffer of filled entries
55-
// FIXME: need to store weights!
56-
std::vector<double> fBuffer;
63+
std::vector<BufferElement> fBuffer;
5764
/// The minimum of the filled entries
5865
double fMinimum = std::numeric_limits<double>::infinity();
5966
/// The maximum of the filled entries
@@ -78,24 +85,58 @@ public:
7885
std::size_t GetNNormalBins() const { return fNNormalBins; }
7986
std::size_t GetMaxBufferSize() const { return fMaxBufferSize; }
8087

88+
private:
89+
void BufferImpl(double x, RWeight weight)
90+
{
91+
if constexpr (SupportsWeightedFilling) {
92+
fBuffer.emplace_back(x, weight);
93+
} else {
94+
assert(weight.fValue == 1.0);
95+
// Silence compiler warning about unused parameter
96+
(void)weight;
97+
fBuffer.push_back(x);
98+
}
99+
fMinimum = std::min(fMinimum, x);
100+
fMaximum = std::max(fMaximum, x);
101+
102+
if (fBuffer.size() >= fMaxBufferSize) {
103+
Flush();
104+
}
105+
}
106+
107+
public:
81108
/// Fill an entry into the histogram.
82109
///
83110
/// \param[in] x the argument
111+
/// \par See also
112+
/// the \ref Fill(double x, RWeight weight) "overload for weighted filling"
84113
void Fill(double x)
85114
{
86115
// If the histogram exists, forward the Fill call.
87116
if (fHist) {
88117
fHist->Fill(x);
89118
return;
90119
}
120+
BufferImpl(x, RWeight(1.0));
121+
}
91122

92-
fBuffer.push_back(x);
93-
fMinimum = std::min(fMinimum, x);
94-
fMaximum = std::max(fMaximum, x);
95-
96-
if (fBuffer.size() >= fMaxBufferSize) {
97-
Flush();
123+
/// Fill an entry into the histogram with a weight.
124+
///
125+
/// This overload is only available for floating-point bin content types (see
126+
/// \ref RHistEngine::SupportsWeightedFilling).
127+
///
128+
/// \param[in] x the argument
129+
/// \param[in] weight the weight for this entry
130+
/// \par See also
131+
/// the \ref Fill(double x) "overload for unweighted filling"
132+
void Fill(double x, RWeight weight)
133+
{
134+
// If the histogram exists, forward the Fill call.
135+
if (fHist) {
136+
fHist->Fill(x, weight);
137+
return;
98138
}
139+
BufferImpl(x, weight);
99140
}
100141

101142
/// Flush the buffer of entries and construct the histogram.
@@ -124,8 +165,12 @@ public:
124165
assert(high > fMaximum);
125166
fHist.emplace(fNNormalBins, std::make_pair(fMinimum, high));
126167

127-
for (double x : fBuffer) {
128-
fHist->Fill(x);
168+
for (auto &&x : fBuffer) {
169+
if constexpr (SupportsWeightedFilling) {
170+
fHist->Fill(x.first, x.second);
171+
} else {
172+
fHist->Fill(x);
173+
}
129174
}
130175
fBuffer.clear();
131176
}

hist/histv7/test/hist_auto.cxx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,36 @@ TEST(RHistAutoAxisFiller, FillMax0)
8585
EXPECT_EQ(hist.GetBinContent(RBinIndex::Overflow()), 0);
8686
}
8787

88+
TEST(RHistAutoAxisFiller, FillFloat)
89+
{
90+
RHistAutoAxisFiller<float> filler(3);
91+
92+
filler.Fill(1);
93+
filler.Fill(2);
94+
95+
auto &hist = filler.GetHist();
96+
EXPECT_EQ(hist.GetBinContent(0), 1);
97+
EXPECT_EQ(hist.GetBinContent(2), 1);
98+
99+
filler.Fill(1.5);
100+
EXPECT_EQ(hist.GetBinContent(1), 1);
101+
}
102+
103+
TEST(RHistAutoAxisFiller, FillWeight)
104+
{
105+
RHistAutoAxisFiller<float> filler(3);
106+
107+
filler.Fill(1, RWeight(0.8));
108+
filler.Fill(2, RWeight(0.9));
109+
110+
auto &hist = filler.GetHist();
111+
EXPECT_FLOAT_EQ(hist.GetBinContent(0), 0.8);
112+
EXPECT_FLOAT_EQ(hist.GetBinContent(2), 0.9);
113+
114+
filler.Fill(1.5, RWeight(0.85));
115+
EXPECT_FLOAT_EQ(hist.GetBinContent(1), 0.85);
116+
}
117+
88118
TEST(RHistAutoAxisFiller, FlushError)
89119
{
90120
static constexpr std::size_t Bins = 20;

0 commit comments

Comments
 (0)