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   void FastJets::_init1(JetAlgName alg, double rparameter, double seed_threshold) {
00018     _initBase();
00019     MSG_DEBUG("JetAlg = " << alg);
00020     MSG_DEBUG("R parameter = " << rparameter);
00021     MSG_DEBUG("Seed threshold = " << seed_threshold);
00022     if (alg == KT) {
00023       _jdef = fastjet::JetDefinition(fastjet::kt_algorithm, rparameter, fastjet::E_scheme);
00024     } else if (alg == CAM) {
00025       _jdef = fastjet::JetDefinition(fastjet::cambridge_algorithm, rparameter, fastjet::E_scheme);
00026     } else if (alg == ANTIKT) {
00027       _jdef = fastjet::JetDefinition(fastjet::antikt_algorithm, rparameter, fastjet::E_scheme);
00028     } else if (alg == DURHAM) {
00029       _jdef = fastjet::JetDefinition(fastjet::ee_kt_algorithm, fastjet::E_scheme);
00030     } else {
00031       // Plugins:
00032       if (alg == SISCONE) {
00033         const double OVERLAP_THRESHOLD = 0.75;
00034         _plugin.reset(new fastjet::SISConePlugin(rparameter, OVERLAP_THRESHOLD));
00035       // } else if (alg == PXCONE) {
00036       //   string msg = "PxCone currently not supported, since FastJet doesn't install it by default. ";
00037       //   msg += "Please notify the Rivet authors if this behaviour should be changed.";
00038       //   throw Error(msg);
00039         //_plugin.reset(new fastjet::PxConePlugin(rparameter));
00040       } else if (alg == ATLASCONE) {
00041         const double OVERLAP_THRESHOLD = 0.5;
00042         _plugin.reset(new fastjet::ATLASConePlugin(rparameter, seed_threshold, OVERLAP_THRESHOLD));
00043       } else if (alg == CMSCONE) {
00044         _plugin.reset(new fastjet::CMSIterativeConePlugin(rparameter, seed_threshold));
00045       } else if (alg == CDFJETCLU) {
00046         const double OVERLAP_THRESHOLD = 0.75;
00047         _plugin.reset(new fastjet::CDFJetCluPlugin(rparameter, OVERLAP_THRESHOLD, seed_threshold));
00048       } else if (alg == CDFMIDPOINT) {
00049         const double OVERLAP_THRESHOLD = 0.5;
00050         _plugin.reset(new fastjet::CDFMidPointPlugin(rparameter, OVERLAP_THRESHOLD, seed_threshold));
00051       } else if (alg == D0ILCONE) {
00052         const double min_jet_Et = 6.0;
00053         _plugin.reset(new fastjet::D0RunIIConePlugin(rparameter, min_jet_Et));
00054       } else if (alg == JADE) {
00055         _plugin.reset(new fastjet::JadePlugin());
00056       } else if (alg == TRACKJET) {
00057         _plugin.reset(new fastjet::TrackJetPlugin(rparameter));
00058       }
00059       _jdef = fastjet::JetDefinition(_plugin.get());
00060     }
00061   }
00062 
00063   void FastJets::_init2(fastjet::JetAlgorithm type,
00064                         fastjet::RecombinationScheme recom, double rparameter) {
00065     _initBase();
00066     _jdef = fastjet::JetDefinition(type, rparameter, recom);
00067   }
00068 
00069   void FastJets::_init3(const fastjet::JetDefinition& jdef) {
00070     _initBase();
00071     _jdef = jdef;
00072   }
00073 
00074   void FastJets::_init4(fastjet::JetDefinition::Plugin* plugin) {
00075     _initBase();
00076     _plugin.reset(plugin);
00077     _jdef = fastjet::JetDefinition(_plugin.get());
00078   }
00079 
00080 
00081 
00082   int FastJets::compare(const Projection& p) const {
00083     const FastJets& other = dynamic_cast<const FastJets&>(p);
00084     return \
00085       cmp(_useMuons, other._useMuons) ||
00086       cmp(_useInvisibles, other._useInvisibles) ||
00087       mkNamedPCmp(other, "FS") ||
00088       cmp(_jdef.jet_algorithm(), other._jdef.jet_algorithm()) ||
00089       cmp(_jdef.recombination_scheme(), other._jdef.recombination_scheme()) ||
00090       cmp(_jdef.plugin(), other._jdef.plugin()) ||
00091       cmp(_jdef.R(), other._jdef.R()) ||
00092       cmp(_adef, other._adef);
00093   }
00094 
00095 
00096   namespace {
00097     bool isPromptInvisible(const Particle& p) { return !(p.isVisible() || p.fromDecay()); }
00098     // bool isMuon(const Particle& p) { return p.abspid() == PID::MUON; }
00099     bool isPromptMuon(const Particle& p) { return isMuon(p) && !p.fromDecay(); }
00100   }
00101 
00102 
00103   void FastJets::project(const Event& e) {
00104     // Assemble final state particles
00105     const string fskey = (_useInvisibles == JetAlg::NO_INVISIBLES) ? "VFS" : "FS";
00106     Particles fsparticles = applyProjection<FinalState>(e, fskey).particles();
00107     // Remove prompt invisibles if needed (already done by VFS if using NO_INVISIBLES)
00108     if (_useInvisibles == JetAlg::DECAY_INVISIBLES)
00109       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isPromptInvisible), fsparticles.end() );
00110     // Remove prompt/all muons if needed
00111     if (_useMuons == JetAlg::DECAY_MUONS)
00112       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isPromptMuon), fsparticles.end() );
00113     else if (_useMuons == JetAlg::NO_MUONS)
00114       fsparticles.erase( std::remove_if(fsparticles.begin(), fsparticles.end(), isMuon), fsparticles.end() );
00115 
00116     // Tagging particles
00117     const Particles chadrons = applyProjection<HeavyHadrons>(e, "HFHadrons").cHadrons();
00118     const Particles bhadrons = applyProjection<HeavyHadrons>(e, "HFHadrons").bHadrons();
00119     const Particles taus = applyProjection<FinalState>(e, "Taus").particles();
00120     calc(fsparticles, chadrons+bhadrons+taus);
00121   }
00122 
00123 
00124   void FastJets::calc(const Particles& fsparticles, const Particles& tagparticles) {
00125     _particles.clear();
00126     vector<fastjet::PseudoJet> pjs;
00127 
00128     /// @todo Use FastJet3's UserInfo system
00129 
00130     // Store 4 vector data about each particle into FastJet's PseudoJets
00131     int counter = 1;
00132     foreach (const Particle& p, fsparticles) {
00133       const FourMomentum fv = p.momentum();
00134       fastjet::PseudoJet pj(fv.px(), fv.py(), fv.pz(), fv.E()); ///< @todo Eliminate with implicit cast?
00135       pj.set_user_index(counter);
00136       pjs.push_back(pj);
00137       _particles[counter] = p;
00138       counter += 1;
00139     }
00140     // And the same for ghost tagging particles (with negative user indices)
00141     counter = 1;
00142     foreach (const Particle& p, tagparticles) {
00143       const FourMomentum fv = 1e-20 * p.momentum(); ///< Ghostify the momentum
00144       fastjet::PseudoJet pj(fv.px(), fv.py(), fv.pz(), fv.E()); ///< @todo Eliminate with implicit cast?
00145       pj.set_user_index(-counter);
00146       pjs.push_back(pj);
00147       _particles[-counter] = p;
00148       counter += 1;
00149     }
00150 
00151     MSG_DEBUG("Running FastJet ClusterSequence construction");
00152     // Choose cseq as basic or area-calculating
00153     if (_adef == NULL) {
00154       _cseq.reset(new fastjet::ClusterSequence(pjs, _jdef));
00155     } else {
00156       _cseq.reset(new fastjet::ClusterSequenceArea(pjs, _jdef, *_adef));
00157     }
00158   }
00159 
00160 
00161   void FastJets::reset() {
00162     _yscales.clear();
00163     _particles.clear();
00164     /// @todo _cseq = fastjet::ClusterSequence();
00165   }
00166 
00167 
00168   size_t FastJets::numJets(double ptmin) const {
00169     if (_cseq.get() == NULL) return 0;
00170     return _cseq->inclusive_jets(ptmin).size();
00171   }
00172 
00173 
00174   Jets FastJets::_jets(double ptmin) const {
00175     Jets rtn;
00176     foreach (const fastjet::PseudoJet& pj, pseudojets()) {
00177       assert(clusterSeq() != NULL);
00178       const PseudoJets parts = clusterSeq()->constituents(pj);
00179       vector<Particle> constituents, tags;
00180       constituents.reserve(parts.size());
00181       foreach (const fastjet::PseudoJet& p, parts) {
00182         map<int, Particle>::const_iterator found = _particles.find(p.user_index());
00183         assert(found != _particles.end());
00184         assert(found->first != 0);
00185         if (found->first > 0) constituents.push_back(found->second);
00186         else if (found->first < 0) tags.push_back(found->second);
00187       }
00188       Jet j(pj, constituents, tags);
00189       rtn.push_back(j);
00190     }
00191     /// @todo Cache?
00192     return rtn;
00193   }
00194 
00195 
00196   PseudoJets FastJets::pseudoJets(double ptmin) const {
00197     return (clusterSeq() != NULL) ? clusterSeq()->inclusive_jets(ptmin) : PseudoJets();
00198   }
00199 
00200 
00201 
00202   // DISABLED FROM 2.3.0, USE FASTJET OBJECTS DIRECTLY INSTEAD
00203 
00204   // vector<double> FastJets::ySubJet(const fastjet::PseudoJet& jet) const {
00205   //   assert(clusterSeq());
00206   //   fastjet::ClusterSequence subjet_cseq(clusterSeq()->constituents(jet), _jdef);
00207   //   vector<double> yMergeVals;
00208   //   for (int i = 1; i < 4; ++i) {
00209   //     // Multiply the dmerge value by R^2 so that it corresponds to a
00210   //     // relative k_T (fastjet has 1/R^2 in the d_ij distance by default)
00211   //     const double ktmerge = subjet_cseq.exclusive_dmerge(i) * _jdef.R()*_jdef.R();
00212   //     yMergeVals.push_back(ktmerge/jet.perp2());
00213   //   }
00214   //   _yscales.insert(make_pair( jet.cluster_hist_index(), yMergeVals ));
00215   //   return yMergeVals;
00216   // }
00217 
00218 
00219 
00220   // fastjet::PseudoJet FastJets::splitJet(fastjet::PseudoJet jet, double& last_R) const {
00221   //   // Sanity cuts
00222   //   if (jet.E() <= 0 || _cseq->constituents(jet).size() <= 1) {
00223   //     return jet;
00224   //   }
00225 
00226   //   // Build a new cluster sequence just using the consituents of this jet.
00227   //   assert(clusterSeq());
00228   //   fastjet::ClusterSequence cs(clusterSeq()->constituents(jet), _jdef);
00229 
00230   //   // Get the jet back again
00231   //   fastjet::PseudoJet remadeJet = cs.inclusive_jets()[0];
00232   //   MSG_DEBUG("Jet2:" << remadeJet.m() << "," << remadeJet.e());
00233 
00234   //   fastjet::PseudoJet parent1, parent2;
00235   //   fastjet::PseudoJet split(0.0, 0.0, 0.0, 0.0);
00236   //   while (cs.has_parents(remadeJet, parent1, parent2)) {
00237   //     MSG_DEBUG("Parents:" << parent1.m() << "," << parent2.m());
00238   //     if (parent1.m2() < parent2.m2()) {
00239   //       fastjet::PseudoJet tmp;
00240   //       tmp = parent1; parent1 = parent2; parent2 = tmp;
00241   //     }
00242 
00243   //     double ktdist = parent1.kt_distance(parent2);
00244   //     double rtycut2 = 0.3*0.3;
00245   //     if (parent1.m() < ((2.0*remadeJet.m())/3.0) && ktdist > rtycut2*remadeJet.m2()) {
00246   //       break;
00247   //     } else {
00248   //       remadeJet = parent1;
00249   //     }
00250   //   }
00251 
00252   //   last_R = 0.5 * sqrt(parent1.squared_distance(parent2));
00253   //   split.reset(remadeJet.px(), remadeJet.py(), remadeJet.pz(), remadeJet.E());
00254   //   return split;
00255   // }
00256 
00257 
00258 
00259   // fastjet::PseudoJet FastJets::filterJet(fastjet::PseudoJet jet,
00260   //                                        double& stingy_R, const double def_R) const {
00261   //   assert(clusterSeq());
00262 
00263   //   if (jet.E() <= 0.0 || clusterSeq()->constituents(jet).size() == 0) {
00264   //     return jet;
00265   //   }
00266   //   if (stingy_R == 0.0) {
00267   //     stingy_R = def_R;
00268   //   }
00269 
00270   //   stingy_R = def_R < stingy_R ? def_R : stingy_R;
00271   //   fastjet::JetDefinition stingy_jet_def(fastjet::cambridge_algorithm, stingy_R);
00272 
00273   //   //FlavourRecombiner recom;
00274   //   //stingy_jet_def.set_recombiner(&recom);
00275   //   fastjet::ClusterSequence scs(clusterSeq()->constituents(jet), stingy_jet_def);
00276   //   std::vector<fastjet::PseudoJet> stingy_jets = sorted_by_pt(scs.inclusive_jets());
00277 
00278   //   fastjet::PseudoJet reconst_jet(0.0, 0.0, 0.0, 0.0);
00279 
00280   //   for (unsigned isj = 0; isj < std::min(3U, (unsigned int) stingy_jets.size()); ++isj) {
00281   //     reconst_jet += stingy_jets[isj];
00282   //   }
00283   //   return reconst_jet;
00284   // }
00285 
00286 
00287 }