Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions hist/histv7/inc/ROOT/RProfile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ public:
Internal::AtomicAdd(&fSum, rhs.fSum);
Internal::AtomicAdd(&fSum2, rhs.fSum2);
}

/// Compute the arithmetic mean in this bin.
///
/// \f[
/// \mu = \frac{\sum w_i \cdot x_i}{\sum w_i}
/// \f]
///
/// \return the arithmetic mean in this bin
double ComputeMean() const
{
if (fSum == 0) {
return std::numeric_limits<double>::signaling_NaN();
}
return fSumValues / fSum;
}
};

private:
Expand Down
16 changes: 16 additions & 0 deletions hist/histv7/test/hist_profile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,22 @@ TEST(RProfile, Clone)
EXPECT_EQ(profileB.GetBinContent(9).fSumValues, 25.0);
}

TEST(RProfile, ComputeMean)
{
static constexpr std::size_t Bins = 20;
RProfile profile(Bins, {0, Bins});
EXPECT_TRUE(std::isnan(profile.GetBinContent(0).ComputeMean()));

profile.Fill(8.5, 23.0);
profile.Fill(8.5, 25.0);

profile.Fill(9.5, 23.0, RWeight(0.8));
profile.Fill(9.5, 25.0, RWeight(0.7));

EXPECT_EQ(profile.GetBinContent(8).ComputeMean(), 24.0);
EXPECT_FLOAT_EQ(profile.GetBinContent(9).ComputeMean(), 23.933333);
}

TEST(RProfile, Fill)
{
static constexpr std::size_t Bins = 20;
Expand Down
90 changes: 90 additions & 0 deletions tutorials/hist/histv7/hist010_RProfile.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/// \file
/// \ingroup tutorial_histv7
///
/// Profile histograms with RProfile.
///
/// \macro_code
/// \macro_output
///
/// \date July 2026
/// \author The ROOT Team

#include <ROOT/RBinIndex.hxx>
#include <ROOT/RProfile.hxx>
#include <ROOT/RRegularAxis.hxx>

#include <cstddef>
#include <iostream>
#include <random>

void hist010_RProfile()
{
// Create an axis that can be used for multiple histograms.
ROOT::Experimental::RRegularAxis axis(40, {0.0, 20.0});

// Create a profile histogram and fill with random values.
ROOT::Experimental::RProfile profile(40, {0.0, 20.0});

std::mt19937 gen;
// Create a first normal distribution with mean 10.0 and stddev 4.0.
std::normal_distribution normal1(10.0, 4.0);
// Create a second normal distribution for the value.
std::normal_distribution normal2(40.0, 10.0);
for (std::size_t i = 0; i < 1000; i++) {
double x = normal1(gen);
double v = normal2(gen);
profile.Fill(x, v);
}

// Print (some of) the global statistics.
std::cout << "entries = " << profile.GetNEntries() << "\n";
std::cout << "binned mean = " << profile.ComputeMean(0);
std::cout << ", stddev = " << profile.ComputeStdDev(0);
std::cout << "\n";

// "Draw" the entries of the profile histogram with ASCII characters. The height is hard-coded to work for this
// tutorial.
for (int row = 8; row > 0; row--) {
auto print = [&](ROOT::Experimental::RBinIndex bin) {
const auto &content = profile.GetBinContent(bin);
static constexpr int Scale = 10;
std::cout << (content.fSum >= (row * Scale) ? '*' : ' ');
};

// First the underflow bin, separated by a vertical bar.
print(ROOT::Experimental::RBinIndex::Underflow());
std::cout << '|';

// Now iterate the normal bins and print a '*' if the value is sufficiently large.
for (auto bin : axis.GetNormalRange()) {
print(bin);
}

// Finally the overflow bin after a separating vertical bar.
std::cout << '|';
print(ROOT::Experimental::RBinIndex::Overflow());
std::cout << "\n";
}

std::cout << "\n";
std::cout << "value mean = " << profile.ComputeMean(1);
std::cout << ", stddev = " << profile.ComputeStdDev(1);
std::cout << "\n";

auto printBin = [&](ROOT::Experimental::RBinIndex bin) {
const auto &content = profile.GetBinContent(bin);
std::cout << "entries = " << content.fSum << ", mean = " << content.ComputeMean();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I wasn't sure what to print. Initially I wanted to do "errors", but there are several definitions so I kept it to the minimum... Let me know if you would like to see something else printed.

};

std::cout << "underflow bin: ";
printBin(ROOT::Experimental::RBinIndex::Underflow());
std::cout << "\n";

std::cout << "bin #5: ";
printBin(5);
std::cout << "\n";

std::cout << "bin #10: ";
printBin(10);
std::cout << "\n";
}
3 changes: 2 additions & 1 deletion tutorials/hist/histv7/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
\defgroup tutorial_histv7 RHist tutorials
\defgroup tutorial_histv7 Experimental histogram tutorials
\ingroup tutorial_hist

Examples demonstrating ROOT's histogram package.
Expand All @@ -10,6 +10,7 @@ Examples demonstrating ROOT's histogram package.
| hist003_RHist_multi.C | Multidimensional RHist with different axis types. |
| hist004_RHist_concurrent.C | Concurrent filling of RHist. |
| hist005_RHist_convert_TH1.C | Conversion of RHist to TH1. |
| hist010_RProfile.C | Profile histograms with RProfile. |

A second set of tutorials demonstrates usage with RDataFrame.

Expand Down
Loading