rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2019_I1746286

K-short and Lambda production in ttbar events at 7 TeV
Experiment: ATLAS (LHC)
Inspire ID: 1746286
Status: VALIDATED
Authors:
  • Sergio Calvente
  • Fernando Barreiro
  • Javier LLorente
References: Beams: p+ p+
Beam energies: (3500.0, 3500.0) GeV
Run details:
  • ttbar production at 7 TeV. No c*tau cut, or set c*tau > 100 mm stable so K0S and Lambda decay.

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}