rivet is hosted by Hepforge, IPPP Durham
FastJets.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Config/RivetCommon.hh"
00003 #include "Rivet/Tools/Logging.hh"
00004 #include "Rivet/Projections/FastJets.hh"
00005 #include "Rivet/Projections/HeavyHadrons.hh"
00006 #include "Rivet/Projections/TauFinder.hh"
00007 
00008 namespace Rivet {
00009 
00010 
00011   void FastJets::_initBase() {
00012     setName("FastJets");
00013     addProjection(HeavyHadrons(), "HFHadrons");
00014     addProjection(TauFinder(TauFinder::HADRONIC), "Taus");
00015   }
00016 
00017 
00018   // void FastJets::_init1(JetAlgName alg, double rparameter, double seed_threshold) {
00019   //   _initBase();
00020 
00021 
00022   void FastJets::_initJdef(JetAlgName alg, double rparameter, double seed_threshold) {
00023     MSG_DEBUG("JetAlg = " << alg);
00024     MSG_DEBUG("R parameter = " << rparameter);
00025     MSG_DEBUG("Seed threshold = " << seed_threshold);
00026     if (alg == KT) {
00027       _jdef = fastjet::JetDefinition(fastjet::kt_algorithm, rparameter, fastjet::E_scheme);
00028     } else if (alg == CAM) {
00029       _jdef = fastjet::JetDefinition(fastjet::cambridge_algorithm, rparameter, fastjet::E_scheme);
00030     } else if (alg == ANTIKT) {
00031       _jdef = fastjet::JetDefinition(fastjet::antikt_algorithm, rparameter, fastjet::E_scheme);
00032     } else if (alg == DURHAM) {
00033       _jdef = fastjet::JetDefinition(fastjet::ee_kt_algorithm, fastjet::E_scheme);
00034     } else {
00035       // Plugins:
00036       if (alg == SISCONE) {
00037         const double OVERLAP_THRESHOLD = 0.75;
00038         _plugin.reset(new fastjet::SISConePlugin(rparameter, OVERLAP_THRESHOLD));
00039       // } else if (alg == PXCONE) {
00040       //   string msg = "PxCone currently not supported, since FastJet doesn't install it by default. ";
00041       //   msg += "Please notify the Rivet authors if this behaviour should be changed.";
00042       //   throw Error(msg);
00043       //  _plugin.reset(new fastjet::PxConePlugin(rparameter));
00044       } else if (alg == ATLASCONE) {
00045         const double OVERLAP_THRESHOLD = 0.5;
00046         _plugin.reset(new fastjet::ATLASConePlugin(rparameter, seed_threshold, OVERLAP_THRESHOLD));
00047       } else if (alg == CMSCONE) {
00048         _plugin.reset(new fastjet::CMSIterativeConePlugin(rparameter, seed_threshold));
00049       } else if (alg == CDFJETCLU) {
00050         const double OVERLAP_THRESHOLD = 0.75;
00051         _plugin.reset(new fastjet::CDFJetCluPlugin(rparameter, OVERLAP_THRESHOLD, seed_threshold));
00052       } else if (alg == CDFMIDPOINT) {
00053         const double OVERLAP_THRESHOLD = 0.5;
00054         _plugin.reset(new fastjet::CDFMidPointPlugin(rparameter, OVERLAP_THRESHOLD, seed_threshold));
00055       } else if (alg == D0ILCONE) {
00056         const double min_jet_Et = 6.0;
00057         _plugin.reset(new fastjet::D0RunIIConePlugin(rparameter, min_jet_Et));
00058       } else if (alg == JADE) {
00059         _plugin.reset(new fastjet::JadePlugin());
00060       } else if (alg == TRACKJET) {
00061         _plugin.reset(new fastjet::TrackJetPlugin(rparameter));
00062       }
00063       _jdef = fastjet::JetDefinition(_plugin.get());
00064     }
00065   }
00066 
00067 
00068   // void FastJets::_init2(fastjet::JetAlgorithm type,
00069   //                       fastjet::RecombinationScheme recom, double rparameter)
00070   //   : FastJets
00071   // {
00072 
00073   //   _initBase();
00074   //   _jdef = fastjet::JetDefinition(type, rparameter, recom);
00075   // }
00076 
00077 
00078   // void FastJets::_init3(const fastjet::JetDefinition& jdef) {
00079   //   _initBase();
00080   //   _jdef = jdef;
00081   // }
00082 
00083 
00084   // void FastJets::_init4(fastjet::JetDefinition::Plugin* plugin) {
00085   //   _initBase();
00086   //   _plugin.reset(plugin);
00087   //   _jdef = fastjet::JetDefinition(_plugin.get());
00088   // }
00089 
00090 
00091 
00092   int FastJets::compare(const Projection& p) const {
00093     const FastJets& other = dynamic_cast<const FastJets&>(p);
00094     return \
00095       cmp(_useMuons, other._useMuons) ||
00096       cmp(_useInvisibles, other._useInvisibles) ||
00097       mkNamedPCmp(other, "FS") ||
00098       cmp(_jdef.jet_algorithm(), other._jdef.jet_algorithm()) ||
00099       cmp(_jdef.recombination_scheme(), other._jdef.recombination_scheme()) ||
00100       cmp(_jdef.plugin(), other._jdef.plugin()) ||
00101       cmp(_jdef.R(), other._jdef.R()) ||
00102       cmp(_adef, other._adef);
00103   }
00104 
00105 
00106   namespace {
00107     /// @todo Replace with C++11 lambdas
00108     bool isPromptInvisible(const Particle& p) { return !(p.isVisible() || p.fromDecay()); }
00109     // bool isMuon(const Particle& p) { return p.abspid() == PID::MUON; }
00110     bool isPromptMuon(const Particle& p) { return isMuon(p) && !p.fromDecay(); }
00111   }
00112 
00113 
00114   void FastJets::project(const Event& e) {
00115     // Assemble final state particles
00116     const string fskey = (_useInvisibles == JetAlg::NO_INVISIBLES) ? "VFS" : "FS";
00117     Particles fsparticles = applyProjection<FinalState>(e, fskey).particles();
00118     // Remove prompt invisibles if needed (already done by VFS if using NO_INVISIBLES)
00119     if (_useInvisibles == JetAlg::DECAY_INVISIBLES)
00120       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isPromptInvisible), fsparticles.end() );
00121     // Remove prompt/all muons if needed
00122     if (_useMuons == JetAlg::DECAY_MUONS)
00123       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isPromptMuon), fsparticles.end() );
00124     else if (_useMuons == JetAlg::NO_MUONS)
00125       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isMuon), fsparticles.end() );
00126 
00127     // Tagging particles
00128     /// @todo Allow the user to specify tag particle kinematic thresholds
00129     const Particles chadrons = applyProjection<HeavyHadrons>(e, "HFHadrons").cHadrons();
00130     const Particles bhadrons = applyProjection<HeavyHadrons>(e, "HFHadrons").bHadrons();
00131     const Particles taus = applyProjection<FinalState>(e, "Taus").particles();
00132     calc(fsparticles, chadrons+bhadrons+taus);
00133   }
00134 
00135 
00136   void FastJets::calc(const Particles& fsparticles, const Particles& tagparticles) {
00137     _particles.clear();
00138     vector<fastjet::PseudoJet> pjs;
00139 
00140     MSG_DEBUG("Finding jets from " << fsparticles.size() << " input particles");
00141 
00142     /// @todo Use FastJet3's UserInfo system
00143 
00144     // Store 4 vector data about each particle into FastJet's PseudoJets
00145     int counter = 1;
00146     for (const Particle& p : fsparticles) {
00147       fastjet::PseudoJet pj = p;
00148       pj.set_user_index(counter);
00149       pjs.push_back(pj);
00150       _particles[counter] = p;
00151       counter += 1;
00152     }
00153     // And the same for ghost tagging particles (with negative user indices)
00154     counter = 1;
00155     for (const Particle& p : tagparticles) {
00156       fastjet::PseudoJet pj = p;
00157       pj *= 1e-20; ///< Ghostify the momentum
00158       pj.set_user_index(-counter);
00159       pjs.push_back(pj);
00160       _particles[-counter] = p;
00161       counter += 1;
00162     }
00163 
00164     // Choose cseq as basic or area-calculating
00165     if (_adef) {
00166       _cseq.reset(new fastjet::ClusterSequenceArea(pjs, _jdef, *_adef));
00167     } else {
00168       _cseq.reset(new fastjet::ClusterSequence(pjs, _jdef));
00169     }
00170     MSG_DEBUG("FastJet ClusterSequence constructed; Njets_tot = "
00171               << _cseq->inclusive_jets().size() << ", Njets_10 = "
00172               << _cseq->inclusive_jets(10*GeV).size()); //< only inefficient in debug mode
00173   }
00174 
00175 
00176   void FastJets::reset() {
00177     _yscales.clear();
00178     _particles.clear();
00179     /// @todo _cseq = fastjet::ClusterSequence();
00180   }
00181 
00182 
00183   Jets FastJets::_jets() const {
00184     Jets rtn; rtn.reserve(pseudojets().size());
00185     foreach (const fastjet::PseudoJet& pj, pseudojets()) {
00186       rtn.push_back(_mkJet(pj));
00187     }
00188     /// @todo Cache?
00189     return rtn;
00190   }
00191 
00192 
00193   Jet FastJets::trimJet(const Jet &input, const fastjet::Filter &trimmer)const{
00194     assert(input.pseudojet().associated_cluster_sequence() == clusterSeq().get());
00195     PseudoJet pj = trimmer(input);
00196     return _mkJet(pj);
00197   }
00198 
00199 
00200   PseudoJets FastJets::pseudoJets(double ptmin) const {
00201     return clusterSeq() ? clusterSeq()->inclusive_jets(ptmin) : PseudoJets();
00202   }
00203 
00204 
00205   Jet FastJets::_mkJet(const PseudoJet &pj)const{
00206     assert(clusterSeq());
00207 
00208     // Take the constituents from the cluster sequence, unless the jet was not
00209     // associated with the cluster sequence (could be the case for trimmed jets)
00210     const PseudoJets parts = (pj.associated_cluster_sequence() == clusterSeq().get())
00211       ? clusterSeq()->constituents(pj) : pj.constituents();
00212 
00213     vector<Particle> constituents, tags;
00214     constituents.reserve(parts.size());
00215     for (const fastjet::PseudoJet& p : parts) {
00216       map<int, Particle>::const_iterator found = _particles.find(p.user_index());
00217       // assert(found != _particles.end());
00218       if (found == _particles.end() && p.is_pure_ghost()) continue; //< Pure FJ ghosts are ok
00219       assert(found != _particles.end()); //< Anything else must be known
00220       assert(found->first != 0); //< All mapping IDs are pos-def (particles) or neg-def (tags)
00221       if (found->first > 0) constituents.push_back(found->second);
00222       else if (found->first < 0) tags.push_back(found->second);
00223     }
00224 
00225     return Jet(pj, constituents, tags);
00226   }
00227 
00228 
00229 }