9#include <generators/modules/fragmentation/FragmentationModule.h>
11#include <generators/evtgen/EvtGenInterface.h>
12#include <generators/utilities/GeneratorConst.h>
14#include <framework/gearbox/Unit.h>
15#include <framework/gearbox/Const.h>
16#include <framework/particledb/EvtGenDatabasePDG.h>
17#include <framework/utilities/FileSystem.h>
21#include <mdst/dataobjects/MCParticleGraph.h>
23#include <framework/logging/Logger.h>
24#include <framework/utilities/IOIntercept.h>
30using namespace Pythia8;
48 addParam(
"ListPYTHIAEvent",
m_listEvent,
"List event record of PYTHIA after hadronization", 0);
55 "PDG Code of the mother particle of the quark pair (default Z0 boson)", 23);
78 statLogCapture.
start();
86 B2WARNING(
"Not all events could be fragmented: " <<
nAll -
nGood <<
" events failed.");
87 B2WARNING(
"Total number of events: " <<
nAll <<
", of these fragmented: " <<
nGood <<
", success-ratio (should be >97%): " << ratio
89 B2WARNING(
"Please contact the generator librarian if the success ratio is below 97%.");
90 B2WARNING(
"Please treat the success-ratio as correction of the effective cross section due to unphysical events.");
101 B2DEBUG(150,
"Initialize PYTHIA8");
109 initLogCapture.
start();
113 (*m_PythiaEvent) = 0;
120 m_Pythia->readString(
"ProcessLevel:all = off");
124 B2FATAL(
"Cannot read Pythia parameter file.");
128 m_Pythia->setRndmEnginePtr(fragRndm);
137 B2INFO(
"Using PYTHIA EvtGen Interface");
140 B2ERROR(
"No global decay file defined, please make sure the parameter 'DecFile' is set correctly");
143 if (defaultDecFile.empty()) {
144 B2WARNING(
"Cannot find default decay file");
145 }
else if (defaultDecFile !=
m_DecFile) {
146 B2INFO(
"Using non-standard DECAY file \"" <<
m_DecFile <<
"\"");
180 resetLogCapture.
start();
190 std::map<int, int> indexPYTHIA;
193 std::map<int, int> indexMCGraph;
196 int quarkPosition = 0;
200 for (
int iPart = 0; iPart < nPart; iPart++) {
207 if (pythiaIndex != 0) {
208 indexPYTHIA[
nAdded] = iPart;
209 if (pythiaIndex > 0) quarkPosition = iPart;
215 B2FATAL(
"Invalid number of quarks: " <<
nQuarks <<
" (should be 2)!");
219 B2WARNING(
"No virtual exchange particle given, no PYTHIA FSR in Decays");
222 m_Pythia->forceTimeShower(2, 3, 20.00);
233 eventLogCapture.
start();
239 listLogCapture.
start();
251 decayLogCapture.
start();
258 for (
int iPythiaPart = 0; iPythiaPart <
m_Pythia->event.size(); ++iPythiaPart) {
259 auto oldindex = indexPYTHIA.find(iPythiaPart);
262 if (
m_Pythia->event[iPythiaPart].id() == 90)
continue;
264 if (oldindex == end(indexPYTHIA)) {
270 indexMCGraph[iPythiaPart] = position;
276 if (
m_Pythia->event[iPythiaPart].statusHepMC() < 1)
continue;
279 p->setPDG(
m_Pythia->event[iPythiaPart].id());
282 ROOT::Math::PxPyPzEVector p4(
m_Pythia->event[iPythiaPart].px(),
m_Pythia->event[iPythiaPart].py(),
286 p->setMass(
m_Pythia->event[iPythiaPart].m());
292 p->setValidVertex(
true);
298 if (
m_Pythia->event[iPythiaPart].status() == 51 &&
m_Pythia->event[iPythiaPart].id() == 22) {
303 if (
m_Pythia->event[iPythiaPart].status() == GeneratorConst::FSR_STATUS_CODE &&
m_Pythia->event[iPythiaPart].id() == 22) {
308 if (
m_Pythia->event[iPythiaPart].statusHepMC() == 1) {
313 const int motherid =
m_Pythia->event[iPythiaPart].mother1();
316 auto motherindex = indexMCGraph.find(motherid);
318 if (motherindex != end(indexMCGraph)) {
319 int motheridingraph = indexMCGraph[motherid];
350 const int id = mcParticle.
getPDG();
354 bool isQuark =
false;
355 if (abs(
id) >= 1 && abs(
id) <= 5) isQuark =
true;
358 if (!(isVPho || isQuark))
return 0;
362 B2WARNING(
"Quark already has a daughter!");
367 const double mass = mcParticle.
getMass();
368 const ROOT::Math::XYZVector& p = mcParticle.
getMomentum();
369 const double energy =
sqrt(mass * mass + p.Mag2());
373 m_PythiaEvent->append(
m_quarkPairMotherParticle, -22, 0, 0, 2, 3, 0, 0, p.X(), p.Y(), p.Z(), energy, mass);
376 m_PythiaEvent->append(
id, 23, 1, 0, 0, 0, 101, 0, p.X(), p.Y(), p.Z(), energy, mass, 20.0);
379 m_PythiaEvent->append(
id, 23, 1, 0, 0, 0, 0, 101, p.X(), p.Y(), p.Z(), energy, mass, 20.0);
390 Pythia8::ParticleData* particleData = &pythia->particleData;
391 int nParticles = EvtPDL::entries();
392 for (
int i = 0; i < nParticles; ++i) {
393 EvtId evtgenParticle = EvtPDL::getEntry(i);
399 int pdg = EvtPDL::getStdHep(evtgenParticle);
400 if (pdg <= 10 || (pdg > 20 && pdg <= 100))
402 EvtId evtgenAntiParticle = EvtPDL::chargeConj(evtgenParticle);
403 if (particleData->isParticle(pdg)) {
404 particleData->setAll(pdg,
405 EvtPDL::name(evtgenParticle),
406 EvtPDL::name(evtgenAntiParticle),
407 EvtPDL::getSpinType(evtgenParticle),
408 EvtPDL::chg3(evtgenParticle),
411 EvtPDL::getMeanMass(evtgenParticle),
412 EvtPDL::getWidth(evtgenParticle),
413 EvtPDL::getMinMass(evtgenParticle),
414 EvtPDL::getMaxMass(evtgenParticle),
415 EvtPDL::getctau(evtgenParticle));
417 particleData->addParticle(
419 EvtPDL::name(evtgenParticle),
420 EvtPDL::name(evtgenAntiParticle),
421 EvtPDL::getSpinType(evtgenParticle),
422 EvtPDL::chg3(evtgenParticle),
425 EvtPDL::getMeanMass(evtgenParticle),
426 EvtPDL::getWidth(evtgenParticle),
427 EvtPDL::getMinMass(evtgenParticle),
428 EvtPDL::getMaxMass(evtgenParticle),
429 EvtPDL::getctau(evtgenParticle));
437FragmentationRndm::FragmentationRndm() : Pythia8::RndmEngine()
444 double value = gRandom->Rndm();
static const double speedOfLight
[cm/ns]
static EvtGen * createEvtGen(const std::string &decayFileName, bool coherentMixing)
Create and initialize an EvtGen instance:
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
EvtGenDecays * evtgen
EvtGen decay engine inside PYTHIA8.
int nGood
number of events with successful fragmentation.
FragmentationModule()
Constructor.
void loadEvtGenParticleData(Pythia8::Pythia *pythia)
Load EvtGen particle data.
bool m_coherentMixing
decay the B0-B0bar coherently.
int nVpho
number of virtual exchange particles.
virtual void initialize() override
Initialize the module.
virtual void event() override
Event method (process events)
Pythia8::Pythia * m_Pythia
Pythia generator.
StoreArray< MCParticle > m_mcparticles
store array for the MCParticles
virtual ~FragmentationModule()
Destructor.
virtual void terminate() override
terminate the module
Pythia8::Event * m_PythiaEvent
Pythia event.
int addParticleToPYTHIA(const MCParticle &mcParticle)
Add particle to Pythia event.
std::string m_DecFile
EvtGen decay file.
int m_useEvtGen
use EvtGen for some decays.
int nAll
number of events created.
std::string m_UserDecFile
User EvtGen decay file.
std::string m_particleList
The name of the MCParticle collection.
int nQuarks
number of quarks.
MCParticleGraph mcParticleGraph
An instance of the MCParticle graph.
std::string m_parameterfile
Module parameters.
std::vector< int > m_additionalPDGCodes
Additional particles used in Pythia.
int nAdded
number of added particles.
int m_quarkPairMotherParticle
PDG Code of the mother particle of the quark pair.
int m_listEvent
list event generated by PYTHIA.
Minimal class for external random generator to be used in PYTHIA.
double flat()
flat random generator.
bool start()
Start intercepting the output.
Capture stdout and stderr and convert into log messages.
bool finish()
Finish the capture and emit the message if output has appeard on stdout or stderr.
@ c_Error
Error: for things that went wrong and have to be fixed.
@ c_Debug
Debug: for code development.
@ c_Warning
Warning: for potential problems that the user should pay attention to.
Class to represent Particle data in graph.
@ c_checkCyclic
Check for cyclic dependencies.
@ c_clearParticles
Clear the particle list before adding the graph.
@ c_setDecayInfo
Set decay time and vertex.
size_t size() const
Return the number of particles in the graph.
void loadList(const std::string &name="")
Load the MCParticle list given by name into 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.
A Class to store the Monte Carlo particle information.
@ c_IsFSRPhoton
bit 7: Particle is from final state radiation
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
float getMass() const
Return the particle mass in GeV.
int getPDG() const
Return PDG code of particle.
ROOT::Math::XYZVector getMomentum() const
Return momentum.
void setDescription(const std::string &description)
Sets the description of the module.
void setReturnValue(int value)
Sets the return value for this module as integer.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
int getEntries() const
Get the number of objects in the array.
static const double mm
[millimeters]
A class to perform decays via the external EvtGen decay program, see http://evtgen....
void readDecayFile(std::string decayFile, bool xml=false)
Read an EvtGen user decay file.
std::string signalSuffix
The suffix indicating an EvtGen particle or alias is signal.
double decay()
Perform all decays and return the event weight.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
void clear()
Reset particles and decay information to make the class reusable.
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.