rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

CMS_2018_I1620050

Measurement of normalized differential ttbar cross sections in the dilepton channel from pp collisions at 13 TeV
Experiment: CMS (LHC)
Inspire ID: 1620050
Status: VALIDATED
Authors:
  • Youn Jung Roh
  • Suyong Choi
  • Junghwan Goh
  • Dajeong Jeon
  • Jason S. H. Lee
References:
  • JHEP 1804 (2018) 060
  • DOI:10.1007/JHEP04(2018)060
  • arXiv: 1708.07638
  • https://www.hepdata.net/record/81686
  • Public page: CMS-TOP-16-007
Beams: p+ p+
Beam energies: (6500.0, 6500.0) GeV
Run details:
  • pp QCD interactions at $\sqrt{s} = 13$ TeV. Data collected by CMS during the year 2015. Selection of dilepton top pair candidate events at particle level.

Abstract: Normalized differential cross sections for top quark pair production are measured in the dilepton ($e^{+}e^{-}$, $\mu^{+}\mu^{-}$, and $\mu^{\mp}e^{\pm}$) decay channels in proton-proton collisions at a center-of-mass energy of 13TeV. The measurements are performed with data corresponding to an integrated luminosity of 2.1$fb^{-1}$ using the CMS detector at the LHC. The cross sections are measured differentially as a function of the kinematic properties of the leptons, jets from bottom quark hadronization, top quarks, and top quark pairs at the particle and parton levels. The results are compared to several Monte Carlo generators that implement calculations up to next-to-leading order in perturbative quantum chromodynamics interfaced with parton showering, and also to fixed-order theoretical calculations of top quark pair production up to next-to-next-to-leading order. Rivet: This analysis is to be run on $\text{t}\bar{\text{t}}$ Monte Carlo. The particle-level phase space is defined using the following definitions: \begin{description} \item[lepton]: an electron or muon with $p_\text{T}>30\,\text{GeV}$ and $|\eta|<2.4$, dressed within a cone of radius 0.1, \item[jet]: a jet is reconstructed with the anti-$k_t$ algorithm with a radius of 0.4, after removing the neutrinos and dressed leptons, with $p_\text{T]>30\,\text{GeV}$ and $|\eta|<2.4$, \item[b-jet]: a jet that contains a B-hadron. \end{description} A W boson at the particle level is defined by combining a dressed lepton and a neutrino. In each event, a pair of particle-level W bosons is chosen among the possible combinations such that the sum of the absolute values of the invariant mass differences with respect to the W boson mass is minimal. Similarly, a top quark at the particle level is defined by combining a particle-level W boson and a b jet. The combination of a W boson and a b jet with the minimum invariant mass difference from the correct top quark mass is selected.

