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
64}
65
66bool ContainsLeaf(const std::set<TLeaf *> &leaves, TLeaf *leaf)
67{
68 return (leaves.find(leaf) != leaves.end());
69}
70
71///////////////////////////////////////////////////////////////////////////////
72/// This overload does not check whether the leaf/branch is already in bNamesReg. In case this is a friend leaf/branch,
73/// `allowDuplicates` controls whether we add both `friendname.bname` and `bname` or just the shorter version.
74void InsertBranchName(std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, const std::string &branchName,
75 const std::string &friendName, bool allowDuplicates)
76{
77 if (!friendName.empty()) {
78 // In case of a friend tree, users might prepend its name/alias to the branch names
79 const auto friendBName = friendName + "." + branchName;
80 if (bNamesReg.insert(friendBName).second)
81 bNames.push_back(friendBName);
82 }
83
84 if (allowDuplicates || friendName.empty()) {
85 if (bNamesReg.insert(branchName).second)
86 bNames.push_back(branchName);
87 }
88}
89
90///////////////////////////////////////////////////////////////////////////////
91/// This overload makes sure that the TLeaf has not been already inserted.
92void InsertBranchName(std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, const std::string &branchName,
93 const std::string &friendName, std::set<TLeaf *> &foundLeaves, TLeaf *leaf, bool allowDuplicates)
94{
96 if (!canAdd) {
97 return;
98 }
99
101
102 foundLeaves.insert(leaf);
103}
104
105void ExploreBranch(TTree &t, std::set<std::string> &bNamesReg, std::vector<std::string> &bNames, TBranch *b,
106 std::string prefix, std::string &friendName, bool allowDuplicates)
107{
108 // We want to avoid situations of overlap between the prefix and the
109 // sub-branch name that might happen when the branch is composite, e.g.
110 // prefix=reco_Wdecay2_from_tbar_4vect_NOSYS.fCoordinates.
111 // subBranchName=fCoordinates.fPt
112 // which would lead to a repetition of fCoordinates in the output branch name
113 // Boundary to search for the token before the last dot
114 auto prefixEndingDot = std::string::npos;
115 if (!prefix.empty() && prefix.back() == '.')
116 prefixEndingDot = prefix.size() - 2;
117 std::string lastPrefixToken{};
118 if (auto prefixLastRealDot = prefix.find_last_of('.', prefixEndingDot); prefixLastRealDot != std::string::npos)
120
121 for (auto sb : *b->GetListOfBranches()) {
122 TBranch *subBranch = static_cast<TBranch *>(sb);
123 auto subBranchName = std::string(subBranch->GetName());
124 auto fullName = prefix + subBranchName;
125
126 if (auto subNameFirstDot = subBranchName.find_first_of('.'); subNameFirstDot != std::string::npos) {
127 // Concatenate the prefix to the sub-branch name without overlaps
128 if (!lastPrefixToken.empty() && lastPrefixToken == subBranchName.substr(0, subNameFirstDot))
129 fullName = prefix + subBranchName.substr(subNameFirstDot + 1);
130 }
131
132 std::string newPrefix;
133 if (!prefix.empty())
134 newPrefix = fullName + ".";
135
137
138 auto branchDirectlyFromTree = t.GetBranch(fullName.c_str());
140 branchDirectlyFromTree = t.FindBranch(fullName.c_str()); // try harder
144
145 if (bNamesReg.find(subBranchName) == bNamesReg.end() && t.GetBranch(subBranchName.c_str()))
147 }
148}
149
150void GetBranchNamesImpl(TTree &t, std::set<std::string> &bNamesReg, std::vector<std::string> &bNames,
151 std::set<TTree *> &analysedTrees, std::string &friendName, bool allowDuplicates)
152{
153 std::set<TLeaf *> foundLeaves;
154 if (!analysedTrees.insert(&t).second) {
155 return;
156 }
157
158 const auto branches = t.GetListOfBranches();
159 // Getting the branches here triggered the read of the first file of the chain if t is a chain.
160 // We check if a tree has been successfully read, otherwise we throw (see ROOT-9984) to avoid further
161 // operations
162 if (!t.GetTree()) {
163 std::string err("GetBranchNames: error in opening the tree ");
164 err += t.GetName();
165 throw std::runtime_error(err);
166 }
167 if (branches) {
168 for (auto b : *branches) {
169 TBranch *branch = static_cast<TBranch *>(b);
170 const auto branchName = std::string(branch->GetName());
171 if (branch->IsA() == TBranch::Class()) {
172 // Leaf list
173 auto listOfLeaves = branch->GetListOfLeaves();
174 if (listOfLeaves->GetEntriesUnsafe() == 1) {
175 auto leaf = static_cast<TLeaf *>(listOfLeaves->UncheckedAt(0));
177 }
178
179 for (auto leaf : *listOfLeaves) {
180 auto castLeaf = static_cast<TLeaf *>(leaf);
181 const auto leafName = std::string(leaf->GetName());
182 const auto fullName = branchName + "." + leafName;
184 }
185 } else if (branch->IsA() == TBranchObject::Class()) {
186 // TBranchObject
189 } else {
190 // TBranchElement
191 // Check if there is explicit or implicit dot in the name
192
193 bool dotIsImplied = false;
194 auto be = dynamic_cast<TBranchElement *>(b);
195 if (!be)
196 throw std::runtime_error("GetBranchNames: unsupported branch type");
197 // TClonesArray (3) and STL collection (4)
198 if (be->GetType() == 3 || be->GetType() == 4)
199 dotIsImplied = true;
200
201 if (dotIsImplied || branchName.back() == '.')
203 else
205
207 }
208 }
209 }
210
211 // The list of friends needs to be accessed via GetTree()->GetListOfFriends()
212 // (and not via GetListOfFriends() directly), otherwise when `t` is a TChain we
213 // might not recover the list correctly (https://github.com/root-project/root/issues/6741).
214 auto friendTrees = t.GetTree()->GetListOfFriends();
215
216 if (!friendTrees)
217 return;
218
219 for (auto friendTreeObj : *friendTrees) {
220 auto friendTree = ((TFriendElement *)friendTreeObj)->GetTree();
221
222 std::string frName;
224 if (alias != nullptr)
225 frName = std::string(alias);
226 else
227 frName = std::string(friendTree->GetName());
228
230 }
231}
232
233///////////////////////////////////////////////////////////////////////////////
234/// Get all the branches names, including the ones of the friend trees
235std::vector<std::string> RetrieveDatasetSchema(TTree &t, bool allowDuplicates = true)
236{
237 std::set<std::string> bNamesSet;
238 std::vector<std::string> bNames;
239 std::set<TTree *> analysedTrees;
240 std::string emptyFrName = "";
242 return bNames;
243}
244} // namespace
245
246// Destructor is defined here, where the data member types are actually available
248{
250 // fNoCleanupNotifier was created only if the input TTree is a TChain
251 fNoCleanupNotifier->RemoveLink(*static_cast<TChain *>(fTree.get()));
252};
253
255{
256 fTree = tree;
257
258 if (friendInfo) {
260 for (std::size_t i = 0ul; i < fFriends.size(); i++) {
261 const auto &thisFriendAlias = friendInfo->fFriendNames[i].second;
262 fTree->AddFriend(fFriends[i].get(), thisFriendAlias.c_str());
263 }
264 }
265
266 if (fBranchNamesWithDuplicates.empty())
267 fBranchNamesWithDuplicates = RetrieveDatasetSchema(*fTree);
268 if (fBranchNamesWithoutDuplicates.empty())
269 fBranchNamesWithoutDuplicates = RetrieveDatasetSchema(*fTree, /*allowDuplicates*/ false);
270 if (fTopLevelBranchNames.empty())
271 fTopLevelBranchNames = ROOT::Internal::TreeUtils::GetTopLevelBranchNames(*fTree);
272}
273
274ROOT::Internal::RDF::RTTreeDS::RTTreeDS(std::shared_ptr<TTree> tree)
275{
276 assert(tree && "No tree passed to the constructor of RTTreeDS!");
277 Setup(std::move(tree));
278}
279
281{
282 assert(tree && "No tree passed to the constructor of RTTreeDS!");
283 Setup(std::move(tree), &friendInfo);
284}
285
287{
288 if (!dirPtr) {
289 throw std::runtime_error("RDataFrame: invalid TDirectory when constructing the data source.");
290 }
291 const std::string treeNameInt(treeName);
292 auto tree = dirPtr->Get<TTree>(treeName.data());
293 if (!tree) {
294 throw std::runtime_error("RDataFrame: TTree dataset '" + std::string(treeName) + "' cannot be found in '" +
295 dirPtr->GetName() + "'.");
296 }
298
299 // We keep the existing functionality from RLoopManager, until proven not necessary.
300 // See https://github.com/root-project/root/pull/10729
301 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
302 // a file name or list of file names, see
303 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
304 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
305 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
306 fNoCleanupNotifier->RegisterChain(*ch);
307 }
308}
309
311{
312 std::string treeNameInt{treeName};
313 std::string fileNameGlobInt{fileNameGlob};
315 chain->Add(fileNameGlobInt.c_str());
316
317 Setup(std::move(chain));
318 // We keep the existing functionality from RLoopManager, until proven not necessary.
319 // See https://github.com/root-project/root/pull/10729
320 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
321 // a file name or list of file names, see
322 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
323 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
324 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
325 fNoCleanupNotifier->RegisterChain(*ch);
326 }
327}
328
329ROOT::Internal::RDF::RTTreeDS::RTTreeDS(std::string_view treeName, const std::vector<std::string> &fileNameGlobs)
330{
331 std::string treeNameInt(treeName);
333 for (auto &&f : fileNameGlobs)
334 chain->Add(f.c_str());
335
336 Setup(std::move(chain));
337
338 // We keep the existing functionality from RLoopManager, until proven not necessary.
339 // See https://github.com/root-project/root/pull/10729
340 // The only constructors that were using this functionality are the ones taking a TDirectory * and the ones taking
341 // a file name or list of file names, see
342 // https://github.com/root-project/root/blob/f8b8277627f08cb79d71cec1006b219a82ae273c/tree/dataframe/src/RDataFrame.cxx
343 if (auto ch = dynamic_cast<TChain *>(fTree.get()); ch && !fNoCleanupNotifier) {
344 fNoCleanupNotifier = std::make_unique<ROOT::Internal::TreeUtils::RNoCleanupNotifier>();
345 fNoCleanupNotifier->RegisterChain(*ch);
346 }
347}
348
350{
351 return ROOT::RDataFrame(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(treeName, fileNameGlob));
352}
353
355ROOT::Internal::RDF::FromTTree(std::string_view treeName, const std::vector<std::string> &fileNameGlobs)
356{
357 return ROOT::RDataFrame(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(treeName, fileNameGlobs));
358}
359
361 unsigned int, const std::unordered_map<std::string, ROOT::RDF::Experimental::RSample *> &sampleMap) const
362{
363 // one GetTree to retrieve the TChain, another to retrieve the underlying TTree
364 auto *tree = fTreeReader->GetTree()->GetTree();
365 // tree might be missing e.g. when a file in a chain does not exist
366 if (!tree)
367 return ROOT::RDF::RSampleInfo{};
368
369 const std::string treename = ROOT::Internal::TreeUtils::GetTreeFullPaths(*tree)[0];
370 auto *file = tree->GetCurrentFile();
371 const std::string fname = file != nullptr ? file->GetName() : "#inmemorytree#";
372
373 std::pair<Long64_t, Long64_t> range = fTreeReader->GetEntriesRange();
374 R__ASSERT(range.first >= 0);
375 if (range.second == -1) {
376 range.second = tree->GetEntries(); // convert '-1', i.e. 'until the end', to the actual entry number
377 }
378 // If the tree is stored in a subdirectory, treename will be the full path to it starting with the root directory '/'
379 const std::string &id = fname + (treename.rfind('/', 0) == 0 ? "" : "/") + treename;
380 if (sampleMap.empty()) {
381 return RSampleInfo(id, range);
382 } else {
383 if (sampleMap.find(id) == sampleMap.end())
384 throw std::runtime_error("Full sample identifier '" + id + "' cannot be found in the available samples.");
385 return RSampleInfo(id, range, sampleMap.at(id));
386 }
387}
388
390{
391#ifdef R__USE_IMT
393 std::atomic<ULong64_t> entryCount(0ull);
394
395 const auto &entryList = fTree->GetEntryList() ? *fTree->GetEntryList() : TEntryList();
396 const auto &suppressErrorsForMissingBranches = lm.GetSuppressErrorsForMissingBranches();
397 auto tp{fGlobalEntryRange.has_value()
398 ? std::make_unique<ROOT::TTreeProcessorMT>(*fTree, fNSlots, fGlobalEntryRange.value(),
400 : std::make_unique<ROOT::TTreeProcessorMT>(*fTree, entryList, fNSlots, suppressErrorsForMissingBranches)};
401
402 tp->Process([&lm, &slotStack, &entryCount](TTreeReader &treeReader) {
403 lm.TTreeThreadTask(treeReader, slotStack, entryCount);
404 });
405
406 if (fGlobalEntryRange.has_value()) {
407 auto &&[begin, end] = fGlobalEntryRange.value();
408 auto &&processedEntries = entryCount.load();
409 if ((end - begin) > processedEntries) {
410 Warning("RDataFrame::Run",
411 "RDataFrame stopped processing after %lld entries, whereas an entry range (begin=%lld,end=%lld) was "
412 "requested. Consider adjusting the end value of the entry range to a maximum of %lld.",
413 processedEntries, begin, end, begin + processedEntries);
414 }
415 }
416#else
417 (void)lm;
418#endif
419}
420
422{
423 assert(fTree && "The internal TTree is not available, something went wrong.");
424 if (dynamic_cast<TChain *>(fTree.get()))
426
427 return fTree->GetCurrentFile() ? 1 : 0;
428}
429
431{
432 assert(fTree && "The internal TTree is not available, something went wrong.");
433 const auto treeName = fTree->GetName();
434 const auto isTChain = dynamic_cast<TChain *>(fTree.get()) ? true : false;
435 const auto treeType = isTChain ? "TChain" : "TTree";
436 const auto isInMemory = !isTChain && !fTree->GetCurrentFile() ? true : false;
438 const auto hasFriends = friendInfo.fFriendNames.empty() ? false : true;
439 std::stringstream ss;
440 ss << "Dataframe from " << treeType;
441 if (*treeName != 0) {
442 ss << " " << treeName;
443 }
444 if (isInMemory) {
445 ss << " (in-memory)";
446 } else {
448 const auto numFiles = files.size();
449 if (numFiles == 1) {
450 ss << " in file " << files[0];
451 } else {
452 ss << " in files\n";
453 for (auto i = 0u; i < numFiles; i++) {
454 ss << " " << files[i];
455 if (i < numFiles - 1)
456 ss << '\n';
457 }
458 }
459 }
460 if (hasFriends) {
461 const auto numFriends = friendInfo.fFriendNames.size();
462 if (numFriends == 1) {
463 ss << "\nwith friend\n";
464 } else {
465 ss << "\nwith friends\n";
466 }
467 for (auto i = 0u; i < numFriends; i++) {
468 const auto nameAlias = friendInfo.fFriendNames[i];
469 const auto files = friendInfo.fFriendFileNames[i];
470 const auto numFiles = files.size();
471 const auto subnames = friendInfo.fFriendChainSubNames[i];
472 ss << " " << nameAlias.first;
473 if (nameAlias.first != nameAlias.second)
474 ss << " (" << nameAlias.second << ")";
475 // case: TTree as friend
476 if (numFiles == 1) {
477 ss << " " << files[0];
478 }
479 // case: TChain as friend
480 else {
481 ss << '\n';
482 for (auto j = 0u; j < numFiles; j++) {
483 ss << " " << subnames[j] << " " << files[j];
484 if (j < numFiles - 1)
485 ss << '\n';
486 }
487 }
488 if (i < numFriends - 1)
489 ss << '\n';
490 }
491 }
492 return ss.str();
493}
494
495std::unique_ptr<ROOT::Detail::RDF::RColumnReaderBase>
496ROOT::Internal::RDF::RTTreeDS::CreateColumnReader(unsigned int /*slot*/, std::string_view col, const std::type_info &ti,
498{
499 // In a single thread run, use the TTreeReader data member.
500 if (fTreeReader) {
501 treeReader = fTreeReader.get();
502 }
503
504 // The TTreeReader might still not be available if CreateColumnReader was called before the start of the computation
505 // graph execution, e.g. in AddDSColumns.
506 if (!treeReader)
507 return nullptr;
508
509 if (ti == typeid(void))
510 return std::make_unique<ROOT::Internal::RDF::RTreeOpaqueColumnReader>(*treeReader, col);
511
512 const auto typeName = ROOT::Internal::RDF::TypeID2TypeName(ti);
513 if (auto &&[toConvert, innerTypeName, collType] = GetCollectionInfo(typeName); toConvert)
514 return std::make_unique<ROOT::Internal::RDF::RTreeUntypedArrayColumnReader>(*treeReader, col, innerTypeName,
515 collType);
516 else
517 return std::make_unique<ROOT::Internal::RDF::RTreeUntypedValueColumnReader>(*treeReader, col, typeName);
518}
519
521{
522 // The first entry of each tree in a chain is read in GetEntryRanges, we avoid repeating it here
523 if (fTreeReader->GetCurrentEntry() != static_cast<Long64_t>(entry))
524 fTreeReader->SetEntry(entry);
525 return ValidRead(fTreeReader->GetEntryStatus());
526}
527
529{
532 std::vector<std::string> split;
533 int dummy;
534 TClassEdit::GetSplit(colTypeName.c_str(), split, dummy);
535 auto &valueType = split[1];
536 colTypeName = "ROOT::VecOps::RVec<" + valueType + ">";
537 }
538 return colTypeName;
539}
540
541std::string ROOT::Internal::RDF::RTTreeDS::GetTypeName(std::string_view colName) const
542{
545 std::vector<std::string> split;
546 int dummy;
547 TClassEdit::GetSplit(colTypeName.c_str(), split, dummy);
548 auto &valueType = split[1];
549 colTypeName = "ROOT::VecOps::RVec<" + valueType + ">";
550 }
551 return colTypeName;
552}
553
554std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetTTreeEntryRange(TTree &tree)
555{
556 // Restrict the range to the global range if available
557 const ULong64_t rangeBegin = fGlobalEntryRange.has_value() ? std::max(0ull, fGlobalEntryRange->first) : 0ull;
558 const ULong64_t rangeEnd = fGlobalEntryRange.has_value()
559 ? std::min(static_cast<ULong64_t>(tree.GetEntries()), fGlobalEntryRange->second)
560 : static_cast<ULong64_t>(tree.GetEntries());
561 return std::vector<std::pair<ULong64_t, ULong64_t>>{{rangeBegin, rangeEnd}};
562}
563
564std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetTChainEntryRange(TChain &chain)
565{
566 // We are either at a complete new beginning (entry == -1) or at the
567 // end of processing of the previous tree in the chain. Go to the next
568 // entry, which should always be the first entry in a tree. This allows
569 // to get the proper tree offset for the range.
570 fTreeReader->Next();
571 if (!ValidRead(fTreeReader->GetEntryStatus()))
572 return {};
573 auto treeOffsets = chain.GetTreeOffset();
574 auto treeNumber = chain.GetTreeNumber();
577 // Restrict the range to the global range if available
578 const ULong64_t rangeBegin =
579 fGlobalEntryRange.has_value() ? std::max(thisTreeBegin, fGlobalEntryRange->first) : thisTreeBegin;
580 const ULong64_t rangeEnd =
581 fGlobalEntryRange.has_value() ? std::min(thisTreeEnd, fGlobalEntryRange->second) : thisTreeEnd;
582 return std::vector<std::pair<ULong64_t, ULong64_t>>{{rangeBegin, rangeEnd}};
583}
584
585std::vector<std::pair<ULong64_t, ULong64_t>> ROOT::Internal::RDF::RTTreeDS::GetEntryRanges()
586{
587 assert(fTreeReader && "TTreeReader is not available, this should never happen.");
588 auto treeOrChain = fTreeReader->GetTree();
589 assert(treeOrChain && "Could not retrieve TTree from TTreeReader, something went wrong.");
590
591 // End of dataset or entry range
592 if (fTreeReader->GetCurrentEntry() >= treeOrChain->GetEntriesFast() - 1 ||
593 (fGlobalEntryRange.has_value() &&
594 (static_cast<ULong64_t>(fTreeReader->GetCurrentEntry()) >= fGlobalEntryRange->first &&
595 static_cast<ULong64_t>(fTreeReader->GetCurrentEntry()) == fGlobalEntryRange->second - 1))) {
596 // Place the TTreeReader beyond the end of the dataset, so RunFinalChecks can work properly
597 fTreeReader->Next();
598 return {};
599 }
600
601 if (auto chain = dynamic_cast<TChain *>(treeOrChain)) {
602 return GetTChainEntryRange(*chain);
603 } else {
604 return GetTTreeEntryRange(*treeOrChain);
605 }
606}
607
609{
610 // At the end of the event loop, reset the TTreeReader to be ready for
611 // a possible new run.
612 if (fTreeReader)
613 fTreeReader.reset();
614}
615
617{
618 if (fNSlots == 1) {
619 assert(!fTreeReader);
620 fTreeReader = std::make_unique<TTreeReader>(fTree.get(), fTree->GetEntryList(), /*warnAboutLongerFriends*/ true);
621 if (fGlobalEntryRange.has_value() && fGlobalEntryRange->first <= std::numeric_limits<Long64_t>::max() &&
622 fGlobalEntryRange->second <= std::numeric_limits<Long64_t>::max() && fTreeReader &&
623 fTreeReader->SetEntriesRange(fGlobalEntryRange->first, fGlobalEntryRange->second) !=
625 throw std::logic_error("Something went wrong in initializing the TTreeReader.");
626 }
627 }
628}
629
631{
632 Initialize();
633 if (fTreeReader)
634 fTreeReader->SetSuppressErrorsForMissingBranches(suppressErrorsForMissingBranches);
635}
636
638{
639 if (fTreeReader->GetEntryStatus() != TTreeReader::kEntryBeyondEnd && nodesLeftNotRun) {
640 // something went wrong in the TTreeReader event loop
641 throw std::runtime_error("An error was encountered while processing the data. TTreeReader status code is: " +
642 std::to_string(fTreeReader->GetEntryStatus()));
643 }
644}
645
647{
648 assert(fTree);
649 return fTree.get();
650}
#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:554
std::size_t GetNFiles() const final
Returns the number of files from which the dataset is constructed.
Definition RTTreeDS.cxx:421
std::string DescribeDataset() final
Definition RTTreeDS.cxx:430
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:254
void Initialize() final
Convenience method called before starting an event-loop.
Definition RTTreeDS.cxx:616
void Finalize() final
Convenience method called after concluding an event-loop.
Definition RTTreeDS.cxx:608
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:520
void InitializeWithOpts(const std::set< std::string > &suppressErrorsForMissingBranches) final
Definition RTTreeDS.cxx:630
std::vector< std::pair< ULong64_t, ULong64_t > > GetTChainEntryRange(TChain &chain)
Definition RTTreeDS.cxx:564
RTTreeDS(std::shared_ptr< TTree > tree)
Definition RTTreeDS.cxx:274
std::vector< std::pair< ULong64_t, ULong64_t > > GetEntryRanges() final
Return ranges of entries to distribute to tasks.
Definition RTTreeDS.cxx:585
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:541
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:4891
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5431
virtual TObjArray * GetListOfBranches()
Definition TTree.h:565
virtual TTree * GetTree() const
Definition TTree.h:594
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition TTree.cxx:6114
auto MakeAliasedSharedPtr(T *rawPtr)
Definition Utils.hxx:323
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:178
ROOT::RDataFrame FromTTree(std::string_view treeName, std::string_view fileNameGlob)
Definition RTTreeDS.cxx:349
std::string GetBranchOrLeafTypeName(TTree &t, const std::string &colName)
Return the typename of object colName stored in t, if any.
Definition RDFUtils.cxx:255
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)
@ 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.