Rivet analyses


title: ATLAS_2016_I1458270

0-lepton SUSY search with 3.2/fb of 13 TeV $pp$ data

Experiment: ATLAS (LHC)

Inspire ID: 1458270

Status: VALIDATED, UNOFFICIAL

Authors: - Andy Buckley - Louie Corpe

References: - Expt page: ATLAS-SUSY-2015-06 - Eur.Phys.J. C76 (2016) no.7, 392 - DOI:10.1140/epjc/s10052-016-4184-8 - arXiv: 1605.03814

Beams: p+ p+

Beam energies: (6500.0, 6500.0)GeV

Run details: - BSM signal events

ATLAS 0-lepton SUSY search using 3.2/fb of LHC $pp$ data at 13~TeV, recorded in 2015. The event selection is via signal regions requiring from 2-6 high-energy jets, and significant missing transverse energy. Detailed info: http://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/SUSY-2015-06/

Source code:ATLAS_2016_I1458270.cc

```c++ // -- C++ --

include "Rivet/Analysis.hh"

include "Rivet/Projections/FastJets.hh"

include "Rivet/Projections/FinalState.hh"

include "Rivet/Projections/PromptFinalState.hh"

include "Rivet/Projections/SmearedJets.hh"

include "Rivet/Projections/SmearedMET.hh"

include "Rivet/Projections/SmearedParticles.hh"

include "Rivet/Projections/Sphericity.hh"

include "Rivet/Tools/Cutflow.hh"

namespace Rivet {

/// @brief ATLAS 0-lepton SUSY search with 3.2/fb of 13 TeV pp data class ATLAS_2016_I1458270 : public Analysis { public:

/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2016_I1458270);


/// @name Analysis methods
/// @{

/// Book histograms and initialise projections before the run
void init() {

  // Initialise and register projections
  FinalState calofs(Cuts::abseta < 4.8);
  FastJets fj(calofs, JetAlg::ANTIKT, 0.4, JetMuons::DECAY);
  declare(fj, "TruthJets");
  declare(SmearedJets(fj, JET_SMEAR_ATLAS_RUN2, JET_BTAG_ATLAS_RUN2_MV2C20), "RecoJets");

  MissingMomentum mm(calofs);
  declare(mm, "TruthMET");
  declare(SmearedMET(mm, MET_SMEAR_ATLAS_RUN2), "RecoMET");

  PromptFinalState es(Cuts::abseta < 2.47 && Cuts::abspid == PID::ELECTRON, TauDecaysAs::PROMPT,
                      MuDecaysAs::PROMPT);
  declare(es, "TruthElectrons");
  declare(SmearedParticles(es, ELECTRON_RECOEFF_ATLAS_RUN2, ELECTRON_SMEAR_ATLAS_RUN2), "RecoElectrons");

  PromptFinalState mus(Cuts::abseta < 2.7 && Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
  declare(mus, "TruthMuons");
  declare(SmearedParticles(mus, MUON_EFF_ATLAS_RUN2_LOOSE, MUON_SMEAR_ATLAS_RUN2), "RecoMuons");


  // Book histograms/counters
  book(_h_2jl, "2jl");
  book(_h_2jm, "2jm");
  book(_h_2jt, "2jt");
  book(_h_4jt, "4jt");
  book(_h_5j, "5j");
  book(_h_6jm, "6jm");
  book(_h_6jt, "6jt");

  book(_hMeff_2jl, 4, 1, 1);
  book(_hMeff_2jm, 5, 1, 1);
  book(_hMeff_2jt, 6, 1, 1);
  book(_hMeff_4jt, 7, 1, 1);
  book(_hMeff_5j, 8, 1, 1);
  book(_hMeff_6jm, 9, 1, 1);
  book(_hMeff_6jt, 10, 1, 1);

  book(_h_temp_Meff_2jl, "_temp_Meff_2jl", refData(4, 1, 1));
  book(_h_temp_Meff_2jm, "_temp_Meff_2jm", refData(5, 1, 1));
  book(_h_temp_Meff_2jt, "_temp_Meff_2jt", refData(6, 1, 1));
  book(_h_temp_Meff_4jt, "_temp_Meff_4jt", refData(7, 1, 1));
  book(_h_temp_Meff_5j, "_temp_Meff_5j", refData(8, 1, 1));
  book(_h_temp_Meff_6jm, "_temp_Meff_6jm", refData(9, 1, 1));
  book(_h_temp_Meff_6jt, "_temp_Meff_6jt", refData(10, 1, 1));


  // Book cut-flows
  const vector<string> cuts2j = {"Pre-sel+MET+pT1", "Njet",       "Dphi_min(j,MET)", "pT2",
                                 "MET/sqrtHT",      "m_eff(incl)"};
  const vector<string> cutsXj = {"Pre-sel+MET+pT1", "Njet",          "Dphi_min(j,MET)", "pT2", "pT4",
                                 "Aplanarity",      "MET/m_eff(Nj)", "m_eff(incl)"};
  book(_flows, {"CF-2jl", "CF-2jm", "CF-2jt", "CF-4jt", "CF-5j", "CF-6jm", "CF-6jt"});
  for (auto& b : _flows->bins()) {
    if (b.index() < 4)
      book(b, b.xEdge(), cuts2j);
    else
      book(b, b.xEdge(), cutsXj);
  }
}

/// Perform the per-event analysis
void analyze(const Event& event) {

  _flows->groupfillinit();

  // Same MET cut for all signal regions
  //const Vector3 vmet = -apply<MissingMomentum>(event, "TruthMET").vectorEt();
  const Vector3 vmet = -apply<SmearedMET>(event, "RecoMET").vectorEt();
  const double met = vmet.mod();
  if (met < 200 * GeV) vetoEvent;

  // Get baseline electrons, muons, and jets
  Particles elecs = apply<ParticleFinder>(event, "RecoElectrons").particles(Cuts::pT > 10 * GeV);
  Particles muons = apply<ParticleFinder>(event, "RecoMuons").particles(Cuts::pT > 10 * GeV);
  Jets jets = apply<JetFinder>(event, "RecoJets")
                  .jetsByPt(Cuts::pT > 20 * GeV && Cuts::abseta < 2.8); ///< @todo Pile-up subtraction

  // Jet/electron/muons overlap removal and selection
  // Remove any |eta| < 2.8 jet within dR = 0.2 of a baseline electron
  for (const Particle& e : elecs) idiscard(jets, deltaRLess(e, 0.2, RAPIDITY));
  // Remove any electron or muon with dR < 0.4 of a remaining (Nch > 3) jet
  for (const Jet& j : jets) {
    /// @todo Add track efficiency random ing
    idiscard(elecs, deltaRLess(j, 0.4, RAPIDITY));
    if (j.particles(Cuts::abscharge > 0 && Cuts::pT > 500 * MeV).size() >= 3)
      idiscard(muons, deltaRLess(j, 0.4, RAPIDITY));
  }
  // Discard the softer of any electrons within dR < 0.05
  for (size_t i = 0; i < elecs.size(); ++i) {
    const Particle& e1 = elecs[i];
    /// @todo Would be nice to pass a "tail view" for the filtering, but awkward without range API / iterator guts
    idiscard(elecs, [&](const Particle& e2) { return e2.pT() < e1.pT() && deltaR(e1, e2) < 0.05; });
  }

  // Loose electron selection
  iselect(elecs, ParticleEffFilter(ELECTRON_EFF_ATLAS_RUN2_LOOSE));

  // Veto the event if there are any remaining baseline leptons
  if (!elecs.empty()) vetoEvent;
  if (!muons.empty()) vetoEvent;

  // Signal jets have pT > 50 GeV
  const Jets jets50 = select(jets, Cuts::pT > 50 * GeV);
  if (jets50.size() < 2) vetoEvent;
  vector<double> jetpts;
  transform(jets, jetpts, pT);
  vector<double> jetpts50;
  transform(jets50, jetpts50, pT);
  const double j1pt = jetpts50[0];
  const double j2pt = jetpts50[1];
  if (j1pt < 200 * GeV) vetoEvent;

  // Construct multi-jet observables
  const double ht = sum(jetpts, 0.0);
  const double met_sqrt_ht = met / sqrt(ht);
  const double meff_incl = sum(jetpts50, met);

  // Get dphis between MET and jets
  vector<double> dphimets50;
  transform(jets50, dphimets50, deltaPhiWRT(vmet));
  const double min_dphi_met_3 = min(head(dphimets50, 3));
  MSG_DEBUG(dphimets50 << ", " << min_dphi_met_3);

  // Jet aplanarity
  Sphericity sph;
  sph.calc(jets);
  const double aplanarity = sph.aplanarity();


  // Fill SR counters
  // 2-jet SRs
  if (_flows->fillnext("CF-2jl",
                       {true, true, min_dphi_met_3 > 0.8, j2pt > 200 * GeV, met_sqrt_ht > 15 * sqrt(GeV),
                        meff_incl > 1200 * GeV}))
    _h_2jl->fill();
  if (_flows->fillnext("CF-2jm",
                       {j1pt > 300 * GeV, true, min_dphi_met_3 > 0.4, j2pt > 50 * GeV,
                        met_sqrt_ht > 15 * sqrt(GeV), meff_incl > 1600 * GeV}))
    _h_2jm->fill();
  if (_flows->fillnext("CF-2jt",
                       {true, true, min_dphi_met_3 > 0.8, j2pt > 200 * GeV, met_sqrt_ht > 20 * sqrt(GeV),
                        meff_incl > 2000 * GeV}))
    _h_2jt->fill();

  // Fill SR Meff Histo1Ds
  // 2-jet SRs
  if ((min_dphi_met_3 > 0.8) && (j2pt > 200 * GeV) && (met_sqrt_ht > 15 * sqrt(GeV)))
    _h_temp_Meff_2jl->fill(meff_incl);
  if ((j1pt > 300 * GeV) && (min_dphi_met_3 > 0.4) && (j2pt > 50 * GeV) && (met_sqrt_ht > 15 * sqrt(GeV)))
    _h_temp_Meff_2jm->fill(meff_incl);
  if ((min_dphi_met_3 > 0.8) && (j2pt > 200 * GeV) && (met_sqrt_ht > 20 * sqrt(GeV)))
    _h_temp_Meff_2jt->fill(meff_incl);

  // Upper multiplicity SRs
  const double j4pt = jets50.size() > 3 ? jetpts50[3] : -1;
  const double j5pt = jets50.size() > 4 ? jetpts50[4] : -1;
  const double j6pt = jets50.size() > 5 ? jetpts50[5] : -1;
  const double meff_4 = jets50.size() > 3 ? sum(head(jetpts50, 4), met) : -1;
  const double meff_5 = jets50.size() > 4 ? meff_4 + jetpts50[4] : -1;
  const double meff_6 = jets50.size() > 5 ? meff_5 + jetpts50[5] : -1;
  const double met_meff_4 = met / meff_4;
  const double met_meff_5 = met / meff_5;
  const double met_meff_6 = met / meff_6;
  const double min_dphi_met_more = jets50.size() > 3 ? min(tail(dphimets50, -3)) : -1;


  if (_flows->fillnext("CF-4jt",
                       {true, jets50.size() >= 4, min_dphi_met_3 > 0.4 && min_dphi_met_more > 0.2,
                        jetpts[1] > 100 * GeV, j4pt > 100 * GeV, aplanarity > 0.04, met_meff_4 > 0.20,
                        meff_incl > 2200 * GeV}))
    _h_4jt->fill();
  if (_flows->fillnext("CF-5j",
                       {true, jets50.size() >= 5, min_dphi_met_3 > 0.4 && min_dphi_met_more > 0.2,
                        jetpts[1] > 100 * GeV, j4pt > 100 * GeV && j5pt > 50 * GeV, aplanarity > 0.04,
                        met_meff_5 > 0.25, meff_incl > 1600 * GeV}))
    _h_5j->fill();
  if (_flows->fillnext("CF-6jm",
                       {true, jets50.size() >= 6, min_dphi_met_3 > 0.4 && min_dphi_met_more > 0.2,
                        jetpts[1] > 100 * GeV, j4pt > 100 * GeV && j6pt > 50 * GeV, aplanarity > 0.04,
                        met_meff_6 > 0.25, meff_incl > 1600 * GeV}))
    _h_6jm->fill();
  if (_flows->fillnext("CF-6jt",
                       {true, jets50.size() >= 6, min_dphi_met_3 > 0.4 && min_dphi_met_more > 0.2,
                        jetpts[1] > 100 * GeV, j4pt > 100 * GeV && j6pt > 50 * GeV, aplanarity > 0.04,
                        met_meff_6 > 0.20, meff_incl > 2000 * GeV}))
    _h_6jt->fill();

  // Fill SR Meff Histo1Ds
  // Upper multiplicity SRs
  if (((jets50.size() >= 4) && (min_dphi_met_3 > 0.4) && (min_dphi_met_more > 0.2)
       && (jetpts[1] > 100 * GeV) && (j4pt > 100 * GeV) && (aplanarity > 0.04) && (met_meff_4 > 0.20)))
    _h_temp_Meff_4jt->fill(meff_incl);
  if (((jets50.size() >= 5) && (min_dphi_met_3 > 0.4) && (min_dphi_met_more > 0.2)
       && (jetpts[1] > 100 * GeV) && (j4pt > 100 * GeV) && (j5pt > 50 * GeV) && (aplanarity > 0.04)
       && (met_meff_5 > 0.25)))
    _h_temp_Meff_5j->fill(meff_incl);
  if (((jets50.size() >= 6) && (min_dphi_met_3 > 0.4) && (min_dphi_met_more > 0.2)
       && (jetpts[1] > 100 * GeV) && (j4pt > 100 * GeV) && (j6pt > 50 * GeV) && (aplanarity > 0.04)
       && (met_meff_6 > 0.25)))
    _h_temp_Meff_6jm->fill(meff_incl);
  if (((jets50.size() >= 6) && (min_dphi_met_3 > 0.4) && (min_dphi_met_more > 0.2)
       && (jetpts[1] > 100 * GeV) && (j4pt > 100 * GeV) && (j6pt > 50 * GeV) && (aplanarity > 0.04)
       && (met_meff_6 > 0.20)))
    _h_temp_Meff_6jt->fill(meff_incl);
}


/// Normalise histograms etc., after the run
void finalize() {

  const double sf = 3.2 * crossSection() / femtobarn / sumOfWeights();
  scale(_h_2jl, sf);
  scale(_h_2jm, sf);
  scale(_h_2jt, sf);
  scale(_h_4jt, sf);
  scale(_h_5j, sf);
  scale(_h_6jm, sf);
  scale(_h_6jt, sf);

  scale(_h_temp_Meff_2jl, sf);
  scale(_h_temp_Meff_2jm, sf);
  scale(_h_temp_Meff_2jt, sf);
  scale(_h_temp_Meff_4jt, sf);
  scale(_h_temp_Meff_5j, sf);
  scale(_h_temp_Meff_6jm, sf);
  scale(_h_temp_Meff_6jt, sf);


  // the HEPData entry corresponding to this does not divide their distributions
  // by bin width... so to avoid this we need to convert to Estimate1D which is not divided by bw
  barchart(_h_temp_Meff_2jl, _hMeff_2jl);
  barchart(_h_temp_Meff_2jm, _hMeff_2jm);
  barchart(_h_temp_Meff_2jt, _hMeff_2jt);
  barchart(_h_temp_Meff_4jt, _hMeff_4jt);
  barchart(_h_temp_Meff_5j, _hMeff_5j);
  barchart(_h_temp_Meff_6jm, _hMeff_6jm);
  barchart(_h_temp_Meff_6jt, _hMeff_6jt);
}

/// @}

private:

/// @name Histograms
/// @{
CounterPtr _h_2jl, _h_2jm, _h_2jt;
CounterPtr _h_4jt, _h_5j;
CounterPtr _h_6jm, _h_6jt;

Estimate1DPtr _hMeff_2jl, _hMeff_2jm, _hMeff_2jt;
Estimate1DPtr _hMeff_4jt, _hMeff_5j;
Estimate1DPtr _hMeff_6jm, _hMeff_6jt;

Histo1DPtr _h_temp_Meff_2jl, _h_temp_Meff_2jm, _h_temp_Meff_2jt;
Histo1DPtr _h_temp_Meff_4jt, _h_temp_Meff_5j;
Histo1DPtr _h_temp_Meff_6jm, _h_temp_Meff_6jt;
/// @}

/// Cut-flows
CutflowsPtr _flows;

};

RIVET_DECLARE_PLUGIN(ATLAS_2016_I1458270);

} ```