Rivet analyses referenceATLAS_2019_I1746286K-short and Lambda production in ttbar events at 7 TeVExperiment: ATLAS (LHC) Inspire ID: 1746286 Status: VALIDATED Authors:
Beam energies: (3500.0, 3500.0) GeV Run details:
Measurements of $K^0_S$ and $\Lambda^0$ production in $t\bar{t}$ final states have been performed. They are based on a data sample with integrated luminosity of 4.6 fb$^{-1}$ from proton-proton collisions at a centre-of-mass energy of 7 TeV, collected in 2011 with the ATLAS detector at the Large Hadron Collider. Neutral strange particles are separated into three classes, depending on whether they are contained in a jet, with or without a $b$-tag, or not associated with a selected jet. The aim is to look for differences in their main kinematic distributions. A comparison of data with several Monte Carlo simulations using different hadronisation and fragmentation schemes, colour reconnection models and different tunes for the underlying event has been made. The production of neutral strange particles in $t\bar{t}$ dileptonic events is found to be well described by current Monte Carlo models for $K^0_S$ ans $\Lambda^0$ production within jets, but not for those produced outside jets. Source code: ATLAS_2019_I1746286.cc 1// -*- C++ -*-
2#include "Rivet/Analysis.hh"
3#include "Rivet/Projections/FinalState.hh"
4#include "Rivet/Projections/UnstableParticles.hh"
5#include "Rivet/Projections/FastJets.hh"
6#include "Rivet/Projections/HeavyHadrons.hh"
7
8namespace Rivet {
9
10
11 class ATLAS_2019_I1746286 : public Analysis {
12 public:
13
14 /// Constructor
15 RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2019_I1746286);
16
17 /// Book histograms and initialise projections before the run
18 void init() {
19 // Set up projections
20 const FinalState fs(Cuts::abseta < 4.5);
21
22 /// Get electrons from truth record
23 FinalState elec_fs(Cuts::abspid == PID::ELECTRON && Cuts::abseta < 2.47 && Cuts::pT > 25*GeV);
24 declare(elec_fs, "ELEC_FS");
25
26 /// Get muons which pass the initial kinematic cuts:
27 FinalState muon_fs(Cuts::abspid == PID::MUON && Cuts::abseta < 2.5 && Cuts::pT > 20*GeV);
28 declare(muon_fs, "MUON_FS");
29
30 // get b-hadrons
31 declare(HeavyHadrons(Cuts::pT > 5*GeV), "BHadrons");
32
33 UnstableParticles k0_fs(Cuts::abspid == PID::K0S && Cuts::abseta < 2.5 && Cuts::E > 1*GeV);
34 declare(k0_fs, "K0_FS");
35
36 UnstableParticles lambda_fs(Cuts::abspid == PID::LAMBDA && Cuts::abseta < 2.5 && Cuts::E > 1*GeV);
37 declare(lambda_fs, "LAMBDA_FS");
38
39 // Final state used as input for jet-finding.
40 // We include everything except the muons and neutrinos
41 FastJets jets(fs, JetAlg::ANTIKT, 0.4, JetMuons::NONE, JetInvisibles::NONE);
42 declare(jets, "JETS");
43
44 // Book histograms
45 book(_h["b_k0_pt"], 1, 1, 1);
46 book(_h["b_k0_x"], 2, 1, 1);
47 book(_h["b_k0_e"], 3, 1, 1);
48 book(_h["b_k0_eta"], 4, 1, 1);
49 book(_d["b_k0_n"], 5, 1, 1);
50
51 book(_h["j_k0_pt"], 6, 1, 1);
52 book(_h["j_k0_x"], 7, 1, 1);
53 book(_h["j_k0_e"], 8, 1, 1);
54 book(_h["j_k0_eta"], 9, 1, 1);
55 book(_d["j_k0_n"], 10, 1, 1);
56
57 book(_h["out_k0_pt"], 11, 1, 1);
58 book(_h["out_k0_e"], 12, 1, 1);
59 book(_h["out_k0_eta"], 13, 1, 1);
60 book(_s["out_k0_n"], 14, 1, 1);
61
62 book(_h["all_k0_pt"], 15, 1, 1);
63 book(_h["all_k0_e"], 16, 1, 1);
64 book(_h["all_k0_eta"], 17, 1, 1);
65 book(_s["all_k0_n"], 18, 1, 1);
66
67 book(_h["all_l_pt"], 19, 1, 1);
68 book(_h["all_l_e"], 20, 1, 1);
69 book(_h["all_l_eta"], 21, 1, 1);
70
71 }
72
73
74 /// Perform the per-event analysis
75 void analyze(const Event& event) {
76
77 /// Get the various sets of final state particles
78 const Particles& elecFS = apply<FinalState>(event, "ELEC_FS").particlesByPt();
79 const Particles& muonFS = apply<FinalState>(event, "MUON_FS").particlesByPt();
80 const Particles& k0FS = apply<UnstableParticles>(event, "K0_FS").particlesByPt();
81 const Particles& lambdaFS = apply<UnstableParticles>(event, "LAMBDA_FS").particlesByPt();
82
83 // Get all jets with pT > 7 GeV (ATLAS standard jet collection)
84 Jets jets = apply<FastJets>(event, "JETS").jetsByPt(Cuts::pT > 7*GeV);
85
86 // Keep any jets that pass the pt cut
87 Jets good_jets = select(jets, Cuts::pT > 25*GeV && Cuts::abseta < 2.5);
88
89 // Remove jets too close to an electron
90 idiscardIfAnyDeltaRLess(good_jets, elecFS, 0.2);
91
92 // Classify the event type
93 const size_t nElec = elecFS.size();
94 const size_t nMuon = muonFS.size();
95 bool isDilepton = false;
96 if (nElec == 2 && nMuon == 0) {
97 if (charge(elecFS[0]) != charge(elecFS[1])) isDilepton = true;
98 } else if (nElec == 1 && nMuon == 1) {
99 if (charge(elecFS[0]) != charge(muonFS[0])) isDilepton = true;
100 } else if (nElec == 0 && nMuon == 2) {
101 if (charge(muonFS[0]) != charge(muonFS[1])) isDilepton = true;
102 }
103 const bool isGoodEvent = (isDilepton && good_jets.size() >= 2);
104 if (!isGoodEvent) vetoEvent;
105
106 // Select b-hadrons
107 const Particles& bHadrons = apply<HeavyHadrons>(event, "BHadrons").bHadrons();
108
109 // Select b-jets as those containing a b-hadron
110 Jets bjets = discardIfAnyDeltaRLess(good_jets, bHadrons, 0.3);
111
112 size_t n_k0_all_visible = 0;
113 size_t n_k0_out_visible = 0;
114 size_t n_k0_b_visible = 0;
115 size_t n_k0_j_visible = 0;
116
117 bool isVisible = false;
118 // Loop over all K0s particles
119 for (const Particle& k : k0FS) {
120 if (k.hasStableDescendantWith(Cuts::pid == PID::PIPLUS)) isVisible = true;
121
122 if (isVisible) n_k0_all_visible += 1;
123 _h["all_k0_pt"]->fill(k.pT()/GeV);
124 _h["all_k0_eta"]->fill(k.abseta());
125 _h["all_k0_e"]->fill(k.E()/GeV);
126
127 bool isJetAssoc = false, isBjet = false;
128 double minDeltaR = 1000., jetAssocE = 0.;
129
130 for (const Jet& j : good_jets) {
131 const double k0_jetdR = deltaR(j, k);
132 if (k0_jetdR < 0.4 && k0_jetdR < minDeltaR) {
133 isJetAssoc = true;
134 minDeltaR = k0_jetdR;
135 jetAssocE = j.E();
136 isBjet = any(bHadrons, DeltaRLess(j, 0.3));
137 }
138 }
139
140 // K0s not associated to jets
141 if (!isJetAssoc){
142 if(isVisible) n_k0_out_visible += 1;
143 _h["out_k0_pt"]->fill(k.pT()/GeV);
144 _h["out_k0_eta"]->fill(k.abseta());
145 _h["out_k0_e"]->fill(k.E()/GeV);
146 }
147
148 //K0s associated to b-jets
149 if (isJetAssoc && isBjet){
150 if (isVisible) n_k0_b_visible += 1;
151 _h["b_k0_pt"]->fill(k.pT()/GeV);
152 _h["b_k0_eta"]->fill(k.abseta());
153 _h["b_k0_e"]->fill(k.E()/GeV);
154 _h["b_k0_x"]->fill(k.E()/jetAssocE);
155 }
156
157 //K0s associated to non b-jets
158 if(isJetAssoc && !isBjet){
159 if(isVisible) n_k0_j_visible += 1;
160 _h["j_k0_pt"]->fill(k.pT()/GeV);
161 _h["j_k0_eta"]->fill(k.abseta());
162 _h["j_k0_e"]->fill(k.E()/GeV);
163 _h["j_k0_x"]->fill(k.E()/jetAssocE);
164 }
165 }
166
167
168 // K0s multiplicities
169 _s["all_k0_n"]->fill(allEdge(n_k0_all_visible));
170 _s["out_k0_n"]->fill(outEdge(n_k0_out_visible));
171 _d["b_k0_n"]->fill(n_k0_b_visible);
172 _d["j_k0_n"]->fill(n_k0_j_visible);
173
174
175 // Loop over all Lambda particles
176 //size_t n_lambda_all = 0;
177 for (const Particle& l : lambdaFS) {
178 //n_lambda_all += 1;
179 _h["all_l_pt"]->fill(l.pT()/GeV);
180 _h["all_l_eta"]->fill(l.abseta());
181 _h["all_l_e"]->fill(l.E()/GeV);
182 }
183 }
184
185 const string outEdge(const size_t n) {
186 if (outEdges.empty()) outEdges = _s["out_k0_n"]->xEdges();
187 if (n > 9) return ""; // otherflow
188 return outEdges[(n == 9)? 8 : n];
189 }
190
191 const string allEdge(const size_t n) {
192 if (allEdges.empty()) allEdges = _s["all_k0_n"]->xEdges();
193 if (n > 11) return ""; // otherflow
194 return allEdges[(n == 10 || n == 11)? 9 : n];
195 }
196
197 // Histogram normalization to the number of events passing the cuts
198 void finalize() {
199 const double sf = 1.0 / _s["all_k0_n"]->sumW();
200 scale(_h, sf);
201 scale(_d, sf);
202 scale(_s, sf);
203 }
204
205 private:
206
207 // Counters
208 map<string, Histo1DPtr> _h;
209 map<string, BinnedHistoPtr<int>> _d;
210 map<string, BinnedHistoPtr<string>> _s;
211 vector<string> outEdges, allEdges;
212
213 };
214
215 RIVET_DECLARE_PLUGIN(ATLAS_2019_I1746286);
216}
|