diff --git a/include/Rivet/Tools/JetUtils.hh b/include/Rivet/Tools/JetUtils.hh --- a/include/Rivet/Tools/JetUtils.hh +++ b/include/Rivet/Tools/JetUtils.hh @@ -1,210 +1,227 @@ #ifndef RIVET_JETUTILS_HH #define RIVET_JETUTILS_HH #include "Rivet/Jet.hh" #include "Rivet/Tools/ParticleBaseUtils.hh" namespace Rivet { /// @name Unbound functions for converting between Jets, Particles and PseudoJets //@{ inline PseudoJets mkPseudoJets(const Particles& ps) { PseudoJets rtn; rtn.reserve(ps.size()); for (const Particle& p : ps) rtn.push_back(p); return rtn; } inline PseudoJets mkPseudoJets(const Jets& js) { PseudoJets rtn; rtn.reserve(js.size()); for (const Jet& j : js) rtn.push_back(j); return rtn; } inline Jets mkJets(const PseudoJets& pjs) { Jets rtn; rtn.reserve(pjs.size()); for (const PseudoJet& pj : pjs) rtn.push_back(pj); return rtn; } //@} /// @name Jet classifier -> bool functors //@{ /// std::function instantiation for functors taking a Jet and returning a bool using JetSelector = function; /// std::function instantiation for functors taking two Jets and returning a bool using JetSorter = function; /// Base type for Jet -> bool functors struct BoolJetFunctor { virtual bool operator()(const Jet& p) const = 0; virtual ~BoolJetFunctor() {} }; /// Functor for and-combination of selector logic struct BoolJetAND : public BoolJetFunctor { BoolJetAND(const std::vector& sels) : selectors(sels) {} BoolJetAND(const JetSelector& a, const JetSelector& b) : selectors({a,b}) {} BoolJetAND(const JetSelector& a, const JetSelector& b, const JetSelector& c) : selectors({a,b,c}) {} bool operator()(const Jet& j) const { for (const JetSelector& sel : selectors) if (!sel(j)) return false; return true; } std::vector selectors; }; /// Operator syntactic sugar for AND construction inline BoolJetAND operator && (const JetSelector& a, const JetSelector& b) { return BoolJetAND(a, b); } /// Functor for or-combination of selector logic struct BoolJetOR : public BoolJetFunctor { BoolJetOR(const std::vector& sels) : selectors(sels) {} BoolJetOR(const JetSelector& a, const JetSelector& b) : selectors({a,b}) {} BoolJetOR(const JetSelector& a, const JetSelector& b, const JetSelector& c) : selectors({a,b,c}) {} bool operator()(const Jet& j) const { for (const JetSelector& sel : selectors) if (sel(j)) return true; return false; } std::vector selectors; }; /// Operator syntactic sugar for OR construction inline BoolJetOR operator || (const JetSelector& a, const JetSelector& b) { return BoolJetOR(a, b); } /// Functor for inverting selector logic struct BoolJetNOT : public BoolJetFunctor { BoolJetNOT(const JetSelector& sel) : selector(sel) {} bool operator()(const Jet& j) const { return !selector(j); } JetSelector selector; }; /// Operator syntactic sugar for NOT construction inline BoolJetNOT operator ! (const JetSelector& a) { return BoolJetNOT(a); } /// B-tagging functor, with a tag selection cut as the stored state struct HasBTag : BoolJetFunctor { HasBTag(const Cut& c=Cuts::open()) : cut(c) {} // HasBTag(const std::function& f) : selector(f) {} bool operator() (const Jet& j) const { return j.bTagged(cut); } // const std::function selector; const Cut cut; }; using hasBTag = HasBTag; /// C-tagging functor, with a tag selection cut as the stored state struct HasCTag : BoolJetFunctor { HasCTag(const Cut& c=Cuts::open()) : cut(c) {} // HasCTag(const std::function& f) : selector(f) {} bool operator() (const Jet& j) const { return j.cTagged(cut); } // const std::function selector; const Cut cut; }; using hasCTag = HasCTag; /// Anti-B/C-tagging functor, with a tag selection cut as the stored state struct HasNoTag : BoolJetFunctor { HasNoTag(const Cut& c=Cuts::open()) : cut(c) {} // HasNoTag(const std::function& f) : selector(f) {} bool operator() (const Jet& j) const { return !j.bTagged(cut) && !j.cTagged(cut); } // const std::function selector; const Cut cut; }; using hasNoTag = HasNoTag; //@} /// @name Unbound functions for filtering jets //@{ /// Filter a jet collection in-place to the subset that passes the supplied Cut Jets& ifilter_select(Jets& jets, const Cut& c); /// Alias for ifilter_select /// @deprecated Use ifilter_select inline Jets& ifilterBy(Jets& jets, const Cut& c) { return ifilter_select(jets, c); } + /// New alias for ifilter_select + inline Jets& iselect(Jets& jets, const Cut& c) { return ifilter_select(jets, c); } + /// Filter a jet collection in-place to the subset that passes the supplied Cut inline Jets filter_select(const Jets& jets, const Cut& c) { Jets rtn = jets; return ifilter_select(rtn, c); } - /// Alias for ifilter_select + /// Alias for filter_select /// @deprecated Use filter_select inline Jets filterBy(const Jets& jets, const Cut& c) { return filter_select(jets, c); } + /// New alias for filter_select + inline Jets select(const Jets& jets, const Cut& c) { return filter_select(jets, c); } + /// Filter a jet collection in-place to the subset that passes the supplied Cut inline Jets filter_select(const Jets& jets, const Cut& c, Jets& out) { out = filter_select(jets, c); return out; } - /// Alias for ifilter_select + /// Alias for filter_select /// @deprecated Use filter_select inline Jets filterBy(const Jets& jets, const Cut& c, Jets& out) { return filter_select(jets, c, out); } + /// New alias for filter_select + inline Jets select(const Jets& jets, const Cut& c, Jets& out) { return filter_select(jets, c, out); } + /// Filter a jet collection in-place to the subset that fails the supplied Cut Jets& ifilter_discard(Jets& jets, const Cut& c); + /// New alias for ifilter_discard + inline Jets& idiscard(Jets& jets, const Cut& c) { return ifilter_discard(jets, c); } + /// Filter a jet collection in-place to the subset that fails the supplied Cut inline Jets filter_discard(const Jets& jets, const Cut& c) { Jets rtn = jets; return ifilter_discard(rtn, c); } + /// New alias for filter_discard + inline Jets discard(const Jets& jets, const Cut& c) { return filter_discard(jets, c); } + /// Filter a jet collection in-place to the subset that fails the supplied Cut inline Jets filter_discard(const Jets& jets, const Cut& c, Jets& out) { out = filter_discard(jets, c); return out; } + /// New alias for filter_discard + inline Jets discard(const Jets& jets, const Cut& c, Jets& out) { return filter_discard(jets, c, out); } //@} /// @name Operations on collections of Jet /// @note This can't be done on generic collections of ParticleBase -- thanks, C++ :-/ //@{ namespace Kin { inline double sumPt(const Jets& js) { return sum(js, pT, 0.0); } inline FourMomentum sumP4(const Jets& js) { return sum(js, p4, FourMomentum()); } inline Vector3 sumP3(const Jets& js) { return sum(js, p3, Vector3()); } /// @todo Min dPhi, min dR? /// @todo Isolation routines? } //@} // Import Kin namespace into Rivet using namespace Kin; } #endif diff --git a/include/Rivet/Tools/ParticleUtils.hh b/include/Rivet/Tools/ParticleUtils.hh --- a/include/Rivet/Tools/ParticleUtils.hh +++ b/include/Rivet/Tools/ParticleUtils.hh @@ -1,777 +1,789 @@ #ifndef RIVET_PARTICLEUTILS_HH #define RIVET_PARTICLEUTILS_HH #include "Rivet/Particle.hh" #include "Rivet/Tools/ParticleBaseUtils.hh" #include "Rivet/Tools/ParticleIdUtils.hh" // Macros to map Rivet::Particle functions to PID:: functions of the same name #define PARTICLE_TO_PID_BOOLFN(fname) inline bool fname (const Particle& p) { return PID:: fname (p.pid()); } #define PARTICLE_TO_PID_INTFN(fname) inline int fname (const Particle& p) { return PID:: fname (p.pid()); } #define PARTICLE_TO_PID_DBLFN(fname) inline double fname (const Particle& p) { return PID:: fname (p.pid()); } namespace Rivet { /// @name Particle classifier functions //@{ /// Unbound function access to PID code inline int pid(const Particle& p) { return p.pid(); } /// Unbound function access to abs PID code inline int abspid(const Particle& p) { return p.abspid(); } /// Is this particle species charged? PARTICLE_TO_PID_BOOLFN(isCharged) /// Is this particle species neutral? PARTICLE_TO_PID_BOOLFN(isNeutral) /// Is this a neutrino? PARTICLE_TO_PID_BOOLFN(isNeutrino) /// Determine if the PID is that of a charged lepton PARTICLE_TO_PID_BOOLFN(isChargedLepton) PARTICLE_TO_PID_BOOLFN(isChLepton) /// Determine if the PID is that of a lepton (charged or neutral) PARTICLE_TO_PID_BOOLFN(isLepton) /// Determine if the PID is that of a photon PARTICLE_TO_PID_BOOLFN(isPhoton) /// Determine if the PID is that of an electron or positron PARTICLE_TO_PID_BOOLFN(isElectron) /// Determine if the PID is that of an muon or antimuon PARTICLE_TO_PID_BOOLFN(isMuon) /// Determine if the PID is that of an tau or antitau PARTICLE_TO_PID_BOOLFN(isTau) /// Determine if the PID is that of a hadron PARTICLE_TO_PID_BOOLFN(isHadron) /// Determine if the PID is that of a meson PARTICLE_TO_PID_BOOLFN(isMeson) /// Determine if the PID is that of a baryon PARTICLE_TO_PID_BOOLFN(isBaryon) /// Determine if the PID is that of a quark PARTICLE_TO_PID_BOOLFN(isQuark) /// Determine if the PID is that of a parton (quark or gluon) PARTICLE_TO_PID_BOOLFN(isParton) /// Determine if the PID is that of a W+ PARTICLE_TO_PID_BOOLFN(isWplus) /// Determine if the PID is that of a W- PARTICLE_TO_PID_BOOLFN(isWminus) /// Determine if the PID is that of a W+- PARTICLE_TO_PID_BOOLFN(isW) /// Determine if the PID is that of a Z0 PARTICLE_TO_PID_BOOLFN(isZ) /// Determine if the PID is that of an SM/lightest SUSY Higgs PARTICLE_TO_PID_BOOLFN(isHiggs) /// Determine if the PID is that of an s/sbar PARTICLE_TO_PID_BOOLFN(isStrange) /// Determine if the PID is that of a c/cbar PARTICLE_TO_PID_BOOLFN(isCharm) /// Determine if the PID is that of a b/bbar PARTICLE_TO_PID_BOOLFN(isBottom) /// Determine if the PID is that of a t/tbar PARTICLE_TO_PID_BOOLFN(isTop) /// Determine if the particle is a heavy flavour hadron or parton PARTICLE_TO_PID_BOOLFN(isHeavyFlavour) /// Determine if the PID is that of a heavy parton (c,b,t) PARTICLE_TO_PID_BOOLFN(isHeavyParton) /// Determine if the PID is that of a light parton (u,d,s) PARTICLE_TO_PID_BOOLFN(isLightParton) /// Determine if the PID is that of a heavy flavour (b or c) meson PARTICLE_TO_PID_BOOLFN(isHeavyMeson) /// Determine if the PID is that of a heavy flavour (b or c) baryon PARTICLE_TO_PID_BOOLFN(isHeavyBaryon) /// Determine if the PID is that of a heavy flavour (b or c) hadron PARTICLE_TO_PID_BOOLFN(isHeavyHadron) /// Determine if the PID is that of a light flavour (not b or c) meson PARTICLE_TO_PID_BOOLFN(isLightMeson) /// Determine if the PID is that of a light flavour (not b or c) baryon PARTICLE_TO_PID_BOOLFN(isLightBaryon) /// Determine if the PID is that of a light flavour (not b or c) hadron PARTICLE_TO_PID_BOOLFN(isLightHadron) /// Determine if the PID is that of a b-meson. PARTICLE_TO_PID_BOOLFN(isBottomMeson) /// Determine if the PID is that of a b-baryon. PARTICLE_TO_PID_BOOLFN(isBottomBaryon) /// Determine if the PID is that of a b-hadron. PARTICLE_TO_PID_BOOLFN(isBottomHadron) /// @brief Determine if the PID is that of a c-meson. /// /// Specifically, the _heaviest_ quark is a c: a B_c is a b-meson and NOT a c-meson. /// Charmonia (closed charm) are counted as c-mesons here. PARTICLE_TO_PID_BOOLFN(isCharmMeson) /// @brief Determine if the PID is that of a c-baryon. /// /// Specifically, the _heaviest_ quark is a c: a baryon containing a b & c /// is a b-baryon and NOT a c-baryon. To test for the simpler case, just use /// a combination of hasCharm() and isBaryon(). PARTICLE_TO_PID_BOOLFN(isCharmBaryon) /// Determine if the PID is that of a c-hadron. PARTICLE_TO_PID_BOOLFN(isCharmHadron) // /// Determine if the PID is that of a strange meson // PARTICLE_TO_PID_BOOLFN(isStrangeMeson) // /// Determine if the PID is that of a strange baryon // PARTICLE_TO_PID_BOOLFN(isStrangeBaryon) // /// Determine if the PID is that of a strange hadron // PARTICLE_TO_PID_BOOLFN(isStrangeHadron) /// Is this a pomeron, odderon, or generic reggeon? PARTICLE_TO_PID_BOOLFN(isReggeon) /// Determine if the PID is that of a diquark (used in hadronization models) PARTICLE_TO_PID_BOOLFN(isDiquark) /// Determine if the PID is that of a pentaquark (hypothetical hadron) PARTICLE_TO_PID_BOOLFN(isPentaquark) /// Is this a fundamental SUSY particle? PARTICLE_TO_PID_BOOLFN(isSUSY) /// Is this an R-hadron? PARTICLE_TO_PID_BOOLFN(isRhadron) /// Is this a technicolor particle? PARTICLE_TO_PID_BOOLFN(isTechnicolor) /// Is this an excited (composite) quark or lepton? PARTICLE_TO_PID_BOOLFN(isExcited) /// Is this a Kaluza-Klein excitation? PARTICLE_TO_PID_BOOLFN(isKK) /// Is this a graviton? PARTICLE_TO_PID_BOOLFN(isGraviton) /// Is this a BSM particle (including graviton)? PARTICLE_TO_PID_BOOLFN(isBSM) /// Determine if the PID is in the generator-specific range PARTICLE_TO_PID_BOOLFN(isGenSpecific) /// Determine if the PID is that of an EW scale resonance PARTICLE_TO_PID_BOOLFN(isResonance) /// Check the PID for usability in transport codes like Geant4 PARTICLE_TO_PID_BOOLFN(isTransportable) /// Does this particle contain an up quark? PARTICLE_TO_PID_BOOLFN(hasUp) /// Does this particle contain a down quark? PARTICLE_TO_PID_BOOLFN(hasDown) /// Does this particle contain a strange quark? PARTICLE_TO_PID_BOOLFN(hasStrange) /// Does this particle contain a charm quark? PARTICLE_TO_PID_BOOLFN(hasCharm) /// Does this particle contain a bottom quark? PARTICLE_TO_PID_BOOLFN(hasBottom) /// Does this particle contain a top quark? PARTICLE_TO_PID_BOOLFN(hasTop) /// jSpin returns 2J+1, where J is the total spin PARTICLE_TO_PID_INTFN(jSpin) /// sSpin returns 2S+1, where S is the spin PARTICLE_TO_PID_INTFN(sSpin) /// lSpin returns 2L+1, where L is the orbital angular momentum PARTICLE_TO_PID_INTFN(lSpin) /// Return the charge PARTICLE_TO_PID_DBLFN(charge) /// Return 3 times the charge (3 x quark charge is an int) PARTICLE_TO_PID_INTFN(charge3) /// Return the absolute charge PARTICLE_TO_PID_DBLFN(abscharge) /// Return 3 times the abs charge (3 x quark charge is an int) PARTICLE_TO_PID_INTFN(abscharge3) /// Get the atomic number (number of protons) in a nucleus/ion PARTICLE_TO_PID_INTFN(nuclZ) /// Get the atomic weight (number of nucleons) in a nucleus/ion PARTICLE_TO_PID_INTFN(nuclA) /// If this is a nucleus (ion), get nLambda PARTICLE_TO_PID_INTFN(nuclNlambda) //@} /// @name Particle pair classifiers /// @todo Make versions that work on ParticlePair? //@{ inline bool isSameSign(const Particle& a, const Particle& b) { return PID::isSameSign(a.pid(), b.pid()); } inline bool isOppSign(const Particle& a, const Particle& b) { return PID::isOppSign(a.pid(), b.pid()); } inline bool isSameFlav(const Particle& a, const Particle& b) { return PID::isSameFlav(a.pid(), b.pid()); } inline bool isOppFlav(const Particle& a, const Particle& b) { return PID::isOppFlav(a.pid(), b.pid()); } inline bool isOSSF(const Particle& a, const Particle& b) { return PID::isOSSF(a.pid(), b.pid()); } inline bool isSSSF(const Particle& a, const Particle& b) { return PID::isSSSF(a.pid(), b.pid()); } inline bool isOSOF(const Particle& a, const Particle& b) { return PID::isOSOF(a.pid(), b.pid()); } inline bool isSSOF(const Particle& a, const Particle& b) { return PID::isSSOF(a.pid(), b.pid()); } //@} /// @name Particle charge/sign comparison functions //@{ /// @brief Return true if Particles @a a and @a b have the opposite charge sign /// @note Two neutrals returns false inline bool oppSign(const Particle& a, const Particle& b) { return sign(a.charge3()) == -sign(b.charge3()) && sign(a.charge3()) != ZERO; } /// Return true if Particles @a a and @a b have the same charge sign /// @note Two neutrals returns true inline bool sameSign(const Particle& a, const Particle& b) { return sign(a.charge3()) == sign(b.charge3()); } /// Return true if Particles @a a and @a b have the exactly opposite charge /// @note Two neutrals returns false inline bool oppCharge(const Particle& a, const Particle& b) { return a.charge3() == -b.charge3() && a.charge3() != 0; } /// Return true if Particles @a a and @a b have the same charge (including neutral) /// @note Two neutrals returns true inline bool sameCharge(const Particle& a, const Particle& b) { return a.charge3() == b.charge3(); } /// Return true if Particles @a a and @a b have a different (not necessarily opposite) charge inline bool diffCharge(const Particle& a, const Particle& b) { return a.charge3() != b.charge3(); } //@} ////////////////////////////////////// /// @name Non-PID particle properties, via unbound functions //@{ /// @brief Determine whether a particle is the first in a decay chain to meet the function requirement inline bool isFirstWith(const Particle& p, const ParticleSelector& f) { return p.isFirstWith(f); } /// @brief Determine whether a particle is the first in a decay chain not to meet the function requirement inline bool isFirstWithout(const Particle& p, const ParticleSelector& f) { return p.isFirstWithout(f); } /// @brief Determine whether a particle is the last in a decay chain to meet the function requirement inline bool isLastWith(const Particle& p, const ParticleSelector& f) { return p.isLastWith(f); } /// @brief Determine whether a particle is the last in a decay chain not to meet the function requirement inline bool isLastWithout(const Particle& p, const ParticleSelector& f) { return p.isLastWithout(f); } /// @brief Determine whether a particle has an ancestor which meets the function requirement inline bool hasAncestorWith(const Particle& p, const ParticleSelector& f, bool only_physical=true) { return p.hasAncestorWith(f, only_physical); } /// @brief Determine whether a particle has an ancestor which doesn't meet the function requirement inline bool hasAncestorWithout(const Particle& p, const ParticleSelector& f, bool only_physical=true) { return p.hasAncestorWithout(f, only_physical); } /// @brief Determine whether a particle has a parent which meets the function requirement inline bool hasParentWith(const Particle& p, const ParticleSelector& f) { return p.hasParentWith(f); } /// @brief Determine whether a particle has a parent which doesn't meet the function requirement inline bool hasParentWithout(const Particle& p, const ParticleSelector& f) { return p.hasParentWithout(f); } /// @brief Determine whether a particle has a child which meets the function requirement inline bool hasChildWith(const Particle& p, const ParticleSelector& f) { return p.hasChildWith(f); } /// @brief Determine whether a particle has a child which doesn't meet the function requirement inline bool hasChildWithout(const Particle& p, const ParticleSelector& f) { return p.hasChildWithout(f); } /// @brief Determine whether a particle has a descendant which meets the function requirement inline bool hasDescendantWith(const Particle& p, const ParticleSelector& f, bool remove_duplicates=true) { return p.hasDescendantWith(f, remove_duplicates); } /// @brief Determine whether a particle has a descendant which doesn't meet the function requirement inline bool hasDescendantWithout(const Particle& p, const ParticleSelector& f, bool remove_duplicates=true) { return p.hasDescendantWithout(f, remove_duplicates); } /// @brief Determine whether a particle has a stable descendant which meets the function requirement inline bool hasStableDescendantWith(const Particle& p, const ParticleSelector& f) { return p.hasStableDescendantWith(f); } /// @brief Determine whether a particle has a stable descendant which doesn't meet the function requirement inline bool hasStableDescendantWithout(const Particle& p, const ParticleSelector& f) { return p.hasStableDescendantWithout(f); } /// Is this particle potentially visible in a detector? inline bool isVisible(const Particle& p) { return p.isVisible(); } /// @brief Decide if a given particle is direct, via Particle::isDirect() /// /// A "direct" particle is one directly connected to the hard process. It is a /// preferred alias for "prompt", since it has no confusing implications about /// distinguishability by timing information. /// /// The boolean arguments allow a decay lepton to be considered direct if /// its parent was a "real" direct lepton. inline bool isDirect(const Particle& p, bool allow_from_direct_tau=false, bool allow_from_direct_mu=false) { return p.isDirect(allow_from_direct_tau, allow_from_direct_mu); } /// @brief Decide if a given particle is prompt, via Particle::isPrompt() /// /// The boolean arguments allow a decay lepton to be considered prompt if /// its parent was a "real" prompt lepton. inline bool isPrompt(const Particle& p, bool allow_from_prompt_tau=false, bool allow_from_prompt_mu=false) { return p.isPrompt(allow_from_prompt_tau, allow_from_prompt_mu); } /// Decide if a given particle is stable, via Particle::isStable() inline bool isStable(const Particle& p) { return p.isStable(); } /// Decide if a given particle decays hadronically inline bool hasHadronicDecay(const Particle& p) { if (p.isStable()) return false; if (p.hasChildWith(isHadron)) return true; return false; } /// Decide if a given particle decays leptonically (decays, and no hadrons) inline bool hasLeptonicDecay(const Particle& p) { if (p.isStable()) return false; if (p.hasChildWith(isHadron)) return false; return true; } /// Check whether a given PID is found in the particle's ancestor list /// @deprecated Prefer hasAncestorWith inline bool hasAncestor(const Particle& p, PdgId pid) { return p.hasAncestor(pid); } /// Determine whether the particle is from a b-hadron decay inline bool fromBottom(const Particle& p) { return p.fromBottom(); } /// @brief Determine whether the particle is from a c-hadron decay inline bool fromCharm(const Particle& p) { return p.fromCharm(); } /// @brief Determine whether the particle is from a hadron decay inline bool fromHadron(const Particle& p) { return p.fromHadron(); } /// @brief Determine whether the particle is from a tau decay inline bool fromTau(const Particle& p, bool prompt_taus_only=false) { return p.fromTau(prompt_taus_only); } /// @brief Determine whether the particle is from a prompt tau decay inline bool fromPromptTau(const Particle& p) { return p.fromPromptTau(); } // /// @brief Determine whether the particle is from a hadron or tau decay // DEPRECATED("Too vague: use fromHadron or fromHadronicTau") // inline bool fromDecay(const Particle& p) { return p.fromDecay(); } //@} /// @name Particle classifier -> bool functors /// /// To be passed to any() or all() e.g. any(p.children(), HasPID(PID::MUON)) //@{ /// Base type for Particle -> bool functors struct BoolParticleFunctor { virtual bool operator()(const Particle& p) const = 0; virtual ~BoolParticleFunctor() {} }; /// Functor for and-combination of selector logic struct BoolParticleAND : public BoolParticleFunctor { BoolParticleAND(const std::vector& sels) : selectors(sels) {} BoolParticleAND(const ParticleSelector& a, const ParticleSelector& b) : selectors({a,b}) {} BoolParticleAND(const ParticleSelector& a, const ParticleSelector& b, const ParticleSelector& c) : selectors({a,b,c}) {} bool operator()(const Particle& p) const { for (const ParticleSelector& sel : selectors) if (!sel(p)) return false; return true; } std::vector selectors; }; /// Operator syntactic sugar for AND construction inline BoolParticleAND operator && (const ParticleSelector& a, const ParticleSelector& b) { return BoolParticleAND(a, b); } /// Functor for or-combination of selector logic struct BoolParticleOR : public BoolParticleFunctor { BoolParticleOR(const std::vector& sels) : selectors(sels) {} BoolParticleOR(const ParticleSelector& a, const ParticleSelector& b) : selectors({a,b}) {} BoolParticleOR(const ParticleSelector& a, const ParticleSelector& b, const ParticleSelector& c) : selectors({a,b,c}) {} bool operator()(const Particle& p) const { for (const ParticleSelector& sel : selectors) if (sel(p)) return true; return false; } std::vector selectors; }; /// Operator syntactic sugar for OR construction inline BoolParticleOR operator || (const ParticleSelector& a, const ParticleSelector& b) { return BoolParticleOR(a, b); } /// Functor for inverting selector logic struct BoolParticleNOT : public BoolParticleFunctor { BoolParticleNOT(const ParticleSelector& sel) : selector(sel) {} bool operator()(const Particle& p) const { return !selector(p); } ParticleSelector selector; }; /// Operator syntactic sugar for NOT construction inline BoolParticleNOT operator ! (const ParticleSelector& a) { return BoolParticleNOT(a); } /// PID matching functor struct HasPID : public BoolParticleFunctor { HasPID(PdgId pid) : targetpids{pid} { } HasPID(vector pids) : targetpids{pids} { } HasPID(initializer_list pids) : targetpids{pids} { } bool operator()(const Particle& p) const { return contains(targetpids, p.pid()); } vector targetpids; }; using hasPID = HasPID; /// |PID| matching functor struct HasAbsPID : public BoolParticleFunctor { HasAbsPID(PdgId pid) : targetapids{abs(pid)} { } HasAbsPID(vector pids) { for (PdgId pid : pids) targetapids.push_back(abs(pid)); } HasAbsPID(initializer_list pids) { for (PdgId pid : pids) targetapids.push_back(abs(pid)); } bool operator()(const Particle& p) const { return contains(targetapids, p.abspid()); } vector targetapids; }; using hasAbsPID = HasAbsPID; /// Determine whether a particle is the first in a decay chain to meet the cut/function struct FirstParticleWith : public BoolParticleFunctor { FirstParticleWith(const ParticleSelector& f) : fn(f) { } FirstParticleWith(const Cut& c); bool operator()(const Particle& p) const { return isFirstWith(p, fn); } ParticleSelector fn; }; using firstParticleWith = FirstParticleWith; /// Determine whether a particle is the first in a decay chain not to meet the cut/function struct FirstParticleWithout : public BoolParticleFunctor { FirstParticleWithout(const ParticleSelector& f) : fn(f) { } FirstParticleWithout(const Cut& c); bool operator()(const Particle& p) const { return isFirstWithout(p, fn); } ParticleSelector fn; }; using firstParticleWithout = FirstParticleWithout; /// Determine whether a particle is the last in a decay chain to meet the cut/function struct LastParticleWith : public BoolParticleFunctor { template LastParticleWith(const FN& f) : fn(f) { } LastParticleWith(const Cut& c); bool operator()(const Particle& p) const { return isLastWith(p, fn); } std::function fn; }; using lastParticleWith = LastParticleWith; /// Determine whether a particle is the last in a decay chain not to meet the cut/function struct LastParticleWithout : public BoolParticleFunctor { LastParticleWithout(const ParticleSelector& f) : fn(f) { } LastParticleWithout(const Cut& c); bool operator()(const Particle& p) const { return isLastWithout(p, fn); } ParticleSelector fn; }; using lastParticleWithout = LastParticleWithout; /// Determine whether a particle has an ancestor which meets the cut/function struct HasParticleAncestorWith : public BoolParticleFunctor { HasParticleAncestorWith(const ParticleSelector& f, bool only_physical=true) : fn(f), onlyphysical(only_physical) { } HasParticleAncestorWith(const Cut& c, bool only_physical=true); bool operator()(const Particle& p) const { return hasAncestorWith(p, fn, onlyphysical); } ParticleSelector fn; bool onlyphysical; }; using hasParticleAncestorWith = HasParticleAncestorWith; /// Determine whether a particle has an ancestor which doesn't meet the cut/function struct HasParticleAncestorWithout : public BoolParticleFunctor { HasParticleAncestorWithout(const ParticleSelector& f, bool only_physical=true) : fn(f), onlyphysical(only_physical) { } HasParticleAncestorWithout(const Cut& c, bool only_physical=true); bool operator()(const Particle& p) const { return hasAncestorWithout(p, fn, onlyphysical); } ParticleSelector fn; bool onlyphysical; }; using hasParticleAncestorWithout = HasParticleAncestorWithout; /// Determine whether a particle has an parent which meets the cut/function struct HasParticleParentWith : public BoolParticleFunctor { HasParticleParentWith(const ParticleSelector& f) : fn(f) { } HasParticleParentWith(const Cut& c); bool operator()(const Particle& p) const { return hasParentWith(p, fn); } ParticleSelector fn; }; using hasParticleParentWith = HasParticleParentWith; /// Determine whether a particle has an parent which doesn't meet the cut/function struct HasParticleParentWithout : public BoolParticleFunctor { HasParticleParentWithout(const ParticleSelector& f) : fn(f) { } HasParticleParentWithout(const Cut& c); bool operator()(const Particle& p) const { return hasParentWithout(p, fn); } ParticleSelector fn; }; using hasParticleParentWithout = HasParticleParentWithout; /// Determine whether a particle has a child which meets the cut/function struct HasParticleChildWith : public BoolParticleFunctor { HasParticleChildWith(const ParticleSelector& f) : fn(f) { } HasParticleChildWith(const Cut& c); bool operator()(const Particle& p) const { return hasChildWith(p, fn); } ParticleSelector fn; }; using hasParticleChildWith = HasParticleChildWith; /// Determine whether a particle has a child which doesn't meet the cut/function struct HasParticleChildWithout : public BoolParticleFunctor { HasParticleChildWithout(const ParticleSelector& f) : fn(f) { } HasParticleChildWithout(const Cut& c); bool operator()(const Particle& p) const { return hasChildWithout(p, fn); } ParticleSelector fn; }; using hasParticleChildWithout = HasParticleChildWithout; /// Determine whether a particle has a descendant which meets the cut/function struct HasParticleDescendantWith : public BoolParticleFunctor { HasParticleDescendantWith(const ParticleSelector& f, bool remove_duplicates=true) : fn(f), rmduplicates(remove_duplicates) { } HasParticleDescendantWith(const Cut& c, bool remove_duplicates=true); bool operator()(const Particle& p) const { return hasDescendantWith(p, fn, rmduplicates); } ParticleSelector fn; bool rmduplicates; }; using hasParticleDescendantWith = HasParticleDescendantWith; /// Determine whether a particle has a descendant which doesn't meet the cut/function struct HasParticleDescendantWithout : public BoolParticleFunctor { HasParticleDescendantWithout(const ParticleSelector& f, bool remove_duplicates=true) : fn(f), rmduplicates(remove_duplicates) { } HasParticleDescendantWithout(const Cut& c, bool remove_duplicates=true); bool operator()(const Particle& p) const { return hasDescendantWithout(p, fn, rmduplicates); } ParticleSelector fn; bool rmduplicates; }; using hasParticleDescendantWithout = HasParticleDescendantWithout; //@} /// @name Unbound functions for filtering particles //@{ /// Filter a particle collection in-place to the subset that passes the supplied Cut Particles& ifilter_select(Particles& particles, const Cut& c); /// Alias for ifilter_select /// @deprecated Use ifilter_select inline Particles& ifilterBy(Particles& particles, const Cut& c) { return ifilter_select(particles, c); } + /// New alias for ifilter_select + inline Particles& iselect(Particles& particles, const Cut& c) { return ifilter_select(particles, c); } /// Filter a particle collection in-place to the subset that passes the supplied Cut inline Particles filter_select(const Particles& particles, const Cut& c) { Particles rtn = particles; return ifilter_select(rtn, c); } /// Alias for ifilter_select /// @deprecated Use filter_select inline Particles filterBy(const Particles& particles, const Cut& c) { return filter_select(particles, c); } + /// New alias for ifilter_select + inline Particles select(const Particles& particles, const Cut& c) { return filter_select(particles, c); } /// Filter a particle collection in-place to the subset that passes the supplied Cut inline Particles filter_select(const Particles& particles, const Cut& c, Particles& out) { out = filter_select(particles, c); return out; } /// Alias for ifilter_select /// @deprecated Use filter_select inline Particles filterBy(const Particles& particles, const Cut& c, Particles& out) { return filter_select(particles, c, out); } + /// New alias for ifilter_select + inline Particles select(const Particles& particles, const Cut& c, Particles& out) { return filter_select(particles, c, out); } /// Filter a particle collection in-place to the subset that fails the supplied Cut Particles& ifilter_discard(Particles& particles, const Cut& c); + /// New alias for ifilter_discard + inline Particles& idiscard(Particles& particles, const Cut& c) { return ifilter_discard(particles, c); } /// Filter a particle collection in-place to the subset that fails the supplied Cut inline Particles filter_discard(const Particles& particles, const Cut& c) { Particles rtn = particles; return ifilter_discard(rtn, c); } + /// New alias for filter_discard + inline Particles discard(const Particles& particles, const Cut& c) { return filter_discard(particles, c); } /// Filter a particle collection in-place to the subset that fails the supplied Cut inline Particles filter_discard(const Particles& particles, const Cut& c, Particles& out) { out = filter_discard(particles, c); return out; } + /// New alias for filter_discard + inline Particles discard(const Particles& particles, const Cut& c, Particles& out) { return filter_discard(particles, c, out); } // inline void ifilterIsolateDeltaR(Particles& particles, const FourMomenta& vecs) { // ifilter_discard(particles, // } // inline Particles filterIsolateDeltaR(const Particles& particles, const FourMomenta& vecs) { // } //@} /// @name Particle pair functions //@{ /// Get the PDG ID codes of a ParticlePair /// @todo Make ParticlePair a custom class instead? inline PdgIdPair pids(const ParticlePair& pp) { return make_pair(pp.first.pid(), pp.second.pid()); } //@} /// @name Operations on collections of Particle /// @note This can't be done on generic collections of ParticleBase -- thanks, C++ :-/ //@{ namespace Kin { inline double sumPt(const Particles& ps) { return sum(ps, pT, 0.0); } inline FourMomentum sumP4(const Particles& ps) { return sum(ps, p4, FourMomentum()); } inline Vector3 sumP3(const Particles& ps) { return sum(ps, p3, Vector3()); } /// @todo Min dPhi, min dR? /// @todo Isolation routines? } //@} // Import Kin namespace into Rivet using namespace Kin; /// Check Particle equivalence inline bool isSame(const Particle& a, const Particle& b) { return a.isSame(b); } } #endif