rivet is hosted by Hepforge, IPPP Durham
ATLAS_2016_I1424838.cc
Go to the documentation of this file.
00001 #include "Rivet/Analysis.hh"
00002 #include "Rivet/Projections/Thrust.hh"
00003 #include "Rivet/Projections/ZFinder.hh"
00004 #include "Rivet/Projections/FParameter.hh"
00005 #include "Rivet/Projections/Spherocity.hh"
00006 #include "Rivet/Projections/ChargedFinalState.hh"
00007 #include "Rivet/Projections/VetoedFinalState.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   /// @brief Event shapes in leptonic $Z$-events
00013   class ATLAS_2016_I1424838 : public Analysis {
00014   public:
00015 
00016     /// Constructor
00017     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2016_I1424838);
00018 
00019 
00020     /// Book histograms and initialise projections before the run
00021     void init() {
00022 
00023       // Charged particles inside acceptance region
00024       const ChargedFinalState cfs(Cuts::abseta < 2.5 && Cuts::pT > 500*MeV);
00025       declare(cfs, "CFS");
00026 
00027       // ZFinders
00028       ZFinder zfinder(cfs, Cuts::abseta<2.4 && Cuts::pT>20.0*GeV, PID::ELECTRON, 66*GeV, 116*GeV, 0.1, ZFinder::CLUSTERNODECAY);
00029       declare(zfinder, "ZFinder");
00030       ZFinder zfinder_mu(cfs, Cuts::abseta<2.4 && Cuts::pT>20.0*GeV, PID::MUON, 66*GeV, 116*GeV, 0.1, ZFinder::CLUSTERNODECAY);
00031       declare(zfinder_mu, "ZFinderMu");
00032 
00033       // This CFS only contains charged particles inside the acceptance excluding the leptons
00034       VetoedFinalState remfs(cfs);
00035       remfs.addVetoOnThisFinalState(zfinder);
00036       remfs.addVetoOnThisFinalState(zfinder_mu);
00037       declare(remfs, "REMFS");
00038 
00039       const FParameter fparam(remfs);
00040       declare(fparam, "FParameter_");
00041 
00042       const Spherocity sphero(remfs);
00043       declare(sphero, "Spherocity_");
00044 
00045 
00046       // Booking of ES histos
00047       for (size_t alg = 0; alg < 5; ++alg) {
00048         // Book the inclusive histograms
00049         _h_Elec_Ntrk[alg]         = bookHisto1D(_mkHistoName(1, 1, alg));
00050         _h_Elec_SumPt[alg]        = bookHisto1D(_mkHistoName(2, 1, alg));
00051         _h_Elec_Beamthrust[alg]   = bookHisto1D(_mkHistoName(3, 1, alg));
00052         _h_Elec_Thrust[alg]       = bookHisto1D(_mkHistoName(4, 1, alg));
00053         _h_Elec_FParam[alg]       = bookHisto1D(_mkHistoName(5, 1, alg));
00054         _h_Elec_Spherocity[alg]   = bookHisto1D(_mkHistoName(6, 1, alg));
00055         _h_Muon_Ntrk[alg]         = bookHisto1D(_mkHistoName(1, 2, alg));
00056         _h_Muon_SumPt[alg]        = bookHisto1D(_mkHistoName(2, 2, alg));
00057         _h_Muon_Beamthrust[alg]   = bookHisto1D(_mkHistoName(3, 2, alg));
00058         _h_Muon_Thrust[alg]       = bookHisto1D(_mkHistoName(4, 2, alg));
00059         _h_Muon_FParam[alg]       = bookHisto1D(_mkHistoName(5, 2, alg));
00060         _h_Muon_Spherocity[alg]   = bookHisto1D(_mkHistoName(6, 2, alg));
00061       }
00062     }
00063 
00064 
00065     /// Perform the per-event analysis
00066     void analyze(const Event& event) {
00067 
00068       // Get generator weight
00069       const double weight = event.weight();
00070 
00071       // Check for Z boson in event
00072       const ZFinder& zfinder    = apply<ZFinder>(event, "ZFinder");
00073       MSG_DEBUG("Num e+ e- pairs found = " << zfinder.bosons().size());
00074       const bool isElec = zfinder.bosons().size() == 1;
00075 
00076       const ZFinder& zfinder_mu = apply<ZFinder>(event, "ZFinderMu");
00077       MSG_DEBUG("Num mu+ mu- pairs found = " << zfinder_mu.bosons().size());
00078       const bool isMuon = zfinder_mu.bosons().size() == 1;
00079 
00080       // Only accept events with exactly two electrons or exactly two muons
00081       if (isElec && isMuon) vetoEvent;
00082       if (!(isElec || isMuon)) vetoEvent;
00083 
00084       // This determines the Zpt phase-space
00085       double zpT = -1000;
00086       if (isElec) zpT = zfinder.bosons()[0].pT();
00087       if (isMuon) zpT = zfinder_mu.bosons()[0].pT();
00088 
00089       unsigned int alg = 4; //< for > 25 GeV
00090       if (zpT < 6*GeV) alg = 1;
00091       else if (inRange(zpT/GeV, 6, 12)) alg = 2;
00092       else if (inRange(zpT/GeV, 12, 25)) alg = 3;
00093       assert(alg < 5);
00094       assert(alg > 0);
00095 
00096       // All charged particles within |eta|<2.5 except the leptons from Z-decay
00097       const VetoedFinalState& remfs = apply<VetoedFinalState>(event, "REMFS");
00098       // sumPt and Beamthrust (the latter will only be filled if the min Nch criterion is met)
00099       // and Thrust preparation
00100       double sumPt = 0.0, beamThrust = 0.0;
00101 
00102       vector<Vector3> momenta;
00103       foreach(const Particle& p , remfs.particles()) {
00104         double pT = fabs(p.momentum().pT());
00105         double eta = p.momentum().eta();
00106         sumPt += pT;
00107         beamThrust += pT*exp(-1.0*fabs(eta));
00108         Vector3 mom = p.momentum().vector3();
00109         mom.setZ(0.0);
00110         momenta.push_back(mom);
00111       }
00112 
00113 
00114       // Fill inclusive histos
00115       if (isElec) {
00116         _h_Elec_Ntrk[alg]       ->fill(remfs.size(),        weight);
00117         _h_Elec_Ntrk[0]         ->fill(remfs.size(),        weight);
00118         _h_Elec_SumPt[alg]      ->fill(sumPt,               weight);
00119         _h_Elec_SumPt[0]        ->fill(sumPt,               weight);
00120       }
00121       if (isMuon) {
00122         _h_Muon_Ntrk[alg]       ->fill(remfs.size(),        weight);
00123         _h_Muon_Ntrk[0]         ->fill(remfs.size(),        weight);
00124         _h_Muon_SumPt[alg]      ->fill(sumPt,               weight);
00125         _h_Muon_SumPt[0]        ->fill(sumPt,               weight);
00126       }
00127 
00128       // Skip event shape calculation if we don't match the minimum Nch criterion
00129       if (remfs.size() >=2) {
00130 
00131         // Eventshape calculations
00132 
00133         // Calculate transverse Thrust using all charged FS particles except the lepton
00134         // This is copied/inspired from the CMS_6000011_S8957746 analysis
00135         if (momenta.size() == 2) {
00136           // We need to use a ghost so that Thrust.calc() doesn't return 1.
00137           momenta.push_back(Vector3(1e-10*MeV, 0., 0.));
00138         }
00139         Thrust thrustC;
00140         thrustC.calc(momenta);
00141 
00142         double thrust = thrustC.thrust();
00143 
00144         // F-Parameter
00145         const FParameter& fparam = apply<FParameter>(event, "FParameter_");
00146         // Spherocity
00147         const Spherocity& sphero = apply<Spherocity>(event, "Spherocity_");
00148 
00149         // Histos differential in NMPI
00150 
00151         // Fill inclusive histos
00152         if (isElec) {
00153           _h_Elec_Thrust[alg]     ->fill(thrust,              weight);
00154           _h_Elec_Thrust[0]       ->fill(thrust,              weight);
00155           _h_Elec_FParam[alg]     ->fill(fparam.F(),          weight);
00156           _h_Elec_FParam[0]       ->fill(fparam.F(),          weight);
00157           _h_Elec_Spherocity[alg] ->fill(sphero.spherocity(), weight);
00158           _h_Elec_Spherocity[0]   ->fill(sphero.spherocity(), weight);
00159           _h_Elec_Beamthrust[alg] ->fill(beamThrust,          weight);
00160           _h_Elec_Beamthrust[0]   ->fill(beamThrust,          weight);
00161         }
00162         if (isMuon) {
00163           _h_Muon_Thrust[alg]     ->fill(thrust,              weight);
00164           _h_Muon_Thrust[0]       ->fill(thrust,              weight);
00165           _h_Muon_FParam[alg]     ->fill(fparam.F(),          weight);
00166           _h_Muon_FParam[0]       ->fill(fparam.F(),          weight);
00167           _h_Muon_Spherocity[alg] ->fill(sphero.spherocity(), weight);
00168           _h_Muon_Spherocity[0]   ->fill(sphero.spherocity(), weight);
00169           _h_Muon_Beamthrust[alg] ->fill(beamThrust,          weight);
00170           _h_Muon_Beamthrust[0]   ->fill(beamThrust,          weight);
00171         }
00172       }
00173     }
00174 
00175 
00176     /// Normalise histograms etc., after the run
00177     void finalize() {
00178       for (size_t alg = 0; alg < 5; ++alg) {
00179         normalize(_h_Elec_Ntrk[alg]);
00180         normalize(_h_Elec_SumPt[alg]);
00181         normalize(_h_Elec_Beamthrust[alg]);
00182         normalize(_h_Elec_Thrust[alg]);
00183         normalize(_h_Elec_FParam[alg]);
00184         normalize(_h_Elec_Spherocity[alg]);
00185         normalize(_h_Muon_Ntrk[alg]);
00186         normalize(_h_Muon_SumPt[alg]);
00187         normalize(_h_Muon_Beamthrust[alg]);
00188         normalize(_h_Muon_Thrust[alg]);
00189         normalize(_h_Muon_FParam[alg]);
00190         normalize(_h_Muon_Spherocity[alg]);
00191       }
00192     }
00193 
00194 
00195   private:
00196 
00197     // Convenience method for histogram booking
00198     string _mkHistoName(int idDS, int channel, int i) {
00199       return "d0" + toString(idDS) + "-x0" + toString(channel) + "-y0" + toString(i+1);
00200     }
00201 
00202     Histo1DPtr _h_Elec_Ntrk[5];
00203     Histo1DPtr _h_Elec_SumPt[5];
00204     Histo1DPtr _h_Elec_Beamthrust[5];
00205     Histo1DPtr _h_Elec_Thrust[5];
00206     Histo1DPtr _h_Elec_FParam[5];
00207     Histo1DPtr _h_Elec_Spherocity[5];
00208 
00209     Histo1DPtr _h_Muon_Ntrk[5];
00210     Histo1DPtr _h_Muon_SumPt[5];
00211     Histo1DPtr _h_Muon_Beamthrust[5];
00212     Histo1DPtr _h_Muon_Thrust[5];
00213     Histo1DPtr _h_Muon_FParam[5];
00214     Histo1DPtr _h_Muon_Spherocity[5];
00215 
00216   };
00217 
00218 
00219   DECLARE_RIVET_PLUGIN(ATLAS_2016_I1424838);
00220 
00221 
00222 }