Belle II Software  release-08-01-10
LHEReader.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/lhe/LHEReader.h>
13 #include <mdst/dataobjects/MCParticle.h>
14 
15 #include <string>
16 #include <boost/lexical_cast.hpp>
17 #include <boost/algorithm/string.hpp>
18 #include <boost/foreach.hpp>
19 #include <boost/format.hpp>
20 
21 #include <TF1.h>
22 
23 using namespace std;
24 using namespace Belle2;
25 
26 const boost::char_separator<char> LHEReader::sep(",; \t");
27 
28 void LHEReader::open(const string& filename)
29 {
30  m_lineNr = 0;
31  m_input.open(filename.c_str());
32  if (!m_input) throw(LHECouldNotOpenFileError() << filename);
33 }
34 
35 
36 int LHEReader::getEvent(MCParticleGraph& graph, double& eventWeight)
37 {
38  int nparticles = readEventHeader(eventWeight);
39  if (nparticles <= 0) {
40  throw (LHEEmptyEventError() << 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 
49  double r, x = 0, y = 0, z = 0, t = 0;
50  //Read particles from file
51  for (int i = 0; i < nparticles; ++i) {
52  MCParticleGraph::GraphParticle& p = graph[first + i];
53  int mother = readParticle(p);
54 
55  // add the mother
56  if (mother > 0) {
57  MCParticleGraph::GraphParticle* q = &graph[mother - 1];
58  p.comesFrom(*q);
59  }
60 
61  // if positron goes to positive z-direction, we have to rotate along y-axis by 180deg
62  if (m_wrongSignPz) {
63  ROOT::Math::PxPyPzEVector p4 = p.get4Vector();
64  p4.SetPz(-1.0 * p4.Pz());
65  p4.SetPx(-1.0 * p4.Px());
66  p.set4Vector(p4);
67  }
68 
69  //move vertex position of selected particle and its daughters
70  if (m_meanDecayLength > 0) {
71  if (p.getPDG() == m_pdgDisplaced) {
72  TF1 fr("fr", "exp(-x/[0])", 0, 1000000);
73  ROOT::Math::PxPyPzEVector p4 = p.get4Vector();
74  fr.SetRange(m_Rmin, m_Rmax);
75  fr.SetParameter(0, m_meanDecayLength * p4.Gamma());
76  r = fr.GetRandom();
77  x = r * p4.Px() / p4.P();
78  y = r * p4.Py() / p4.P();
79  z = r * p4.Pz() / p4.P();
80  p.setDecayVertex(x, y, z);
81  t = (r / Const::speedOfLight) * (p4.E() / p4.P());
82  p.setDecayTime(t);
83  p.setValidVertex(true);
84  }
85 
86  if (mother > 0) {
87  if (graph[mother - 1].getPDG() == m_pdgDisplaced) {
88  p.setProductionVertex(x, y, z);
89  p.setProductionTime(t);
90  p.setValidVertex(true);
91  }
92  }
93  }
94 
95 
96  // initial 2 (e+/e-), virtual 3 (Z/gamma*)
97  // check if particle should be made virtual according to steering options:
98  if (i < m_indexVirtual && i >= m_indexInitial)
99  p.addStatus(MCParticle::c_IsVirtual);
100 
101  if (i < m_indexInitial)
102  p.addStatus(MCParticle::c_Initial);
103 
104  if (m_indexVirtual < m_indexInitial) B2WARNING("IsVirtual particle requested but is overwritten by Initial");
105 
106  }
107 // return eventID;
108  return -1;
109 }
110 
111 
112 bool LHEReader::skipEvents(int n)
113 {
114 // int eventID;
115  double weight;
116  for (int i = 0; i < n; i++) {
117 // int nparticles = readEventHeader(eventID, weight);
118  int nparticles = readEventHeader(weight);
119  if (nparticles < 0) return false;
120  for (int j = 0; j < nparticles; j++) getLine();
121  }
122  return true;
123 }
124 
125 
126 //===================================================================
127 // Protected methods
128 //===================================================================
129 
130 std::string LHEReader::getLine()
131 {
132  std::string line;
133  do {
134  getline(m_input, line);
135  m_lineNr++;
136  size_t commentPos = line.find_first_of('#');
137  if (commentPos != string::npos) {
138  line = line.substr(0, commentPos);
139  }
140  boost::trim(line);
141 
142  } while (line == "" && !m_input.eof());
143 
144  return line;
145 }
146 
147 
148 // int LHEReader::readEventHeader(int& eventID, double& eventWeight)
149 int LHEReader::readEventHeader(double& eventWeight)
150 {
151 
152  // Search for next <event>
153  std::string line2;
154  do {
155  getline(m_input, line2);
156  m_lineNr++;
157  size_t commentPos = line2.find_first_of('#');
158  if (commentPos != string::npos) {
159  line2 = line2.substr(0, commentPos);
160  }
161  boost::trim(line2);
162 
163  } while (line2 != "<event>" && !m_input.eof());
164 
165  //Get number of particles from file
166  int nparticles = -1;
167  string line = getLine();
168 
169  if (line == "" || m_input.eof()) return -1;
170 
171  vector<double> fields;
172  fields.reserve(15);
173 
174  tokenizer tokens(line, sep);
175  int index(0);
176 
177  BOOST_FOREACH(const string & tok, tokens) {
178  ++index;
179  try {
180  fields.push_back(boost::lexical_cast<double>(tok));
181  } catch (boost::bad_lexical_cast& e) {
182  throw (LHEConvertFieldError() << m_lineNr << index << tok);
183  }
184  }
185 
186  switch (fields.size()) {
187  default:
188  eventWeight = 1.0;
189  nparticles = static_cast<int>(fields[0]); //other fields in LHE contain effective couplings
190  break;
191  }
192  return nparticles;
193 }
194 
195 
196 int LHEReader::readParticle(MCParticleGraph::GraphParticle& particle)
197 {
198  int mother = -1;
199 
200  string line = getLine();
201  vector<double> fields;
202  fields.reserve(15);
203 
204  tokenizer tokens(line, sep);
205  int index(0);
206 
207  BOOST_FOREACH(const string & tok, tokens) {
208  ++index;
209  try {
210  fields.push_back(boost::lexical_cast<double>(tok));
211  } catch (boost::bad_lexical_cast& e) {
212  throw (LHEConvertFieldError() << m_lineNr << index << tok);
213  }
214  }
215 
216  switch (fields.size()) {
217  case 13:
218  particle.addStatus(MCParticle::c_PrimaryParticle);
219  particle.setPDG(static_cast<int>(fields[0]));
220  mother = static_cast<int>(fields[2]);
221  particle.setMomentum(ROOT::Math::XYZVector(fields[6], fields[7], fields[8]));
222  particle.setEnergy(fields[9]);
223  particle.setMass(fields[10]);
224  break;
225  default:
226  throw (LHEParticleFormatError() << m_lineNr << fields.size());
227  }
228 
229  return mother;
230 }
boost::tokenizer< boost::char_separator< char > > tokenizer
Just a typedef for simple use of the boost::tokenizer to split the lines.
Definition: LHEReader.h:110
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.