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