14 #include <generators/utilities/GeneratorConst.h>
15 #include "Pythia8/Pythia.h"
16 #include "EvtGen/EvtGen.hh"
17 #include "EvtGenBase/EvtRandomEngine.hh"
18 #include "EvtGenBase/EvtParticle.hh"
19 #include "EvtGenBase/EvtParticleFactory.hh"
20 #include "EvtGenBase/EvtPDL.hh"
21 #include "EvtGenBase/EvtDecayTable.hh"
22 #include "EvtGenBase/EvtParticleDecayList.hh"
23 #include "EvtGenBase/EvtDecayBase.hh"
24 #include "EvtGenExternal/EvtExternalGenList.hh"
93 EvtGenDecays(Pythia8::Pythia* pythiaPtrIn, EvtGen* evtGen,
bool limit =
true);
96 EvtGenDecays(Pythia8::Pythia* pythiaPtrIn, std::string decayFile, std::string particleDataFile,
97 EvtExternalGenList* extPtrIn = 0, EvtAbsRadCorr* fsrPtrIn = 0,
98 int mixing = 1,
bool xml =
false,
bool limit =
true,
99 bool extUse =
true,
bool fsrUse =
true);
162 void updateEvent(Pythia8::Particle* pyPro, EvtParticle* egPro,
163 std::vector<int>* pySigs = 0, std::vector<EvtParticle*>* egSigs = 0,
164 std::vector<double>* bfs = 0,
double* wgt = 0);
256 extOwner(false), fsrOwner(false), extPtr(nullptr), fsrPtr(nullptr),
257 signalSuffix(
"_SIGNAL"), pythiaPtr(pythiaPtrIn), rndm(nullptr),
258 evtgen(evtGen), updated(false)
264 std::string particleDataFile, EvtExternalGenList* extPtrIn,
265 EvtAbsRadCorr* fsrPtrIn,
int mixing,
bool xml,
bool limit,
266 bool extUse,
bool fsrUse) : extPtr(extPtrIn), fsrPtr(fsrPtrIn),
267 signalSuffix(
"_SIGNAL"), pythiaPtr(pythiaPtrIn), rndm(&pythiaPtr->rndm),
273 B2ERROR(
"Error in EvtGenDecays::EvtGenDecays: extPtr is null but fsrPtr is provided");
281 evtgen =
new EvtGen(decayFile.c_str(), particleDataFile.c_str(),
335 Pythia8::Event&
event =
pythiaPtr->event;
336 std::vector<int> pySigs; std::vector<EvtParticle*> egSigs, egPrts;
337 std::vector<double> bfs;
double wgt(1.);
338 for (
int iPro = 0; iPro <
event.size(); ++iPro) {
341 Pythia8::Particle* pyPro = &
event[iPro];
342 if (!pyPro->isFinal())
continue;
344 if (pyPro->status() == 93 || pyPro->status() == 94)
continue;
347 EvtParticle* egPro = EvtParticleFactory::particleFactory
348 (EvtPDL::evtIdFromStdHep(pyPro->id()),
349 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
350 egPrts.push_back(egPro);
351 egPro->setDiagonalSpinDensity();
352 evtgen->generateDecay(egPro);
353 pyPro->tau(egPro->getLifetime());
358 updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
362 pySigs.push_back(pyPro->index());
363 egSigs.push_back(egPro);
364 bfs.push_back(
signal->second.bfs[0]);
365 wgt *= 1 - bfs.back();
366 egPro->deleteDaughters();
367 EvtParticle* egDau = EvtParticleFactory::particleFactory
368 (EvtPDL::evtIdFromStdHep(pyPro->id()),
369 EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
370 egDau->addDaug(egPro);
371 egDau->setDiagonalSpinDensity();
374 }
else updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
376 if (pySigs.size() == 0) {
377 for (
int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
378 egPrts[iPrt]->deleteTree();
383 std::vector<int> modes;
int force(-1);
384 for (
int iTry = 1; iTry <=
NTRYDECAY; ++iTry) {
387 modes.clear(); force =
pythiaPtr->rndm.pick(bfs); n = 0;
388 for (
int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
389 if (iSig == force) modes.push_back(0);
390 else modes.push_back(
pythiaPtr->rndm.flat() > bfs[iSig]);
391 if (modes.back() == 0) ++n;
393 if (
pythiaPtr->rndm.flat() <= 1.0 / n)
break;
396 B2WARNING(
"Warning in EvtGenDecays::decay: maximum number of signal decay attempts exceeded"
402 for (
int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
403 EvtParticle* egSig = egSigs[iSig];
404 Pythia8::Particle* pySig = &
event[pySigs[iSig]];
406 if (egSig->getNDaug() > 0) egSig = egSig->getDaug(0);
407 if (modes[iSig] == 0) egSig->setId(
signal->second.egId);
409 signal->second.modes.getDecayModel(egSig);
410 egSig->setChannel(
signal->second.map[egSig->getChannel()]);
413 pySig->status(pySig->status() == 92 || pySig->status() == 94 ? 96 : 95);
414 evtgen->generateDecay(egSig);
419 for (
int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
420 egPrts[iPrt]->deleteTree();
436 for (
int entry = 0; entry < (int)EvtPDL::entries(); ++entry) {
437 EvtId egId = EvtPDL::getEntry(entry);
438 int pyId = EvtPDL::getStdHep(egId);
439 pythiaPtr->particleData.spinType(pyId, EvtPDL::getSpinType(egId));
440 pythiaPtr->particleData.chargeType(pyId, EvtPDL::chg3(egId));
441 pythiaPtr->particleData.m0(pyId, EvtPDL::getMass(egId));
442 pythiaPtr->particleData.mWidth(pyId, EvtPDL::getWidth(egId));
443 pythiaPtr->particleData.mMin(pyId, EvtPDL::getMinMass(egId));
444 pythiaPtr->particleData.mMax(pyId, EvtPDL::getMaxMass(egId));
445 pythiaPtr->particleData.tau0(pyId, EvtPDL::getctau(egId));
460 int pyId =
pythiaPtr->particleData.nextId(0);
462 EvtId egId = EvtPDL::evtIdFromStdHep(pyId);
463 EvtPDL::reSetMass(egId,
pythiaPtr->particleData.m0(pyId));
464 EvtPDL::reSetWidth(egId,
pythiaPtr->particleData.mWidth(pyId));
465 EvtPDL::reSetMassMin(egId,
pythiaPtr->particleData.mMin(pyId));
466 EvtPDL::reSetMassMax(egId,
pythiaPtr->particleData.mMax(pyId));
467 pyId =
pythiaPtr->particleData.nextId(pyId);
488 EvtDecayTable* egTable = EvtDecayTable::getInstance();
489 if (!egTable)
return;
490 for (
int iEntry = 0; iEntry < (int)EvtPDL::entries(); ++iEntry) {
491 EvtId egId = EvtPDL::getEntry(iEntry);
492 int pyId = EvtPDL::getStdHep(egId);
493 if (egTable->getNModes(egId) == 0)
continue;
499 pythiaPtr->particleData.mayDecay(pyId,
false);
503 std::string egName = EvtPDL::name(egId);
504 if (egName.size() <=
signalSuffix.size() || egName.substr
511 signal->second.egId = egId;
512 signal->second.bfs = std::vector<double>(2, 0);
513 if (!
final)
continue;
516 std::vector<EvtParticleDecayList> egList = egTable->getDecayTable();
517 int sigIdx = egId.getAlias();
518 int bkgIdx = EvtPDL::evtIdFromStdHep(pyId).getAlias();
519 if (sigIdx > (
int)egList.size() || bkgIdx > (
int)egList.size())
continue;
520 EvtParticleDecayList sigModes = egList[sigIdx];
521 EvtParticleDecayList bkgModes = egList[bkgIdx];
522 EvtParticleDecayList allModes = egList[bkgIdx];
526 for (
int iMode = 0; iMode < sigModes.getNMode(); ++iMode) {
527 EvtDecayBase* mode = sigModes.getDecayModel(iMode);
529 signal->second.bfs[0] += mode->getBranchingFraction();
530 sum += mode->getBranchingFraction();
534 for (
int iMode = 0; iMode < allModes.getNMode(); ++iMode) {
535 EvtDecayBase* mode = allModes.getDecayModel(iMode);
538 for (
int jMode = 0; jMode < sigModes.getNMode(); ++jMode)
539 if (mode->matchingDecay(*(sigModes.getDecayModel(jMode)))) {
542 if (match) bkgModes.removeMode(mode);
544 signal->second.map.push_back(iMode);
545 signal->second.bfs[1] += mode->getBranchingFraction();
546 sum += mode->getBranchingFraction();
549 signal->second.modes = bkgModes;
550 for (
int iBf = 0; iBf < (int)
signal->second.bfs.size(); ++iBf)
551 signal->second.bfs[iBf] /= sum;
577 std::vector<int>* pySigs, std::vector<EvtParticle*>* egSigs,
578 std::vector<double>* bfs,
double* wgt)
583 EvtParticle* egMom = egPro;
584 if (egPro->getNDaug() == 1 && egPro->getPDGId() ==
585 egPro->getDaug(0)->getPDGId()) egMom = egPro->getDaug(0);
586 Pythia8::Event&
event =
pythiaPtr->event;
587 std::vector< std::pair<EvtParticle*, int> >
588 moms(1, std::pair<EvtParticle*, int>(egMom, pyPro->index()));
591 while (moms.size() != 0) {
594 egMom = moms.back().first;
595 int iMom = moms.back().second;
596 Pythia8::Particle* pyMom = &
event[iMom];
602 pyMom->daughters(event.size(), event.size() + egMom->getNDaug() - 1);
604 Pythia8::Vec4 vProd = pyMom->vDec();
605 for (
int iDtr = 0 ; iDtr < (int)egMom->getNDaug(); ++iDtr) {
606 EvtParticle* egDtr = egMom->getDaug(iDtr);
607 int id = egDtr->getPDGId();
608 EvtVector4R p = egDtr->getP4Lab();
609 int idx =
event.append(
id, 93, iMom, 0, 0, 0, 0, 0, p.get(1),
610 p.get(2), p.get(3), p.get(0), egDtr->mass());
611 Pythia8::Particle* pyDtr = &
event.back();
613 pyDtr->tau(egDtr->getLifetime());
614 if (pySigs && egSigs && bfs && wgt &&
checkSignal(pyDtr)) {
615 pySigs->push_back(pyDtr->index());
616 egSigs->push_back(egDtr);
617 bfs->push_back(
signal->second.bfs[0]);
618 (*wgt) *= 1 - bfs->back();
619 egDtr->deleteDaughters();
621 if (osc) pyDtr->status(94);
622 if (egDtr->getAttribute(
"FSR"))
623 pyDtr->status(Belle2::GeneratorConst::FSR_STATUS_CODE);
624 if (egDtr->getNDaug() > 0)
625 moms.push_back(std::pair<EvtParticle*, int>(egDtr, idx));
639 using ::Pythia8::pow2;
644 if (
limitRadius && pow2(pyPro->xDec()) + pow2(pyPro->yDec())
645 + pow2(pyPro->zDec()) > pow2(
rMax))
return false;
646 if (
limitCylinder && (pow2(pyPro->xDec()) + pow2(pyPro->yDec())
647 > pow2(
xyMax) || abs(pyPro->zDec()) >
zMax))
return false;
659 signal->second.status == pyPro->status()))
return true;
672 if (egPro && egPro->getNDaug() == 1 &&
673 egPro->getPDGId() != egPro->getDaug(0)->getPDGId())
return true;
A class to perform decays via the external EvtGen decay program, see http://evtgen....
EvtGen * evtgen
The EvtGen object.
void updateData(bool final=false)
Update the particles to decay with EvtGen, and the selected signals.
EvtAbsRadCorr * fsrPtr
FSR model pointer.
void exclude(int id)
Stop EvtGen decaying a particle.
std::map< int, Signal >::iterator signal
The selected signal iterator.
double tauMax
the pythia parameter ParticleDecays:tauMax
EvtGenDecays & operator=(const EvtGenDecays &)=delete
forbid assignment
bool limitCylinder
the pythia parameter ParticleDecays:limitCylinder
~EvtGenDecays()
Destructor.
EvtGenDecays(Pythia8::Pythia *pythiaPtrIn, EvtGen *evtGen, bool limit=true)
Expert constructor which takes an already initialized EvtGen instance.
bool fsrOwner
bool has FSR model
std::map< int, Signal > signals
signal particles and statuses
std::set< int > incIds
Set of particle IDs to include decays with EvtGen.
std::list< EvtDecayBase * > models
list of model pointers
bool checkSignal(Pythia8::Particle *pyPro)
Check if a particle is signal.
bool updated
Flag whether the final particle update has been performed.
EvtGenDecays(const EvtGenDecays &)=delete
forbid copy
EvtExternalGenList * extPtr
External model pointer.
bool checkVertex(Pythia8::Particle *pyPro)
Check if a particle can decay.
double zMax
the pythia parameter ParticleDecays:zMax
void updatePythia()
Update the Pythia particle database from EvtGen.
bool checkOsc(EvtParticle *egPro)
Check if an EvtGen particle has oscillated.
double xyMax
the pythia parameter ParticleDecays:xyMax
std::set< int > excIds
Set of particle IDs to exclude decays with EvtGen.
bool limitTau
the pythia parameter ParticleDecays:limitTau
double rMax
the pythia parameter ParticleDecays:rMax
static constexpr int NTRYDECAY
Number of times to try a decay sampling (constant).
void updateEvtGen()
Update the EvtGen particle database from Pythia.
bool limitRadius
the pythia parameter ParticleDecays:limitRadius
bool limitDecay
is the decay limited
void readDecayFile(std::string decayFile, bool xml=false)
Read an EvtGen user decay file.
bool extOwner
bool has external model
void getDecayLimits(bool limit)
Get the Decay limits from Pythia.
std::string signalSuffix
The suffix indicating an EvtGen particle or alias is signal.
void updateEvent(Pythia8::Particle *pyPro, EvtParticle *egPro, std::vector< int > *pySigs=0, std::vector< EvtParticle * > *egSigs=0, std::vector< double > *bfs=0, double *wgt=0)
Update the Pythia event record with an EvtGen decay tree.
EvtGenRandom rndm
Random number wrapper for EvtGen.
double decay()
Perform all decays and return the event weight.
bool limitTau0
the pythia parameter ParticleDecays:limitTau0
Pythia8::Pythia * pythiaPtr
The pointer to the associated Pythia object.
double tau0Max
Parameters used to check if a particle should decay (as set via Pythia).
A class to wrap the Pythia random number generator for use by EvtGen.
double random()
Return a random number.
EvtGenRandom(Pythia8::Rndm *rndmPtrIn)
Constructor.
Pythia8::Rndm * rndmPtr
The random number pointer.
Class to store variables with their name which were sent to the logging service.
Map of signal particle info.
std::vector< int > map
the map for statuses
int status
status needed to consider a particle a signal
EvtParticleDecayList modes
list of decay modes &
std::vector< double > bfs
branching fractions