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 "fastjet/version.hh"
00035 #include<iostream>
00036 #include<sstream>
00037 #include<cmath>
00038 #include<cstdlib>
00039 #include<cassert>
00040 #include<string>
00041
00042 FASTJET_BEGIN_NAMESPACE
00043
00044 using namespace std;
00045
00047 JetFinder ClusterSequence::_default_jet_finder = kt_algorithm;
00048
00049
00050
00051
00052 void ClusterSequence::_initialise_and_run (
00053 const double & R,
00054 const Strategy & strategy,
00055 const bool & writeout_combinations) {
00056
00057 JetDefinition jet_def(_default_jet_finder, R, strategy);
00058 _initialise_and_run(jet_def, writeout_combinations);
00059 }
00060
00061
00062
00063 void ClusterSequence::_initialise_and_run (
00064 const JetDefinition & jet_def,
00065 const bool & writeout_combinations) {
00066
00067
00068 _decant_options(jet_def, writeout_combinations);
00069
00070
00071
00072 _fill_initial_history();
00073
00074
00075 if (_jet_finder == plugin_algorithm) {
00076 _plugin_activated = true;
00077 _jet_def.plugin()->run_clustering( (*this) );
00078 _plugin_activated = false;
00079 return;
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 if (_strategy == Best) {
00089 int N = _jets.size();
00090 if (N > 6200/pow(_Rparam,2.0)
00091 && jet_def.jet_finder() == cambridge_algorithm) {
00092 _strategy = NlnNCam;}
00093 else
00094 #ifndef DROP_CGAL
00095 if (N > 16000/pow(_Rparam,1.15)) {
00096 _strategy = NlnN; }
00097 else
00098 #endif // DROP_CGAL
00099 if (N > 450) {
00100 _strategy = N2MinHeapTiled;
00101 }
00102 else if (N > 55*max(0.5,min(1.0,_Rparam))) {
00103 _strategy = N2Tiled;
00104 } else {
00105 _strategy = N2Plain;
00106 }
00107 }
00108
00109
00110
00111 if (_strategy == NlnN || _strategy == NlnN3pi
00112 || _strategy == NlnN4pi ) {
00113 this->_delaunay_cluster();
00114 } else if (_strategy == N3Dumb ) {
00115 this->_really_dumb_cluster();
00116 } else if (_strategy == N2Tiled) {
00117 this->_faster_tiled_N2_cluster();
00118 } else if (_strategy == N2PoorTiled) {
00119 this->_tiled_N2_cluster();
00120 } else if (_strategy == N2Plain) {
00121 this->_simple_N2_cluster();
00122 } else if (_strategy == N2MinHeapTiled) {
00123 this->_minheap_faster_tiled_N2_cluster();
00124 } else if (_strategy == NlnNCam4pi) {
00125 this->_CP2DChan_cluster();
00126 } else if (_strategy == NlnNCam2pi2R) {
00127 this->_CP2DChan_cluster_2pi2R();
00128 } else if (_strategy == NlnNCam) {
00129 this->_CP2DChan_cluster_2piMultD();
00130 } else {
00131 ostringstream err;
00132 err << "Unrecognised value for strategy: "<<_strategy;
00133 throw Error(err.str());
00134
00135 }
00136 }
00137
00138
00139
00140 bool ClusterSequence::_first_time = true;
00141 int ClusterSequence::_n_exclusive_warnings = 0;
00142
00143
00144
00145 void ClusterSequence::_print_banner() {
00146
00147 if (!_first_time) {return;}
00148 _first_time = false;
00149
00150
00151
00152
00153 cout << "#------------------------------------------------------------------------\n";
00154 cout << "# FastJet release " << fastjet_version << endl;
00155 cout << "# Written by Matteo Cacciari and Gavin Salam \n";
00156 cout << "# http://www.lpthe.jussieu.fr/~salam/fastjet \n";
00157 cout << "# \n";
00158 cout << "# Longitudinally invariant Kt, and inclusive Cambridge/Aachen clustering\n";
00159 cout << "# using fast geometric algorithms, with optional external jet-finder \n";
00160 cout << "# plugins. Please cite hep-ph/0512210 if you use this code. \n";
00161 cout << "# \n";
00162 cout << "# This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM \n";
00163 cout << "# Symp. Discr. Alg, p.472 (2002)";
00164 #ifndef DROP_CGAL
00165 cout << " as well as CGAL: http://www.cgal.org/";
00166 #endif // DROP_CGAL
00167 cout << ".\n";
00168 cout << "#-----------------------------------------------------------------------\n";
00169 }
00170
00171
00172
00173 void ClusterSequence::_decant_options(const JetDefinition & jet_def,
00174 const bool & writeout_combinations) {
00175
00176
00177 _print_banner();
00178
00179
00180 _jet_def = jet_def;
00181
00182 _writeout_combinations = writeout_combinations;
00183 _jet_finder = jet_def.jet_finder();
00184 _Rparam = jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
00185 _strategy = jet_def.strategy();
00186
00187
00188 _plugin_activated = false;
00189
00190 }
00191
00192
00193
00194
00195 void ClusterSequence::_fill_initial_history () {
00196
00197 if (_jets.size() == 0) {throw Error("Cannot run jet-finder on empty event");}
00198
00199
00200 _jets.reserve(_jets.size()*2);
00201 _history.reserve(_jets.size()*2);
00202
00203 for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
00204 history_element element;
00205 element.parent1 = InexistentParent;
00206 element.parent2 = InexistentParent;
00207 element.child = Invalid;
00208 element.jetp_index = i;
00209 element.dij = 0.0;
00210 element.max_dij_so_far = 0.0;
00211
00212 _history.push_back(element);
00213
00214
00215 _jet_def.recombiner()->preprocess(_jets[i]);
00216
00217
00218 _jets[i].set_cluster_hist_index(i);
00219 }
00220 _initial_n = _jets.size();
00221 }
00222
00223
00224
00225
00226
00227 string ClusterSequence::strategy_string () const {
00228 string strategy;
00229 switch(_strategy) {
00230 case NlnN:
00231 strategy = "NlnN"; break;
00232 case NlnN3pi:
00233 strategy = "NlnN3pi"; break;
00234 case NlnN4pi:
00235 strategy = "NlnN4pi"; break;
00236 case N2Plain:
00237 strategy = "N2Plain"; break;
00238 case N2Tiled:
00239 strategy = "N2Tiled"; break;
00240 case N2MinHeapTiled:
00241 strategy = "N2MinHeapTiled"; break;
00242 case N2PoorTiled:
00243 strategy = "N2PoorTiled"; break;
00244 case N3Dumb:
00245 strategy = "N3Dumb"; break;
00246 case NlnNCam4pi:
00247 strategy = "NlnNCam4pi"; break;
00248 case NlnNCam2pi2R:
00249 strategy = "NlnNCam2pi2R"; break;
00250 case NlnNCam:
00251 strategy = "NlnNCam"; break;
00252 case plugin_strategy:
00253 strategy = "plugin strategy"; break;
00254 default:
00255 strategy = "Unrecognized";
00256 }
00257 return strategy;
00258 }
00259
00260
00261
00262
00263
00264 void ClusterSequence::plugin_record_ij_recombination(
00265 int jet_i, int jet_j, double dij,
00266 const PseudoJet & newjet, int & newjet_k) {
00267
00268 plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
00269
00270
00271 int tmp_index = _jets[newjet_k].cluster_hist_index();
00272 _jets[newjet_k] = newjet;
00273 _jets[newjet_k].set_cluster_hist_index(tmp_index);
00274 }
00275
00276
00277
00278
00279 vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
00280 double dcut = ptmin*ptmin;
00281 int i = _history.size() - 1;
00282 vector<PseudoJet> jets;
00283 if (_jet_finder == kt_algorithm) {
00284 while (i >= 0) {
00285
00286
00287
00288 if (_history[i].max_dij_so_far < dcut) {break;}
00289 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00290
00291 int parent1 = _history[i].parent1;
00292 jets.push_back(_jets[_history[parent1].jetp_index]);}
00293 i--;
00294 }
00295 } else if (_jet_finder == cambridge_algorithm) {
00296 while (i >= 0) {
00297
00298
00299
00300 if (_history[i].parent2 != BeamJet) {break;}
00301 int parent1 = _history[i].parent1;
00302 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00303 if (jet.perp2() >= dcut) {jets.push_back(jet);}
00304 i--;
00305 }
00306 } else if (_jet_finder == plugin_algorithm) {
00307
00308
00309
00310 while (i >= 0) {
00311 if (_history[i].parent2 == BeamJet) {
00312 int parent1 = _history[i].parent1;
00313 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00314 if (jet.perp2() >= dcut) {jets.push_back(jet);}
00315 }
00316 i--;
00317 }
00318 } else {throw Error("Unrecognized jet algorithm");}
00319 return jets;
00320 }
00321
00322
00323
00324
00325
00326 int ClusterSequence::n_exclusive_jets (const double & dcut) const {
00327
00328
00329
00330 int i = _history.size() - 1;
00331 while (i >= 0) {
00332 if (_history[i].max_dij_so_far <= dcut) {break;}
00333 i--;
00334 }
00335 int stop_point = i + 1;
00336
00337
00338 int njets = 2*_initial_n - stop_point;
00339 return njets;
00340 }
00341
00342
00343
00344
00345 vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
00346 int njets = n_exclusive_jets(dcut);
00347 return exclusive_jets(njets);
00348 }
00349
00350
00351
00352
00353 vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
00354
00355
00356
00357 assert (njets <= _initial_n);
00358
00359
00360 if (_jet_def.jet_finder() != kt_algorithm && _n_exclusive_warnings < 5) {
00361 _n_exclusive_warnings++;
00362 cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
00363 }
00364
00365
00366
00367
00368
00369 int stop_point = 2*_initial_n - njets;
00370
00371
00372
00373 if (2*_initial_n != static_cast<int>(_history.size())) {
00374 ostringstream err;
00375 err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00376 throw Error(err.str());
00377
00378 }
00379
00380
00381
00382
00383
00384
00385 vector<PseudoJet> jets;
00386 for (unsigned int i = stop_point; i < _history.size(); i++) {
00387 int parent1 = _history[i].parent1;
00388 if (parent1 < stop_point) {
00389 jets.push_back(_jets[_history[parent1].jetp_index]);
00390 }
00391 int parent2 = _history[i].parent2;
00392 if (parent2 < stop_point && parent2 > 0) {
00393 jets.push_back(_jets[_history[parent2].jetp_index]);
00394 }
00395
00396 }
00397
00398
00399 if (static_cast<int>(jets.size()) != njets) {
00400 ostringstream err;
00401 err << "ClusterSequence::exclusive_jets: size of returned vector ("
00402 <<jets.size()<<") does not coincide with requested number of jets ("
00403 <<njets<<")";
00404 throw Error(err.str());
00405 }
00406
00407 return jets;
00408 }
00409
00410
00413 double ClusterSequence::exclusive_dmerge (const int & njets) const {
00414 assert(njets > 0);
00415 if (njets >= _initial_n) {return 0.0;}
00416 return _history[2*_initial_n-njets-1].dij;
00417 }
00418
00419
00420
00425 double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
00426 assert(njets > 0);
00427 if (njets >= _initial_n) {return 0.0;}
00428 return _history[2*_initial_n-njets-1].max_dij_so_far;
00429 }
00430
00431
00432
00433
00434 vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
00435 vector<PseudoJet> subjets;
00436 add_constituents(jet, subjets);
00437 return subjets;
00438 }
00439
00440
00441
00446 vector<int> ClusterSequence::particle_jet_indices(
00447 const vector<PseudoJet> & jets) const {
00448
00449 vector<int> indices(n_particles());
00450
00451
00452 for (unsigned ipart = 0; ipart < n_particles(); ipart++)
00453 indices[ipart] = -1;
00454
00455
00456
00457 for (unsigned ijet = 0; ijet < jets.size(); ijet++) {
00458
00459 vector<PseudoJet> jet_constituents(constituents(jets[ijet]));
00460
00461 for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
00462
00463
00464
00465 unsigned iclust = jet_constituents[ip].cluster_hist_index();
00466 unsigned ipart = history()[iclust].jetp_index;
00467 indices[ipart] = ijet;
00468 }
00469 }
00470
00471 return indices;
00472 }
00473
00474
00475
00476
00477 void ClusterSequence::add_constituents (
00478 const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
00479
00480 int i = jet.cluster_hist_index();
00481 int parent1 = _history[i].parent1;
00482 int parent2 = _history[i].parent2;
00483
00484 if (parent1 == InexistentParent) {
00485
00486
00487 subjet_vector.push_back(jet);
00488 return;
00489 }
00490
00491
00492 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
00493
00494
00495 if (parent2 != BeamJet) {
00496 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
00497 }
00498 }
00499
00500
00501
00502
00503
00504 void ClusterSequence::_add_step_to_history (
00505 const int & step_number, const int & parent1,
00506 const int & parent2, const int & jetp_index,
00507 const double & dij) {
00508
00509 history_element element;
00510 element.parent1 = parent1;
00511 element.parent2 = parent2;
00512 element.jetp_index = jetp_index;
00513 element.child = Invalid;
00514 element.dij = dij;
00515 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00516 _history.push_back(element);
00517
00518 int local_step = _history.size()-1;
00519 assert(local_step == step_number);
00520
00521 assert(parent1 >= 0);
00522 _history[parent1].child = local_step;
00523 if (parent2 >= 0) {_history[parent2].child = local_step;}
00524
00525
00526 if (jetp_index != Invalid) {
00527 assert(jetp_index >= 0);
00528
00529 _jets[jetp_index].set_cluster_hist_index(local_step);
00530 }
00531
00532 if (_writeout_combinations) {
00533 cout << local_step << ": "
00534 << parent1 << " with " << parent2
00535 << "; y = "<< dij<<endl;
00536 }
00537
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 vector<int> ClusterSequence::unique_history_order() const {
00549
00550
00551
00552
00553
00554 valarray<int> lowest_constituent(_history.size());
00555 int hist_n = _history.size();
00556 lowest_constituent = hist_n;
00557 for (int i = 0; i < hist_n; i++) {
00558
00559 lowest_constituent[i] = min(lowest_constituent[i],i);
00560
00561 if (_history[i].child > 0) lowest_constituent[_history[i].child]
00562 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00563 }
00564
00565
00566 valarray<bool> extracted(_history.size()); extracted = false;
00567 vector<int> unique_tree;
00568 unique_tree.reserve(_history.size());
00569
00570
00571 for (unsigned i = 0; i < n_particles(); i++) {
00572 if (!extracted[i]) {
00573 unique_tree.push_back(i);
00574 extracted[i] = true;
00575 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
00576 }
00577 }
00578
00579 return unique_tree;
00580 }
00581
00582
00583
00584 void ClusterSequence::_extract_tree_children(
00585 int position,
00586 valarray<bool> & extracted,
00587 const valarray<int> & lowest_constituent,
00588 vector<int> & unique_tree) const {
00589 if (!extracted[position]) {
00590
00591
00592 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
00593 }
00594
00595
00596 int child = _history[position].child;
00597 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
00598 }
00599
00600
00601
00602
00603 vector<PseudoJet> ClusterSequence::unclustered_particles() const {
00604 vector<PseudoJet> unclustered;
00605 for (unsigned i = 0; i < n_particles() ; i++) {
00606 if (_history[i].child == Invalid)
00607 unclustered.push_back(_jets[_history[i].jetp_index]);
00608 }
00609 return unclustered;
00610 }
00611
00612
00613
00614
00615
00616 void ClusterSequence::_extract_tree_parents(
00617 int position,
00618 valarray<bool> & extracted,
00619 const valarray<int> & lowest_constituent,
00620 vector<int> & unique_tree) const {
00621
00622 if (!extracted[position]) {
00623 int parent1 = _history[position].parent1;
00624 int parent2 = _history[position].parent2;
00625
00626
00627 if (parent1 >= 0 && parent2 >= 0) {
00628 if (lowest_constituent[parent1] > lowest_constituent[parent2])
00629 swap(parent1, parent2);
00630 }
00631
00632 if (parent1 >= 0 && !extracted[parent1])
00633 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
00634 if (parent2 >= 0 && !extracted[parent2])
00635 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
00636
00637
00638 unique_tree.push_back(position);
00639 extracted[position] = true;
00640 }
00641 }
00642
00643
00644
00648 void ClusterSequence::_do_ij_recombination_step(
00649 const int & jet_i, const int & jet_j,
00650 const double & dij,
00651 int & newjet_k) {
00652
00653
00654 PseudoJet newjet;
00655 _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
00656 _jets.push_back(newjet);
00657
00658
00659
00660
00661 newjet_k = _jets.size()-1;
00662
00663
00664 int newstep_k = _history.size();
00665
00666 _jets[newjet_k].set_cluster_hist_index(newstep_k);
00667
00668
00669 int hist_i = _jets[jet_i].cluster_hist_index();
00670 int hist_j = _jets[jet_j].cluster_hist_index();
00671
00672 _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
00673 newjet_k, dij);
00674
00675 }
00676
00677
00678
00681 void ClusterSequence::_do_iB_recombination_step(
00682 const int & jet_i, const double & diB) {
00683
00684 int newstep_k = _history.size();
00685
00686
00687 _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
00688 Invalid, diB);
00689
00690 }
00691
00692 FASTJET_END_NAMESPACE
00693