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     /// @todo Shouldn't a const vertex be being returned? Ah, HepMC...
00033     GenVertex* prodVtx = p.genParticle()->production_vertex();
00034     if (prodVtx == NULL) return false; // orphaned particle, has to be assume false
00035     const pair<GenParticle*, GenParticle*> beams = prodVtx->parent_event()->beam_particles();
00036 
00037     /// @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
00038     foreach (const GenParticle* ancestor, Rivet::particles(prodVtx, HepMC::ancestors)) {
00039       const PdgId pid = ancestor->pdg_id();
00040       if (ancestor->status() != 2) continue; // no non-standard statuses or beams to be used in decision making
00041       if (ancestor == beams.first || ancestor == beams.second) continue; // PYTHIA6 uses status 2 for beams, I think... (sigh)
00042       if (PID::isParton(pid)) continue; // PYTHIA6 also uses status 2 for some partons, I think... (sigh)
00043       if (PID::isHadron(pid)) return false; // prompt particles can't be from hadron decays
00044       if (abs(pid) == PID::TAU && p.abspid() != PID::TAU && !_acceptTauDecays) return false; // allow or ban particles from tau decays (permitting tau copies)
00045       if (abs(pid) == PID::MUON && p.abspid() != PID::MUON && !_acceptMuDecays) return false; // allow or ban particles from muon decays (permitting muon copies)
00046     }
00047     return true;
00048   }
00049 
00050 
00051   void PromptFinalState::project(const Event& e) {
00052     _theParticles.clear();
00053 
00054     const Particles& particles = applyProjection<FinalState>(e, "FS").particles();
00055     foreach (const Particle& p, particles)
00056       if (isPrompt(p)) _theParticles.push_back(p);
00057     MSG_DEBUG("Number of final state particles not from hadron decays = " << _theParticles.size());
00058 
00059     if (getLog().isActive(Log::TRACE)) {
00060       foreach (const Particle& p, _theParticles)
00061         MSG_TRACE("Selected: " << p.pid() << ", charge = " << p.charge());
00062     }
00063   }
00064 
00065 
00066 }