Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8308875
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
49 KB
Subscribers
None
View Options
diff --git a/analyses/pluginCMS/CMS_2015_I1397174.cc b/analyses/pluginCMS/CMS_2015_I1397174.cc
--- a/analyses/pluginCMS/CMS_2015_I1397174.cc
+++ b/analyses/pluginCMS/CMS_2015_I1397174.cc
@@ -1,386 +1,386 @@
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/PartonicTops.hh"
#include "Rivet/Projections/VetoedFinalState.hh"
#include "Rivet/Projections/FastJets.hh"
namespace Rivet {
/// Fully leptonic partonic ttbar analysis
class CMS_2015_I1397174 : public Analysis {
public:
/// Minimal constructor
CMS_2015_I1397174()
: Analysis("CMS_2015_I1397174") { }
/// @name Analysis methods
//@{
/// Set up projections and book histograms
void init() {
// Parton level top quarks
addProjection(PartonicTops(PartonicTops::E_MU, false), "PartonTops");
// Find jets not related to the top/W decays
VetoedFinalState vfs;
vfs.addDecayProductsVeto(PID::WPLUSBOSON);
vfs.addDecayProductsVeto(PID::WMINUSBOSON);
FastJets fj(vfs, FastJets::ANTIKT, 0.5, JetAlg::ALL_MUONS, JetAlg::ALL_INVISIBLES);
addProjection(fj, "Jets");
// Book histograms
_hVis_nJet30_abs = bookHisto1D( 1, 1, 1);
_hVis_nJet30 = bookHisto1D( 2, 1, 1);
_hVis_nJet60_abs = bookHisto1D( 3, 1, 1);
_hVis_nJet60 = bookHisto1D( 4, 1, 1);
_hVis_nJet100_abs = bookHisto1D( 5, 1, 1);
_hVis_nJet100 = bookHisto1D( 6, 1, 1);
_hVis_addJet1Pt_abs = bookHisto1D( 7, 1, 1);
_hVis_addJet1Pt = bookHisto1D( 8, 1, 1);
_hVis_addJet1Eta_abs = bookHisto1D( 9, 1, 1);
_hVis_addJet1Eta = bookHisto1D(10, 1, 1);
_hVis_addJet2Pt_abs = bookHisto1D(11, 1, 1);
_hVis_addJet2Pt = bookHisto1D(12, 1, 1);
_hVis_addJet2Eta_abs = bookHisto1D(13, 1, 1);
_hVis_addJet2Eta = bookHisto1D(14, 1, 1);
_hVis_addJJMass_abs = bookHisto1D(15, 1, 1);
_hVis_addJJMass = bookHisto1D(16, 1, 1);
_hVis_addJJDR_abs = bookHisto1D(17, 1, 1);
_hVis_addJJDR = bookHisto1D(18, 1, 1);
_hVis_addJJHT_abs = bookHisto1D(19, 1, 1);
_hVis_addJJHT = bookHisto1D(20, 1, 1);
_hFull_addJet1Pt_abs = bookHisto1D(21, 1, 1);
_hFull_addJet1Pt = bookHisto1D(22, 1, 1);
_hFull_addJet1Eta_abs = bookHisto1D(23, 1, 1);
_hFull_addJet1Eta = bookHisto1D(24, 1, 1);
_hFull_addJet2Pt_abs = bookHisto1D(25, 1, 1);
_hFull_addJet2Pt = bookHisto1D(26, 1, 1);
_hFull_addJet2Eta_abs = bookHisto1D(27, 1, 1);
_hFull_addJet2Eta = bookHisto1D(28, 1, 1);
_hFull_addJJMass_abs = bookHisto1D(29, 1, 1);
_hFull_addJJMass = bookHisto1D(30, 1, 1);
_hFull_addJJDR_abs = bookHisto1D(31, 1, 1);
_hFull_addJJDR = bookHisto1D(32, 1, 1);
_hFull_addJJHT_abs = bookHisto1D(33, 1, 1);
_hFull_addJJHT = bookHisto1D(34, 1, 1);
_hVis_addBJet1Pt_abs = bookHisto1D(35, 1, 1);
_hVis_addBJet1Pt = bookHisto1D(36, 1, 1);
_hVis_addBJet1Eta_abs = bookHisto1D(37, 1, 1);
_hVis_addBJet1Eta = bookHisto1D(38, 1, 1);
_hVis_addBJet2Pt_abs = bookHisto1D(39, 1, 1);
_hVis_addBJet2Pt = bookHisto1D(40, 1, 1);
_hVis_addBJet2Eta_abs = bookHisto1D(41, 1, 1);
_hVis_addBJet2Eta = bookHisto1D(42, 1, 1);
_hVis_addBBMass_abs = bookHisto1D(43, 1, 1);
_hVis_addBBMass = bookHisto1D(44, 1, 1);
_hVis_addBBDR_abs = bookHisto1D(45, 1, 1);
_hVis_addBBDR = bookHisto1D(46, 1, 1);
_hFull_addBJet1Pt_abs = bookHisto1D(47, 1, 1);
_hFull_addBJet1Pt = bookHisto1D(48, 1, 1);
_hFull_addBJet1Eta_abs = bookHisto1D(49, 1, 1);
_hFull_addBJet1Eta = bookHisto1D(50, 1, 1);
_hFull_addBJet2Pt_abs = bookHisto1D(51, 1, 1);
_hFull_addBJet2Pt = bookHisto1D(52, 1, 1);
_hFull_addBJet2Eta_abs = bookHisto1D(53, 1, 1);
_hFull_addBJet2Eta = bookHisto1D(54, 1, 1);
_hFull_addBBMass_abs = bookHisto1D(55, 1, 1);
_hFull_addBBMass = bookHisto1D(56, 1, 1);
_hFull_addBBDR_abs = bookHisto1D(57, 1, 1);
_hFull_addBBDR = bookHisto1D(58, 1, 1);
_h_gap_addJet1Pt = bookProfile1D(59, 1, 1);
_h_gap_addJet1Pt_eta0 = bookProfile1D(60, 1, 1);
_h_gap_addJet1Pt_eta1 = bookProfile1D(61, 1, 1);
_h_gap_addJet1Pt_eta2 = bookProfile1D(62, 1, 1);
_h_gap_addJet2Pt = bookProfile1D(63, 1, 1);
_h_gap_addJet2Pt_eta0 = bookProfile1D(64, 1, 1);
_h_gap_addJet2Pt_eta1 = bookProfile1D(65, 1, 1);
_h_gap_addJet2Pt_eta2 = bookProfile1D(66, 1, 1);
_h_gap_addJetHT = bookProfile1D(67, 1, 1);
_h_gap_addJetHT_eta0 = bookProfile1D(68, 1, 1);
_h_gap_addJetHT_eta1 = bookProfile1D(69, 1, 1);
_h_gap_addJetHT_eta2 = bookProfile1D(70, 1, 1);
}
void analyze(const Event& event) {
// The objects used in the PAPER 12-041 are defined as follows (see p.16 for details):
//
// * Leptons : from the W boson decays after FSR
// * Jets : anti-kT R=0.5 to all stable particles
// exclude W->enu, munu, taunu
// * B jet : B-Ghost matched
// * B from top : B hadron from top->b decay
//
// Visible phase space definition:
//
// * Leptons : pT > 20, |eta| < 2.4
// * B jets from top : pT > 30, |eta| < 2.4
// Additional jets : pT > 20, |eta| < 2.4
// *
// Full phase space definition:
//
// * Correction to dilepton BR from W boson BR
// * No cut on top decay products
// * Additional jets : pT > 20, |eta| < 2.4
// Do the analysis only for the ttbar full leptonic channel, removing tau decays
const Particles partontops = apply<ParticleFinder>(event, "PartonTops").particlesByPt();
if (partontops.size() != 2) vetoEvent;
const Particle& t1 = partontops[0];
const Particle& t2 = partontops[1];
// Apply acceptance cuts on top-decay leptons (existence should be guaranteed)
const auto isPromptChLepton = [](const Particle& p){return isChargedLepton(p) && !fromDecay(p);};
const Particle lep1 = t1.allDescendants(lastParticleWith(isPromptChLepton)).front();
const Particle lep2 = t2.allDescendants(lastParticleWith(isPromptChLepton)).front();
if (lep1.pT() < 1e-9*GeV || lep2.pT() < 1e-9*GeV) vetoEvent; // sanity check?
const Jets jets = apply<JetAlg>(event, "Jets").jetsByPt(Cuts::pT > 20*GeV && Cuts::abseta < 2.4);
int nJet30 = 0, nJet60 = 0, nJet100 = 0;
Jets topBJets, addJets, addBJets, addJets_eta0, addJets_eta1, addJets_eta2;
for (const Jet& jet : jets) {
if (jet.pT() > 30*GeV) nJet30 += 1;
if (jet.pT() > 60*GeV) nJet60 += 1;
if (jet.pT() > 100*GeV) nJet100 += 1;
const bool isBtagged = jet.bTagged();
- const bool isBFromTop = any(jet.bTags(), hasParticleAncestorWith(Cuts::abspid == PID::TQUARK));
+ const bool isBFromTop = any(jet.bTags(), hasParticleAncestorWith(Cuts::abspid == PID::TQUARK, false));
if (isBFromTop) {
if (jet.pT() > 30*GeV) topBJets.push_back(jet);
} else {
addJets.push_back(jet);
if (isBtagged) addBJets.push_back(jet);
if (jet.abseta() < 0.8 ) addJets_eta0.push_back(jet);
else if (jet.abseta() < 1.5 ) addJets_eta1.push_back(jet);
else if (jet.abseta() < 2.4 ) addJets_eta2.push_back(jet);
}
}
const bool isVisiblePS = topBJets.size() >= 2
&& lep1.pT() > 20*GeV && lep1.abseta() < 2.4 && lep2.pT() > 20*GeV && lep2.abseta() < 2.4;
MSG_DEBUG(isVisiblePS << ": #b(top) = " << topBJets.size()
<< "; l1 = " << lep1.pT() << ", " << lep1.abseta()
<< "; l2 = " << lep2.pT() << ", " << lep2.abseta());
const double weight = event.weight();
if (isVisiblePS) {
fillWithOF(_hVis_nJet30_abs, nJet30, weight);
fillWithOF(_hVis_nJet30, nJet30, weight);
fillWithOF(_hVis_nJet60_abs, nJet60, weight);
fillWithOF(_hVis_nJet60, nJet60, weight);
fillWithOF(_hVis_nJet100_abs, nJet100, weight);
fillWithOF(_hVis_nJet100, nJet100, weight);
fillGapFractions(addJets, _h_gap_addJet1Pt, _h_gap_addJet2Pt, _h_gap_addJetHT, weight);
fillGapFractions(addJets_eta0, _h_gap_addJet1Pt_eta0, _h_gap_addJet2Pt_eta0, _h_gap_addJetHT_eta0, weight);
fillGapFractions(addJets_eta1, _h_gap_addJet1Pt_eta1, _h_gap_addJet2Pt_eta1, _h_gap_addJetHT_eta1, weight);
fillGapFractions(addJets_eta2, _h_gap_addJet1Pt_eta2, _h_gap_addJet2Pt_eta2, _h_gap_addJetHT_eta2, weight);
}
// Plots with two additional jets
if (addJets.size() >= 1) {
const double ht = sum(addJets, Kin::pT, 0.0);
_hFull_addJJHT_abs->fill(ht/GeV, weight);
_hFull_addJJHT ->fill(ht/GeV, weight);
if (isVisiblePS) {
_hVis_addJJHT_abs->fill(ht/GeV, weight);
_hVis_addJJHT ->fill(ht/GeV, weight);
}
const Jet& j1 = addJets[0];
_hFull_addJet1Pt_abs ->fill(j1.pT()/GeV, weight);
_hFull_addJet1Pt ->fill(j1.pT()/GeV, weight);
_hFull_addJet1Eta_abs->fill(j1.abseta(), weight);
_hFull_addJet1Eta ->fill(j1.abseta(), weight);
if (isVisiblePS) {
_hVis_addJet1Pt_abs ->fill(j1.pT()/GeV, weight);
_hVis_addJet1Pt ->fill(j1.pT()/GeV, weight);
_hVis_addJet1Eta_abs->fill(j1.abseta(), weight);
_hVis_addJet1Eta ->fill(j1.abseta(), weight);
}
if (addJets.size() >= 2) {
const Jet& j2 = addJets[1];
_hFull_addJet2Pt_abs ->fill(j2.pT()/GeV, weight);
_hFull_addJet2Pt ->fill(j2.pT()/GeV, weight);
_hFull_addJet2Eta_abs->fill(j2.abseta(), weight);
_hFull_addJet2Eta ->fill(j2.abseta(), weight);
if (isVisiblePS) {
_hVis_addJet2Pt_abs ->fill(j2.pT()/GeV, weight);
_hVis_addJet2Pt ->fill(j2.pT()/GeV, weight);
_hVis_addJet2Eta_abs->fill(j2.abseta(), weight);
_hVis_addJet2Eta ->fill(j2.abseta(), weight);
}
const double jjmass = (j1.mom() + j2.mom()).mass();
const double jjdR = deltaR(j1, j2);
_hFull_addJJMass_abs->fill(jjmass/GeV, weight);
_hFull_addJJMass ->fill(jjmass/GeV, weight);
_hFull_addJJDR_abs ->fill(jjdR, weight);
_hFull_addJJDR ->fill(jjdR, weight);
if (isVisiblePS) {
_hVis_addJJMass_abs->fill(jjmass/GeV, weight);
_hVis_addJJMass ->fill(jjmass/GeV, weight);
_hVis_addJJDR_abs ->fill(jjdR, weight);
_hVis_addJJDR ->fill(jjdR, weight);
}
}
}
// Same set of plots if there are additional b-jets
if (addBJets.size() >= 1) {
const Jet& b1 = addBJets[0];
_hFull_addBJet1Pt_abs ->fill(b1.pT()/GeV, weight);
_hFull_addBJet1Pt ->fill(b1.pT()/GeV, weight);
_hFull_addBJet1Eta_abs->fill(b1.abseta(), weight);
_hFull_addBJet1Eta ->fill(b1.abseta(), weight);
if (isVisiblePS) {
_hVis_addBJet1Pt_abs ->fill(b1.pT()/GeV, weight);
_hVis_addBJet1Pt ->fill(b1.pT()/GeV, weight);
_hVis_addBJet1Eta_abs->fill(b1.abseta(), weight);
_hVis_addBJet1Eta ->fill(b1.abseta(), weight);
}
if (addBJets.size() >= 2) {
const Jet& b2 = addBJets[1];
_hFull_addBJet2Pt_abs ->fill(b2.pT()/GeV, weight);
_hFull_addBJet2Pt ->fill(b2.pT()/GeV, weight);
_hFull_addBJet2Eta_abs->fill(b2.abseta(), weight);
_hFull_addBJet2Eta ->fill(b2.abseta(), weight);
if (isVisiblePS) {
_hVis_addBJet2Pt_abs ->fill(b2.pT()/GeV, weight);
_hVis_addBJet2Pt ->fill(b2.pT()/GeV, weight);
_hVis_addBJet2Eta_abs->fill(b2.abseta(), weight);
_hVis_addBJet2Eta ->fill(b2.abseta(), weight);
}
const double bbmass = (b1.mom() + b2.mom()).mass();
const double bbdR = deltaR(b1, b2);
_hFull_addBBMass_abs->fill(bbmass/GeV, weight);
_hFull_addBBMass ->fill(bbmass/GeV, weight);
_hFull_addBBDR_abs ->fill(bbdR, weight);
_hFull_addBBDR ->fill(bbdR, weight);
if (isVisiblePS) {
_hVis_addBBMass_abs->fill(bbmass/GeV, weight);
_hVis_addBBMass ->fill(bbmass/GeV, weight);
_hVis_addBBDR_abs ->fill(bbdR, weight);
_hVis_addBBDR ->fill(bbdR, weight);
}
}
}
}
void finalize() {
const double ttbarXS = !std::isnan(crossSectionPerEvent()) ? crossSection() : 252.89*picobarn;
if (std::isnan(crossSectionPerEvent()))
MSG_INFO("No valid cross-section given, using NNLO (arXiv:1303.6254; sqrt(s)=8 TeV, m_t=172.5 GeV): " << ttbarXS/picobarn << " pb");
normalize({_hVis_nJet30,_hVis_nJet60, _hVis_nJet100,
_hVis_addJet1Pt, _hVis_addJet1Eta, _hVis_addJet2Pt, _hVis_addJet2Eta,
_hVis_addJJMass, _hVis_addJJDR, _hVis_addJJHT,
_hFull_addJet1Pt, _hFull_addJet1Eta, _hFull_addJet2Pt, _hFull_addJet2Eta,
_hFull_addJJMass, _hFull_addJJDR, _hFull_addJJHT,
_hVis_addBJet1Pt, _hVis_addBJet1Eta, _hVis_addBJet2Pt, _hVis_addBJet2Eta,
_hVis_addBBMass, _hVis_addBBDR,
_hFull_addBJet1Pt, _hFull_addBJet1Eta, _hFull_addBJet2Pt, _hFull_addBJet2Eta,
_hFull_addBBMass, _hFull_addBBDR});
const double xsPerWeight = ttbarXS/picobarn / sumOfWeights();
scale({_hVis_nJet30_abs, _hVis_nJet60_abs, _hVis_nJet100_abs,
_hVis_addJet1Pt_abs, _hVis_addJet1Eta_abs, _hVis_addJet2Pt_abs, _hVis_addJet2Eta_abs,
_hVis_addJJMass_abs, _hVis_addJJDR_abs, _hVis_addJJHT_abs,
_hVis_addBJet1Pt_abs, _hVis_addBJet1Eta_abs, _hVis_addBJet2Pt_abs, _hVis_addBJet2Eta_abs,
_hVis_addBBMass_abs, _hVis_addBBDR_abs}, xsPerWeight);
const double sfull = xsPerWeight / 0.0454; //< correct for dilepton branching fraction
scale({_hFull_addJet1Pt_abs, _hFull_addJet1Eta_abs, _hFull_addJet2Pt_abs, _hFull_addJet2Eta_abs,
_hFull_addJJMass_abs, _hFull_addJJDR_abs, _hFull_addJJHT_abs,
_hFull_addBJet1Pt_abs, _hFull_addBJet1Eta_abs, _hFull_addBJet2Pt_abs, _hFull_addBJet2Eta_abs,
_hFull_addBBMass_abs, _hFull_addBBDR_abs}, sfull);
}
//@}
void fillWithOF(Histo1DPtr h, double x, double w) {
h->fill(std::min(x, h->xMax()-1e-9), w);
}
void fillGapFractions(const Jets& addJets, Profile1DPtr h_gap_addJet1Pt, Profile1DPtr h_gap_addJet2Pt, Profile1DPtr h_gap_addJetHT, double weight) {
const double j1pt = (addJets.size() > 0) ? addJets[0].pT() : 0;
for (size_t i = 0; i < h_gap_addJet1Pt->numBins(); ++i) {
const double binCenter = h_gap_addJet1Pt->bin(i).xMid();
h_gap_addJet1Pt->fillBin(i, int(j1pt/GeV < binCenter), weight);
}
const double j2pt = (addJets.size() > 1) ? addJets[1].pT() : 0;
for (size_t i = 0; i < h_gap_addJet2Pt->numBins(); ++i) {
const double binCenter = h_gap_addJet2Pt->bin(i).xMid();
h_gap_addJet2Pt->fillBin(i, int(j2pt/GeV < binCenter), weight);
}
const double ht = sum(addJets, Kin::pT, 0.);
for (size_t i = 0; i < h_gap_addJetHT->numBins(); ++i) {
const double binCenter = h_gap_addJetHT->bin(i).xMid();
h_gap_addJetHT->fillBin(i, int(ht/GeV < binCenter) , weight);
}
}
// @name Histogram data members
//@{
Histo1DPtr _hVis_nJet30_abs, _hVis_nJet60_abs, _hVis_nJet100_abs;
Histo1DPtr _hVis_addJet1Pt_abs, _hVis_addJet1Eta_abs, _hVis_addJet2Pt_abs, _hVis_addJet2Eta_abs;
Histo1DPtr _hVis_addJJMass_abs, _hVis_addJJDR_abs, _hVis_addJJHT_abs;
Histo1DPtr _hFull_addJet1Pt_abs, _hFull_addJet1Eta_abs, _hFull_addJet2Pt_abs, _hFull_addJet2Eta_abs;
Histo1DPtr _hFull_addJJMass_abs, _hFull_addJJDR_abs, _hFull_addJJHT_abs;
Histo1DPtr _hVis_addBJet1Pt_abs, _hVis_addBJet1Eta_abs, _hVis_addBJet2Pt_abs, _hVis_addBJet2Eta_abs;
Histo1DPtr _hVis_addBBMass_abs, _hVis_addBBDR_abs;
Histo1DPtr _hFull_addBJet1Pt_abs, _hFull_addBJet1Eta_abs, _hFull_addBJet2Pt_abs, _hFull_addBJet2Eta_abs;
Histo1DPtr _hFull_addBBMass_abs, _hFull_addBBDR_abs;
Histo1DPtr _hVis_nJet30, _hVis_nJet60, _hVis_nJet100;
Histo1DPtr _hVis_addJet1Pt, _hVis_addJet1Eta, _hVis_addJet2Pt, _hVis_addJet2Eta;
Histo1DPtr _hVis_addJJMass, _hVis_addJJDR, _hVis_addJJHT;
Histo1DPtr _hFull_addJet1Pt, _hFull_addJet1Eta, _hFull_addJet2Pt, _hFull_addJet2Eta;
Histo1DPtr _hFull_addJJMass, _hFull_addJJDR, _hFull_addJJHT;
Histo1DPtr _hVis_addBJet1Pt, _hVis_addBJet1Eta, _hVis_addBJet2Pt, _hVis_addBJet2Eta;
Histo1DPtr _hVis_addBBMass, _hVis_addBBDR;
Histo1DPtr _hFull_addBJet1Pt, _hFull_addBJet1Eta, _hFull_addBJet2Pt, _hFull_addBJet2Eta;
Histo1DPtr _hFull_addBBMass, _hFull_addBBDR;
Profile1DPtr _h_gap_addJet1Pt, _h_gap_addJet1Pt_eta0, _h_gap_addJet1Pt_eta1, _h_gap_addJet1Pt_eta2;
Profile1DPtr _h_gap_addJet2Pt, _h_gap_addJet2Pt_eta0, _h_gap_addJet2Pt_eta1, _h_gap_addJet2Pt_eta2;
Profile1DPtr _h_gap_addJetHT, _h_gap_addJetHT_eta0, _h_gap_addJetHT_eta1, _h_gap_addJetHT_eta2;
//@}
};
// The hook for the plugin system
DECLARE_RIVET_PLUGIN(CMS_2015_I1397174);
}
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,778 +1,782 @@
#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)
/// Alias for charge3
/// @deprecated Use charge3
PARTICLE_TO_PID_INTFN(threeCharge)
/// 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<ParticleSelector>& 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<ParticleSelector> 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<ParticleSelector>& 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<ParticleSelector> 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<PdgId> pids) : targetpids{pids} { }
HasPID(initializer_list<PdgId> pids) : targetpids{pids} { }
bool operator()(const Particle& p) const { return contains(targetpids, p.pid()); }
vector<PdgId> targetpids;
};
using hasPID = HasPID;
/// |PID| matching functor
struct HasAbsPID : public BoolParticleFunctor {
HasAbsPID(PdgId pid) : targetapids{abs(pid)} { }
HasAbsPID(vector<PdgId> pids) { for (PdgId pid : pids) targetapids.push_back(abs(pid)); }
HasAbsPID(initializer_list<PdgId> pids) { for (PdgId pid : pids) targetapids.push_back(abs(pid)); }
bool operator()(const Particle& p) const { return contains(targetapids, p.abspid()); }
vector<PdgId> 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 <typename FN>
LastParticleWith(const FN& f) : fn(f) { }
LastParticleWith(const Cut& c);
bool operator()(const Particle& p) const { return isLastWith(p, fn); }
std::function<bool(const Particle&)> 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) : fn(f) { }
- HasParticleAncestorWith(const Cut& c);
- bool operator()(const Particle& p) const { return hasAncestorWith(p, fn); }
+ 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) : fn(f) { }
- HasParticleAncestorWithout(const Cut& c);
- bool operator()(const Particle& p) const { return hasAncestorWithout(p, fn); }
+ 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) : fn(f) { }
- HasParticleDescendantWith(const Cut& c);
- bool operator()(const Particle& p) const { return hasDescendantWith(p, fn); }
+ 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) : fn(f) { }
- HasParticleDescendantWithout(const Cut& c);
- bool operator()(const Particle& p) const { return hasDescendantWithout(p, fn); }
+ 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); }
/// 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); }
/// 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); }
/// Filter a particle collection in-place to the subset that fails the supplied Cut
Particles& ifilter_discard(Particles& particles, const Cut& 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);
}
/// 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;
}
// 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
diff --git a/src/Tools/ParticleUtils.cc b/src/Tools/ParticleUtils.cc
--- a/src/Tools/ParticleUtils.cc
+++ b/src/Tools/ParticleUtils.cc
@@ -1,58 +1,62 @@
#include "Rivet/Tools/ParticleUtils.hh"
#include "Rivet/Tools/Cuts.hh"
namespace Rivet {
FirstParticleWith::FirstParticleWith(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
FirstParticleWithout::FirstParticleWithout(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
LastParticleWith::LastParticleWith(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
LastParticleWithout::LastParticleWithout(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
- HasParticleAncestorWith::HasParticleAncestorWith(const Cut& c)
- : fn([&](const Particle& p){ return c->accept(p); }) { }
+ HasParticleAncestorWith::HasParticleAncestorWith(const Cut& c, bool only_physical)
+ : fn([&](const Particle& p){ return c->accept(p); }),
+ onlyphysical(only_physical) { }
- HasParticleAncestorWithout::HasParticleAncestorWithout(const Cut& c)
- : fn([&](const Particle& p){ return c->accept(p); }) { }
+ HasParticleAncestorWithout::HasParticleAncestorWithout(const Cut& c, bool only_physical)
+ : fn([&](const Particle& p){ return c->accept(p); }),
+ onlyphysical(only_physical) { }
HasParticleParentWith::HasParticleParentWith(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
HasParticleParentWithout::HasParticleParentWithout(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
HasParticleChildWith::HasParticleChildWith(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
HasParticleChildWithout::HasParticleChildWithout(const Cut& c)
: fn([&](const Particle& p){ return c->accept(p); }) { }
- HasParticleDescendantWith::HasParticleDescendantWith(const Cut& c)
- : fn([&](const Particle& p){ return c->accept(p); }) { }
+ HasParticleDescendantWith::HasParticleDescendantWith(const Cut& c, bool remove_duplicates)
+ : fn([&](const Particle& p){ return c->accept(p); }),
+ rmduplicates(remove_duplicates) { }
- HasParticleDescendantWithout::HasParticleDescendantWithout(const Cut& c)
- : fn([&](const Particle& p){ return c->accept(p); }) { }
+ HasParticleDescendantWithout::HasParticleDescendantWithout(const Cut& c, bool remove_duplicates)
+ : fn([&](const Particle& p){ return c->accept(p); }),
+ rmduplicates(remove_duplicates) { }
Particles& ifilter_select(Particles& particles, const Cut& c) {
if (c == Cuts::OPEN) return particles;
// return ifilter_select(particles, *c);
return ifilter_select(particles, [&](const Particle& p){return c->accept(p);});
}
Particles& ifilter_discard(Particles& particles, const Cut& c) {
if (c == Cuts::OPEN) { particles.clear(); return particles; }
// return ifilter_discard(particles, *c);
return ifilter_discard(particles, [&](const Particle& p){return c->accept(p);});
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 1:27 PM (1 d, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4022956
Default Alt Text
(49 KB)
Attached To
rRIVETHG rivethg
Event Timeline
Log In to Comment