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