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