rivet is hosted by Hepforge, IPPP Durham
ATLAS_2015_I1345452.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/VetoedFinalState.hh"
00005 #include "Rivet/Projections/IdentifiedFinalState.hh"
00006 #include "Rivet/Projections/PromptFinalState.hh"
00007 #include "Rivet/Projections/DressedLeptons.hh"
00008 #include "Rivet/Projections/FastJets.hh"
00009 
00010 namespace Rivet {
00011 
00012   /// @brief ATLAS 7 TeV pseudo-top analysis
00013   ///
00014   /// @author K .Finelli <kevin.finelli@cern.ch>
00015   /// @author A. Saavedra <a.saavedra@physics.usyd.edu.au>
00016   /// @author L. Lan <llan@physics.usyd.edu.au>
00017   class ATLAS_2015_I1345452 : public Analysis {
00018     public:
00019 
00020       /// Constructor
00021       ATLAS_2015_I1345452()
00022         : Analysis("ATLAS_2015_I1345452")
00023       {
00024         setNeedsCrossSection(true);
00025       }
00026 
00027 
00028       void init() {
00029         // Eta ranges
00030         Cut eta_full = (Cuts::abseta < 5.0) & (Cuts::pT >= 1.0*MeV);
00031         Cut eta_lep = (Cuts::abseta < 2.5);
00032 
00033         // All final state particles
00034         FinalState fs(eta_full);
00035 
00036         // Get photons to dress leptons
00037         IdentifiedFinalState photons(fs);
00038         photons.acceptIdPair(PID::PHOTON);
00039 
00040         // Projection to find the electrons
00041         IdentifiedFinalState el_id(fs);
00042         el_id.acceptIdPair(PID::ELECTRON);
00043 
00044         PromptFinalState electrons(el_id);
00045         electrons.acceptTauDecays(true);
00046         addProjection(electrons, "electrons");
00047 
00048         DressedLeptons dressedelectrons(photons, electrons, 0.1, eta_lep & (Cuts::pT >= 25.0*GeV), true, true);
00049         addProjection(dressedelectrons, "dressedelectrons");
00050 
00051         DressedLeptons ewdressedelectrons(photons, electrons, 0.1, eta_full, true, true);
00052         addProjection(ewdressedelectrons, "ewdressedelectrons");
00053 
00054         DressedLeptons vetodressedelectrons(photons, electrons, 0.1, eta_lep & (Cuts::pT >= 15.0*GeV), true, true);
00055         addProjection(vetodressedelectrons, "vetodressedelectrons");
00056 
00057         // Projection to find the muons
00058         IdentifiedFinalState mu_id(fs);
00059         mu_id.acceptIdPair(PID::MUON);
00060         PromptFinalState muons(mu_id);
00061         muons.acceptTauDecays(true);
00062         addProjection(muons, "muons");
00063         DressedLeptons dressedmuons(photons, muons, 0.1, eta_lep & (Cuts::pT >= 25.0*GeV), true, true);
00064         addProjection(dressedmuons, "dressedmuons");
00065         DressedLeptons ewdressedmuons(photons, muons, 0.1, eta_full, true, true);
00066         addProjection(ewdressedmuons, "ewdressedmuons");
00067         DressedLeptons vetodressedmuons(photons, muons, 0.1, eta_lep & (Cuts::pT >= 15.0*GeV), true, true);
00068         addProjection(vetodressedmuons, "vetodressedmuons");
00069 
00070         // Projection to find neutrinos and produce MET
00071         IdentifiedFinalState nu_id;
00072         nu_id.acceptNeutrinos();
00073         PromptFinalState neutrinos(nu_id);
00074         neutrinos.acceptTauDecays(true);
00075         addProjection(neutrinos, "neutrinos");
00076 
00077         // Jet clustering.
00078         VetoedFinalState vfs;
00079         vfs.addVetoOnThisFinalState(ewdressedelectrons);
00080         vfs.addVetoOnThisFinalState(ewdressedmuons);
00081         vfs.addVetoOnThisFinalState(neutrinos);
00082         FastJets jets(vfs, FastJets::ANTIKT, 0.4);
00083         jets.useInvisibles();
00084         addProjection(jets, "jets");
00085 
00086         //pseudotop leptons and hadrons
00087         _h["ptpseudotophadron_mu"]     = bookHisto1D( 1, 1, 2);
00088         _h["ptpseudotophadron_el"]     = bookHisto1D( 2, 1, 2);
00089         _h["absrappseudotophadron_mu"] = bookHisto1D( 3, 1, 2);
00090         _h["absrappseudotophadron_el"] = bookHisto1D( 4, 1, 2);
00091         _h["ptpseudotoplepton_mu"]     = bookHisto1D( 5, 1, 2);
00092         _h["ptpseudotoplepton_el"]     = bookHisto1D( 6, 1, 2);
00093         _h["absrappseudotoplepton_mu"] = bookHisto1D( 7, 1, 2);
00094         _h["absrappseudotoplepton_el"] = bookHisto1D( 8, 1, 2);
00095         _h["ptttbar_mu"]               = bookHisto1D( 9, 1, 2);
00096         _h["ptttbar_el"]               = bookHisto1D(10, 1, 2);
00097         _h["absrapttbar_mu"]           = bookHisto1D(11, 1, 2);
00098         _h["absrapttbar_el"]           = bookHisto1D(12, 1, 2);
00099         _h["ttbarmass_mu"]             = bookHisto1D(13, 1, 2);
00100         _h["ttbarmass_el"]             = bookHisto1D(14, 1, 2);
00101         _h["ptpseudotophadron"]        = bookHisto1D(15, 1, 2);
00102         _h["absrappseudotophadron"]    = bookHisto1D(16, 1, 2);
00103         _h["ptpseudotoplepton"]        = bookHisto1D(17, 1, 2);
00104         _h["absrappseudotoplepton"]    = bookHisto1D(18, 1, 2);
00105         _h["ptttbar"]                  = bookHisto1D(19, 1, 2);
00106         _h["absrapttbar"]              = bookHisto1D(20, 1, 2);
00107         _h["ttbarmass"]                = bookHisto1D(21, 1, 2);
00108 
00109       }
00110 
00111       void analyze(const Event& event) {
00112 
00113         // Get the selected objects, using the projections.
00114         _dressedelectrons     = applyProjection<DressedLeptons>(  event, "dressedelectrons").dressedLeptons();
00115         _vetodressedelectrons = applyProjection<DressedLeptons>(  event, "vetodressedelectrons").dressedLeptons();
00116         _dressedmuons         = applyProjection<DressedLeptons>(  event, "dressedmuons").dressedLeptons();
00117         _vetodressedmuons     = applyProjection<DressedLeptons>(  event, "vetodressedmuons").dressedLeptons();
00118         _neutrinos            = applyProjection<PromptFinalState>(event, "neutrinos").particlesByPt();
00119         const Jets& all_jets  = applyProjection<FastJets>(        event, "jets").jetsByPt(Cuts::pT > 25.0*GeV && Cuts::abseta < 2.5);
00120 
00121         //get true l+jets events by removing events with more than 1 electron||muon neutrino
00122         unsigned int n_elmu_neutrinos = 0;
00123         foreach (const Particle p, _neutrinos) {
00124           if (p.abspid() == 12 || p.abspid() == 14)  ++n_elmu_neutrinos;
00125         }
00126         if (n_elmu_neutrinos != 1)  vetoEvent;
00127 
00128         DressedLepton *lepton;
00129         if ( _dressedelectrons.size())  lepton = &_dressedelectrons[0];
00130         else if (_dressedmuons.size())  lepton = &_dressedmuons[0];
00131         else vetoEvent;
00132 
00133         // Calculate the missing ET, using the prompt neutrinos only (really?)
00134         /// @todo Why not use MissingMomentum?
00135         FourMomentum met;
00136         foreach (const Particle& p, _neutrinos)  met += p.momentum();
00137 
00138         //remove jets if they are within dR < 0.2 of lepton
00139         Jets jets;
00140         foreach(const Jet& jet, all_jets) {
00141           bool keep = true;
00142           foreach (const DressedLepton& el, _vetodressedelectrons) {
00143             keep &= deltaR(jet, el) >= 0.2;
00144           }
00145           if (keep)  jets += jet;
00146         }
00147 
00148         bool overlap = false;
00149         Jets bjets, lightjets;
00150         for (unsigned int i = 0; i < jets.size(); ++i) {
00151           const Jet& jet = jets[i];
00152           foreach (const DressedLepton& el, _dressedelectrons)  overlap |= deltaR(jet, el) < 0.4;
00153           foreach (const DressedLepton& mu, _dressedmuons)      overlap |= deltaR(jet, mu) < 0.4;
00154           for (unsigned int j = i + 1; j < jets.size(); ++j) {
00155             overlap |= deltaR(jet, jets[j]) < 0.5;
00156           }
00157           //// Count the number of b-tags
00158           bool b_tagged = false;           //  This is closer to the
00159           Particles bTags = jet.bTags();   //  analysis. Something 
00160           foreach ( Particle b, bTags ) {  //  about ghost-associated
00161             b_tagged |= b.pT() > 5*GeV;    //  B-hadrons
00162           }                                //
00163           if ( b_tagged )  bjets += jet;
00164           else lightjets += jet;
00165         }
00166 
00167         // remove events with object overlap
00168         if (overlap) vetoEvent;
00169 
00170         if (bjets.size() < 2 || lightjets.size() < 2)  vetoEvent;
00171 
00172         FourMomentum pbjet1; //Momentum of bjet1
00173         FourMomentum pbjet2; //Momentum of bjet2
00174         if ( deltaR(bjets[0], *lepton) <= deltaR(bjets[1], *lepton) ) {
00175           pbjet1 = bjets[0].momentum();
00176           pbjet2 = bjets[1].momentum();
00177         } else {
00178           pbjet1 = bjets[1].momentum();
00179           pbjet2 = bjets[0].momentum();
00180         } 
00181 
00182         FourMomentum pjet1; // Momentum of jet1
00183         if (lightjets.size())  pjet1 = lightjets[0].momentum();
00184 
00185         FourMomentum pjet2; // Momentum of jet 2
00186         if (lightjets.size() > 1)  pjet2 = lightjets[1].momentum();
00187 
00188         double pz = computeneutrinoz(lepton->momentum(), met);
00189         FourMomentum ppseudoneutrino( sqrt(sqr(met.px()) + sqr(met.py()) + sqr(pz)), met.px(), met.py(), pz);
00190 
00191         //compute leptonic, hadronic, combined pseudo-top
00192         FourMomentum ppseudotoplepton = lepton->momentum() + ppseudoneutrino + pbjet1;
00193         FourMomentum ppseudotophadron = pbjet2 + pjet1 + pjet2;
00194         FourMomentum pttbar = ppseudotoplepton + ppseudotophadron;
00195 
00196         // Evaluate basic event selection
00197         bool pass_eljets = (_dressedelectrons.size() == 1) &&
00198                            (_vetodressedelectrons.size() < 2) &&
00199                            (_vetodressedmuons.empty()) &&
00200                            (met.pT() > 30*GeV) &&
00201                            (_mT(_dressedelectrons[0].momentum(), met) > 35*GeV) &&
00202                            (jets.size() >= 4);
00203         bool pass_mujets = (_dressedmuons.size() == 1) &&
00204                            (_vetodressedmuons.size() < 2) &&
00205                            (_vetodressedelectrons.empty()) &&
00206                            (met.pT() > 30*GeV) &&
00207                            (_mT(_dressedmuons[0].momentum(), met) > 35*GeV) &&
00208                            (jets.size() >= 4);
00209 
00210         // basic event selection requirements
00211         if (!pass_eljets && !pass_mujets) vetoEvent;
00212 
00213         // Fill histograms
00214         const double weight = event.weight();
00215 
00216         //pseudotop hadrons and leptons fill histogram
00217         _h["ptpseudotoplepton"]->fill(    ppseudotoplepton.pt(),     weight); //pT of pseudo top lepton
00218         _h["absrappseudotoplepton"]->fill(ppseudotoplepton.absrap(), weight); //absolute rapidity of pseudo top lepton
00219         _h["ptpseudotophadron"]->fill(    ppseudotophadron.pt(),     weight); //pT of pseudo top hadron
00220         _h["absrappseudotophadron"]->fill(ppseudotophadron.absrap(), weight); //absolute rapidity of pseudo top hadron
00221         _h["absrapttbar"]->fill(          pttbar.absrap(),           weight); //absolute rapidity of ttbar
00222         _h["ttbarmass"]->fill(            pttbar.mass(),             weight); //mass of ttbar 
00223         _h["ptttbar"]->fill(              pttbar.pt(),               weight); //fill pT of ttbar in combined channel
00224 
00225         if (pass_eljets) { // electron channel fill histogram
00226           _h["ptpseudotoplepton_el"]->fill(    ppseudotoplepton.pt(),     weight); //pT of pseudo top lepton
00227           _h["absrappseudotoplepton_el"]->fill(ppseudotoplepton.absrap(), weight); //absolute rapidity of pseudo top lepton
00228           _h["ptpseudotophadron_el"]->fill(    ppseudotophadron.pt(),     weight); //pT of pseudo top hadron
00229           _h["absrappseudotophadron_el"]->fill(ppseudotophadron.absrap(), weight); //absolute rapidity of pseudo top hadron
00230           _h["absrapttbar_el"]->fill(          pttbar.absrap(),           weight); //absolute rapidity of ttbar
00231           _h["ttbarmass_el"]->fill(            pttbar.mass(),             weight); // fill electron channel ttbar mass
00232           _h["ptttbar_el"]->fill(              pttbar.pt(),               weight); //fill pT of ttbar in electron channel
00233         }
00234         else { // muon channel fill histogram
00235           _h["ptpseudotoplepton_mu"]->fill(    ppseudotoplepton.pt(),     weight); //pT of pseudo top lepton
00236           _h["absrappseudotoplepton_mu"]->fill(ppseudotoplepton.absrap(), weight); //absolute rapidity of pseudo top lepton
00237           _h["ptpseudotophadron_mu"]->fill(    ppseudotophadron.pt(),     weight); //pT of pseudo top hadron
00238           _h["absrappseudotophadron_mu"]->fill(ppseudotophadron.absrap(), weight); //absolute rapidity of pseudo top hadron
00239           _h["absrapttbar_mu"]->fill(          pttbar.absrap(),           weight); //absolute rapidity of ttbar
00240           _h["ttbarmass_mu"]->fill(            pttbar.mass(),             weight); //fill muon channel histograms 
00241           _h["ptttbar_mu"]->fill(              pttbar.pt(),               weight); //fill pT of ttbar in electron channel
00242         }
00243       } 
00244 
00245       void finalize() {
00246         // Normalize to cross-section
00247         const double scalefactor(crossSection() / sumOfWeights());
00248         for (map<string, Histo1DPtr>::iterator hit = _h.begin(); hit != _h.end(); ++hit) {
00249           double sf = scalefactor;
00250           if ( (hit->first).find("_") == std::string::npos )  sf *= 0.5;
00251           scale(hit->second, sf);
00252         }
00253       }
00254 
00255     private:
00256 
00257 
00258       double computeneutrinoz(const FourMomentum& lepton, FourMomentum& met) const {
00259         //computing z component of neutrino momentum given lepton and met
00260         double pzneutrino;
00261         double m_W = 80.399; // in GeV, given in the paper
00262         double k = (( sqr( m_W ) - sqr( lepton.mass() ) ) / 2 ) + (lepton.px() * met.px() + lepton.py() * met.py());
00263         double a = sqr ( lepton.E() )- sqr ( lepton.pz() );
00264         double b = -2*k*lepton.pz();
00265         double c = sqr( lepton.E() ) * sqr( met.pT() ) - sqr( k );
00266         double discriminant = sqr(b) - 4 * a * c;
00267         double quad[2] = { (- b - sqrt(discriminant)) / (2 * a), (- b + sqrt(discriminant)) / (2 * a) }; //two possible quadratic solns
00268         if (discriminant < 0)  pzneutrino = - b / (2 * a); //if the discriminant is negative
00269         else { //if the discriminant is greater than or equal to zero, take the soln with smallest absolute value
00270           double absquad[2];
00271           for (int n=0; n<2; ++n)  absquad[n] = fabs(quad[n]);
00272           if (absquad[0] < absquad[1])  pzneutrino = quad[0];
00273           else                          pzneutrino = quad[1];
00274         }
00275         if ( !std::isfinite(pzneutrino) )  std::cout << "Found non-finite value" << std::endl;
00276         return pzneutrino;
00277       }
00278 
00279       double _mT(const FourMomentum &l, FourMomentum &nu) const {
00280         return sqrt( 2 * l.pT() * nu.pT() * (1 - cos(deltaPhi(l, nu))) );
00281       }
00282 
00283       /// @name Objects that are used by the event selection decisions
00284       vector<DressedLepton> _dressedelectrons, _vetodressedelectrons, _dressedmuons, _vetodressedmuons;
00285       Particles _neutrinos;
00286       map<string, Histo1DPtr> _h;
00287   };
00288 
00289   // The hook for the plugin system
00290   DECLARE_RIVET_PLUGIN(ATLAS_2015_I1345452);
00291 
00292 }