File indexing completed on 2025-07-29 08:51:04
0001
0002 #include "Rivet/Analysis.hh"
0003 #include "Rivet/Projections/FinalState.hh"
0004 #include "Rivet/Projections/FastJets.hh"
0005 #include "Rivet/Projections/LeptonFinder.hh"
0006 #include "Rivet/Projections/TauFinder.hh"
0007 #include "Rivet/Projections/MissingMomentum.hh"
0008 #include "Rivet/Projections/DirectFinalState.hh"
0009 #include "Rivet/Projections/Smearing.hh"
0010 #include "Rivet/Tools/Cutflow.hh"
0011
0012 namespace Rivet {
0013
0014
0015
0016 class SimpleAnalysis : public Analysis {
0017 public:
0018
0019
0020 enum class IDClass { LOOSE, MEDIUM, TIGHT };
0021
0022
0023 SimpleAnalysis(const std::string& name)
0024 : Analysis(name)
0025 { }
0026
0027
0028 virtual ~SimpleAnalysis()
0029 { }
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 void postInit() {
0040
0041
0042 FinalState es(_acut && _ecut && Cuts::abspid == PID::ELECTRON);
0043 LeptonFinder es_prompt(_acut && _ecut && Cuts::abspid == PID::ELECTRON, 0.1);
0044 for (const auto& classkv : _idclasses()) {
0045 const IDClass& idc = classkv.first;
0046 const string p = "Electrons";
0047 const string aname = _pckey(true, idc, p);
0048 if (!hasProjection(aname))
0049 declare(SmearedParticles(es, _effs_electron[idc], _smear_electron), aname);
0050 const string pname = _pckey(false, idc, p);
0051 if (!hasProjection(pname))
0052 declare(SmearedParticles(es_prompt, _effs_electron[idc], _smear_electron), pname);
0053 }
0054
0055
0056 FinalState ms(_acut && _mcut && Cuts::abspid == PID::MUON);
0057 LeptonFinder ms_prompt(_acut && _mcut && Cuts::abspid == PID::MUON, 0.1);
0058 for (const auto& classkv : _idclasses()) {
0059 const IDClass& idc = classkv.first;
0060 const string p = "Muons";
0061 const string aname = _pckey(true, idc, p);
0062 if (!hasProjection(aname))
0063 declare(SmearedParticles(ms, _effs_muon[idc], _smear_muon), aname);
0064 const string pname = _pckey(false, idc, p);
0065 if (!hasProjection(pname))
0066 declare(SmearedParticles(ms_prompt, _effs_muon[idc], _smear_muon), pname);
0067 }
0068
0069
0070 FinalState ys(_acut && _phocut && Cuts::abspid == PID::PHOTON);
0071 DirectFinalState ys_prompt(_acut && _phocut && Cuts::abspid == PID::PHOTON);
0072 for (const auto& classkv : _idclasses()) {
0073 const IDClass& idc = classkv.first;
0074 const string p = "Photons";
0075 const string aname = _pckey(true, idc, p);
0076 if (!hasProjection(aname))
0077 declare(SmearedParticles(ys, _effs_photon[idc], _smear_photon), aname);
0078 const string pname = _pckey(false, idc, p);
0079 if (!hasProjection(pname))
0080 declare(SmearedParticles(ys_prompt, _effs_photon[idc], _smear_photon), pname);
0081 }
0082
0083
0084 TauFinder ts(TauDecay::HADRONIC, LeptonOrigin::ANY, _acut && _tcut);
0085 TauFinder ts_prompt(TauDecay::HADRONIC, LeptonOrigin::NODECAY, _acut && _tcut);
0086 for (const auto& classkv : _idclasses()) {
0087 const IDClass& idc = classkv.first;
0088 const string p = "Taus";
0089 const string aname = _pckey(true, idc, p);
0090 if (!hasProjection(aname))
0091 declare(SmearedParticles(ts, _effs_tau[idc], _smear_tau), aname);
0092 const string pname = _pckey(false, idc, p);
0093 if (!hasProjection(pname))
0094 declare(SmearedParticles(ts_prompt, _effs_tau[idc], _smear_tau), pname);
0095 }
0096
0097
0098 const FinalState trkfs(_acut && _trkcut && Cuts::abscharge > 0);
0099 if (!hasProjection("Tracks"))
0100 declare(SmearedParticles(trkfs, _eff_trk, _smear_trk), "Tracks");
0101
0102
0103 const FinalState allfs(_acut);
0104 declare(allfs, "AllParticles");
0105 for (const auto& jditem : _jdefs) {
0106 const JetScheme& jd = jditem.second;
0107
0108 FastJets jetfs(allfs, jd.alg, jd.R, jd.muons, jd.invis);
0109
0110 if (!hasProjection("Jets"+jditem.first))
0111 declare(SmearedJets(jetfs, _smears_jet[jditem.first], _effs_btag[jditem.first]), "Jets"+jditem.first);
0112 }
0113
0114
0115 if (!hasProjection("MET"))
0116 declare(SmearedMET(MissingMomentum(allfs), _smearps_met, _smear_met), "MET");
0117 }
0118
0119
0120
0121 void preAnalyze(const Event& event) {
0122 _electrons.clear();
0123 _muons.clear();
0124 _taus.clear();
0125 _photons.clear();
0126 _jets.clear();
0127 _bjets.clear();
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 void setElectronReco(const ParticleEffFn& eff, const ParticleSmearFn& smear=PARTICLE_SMEAR_IDENTITY, IDClass idc=IDClass::MEDIUM) {
0142 _effs_electron[idc] = eff;
0143 _smear_electron = smear;
0144 }
0145
0146 void setMuonReco(const ParticleEffFn& eff, const ParticleSmearFn& smear=PARTICLE_SMEAR_IDENTITY, IDClass idc=IDClass::MEDIUM) {
0147 _effs_muon[idc] = eff;
0148 _smear_muon = smear;
0149 }
0150
0151 void setPhotonReco(const ParticleEffFn& eff, const ParticleSmearFn& smear=PARTICLE_SMEAR_IDENTITY, IDClass idc=IDClass::MEDIUM) {
0152 _effs_photon[idc] = eff;
0153 _smear_photon = smear;
0154 }
0155
0156 void setTauReco(const ParticleEffFn& eff, const ParticleSmearFn& smear=PARTICLE_SMEAR_IDENTITY, IDClass idc=IDClass::MEDIUM) {
0157 _effs_tau[idc] = eff;
0158 _smear_tau = smear;
0159 }
0160
0161 void setTrkReco(const ParticleEffFn& eff, const ParticleSmearFn& smear=PARTICLE_SMEAR_IDENTITY) {
0162 _eff_trk = eff;
0163 _smear_trk = smear;
0164 }
0165
0166 void setJetReco(const JetSmearFn& smear, const JetEffFn& btageff, const std::string& jetname="DEFAULT") {
0167 _smears_jet[jetname] = smear;
0168 _effs_btag[jetname] = btageff;
0169 }
0170
0171 void setMETReco(const METSmearParamsFn& smearps) {
0172 _smearps_met = smearps;
0173 }
0174
0175 void setMETReco(const METSmearParamsFn& smearps, const METSmearFn& smear) {
0176 _smearps_met = smearps;
0177 _smear_met = smear;
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187 void setAccCut(const Cut& cut) { _acut = cut; }
0188 void setElectronCut(const Cut& cut) { _ecut = cut; }
0189 void setMuonCut(const Cut& cut) { _mcut = cut; }
0190 void setPhotonCut(const Cut& cut) { _phocut = cut; }
0191 void setTauCut(const Cut& cut) { _tcut = cut; }
0192 void setTrkCut(const Cut& cut) { _trkcut = cut; }
0193 void setJetDef(const JetScheme& jdef, const std::string& jetname="DEFAULT") { _jdefs[jetname] = jdef; }
0194 void setJetCut(const Cut& cut, const std::string& jetname="DEFAULT") { _jcuts[jetname] = cut; }
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 const Particles& electrons(IDClass eclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0206 const std::string kpc = _pckey(include_nonprompt, eclass);
0207 if (_electrons.find(kpc) == _electrons.end()) {
0208 _electrons[kpc] = apply<ParticleFinder>(currentEvent(), "Electrons"+kpc).particlesByPt();
0209 }
0210 return _electrons.at(kpc);
0211 }
0212
0213 Particles electrons(const Cut& cut, IDClass eclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0214 return select(electrons(eclass, include_nonprompt), cut);
0215 }
0216
0217
0218
0219 const Particles& muons(IDClass muclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0220 const std::string kpc = _pckey(include_nonprompt, muclass);
0221 if (_muons.find(kpc) == _muons.end()) {
0222 _muons[kpc] = apply<ParticleFinder>(currentEvent(), "Muons"+kpc).particlesByPt();
0223 }
0224 return _muons.at(kpc);
0225 }
0226
0227 Particles muons(const Cut& cut, IDClass muclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0228 return select(muons(muclass, include_nonprompt), cut);
0229 }
0230
0231
0232
0233 const Particles& photons(IDClass phoclass=IDClass::MEDIUM, bool include_nonprompt=false, double dRiso=0.4, double isofrac=0.1) const {
0234 const std::string kpc = _pckey(include_nonprompt, phoclass);
0235 if (_photons.find(kpc) == _photons.end()) {
0236 Particles ystmp = apply<ParticleFinder>(currentEvent(), "Photons"+kpc).particlesByPt();
0237 const Particles& clusters = apply<ParticleFinder>(currentEvent(), "AllParticles").particles();
0238 _photons[kpc].reserve(ystmp.size());
0239 for (const Particle& y : ystmp) {
0240 double sumpt = 0;
0241 for (const Particle& cl : select(clusters, deltaRLess(y, dRiso))) {
0242 if (deltaR(cl, y) == 0.01) continue;
0243 sumpt += cl.pT();
0244 }
0245 if (sumpt/y.pT() < isofrac) _photons[kpc].push_back(y);
0246 }
0247 }
0248 return _photons.at(kpc);
0249 }
0250
0251 Particles photons(const Cut& cut, IDClass phoclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0252 return select(photons(phoclass, include_nonprompt), cut);
0253 }
0254
0255
0256
0257 const Particles& taus(IDClass tauclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0258 const std::string kpc = _pckey(include_nonprompt, tauclass);
0259 if (_taus.find(kpc) == _taus.end()) {
0260 _taus[kpc] = apply<ParticleFinder>(currentEvent(), "Taus"+kpc).particlesByPt();
0261 }
0262 return _taus.at(kpc);
0263 }
0264
0265 Particles taus(const Cut& cut, IDClass tauclass=IDClass::MEDIUM, bool include_nonprompt=false) const {
0266 return select(taus(tauclass, include_nonprompt), cut);
0267 }
0268
0269
0270
0271
0272
0273
0274 const Particles tracks() const {
0275 return apply<ParticleFinder>(currentEvent(), "Tracks").particlesByPt();
0276 }
0277
0278
0279
0280
0281 Particles tracks(const Cut& cut) const {
0282 return apply<ParticleFinder>(currentEvent(), "Tracks").particlesByPt(cut);
0283 }
0284
0285
0286
0287 const std::vector<std::string> jetnames() const {
0288 std::vector<std::string> rtn;
0289 rtn.reserve(_jets.size());
0290 for (const auto& kv : _jets) rtn.push_back(kv.first);
0291 return rtn;
0292 }
0293
0294
0295 const Jets& jets(const std::string& jetname="DEFAULT") const {
0296 if (_jets.find(jetname) == _jets.end()) {
0297
0298 _jets[jetname] = apply<JetFinder>(currentEvent(), "Jets"+jetname).jetsByPt(_jcuts.at(jetname));
0299 }
0300 return _jets.at(jetname);
0301 }
0302
0303 Jets jets(const Cut& cut, const std::string& jetname="DEFAULT") const {
0304 return select(jets(jetname), cut);
0305 }
0306
0307
0308
0309 const Jets& bjets(const std::string& jetname="DEFAULT") const {
0310 if (_bjets.find(jetname) == _bjets.end()) {
0311 _bjets[jetname] = select(jets(jetname), hasBTag(_bcut, _bdeltaR));
0312 }
0313 return _bjets.at(jetname);
0314 }
0315
0316 Jets bjets(const Cut& cut, const std::string& jetname="DEFAULT") const {
0317 return select(bjets(jetname), cut);
0318 }
0319
0320
0321
0322 Vector3 vmet() const {
0323 return apply<METFinder>(currentEvent(), "MET").vectorMissingPt();
0324 }
0325
0326
0327 double met() const {
0328 return vmet().mod();
0329 }
0330
0331
0332 double set() const {
0333 return apply<METFinder>(currentEvent(), "MET").scalarEt();
0334 }
0335
0336
0337 double metSignf() const {
0338 return apply<SmearedMET>(currentEvent(), "MET").missingEtSignf();
0339 }
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364 void doSimpleOverlapRemoval(IDClass eclass=IDClass::MEDIUM, IDClass muclass=IDClass::MEDIUM,
0365 IDClass phoclass=IDClass::MEDIUM,
0366 bool include_nonprompt=false, const std::string& jetname="DEFAULT") {
0367
0368 Jets& myjets = const_cast<Jets&>(jets(jetname));
0369 Jets& mybjets = const_cast<Jets&>(bjets(jetname));
0370 Particles& myes = const_cast<Particles&>(electrons(eclass, include_nonprompt));
0371 Particles& myms = const_cast<Particles&>(muons(muclass, include_nonprompt));
0372
0373 Particles& myys = const_cast<Particles&>(photons(phoclass, include_nonprompt));
0374
0375 idiscardIfAnyDeltaRLess(myjets, myes, 0.2);
0376 idiscardIfAnyDeltaRLess(myjets, myms, 0.2);
0377 idiscardIfAnyDeltaRLess(mybjets, myes, 0.2);
0378 idiscardIfAnyDeltaRLess(mybjets, myms, 0.2);
0379
0380
0381 idiscardIfAnyDeltaRLess(myys, myes, 0.2);
0382
0383 idiscardIfAnyDeltaRLess(myes, myjets, _jdefs.at(jetname).R);
0384 idiscardIfAnyDeltaRLess(myms, myjets, _jdefs.at(jetname).R);
0385
0386 }
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 template<typename T>
0402 void scaleToIntLumi(T& ao, double intlumi) {
0403 scale(ao, intlumi*crossSection()/sumOfWeights());
0404 }
0405
0406
0407
0408
0409
0410
0411
0412
0413 const ParticleFinder& electronsProj(IDClass eclass=IDClass::MEDIUM, bool include_nonprompt=false) {
0414 return getProjection<ParticleFinder>(_pckey(include_nonprompt, eclass, "Electrons"));
0415 }
0416
0417 const ParticleFinder& muonsProj(IDClass muclass=IDClass::MEDIUM, bool include_nonprompt=false) {
0418 return getProjection<ParticleFinder>(_pckey(include_nonprompt, muclass, "Muons"));
0419 }
0420
0421 const ParticleFinder& tausProj(IDClass tauclass=IDClass::MEDIUM, bool include_nonprompt=false) {
0422 return getProjection<ParticleFinder>(_pckey(include_nonprompt, tauclass, "Taus"));
0423 }
0424
0425 const ParticleFinder& photonsProj(IDClass phoclass=IDClass::MEDIUM, bool include_nonprompt=false) {
0426 return getProjection<ParticleFinder>(_pckey(include_nonprompt, phoclass, "Photons"));
0427 }
0428
0429 const ParticleFinder& tracksProj() {
0430 return getProjection<ParticleFinder>("Tracks");
0431 }
0432
0433 const JetFinder& jetsProj(const std::string& jetname="DEFAULT") {
0434 return getProjection<JetFinder>("Jets_"+jetname);
0435 }
0436
0437 const METFinder& metProj() { return getProjection<METFinder>("MET"); }
0438
0439
0440
0441
0442 private:
0443
0444
0445
0446 std::map<IDClass, ParticleEffFn> _effs_electron{ { IDClass::LOOSE, PARTICLE_EFF_ONE }, { IDClass::MEDIUM, PARTICLE_EFF_ONE }, { IDClass::TIGHT, PARTICLE_EFF_ONE } };
0447 std::map<IDClass, ParticleEffFn> _effs_muon{ { IDClass::LOOSE, PARTICLE_EFF_ONE }, { IDClass::MEDIUM, PARTICLE_EFF_ONE }, { IDClass::TIGHT, PARTICLE_EFF_ONE } };
0448 std::map<IDClass, ParticleEffFn> _effs_photon{ { IDClass::LOOSE, PARTICLE_EFF_ONE }, { IDClass::MEDIUM, PARTICLE_EFF_ONE }, { IDClass::TIGHT, PARTICLE_EFF_ONE } };
0449 std::map<IDClass, ParticleEffFn> _effs_tau{ { IDClass::LOOSE, PARTICLE_EFF_ONE }, { IDClass::MEDIUM, PARTICLE_EFF_ONE }, { IDClass::TIGHT, PARTICLE_EFF_ONE } };
0450 ParticleSmearFn _smear_electron{PARTICLE_SMEAR_IDENTITY}, _smear_muon{PARTICLE_SMEAR_IDENTITY}, _smear_photon{PARTICLE_SMEAR_IDENTITY}, _smear_tau{PARTICLE_SMEAR_IDENTITY};
0451 ParticleEffFn _eff_trk{PARTICLE_EFF_ONE};
0452 ParticleSmearFn _smear_trk{PARTICLE_SMEAR_IDENTITY};
0453 std::map<std::string, JetSmearFn> _smears_jet{ { "DEFAULT", JET_SMEAR_IDENTITY } };
0454 std::map<std::string, JetEffFn> _effs_btag{ { "DEFAULT", JET_BTAG_IDENTITY } };
0455 METSmearParamsFn _smearps_met{MET_SMEARPARAMS_IDENTITY};
0456 METSmearFn _smear_met{MET_SMEAR_IDENTITY};
0457
0458
0459
0460
0461 Cut _acut = Cuts::abseta < 5.0;
0462 Cut _ecut = Cuts::pT > 10*GeV;
0463 Cut _mcut = Cuts::pT > 10*GeV;
0464 Cut _tcut = Cuts::pT > 10*GeV;
0465 Cut _trkcut = Cuts::abseta < 2.5;
0466 Cut _phocut = Cuts::pT > 10*GeV;
0467 std::map<std::string, Cut> _jcuts = {{ "DEFAULT", Cuts::pT > 20*GeV && Cuts::abseta < 5.0 }};
0468 std::map<std::string, JetScheme> _jdefs = {{ "DEFAULT", JetScheme(JetAlg::ANTIKT, 0.4) }};
0469
0470
0471
0472
0473
0474
0475
0476 Cut _bcut = Cuts::pT > 5*GeV && Cuts::abseta < 2.5;
0477 double _bdeltaR = 0.3;
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 mutable std::map<std::string, Particles> _electrons, _muons, _taus, _photons;
0492
0493
0494 mutable std::map<std::string, Jets> _jets, _bjets;
0495
0496
0497
0498
0499
0500
0501
0502 const std::map<IDClass, std::string>& _idclasses() const {
0503
0504 static const auto* map = new std::map<IDClass, std::string>{
0505 {IDClass::LOOSE, "Loose"}, {IDClass::MEDIUM, "Medium"}, {IDClass::TIGHT, "Tight"} };
0506 return *map;
0507 }
0508 const std::string& _idclassname(const IDClass& idc) const {
0509 return _idclasses().at(idc);
0510 }
0511
0512
0513 std::string _pckey(bool include_nonprompt, IDClass idc, const std::string& prefix="") const {
0514 return prefix + (include_nonprompt ? "All" : "Prompt") + _idclassname(idc);
0515 }
0516
0517 };
0518
0519
0520 }
0521
0522
0523
0524
0525
0526 #define RIVET_DEFAULT_SIMPLEANALYSIS_CTOR(clsname) clsname() : SimpleAnalysis(# clsname) {}
0527
0528
0529
0530
0531
0532
0533 #define setDetSmearing(DET, BTAG) do { \
0534 setElectronReco(ELECTRON_EFF_ ## DET ## _LOOSE, ELECTRON_SMEAR_ ## DET, IDClass::LOOSE) ; \
0535 setElectronReco(ELECTRON_EFF_ ## DET ## _MEDIUM, ELECTRON_SMEAR_ ## DET, IDClass::MEDIUM) ; \
0536 setElectronReco(ELECTRON_EFF_ ## DET ## _TIGHT, ELECTRON_SMEAR_ ## DET, IDClass::TIGHT) ; \
0537 setMuonReco(MUON_EFF_ ## DET ## _LOOSE, MUON_SMEAR_ ## DET, IDClass::LOOSE) ; \
0538 setMuonReco(MUON_EFF_ ## DET ## _MEDIUM, MUON_SMEAR_ ## DET, IDClass::MEDIUM) ; \
0539 setMuonReco(MUON_EFF_ ## DET ## _TIGHT, MUON_SMEAR_ ## DET, IDClass::TIGHT) ; \
0540 setPhotonReco(PHOTON_EFF_ ## DET ## _LOOSE, ELECTRON_SMEAR_ ## DET, IDClass::LOOSE) ; \
0541 setPhotonReco(PHOTON_EFF_ ## DET ## _MEDIUM, ELECTRON_SMEAR_ ## DET, IDClass::MEDIUM) ; \
0542 setPhotonReco(PHOTON_EFF_ ## DET ## _TIGHT, ELECTRON_SMEAR_ ## DET, IDClass::TIGHT) ; \
0543 setTauReco(TAU_EFF_ ## DET ## _LOOSE, TAU_SMEAR_ ## DET, IDClass::LOOSE) ; \
0544 setTauReco(TAU_EFF_ ## DET ## _MEDIUM, TAU_SMEAR_ ## DET, IDClass::MEDIUM) ; \
0545 setTauReco(TAU_EFF_ ## DET ## _TIGHT, TAU_SMEAR_ ## DET, IDClass::TIGHT) ; \
0546 setTrkReco(TRK_EFF_ ## DET, TRK_SMEAR_ ## DET) ; \
0547 for (const std::string& jname : jetnames()) \
0548 setJetReco(JET_SMEAR_ ## DET, JET_BTAG_ ## DET ## _ ## BTAG, jname) ; \
0549 setMETReco(MET_SMEARPARAMS_ ## DET, MET_SMEAR_ ## DET) ; \
0550 } while (0)