26#include "CLHEP/Random/RandomEngine.h"
32 double r = engine->flat();
33 return ((-ct)*std::log(1.-
r));
39 double r = engine->flat();
95 double e = genpart->momentum().e();
96 double theta = genpart->momentum().theta();
97 double phi = genpart->momentum().phi();
99 double p2 = e*e - newMass*newMass;
101 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- you have generated a tachyon!");
102 return StatusCode::FAILURE;
105 double p = std::sqrt(p2);
106 double px = p*std::sin(
theta)*std::cos(
phi);
107 double py = p*std::sin(
theta)*std::sin(
phi);
108 double pz = p*std::cos(
theta);
110 const CLHEP::HepLorentzVector updatedLV(px,py,pz,e);
111 genpart->set_momentum(
HepMC::FourVector(updatedLV.x(),updatedLV.y(),updatedLV.z(),updatedLV.e()));
112 genpart->set_generated_mass(newMass);
113 return StatusCode::SUCCESS;
121 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- no production vertex position found!");
122 return StatusCode::FAILURE;
127 end_vtx->set_position(vtxp->position());
128 end_vtx->add_particle_in(std::move(genpart));
129 event->add_vertex(std::move(end_vtx));
130 return StatusCode::SUCCESS;
134 double gamma = genpart->momentum().e()/genpart->momentum().m();
136 double theta = genpart->momentum().theta();
152 double distanceToEdge = -999.;
164 return StatusCode::FAILURE;
166 double Limit = distanceToEdge / gamma;
171 while ( ctau > Limit )
184 double decayRadius = -999.;
188 double outerRadius = outerLength*std::sin(
theta);
195 double decayLength = decayRadius/std::sin(
theta);
196 ctau = decayLength/gamma;
199 ATH_MSG_FATAL(
"have to pick uniform or exponential decay distance");
200 return StatusCode::FAILURE;
203 double ctg = gamma * ctau;
204 double px = genpart->momentum().px();
205 double py = genpart->momentum().py();
206 double pz = genpart->momentum().pz();
207 double p = std::sqrt(px*px + py*py + pz*pz);
209 const CLHEP::HepLorentzVector posLV(((ctg*px/p)+(vtxp->position().x())), ((ctg*py/p)+(vtxp->position().y())), ((ctg*pz/p)+(vtxp->position().z())), ((ctg)+(vtxp->position().t())));
213 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the decay vertex");
215 end_vtx->set_position(
HepMC::FourVector(posLV.x(),posLV.y(),posLV.z(),posLV.t()));
216 end_vtx->add_particle_in(std::move(genpart));
217 event->add_vertex(std::move(end_vtx));
218 return StatusCode::SUCCESS;
263 ATH_MSG_FATAL(
"Cannot configure exponential and uniform decay at the same time.");
264 return StatusCode::FAILURE;
268 if (TOTBR>1.0000001) {
269 ATH_MSG_FATAL(
"ParticleDecayer::genInitialize: -- Branching Ratio sum is larger than 1!! Please check the values in your jobOption.");
273 ATH_MSG_FATAL(
"ParticleDecayer::genInitialize: -- Total Branching Ratio " << TOTBR);
274 return StatusCode::FAILURE;
283 return StatusCode::FAILURE;
287 return StatusCode::SUCCESS;
295 const EventContext& ctx = Gaudi::Hive::currentContext();
296 CLHEP::HepRandomEngine* engine = this->
getRandomEngine(
"ParticleDecayer", ctx);
298 StatusCode status = StatusCode::SUCCESS;
303 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Found an McEventCollection for ParticleDecayer");
306 status = StatusCode::FAILURE;
310 event = mcEvtColl->
back();
313 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- McEvent was not successfully created");
314 status = StatusCode::FAILURE;
318 for (
auto genpart : *event) {
320 const bool hasRightPDG = (genpart->pdg_id() ==
m_particleID);
321 const bool isStable = (genpart->status() == 1);
322 const bool hasEndVtx = (genpart->end_vertex() !=
nullptr);
329 if (!isStable || hasEndVtx) {
330 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- skip particle with PDG ID = "
332 <<
" status = " << genpart->status()
333 <<
" end_vertex = " << (hasEndVtx ?
"yes" :
"no"));
342 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- only one dark photon per LeptonJet");
343 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- found MC particle with PDG ID = " << genpart->pdg_id());
358 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new status = 2");
359 genpart->set_status(2);
362 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new momentum");
372 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- two dark photons per LeptonJet");
373 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- found MC particle with PDG ID = " << genpart->pdg_id());
386 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new status = 2");
387 genpart->set_status(2);
394 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- allow the two-body decay of the dark scalar to dark photons...");
397 std::vector<CLHEP::HepLorentzVector> darkPhotonLVs;
398 CHECK(
getDecayProducts( engine, CLHEP::HepLorentzVector( genpart->momentum().px(), genpart->momentum().py(), genpart->momentum().pz(), genpart->momentum().e() ),
403 auto v0=darkPhotonLVs.at(0).vect();
406 auto v1=darkPhotonLVs.at(1).vect();
410 int polarizationSwitch = 1;
411 const std::vector<HepMC::GenParticlePtr>& particlesOut = genpart->end_vertex()->particles_out();
412 std::vector<HepMC::GenParticlePtr>::const_iterator pItBegin = particlesOut.begin();
413 std::vector<HepMC::GenParticlePtr>::const_iterator pItEnd = particlesOut.end();
414 for (
auto pIt=pItBegin ; pIt != pItEnd; ++pIt )
420 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Now allow the two-body decay of the dark photons");
424 polarizationSwitch = -polarizationSwitch;
432 return StatusCode::FAILURE;
440 if (event->weights().empty()) {
441 event->weights().push_back(1.);
460 mass =
m_gendata->particleMass(pdg).value();
462 double energy=std::sqrt(std::pow(momentum.x(),2)+std::pow(momentum.y(),2)+std::pow(momentum.z(),2)+mass*mass);
466 prod_vtx->add_particle_out(std::move(aParticle));
473 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- allow the two-body decay of the dark photon...");
476 CLHEP::HepLorentzVector boostDF( genpart->momentum().px(), genpart->momentum().py(), genpart->momentum().pz(), genpart->momentum().e() );
488 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- decayMode = " << ModeOfDecay);
491 double decayPartMass =
m_gendata->particleMass(ModeOfDecay).value();
496 if(Polarization==0) {
498 }
else if(Polarization==-1 && (ModeOfDecay==11 || ModeOfDecay==13)) {
500 }
else if(Polarization==1 && (ModeOfDecay==11 || ModeOfDecay==13)) {
502 }
else if(Polarization==-1 && ModeOfDecay==211) {
504 }
else if(Polarization==1 && ModeOfDecay==211) {
507 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- wrong polarization value... please check!");
508 return StatusCode::FAILURE;
512 std::vector<CLHEP::HepLorentzVector> daughterLVs;
516 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Add the daughters to the pool file");
517 auto end_vtx = genpart->end_vertex();
518 auto v0=daughterLVs.at(0).vect();
520 auto v1=daughterLVs.at(1).vect();
523 return StatusCode::SUCCESS;
528 double decayPartMass,
529 std::vector<CLHEP::HepLorentzVector>& daughterLVs,
532 double parentMass = parentLV.m();
533 CLHEP::Hep3Vector boostVec = parentLV.boostVector();
535 if( decayPartMass > parentMass/2.)
537 ATH_MSG_FATAL(
"Decay particle has more than half the mass of parent.");
538 return StatusCode::FAILURE;
542 double ct_rf =
cosgen(engine, decayType);
543 double theta_rf = std::acos(ct_rf);
546 double p1_rf = std::sqrt(parentMass*parentMass/4. - decayPartMass*decayPartMass);
547 double px_rf = p1_rf*std::cos(phi_rf)*std::sin(theta_rf);
548 double py_rf = p1_rf*std::sin(phi_rf)*std::sin(theta_rf);
549 double pz_rf = p1_rf*ct_rf;
550 CLHEP::HepLorentzVector hlv1( px_rf, py_rf, pz_rf, parentMass/2.);
551 CLHEP::HepLorentzVector hlv2( -px_rf, -py_rf, -pz_rf, parentMass/2.);
554 hlv1.rotateUz((parentLV.vect()).unit());
555 hlv2.rotateUz((parentLV.vect()).unit());
558 hlv1.boost(boostVec);
559 hlv2.boost(boostVec);
561 daughterLVs.push_back(hlv1);
562 daughterLVs.push_back(hlv2);
564 return StatusCode::SUCCESS;
Scalar phi() const
phi method
Scalar theta() const
theta method
#define CHECK(...)
Evaluate an expression and check for errors.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
const T * back() const
Access the last element in the collection as an rvalue.
GenData is a class for particle data access.
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
std::unique_ptr< GenData > m_gendata
bool m_doExponentialDecay
StatusCode changeMass(HepMC::GenParticlePtr, double)
bool m_expDecayDoVariableLifetime
StatusCode DFTwoBodyDecay(CLHEP::HepRandomEngine *engine, HepMC::GenParticlePtr, int)
StatusCode getDecayProducts(CLHEP::HepRandomEngine *engine, CLHEP::HepLorentzVector, double, std::vector< CLHEP::HepLorentzVector > &, int decayType=0)
StatusCode setDecayPosition(CLHEP::HepRandomEngine *engine, HepMC::GenParticlePtr, HepMC::GenEvent *, bool doScalarDecay=false)
double rnd_DoubleRange(CLHEP::HepRandomEngine *engine, double a, double b)
std::string m_truthParticleContainerName
void addParticle(HepMC::GenVertexPtr, int pdg, HepMC::FourVector, int statusCode)
ParticleDecayer(const std::string &name, ISvcLocator *pSvcLocator)
double m_particleLifeTime
bool m_oppositePolarization
double m_thetaEndCapBarrel
double cosgen(CLHEP::HepRandomEngine *engine, int itype)
int m_particlePolarization
double m_expDecayFractionToKeep
StatusCode fillEvt(HepMC::GenEvent *)
For filling the HepMC event object.
bool m_expDecayDoTruncateLongDecays
StatusCode genInitialize()
For initializing the generator, if required.
double rnd_ExpLifetime(CLHEP::HepRandomEngine *engine, double ct)
bool contains(const std::string &s, const std::string ®x)
does a string contain the substring
HepMC3::FourVector FourVector
GenParticlePtr newGenParticlePtr(const HepMC3::FourVector &mom=HepMC3::FourVector::ZERO_VECTOR(), int pid=0, int status=0)
HepMC3::GenParticlePtr GenParticlePtr
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
HepMC3::GenVertexPtr GenVertexPtr
HepMC3::GenEvent GenEvent