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<fstream>
00038 #include<cmath>
00039 #include<cstdlib>
00040 #include<cassert>
00041 #include<string>
00042 #include<set>
00043
00044 FASTJET_BEGIN_NAMESPACE
00045
00046 using namespace std;
00047
00049 JetAlgorithm ClusterSequence::_default_jet_algorithm = kt_algorithm;
00050
00051
00052
00053
00054 ClusterSequence::~ClusterSequence () {}
00055
00056
00057 void ClusterSequence::_initialise_and_run (
00058 const double & R,
00059 const Strategy & strategy,
00060 const bool & writeout_combinations) {
00061
00062 JetDefinition jet_def(_default_jet_algorithm, R, strategy);
00063 _initialise_and_run(jet_def, writeout_combinations);
00064 }
00065
00066
00067
00068 void ClusterSequence::_initialise_and_run (
00069 const JetDefinition & jet_def,
00070 const bool & writeout_combinations) {
00071
00072
00073 _decant_options(jet_def, writeout_combinations);
00074
00075
00076
00077 _fill_initial_history();
00078
00079
00080 if (n_particles() == 0) return;
00081
00082
00083 if (_jet_algorithm == plugin_algorithm) {
00084
00085 _plugin_activated = true;
00086
00087 _jet_def.plugin()->run_clustering( (*this) );
00088 _plugin_activated = false;
00089 return;
00090 } else if (_jet_algorithm == ee_kt_algorithm ||
00091 _jet_algorithm == ee_genkt_algorithm) {
00092
00093 _strategy = N2Plain;
00094 if (_jet_algorithm == ee_kt_algorithm) {
00095
00096
00097
00098 assert(_Rparam > 2.0);
00099
00100
00101
00102 _invR2 = 1.0;
00103 } else {
00104
00105
00106
00107
00108 if (_Rparam > pi) {
00109
00110
00111
00112 _R2 = 2 * ( 3.0 + cos(_Rparam) );
00113 } else {
00114 _R2 = 2 * ( 1.0 - cos(_Rparam) );
00115 }
00116 _invR2 = 1.0/_R2;
00117 }
00118
00119 _simple_N2_cluster_EEBriefJet();
00120 return;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 if (_strategy == Best) {
00130 int N = _jets.size();
00131 if (N > 6200/pow(_Rparam,2.0)
00132 && jet_def.jet_algorithm() == cambridge_algorithm) {
00133 _strategy = NlnNCam;}
00134 else
00135 #ifndef DROP_CGAL
00136 if ((N > 16000/pow(_Rparam,1.15) && jet_def.jet_algorithm() != antikt_algorithm)
00137 || N > 35000/pow(_Rparam,1.15)) {
00138 _strategy = NlnN; }
00139 else
00140 #endif // DROP_CGAL
00141 if (N > 450) {
00142 _strategy = N2MinHeapTiled;
00143 }
00144 else if (N > 55*max(0.5,min(1.0,_Rparam))) {
00145 _strategy = N2Tiled;
00146 } else {
00147 _strategy = N2Plain;
00148 }
00149 }
00150
00151
00152
00153 if (_strategy == NlnN || _strategy == NlnN3pi
00154 || _strategy == NlnN4pi ) {
00155 this->_delaunay_cluster();
00156 } else if (_strategy == N3Dumb ) {
00157 this->_really_dumb_cluster();
00158 } else if (_strategy == N2Tiled) {
00159 this->_faster_tiled_N2_cluster();
00160 } else if (_strategy == N2PoorTiled) {
00161 this->_tiled_N2_cluster();
00162 } else if (_strategy == N2Plain) {
00163
00164
00165 this->_simple_N2_cluster_BriefJet();
00166 } else if (_strategy == N2MinHeapTiled) {
00167 this->_minheap_faster_tiled_N2_cluster();
00168 } else if (_strategy == NlnNCam4pi) {
00169 this->_CP2DChan_cluster();
00170 } else if (_strategy == NlnNCam2pi2R) {
00171 this->_CP2DChan_cluster_2pi2R();
00172 } else if (_strategy == NlnNCam) {
00173 this->_CP2DChan_cluster_2piMultD();
00174 } else {
00175 ostringstream err;
00176 err << "Unrecognised value for strategy: "<<_strategy;
00177 throw Error(err.str());
00178
00179 }
00180 }
00181
00182
00183
00184 bool ClusterSequence::_first_time = true;
00185 int ClusterSequence::_n_exclusive_warnings = 0;
00186
00187
00188
00189
00190 string fastjet_version_string() {
00191 return "FastJet version "+string(fastjet_version);
00192 }
00193
00194
00195
00196
00197 void ClusterSequence::_print_banner() {
00198
00199 if (!_first_time) {return;}
00200 _first_time = false;
00201
00202
00203
00204
00205 cout << "#--------------------------------------------------------------------------\n";
00206 cout << "# FastJet release " << fastjet_version << endl;
00207 cout << "# Written by M. Cacciari, G.P. Salam and G. Soyez \n";
00208 cout << "# http://www.fastjet.fr \n";
00209 cout << "# \n";
00210 cout << "# Longitudinally invariant Kt, anti-Kt, and inclusive Cambridge/Aachen \n";
00211 cout << "# clustering using fast geometric algorithms, with area measures and optional\n";
00212 cout << "# external jet-finder plugins. \n";
00213 cout << "# Please cite Phys. Lett. B641 (2006) [hep-ph/0512210] if you use this code.\n";
00214 cout << "# \n";
00215 cout << "# This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM \n";
00216 cout << "# Symp. Discr. Alg, p.472 (2002), S.Fortune's Voronoi algorithm and code " ;
00217 #ifndef DROP_CGAL
00218 cout << endl << "# and CGAL: http://www.cgal.org/";
00219 #endif // DROP_CGAL
00220 cout << ".\n";
00221 cout << "#-------------------------------------------------------------------------\n";
00222 }
00223
00224
00225
00226 void ClusterSequence::_decant_options(const JetDefinition & jet_def,
00227 const bool & writeout_combinations) {
00228
00229
00230 _print_banner();
00231
00232
00233 _jet_def = jet_def;
00234
00235 _writeout_combinations = writeout_combinations;
00236 _jet_algorithm = jet_def.jet_algorithm();
00237 _Rparam = jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
00238 _strategy = jet_def.strategy();
00239
00240
00241 _plugin_activated = false;
00242
00243 }
00244
00245
00246
00247
00248 void ClusterSequence::_fill_initial_history () {
00249
00250
00251
00252
00253 _jets.reserve(_jets.size()*2);
00254 _history.reserve(_jets.size()*2);
00255
00256 _Qtot = 0;
00257
00258 for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
00259 history_element element;
00260 element.parent1 = InexistentParent;
00261 element.parent2 = InexistentParent;
00262 element.child = Invalid;
00263 element.jetp_index = i;
00264 element.dij = 0.0;
00265 element.max_dij_so_far = 0.0;
00266
00267 _history.push_back(element);
00268
00269
00270 _jet_def.recombiner()->preprocess(_jets[i]);
00271
00272
00273 _jets[i].set_cluster_hist_index(i);
00274
00275
00276 _Qtot += _jets[i].E();
00277 }
00278 _initial_n = _jets.size();
00279 }
00280
00281
00282
00283
00284
00285 string ClusterSequence::strategy_string () const {
00286 string strategy;
00287 switch(_strategy) {
00288 case NlnN:
00289 strategy = "NlnN"; break;
00290 case NlnN3pi:
00291 strategy = "NlnN3pi"; break;
00292 case NlnN4pi:
00293 strategy = "NlnN4pi"; break;
00294 case N2Plain:
00295 strategy = "N2Plain"; break;
00296 case N2Tiled:
00297 strategy = "N2Tiled"; break;
00298 case N2MinHeapTiled:
00299 strategy = "N2MinHeapTiled"; break;
00300 case N2PoorTiled:
00301 strategy = "N2PoorTiled"; break;
00302 case N3Dumb:
00303 strategy = "N3Dumb"; break;
00304 case NlnNCam4pi:
00305 strategy = "NlnNCam4pi"; break;
00306 case NlnNCam2pi2R:
00307 strategy = "NlnNCam2pi2R"; break;
00308 case NlnNCam:
00309 strategy = "NlnNCam"; break;
00310 case plugin_strategy:
00311 strategy = "plugin strategy"; break;
00312 default:
00313 strategy = "Unrecognized";
00314 }
00315 return strategy;
00316 }
00317
00318
00319 double ClusterSequence::jet_scale_for_algorithm(
00320 const PseudoJet & jet) const {
00321 if (_jet_algorithm == kt_algorithm) {return jet.kt2();}
00322 else if (_jet_algorithm == cambridge_algorithm) {return 1.0;}
00323 else if (_jet_algorithm == antikt_algorithm) {
00324 double kt2=jet.kt2();
00325 return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
00326 } else if (_jet_algorithm == genkt_algorithm) {
00327 double kt2 = jet.kt2();
00328 double p = jet_def().extra_param();
00329 if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300;
00330 return pow(kt2, p);
00331 } else if (_jet_algorithm == cambridge_for_passive_algorithm) {
00332 double kt2 = jet.kt2();
00333 double lim = _jet_def.extra_param();
00334 if (kt2 < lim*lim && kt2 != 0.0) {
00335 return 1.0/kt2;
00336 } else {return 1.0;}
00337 } else {throw Error("Unrecognised jet algorithm");}
00338 }
00339
00340
00341
00345 void ClusterSequence::transfer_from_sequence(ClusterSequence & from_seq) {
00346
00347
00348 _jet_def = from_seq._jet_def ;
00349 _writeout_combinations = from_seq._writeout_combinations ;
00350 _initial_n = from_seq._initial_n ;
00351 _Rparam = from_seq._Rparam ;
00352 _R2 = from_seq._R2 ;
00353 _invR2 = from_seq._invR2 ;
00354 _strategy = from_seq._strategy ;
00355 _jet_algorithm = from_seq._jet_algorithm ;
00356 _plugin_activated = from_seq._plugin_activated ;
00357
00358
00359 _jets = from_seq._jets;
00360 _history = from_seq._history;
00361
00362 _extras = from_seq._extras;
00363
00364 }
00365
00366
00367
00368
00369 void ClusterSequence::plugin_record_ij_recombination(
00370 int jet_i, int jet_j, double dij,
00371 const PseudoJet & newjet, int & newjet_k) {
00372
00373 plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
00374
00375
00376 int tmp_index = _jets[newjet_k].cluster_hist_index();
00377 _jets[newjet_k] = newjet;
00378 _jets[newjet_k].set_cluster_hist_index(tmp_index);
00379 }
00380
00381
00382
00383
00384 vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
00385 double dcut = ptmin*ptmin;
00386 int i = _history.size() - 1;
00387 vector<PseudoJet> jets;
00388 if (_jet_algorithm == kt_algorithm) {
00389 while (i >= 0) {
00390
00391
00392
00393 if (_history[i].max_dij_so_far < dcut) {break;}
00394 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00395
00396 int parent1 = _history[i].parent1;
00397 jets.push_back(_jets[_history[parent1].jetp_index]);}
00398 i--;
00399 }
00400 } else if (_jet_algorithm == cambridge_algorithm) {
00401 while (i >= 0) {
00402
00403
00404
00405 if (_history[i].parent2 != BeamJet) {break;}
00406 int parent1 = _history[i].parent1;
00407 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00408 if (jet.perp2() >= dcut) {jets.push_back(jet);}
00409 i--;
00410 }
00411 } else if (_jet_algorithm == plugin_algorithm
00412 || _jet_algorithm == ee_kt_algorithm
00413 || _jet_algorithm == antikt_algorithm
00414 || _jet_algorithm == genkt_algorithm
00415 || _jet_algorithm == ee_genkt_algorithm
00416 || _jet_algorithm == cambridge_for_passive_algorithm) {
00417
00418
00419
00420 while (i >= 0) {
00421 if (_history[i].parent2 == BeamJet) {
00422 int parent1 = _history[i].parent1;
00423 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00424 if (jet.perp2() >= dcut) {jets.push_back(jet);}
00425 }
00426 i--;
00427 }
00428 } else {throw Error("cs::inclusive_jets(...): Unrecognized jet algorithm");}
00429 return jets;
00430 }
00431
00432
00433
00434
00435
00436 int ClusterSequence::n_exclusive_jets (const double & dcut) const {
00437
00438
00439
00440 int i = _history.size() - 1;
00441 while (i >= 0) {
00442 if (_history[i].max_dij_so_far <= dcut) {break;}
00443 i--;
00444 }
00445 int stop_point = i + 1;
00446
00447
00448 int njets = 2*_initial_n - stop_point;
00449 return njets;
00450 }
00451
00452
00453
00454
00455 vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
00456 int njets = n_exclusive_jets(dcut);
00457 return exclusive_jets(njets);
00458 }
00459
00460
00461
00462
00463 vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
00464
00465
00466
00467 assert (njets <= _initial_n);
00468
00469
00470
00471
00472
00473
00474 if (( _jet_def.jet_algorithm() != kt_algorithm) &&
00475 ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
00476 ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
00477 (((_jet_def.jet_algorithm() != genkt_algorithm) &&
00478 (_jet_def.jet_algorithm() != ee_genkt_algorithm)) ||
00479 (_jet_def.extra_param() <0)) &&
00480 ((_jet_def.jet_algorithm() != plugin_algorithm) ||
00481 (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
00482 (_n_exclusive_warnings < 5)) {
00483 _n_exclusive_warnings++;
00484 cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
00485 }
00486
00487
00488
00489
00490
00491 int stop_point = 2*_initial_n - njets;
00492
00493
00494
00495 if (2*_initial_n != static_cast<int>(_history.size())) {
00496 ostringstream err;
00497 err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00498 throw Error(err.str());
00499
00500 }
00501
00502
00503
00504
00505
00506
00507 vector<PseudoJet> jets;
00508 for (unsigned int i = stop_point; i < _history.size(); i++) {
00509 int parent1 = _history[i].parent1;
00510 if (parent1 < stop_point) {
00511 jets.push_back(_jets[_history[parent1].jetp_index]);
00512 }
00513 int parent2 = _history[i].parent2;
00514 if (parent2 < stop_point && parent2 > 0) {
00515 jets.push_back(_jets[_history[parent2].jetp_index]);
00516 }
00517
00518 }
00519
00520
00521 if (static_cast<int>(jets.size()) != njets) {
00522 ostringstream err;
00523 err << "ClusterSequence::exclusive_jets: size of returned vector ("
00524 <<jets.size()<<") does not coincide with requested number of jets ("
00525 <<njets<<")";
00526 throw Error(err.str());
00527 }
00528
00529 return jets;
00530 }
00531
00532
00535 double ClusterSequence::exclusive_dmerge (const int & njets) const {
00536 assert(njets >= 0);
00537 if (njets >= _initial_n) {return 0.0;}
00538 return _history[2*_initial_n-njets-1].dij;
00539 }
00540
00541
00542
00547 double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
00548 assert(njets >= 0);
00549 if (njets >= _initial_n) {return 0.0;}
00550 return _history[2*_initial_n-njets-1].max_dij_so_far;
00551 }
00552
00553
00554
00558 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
00559 (const PseudoJet & jet, const double & dcut) const {
00560
00561 set<const history_element*> subhist;
00562
00563
00564
00565 get_subhist_set(subhist, jet, dcut, 0);
00566
00567
00568 vector<PseudoJet> subjets;
00569 subjets.reserve(subhist.size());
00570 for (set<const history_element*>::iterator elem = subhist.begin();
00571 elem != subhist.end(); elem++) {
00572 subjets.push_back(_jets[(*elem)->jetp_index]);
00573 }
00574 return subjets;
00575 }
00576
00577
00581 int ClusterSequence::n_exclusive_subjets(const PseudoJet & jet,
00582 const double & dcut) const {
00583 set<const history_element*> subhist;
00584
00585
00586 get_subhist_set(subhist, jet, dcut, 0);
00587 return subhist.size();
00588 }
00589
00590
00594 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
00595 (const PseudoJet & jet, int n) const {
00596
00597 set<const history_element*> subhist;
00598
00599
00600
00601 get_subhist_set(subhist, jet, -1.0, n);
00602
00603
00604 vector<PseudoJet> subjets;
00605 subjets.reserve(subhist.size());
00606 for (set<const history_element*>::iterator elem = subhist.begin();
00607 elem != subhist.end(); elem++) {
00608 subjets.push_back(_jets[(*elem)->jetp_index]);
00609 }
00610 return subjets;
00611 }
00612
00613
00614
00619 double ClusterSequence::exclusive_subdmerge(const PseudoJet & jet, int nsub) const {
00620 set<const history_element*> subhist;
00621
00622
00623
00624 get_subhist_set(subhist, jet, -1.0, nsub);
00625
00626 set<const history_element*>::iterator highest = subhist.end();
00627 highest--;
00630 return (*highest)->dij;
00631 }
00632
00633
00634
00640 double ClusterSequence::exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const {
00641
00642 set<const history_element*> subhist;
00643
00644
00645
00646 get_subhist_set(subhist, jet, -1.0, nsub);
00647
00648 set<const history_element*>::iterator highest = subhist.end();
00649 highest--;
00652 return (*highest)->max_dij_so_far;
00653 }
00654
00655
00656
00657
00664 void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
00665 const PseudoJet & jet,
00666 double dcut, int maxjet) const {
00667 subhist.clear();
00668 subhist.insert(&(_history[jet.cluster_hist_index()]));
00669
00670
00671 int njet = 1;
00672 while (true) {
00673
00674
00675 set<const history_element*>::iterator highest = subhist.end();
00676 assert (highest != subhist.begin());
00677 highest--;
00678 const history_element* elem = *highest;
00679
00680 if (njet == maxjet) break;
00681
00682 if (elem->parent1 < 0) break;
00683
00684 if (elem->max_dij_so_far <= dcut) break;
00685
00686
00687 subhist.erase(highest);
00688 subhist.insert(&(_history[elem->parent1]));
00689 subhist.insert(&(_history[elem->parent2]));
00690 njet++;
00691 }
00692 }
00693
00694
00695
00696 bool ClusterSequence::object_in_jet(const PseudoJet & object,
00697 const PseudoJet & jet) const {
00698
00699
00700
00701 assert(_potentially_valid(object) && _potentially_valid(jet));
00702
00703 const PseudoJet * this_object = &object;
00704 const PseudoJet * childp;
00705 while(true) {
00706 if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
00707 return true;
00708 } else if (has_child(*this_object, childp)) {this_object = childp;}
00709 else {return false;}
00710 }
00711 }
00712
00713
00719 bool ClusterSequence::has_parents(const PseudoJet & jet, PseudoJet & parent1,
00720 PseudoJet & parent2) const {
00721
00722 const history_element & hist = _history[jet.cluster_hist_index()];
00723
00724
00725
00726 assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
00727 (hist.parent1 < 0 && hist.parent2 < 0));
00728
00729 if (hist.parent1 < 0) {
00730 parent1 = PseudoJet(0.0,0.0,0.0,0.0);
00731 parent2 = parent1;
00732 return false;
00733 } else {
00734 parent1 = _jets[_history[hist.parent1].jetp_index];
00735 parent2 = _jets[_history[hist.parent2].jetp_index];
00736
00737 if (parent1.perp2() < parent2.perp2()) swap(parent1,parent2);
00738 return true;
00739 }
00740 }
00741
00742
00745 bool ClusterSequence::has_child(const PseudoJet & jet, PseudoJet & child) const {
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 const PseudoJet * childp;
00757 bool res = has_child(jet, childp);
00758 if (res) {
00759 child = *childp;
00760 return true;
00761 } else {
00762 child = PseudoJet(0.0,0.0,0.0,0.0);
00763 return false;
00764 }
00765 }
00766
00767 bool ClusterSequence::has_child(const PseudoJet & jet, const PseudoJet * & childp) const {
00768
00769 const history_element & hist = _history[jet.cluster_hist_index()];
00770
00771
00772
00773
00774 if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
00775 childp = &(_jets[_history[hist.child].jetp_index]);
00776 return true;
00777 } else {
00778 childp = NULL;
00779 return false;
00780 }
00781 }
00782
00783
00784
00788 bool ClusterSequence::has_partner(const PseudoJet & jet,
00789 PseudoJet & partner) const {
00790
00791 const history_element & hist = _history[jet.cluster_hist_index()];
00792
00793
00794
00795 if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
00796 const history_element & child_hist = _history[hist.child];
00797 if (child_hist.parent1 == jet.cluster_hist_index()) {
00798
00799
00800 partner = _jets[_history[child_hist.parent2].jetp_index];
00801 } else {
00802
00803 partner = _jets[_history[child_hist.parent1].jetp_index];
00804 }
00805 return true;
00806 } else {
00807 partner = PseudoJet(0.0,0.0,0.0,0.0);
00808 return false;
00809 }
00810 }
00811
00812
00813
00814
00815 vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
00816 vector<PseudoJet> subjets;
00817 add_constituents(jet, subjets);
00818 return subjets;
00819 }
00820
00821
00830 void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets,
00831 ostream & ostr) const {
00832 for (unsigned i = 0; i < jets.size(); i++) {
00833 ostr << i << " "
00834 << jets[i].px() << " "
00835 << jets[i].py() << " "
00836 << jets[i].pz() << " "
00837 << jets[i].E() << endl;
00838 vector<PseudoJet> cst = constituents(jets[i]);
00839 for (unsigned j = 0; j < cst.size() ; j++) {
00840 ostr << " " << j << " "
00841 << cst[j].rap() << " "
00842 << cst[j].phi() << " "
00843 << cst[j].perp() << endl;
00844 }
00845 ostr << "#END" << endl;
00846 }
00847 }
00848
00849 void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets,
00850 const std::string & filename,
00851 const std::string & comment ) const {
00852 std::ofstream ostr(filename.c_str());
00853 if (comment != "") ostr << "# " << comment << endl;
00854 print_jets_for_root(jets, ostr);
00855 }
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00875 vector<int> ClusterSequence::particle_jet_indices(
00876 const vector<PseudoJet> & jets) const {
00877
00878 vector<int> indices(n_particles());
00879
00880
00881 for (unsigned ipart = 0; ipart < n_particles(); ipart++)
00882 indices[ipart] = -1;
00883
00884
00885
00886 for (unsigned ijet = 0; ijet < jets.size(); ijet++) {
00887
00888 vector<PseudoJet> jet_constituents(constituents(jets[ijet]));
00889
00890 for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
00891
00892
00893
00894 unsigned iclust = jet_constituents[ip].cluster_hist_index();
00895 unsigned ipart = history()[iclust].jetp_index;
00896 indices[ipart] = ijet;
00897 }
00898 }
00899
00900 return indices;
00901 }
00902
00903
00904
00905
00906 void ClusterSequence::add_constituents (
00907 const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
00908
00909 int i = jet.cluster_hist_index();
00910 int parent1 = _history[i].parent1;
00911 int parent2 = _history[i].parent2;
00912
00913 if (parent1 == InexistentParent) {
00914
00915
00916
00917
00918
00919 subjet_vector.push_back(_jets[i]);
00920 return;
00921 }
00922
00923
00924 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
00925
00926
00927 if (parent2 != BeamJet) {
00928 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
00929 }
00930 }
00931
00932
00933
00934
00935
00936 void ClusterSequence::_add_step_to_history (
00937 const int & step_number, const int & parent1,
00938 const int & parent2, const int & jetp_index,
00939 const double & dij) {
00940
00941 history_element element;
00942 element.parent1 = parent1;
00943 element.parent2 = parent2;
00944 element.jetp_index = jetp_index;
00945 element.child = Invalid;
00946 element.dij = dij;
00947 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00948 _history.push_back(element);
00949
00950 int local_step = _history.size()-1;
00951 assert(local_step == step_number);
00952
00953 assert(parent1 >= 0);
00954 _history[parent1].child = local_step;
00955 if (parent2 >= 0) {_history[parent2].child = local_step;}
00956
00957
00958 if (jetp_index != Invalid) {
00959 assert(jetp_index >= 0);
00960
00961 _jets[jetp_index].set_cluster_hist_index(local_step);
00962 }
00963
00964 if (_writeout_combinations) {
00965 cout << local_step << ": "
00966 << parent1 << " with " << parent2
00967 << "; y = "<< dij<<endl;
00968 }
00969
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 vector<int> ClusterSequence::unique_history_order() const {
00981
00982
00983
00984
00985
00986 valarray<int> lowest_constituent(_history.size());
00987 int hist_n = _history.size();
00988 lowest_constituent = hist_n;
00989 for (int i = 0; i < hist_n; i++) {
00990
00991 lowest_constituent[i] = min(lowest_constituent[i],i);
00992
00993 if (_history[i].child > 0) lowest_constituent[_history[i].child]
00994 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00995 }
00996
00997
00998 valarray<bool> extracted(_history.size()); extracted = false;
00999 vector<int> unique_tree;
01000 unique_tree.reserve(_history.size());
01001
01002
01003 for (unsigned i = 0; i < n_particles(); i++) {
01004 if (!extracted[i]) {
01005 unique_tree.push_back(i);
01006 extracted[i] = true;
01007 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
01008 }
01009 }
01010
01011 return unique_tree;
01012 }
01013
01014
01015
01016 void ClusterSequence::_extract_tree_children(
01017 int position,
01018 valarray<bool> & extracted,
01019 const valarray<int> & lowest_constituent,
01020 vector<int> & unique_tree) const {
01021 if (!extracted[position]) {
01022
01023
01024 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
01025 }
01026
01027
01028 int child = _history[position].child;
01029 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
01030 }
01031
01032
01033
01034
01035 vector<PseudoJet> ClusterSequence::unclustered_particles() const {
01036 vector<PseudoJet> unclustered;
01037 for (unsigned i = 0; i < n_particles() ; i++) {
01038 if (_history[i].child == Invalid)
01039 unclustered.push_back(_jets[_history[i].jetp_index]);
01040 }
01041 return unclustered;
01042 }
01043
01044
01045
01046
01047
01048 void ClusterSequence::_extract_tree_parents(
01049 int position,
01050 valarray<bool> & extracted,
01051 const valarray<int> & lowest_constituent,
01052 vector<int> & unique_tree) const {
01053
01054 if (!extracted[position]) {
01055 int parent1 = _history[position].parent1;
01056 int parent2 = _history[position].parent2;
01057
01058
01059 if (parent1 >= 0 && parent2 >= 0) {
01060 if (lowest_constituent[parent1] > lowest_constituent[parent2])
01061 swap(parent1, parent2);
01062 }
01063
01064 if (parent1 >= 0 && !extracted[parent1])
01065 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
01066 if (parent2 >= 0 && !extracted[parent2])
01067 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
01068
01069
01070 unique_tree.push_back(position);
01071 extracted[position] = true;
01072 }
01073 }
01074
01075
01076
01080 void ClusterSequence::_do_ij_recombination_step(
01081 const int & jet_i, const int & jet_j,
01082 const double & dij,
01083 int & newjet_k) {
01084
01085
01086 PseudoJet newjet;
01087 _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
01088 _jets.push_back(newjet);
01089
01090
01091
01092
01093 newjet_k = _jets.size()-1;
01094
01095
01096 int newstep_k = _history.size();
01097
01098 _jets[newjet_k].set_cluster_hist_index(newstep_k);
01099
01100
01101 int hist_i = _jets[jet_i].cluster_hist_index();
01102 int hist_j = _jets[jet_j].cluster_hist_index();
01103
01104 _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
01105 newjet_k, dij);
01106
01107 }
01108
01109
01110
01113 void ClusterSequence::_do_iB_recombination_step(
01114 const int & jet_i, const double & diB) {
01115
01116 int newstep_k = _history.size();
01117
01118
01119 _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
01120 Invalid, diB);
01121
01122 }
01123
01124 FASTJET_END_NAMESPACE
01125