rivet is hosted by Hepforge, IPPP Durham
ATLAS_2015_I1404878.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 #include "Rivet/Projections/VisibleFinalState.hh"
00010 
00011 namespace Rivet {
00012 
00013   class ATLAS_2015_I1404878 : public Analysis {
00014     public:
00015 
00016       /// Constructor
00017       DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2015_I1404878);
00018 
00019       void init() {
00020         // Eta ranges
00021         Cut eta_full = (Cuts::abseta < 4.2) & (Cuts::pT >= 1.0*MeV);
00022         Cut lep_cuts = (Cuts::abseta < 2.5) && (Cuts::pT > 25*GeV);
00023 
00024         // All final state particles
00025         FinalState fs(eta_full);
00026 
00027         // Get photons to dress leptons
00028         IdentifiedFinalState photons(fs);
00029         photons.acceptIdPair(PID::PHOTON);
00030 
00031         // Projection to find the electrons
00032         IdentifiedFinalState el_id(fs);
00033         el_id.acceptIdPair(PID::ELECTRON);
00034 
00035         PromptFinalState electrons(el_id);
00036         electrons.acceptTauDecays(true);
00037         declare(electrons, "electrons");
00038 
00039         DressedLeptons dressedelectrons(photons, electrons, 0.1, lep_cuts, true, true);
00040         declare(dressedelectrons, "dressedelectrons");
00041 
00042         DressedLeptons ewdressedelectrons(photons, electrons, 0.1, eta_full, true, true);
00043         declare(ewdressedelectrons, "ewdressedelectrons");
00044         
00045         // Projection to find the muons
00046         IdentifiedFinalState mu_id(fs);
00047         mu_id.acceptIdPair(PID::MUON);
00048 
00049         PromptFinalState muons(mu_id);
00050         muons.acceptTauDecays(true);
00051         declare(muons, "muons");
00052 
00053         DressedLeptons dressedmuons(photons, muons, 0.1, lep_cuts, true, true);
00054         declare(dressedmuons, "dressedmuons");
00055 
00056         DressedLeptons ewdressedmuons(photons, muons, 0.1, eta_full, true, true);
00057         declare(ewdressedmuons, "ewdressedmuons");
00058 
00059         // Projection to find neutrinos
00060         IdentifiedFinalState nu_id;
00061         nu_id.acceptNeutrinos();
00062         PromptFinalState neutrinos(nu_id);
00063         neutrinos.acceptTauDecays(true);
00064 
00065         // get MET from generic invisibles
00066         VetoedFinalState inv_fs(fs);
00067         inv_fs.addVetoOnThisFinalState(VisibleFinalState(fs));
00068         declare(inv_fs, "InvisibleFS");
00069 
00070         // Jet clustering.
00071         VetoedFinalState vfs;
00072         vfs.addVetoOnThisFinalState(ewdressedelectrons);
00073         vfs.addVetoOnThisFinalState(ewdressedmuons);
00074         vfs.addVetoOnThisFinalState(neutrinos);
00075         FastJets jets(vfs, FastJets::ANTIKT, 0.4);
00076         jets.useInvisibles(true);
00077         declare(jets, "jets");
00078 
00079         // Histogram booking 
00080         _h["massttbar"]                  = bookHisto1D( 1, 1, 1);
00081         _h["massttbar_norm"]             = bookHisto1D( 2, 1, 1);
00082         _h["ptttbar"]                    = bookHisto1D( 3, 1, 1);
00083         _h["ptttbar_norm"]               = bookHisto1D( 4, 1, 1);
00084         _h["absrapttbar"]                = bookHisto1D( 5, 1, 1);
00085         _h["absrapttbar_norm"]           = bookHisto1D( 6, 1, 1);
00086         _h["ptpseudotophadron"]          = bookHisto1D( 7, 1, 1);
00087         _h["ptpseudotophadron_norm"]     = bookHisto1D( 8, 1, 1);
00088         _h["absrappseudotophadron"]      = bookHisto1D( 9, 1, 1);
00089         _h["absrappseudotophadron_norm"] = bookHisto1D(10, 1, 1);
00090         _h["absPout"]                    = bookHisto1D(11, 1, 1);
00091         _h["absPout_norm"]               = bookHisto1D(12, 1, 1);
00092         _h["dPhittbar"]                  = bookHisto1D(13, 1, 1);
00093         _h["dPhittbar_norm"]             = bookHisto1D(14, 1, 1);
00094         _h["HTttbar"]                    = bookHisto1D(15, 1, 1);
00095         _h["HTttbar_norm"]               = bookHisto1D(16, 1, 1);
00096         _h["Yboost"]                     = bookHisto1D(17, 1, 1);
00097         _h["Yboost_norm"]                = bookHisto1D(18, 1, 1);
00098         _h["chittbar"]                   = bookHisto1D(19, 1, 1);
00099         _h["chittbar_norm"]              = bookHisto1D(20, 1, 1);
00100         _h["RWt"]                        = bookHisto1D(21, 1, 1);
00101         _h["RWt_norm"]                   = bookHisto1D(22, 1, 1);
00102 
00103       }
00104 
00105       void analyze(const Event& event) {
00106 
00107         const double weight = event.weight();
00108 
00109         // Get the selected objects, using the projections.
00110         vector<DressedLepton> electrons = applyProjection<DressedLeptons>(event, "dressedelectrons").dressedLeptons();
00111         vector<DressedLepton> muons     = applyProjection<DressedLeptons>(event, "dressedmuons").dressedLeptons();
00112         const Jets& jets = applyProjection<FastJets>(event, "jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 2.5);
00113         const FinalState& ifs = applyProjection<FinalState>(event, "InvisibleFS");
00114 
00115         // Calculate MET
00116         FourMomentum met;
00117         foreach (const Particle& p, ifs.particles())  met += p.momentum();
00118 
00119         // Count the number of b-tags
00120         Jets bjets, lightjets;
00121         foreach (const Jet& jet, jets){
00122           bool b_tagged = jet.bTags(Cuts::pT > 5*GeV).size();
00123           if ( b_tagged && bjets.size() < 2 )  bjets += jet;
00124           else lightjets += jet;
00125         }
00126    
00127         bool single_electron = (electrons.size() == 1) && (muons.empty());
00128         bool single_muon     = (muons.size() == 1) && (electrons.empty());
00129     
00130         DressedLepton *lepton = NULL;
00131         if (single_electron)   lepton = &electrons[0];
00132         else if (single_muon)  lepton = &muons[0];
00133         
00134         if(!single_electron && !single_muon)  vetoEvent;
00135         if (jets.size()  < 4 || bjets.size() < 2)  vetoEvent;
00136 
00137         FourMomentum pbjet1; //Momentum of bjet1
00138         FourMomentum pbjet2; //Momentum of bjet2
00139         if ( deltaR(bjets[0], *lepton) <= deltaR(bjets[1], *lepton) ) {
00140           pbjet1 = bjets[0].momentum();
00141           pbjet2 = bjets[1].momentum();
00142         } else {
00143           pbjet1 = bjets[1].momentum();
00144           pbjet2 = bjets[0].momentum();
00145         } 
00146 
00147 
00148         double bestWmass = 1000.0*TeV;
00149         double mWPDG = 80.399*GeV;
00150         int Wj1index = -1, Wj2index = -1;
00151         for (unsigned int i = 0; i < (lightjets.size() - 1); ++i) {
00152           for (unsigned int j = i + 1; j < lightjets.size(); ++j) {
00153             double wmass = (lightjets[i].momentum() + lightjets[j].momentum()).mass();
00154             if (fabs(wmass - mWPDG) < fabs(bestWmass - mWPDG)) {
00155               bestWmass = wmass;
00156               Wj1index = i;
00157               Wj2index = j;
00158             }
00159           }
00160         }
00161         
00162         // compute hadronic W boson
00163         FourMomentum pWhadron = lightjets[Wj1index].momentum() + lightjets[Wj2index].momentum();
00164         double pz = computeneutrinoz(lepton->momentum(), met);
00165         FourMomentum ppseudoneutrino( sqrt(sqr(met.px()) + sqr(met.py()) + sqr(pz)), met.px(), met.py(), pz);
00166 
00167 
00168         //compute leptonic, hadronic, combined pseudo-top
00169         FourMomentum ppseudotoplepton = lepton->momentum() + ppseudoneutrino + pbjet1;
00170         FourMomentum ppseudotophadron = pbjet2 + pWhadron;
00171         FourMomentum pttbar = ppseudotoplepton + ppseudotophadron;
00172     
00173         Vector3 z_versor(0,0,1);
00174         Vector3 vpseudotophadron = ppseudotophadron.vector3();
00175         Vector3 vpseudotoplepton = ppseudotoplepton.vector3(); 
00176         // Observables
00177         double ystar = 0.5 * deltaRap(ppseudotophadron, ppseudotoplepton);
00178         double chi_ttbar = exp(2 * fabs(ystar));
00179         double deltaPhi_ttbar = deltaPhi(ppseudotoplepton,ppseudotophadron);
00180         double HT_ttbar = ppseudotophadron.pt() + ppseudotoplepton.pt();
00181         double Yboost = 0.5 * fabs(ppseudotophadron.rapidity() + ppseudotoplepton.rapidity());
00182         double R_Wt = pWhadron.pt() / ppseudotophadron.pt();
00183         double absPout = fabs(vpseudotophadron.dot((vpseudotoplepton.cross(z_versor))/(vpseudotoplepton.cross(z_versor).mod())));
00184 
00185         // absolute cross sections
00186         _h["ptpseudotophadron"]->fill(    ppseudotophadron.pt(),     weight); //pT of pseudo top hadron
00187         _h["ptttbar"]->fill(              pttbar.pt(),               weight); //fill pT of ttbar in combined channel
00188         _h["absrappseudotophadron"]->fill(ppseudotophadron.absrap(), weight);
00189         _h["absrapttbar"]->fill(          pttbar.absrap(),           weight);
00190         _h["massttbar"]->fill(            pttbar.mass(),             weight);
00191         _h["absPout"]->fill(              absPout,                   weight);
00192         _h["chittbar"]->fill(             chi_ttbar,                 weight);
00193         _h["dPhittbar"]->fill(            deltaPhi_ttbar,            weight);
00194         _h["HTttbar"]->fill(              HT_ttbar,                  weight);
00195         _h["Yboost"]->fill(               Yboost,                    weight);
00196         _h["RWt"]->fill(                  R_Wt,                      weight);
00197         // normalised cross sections
00198         _h["ptpseudotophadron_norm"]->fill(    ppseudotophadron.pt(),     weight); //pT of pseudo top hadron
00199         _h["ptttbar_norm"]->fill(              pttbar.pt(),               weight); //fill pT of ttbar in combined channel
00200         _h["absrappseudotophadron_norm"]->fill(ppseudotophadron.absrap(), weight);
00201         _h["absrapttbar_norm"]->fill(          pttbar.absrap(),           weight);
00202         _h["massttbar_norm"]->fill(            pttbar.mass(),             weight);
00203         _h["absPout_norm"]->fill(              absPout,                   weight);
00204         _h["chittbar_norm"]->fill(             chi_ttbar,                 weight);
00205         _h["dPhittbar_norm"]->fill(            deltaPhi_ttbar,            weight);
00206         _h["HTttbar_norm"]->fill(              HT_ttbar,                  weight);
00207         _h["Yboost_norm"]->fill(               Yboost,                    weight);
00208         _h["RWt_norm"]->fill(                  R_Wt,                      weight);
00209         
00210       } 
00211 
00212       void finalize() {
00213         // Normalize to cross-section
00214         const double sf = (crossSection() / sumOfWeights());
00215         for (map<string, Histo1DPtr>::iterator hit = _h.begin(); hit != _h.end(); ++hit) {
00216           scale(hit->second, sf);
00217           if (hit->first.find("_norm") != string::npos)  normalize(hit->second);
00218         }
00219       }
00220 
00221     private:
00222 
00223 
00224       double computeneutrinoz(const FourMomentum& lepton, FourMomentum& met) const {
00225         //computing z component of neutrino momentum given lepton and met
00226         double pzneutrino;
00227         double m_W = 80.399; // in GeV, given in the paper
00228         double k = (( sqr( m_W ) - sqr( lepton.mass() ) ) / 2 ) + (lepton.px() * met.px() + lepton.py() * met.py());
00229         double a = sqr ( lepton.E() )- sqr ( lepton.pz() );
00230         double b = -2*k*lepton.pz();
00231         double c = sqr( lepton.E() ) * sqr( met.pT() ) - sqr( k );
00232         double discriminant = sqr(b) - 4 * a * c;
00233         double quad[2] = { (- b - sqrt(discriminant)) / (2 * a), (- b + sqrt(discriminant)) / (2 * a) }; //two possible quadratic solns
00234         if (discriminant < 0)  pzneutrino = - b / (2 * a); //if the discriminant is negative
00235         else { //if the discriminant is greater than or equal to zero, take the soln with smallest absolute value
00236           double absquad[2];
00237           for (int n=0; n<2; ++n)  absquad[n] = fabs(quad[n]);
00238           if (absquad[0] < absquad[1])  pzneutrino = quad[0];
00239           else                          pzneutrino = quad[1];
00240         }
00241            
00242         return pzneutrino;
00243       }
00244 
00245       double _mT(const FourMomentum &l, FourMomentum &nu) const {
00246         return sqrt( 2 * l.pT() * nu.pT() * (1 - cos(deltaPhi(l, nu))) );
00247       }
00248 
00249       /// @name Objects that are used by the event selection decisions
00250       map<string, Histo1DPtr> _h;
00251   };
00252 
00253   // The hook for the plugin system
00254   DECLARE_RIVET_PLUGIN(ATLAS_2015_I1404878);
00255 
00256 }