FastJet 3.0beta1
|
00001 //---------------------------------------------------------------------- 00002 /// \file 00003 /// \page Example09 09 - adding user information to a fastjet::PseudoJet 00004 /// 00005 /// This example illustrates how it is possible to associate 00006 /// user-defined information to a fastjet::PseudoJet (beyond the 00007 /// simple user index), using a class derived from 00008 /// fastjet::UserInfoBase. 00009 /// 00010 /// Note that in this example we have chosen to use this 00011 /// user-defined information to obtain properties of the constituents 00012 /// of the reconstructed jet (e.g. if the event is made of a hard 00013 /// interaction and pileup, what part of the reconstructed jet comes 00014 /// from the hard interaction). To do that, we also show how to 00015 /// introduce a user-defined fastjet::Selector. For some applications, 00016 /// it might also be useful to define new recombination schemes using 00017 /// the extra information. 00018 /// 00019 /// run it with : ./09-user_info < data/Pythia-dijet-ptmin100-lhc-pileup-1ev.dat 00020 /// 00021 /// (Note that this event consists of many sub-events, the first one 00022 /// being the "hard" interaction and the following being minbias 00023 /// events composing the pileup. It has the specificity that it also 00024 /// contains the PDG id of the particles) 00025 /// 00026 /// Source code: 09-user_info.cc 00027 //---------------------------------------------------------------------- 00028 00029 //STARTHEADER 00030 // $Id: 09-user_info.cc 2521 2011-08-08 15:25:15Z salam $ 00031 // 00032 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin Salam and Gregory Soyez 00033 // 00034 //---------------------------------------------------------------------- 00035 // This file is part of FastJet. 00036 // 00037 // FastJet is free software; you can redistribute it and/or modify 00038 // it under the terms of the GNU General Public License as published by 00039 // the Free Software Foundation; either version 2 of the License, or 00040 // (at your option) any later version. 00041 // 00042 // The algorithms that underlie FastJet have required considerable 00043 // development and are described in hep-ph/0512210. If you use 00044 // FastJet as part of work towards a scientific publication, please 00045 // include a citation to the FastJet paper. 00046 // 00047 // FastJet is distributed in the hope that it will be useful, 00048 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00049 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00050 // GNU General Public License for more details. 00051 // 00052 // You should have received a copy of the GNU General Public License 00053 // along with FastJet; if not, write to the Free Software 00054 // Foundation, Inc.: 00055 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00056 //---------------------------------------------------------------------- 00057 //ENDHEADER 00058 00059 #include "fastjet/ClusterSequence.hh" 00060 #include "fastjet/Selector.hh" 00061 #include <iostream> // needed for io 00062 #include <sstream> // needed for io 00063 #include <cstdio> // needed for io 00064 00065 using namespace std; 00066 using namespace fastjet; 00067 00068 //------------------------------------------------------------------------ 00069 // the user information 00070 // 00071 // To associate extra information to a PseudoJet, one first has to 00072 // create a class, derived from fastjet::UserInfoBase, that contains 00073 // that information. 00074 // 00075 // In our simple example, we shall use 2 informations 00076 // - the PDG id associated with the particle 00077 // - the "vertex number" associated with the particle 00078 class MyUserInfo : public PseudoJet::UserInfoBase{ 00079 public: 00080 // default ctor 00081 // - pdg_id the PDG id of the particle 00082 // - vertex_number theid of the vertex it originates from 00083 MyUserInfo(const int & pdg_id, const int & vertex_number) : 00084 _pdg_id(pdg_id), _vertex_number(vertex_number){} 00085 00086 /// access to the PDG id 00087 int pdg_id() const { return _pdg_id;} 00088 00089 /// access to the vertex number 00090 int vertex_number() const { return _vertex_number;} 00091 00092 protected: 00093 int _pdg_id; // the associated pdg id 00094 int _vertex_number; // the associated vertex number 00095 }; 00096 00097 00098 //------------------------------------------------------------------------ 00099 // Select pi0 and photons 00100 // 00101 // This shows how we can build a Selector that uses the user-defined 00102 // information to select particles that are either pi0's or photons 00103 // (we choose this purely for simplicity). 00104 // 00105 // To create a user-defined fastjet::Selector, the first step is to 00106 // create its associated "worker" class, i.e. to derive a class from 00107 // fastjet::SelectorWorker. Then (see below), we just write a function 00108 // (SelectorIsPi0Gamma()) that creates a fastjet::Selector with the 00109 // appropriate worker class. 00110 class SW_IsPi0Gamma : public SelectorWorker{ 00111 public: 00112 // default ctor 00113 SW_IsPi0Gamma(){} 00114 00115 // the selector's description 00116 string description() const{ 00117 return "neutral pions or photons"; 00118 } 00119 00120 // keeps the ones that have the pdg id of the pi0 00121 bool pass(const PseudoJet &p) const{ 00122 // This is how we access the extra information associated with the 00123 // particles we test. 00124 // p.user_info<MyUserInfo>() 00125 // returns a reference to the user-defined information (of type 00126 // MyUserInfo, as mentioned explicitly). It ensures automatically 00127 // that there is an associated user info compatible with the 00128 // requested type (and throws an error if it is not the case) 00129 // 00130 // We can then access the "pdg_id" member of MyUserInfo to 00131 // extract the targeted information. 00132 const int & pdgid = p.user_info<MyUserInfo>().pdg_id(); 00133 return (pdgid == 111) || (pdgid == 22); 00134 } 00135 }; 00136 00137 // the function that allows to write simply 00138 // Selector sel = SelectorIsPi0Gamma(); 00139 Selector SelectorIsPi0Gamma(){ 00140 return Selector(new SW_IsPi0Gamma()); 00141 } 00142 00143 //------------------------------------------------------------------------ 00144 // Select particles from a given vertex number 00145 // 00146 // This is the same kind of construct as just above except that we 00147 // select on particles that are originated from a given vertex. The 00148 // test event has been structured as a superposition of sub-events 00149 // (the 0th being the hard interaction) and each particle will be 00150 // associated a vertex number. This Selector allows to select 00151 // particles corresponding to a given vertex number. 00152 // 00153 // As in the previous case, we start with the worker class and then 00154 // write a function for the Selector itself. 00155 class SW_VertexNumber : public SelectorWorker{ 00156 public: 00157 // ctor from the vertex we want to keep 00158 SW_VertexNumber(const int & vertex_number) : _vertex_number(vertex_number){} 00159 00160 // the selector's description 00161 string description() const{ 00162 ostringstream oss; 00163 oss << "vertex number " << _vertex_number; 00164 return oss.str(); 00165 } 00166 00167 // keeps the ones that have the correct vertex number 00168 bool pass(const PseudoJet &p) const{ 00169 // This is how we access the extra information associated with the 00170 // particles we test. 00171 // p.user_info<MyUserInfo>() 00172 // returns a reference to the user-defined information (of type 00173 // MyUserInfo, as mentioned explicitly). It ensures automatically 00174 // that there is an associated user info compatible with the 00175 // requested type (and throws an error if it is not the case) 00176 // 00177 // We can then access the "vertex_number" member of MyUserInfo to 00178 // extract the targeted information. 00179 return p.user_info<MyUserInfo>().vertex_number()==_vertex_number; 00180 } 00181 00182 private: 00183 int _vertex_number; // the vertex number we're selecting 00184 }; 00185 00186 // The function that allows to write e.g. 00187 // Selector sel = !SelectorVertexNumber(0); 00188 // to select particles from all vertices except the 0th. 00189 Selector SelectorVertexNumber(const int & vertex_number){ 00190 return Selector(new SW_VertexNumber(vertex_number)); 00191 } 00192 00193 00194 //------------------------------------------------------------------------ 00195 // The example code associating user-info to the particles in the event 00196 int main (int argc, char ** argv) { 00197 // read in input particles 00198 //---------------------------------------------------------- 00199 vector<fastjet::PseudoJet> input_particles; 00200 00201 double px, py , pz, E; 00202 string str; 00203 int vertex_number=-1; 00204 int pdg_id = 21; 00205 while (getline(cin, str)){ 00206 // if the line does not start with #, it's a particle 00207 // read its momentum and pdg id 00208 if (str[0] != '#'){ 00209 istringstream iss(str); 00210 if (! (iss >> px >> py >> pz >> E >> pdg_id)){ 00211 cerr << "Wrong file format: particles must be specified with" << endl; 00212 cerr << " px py pz E pdg_id" << endl; 00213 } 00214 00215 // first create a PseudoJet with the correct momentum 00216 PseudoJet p(px,py,pz,E); 00217 00218 // associate to that our user-defined extra information 00219 // which is done using 00220 // PseudoJet::set_user_info() 00221 // 00222 // IMPORTANT NOTE: set_user_info(...) takes a pointer as an 00223 // argument. It will "own" that pointer i.e. will delete it when 00224 // all the PseudoJet's using it will be deleted. 00225 // 00226 // NB: once you've done p.set_user_info(my_user_info_ptr), you must 00227 // not call p2.set_user_info(my_user_info_ptr) with the same pointer 00228 // because p and p2 will both attempt to delete it when they go out 00229 // of scope causing a double-free corruption error. Instead do 00230 // p2.user_info_shared_ptr() = p.user_info_shared_ptr(); 00231 p.set_user_info(new MyUserInfo(pdg_id, vertex_number)); 00232 PseudoJet p2; // defined only to make the above documentation consistent! 00233 00234 input_particles.push_back(p); 00235 continue; 00236 } 00237 00238 // check if we start a new sub-event 00239 if ((str.length()>=9) && (str.compare(0,9,"#SUBSTART")==0)){ 00240 vertex_number++; 00241 } 00242 } 00243 00244 00245 // create a jet definition: 00246 // a jet algorithm with a given radius parameter 00247 //---------------------------------------------------------- 00248 double R = 0.6; 00249 fastjet::JetDefinition jet_def(fastjet::antikt_algorithm, R); 00250 00251 00252 // run the jet clustering with the above jet definition 00253 //---------------------------------------------------------- 00254 fastjet::ClusterSequence clust_seq(input_particles, jet_def); 00255 00256 00257 // get the resulting jets ordered in pt 00258 //---------------------------------------------------------- 00259 double ptmin = 25.0; 00260 vector<fastjet::PseudoJet> inclusive_jets = sorted_by_pt(clust_seq.inclusive_jets(ptmin)); 00261 00262 00263 // tell the user what was done 00264 // - the description of the algorithm used 00265 // - extract the inclusive jets with pt > 5 GeV 00266 // show the output as 00267 // {index, rap, phi, pt} 00268 //---------------------------------------------------------- 00269 cout << "Ran " << jet_def.description() << endl; 00270 00271 // label the columns 00272 printf("%5s %15s %15s %15s %15s %15s\n","jet #", 00273 "rapidity", "phi", "pt", 00274 "pt_hard", "pt_pi0+gamma"); 00275 00276 // a selection on the 1st vertex 00277 Selector sel_vtx0 = SelectorVertexNumber(0); 00278 00279 // a selection on the pi0 00280 Selector sel_pi0gamma = SelectorIsPi0Gamma(); 00281 00282 // print out the details for each jet 00283 for (unsigned int i = 0; i < inclusive_jets.size(); i++) { 00284 const PseudoJet & full = inclusive_jets[i]; 00285 const vector<PseudoJet> constituents = full.constituents(); 00286 00287 // get the contribution from the 1st vertex 00288 PseudoJet hard = join(sel_vtx0(constituents)); 00289 00290 // get the contribution from the pi0's 00291 PseudoJet pi0gamma = join(sel_pi0gamma(constituents)); 00292 00293 // print the result 00294 printf("%5u %15.8f %15.8f %15.8f %15.8f %15.8f\n", i, 00295 full.rap(), full.phi(), full.perp(), 00296 hard.perp(), pi0gamma.perp()); 00297 } 00298 00299 return 0; 00300 }