rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2012_I1204447

Inclusive multi-lepton search
Experiment: ATLAS (LHC)
Inspire ID: 1204447
Status: VALIDATED
Authors:
  • Joern Mahlstedt
References: Beams: p+ p+
Beam energies: (3500.0, 3500.0) GeV
Run details:
  • Any process producing at least 3 leptons (e.g. pair production of doubly-charged Higgs)

A generic search for anomalous production of events with at least three charged leptons is presented. The search uses a pp-collision data sample at a center-of-mass energy of $\sqrt{s}$ = 7 TeV corresponding to 4.6/fb of integrated luminosity collected in 2011 by the ATLAS detector at the CERN Large Hadron Collider. Events are required to contain at least two electrons or muons, while the third lepton may either be an additional electron or muon, or a hadronically decaying tau lepton. Events are categorized by the presence or absence of a reconstructed tau-lepton or Z-boson candidate decaying to leptons. No significant excess above backgrounds expected from Standard Model processes is observed. Results are presented as upper limits on event yields from non-Standard-Model processes producing at least three prompt, isolated leptons, given as functions of lower bounds on several kinematic variables. Fiducial efficiencies for model testing are also provided. This Rivet module implements the event selection and the fiducial efficiencies to test various models for their exclusion based on observed/excluded limits.

