Belle II Software development
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
18using namespace std;
19using namespace Belle2;
20
21
22void 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
29int 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
44int 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
146void 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
162int 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}
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
void readNextEvent(HepMC::GenEvent &evt)
read the next event from the IO stream and write into evt
Definition: HepMCReader.cc:146
int countEvents(const std::string &filename)
Count events in file.
Definition: HepMCReader.cc:162
void open(const std::string &filename)
Opens an ascii file and prepares it for reading.
Definition: HepMCReader.cc:22
std::ifstream m_input
The input stream of the ascii file.
Definition: HepMCReader.h:97
const int m_maxEvent
max events to process
Definition: HepMCReader.h:91
int getEvent(MCParticleGraph &graph, double &weight)
Reads the next event and stores the result in the given MCParticle graph.
Definition: HepMCReader.cc:44
bool m_wrongSignPz
Bool to indicate that HER and LER were swapped.
Definition: HepMCReader.h:89
int nextValidEvent(HepMC::GenEvent &evt)
Got to next event in bounds.
Definition: HepMCReader.cc:29
const int m_minEvent
min event nr to process
Definition: HepMCReader.h:90
int m_nVirtual
The number of particles in each event with a set Virtual flag.
Definition: HepMCReader.h:88
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.
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
static const double cm
Standard units with the value = 1.
Definition: Unit.h:47
static const double GeV
Standard of [energy, momentum, mass].
Definition: Unit.h:51
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
STL namespace.