Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RTTreeDS.cxx
Go to the documentation of this file.
1#include <sstream>
2
3#include <ROOT/RTTreeDS.hxx>
4#include <ROOT/RDataFrame.hxx>
5#include <ROOT/RDF/RLoopManager.hxx> // GetBranchNames
7#include <ROOT/RDF/Utils.hxx> // GetBranchOrLeafTypeName
8
9#include <TBranchObject.h>
10#include <TClassEdit.h>
11#include <TFile.h>
12#include <TTree.h>
13#include <TChain.h>
14#include <TFriendElement.h>
15#include <TTreeReader.h>
16#include <ROOT/RFriendInfo.hxx>
17#include <ROOT/InternalTreeUtils.hxx> // GetTopLevelBranchNames
18
19#ifdef R__USE_IMT
20#include <TROOT.h>
21#include <TEntryList.h>
23#include <ROOT/RSlotStack.hxx>
24#endif
25
26namespace {
28{
29 switch (entryStatus) {
30 case TTreeReader::kEntryValid: return true;
31 case TTreeReader::kIndexedFriendNoMatch: return true;
33 default: return false;
34 }
35}
36
37std::tuple<bool, std::string, ROOT::Internal::RDF::RTreeUntypedArrayColumnReader::ECollectionType>
38GetCollectionInfo(const std::string &typeName)
39{
40 const auto beginType = typeName.substr(0, typeName.find_first_of('<') + 1);
41
42 // Find TYPE from ROOT::RVec<TYPE>
43 if (auto pos = beginType.find("RVec<"); pos != std::string::npos) {
44 const auto begin = typeName.find_first_of('<', pos) + 1;
45 const auto end = typeName.find_last_of('>');
46 const auto innerTypeName = typeName.substr(begin, end - begin);
47 if (innerTypeName.find("bool") != std::string::npos)
49 else
51 }
52
53 // Find TYPE from std::array<TYPE,N>
54 if (auto pos = beginType.find("array<"); pos != std::string::npos) {
55 const auto begin = typeName.find_first_of('<', pos) + 1;
56 const auto end = typeName.find_last_of('>');
57 const auto arrTemplArgs = typeName.substr(begin, end - begin);
58 const auto lastComma = arrTemplArgs.find_last_of(',');
59 return {true, arrTemplArgs.substr(0, lastComma),
61 }
62
63 // Find TYPE from std::vector<TYPE>
64 if (auto pos = beginType.find("vector<"); pos != std::string::npos) {
65 const auto begin = typeName.find_first_of('<', pos) + 1;
66 const auto end = typeName.find_last_of('>');
67 const auto innerTypeName = typeName.substr(begin, end - begin);
69 }
70
72}
73
74bool ContainsLeaf(const std::set<TLeaf *> &leaves, TLeaf *leaf)
75{
76 return (leaves.find(leaf) != leaves.end());
77}
78
79///////////////////////////////////////////////////////////////////////////////
80/// This overload does not check whether the leaf/branch is already in bNamesReg. In case this is a friend leaf/branch,
81/// `allowDuplicates` controls whether we add both `friendname.bname` and `bname` or just the shorter version.
82void InsertBranchName(std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, const std::string &branchName,
83 const std::string &friendName, bool allowDuplicates)
84{
85 if (!friendName.empty()) {
86 // In case of a friend tree, users might prepend its name/alias to the branch names
87 const auto friendBName = friendName + "." + branchName;
88 if (bNamesReg.insert(friendBName).second)
89 bNames.push_back(friendBName);
90 }
91
92 if (allowDuplicates || friendName.empty()) {
93 if (bNamesReg.insert(branchName).second)
94 bNames.push_back(branchName);
95 }
96}
97
98///////////////////////////////////////////////////////////////////////////////
99/// This overload makes sure that the TLeaf has not been already inserted.
100void InsertBranchName(std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, const std::string &branchName,
101 const std::string &friendName, std::set<TLeaf *> &foundLeaves, TLeaf *leaf, bool allowDuplicates)
102{
104 if (!canAdd) {
105 return;
106 }
107
109
110 foundLeaves.insert(leaf);
111}
112
113void ExploreBranch(TTree &t, std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, TBranch *b,
114 std::string prefix, std::string &friendName, bool allowDuplicates)
115{
116 // We want to avoid situations of overlap between the prefix and the
117 // sub-branch name that might happen when the branch is composite, e.g.
118 // prefix=reco_Wdecay2_from_tbar_4vect_NOSYS.fCoordinates.
119 // subBranchName=fCoordinates.fPt
120 // which would lead to a repetition of fCoordinates in the output branch name
121 // Boundary to search for the token before the last dot
122 auto prefixEndingDot = std::string::npos;
123 if (!prefix.empty() && prefix.back() == '.')
124 prefixEndingDot = prefix.size() - 2;
125 std::string lastPrefixToken{};
126 if (auto prefixLastRealDot = prefix.find_last_of('.', prefixEndingDot); prefixLastRealDot != std::string::npos)
128
129 for (auto sb : *b->GetListOfBranches()) {
130 TBranch *subBranch = static_cast<TBranch *>(sb);
131 auto subBranchName = std::string(subBranch->GetName());
132 auto fullName = prefix + subBranchName;
133
134 if (auto subNameFirstDot = subBranchName.find_first_of('.'); subNameFirstDot != std::string::npos) {
135 // Concatenate the prefix to the sub-branch name without overlaps
136 if (!lastPrefixToken.empty() && lastPrefixToken == subBranchName.substr(0, subNameFirstDot))
137 fullName = prefix + subBranchName.substr(subNameFirstDot + 1);
138 }
139
140 std::string newPrefix;
141 if (!prefix.empty())
142 newPrefix = fullName + ".";
143
145
146 auto branchDirectlyFromTree = t.GetBranch(fullName.c_str());
148 branchDirectlyFromTree = t.FindBranch(fullName.c_str()); // try harder
152
153 if (bNamesReg.find(subBranchName) == bNamesReg.end() && t.GetBranch(subBranchName.c_str()))
155 }
156}
157
158void GetBranchNamesImpl(TTree &t, std::set<std::string> &bNamesReg, std::vector<std::string> &bNames,
159 std::set<TTree *> &analysedTrees, std::string &friendName, bool allowDuplicates)
160{
161 std::set<TLeaf *> foundLeaves;
162 if (!analysedTrees.insert(&t).second) {
163 return;
164 }
165
166 const auto branches = t.GetListOfBranches();
167 // Getting the branches here triggered the read of the first file of the chain if t is a chain.
168 // We check if a tree has been successfully read, otherwise we throw (see ROOT-9984) to avoid further
169 // operations
170 if (!t.GetTree()) {
171 std::string err("GetBranchNames: error in opening the tree ");
172 err += t.GetName();
173 throw std::runtime_error(err);
174 }
175 if (branches) {
176 for (auto b : *branches) {
177 TBranch *branch = static_cast<TBranch *>(b);
178 const auto branchName = std::string(branch->GetName());
179 if (branch->IsA() == TBranch::Class()) {
180 // Leaf list
181 auto listOfLeaves = branch->GetListOfLeaves();
182 if (listOfLeaves->GetEntriesUnsafe() == 1) {
183 auto leaf = static_cast<TLeaf *>(listOfLeaves->UncheckedAt(0));
185 }
186
187 for (auto leaf : *listOfLeaves) {
188 auto castLeaf = static_cast<TLeaf *>(leaf);
189 const auto leafName = std::string(leaf->GetName());
190 const auto fullName = branchName + "." + leafName;
192 }
193 } else if (branch->IsA() == TBranchObject::Class()) {
194 // TBranchObject
197 } else {
198 // TBranchElement
199 // Check if there is explicit or implicit dot in the name
200
201 bool dotIsImplied = false;
202 auto be = dynamic_cast<TBranchElement *>(b);
203 if (!be)
204 throw std::runtime_error("GetBranchNames: unsupported branch type");
205 // TClonesArray (3) and STL collection (4)
206 if (be->GetType() == 3 || be->GetType() == 4)
207 dotIsImplied = true;
208
209 if (dotIsImplied || branchName.back() == '.')
211 else
213
215 }
216 }
217 }
218
219 // The list of friends needs to be accessed via GetTree()->GetListOfFriends()
220 // (and not via GetListOfFriends() directly), otherwise when `t` is a TChain we
221 // might not recover the list correctly (https://github.com/root-project/root/issues/6741).
222 auto friendTrees = t.GetTree()->GetListOfFriends();
223
224 if (!friendTrees)
225 return;
226
227 for (auto friendTreeObj : *friendTrees) {
228 auto friendTree = ((TFriendElement *)friendTreeObj)->GetTree();
229
230 std::string frName;
232 if (alias != nullptr)
233 frName = std::string(alias);
234 else
235 frName = std::string(friendTree->GetName());
236
238 }
239}
240
241///////////////////////////////////////////////////////////////////////////////
242/// Get all the branches names, including the ones of the friend trees
243std::vector<std::string> RetrieveDatasetSchema(TTree &t, bool allowDuplicates = true)
244{
245 std::set<std::string> bNamesSet;
246 std::vector<std::string> bNames;
247 std::set<TTree *> analysedTrees;
248 std::string emptyFrName = "";
250 return bNames;
251}
252} // namespace
253
254// Destructor is defined here, where the data member types are actually available
256{
258 // fNoCleanupNotifier was created only if the input TTree is a TChain
259 fNoCleanupNotifier->RemoveLink(*static_cast<TChain *>(fTree.get()));
260};
261
263{
264 fTree = tree;
265
266 if (friendInfo) {
268 for (std::size_t i = 0ul; i < fFriends.size(); i++) {
269 const auto &thisFriendAlias = friendInfo->fFriendNames[i].second;
270 fTree->AddFriend(fFriends[i].get(), thisFriendAlias.c_str());
271 }
272 }
273
274 if (fBranchNamesWithDuplicates.empty())
275 fBranchNamesWithDuplicates = RetrieveDatasetSchema(*fTree);
276 if (fBranchNamesWithoutDuplicates.empty())
277 fBranchNamesWithoutDuplicates = RetrieveDatasetSchema(*fTree, /*allowDuplicates*/ false);
278 if (fTopLevelBranchNames.empty())
279 fTopLevelBranchNames = ROOT::Internal::TreeUtils::GetTopLevelBranchNames(*fTree);
280}
281
282ROOT::Internal::RDF::RTTreeDS::RTTreeDS(std::shared_ptr<TTree> tree)
283{
284 assert(tree && "No tree passed to the constructor of RTTreeDS!");
285 Setup(std::move(tree));
286}
287
289{
290 assert(tree && "No tree passed to the constructor of RTTreeDS!");
291 Setup(std::move(tree), &friendInfo);
292}
293
295{
296 if (!dirPtr) {
297 throw std::runtime_error("RDataFrame: invalid TDirectory when constructing the data source.");
298 }
299 const std::string treeNameInt(treeName);
300 auto tree = dirPtr->Get<TTree>(treeName.data());
301 if (!tree) {
302 throw std::runtime_error("RDataFrame: TTree dataset '" + std::string(treeName) + "' cannot be found in '" +
303 dirPtr->GetName() + "'.");
304 }
306
307 // We keep the existing functionality from RLoopManager, until proven not necessary.
308 // See https://github.com/root-project/root/pull/10729
309 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
310 // a file name or list of file names, see
311 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
312 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
313 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
314 fNoCleanupNotifier->RegisterChain(*ch);
315 }
316}
317
319{
320 std::string treeNameInt{treeName};
321 std::string fileNameGlobInt{fileNameGlob};
323 chain->Add(fileNameGlobInt.c_str());
324
325 Setup(std::move(chain));
326 // We keep the existing functionality from RLoopManager, until proven not necessary.
327 // See https://github.com/root-project/root/pull/10729
328 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
329 // a file name or list of file names, see
330 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
331 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
332 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
333 fNoCleanupNotifier->RegisterChain(*ch);
334 }
335}
336
337ROOT::Internal::RDF::RTTreeDS::RTTreeDS(std::string_view treeName, const std::vector<std::string> &fileNameGlobs)
338{
339 std::string treeNameInt(treeName);
341 for (auto &&f : fileNameGlobs)
342 chain->Add(f.c_str());
343
344 Setup(std::move(chain));
345
346 // We keep the existing functionality from RLoopManager, until proven not necessary.
347 // See https://github.com/root-project/root/pull/10729
348 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
349 // a file name or list of file names, see
350 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
351 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
352 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
353 fNoCleanupNotifier->RegisterChain(*ch);
354 }
355}
356
358{
359 return ROOT::RDataFrame(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(treeName, fileNameGlob));
360}
361
363ROOT::Internal::RDF::FromTTree(std::string_view treeName, const std::vector<std::string> &fileNameGlobs)
364{
365 return ROOT::RDataFrame(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(treeName, fileNameGlobs));
366}
367
369 unsigned int, const std::unordered_map<std::string, ROOT::RDF::Experimental::RSample *> &sampleMap) const
370{
371 // one GetTree to retrieve the TChain, another to retrieve the underlying TTree
372 auto *tree = fTreeReader->GetTree()->GetTree();
373 // tree might be missing e.g. when a file in a chain does not exist
374 if (!tree)
375 return ROOT::RDF::RSampleInfo{};
376
377 const std::string treename = ROOT::Internal::TreeUtils::GetTreeFullPaths(*tree)[0];
378 auto *file = tree->GetCurrentFile();
379 const std::string fname = file != nullptr ? file->GetName() : "#inmemorytree#";
380
381 std::pair<Long64_t, Long64_t> range = fTreeReader->GetEntriesRange();
382 R__ASSERT(range.first >= 0);
383 if (range.second == -1) {
384 range.second = tree->GetEntries(); // convert '-1', i.e. 'until the end', to the actual entry number
385 }
386 // If the tree is stored in a subdirectory, treename will be the full path to it starting with the root directory '/'
387 const std::string &id = fname + (treename.rfind('/', 0) == 0 ? "" : "/") + treename;
388 if (sampleMap.empty()) {
389 return RSampleInfo(id, range, nullptr, tree->GetEntries());
390 } else {
391 if (sampleMap.find(id) == sampleMap.end())
392 throw std::runtime_error("Full sample identifier '" + id + "' cannot be found in the available samples.");
393 return RSampleInfo(id, range, sampleMap.at(id), tree->GetEntries());
394 }
395}
396
398{
399#ifdef R__USE_IMT
401 std::atomic<ULong64_t> entryCount(0ull);
402
403 const auto &entryList = fTree->GetEntryList() ? *fTree->GetEntryList() : TEntryList();
404 const auto &suppressErrorsForMissingBranches = lm.GetSuppressErrorsForMissingBranches();
405 auto tp{fGlobalEntryRange.has_value()
406 ? std::make_unique<ROOT::TTreeProcessorMT>(*fTree, fNSlots, fGlobalEntryRange.value(),
408 : std::make_unique<ROOT::TTreeProcessorMT>(*fTree, entryList, fNSlots, suppressErrorsForMissingBranches)};
409
410 tp->Process([&lm, &slotStack, &entryCount](TTreeReader &treeReader) {
411 lm.TTreeThreadTask(treeReader, slotStack, entryCount);
412 });
413
414 if (fGlobalEntryRange.has_value()) {
415 auto &&[begin, end] = fGlobalEntryRange.value();
416 auto &&processedEntries = entryCount.load();
417 if ((end - begin) > processedEntries) {
418 Warning("RDataFrame::Run",
419 "RDataFrame stopped processing after %lld entries, whereas an entry range (begin=%lld,end=%lld) was "
420 "requested. Consider adjusting the end value of the entry range to a maximum of %lld.",
421 processedEntries, begin, end, begin + processedEntries);
422 }
423 }
424#else
425 (void)lm;
426#endif
427}
428
430{
431 assert(fTree && "The internal TTree is not available, something went wrong.");
432 if (dynamic_cast<TChain *>(fTree.get()))
434
435 return fTree->GetCurrentFile() ? 1 : 0;
436}
437
439{
440 assert(fTree && "The internal TTree is not available, something went wrong.");
441 const auto treeName = fTree->GetName();
442 const auto isTChain = dynamic_cast<TChain *>(fTree.get()) ? true : false;
443 const auto treeType = isTChain ? "TChain" : "TTree";
444 const auto isInMemory = !isTChain && !fTree->GetCurrentFile() ? true : false;
446 const auto hasFriends = friendInfo.fFriendNames.empty() ? false : true;
447 std::stringstream ss;
448 ss << "Dataframe from " << treeType;
449 if (*treeName != 0) {
450 ss << " " << treeName;
451 }
452 if (isInMemory) {
453 ss << " (in-memory)";
454 } else {
456 const auto numFiles = files.size();
457 if (numFiles == 1) {
458 ss << " in file " << files[0];
459 } else {
460 ss << " in files\n";
461 for (auto i = 0u; i < numFiles; i++) {
462 ss << " " << files[i];
463 if (i < numFiles - 1)
464 ss << '\n';
465 }
466 }
467 }
468 if (hasFriends) {
469 const auto numFriends = friendInfo.fFriendNames.size();
470 if (numFriends == 1) {
471 ss << "\nwith friend\n";
472 } else {
473 ss << "\nwith friends\n";
474 }
475 for (auto i = 0u; i < numFriends; i++) {
476 const auto nameAlias = friendInfo.fFriendNames[i];
477 const auto files = friendInfo.fFriendFileNames[i];
478 const auto numFiles = files.size();
479 const auto subnames = friendInfo.fFriendChainSubNames[i];
480 ss << " " << nameAlias.first;
481 if (nameAlias.first != nameAlias.second)
482 ss << " (" << nameAlias.second << ")";
483 // case: TTree as friend
484 if (numFiles == 1) {
485 ss << " " << files[0];
486 }
487 // case: TChain as friend
488 else {
489 ss << '\n';
490 for (auto j = 0u; j < numFiles; j++) {
491 ss << " " << subnames[j] << " " << files[j];
492 if (j < numFiles - 1)
493 ss << '\n';
494 }
495 }
496 if (i < numFriends - 1)
497 ss << '\n';
498 }
499 }
500 return ss.str();
501}
502
503std::unique_ptr<ROOT::Detail::RDF::RColumnReaderBase>
504ROOT::Internal::RDF::RTTreeDS::CreateColumnReader(unsigned int /*slot*/, std::string_view col, const std::type_info &ti,
506{
507 // In a single thread run, use the TTreeReader data member.
508 if (fTreeReader) {
509 treeReader = fTreeReader.get();
510 }
511
512 // The TTreeReader might still not be available if CreateColumnReader was called before the start of the computation
513 // graph execution, e.g. in AddDSColumns.
514 if (!treeReader)
515 return nullptr;
516
517 std::unique_ptr<ROOT::Detail::RDF::RColumnReaderBase> colReader;
518
519 if (ti == typeid(void)) {
520 colReader = std::make_unique<ROOT::Internal::RDF::RTreeOpaqueColumnReader>(*treeReader, col);
521 } else {
522 const auto typeName = ROOT::Internal::RDF::TypeID2TypeName(ti);
523 if (auto &&[toConvert, innerTypeName, collType] = GetCollectionInfo(typeName); toConvert)
524 colReader = std::make_unique<ROOT::Internal::RDF::RTreeUntypedArrayColumnReader>(*treeReader, col,
526 else
527 colReader = std::make_unique<ROOT::Internal::RDF::RTreeUntypedValueColumnReader>(*treeReader, col, typeName);
528 }
529
530 if (TDirectory *treeDir = treeReader->GetTree()->GetDirectory(); treeDir) {
531 using Map_t = std::unordered_map<std::string, std::pair<std::string, unsigned int>>;
532 const std::string bitmaskMapName =
533 std::string{"R_rdf_column_to_bitmask_mapping_"} + treeReader->GetTree()->GetName();
534 if (Map_t const *columnMaskMap = treeDir->Get<Map_t>(bitmaskMapName.c_str()); columnMaskMap) {
535 if (auto it = columnMaskMap->find(std::string(col)); it != columnMaskMap->end()) {
536 colReader = std::make_unique<RMaskedColumnReader>(*treeReader, std::move(colReader), it->second.first,
537 it->second.second);
538 }
539 }
540 }
541
542 return colReader;
543}
544
546{
547 // The first entry of each tree in a chain is read in GetEntryRanges, we avoid repeating it here
548 if (fTreeReader->GetCurrentEntry() != static_cast<Long64_t>(entry))
549 fTreeReader->SetEntry(entry);
550 return ValidRead(fTreeReader->GetEntryStatus());
551}
552
554{
557 std::vector<std::string> split;
558 int dummy;
559 TClassEdit::GetSplit(colTypeName.c_str(), split, dummy);
560 auto &valueType = split[1];
561 colTypeName = "ROOT::VecOps::RVec<" + valueType + ">";
562 }
563 return colTypeName;
564}
565
566std::string ROOT::Internal::RDF::RTTreeDS::GetTypeName(std::string_view colName) const
567{
570 std::vector<std::string> split;
571 int dummy;
572 TClassEdit::GetSplit(colTypeName.c_str(), split, dummy);
573 auto &valueType = split[1];
574 colTypeName = "ROOT::VecOps::RVec<" + valueType + ">";
575 }
576 return colTypeName;
577}
578
579std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetTTreeEntryRange(TTree &tree)
580{
581 // Restrict the range to the global range if available
582 const ULong64_t rangeBegin = fGlobalEntryRange.has_value() ? std::max(0ull, fGlobalEntryRange->first) : 0ull;
583 const ULong64_t rangeEnd = fGlobalEntryRange.has_value()
584 ? std::min(static_cast<ULong64_t>(tree.GetEntries()), fGlobalEntryRange->second)
585 : static_cast<ULong64_t>(tree.GetEntries());
586 return std::vector<std::pair<ULong64_t, ULong64_t>>{{rangeBegin, rangeEnd}};
587}
588
589std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetTChainEntryRange(TChain &chain)
590{
591 // We are either at a complete new beginning (entry == -1) or at the
592 // end of processing of the previous tree in the chain. Go to the next
593 // entry, which should always be the first entry in a tree. This allows
594 // to get the proper tree offset for the range.
595 fTreeReader->Next();
596 if (!ValidRead(fTreeReader->GetEntryStatus()))
597 return {};
598 auto treeOffsets = chain.GetTreeOffset();
599 auto treeNumber = chain.GetTreeNumber();
602 // Restrict the range to the global range if available
603 const ULong64_t rangeBegin =
604 fGlobalEntryRange.has_value() ? std::max(thisTreeBegin, fGlobalEntryRange->first) : thisTreeBegin;
605 const ULong64_t rangeEnd =
606 fGlobalEntryRange.has_value() ? std::min(thisTreeEnd, fGlobalEntryRange->second) : thisTreeEnd;
607 return std::vector<std::pair<ULong64_t, ULong64_t>>{{rangeBegin, rangeEnd}};
608}
609
610std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetEntryRanges()
611{
612 assert(fTreeReader && "TTreeReader is not available, this should never happen.");
613 auto treeOrChain = fTreeReader->GetTree();
614 assert(treeOrChain && "Could not retrieve TTree from TTreeReader, something went wrong.");
615
616 // End of dataset or entry range
617 if (fTreeReader->GetCurrentEntry() >= treeOrChain->GetEntriesFast() - 1 ||
618 (fGlobalEntryRange.has_value() &&
619 (static_cast<ULong64_t>(fTreeReader->GetCurrentEntry()) >= fGlobalEntryRange->first &&
620 static_cast<ULong64_t>(fTreeReader->GetCurrentEntry()) == fGlobalEntryRange->second - 1))) {
621 // Place the TTreeReader beyond the end of the dataset, so RunFinalChecks can work properly
622 fTreeReader->Next();
623 return {};
624 }
625
626 if (auto chain = dynamic_cast<TChain *>(treeOrChain)) {
627 return GetTChainEntryRange(*chain);
628 } else {
629 return GetTTreeEntryRange(*treeOrChain);
630 }
631}
632
634{
635 // At the end of the event loop, reset the TTreeReader to be ready for
636 // a possible new run.
637 if (fTreeReader)
638 fTreeReader.reset();
639}
640
642{
644 return;
645 assert(!fTreeReader);
646 fTreeReader = std::make_unique<TTreeReader>(fTree.get(), fTree->GetEntryList(), /*warnAboutLongerFriends*/ true);
647 if (fGlobalEntryRange.has_value() && fGlobalEntryRange->first <= std::numeric_limits<Long64_t>::max() &&
648 fGlobalEntryRange->second <= std::numeric_limits<Long64_t>::max() && fTreeReader &&
649 fTreeReader->SetEntriesRange(fGlobalEntryRange->first, fGlobalEntryRange->second) != TTreeReader::kEntryValid) {
650 throw std::logic_error("Something went wrong in initializing the TTreeReader.");
651 }
652}
653
655{
656 Initialize();
657 if (fTreeReader)
658 fTreeReader->SetSuppressErrorsForMissingBranches(suppressErrorsForMissingBranches);
659}
660
662{
663 if (fTreeReader->GetEntryStatus() != TTreeReader::kEntryBeyondEnd && nodesLeftNotRun) {
664 // something went wrong in the TTreeReader event loop
665 throw std::runtime_error("An error was encountered while processing the data. TTreeReader status code is: " +
666 std::to_string(fTreeReader->GetEntryStatus()));
667 }
668}
669
671{
672 assert(fTree);
673 return fTree.get();
674}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
Definition RtypesCore.h:84
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
The head node of a RDF computation graph.
std::vector< std::pair< ULong64_t, ULong64_t > > GetTTreeEntryRange(TTree &tree)
Definition RTTreeDS.cxx:579
std::size_t GetNFiles() const final
Returns the number of files from which the dataset is constructed.
Definition RTTreeDS.cxx:429
std::string DescribeDataset() final
Definition RTTreeDS.cxx:438
std::unique_ptr< ROOT::Internal::TreeUtils::RNoCleanupNotifier > fNoCleanupNotifier
Definition RTTreeDS.hxx:75
void Setup(std::shared_ptr< TTree > &&tree, const ROOT::TreeUtils::RFriendInfo *friendInfo=nullptr)
Definition RTTreeDS.cxx:262
void Initialize() final
Convenience method called before starting an event-loop.
Definition RTTreeDS.cxx:641
void Finalize() final
Convenience method called after concluding an event-loop.
Definition RTTreeDS.cxx:633
bool SetEntry(unsigned int, ULong64_t entry) final
Advance the "cursors" returned by GetColumnReaders to the selected entry for a particular slot.
Definition RTTreeDS.cxx:545
void InitializeWithOpts(const std::set< std::string > &suppressErrorsForMissingBranches) final
Definition RTTreeDS.cxx:654
std::vector< std::pair< ULong64_t, ULong64_t > > GetTChainEntryRange(TChain &chain)
Definition RTTreeDS.cxx:589
RTTreeDS(std::shared_ptr< TTree > tree)
Definition RTTreeDS.cxx:282
std::vector< std::pair< ULong64_t, ULong64_t > > GetEntryRanges() final
Return ranges of entries to distribute to tasks.
Definition RTTreeDS.cxx:610
std::shared_ptr< TTree > fTree
Definition RTTreeDS.hxx:67
std::string GetTypeName(std::string_view colName) const final
Type of a column as a string, e.g.
Definition RTTreeDS.cxx:566
A thread-safe list of N indexes (0 to size - 1).
friend std::string ROOT::Internal::RDF::GetTypeNameWithOpts(const RDataSource &, std::string_view, bool)
friend ROOT::RDF::RSampleInfo ROOT::Internal::RDF::CreateSampleInfo(const ROOT::RDF::RDataSource &, unsigned int, const std::unordered_map< std::string, ROOT::RDF::Experimental::RSample * > &)
friend std::unique_ptr< ROOT::Detail::RDF::RColumnReaderBase > ROOT::Internal::RDF::CreateColumnReader(ROOT::RDF::RDataSource &, unsigned int, std::string_view, const std::type_info &, TTreeReader *)
friend void ROOT::Internal::RDF::ProcessMT(RDataSource &, ROOT::Detail::RDF::RLoopManager &)
friend void ROOT::Internal::RDF::RunFinalChecks(const ROOT::RDF::RDataSource &, bool)
This type represents a sample identifier, to be used in conjunction with RDataFrame features such as ...
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...
const_iterator end() const
A Branch for the case of an object.
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
static TClass * Class()
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
Describe directory structure in memory.
Definition TDirectory.h:45
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
A TFriendElement TF describes a TTree object TF in a file.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
@ kIndexedFriendNoMatch
A friend with TTreeIndex doesn't have an entry for this index.
@ kMissingBranchWhenSwitchingTree
A branch was not found when switching to the next TTree in the chain.
@ kEntryBeyondEnd
last entry loop has reached its end
@ kEntryValid
data read okay
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
Definition TTree.cxx:4890
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5430
virtual Long64_t GetEntries() const
Definition TTree.h:510
virtual TObjArray * GetListOfBranches()
Definition TTree.h:575
virtual TTree * GetTree() const
Definition TTree.h:604
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6113
auto MakeAliasedSharedPtr(T *rawPtr)
Definition Utils.hxx:326
std::string TypeID2TypeName(const std::type_info &id)
Returns the name of a type starting from its type_info An empty string is returned in case of failure...
Definition RDFUtils.cxx:191
ROOT::RDataFrame FromTTree(std::string_view treeName, std::string_view fileNameGlob)
Definition RTTreeDS.cxx:357
std::string GetBranchOrLeafTypeName(TTree &t, const std::string &colName)
Return the typename of object colName stored in t, if any.
Definition RDFUtils.cxx:273
std::vector< std::string > GetTreeFullPaths(const TTree &tree)
std::vector< std::string > GetTopLevelBranchNames(TTree &t)
Get all the top-level branches names, including the ones of the friend trees.
std::unique_ptr< TChain > MakeChainForMT(const std::string &name="", const std::string &title="")
Create a TChain object with options that avoid common causes of thread contention.
std::vector< std::unique_ptr< TChain > > MakeFriends(const ROOT::TreeUtils::RFriendInfo &finfo)
Create friends from the main TTree.
ROOT::TreeUtils::RFriendInfo GetFriendInfo(const TTree &tree, bool retrieveEntries=false)
std::vector< std::string > GetFileNamesFromTree(const TTree &tree)
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:675
@ kSTLvector
Definition ESTLType.h:30
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Information about friend trees of a certain TTree or TChain object.