FastJet 3.0beta1
|
00001 //---------------------------------------------------------------------- 00002 /// \file 00003 /// \page Example12 12 - boosted Higgs tagging 00004 /// 00005 /// fastjet example program, illustration of carrying out boosted 00006 /// Higgs subjet ID analysis 00007 /// 00008 /// It illustrates two kinds of functionality: 00009 /// 00010 /// - using a boosted higgs tagger 00011 /// - following information on a b-tag through the jet 00012 /// 00013 /// This kind of functionality was used in arXiv:0802.2470 00014 /// (Butterworth, Davison, Rubin & Salam) for boosted Higgs searches, 00015 /// and related functionality was used in arXiv:0806.0848 (Kaplan, 00016 /// Rehermann, Schwartz & Tweedie) in searching for boosted tops 00017 /// (without b-tag assumptions). 00018 /// 00019 /// run it with : ./12-boosted_higgs < data/HZ-event-Hmass115.dat 00020 /// 00021 /// Source code: 12-boosted_higgs.cc 00022 //---------------------------------------------------------------------- 00023 00024 00025 //STARTHEADER 00026 // $Id: 12-boosted_higgs.cc 2470 2011-07-26 09:40:41Z cacciari $ 00027 // 00028 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin Salam and Gregory Soyez 00029 // 00030 //---------------------------------------------------------------------- 00031 // This file is part of FastJet. 00032 // 00033 // FastJet is free software; you can redistribute it and/or modify 00034 // it under the terms of the GNU General Public License as published by 00035 // the Free Software Foundation; either version 2 of the License, or 00036 // (at your option) any later version. 00037 // 00038 // The algorithms that underlie FastJet have required considerable 00039 // development and are described in hep-ph/0512210. If you use 00040 // FastJet as part of work towards a scientific publication, please 00041 // include a citation to the FastJet paper. 00042 // 00043 // FastJet is distributed in the hope that it will be useful, 00044 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00045 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00046 // GNU General Public License for more details. 00047 // 00048 // You should have received a copy of the GNU General Public License 00049 // along with FastJet; if not, write to the Free Software 00050 // Foundation, Inc.: 00051 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00052 //---------------------------------------------------------------------- 00053 //ENDHEADER 00054 00055 #include <iostream> // needed for io 00056 #include <sstream> // needed for internal io 00057 #include <iomanip> 00058 #include <cmath> 00059 00060 #include <fastjet/ClusterSequence.hh> 00061 #include <fastjet/tools/MassDropTagger.hh> 00062 #include <fastjet/tools/Filter.hh> 00063 00064 using namespace std; 00065 using namespace fastjet; 00066 00067 00068 //---------------------------------------------------------------------- 00069 // set up a class to give standard (by default E-scheme) 00070 // recombination, with additional tracking of flavour information in 00071 // the user_index. 00072 // 00073 // b-tagged particles are assumed to have their user_index set to 1, 00074 // and other particles should have user_index to 0. 00075 // 00076 // Watch out however that, by default, the user_index of a particle is 00077 // set to -1 and you may not have control over that (e.g. if you 00078 // compute the jet area using explicit ghosts, the ghosts will have a 00079 // default user_index of -1). For that reason, if one of the particle 00080 // being combined has a user index of -1, we assume it is not b-tagged 00081 // (i.e. we count it as 0 in the recombination) 00082 // 00083 // This will work for native algorithms, but not for all plugins 00084 //---------------------------------------------------------------------- 00085 typedef JetDefinition::DefaultRecombiner DefRecomb; 00086 00087 class FlavourRecombiner : public DefRecomb { 00088 public: 00089 FlavourRecombiner(RecombinationScheme recomb_scheme = E_scheme) : 00090 DefRecomb(recomb_scheme) {}; 00091 00092 virtual std::string description() const { 00093 return DefRecomb::description()+" (with user index addition)";} 00094 00095 /// recombine pa and pb and put result into pab 00096 virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 00097 PseudoJet & pab) const { 00098 DefRecomb::recombine(pa,pb,pab); 00099 // Note: see the above discussion for the fact that we consider 00100 // negative user indices as "0" 00101 pab.set_user_index(max(pa.user_index(),0) + max(pb.user_index(),0)); 00102 } 00103 }; 00104 00105 00106 //---------------------------------------------------------------------- 00107 // forward declaration for printing out info about a jet 00108 //---------------------------------------------------------------------- 00109 ostream & operator<<(ostream &, const PseudoJet &); 00110 00111 00112 //---------------------------------------------------------------------- 00113 // core of the program 00114 //---------------------------------------------------------------------- 00115 int main (int argc, char ** argv) { 00116 00117 vector<PseudoJet> particles; 00118 00119 // read in data in format px py pz E b-tag [last of these is optional] 00120 // lines starting with "#" are considered as comments and discarded 00121 //---------------------------------------------------------- 00122 00123 string line; 00124 while (getline(cin,line)) { 00125 if (line.substr(0,1) == "#") {continue;} 00126 istringstream linestream(line); 00127 double px,py,pz,E; 00128 linestream >> px >> py >> pz >> E; 00129 00130 // optionally read in btag information 00131 int btag; 00132 if (! (linestream >> btag)) btag = 0; 00133 00134 // construct the particle 00135 PseudoJet particle(px,py,pz,E); 00136 particle.set_user_index(btag); // btag info goes in user index, for flavour tracking 00137 particles.push_back(particle); 00138 } 00139 00140 00141 // set up the jet finding 00142 // 00143 // This also shows how to use the "FlavourRecombiner" user-defined 00144 // recombiner 00145 // ---------------------------------------------------------- 00146 double R = 1.2; 00147 FlavourRecombiner flav_recombiner; // for tracking flavour 00148 JetDefinition jet_def(cambridge_algorithm, R, &flav_recombiner); 00149 00150 00151 // run the jet finding; find the hardest jet 00152 ClusterSequence cs(particles, jet_def); 00153 vector<PseudoJet> jets = sorted_by_pt(cs.inclusive_jets()); 00154 00155 cout << "Ran: " << jet_def.description() << endl << endl; 00156 cout << "Hardest jet: " << jets[0] << endl << endl; 00157 00158 // now do jet tagging using a mass drop tagger 00159 // 00160 // Note: if you prefer, you may as well use a CASubJetTagger 00161 // CASubJetTagger ca_tagger; 00162 // PseudoJet tagged = ca_tagger(jets[0]); 00163 // This requires including fastjet/tools/CASubJetTagger.hh 00164 // You also need to adapt the 2 lines below accessing 00165 // the extra structural information provided by the tagger 00166 //---------------------------------------------------------- 00167 MassDropTagger md_tagger(0.667, 0.09); 00168 PseudoJet tagged = md_tagger(jets[0]); 00169 00170 if (tagged == 0){ 00171 cout << "No substructure found" << endl; 00172 return 0; 00173 } 00174 00175 PseudoJet parent1 = tagged.pieces()[0]; 00176 PseudoJet parent2 = tagged.pieces()[1]; 00177 cout << "Found suitable pair of subjets: " << endl; 00178 cout << " " << parent1 << endl; 00179 cout << " " << parent2 << endl; 00180 cout << "Total = " << endl; 00181 cout << " " << tagged << endl; 00182 cout << "(mass drop = " << tagged.structure_of<MassDropTagger>().mu() 00183 << ", y = " << tagged.structure_of<MassDropTagger>().y() << ")" 00184 << endl << endl; 00185 00186 // next we "filter" it, to remove UE & pileup contamination 00187 //---------------------------------------------------------- 00188 // 00189 // [there are two ways of doing this; here we directly use the 00190 // existing cluster sequence and find the exclusive subjets of 00191 // this_jet (i.e. work backwards within the cs starting from 00192 // this_jet); alternatively one can recluster just the 00193 // constituents of the jet] 00194 // 00195 // first get separation between the subjets (called Rbb -- assuming 00196 // it's a Higgs!) 00197 // 00198 // See example 11-filter.cc for another way of implementing the dynamic 00199 // Rfilt used below 00200 double Rbb = parent1.delta_R(parent2); 00201 double Rfilt = min(Rbb/2, 0.3); // somewhat arbitrary choice 00202 unsigned nfilt = 3; // number of pieces we'll take 00203 cout << "Subjet separation (Rbb) = " << Rbb << ", Rfilt = " << Rfilt << endl; 00204 00205 Filter filter(JetDefinition(cambridge_algorithm, Rfilt, &flav_recombiner), 00206 SelectorNHardest(nfilt)); 00207 PseudoJet filtered = filter(tagged); 00208 00209 // now print out the filtered jets and reconstruct total 00210 // at the same time 00211 const vector<PseudoJet> & filtered_pieces = filtered.pieces(); 00212 cout << "Filtered pieces are " << endl; 00213 for (unsigned i = 0; i < nfilt && i < filtered_pieces.size(); i++) { 00214 cout << " " << filtered_pieces[i] << endl; 00215 } 00216 cout << "Filtered total is " << endl; 00217 cout << " " << filtered << endl; 00218 00219 } 00220 00221 00222 //---------------------------------------------------------------------- 00223 // does the actual work for printing out a jet 00224 //---------------------------------------------------------------------- 00225 ostream & operator<<(ostream & ostr, const PseudoJet & jet) { 00226 ostr << "pt, y, phi =" 00227 << " " << setw(10) << jet.perp() 00228 << " " << setw(6) << jet.rap() 00229 << " " << setw(6) << jet.phi() 00230 << ", mass = " << setw(10) << jet.m() 00231 << ", btag = " << jet.user_index(); 00232 return ostr; 00233 }