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