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