rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2016_CONF_2016_037

Search for SUSY in 13 \text{TeV} events with 2 or 3 leptons and multiple jets
Experiment: ATLAS (LHC)
Status: UNVALIDATED
Authors:
  • Andy Buckley
No references listed
Beams: p+ p+
Beam energies: (6500.0, 6500.0) GeV
Run details:
  • BSM signal events

A search for strongly produced supersymmetric particles using signatures involving multiple energetic jets and either two isolated same-sign leptons ($e$ or $\mu$) or at least three isolated leptons. The analysis also utilises other observables, such as $b$-tagged jets or missing transverse momentum, to extend its sensitivity. A data sample of proton--proton collisions at $\sqrt{s} = 13 \text{TeV}$ recorded with the ATLAS detector at the Large Hadron Collider in 2015 and 2016, corresponding to a total integrated luminosity of 13.2/fb, is used for the search. No significant excess over the Standard Model expectation is observed.

Source code: ATLAS_2016_CONF_2016_037.cc
  1// -*- C++ -*-
  2#include "Rivet/Analysis.hh"
  3#include "Rivet/Projections/FinalState.hh"
  4#include "Rivet/Projections/PromptFinalState.hh"
  5#include "Rivet/Projections/FastJets.hh"
  6#include "Rivet/Projections/Sphericity.hh"
  7#include "Rivet/Projections/SmearedParticles.hh"
  8#include "Rivet/Projections/SmearedJets.hh"
  9#include "Rivet/Projections/SmearedMET.hh"
 10#include "Rivet/Tools/Cutflow.hh"
 11
 12namespace Rivet {
 13
 14
 15  /// @brief ATLAS 2016 2 -SS-lepton / 3-lepton SUSY search, from 13.2/fb CONF note
 16  class ATLAS_2016_CONF_2016_037 : public Analysis {
 17  public:
 18
 19    /// Constructor
 20    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2016_CONF_2016_037);
 21
 22
 23    /// @name Analysis methods
 24    //@{
 25
 26    /// Book histograms and initialise projections before the run
 27    void init() {
 28
 29      // Initialise and register projections
 30      FinalState calofs(Cuts::abseta < 4.9);
 31      declare(calofs, "Clusters");
 32      FastJets fj(calofs, FastJets::ANTIKT, 0.4);
 33      declare(fj, "TruthJets");
 34      declare(SmearedJets(fj, JET_SMEAR_ATLAS_RUN2, [](const Jet& j) {
 35            if (j.abseta() > 2.5) return 0.;
 36            return j.bTagged(Cuts::pT > 5*GeV) ? 0.70 :
 37              j.cTagged(Cuts::pT > 5*GeV) ? 1/12. :
 38              j.tauTagged(Cuts::pT > 5*GeV) ? 1/54. : 1/380.; }), "Jets");
 39
 40      MissingMomentum mm(calofs);
 41      declare(mm, "TruthMET");
 42      declare(SmearedMET(mm, MET_SMEAR_ATLAS_RUN2), "MET");
 43
 44      FinalState es(Cuts::abspid == PID::ELECTRON && Cuts::abseta < 2.47 && !Cuts::absetaIn(1.37, 1.52) && Cuts::pT > 10*GeV);
 45      declare(es, "TruthElectrons");
 46      declare(SmearedParticles(es, ELECTRON_RECOEFF_ATLAS_RUN2, ELECTRON_SMEAR_ATLAS_RUN2), "Electrons");
 47
 48      FinalState mus(Cuts::abspid == PID::MUON && Cuts::abseta < 2.5 && Cuts::pT > 10*GeV);
 49      declare(mus, "TruthMuons");
 50      declare(SmearedParticles(mus, MUON_EFF_ATLAS_RUN2, MUON_SMEAR_ATLAS_RUN2), "Muons");
 51
 52      FinalState cfs(Cuts::abseta < 2.5 && Cuts::abscharge > 0);
 53      declare(cfs, "TruthTracks");
 54      declare(SmearedParticles(cfs, TRK_EFF_ATLAS_RUN2), "Tracks");
 55
 56
 57      // Book histograms/counters
 58      book(_h_3l1,"SR3l1");
 59      book(_h_3l2,"SR3l2");
 60      book(_h_0b1,"SR0b1");
 61      book(_h_0b2,"SR0b2");
 62      book(_h_1b,"SR1b");
 63      book(_h_3b,"SR3b");
 64      book(_h_1bDD,"SR1bDD");
 65      book(_h_3bDD,"SR3bDD");
 66      book(_h_1bGG,"SR1bGG");
 67
 68    }
 69
 70
 71    /// Perform the per-event analysis
 72    void analyze(const Event& event) {
 73
 74      // Get baseline electrons, muons, and jets
 75      Particles elecs = apply<ParticleFinder>(event, "Electrons").particlesByPt();
 76      Particles muons = apply<ParticleFinder>(event, "Muons").particlesByPt();
 77      Jets jets = apply<JetAlg>(event, "Jets").jetsByPt(Cuts::pT > 20*GeV && Cuts::abseta < 2.8);
 78      const Jets bjets = filter_select(jets, [&](const Jet& j) { return j.bTagged(Cuts::pT > 5*GeV); });
 79
 80
 81      // Jet/electron/muon overlap removal and selection
 82      // Remove any electron or muon within dR = 0.2 of a b-tagged jet
 83      for (const Jet& bj : bjets) {
 84        ifilter_discard(elecs, deltaRLess(bj, 0.2, RAPIDITY));
 85        ifilter_discard(muons, deltaRLess(bj, 0.2, RAPIDITY));
 86      }
 87      // Remove any untagged jet within dR = 0.2 of an electron or muon
 88      for (const Particle& e : elecs)
 89        ifilter_discard(jets, deltaRLess(e, 0.2, RAPIDITY));
 90      for (const Particle& m : muons)
 91        ifilter_discard(jets, deltaRLess(m, 0.2, RAPIDITY));
 92      // Remove any untagged low-multiplicity/muon-dominated jet within dR = 0.4 of a muon
 93      for (const Particle& m : muons)
 94        ifilter_discard(jets, [&](const Jet& j) {
 95            if (deltaR(m, j, RAPIDITY) > 0.4) return false;
 96            const Particles trks = j.particles(Cuts::abscharge != 0);
 97            if (trks.size() < 3) return true;
 98            return m.pT()/j.pT() > 0.5 && m.pT()/sum(trks, pT, 0.0) > 0.7;
 99          });
100      // Remove any electron or muon near a remaining jet, with a shrinking cone
101      const auto lcone_iso_fn = [&](const Particle& l) {
102        const double dr = min(0.4, 0.04 + 10*GeV/l.pT());
103        return any(jets, deltaRLess(l, dr, RAPIDITY));
104      };
105      ifilter_discard(elecs, lcone_iso_fn);
106      ifilter_discard(muons, lcone_iso_fn);
107      // Track-sharing e,mu also filtered, but that decision can't be made here
108      const Jets& sigjets = jets;
109      const Jets& sigbjets = bjets;
110
111
112      // Lepton isolation
113      Particles sigelecs = filter_select(elecs, Cuts::abseta < 2);
114      Particles sigmuons = muons;
115      ifilter_select(sigelecs, ParticleEffFilter(ELECTRON_EFF_ATLAS_RUN2_MEDIUM));
116      const Particles trks = apply<ParticleFinder>(event, "Tracks").particles();
117      const Particles clus = apply<ParticleFinder>(event, "Clusters").particles();
118      ifilter_discard(sigelecs, [&](const Particle& e) {
119          const double R = min(0.2, 10*GeV/e.pT());
120          double ptsum = -e.pT(), etsum = -e.Et();
121          for (const Particle& t : trks)
122            if (deltaR(t,e) < R) ptsum += t.pT();
123          for (const Particle& c : clus)
124            if (deltaR(c,e) < 0.2) etsum += c.pT(); ///< @todo Bit vague about "energy"
125          return ptsum / e.pT() > 0.06 || etsum / e.pT() > 0.06;
126        });
127      ifilter_discard(sigmuons, [&](const Particle& m) {
128          const double R = min(0.3, 10*GeV/m.pT());
129          double ptsum = -m.pT();
130          for (const Particle& t : trks)
131            if (deltaR(t,m) < R) ptsum += t.pT();
132          return ptsum / m.pT() > 0.06;
133        });
134      /// @todo Note is vague about whether "signal lepton" defn includes pT > 20?
135      ifilter_discard(sigelecs, Cuts::pT > 20*GeV);
136      ifilter_discard(sigmuons, Cuts::pT > 20*GeV);
137
138
139      // MET calculation (NB. done generically, with smearing, rather than via explicit physics objects)
140      const Vector3 vmet = -apply<SmearedMET>(event, "MET").vectorEt();
141      const double etmiss = vmet.mod();
142
143
144      //////////////////
145
146
147      // Event selection cuts
148      const Particles sigleptons = sigelecs + sigmuons;
149      if (sigleptons.size() < 2) vetoEvent;
150      if (sigleptons.size() == 2 && sigleptons[0].charge() != sigleptons[1].charge()) vetoEvent;
151
152      // Jet sub-selections and meff calculation
153      const Jets sigjets25 = filter_select(sigjets, Cuts::pT > 25*GeV);
154      const Jets sigjets40 = filter_select(sigjets25, Cuts::pT > 40*GeV);
155      const Jets sigjets50 = filter_select(sigjets40, Cuts::pT > 50*GeV);
156      /// @todo Is meff specific to the jet pT cut?
157      const double meff = sum(sigjets, pT, 0.0) + sum(sigleptons, pT, 0.0);
158
159      // Fill counters
160      if (sigleptons.size() >= 3 && sigbjets.empty() && sigjets40.size() >= 4 && etmiss > 150*GeV) _h_3l1->fill();
161      if (sigleptons.size() >= 3 && sigbjets.empty() && sigjets40.size() >= 4 && etmiss > 200*GeV && meff > 1500*GeV) _h_3l2->fill();
162      if (sigleptons.size() >= 2 && sigbjets.empty() && sigjets25.size() >= 6 && etmiss > 150*GeV && meff > 500*GeV) _h_0b1->fill();
163      if (sigleptons.size() >= 2 && sigbjets.empty() && sigjets40.size() >= 6 && etmiss > 150*GeV && meff > 900*GeV) _h_0b2->fill();
164      if (sigleptons.size() >= 2 && sigbjets.size() >= 1 && sigjets25.size() >= 6 && etmiss > 200*GeV && meff > 650*GeV) _h_1b->fill();
165      if (sigleptons.size() >= 2 && sigbjets.size() >= 3 && sigjets25.size() >= 6 && etmiss > 150*GeV && meff > 600*GeV) _h_3b->fill();
166      if (filter_select(sigleptons, Cuts::charge < 0).size() >= 2) {
167        if (sigleptons.size() >= 2 && sigbjets.size() >= 1 && sigjets50.size() >= 6 && meff > 1200*GeV) _h_1bDD->fill();
168        if (sigleptons.size() >= 2 && sigbjets.size() >= 3 && sigjets50.size() >= 6 && meff > 1000*GeV) _h_3bDD->fill();
169        if (sigleptons.size() >= 2 && sigbjets.size() >= 1 && sigjets50.size() >= 6 && meff > 1800*GeV) _h_1bGG->fill();
170      }
171
172    }
173
174
175    /// Normalise counters after the run
176    void finalize() {
177
178      const double sf = 13.2*crossSection()/femtobarn/sumOfWeights();
179      scale(_h_3l1, sf); scale(_h_3l2, sf); scale(_h_0b1, sf);
180      scale(_h_0b2, sf); scale(_h_1b, sf); scale(_h_3b, sf);
181      scale(_h_1bDD, sf); scale(_h_3bDD, sf); scale(_h_1bGG, sf);
182
183    }
184
185    //@}
186
187
188  private:
189
190    /// @name Histograms
191    //@{
192    CounterPtr _h_3l1, _h_3l2, _h_0b1, _h_0b2, _h_1b, _h_3b, _h_1bDD, _h_3bDD, _h_1bGG;
193    //@}
194
195
196  };
197
198
199
200  // The hook for the plugin system
201  RIVET_DECLARE_PLUGIN(ATLAS_2016_CONF_2016_037);
202
203
204}