Belle II Software  release-08-01-10
HepMCReader.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <generators/hepmc/HepMCReader.h>
10 #include <framework/gearbox/Unit.h>
11 #include <framework/gearbox/Const.h>
12 #include <framework/logging/Logger.h>
13 
14 #include <HepMC/IO_GenEvent.h>
15 
16 #include <Math/Vector4D.h>
17 
18 using namespace std;
19 using namespace Belle2;
20 
21 
22 void HepMCReader::open(const string& filename)
23 {
24  B2INFO("Reading HEPMC inputfile at " << filename);
25  m_input.open(filename.c_str());
26  if (!m_input) { throw (HepMCCouldNotOpenFileError() << filename); }
27 }
28 
29 int HepMCReader::nextValidEvent(HepMC::GenEvent& evt)
30 {
31  readNextEvent(evt);
32  int eventID = evt.event_number();
33  // if eventID is not in the valid bounds get next event
34  if (eventID < m_minEvent) {
35  while (!(eventID >= m_minEvent)) {
36  readNextEvent(evt);
37  eventID = evt.event_number();
38  }
39  }
40  if (eventID >= m_maxEvent) { return -999; } // went too far; there is no int nan
41  return eventID;
42 }
43 
44 int HepMCReader::getEvent(MCParticleGraph& graph, double& eventWeight)
45 {
46  int eventID;
47 
48  HepMC::GenEvent evt;
49  // read event number once
50  eventID = nextValidEvent(evt); // check if this event is in the bounds if not go to next one in bounds
51  if (eventID == -999) { throw HepMCInvalidEventError(); }
52 
53  eventWeight = 1; // why is evt.weights() a std::vector?
54  const int nparticles = evt.particles_size();
55 
56  B2DEBUG(20, "Found eventID " << eventID << " with " << nparticles << " particles.");
57 
58  if (nparticles <= 0) {
59  throw (HepMCInvalidEventError());
60  }
61  const int event_offset = graph.size(); //offset
62  //Make list of particles; Prepare graph
63  for (int i = 0; i < nparticles; i++) {
64  graph.addParticle();
65  }
66 
67  std::unordered_map<int, int> hash_index_map;
68  HepMC::GenEvent::particle_iterator tmp_particle = evt.particles_begin();
69  for (int i = 0; i < nparticles; ++i) {
70  //the barcode seems to just do 0++ etc. but im not sure if there are exceptions
71  const int hash = (*tmp_particle)->barcode();
72  hash_index_map[hash] = i;
73  ++tmp_particle;
74  }
75  const double len_conv = HepMC::Units::conversion_factor(evt.length_unit(), HepMC::Units::CM); // from, to
76  const double mom_conv = HepMC::Units::conversion_factor(evt.momentum_unit(), HepMC::Units::GEV); // from, to
77  auto read_particle = evt.particles_begin();
78  //Read particles from file
79  for (int i = 0; i < nparticles; ++i) {
80  auto* decay_vertex = (*read_particle)->end_vertex();
81  auto* production_vertex = (*read_particle)->production_vertex();
82 
83  MCParticleGraph::GraphParticle& p = graph[event_offset + i];
84 
85  const int status = (*read_particle)->status();
86  const bool isFinalstate = !decay_vertex && status == 1;
87  const bool isVirtual = (status == 4) || (status == 21) || (status == 22) || (status == 23) || (status == 51) || (status == 52)
88  || (status == 71) ; //hepmc internal status flags. 4 are beam particles, rest could be refined if needed
89  const int pdg_code = (*read_particle)->pdg_id() ;
90  const double mass = (*read_particle)->generated_mass() * mom_conv;
91  auto const mom_tmp = (*read_particle)->momentum();
92 
93  const HepMC::FourVector momentum(
94  mom_tmp.x()*mom_conv * Unit::GeV,
95  mom_tmp.y()*mom_conv * Unit::GeV,
96  mom_tmp.z()*mom_conv * Unit::GeV,
97  mom_tmp.t()*mom_conv * Unit::GeV
98  );
99 
100  B2DEBUG(20, "Read particle: status " << status << " isFinal " << isFinalstate << " isVirtual " << isVirtual << " pdg " << pdg_code
101  << " mass " << mass << " px " << momentum.x() << " py " << momentum.y() << " px " << momentum.z() << " E " << momentum.t());
102  p.addStatus(MCParticle::c_PrimaryParticle); // all particles part of the hepmc file should be set as primary
103  p.setPDG(pdg_code);
104  p.setMomentum(ROOT::Math::XYZVector(momentum.x(), momentum.y(), momentum.z()));
105  p.setEnergy(momentum.t());
106  p.setMass(mass);
107  if (production_vertex) {
108  const auto pos = production_vertex->position();
109  p.setProductionVertex(ROOT::Math::XYZVector(pos.x(), pos.y(), pos.z()) * len_conv * Unit::cm);
110  p.setProductionTime(pos.t() * len_conv * Unit::cm / Const::speedOfLight);
111  p.setValidVertex(true);
112  }
113 
114  if (status == 21) { //removes massless beam particles carried over from MadGraph
115  p.setIgnore(true); //they are just used for internal bookkeeping and serve no other purpose
116  }
117 
118  //assign the parent particle:
119  //for two incoming particles only one of them is assigned as parent
120  if (production_vertex) {
121  if (production_vertex->particles_in_const_begin() != production_vertex->particles_in_const_end()) {
122  auto parent = production_vertex->particles_begin(HepMC::parents);
123  const int parent_index_in_graph = hash_index_map[(*parent)->barcode()];
124  p.comesFrom(graph[event_offset + parent_index_in_graph]);
125  }
126  }
127 
128  if (m_wrongSignPz) { // this means we have to mirror Pz
129  ROOT::Math::PxPyPzEVector p4 = p.get4Vector();
130  p4.SetPz(-1.0 * p4.Pz());
131  p.set4Vector(p4);
132  }
133 
134 
136  if (i < m_nVirtual || isVirtual) {
137  p.setVirtual();
138  }
139  ++read_particle;
140  }
141  eventID += 1;
142  B2DEBUG(20, "Returning event id " << eventID);
143  return eventID;
144 }
145 
146 void HepMCReader::readNextEvent(HepMC::GenEvent& evt)
147 {
148  // walk through the IOStream
149  if (m_input) {
150  evt.read(m_input);
151  if (evt.is_valid()) {
152  const int nparticles = evt.particles_size();
153  B2DEBUG(20, "Found valid event.i N particles " << nparticles);
154  return; //
155  } else {
156  B2DEBUG(20, "The next event was invalid. Will stop reading now.");
157  }
158  }
159  return;
160 }
161 
162 int HepMCReader::countEvents(const std::string& filename)
163 {
164  //different way to read file for consitency check
165  HepMC::IO_GenEvent ascii_in(filename.c_str(), std::ios::in);
166  int count = 0;
167  HepMC::GenEvent* evt = ascii_in.read_next_event();
168  while (evt) {
169  evt = ascii_in.read_next_event();
170  count++;
171  }
172  B2INFO("Counted " << count << " events in " << filename << ".");
173  return count;
174 }
Class to represent Particle data in graph.
Class to build, validate and sort a particle decay chain.
size_t size() const
Return the number of particles in the graph.
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.