11#include " ROOT/RDataFrame.hxx"
22#include " ROOT/RDF/Utils.hxx"
3+ #include " ROOT/RNTupleDS.hxx"
34#include " TTree.h"
45
56#include " gtest/gtest.h"
89#include < vector>
910
1011#include < TBranch.h>
12+ #include < TSystem.h>
1113
1214namespace RDFInt = ROOT::Internal::RDF;
1315
@@ -237,3 +239,85 @@ TEST(RDataFrameUtils, TypeName2TypeID)
237239 EXPECT_THROW (RDFInt::TypeName2TypeID (" float *" ), std::runtime_error);
238240 EXPECT_THROW (RDFInt::TypeName2TypeID (" float &" ), std::runtime_error);
239241}
242+
243+ TEST (RDataFrameUtils, GetClusterRanges)
244+ {
245+ const std::string fnameTTree1 = " dataframe_interfaceAndUtils_2_tree_1.root" ;
246+ const std::string fnameTTree2 = " dataframe_interfaceAndUtils_2_tree_2.root" ;
247+ const std::string fnameRNTuple1 = " dataframe_interfaceAndUtils_2_rntuple_1.root" ;
248+ const std::string fnameRNTuple2 = " dataframe_interfaceAndUtils_2_rntuple_2.root" ;
249+ const int nEntries = 1000 ;
250+ const int clusterSize = 250 ;
251+
252+ // Test TTree single file
253+ {
254+ ROOT::RDF::RSnapshotOptions opts;
255+ opts.fAutoFlush = clusterSize;
256+ auto df = ROOT::RDataFrame (nEntries).Define (" i" , " rdfentry_" );
257+ df.Snapshot (" t" , fnameTTree1, {" i" }, opts);
258+ df.Snapshot (" t" , fnameTTree2, {" i" }, opts);
259+ }
260+ {
261+ ROOT::RDataFrame dfTTree (" t" , fnameTTree1);
262+ auto *lmTTree = dfTTree.GetLoopManager ();
263+ auto rangesTTree = RDFInt::GetClusterRanges (*lmTTree);
264+
265+ EXPECT_EQ (rangesTTree.size (), nEntries / clusterSize);
266+ for (size_t i = 0 ; i < rangesTTree.size (); ++i) {
267+ EXPECT_EQ (rangesTTree[i].first , i * clusterSize);
268+ EXPECT_EQ (rangesTTree[i].second , (i + 1 ) * clusterSize);
269+ }
270+ }
271+
272+ // Test TTree multiple files (chain)
273+ {
274+ ROOT::RDataFrame dfTTreeChain (" t" , {fnameTTree1, fnameTTree2});
275+ auto *lmTTreeChain = dfTTreeChain.GetLoopManager ();
276+ auto rangesTTreeChain = RDFInt::GetClusterRanges (*lmTTreeChain);
277+
278+ EXPECT_EQ (rangesTTreeChain.size (), 2 * nEntries / clusterSize);
279+ for (size_t i = 0 ; i < rangesTTreeChain.size (); ++i) {
280+ EXPECT_EQ (rangesTTreeChain[i].first , i * clusterSize);
281+ EXPECT_EQ (rangesTTreeChain[i].second , (i + 1 ) * clusterSize);
282+ }
283+ }
284+ gSystem ->Unlink (fnameTTree1.c_str ());
285+ gSystem ->Unlink (fnameTTree2.c_str ());
286+
287+ // Test RNTuple single file
288+ {
289+ ROOT::RDF::RSnapshotOptions opts;
290+ opts.fOutputFormat = ROOT::RDF::ESnapshotOutputFormat::kRNTuple ;
291+ auto df = ROOT::RDataFrame (nEntries).Define (" i" , " rdfentry_" );
292+ df.Snapshot (" nt" , fnameRNTuple1, {" i" }, opts);
293+ df.Snapshot (" nt" , fnameRNTuple2, {" i" }, opts);
294+ }
295+ {
296+ auto dfRNTuple = ROOT::RDF::FromRNTuple (" nt" , fnameRNTuple1);
297+ auto *lmRNTuple = dfRNTuple.GetLoopManager ();
298+ auto rangesRNTuple = RDFInt::GetClusterRanges (*lmRNTuple);
299+
300+ EXPECT_FALSE (rangesRNTuple.empty ());
301+ EXPECT_EQ (rangesRNTuple.front ().first , 0u );
302+ EXPECT_EQ (rangesRNTuple.back ().second , ULong64_t (nEntries));
303+ for (size_t i = 1 ; i < rangesRNTuple.size (); ++i) {
304+ EXPECT_EQ (rangesRNTuple[i].first , rangesRNTuple[i - 1 ].second );
305+ }
306+ }
307+
308+ // Test RNTuple multiple files
309+ {
310+ auto dfRNTupleChain = ROOT::RDF::FromRNTuple (" nt" , {fnameRNTuple1, fnameRNTuple2});
311+ auto *lmRNTupleChain = dfRNTupleChain.GetLoopManager ();
312+ auto rangesRNTupleChain = RDFInt::GetClusterRanges (*lmRNTupleChain);
313+
314+ EXPECT_FALSE (rangesRNTupleChain.empty ());
315+ EXPECT_EQ (rangesRNTupleChain.front ().first , 0u );
316+ EXPECT_EQ (rangesRNTupleChain.back ().second , ULong64_t (2 * nEntries));
317+ for (size_t i = 1 ; i < rangesRNTupleChain.size (); ++i) {
318+ EXPECT_EQ (rangesRNTupleChain[i].first , rangesRNTupleChain[i - 1 ].second );
319+ }
320+ }
321+ gSystem ->Unlink (fnameRNTuple1.c_str ());
322+ gSystem ->Unlink (fnameRNTuple2.c_str ());
323+ }
0 commit comments