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