rivet is hosted by Hepforge, IPPP Durham
PDG_TAUS.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/TauFinder.hh"
00004 
00005 namespace Rivet {
00006 
00007 
00008   class PDG_TAUS : public Analysis {
00009   public:
00010 
00011     /// Constructor
00012     PDG_TAUS()
00013       : Analysis("PDG_TAUS"),
00014         _weights_had(0),
00015         _weights_mu(0),
00016         _weights_el(0)
00017     {   }
00018 
00019 
00020     /// @name Analysis methods
00021     //@{
00022 
00023     /// Book histograms and initialise projections before the run
00024     void init() {
00025 
00026       TauFinder tauleptonic(TauFinder::LEPTONIC); // open cuts, leptonic decays
00027       addProjection(tauleptonic, "TauLeptonic");
00028 
00029       TauFinder tauhadronic(TauFinder::HADRONIC); // open cuts, hadronic decays
00030       addProjection(tauhadronic, "TauHadronic");
00031 
00032       populateDecayMap();
00033 
00034       _h_ratio_mu        = bookHisto1D(1, 1, 1);
00035       _h_ratio_el        = bookHisto1D(1, 1, 2);
00036       _h_1prong_pinu     = bookHisto1D(2, 1, 1);
00037       _h_1prong_Kpnu     = bookHisto1D(2, 1, 2);
00038       _h_1prong_pipinu   = bookHisto1D(2, 1, 3);
00039       _h_1prong_Kppinu   = bookHisto1D(2, 1, 4);
00040       _h_1prong_pipipinu = bookHisto1D(2, 1, 5);
00041       _h_1prong_Knpinu   = bookHisto1D(2, 1, 6);
00042       _h_3prong_pipipinu = bookHisto1D(2, 2, 1);
00043       _h_5prong          = bookHisto1D(2, 3, 1);
00044     }
00045 
00046 
00047     /// Perform the per-event analysis
00048     void analyze(const Event& e) {
00049       const double weight = e.weight();
00050 
00051       const TauFinder& taulep = applyProjection<TauFinder>(e, "TauLeptonic");
00052       const TauFinder& tauhad = applyProjection<TauFinder>(e, "TauHadronic");
00053 
00054       // Hadronic tau decays --- prong decays
00055       foreach(const Particle& tau, tauhad.taus()) {
00056         _weights_had += weight;
00057         int prongs = countProngs(tau); // number of charged particles among decay products
00058         // Only do 1 prong decays here
00059         if (prongs == 1) {
00060           ////// Exclusive decay modes "1-prong"
00061           if (analyzeDecay(tau,   decay_pids["pinu"], true))     _h_1prong_pinu->fill(1, weight);
00062           if (analyzeDecay(tau,   decay_pids["Kpnu"], true))     _h_1prong_Kpnu->fill(1, weight);
00063           if (analyzeDecay(tau, decay_pids["pipinu"], true))     _h_1prong_pipinu->fill(1, weight);
00064           if (analyzeDecay(tau, decay_pids["Kppinu"]  , true))   _h_1prong_Kppinu->fill(1, weight);
00065           if (analyzeDecay(tau, decay_pids["pipipinu"], true))   _h_1prong_pipipinu->fill(1, weight);
00066           // Kshort, Klong --- (twice) filling the K0 labelled PDG histo
00067           if (analyzeDecay(tau, decay_pids["KSpinu"]  , true))   _h_1prong_Knpinu->fill(1, weight);
00068           if (analyzeDecay(tau, decay_pids["KLpinu"]  , true))   _h_1prong_Knpinu->fill(1, weight);
00069         }
00070         else if (prongs == 3) {
00071           if (analyzeDecay(tau, decay_pids["3pipipinu"], true))  _h_3prong_pipipinu->fill(1, weight);
00072         }
00073         else if (prongs == 5 && !any(tau.children(), HasAbsPID(310))) _h_5prong->fill(1, weight);
00074       }
00075 
00076       // Leptonic tau decays --- look for radiative and non-radiative 1 prong decays
00077       foreach(const Particle& tau, taulep.taus()) {
00078         int prongs = countProngs(tau); // number of charged particles among decay products
00079         // Only do 1 prong decays here
00080         if (prongs == 1) {
00081           analyzeRadiativeDecay(tau, decay_pids["muids"], _weights_mu,  weight, true, _h_ratio_mu);
00082           analyzeRadiativeDecay(tau, decay_pids["elids"], _weights_el,  weight, true, _h_ratio_el);
00083         }
00084       }
00085     }
00086 
00087 
00088     /// Normalise histograms etc., after the run
00089     void finalize() {
00090       scale(_h_ratio_mu, 1./_weights_mu);
00091       scale(_h_ratio_el, 1./_weights_el);
00092 
00093       const double norm = _weights_had + _weights_mu + _weights_el;
00094       scale(_h_1prong_pinu,     1./norm);
00095       scale(_h_1prong_Kpnu,     1./norm);
00096       scale(_h_1prong_pipinu,   1./norm);
00097       scale(_h_1prong_Kppinu,   1./norm);
00098       scale(_h_1prong_pipipinu, 1./norm);
00099       scale(_h_1prong_Knpinu,   1./norm);
00100       scale(_h_3prong_pipipinu, 1./norm);
00101       scale(_h_5prong,          1./norm);
00102     }
00103 
00104 
00105     // Short hand
00106     bool contains(Particle& mother, int id, bool abs=false) {
00107       if (abs) return any(mother.children(), HasAbsPID(id));
00108       return any(mother.children(), HasPID(id));
00109     }
00110 
00111 
00112     // Count charged decay products
00113     int countProngs(Particle mother) {
00114       int n_prongs = 0;
00115       foreach(Particle p, mother.children())
00116         if (p.threeCharge()!=0) ++n_prongs;
00117       return n_prongs;
00118     }
00119 
00120 
00121     // Set up a lookup table for decays
00122     void populateDecayMap() {
00123       decay_pids["muids"]     += 13,14,16;
00124       decay_pids["elids"]     += 11,12,16;
00125       decay_pids["pinu"]      += 211,16;
00126       decay_pids["Kpnu"]      += 321,16;
00127       decay_pids["pipinu"]    += 111,211,16;
00128       decay_pids["Kppinu"]    += 111,321,16;
00129       decay_pids["pipipinu"]  += 111,111,211,16;
00130       decay_pids["KSpinu"]    += 211,310,16;
00131       decay_pids["KLpinu"]    += 211,130,16;
00132       decay_pids["3pipipinu"] += 211,211,211,16;
00133     }
00134 
00135 
00136     bool analyzeDecay(Particle mother, vector<int> ids, bool absolute) {
00137       // There is no point in looking for decays with less particles than to be analysed
00138       if (mother.children().size() == ids.size()) {
00139         bool decayfound = true;
00140         foreach (int id, ids) {
00141           if (!contains(mother, id, absolute)) decayfound = false;
00142         }
00143         return decayfound;
00144       } // end of first if
00145       return false;
00146     }
00147 
00148 
00149     // Look for radiative (and non-radiative) tau decays to fill a ratio histo
00150     void analyzeRadiativeDecay(Particle mother, vector<int> ids, double &w_incl, double e_weight, bool absolute, Histo1DPtr h_ratio) {
00151       // w_incl   ... reference to a global weight counter for all leptonic tau decays
00152       // e_weight ... the current event weight
00153       // h_ratio  ... pointer to ratio histo --- filled with e_weight in case of radiative events only
00154 
00155       // There is no point in looking for decays with less particles than to be analysed
00156       if (mother.children().size() >= ids.size()) {
00157         bool decayfound = true;
00158         foreach (int id, ids) {
00159           if (!contains(mother, id, absolute)) decayfound = false;
00160         }
00161         // Do not increment counters if the specified decay products were not found
00162         if (decayfound) {
00163           w_incl += e_weight; // the (global) weight counter for leptonic decays
00164           bool radiative = any(mother.children(), HasPID(PID::PHOTON));
00165 
00166           // Only fill the histo if there is a radiative decay
00167           if (radiative) {
00168             // Iterate over decay products to find photon with 5MeV energy
00169             foreach (const Particle& son, mother.children()) {
00170               if (son.pid() == PID::PHOTON) {
00171                 // Require photons to have at least 5 MeV energy in the rest frame of the tau
00172                 // boosted taus
00173                 if (!mother.momentum().boostVector().isZero()) {
00174                   LorentzTransform cms_boost;
00175                     Vector3 bv = -mother.momentum().boostVector();
00176                     cms_boost = LorentzTransform(bv);
00177                     if (cms_boost.transform(son.momentum())[0]/MeV > 5.) {
00178                       h_ratio->fill(1, e_weight);
00179                       break;
00180                     }
00181                 }
00182                 // not boosted taus
00183                 else {
00184                   if (son.momentum()[0]/MeV > 5.) {
00185                     h_ratio->fill(1, e_weight);
00186                     break;
00187                   }
00188                 }
00189               }
00190             } // end loop over decay products
00191           } // end of radiative
00192         } // end of decayfound
00193       } // end of first if
00194     }
00195 
00196 
00197   private:
00198 
00199     /// @name Histograms
00200     //@{
00201     Histo1DPtr _h_ratio_mu, _h_ratio_el;
00202     Histo1DPtr _h_1prong_pinu, _h_1prong_Kpnu, _h_1prong_Kppinu, _h_1prong_pipinu, _h_1prong_pipipinu, _h_1prong_Knpinu;
00203     Histo1DPtr _h_3prong_pipipinu;
00204     Histo1DPtr _h_5prong;
00205     //@}
00206 
00207     double _weights_had, _weights_mu, _weights_el;
00208     map<string, vector<int> > decay_pids;
00209 
00210   };
00211 
00212 
00213   // The hook for the plugin system
00214   DECLARE_RIVET_PLUGIN(PDG_TAUS);
00215 
00216 }