rivet is hosted by Hepforge, IPPP Durham
ATLAS_2012_I1204447.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/FinalState.hh"
00004 #include "Rivet/Projections/ChargedFinalState.hh"
00005 #include "Rivet/Projections/VisibleFinalState.hh"
00006 #include "Rivet/Projections/VetoedFinalState.hh"
00007 #include "Rivet/Projections/IdentifiedFinalState.hh"
00008 #include "Rivet/Projections/UnstableFinalState.hh"
00009 #include "Rivet/Projections/FastJets.hh"
00010 
00011 namespace Rivet {
00012 
00013 
00014   class ATLAS_2012_I1204447 : public Analysis {
00015   public:
00016 
00017     /// Constructor
00018     ATLAS_2012_I1204447()
00019       : Analysis("ATLAS_2012_I1204447") {  }
00020 
00021 
00022     /// Book histograms and initialise projections before the run
00023     void init() {
00024 
00025       // To calculate the acceptance without having the fiducial lepton efficiencies included, this part can be turned off
00026       _use_fiducial_lepton_efficiency = true;
00027 
00028       // Random numbers for simulation of ATLAS detector reconstruction efficiency
00029       srand(160385);
00030 
00031       // Read in all signal regions
00032       _signal_regions = getSignalRegions();
00033 
00034       // Set number of events per signal region to 0
00035       for (size_t i = 0; i < _signal_regions.size(); i++)
00036         _eventCountsPerSR[_signal_regions[i]] = 0.0;
00037 
00038       // Final state including all charged and neutral particles
00039       const FinalState fs(-5.0, 5.0, 1*GeV);
00040       addProjection(fs, "FS");
00041 
00042       // Final state including all charged particles
00043       addProjection(ChargedFinalState(-2.5,2.5, 1*GeV), "CFS");
00044 
00045       // Final state including all visible particles (to calculate MET, Jets etc.)
00046       addProjection(VisibleFinalState(-5.0,5.0), "VFS");
00047 
00048       // Final state including all AntiKt 04 Jets
00049       VetoedFinalState vfs;
00050       vfs.addVetoPairId(PID::MUON);
00051       addProjection(FastJets(vfs, FastJets::ANTIKT, 0.4), "AntiKtJets04");
00052 
00053       // Final state including all unstable particles (including taus)
00054       addProjection(UnstableFinalState(-5.0,5.0, 5*GeV),"UFS");
00055 
00056       // Final state including all electrons
00057       IdentifiedFinalState elecs(-2.47,2.47, 10*GeV);
00058       elecs.acceptIdPair(PID::ELECTRON);
00059       addProjection(elecs, "elecs");
00060 
00061       // Final state including all muons
00062       IdentifiedFinalState muons(-2.5,2.5, 10*GeV);
00063       muons.acceptIdPair(PID::MUON);
00064       addProjection(muons, "muons");
00065 
00066       // Book histograms
00067       _h_HTlep_all  = bookHisto1D("HTlep_all" , 30, 0, 1500);
00068       _h_HTjets_all = bookHisto1D("HTjets_all", 30, 0, 1500);
00069       _h_MET_all    = bookHisto1D("MET_all"   , 20, 0, 1000);
00070       _h_Meff_all   = bookHisto1D("Meff_all"  , 30, 0, 3000);
00071 
00072       _h_e_n        = bookHisto1D("e_n"  , 10, -0.5, 9.5);
00073       _h_mu_n       = bookHisto1D("mu_n" , 10, -0.5, 9.5);
00074       _h_tau_n      = bookHisto1D("tau_n", 10, -0.5, 9.5);
00075 
00076       _h_pt_1_3l    = bookHisto1D("pt_1_3l", 100, 0, 2000);
00077       _h_pt_2_3l    = bookHisto1D("pt_2_3l", 100, 0, 2000);
00078       _h_pt_3_3l    = bookHisto1D("pt_3_3l", 100, 0, 2000);
00079       _h_pt_1_2ltau = bookHisto1D("pt_1_2ltau", 100, 0, 2000);
00080       _h_pt_2_2ltau = bookHisto1D("pt_2_2ltau", 100, 0, 2000);
00081       _h_pt_3_2ltau = bookHisto1D("pt_3_2ltau", 100, 0, 2000);
00082 
00083       _h_excluded   = bookHisto1D("excluded", 2, -0.5, 1.5);
00084     }
00085 
00086 
00087     /// Perform the per-event analysis
00088     void analyze(const Event& event) {
00089 
00090       // Muons
00091       Particles muon_candidates;
00092       const Particles charged_tracks    = applyProjection<ChargedFinalState>(event, "CFS").particles();
00093       const Particles visible_particles = applyProjection<VisibleFinalState>(event, "VFS").particles();
00094       foreach (const Particle& mu, applyProjection<IdentifiedFinalState>(event, "muons").particlesByPt()) {
00095         // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of muon itself)
00096         double pTinCone = -mu.pT();
00097         foreach (const Particle& track, charged_tracks) {
00098           if (deltaR(mu.momentum(), track.momentum()) < 0.3)
00099             pTinCone += track.pT();
00100         }
00101 
00102         // Calculate eTCone30 variable (pT of all visible particles within dR<0.3)
00103         double eTinCone = 0.;
00104         foreach (const Particle& visible_particle, visible_particles) {
00105           if (visible_particle.abspid() != PID::MUON && inRange(deltaR(mu.momentum(), visible_particle.momentum()), 0.1, 0.3))
00106             eTinCone += visible_particle.pT();
00107         }
00108 
00109         // Apply reconstruction efficiency and simulate reco
00110         int muon_id = 13;
00111         if ( mu.hasAncestor(15) || mu.hasAncestor(-15)) muon_id = 14;
00112         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(muon_id, mu) : 1.0;
00113         const bool keep_muon = rand()/static_cast<double>(RAND_MAX) <= eff;
00114 
00115         // Keep muon if pTCone30/pT < 0.15 and eTCone30/pT < 0.2 and reconstructed
00116         if (keep_muon && pTinCone/mu.pT() <= 0.15 && eTinCone/mu.pT() < 0.2)
00117           muon_candidates.push_back(mu);
00118       }
00119 
00120 
00121       // Electrons
00122       Particles electron_candidates;
00123       foreach (const Particle& e, applyProjection<IdentifiedFinalState>(event, "elecs").particlesByPt()) {
00124         // Neglect electrons in crack regions
00125         if (inRange(e.abseta(), 1.37, 1.52)) continue;
00126 
00127         // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of electron itself)
00128         double pTinCone = -e.pT();
00129         foreach (const Particle& track, charged_tracks) {
00130           if (deltaR(e.momentum(), track.momentum()) < 0.3) pTinCone += track.pT();
00131         }
00132 
00133         // Calculate eTCone30 variable (pT of all visible particles (except muons) within dR<0.3)
00134         double eTinCone = 0.;
00135         foreach (const Particle& visible_particle, visible_particles) {
00136           if (visible_particle.abspid() != PID::MUON && inRange(deltaR(e.momentum(), visible_particle.momentum()), 0.1, 0.3))
00137             eTinCone += visible_particle.pT();
00138         }
00139 
00140         // Apply reconstruction efficiency and simulate reco
00141         int elec_id = 11;
00142         if (e.hasAncestor(15) || e.hasAncestor(-15)) elec_id = 12;
00143         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(elec_id, e) : 1.0;
00144         const bool keep_elec = rand()/static_cast<double>(RAND_MAX) <= eff;
00145 
00146         // Keep electron if pTCone30/pT < 0.13 and eTCone30/pT < 0.2 and reconstructed
00147         if (keep_elec && pTinCone/e.pT() <= 0.13 && eTinCone/e.pT() < 0.2)
00148           electron_candidates.push_back(e);
00149       }
00150 
00151 
00152       // Taus
00153       /// @todo This could benefit from a tau finder projection
00154       Particles tau_candidates;
00155       foreach (const Particle& tau, applyProjection<UnstableFinalState>(event, "UFS").particlesByPt()) {
00156         // Only pick taus out of all unstable particles
00157         if (tau.abspid() != PID::TAU) continue;
00158 
00159         // Check that tau has decayed into daughter particles
00160         /// @todo Huh? Unstable taus with no decay vtx? Can use Particle.isStable()? But why in this situation?
00161         if (tau.genParticle()->end_vertex() == 0) continue;
00162 
00163         // Calculate visible tau pT from pT of tau neutrino in tau decay for pT and |eta| cuts
00164         const FourMomentum tau_neutrino_mom = get_tau_neutrino_mom(tau);
00165         const FourMomentum visible_tau_mom = tau.momentum() - tau_neutrino_mom;
00166         if (visible_tau_mom.pT() < 15*GeV || visible_tau_mom.abseta() > 2.5) continue;
00167 
00168         // Get prong number (number of tracks) in tau decay and check if tau decays leptonically
00169         unsigned int nprong = 0;
00170         bool lep_decaying_tau = false;
00171         get_prong_number(tau.genParticle(), nprong, lep_decaying_tau);
00172 
00173         // Apply reconstruction efficiency
00174         int tau_id = 15;
00175         if (nprong == 1) tau_id = 15;
00176         else if (nprong == 3) tau_id = 16;
00177 
00178         // Get fiducial lepton efficiency simulate reco efficiency
00179         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(tau_id, tau) : 1.0;
00180         const bool keep_tau = rand()/static_cast<double>(RAND_MAX) <= eff;
00181 
00182         // Keep tau if nprong = 1, it decays hadronically, and it's reconstructed by the detector
00183         if ( !lep_decaying_tau && nprong == 1 && keep_tau) tau_candidates.push_back(tau);
00184       }
00185 
00186 
00187       // Jets (all anti-kt R=0.4 jets with pT > 25 GeV and eta < 4.9)
00188       Jets jet_candidates;
00189       foreach (const Jet& jet, applyProjection<FastJets>(event, "AntiKtJets04").jetsByPt(25*GeV)) {
00190         if (jet.abseta() < 4.9) jet_candidates.push_back(jet);
00191       }
00192 
00193 
00194       // ETmiss
00195       Particles vfs_particles = applyProjection<VisibleFinalState>(event, "VFS").particles();
00196       FourMomentum pTmiss;
00197       foreach (const Particle& p, vfs_particles) pTmiss -= p.momentum();
00198       double eTmiss = pTmiss.pT()/GeV;
00199 
00200 
00201       //------------------
00202       // Overlap removal
00203 
00204       // electron - electron
00205       Particles electron_candidates_2;
00206       for (size_t ie = 0; ie < electron_candidates.size(); ++ie) {
00207         const Particle & e = electron_candidates[ie];
00208         bool away = true;
00209         // If electron pair within dR < 0.1: remove electron with lower pT
00210         for (size_t ie2=0; ie2 < electron_candidates_2.size(); ++ie2) {
00211           if ( deltaR( e.momentum(), electron_candidates_2[ie2].momentum()) < 0.1 ) {
00212             away = false;
00213             break;
00214           }
00215         }
00216         // If isolated keep it
00217         if ( away )
00218           electron_candidates_2.push_back( e );
00219       }
00220       // jet - electron
00221       Jets recon_jets;
00222       foreach (const Jet& jet, jet_candidates) {
00223         bool away = true;
00224         // if jet within dR < 0.2 of electron: remove jet
00225         foreach (const Particle& e, electron_candidates_2) {
00226           if (deltaR(e.momentum(), jet.momentum()) < 0.2) {
00227             away = false;
00228             break;
00229           }
00230         }
00231         // jet - tau
00232         if (away)  {
00233           // If jet within dR < 0.2 of tau: remove jet
00234           foreach (const Particle& tau, tau_candidates) {
00235             if (deltaR(tau.momentum(), jet.momentum()) < 0.2) {
00236               away = false;
00237               break;
00238             }
00239           }
00240         }
00241         // If isolated keep it
00242         if ( away )
00243           recon_jets.push_back( jet );
00244       }
00245 
00246 
00247       // electron - jet
00248       Particles recon_leptons, recon_e;
00249       for (size_t ie = 0; ie < electron_candidates_2.size(); ++ie) {
00250         const Particle& e = electron_candidates_2[ie];
00251         // If electron within 0.2 < dR < 0.4 from any jets: remove electron
00252         bool away = true;
00253         foreach (const Jet& jet, recon_jets) {
00254           if (deltaR(e.momentum(), jet.momentum()) < 0.4) {
00255             away = false;
00256             break;
00257           }
00258         }
00259         // electron - muon
00260         // if electron within dR < 0.1 of a muon: remove electron
00261         if (away) {
00262           foreach (const Particle& mu, muon_candidates) {
00263             if (deltaR(mu.momentum(), e.momentum()) < 0.1) {
00264               away = false;
00265               break;
00266             }
00267           }
00268         }
00269         // If isolated keep it
00270         if (away)  {
00271           recon_e += e;
00272           recon_leptons += e;
00273         }
00274       }
00275 
00276 
00277       // tau - electron
00278       Particles recon_tau;
00279       foreach ( const Particle& tau, tau_candidates ) {
00280         bool away = true;
00281         // If tau within dR < 0.2 of an electron: remove tau
00282         foreach ( const Particle& e, recon_e ) {
00283           if (deltaR( tau.momentum(), e.momentum()) < 0.2) {
00284             away = false;
00285             break;
00286           }
00287         }
00288         // tau - muon
00289         // If tau within dR < 0.2 of a muon: remove tau
00290         if (away)  {
00291           foreach (const Particle& mu, muon_candidates) {
00292             if (deltaR(tau.momentum(), mu.momentum()) < 0.2) {
00293               away = false;
00294               break;
00295             }
00296           }
00297         }
00298         // If isolated keep it
00299         if (away) recon_tau.push_back( tau );
00300       }
00301 
00302       // Muon - jet isolation
00303       Particles recon_mu, trigger_mu;
00304       // If muon within dR < 0.4 of a jet, remove muon
00305       foreach (const Particle& mu, muon_candidates) {
00306         bool away = true;
00307         foreach (const Jet& jet, recon_jets) {
00308           if ( deltaR( mu.momentum(), jet.momentum()) < 0.4 ) {
00309             away = false;
00310             break;
00311           }
00312         }
00313         if (away) {
00314           recon_mu.push_back( mu );
00315           recon_leptons.push_back( mu );
00316           if (mu.abseta() < 2.4) trigger_mu.push_back( mu );
00317         }
00318       }
00319 
00320       // End overlap removal
00321       //------------------
00322 
00323 
00324       // Jet cleaning
00325       if (rand()/static_cast<double>(RAND_MAX) <= 0.42) {
00326         foreach (const Jet& jet, recon_jets) {
00327           const double eta = jet.rapidity();
00328           const double phi = jet.azimuthalAngle(MINUSPI_PLUSPI);
00329           if (jet.pT() > 25*GeV && inRange(eta, -0.1, 1.5) && inRange(phi, -0.9, -0.5)) vetoEvent;
00330         }
00331       }
00332 
00333 
00334       // Post-isolation event cuts
00335       // Require at least 3 charged tracks in event
00336       if (charged_tracks.size() < 3) vetoEvent;
00337 
00338       // And at least one e/mu passing trigger
00339       if (!( !recon_e   .empty() && recon_e[0]   .pT() > 25*GeV)  &&
00340           !( !trigger_mu.empty() && trigger_mu[0].pT() > 25*GeV) ) {
00341         MSG_DEBUG("Hardest lepton fails trigger");
00342         vetoEvent;
00343       }
00344 
00345       // And only accept events with at least 2 electrons and muons and at least 3 leptons in total
00346       if (recon_mu.size() + recon_e.size() + recon_tau.size() < 3 || recon_leptons.size() < 2) vetoEvent;
00347 
00348       // Now it's worth getting the event weight
00349       const double weight = event.weight();
00350 
00351       // Sort leptons by decreasing pT
00352       sortByPt(recon_leptons);
00353       sortByPt(recon_tau);
00354 
00355       // Calculate HTlep, fill lepton pT histograms & store chosen combination of 3 leptons
00356       double HTlep = 0.;
00357       Particles chosen_leptons;
00358       if ( recon_leptons.size() > 2 ) {
00359         _h_pt_1_3l->fill(recon_leptons[0].perp()/GeV, weight);
00360         _h_pt_2_3l->fill(recon_leptons[1].perp()/GeV, weight);
00361         _h_pt_3_3l->fill(recon_leptons[2].perp()/GeV, weight);
00362         HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_leptons[2].pT())/GeV;
00363         chosen_leptons.push_back( recon_leptons[0] );
00364         chosen_leptons.push_back( recon_leptons[1] );
00365         chosen_leptons.push_back( recon_leptons[2] );
00366       }
00367       else {
00368         _h_pt_1_2ltau->fill(recon_leptons[0].perp()/GeV, weight);
00369         _h_pt_2_2ltau->fill(recon_leptons[1].perp()/GeV, weight);
00370         _h_pt_3_2ltau->fill(recon_tau[0].perp()/GeV,     weight);
00371         HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_tau[0].pT())/GeV ;
00372         chosen_leptons.push_back( recon_leptons[0] );
00373         chosen_leptons.push_back( recon_leptons[1] );
00374         chosen_leptons.push_back( recon_tau[0] );
00375       }
00376 
00377       // Number of prompt e/mu and had taus
00378       _h_e_n  ->fill(recon_e.size()  , weight);
00379       _h_mu_n ->fill(recon_mu.size() , weight);
00380       _h_tau_n->fill(recon_tau.size(), weight);
00381 
00382       // Calculate HTjets
00383       double HTjets = 0.;
00384       foreach ( const Jet & jet, recon_jets )
00385         HTjets += jet.perp()/GeV;
00386 
00387       // Calculate meff
00388       double meff = eTmiss + HTjets;
00389       Particles all_leptons;
00390       foreach ( const Particle & e , recon_e  )  {
00391         meff += e.perp()/GeV;
00392         all_leptons.push_back( e );
00393       }
00394       foreach ( const Particle & mu, recon_mu )  {
00395         meff += mu.perp()/GeV;
00396         all_leptons.push_back( mu );
00397       }
00398       foreach ( const Particle & tau, recon_tau )  {
00399         meff += tau.perp()/GeV;
00400         all_leptons.push_back( tau );
00401       }
00402 
00403       // Fill histogram of kinematic variables
00404       _h_HTlep_all ->fill(HTlep , weight);
00405       _h_HTjets_all->fill(HTjets, weight);
00406       _h_MET_all   ->fill(eTmiss, weight);
00407       _h_Meff_all  ->fill(meff  , weight);
00408 
00409       // Determine signal region (3l/2ltau, onZ/offZ)
00410       string basic_signal_region;
00411       if ( recon_mu.size() + recon_e.size() > 2 )
00412         basic_signal_region += "3l_";
00413       else if ( (recon_mu.size() + recon_e.size() == 2) && (recon_tau.size() > 0))
00414         basic_signal_region += "2ltau_";
00415       // Is there an OSSF pair or a three lepton combination with an invariant mass close to the Z mass
00416       int onZ = isonZ(chosen_leptons);
00417       if      (onZ == 1)   basic_signal_region += "onZ";
00418       else if (onZ == 0)   basic_signal_region += "offZ";
00419       // Check in which signal regions this event falls and adjust event counters
00420       fillEventCountsPerSR(basic_signal_region, onZ, HTlep, eTmiss, HTjets, meff, weight);
00421     }
00422 
00423 
00424     /// Normalise histograms etc., after the run
00425     void finalize() {
00426 
00427       // Normalize to an integrated luminosity of 1 fb-1
00428       double norm = crossSection()/femtobarn/sumOfWeights();
00429       string best_signal_region = "";
00430       double ratio_best_SR = 0.;
00431 
00432       // Loop over all signal regions and find signal region with best sensitivity (ratio signal events/visible cross-section)
00433       for (size_t i = 0; i < _signal_regions.size(); i++)  {
00434         double signal_events = _eventCountsPerSR[_signal_regions[i]] * norm;
00435         // Use expected upper limits to find best signal region
00436         double UL95  = getUpperLimit(_signal_regions[i], false);
00437         double ratio = signal_events / UL95;
00438         if (ratio > ratio_best_SR)  {
00439           best_signal_region = _signal_regions[i];
00440           ratio_best_SR = ratio;
00441         }
00442       }
00443 
00444       double signal_events_best_SR = _eventCountsPerSR[best_signal_region] * norm;
00445       double exp_UL_best_SR = getUpperLimit(best_signal_region, false);
00446       double obs_UL_best_SR = getUpperLimit(best_signal_region, true);
00447 
00448       // Print out result
00449       cout << "----------------------------------------------------------------------------------------" << endl;
00450       cout << "Best signal region: " << best_signal_region << endl;
00451       cout << "Normalized number of signal events in this best signal region (per fb-1): " << signal_events_best_SR << endl;
00452       cout << "Efficiency*Acceptance: " <<  _eventCountsPerSR[best_signal_region]/sumOfWeights() << endl;
00453       cout << "Cross-section [fb]: " << crossSection()/femtobarn << endl;
00454       cout << "Expected visible cross-section (per fb-1): " << exp_UL_best_SR << endl;
00455       cout << "Ratio (signal events / expected visible cross-section): " << ratio_best_SR << endl;
00456       cout << "Observed visible cross-section (per fb-1): " << obs_UL_best_SR << endl;
00457       cout << "Ratio (signal events / observed visible cross-section): " <<  signal_events_best_SR/obs_UL_best_SR << endl;
00458       cout << "----------------------------------------------------------------------------------------" << endl;
00459 
00460       cout << "Using the EXPECTED limits (visible cross-section) of the analysis: " << endl;
00461       if (signal_events_best_SR > exp_UL_best_SR)  {
00462         cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
00463         _h_excluded->fill(1);
00464       }
00465       else  {
00466         cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
00467         _h_excluded->fill(0);
00468       }
00469       cout << "----------------------------------------------------------------------------------------" << endl;
00470 
00471       cout << "Using the OBSERVED limits (visible cross-section) of the analysis: " << endl;
00472       if (signal_events_best_SR > obs_UL_best_SR)  {
00473         cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
00474         _h_excluded->fill(1);
00475       }
00476       else  {
00477         cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
00478         _h_excluded->fill(0);
00479       }
00480       cout << "----------------------------------------------------------------------------------------" << endl;
00481 
00482 
00483       // Normalize to cross section
00484       if (norm != 0)  {
00485         scale(_h_HTlep_all,  norm);
00486         scale(_h_HTjets_all, norm);
00487         scale(_h_MET_all,    norm);
00488         scale(_h_Meff_all,   norm);
00489 
00490         scale(_h_pt_1_3l,    norm);
00491         scale(_h_pt_2_3l,    norm);
00492         scale(_h_pt_3_3l,    norm);
00493         scale(_h_pt_1_2ltau, norm);
00494         scale(_h_pt_2_2ltau, norm);
00495         scale(_h_pt_3_2ltau, norm);
00496 
00497         scale(_h_e_n,        norm);
00498         scale(_h_mu_n,       norm);
00499         scale(_h_tau_n,      norm);
00500 
00501         scale(_h_excluded,   signal_events_best_SR);
00502       }
00503     }
00504 
00505 
00506     /// Helper functions
00507     //@{
00508 
00509     /// Function giving a list of all signal regions
00510     vector<string> getSignalRegions()  {
00511 
00512       // List of basic signal regions
00513       vector<string> basic_signal_regions;
00514       basic_signal_regions.push_back("3l_offZ");
00515       basic_signal_regions.push_back("3l_onZ");
00516       basic_signal_regions.push_back("2ltau_offZ");
00517       basic_signal_regions.push_back("2ltau_onZ");
00518 
00519       // List of kinematic variables
00520       vector<string> kinematic_variables;
00521       kinematic_variables.push_back("HTlep");
00522       kinematic_variables.push_back("METStrong");
00523       kinematic_variables.push_back("METWeak");
00524       kinematic_variables.push_back("Meff");
00525       kinematic_variables.push_back("MeffStrong");
00526 
00527       vector<string> signal_regions;
00528       // Loop over all kinematic variables and basic signal regions
00529       for (size_t i0 = 0; i0 < kinematic_variables.size(); i0++)  {
00530         for (size_t i1 = 0; i1 < basic_signal_regions.size(); i1++)  {
00531           // Is signal region onZ?
00532           int onZ = (basic_signal_regions[i1].find("onZ") != string::npos) ? 1 : 0;
00533           // Get cut values for this kinematic variable
00534           vector<int> cut_values = getCutsPerSignalRegion(kinematic_variables[i0], onZ);
00535           // Loop over all cut values
00536           for (size_t i2 = 0; i2 < cut_values.size(); i2++)  {
00537             // push signal region into vector
00538             signal_regions.push_back( (kinematic_variables[i0] + "_" + basic_signal_regions[i1] + "_cut_" + toString(i2)) );
00539           }
00540         }
00541       }
00542       return signal_regions;
00543     }
00544 
00545 
00546     /// Function giving all cut vales per kinematic variable (taking onZ for MET into account)
00547     vector<int> getCutsPerSignalRegion(const string& signal_region, int onZ=0)  {
00548       vector<int> cutValues;
00549 
00550       // Cut values for HTlep
00551       if (signal_region.compare("HTlep") == 0)  {
00552         cutValues.push_back(0);
00553         cutValues.push_back(100);
00554         cutValues.push_back(150);
00555         cutValues.push_back(200);
00556         cutValues.push_back(300);
00557       }
00558       // Cut values for METStrong (HTjets > 100 GeV) and METWeak (HTjets < 100 GeV)
00559       else if (signal_region.compare("METStrong") == 0 || signal_region.compare("METWeak") == 0)  {
00560         if      (onZ == 0) cutValues.push_back(0);
00561         else if (onZ == 1) cutValues.push_back(20);
00562         cutValues.push_back(50);
00563         cutValues.push_back(75);
00564       }
00565       // Cut values for Meff and MeffStrong (MET > 75 GeV)
00566       if (signal_region.compare("Meff") == 0 || signal_region.compare("MeffStrong") == 0)  {
00567         cutValues.push_back(0);
00568         cutValues.push_back(150);
00569         cutValues.push_back(300);
00570         cutValues.push_back(500);
00571       }
00572 
00573       return cutValues;
00574     }
00575 
00576 
00577     /// function fills map EventCountsPerSR by looping over all signal regions
00578     /// and looking if the event falls into this signal region
00579     void fillEventCountsPerSR(const string& basic_signal_region, int onZ,
00580                               double HTlep, double eTmiss,
00581                               double HTjets, double meff,
00582                               double weight)  {
00583 
00584       // Get cut values for HTlep, loop over them and add event if cut is passed
00585       vector<int> cut_values = getCutsPerSignalRegion("HTlep", onZ);
00586       for (size_t i = 0; i < cut_values.size(); i++)  {
00587         if (HTlep > cut_values[i])
00588           _eventCountsPerSR[("HTlep_" + basic_signal_region + "_cut_" + toString(cut_values[i]))] += weight;
00589       }
00590 
00591       // Get cut values for METStrong, loop over them and add event if cut is passed
00592       cut_values = getCutsPerSignalRegion("METStrong", onZ);
00593       for (size_t i = 0; i < cut_values.size(); i++)  {
00594         if (eTmiss > cut_values[i] && HTjets > 100.)
00595           _eventCountsPerSR[("METStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))] += weight;
00596       }
00597 
00598       // Get cut values for METWeak, loop over them and add event if cut is passed
00599       cut_values = getCutsPerSignalRegion("METWeak", onZ);
00600       for (size_t i = 0; i < cut_values.size(); i++)  {
00601         if (eTmiss > cut_values[i] && HTjets <= 100.)
00602           _eventCountsPerSR[("METWeak_" + basic_signal_region + "_cut_" + toString(cut_values[i]))] += weight;
00603       }
00604 
00605       // Get cut values for Meff, loop over them and add event if cut is passed
00606       cut_values = getCutsPerSignalRegion("Meff", onZ);
00607       for (size_t i = 0; i < cut_values.size(); i++)  {
00608         if (meff > cut_values[i])
00609           _eventCountsPerSR[("Meff_" + basic_signal_region + "_cut_" + toString(cut_values[i]))] += weight;
00610       }
00611 
00612       // Get cut values for MeffStrong, loop over them and add event if cut is passed
00613       cut_values = getCutsPerSignalRegion("MeffStrong", onZ);
00614       for (size_t i = 0; i < cut_values.size(); i++)  {
00615         if (meff > cut_values[i] && eTmiss > 75.)
00616           _eventCountsPerSR[("MeffStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))] += weight;
00617       }
00618     }
00619 
00620 
00621     /// Function returning 4-vector of daughter-particle if it is a tau neutrino
00622     /// @todo Move to TauFinder and make less HepMC-ish
00623     FourMomentum get_tau_neutrino_mom(const Particle& p)  {
00624       assert(p.abspid() == PID::TAU);
00625       const GenVertex* dv = p.genParticle()->end_vertex();
00626       assert(dv != NULL);
00627       for (GenVertex::particles_out_const_iterator pp = dv->particles_out_const_begin(); pp != dv->particles_out_const_end(); ++pp) {
00628         if ((*pp)->pdg_id() == PID::NU_TAU) return FourMomentum((*pp)->momentum());
00629       }
00630       return FourMomentum();
00631     }
00632 
00633 
00634     /// Function calculating the prong number of taus
00635     /// @todo Move to TauFinder and make less HepMC-ish
00636     void get_prong_number(const GenParticle* p, unsigned int& nprong, bool& lep_decaying_tau) {
00637       assert(p != NULL);
00638       //const int tau_barcode = p->barcode();
00639       const GenVertex* dv = p->end_vertex();
00640       assert(dv != NULL);
00641       for (GenVertex::particles_out_const_iterator pp = dv->particles_out_const_begin(); pp != dv->particles_out_const_end(); ++pp) {
00642         // If they have status 1 and are charged they will produce a track and the prong number is +1
00643         if ((*pp)->status() == 1 )  {
00644           const int id = (*pp)->pdg_id();
00645           if (Rivet::PID::charge(id) != 0 ) ++nprong;
00646           // Check if tau decays leptonically
00647           // @todo Can a tau decay include a tau in its decay daughters?!
00648           if ((abs(id) == PID::ELECTRON || abs(id) == PID::MUON || abs(id) == PID::TAU) && abs(p->pdg_id()) == PID::TAU) lep_decaying_tau = true;
00649         }
00650         // If the status of the daughter particle is 2 it is unstable and the further decays are checked
00651         else if ((*pp)->status() == 2 )  {
00652           get_prong_number(*pp, nprong, lep_decaying_tau);
00653         }
00654       }
00655     }
00656 
00657 
00658     /// Function giving fiducial lepton efficiency
00659     double apply_reco_eff(int flavor, const Particle& p) {
00660       float pt = p.pT()/GeV;
00661       float eta = p.eta();
00662 
00663       double eff = 0.;
00664       //double err = 0.;
00665 
00666       if (flavor == 11) { // weight prompt electron -- now including data/MC ID SF in eff.
00667         //float rho = 0.820;
00668         float p0 = 7.34;  float p1 = 0.8977;
00669         //float ep0= 0.5 ;  float ep1= 0.0087;
00670         eff = p1 - p0/pt;
00671 
00672         //double err0 = ep0/pt; // d(eff)/dp0
00673         //double err1 = ep1;    // d(eff)/dp1
00674         //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
00675 
00676         double avgrate = 0.6867;
00677         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,};
00678         //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,};
00679         int ibin = 3;
00680 
00681         if (eta >= -2.5 && eta < -2.0) ibin = 0;
00682         if (eta >= -2.0 && eta < -1.5) ibin = 1;
00683         if (eta >= -1.5 && eta < -1.0) ibin = 2;
00684         if (eta >= -1.0 && eta < -0.5) ibin = 3;
00685         if (eta >= -0.5 && eta < -0.1) ibin = 4;
00686         if (eta >= -0.1 && eta <  0.1) ibin = 5;
00687         if (eta >=  0.1 && eta <  0.5) ibin = 6;
00688         if (eta >=  0.5 && eta <  1.0) ibin = 7;
00689         if (eta >=  1.0 && eta <  1.5) ibin = 8;
00690         if (eta >=  1.5 && eta <  2.0) ibin = 9;
00691         if (eta >=  2.0 && eta <  2.5) ibin = 10;
00692 
00693         double eff_eta = wz_ele_eta[ibin];
00694         //double err_eta = ewz_ele_eta[ibin];
00695 
00696         eff = (eff*eff_eta)/avgrate;
00697       }
00698 
00699       if (flavor == 12)  { // weight electron from tau
00700         //float rho = 0.884;
00701         float p0 = 6.799;  float p1 = 0.842;
00702         //float ep0= 0.664;  float ep1= 0.016;
00703         eff = p1 - p0/pt;
00704 
00705         //double err0 = ep0/pt; // d(eff)/dp0
00706         //double err1 = ep1;    // d(eff)/dp1
00707         //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
00708 
00709         double avgrate = 0.5319;
00710         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,};
00711         //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,};
00712         int ibin = 3;
00713 
00714         if (eta >= -2.5 && eta < -2.0) ibin = 0;
00715         if (eta >= -2.0 && eta < -1.5) ibin = 1;
00716         if (eta >= -1.5 && eta < -1.0) ibin = 2;
00717         if (eta >= -1.0 && eta < -0.5) ibin = 3;
00718         if (eta >= -0.5 && eta < -0.1) ibin = 4;
00719         if (eta >= -0.1 && eta <  0.1) ibin = 5;
00720         if (eta >=  0.1 && eta <  0.5) ibin = 6;
00721         if (eta >=  0.5 && eta <  1.0) ibin = 7;
00722         if (eta >=  1.0 && eta <  1.5) ibin = 8;
00723         if (eta >=  1.5 && eta <  2.0) ibin = 9;
00724         if (eta >=  2.0 && eta <  2.5) ibin = 10;
00725 
00726         double eff_eta = wz_elet_eta[ibin];
00727         //double err_eta = ewz_elet_eta[ibin];
00728 
00729         eff = (eff*eff_eta)/avgrate;
00730 
00731       }
00732 
00733       if (flavor == 13)  {// weight prompt muon
00734 
00735         //if eta>0.1
00736         float p0 = -18.21;  float p1 = 14.83;  float p2 = 0.9312;
00737         //float ep0= 5.06;    float ep1= 1.9;    float ep2=0.00069;
00738 
00739         if ( fabs(eta) < 0.1)  {
00740           p0  = 7.459; p1 = 2.615; p2  = 0.5138;
00741           //ep0 = 10.4; ep1 = 4.934; ep2 = 0.0034;
00742         }
00743 
00744         double arg = ( pt-p0 )/( 2.*p1 ) ;
00745         eff = 0.5 * p2 * (1.+erf(arg));
00746         //err = 0.1*eff;
00747       }
00748 
00749       if (flavor == 14)  {// weight muon from tau
00750 
00751         if (fabs(eta) < 0.1) {
00752           float p0 = -1.756;  float p1 = 12.38;  float p2 = 0.4441;
00753           //float ep0= 10.39;   float ep1= 7.9;  float ep2=0.022;
00754           double arg = ( pt-p0 )/( 2.*p1 ) ;
00755           eff = 0.5 * p2 * (1.+erf(arg));
00756           //err = 0.1*eff;
00757         }
00758         else {
00759           float p0 = 2.102;  float p1 = 0.8293;
00760           //float ep0= 0.271;  float ep1= 0.0083;
00761           eff = p1 - p0/pt;
00762           //double err0 = ep0/pt; // d(eff)/dp0
00763           //double err1 = ep1;    // d(eff)/dp1
00764           //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
00765         }
00766       }
00767 
00768       if (flavor == 15)  {// weight hadronic tau 1p
00769 
00770         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,};
00771         //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,};
00772         int ibin = 0;
00773         if (pt > 15)  ibin = 1;
00774         if (pt > 20)  ibin = 2;
00775         if (pt > 25)  ibin = 3;
00776         if (pt > 30)  ibin = 4;
00777         if (pt > 40)  ibin = 5;
00778         if (pt > 50)  ibin = 6;
00779         if (pt > 60)  ibin = 7;
00780         if (pt > 80)  ibin = 8;
00781         if (pt > 100) ibin = 9;
00782         if (pt > 200) ibin = 10;
00783 
00784         eff = wz_tau1p[ibin];
00785         //err = ewz_tau1p[ibin];
00786 
00787 
00788         double avgrate = 0.1718;
00789         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,};
00790         //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,};
00791 
00792         ibin = 3;
00793         if (eta >= -2.5 && eta < -2.0) ibin = 0;
00794         if (eta >= -2.0 && eta < -1.5) ibin = 1;
00795         if (eta >= -1.5 && eta < -1.0) ibin = 2;
00796         if (eta >= -1.0 && eta < -0.5) ibin = 3;
00797         if (eta >= -0.5 && eta < -0.1) ibin = 4;
00798         if (eta >= -0.1 && eta <  0.1) ibin = 5;
00799         if (eta >=  0.1 && eta <  0.5) ibin = 6;
00800         if (eta >=  0.5 && eta <  1.0) ibin = 7;
00801         if (eta >=  1.0 && eta <  1.5) ibin = 8;
00802         if (eta >=  1.5 && eta <  2.0) ibin = 9;
00803         if (eta >=  2.0 && eta <  2.5) ibin = 10;
00804 
00805         double eff_eta = wz_tau1p_eta[ibin];
00806         //double err_eta = ewz_tau1p_eta[ibin];
00807 
00808         eff = (eff*eff_eta)/avgrate;
00809       }
00810 
00811       if (flavor == 16)  { //weight hadronic tau 3p
00812 
00813         float wz_tau3p[] = {0.000587199,0.00247181,0.0013031,0.00280112,};
00814         //float ewz_tau3p[] ={0.000415091,0.000617187,0.000582385,0.00197792,};
00815 
00816         int ibin = 0;
00817         if (pt > 15) ibin = 1;
00818         if (pt > 20) ibin = 2;
00819         if (pt > 40) ibin = 3;
00820         if (pt > 80) ibin = 4;
00821 
00822         eff = wz_tau3p[ibin];
00823         //err = ewz_tau3p[ibin];
00824       }
00825 
00826       return eff;
00827     }
00828 
00829 
00830     /// Function giving observed upper limit (visible cross-section)
00831     double getUpperLimit(const string& signal_region, bool observed)  {
00832       map<string,double> upperLimitsObserved;
00833       upperLimitsObserved["HTlep_3l_offZ_cut_0"] = 11.;
00834       upperLimitsObserved["HTlep_3l_offZ_cut_100"] = 8.7;
00835       upperLimitsObserved["HTlep_3l_offZ_cut_150"] = 4.0;
00836       upperLimitsObserved["HTlep_3l_offZ_cut_200"] = 4.4;
00837       upperLimitsObserved["HTlep_3l_offZ_cut_300"] = 1.6;
00838       upperLimitsObserved["HTlep_2ltau_offZ_cut_0"] = 25.;
00839       upperLimitsObserved["HTlep_2ltau_offZ_cut_100"] = 14.;
00840       upperLimitsObserved["HTlep_2ltau_offZ_cut_150"] = 6.1;
00841       upperLimitsObserved["HTlep_2ltau_offZ_cut_200"] = 3.3;
00842       upperLimitsObserved["HTlep_2ltau_offZ_cut_300"] = 1.2;
00843       upperLimitsObserved["HTlep_3l_onZ_cut_0"] = 48.;
00844       upperLimitsObserved["HTlep_3l_onZ_cut_100"] = 38.;
00845       upperLimitsObserved["HTlep_3l_onZ_cut_150"] = 14.;
00846       upperLimitsObserved["HTlep_3l_onZ_cut_200"] = 7.2;
00847       upperLimitsObserved["HTlep_3l_onZ_cut_300"] = 4.5;
00848       upperLimitsObserved["HTlep_2ltau_onZ_cut_0"] = 85.;
00849       upperLimitsObserved["HTlep_2ltau_onZ_cut_100"] = 53.;
00850       upperLimitsObserved["HTlep_2ltau_onZ_cut_150"] = 11.0;
00851       upperLimitsObserved["HTlep_2ltau_onZ_cut_200"] = 5.2;
00852       upperLimitsObserved["HTlep_2ltau_onZ_cut_300"] = 3.0;
00853       upperLimitsObserved["METStrong_3l_offZ_cut_0"] = 2.6;
00854       upperLimitsObserved["METStrong_3l_offZ_cut_50"] = 2.1;
00855       upperLimitsObserved["METStrong_3l_offZ_cut_75"] = 2.1;
00856       upperLimitsObserved["METStrong_2ltau_offZ_cut_0"] = 4.2;
00857       upperLimitsObserved["METStrong_2ltau_offZ_cut_50"] = 3.1;
00858       upperLimitsObserved["METStrong_2ltau_offZ_cut_75"] = 2.6;
00859       upperLimitsObserved["METStrong_3l_onZ_cut_20"] = 11.0;
00860       upperLimitsObserved["METStrong_3l_onZ_cut_50"] = 6.4;
00861       upperLimitsObserved["METStrong_3l_onZ_cut_75"] = 5.1;
00862       upperLimitsObserved["METStrong_2ltau_onZ_cut_20"] = 5.9;
00863       upperLimitsObserved["METStrong_2ltau_onZ_cut_50"] = 3.4;
00864       upperLimitsObserved["METStrong_2ltau_onZ_cut_75"] = 1.2;
00865       upperLimitsObserved["METWeak_3l_offZ_cut_0"] = 11.;
00866       upperLimitsObserved["METWeak_3l_offZ_cut_50"] = 5.3;
00867       upperLimitsObserved["METWeak_3l_offZ_cut_75"] = 3.1;
00868       upperLimitsObserved["METWeak_2ltau_offZ_cut_0"] = 23.;
00869       upperLimitsObserved["METWeak_2ltau_offZ_cut_50"] = 4.3;
00870       upperLimitsObserved["METWeak_2ltau_offZ_cut_75"] = 3.1;
00871       upperLimitsObserved["METWeak_3l_onZ_cut_20"] = 41.;
00872       upperLimitsObserved["METWeak_3l_onZ_cut_50"] = 16.;
00873       upperLimitsObserved["METWeak_3l_onZ_cut_75"] = 8.0;
00874       upperLimitsObserved["METWeak_2ltau_onZ_cut_20"] = 80.;
00875       upperLimitsObserved["METWeak_2ltau_onZ_cut_50"] = 4.4;
00876       upperLimitsObserved["METWeak_2ltau_onZ_cut_75"] = 1.8;
00877       upperLimitsObserved["Meff_3l_offZ_cut_0"] = 11.;
00878       upperLimitsObserved["Meff_3l_offZ_cut_150"] = 8.1;
00879       upperLimitsObserved["Meff_3l_offZ_cut_300"] = 3.1;
00880       upperLimitsObserved["Meff_3l_offZ_cut_500"] = 2.1;
00881       upperLimitsObserved["Meff_2ltau_offZ_cut_0"] = 25.;
00882       upperLimitsObserved["Meff_2ltau_offZ_cut_150"] = 12.;
00883       upperLimitsObserved["Meff_2ltau_offZ_cut_300"] = 3.9;
00884       upperLimitsObserved["Meff_2ltau_offZ_cut_500"] = 2.2;
00885       upperLimitsObserved["Meff_3l_onZ_cut_0"] = 48.;
00886       upperLimitsObserved["Meff_3l_onZ_cut_150"] = 37.;
00887       upperLimitsObserved["Meff_3l_onZ_cut_300"] = 11.;
00888       upperLimitsObserved["Meff_3l_onZ_cut_500"] = 4.8;
00889       upperLimitsObserved["Meff_2ltau_onZ_cut_0"] = 85.;
00890       upperLimitsObserved["Meff_2ltau_onZ_cut_150"] = 28.;
00891       upperLimitsObserved["Meff_2ltau_onZ_cut_300"] = 5.9;
00892       upperLimitsObserved["Meff_2ltau_onZ_cut_500"] = 1.9;
00893       upperLimitsObserved["MeffStrong_3l_offZ_cut_0"] = 3.8;
00894       upperLimitsObserved["MeffStrong_3l_offZ_cut_150"] = 3.8;
00895       upperLimitsObserved["MeffStrong_3l_offZ_cut_300"] = 2.8;
00896       upperLimitsObserved["MeffStrong_3l_offZ_cut_500"] = 2.1;
00897       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_0"] = 3.9;
00898       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_150"] = 4.0;
00899       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_300"] = 2.9;
00900       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_500"] = 1.5;
00901       upperLimitsObserved["MeffStrong_3l_onZ_cut_0"] = 10.0;
00902       upperLimitsObserved["MeffStrong_3l_onZ_cut_150"] = 10.0;
00903       upperLimitsObserved["MeffStrong_3l_onZ_cut_300"] = 6.8;
00904       upperLimitsObserved["MeffStrong_3l_onZ_cut_500"] = 3.9;
00905       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_0"] = 1.6;
00906       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_150"] = 1.4;
00907       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_300"] = 1.5;
00908       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_500"] = 0.9;
00909 
00910       // Expected upper limits are also given but not used in this analysis
00911       map<string,double> upperLimitsExpected;
00912       upperLimitsExpected["HTlep_3l_offZ_cut_0"] = 11.;
00913       upperLimitsExpected["HTlep_3l_offZ_cut_100"] = 8.5;
00914       upperLimitsExpected["HTlep_3l_offZ_cut_150"] = 4.6;
00915       upperLimitsExpected["HTlep_3l_offZ_cut_200"] = 3.6;
00916       upperLimitsExpected["HTlep_3l_offZ_cut_300"] = 1.9;
00917       upperLimitsExpected["HTlep_2ltau_offZ_cut_0"] = 23.;
00918       upperLimitsExpected["HTlep_2ltau_offZ_cut_100"] = 14.;
00919       upperLimitsExpected["HTlep_2ltau_offZ_cut_150"] = 6.4;
00920       upperLimitsExpected["HTlep_2ltau_offZ_cut_200"] = 3.6;
00921       upperLimitsExpected["HTlep_2ltau_offZ_cut_300"] = 1.5;
00922       upperLimitsExpected["HTlep_3l_onZ_cut_0"] = 33.;
00923       upperLimitsExpected["HTlep_3l_onZ_cut_100"] = 25.;
00924       upperLimitsExpected["HTlep_3l_onZ_cut_150"] = 12.;
00925       upperLimitsExpected["HTlep_3l_onZ_cut_200"] = 6.5;
00926       upperLimitsExpected["HTlep_3l_onZ_cut_300"] = 3.1;
00927       upperLimitsExpected["HTlep_2ltau_onZ_cut_0"] = 94.;
00928       upperLimitsExpected["HTlep_2ltau_onZ_cut_100"] = 61.;
00929       upperLimitsExpected["HTlep_2ltau_onZ_cut_150"] = 9.9;
00930       upperLimitsExpected["HTlep_2ltau_onZ_cut_200"] = 4.5;
00931       upperLimitsExpected["HTlep_2ltau_onZ_cut_300"] = 1.9;
00932       upperLimitsExpected["METStrong_3l_offZ_cut_0"] = 3.1;
00933       upperLimitsExpected["METStrong_3l_offZ_cut_50"] = 2.4;
00934       upperLimitsExpected["METStrong_3l_offZ_cut_75"] = 2.3;
00935       upperLimitsExpected["METStrong_2ltau_offZ_cut_0"] = 4.8;
00936       upperLimitsExpected["METStrong_2ltau_offZ_cut_50"] = 3.3;
00937       upperLimitsExpected["METStrong_2ltau_offZ_cut_75"] = 2.1;
00938       upperLimitsExpected["METStrong_3l_onZ_cut_20"] = 8.7;
00939       upperLimitsExpected["METStrong_3l_onZ_cut_50"] = 4.9;
00940       upperLimitsExpected["METStrong_3l_onZ_cut_75"] = 3.8;
00941       upperLimitsExpected["METStrong_2ltau_onZ_cut_20"] = 7.3;
00942       upperLimitsExpected["METStrong_2ltau_onZ_cut_50"] = 2.8;
00943       upperLimitsExpected["METStrong_2ltau_onZ_cut_75"] = 1.5;
00944       upperLimitsExpected["METWeak_3l_offZ_cut_0"] = 10.;
00945       upperLimitsExpected["METWeak_3l_offZ_cut_50"] = 4.7;
00946       upperLimitsExpected["METWeak_3l_offZ_cut_75"] = 3.0;
00947       upperLimitsExpected["METWeak_2ltau_offZ_cut_0"] = 21.;
00948       upperLimitsExpected["METWeak_2ltau_offZ_cut_50"] = 4.0;
00949       upperLimitsExpected["METWeak_2ltau_offZ_cut_75"] = 2.6;
00950       upperLimitsExpected["METWeak_3l_onZ_cut_20"] = 30.;
00951       upperLimitsExpected["METWeak_3l_onZ_cut_50"] = 10.;
00952       upperLimitsExpected["METWeak_3l_onZ_cut_75"] = 5.4;
00953       upperLimitsExpected["METWeak_2ltau_onZ_cut_20"] = 88.;
00954       upperLimitsExpected["METWeak_2ltau_onZ_cut_50"] = 5.5;
00955       upperLimitsExpected["METWeak_2ltau_onZ_cut_75"] = 2.2;
00956       upperLimitsExpected["Meff_3l_offZ_cut_0"] = 11.;
00957       upperLimitsExpected["Meff_3l_offZ_cut_150"] = 8.8;
00958       upperLimitsExpected["Meff_3l_offZ_cut_300"] = 3.7;
00959       upperLimitsExpected["Meff_3l_offZ_cut_500"] = 2.1;
00960       upperLimitsExpected["Meff_2ltau_offZ_cut_0"] = 23.;
00961       upperLimitsExpected["Meff_2ltau_offZ_cut_150"] = 13.;
00962       upperLimitsExpected["Meff_2ltau_offZ_cut_300"] = 4.9;
00963       upperLimitsExpected["Meff_2ltau_offZ_cut_500"] = 2.4;
00964       upperLimitsExpected["Meff_3l_onZ_cut_0"] = 33.;
00965       upperLimitsExpected["Meff_3l_onZ_cut_150"] = 25.;
00966       upperLimitsExpected["Meff_3l_onZ_cut_300"] = 9.;
00967       upperLimitsExpected["Meff_3l_onZ_cut_500"] = 3.9;
00968       upperLimitsExpected["Meff_2ltau_onZ_cut_0"] = 94.;
00969       upperLimitsExpected["Meff_2ltau_onZ_cut_150"] = 35.;
00970       upperLimitsExpected["Meff_2ltau_onZ_cut_300"] = 6.8;
00971       upperLimitsExpected["Meff_2ltau_onZ_cut_500"] = 2.5;
00972       upperLimitsExpected["MeffStrong_3l_offZ_cut_0"] = 3.9;
00973       upperLimitsExpected["MeffStrong_3l_offZ_cut_150"] = 3.9;
00974       upperLimitsExpected["MeffStrong_3l_offZ_cut_300"] = 3.0;
00975       upperLimitsExpected["MeffStrong_3l_offZ_cut_500"] = 2.0;
00976       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_0"] = 3.8;
00977       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_150"] = 3.9;
00978       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_300"] = 3.1;
00979       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_500"] = 1.6;
00980       upperLimitsExpected["MeffStrong_3l_onZ_cut_0"] = 6.9;
00981       upperLimitsExpected["MeffStrong_3l_onZ_cut_150"] = 7.1;
00982       upperLimitsExpected["MeffStrong_3l_onZ_cut_300"] = 4.9;
00983       upperLimitsExpected["MeffStrong_3l_onZ_cut_500"] = 3.0;
00984       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_0"] = 2.4;
00985       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_150"] = 2.5;
00986       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_300"] = 2.0;
00987       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_500"] = 1.1;
00988 
00989       if (observed) return upperLimitsObserved[signal_region];
00990       else          return upperLimitsExpected[signal_region];
00991     }
00992 
00993 
00994     /// Function checking if there is an OSSF lepton pair or a combination of 3 leptons with an invariant mass close to the Z mass
00995     /// @todo Should the reference Z mass be 91.2?
00996     int isonZ (const Particles& particles)  {
00997       int onZ = 0;
00998       double best_mass_2 = 999.;
00999       double best_mass_3 = 999.;
01000 
01001       // Loop over all 2 particle combinations to find invariant mass of OSSF pair closest to Z mass
01002       foreach ( const Particle& p1, particles  )  {
01003         foreach ( const Particle& p2, particles  )  {
01004           double mass_difference_2_old = fabs(91.0 - best_mass_2);
01005           double mass_difference_2_new = fabs(91.0 - (p1.momentum() + p2.momentum()).mass()/GeV);
01006 
01007           // If particle combination is OSSF pair calculate mass difference to Z mass
01008           if ( (p1.pid()*p2.pid() == -121 || p1.pid()*p2.pid() == -169) )  {
01009 
01010             // Get invariant mass closest to Z mass
01011             if (mass_difference_2_new < mass_difference_2_old)
01012               best_mass_2 = (p1.momentum() + p2.momentum()).mass()/GeV;
01013 
01014             // In case there is an OSSF pair take also 3rd lepton into account (e.g. from FSR and photon to electron conversion)
01015             foreach ( const Particle & p3 , particles  )  {
01016               double mass_difference_3_old = fabs(91.0 - best_mass_3);
01017               double mass_difference_3_new = fabs(91.0 - (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV);
01018               if (mass_difference_3_new < mass_difference_3_old)
01019                 best_mass_3 = (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV;
01020             }
01021           }
01022         }
01023       }
01024 
01025       // Pick the minimum invariant mass of the best OSSF pair combination and the best 3 lepton combination
01026       // If this mass is in a 20 GeV window around the Z mass, the event is classified as onZ
01027       double best_mass = min(best_mass_2, best_mass_3);
01028       if (fabs(91.0 - best_mass) < 20) onZ = 1;
01029       return onZ;
01030     }
01031 
01032     //@}
01033 
01034 
01035   private:
01036 
01037     /// Histograms
01038     //@{
01039     Histo1DPtr _h_HTlep_all, _h_HTjets_all, _h_MET_all, _h_Meff_all;
01040     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;
01041     Histo1DPtr _h_e_n, _h_mu_n, _h_tau_n;
01042     Histo1DPtr _h_excluded;
01043     //@}
01044 
01045     /// Fiducial efficiencies to model the effects of the ATLAS detector
01046     bool _use_fiducial_lepton_efficiency;
01047 
01048     /// List of signal regions and event counts per signal region
01049     vector<string> _signal_regions;
01050     map<string, double> _eventCountsPerSR;
01051 
01052   };
01053 
01054 
01055 
01056   DECLARE_RIVET_PLUGIN(ATLAS_2012_I1204447);
01057 
01058 }