00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "fastjet/Error.hh"
00032 #include "fastjet/PseudoJet.hh"
00033 #include "fastjet/ClusterSequence.hh"
00034 #include<iostream>
00035 #include<sstream>
00036 #include<cmath>
00037 #include<cstdlib>
00038 #include<cassert>
00039 #include<string>
00040
00041 FASTJET_BEGIN_NAMESPACE
00042
00043 using namespace std;
00044
00046 JetFinder ClusterSequence::_default_jet_finder = kt_algorithm;
00047
00048
00049
00050
00051 void ClusterSequence::_initialise_and_run (
00052 const double & R,
00053 const Strategy & strategy,
00054 const bool & writeout_combinations) {
00055
00056 JetDefinition jet_def(_default_jet_finder, R, strategy);
00057 _initialise_and_run(jet_def, writeout_combinations);
00058 }
00059
00060
00061
00062 void ClusterSequence::_initialise_and_run (
00063 const JetDefinition & jet_def,
00064 const bool & writeout_combinations) {
00065
00066
00067 _decant_options(jet_def, writeout_combinations);
00068
00069
00070
00071 _fill_initial_history();
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 if (_strategy == Best) {
00099 int N = _jets.size();
00100 if (N > 6200/pow(_Rparam,2.0)
00101 && jet_def.jet_finder() == cambridge_algorithm) {
00102 _strategy = NlnNCam;}
00103 else
00104 #ifndef DROP_CGAL
00105 if (N > 16000/pow(_Rparam,1.15)) {
00106 _strategy = NlnN; }
00107 else
00108 #endif // DROP_CGAL
00109 if (N > 450) {
00110 _strategy = N2MinHeapTiled;
00111 }
00112 else if (N > 55*max(0.5,min(1.0,_Rparam))) {
00113 _strategy = N2Tiled;
00114 } else {
00115 _strategy = N2Plain;
00116 }
00117 }
00118
00119
00120
00121 if (_strategy == NlnN || _strategy == NlnN3pi
00122 || _strategy == NlnN4pi ) {
00123 this->_delaunay_cluster();
00124 } else if (_strategy == N3Dumb ) {
00125 this->_really_dumb_cluster();
00126 } else if (_strategy == N2Tiled) {
00127 this->_faster_tiled_N2_cluster();
00128 } else if (_strategy == N2PoorTiled) {
00129 this->_tiled_N2_cluster();
00130 } else if (_strategy == N2Plain) {
00131 this->_simple_N2_cluster();
00132 } else if (_strategy == N2MinHeapTiled) {
00133 this->_minheap_faster_tiled_N2_cluster();
00134 } else if (_strategy == NlnNCam4pi) {
00135 this->_CP2DChan_cluster();
00136 } else if (_strategy == NlnNCam2pi2R) {
00137 this->_CP2DChan_cluster_2pi2R();
00138 } else if (_strategy == NlnNCam) {
00139 this->_CP2DChan_cluster_2piMultD();
00140 } else {
00141 ostringstream err;
00142 err << "Unrecognised value for strategy: "<<_strategy;
00143 throw Error(err.str());
00144
00145 }
00146 }
00147
00148
00149
00150 bool ClusterSequence::_first_time = true;
00151
00152
00153 void ClusterSequence::_print_banner() {
00154
00155 if (!_first_time) {return;}
00156 _first_time = false;
00157
00158 cout << "#---------------------------------------------------------------------\n";
00159 cout << "# FastJet release 2.0 \n";
00160 cout << "# Written by Matteo Cacciari and Gavin Salam \n";
00161 cout << "# http://www.lpthe.jussieu.fr/~salam/fastjet \n";
00162 cout << "# \n";
00163 cout << "# Longitudinally invariant Kt Jet clustering, using the fast geometric\n";
00164 cout << "# algorithms of hep-ph/0512210 (please cite this if you use FastJet) \n";
00165 #ifndef DROP_CGAL
00166 cout << "# This package makes use of the CGAL library: http://www.cgal.org/ \n";
00167 #endif // DROP_CGAL
00168 cout << "# This package incorporates T.Chan's closest-pair algorithm, Proc. 13th \n";
00169 cout << "# ACM-SIAM Symposium on Discrete Algorithms, pp.472-473, 2002\n";
00170 cout << "#---------------------------------------------------------------------\n";
00171 }
00172
00173
00174
00175 void ClusterSequence::_decant_options(const JetDefinition & jet_def,
00176 const bool & writeout_combinations) {
00177
00178
00179 _print_banner();
00180
00181
00182 _jet_def = jet_def;
00183
00184 _writeout_combinations = writeout_combinations;
00185 _jet_finder = jet_def.jet_finder();
00186 _Rparam = jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
00187 _strategy = jet_def.strategy();
00188 }
00189
00190
00191
00192
00193 void ClusterSequence::_fill_initial_history () {
00194
00195 if (_jets.size() == 0) {throw Error("Cannot run jet-finder on empty event");}
00196
00197
00198 _jets.reserve(_jets.size()*2);
00199 _history.reserve(_jets.size()*2);
00200
00201 for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
00202 history_element element;
00203 element.parent1 = InexistentParent;
00204 element.parent2 = InexistentParent;
00205 element.child = Invalid;
00206 element.jetp_index = i;
00207 element.dij = 0.0;
00208 element.max_dij_so_far = 0.0;
00209
00210 _history.push_back(element);
00211
00212
00213 _jets[i].set_cluster_hist_index(i);
00214 }
00215 _initial_n = _jets.size();
00216 }
00217
00218
00219
00220
00221
00222 string ClusterSequence::strategy_string () const {
00223 string strategy;
00224 switch(_strategy) {
00225 case NlnN:
00226 strategy = "NlnN"; break;
00227 case NlnN3pi:
00228 strategy = "NlnN3pi"; break;
00229 case NlnN4pi:
00230 strategy = "NlnN4pi"; break;
00231 case N2Plain:
00232 strategy = "N2Plain"; break;
00233 case N2Tiled:
00234 strategy = "N2Tiled"; break;
00235 case N2MinHeapTiled:
00236 strategy = "N2MinHeapTiled"; break;
00237 case N2PoorTiled:
00238 strategy = "N2PoorTiled"; break;
00239 case N3Dumb:
00240 strategy = "N3Dumb"; break;
00241 case NlnNCam4pi:
00242 strategy = "NlnNCam4pi"; break;
00243 case NlnNCam2pi2R:
00244 strategy = "NlnNCam2pi2R"; break;
00245 case NlnNCam:
00246 strategy = "NlnNCam"; break;
00247 default:
00248 strategy = "Unrecognized";
00249 }
00250 return strategy;
00251 }
00252
00253
00254
00255
00256 vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
00257 double dcut = ptmin*ptmin;
00258 int i = _history.size() - 1;
00259 vector<PseudoJet> jets;
00260 if (_jet_finder == kt_algorithm) {
00261 while (i >= 0) {
00262
00263
00264
00265 if (_history[i].max_dij_so_far < dcut) {break;}
00266 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00267
00268 int parent1 = _history[i].parent1;
00269 jets.push_back(_jets[_history[parent1].jetp_index]);}
00270 i--;
00271 }
00272 } else if (_jet_finder == cambridge_algorithm) {
00273 while (i >= 0) {
00274
00275
00276
00277 if (_history[i].parent2 != BeamJet) {break;}
00278 int parent1 = _history[i].parent1;
00279 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00280 if (jet.perp2() >= dcut) {jets.push_back(jet);}
00281 i--;
00282 }
00283 } else {throw Error("Unrecognized jet algorithm");}
00284 return jets;
00285 }
00286
00287
00288
00289
00290
00291 int ClusterSequence::n_exclusive_jets (const double & dcut) const {
00292
00293
00294
00295 int i = _history.size() - 1;
00296 while (i >= 0) {
00297 if (_history[i].max_dij_so_far <= dcut) {break;}
00298 i--;
00299 }
00300 int stop_point = i + 1;
00301
00302
00303 int njets = 2*_initial_n - stop_point;
00304 return njets;
00305 }
00306
00307
00308
00309
00310 vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
00311 int njets = n_exclusive_jets(dcut);
00312 return exclusive_jets(njets);
00313 }
00314
00315
00316
00317
00318 vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
00319
00320
00321
00322 assert (njets <= _initial_n);
00323
00324
00325
00326
00327 int stop_point = 2*_initial_n - njets;
00328
00329
00330
00331 if (2*_initial_n != static_cast<int>(_history.size())) {
00332 ostringstream err;
00333 err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00334 throw Error(err.str());
00335
00336 }
00337
00338
00339
00340
00341
00342
00343 vector<PseudoJet> jets;
00344 for (unsigned int i = stop_point; i < _history.size(); i++) {
00345 int parent1 = _history[i].parent1;
00346 if (parent1 < stop_point) {
00347 jets.push_back(_jets[_history[parent1].jetp_index]);
00348 }
00349 int parent2 = _history[i].parent2;
00350 if (parent2 < stop_point && parent2 > 0) {
00351 jets.push_back(_jets[_history[parent2].jetp_index]);
00352 }
00353
00354 }
00355
00356
00357 if (static_cast<int>(jets.size()) != njets) {
00358 ostringstream err;
00359 err << "ClusterSequence::exclusive_jets: size of returned vector ("
00360 <<jets.size()<<") does not coincide with requested number of jets ("
00361 <<njets<<")";
00362 throw Error(err.str());
00363 }
00364
00365 return jets;
00366 }
00367
00368
00371 double ClusterSequence::exclusive_dmerge (const int & njets) const {
00372 assert(njets > 0);
00373 if (njets >= _initial_n) {return 0.0;}
00374 return _history[2*_initial_n-njets-1].dij;
00375 }
00376
00377
00378
00383 double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
00384 assert(njets > 0);
00385 if (njets >= _initial_n) {return 0.0;}
00386 return _history[2*_initial_n-njets-1].max_dij_so_far;
00387 }
00388
00389
00390
00391
00392 vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
00393 vector<PseudoJet> subjets;
00394 add_constituents(jet, subjets);
00395 return subjets;
00396 }
00397
00398
00399
00400
00401 void ClusterSequence::add_constituents (
00402 const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
00403
00404 int i = jet.cluster_hist_index();
00405 int parent1 = _history[i].parent1;
00406 int parent2 = _history[i].parent2;
00407
00408 if (parent1 == InexistentParent) {
00409
00410
00411 subjet_vector.push_back(jet);
00412 return;
00413 }
00414
00415
00416 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
00417
00418
00419 if (parent2 != BeamJet) {
00420 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
00421 }
00422 }
00423
00424
00425
00426
00427
00428 void ClusterSequence::_add_step_to_history (
00429 const int & step_number, const int & parent1,
00430 const int & parent2, const int & jetp_index,
00431 const double & dij) {
00432
00433 history_element element;
00434 element.parent1 = parent1;
00435 element.parent2 = parent2;
00436 element.jetp_index = jetp_index;
00437 element.child = Invalid;
00438 element.dij = dij;
00439 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00440 _history.push_back(element);
00441
00442 int local_step = _history.size()-1;
00443 assert(local_step == step_number);
00444
00445 assert(parent1 >= 0);
00446 _history[parent1].child = local_step;
00447 if (parent2 >= 0) {_history[parent2].child = local_step;}
00448
00449
00450 if (jetp_index != Invalid) {
00451 assert(jetp_index >= 0);
00452
00453 _jets[jetp_index].set_cluster_hist_index(local_step);
00454 }
00455
00456 if (_writeout_combinations) {
00457 cout << local_step << ": "
00458 << parent1 << " with " << parent2
00459 << "; y = "<< dij<<endl;
00460 }
00461
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 vector<int> ClusterSequence::unique_history_order() const {
00473
00474
00475
00476
00477
00478 valarray<int> lowest_constituent(_history.size());
00479 int hist_n = _history.size();
00480 lowest_constituent = hist_n;
00481 for (int i = 0; i < hist_n; i++) {
00482
00483 lowest_constituent[i] = min(lowest_constituent[i],i);
00484
00485 if (_history[i].child > 0) lowest_constituent[_history[i].child]
00486 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00487 }
00488
00489
00490 valarray<bool> extracted(_history.size()); extracted = false;
00491 vector<int> unique_tree;
00492 unique_tree.reserve(_history.size());
00493
00494
00495 for (unsigned i = 0; i < n_particles(); i++) {
00496 if (!extracted[i]) {
00497 unique_tree.push_back(i);
00498 extracted[i] = true;
00499 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
00500 }
00501 }
00502
00503 return unique_tree;
00504 }
00505
00506
00507
00508 void ClusterSequence::_extract_tree_children(
00509 int position,
00510 valarray<bool> & extracted,
00511 const valarray<int> & lowest_constituent,
00512 vector<int> & unique_tree) const {
00513 if (!extracted[position]) {
00514
00515
00516 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
00517 }
00518
00519
00520 int child = _history[position].child;
00521 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
00522 }
00523
00524
00525
00526 void ClusterSequence::_extract_tree_parents(
00527 int position,
00528 valarray<bool> & extracted,
00529 const valarray<int> & lowest_constituent,
00530 vector<int> & unique_tree) const {
00531
00532 if (!extracted[position]) {
00533 int parent1 = _history[position].parent1;
00534 int parent2 = _history[position].parent2;
00535
00536
00537 if (parent1 >= 0 && parent2 >= 0) {
00538 if (lowest_constituent[parent1] > lowest_constituent[parent2])
00539 swap(parent1, parent2);
00540 }
00541
00542 if (parent1 >= 0 && !extracted[parent1])
00543 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
00544 if (parent2 >= 0 && !extracted[parent2])
00545 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
00546
00547
00548 unique_tree.push_back(position);
00549 extracted[position] = true;
00550 }
00551 }
00552
00553
00554
00558 void ClusterSequence::_do_ij_recombination_step(
00559 const int & jet_i, const int & jet_j,
00560 const double & dij,
00561 int & newjet_k) {
00562
00563
00564 _jets.push_back(_jets[jet_i] + _jets[jet_j]);
00565
00566
00567 newjet_k = _jets.size()-1;
00568
00569
00570 int newstep_k = _history.size();
00571
00572 _jets[newjet_k].set_cluster_hist_index(newstep_k);
00573
00574
00575 int hist_i = _jets[jet_i].cluster_hist_index();
00576 int hist_j = _jets[jet_j].cluster_hist_index();
00577
00578 _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
00579 newjet_k, dij);
00580
00581 }
00582
00583
00584
00587 void ClusterSequence::_do_iB_recombination_step(
00588 const int & jet_i, const double & diB) {
00589
00590 int newstep_k = _history.size();
00591
00592
00593 _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
00594 Invalid, diB);
00595
00596 }
00597
00598 FASTJET_END_NAMESPACE
00599