Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:36

0001 // EvtGen.h is a part of the PYTHIA event generator.
0002 // Copyright (C) 2024 Torbjorn Sjostrand.
0003 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
0004 // Please respect the MCnet Guidelines, see GUIDELINES for details.
0005 // Author: Philip Ilten.
0006 
0007 // This file contains an EvtGen interface. HepMC and EvtGen must be enabled.
0008 
0009 #ifndef Pythia8_EvtGen_H
0010 #define Pythia8_EvtGen_H
0011 
0012 #include "Pythia8/Pythia.h"
0013 #include "EvtGen/EvtGen.hh"
0014 #include "EvtGenBase/EvtRandomEngine.hh"
0015 #include "EvtGenBase/EvtParticle.hh"
0016 #include "EvtGenBase/EvtParticleFactory.hh"
0017 #include "EvtGenBase/EvtPDL.hh"
0018 #include "EvtGenBase/EvtDecayTable.hh"
0019 #include "EvtGenBase/EvtParticleDecayList.hh"
0020 #include "EvtGenBase/EvtDecayBase.hh"
0021 #include "EvtGenExternal/EvtExternalGenList.hh"
0022 
0023 namespace Pythia8 {
0024 
0025 //==========================================================================
0026 
0027 // A class to wrap the Pythia random number generator for use by EvtGen.
0028 
0029 class EvtGenRandom : public EvtRandomEngine {
0030 
0031 public:
0032 
0033   // Constructor.
0034   EvtGenRandom(Rndm *rndmPtrIn) {rndmPtr = rndmPtrIn;}
0035 
0036   // Return a random number.
0037   double random() {if (rndmPtr) return rndmPtr->flat(); else return -1.0;}
0038 
0039   // The random number pointer.
0040   Rndm *rndmPtr;
0041 
0042 };
0043 
0044 //==========================================================================
0045 
0046 // A class to perform decays via the external EvtGen decay program,
0047 // see http://evtgen.warwick.ac.uk/, the program manual provided with
0048 // the EvtGen distribution, and D. J. Lange,
0049 // Nucl. Instrum. Meth. A462, 152 (2001) for details.
0050 
0051 // EvtGen performs a series of decays from some initial particle
0052 // decay, rather than just a single decay, and so EvtGen cannot be
0053 // interfaced through the standard external DecayHandler class without
0054 // considerable complication. Consequently, EvtGen is called on the
0055 // complete event record after all steps of Pythia are completed.
0056 
0057 // Oftentimes a specific "signal" decay is needed to occur once in an
0058 // event, and all other decays performed normally. This is possible
0059 // via reading in a user decay file (with readDecayFile) and creating
0060 // aliased particles with names ending with signalSuffix. By default,
0061 // this is "_SIGNAL". When decay() is called, all particles in the
0062 // Pythia event record that are of the same types as the signal
0063 // particles are collected. One is selected at random and decayed via
0064 // the channel(s) defined for that aliased signal particle. All other
0065 // particles are decayed normally. The weight for the event is
0066 // calculated and returned.
0067 
0068 // It is also possible to specify a status needed to consider a
0069 // particle as a signal candidate. This can be done by modifying the
0070 // signals map, e.g. if the tau- is a signal candidate, then
0071 //     EvtGenDecays.signals[15].status = 201
0072 // will only only select as candidates any tau- with this status. This
0073 // allows the event record to be changed before decays, so only
0074 // certain particles are selected as possible signal candidates
0075 // (e.g. passing kinematic requirements).
0076 
0077 // Please note that particles produced from a signal candidate decay
0078 // are not searched for additional signal candidates. This means that
0079 // if B0 and tau- have been designated as signal, then a tau- from a
0080 // W- decay would be a signal candidate, while a tau- from a B0 decay
0081 // would not. This restriction arises from the additional complexity
0082 // of allowing recursive signal decays. The following statuses are
0083 // used: 93 for particles decayed with EvtGen, 94 for particles
0084 // oscillated with EvtGen, 95 for signal particles, and 96 for signal
0085 // particles from an oscillation.
0086 
0087 class EvtGenDecays {
0088 
0089 public:
0090 
0091   // Constructor.
0092   EvtGenDecays(Pythia *pythiaPtrIn, string decayFile, string particleDataFile,
0093     EvtExternalGenList *extPtrIn = 0, EvtAbsRadCorr *fsrPtrIn = 0,
0094     int mixing = 1, bool xml = false, bool limit = true,
0095     bool extUse = true, bool fsrUse = true);
0096 
0097   // Destructor.
0098   ~EvtGenDecays() {
0099     if (evtgen) delete evtgen;
0100     if (extOwner && extPtr) delete extPtr;
0101     if (fsrOwner && fsrPtr) delete fsrPtr;
0102   }
0103 
0104   // Perform all decays and return the event weight.
0105   double decay();
0106 
0107   // Stop EvtGen decaying a particle.
0108   void exclude(int id) {excIds.insert(id);}
0109 
0110   // Update the Pythia particle database from EvtGen.
0111   void updatePythia();
0112 
0113   // Update the EvtGen particle database from Pythia.
0114   void updateEvtGen();
0115 
0116   // Read an EvtGen user decay file.
0117   void readDecayFile(string decayFile, bool xml = false) {
0118     evtgen->readUDecay(decayFile.c_str(), xml); updateData();}
0119 
0120   // External model pointer and FSR model pointer.
0121   bool extOwner, fsrOwner;
0122   EvtExternalGenList *extPtr;
0123   EvtAbsRadCorr      *fsrPtr;
0124   std::list<EvtDecayBase*> models;
0125 
0126   // Map of signal particle info.
0127   struct Signal {int status; EvtId egId; vector<double> bfs; vector<int> map;
0128     EvtParticleDecayList modes;};
0129   map<int, Signal> signals;
0130 
0131   // The suffix indicating an EvtGen particle or alias is signal.
0132   string signalSuffix;
0133 
0134 protected:
0135 
0136   // Update the particles to decay with EvtGen, and the selected signals.
0137   void updateData(bool final = false);
0138 
0139   // Update the Pythia event record with an EvtGen decay tree.
0140   void updateEvent(Particle *pyPro, EvtParticle *egPro,
0141     vector<int> *pySigs = 0, vector<EvtParticle*> *egSigs = 0,
0142     vector<double> *bfs = 0, double *wgt = 0);
0143 
0144   // Check if a particle can decay.
0145   bool checkVertex(Particle *pyPro);
0146 
0147   // Check if a particle is signal.
0148   bool checkSignal(Particle *pyPro);
0149 
0150   // Check if an EvtGen particle has oscillated.
0151   bool checkOsc(EvtParticle *egPro);
0152 
0153   // Number of times to try a decay sampling (constant).
0154   static const int NTRYDECAY = 1000;
0155 
0156   // The pointer to the associated Pythia object.
0157   Pythia *pythiaPtr;
0158 
0159   // Random number wrapper for EvtGen.
0160   EvtGenRandom rndm;
0161 
0162   // The EvtGen object.
0163   EvtGen *evtgen;
0164 
0165   // Set of particle IDs to include and exclude decays with EvtGen.
0166   set<int> incIds, excIds;
0167 
0168   // Flag whether the final particle update has been performed.
0169   bool updated;
0170 
0171   // The selected signal iterator.
0172   map<int, Signal>::iterator signal;
0173 
0174   // Parameters used to check if a particle should decay (as set via Pythia).
0175   double tau0Max, tauMax, rMax, xyMax, zMax;
0176   bool limitTau0, limitTau, limitRadius, limitCylinder, limitDecay;
0177 
0178 };
0179 
0180 //--------------------------------------------------------------------------
0181 
0182 // The constructor.
0183 
0184 // The EvtGenDecays object is associated with a single Pythia
0185 // instance. This is to ensure a consistent random number generator
0186 // across the two, as well as any updates to particle data, etc. Note
0187 // that if multiple EvtGenDecays objects exist, that they will modify
0188 // one anothers particle databases due to the design of EvtGen.
0189 
0190 // This constructor also sets all particles to be decayed by EvtGen as
0191 // stable within Pythia. The parameters within Pythia used to check if
0192 // a particle should be decayed, as described in the "Particle Decays"
0193 // section of the Pythia manual, are set. Note that if the variable
0194 // "limit" is set to "false", then no check will be made before
0195 // decaying a particle with EvtGen.
0196 
0197 // The constructor is designed to have the exact same form as the
0198 // EvtGen constructor except for these five differences.
0199 // (1) The first variable is the pointer to the Pythia object.
0200 // (2) The third last argument is a flag to limit decays based on the
0201 //     Pythia criteria (based on the particle decay vertex).
0202 // (3) The second last argument is a flag if external models should be
0203 //     passed to EvtGen (default is true).
0204 // (4) The last argument is a flag if an FSR model should be passed
0205 //     to EvtGen (default is true).
0206 // (5) No random engine pointer is passed, as this is obtained from
0207 //     Pythia.
0208 
0209 //   pythiaPtrIn:      the pointer to the associated Pythia object.
0210 //   decayFile:        the name of the decay file to pass to EvtGen.
0211 //   particleDataFile: the name of the particle data file to pass to EvtGen.
0212 //   extPtrIn:         the optional EvtExternalGenList pointer, this must be
0213 //                     be provided if fsrPtrIn is provided to avoid double
0214 //                     initializations.
0215 //   fsrPtrIn:         the EvtAbsRadCorr pointer to pass to EvtGen.
0216 //   mixing:           the mixing type to pass to EvtGen.
0217 //   xml:              flag to use XML files to pass to EvtGen.
0218 //   limit:            flag to limit particle decays based on Pythia criteria.
0219 //   extUse:           flag to use external models with EvtGen.
0220 //   fsrUse:           flag to use radiative correction engine with EvtGen.
0221 
0222 EvtGenDecays::EvtGenDecays(Pythia *pythiaPtrIn, string decayFile,
0223   string particleDataFile, EvtExternalGenList *extPtrIn,
0224   EvtAbsRadCorr *fsrPtrIn, int mixing, bool xml, bool limit,
0225   bool extUse, bool fsrUse) : extPtr(extPtrIn), fsrPtr(fsrPtrIn),
0226   signalSuffix("_SIGNAL"), pythiaPtr(pythiaPtrIn), rndm(&pythiaPtr->rndm),
0227   updated(false) {
0228 
0229   // Initialize EvtGen.
0230   if (!extPtr && fsrPtr) {
0231     cout << "Error in EvtGenDecays::"
0232          << "EvtGenDecays: extPtr is null but fsrPtr is provided\n";
0233     return;
0234   }
0235   if (extPtr) extOwner = false;
0236   else {extOwner = true; extPtr = new EvtExternalGenList();}
0237   if (fsrPtr) fsrOwner = false;
0238   else {fsrOwner = true; fsrPtr = extPtr->getPhotosModel();}
0239   models = extPtr->getListOfModels();
0240   evtgen = new EvtGen(decayFile.c_str(), particleDataFile.c_str(),
0241     &rndm, fsrUse ? fsrPtr : 0, extUse ? &models : 0, mixing, xml);
0242 
0243   // Get the Pythia decay limits.
0244   if (!pythiaPtr) return;
0245   limitTau0     = pythiaPtr->settings.flag("ParticleDecays:limitTau0");
0246   tau0Max       = pythiaPtr->settings.parm("ParticleDecays:tau0Max");
0247   limitTau      = pythiaPtr->settings.flag("ParticleDecays:limitTau");
0248   tauMax        = pythiaPtr->settings.parm("ParticleDecays:tauMax");
0249   limitRadius   = pythiaPtr->settings.flag("ParticleDecays:limitRadius");
0250   rMax          = pythiaPtr->settings.parm("ParticleDecays:rMax");
0251   limitCylinder = pythiaPtr->settings.flag("ParticleDecays:limitCylinder");
0252   xyMax         = pythiaPtr->settings.parm("ParticleDecays:xyMax");
0253   zMax          = pythiaPtr->settings.parm("ParticleDecays:zMax");
0254   limitDecay    = limit && (limitTau0 || limitTau ||
0255                             limitRadius || limitCylinder);
0256 
0257 }
0258 
0259 //--------------------------------------------------------------------------
0260 
0261 // Perform all decays and return the event weight.
0262 
0263 // All particles in the event record that can be decayed by EvtGen are
0264 // decayed. If a particle is a signal particle, then this is stored in
0265 // a vector of signal particles. A signal particle is only stored if
0266 // its status is the same as the status provided in the signals map. A
0267 // negative status in the signal map indicates that all statuses
0268 // should be accepted. After all signal particles are identified, one
0269 // is randomly chosen and decayed as signal. The remainder are decayed
0270 // normally.
0271 
0272 // Forcing a signal decay changes the weight of an event from unity,
0273 // and so the relative event weight is returned, given the forced
0274 // signal decay. A weight of 0 indicates no signal in the event, while
0275 // a weight of -1 indicates something is wrong, e.g. either the Pythia
0276 // or EvtGen pointers are not available or the number of tries has
0277 // been exceeded. For the event weight to be valid, one should not
0278 // change the absolute branching fractions in the signal and inclusive
0279 // definitions, but rather just remove the unwanted decay channels
0280 // from the signal decay definition.
0281 
0282 double EvtGenDecays::decay() {
0283 
0284   // Reset the signal and signal counters.
0285   if (!pythiaPtr || !evtgen) return -1;
0286   if (!updated) updateData(true);
0287 
0288   // Loop over all particles in the Pythia event.
0289   Event &event = pythiaPtr->event;
0290   vector<int> pySigs; vector<EvtParticle*> egSigs, egPrts;
0291   vector<double> bfs; double wgt(1.);
0292   for (int iPro = 0; iPro < event.size(); ++iPro) {
0293 
0294     // Check particle is final and can be decayed by EvtGen.
0295     Particle *pyPro = &event[iPro];
0296     if (!pyPro->isFinal()) continue;
0297     if (incIds.find(pyPro->id()) == incIds.end()) continue;
0298     if (pyPro->status() == 93 || pyPro->status() == 94) continue;
0299 
0300     // Decay the progenitor with EvtGen.
0301     EvtParticle *egPro = EvtParticleFactory::particleFactory
0302       (EvtPDL::evtIdFromStdHep(pyPro->id()),
0303        EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
0304     egPrts.push_back(egPro);
0305     egPro->setDiagonalSpinDensity();
0306     evtgen->generateDecay(egPro);
0307     pyPro->tau(egPro->getLifetime());
0308     if (!checkVertex(pyPro)) continue;
0309 
0310     // Add oscillations to event record.
0311     if (checkOsc(egPro))
0312       updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
0313 
0314     // Undo decay if signal (duplicate to stop oscillations).
0315     else if (checkSignal(pyPro)) {
0316       pySigs.push_back(pyPro->index());
0317       egSigs.push_back(egPro);
0318       bfs.push_back(signal->second.bfs[0]);
0319       wgt *= 1 - bfs.back();
0320       egPro->deleteDaughters();
0321       EvtParticle *egDau = EvtParticleFactory::particleFactory
0322         (EvtPDL::evtIdFromStdHep(pyPro->id()),
0323          EvtVector4R(pyPro->e(), pyPro->px(), pyPro->py(), pyPro->pz()));
0324       egDau->addDaug(egPro);
0325       egDau->setDiagonalSpinDensity();
0326 
0327     // If not signal, add to event record.
0328     } else updateEvent(pyPro, egPro, &pySigs, &egSigs, &bfs, &wgt);
0329   }
0330   if (pySigs.size() == 0) {
0331     for (int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
0332       egPrts[iPrt]->deleteTree();
0333     return 0;
0334   }
0335 
0336   // Determine the decays of the signal particles (signal or background).
0337   vector<int> modes; int force(-1), n(0);
0338   for (int iTry = 1; iTry <= NTRYDECAY; ++iTry) {
0339     modes.clear(); force = pythiaPtr->rndm.pick(bfs); n = 0;
0340     for (int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
0341       if (iSig == force) modes.push_back(0);
0342       else modes.push_back(pythiaPtr->rndm.flat() > bfs[iSig]);
0343       if (modes.back() == 0) ++n;
0344     }
0345     if (pythiaPtr->rndm.flat() <= 1.0 / n) break;
0346     if (iTry == NTRYDECAY) {
0347       wgt = 2.;
0348       cout << "Warning in EvtGenDecays::decay: maximum "
0349            << "number of signal decay attempts exceeded";
0350     }
0351   }
0352 
0353   // Decay the signal particles and mark forced decay.
0354   for (int iSig = 0; iSig < (int)pySigs.size(); ++iSig) {
0355     EvtParticle *egSig = egSigs[iSig];
0356     Particle    *pySig = &event[pySigs[iSig]];
0357     signal = signals.find(pySig->id());
0358     if (egSig->getNDaug() > 0) egSig = egSig->getDaug(0);
0359     if (modes[iSig] == 0) egSig->setId(signal->second.egId);
0360     else {
0361       signal->second.modes.getDecayModel(egSig);
0362       egSig->setChannel(signal->second.map[egSig->getChannel()]);
0363     }
0364     if (iSig == force)
0365       pySig->status(pySig->status() == 92 || pySig->status() == 94 ? 96 : 95);
0366     evtgen->generateDecay(egSig);
0367     updateEvent(pySig, egSigs[iSig]);
0368   }
0369 
0370   // Delete all EvtGen particles and return weight.
0371   for (int iPrt = 0; iPrt < (int)egPrts.size(); ++iPrt)
0372     egPrts[iPrt]->deleteTree();
0373   return 1. - wgt;
0374 
0375 }
0376 
0377 //--------------------------------------------------------------------------
0378 
0379 // Update the Pythia particle database from EvtGen.
0380 
0381 // Note that only the particle spin type, charge type, nominal mass,
0382 // width, minimum mass, maximum mass, and nominal lifetime are
0383 // set. The name string is not set.
0384 
0385 void EvtGenDecays::updatePythia() {
0386   if (!pythiaPtr || !evtgen) return;
0387   for (int entry = 0; entry < (int)EvtPDL::entries(); ++entry) {
0388     EvtId egId = EvtPDL::getEntry(entry);
0389     int   pyId = EvtPDL::getStdHep(egId);
0390     pythiaPtr->particleData.spinType  (pyId, EvtPDL::getSpinType(egId));
0391     pythiaPtr->particleData.chargeType(pyId, EvtPDL::chg3(egId));
0392     pythiaPtr->particleData.m0        (pyId, EvtPDL::getMass(egId));
0393     pythiaPtr->particleData.mWidth    (pyId, EvtPDL::getWidth(egId));
0394     pythiaPtr->particleData.mMin      (pyId, EvtPDL::getMinMass(egId));
0395     pythiaPtr->particleData.mMax      (pyId, EvtPDL::getMaxMass(egId));
0396     pythiaPtr->particleData.tau0      (pyId, EvtPDL::getctau(egId));
0397   }
0398 }
0399 
0400 //--------------------------------------------------------------------------
0401 
0402 // Update the EvtGen particle database from Pythia.
0403 
0404 // The particle update database between Pythia and EvtGen is not
0405 // symmetric. Particularly, it is not possible to update the spin
0406 // type, charge, or nominal lifetime in the EvtGen particle database.
0407 
0408 void EvtGenDecays::updateEvtGen() {
0409   if (!pythiaPtr || !evtgen) return;
0410   int pyId = pythiaPtr->particleData.nextId(1);
0411   while (pyId != 0) {
0412     EvtId egId = EvtPDL::evtIdFromStdHep(pyId);
0413     EvtPDL::reSetMass   (egId, pythiaPtr->particleData.m0(pyId));
0414     EvtPDL::reSetWidth  (egId, pythiaPtr->particleData.mWidth(pyId));
0415     EvtPDL::reSetMassMin(egId, pythiaPtr->particleData.mMin(pyId));
0416     EvtPDL::reSetMassMax(egId, pythiaPtr->particleData.mMax(pyId));
0417     pyId = pythiaPtr->particleData.nextId(pyId);
0418   }
0419 }
0420 
0421 //--------------------------------------------------------------------------
0422 
0423 // Update the particles to decay with EvtGen, and the selected signals.
0424 
0425 // If final is false, then only signals are initialized in the signal
0426 // map. Any particle or alias that ends with signalSuffix is taken as
0427 // a signal particle. If final is true all particle entries in EvtGen
0428 // are checked to see if they should be set stable in Pythia. If an
0429 // EvtGen particle has no decay modes, then Pythia is still allowed to
0430 // decay the particle. Additionally, the signal decay channels are
0431 // turned off for the non-aliased signal particle.
0432 
0433 void EvtGenDecays::updateData(bool final) {
0434 
0435   // Loop over the EvtGen entries.
0436   if (!pythiaPtr) return;
0437   EvtDecayTable *egTable = EvtDecayTable::getInstance();
0438   if (!egTable) return;
0439   for (int iEntry = 0; iEntry < (int)EvtPDL::entries(); ++iEntry) {
0440     EvtId egId = EvtPDL::getEntry(iEntry);
0441     int   pyId = EvtPDL::getStdHep(egId);
0442     if (egTable->getNModes(egId) == 0) continue;
0443     if (excIds.find(pyId) != excIds.end()) continue;
0444 
0445     // Stop Pythia from decaying the particle and include in decay set.
0446     if (final)  {
0447       incIds.insert(pyId);
0448       pythiaPtr->particleData.mayDecay(pyId, false);
0449     }
0450 
0451     // Check for signal.
0452     string egName = EvtPDL::name(egId);
0453     if (egName.size() <= signalSuffix.size() || egName.substr
0454         (egName.size() - signalSuffix.size()) != signalSuffix) continue;
0455     signal = signals.find(pyId);
0456     if (signal == signals.end()) {
0457       signals[pyId].status = -1;
0458       signal = signals.find(pyId);
0459     }
0460     signal->second.egId  = egId;
0461     signal->second.bfs   = vector<double>(2, 0);
0462     if (!final) continue;
0463 
0464     // Get the signal and background decay modes.
0465     vector<EvtParticleDecayList> egList = egTable->getDecayTable();
0466     int sigIdx = egId.getAlias();
0467     int bkgIdx = EvtPDL::evtIdFromStdHep(pyId).getAlias();
0468     if (sigIdx > (int)egList.size() || bkgIdx > (int)egList.size()) continue;
0469     EvtParticleDecayList sigModes = egList[sigIdx];
0470     EvtParticleDecayList bkgModes = egList[bkgIdx];
0471     EvtParticleDecayList allModes = egList[bkgIdx];
0472     double sum(0);
0473 
0474     // Sum signal branching fractions.
0475     for (int iMode = 0; iMode < sigModes.getNMode(); ++iMode) {
0476       EvtDecayBase *mode = sigModes.getDecayModel(iMode);
0477       if (!mode) continue;
0478       signal->second.bfs[0] += mode->getBranchingFraction();
0479       sum += mode->getBranchingFraction();
0480     }
0481 
0482     // Sum remaining background branching fractions.
0483     for (int iMode = 0; iMode < allModes.getNMode(); ++iMode) {
0484       EvtDecayBase *mode = allModes.getDecayModel(iMode);
0485       if (!mode) continue;
0486       bool match(false);
0487       for (int jMode = 0; jMode < sigModes.getNMode(); ++jMode)
0488         if (mode->matchingDecay(*(sigModes.getDecayModel(jMode)))) {
0489           match = true; break;}
0490       if (match) bkgModes.removeMode(mode);
0491       else {
0492         signal->second.map.push_back(iMode);
0493         signal->second.bfs[1] += mode->getBranchingFraction();
0494         sum += mode->getBranchingFraction();
0495       }
0496     }
0497     signal->second.modes = bkgModes;
0498     for (int iBf = 0; iBf < (int)signal->second.bfs.size(); ++iBf)
0499       signal->second.bfs[iBf] /= sum;
0500   }
0501   if (final) updated = true;
0502 
0503 }
0504 
0505 //--------------------------------------------------------------------------
0506 
0507 // Update the Pythia event record with an EvtGen decay tree.
0508 
0509 // The production vertex of each particle (which can also be obtained
0510 // in EvtGen via EvtParticle::get4Pos()) is set by the decay vertex of
0511 // its mother, which in turn is calculated from the mother's
0512 // lifetime. The status code 93 is used to indicate an external decay,
0513 // while the status code 94 is used to indicate an oscillated external
0514 // decay. If the progenitor has a single daughter with the same ID,
0515 // this daughter is used as the progenitor. This is used to prevent
0516 // double oscillations.
0517 
0518 // If the arguments after egPro are no NULL and a particle in the
0519 // decay tree is a signal particle, the decay for this particle is
0520 // removed and the particle is stored as a signal candidate in the
0521 // pySigs and egSigs vectors, to be decayed later. However, if any of
0522 // these arguments is NULL then the entire tree is written.
0523 
0524 void EvtGenDecays::updateEvent(Particle *pyPro, EvtParticle *egPro,
0525   vector<int> *pySigs, vector<EvtParticle*> *egSigs,
0526   vector<double> *bfs, double *wgt) {
0527 
0528   // Set up the mother vector.
0529   if (!pythiaPtr) return;
0530   EvtParticle* egMom = egPro;
0531   if (egPro->getNDaug() == 1 && egPro->getPDGId() ==
0532       egPro->getDaug(0)->getPDGId()) egMom = egPro->getDaug(0);
0533   Event &event = pythiaPtr->event;
0534   vector< pair<EvtParticle*, int> >
0535     moms(1, pair<EvtParticle*, int>(egMom, pyPro->index()));
0536 
0537   // Loop over the mothers.
0538   while (moms.size() != 0) {
0539 
0540     // Check if particle can decay.
0541     egMom = moms.back().first;
0542     int       iMom  = moms.back().second;
0543     Particle* pyMom = &event[iMom];
0544     moms.pop_back();
0545     if (!checkVertex(pyMom)) continue;
0546     bool osc(checkOsc(egMom));
0547 
0548     // Set the children of the mother.
0549     pyMom->daughters(event.size(), event.size() + egMom->getNDaug() - 1);
0550     pyMom->statusNeg();
0551     Vec4 vProd = pyMom->vDec();
0552     for (int iDtr = 0 ; iDtr < (int)egMom->getNDaug(); ++iDtr) {
0553       EvtParticle *egDtr = egMom->getDaug(iDtr);
0554       int          id    = egDtr->getPDGId();
0555       EvtVector4R  p     = egDtr->getP4Lab();
0556       int idx = event.append(id, 93, iMom, 0, 0, 0, 0, 0, p.get(1),
0557                              p.get(2), p.get(3), p.get(0), egDtr->mass());
0558       Particle *pyDtr = &event.back();
0559       pyDtr->vProd(vProd);
0560       pyDtr->tau(egDtr->getLifetime());
0561       if (pySigs && egSigs && bfs && wgt && checkSignal(pyDtr)) {
0562         pySigs->push_back(pyDtr->index());
0563         egSigs->push_back(egDtr);
0564         bfs->push_back(signal->second.bfs[0]);
0565         (*wgt) *= 1 - bfs->back();
0566         egDtr->deleteDaughters();
0567       }
0568       if (osc) pyDtr->status(94);
0569       if (egDtr->getNDaug() > 0)
0570         moms.push_back(pair<EvtParticle*, int>(egDtr, idx));
0571     }
0572   }
0573 
0574 }
0575 
0576 //--------------------------------------------------------------------------
0577 
0578 // Check if a particle can decay.
0579 
0580 // Modified slightly from ParticleDecays::checkVertex.
0581 
0582 bool EvtGenDecays::checkVertex(Particle *pyPro) {
0583   if (!limitDecay) return true;
0584   if (limitTau0 && pyPro->tau0() > tau0Max) return false;
0585   if (limitTau && pyPro->tau() > tauMax) return false;
0586   if (limitRadius && pow2(pyPro->xDec()) + pow2(pyPro->yDec())
0587     + pow2(pyPro->zDec()) > pow2(rMax)) return false;
0588   if (limitCylinder && (pow2(pyPro->xDec()) + pow2(pyPro->yDec())
0589     > pow2(xyMax) || abs(pyPro->zDec()) > zMax) ) return false;
0590   return true;
0591 }
0592 
0593 //--------------------------------------------------------------------------
0594 
0595 // Check if a particle is signal.
0596 
0597 bool EvtGenDecays::checkSignal(Particle *pyPro) {
0598   signal = signals.find(pyPro->id());
0599   if (signal != signals.end() && (signal->second.status < 0 ||
0600     signal->second.status == pyPro->status())) return true;
0601   else return false;
0602 }
0603 
0604 //--------------------------------------------------------------------------
0605 
0606 // Check if an EvtGen particle has oscillated.
0607 
0608 // The criteria defined here for oscillation is a single daughter but
0609 // with a different ID from the mother.
0610 
0611 bool EvtGenDecays::checkOsc(EvtParticle *egPro) {
0612   if (egPro && egPro->getNDaug() == 1 &&
0613       egPro->getPDGId() != egPro->getDaug(0)->getPDGId()) return true;
0614   else return false;
0615 }
0616 
0617 //==========================================================================
0618 
0619 } // end namespace Pythia8
0620 
0621 #endif // end Pythia8_EvtGen_H