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