Particle.cc
Go to the documentation of this file.
00001 #include "Rivet/Particle.hh" 00002 #include "Rivet/Tools/Cuts.hh" 00003 #include "Rivet/Tools/ParticleIdUtils.hh" 00004 00005 namespace Rivet { 00006 00007 00008 Particle& Particle::transformBy(const LorentzTransform& lt) { 00009 _momentum = lt.transform(_momentum); 00010 return *this; 00011 } 00012 00013 00014 bool Particle::isVisible() const { 00015 // Charged particles are visible 00016 if ( PID::threeCharge(pid()) != 0 ) return true; 00017 // Neutral hadrons are visible 00018 if ( PID::isHadron(pid()) ) return true; 00019 // Photons are visible 00020 if ( pid() == PID::PHOTON ) return true; 00021 // Gluons are visible (for parton level analyses) 00022 if ( pid() == PID::GLUON ) return true; 00023 // Everything else is invisible 00024 return false; 00025 } 00026 00027 00028 bool Particle::isStable() const { 00029 return genParticle() != NULL && 00030 genParticle()->status() == 1 && 00031 genParticle()->end_vertex() == NULL; 00032 } 00033 00034 00035 vector<Particle> Particle::parents(const Cut& c) const { 00036 vector<Particle> rtn; 00037 /// @todo Remove this const mess crap when HepMC doesn't suck 00038 GenVertexPtr gv = const_cast<GenVertexPtr>( genParticle()->production_vertex() ); 00039 if (gv == NULL) return rtn; 00040 /// @todo Would like to do this, but the range objects are broken 00041 // foreach (const GenParticlePtr gp, gv->particles(HepMC::children)) 00042 // rtn += Particle(gp); 00043 for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::parents); it != gv->particles_end(HepMC::parents); ++it) { 00044 const Particle p(*it); 00045 if (c != Cuts::OPEN && !c->accept(p)) continue; 00046 rtn += p; 00047 } 00048 return rtn; 00049 } 00050 00051 00052 vector<Particle> Particle::children(const Cut& c) const { 00053 vector<Particle> rtn; 00054 if (isStable()) return rtn; 00055 /// @todo Remove this const mess crap when HepMC doesn't suck 00056 GenVertexPtr gv = const_cast<GenVertexPtr>( genParticle()->end_vertex() ); 00057 if (gv == NULL) return rtn; 00058 /// @todo Would like to do this, but the range objects are broken 00059 // foreach (const GenParticlePtr gp, gv->particles(HepMC::children)) 00060 // rtn += Particle(gp); 00061 for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::children); it != gv->particles_end(HepMC::children); ++it) { 00062 const Particle p(*it); 00063 if (c != Cuts::OPEN && !c->accept(p)) continue; 00064 rtn += p; 00065 } 00066 return rtn; 00067 } 00068 00069 00070 /// @todo Insist that the current particle is post-hadronization, otherwise throw an exception? 00071 /// @todo Use recursion through replica-avoiding functions to avoid bookkeeping duplicates 00072 vector<Particle> Particle::allDescendants(const Cut& c, bool remove_duplicates) const { 00073 vector<Particle> rtn; 00074 if (isStable()) return rtn; 00075 /// @todo Remove this const mess crap when HepMC doesn't suck 00076 GenVertexPtr gv = const_cast<GenVertexPtr>( genParticle()->end_vertex() ); 00077 if (gv == NULL) return rtn; 00078 /// @todo Would like to do this, but the range objects are broken 00079 // foreach (const GenParticlePtr gp, gv->particles(HepMC::descendants)) 00080 for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::descendants); it != gv->particles_end(HepMC::descendants); ++it) { 00081 const Particle p(*it); 00082 if (c != Cuts::OPEN && !c->accept(p)) continue; 00083 if (remove_duplicates && (*it)->end_vertex() != NULL) { 00084 // size_t n = 0; ///< @todo Only remove 1-to-1 duplicates? 00085 bool dup = false; 00086 /// @todo Yuck, HepMC 00087 for (GenVertex::particle_iterator it2 = (*it)->end_vertex()->particles_begin(HepMC::children); it2 != (*it)->end_vertex()->particles_end(HepMC::children); ++it2) { 00088 // n += 1; if (n > 1) break; 00089 if ((*it)->pdg_id() == (*it2)->pdg_id()) { dup = true; break; } 00090 } 00091 if (dup) continue; 00092 } 00093 rtn += p; 00094 } 00095 return rtn; 00096 } 00097 00098 00099 /// @todo Insist that the current particle is post-hadronization, otherwise throw an exception? 00100 vector<Particle> Particle::stableDescendants(const Cut& c) const { 00101 vector<Particle> rtn; 00102 if (isStable()) return rtn; 00103 /// @todo Remove this const mess crap when HepMC doesn't suck 00104 GenVertexPtr gv = const_cast<GenVertexPtr>( genParticle()->end_vertex() ); 00105 if (gv == NULL) return rtn; 00106 /// @todo Would like to do this, but the range objects are broken 00107 // foreach (const GenParticlePtr gp, gv->particles(HepMC::descendants)) 00108 for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::descendants); it != gv->particles_end(HepMC::descendants); ++it) { 00109 // if ((*it)->status() != 1 || (*it)->end_vertex() != NULL) continue; 00110 const Particle p(*it); 00111 if (!p.isStable()) continue; 00112 if (c != Cuts::OPEN && !c->accept(p)) continue; 00113 rtn += p; 00114 } 00115 return rtn; 00116 } 00117 00118 00119 double Particle::flightLength() const { 00120 if (isStable()) return -1; 00121 if (genParticle() == NULL) return 0; 00122 if (genParticle()->production_vertex() == NULL) return 0; 00123 const HepMC::FourVector v1 = genParticle()->production_vertex()->position(); 00124 const HepMC::FourVector v2 = genParticle()->end_vertex()->position(); 00125 return sqrt(sqr(v2.x()-v1.x()) + sqr(v2.y()-v1.y()) + sqr(v2.z()-v1.z())); 00126 } 00127 00128 00129 bool Particle::hasParent(PdgId pid) const { 00130 return _hasRelativeWith(HepMC::parents, hasPID(pid)); 00131 } 00132 00133 bool Particle::hasParentWith(const Cut& c) const { 00134 return hasParentWith([&](const Particle& p){return c->accept(p);}); 00135 } 00136 00137 00138 bool Particle::hasAncestor(PdgId pid) const { 00139 return _hasRelativeWith(HepMC::ancestors, hasPID(pid)); 00140 } 00141 00142 bool Particle::hasAncestorWith(const Cut& c) const { 00143 return hasAncestorWith([&](const Particle& p){return c->accept(p);}); 00144 } 00145 00146 00147 bool Particle::fromBottom() const { 00148 return _hasRelativeWith(HepMC::ancestors, [](const Particle& p){ 00149 return p.genParticle()->status() == 2 && p.isHadron() && p.hasBottom(); 00150 }); 00151 // const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00152 // if (prodVtx == NULL) return false; 00153 // foreach (const GenParticlePtr ancestor, particles(prodVtx, HepMC::ancestors)) { 00154 // const PdgId pid = ancestor->pdg_id(); 00155 // if (ancestor->status() == 2 && (PID::isHadron(pid) && PID::hasBottom(pid))) return true; 00156 // } 00157 // return false; 00158 } 00159 00160 00161 bool Particle::fromCharm() const { 00162 return _hasRelativeWith(HepMC::ancestors, [](const Particle& p){ 00163 return p.genParticle()->status() == 2 && p.isHadron() && p.hasCharm(); 00164 }); 00165 // const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00166 // if (prodVtx == NULL) return false; 00167 // foreach (const GenParticlePtr ancestor, particles(prodVtx, HepMC::ancestors)) { 00168 // const PdgId pid = ancestor->pdg_id(); 00169 // if (ancestor->status() == 2 && (PID::isHadron(pid) && PID::hasCharm(pid) && !PID::hasBottom(pid))) return true; 00170 // } 00171 // return false; 00172 } 00173 00174 00175 bool Particle::fromHadron() const { 00176 return _hasRelativeWith(HepMC::ancestors, [](const Particle& p){ 00177 return p.genParticle()->status() == 2 && p.isHadron(); 00178 }); 00179 // const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00180 // if (prodVtx == NULL) return false; 00181 // foreach (const GenParticlePtr ancestor, particles(prodVtx, HepMC::ancestors)) { 00182 // const PdgId pid = ancestor->pdg_id(); 00183 // if (ancestor->status() == 2 && PID::isHadron(pid)) return true; 00184 // } 00185 // return false; 00186 } 00187 00188 00189 bool Particle::fromTau(bool prompt_taus_only) const { 00190 if (prompt_taus_only && fromHadron()) return false; 00191 return _hasRelativeWith(HepMC::ancestors, [](const Particle& p){ 00192 return p.genParticle()->status() == 2 && isTau(p); 00193 }); 00194 // const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00195 // if (prodVtx == NULL) return false; 00196 // foreach (const GenParticlePtr ancestor, particles(prodVtx, HepMC::ancestors)) { 00197 // const PdgId pid = ancestor->pdg_id(); 00198 // if (ancestor->status() == 2 && abs(pid) == PID::TAU) return true; 00199 // } 00200 // return false; 00201 } 00202 00203 00204 // bool Particle::fromDecay() const { 00205 // const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00206 // if (prodVtx == NULL) return false; 00207 // foreach (const GenParticlePtr ancestor, particles(prodVtx, HepMC::ancestors)) { 00208 // const PdgId pid = ancestor->pdg_id(); 00209 // if (ancestor->status() == 2 && (PID::isHadron(pid) || abs(pid) == PID::TAU)) return true; 00210 // } 00211 // return false; 00212 // } 00213 00214 00215 bool Particle::isPrompt(bool allow_from_prompt_tau, bool allow_from_prompt_mu) const { 00216 if (genParticle() == NULL) return false; // no HepMC connection, give up! Throw UserError exception? 00217 const GenVertexPtr prodVtx = genParticle()->production_vertex(); 00218 if (prodVtx == NULL) return false; // orphaned particle, has to be assume false 00219 const pair<GenParticlePtr, GenParticlePtr> beams = prodVtx->parent_event()->beam_particles(); 00220 00221 /// @todo Would be nicer to be able to write this recursively up the chain, exiting as soon as a parton or string/cluster is seen 00222 for (const GenParticlePtr ancestor : Rivet::particles(prodVtx, HepMC::ancestors)) { 00223 const PdgId pid = ancestor->pdg_id(); 00224 if (ancestor->status() != 2) continue; // no non-standard statuses or beams to be used in decision making 00225 if (ancestor == beams.first || ancestor == beams.second) continue; // PYTHIA6 uses status 2 for beams, I think... (sigh) 00226 if (PID::isParton(pid)) continue; // PYTHIA6 also uses status 2 for some partons, I think... (sigh) 00227 if (PID::isHadron(pid)) return false; // prompt particles can't be from hadron decays 00228 if (abs(pid) == PID::TAU && abspid() != PID::TAU && !allow_from_prompt_tau) return false; // allow or ban particles from tau decays (permitting tau copies) 00229 if (abs(pid) == PID::MUON && abspid() != PID::MUON && !allow_from_prompt_mu) return false; // allow or ban particles from muon decays (permitting muon copies) 00230 } 00231 return true; 00232 } 00233 00234 00235 00236 /////////////////////// 00237 00238 00239 00240 string to_str(const Particle& p) { 00241 string pname; 00242 try { 00243 pname = PID::toParticleName(p.pid()); 00244 } catch (...) { 00245 pname = "PID=" + to_str(p.pid()); 00246 } 00247 stringstream out; 00248 out << pname << " @ " << p.momentum() << " GeV"; 00249 return out.str(); 00250 } 00251 00252 00253 string to_str(const ParticlePair& pair) { 00254 stringstream out; 00255 out << "[" << pair.first << ", " << pair.second << "]"; 00256 // out << "[" 00257 // << PID::toParticleName(pair.first.pid()) << " @ " 00258 // << pair.first.momentum().E()/GeV << " GeV, " 00259 // << PID::toParticleName(pair.second.pid()) << " @ " 00260 // << pair.second.momentum().E()/GeV << " GeV]"; 00261 return out.str(); 00262 } 00263 00264 00265 00266 } Generated on Tue Dec 13 2016 16:32:39 for The Rivet MC analysis system by ![]() |