Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fun4AllHepMCInputManager.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Fun4AllHepMCInputManager.cc
2 
3 #include "PHHepMCGenEvent.h"
4 #include "PHHepMCGenEventMap.h"
5 
6 #include <frog/FROG.h>
7 
8 #include <fun4all/Fun4AllInputManager.h> // for Fun4AllInpu...
10 #include <fun4all/Fun4AllServer.h>
12 
13 #include <phool/PHCompositeNode.h>
14 #include <phool/PHIODataNode.h> // for PHIODataNode
15 #include <phool/PHNodeIterator.h> // for PHNodeIterator
16 #include <phool/PHObject.h> // for PHObject
17 #include <phool/getClass.h>
18 #include <phool/phool.h> // for PHWHERE
19 #include <phool/recoConsts.h>
20 
21 #include <HepMC/GenEvent.h>
22 #include <HepMC/GenParticle.h> // for GenParticle
23 #include <HepMC/GenVertex.h> // for GenVertex
24 #include <HepMC/IO_GenEvent.h>
25 #include <HepMC/SimpleVector.h> // for FourVector
26 #include <HepMC/Units.h> // for CM, GEV
27 
28 #include <TPRegexp.h>
29 #include <TString.h>
30 
31 #include <boost/iostreams/filter/bzip2.hpp>
32 #include <boost/iostreams/filter/gzip.hpp>
33 
34 #include <cmath>
35 #include <cstdlib>
36 #include <fstream>
37 #include <iostream>
38 #include <map> // for _Rb_tree_it...
39 #include <sstream>
40 #include <vector> // for vector
41 
42 static const double toMM = 1.e-12;
43 
45  : Fun4AllInputManager(name, nodename, topnodename)
46  , topNodeName(topnodename)
47 {
48  set_embedding_id(0); // default embedding ID. Welcome to change via macro
49 
52  PHNodeIterator iter(topNode);
53  PHCompositeNode *dstNode = se->getNode(InputNode(), topNodeName);
54 
55  PHHepMCGenEventMap *geneventmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
56  if (!geneventmap)
57  {
58  geneventmap = new PHHepMCGenEventMap();
59  PHIODataNode<PHObject> *newmapnode = new PHIODataNode<PHObject>(geneventmap, "PHHepMCGenEventMap", "PHObject");
60  dstNode->addNode(newmapnode);
61  }
62 
64 
65  return;
66 }
67 
69 {
70  fileclose();
71  if (!m_HepMCTmpFile.empty())
72  {
73  // okay if the file does not exist
74  remove(m_HepMCTmpFile.c_str());
75  }
76  delete ascii_in;
77  delete filestream;
78  delete unzipstream;
79 }
80 
82 {
83  if (!MySyncManager())
84  {
85  std::cout << "Call fileopen only after you registered your Input Manager " << Name() << " with the Fun4AllServer" << std::endl;
86  exit(1);
87  }
88  if (IsOpen())
89  {
90  std::cout << "Closing currently open file "
91  << filename
92  << " and opening " << filenam << std::endl;
93  fileclose();
94  }
95  filename = filenam;
96  FROG frog;
98  if (Verbosity() > 0)
99  {
100  std::cout << Name() << ": opening file " << fname << std::endl;
101  }
102 
103  if (m_ReadOscarFlag)
104  {
105  theOscarFile.open(fname);
106  }
107  else
108  {
109  TString tstr(fname);
110  TPRegexp bzip_ext(".bz2$");
111  TPRegexp gzip_ext(".gz$");
112  if (tstr.Contains(bzip_ext))
113  {
114  // use boost iosteam library to decompress bz2 on the fly
115  filestream = new std::ifstream(fname, std::ios::in | std::ios::binary);
116  zinbuffer.push(boost::iostreams::bzip2_decompressor());
117  zinbuffer.push(*filestream);
118  unzipstream = new std::istream(&zinbuffer);
119  ascii_in = new HepMC::IO_GenEvent(*unzipstream);
120  }
121  else if (tstr.Contains(gzip_ext))
122  {
123  // use boost iosream to decompress the gzip file on the fly
124  filestream = new std::ifstream(fname, std::ios::in | std::ios::binary);
125  zinbuffer.push(boost::iostreams::gzip_decompressor());
126  zinbuffer.push(*filestream);
127  unzipstream = new std::istream(&zinbuffer);
128  ascii_in = new HepMC::IO_GenEvent(*unzipstream);
129  }
130  else
131  {
132  // expects normal ascii hepmc file
133  ascii_in = new HepMC::IO_GenEvent(fname, std::ios::in);
134  }
135  }
136 
138  static bool run_number_forced = rc->FlagExist("RUNNUMBER");
139  if (run_number_forced)
140  {
141  MySyncManager()->CurrentRun(rc->get_IntFlag("RUNNUMBER"));
142  }
143  else
144  {
145  MySyncManager()->CurrentRun(-1);
146  }
147  events_thisfile = 0;
148  IsOpen(1);
149  AddToFileOpened(fname); // add file to the list of files which were opened
150  return 0;
151 }
152 
153 int Fun4AllHepMCInputManager::run(const int /*nevents*/)
154 {
155  // attempt to retrieve a valid event from inputs
156  while (true)
157  {
158  if (!IsOpen())
159  {
160  if (FileListEmpty())
161 
162  {
163  if (Verbosity() > 0)
164  {
165  std::cout << "Fun4AllHepMCInputManager::run::" << Name() << ": No Input file open" << std::endl;
166  }
167  return -1;
168  }
169  else
170  {
171  if (OpenNextFile())
172  {
173  std::cout << "Fun4AllHepMCInputManager::run::" << Name() << ": No Input file from filelist opened" << std::endl;
174  return -1;
175  }
176  }
177  }
178 
179  if (m_EventPushedBackFlag) // if an event was pushed back, reuse save copy
180  {
181  HepMC::IO_GenEvent ascii_tmp_in(m_HepMCTmpFile, std::ios::in);
182  ascii_tmp_in >> evt;
184  remove(m_HepMCTmpFile.c_str());
185  }
186  else
187  {
188  if (m_ReadOscarFlag)
189  {
190  evt = ConvertFromOscar();
191  }
192  else
193  {
194  evt = ascii_in->read_next_event();
195  }
196  }
197 
198  if (!evt)
199  {
200  if (Verbosity() > 1)
201  {
202  std::cout << "Fun4AllHepMCInputManager::run::" << Name()
203  << ": error type: " << ascii_in->error_type()
204  << ", rdstate: " << ascii_in->rdstate() << std::endl;
205  }
206  fileclose();
207  }
208  else
209  {
210  MySyncManager()->CurrentEvent(evt->event_number());
211  if (Verbosity() > 0)
212  {
213  std::cout << "Fun4AllHepMCInputManager::run::" << Name()
214  << ": hepmc evt no: " << evt->event_number() << std::endl;
215  }
216  m_MyEvent.push_back(evt->event_number());
218  if (ievt != PHHepMCGenHelper::get_geneventmap()->end())
219  {
220  // override existing event
221  ievt->second->addEvent(evt);
222  }
223  else
224  {
226  }
227 
228  events_total++;
229  events_thisfile++;
230 
231  // check if the local SubsysReco discards this event
233  {
234  // if this event is discarded we only need to remove the event from the list of event numbers
235  // the new event will overwrite the event on the node tree without issues
236  m_MyEvent.pop_back();
237  }
238  else
239  {
240  break; // have a good event, move on
241  }
242  }
243  } // attempt to retrieve a valid event from inputs
245 }
246 
248 {
249  if (!IsOpen())
250  {
251  std::cout << Name() << ": fileclose: No Input file open" << std::endl;
252  return -1;
253  }
254  if (m_ReadOscarFlag)
255  {
256  theOscarFile.close();
257  }
258  else
259  {
260  delete ascii_in;
261  ascii_in = nullptr;
262  }
263  IsOpen(0);
264  // if we have a file list, move next entry to top of the list
265  // or repeat the same entry again
266  UpdateFileList();
267  return 0;
268 }
269 
271 {
273  std::cout << Name() << " Vertex Settings: " << std::endl;
275  return;
276 }
277 
279 {
280  // PushBackEvents is supposedly pushing events back on the stack which works
281  // easily with root trees (just grab a different entry) but hard in these HepMC ASCII files.
282  // A special case is when the synchronization fails and we need to only push back a single
283  // event. In this case we save the evt in a temporary file which is read back in the run method
284  // instead of getting the next event.
285  if (i > 0)
286  {
287  if (i == 1 && evt) // check on evt pointer makes sure it is not done from the cmd line
288  {
289  // root barfs when writing the node to the output.
290  // Saving the pointer - even using a deep copy and reusing it did not work
291  // The hackaround which works is to write this event into a temporary file and read it back
292  if (m_HepMCTmpFile.empty())
293  {
294  // we need to create this filename just once, we reuse it. Do it only if we need it
295  m_HepMCTmpFile = "/tmp/HepMCTmpEvent-" + Name() + "-" + std::to_string(getpid()) + ".hepmc";
296  }
297  HepMC::IO_GenEvent ascii_io(m_HepMCTmpFile, std::ios::out);
298  ascii_io << evt;
300  m_MyEvent.pop_back();
301 
302  if (Verbosity() > 3)
303  {
304  std::cout << Name() << ": pushing back evt no " << evt->event_number() << std::endl;
305  }
306  return 0;
307  }
308  std::cout << PHWHERE << Name()
309  << " Fun4AllHepMCInputManager cannot pop back more than 1 event"
310  << std::endl;
311  return -1;
312  }
313  if (!IsOpen())
314  {
315  std::cout << PHWHERE << Name()
316  << " no file opened yet" << std::endl;
317  return -1;
318  }
319  // Skipping events is implemented as
320  // pushing a negative number of events on the stack, so in order to implement
321  // the skipping of events we read -i events.
322  int nevents = -i; // negative number of events to push back -> skip num events
323  int errorflag = 0;
324  while (nevents > 0 && !errorflag)
325  {
326  evt = ascii_in->read_next_event();
327  if (!evt)
328  {
329  std::cout << "Error after skipping " << i - nevents << std::endl;
330  std::cout << "error type: " << ascii_in->error_type()
331  << ", rdstate: " << ascii_in->rdstate() << std::endl;
332  errorflag = -1;
333  fileclose();
334  }
335  else
336  {
337  m_MyEvent.push_back(evt->event_number());
338  if (Verbosity() > 3)
339  {
340  std::cout << "Skipping evt no: " << evt->event_number() << std::endl;
341  }
342  }
343  delete evt;
344  nevents--;
345  }
346  return errorflag;
347 }
348 
349 HepMC::GenEvent *
351 {
352  if (theOscarFile.eof()) // if the file is exhausted bail out during this next read
353  {
354  return nullptr;
355  }
356 
357  delete evt;
358  //use PHENIX unit
359  evt = new HepMC::GenEvent(HepMC::Units::GEV, HepMC::Units::CM);
360 
361  if (Verbosity() > 1) std::cout << "Reading Oscar Event " << events_total << std::endl;
362  //Grab New Event From Oscar
363  std::string theLine;
364  std::vector<std::vector<double> > theEventVec;
365  std::vector<HepMC::FourVector> theVtxVec;
366  while (getline(theOscarFile, theLine))
367  {
368  if (theLine.compare(0, 1, "#") == 0) continue;
369  std::vector<double> theInfo; //format: N,pid,px,py,pz,E,mass,xvtx,yvtx,zvtx,?
370  double number = NAN;
371  for (std::istringstream numbers_iss(theLine); numbers_iss >> number;)
372  {
373  theInfo.push_back(number);
374  }
375 
376  if (theInfo.size() == 2 && theInfo[0] == 0 && theInfo[1] == 0)
377  {
378  break;
379  }
380  else if (theInfo.size() == 2 && theInfo[0] == 0 && theInfo[1] > 0)
381  {
382  continue;
383  }
384  else
385  {
386  theEventVec.push_back(theInfo);
387  HepMC::FourVector vert(theInfo[8] * toMM, theInfo[9] * toMM, theInfo[10] * toMM, theInfo[11]);
388  theVtxVec.push_back(vert);
389  }
390 
391  } //while(getline)
392 
393  //Set Event Number
394  evt->set_event_number(events_total);
395 
396  //Loop Over One Event, Fill HepMC
397  for (unsigned int i = 0; i < theEventVec.size(); i++)
398  {
399  //int N = (int)theEventVec[i][0];
400  int pid = (int) theEventVec[i][1];
401  double px = theEventVec[i][3];
402  double py = theEventVec[i][4];
403  double pz = theEventVec[i][5];
404  double E = theEventVec[i][6];
405  double m = theEventVec[i][7];
406  int status = 1; //oscar only writes final state particles
407 
408  HepMC::GenVertex *v = new HepMC::GenVertex(theVtxVec[i]);
409  evt->add_vertex(v);
410 
411  HepMC::GenParticle *p = new HepMC::GenParticle(HepMC::FourVector(px, py, pz, E), pid, status);
412  p->setGeneratedMass(m);
413  p->suggest_barcode(i + 1);
414  v->add_particle_out(p);
415  }
416  if (Verbosity() > 3)
417  {
418  evt->print();
419  }
420  return evt;
421 }
422 
424 {
425  m_MyEvent.clear();
426  return 0;
427 }
428 
429 int Fun4AllHepMCInputManager::MyCurrentEvent(const unsigned int index) const
430 {
431  if (m_MyEvent.empty())
432  {
433  return 0;
434  }
435  return m_MyEvent.at(index);
436 }
437