rivet is hosted by Hepforge, IPPP Durham
Particle.hh
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_Particle_HH
00003 #define RIVET_Particle_HH
00004 
00005 #include "Rivet/Particle.fhh"
00006 #include "Rivet/ParticleBase.hh"
00007 #include "Rivet/Config/RivetCommon.hh"
00008 #include "Rivet/Tools/Utils.hh"
00009 // NOTE: Rivet/Tools/ParticleUtils.hh included at the end
00010 #include "fastjet/PseudoJet.hh"
00011 
00012 namespace Rivet {
00013 
00014 
00015   /// Representation of particles from a HepMC::GenEvent.
00016   class Particle : public ParticleBase {
00017   public:
00018 
00019     /// Default constructor.
00020     /// @note A particle without info is useless. This only exists to keep STL containers happy.
00021     Particle()
00022       : ParticleBase(),
00023         _original(0), _id(0), _momentum()
00024     { }
00025 
00026     /// Constructor without GenParticle.
00027     Particle(PdgId pid, const FourMomentum& mom)
00028       : ParticleBase(),
00029         _original(0), _id(pid), _momentum(mom)
00030     { }
00031 
00032     /// Constructor from a HepMC GenParticle.
00033     Particle(const GenParticle& gp)
00034       : ParticleBase(),
00035         _original(&gp), _id(gp.pdg_id()),
00036         _momentum(gp.momentum())
00037     { }
00038 
00039     /// Constructor from a HepMC GenParticle pointer.
00040     Particle(const GenParticle* gp)
00041       : ParticleBase(),
00042         _original(gp), _id(gp->pdg_id()),
00043         _momentum(gp->momentum())
00044     { }
00045 
00046 
00047   public:
00048 
00049     /// Converter to FastJet3 PseudoJet
00050     virtual fastjet::PseudoJet pseudojet() const {
00051       return fastjet::PseudoJet(mom().px(), mom().py(), mom().pz(), mom().E());
00052     }
00053 
00054     /// Cast operator to FastJet3 PseudoJet
00055     operator PseudoJet () const { return pseudojet(); }
00056 
00057 
00058   public:
00059 
00060     /// @name Basic particle specific properties
00061     //@{
00062 
00063     /// Get a const pointer to the original GenParticle.
00064     const GenParticle* genParticle() const {
00065       return _original;
00066     }
00067 
00068     /// Cast operator for conversion to GenParticle*
00069     operator const GenParticle* () const { return genParticle(); }
00070 
00071     /// The momentum.
00072     const FourMomentum& momentum() const {
00073       return _momentum;
00074     }
00075     /// Set the momentum.
00076     Particle& setMomentum(const FourMomentum& momentum) {
00077       _momentum = momentum;
00078       return *this;
00079     }
00080 
00081     //@}
00082 
00083 
00084     /// @name Particle ID code accessors
00085     //@{
00086 
00087     /// This Particle's PDG ID code.
00088     PdgId pid() const { return _id; }
00089     /// Absolute value of the PDG ID code.
00090     PdgId abspid() const { return std::abs(_id); }
00091     /// This Particle's PDG ID code (alias).
00092     /// @deprecated Prefer the pid/abspid form
00093     PdgId pdgId() const { return _id; }
00094 
00095     //@}
00096 
00097 
00098     /// @name Particle species properties
00099     //@{
00100 
00101     /// The charge of this Particle.
00102     double charge() const {
00103       return PID::charge(pid());
00104     }
00105     /// Three times the charge of this Particle (i.e. integer multiple of smallest quark charge).
00106     int threeCharge() const {
00107       return PID::threeCharge(pid());
00108     }
00109 
00110     /// Is this a hadron?
00111     bool isHadron() const { return PID::isHadron(pid()); }
00112 
00113     /// Is this a meson?
00114     bool isMeson() const { return PID::isMeson(pid()); }
00115 
00116     /// Is this a baryon?
00117     bool isBaryon() const { return PID::isBaryon(pid()); }
00118 
00119     /// Is this a lepton?
00120     bool isLepton() const { return PID::isLepton(pid()); }
00121 
00122     /// Is this a neutrino?
00123     bool isNeutrino() const { return PID::isNeutrino(pid()); }
00124 
00125     /// Does this (hadron) contain a b quark?
00126     bool hasBottom() const { return PID::hasBottom(pid()); }
00127 
00128     /// Does this (hadron) contain a c quark?
00129     bool hasCharm() const { return PID::hasCharm(pid()); }
00130 
00131     /// Is this particle potentially visible in a detector?
00132     bool isVisible() const {
00133       // Charged particles are visible
00134       if ( PID::threeCharge(pid()) != 0 ) return true;
00135       // Neutral hadrons are visible
00136       if ( PID::isHadron(pid()) ) return true;
00137       // Photons are visible
00138       if ( pid() == PID::PHOTON ) return true;
00139       // Gluons are visible (for parton level analyses)
00140       if ( pid() == PID::GLUON ) return true;
00141       // Everything else is invisible
00142       return false;
00143     }
00144 
00145     // /// Does this (hadron) contain an s quark?
00146     // bool hasStrange() const { return PID::hasStrange(pid()); }
00147 
00148     //@}
00149 
00150 
00151     /// @name Ancestry properties
00152     //@{
00153 
00154     /// Check whether a given PID is found in the GenParticle's ancestor list
00155     ///
00156     /// @note This question is valid in MC, but may not be answerable
00157     /// experimentally -- use this function with care when replicating
00158     /// experimental analyses!
00159     bool hasAncestor(PdgId pdg_id) const;
00160 
00161     /// @brief Determine whether the particle is from a b-hadron decay
00162     ///
00163     /// @note This question is valid in MC, but may not be perfectly answerable
00164     /// experimentally -- use this function with care when replicating
00165     /// experimental analyses!
00166     bool fromBottom() const;
00167 
00168     /// @brief Determine whether the particle is from a c-hadron decay
00169     ///
00170     /// @note If a hadron contains b and c quarks it is considered a bottom
00171     /// hadron and NOT a charm hadron.
00172     ///
00173     /// @note This question is valid in MC, but may not be perfectly answerable
00174     /// experimentally -- use this function with care when replicating
00175     /// experimental analyses!
00176     bool fromCharm() const;
00177 
00178     // /// @brief Determine whether the particle is from a s-hadron decay
00179     // ///
00180     // /// @note If a hadron contains b or c quarks as well as strange it is
00181     // /// considered a b or c hadron, but NOT a strange hadron.
00182     // ///
00183     // /// @note This question is valid in MC, but may not be perfectly answerable
00184     // /// experimentally -- use this function with care when replicating
00185     // /// experimental analyses!
00186     // bool fromStrange() const;
00187 
00188     /// @brief Determine whether the particle is from a hadron decay
00189     ///
00190     /// @note This question is valid in MC, but may not be perfectly answerable
00191     /// experimentally -- use this function with care when replicating
00192     /// experimental analyses!
00193     bool fromHadron() const;
00194 
00195     /// @brief Determine whether the particle is from a tau decay
00196     ///
00197     /// @note This question is valid in MC, but may not be perfectly answerable
00198     /// experimentally -- use this function with care when replicating
00199     /// experimental analyses!
00200     bool fromTau(bool prompt_taus_only=false) const;
00201 
00202     /// @brief Determine whether the particle is from a prompt tau decay
00203     ///
00204     /// @note This question is valid in MC, but may not be perfectly answerable
00205     /// experimentally -- use this function with care when replicating
00206     /// experimental analyses!
00207     bool fromPromptTau() const { return fromTau(true); }
00208 
00209     /// @brief Determine whether the particle is from a hadron or tau decay
00210     ///
00211     /// Specifically, walk up the ancestor chain until a status 2 hadron or
00212     /// tau is found, if at all.
00213     ///
00214     /// @note This question is valid in MC, but may not be perfectly answerable
00215     /// experimentally -- use this function with care when replicating
00216     /// experimental analyses!
00217     bool fromDecay() const { return fromHadron() || fromPromptTau(); }
00218 
00219     //@}
00220 
00221 
00222     /// @name Decay info
00223     //@{
00224 
00225     /// Whether this particle is stable according to the generator
00226     bool isStable() const {
00227       return genParticle() != NULL && genParticle()->status() == 1 && genParticle()->end_vertex() == NULL;
00228     }
00229 
00230     /// Get a list of the direct descendants from the current particle
00231     vector<Particle> children() const {
00232       vector<Particle> rtn;
00233       if (isStable()) return rtn;
00234       /// @todo Remove this const mess crap when HepMC doesn't suck
00235       HepMC::GenVertex* gv = const_cast<HepMC::GenVertex*>( genParticle()->end_vertex() );
00236       /// @todo Would like to do this, but the range objects are broken
00237       // foreach (const GenParticle* gp, gv->particles(HepMC::children))
00238       //   rtn += Particle(gp);
00239       for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::children); it != gv->particles_end(HepMC::children); ++it)
00240         rtn += Particle(*it);
00241       return rtn;
00242     }
00243 
00244     /// Get a list of all the descendants (including duplication of parents and children) from the current particle
00245     /// @todo Use recursion through replica-avoiding MCUtils functions to avoid bookkeeping duplicates
00246     /// @todo Insist that the current particle is post-hadronization, otherwise throw an exception?
00247     vector<Particle> allDescendants() const {
00248       vector<Particle> rtn;
00249       if (isStable()) return rtn;
00250       /// @todo Remove this const mess crap when HepMC doesn't suck
00251       HepMC::GenVertex* gv = const_cast<HepMC::GenVertex*>( genParticle()->end_vertex() );
00252       /// @todo Would like to do this, but the range objects are broken
00253       // foreach (const GenParticle* gp, gv->particles(HepMC::descendants))
00254       //   rtn += Particle(gp);
00255       for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::descendants); it != gv->particles_end(HepMC::descendants); ++it)
00256         rtn += Particle(*it);
00257       return rtn;
00258     }
00259 
00260     /// Get a list of all the stable descendants from the current particle
00261     /// @todo Use recursion through replica-avoiding MCUtils functions to avoid bookkeeping duplicates
00262     /// @todo Insist that the current particle is post-hadronization, otherwise throw an exception?
00263     vector<Particle> stableDescendants() const {
00264       vector<Particle> rtn;
00265       if (isStable()) return rtn;
00266       /// @todo Remove this const mess crap when HepMC doesn't suck
00267       HepMC::GenVertex* gv = const_cast<HepMC::GenVertex*>( genParticle()->end_vertex() );
00268       /// @todo Would like to do this, but the range objects are broken
00269       // foreach (const GenParticle* gp, gv->particles(HepMC::descendants))
00270       //   if (gp->status() == 1 && gp->end_vertex() == NULL)
00271       //     rtn += Particle(gp);
00272       for (GenVertex::particle_iterator it = gv->particles_begin(HepMC::descendants); it != gv->particles_end(HepMC::descendants); ++it)
00273         if ((*it)->status() == 1 && (*it)->end_vertex() == NULL)
00274           rtn += Particle(*it);
00275       return rtn;
00276     }
00277 
00278     /// Flight length (divide by mm or cm to get the appropriate units)
00279     double flightLength() const {
00280       if (isStable()) return -1;
00281       if (genParticle() == NULL) return 0;
00282       if (genParticle()->production_vertex() == NULL) return 0;
00283       const HepMC::FourVector v1 = genParticle()->production_vertex()->position();
00284       const HepMC::FourVector v2 = genParticle()->end_vertex()->position();
00285       return sqrt(sqr(v2.x()-v1.x()) + sqr(v2.y()-v1.y()) + sqr(v2.z()-v1.z()));
00286     }
00287 
00288     //@}
00289 
00290 
00291   private:
00292 
00293     /// A pointer to the original GenParticle from which this Particle is projected.
00294     const GenParticle* _original;
00295 
00296     /// The PDG ID code for this Particle.
00297     PdgId _id;
00298 
00299     /// The momentum of this projection of the Particle.
00300     FourMomentum _momentum;
00301 
00302   };
00303 
00304 
00305   /// @name String representation
00306   //@{
00307 
00308   /// Print a ParticlePair as a string.
00309   inline std::string to_str(const ParticlePair& pair) {
00310     stringstream out;
00311     out << "["
00312         << PID::toParticleName(pair.first.pid()) << " @ "
00313         << pair.first.momentum().E()/GeV << " GeV, "
00314         << PID::toParticleName(pair.second.pid()) << " @ "
00315         << pair.second.momentum().E()/GeV << " GeV]";
00316     return out.str();
00317   }
00318 
00319   /// Allow ParticlePair to be passed to an ostream.
00320   inline std::ostream& operator<<(std::ostream& os, const ParticlePair& pp) {
00321     os << to_str(pp);
00322     return os;
00323   }
00324 
00325   //@}
00326 
00327 
00328 }
00329 
00330 
00331 #include "Rivet/Tools/ParticleUtils.hh"
00332 
00333 #endif