Source code: ATLAS_2012_I1204447.cc
   1// -*- C++ -*-
   2#include "Rivet/Analysis.hh"
   3#include "Rivet/Projections/FinalState.hh"
   4#include "Rivet/Projections/ChargedFinalState.hh"
   5#include "Rivet/Projections/VisibleFinalState.hh"
   6#include "Rivet/Projections/VetoedFinalState.hh"
   7#include "Rivet/Projections/IdentifiedFinalState.hh"
   8#include "Rivet/Projections/UnstableParticles.hh"
   9#include "Rivet/Projections/FastJets.hh"
  10#include "Rivet/Tools/Random.hh"
  11
  12namespace Rivet {
  13
  14
  15  class ATLAS_2012_I1204447 : public Analysis {
  16  public:
  17
  18    /// Constructor
  19    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2012_I1204447);
  20
  21
  22    /// Book histograms and initialise projections before the run
  23    void init() {
  24
  25      // To calculate the acceptance without having the fiducial lepton efficiencies included, this part can be turned off
  26      _use_fiducial_lepton_efficiency = true;
  27
  28      // Read in all signal regions
  29      _signal_regions = getSignalRegions();
  30
  31      // Set number of events per signal region to 0
  32      for (size_t i = 0; i < _signal_regions.size(); i++)
  33        book(_eventCountsPerSR[_signal_regions[i]], "_eventCountsPerSR_" + _signal_regions[i]);
  34
  35      // Final state including all charged and neutral particles
  36      const FinalState fs((Cuts::etaIn(-5.0, 5.0) && Cuts::pT >=  1*GeV));
  37      declare(fs, "FS");
  38
  39      // Final state including all charged particles
  40      declare(ChargedFinalState(Cuts::abseta < 2.5 && Cuts::pT > 1*GeV), "CFS");
  41
  42      // Final state including all visible particles (to calculate MET, Jets etc.)
  43      declare(VisibleFinalState(Cuts::abseta < 5.0), "VFS");
  44
  45      // Final state including all AntiKt 04 Jets
  46      VetoedFinalState vfs;
  47      vfs.addVetoPairId(PID::MUON);
  48      declare(FastJets(vfs, JetAlg::ANTIKT, 0.4), "AntiKtJets04");
  49
  50      // Final state including all unstable particles (including taus)
  51      declare(UnstableParticles(Cuts::abseta < 5.0 && Cuts::pT > 5*GeV), "UFS");
  52
  53      // Final state including all electrons
  54      IdentifiedFinalState elecs(Cuts::abseta < 2.47 && Cuts::pT > 10*GeV);
  55      elecs.acceptIdPair(PID::ELECTRON);
  56      declare(elecs, "elecs");
  57
  58      // Final state including all muons
  59      IdentifiedFinalState muons(Cuts::abseta < 2.5 && Cuts::pT > 10*GeV);
  60      muons.acceptIdPair(PID::MUON);
  61      declare(muons, "muons");
  62
  63      // Book histograms
  64      book(_h_HTlep_all  ,"HTlep_all" , 30, 0, 1500);
  65      book(_h_HTjets_all ,"HTjets_all", 30, 0, 1500);
  66      book(_h_MET_all    ,"MET_all"   , 20, 0, 1000);
  67      book(_h_Meff_all   ,"Meff_all"  , 30, 0, 3000);
  68
  69      book(_h_e_n        ,"e_n"  , 10, -0.5, 9.5);
  70      book(_h_mu_n       ,"mu_n" , 10, -0.5, 9.5);
  71      book(_h_tau_n      ,"tau_n", 10, -0.5, 9.5);
  72
  73      book(_h_pt_1_3l    ,"pt_1_3l", 100, 0, 2000);
  74      book(_h_pt_2_3l    ,"pt_2_3l", 100, 0, 2000);
  75      book(_h_pt_3_3l    ,"pt_3_3l", 100, 0, 2000);
  76      book(_h_pt_1_2ltau ,"pt_1_2ltau", 100, 0, 2000);
  77      book(_h_pt_2_2ltau ,"pt_2_2ltau", 100, 0, 2000);
  78      book(_h_pt_3_2ltau ,"pt_3_2ltau", 100, 0, 2000);
  79
  80      book(_h_excluded   ,"excluded", 2, -0.5, 1.5);
  81    }
  82
  83
  84    /// Perform the per-event analysis
  85    void analyze(const Event& event) {
  86
  87      // Muons
  88      Particles muon_candidates;
  89      const Particles charged_tracks    = apply<ChargedFinalState>(event, "CFS").particles();
  90      const Particles visible_particles = apply<VisibleFinalState>(event, "VFS").particles();
  91      for (const Particle& mu : apply<IdentifiedFinalState>(event, "muons").particlesByPt()) {
  92        // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of muon itself)
  93        double pTinCone = -mu.pT();
  94        for (const Particle& track : charged_tracks) {
  95          if (deltaR(mu.momentum(), track.momentum()) < 0.3)
  96            pTinCone += track.pT();
  97        }
  98
  99        // Calculate eTCone30 variable (pT of all visible particles within dR<0.3)
 100        double eTinCone = 0.;
 101        for (const Particle& visible_particle : visible_particles) {
 102          if (visible_particle.abspid() != PID::MUON && inRange(deltaR(mu.momentum(), visible_particle.momentum()), 0.1, 0.3))
 103            eTinCone += visible_particle.pT();
 104        }
 105
 106        // Apply reconstruction efficiency and simulate reco
 107        int muon_id = 13;
 108        if ( mu.hasAncestorWith(Cuts::pid == 15) || mu.hasAncestorWith(Cuts::pid == -15)) muon_id = 14;
 109        const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(muon_id, mu) : 1.0;
 110        const bool keep_muon = rand01() <= eff;
 111
 112        // Keep muon if pTCone30/pT < 0.15 and eTCone30/pT < 0.2 and reconstructed
 113        if (keep_muon && pTinCone/mu.pT() <= 0.15 && eTinCone/mu.pT() < 0.2)
 114          muon_candidates.push_back(mu);
 115      }
 116
 117
 118      // Electrons
 119      Particles electron_candidates;
 120      for (const Particle& e : apply<IdentifiedFinalState>(event, "elecs").particlesByPt()) {
 121        // Neglect electrons in crack regions
 122        if (inRange(e.abseta(), 1.37, 1.52)) continue;
 123
 124        // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of electron itself)
 125        double pTinCone = -e.pT();
 126        for (const Particle& track : charged_tracks) {
 127          if (deltaR(e.momentum(), track.momentum()) < 0.3) pTinCone += track.pT();
 128        }
 129
 130        // Calculate eTCone30 variable (pT of all visible particles (except muons) within dR<0.3)
 131        double eTinCone = 0.;
 132        for (const Particle& visible_particle : visible_particles) {
 133          if (visible_particle.abspid() != PID::MUON && inRange(deltaR(e.momentum(), visible_particle.momentum()), 0.1, 0.3))
 134            eTinCone += visible_particle.pT();
 135        }
 136
 137        // Apply reconstruction efficiency and simulate reco
 138        int elec_id = 11;
 139        if (e.hasAncestorWith(Cuts::pid == 15) || e.hasAncestorWith(Cuts::pid == -15)) elec_id = 12;
 140        const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(elec_id, e) : 1.0;
 141        const bool keep_elec = rand01() <= eff;
 142
 143        // Keep electron if pTCone30/pT < 0.13 and eTCone30/pT < 0.2 and reconstructed
 144        if (keep_elec && pTinCone/e.pT() <= 0.13 && eTinCone/e.pT() < 0.2)
 145          electron_candidates.push_back(e);
 146      }
 147
 148
 149      // Taus
 150      /// @todo This could benefit from a tau finder projection
 151      Particles tau_candidates;
 152      for (const Particle& tau : apply<UnstableParticles>(event, "UFS").particlesByPt()) {
 153        // Only pick taus out of all unstable particles
 154        if (tau.abspid() != PID::TAU) continue;
 155
 156        // Check that tau has decayed into daughter particles
 157        /// @todo Huh? Unstable taus with no decay vtx? Can use Particle.isStable()? But why in this situation?
 158        if (tau.genParticle()->end_vertex() == 0) continue;
 159
 160        // Calculate visible tau pT from pT of tau neutrino in tau decay for pT and |eta| cuts
 161        FourMomentum daughter_tau_neutrino_momentum = get_tau_neutrino_mom(tau);
 162        Particle tau_vis = tau;
 163        tau_vis.setMomentum(tau.momentum()-daughter_tau_neutrino_momentum);
 164        // keep only taus in certain eta region and above 15 GeV of visible tau pT
 165        if ( tau_vis.pT() <= 15.0*GeV || tau_vis.abseta() > 2.5) continue;
 166
 167        // Get prong number (number of tracks) in tau decay and check if tau decays leptonically
 168        unsigned int nprong = 0;
 169        bool lep_decaying_tau = false;
 170        get_prong_number(tau.genParticle(), nprong, lep_decaying_tau);
 171
 172        // Apply reconstruction efficiency
 173        int tau_id = 15;
 174        if (nprong == 1) tau_id = 15;
 175        else if (nprong == 3) tau_id = 16;
 176
 177        // Get fiducial lepton efficiency simulate reco efficiency
 178        const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(tau_id, tau_vis) : 1.0;
 179        const bool keep_tau = rand01() <= eff;
 180
 181        // Keep tau if nprong = 1, it decays hadronically, and it's reconstructed by the detector
 182        if ( !lep_decaying_tau && nprong == 1 && keep_tau) tau_candidates.push_back(tau_vis);
 183      }
 184
 185
 186      // Jets (all anti-kt R=0.4 jets with pT > 25 GeV and eta < 4.9)
 187      Jets jet_candidates = apply<FastJets>(event, "AntiKtJets04").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 4.9);
 188
 189      // ETmiss
 190      Particles vfs_particles = apply<VisibleFinalState>(event, "VFS").particles();
 191      FourMomentum pTmiss;
 192      for (const Particle& p : vfs_particles) pTmiss -= p.momentum();
 193      double eTmiss = pTmiss.pT()/GeV;
 194
 195
 196      //------------------
 197      // Overlap removal
 198
 199      // electron - electron
 200      Particles electron_candidates_2;
 201      for (size_t ie = 0; ie < electron_candidates.size(); ++ie) {
 202        const Particle & e = electron_candidates[ie];
 203        bool away = true;
 204        // If electron pair within dR < 0.1: remove electron with lower pT
 205        for (size_t ie2=0; ie2 < electron_candidates_2.size(); ++ie2) {
 206          if ( deltaR( e.momentum(), electron_candidates_2[ie2].momentum()) < 0.1 ) {
 207            away = false;
 208            break;
 209          }
 210        }
 211        // If isolated keep it
 212        if ( away )
 213          electron_candidates_2.push_back( e );
 214      }
 215      // jet - electron
 216      Jets recon_jets;
 217      for (const Jet& jet : jet_candidates) {
 218        bool away = true;
 219        // if jet within dR < 0.2 of electron: remove jet
 220        for (const Particle& e : electron_candidates_2) {
 221          if (deltaR(e.momentum(), jet.momentum()) < 0.2) {
 222            away = false;
 223            break;
 224          }
 225        }
 226        // jet - tau
 227        if (away)  {
 228          // If jet within dR < 0.2 of tau: remove jet
 229          for (const Particle& tau : tau_candidates) {
 230            if (deltaR(tau.momentum(), jet.momentum()) < 0.2) {
 231              away = false;
 232              break;
 233            }
 234          }
 235        }
 236        // If isolated keep it
 237        if ( away )
 238          recon_jets.push_back( jet );
 239      }
 240
 241
 242      // electron - jet
 243      Particles recon_leptons, recon_e;
 244      for (size_t ie = 0; ie < electron_candidates_2.size(); ++ie) {
 245        const Particle& e = electron_candidates_2[ie];
 246        // If electron within 0.2 < dR < 0.4 from any jets: remove electron
 247        bool away = true;
 248        for (const Jet& jet : recon_jets) {
 249          if (deltaR(e.momentum(), jet.momentum()) < 0.4) {
 250            away = false;
 251            break;
 252          }
 253        }
 254        // electron - muon
 255        // if electron within dR < 0.1 of a muon: remove electron
 256        if (away) {
 257          for (const Particle& mu : muon_candidates) {
 258            if (deltaR(mu.momentum(), e.momentum()) < 0.1) {
 259              away = false;
 260              break;
 261            }
 262          }
 263        }
 264        // If isolated keep it
 265        if (away)  {
 266          recon_e += e;
 267          recon_leptons += e;
 268        }
 269      }
 270
 271
 272      // tau - electron
 273      Particles recon_tau;
 274      for ( const Particle& tau : tau_candidates ) {
 275        bool away = true;
 276        // If tau within dR < 0.2 of an electron: remove tau
 277        for ( const Particle& e : recon_e ) {
 278          if (deltaR( tau.momentum(), e.momentum()) < 0.2) {
 279            away = false;
 280            break;
 281          }
 282        }
 283        // tau - muon
 284        // If tau within dR < 0.2 of a muon: remove tau
 285        if (away)  {
 286          for (const Particle& mu : muon_candidates) {
 287            if (deltaR(tau.momentum(), mu.momentum()) < 0.2) {
 288              away = false;
 289              break;
 290            }
 291          }
 292        }
 293        // If isolated keep it
 294        if (away) recon_tau.push_back( tau );
 295      }
 296
 297      // Muon - jet isolation
 298      Particles recon_mu, trigger_mu;
 299      // If muon within dR < 0.4 of a jet, remove muon
 300      for (const Particle& mu : muon_candidates) {
 301        bool away = true;
 302        for (const Jet& jet : recon_jets) {
 303          if ( deltaR( mu.momentum(), jet.momentum()) < 0.4 ) {
 304            away = false;
 305            break;
 306          }
 307        }
 308        if (away) {
 309          recon_mu.push_back( mu );
 310          recon_leptons.push_back( mu );
 311          if (mu.abseta() < 2.4) trigger_mu.push_back( mu );
 312        }
 313      }
 314
 315      // End overlap removal
 316      //------------------
 317
 318
 319      // Jet cleaning
 320      if (rand01() <= 0.42) {
 321        for (const Jet& jet : recon_jets) {
 322          const double eta = jet.rapidity();
 323          const double phi = jet.azimuthalAngle(MINUSPI_PLUSPI);
 324          if (jet.pT() > 25*GeV && inRange(eta, -0.1, 1.5) && inRange(phi, -0.9, -0.5)) vetoEvent;
 325        }
 326      }
 327
 328
 329      // Post-isolation event cuts
 330      // Require at least 3 charged tracks in event
 331      if (charged_tracks.size() < 3) vetoEvent;
 332
 333      // And at least one e/mu passing trigger
 334      if (!( !recon_e   .empty() && recon_e[0]   .pT() > 25*GeV)  &&
 335          !( !trigger_mu.empty() && trigger_mu[0].pT() > 25*GeV) ) {
 336        MSG_DEBUG("Hardest lepton fails trigger");
 337        vetoEvent;
 338      }
 339
 340      // And only accept events with at least 2 electrons and muons and at least 3 leptons in total
 341      if (recon_mu.size() + recon_e.size() + recon_tau.size() < 3 || recon_leptons.size() < 2) vetoEvent;
 342
 343      // Sort leptons by decreasing pT
 344      isortByPt(recon_leptons);
 345      isortByPt(recon_tau);
 346
 347      // Calculate HTlep, fill lepton pT histograms & store chosen combination of 3 leptons
 348      double HTlep = 0.;
 349      Particles chosen_leptons;
 350      if ( recon_leptons.size() > 2 ) {
 351        _h_pt_1_3l->fill(recon_leptons[0].perp()/GeV);
 352        _h_pt_2_3l->fill(recon_leptons[1].perp()/GeV);
 353        _h_pt_3_3l->fill(recon_leptons[2].perp()/GeV);
 354        HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_leptons[2].pT())/GeV;
 355        chosen_leptons.push_back( recon_leptons[0] );
 356        chosen_leptons.push_back( recon_leptons[1] );
 357        chosen_leptons.push_back( recon_leptons[2] );
 358      }
 359      else {
 360        _h_pt_1_2ltau->fill(recon_leptons[0].perp()/GeV);
 361        _h_pt_2_2ltau->fill(recon_leptons[1].perp()/GeV);
 362        _h_pt_3_2ltau->fill(recon_tau[0].perp()/GeV);
 363        HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_tau[0].pT())/GeV ;
 364        chosen_leptons.push_back( recon_leptons[0] );
 365        chosen_leptons.push_back( recon_leptons[1] );
 366        chosen_leptons.push_back( recon_tau[0] );
 367      }
 368
 369      // Number of prompt e/mu and had taus
 370      _h_e_n  ->fill(recon_e.size());
 371      _h_mu_n ->fill(recon_mu.size());
 372      _h_tau_n->fill(recon_tau.size());
 373
 374      // Calculate HTjets
 375      double HTjets = 0.;
 376      for ( const Jet & jet : recon_jets )
 377        HTjets += jet.perp()/GeV;
 378
 379      // Calculate meff
 380      double meff = eTmiss + HTjets;
 381      Particles all_leptons;
 382      for ( const Particle & e  : recon_e  )  {
 383        meff += e.perp()/GeV;
 384        all_leptons.push_back( e );
 385      }
 386      for ( const Particle & mu : recon_mu )  {
 387        meff += mu.perp()/GeV;
 388        all_leptons.push_back( mu );
 389      }
 390      for ( const Particle & tau : recon_tau )  {
 391        meff += tau.perp()/GeV;
 392        all_leptons.push_back( tau );
 393      }
 394
 395      // Fill histogram of kinematic variables
 396      _h_HTlep_all ->fill(HTlep);
 397      _h_HTjets_all->fill(HTjets);
 398      _h_MET_all   ->fill(eTmiss);
 399      _h_Meff_all  ->fill(meff);
 400
 401      // Determine signal region (3l/2ltau, onZ/offZ)
 402      string basic_signal_region;
 403      if ( recon_mu.size() + recon_e.size() > 2 )
 404        basic_signal_region += "3l_";
 405      else if ( (recon_mu.size() + recon_e.size() == 2) && (recon_tau.size() > 0))
 406        basic_signal_region += "2ltau_";
 407      // Is there an OSSF pair or a three lepton combination with an invariant mass close to the Z mass
 408      int onZ = isonZ(chosen_leptons);
 409      if      (onZ == 1)   basic_signal_region += "onZ";
 410      else if (onZ == 0)   basic_signal_region += "offZ";
 411      // Check in which signal regions this event falls and adjust event counters
 412      fillEventCountsPerSR(basic_signal_region, onZ, HTlep, eTmiss, HTjets, meff);
 413    }
 414
 415
 416    /// Normalise histograms etc., after the run
 417    void finalize() {
 418
 419      // Normalize to an integrated luminosity of 1 fb-1
 420      double norm = crossSection()/femtobarn/sumOfWeights();
 421      string best_signal_region = "";
 422      double ratio_best_SR = 0.;
 423
 424      // Loop over all signal regions and find signal region with best sensitivity (ratio signal events/visible cross-section)
 425      for (size_t i = 0; i < _signal_regions.size(); i++)  {
 426        double signal_events = _eventCountsPerSR[_signal_regions[i]]->val() * norm;
 427        // Use expected upper limits to find best signal region
 428        double UL95  = getUpperLimit(_signal_regions[i], false);
 429        double ratio = signal_events / UL95;
 430        if (ratio > ratio_best_SR)  {
 431          best_signal_region = _signal_regions[i];
 432          ratio_best_SR = ratio;
 433        }
 434      }
 435
 436      double signal_events_best_SR = _eventCountsPerSR[best_signal_region]->val() * norm;
 437      double exp_UL_best_SR = getUpperLimit(best_signal_region, false);
 438      double obs_UL_best_SR = getUpperLimit(best_signal_region, true);
 439
 440      // Print out result
 441      cout << "----------------------------------------------------------------------------------------" << endl;
 442      cout << "Best signal region: " << best_signal_region << endl;
 443      cout << "Normalized number of signal events in this best signal region (per fb-1): " << signal_events_best_SR << endl;
 444      cout << "Efficiency*Acceptance: " <<  _eventCountsPerSR[best_signal_region]->val()/sumOfWeights() << endl;
 445      cout << "Cross-section [fb]: " << crossSection()/femtobarn << endl;
 446      cout << "Expected visible cross-section (per fb-1): " << exp_UL_best_SR << endl;
 447      cout << "Ratio (signal events / expected visible cross-section): " << ratio_best_SR << endl;
 448      cout << "Observed visible cross-section (per fb-1): " << obs_UL_best_SR << endl;
 449      cout << "Ratio (signal events / observed visible cross-section): " <<  signal_events_best_SR/obs_UL_best_SR << endl;
 450      cout << "----------------------------------------------------------------------------------------" << endl;
 451
 452      cout << "Using the EXPECTED limits (visible cross-section) of the analysis: " << endl;
 453      if (signal_events_best_SR > exp_UL_best_SR)  {
 454        cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
 455        _h_excluded->fill(1);
 456      }
 457      else  {
 458        cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
 459        _h_excluded->fill(0);
 460      }
 461      cout << "----------------------------------------------------------------------------------------" << endl;
 462
 463      cout << "Using the OBSERVED limits (visible cross-section) of the analysis: " << endl;
 464      if (signal_events_best_SR > obs_UL_best_SR)  {
 465        cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
 466        _h_excluded->fill(1);
 467      }
 468      else  {
 469        cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
 470        _h_excluded->fill(0);
 471      }
 472      cout << "----------------------------------------------------------------------------------------" << endl;
 473
 474
 475      // Normalize to cross section
 476      if (norm != 0)  {
 477        scale(_h_HTlep_all,  norm);
 478        scale(_h_HTjets_all, norm);
 479        scale(_h_MET_all,    norm);
 480        scale(_h_Meff_all,   norm);
 481
 482        scale(_h_pt_1_3l,    norm);
 483        scale(_h_pt_2_3l,    norm);
 484        scale(_h_pt_3_3l,    norm);
 485        scale(_h_pt_1_2ltau, norm);
 486        scale(_h_pt_2_2ltau, norm);
 487        scale(_h_pt_3_2ltau, norm);
 488
 489        scale(_h_e_n,        norm);
 490        scale(_h_mu_n,       norm);
 491        scale(_h_tau_n,      norm);
 492
 493        scale(_h_excluded,   signal_events_best_SR);
 494      }
 495    }
 496
 497
 498    /// Helper functions
 499    /// @{
 500
 501    /// Function giving a list of all signal regions
 502    vector<string> getSignalRegions()  {
 503
 504      // List of basic signal regions
 505      vector<string> basic_signal_regions;
 506      basic_signal_regions.push_back("3l_offZ");
 507      basic_signal_regions.push_back("3l_onZ");
 508      basic_signal_regions.push_back("2ltau_offZ");
 509      basic_signal_regions.push_back("2ltau_onZ");
 510
 511      // List of kinematic variables
 512      vector<string> kinematic_variables;
 513      kinematic_variables.push_back("HTlep");
 514      kinematic_variables.push_back("METStrong");
 515      kinematic_variables.push_back("METWeak");
 516      kinematic_variables.push_back("Meff");
 517      kinematic_variables.push_back("MeffStrong");
 518
 519      vector<string> signal_regions;
 520      // Loop over all kinematic variables and basic signal regions
 521      for (size_t i0 = 0; i0 < kinematic_variables.size(); i0++)  {
 522        for (size_t i1 = 0; i1 < basic_signal_regions.size(); i1++)  {
 523          // Is signal region onZ?
 524          int onZ = (basic_signal_regions[i1].find("onZ") != string::npos) ? 1 : 0;
 525          // Get cut values for this kinematic variable
 526          vector<int> cut_values = getCutsPerSignalRegion(kinematic_variables[i0], onZ);
 527          // Loop over all cut values
 528          for (size_t i2 = 0; i2 < cut_values.size(); i2++)  {
 529            // push signal region into vector
 530            signal_regions.push_back( (kinematic_variables[i0] + "_" + basic_signal_regions[i1] + "_cut_" + toString(i2)) );
 531          }
 532        }
 533      }
 534      return signal_regions;
 535    }
 536
 537
 538    /// Function giving all cut vales per kinematic variable (taking onZ for MET into account)
 539    vector<int> getCutsPerSignalRegion(const string& signal_region, int onZ=0)  {
 540      vector<int> cutValues;
 541
 542      // Cut values for HTlep
 543      if (signal_region.compare("HTlep") == 0)  {
 544        cutValues.push_back(0);
 545        cutValues.push_back(100);
 546        cutValues.push_back(150);
 547        cutValues.push_back(200);
 548        cutValues.push_back(300);
 549      }
 550      // Cut values for METStrong (HTjets > 100 GeV) and METWeak (HTjets < 100 GeV)
 551      else if (signal_region.compare("METStrong") == 0 || signal_region.compare("METWeak") == 0)  {
 552        if      (onZ == 0) cutValues.push_back(0);
 553        else if (onZ == 1) cutValues.push_back(20);
 554        cutValues.push_back(50);
 555        cutValues.push_back(75);
 556      }
 557      // Cut values for Meff and MeffStrong (MET > 75 GeV)
 558      if (signal_region.compare("Meff") == 0 || signal_region.compare("MeffStrong") == 0)  {
 559        cutValues.push_back(0);
 560        cutValues.push_back(150);
 561        cutValues.push_back(300);
 562        cutValues.push_back(500);
 563      }
 564
 565      return cutValues;
 566    }
 567
 568
 569    /// function fills map EventCountsPerSR by looping over all signal regions
 570    /// and looking if the event falls into this signal region
 571    void fillEventCountsPerSR(const string& basic_signal_region, int onZ,
 572                              double HTlep, double eTmiss,
 573                              double HTjets, double meff)  {
 574
 575      // Get cut values for HTlep, loop over them and add event if cut is passed
 576      vector<int> cut_values = getCutsPerSignalRegion("HTlep", onZ);
 577      for (size_t i = 0; i < cut_values.size(); i++)  {
 578        if (HTlep > cut_values[i])
 579          _eventCountsPerSR[("HTlep_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
 580      }
 581
 582      // Get cut values for METStrong, loop over them and add event if cut is passed
 583      cut_values = getCutsPerSignalRegion("METStrong", onZ);
 584      for (size_t i = 0; i < cut_values.size(); i++)  {
 585        if (eTmiss > cut_values[i] && HTjets > 100.)
 586          _eventCountsPerSR[("METStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
 587      }
 588
 589      // Get cut values for METWeak, loop over them and add event if cut is passed
 590      cut_values = getCutsPerSignalRegion("METWeak", onZ);
 591      for (size_t i = 0; i < cut_values.size(); i++)  {
 592        if (eTmiss > cut_values[i] && HTjets <= 100.)
 593          _eventCountsPerSR[("METWeak_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
 594      }
 595
 596      // Get cut values for Meff, loop over them and add event if cut is passed
 597      cut_values = getCutsPerSignalRegion("Meff", onZ);
 598      for (size_t i = 0; i < cut_values.size(); i++)  {
 599        if (meff > cut_values[i])
 600          _eventCountsPerSR[("Meff_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
 601      }
 602
 603      // Get cut values for MeffStrong, loop over them and add event if cut is passed
 604      cut_values = getCutsPerSignalRegion("MeffStrong", onZ);
 605      for (size_t i = 0; i < cut_values.size(); i++)  {
 606        if (meff > cut_values[i] && eTmiss > 75.)
 607          _eventCountsPerSR[("MeffStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
 608      }
 609    }
 610
 611
 612    /// Function returning 4-vector of daughter-particle if it is a tau neutrino
 613    /// @todo Move to TauFinder and make less HepMC-ish
 614    FourMomentum get_tau_neutrino_mom(const Particle& p)  {
 615      assert(p.abspid() == PID::TAU);
 616      ConstGenVertexPtr dv = p.genParticle()->end_vertex();
 617      assert(dv != nullptr);
 618      for(ConstGenParticlePtr pp: HepMCUtils::particles(dv, Relatives::CHILDREN)){
 619        if (abs(pp->pdg_id()) == PID::NU_TAU) return FourMomentum(pp->momentum());
 620      }
 621      return FourMomentum();
 622    }
 623
 624
 625    /// Function calculating the prong number of taus
 626    /// @todo Move to TauFinder and make less HepMC-ish
 627    void get_prong_number(ConstGenParticlePtr p, unsigned int& nprong, bool& lep_decaying_tau) {
 628      assert(p != nullptr);
 629      //const int tau_barcode = p->barcode();
 630      ConstGenVertexPtr dv = p->end_vertex();
 631      assert(dv != nullptr);
 632      for(ConstGenParticlePtr pp: HepMCUtils::particles(dv, Relatives::CHILDREN)){
 633        // If they have status 1 and are charged they will produce a track and the prong number is +1
 634        if (pp->status() == 1 )  {
 635          const int id = pp->pdg_id();
 636          if (Rivet::PID::charge(id) != 0 ) ++nprong;
 637          // Check if tau decays leptonically
 638          // @todo Can a tau decay include a tau in its decay daughters?!
 639          if ((abs(id) == PID::ELECTRON || abs(id) == PID::MUON || abs(id) == PID::TAU) && abs(p->pdg_id()) == PID::TAU) lep_decaying_tau = true;
 640        }
 641        // If the status of the daughter particle is 2 it is unstable and the further decays are checked
 642        else if (pp->status() == 2 )  {
 643          get_prong_number(pp, nprong, lep_decaying_tau);
 644        }
 645      }
 646    }
 647
 648
 649    /// Function giving fiducial lepton efficiency
 650    double apply_reco_eff(int flavor, const Particle& p) {
 651      float pt = p.pT()/GeV;
 652      float eta = p.eta();
 653
 654      double eff = 0.;
 655      //double err = 0.;
 656
 657      if (flavor == 11) { // weight prompt electron -- now including data/MC ID SF in eff.
 658        //float rho = 0.820;
 659        float p0 = 7.34;  float p1 = 0.8977;
 660        //float ep0= 0.5 ;  float ep1= 0.0087;
 661        eff = p1 - p0/pt;
 662
 663        //double err0 = ep0/pt; // d(eff)/dp0
 664        //double err1 = ep1;    // d(eff)/dp1
 665        //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
 666
 667        double avgrate = 0.6867;
 668        float wz_ele_eta[] = {0.588717,0.603674,0.666135,0.747493,0.762202,0.675051,0.751606,0.745569,0.665333,0.610432,0.592693,};
 669        //float ewz_ele_eta[] ={0.00292902,0.002476,0.00241209,0.00182319,0.00194339,0.00299785,0.00197339,0.00182004,0.00241793,0.00245997,0.00290394,};
 670        int ibin = 3;
 671
 672        if (eta >= -2.5 && eta < -2.0) ibin = 0;
 673        if (eta >= -2.0 && eta < -1.5) ibin = 1;
 674        if (eta >= -1.5 && eta < -1.0) ibin = 2;
 675        if (eta >= -1.0 && eta < -0.5) ibin = 3;
 676        if (eta >= -0.5 && eta < -0.1) ibin = 4;
 677        if (eta >= -0.1 && eta <  0.1) ibin = 5;
 678        if (eta >=  0.1 && eta <  0.5) ibin = 6;
 679        if (eta >=  0.5 && eta <  1.0) ibin = 7;
 680        if (eta >=  1.0 && eta <  1.5) ibin = 8;
 681        if (eta >=  1.5 && eta <  2.0) ibin = 9;
 682        if (eta >=  2.0 && eta <  2.5) ibin = 10;
 683
 684        double eff_eta = wz_ele_eta[ibin];
 685        //double err_eta = ewz_ele_eta[ibin];
 686
 687        eff = (eff*eff_eta)/avgrate;
 688      }
 689
 690      if (flavor == 12)  { // weight electron from tau
 691        //float rho = 0.884;
 692        float p0 = 6.799;  float p1 = 0.842;
 693        //float ep0= 0.664;  float ep1= 0.016;
 694        eff = p1 - p0/pt;
 695
 696        //double err0 = ep0/pt; // d(eff)/dp0
 697        //double err1 = ep1;    // d(eff)/dp1
 698        //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
 699
 700        double avgrate = 0.5319;
 701        float wz_elet_eta[] = {0.468945,0.465953,0.489545,0.58709,0.59669,0.515829,0.59284,0.575828,0.498181,0.463536,0.481738,};
 702        //float ewz_elet_eta[] ={0.00933795,0.00780868,0.00792679,0.00642083,0.00692652,0.0101568,0.00698452,0.00643524,0.0080002,0.00776238,0.0094699,};
 703        int ibin = 3;
 704
 705        if (eta >= -2.5 && eta < -2.0) ibin = 0;
 706        if (eta >= -2.0 && eta < -1.5) ibin = 1;
 707        if (eta >= -1.5 && eta < -1.0) ibin = 2;
 708        if (eta >= -1.0 && eta < -0.5) ibin = 3;
 709        if (eta >= -0.5 && eta < -0.1) ibin = 4;
 710        if (eta >= -0.1 && eta <  0.1) ibin = 5;
 711        if (eta >=  0.1 && eta <  0.5) ibin = 6;
 712        if (eta >=  0.5 && eta <  1.0) ibin = 7;
 713        if (eta >=  1.0 && eta <  1.5) ibin = 8;
 714        if (eta >=  1.5 && eta <  2.0) ibin = 9;
 715        if (eta >=  2.0 && eta <  2.5) ibin = 10;
 716
 717        double eff_eta = wz_elet_eta[ibin];
 718        //double err_eta = ewz_elet_eta[ibin];
 719
 720        eff = (eff*eff_eta)/avgrate;
 721
 722      }
 723
 724      if (flavor == 13)  {// weight prompt muon
 725
 726        //if eta>0.1
 727        float p0 = -18.21;  float p1 = 14.83;  float p2 = 0.9312;
 728        //float ep0= 5.06;    float ep1= 1.9;    float ep2=0.00069;
 729
 730        if ( fabs(eta) < 0.1)  {
 731          p0  = 7.459; p1 = 2.615; p2  = 0.5138;
 732          //ep0 = 10.4; ep1 = 4.934; ep2 = 0.0034;
 733        }
 734
 735        double arg = ( pt-p0 )/( 2.*p1 ) ;
 736        eff = 0.5 * p2 * (1.+erf(arg));
 737        //err = 0.1*eff;
 738      }
 739
 740      if (flavor == 14)  {// weight muon from tau
 741
 742        if (fabs(eta) < 0.1) {
 743          float p0 = -1.756;  float p1 = 12.38;  float p2 = 0.4441;
 744          //float ep0= 10.39;   float ep1= 7.9;  float ep2=0.022;
 745          double arg = ( pt-p0 )/( 2.*p1 ) ;
 746          eff = 0.5 * p2 * (1.+erf(arg));
 747          //err = 0.1*eff;
 748        }
 749        else {
 750          float p0 = 2.102;  float p1 = 0.8293;
 751          //float ep0= 0.271;  float ep1= 0.0083;
 752          eff = p1 - p0/pt;
 753          //double err0 = ep0/pt; // d(eff)/dp0
 754          //double err1 = ep1;    // d(eff)/dp1
 755          //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
 756        }
 757      }
 758
 759      if (flavor == 15)  {// weight hadronic tau 1p
 760
 761        float wz_tau1p[] = {0.0249278,0.146978,0.225049,0.229212,0.21519,0.206152,0.201559,0.197917,0.209249,0.228336,0.193548,};
 762        //float ewz_tau1p[] ={0.00178577,0.00425252,0.00535052,0.00592126,0.00484684,0.00612941,0.00792099,0.0083006,0.0138307,0.015568,0.0501751,};
 763        int ibin = 0;
 764        if (pt > 15)  ibin = 1;
 765        if (pt > 20)  ibin = 2;
 766        if (pt > 25)  ibin = 3;
 767        if (pt > 30)  ibin = 4;
 768        if (pt > 40)  ibin = 5;
 769        if (pt > 50)  ibin = 6;
 770        if (pt > 60)  ibin = 7;
 771        if (pt > 80)  ibin = 8;
 772        if (pt > 100) ibin = 9;
 773        if (pt > 200) ibin = 10;
 774
 775        eff = wz_tau1p[ibin];
 776        //err = ewz_tau1p[ibin];
 777
 778
 779        double avgrate = 0.1718;
 780        float wz_tau1p_eta[] = {0.162132,0.176393,0.139619,0.178813,0.185144,0.210027,0.203937,0.178688,0.137034,0.164216,0.163713,};
 781        //float ewz_tau1p_eta[] ={0.00706705,0.00617989,0.00506798,0.00525172,0.00581865,0.00865675,0.00599245,0.00529877,0.00506368,0.00617025,0.00726219,};
 782
 783        ibin = 3;
 784        if (eta >= -2.5 && eta < -2.0) ibin = 0;
 785        if (eta >= -2.0 && eta < -1.5) ibin = 1;
 786        if (eta >= -1.5 && eta < -1.0) ibin = 2;
 787        if (eta >= -1.0 && eta < -0.5) ibin = 3;
 788        if (eta >= -0.5 && eta < -0.1) ibin = 4;
 789        if (eta >= -0.1 && eta <  0.1) ibin = 5;
 790        if (eta >=  0.1 && eta <  0.5) ibin = 6;
 791        if (eta >=  0.5 && eta <  1.0) ibin = 7;
 792        if (eta >=  1.0 && eta <  1.5) ibin = 8;
 793        if (eta >=  1.5 && eta <  2.0) ibin = 9;
 794        if (eta >=  2.0 && eta <  2.5) ibin = 10;
 795
 796        double eff_eta = wz_tau1p_eta[ibin];
 797        //double err_eta = ewz_tau1p_eta[ibin];
 798
 799        eff = (eff*eff_eta)/avgrate;
 800      }
 801
 802      if (flavor == 16)  { //weight hadronic tau 3p
 803
 804        float wz_tau3p[] = {0.000587199,0.00247181,0.0013031,0.00280112,};
 805        //float ewz_tau3p[] ={0.000415091,0.000617187,0.000582385,0.00197792,};
 806
 807        int ibin = 0;
 808        if (pt > 15) ibin = 1;
 809        if (pt > 20) ibin = 2;
 810        if (pt > 40) ibin = 3;
 811        if (pt > 80) ibin = 4;
 812
 813        eff = wz_tau3p[ibin];
 814        //err = ewz_tau3p[ibin];
 815      }
 816
 817      return eff;
 818    }
 819
 820
 821    /// Function giving observed upper limit (visible cross-section)
 822    double getUpperLimit(const string& signal_region, bool observed)  {
 823      map<string,double> upperLimitsObserved;
 824      upperLimitsObserved["HTlep_3l_offZ_cut_0"] = 11.;
 825      upperLimitsObserved["HTlep_3l_offZ_cut_100"] = 8.7;
 826      upperLimitsObserved["HTlep_3l_offZ_cut_150"] = 4.0;
 827      upperLimitsObserved["HTlep_3l_offZ_cut_200"] = 4.4;
 828      upperLimitsObserved["HTlep_3l_offZ_cut_300"] = 1.6;
 829      upperLimitsObserved["HTlep_2ltau_offZ_cut_0"] = 25.;
 830      upperLimitsObserved["HTlep_2ltau_offZ_cut_100"] = 14.;
 831      upperLimitsObserved["HTlep_2ltau_offZ_cut_150"] = 6.1;
 832      upperLimitsObserved["HTlep_2ltau_offZ_cut_200"] = 3.3;
 833      upperLimitsObserved["HTlep_2ltau_offZ_cut_300"] = 1.2;
 834      upperLimitsObserved["HTlep_3l_onZ_cut_0"] = 48.;
 835      upperLimitsObserved["HTlep_3l_onZ_cut_100"] = 38.;
 836      upperLimitsObserved["HTlep_3l_onZ_cut_150"] = 14.;
 837      upperLimitsObserved["HTlep_3l_onZ_cut_200"] = 7.2;
 838      upperLimitsObserved["HTlep_3l_onZ_cut_300"] = 4.5;
 839      upperLimitsObserved["HTlep_2ltau_onZ_cut_0"] = 85.;
 840      upperLimitsObserved["HTlep_2ltau_onZ_cut_100"] = 53.;
 841      upperLimitsObserved["HTlep_2ltau_onZ_cut_150"] = 11.0;
 842      upperLimitsObserved["HTlep_2ltau_onZ_cut_200"] = 5.2;
 843      upperLimitsObserved["HTlep_2ltau_onZ_cut_300"] = 3.0;
 844      upperLimitsObserved["METStrong_3l_offZ_cut_0"] = 2.6;
 845      upperLimitsObserved["METStrong_3l_offZ_cut_50"] = 2.1;
 846      upperLimitsObserved["METStrong_3l_offZ_cut_75"] = 2.1;
 847      upperLimitsObserved["METStrong_2ltau_offZ_cut_0"] = 4.2;
 848      upperLimitsObserved["METStrong_2ltau_offZ_cut_50"] = 3.1;
 849      upperLimitsObserved["METStrong_2ltau_offZ_cut_75"] = 2.6;
 850      upperLimitsObserved["METStrong_3l_onZ_cut_20"] = 11.0;
 851      upperLimitsObserved["METStrong_3l_onZ_cut_50"] = 6.4;
 852      upperLimitsObserved["METStrong_3l_onZ_cut_75"] = 5.1;
 853      upperLimitsObserved["METStrong_2ltau_onZ_cut_20"] = 5.9;
 854      upperLimitsObserved["METStrong_2ltau_onZ_cut_50"] = 3.4;
 855      upperLimitsObserved["METStrong_2ltau_onZ_cut_75"] = 1.2;
 856      upperLimitsObserved["METWeak_3l_offZ_cut_0"] = 11.;
 857      upperLimitsObserved["METWeak_3l_offZ_cut_50"] = 5.3;
 858      upperLimitsObserved["METWeak_3l_offZ_cut_75"] = 3.1;
 859      upperLimitsObserved["METWeak_2ltau_offZ_cut_0"] = 23.;
 860      upperLimitsObserved["METWeak_2ltau_offZ_cut_50"] = 4.3;
 861      upperLimitsObserved["METWeak_2ltau_offZ_cut_75"] = 3.1;
 862      upperLimitsObserved["METWeak_3l_onZ_cut_20"] = 41.;
 863      upperLimitsObserved["METWeak_3l_onZ_cut_50"] = 16.;
 864      upperLimitsObserved["METWeak_3l_onZ_cut_75"] = 8.0;
 865      upperLimitsObserved["METWeak_2ltau_onZ_cut_20"] = 80.;
 866      upperLimitsObserved["METWeak_2ltau_onZ_cut_50"] = 4.4;
 867      upperLimitsObserved["METWeak_2ltau_onZ_cut_75"] = 1.8;
 868      upperLimitsObserved["Meff_3l_offZ_cut_0"] = 11.;
 869      upperLimitsObserved["Meff_3l_offZ_cut_150"] = 8.1;
 870      upperLimitsObserved["Meff_3l_offZ_cut_300"] = 3.1;
 871      upperLimitsObserved["Meff_3l_offZ_cut_500"] = 2.1;
 872      upperLimitsObserved["Meff_2ltau_offZ_cut_0"] = 25.;
 873      upperLimitsObserved["Meff_2ltau_offZ_cut_150"] = 12.;
 874      upperLimitsObserved["Meff_2ltau_offZ_cut_300"] = 3.9;
 875      upperLimitsObserved["Meff_2ltau_offZ_cut_500"] = 2.2;
 876      upperLimitsObserved["Meff_3l_onZ_cut_0"] = 48.;
 877      upperLimitsObserved["Meff_3l_onZ_cut_150"] = 37.;
 878      upperLimitsObserved["Meff_3l_onZ_cut_300"] = 11.;
 879      upperLimitsObserved["Meff_3l_onZ_cut_500"] = 4.8;
 880      upperLimitsObserved["Meff_2ltau_onZ_cut_0"] = 85.;
 881      upperLimitsObserved["Meff_2ltau_onZ_cut_150"] = 28.;
 882      upperLimitsObserved["Meff_2ltau_onZ_cut_300"] = 5.9;
 883      upperLimitsObserved["Meff_2ltau_onZ_cut_500"] = 1.9;
 884      upperLimitsObserved["MeffStrong_3l_offZ_cut_0"] = 3.8;
 885      upperLimitsObserved["MeffStrong_3l_offZ_cut_150"] = 3.8;
 886      upperLimitsObserved["MeffStrong_3l_offZ_cut_300"] = 2.8;
 887      upperLimitsObserved["MeffStrong_3l_offZ_cut_500"] = 2.1;
 888      upperLimitsObserved["MeffStrong_2ltau_offZ_cut_0"] = 3.9;
 889      upperLimitsObserved["MeffStrong_2ltau_offZ_cut_150"] = 4.0;
 890      upperLimitsObserved["MeffStrong_2ltau_offZ_cut_300"] = 2.9;
 891      upperLimitsObserved["MeffStrong_2ltau_offZ_cut_500"] = 1.5;
 892      upperLimitsObserved["MeffStrong_3l_onZ_cut_0"] = 10.0;
 893      upperLimitsObserved["MeffStrong_3l_onZ_cut_150"] = 10.0;
 894      upperLimitsObserved["MeffStrong_3l_onZ_cut_300"] = 6.8;
 895      upperLimitsObserved["MeffStrong_3l_onZ_cut_500"] = 3.9;
 896      upperLimitsObserved["MeffStrong_2ltau_onZ_cut_0"] = 1.6;
 897      upperLimitsObserved["MeffStrong_2ltau_onZ_cut_150"] = 1.4;
 898      upperLimitsObserved["MeffStrong_2ltau_onZ_cut_300"] = 1.5;
 899      upperLimitsObserved["MeffStrong_2ltau_onZ_cut_500"] = 0.9;
 900
 901      // Expected upper limits are also given but not used in this analysis
 902      map<string,double> upperLimitsExpected;
 903      upperLimitsExpected["HTlep_3l_offZ_cut_0"] = 11.;
 904      upperLimitsExpected["HTlep_3l_offZ_cut_100"] = 8.5;
 905      upperLimitsExpected["HTlep_3l_offZ_cut_150"] = 4.6;
 906      upperLimitsExpected["HTlep_3l_offZ_cut_200"] = 3.6;
 907      upperLimitsExpected["HTlep_3l_offZ_cut_300"] = 1.9;
 908      upperLimitsExpected["HTlep_2ltau_offZ_cut_0"] = 23.;
 909      upperLimitsExpected["HTlep_2ltau_offZ_cut_100"] = 14.;
 910      upperLimitsExpected["HTlep_2ltau_offZ_cut_150"] = 6.4;
 911      upperLimitsExpected["HTlep_2ltau_offZ_cut_200"] = 3.6;
 912      upperLimitsExpected["HTlep_2ltau_offZ_cut_300"] = 1.5;
 913      upperLimitsExpected["HTlep_3l_onZ_cut_0"] = 33.;
 914      upperLimitsExpected["HTlep_3l_onZ_cut_100"] = 25.;
 915      upperLimitsExpected["HTlep_3l_onZ_cut_150"] = 12.;
 916      upperLimitsExpected["HTlep_3l_onZ_cut_200"] = 6.5;
 917      upperLimitsExpected["HTlep_3l_onZ_cut_300"] = 3.1;
 918      upperLimitsExpected["HTlep_2ltau_onZ_cut_0"] = 94.;
 919      upperLimitsExpected["HTlep_2ltau_onZ_cut_100"] = 61.;
 920      upperLimitsExpected["HTlep_2ltau_onZ_cut_150"] = 9.9;
 921      upperLimitsExpected["HTlep_2ltau_onZ_cut_200"] = 4.5;
 922      upperLimitsExpected["HTlep_2ltau_onZ_cut_300"] = 1.9;
 923      upperLimitsExpected["METStrong_3l_offZ_cut_0"] = 3.1;
 924      upperLimitsExpected["METStrong_3l_offZ_cut_50"] = 2.4;
 925      upperLimitsExpected["METStrong_3l_offZ_cut_75"] = 2.3;
 926      upperLimitsExpected["METStrong_2ltau_offZ_cut_0"] = 4.8;
 927      upperLimitsExpected["METStrong_2ltau_offZ_cut_50"] = 3.3;
 928      upperLimitsExpected["METStrong_2ltau_offZ_cut_75"] = 2.1;
 929      upperLimitsExpected["METStrong_3l_onZ_cut_20"] = 8.7;
 930      upperLimitsExpected["METStrong_3l_onZ_cut_50"] = 4.9;
 931      upperLimitsExpected["METStrong_3l_onZ_cut_75"] = 3.8;
 932      upperLimitsExpected["METStrong_2ltau_onZ_cut_20"] = 7.3;
 933      upperLimitsExpected["METStrong_2ltau_onZ_cut_50"] = 2.8;
 934      upperLimitsExpected["METStrong_2ltau_onZ_cut_75"] = 1.5;
 935      upperLimitsExpected["METWeak_3l_offZ_cut_0"] = 10.;
 936      upperLimitsExpected["METWeak_3l_offZ_cut_50"] = 4.7;
 937      upperLimitsExpected["METWeak_3l_offZ_cut_75"] = 3.0;
 938      upperLimitsExpected["METWeak_2ltau_offZ_cut_0"] = 21.;
 939      upperLimitsExpected["METWeak_2ltau_offZ_cut_50"] = 4.0;
 940      upperLimitsExpected["METWeak_2ltau_offZ_cut_75"] = 2.6;
 941      upperLimitsExpected["METWeak_3l_onZ_cut_20"] = 30.;
 942      upperLimitsExpected["METWeak_3l_onZ_cut_50"] = 10.;
 943      upperLimitsExpected["METWeak_3l_onZ_cut_75"] = 5.4;
 944      upperLimitsExpected["METWeak_2ltau_onZ_cut_20"] = 88.;
 945      upperLimitsExpected["METWeak_2ltau_onZ_cut_50"] = 5.5;
 946      upperLimitsExpected["METWeak_2ltau_onZ_cut_75"] = 2.2;
 947      upperLimitsExpected["Meff_3l_offZ_cut_0"] = 11.;
 948      upperLimitsExpected["Meff_3l_offZ_cut_150"] = 8.8;
 949      upperLimitsExpected["Meff_3l_offZ_cut_300"] = 3.7;
 950      upperLimitsExpected["Meff_3l_offZ_cut_500"] = 2.1;
 951      upperLimitsExpected["Meff_2ltau_offZ_cut_0"] = 23.;
 952      upperLimitsExpected["Meff_2ltau_offZ_cut_150"] = 13.;
 953      upperLimitsExpected["Meff_2ltau_offZ_cut_300"] = 4.9;
 954      upperLimitsExpected["Meff_2ltau_offZ_cut_500"] = 2.4;
 955      upperLimitsExpected["Meff_3l_onZ_cut_0"] = 33.;
 956      upperLimitsExpected["Meff_3l_onZ_cut_150"] = 25.;
 957      upperLimitsExpected["Meff_3l_onZ_cut_300"] = 9.;
 958      upperLimitsExpected["Meff_3l_onZ_cut_500"] = 3.9;
 959      upperLimitsExpected["Meff_2ltau_onZ_cut_0"] = 94.;
 960      upperLimitsExpected["Meff_2ltau_onZ_cut_150"] = 35.;
 961      upperLimitsExpected["Meff_2ltau_onZ_cut_300"] = 6.8;
 962      upperLimitsExpected["Meff_2ltau_onZ_cut_500"] = 2.5;
 963      upperLimitsExpected["MeffStrong_3l_offZ_cut_0"] = 3.9;
 964      upperLimitsExpected["MeffStrong_3l_offZ_cut_150"] = 3.9;
 965      upperLimitsExpected["MeffStrong_3l_offZ_cut_300"] = 3.0;
 966      upperLimitsExpected["MeffStrong_3l_offZ_cut_500"] = 2.0;
 967      upperLimitsExpected["MeffStrong_2ltau_offZ_cut_0"] = 3.8;
 968      upperLimitsExpected["MeffStrong_2ltau_offZ_cut_150"] = 3.9;
 969      upperLimitsExpected["MeffStrong_2ltau_offZ_cut_300"] = 3.1;
 970      upperLimitsExpected["MeffStrong_2ltau_offZ_cut_500"] = 1.6;
 971      upperLimitsExpected["MeffStrong_3l_onZ_cut_0"] = 6.9;
 972      upperLimitsExpected["MeffStrong_3l_onZ_cut_150"] = 7.1;
 973      upperLimitsExpected["MeffStrong_3l_onZ_cut_300"] = 4.9;
 974      upperLimitsExpected["MeffStrong_3l_onZ_cut_500"] = 3.0;
 975      upperLimitsExpected["MeffStrong_2ltau_onZ_cut_0"] = 2.4;
 976      upperLimitsExpected["MeffStrong_2ltau_onZ_cut_150"] = 2.5;
 977      upperLimitsExpected["MeffStrong_2ltau_onZ_cut_300"] = 2.0;
 978      upperLimitsExpected["MeffStrong_2ltau_onZ_cut_500"] = 1.1;
 979
 980      if (observed) return upperLimitsObserved[signal_region];
 981      else          return upperLimitsExpected[signal_region];
 982    }
 983
 984
 985    /// Function checking if there is an OSSF lepton pair or a combination of 3 leptons with an invariant mass close to the Z mass
 986    /// @todo Should the reference Z mass be 91.2?
 987    int isonZ (const Particles& particles)  {
 988      int onZ = 0;
 989      double best_mass_2 = 999.;
 990      double best_mass_3 = 999.;
 991
 992      // Loop over all 2 particle combinations to find invariant mass of OSSF pair closest to Z mass
 993      for ( const Particle& p1 : particles  )  {
 994        for ( const Particle& p2 : particles  )  {
 995          double mass_difference_2_old = fabs(91.0 - best_mass_2);
 996          double mass_difference_2_new = fabs(91.0 - (p1.momentum() + p2.momentum()).mass()/GeV);
 997
 998          // If particle combination is OSSF pair calculate mass difference to Z mass
 999          if ( (p1.pid()*p2.pid() == -121 || p1.pid()*p2.pid() == -169) )  {
1000
1001            // Get invariant mass closest to Z mass
1002            if (mass_difference_2_new < mass_difference_2_old)
1003              best_mass_2 = (p1.momentum() + p2.momentum()).mass()/GeV;
1004
1005            // In case there is an OSSF pair take also 3rd lepton into account (e.g. from FSR and photon to electron conversion)
1006            for ( const Particle & p3 : particles  )  {
1007              double mass_difference_3_old = fabs(91.0 - best_mass_3);
1008              double mass_difference_3_new = fabs(91.0 - (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV);
1009              if (mass_difference_3_new < mass_difference_3_old)
1010                best_mass_3 = (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV;
1011            }
1012          }
1013        }
1014      }
1015
1016      // Pick the minimum invariant mass of the best OSSF pair combination and the best 3 lepton combination
1017      // If this mass is in a 20 GeV window around the Z mass, the event is classified as onZ
1018      double best_mass = min(best_mass_2, best_mass_3);
1019      if (fabs(91.0 - best_mass) < 20) onZ = 1;
1020      return onZ;
1021    }
1022
1023    /// @}
1024
1025
1026  private:
1027
1028    /// Histograms
1029    /// @{
1030    Histo1DPtr _h_HTlep_all, _h_HTjets_all, _h_MET_all, _h_Meff_all;
1031    Histo1DPtr _h_pt_1_3l, _h_pt_2_3l, _h_pt_3_3l, _h_pt_1_2ltau, _h_pt_2_2ltau, _h_pt_3_2ltau;
1032    Histo1DPtr _h_e_n, _h_mu_n, _h_tau_n;
1033    Histo1DPtr _h_excluded;
1034    /// @}
1035
1036    /// Fiducial efficiencies to model the effects of the ATLAS detector
1037    bool _use_fiducial_lepton_efficiency;
1038
1039    /// List of signal regions and event counts per signal region
1040    vector<string> _signal_regions;
1041
1042    map<string, CounterPtr> _eventCountsPerSR;
1043
1044  };
1045
1046
1047  RIVET_DECLARE_PLUGIN(ATLAS_2012_I1204447);
1048
1049}