GGS(GenericGEANT4Simulation)Software  2.7.0
 All Data Structures Namespaces Files Functions Variables Typedefs Macros
GGSTRootReader.cpp
Go to the documentation of this file.
1 /*
2  * GGSTRootReader.cpp
3  *
4  * Created on: 23 Aug 2011
5  * Author: Nicola Mori
6  */
7 
10 // GGS headers
12 #include "utils/GGSSmartLog.h"
13 
14 // Boost headers
15 #include "boost/filesystem.hpp"
16 #include "boost/regex.hpp"
17 
18 // Root headers
19 #include "TString.h"
20 
21 // C++ headers
22 #include <algorithm>
23 #include <fstream>
24 
25 GGSTRootReader::GGSTRootReader() : _currentEv(-1) {}
26 
28  for (unsigned int iHandler = 0; iHandler < _filesHandlers.size(); iHandler++) {
29  delete _filesHandlers[iHandler];
30  }
31  for (unsigned int iReader = 0; iReader < _readers.size(); iReader++) {
32  delete _readers[iReader];
33  }
34 }
35 
36 GGSTFilesHandler *GGSTRootReader::Open(const std::string &fileName, GGSTFilesHandler *filesHandler, bool force) {
37  static const std::string routineName("GGSTRootReader::Open");
38 
39  GGSTFilesHandler *handler = nullptr;
40  if (filesHandler == nullptr)
41  handler = new GGSTFilesHandler;
42  else {
43  handler = filesHandler;
44  if (find(_filesHandlers.begin(), _filesHandlers.end(), handler) == _filesHandlers.end())
45  _filesHandlers.push_back(handler);
46  }
47 
48  if (fileName.find('?') != std::string::npos || fileName.find('*') != std::string::npos) {
49  // ******* Name with wildcards *******
50 
51  // ++++ Convert fileName into a regular expression ++++
52  std::string regExpFiles(fileName);
53  // 1. escape all .
54  std::string::size_type pos = 0;
55  while ((pos = regExpFiles.find('.', pos)) != std::string::npos) {
56  regExpFiles.replace(pos, 1, "\\.");
57  pos += 2;
58  }
59  // 2. convert all * to .*
60  pos = 0;
61  while ((pos = regExpFiles.find('*', pos)) != std::string::npos) {
62  regExpFiles.replace(pos, 1, ".*");
63  pos += 2;
64  }
65  // 3. convert all ? to .
66  std::replace(regExpFiles.begin(), regExpFiles.end(), '?', '.');
67 
68  // ++++ Search files using Boost.FileSystem ++++
69  std::string basePathName(fileName);
70  // Extract path
71  size_t posOfLastSlash = basePathName.find_last_of('/');
72  if (posOfLastSlash != std::string::npos)
73  basePathName.erase(posOfLastSlash);
74  else
75  basePathName = boost::filesystem::current_path().string();
76 
77  boost::filesystem::path basePath(basePathName);
78  boost::filesystem::absolute(basePath);
79 
80  boost::filesystem::directory_iterator endItr; // Default constructor yields past-the-end
81  boost::filesystem::directory_iterator dirIter(basePath);
82  if (dirIter == endItr) {
83  if (filesHandler == nullptr)
84  delete handler;
85  return nullptr;
86  }
87 
88  for (; dirIter != endItr; ++dirIter) {
89  // Skip if not a file
90  if (!is_regular_file(dirIter->status()))
91  continue;
92  boost::smatch what;
93  // Skip if no match
94  if (!boost::regex_match(dirIter->path().string(), what, boost::regex(regExpFiles)))
95  continue;
96  // Skip if not a Root file
97  if (dirIter->path().string().substr(dirIter->path().string().size() - 5) != ".root")
98  continue;
99  // File matches, store it
100  handler->_AddFile(dirIter->path().string(), force);
101  }
102  if (handler->GetNFiles() == 0) {
103  COUT(WARNING) << fileName << ": no file found." << ENDL;
104  delete handler;
105  return nullptr;
106  }
107  handler->_SortFiles();
108 
109  } else if (fileName.substr(fileName.size() - 4) == ".txt") {
110  // ******* Text file with file names *******
111  if (boost::filesystem::exists(fileName)) {
112  std::ifstream file(fileName.data(), std::ios::in);
113  std::string currFile;
114  while (file.good()) {
115  getline(file, currFile);
116  if (boost::filesystem::exists(currFile) && currFile.substr(currFile.size() - 5) == ".root")
117  handler->_AddFile(currFile, force);
118  }
119  } else {
120  if (filesHandler == nullptr)
121  delete handler;
122  return nullptr;
123  }
124  } else if (fileName.substr(fileName.size() - 5) == ".root") {
125  // ******* Single root file *******
126  if (boost::filesystem::exists(fileName))
127  handler->_AddFile(fileName, force);
128  else {
129  if (filesHandler == nullptr)
130  delete handler;
131  return nullptr;
132  }
133  } else {
134  if (filesHandler == nullptr)
135  delete handler;
136  return nullptr;
137  }
138 
139  if (find(_filesHandlers.begin(), _filesHandlers.end(), handler) == _filesHandlers.end())
140  _filesHandlers.push_back(handler);
141  return handler;
142 }
143 
144 TChain *GGSTRootReader::_FindChain(const TString &treeName, GGSTFilesHandler *filesHandler) {
145 
146  // Search in files handler (chain already opened by another reader)
147  for (unsigned int iChain = 0; iChain < filesHandler->_chains.size(); iChain++) {
148  if (filesHandler->_chains[iChain]->GetName() == treeName) {
149  return filesHandler->_chains[iChain];
150  }
151  }
152 
153  // Search in files handled by the handler
154  return _CreateChain(treeName, filesHandler);
155 }
156 
157 TChain *GGSTRootReader::_CreateChain(const TString &treeName, GGSTFilesHandler *filesHandler) {
158 
159  static const std::string routineName("GGSTRootReader::_CreateChain");
160  std::vector<TChain *> chains(1);
161  chains[0] = new TChain(treeName);
162  unsigned int iFile = 0;
163 
164  // Find the first file containing the desired tree
165  while (iFile < filesHandler->_files.size()) {
166  TFile *file = TFile::Open(filesHandler->_files[iFile].data());
167  TTree *tree = dynamic_cast<TTree *>(file->Get(treeName));
168  if (tree) {
169  chains[0]->Add(filesHandler->_files[iFile].data(), 0);
170  chains[0]->SetTitle(tree->GetTitle());
171  delete file;
172  break;
173  }
174  iFile++;
175  delete file;
176  }
177 
178  if (iFile == filesHandler->_files.size()) {
179  // Tree not found in any file
180  delete chains[0];
181  return nullptr;
182  }
183 
184  // First tree found.
185  for (iFile += 1; iFile < filesHandler->_files.size(); iFile++) {
186  TFile *file = TFile::Open(filesHandler->_files[iFile].data());
187  if (!(file->IsZombie())) {
188  TTree *tree = dynamic_cast<TTree *>(file->Get(treeName));
189  if (tree) {
190  // Check if branches match with at least one chain
191  bool chainNotFound = true;
192  for (unsigned int iChain = 0; iChain < chains.size(); iChain++) {
193  if (_CheckBranches(chains[iChain], tree)) {
194  // Number of branches and branch names match. Add this file to the current chain.
195  chains[iChain]->Add(filesHandler->_files[iFile].data(), 0);
196  chainNotFound = false;
197  delete file;
198  file = nullptr;
199  break;
200  }
201  }
202  if (chainNotFound) {
203  chains.push_back(new TChain(treeName));
204  chains.back()->SetTitle(tree->GetTitle());
205  chains.back()->Add(filesHandler->_files[iFile].data(), 0);
206  }
207  }
208  }
209  delete file;
210  }
211 
212  // Set friends if more than one chain has been created
213  for (unsigned int iChain = 1; iChain < chains.size(); iChain++) {
214  if (chains[iChain]->GetEntries() != chains[0]->GetEntries()) {
215  COUT(ERROR) << "Mismatch in number of elements:" << ENDL;
216  CCOUT(ERROR) << " Chain 0: " << chains[0]->GetEntries() << " entries" << ENDL;
217  CCOUT(ERROR) << " Title: \"" << chains[0]->GetTitle() << "\"" << ENDL;
218  CCOUT(ERROR) << " Chain " << iChain << ": " << chains[iChain]->GetEntries() << " entries" << ENDL;
219  CCOUT(ERROR) << " Title \": " << chains[iChain]->GetTitle() << "\"" << ENDL;
220  for (unsigned int iChain1 = 0; iChain1 < chains.size(); iChain1++) {
221  delete chains[iChain1];
222  return nullptr;
223  }
224  } else {
225  chains[0]->AddFriend(chains[iChain]);
226  }
227  }
228 
229  // Pass the ownership of all the chains to the file handler
230  for (unsigned int iChain = 0; iChain < chains.size(); iChain++) {
231  filesHandler->_chains.push_back(chains[iChain]);
232  }
233 
234  return chains[0];
235 }
236 
237 bool GGSTRootReader::_CheckBranches(TTree *tree1, TTree *tree2) {
238 
239  TObjArray *branchesInTree1 = tree1->GetListOfBranches();
240  // Retrieve the list of branches in the current tree
241  TObjArray *branchesInTree2 = tree2->GetListOfBranches();
242  // Check if the two lists have the same number of branches with the same names
243  if (branchesInTree1->GetEntries() == branchesInTree2->GetEntries()) {
244  for (int iBranch = 0; iBranch < branchesInTree1->GetEntries(); iBranch++) {
245  if (strcmp(((TBranch *)(branchesInTree1->At(iBranch)))->GetName(),
246  ((TBranch *)(branchesInTree2->At(iBranch)))->GetName())) {
247  return false;
248  }
249  }
250  } else
251  return false;
252 
253  return true;
254 }
255 
256 Long64_t GGSTRootReader::_GetEntriesBlind() {
257 
258  if (_filesHandlers.size() == 0)
259  return 0;
260 
261  if (_filesHandlers[0]->_files.size() == 0)
262  return 0;
263 
264  TFile *file = TFile::Open(_filesHandlers[0]->_files[0].data());
265  TString treeName("");
266  TList *keysList = file->GetListOfKeys();
267  for (int iKey = 0; iKey < keysList->GetEntries(); iKey++) {
268  TString keyName(keysList->At(iKey)->GetName());
269  TTree *key = dynamic_cast<TTree *>(file->Get(keyName));
270  if (key != nullptr) {
271  treeName = ((TTree *)key)->GetName();
272  }
273  }
274 
275  delete file;
276  file = nullptr;
277  if (treeName == "")
278  return 0;
279 
280  TChain *chain = _CreateChain(treeName, _filesHandlers[0]);
281  Long64_t nEntries = 0;
282  if (chain)
283  nEntries = chain->GetEntries();
284  delete chain;
285 
286  return nEntries;
287 }
288 
289 void GGSTRootReader::GetEntry(Long64_t entry) {
290 
291  for (unsigned int i = 0; i < _readers.size(); i++) {
292  _readers[i]->reader->GetEntry(entry);
293  }
294  _currentEv = entry;
295 }
296 
298  static const std::string routineName("GGSTRootReader::GetEntries");
299 
300  if (_readers.size() > 0)
301  return _readers[0]->chain->GetEntries();
302  else {
303  COUT(WARNING) << "GetEntries may return a wrong number of entries when called before GetReader." << ENDL;
304  return _GetEntriesBlind();
305  }
306 }
307 
309 
310  if (filesHandler == nullptr) {
311  if (_filesHandlers.size() > 0)
312  filesHandler = _filesHandlers[0];
313  else
314  return nullptr;
315  }
316 
317  return &(filesHandler->_simInfo);
318 }
319 
321 
322  if (filesHandler == nullptr) {
323  if (_filesHandlers.size() > 0)
324  filesHandler = _filesHandlers[0];
325  else
326  return nullptr;
327  }
328 
329  return &(filesHandler->_geoParams);
330 }
331 
333 
334  if (filesHandler == nullptr) {
335  if (_filesHandlers.size() > 0)
336  filesHandler = _filesHandlers[0];
337  else
338  return nullptr;
339  }
340 
341  return &(filesHandler->_genParams);
342 }
343 
344 const TGeoManager *GGSTRootReader::GetROOTGeometry(const GGSTFilesHandler *filesHandler) {
345  if (filesHandler == nullptr) {
346  if (_filesHandlers.size() > 0)
347  filesHandler = _filesHandlers[0];
348  else
349  return nullptr;
350  }
351 
352  return filesHandler->_geoManager;
353 }
const GGSTGeoParams * GetGeoParams(const GGSTFilesHandler *filesHandler=nullptr)
Returns the geometry parameters.
#define ENDL
Definition: GGSSmartLog.h:105
~GGSTRootReader()
Destructor.
#define COUT(level)
Smart log macro. It writes on stdout only if the specified verbosity level is lesser than the maximum...
Definition: GGSSmartLog.h:76
Long64_t GetEntries()
The total number of events.
void GetEntry(Long64_t entry)
Reads an event.
Class to handle group of Root files.
const GGSTParameters * GetGenParams(const GGSTFilesHandler *filesHandler=nullptr)
Returns the generator parameters.
#define CCOUT(level)
Smart log utility which prints no header at the beginning of the line.
Definition: GGSSmartLog.h:100
Class for storing the geometry parameters on Root output file.
Definition: GGSTGeoParams.h:18
const GGSTSimInfo * GetSimInfo(const GGSTFilesHandler *filesHandler=nullptr)
Returns the simulation informations.
GGSTFilesHandler * Open(const std::string &fileName, GGSTFilesHandler *filesHandler=nullptr, bool force=false)
Open ROOT files.
const TGeoManager * GetROOTGeometry(const GGSTFilesHandler *filesHandler=nullptr)
Returns the simulation geometry in TGeo format.
GGSTRootReader()
Constructor.
unsigned int GetNFiles()
The number of files handled by this object.
A class to store simulation informations.
Definition: GGSTSimInfo.h:21
Class for writing parameters into the output Root file.