rivet is hosted by Hepforge, IPPP Durham
ATLAS_2014_I1279489.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/IdentifiedFinalState.hh"
00005 #include "Rivet/Projections/VetoedFinalState.hh"
00006 #include "Rivet/Projections/FastJets.hh"
00007 #include "Rivet/Projections/DressedLeptons.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   struct Plots {
00013     string label;
00014 
00015     Histo1DPtr h_dy;
00016     Histo1DPtr h_mjj;
00017     Histo1DPtr h_njets;
00018     Histo1DPtr h_dphijj;
00019     Histo1DPtr h_ptbal;
00020 
00021     Histo1DPtr h_jetveto_mjj_veto;
00022     Histo1DPtr h_jetveto_mjj_inc;
00023     Histo1DPtr h_jetveto_dy_veto;
00024     Histo1DPtr h_jetveto_dy_inc;
00025 
00026     Histo1DPtr h_ptbaleff_mjj_veto;
00027     Histo1DPtr h_ptbaleff_mjj_inc;
00028     Histo1DPtr h_ptbaleff_dy_veto;
00029     Histo1DPtr h_ptbaleff_dy_inc;
00030 
00031     Profile1DPtr p_avgnjets_dy;
00032     Profile1DPtr p_avgnjets_mjj;
00033   };
00034 
00035 
00036   struct Variables {
00037 
00038     Variables(const vector<const Jet*>& jets, const Particle* lep1, const Particle* lep2) {
00039       FourMomentum j1 = jets.at(0)->momentum();
00040       FourMomentum j2 = jets.at(1)->momentum();
00041       jet1pt = j1.pT();
00042       jet2pt = j2.pT();
00043       assert(jet1pt > jet2pt);
00044 
00045       zpt = (lep1->mom() + lep2->mom()).pT();
00046 
00047       deltay = fabs(j1.rapidity() - j2.rapidity());
00048       mjj = (j1 + j2).mass();
00049       deltaphijj = deltaPhi(j1, j2) / PI;
00050 
00051       FourMomentum gapjet(0., 0., 0., 0.);
00052       ngapjets = _getNumGapJets(jets, gapjet);
00053 
00054       double ptbal_vec = (j1 + j2 + lep1->mom() + lep2->mom()).pT();
00055       double ptbal_sc = j1.pT() + j2.pT() + lep1->pT() + lep2->pT();
00056       ptbalance2 = ptbal_vec / ptbal_sc;
00057 
00058       double ptbal3_vec = (j1 + j2 + gapjet + lep1->mom() + lep2->mom()).pT();
00059       double ptbal3_sc = j1.pT() + j2.pT() + gapjet.pT() + lep1->pT() + lep2->pT();
00060       ptbalance3 = ptbal3_vec / ptbal3_sc;
00061 
00062       pass_jetveto = gapjet.pT() < 25.0*GeV;
00063       pass_ptbaleff = ptbalance2 < 0.15;
00064     }
00065 
00066 
00067     double jet1pt;
00068     double jet2pt;
00069     double zpt;
00070 
00071     double deltay;
00072     double mjj;
00073     double deltaphijj;
00074     double ptbalance2;
00075     double ptbalance3;
00076     int ngapjets;
00077 
00078     double dilepton_dr;
00079 
00080     bool pass_jetveto;
00081     bool pass_ptbaleff;
00082 
00083 
00084   private:
00085 
00086     bool _isBetween(const Jet* probe, const Jet* boundary1, const Jet* boundary2) {
00087       double y_p = probe->rapidity();
00088       double y_b1 = boundary1->rapidity();
00089       double y_b2 = boundary2->rapidity();
00090 
00091       double y_min = std::min(y_b1, y_b2);
00092       double y_max = std::max(y_b1, y_b2);
00093 
00094       if (y_p > y_min && y_p < y_max) return true;
00095       else return false;
00096     }
00097 
00098     int _getNumGapJets(const vector<const Jet*>& jets, FourMomentum& thirdJet) {
00099       if (jets.size() < 2) return 0;
00100       // The vector of jets is already sorted by pT. So the boundary jets will be the first two.
00101       const Jet* bj1 = jets.at(0);
00102       const Jet* bj2 = jets.at(1);
00103 
00104       int n_between = 0;
00105       // Start loop at the 3rd hardest pT jet
00106       for (size_t i = 2; i < jets.size(); ++i) {
00107         const Jet* j = jets.at(i);
00108         // If this jet is between the boundary jets and is hard enough, increment counter
00109         if (_isBetween(j, bj1, bj2)) {
00110           if (n_between == 0) thirdJet = j->momentum();
00111           ++n_between;
00112         }
00113       }
00114       return n_between;
00115     }
00116 
00117   };
00118 
00119 
00120 
00121   class ATLAS_2014_I1279489 : public Analysis {
00122   public:
00123 
00124     /// Constructor
00125     ATLAS_2014_I1279489()
00126       : Analysis("ATLAS_2014_I1279489")
00127     {    }
00128 
00129 
00130     /// Book histograms and initialise projections before the run
00131     void init() {
00132 
00133       FinalState fs(-5.0, 5.0);
00134 
00135       IdentifiedFinalState photon_fs(fs);
00136       photon_fs.acceptIdPair(PID::PHOTON);
00137 
00138       IdentifiedFinalState electron_fs(fs);
00139       electron_fs.acceptIdPair(PID::ELECTRON);
00140 
00141       IdentifiedFinalState muon_fs(fs);
00142       muon_fs.acceptIdPair(PID::MUON);
00143 
00144       DressedLeptons dressed_electrons(photon_fs, electron_fs, 0.1, true, -2.47, 2.47, 25*GeV, false);
00145       addProjection(dressed_electrons, "DressedElectrons");
00146 
00147       DressedLeptons dressed_muons(photon_fs, muon_fs, 0.1, true, -2.47, 2.47, 25*GeV, false);
00148       addProjection(dressed_muons, "DressedMuons");
00149 
00150       FastJets jets(fs, FastJets::ANTIKT, 0.4);
00151       addProjection(jets, "Jets");
00152 
00153       initialisePlots(baseline_plots, "baseline");
00154       initialisePlots(highpt_plots, "highpt");
00155       initialisePlots(search_plots, "search");
00156       initialisePlots(control_plots, "control");
00157       initialisePlots(highmass_plots, "highmass");
00158     }
00159 
00160 
00161     void initialisePlots(Plots& plots, const string& phase_space){
00162       /****************************************
00163        * Plot labeling:                       *
00164        * format = d0_-x0_-y0_                 *
00165        * d01 = baseline fiducial region       *
00166        * d02 = high-pt fiducial region        *
00167        * d03 = search fiducial region         *
00168        * d04 = control fiducial region        *
00169        * d05 = high-mass fiducial region      *
00170        *                                      *
00171        * x01 = mjj on x-axis                  *
00172        * x02 = delta-y on x-axis              *
00173        * x03 = njets on x-axis                *
00174        * x04 = dphijj on x-axis               *
00175        * x05 = ptbalance on x-axis            *
00176        *                                      *
00177        * y01 = differential cross-section     *
00178        * y02 = jet veto efficiency            *
00179        * y03 = ptbalance efficiency           *
00180        * y04 = average njets                  *
00181        ****************************************/
00182       plots.label = phase_space;
00183 
00184       if (phase_space=="baseline") {
00185         plots.h_mjj = bookHisto1D(1, 1, 1);
00186         plots.h_dy = bookHisto1D(1, 2, 1);
00187 
00188         plots.h_jetveto_mjj_veto = bookHisto1D("jetveto_mjj_baseline_veto", refData(1,1,2));
00189         plots.h_jetveto_mjj_inc = bookHisto1D("jetveto_mjj_baseline_inc", refData(1,1,2));
00190         plots.h_jetveto_dy_veto = bookHisto1D("jetveto_dy_baseline_veto", refData(1,2,2));
00191         plots.h_jetveto_dy_inc = bookHisto1D("jetveto_dy_baseline_inc", refData(1,2,2));
00192 
00193         plots.h_ptbaleff_mjj_veto = bookHisto1D("ptbaleff_mjj_baseline_veto", refData(1,1,3));
00194         plots.h_ptbaleff_mjj_inc = bookHisto1D("ptbaleff_mjj_baseline_inc", refData(1,1,3));
00195         plots.h_ptbaleff_dy_veto = bookHisto1D("ptbaleff_dy_baseline_veto", refData(1,2,3));
00196         plots.h_ptbaleff_dy_inc = bookHisto1D("ptbaleff_dy_baseline_inc", refData(1,2,3));
00197 
00198         plots.p_avgnjets_mjj = bookProfile1D(1,1,4);
00199         plots.p_avgnjets_dy = bookProfile1D(1,2,4);
00200       }
00201 
00202       if (phase_space=="highpt") {
00203         plots.h_mjj = bookHisto1D(2, 1, 1);
00204         plots.h_dy = bookHisto1D(2, 2, 1);
00205 
00206         plots.h_jetveto_mjj_veto = bookHisto1D("jetveto_mjj_highpt_veto", refData(2,1,2));
00207         plots.h_jetveto_mjj_inc = bookHisto1D("jetveto_mjj_highpt_inc", refData(2,1,2));
00208         plots.h_jetveto_dy_veto = bookHisto1D("jetveto_dy_highpt_veto", refData(2,2,2));
00209         plots.h_jetveto_dy_inc = bookHisto1D("jetveto_dy_highpt_inc", refData(2,2,2));
00210 
00211         plots.h_ptbaleff_mjj_veto = bookHisto1D("ptbaleff_mjj_highpt_veto", refData(2,1,3));
00212         plots.h_ptbaleff_mjj_inc = bookHisto1D("ptbaleff_mjj_highpt_inc", refData(2,1,3));
00213         plots.h_ptbaleff_dy_veto = bookHisto1D("ptbaleff_dy_highpt_veto", refData(2,2,3));
00214         plots.h_ptbaleff_dy_inc = bookHisto1D("ptbaleff_dy_highpt_inc", refData(2,2,3));
00215 
00216         plots.p_avgnjets_mjj = bookProfile1D(2,1,4);
00217         plots.p_avgnjets_dy = bookProfile1D(2,2,4);
00218       }
00219 
00220       if (phase_space=="search") {
00221         plots.h_mjj = bookHisto1D(3,1,1);
00222         plots.h_dy = bookHisto1D(3,2,1);
00223       }
00224 
00225       if (phase_space=="control") {
00226         plots.h_mjj = bookHisto1D(4,1,1);
00227         plots.h_dy = bookHisto1D(4,2,1);
00228       }
00229 
00230       if (phase_space=="highmass") {
00231         plots.h_njets = bookHisto1D(5, 3, 1);
00232         plots.h_dphijj = bookHisto1D(5, 4, 1);
00233         plots.h_ptbal = bookHisto1D(5, 5, 1);
00234       }
00235     }
00236 
00237 
00238 
00239     /// Perform the per-event analysis
00240     void analyze(const Event& event) {
00241 
00242       // Make sure that we have a Z-candidate:
00243       const Particle *lep1 = NULL, *lep2 = NULL;
00244       //
00245       const vector<DressedLepton>& muons = applyProjection<DressedLeptons>(event, "DressedMuons").dressedLeptons();
00246       if (muons.size() == 2) {
00247         const FourMomentum dimuon = muons[0].mom() + muons[1].mom();
00248         if ( inRange(dimuon.mass()/GeV, 81.0, 101.0) && muons[0].threeCharge() != muons[1].threeCharge() ) {
00249           lep1 = &muons[0];
00250           lep2 = &muons[1];
00251         }
00252       }
00253       //
00254       const vector<DressedLepton>& electrons = applyProjection<DressedLeptons>(event, "DressedElectrons").dressedLeptons();
00255       if (electrons.size() == 2) {
00256         const FourMomentum dielectron = electrons[0].mom() + electrons[1].mom();
00257         if ( inRange(dielectron.mass()/GeV, 81.0, 101.0) && electrons[0].threeCharge() != electrons[1].threeCharge() ) {
00258           if (lep1 && lep2) {
00259             MSG_INFO("Found Z candidates using both electrons and muons! Continuing with the muon-channel candidate");
00260           } else {
00261             lep1 = &electrons[0];
00262             lep2 = &electrons[1];
00263           }
00264         }
00265       }
00266       // If there's no Z-candidate, we won't use this event:
00267       if (!lep1 || !lep2) vetoEvent;
00268 
00269 
00270       // Do lepton-jet overlap removal:
00271       vector<const Jet*> good_jets;
00272       const Jets& jets = applyProjection<FastJets>(event, "Jets").jetsByPt(25.0*GeV, MAXDOUBLE, -4.4, 4.4, RAPIDITY);
00273       foreach(const Jet& j, jets) {
00274         bool nearby_lepton = false;
00275         foreach (const Particle& m, muons)
00276           if (deltaR(j, m) < 0.3) nearby_lepton = true;
00277         foreach (const Particle& e, electrons)
00278           if (deltaR(j, e) < 0.3) nearby_lepton = true;
00279         if (!nearby_lepton)
00280           good_jets.push_back(&j);
00281       }
00282       // If we don't have at least 2 good jets, we won't use this event.
00283       if (good_jets.size() < 2) vetoEvent;
00284 
00285 
00286       // Plotting, using variables and histo classes calculated by the Variables object constructor
00287       Variables vars(good_jets, lep1, lep2);
00288       bool pass_baseline = (vars.jet1pt > 55.0*GeV && vars.jet2pt > 45.0*GeV);
00289       bool pass_highpt = (vars.jet1pt > 85.0*GeV && vars.jet2pt > 75.0*GeV);
00290       bool pass_highmass = (pass_baseline && vars.mjj > 1000.0*GeV);
00291       bool pass_search = (pass_baseline && vars.zpt > 20.0*GeV && vars.ngapjets == 0 && vars.ptbalance2 < 0.15 && vars.mjj > 250.0*GeV);
00292       bool pass_control = (pass_baseline && vars.zpt > 20.0*GeV && vars.ngapjets > 0 && vars.ptbalance3 < 0.15 && vars.mjj > 250.0*GeV);
00293       //
00294       const double weight = event.weight();
00295       if (pass_baseline) fillPlots(vars, baseline_plots, "baseline", weight);
00296       if (pass_highpt) fillPlots(vars, highpt_plots, "highpt", weight);
00297       if (pass_highmass) fillPlots(vars, highmass_plots, "highmass", weight);
00298       if (pass_search) fillPlots(vars, search_plots, "search", weight);
00299       if (pass_control) fillPlots(vars, control_plots, "control", weight);
00300     }
00301 
00302 
00303     void fillPlots(const Variables& vars, Plots& plots, string phase_space, double weight) {
00304       if (phase_space == "baseline" || phase_space == "highpt" || phase_space == "search" || phase_space == "control") {
00305         plots.h_dy->fill(vars.deltay, weight);
00306         plots.h_mjj->fill(vars.mjj, weight);
00307       }
00308 
00309       if (phase_space == "baseline" || phase_space == "highpt") {
00310         if (vars.pass_jetveto) {
00311           plots.h_jetveto_dy_veto->fill(vars.deltay, weight);
00312           plots.h_jetveto_mjj_veto->fill(vars.mjj, weight);
00313         }
00314         plots.h_jetveto_dy_inc->fill(vars.deltay, weight);
00315         plots.h_jetveto_mjj_inc->fill(vars.mjj, weight);
00316 
00317         if (vars.pass_ptbaleff) {
00318           plots.h_ptbaleff_mjj_veto->fill(vars.mjj, weight);
00319           plots.h_ptbaleff_dy_veto->fill(vars.deltay, weight);
00320         }
00321         plots.h_ptbaleff_mjj_inc->fill(vars.mjj, weight);
00322         plots.h_ptbaleff_dy_inc->fill(vars.deltay, weight);
00323 
00324         plots.p_avgnjets_dy->fill(vars.deltay, vars.ngapjets, weight);
00325         plots.p_avgnjets_mjj->fill(vars.mjj, vars.ngapjets, weight);
00326       }
00327 
00328       if (phase_space == "highmass") {
00329         plots.h_njets->fill(vars.ngapjets, weight);
00330         plots.h_dphijj->fill(vars.deltaphijj, weight);
00331         plots.h_ptbal->fill(vars.ptbalance2, weight);
00332       }
00333     }
00334 
00335 
00336     /// Normalise histograms etc., after the run
00337     void finalize() {
00338       finalizePlots(baseline_plots);
00339       finalizePlots(highpt_plots);
00340       finalizePlots(search_plots);
00341       finalizePlots(control_plots);
00342       finalizePlots(highmass_plots);
00343       finalizeEfficiencies(baseline_plots);
00344       finalizeEfficiencies(highpt_plots);
00345     }
00346 
00347     void finalizePlots(Plots& plots) {
00348       if (plots.h_dy) normalize(plots.h_dy);
00349       if (plots.h_mjj) normalize(plots.h_mjj);
00350       if (plots.h_dphijj) normalize(plots.h_dphijj);
00351       if (plots.h_njets) normalize(plots.h_njets);
00352       if (plots.h_ptbal) normalize(plots.h_ptbal);
00353     }
00354 
00355     void finalizeEfficiencies(Plots& plots) {
00356       int region_index = 0;
00357       if (plots.label=="baseline") region_index = 1;
00358       else if (plots.label=="highpt") region_index = 2;
00359       else return;
00360 
00361       if (plots.h_jetveto_mjj_veto && plots.h_jetveto_mjj_inc) divide(plots.h_jetveto_mjj_veto, plots.h_jetveto_mjj_inc, bookScatter2D(region_index, 1, 2));
00362       getScatter2D(region_index, 1, 2)->addAnnotation("InclusiveSumWeights", plots.h_jetveto_mjj_inc->integral());
00363       removeAnalysisObject(plots.h_jetveto_mjj_veto); removeAnalysisObject(plots.h_jetveto_mjj_inc);
00364 
00365       if (plots.h_jetveto_dy_veto && plots.h_jetveto_dy_inc) divide(plots.h_jetveto_dy_veto, plots.h_jetveto_dy_inc, bookScatter2D(region_index, 2, 2));
00366       getScatter2D(region_index, 2, 2)->addAnnotation("InclusiveSumWeights", plots.h_jetveto_dy_inc->integral());
00367       removeAnalysisObject(plots.h_jetveto_dy_veto); removeAnalysisObject(plots.h_jetveto_dy_inc);
00368 
00369       if (plots.h_ptbaleff_mjj_veto && plots.h_ptbaleff_mjj_inc) divide(plots.h_ptbaleff_mjj_veto, plots.h_ptbaleff_mjj_inc, bookScatter2D(region_index, 1, 3));
00370       getScatter2D(region_index, 1, 3)->addAnnotation("InclusiveSumWeights", plots.h_ptbaleff_mjj_inc->integral());
00371       removeAnalysisObject(plots.h_ptbaleff_mjj_veto); removeAnalysisObject(plots.h_ptbaleff_mjj_inc);
00372 
00373       if (plots.h_ptbaleff_dy_veto && plots.h_ptbaleff_dy_inc) divide(plots.h_ptbaleff_dy_veto, plots.h_ptbaleff_dy_inc, bookScatter2D(region_index, 2, 3));
00374       getScatter2D(region_index, 2, 3)->addAnnotation("InclusiveSumWeights", plots.h_ptbaleff_dy_inc->integral());
00375       removeAnalysisObject(plots.h_ptbaleff_dy_veto); removeAnalysisObject(plots.h_ptbaleff_dy_inc);
00376     }
00377 
00378     //@}
00379 
00380 
00381   private:
00382 
00383     //Variables* vars;
00384 
00385     Plots baseline_plots;
00386     Plots highpt_plots;
00387     Plots search_plots;
00388     Plots control_plots;
00389     Plots highmass_plots;
00390 
00391   };
00392 
00393 
00394   DECLARE_RIVET_PLUGIN(ATLAS_2014_I1279489);
00395 
00396 }