Rivet analyses
Tau branching fractions from PDG
Experiment: PDG (Various)
Inspire ID: 1315584
Status: VALIDATED
Authors: - Holger Schulz
References: - Chin.Phys. C38 (2014) 090001
Beams: * *
Beam energies: ANY
Run details: - Works with collision events and particle guns
Hadronic and leptonic tau decays are analysed to compare to PDG data of branching fractions.
Source
code:PDG_TAUS.cc
// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Tools/ParticleUtils.hh"
#include "Rivet/Projections/TauFinder.hh"
namespace Rivet {
class PDG_TAUS : public Analysis {
public:
/// Constructor
PDG_TAUS()
: Analysis("PDG_TAUS")
{ }
/// @name Analysis methods
/// @{
/// Book histograms and initialise projections before the run
void init() {
TauFinder tauleptonic(TauDecay::LEPTONIC); // open cuts, leptonic decays
declare(tauleptonic, "TauLeptonic");
TauFinder tauhadronic(TauDecay::HADRONIC); // open cuts, hadronic decays
declare(tauhadronic, "TauHadronic");
populateDecayMap();
book(_h_ratio_mu ,1, 1, 1);
book(_h_ratio_el ,1, 1, 2);
book(_h_1prong_pinu ,2, 1, 1);
book(_h_1prong_Kpnu ,2, 1, 2);
book(_h_1prong_pipinu ,2, 1, 3);
book(_h_1prong_Kppinu ,2, 1, 4);
book(_h_1prong_pipipinu ,2, 1, 5);
book(_h_1prong_Knpinu ,2, 1, 6);
book(_h_3prong_pipipinu ,2, 2, 1);
book(_h_5prong ,2, 3, 1);
book(_weights_had, "TMP/weights_had");
book(_weights_mu, "TMP/weights_mu");
book(_weights_el, "TMP/weights_el");
}
/// Perform the per-event analysis
void analyze(const Event& e) {
const TauFinder& taulep = apply<TauFinder>(e, "TauLeptonic");
const TauFinder& tauhad = apply<TauFinder>(e, "TauHadronic");
// Hadronic tau decays --- prong decays
for(const Particle& tau : tauhad.taus()) {
_weights_had->fill();
int prongs = countProngs(tau); // number of charged particles among decay products
// Only do 1 prong decays here
if (prongs == 1) {
////// Exclusive decay modes "1-prong"
if (analyzeDecay(tau, decay_pids["pinu"], true)) _h_1prong_pinu->fill(1);
if (analyzeDecay(tau, decay_pids["Kpnu"], true)) _h_1prong_Kpnu->fill(1);
if (analyzeDecay(tau, decay_pids["pipinu"], true)) _h_1prong_pipinu->fill(1);
if (analyzeDecay(tau, decay_pids["Kppinu"] , true)) _h_1prong_Kppinu->fill(1);
if (analyzeDecay(tau, decay_pids["pipipinu"], true)) _h_1prong_pipipinu->fill(1);
// Kshort, Klong --- (twice) filling the K0 labelled PDG histo
if (analyzeDecay(tau, decay_pids["KSpinu"] , true)) _h_1prong_Knpinu->fill(1);
if (analyzeDecay(tau, decay_pids["KLpinu"] , true)) _h_1prong_Knpinu->fill(1);
}
else if (prongs == 3) {
if (analyzeDecay(tau, decay_pids["3pipipinu"], true)) _h_3prong_pipipinu->fill(1);
}
else if (prongs == 5 && !any(tau.stableDescendants(), HasAbsPID(310))) _h_5prong->fill(1);
}
// Leptonic tau decays --- look for radiative and non-radiative 1 prong decays
for(const Particle& tau : taulep.taus()) {
int prongs = countProngs(tau); // number of charged particles among decay products
// Only do 1 prong decays here
if (prongs == 1) {
analyzeRadiativeDecay(tau, decay_pids["muids"], _weights_mu, true, _h_ratio_mu);
analyzeRadiativeDecay(tau, decay_pids["elids"], _weights_el, true, _h_ratio_el);
}
}
}
/// Normalise histograms etc., after the run
void finalize() {
scale(_h_ratio_mu, 1. / *_weights_mu);
scale(_h_ratio_el, 1. / *_weights_el);
const YODA::Counter norm = *_weights_had + *_weights_mu + *_weights_el;
scale(_h_1prong_pinu, 1./norm);
scale(_h_1prong_Kpnu, 1./norm);
scale(_h_1prong_pipinu, 1./norm);
scale(_h_1prong_Kppinu, 1./norm);
scale(_h_1prong_pipipinu, 1./norm);
scale(_h_1prong_Knpinu, 1./norm);
scale(_h_3prong_pipipinu, 1./norm);
scale(_h_5prong, 1./norm);
}
// Count charged decay products
int countProngs(Particle mother) {
int n_prongs = 0;
for(Particle p : mother.stableDescendants())
if (p.charge3()!=0) ++n_prongs;
return n_prongs;
}
// Set up a lookup table for decays
void populateDecayMap() {
decay_pids["muids"] = {{ 13,14,16 }};
decay_pids["elids"] = {{ 11,12,16 }};
decay_pids["pinu"] = {{ 211,16 }};
decay_pids["Kpnu"] = {{ 321,16 }};
decay_pids["pipinu"] = {{ 111,211,16 }};
decay_pids["Kppinu"] = {{ 111,321,16 }};
decay_pids["pipipinu"] = {{ 111,111,211,16 }};
decay_pids["KSpinu"] = {{ 211,310,16 }};
decay_pids["KLpinu"] = {{ 211,130,16 }};
decay_pids["3pipipinu"] = {{ 211,211,211,16 }};
}
bool analyzeDecay(Particle mother, const vector<int>& ids, bool absolute) {
const Particles parts = { mother };
return cascadeContains(parts, ids, absolute, true);
}
// Look for radiative (and non-radiative) tau decays to fill a ratio histo
void analyzeRadiativeDecay(Particle mother, vector<int> ids, CounterPtr &w_incl, bool absolute, Histo1DPtr h_ratio) {
// w_incl ... reference to a global weight counter for all leptonic tau decays
// h_ratio ... pointer to ratio histo
// There is no point in looking for decays with less particles than to be analysed
const Particles& descendants = mother.stableDescendants();
if (descendants.size() >= ids.size()) {
const Particles parts = { mother };
bool decayfound = cascadeContains(parts, ids, absolute, true);
// Do not increment counters if the specified decay products were not found
if (decayfound) {
w_incl->fill(); // the (global) weight counter for leptonic decays
bool radiative = any(descendants, HasPID(PID::PHOTON));
// Only fill the histo if there is a radiative decay
if (radiative) {
// Iterate over decay products to find photon with 5 MeV energy
for (const Particle& son : mother.stableDescendants()) {
if (son.pid() == PID::PHOTON) {
// Require photons to have at least 5 MeV energy in the rest frame of the tau
// boosted taus
if (!mother.momentum().betaVec().isZero()) {
LorentzTransform cms_boost = LorentzTransform::mkFrameTransformFromBeta(mother.momentum().betaVec());
if (cms_boost.transform(son.momentum())[0]/MeV > 5.) {
h_ratio->fill(1);
break;
}
}
// not boosted taus
else {
if (son.momentum()[0]/MeV > 5.) {
h_ratio->fill(1);
break;
}
}
}
} // end loop over decay products
} // end of radiative
} // end of decayfound
} // end of first if
}
private:
/// @name Histograms
/// @{
Histo1DPtr _h_ratio_mu, _h_ratio_el;
Histo1DPtr _h_1prong_pinu, _h_1prong_Kpnu, _h_1prong_Kppinu, _h_1prong_pipinu, _h_1prong_pipipinu, _h_1prong_Knpinu;
Histo1DPtr _h_3prong_pipipinu;
Histo1DPtr _h_5prong;
/// @}
CounterPtr _weights_had, _weights_mu, _weights_el;
map<string, vector<int> > decay_pids;
};
RIVET_DECLARE_PLUGIN(PDG_TAUS);
}