|
FastJet 3.0alpha3
|
00001 //---------------------------------------------------------------------- 00002 /// \file 00003 /// \page Example11 11 - 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 /// - following the decomposition of a jet into pieces 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 : ./11-boosted_higgs < data/HZ-event-Hmass115.dat 00020 /// 00021 /// Source code: 11-boosted_higgs.cc 00022 //---------------------------------------------------------------------- 00023 00024 00025 //STARTHEADER 00026 // $Id: 11-boosted_higgs.cc 2173 2011-05-20 15:05:31Z soyez $ 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 "fastjet/ClusterSequence.hh" 00056 #include <iostream> // needed for io 00057 #include <sstream> // needed for internal io 00058 #include <iomanip> 00059 #include <cmath> 00060 00061 using namespace std; 00062 using namespace fastjet; 00063 00064 00065 //---------------------------------------------------------------------- 00066 // set up a class to give standard (by default E-scheme) 00067 // recombination, with additional tracking of flavour information in 00068 // the user_index. 00069 // 00070 // b-tagged particles are assumed to have their user_index set to 1, 00071 // and other particles should have user_index to 0. 00072 // 00073 // Watch out however that, by default, the user_index of a particle is 00074 // set to -1 and you may not have control over that (e.g. if you 00075 // compute the jet area using explicit ghosts, the ghosts will have a 00076 // default user_index of -1). For that reason, if one of the particle 00077 // being combined has a user index of -1, we assume it is not b-tagged 00078 // (i.e. we count it as 0 in the recombination) 00079 // 00080 // This will work for native algorithms, but not for all plugins 00081 //---------------------------------------------------------------------- 00082 typedef JetDefinition::DefaultRecombiner DefRecomb; 00083 00084 class FlavourRecombiner : public DefRecomb { 00085 public: 00086 FlavourRecombiner(RecombinationScheme recomb_scheme = E_scheme) : 00087 DefRecomb(recomb_scheme) {}; 00088 00089 virtual std::string description() const { 00090 return DefRecomb::description()+" (with user index addition)";} 00091 00092 /// recombine pa and pb and put result into pab 00093 virtual void recombine(const PseudoJet & pa, const PseudoJet & pb, 00094 PseudoJet & pab) const { 00095 DefRecomb::recombine(pa,pb,pab); 00096 // Note: see the above discussion for the fact that we consider 00097 // negative user indices as "0" 00098 pab.set_user_index(max(pa.user_index(),0) + max(pb.user_index(),0)); 00099 } 00100 }; 00101 00102 00103 //---------------------------------------------------------------------- 00104 // forward declaration for printing out info about a jet 00105 //---------------------------------------------------------------------- 00106 ostream & operator<<(ostream &, PseudoJet &); 00107 00108 00109 //---------------------------------------------------------------------- 00110 // core of the program 00111 //---------------------------------------------------------------------- 00112 int main (int argc, char ** argv) { 00113 00114 vector<PseudoJet> particles; 00115 00116 // read in data in format px py pz E b-tag [last of these is optional] 00117 // lines starting with "#" are considered as comments and discarded 00118 //---------------------------------------------------------- 00119 00120 string line; 00121 while (getline(cin,line)) { 00122 if (line.substr(0,1) == "#") {continue;} 00123 istringstream linestream(line); 00124 double px,py,pz,E; 00125 linestream >> px >> py >> pz >> E; 00126 00127 // optionally read in btag information 00128 int btag; 00129 if (! (linestream >> btag)) btag = 0; 00130 00131 // construct the particle 00132 PseudoJet particle(px,py,pz,E); 00133 particle.set_user_index(btag); // btag info goes in user index, for flavour tracking 00134 particles.push_back(particle); 00135 } 00136 00137 00138 // set up the jet finding 00139 // 00140 // This also shows how to use the "FlavourRecombiner" user-defined 00141 // recombiner 00142 // ---------------------------------------------------------- 00143 double R = 1.2; 00144 FlavourRecombiner flav_recombiner; // for tracking flavour 00145 JetDefinition jet_def(cambridge_algorithm, R, &flav_recombiner); 00146 00147 00148 // run the jet finding; find the hardest jet 00149 ClusterSequence cs(particles, jet_def); 00150 vector<PseudoJet> jets = sorted_by_pt(cs.inclusive_jets()); 00151 00152 cout << "Ran: " << jet_def.description() << endl << endl; 00153 cout << "Hardest jet: " << jets[0] << endl << endl; 00154 00155 // now do the subjet decomposition 00156 //---------------------------------------------------------- 00157 // 00158 // when unpeeling a C/A jet, often only a very soft piece may break off; 00159 // the mass_drop_threshold indicates how much "lighter" the heavier of the two 00160 // resulting pieces must be in order for us to consider that we've really 00161 // seen some form of substructure 00162 double mass_drop_threshold = 0.667; 00163 // QCD backgrounds that give larger jet masses have a component 00164 // where a quite soft gluon is emitted; to eliminate part of this 00165 // one can place a cut on the asymmetry of the branching; 00166 // 00167 // Here the cut is expressed in terms of y, the kt-distance scaled 00168 // to the squared jet mass; an easier way to see it is in terms of 00169 // a requirement on the momentum fraction in the splitting: z/(1-z) 00170 // and (1-z)/z > rtycut^2 [the correspondence holds only at LO] 00171 double rtycut = 0.3; 00172 00173 PseudoJet this_jet = jets[0]; 00174 PseudoJet parent1, parent2; 00175 bool had_parents; 00176 00177 while ((had_parents = this_jet.has_parents(parent1,parent2))) { 00178 // make parent1 the more massive jet 00179 if (parent1.m() < parent2.m()) swap(parent1,parent2); 00180 00181 // if we pass the conditions on the mass drop and its degree of 00182 // asymmetry (z/(1-z) \sim kt_dist/m^2 > rtycut), then we've found 00183 // something interesting, so exit the loop 00184 if (parent1.m() < mass_drop_threshold * this_jet.m() && 00185 parent1.kt_distance(parent2) > pow(rtycut,2) * this_jet.m2()) { 00186 break; 00187 } else { 00188 // otherwise try a futher decomposition on the more massive jet 00189 this_jet = parent1; 00190 } 00191 } 00192 00193 // look to see what we found 00194 if (!had_parents) { 00195 cout << "Did not find suitable hard substructure in this event." << endl; 00196 return 0; 00197 } 00198 00199 cout << "Found suitable pair of subjets: " << endl; 00200 cout << " " << parent1 << endl; 00201 cout << " " << parent2 << endl; 00202 cout << "Total = " << endl; 00203 cout << " " << this_jet << endl << endl; 00204 00205 // next we "filter" it, to remove UE & pileup contamination 00206 //---------------------------------------------------------- 00207 // 00208 // [there are two ways of doing this; here we directly use the 00209 // exsiting cluster sequence and find the exclusive subjets of 00210 // this_jet (i.e. work backwards within the cs starting from 00211 // this_jet); alternatively one can recluster just the 00212 // constituents of the jet] 00213 // 00214 // first get separation between the subjets (called Rbb -- assuming it's a Higgs!) 00215 double Rbb = sqrt(parent1.squared_distance(parent2)); 00216 double Rfilt = min(Rbb/2, 0.3); // somewhat arbitrary choice 00217 unsigned nfilt = 3; // number of pieces we'll take 00218 cout << "Subjet separation (Rbb) = " << Rbb << ", Rfilt = " << Rfilt << endl; 00219 00220 double dcut = pow(Rfilt/R,2); // for C/A get a view at Rfilt by 00221 // using a dcut=(Rfilt/R)^2 00222 vector<PseudoJet> filt_subjets = sorted_by_pt(this_jet.exclusive_subjets(dcut)); 00223 00224 // now print out the filtered jets and reconstruct total 00225 // at the same time 00226 cout << "Filtered pieces are " << endl; 00227 cout << " " << filt_subjets[0] << endl; 00228 PseudoJet filtered_total = filt_subjets[0]; 00229 for (unsigned i = 1; i < nfilt && i < filt_subjets.size(); i++) { 00230 cout << " " << filt_subjets[i] << endl; 00231 flav_recombiner.plus_equal(filtered_total, filt_subjets[i]); 00232 } 00233 cout << "Filtered total is " << endl; 00234 cout << " " << filtered_total << endl; 00235 00236 } 00237 00238 00239 //---------------------------------------------------------------------- 00240 // does the actual work for printing out a jet 00241 //---------------------------------------------------------------------- 00242 ostream & operator<<(ostream & ostr, PseudoJet & jet) { 00243 ostr << "pt, y, phi =" 00244 << " " << setw(10) << jet.perp() 00245 << " " << setw(6) << jet.rap() 00246 << " " << setw(6) << jet.phi() 00247 << ", mass = " << setw(10) << jet.m() 00248 << ", btag = " << jet.user_index(); 00249 return ostr; 00250 }
1.7.4