Belle II Software development
EvtGenInterface.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 <framework/particledb/EvtGenDatabasePDG.h>
13#include <framework/utilities/FileSystem.h>
14#include <generators/evtgen/EvtGenInterface.h>
15#include <mdst/dataobjects/MCParticleGraph.h>
16#include <generators/evtgen/EvtGenModelRegister.h>
17
18#include <memory>
19#include <string>
20#include <queue>
21
22#include <EvtGenExternal/EvtExternalGenList.hh>
23#include <EvtGenBase/EvtAbsRadCorr.hh>
24#include <EvtGenBase/EvtCPUtil.hh>
25#include <EvtGenBase/EvtDecayTable.hh>
26#include <EvtGenBase/EvtDecayBase.hh>
27#include <EvtGenBase/EvtParticleFactory.hh>
28#include <EvtGenBase/EvtPDL.hh>
29#include <EvtGenBase/EvtRandom.hh>
30
31using namespace std;
32using namespace Belle2;
33
35
37{
38 EvtDecayTable* evtDecayTable = EvtDecayTable::getInstance();
39 for (unsigned int i = 0; i < EvtPDL::entries(); ++i) {
40 for (int j = 0; j < evtDecayTable->getNMode(i); ++j) {
41 delete evtDecayTable->getDecay(i, j);
42 }
43 }
44 if (m_Generator) delete m_Generator;
45}
46
47EvtGen* EvtGenInterface::createEvtGen(const std::string& DECFileName, const bool coherentMixing)
48{
49 // Tauola prints normal things to stderr.. oh well.
51 initLogCapture.setIndent(" ");
52 initLogCapture.start();
53 EvtRandom::setRandomEngine(&EvtGenInterface::m_eng);
54
55 // Official BelleII models
56 std::list<EvtDecayBase*> extraModels = EvtGenModelRegister::getModels();
57
58 // Fill model list with pythia, photos etc.
59 // The parameter 'false' means that Pythia codes must not be converted,
60 // since the conversion is applied to all the decfiles since release-06.
61 EvtExternalGenList genList{false};
62 EvtAbsRadCorr* radCorrEngine = genList.getPhotosModel();
63 list<EvtDecayBase*> modelList = genList.getListOfModels();
64 extraModels.insert(extraModels.end(), modelList.begin(), modelList.end());
65
68
69 auto mixingMode = EvtCPUtil::Incoherent;
70 if (coherentMixing)
71 mixingMode = EvtCPUtil::Coherent;
72 else {
73 B2WARNING("Evtgen has been set to decay the B mesons incoherently. This is useful as a workaround only to generate Y(5S, 6S) -> BBar for QCD studies.");
74 B2WARNING("If you are generating Y(4S) events, you _really_ must use the coherent decay mode.");
75 }
76
77 EvtGen* evtGen = new EvtGen(DECFileName.c_str(), tmp.getName().c_str(), &EvtGenInterface::m_eng,
78 radCorrEngine, &extraModels, mixingMode);
79
80 initLogCapture.finish();
81 return evtGen;
82}
83
84int EvtGenInterface::setup(const std::string& DECFileName, const std::string& parentParticle,
85 const std::string& userFileName, const bool coherentMixing)
86{
87 B2DEBUG(20, "Begin initialisation of EvtGen Interface.");
88
89 // Tauola prints normal things to stderr.. oh well.
91 initLogCapture.setIndent(" ");
92 initLogCapture.start();
93 if (!m_Generator) {
94 m_Generator = createEvtGen(DECFileName, coherentMixing);
95 }
96 if (!userFileName.empty()) {
97 m_Generator->readUDecay(userFileName.c_str());
98 }
99
100 // Setup Parent Particle in rest frame
101 if (parentParticle != "") {
102 m_ParentInitialized = true;
103 m_ParentParticle = EvtPDL::getId(parentParticle);
104 }
105 initLogCapture.finish();
106
107 B2DEBUG(20, "End initialisation of EvtGen Interface.");
108
109 return 0;
110}
111
112
113// Add colliding electron/positron to the event graph
114static void addInitialParticle(MCParticleGraph& mpg, int pdg, ROOT::Math::PxPyPzEVector p4)
115{
117
120 part.setPDG(pdg);
121
122 part.set4Vector(p4);
123
124 part.setProductionVertex(0, 0, 0);
125 part.setProductionTime(0);
126 part.setValidVertex(false);
127}
128
129
130
131
133 const std::string& inclusiveParticle)
134{
135 EvtId inclusiveParticleID, inclusiveAntiParticleID;
136
138 B2FATAL("Parent particle is not initialized.");
139 //Init evtgen
140
141 ROOT::Math::PxPyPzEVector pParentParticle = initial.getHER() + initial.getLER();
142 ROOT::Math::PxPyPzEVector herCMS = initial.getBoostedHER();
143 ROOT::Math::XYZVector pPrimaryVertex = initial.getVertex();
144
145 EvtVector4R pinit(pParentParticle.E(), pParentParticle.X(), pParentParticle.Y(), pParentParticle.Z());
146
147 if (inclusiveType != 0) {
148 inclusiveParticleID = EvtPDL::getId(inclusiveParticle);
149 if (inclusiveParticleID.getId() < 0)
150 B2FATAL("Incorrect inclusive particle " << inclusiveParticle);
151 inclusiveAntiParticleID = EvtPDL::chargeConj(inclusiveParticleID);
152 if (inclusiveAntiParticleID.getId() < 0) {
153 B2FATAL("Cannot find the charge-conjugate particle for "
154 << inclusiveParticle);
155 }
156 }
157
158 bool we_got_inclusive_particle = false;
159 do {
161 m_parent = EvtParticleFactory::particleFactory(m_ParentParticle, pinit);
162
163
164 // spin-density matrix for Vector particle produced in e+e-
165 EvtSpinDensity rho;
166 //Set helicity +1 and -1 to 1.
167 rho.setDiag(m_parent->getSpinStates());
168 rho.set(1, 1, EvtComplex(0.0, 0.0));
169
170 // set spin-density matrix, polarisation axis in CMS defined by alpha,beta Euler angles
171 double alpha = herCMS.Phi(), beta = herCMS.Theta(), gamma = 0;
172 m_parent->setSpinDensityForwardHelicityBasis(rho, alpha, beta, gamma);
173
174
175 m_Generator->generateDecay(m_parent);
177
178 if (inclusiveType != 0) {
179 EvtParticle* p = m_parent;
180 // following loop will go through generated event and check it for
181 // presense of inclusive particle
182 do {
183 //for (int ii = 0; ii < iPart ; ii++) {
184 //std::cout << p->getPDGId() << std::endl;
185 if (p->getId() == inclusiveParticleID ||
186 (inclusiveType == 2 && p->getId() == inclusiveAntiParticleID)) {
187 we_got_inclusive_particle = true;
188 break;
189 }
190 p = p->nextIter(m_parent);
191 } while (p != 0);
192
193 if (!we_got_inclusive_particle) {
194 m_parent->deleteTree();
195 }
196 } else {
197 // we don't do inclusive skimming so any generated event will do
198 we_got_inclusive_particle = true;
199 }
200 } while (!we_got_inclusive_particle);
201
202 // B2INFO("after generate Decay.");
203 MCParticleGraph graph;
204
205 addInitialParticle(graph, 11, initial.getHER());
206 addInitialParticle(graph, -11, initial.getLER());
207
208 int iPart = addParticles2Graph(m_parent, graph, pPrimaryVertex, NULL);
210
211 m_parent->deleteTree();
212
213 return iPart; //returns the number of generated particles from evtgen
214}
215
218{
219 int pdg;
220 EvtId id;
221 ROOT::Math::PxPyPzEVector momentum = parent.get4Vector();
222 ROOT::Math::XYZVector vertex = parent.getVertex();
223 EvtVector4R pinit(momentum.E(), momentum.X(), momentum.Y(), momentum.Z());
225 // we want to decay the particle so the decay time in the tree needs to be lower
226 // than whatever the daughters will get
227 parent.setDecayTime(-std::numeric_limits<float>::infinity());
228 pdg = parent.getPDG();
229 id = EvtPDL::evtIdFromStdHep(pdg);
230 m_parent = EvtParticleFactory::particleFactory(id, pinit);
231 if (pdg == 10022) // Virtual photon
232 m_parent->setVectorSpinDensity();
233 else
234 m_parent->setDiagonalSpinDensity();
235 m_Generator->generateDecay(m_parent);
237 int iPart = addParticles2Graph(m_parent, graph, vertex, &parent, parent.getProductionTime());
238 m_parent->deleteTree();
239 return iPart;
240}
241
242int EvtGenInterface::addParticles2Graph(EvtParticle* top, MCParticleGraph& graph, ROOT::Math::XYZVector pPrimaryVertex,
243 MCParticleGraph::GraphParticle* parent, double timeOffset)
244{
245 //Fill top particle in the tree & starting the queue:
246 const int existingParticles = graph.size();
248 if (parent == NULL)
249 p = &graph.addParticle();
250 else
251 p = parent;
252 updateGraphParticle(top, p, pPrimaryVertex);
253
254 typedef pair<MCParticleGraph::GraphParticle*, EvtParticle*> halfFamily;
255 halfFamily currFamily;
256 queue < halfFamily > heritancesQueue;
257
258 for (uint idaughter = 0; idaughter < top->getNDaug(); idaughter++) {
259 currFamily.first = p;
260 currFamily.second = top->getDaug(idaughter);
261 heritancesQueue.push(currFamily);
262 }
263
264 //now we can go through the queue:
265 while (!heritancesQueue.empty()) {
266 currFamily = heritancesQueue.front(); //get the first entry from the queue
267 heritancesQueue.pop(); //remove the entry.
268
269 MCParticleGraph::GraphParticle* currMother = currFamily.first;
270 EvtParticle* currDaughter = currFamily.second;
271
272 //putting the daughter in the graph:
273 MCParticleGraph::GraphParticle* graphDaughter = &graph.addParticle();
274 updateGraphParticle(currDaughter, graphDaughter, pPrimaryVertex, timeOffset);
275
276 //add relation between mother and daughter to graph:
277 currMother->decaysInto((*graphDaughter));
278
279 int nGrandChildren = currDaughter->getNDaug();
280
281 if (nGrandChildren == 0)
283 else {
284 for (int igrandchild = 0; igrandchild < nGrandChildren; igrandchild++) {
285 currFamily.first = graphDaughter;
286 currFamily.second = currDaughter->getDaug(igrandchild);
287 heritancesQueue.push(currFamily);
288 }
289 }
290 }
291
292 return graph.size() - existingParticles;
293}
294
295
297 ROOT::Math::XYZVector pPrimaryVertex, double timeOffset)
298{
299 //updating the GraphParticle information from the EvtParticle information
300
302 gParticle->setMass(eParticle->mass());
303 gParticle->setPDG(EvtPDL::getStdHep(eParticle->getId()));
304
305 EvtVector4R EvtP4 = eParticle->getP4Lab();
306 ROOT::Math::PxPyPzEVector p4(EvtP4.get(1), EvtP4.get(2), EvtP4.get(3), EvtP4.get(0));
307 gParticle->set4Vector(p4);
308
309 EvtVector4R Evtpos = eParticle->get4Pos();
310
311 ROOT::Math::XYZVector pVertex(Evtpos.get(1)*Unit::mm, Evtpos.get(2)*Unit::mm, Evtpos.get(3)*Unit::mm);
312 pVertex = pVertex + pPrimaryVertex;
313
314 gParticle->setProductionVertex(pVertex.x(), pVertex.y(), pVertex.z());
315 gParticle->setProductionTime((Evtpos.get(0)*Unit::mm / Const::speedOfLight) + timeOffset);
316 gParticle->setValidVertex(true);
317
318 //add PHOTOS flag
319 if (eParticle->getAttribute("FSR")) {
321 }
322
323}
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
static const double electronMass
electron mass
Definition: Const.h:685
static EvtGenDatabasePDG * Instance()
Instance method that loads the EvtGen table.
void WriteEvtGenTable(std::ostream &out)
Write current database as EvtGen table to a stream.
int simulateEvent(MCInitialParticles initial, int inclusiveType, const std::string &inclusiveParticle)
Generate a single event.
int simulateDecay(MCParticleGraph &graph, MCParticleGraph::GraphParticle &parent)
Simulate a particle decay.
EvtGen * m_Generator
Variable needed for EvtGen generator.
IOIntercept::OutputToLogMessages m_logCaptureDebug
Capture EvtGen log and transform into basf2 logging as B2DEBUG messages.
int setup(const std::string &decayFileName, const std::string &parentParticle, const std::string &userFileName=std::string(""), bool coherentMixing=true)
Setup evtgen with the given decay files
static EvtGenFwRandEngine m_eng
Variable needed for random generator.
EvtParticle * m_parent
Variable needed for parent particle.
static EvtGen * createEvtGen(const std::string &decayFileName, bool coherentMixing)
Create and initialize an EvtGen instance:
EvtId m_ParentParticle
Variable needed for parent particle ID.
bool m_ParentInitialized
Whether parent particle is initialized.
void updateGraphParticle(EvtParticle *eParticle, MCParticleGraph::GraphParticle *gParticle, ROOT::Math::XYZVector pPrimaryVertex, double timeOffset=0)
Copy parameters from EvtParticle to MCParticle.
int addParticles2Graph(EvtParticle *particle, MCParticleGraph &graph, ROOT::Math::XYZVector pPrimaryVertex, MCParticleGraph::GraphParticle *parent, double timeOffset=0)
Convert EvtParticle structure to flat MCParticle list.
Helper file to create a temporary file and ensure deletion if object goes out of scope.
Definition: FileSystem.h:128
std::string getName() const
get filename of the temporary file
Definition: FileSystem.h:141
bool start()
Start intercepting the output.
Definition: IOIntercept.h:155
Capture stdout and stderr and convert into log messages.
Definition: IOIntercept.h:226
void setIndent(const std::string &indent)
Set the indent for each line of the output, default is the supplied name + ": "
Definition: IOIntercept.h:257
bool finish()
Finish the capture and emit the message if output has appeard on stdout or stderr.
Definition: IOIntercept.cc:236
@ c_Info
Info: for informational messages, e.g.
Definition: LogConfig.h:27
This class contains the initial state for the given event.
const ROOT::Math::PxPyPzEVector & getHER() const
Get 4vector of the high energy beam.
ROOT::Math::PxPyPzEVector getBoostedHER() const
Get the 4-vector of electron beam in CM system obtained by pure boost.
const ROOT::Math::PxPyPzEVector & getLER() const
Get 4vector of the low energy beam.
const ROOT::Math::XYZVector & getVertex() const
Get the position of the collision.
Class to represent Particle data in graph.
void decaysInto(GraphParticle &daughter)
Tells the graph that this particle decays into daughter.
Class to build, validate and sort a particle decay chain.
@ c_checkCyclic
Check for cyclic dependencies.
@ c_setDecayInfo
Set decay time and vertex.
size_t size() const
Return the number of particles in the graph.
void generateList(const std::string &name="", int options=c_setNothing)
Generates the MCParticle list and stores it in the StoreArray with the given name.
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
Definition: MCParticle.h:57
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition: MCParticle.h:63
@ 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
void setDecayTime(float time)
Set decay time.
Definition: MCParticle.h:390
void setMass(float mass)
Set particle mass.
Definition: MCParticle.h:366
void addStatus(unsigned short int bitmask)
Add bitmask to current status.
Definition: MCParticle.h:353
ROOT::Math::XYZVector getVertex() const
Return production vertex position, shorthand for getProductionVertex().
Definition: MCParticle.h:183
void setValidVertex(bool valid)
Set indication wether vertex and time information is valid or just default.
Definition: MCParticle.h:378
void setProductionVertex(const ROOT::Math::XYZVector &vertex)
Set production vertex position.
Definition: MCParticle.h:396
ROOT::Math::PxPyPzEVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:207
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:335
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
float getProductionTime() const
Return production time in ns.
Definition: MCParticle.h:159
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:438
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:346
void setProductionTime(float time)
Set production time.
Definition: MCParticle.h:384
static const double mm
[millimeters]
Definition: Unit.h:70
Evtgen random generator.
static std::list< EvtDecayBase * > getModels()
Return a list of models.
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
STL namespace.