FastJet 3.0beta1
|
00001 //STARTHEADER 00002 // $Id: JetDefinition.cc 2386 2011-07-07 13:53:47Z soyez $ 00003 // 00004 // Copyright (c) 2005-2007, Matteo Cacciari and Gavin Salam 00005 // 00006 //---------------------------------------------------------------------- 00007 // This file is part of FastJet. 00008 // 00009 // FastJet is free software; you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation; either version 2 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // The algorithms that underlie FastJet have required considerable 00015 // development and are described in hep-ph/0512210. If you use 00016 // FastJet as part of work towards a scientific publication, please 00017 // include a citation to the FastJet paper. 00018 // 00019 // FastJet is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 // GNU General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with FastJet; if not, write to the Free Software 00026 // Foundation, Inc.: 00027 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 //---------------------------------------------------------------------- 00029 //ENDHEADER 00030 00031 #include "fastjet/JetDefinition.hh" 00032 #include "fastjet/Error.hh" 00033 #include "fastjet/CompositeJetStructure.hh" 00034 #include<sstream> 00035 00036 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00037 00038 using namespace std; 00039 00040 //---------------------------------------------------------------------- 00041 // [NB: implementation was getting complex, so in 2.4-devel moved it 00042 // from .hh to .cc] 00043 JetDefinition::JetDefinition(JetAlgorithm jet_algorithm, 00044 double R, 00045 Strategy strategy, 00046 RecombinationScheme recomb_scheme, 00047 int nparameters) : 00048 _jet_algorithm(jet_algorithm), _Rparam(R), _strategy(strategy) { 00049 00050 // set R parameter or ensure its sensibleness, as appropriate 00051 if (jet_algorithm == ee_kt_algorithm) { 00052 _Rparam = 4.0; // introduce a fictional R that ensures that 00053 // our clustering sequence will not produce 00054 // "beam" jets except when only a single particle remains. 00055 // Any value > 2 would have done here 00056 } else { 00057 // We maintain some limit on R because particles with pt=0, m=0 00058 // can have rapidities O(10000) and one doesn't want the 00059 // clustering to start including them as if their rapidities were 00060 // physical. 00061 assert ( R < 1000.0); 00062 } 00063 00064 // cross-check the number of parameters that were declared in setting up the 00065 // algorithm (passed internally from the public constructors) 00066 ostringstream oss; 00067 switch (jet_algorithm) { 00068 case ee_kt_algorithm: 00069 if (nparameters != 0) oss << "ee_kt_algorithm should be constructed with 0 parameters but was called with " 00070 << nparameters << " parameter(s)\n"; 00071 break; 00072 case genkt_algorithm: 00073 case ee_genkt_algorithm: 00074 if (nparameters != 2) oss << "(ee_)genkt_algorithm should be constructed with 2 parameters but was called with " 00075 << nparameters << " parameter(s)\n"; 00076 break; 00077 default: 00078 if (nparameters != 1) 00079 oss << "The jet algorithm you requested (" 00080 << jet_algorithm << ") should be constructed with 1 parameter but was called with " 00081 << nparameters << " parameter(s)\n"; 00082 } 00083 if (oss.str() != "") throw Error(oss.str()); 00084 00085 // make sure the strategy requested is sensible 00086 assert (_strategy != plugin_strategy); 00087 00088 _plugin = NULL; 00089 set_recombination_scheme(recomb_scheme); 00090 set_extra_param(0.0); // make sure it's defined 00091 } 00092 00093 00094 //---------------------------------------------------------------------- 00095 string JetDefinition::description() const { 00096 ostringstream name; 00097 if (jet_algorithm() == plugin_algorithm) { 00098 return plugin()->description(); 00099 } else if (jet_algorithm() == kt_algorithm) { 00100 name << "Longitudinally invariant kt algorithm with R = " << R(); 00101 name << " and " << recombiner()->description(); 00102 } else if (jet_algorithm() == cambridge_algorithm) { 00103 name << "Longitudinally invariant Cambridge/Aachen algorithm with R = " 00104 << R() ; 00105 name << " and " << recombiner()->description(); 00106 } else if (jet_algorithm() == antikt_algorithm) { 00107 name << "Longitudinally invariant anti-kt algorithm with R = " 00108 << R() ; 00109 name << " and " << recombiner()->description(); 00110 } else if (jet_algorithm() == genkt_algorithm) { 00111 name << "Longitudinally invariant generalised kt algorithm with R = " 00112 << R() << ", p = " << extra_param(); 00113 name << " and " << recombiner()->description(); 00114 } else if (jet_algorithm() == cambridge_for_passive_algorithm) { 00115 name << "Longitudinally invariant Cambridge/Aachen algorithm with R = " 00116 << R() << "and a special hack whereby particles with kt < " 00117 << extra_param() << "are treated as passive ghosts"; 00118 } else if (jet_algorithm() == ee_kt_algorithm) { 00119 name << "e+e- kt (Durham) algorithm (NB: no R)"; 00120 name << " with " << recombiner()->description(); 00121 } else if (jet_algorithm() == ee_genkt_algorithm) { 00122 name << "e+e- generalised kt algorithm with R = " 00123 << R() << ", p = " << extra_param(); 00124 name << " and " << recombiner()->description(); 00125 } else if (jet_algorithm() == undefined_jet_algorithm) { 00126 name << "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ; 00127 } else { 00128 throw Error("JetDefinition::description(): unrecognized jet_algorithm"); 00129 } 00130 return name.str(); 00131 } 00132 00133 00134 void JetDefinition::set_recombination_scheme( 00135 RecombinationScheme recomb_scheme) { 00136 _default_recombiner = JetDefinition::DefaultRecombiner(recomb_scheme); 00137 00138 // do not forget to delete the existing recombiner if needed 00139 if (_recombiner_shared()) _recombiner_shared.reset(); 00140 00141 _recombiner = 0; 00142 } 00143 00144 00145 // returns true if the current jet definitions shares the same 00146 // recombiner as teh one passed as an argument 00147 bool JetDefinition::has_same_recombiner(const JetDefinition &other_jd) const{ 00148 // first make sure that they have the same recombination scheme 00149 const RecombinationScheme & scheme = recombination_scheme(); 00150 if (other_jd.recombination_scheme() != scheme) return false; 00151 00152 // if the scheme is "external", also check that they ahve the same 00153 // recombiner 00154 return (scheme != external_scheme) 00155 || (recombiner() == other_jd.recombiner()); 00156 } 00157 00158 /// allows to let the JetDefinition handle the deletion of the 00159 /// recombiner when it is no longer used 00160 void JetDefinition::delete_recombiner_when_unused(){ 00161 if (_recombiner == 0){ 00162 throw Error("tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme"); 00163 } 00164 00165 _recombiner_shared.reset(_recombiner); 00166 } 00167 00168 /// allows to let the JetDefinition handle the deletion of the 00169 /// plugin when it is no longer used 00170 void JetDefinition::delete_plugin_when_unused(){ 00171 if (_plugin == 0){ 00172 throw Error("tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin"); 00173 } 00174 00175 _plugin_shared.reset(_plugin); 00176 } 00177 00178 00179 00180 string JetDefinition::DefaultRecombiner::description() const { 00181 switch(_recomb_scheme) { 00182 case E_scheme: 00183 return "E scheme recombination"; 00184 case pt_scheme: 00185 return "pt scheme recombination"; 00186 case pt2_scheme: 00187 return "pt2 scheme recombination"; 00188 case Et_scheme: 00189 return "Et scheme recombination"; 00190 case Et2_scheme: 00191 return "Et2 scheme recombination"; 00192 case BIpt_scheme: 00193 return "boost-invariant pt scheme recombination"; 00194 case BIpt2_scheme: 00195 return "boost-invariant pt2 scheme recombination"; 00196 default: 00197 ostringstream err; 00198 err << "DefaultRecombiner: unrecognized recombination scheme " 00199 << _recomb_scheme; 00200 throw Error(err.str()); 00201 } 00202 } 00203 00204 00205 void JetDefinition::DefaultRecombiner::recombine( 00206 const PseudoJet & pa, const PseudoJet & pb, 00207 PseudoJet & pab) const { 00208 00209 double weighta, weightb; 00210 00211 switch(_recomb_scheme) { 00212 case E_scheme: 00213 // a call to reset turns out to be somewhat more efficient 00214 // than a sum and assignment 00215 //pab = pa + pb; 00216 pab.reset(pa.px()+pb.px(), 00217 pa.py()+pb.py(), 00218 pa.pz()+pb.pz(), 00219 pa.E ()+pb.E ()); 00220 return; 00221 // all remaining schemes are massless recombinations and locally 00222 // we just set weights, while the hard work is done below... 00223 case pt_scheme: 00224 case Et_scheme: 00225 case BIpt_scheme: 00226 weighta = pa.perp(); 00227 weightb = pb.perp(); 00228 break; 00229 case pt2_scheme: 00230 case Et2_scheme: 00231 case BIpt2_scheme: 00232 weighta = pa.perp2(); 00233 weightb = pb.perp2(); 00234 break; 00235 default: 00236 ostringstream err; 00237 err << "DefaultRecombiner: unrecognized recombination scheme " 00238 << _recomb_scheme; 00239 throw Error(err.str()); 00240 } 00241 00242 double perp_ab = pa.perp() + pb.perp(); 00243 if (perp_ab != 0.0) { // weights also non-zero... 00244 double y_ab = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb); 00245 00246 // take care with periodicity in phi... 00247 double phi_a = pa.phi(), phi_b = pb.phi(); 00248 if (phi_a - phi_b > pi) phi_b += twopi; 00249 if (phi_a - phi_b < -pi) phi_b -= twopi; 00250 double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb); 00251 00252 // this is much more efficient... 00253 pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab); 00254 // pab = PseudoJet(perp_ab*cos(phi_ab), 00255 // perp_ab*sin(phi_ab), 00256 // perp_ab*sinh(y_ab), 00257 // perp_ab*cosh(y_ab)); 00258 } else { // weights are zero 00259 //pab = PseudoJet(0.0,0.0,0.0,0.0); 00260 pab.reset(0.0, 0.0, 0.0, 0.0); 00261 } 00262 } 00263 00264 00265 void JetDefinition::DefaultRecombiner::preprocess(PseudoJet & p) const { 00266 switch(_recomb_scheme) { 00267 case E_scheme: 00268 case BIpt_scheme: 00269 case BIpt2_scheme: 00270 break; 00271 case pt_scheme: 00272 case pt2_scheme: 00273 { 00274 // these schemes (as in the ktjet implementation) need massless 00275 // initial 4-vectors with essentially E=|p|. 00276 double newE = sqrt(p.perp2()+p.pz()*p.pz()); 00277 p.reset_momentum(p.px(), p.py(), p.pz(), newE); 00278 // FJ2.x version 00279 // int user_index = p.user_index(); 00280 // p = PseudoJet(p.px(), p.py(), p.pz(), newE); 00281 // p.set_user_index(user_index); 00282 } 00283 break; 00284 case Et_scheme: 00285 case Et2_scheme: 00286 { 00287 // these schemes (as in the ktjet implementation) need massless 00288 // initial 4-vectors with essentially E=|p|. 00289 double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz()); 00290 p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E()); 00291 // FJ2.x version 00292 // int user_index = p.user_index(); 00293 // p = PseudoJet(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E()); 00294 // p.set_user_index(user_index); 00295 } 00296 break; 00297 default: 00298 ostringstream err; 00299 err << "DefaultRecombiner: unrecognized recombination scheme " 00300 << _recomb_scheme; 00301 throw Error(err.str()); 00302 } 00303 } 00304 00305 void JetDefinition::Plugin::set_ghost_separation_scale(double scale) const { 00306 throw Error("set_ghost_separation_scale not supported"); 00307 } 00308 00309 00310 00311 //------------------------------------------------------------------------------- 00312 // helper functions to build a jet made of pieces 00313 // 00314 // This is the extended version with support for a user-defined 00315 // recombination-scheme 00316 // ------------------------------------------------------------------------------- 00317 00318 // build a "CompositeJet" from the vector of its pieces 00319 // 00320 // the user passes the reciombination scheme used to "sum" the pieces. 00321 PseudoJet join(const vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner){ 00322 // compute the total momentum 00323 //-------------------------------------------------- 00324 PseudoJet result; // automatically initialised to 0 00325 if (pieces.size()>0){ 00326 result = pieces[0]; 00327 for (unsigned int i=1; i<pieces.size(); i++) 00328 recombiner.plus_equal(result, pieces[i]); 00329 } 00330 00331 // attach a CompositeJetStructure to the result 00332 //-------------------------------------------------- 00333 CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces, &recombiner); 00334 00335 result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct)); 00336 00337 return result; 00338 } 00339 00340 // build a "CompositeJet" from a single PseudoJet 00341 PseudoJet join(const PseudoJet & j1, 00342 const JetDefinition::Recombiner & recombiner){ 00343 return join(vector<PseudoJet>(1,j1), recombiner); 00344 } 00345 00346 // build a "CompositeJet" from two PseudoJet 00347 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, 00348 const JetDefinition::Recombiner & recombiner){ 00349 vector<PseudoJet> pieces; 00350 pieces.push_back(j1); 00351 pieces.push_back(j2); 00352 return join(pieces, recombiner); 00353 } 00354 00355 // build a "CompositeJet" from 3 PseudoJet 00356 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, 00357 const JetDefinition::Recombiner & recombiner){ 00358 vector<PseudoJet> pieces; 00359 pieces.push_back(j1); 00360 pieces.push_back(j2); 00361 pieces.push_back(j3); 00362 return join(pieces, recombiner); 00363 } 00364 00365 // build a "CompositeJet" from 4 PseudoJet 00366 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4, 00367 const JetDefinition::Recombiner & recombiner){ 00368 vector<PseudoJet> pieces; 00369 pieces.push_back(j1); 00370 pieces.push_back(j2); 00371 pieces.push_back(j3); 00372 pieces.push_back(j4); 00373 return join(pieces, recombiner); 00374 } 00375 00376 00377 00378 00379 FASTJET_END_NAMESPACE