00001 // -*- C++ -*- 00003 // File: area.h // 00004 // Description: header file for the computation of jet area // 00005 // This file is part of the SISCone project. // 00006 // For more details, see http://projects.hepforge.org/siscone // 00007 // // 00008 // Copyright (c) 2006 Gavin Salam and Gregory Soyez // 00009 // // 00010 // This program is free software; you can redistribute it and/or modify // 00011 // it under the terms of the GNU General Public License as published by // 00012 // the Free Software Foundation; either version 2 of the License, or // 00013 // (at your option) any later version. // 00014 // // 00015 // This program is distributed in the hope that it will be useful, // 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00018 // GNU General Public License for more details. // 00019 // // 00020 // You should have received a copy of the GNU General Public License // 00021 // along with this program; if not, write to the Free Software // 00022 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // 00023 // // 00024 // $Revision:: 149 $// 00025 // $Date:: 2007-03-15 00:13:58 +0100 (Thu, 15 Mar 2007) $// 00027 00028 #include "area.h" 00029 #include "momentum.h" 00030 #include <stdlib.h> 00031 #include <iostream> 00032 00033 namespace siscone{ 00034 using namespace std; 00035 00036 /******************************************************* 00037 * Cjet_area implementation * 00038 * real Jet information, including its area(s) * 00039 * * 00040 * This class contains information for one single jet. * 00041 * That is, first, its momentum carrying information * 00042 * about its centre and pT, and second, its particle * 00043 * contents (from CJeT). * 00044 * Compared to the Cjet class, it also includes the * 00045 * passive and active areas of the jet computed using * 00046 * the Carea class. * 00047 *******************************************************/ 00048 00049 // default ctor 00050 //-------------- 00051 Cjet_area::Cjet_area(){ 00052 active_area = passive_area = 0.0; 00053 } 00054 00055 // jet-initiated ctor 00056 //------------------- 00057 Cjet_area::Cjet_area(Cjet &j){ 00058 v = j.v; 00059 n = j.n; 00060 contents = j.contents; 00061 00062 pass = j.pass; 00063 00064 pt_tilde = j.pt_tilde; 00065 sm_var2 = j.sm_var2; 00066 00067 active_area = passive_area = 0.0; 00068 } 00069 00070 // default dtor 00071 //-------------- 00072 Cjet_area::~Cjet_area(){ 00073 00074 } 00075 00076 00077 /****************************************************************** 00078 * Csiscone_area implementation * 00079 * class for the computation of jet areas. * 00080 * * 00081 * This is the class user should use whenever you want to compute * 00082 * the jet area (passive and active). * 00083 * It uses the SISCone algorithm to perform the jet analysis. * 00084 ******************************************************************/ 00085 00086 // default ctor 00087 //------------- 00088 Carea::Carea(){ 00089 grid_size = 60; // 3600 particles added 00090 grid_eta_max = 6.0; // maybe having twice more points in eta than in phi should be nice 00091 grid_shift = 0.5; // 50% "shacking" 00092 00093 pt_soft = 1e-100; 00094 pt_shift = 0.05; 00095 pt_soft_min = 1e-90; 00096 } 00097 00098 // default dtor 00099 //------------- 00100 Carea::~Carea(){ 00101 00102 } 00103 00104 /* 00105 * compute the jet areas from a given particle set. 00106 * The parameters of this method are the ones which control the jet clustering alghorithm. 00107 * Note that the pt_min is not allowed here soince the jet-area determination involves soft 00108 * particles/jets and thus is used internally. 00109 * - _particles list of particles 00110 * - _radius cone radius 00111 * - _f shared energy threshold for splitting&merging 00112 * - _n_pass_max maximum number of passes (0=full search, the default) 00113 * - _split_merge_scale the scale choice for the split-merge procedure 00114 * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 00115 * SM_Et is IR safe but not boost invariant and not implemented(!) 00116 * SM_mt is IR safe for hadronic events, but not for decays of two 00117 * back-to-back particles of identical mass 00118 * SM_pttilde 00119 * is always IR safe, and also boost invariant (default) 00120 * - _hard_only when this is set on, only hard jets are computed 00121 * and not the purely ghosted jets (default: false) 00122 * return the jets together with their areas 00123 ********************************************************************************************/ 00124 int Carea::compute_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 00125 int _n_pass_max, Esplit_merge_scale _split_merge_scale, 00126 bool _hard_only){ 00127 00128 vector<Cmomentum> all_particles; 00129 00130 // put "hardest cut-off" if needed 00131 // this avoids computation of ghosted jets when not required and 00132 // significantly shortens the SM. 00133 if (_hard_only){ 00134 SM_var2_hardest_cut_off = pt_soft_min*pt_soft_min; 00135 } 00136 00137 // clear potential previous runs 00138 jet_areas.clear(); 00139 00140 // put initial set of particles in the list 00141 int n_hard = _particles.size(); 00142 all_particles = _particles; 00143 00144 // build the set of ghost particles and add them to the particle list 00145 int i,j; 00146 double eta,phi,pt; 00147 00148 for (i=0;i<grid_size;i++){ 00149 for (j=0;j<grid_size;j++){ 00150 eta = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00151 phi = M_PI *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00152 pt = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0)))); 00153 all_particles.push_back(Cmomentum(pt*cos(phi),pt*sin(phi),pt*sinh(eta),pt*cosh(eta))); 00154 } 00155 } 00156 00157 // run clustering with all particles. 00158 // the split-merge here dynamically accounts for the purely soft jets. 00159 // we therefore end up with the active area for the jets 00160 compute_jets(all_particles, _radius, _f, _n_pass_max, 0.0, _split_merge_scale); 00161 00162 // save jets in the Cjet_area structure 00163 // and determine their size 00164 // jet contents is ordered by increasing index of the initial 00165 // particles. Hence, we look for the first particle with index >= n_hard 00166 // and deduce the number of ghosts in the jet, hence the area. 00167 double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size); 00168 00169 for (i=0;i<(int) jets.size();i++){ 00170 jet_areas.push_back(jets[i]); 00171 j=0; 00172 while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++; 00173 jet_areas[i].active_area = (jets[i].n-j)*area_factor; 00174 } 00175 00176 // determine passive jet area 00177 // for that onem we use the pt_min cut in order to remove purely 00178 // soft jets from the SM procedure 00179 recompute_jets(_f, pt_soft_min); 00180 00181 // for the area computation, we assume the jete order is the same! 00182 for (i=0;i<(int) jets.size();i++){ 00183 j=0; 00184 while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++; 00185 jet_areas[i].passive_area = (jets[i].n-j)*area_factor; 00186 } 00187 00188 // Note: 00189 // there surely remain purely soft je at the end 00190 // their active area is 0 by default (see ctor) 00191 00192 jets.clear(); 00193 00194 return 0; 00195 } 00196 00197 /* 00198 * compute the passive jet areas from a given particle set. 00199 * The parameters of this method are the ones which control the jet clustering alghorithm. 00200 * Note that the pt_min is not allowed here soince the jet-area determination involves soft 00201 * particles/jets and thus is used internally. 00202 * - _particles list of particles 00203 * - _radius cone radius 00204 * - _f shared energy threshold for splitting&merging 00205 * - _n_pass_max maximum number of passes (0=full search, the default) 00206 * - _split_merge_scale the scale choice for the split-merge procedure 00207 * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 00208 * SM_Et is IR safe but not boost invariant and not implemented(!) 00209 * SM_mt is IR safe for hadronic events, but not for decays of two 00210 * back-to-back particles of identical mass 00211 * SM_pttilde 00212 * is always IR safe, and also boost invariant (default) 00213 * return the jets together with their passive areas 00214 ********************************************************************************************/ 00215 int Carea::compute_passive_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 00216 int _n_pass_max, Esplit_merge_scale _split_merge_scale){ 00217 00218 vector<Cmomentum> all_particles; 00219 00220 // clear potential previous runs 00221 jet_areas.clear(); 00222 00223 // put initial set of particles in the list 00224 int n_hard = _particles.size(); 00225 all_particles = _particles; 00226 00227 // build the set of ghost particles and add them to the particle list 00228 int i,j; 00229 double eta,phi,pt; 00230 00231 for (i=0;i<grid_size;i++){ 00232 for (j=0;j<grid_size;j++){ 00233 eta = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00234 phi = M_PI *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00235 pt = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0)))); 00236 all_particles.push_back(Cmomentum(pt*cos(phi),pt*sin(phi),pt*sinh(eta),pt*cosh(eta))); 00237 } 00238 } 00239 00240 // determine passive jet area 00241 // for that onem we use the pt_min cut in order to remove purely 00242 // soft jets from the SM procedure 00243 compute_jets(all_particles, _radius, _f, _n_pass_max, pt_soft_min, _split_merge_scale); 00244 00245 // save jets in the Cjet_area structure 00246 // and determine their size 00247 // jet contents is ordered by increasing index of the initial 00248 // particles. Hence, we look for the first particle with index >= n_hard 00249 // and deduce the number of ghosts in the jet, hence the area. 00250 double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size); 00251 for (i=0;i<(int) jets.size();i++){ 00252 j=0; 00253 while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++; 00254 jet_areas[i].passive_area = (jets[i].n-j)*area_factor; 00255 } 00256 00257 jets.clear(); 00258 00259 return 0; 00260 } 00261 00262 /* 00263 * compute the active jet areas from a given particle set. 00264 * The parameters of this method are the ones which control the jet clustering alghorithm. 00265 * Note that the pt_min is not allowed here soince the jet-area determination involves soft 00266 * particles/jets and thus is used internally. 00267 * - _particles list of particles 00268 * - _radius cone radius 00269 * - _f shared energy threshold for splitting&merging 00270 * - _n_pass_max maximum number of passes (0=full search, the default) 00271 * - _split_merge_scale the scale choice for the split-merge procedure 00272 * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation. 00273 * SM_Et is IR safe but not boost invariant and not implemented(!) 00274 * SM_mt is IR safe for hadronic events, but not for decays of two 00275 * back-to-back particles of identical mass 00276 * SM_pttilde 00277 * is always IR safe, and also boost invariant (default) 00278 * - _hard_only when this is set on, only hard jets are computed 00279 * and not the purely ghosted jets (default: false) 00280 * return the jets together with their active areas 00281 ********************************************************************************************/ 00282 int Carea::compute_active_areas(std::vector<Cmomentum> &_particles, double _radius, double _f, 00283 int _n_pass_max, Esplit_merge_scale _split_merge_scale, 00284 bool _hard_only){ 00285 00286 vector<Cmomentum> all_particles; 00287 00288 // put "hardest cut-off" if needed 00289 // this avoids computation of ghosted jets when not required and 00290 // significantly shortens the SM. 00291 if (_hard_only){ 00292 SM_var2_hardest_cut_off = pt_soft_min*pt_soft_min; 00293 } 00294 00295 // clear potential previous runs 00296 jet_areas.clear(); 00297 00298 // put initial set of particles in the list 00299 int n_hard = _particles.size(); 00300 all_particles = _particles; 00301 00302 // build the set of ghost particles and add them to the particle list 00303 int i,j; 00304 double eta,phi,pt; 00305 00306 for (i=0;i<grid_size;i++){ 00307 for (j=0;j<grid_size;j++){ 00308 eta = grid_eta_max*(-1.0+2.0*(i+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00309 phi = M_PI *(-1.0+2.0*(j+0.5+grid_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0))))/grid_size); 00310 pt = pt_soft*(1.0+pt_shift*(-1.0+2.0*(rand()/(RAND_MAX+1.0)))); 00311 all_particles.push_back(Cmomentum(pt*cos(phi),pt*sin(phi),pt*sinh(eta),pt*cosh(eta))); 00312 } 00313 } 00314 00315 // run clustering with all particles. 00316 // the split-merge here dynamically accounts for the purely soft jets. 00317 // we therefore end up with the active area for the jets 00318 compute_jets(all_particles, _radius, _f, _n_pass_max, 0.0, _split_merge_scale); 00319 00320 // save jets in the Cjet_area structure 00321 // and determine their size 00322 // jet contents is ordered by increasing index of the initial 00323 // particles. Hence, we look for the first particle with index >= n_hard 00324 // and deduce the number of ghosts in the jet, hence the area. 00325 double area_factor = (2.0*grid_eta_max/grid_size)*(twopi/grid_size); 00326 00327 for (i=0;i<(int) jets.size();i++){ 00328 jet_areas.push_back(jets[i]); 00329 j=0; 00330 while ((j<jets[i].n) && (jets[i].contents[j]<n_hard)) j++; 00331 jet_areas[i].active_area = (jets[i].n-j)*area_factor; 00332 } 00333 00334 jets.clear(); 00335 00336 return 0; 00337 } 00338 00339 }