Source code: CMS_2018_I1620050.cc
  1#include "Rivet/Analysis.hh"
  2#include "Rivet/Projections/FinalState.hh"
  3#include "Rivet/Projections/FastJets.hh"
  4#include "Rivet/Projections/PartonicTops.hh"
  5#include "Rivet/Projections/LeptonFinder.hh"
  6#include "Rivet/Projections/IdentifiedFinalState.hh"
  7#include "Rivet/Projections/PromptFinalState.hh"
  8#include "Rivet/Projections/VetoedFinalState.hh"
  9
 10namespace Rivet {
 11
 12
 13  /// Normalized dilepton ttbar differential cross-sections in pp collisions at 13 TeV
 14  class CMS_2018_I1620050 : public Analysis {
 15  public:
 16
 17    RIVET_DEFAULT_ANALYSIS_CTOR(CMS_2018_I1620050);
 18
 19    void init() {
 20
 21      // Parton level top quark to analyze dilepton channels only
 22      declare(PartonicTops(TopDecay::MUON, PromptEMuFromTau::NO), "PartonTopsToMuon"); // Partonic top decaying to mu
 23      declare(PartonicTops(TopDecay::ELECTRON, PromptEMuFromTau::NO), "PartonTopsToElectron"); // Partonic top decaying to e
 24
 25      // Build particle level tops starting from FinalState
 26      const FinalState fs(Cuts::pT > 0. && Cuts::abseta < 6.);
 27
 28      // Neutrinos
 29      IdentifiedFinalState neutrinos(fs);
 30      neutrinos.acceptNeutrinos();
 31      PromptFinalState prompt_neutrinos(neutrinos, TauDecaysAs::PROMPT, MuDecaysAs::PROMPT);
 32      declare(prompt_neutrinos, "Neutrinos");
 33
 34      // Projection for electrons and muons
 35      Cut leptonCuts = Cuts::pt > 20*GeV && Cuts::abseta < 2.4;
 36
 37      PromptFinalState fsLepton(fs);
 38      fsLepton.acceptMuonDecays(true);
 39      fsLepton.acceptTauDecays(true);
 40      SpecialLeptonFinder dressedLeptons(fsLepton, leptonCuts);
 41      declare(dressedLeptons, "LeptonFinder");
 42
 43      // Projection for jets
 44      VetoedFinalState fs_jets(fs);
 45      fs_jets.addVetoOnThisFinalState(dressedLeptons);
 46      fs_jets.vetoNeutrinos();
 47      declare(FastJets(fs_jets, JetAlg::ANTIKT, 0.4), "ak4jets");
 48
 49      // Book hists
 50      book(_hist_lep_pt, "d01-x01-y01");
 51      book(_hist_jet_pt, "d02-x01-y01");
 52      book(_hist_top_pt, "d03-x01-y01");
 53      book(_hist_top_y, "d04-x01-y01");
 54      book(_hist_tt_pt, "d05-x01-y01");
 55      book(_hist_tt_y, "d06-x01-y01");
 56      book(_hist_tt_m, "d07-x01-y01");
 57      book(_hist_tt_dphi, "d08-x01-y01");
 58    }
 59
 60
 61    void analyze(const Event& event) {
 62
 63      // Do the analysis only for the full-dleptonic channel
 64      const Particles partonTopsToMuon     = apply<ParticleFinder>(event, "PartonTopsToMuon").particles();
 65      //const Particles partonTopsToElectron = apply<ParticleFinder>(event, "PartonTopsToElectron").particles();
 66      Particles partonTopsToElectron;
 67      for (const Particle& x : apply<ParticleFinder>(event, "PartonTopsToElectron").particles() ) {
 68        bool isDuplicated = false;
 69        for (const Particle& y : partonTopsToMuon ) {
 70          if ( std::abs(x.pt()-y.pt()) < 0.01 and deltaR(x, y) < 0.01 ) {
 71            isDuplicated = true;
 72            break;
 73          }
 74        }
 75        if ( !isDuplicated ) partonTopsToElectron.push_back(x);
 76      }
 77      const int nPartonElectrons = partonTopsToElectron.size();
 78      const int nPartonMuons     = partonTopsToMuon.size();
 79      if ( nPartonElectrons+nPartonMuons != 2 ) vetoEvent;
 80
 81      // Select leptons
 82      const DressedLeptons& dressedLeptons = apply<SpecialLeptonFinder>(event, "LeptonFinder").dressedLeptons();
 83      if ( dressedLeptons.size() < 2 ) vetoEvent;
 84
 85      const FourMomentum& lepton1 = dressedLeptons[0].momentum();
 86      const FourMomentum& lepton2 = dressedLeptons[1].momentum();
 87      const int channel = dressedLeptons[0].abspid() + dressedLeptons[1].abspid();
 88      if ( !((channel == 22 and nPartonElectrons == 2) or
 89             (channel == 24 and nPartonElectrons == 1 and nPartonMuons == 1) or
 90             (channel == 26 and nPartonMuons == 2)) ) vetoEvent;
 91
 92      // Select neutrinos
 93      const Particles neutrinos = apply<PromptFinalState>(event, "Neutrinos").particlesByPt();
 94      if ( neutrinos.size() < 2 ) vetoEvent;
 95
 96      // Select bjets
 97      const FastJets& fjJets = apply<FastJets>(event, "ak4jets");
 98      const Jets jets = fjJets.jetsByPt(Cuts::abseta < 2.4 && Cuts::pT > 30*GeV);
 99      const Jets bJets = select(jets, hasBTag());
100      // There should at least two b jets.
101      if ( bJets.size() < 2 ) vetoEvent;
102
103      // Construct particle level top
104      FourMomentum nu1 = neutrinos[0].momentum();
105      FourMomentum nu2 = neutrinos[1].momentum();
106      if ( std::abs((lepton1+nu1).mass()-80.4) + std::abs((lepton2+nu2).mass()-80.4) >
107           std::abs((lepton1+nu2).mass()-80.4) + std::abs((lepton2+nu1).mass()-80.4) ) {
108        std::swap(nu1, nu2);
109      }
110      const FourMomentum w1 = lepton1 + nu1;
111      const FourMomentum w2 = lepton2 + nu2;
112
113      FourMomentum bjet1 = bJets[0].momentum();
114      FourMomentum bjet2 = bJets[1].momentum();
115      if ( std::abs((w1+bjet1).mass()-172.5) + std::abs((w2+bjet2).mass()-172.5) >
116           std::abs((w1+bjet2).mass()-172.5) + std::abs((w2+bjet1).mass()-172.5) ) {
117        std::swap(bjet1, bjet2);
118      }
119      const FourMomentum t1 = w1 + bjet1;
120      const FourMomentum t2 = w2 + bjet2;
121      const FourMomentum tt = t1+t2;
122
123      _hist_lep_pt->fill(lepton1.pt());
124      _hist_lep_pt->fill(lepton2.pt());
125      _hist_jet_pt->fill(bjet1.pt());
126      _hist_jet_pt->fill(bjet2.pt());
127
128      _hist_top_pt->fill(t1.pt());
129      _hist_top_pt->fill(t2.pt());
130      _hist_top_y->fill(t1.rapidity());
131      _hist_top_y->fill(t2.rapidity());
132
133      _hist_tt_pt->fill(tt.pt());
134      _hist_tt_y->fill(tt.rapidity());
135      _hist_tt_m->fill(tt.mass());
136      _hist_tt_dphi->fill(deltaPhi(t1.phi(), t2.phi()));
137    }
138
139
140    /// Normalise histograms etc., after the run
141    void finalize() {
142      normalize(_hist_lep_pt);
143      normalize(_hist_jet_pt);
144      normalize(_hist_top_pt);
145      normalize(_hist_top_y);
146      normalize(_hist_tt_pt);
147      normalize(_hist_tt_y);
148      normalize(_hist_tt_m);
149      normalize(_hist_tt_dphi);
150    }
151
152
153    /// @brief Special dressed-lepton finder
154    ///
155    /// Find dressed leptons by clustering all leptons and photons
156    class SpecialLeptonFinder : public FinalState {
157    public:
158
159      /// The default constructor. May specify cuts
160      SpecialLeptonFinder(const FinalState& fs, const Cut& cut)
161        : FinalState(cut)
162      {
163        setName("SpecialLeptonFinder");
164        IdentifiedFinalState ifs(fs);
165        ifs.acceptIdPair(PID::PHOTON);
166        ifs.acceptIdPair(PID::ELECTRON);
167        ifs.acceptIdPair(PID::MUON);
168        declare(ifs, "IFS");
169        declare(FastJets(ifs, JetAlg::ANTIKT, 0.1), "LeptonJets");
170      }
171
172      /// Clone on the heap.
173      virtual unique_ptr<Projection> clone() const {
174        return unique_ptr<Projection>(new SpecialLeptonFinder(*this));
175      }
176
177      /// Import to avoid warnings about overload-hiding
178      using Projection::operator =;
179
180      /// Retrieve the dressed leptons
181      const DressedLeptons& dressedLeptons() const { return _clusteredLeptons; }
182
183      /// Perform the calculation
184      void project(const Event& e) {
185        _theParticles.clear();
186        _clusteredLeptons.clear();
187
188        DressedLeptons allClusteredLeptons;
189        const Jets jets = apply<FastJets>(e, "LeptonJets").jetsByPt(Cuts::pT > 5*GeV);
190        for (const Jet& jet : jets) {
191          Particle lepCand;
192          for (const Particle& cand : jet.particles()) {
193            const int absPdgId = cand.abspid();
194            if (absPdgId == PID::ELECTRON || absPdgId == PID::MUON) {
195              if (cand.pt() > lepCand.pt()) lepCand = cand;
196            }
197          }
198
199          if (!lepCand.isChargedLepton()) continue;
200
201          DressedLepton lepton = DressedLepton(lepCand);
202          for (const Particle& cand : jet.particles()) {
203            if (isSame(cand, lepCand)) continue;
204            lepton.addConstituent(cand, true);
205          }
206          allClusteredLeptons.push_back(lepton);
207        }
208
209        for (const DressedLepton& lepton : allClusteredLeptons) {
210          if (accept(lepton)) {
211            _clusteredLeptons.push_back(lepton);
212            _theParticles.push_back(lepton.bareLepton());
213            _theParticles += lepton.photons();
214          }
215        }
216      }
217    private:
218
219      /// Container which stores the clustered lepton objects
220      DressedLeptons _clusteredLeptons;
221
222    };
223
224  private:
225
226    Histo1DPtr _hist_lep_pt;
227    Histo1DPtr _hist_jet_pt;
228    Histo1DPtr _hist_top_pt;
229    Histo1DPtr _hist_top_y;
230    Histo1DPtr _hist_tt_pt;
231    Histo1DPtr _hist_tt_y;
232    Histo1DPtr _hist_tt_m;
233    Histo1DPtr _hist_tt_dphi;
234
235  };
236
237
238  RIVET_DECLARE_PLUGIN(CMS_2018_I1620050);
239
240}