FastJet 3.0beta1
09-user_info.cc
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends