Skip to content
Merged
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
56 changes: 53 additions & 3 deletions tree/dataframe/inc/ROOT/RDF/RInterface.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -2493,7 +2493,31 @@ public:
/// ROOT::Experimental::RRegularAxis axis(10, {5.0, 15.0});
/// auto myHist = myDf.Hist({axis}, {"col0"});
/// ~~~
template <typename BinContentType = double, typename ColumnType = RDFDetail::RInferredType, typename... ColumnTypes>
template <typename BinContentType = double>
RResultPtr<ROOT::Experimental::RHist<BinContentType>>
Hist(std::vector<ROOT::Experimental::RAxisVariant> axes, const ColumnNames_t &columnList)
{
// Note: this overload works around limitations for automatic pythonization of variadic function templates with
// template parameter packs.
return Hist<BinContentType, RDFDetail::RInferredType>(std::move(axes), columnList);
}

////////////////////////////////////////////////////////////////////////////
/// \brief Fill and return an RHist (*lazy action*).
/// \tparam BinContentType The bin content type of the returned RHist.
/// \param[in] axes The returned histogram will be constructed using these axes.
/// \param[in] columnList A list containing the names of the columns that will be passed when calling `Fill`
/// \return the histogram wrapped in a RResultPtr.
///
/// This action is *lazy*: upon invocation of this method the calculation is
/// booked but not executed. Also see RResultPtr.
///
/// ### Example usage:
/// ~~~{.cpp}
/// ROOT::Experimental::RRegularAxis axis(10, {5.0, 15.0});
/// auto myHist = myDf.Hist<double, double>({axis}, {"col0"});
/// ~~~
template <typename BinContentType, typename ColumnType, typename... ColumnTypes>
RResultPtr<ROOT::Experimental::RHist<BinContentType>>
Hist(std::vector<ROOT::Experimental::RAxisVariant> axes, const ColumnNames_t &columnList)
{
Expand Down Expand Up @@ -2587,8 +2611,34 @@ public:
/// ROOT::Experimental::RRegularAxis axis(10, {5.0, 15.0});
/// auto myHist = myDf.Hist({axis}, {"col0"}, "colW");
/// ~~~
template <typename BinContentType = ROOT::Experimental::RBinWithError,
typename ColumnType = RDFDetail::RInferredType, typename... ColumnTypes>
template <typename BinContentType = ROOT::Experimental::RBinWithError>
RResultPtr<ROOT::Experimental::RHist<BinContentType>>
Hist(std::vector<ROOT::Experimental::RAxisVariant> axes, const ColumnNames_t &columnList, std::string_view wName)
{
// Note: this overload works around limitations for automatic pythonization of variadic function templates with
// template parameter packs.
return Hist<BinContentType, RDFDetail::RInferredType>(std::move(axes), columnList, wName);
}

////////////////////////////////////////////////////////////////////////////
/// \brief Fill and return an RHist with weights (*lazy action*).
/// \tparam BinContentType The bin content type of the returned RHist.
/// \param[in] axes The returned histogram will be constructed using these axes.
/// \param[in] columnList A list containing the names of the columns that will be passed when calling `Fill`
/// \param[in] wName The name of the column that will provide the weights.
/// \return the histogram wrapped in a RResultPtr.
///
/// This action is *lazy*: upon invocation of this method the calculation is
/// booked but not executed. Also see RResultPtr.
///
/// This overload is not available for integral bin content types (see \ref RHistEngine::SupportsWeightedFilling).
///
/// ### Example usage:
/// ~~~{.cpp}
/// ROOT::Experimental::RRegularAxis axis(10, {5.0, 15.0});
/// auto myHist = myDf.Hist<ROOT::Experimental::RBinWithError, double, double>({axis}, {"col0"}, "colW");
/// ~~~
template <typename BinContentType = ROOT::Experimental::RBinWithError, typename ColumnType, typename... ColumnTypes>
RResultPtr<ROOT::Experimental::RHist<BinContentType>>
Hist(std::vector<ROOT::Experimental::RAxisVariant> axes, const ColumnNames_t &columnList, std::string_view wName)
{
Expand Down
3 changes: 3 additions & 0 deletions tree/dataframe/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ if(pyroot)
ROOT_ADD_PYUNITTEST(dataframe_merge_results dataframe_merge_results.py)
ROOT_ADD_PYUNITTEST(dataframe_snapshot_py dataframe_snapshot.py)
endif()
if(root7)
ROOT_ADD_PYUNITTEST(dataframe_hist dataframe_hist.py)
endif()
endif()

configure_file(.rootrc . COPYONLY)
8 changes: 8 additions & 0 deletions tree/dataframe/test/dataframe_hist.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ TEST_P(RDFHist, RegularJit)
EXPECT_EQ(hist->GetBinContent(index), 1.0);
}

// The user can template explicitly only the bin content type.
hist = dfX.Hist</*BinContentType=*/double>({axis}, {"x"});
EXPECT_EQ(hist->GetNEntries(), 10);

// The one-dimensional specialization returns the same type.
hist = dfX.Hist(10, {5.0, 15.0}, "x");
EXPECT_EQ(hist->GetNEntries(), 10);
Expand Down Expand Up @@ -335,6 +339,10 @@ TEST_P(RDFHist, WeightJit)
EXPECT_FLOAT_EQ(bin.fSum2, weight * weight);
}

// The user can template explicitly only the bin content type.
hist = dfXW.Hist</*BinContentType=*/RBinWithError>({axis}, {"x"}, "w");
EXPECT_EQ(hist->GetNEntries(), 10);

// The one-dimensional specialization returns the same type.
hist = dfXW.Hist(10, {5.0, 15.0}, "x", "w");
EXPECT_EQ(hist->GetNEntries(), 10);
Expand Down
34 changes: 34 additions & 0 deletions tree/dataframe/test/dataframe_hist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import unittest

import ROOT

RRegularAxis = ROOT.Experimental.RRegularAxis
RVariableBinAxis = ROOT.Experimental.RVariableBinAxis


class RDFHist(unittest.TestCase):
def test_Regular(self):
df = ROOT.RDataFrame(10)
dfX = df.Define("x", "rdfentry_ + 5.5")
hist = dfX.Hist(10, (5.0, 15.0), "x")
self.assertEqual(hist.GetNEntries(), 10)

def test_MultiDim(self):
df = ROOT.RDataFrame(10)
dfXY = df.Define("x", "rdfentry_ + 5.5").Define("y", "2 * rdfentry_ + 0.5")

regularAxis = RRegularAxis(10, (5.0, 15.0))
bins = [i for i in range(0, 21)]
variableBinAxis = RVariableBinAxis(bins)
hist = dfXY.Hist([regularAxis, variableBinAxis], ["x", "y"])
self.assertEqual(hist.GetNEntries(), 10)

def test_Weight(self):
df = ROOT.RDataFrame(10)
dfXW = df.Define("x", "rdfentry_ + 5.5").Define("w", "0.1 + rdfentry_ * 0.03")
hist = dfXW.Hist(10, (5.0, 15.0), "x", "w")
self.assertEqual(hist.GetNEntries(), 10)

regularAxis = RRegularAxis(10, (5.0, 15.0))
hist = dfXW.Hist([regularAxis], ["x"], "w")
self.assertEqual(hist.GetNEntries(), 10)
Loading