EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Forester.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Forester.cxx
1 
11 
12 #include <iomanip>
13 #include <memory>
14 #include <stdexcept>
15 #include <string>
16 
17 #include <TRefArray.h>
18 #include <TString.h>
19 
21 #include "eicsmear/erhic/File.h"
23 
24 #include "eicsmear/gzstream.h"
25 
26 namespace erhic {
27 
29 : mQuit(false)
30 , mVerbose(false)
31 , mTree(NULL)
32 , mEvent(NULL)
33 , mFile(NULL)
34 , mRootFile(NULL)
35 , mMaxNEvents(0)
36 , mInterval(1)
37 , mTextFile(NULL)
38 , mInputName("default.txt")
39 , mOutputName("default.root")
40 , mTreeName("EICTree")
41 , mBranchName("event")
42 , mFactory(NULL) {
43 }
44 
46  if (mFile) {
47  delete mFile;
48  mFile = NULL;
49  } // if
50  if (mEvent) {
51  delete mEvent;
52  mEvent = NULL;
53  } // if
54  if (mFactory) {
55  delete mFactory;
56  mFactory = NULL;
57  } // if
58  if (mRootFile) {
59  delete mRootFile;
60  mRootFile = NULL;
61  } // if
62  // if (mTextFile) {
63  // delete mTextFile;
64  // mTextFile = NULL;
65  // } // if
66  // We don't delete the mTree pointer because mRootFile
67  // has ownership of it.
68 }
69 
70 Long64_t Forester::Plant() {
71  try {
72  // Initialisation of the input and output files.
73  OpenInput();
74  SetupOutput();
75  if (BeVerbose()) {
76  std::cout << "\nProcessing " << GetInputFileName() << std::endl;
77  } // if
82  static int i(0);
83  while (!MustQuit()) {
84  ++i;
85  if (BeVerbose() && i % mInterval == 0) {
86  // Make the field just wide enough for the maximum
87  // number of events.
88  int width = static_cast<int>(::log10(GetMaxNEvents()) + 1);
89  std::cout << "Processing event "<< std::setw(width) << i;
90  if (GetMaxNEvents() > 0) {
91  std::cout << "/" << std::setw(width) << GetMaxNEvents();
92  } // if
93  std::cout << std::endl;
94  } // if
95  // Build the next event
96  if (mEvent) {
97  delete mEvent;
98  mEvent = NULL;
99  } // if
100  // Catch exceptions from event builder here so we don't break
101  // out of the whole tree building loop for a single bad event.
102  try {
103  mEvent = mFactory->Create();
104  // Fill the tree
105  if (mEvent) {
106  mTree->Fill();
107  if (GetMaxNEvents() > 0 && i >= GetMaxNEvents()) {
108  SetMustQuit(true); // Hit max number of events, so quit
109  } // if
112  // We must ResetBranchAddress before deleting the event.
113  } else {
114  break;
115  } // if
116  } // try
117  catch(std::exception& e) {
118  std::cerr << "Caught exception in Forester::Plant(): "
119  << e.what() << std::endl;
120  std::cerr << "Event will be skipped..." << std::endl;
121  } // catch
122  } // while
123  Finish();
124  return 0;
125  } // try
126  catch(std::exception& e) {
127  std::cerr << "Caught exception in Forester::Plant(): "
128  << e.what() << std::endl;
129  return -1;
130  } // catch
131 }
132 
134  try {
135  // Open the input file for reading.
136  if ( TString(GetInputFileName()).EndsWith("gz", TString::kIgnoreCase) ||
137  TString(GetInputFileName()).EndsWith("zip", TString::kIgnoreCase)){
138  auto tmp = std::make_shared<igzstream>();
139  tmp->open(GetInputFileName().c_str());
140  // Throw a runtime_error if the file could not be opened.
141  if (!tmp->good()) {
142  std::string message("Unable to open file ");
143  throw std::runtime_error(message.append(GetInputFileName()));
144  } // if
145  mTextFile = tmp;
146  } else {
147  auto tmp = std::make_shared<std::ifstream>();
148  tmp->open(GetInputFileName().c_str());
149  // Throw a runtime_error if the file could not be opened.
150  if (!tmp->good()) {
151  std::string message("Unable to open file ");
152  throw std::runtime_error(message.append(GetInputFileName()));
153  } // if
154  mTextFile = tmp;
155  }
156 
157  // Determine which Monte Carlo generator produced the file.
158  // hand over file name too, because the next function is destructive to the stream
159  // and gzipped hepmc files need to reopen the stream
161  if (!mFile) {
162  throw std::runtime_error(GetInputFileName() +
163  " is not from a supported generator");
164  } // for
167  return true;
168  } // Pass the exception on to be dealt with higher up the food chain.
169  catch(std::exception&) {
170  throw;
171  } // catch
172 }
173 
175  try {
176  // Open the ROOT file and check it opened OK
177  mRootFile = new TFile(GetOutputFileName().c_str(), "RECREATE");
178  if (!mRootFile->IsOpen()) {
179  std::string message("Unable to open file ");
180  throw std::runtime_error(message.append(GetOutputFileName()));
181  } // if
182  // Create the tree and check for errors
183  mTree = new TTree(GetTreeName().c_str(), "my EIC tree");
184  if (!mTree) {
185  std::string message("Error allocating TTree ");
186  throw std::runtime_error(message.append(GetTreeName()));
187  } // if
188  // Allocate memory for the branch buffer and
189  // add the branch to the tree
190  AllocateEvent();
191  mTree->Branch(GetBranchName().c_str(), mEvent->ClassName(),
192  &mEvent, 32000, 99);
193  // Auto-save every 500 MB
194  mTree->SetAutoSave(500LL * 1024LL * 1024LL);
195  // Align the input file at the start of the first event (event generator dependent).
197  // Start timing after opening and creating files,
198  // before looping over events
200  return true;
201  } // try...
202  catch(std::exception&) {
203  throw;
204  } // catch
205 }
206 
208  if (BeVerbose()) {
209  std::cout << "\nProcessed " << GetInputFileName() << std::endl;
210  } // if
211  // Write the TTree to the file.
212  mRootFile = mTree->GetCurrentFile();
213  mRootFile->cd();
214  mTree->Write();
215  for ( auto namedobject : mFactory->mObjectsToWriteAtTheEnd ){
216  namedobject.second->Write(namedobject.first);
217  }
218  mRootFile->ls();
219  // Write the Forester itself to make it easier to reproduce the file
220  // with the same settings.
221  Write("forester");
222  // Reset quit flag in case of further runs.
223  SetMustQuit(false);
224  // Stop timing the run.
225  mStatus.StopTimer();
226  if (BeVerbose()) {
227  GetGetStatus().Print(std::cout); // Messages for the user
228  } // if
229  mRootFile->Close();
230 }
231 
233  try {
234  if (mEvent) {
235  delete mEvent;
236  mEvent = NULL;
237  } // if
239  return mEvent;
240  } // try...
241  // Catch exceptions and pass up the food chain
242  catch(std::exception&) {
243  throw;
244  } // catch
245 }
246 
248  // Naughty kludge alert!
249  // The first line was already read to determine the generator.
250  // The header in the text files is six lines, so
251  // read the remaining five lines of header.
257  return true;
258 }
259 
260 void Forester::Print(std::ostream& os) const {
261  os << "Input file: " << mInputName << std::endl;
262  os << "Output file: " << mOutputName << std::endl;
263  os << "Output tree: " << mTreeName << std::endl;
264  os << "Output branch: " << mBranchName << std::endl;
265  os << "Maximum number of events: " << mMaxNEvents << std::endl;
266  if (mEvent) {
267  os << "Event type: " << mEvent->ClassName() << std::endl;
268  } // if
269 }
270 
271 void Forester::Print(Option_t* /* not used */) const {
272  Print(std::cout);
273 }
274 
276  : mNEvents(0)
277  , mNParticles(0) {
278  // Initialise the start and end time to the creation time and reset
279  // the timer to ensure it is at zero.
282  mTimer.Reset();
283  }
284 
285  Forester::Status::~Status() { /* noop */ }
286 
287  std::ostream& Forester::Status::Print(std::ostream& os) const {
288  // Put start and end times in different os <<... otherwise I get
289  // the same time for each...
290  os << "Began on " << std::ctime(&mStartTime);
291  os << "Ended on " << std::ctime(&mEndTime);
292  os << "Processed " << mNEvents << " events containing "
293  << mNParticles << " particles in "
294  << mTimer.RealTime() << " seconds "
295  << '(' << mTimer.RealTime()/mNEvents <<" sec/event)" << std::endl;
296  return os;
297  }
298 
300  std::time(&mStartTime);
301  mTimer.Start();
302  }
303 
305  std::time(&mEndTime);
306  mTimer.Stop();
307  }
308 
309  void Forester::Status::ModifyEventCount(Long64_t count) {
310  mNEvents += count;
311  }
312 
314  mNParticles += count;
315  }
316 
317  // ClassImp( ForesterStatus ); // throws error for some reason
318 
319 
320 
321 } // namespace erhic