Belle II Software  release-05-02-19
RootIOUtilities.cc
1 #include <framework/io/RootIOUtilities.h>
2 
3 #include <framework/datastore/DataStore.h>
4 #include <framework/dataobjects/FileMetaData.h>
5 #include <framework/logging/Logger.h>
6 
7 #include <RVersion.h>
8 #include <TTree.h>
9 #include <TList.h>
10 #include <TClass.h>
11 #include <TBaseClass.h>
12 #include <TSystem.h>
13 
14 #include <wordexp.h>
15 
16 #include <queue>
17 
18 using namespace Belle2;
19 
20 const std::string RootIOUtilities::c_treeNames[] = { "tree", "persistent" };
21 const std::string RootIOUtilities::c_SteerBranchNames[] = { "branchNames", "branchNamesPersistent" };
22 const std::string RootIOUtilities::c_SteerExcludeBranchNames[] = { "excludeBranchNames", "excludeBranchNamesPersistent" };
23 const std::string RootIOUtilities::c_SteerAdditionalBranchNames[] = { "additionalBranchNames", "additionalBranchNamesPersistent" };
24 
25 std::set<std::string> RootIOUtilities::filterBranches(const std::set<std::string>& branchesToFilter,
26  const std::vector<std::string>& branches,
27  const std::vector<std::string>& excludeBranches, int durability, bool quiet)
28 {
29  std::set<std::string> branchSet, excludeBranchSet;
30  for (const std::string& b : branches) {
31  if (branchesToFilter.count(b) == 0 and not quiet)
32  B2WARNING("The branch " << b << " given in " << c_SteerBranchNames[durability] << " does not exist.");
33  if (!branchSet.insert(b).second and not quiet)
34  B2WARNING(c_SteerBranchNames[durability] << " has duplicate entry " << b);
35  }
36  for (const std::string& b : excludeBranches) {
37  // FIXME: ProcessStatistics is excluded by default but not always present. We should switch that to not write it out
38  // in the first place but the info message is meaningless for almost everyone
39  if (branchesToFilter.count(b) == 0 and not quiet and b != "ProcessStatistics")
40  B2INFO("The branch " << b << " given in " << c_SteerExcludeBranchNames[durability] << " does not exist.");
41  if (!excludeBranchSet.insert(b).second and not quiet)
42  B2WARNING(c_SteerExcludeBranchNames[durability] << " has duplicate entry " << b);
43  }
44 
45  std::set<std::string> out, relations, excluderelations;
46  for (const std::string& branch : branchesToFilter) {
47  if (excludeBranchSet.count(branch))
48  continue;
49  if (branchSet.empty() or branchSet.count(branch))
50  out.insert(branch);
51  }
52  if (!excludeBranchSet.empty()) {
53  //remove relations for excluded things
54  for (const std::string& from : branchesToFilter) {
55  for (const std::string& to : branchesToFilter) {
56  std::string branch = DataStore::relationName(from, to);
57  if (out.count(branch) == 0)
58  continue; //not selected
59  if (excludeBranchSet.count(from) == 0 and excludeBranchSet.count(to) == 0)
60  continue; //at least one side should be excluded
61  if (branchSet.count(branch) != 0)
62  continue; //specifically included
63  excluderelations.insert(branch);
64  }
65  }
66  for (const std::string& rel : excluderelations) {
67  out.erase(rel);
68  }
69  }
70  //add relations between accepted branches
71  for (const std::string& from : out) {
72  for (const std::string& to : out) {
73  std::string branch = DataStore::relationName(from, to);
74  if (branchesToFilter.count(branch) == 0)
75  continue; //not in input
76  if (excludeBranchSet.count(branch))
77  continue;
78  relations.insert(branch);
79  }
80  }
81  out.insert(relations.begin(), relations.end());
82  return out;
83 }
84 
85 size_t RootIOUtilities::setBranchStatus(TBranch* branch, bool process)
86 {
87  size_t found{0};
88  std::queue<TBranch*> branches;
89  branches.emplace(branch);
90  while (!branches.empty()) {
91  ++found;
92  auto* current = branches.front();
93  branches.pop();
94  // set the flag we need
95  if (process) current->ResetBit(kDoNotProcess);
96  else current->SetBit(kDoNotProcess);
97  // add all children to the queue
98  auto* children = current->GetListOfBranches();
99  const auto nchildren = children->GetEntriesFast();
100  for (int i = 0; i < nchildren; ++i) {
101  branches.emplace(dynamic_cast<TBranch*>(children->UncheckedAt(i)));
102  }
103  }
104  return found;
105 }
106 
107 std::vector<std::string> RootIOUtilities::expandWordExpansions(const std::vector<std::string>& filenames)
108 {
109  std::vector<std::string> out;
110  wordexp_t expansions;
111  wordexp("", &expansions, 0);
112  for (const std::string& pattern : filenames) {
113  if (wordexp(pattern.c_str(), &expansions, WRDE_APPEND | WRDE_NOCMD | WRDE_UNDEF) != 0) {
114  B2ERROR("Failed to expand pattern '" << pattern << "'!");
115  }
116  }
117  out.resize(expansions.we_wordc);
118  for (unsigned int i = 0; i < expansions.we_wordc; i++) {
119  out[i] = expansions.we_wordv[i];
120  }
121  wordfree(&expansions);
122  return out;
123 }
124 
125 
126 long RootIOUtilities::getEntryNumberWithEvtRunExp(TTree* tree, long event, long run, long experiment)
127 {
128  const long major = 1000000 * experiment + run;
129  const long minor = event;
130 
131  if (!tree->GetTreeIndex()) {
132  B2DEBUG(100, "No TTreeIndex found, rebuild it...");
133  buildIndex(tree);
134  }
135  long entry = tree->GetEntryNumberWithIndex(major, minor);
136 
137  if (entry == -1) {
138  //should be handled by caller
139  B2DEBUG(100, "Couldn't find entry (" << event << ", " << run << ", " << experiment << ") in file! (major index: " << major <<
140  ", minor index: " << minor << ")");
141  }
142  return entry;
143 }
144 
146 {
147  tree->BuildIndex("1000000*EventMetaData.m_experiment+EventMetaData.m_run", "EventMetaData.m_event");
148 }
149 
150 bool RootIOUtilities::hasStreamer(const TClass* cl)
151 {
152  if (cl == TObject::Class())
153  return false;
154 
155  if (cl->GetClassVersion() <= 0) {
156  // version number == 0 means no streamers for this class, check base classes
157  TList* baseClasses = const_cast<TClass*>(cl)->GetListOfBases(); //method might update an internal cache, but is const otherwise
158  TIter it(baseClasses);
159  while (auto* base = static_cast<TBaseClass*>(it())) {
160  if (hasStreamer(base->GetClassPointer()))
161  return true;
162  }
163  //nothing found
164  return false;
165  } else {
166  return true;
167  }
168 }
169 
170 
172 {
173  //does this class have a custom streamer? (magic from from TTree.cxx)
174  return cl->TestBit(TClass::kHasCustomStreamerMember);
175 }
176 
178 {
179  std::string site;
180  char date[100];
181  auto now = time(nullptr);
182  strftime(date, 100, "%Y-%m-%d %H:%M:%S", gmtime(&now));
183  const char* belle2_site = getenv("BELLE2_SITE");
184  if (belle2_site) {
185  site = belle2_site;
186  } else {
187  char hostname[1024];
188  gethostname(hostname, 1023); //will not work well for ipv6
189  hostname[1023] = '\0'; //if result is truncated, terminating null byte may be missing
190  site = hostname;
191  }
192  const char* user = getenv("BELLE2_USER");
193  if (!user) user = getenv("USER");
194  if (!user) user = getlogin();
195  if (!user) user = "unknown";
196  auto commitid = RootIOUtilities::getCommitID();
197  metadata.setCreationData(date, site, user, commitid);
198 }
199 
201 {
202  return GIT_COMMITID;
203 }
Belle2::RootIOUtilities::c_SteerAdditionalBranchNames
const std::string c_SteerAdditionalBranchNames[]
Steering parameter names for m_additionalBranchNames.
Definition: RootIOUtilities.cc:23
Belle2::RootIOUtilities::c_SteerBranchNames
const std::string c_SteerBranchNames[]
Steering parameter names for m_branchNames.
Definition: RootIOUtilities.cc:21
Belle2::RootIOUtilities::getCommitID
std::string getCommitID()
Return git SHA1 hashes taking into account local & central release.
Definition: RootIOUtilities.cc:200
Belle2::RootIOUtilities::hasStreamer
bool hasStreamer(const TClass *cl)
Returns true if and only if 'cl' or one of its bases has I/O streamers.
Definition: RootIOUtilities.cc:150
Belle2::RootIOUtilities::c_SteerExcludeBranchNames
const std::string c_SteerExcludeBranchNames[]
Steering parameter names for m_excludeBranchNames.
Definition: RootIOUtilities.cc:22
Belle2::RootIOUtilities::c_treeNames
const std::string c_treeNames[]
Names of trees.
Definition: RootIOUtilities.cc:20
Belle2::RootIOUtilities::hasCustomStreamer
bool hasCustomStreamer(const TClass *cl)
Returns true if and only if 'cl' has a user-defined streamer.
Definition: RootIOUtilities.cc:171
Belle2::FileMetaData
Metadata information about a file.
Definition: FileMetaData.h:39
Belle2::RootIOUtilities::buildIndex
void buildIndex(TTree *tree)
Build TTreeIndex on tree (assumes EventMetaData branch exists there).
Definition: RootIOUtilities.cc:145
Belle2::RootIOUtilities::expandWordExpansions
std::vector< std::string > expandWordExpansions(const std::vector< std::string > &filenames)
Performs wildcard expansion using wordexp(), returns matches.
Definition: RootIOUtilities.cc:107
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::RootIOUtilities::setCreationData
void setCreationData(FileMetaData &metadata)
Fill the creation info of a file meta data: site, user, data.
Definition: RootIOUtilities.cc:177
Belle2::RootIOUtilities::filterBranches
std::set< std::string > filterBranches(const std::set< std::string > &branchesToFilter, const std::vector< std::string > &branches, const std::vector< std::string > &excludeBranches, int durability, bool quiet=false)
Given a list of input branches and lists of branches to include/exclude, returns a list of branches t...
Definition: RootIOUtilities.cc:25
Belle2::RootIOUtilities::setBranchStatus
size_t setBranchStatus(TBranch *branch, bool process)
Set Branch to be read or not.
Definition: RootIOUtilities.cc:85
Belle2::DataStore::relationName
static std::string relationName(const std::string &fromName, const std::string &toName, std::string const &namedRelation="")
Return storage name for a relation between two arrays of the given names.
Definition: DataStore.h:182
Belle2::RootIOUtilities::getEntryNumberWithEvtRunExp
long getEntryNumberWithEvtRunExp(TTree *tree, long event, long run, long experiment)
return entry number with given (event, run, experiment) from tree.
Definition: RootIOUtilities.cc:126