Logo ROOT  
Reference Guide
InternalTreeUtils.cxx
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
3  * All rights reserved. *
4  * *
5  * For the licensing terms see $ROOTSYS/LICENSE. *
6  * For the list of contributors see $ROOTSYS/README/CREDITS. *
7  *************************************************************************/
8 
10 #include "TTree.h"
11 #include "TChain.h"
12 #include "TFile.h"
13 #include "TFriendElement.h"
14 
15 #include <utility> // std::pair
16 #include <vector>
17 #include <stdexcept> // std::runtime_error
18 #include <string>
19 
20 namespace ROOT {
21 namespace Internal {
22 namespace TreeUtils {
23 
24 ////////////////////////////////////////////////////////////////////////////////
25 /// \fn std::vector<std::string> GetFileNamesFromTree(const TTree &tree)
26 /// \ingroup tree
27 /// \brief Get and store the file names associated with the input tree.
28 /// \param[in] tree The tree from which friends information will be gathered.
29 /// \throws std::runtime_error If no files could be associated with the input tree.
30 std::vector<std::string> GetFileNamesFromTree(const TTree &tree)
31 {
32  std::vector<std::string> filenames;
33 
34  // If the input tree is a TChain, traverse its list of associated files.
35  if (auto chain = dynamic_cast<const TChain *>(&tree)) {
36  const auto *chainFiles = chain->GetListOfFiles();
37  if (!chainFiles) {
38  throw std::runtime_error("Could not retrieve a list of files from the input TChain.");
39  }
40  // Store this in a variable so it can be later used in `filenames.reserve`
41  // if it passes the check.
42  const auto nfiles = chainFiles->GetEntries();
43  if (nfiles == 0) {
44  throw std::runtime_error("The list of files associated with the input TChain is empty.");
45  }
46  filenames.reserve(nfiles);
47  for (const auto *f : *chainFiles)
48  filenames.emplace_back(f->GetTitle());
49  } else {
50  const TFile *f = tree.GetCurrentFile();
51  if (!f) {
52  throw std::runtime_error("The input TTree is not linked to any file, "
53  "in-memory-only trees are not supported.");
54  }
55 
56  filenames.emplace_back(f->GetName());
57  }
58 
59  return filenames;
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// \fn RFriendInfo GetFriendInfo(const TTree &tree)
64 /// \ingroup tree
65 /// \brief Get and store the names, aliases and file names of the direct friends of the tree.
66 /// \param[in] tree The tree from which friends information will be gathered.
67 /// \throws std::runtime_error If the input tree has a list of friends, but any
68 /// of them could not be associated with any file.
69 ///
70 /// Calls TTree::GetListOfFriends and parses its result for the names, aliases
71 /// and file names, with different methodologies depending on whether the
72 /// parameter is a TTree or a TChain.
73 ///
74 /// \note This function only retrieves information about <b>direct friends</b>
75 /// of the input tree. It will not recurse through friends of friends and
76 /// does not take into account circular references in the list of friends
77 /// of the input tree.
78 ///
79 /// \returns An RFriendInfo struct, containing the information parsed from the
80 /// list of friends. The struct will contain three vectors, which elements at
81 /// position `i` represent the `i`-th friend of the input tree. If this friend
82 /// is a TTree, the `i`-th element of each of the three vectors will contain
83 /// respectively:
84 /// - A pair with the name and alias of the tree (the alias might not be
85 /// present, in which case it will be just an empty string).
86 /// - A vector with a single string representing the path to current file where
87 /// the tree is stored.
88 /// - An empty vector.
89 /// .
90 /// If the `i`-th friend is a TChain instead, the `i`-th element of each of the
91 /// three vectors will contain respectively:
92 /// - A pair with the name and alias of the chain (if present, both might be
93 /// empty strings).
94 /// - A vector with all the paths to the files contained in the chain.
95 /// - A vector with all the the names of the trees making up the chain,
96 /// associated with the file names of the previous vector.
98 {
99  std::vector<NameAlias> friendNames;
100  std::vector<std::vector<std::string>> friendFileNames;
101  std::vector<std::vector<std::string>> friendChainSubNames;
102 
103  // Typically, the correct way to call GetListOfFriends would be `tree.GetTree()->GetListOfFriends()`
104  // (see e.g. the discussion at https://github.com/root-project/root/issues/6741).
105  // However, in this case, in case we are dealing with a TChain we really only care about the TChain's
106  // list of friends (which will need to be rebuilt in each processing task) while friends of the TChain's
107  // internal TTree, if any, will be automatically loaded in each task just like they would be automatically
108  // loaded here if we used tree.GetTree()->GetListOfFriends().
109  const auto *friends = tree.GetListOfFriends();
110  if (!friends)
111  return RFriendInfo();
112 
113  for (auto fr : *friends) {
114  // Can't pass fr as const TObject* because TFriendElement::GetTree is not const.
115  // Also, we can't retrieve frTree as const TTree* because of TTree::GetFriendAlias(TTree *) a few lines later
116  auto frTree = static_cast<TFriendElement *>(fr)->GetTree();
117 
118  // The vector of (name,alias) pairs of the current friend
119  friendFileNames.emplace_back();
120  auto &fileNames = friendFileNames.back();
121 
122  // The vector of names of sub trees of the current friend, if it is a TChain.
123  // Otherwise, just an empty vector.
124  friendChainSubNames.emplace_back();
125  auto &chainSubNames = friendChainSubNames.back();
126 
127  // Check if friend tree/chain has an alias
128  const auto *alias_c = tree.GetFriendAlias(frTree);
129  const std::string alias = alias_c != nullptr ? alias_c : "";
130 
131  // If the current tree is a TChain
132  if (auto frChain = dynamic_cast<const TChain *>(frTree)) {
133  // Note that each TChainElement returned by TChain::GetListOfFiles has a name
134  // equal to the tree name of this TChain and a title equal to the filename.
135  // Accessing the information like this ensures that we get the correct
136  // filenames and treenames if the treename is given as part of the filename
137  // via chain.AddFile(file.root/myTree) and as well if the tree name is given
138  // in the constructor via TChain(myTree) and a file is added later by chain.AddFile(file.root).
139  // Caveat: The chain may be made of sub-trees with different names. All
140  // tree names need to be retrieved separately, see below.
141 
142  // Get filelist of the current chain
143  const auto *chainFiles = frChain->GetListOfFiles();
144  if (!chainFiles || chainFiles->GetEntries() == 0) {
145  throw std::runtime_error("A TChain in the list of friends does not contain any file. "
146  "Friends with no associated files are not supported.");
147  }
148 
149  // Retrieve the name of the chain and add a (name, alias) pair
150  friendNames.emplace_back(std::make_pair(frChain->GetName(), alias));
151  // Each file in the chain can contain a TTree with a different name wrt
152  // the main TChain. Retrieve the name of the file through `GetTitle`
153  // and the name of the tree through `GetName`
154  for (const auto *f : *chainFiles) {
155  chainSubNames.emplace_back(f->GetName());
156  fileNames.emplace_back(f->GetTitle());
157  }
158  } else {
159  // Get name of the tree
160  const auto realName = GetTreeFullPaths(*frTree)[0];
161  friendNames.emplace_back(std::make_pair(realName, alias));
162 
163  // Get filename
164  const auto *f = frTree->GetCurrentFile();
165  if (!f)
166  throw std::runtime_error("A TTree in the list of friends is not linked to any file. "
167  "Friends with no associated files are not supported.");
168  fileNames.emplace_back(f->GetName());
169  }
170  }
171 
172  return RFriendInfo{std::move(friendNames), std::move(friendFileNames), std::move(friendChainSubNames)};
173 }
174 
175 ////////////////////////////////////////////////////////////////////////////////
176 /// \fn std::vector<std::string> GetTreeFullPaths(const TTree &tree)
177 /// \ingroup tree
178 /// \brief Retrieve the full path(s) to a TTree or the trees in a TChain.
179 /// \param[in] tree The tree or chain from which the paths will be retrieved.
180 /// \throws std::runtime_error If the input tree is a TChain but no files could
181 /// be found associated with it.
182 /// \return If the input argument is a TChain, returns a vector of strings with
183 /// the name of the tree of each file in the chain. If the input
184 /// argument is a TTree, returns a vector with a single element that is
185 /// the full path of the tree in the file (e.g. the name of the tree
186 /// itself or the path with the directories inside the file). Finally,
187 /// the function returns a vector with just the name of the tree if it
188 /// couldn't do any better.
189 std::vector<std::string> GetTreeFullPaths(const TTree &tree)
190 {
191  // Case 1: this is a TChain. For each file it contains, GetName returns the name of the tree in that file
192  if (auto chain = dynamic_cast<const TChain *>(&tree)) {
193  const auto *chainFiles = chain->GetListOfFiles();
194  if (!chainFiles || chainFiles->GetEntries() == 0) {
195  throw std::runtime_error("The input TChain does not contain any file.");
196  }
197  std::vector<std::string> treeNames;
198  for (const auto *f : *chainFiles)
199  treeNames.emplace_back(f->GetName());
200 
201  return treeNames;
202  }
203 
204  // Case 2: this is a TTree: we get the full path of it
205  if (const auto *treeDir = tree.GetDirectory()) {
206  // We have 2 subcases (ROOT-9948):
207  // - 1. treeDir is a TFile: return the name of the tree.
208  // - 2. treeDir is a directory: reconstruct the path to the tree in the directory.
209  // Use dynamic_cast to check whether the directory is a TFile
210  if (dynamic_cast<const TFile *>(treeDir)) {
211  return {tree.GetName()};
212  }
213  std::string fullPath = treeDir->GetPath(); // e.g. "file.root:/dir"
214  fullPath = fullPath.substr(fullPath.find(":/") + 1); // e.g. "/dir"
215  fullPath += "/";
216  fullPath += tree.GetName(); // e.g. "/dir/tree"
217  return {fullPath};
218  }
219 
220  // We do our best and return the name of the tree
221  return {tree.GetName()};
222 }
223 
224 } // namespace TreeUtils
225 } // namespace Internal
226 } // namespace ROOT
f
#define f(i)
Definition: RSha256.hxx:104
InternalTreeUtils.hxx
ROOT::Internal::TreeUtils::GetTreeFullPaths
std::vector< std::string > GetTreeFullPaths(const TTree &tree)
Retrieve the full path(s) to a TTree or the trees in a TChain.
Definition: InternalTreeUtils.cxx:189
ROOT::Internal::TreeUtils::GetFriendInfo
RFriendInfo GetFriendInfo(const TTree &tree)
Get and store the names, aliases and file names of the direct friends of the tree.
Definition: InternalTreeUtils.cxx:97
tree
Definition: tree.py:1
TTree
A TTree represents a columnar dataset.
Definition: TTree.h:79
ROOT::Internal::TreeUtils::RFriendInfo
Information about friend trees of a certain TTree or TChain object.
Definition: InternalTreeUtils.hxx:42
TFriendElement
A TFriendElement TF describes a TTree object TF in a file.
Definition: TFriendElement.h:33
TFriendElement.h
TTree.h
TFile.h
TChain.h
ROOT::Internal::TreeUtils::GetFileNamesFromTree
std::vector< std::string > GetFileNamesFromTree(const TTree &tree)
Get and store the file names associated with the input tree.
Definition: InternalTreeUtils.cxx:30
extract_docstrings.filenames
filenames
Definition: extract_docstrings.py:27
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TChain
A chain is a collection of files containing TTree objects.
Definition: TChain.h:33
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4