Belle II Software prerelease-11-00-00a
HepevtReader.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 <framework/gearbox/Unit.h>
10#include <framework/gearbox/Const.h>
11#include <framework/logging/Logger.h>
12#include <generators/hepevt/HepevtReader.h>
13
14#include <string>
15#include <boost/lexical_cast.hpp>
16#include <boost/algorithm/string.hpp>
17#include <boost/format.hpp>
18
19#include <Math/Vector4D.h>
20
21using namespace std;
22using namespace Belle2;
23
24const boost::char_separator<char> HepevtReader::sep(",; \t");
25
26void HepevtReader::open(const string& filename)
27{
28 m_lineNr = 0;
29 if (m_input.is_open()) m_input.close();
30 m_input.clear();
31 m_input.open(filename.c_str());
32 if (!m_input) throw(HepEvtCouldNotOpenFileError() << filename);
33}
34
35
36int HepevtReader::getEvent(MCParticleGraph& graph, double& eventWeight)
37{
38 int eventID = -1;
39 int nparticles = readEventHeader(eventID, eventWeight);
40 if (nparticles <= 0) {
41 throw (HepEvtEmptyEventError() << m_lineNr << nparticles);
42 }
43
44 int first = graph.size();
45 //Make list of particles
46 for (int i = 0; i < nparticles; i++) {
47 graph.addParticle();
48 }
49 //Read particles from file
50 for (int i = 0; i < nparticles; ++i) {
51 MCParticleGraph::GraphParticle& p = graph[first + i];
52 readParticle(p);
53
54 if (m_wrongSignPz) { // this means we have to mirror Pz
55 ROOT::Math::PxPyPzEVector p4 = p.get4Vector();
56 p4.SetPz(-1.0 * p4.Pz());
57 p.set4Vector(p4);
58 }
59
60 //Check for sensible daughter indices
61 int d1 = p.getFirstDaughter();
62 int d2 = p.getLastDaughter();
63 if (d1 < 0 || d1 > nparticles || d2 < d1 || d2 > nparticles) {
64 throw (HepEvtInvalidDaughterIndicesError() << m_lineNr << d1 << d2 << nparticles);
65 }
66 if (d1 == 0) p.addStatus(MCParticle::c_StableInGenerator);
67 //Add decays
68 for (int index = d1; index <= d2; ++index) {
69 if (index > 0) p.decaysInto(graph[first + index - 1]);
70 }
71
72 //check if particle should be made virtual according to steering options:
73 if (i < m_nVirtual)
74 p.setVirtual();
75 }
76 return eventID;
77}
78
79
81{
82 int eventID;
83 double weight;
84 for (int i = 0; i < n; i++) {
85 int nparticles = readEventHeader(eventID, weight);
86 if (nparticles < 0) return false;
87 for (int j = 0; j < nparticles; j++) getLine();
88 }
89 return true;
90}
91
92int HepevtReader::countEvents(const std::string& filename)
93{
94 open(filename);
95
96 int count = 0;
97 int eventID;
98 double weight;
99
100 int nparticles;
101 while ((nparticles = readEventHeader(eventID, weight)) >= 0) {
102 count++;
103 for (int j = 0; j < nparticles; j++) getLine();
104 }
105
106 B2INFO("Counted " << count << " events in " << filename << ".");
107 return count;
108}
109
110
111//===================================================================
112// Protected methods
113//===================================================================
114
116{
117 std::string line;
118 do {
119 getline(m_input, line);
120 m_lineNr++;
121 size_t commentPos = line.find_first_of('#');
122 if (commentPos != string::npos) {
123 line = line.substr(0, commentPos);
124 }
125 boost::trim(line);
126 } while (line == "" && !m_input.eof());
127 return line;
128}
129
130
131int HepevtReader::readEventHeader(int& eventID, double& eventWeight)
132{
133 //Get number of particles from file
134 int nparticles = -1;
135 string line = getLine();
136 if (line == "" || m_input.eof()) return -1;
137
138 vector<double> fields;
139 fields.reserve(15);
140
141 tokenizer tokens(line, sep);
142 int index(0);
143
144 for (const string& tok : tokens) {
145 ++index;
146 try {
147 fields.push_back(boost::lexical_cast<double>(tok));
148 } catch (boost::bad_lexical_cast& e) {
149 throw (HepEvtConvertFieldError() << m_lineNr << index << tok);
150 }
151 }
152
153 switch (fields.size()) {
154 case 1:
155 nparticles = static_cast<int>(fields[0]);
156 break;
157 case 2:
158 nparticles = static_cast<int>(fields[1]);
159 eventID = static_cast<int>(fields[0]);
160 break;
161 case 3:
162 nparticles = static_cast<int>(fields[1]);
163 eventID = static_cast<int>(fields[0]);
164 eventWeight = fields[2];
165 break;
166 default:
167 nparticles = static_cast<int>(fields[0]);
168 break;
169 }
170 return nparticles;
171}
172
173
175{
176 string line = getLine();
177 vector<double> fields;
178 fields.reserve(15);
179
180 tokenizer tokens(line, sep);
181 int index(0);
182
183 for (const string& tok : tokens) {
184 ++index;
185 try {
186 fields.push_back(boost::lexical_cast<double>(tok));
187 } catch (boost::bad_lexical_cast& e) {
188 throw (HepEvtConvertFieldError() << m_lineNr << index << tok);
189 }
190 }
191
192 switch (fields.size()) {
193 case 8:
194 particle.setStatus(MCParticle::c_PrimaryParticle);
195 particle.setPDG(static_cast<int>(fields[1]));
196 particle.setFirstDaughter(static_cast<int>(fields[2]));
197 particle.setLastDaughter(static_cast<int>(fields[3]));
198 particle.setMomentum(ROOT::Math::XYZVector(fields[4], fields[5], fields[6]));
199 particle.setMass(fields[7]);
200 break;
201 case 6:
202 particle.setStatus(MCParticle::c_PrimaryParticle);
203 particle.setPDG(static_cast<int>(fields[5]));
204 particle.setFirstDaughter(0);
205 particle.setLastDaughter(0);
206 particle.setMomentum(ROOT::Math::XYZVector(fields[0], fields[1], fields[2]));
207 particle.setMass(fields[4]);
208 particle.setEnergy(fields[3]);
209 break;
210 //modified Pit
211 case 9:
212 particle.setStatus(MCParticle::c_PrimaryParticle);
213 particle.setPDG(static_cast<int>(fields[8]));
214 particle.setFirstDaughter(0);
215 particle.setLastDaughter(0);
216 particle.setProductionVertex(ROOT::Math::XYZVector(fields[0], fields[1], fields[2])*Unit::mm);
217 particle.setMomentum(ROOT::Math::XYZVector(fields[3], fields[4], fields[5]));
218 particle.setMass(fields[6]);
219 particle.setEnergy(fields[7]);
220 break;
221 //end modified Pit
222 case 15:
223 particle.setStatus(MCParticle::c_PrimaryParticle);
224 particle.setPDG(static_cast<int>(fields[1]));
225 particle.setFirstDaughter(static_cast<int>(fields[4]));
226 particle.setLastDaughter(static_cast<int>(fields[5]));
227 particle.setMomentum(ROOT::Math::XYZVector(fields[6], fields[7], fields[8]));
228 //particle.setEnergy(fields[9]);
229 particle.setMass(fields[10]);
230 particle.setProductionVertex(ROOT::Math::XYZVector(fields[11], fields[12], fields[13])*Unit::mm);
231 particle.setProductionTime(fields[14]*Unit::mm / Const::speedOfLight);
232 particle.setValidVertex(true);
233 {
234 //Warn if energy in Hepevt file differs from calculated energy by more than 0.1%
235 const double& E = particle.getEnergy();
236 double dE = fabs(fields[9] - E) / E;
237 if (dE > 1e-3) {
238 B2WARNING(boost::format("line %d: Energy of particle does not match with expected energy: %.6e != %.6e")
239 % m_lineNr % fields[9] % E);
240 B2WARNING(boost::format("delta E = %.2f%% -> ignoring given value") % (dE * 100));
241 }
242 }
243 break;
244 default:
245 throw (HepEvtParticleFormatError() << m_lineNr << fields.size());
246 }
247}
R E
internal precision of FFTW codelets
static const double speedOfLight
[cm/ns]
Definition Const.h:695
bool skipEvents(int n)
Skips a given number of events.
std::string getLine()
Returns the current line from the Hepevt ascii file.
int countEvents(const std::string &filename)
Count events in the file by reading through it.
static const boost::char_separator< char > sep
The characters at which to split, defaults to ",; \t".
int m_lineNr
The current line number within the ascii file.
void open(const std::string &filename)
Opens an ascii file and prepares it for reading.
std::ifstream m_input
The input stream of the ascii file.
boost::tokenizer< boost::char_separator< char > > tokenizer
Just a typedef for simple use of the boost::tokenizer to split the lines.
int readEventHeader(int &eventID, double &eventWeight)
Reads the event header from the hepevt file.
int getEvent(MCParticleGraph &graph, double &weight)
Reads the next event and stores the result in the given MCParticle graph.
bool m_wrongSignPz
Bool to indicate that HER and LER were swapped.
void readParticle(MCParticleGraph::GraphParticle &particle)
Reads the information for a single particle from the Hepevt file.
int m_nVirtual
The number of particles in each event with a set Virtual flag.
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
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition MCParticle.h:49
static const double mm
[millimeters]
Definition Unit.h:70
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
STL namespace.