rivet is hosted by Hepforge, IPPP Durham
PromptFinalState.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Projections/PromptFinalState.hh"
00003 
00004 namespace Rivet {
00005 
00006 
00007   PromptFinalState::PromptFinalState(const FinalState& fsp)
00008     : _acceptMuDecays(false), _acceptTauDecays(false)
00009   {
00010     setName("PromptFinalState");
00011     addProjection(fsp, "FS");
00012   }
00013 
00014 
00015   PromptFinalState::PromptFinalState(const Cut & c)
00016     : _acceptMuDecays(false), _acceptTauDecays(false)
00017   {
00018     setName("PromptFinalState");
00019     addProjection(FinalState(c), "FS");
00020   }
00021 
00022   int PromptFinalState::compare(const Projection& p) const {
00023     const PCmp fscmp = mkNamedPCmp(p, "FS");
00024     if (fscmp != EQUIVALENT) return fscmp;
00025     const PromptFinalState& other = dynamic_cast<const PromptFinalState&>(p);
00026     return cmp(_acceptMuDecays, other._acceptMuDecays) || cmp(_acceptTauDecays, other._acceptTauDecays);
00027   }
00028 
00029 
00030   bool PromptFinalState::isPrompt(const Particle& p) const {
00031     if (p.genParticle() == NULL) return false; // no HepMC connection, give up! Throw UserError exception?
00032     const GenVertex* prodVtx = p.genParticle()->production_vertex();
00033     if (prodVtx == NULL) return false; // orphaned particle, has to be assume false
00034     const pair<GenParticle*, GenParticle*> beams = prodVtx->parent_event()->beam_particles();
00035 
00036     /// @todo Would be nicer to be able to write this recursively up the chain, exiting as soon as a parton or string/cluster is seen
00037     foreach (const GenParticle* ancestor, Rivet::particles(prodVtx, HepMC::ancestors)) {
00038       const PdgId pid = ancestor->pdg_id();
00039       if (ancestor->status() != 2) continue; // no non-standard statuses or beams to be used in decision making
00040       if (ancestor == beams.first || ancestor == beams.second) continue; // PYTHIA6 uses status 2 for beams, I think... (sigh)
00041       if (PID::isParton(pid)) continue; // PYTHIA6 also uses status 2 for some partons, I think... (sigh)
00042       if (PID::isHadron(pid)) return false; // prompt particles can't be from hadron decays
00043       if (abs(pid) == PID::TAU && p.abspid() != PID::TAU && !_acceptTauDecays) return false; // allow or ban particles from tau decays (permitting tau copies)
00044       if (abs(pid) == PID::MUON && p.abspid() != PID::MUON && !_acceptMuDecays) return false; // allow or ban particles from muon decays (permitting muon copies)
00045     }
00046     return true;
00047   }
00048 
00049 
00050   void PromptFinalState::project(const Event& e) {
00051     _theParticles.clear();
00052 
00053     const Particles& particles = applyProjection<FinalState>(e, "FS").particles();
00054     foreach (const Particle& p, particles)
00055       if (isPrompt(p)) _theParticles.push_back(p);
00056     MSG_DEBUG("Number of final state particles not from hadron decays = " << _theParticles.size());
00057 
00058     if (getLog().isActive(Log::TRACE)) {
00059       foreach (const Particle& p, _theParticles)
00060         MSG_TRACE("Selected: " << p.pid() << ", charge = " << p.charge());
00061     }
00062   }
00063 
00064 
00065 }