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