31 #include "fastjet/Error.hh" 32 #include "fastjet/PseudoJet.hh" 33 #include "fastjet/ClusterSequence.hh" 34 #include "fastjet/ClusterSequenceStructure.hh" 35 #include "fastjet/version.hh" 45 FASTJET_BEGIN_NAMESPACE
55 ClusterSequence::~ClusterSequence () {
58 if (_structure_shared_ptr()){
59 ClusterSequenceStructure* csi =
dynamic_cast<ClusterSequenceStructure*
>(_structure_shared_ptr());
65 csi->set_associated_cs(NULL);
73 if (_deletes_self_when_unused) {
74 _structure_shared_ptr.set_count(_structure_shared_ptr.use_count()
75 + _structure_use_count_after_construction);
81 void ClusterSequence::signal_imminent_self_deletion()
const {
95 assert(_deletes_self_when_unused);
96 _deletes_self_when_unused =
false;
100 void ClusterSequence::_initialise_and_run (
102 const Strategy & strategy,
103 const bool & writeout_combinations) {
105 JetDefinition jet_def(_default_jet_algorithm, R, strategy);
106 _initialise_and_run(jet_def, writeout_combinations);
111 void ClusterSequence::_initialise_and_run (
112 const JetDefinition & jet_def,
113 const bool & writeout_combinations) {
116 _decant_options(jet_def, writeout_combinations);
120 _fill_initial_history();
123 if (n_particles() == 0)
return;
126 if (_jet_algorithm == plugin_algorithm) {
128 _plugin_activated =
true;
130 _jet_def.plugin()->run_clustering( (*
this) );
131 _plugin_activated =
false;
132 _update_structure_use_count();
134 }
else if (_jet_algorithm == ee_kt_algorithm ||
135 _jet_algorithm == ee_genkt_algorithm) {
138 if (_jet_algorithm == ee_kt_algorithm) {
142 assert(_Rparam > 2.0);
156 _R2 = 2 * ( 3.0 + cos(_Rparam) );
158 _R2 = 2 * ( 1.0 - cos(_Rparam) );
162 _simple_N2_cluster_EEBriefJet();
164 }
else if (_jet_algorithm == undefined_jet_algorithm) {
165 throw Error(
"A ClusterSequence cannot be created with an uninitialised JetDefinition");
174 if (_strategy == Best) {
175 int N = _jets.size();
176 if (N <= 55*max(0.5,min(1.0,_Rparam))) {
181 }
else if ((N > 16000/pow(_Rparam,1.15) && jet_def.jet_algorithm() !=
antikt_algorithm)
182 || N > 35000/pow(_Rparam,1.15)) {
185 }
else if (N <= 450) {
196 if (_Rparam >= twopi) {
197 if ( _strategy == NlnN
198 || _strategy == NlnN3pi
199 || _strategy == NlnNCam
200 || _strategy == NlnNCam2pi2R
201 || _strategy == NlnNCam4pi) {
208 if (jet_def.strategy() !=
Best && _strategy != jet_def.strategy()) {
210 oss <<
"Cluster strategy " << strategy_string(jet_def.strategy())
211 <<
" automatically changed to " << strategy_string()
212 <<
" because the former is not supported for R = " << _Rparam
214 _changed_strategy_warning.warn(oss.str());
224 if (_strategy == N2Plain) {
226 this->_simple_N2_cluster_BriefJet();
227 }
else if (_strategy == N2Tiled) {
228 this->_faster_tiled_N2_cluster();
229 }
else if (_strategy == N2MinHeapTiled) {
230 this->_minheap_faster_tiled_N2_cluster();
231 }
else if (_strategy == NlnN) {
232 this->_delaunay_cluster();
233 }
else if (_strategy == NlnNCam) {
234 this->_CP2DChan_cluster_2piMultD();
235 }
else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
236 this->_delaunay_cluster();
237 }
else if (_strategy == N3Dumb ) {
238 this->_really_dumb_cluster();
239 }
else if (_strategy == N2PoorTiled) {
240 this->_tiled_N2_cluster();
241 }
else if (_strategy == NlnNCam4pi) {
242 this->_CP2DChan_cluster();
243 }
else if (_strategy == NlnNCam2pi2R) {
244 this->_CP2DChan_cluster_2pi2R();
247 err <<
"Unrecognised value for strategy: "<<_strategy;
248 throw Error(err.str());
255 bool ClusterSequence::_first_time =
true;
256 int ClusterSequence::_n_exclusive_warnings = 0;
262 return "FastJet version "+string(fastjet_version);
268 void ClusterSequence::_print_banner() {
270 if (!_first_time) {
return;}
276 cout <<
"#--------------------------------------------------------------------------\n";
277 cout <<
"# FastJet release " << fastjet_version << endl;
278 cout <<
"# Written by M. Cacciari, G.P. Salam and G. Soyez \n";
279 cout <<
"# http://www.fastjet.fr \n";
281 cout <<
"# Longitudinally invariant Kt, anti-Kt, and inclusive Cambridge/Aachen \n";
282 cout <<
"# clustering using fast geometric algorithms, with jet areas and optional\n";
283 cout <<
"# external jet-finder plugins. If you use this code towards a scientific \n";
284 cout <<
"# publication please cite Phys. Lett. B641 (2006) [hep-ph/0512210] and \n";
285 cout <<
"# M. Cacciari, G.P. Salam and G. Soyez, http://fastjet.fr/ \n";
287 cout <<
"# This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM \n";
288 cout <<
"# Symp. Discr. Alg, p.472 (2002), S.Fortune's Voronoi algorithm and code" ;
290 cout << endl <<
"# and CGAL: http://www.cgal.org/";
293 cout <<
"#-------------------------------------------------------------------------\n";
300 void ClusterSequence::_decant_options(
const JetDefinition & jet_def,
301 const bool & writeout_combinations) {
308 _writeout_combinations = writeout_combinations;
309 _jet_algorithm = jet_def.jet_algorithm();
310 _Rparam = jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
311 _strategy = jet_def.strategy();
314 _plugin_activated =
false;
317 _structure_shared_ptr.reset(
new ClusterSequenceStructure(
this));
318 _update_structure_use_count();
324 void ClusterSequence::_fill_initial_history () {
329 _jets.reserve(_jets.size()*2);
330 _history.reserve(_jets.size()*2);
334 for (
int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
335 history_element element;
336 element.parent1 = InexistentParent;
337 element.parent2 = InexistentParent;
338 element.child = Invalid;
339 element.jetp_index = i;
341 element.max_dij_so_far = 0.0;
343 _history.push_back(element);
346 _jet_def.recombiner()->preprocess(_jets[i]);
349 _jets[i].set_cluster_hist_index(i);
350 _set_structure_shared_ptr(_jets[i]);
353 _Qtot += _jets[i].E();
355 _initial_n = _jets.size();
356 _deletes_self_when_unused =
false;
363 string ClusterSequence::strategy_string (Strategy strategy_in)
const {
365 switch(strategy_in) {
367 strategy =
"NlnN";
break;
369 strategy =
"NlnN3pi";
break;
371 strategy =
"NlnN4pi";
break;
373 strategy =
"N2Plain";
break;
375 strategy =
"N2Tiled";
break;
377 strategy =
"N2MinHeapTiled";
break;
379 strategy =
"N2PoorTiled";
break;
381 strategy =
"N3Dumb";
break;
383 strategy =
"NlnNCam4pi";
break;
385 strategy =
"NlnNCam2pi2R";
break;
387 strategy =
"NlnNCam";
break;
389 strategy =
"plugin strategy";
break;
391 strategy =
"Unrecognized";
397 double ClusterSequence::jet_scale_for_algorithm(
398 const PseudoJet & jet)
const {
399 if (_jet_algorithm == kt_algorithm) {
return jet.kt2();}
400 else if (_jet_algorithm == cambridge_algorithm) {
return 1.0;}
401 else if (_jet_algorithm == antikt_algorithm) {
402 double kt2=jet.kt2();
403 return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
404 }
else if (_jet_algorithm == genkt_algorithm) {
405 double kt2 = jet.kt2();
406 double p = jet_def().extra_param();
407 if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300;
409 }
else if (_jet_algorithm == cambridge_for_passive_algorithm) {
410 double kt2 = jet.kt2();
411 double lim = _jet_def.extra_param();
412 if (kt2 < lim*lim && kt2 != 0.0) {
415 }
else {
throw Error(
"Unrecognised jet algorithm");}
423 void ClusterSequence::transfer_from_sequence(ClusterSequence & from_seq) {
425 if (will_delete_self_when_unused())
426 throw(Error(
"cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
429 _jet_def = from_seq._jet_def ;
430 _writeout_combinations = from_seq._writeout_combinations ;
431 _initial_n = from_seq._initial_n ;
432 _Rparam = from_seq._Rparam ;
434 _invR2 = from_seq._invR2 ;
435 _strategy = from_seq._strategy ;
436 _jet_algorithm = from_seq._jet_algorithm ;
437 _plugin_activated = from_seq._plugin_activated ;
440 _jets = from_seq._jets;
441 _history = from_seq._history;
443 _extras = from_seq._extras;
446 if (_structure_shared_ptr()) {
449 ClusterSequenceStructure* csi =
dynamic_cast<ClusterSequenceStructure*
>(_structure_shared_ptr());
451 csi->set_associated_cs(NULL);
455 _structure_shared_ptr.reset(
new ClusterSequenceStructure(
this));
456 _update_structure_use_count();
458 for (vector<PseudoJet>::iterator jit = _jets.begin(); jit != _jets.end(); jit++)
459 _set_structure_shared_ptr(*jit);
473 void ClusterSequence::transfer_from_sequence(ClusterSequence & from_seq,
474 const FunctionOfPseudoJet<PseudoJet> &action_on_jets){
476 transfer_from_sequence(from_seq);
479 for (vector<PseudoJet>::iterator jit = _jets.begin(); jit != _jets.end(); jit++)
480 *jit = action_on_jets(*jit);
487 void ClusterSequence::plugin_record_ij_recombination(
488 int jet_i,
int jet_j,
double dij,
489 const PseudoJet & newjet,
int & newjet_k) {
491 plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
494 int tmp_index = _jets[newjet_k].cluster_hist_index();
495 _jets[newjet_k] = newjet;
496 _jets[newjet_k].set_cluster_hist_index(tmp_index);
497 _set_structure_shared_ptr(_jets[newjet_k]);
503 vector<PseudoJet> ClusterSequence::inclusive_jets (
const double & ptmin)
const{
504 double dcut = ptmin*ptmin;
505 int i = _history.size() - 1;
506 vector<PseudoJet> jets;
507 if (_jet_algorithm == kt_algorithm) {
512 if (_history[i].max_dij_so_far < dcut) {
break;}
513 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
515 int parent1 = _history[i].parent1;
516 jets.push_back(_jets[_history[parent1].jetp_index]);}
519 }
else if (_jet_algorithm == cambridge_algorithm) {
524 if (_history[i].parent2 != BeamJet) {
break;}
525 int parent1 = _history[i].parent1;
526 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
527 if (jet.perp2() >= dcut) {jets.push_back(jet);}
530 }
else if (_jet_algorithm == plugin_algorithm
531 || _jet_algorithm == ee_kt_algorithm
532 || _jet_algorithm == antikt_algorithm
533 || _jet_algorithm == genkt_algorithm
534 || _jet_algorithm == ee_genkt_algorithm
535 || _jet_algorithm == cambridge_for_passive_algorithm) {
540 if (_history[i].parent2 == BeamJet) {
541 int parent1 = _history[i].parent1;
542 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
543 if (jet.perp2() >= dcut) {jets.push_back(jet);}
547 }
else {
throw Error(
"cs::inclusive_jets(...): Unrecognized jet algorithm");}
555 int ClusterSequence::n_exclusive_jets (
const double & dcut)
const {
559 int i = _history.size() - 1;
561 if (_history[i].max_dij_so_far <= dcut) {
break;}
564 int stop_point = i + 1;
567 int njets = 2*_initial_n - stop_point;
574 vector<PseudoJet> ClusterSequence::exclusive_jets (
const double & dcut)
const {
575 int njets = n_exclusive_jets(dcut);
576 return exclusive_jets(njets);
582 vector<PseudoJet> ClusterSequence::exclusive_jets (
const int & njets)
const {
586 assert (njets <= _initial_n);
598 (_jet_def.extra_param() <0)) &&
600 (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
601 (_n_exclusive_warnings < 5)) {
602 _n_exclusive_warnings++;
603 cerr <<
"FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
610 int stop_point = 2*_initial_n - njets;
614 if (2*_initial_n != static_cast<int>(_history.size())) {
616 err <<
"2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
617 throw Error(err.str());
626 vector<PseudoJet> jets;
627 for (
unsigned int i = stop_point; i < _history.size(); i++) {
628 int parent1 = _history[i].parent1;
629 if (parent1 < stop_point) {
630 jets.push_back(_jets[_history[parent1].jetp_index]);
632 int parent2 = _history[i].parent2;
633 if (parent2 < stop_point && parent2 > 0) {
634 jets.push_back(_jets[_history[parent2].jetp_index]);
640 if (static_cast<int>(jets.size()) != njets) {
642 err <<
"ClusterSequence::exclusive_jets: size of returned vector (" 643 <<jets.size()<<
") does not coincide with requested number of jets (" 645 throw Error(err.str());
654 double ClusterSequence::exclusive_dmerge (
const int & njets)
const {
656 if (njets >= _initial_n) {
return 0.0;}
657 return _history[2*_initial_n-njets-1].dij;
666 double ClusterSequence::exclusive_dmerge_max (
const int & njets)
const {
668 if (njets >= _initial_n) {
return 0.0;}
669 return _history[2*_initial_n-njets-1].max_dij_so_far;
677 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
678 (
const PseudoJet & jet,
const double & dcut)
const {
680 set<const history_element*> subhist;
684 get_subhist_set(subhist, jet, dcut, 0);
687 vector<PseudoJet> subjets;
688 subjets.reserve(subhist.size());
689 for (set<const history_element*>::iterator elem = subhist.begin();
690 elem != subhist.end(); elem++) {
691 subjets.push_back(_jets[(*elem)->jetp_index]);
700 int ClusterSequence::n_exclusive_subjets(
const PseudoJet & jet,
701 const double & dcut)
const {
702 set<const history_element*> subhist;
705 get_subhist_set(subhist, jet, dcut, 0);
706 return subhist.size();
713 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
714 (
const PseudoJet & jet,
int n)
const {
716 set<const history_element*> subhist;
720 get_subhist_set(subhist, jet, -1.0, n);
723 vector<PseudoJet> subjets;
724 subjets.reserve(subhist.size());
725 for (set<const history_element*>::iterator elem = subhist.begin();
726 elem != subhist.end(); elem++) {
727 subjets.push_back(_jets[(*elem)->jetp_index]);
738 double ClusterSequence::exclusive_subdmerge(
const PseudoJet & jet,
int nsub)
const {
739 set<const history_element*> subhist;
743 get_subhist_set(subhist, jet, -1.0, nsub);
745 set<const history_element*>::iterator highest = subhist.end();
749 return (*highest)->dij;
759 double ClusterSequence::exclusive_subdmerge_max(
const PseudoJet & jet,
int nsub)
const {
761 set<const history_element*> subhist;
765 get_subhist_set(subhist, jet, -1.0, nsub);
767 set<const history_element*>::iterator highest = subhist.end();
771 return (*highest)->max_dij_so_far;
783 void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
784 const PseudoJet & jet,
785 double dcut,
int maxjet)
const {
786 assert(contains(jet));
789 subhist.insert(&(_history[jet.cluster_hist_index()]));
796 set<const history_element*>::iterator highest = subhist.end();
797 assert (highest != subhist.begin());
799 const history_element* elem = *highest;
801 if (njet == maxjet)
break;
803 if (elem->parent1 < 0)
break;
805 if (elem->max_dij_so_far <= dcut)
break;
808 subhist.erase(highest);
809 subhist.insert(&(_history[elem->parent1]));
810 subhist.insert(&(_history[elem->parent2]));
817 bool ClusterSequence::object_in_jet(
const PseudoJet &
object,
818 const PseudoJet & jet)
const {
822 assert(contains(
object) && contains(jet));
824 const PseudoJet * this_object = &object;
825 const PseudoJet * childp;
827 if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
829 }
else if (has_child(*this_object, childp)) {
830 this_object = childp;
843 bool ClusterSequence::has_parents(
const PseudoJet & jet, PseudoJet & parent1,
844 PseudoJet & parent2)
const {
846 const history_element & hist = _history[jet.cluster_hist_index()];
850 assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
851 (hist.parent1 < 0 && hist.parent2 < 0));
853 if (hist.parent1 < 0) {
854 parent1 = PseudoJet(0.0,0.0,0.0,0.0);
858 parent1 = _jets[_history[hist.parent1].jetp_index];
859 parent2 = _jets[_history[hist.parent2].jetp_index];
861 if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
869 bool ClusterSequence::has_child(
const PseudoJet & jet, PseudoJet & child)
const {
880 const PseudoJet * childp;
881 bool res = has_child(jet, childp);
886 child = PseudoJet(0.0,0.0,0.0,0.0);
891 bool ClusterSequence::has_child(
const PseudoJet & jet,
const PseudoJet * & childp)
const {
893 const history_element & hist = _history[jet.cluster_hist_index()];
898 if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
899 childp = &(_jets[_history[hist.child].jetp_index]);
912 bool ClusterSequence::has_partner(
const PseudoJet & jet,
913 PseudoJet & partner)
const {
915 const history_element & hist = _history[jet.cluster_hist_index()];
919 if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
920 const history_element & child_hist = _history[hist.child];
921 if (child_hist.parent1 == jet.cluster_hist_index()) {
924 partner = _jets[_history[child_hist.parent2].jetp_index];
927 partner = _jets[_history[child_hist.parent1].jetp_index];
931 partner = PseudoJet(0.0,0.0,0.0,0.0);
939 vector<PseudoJet> ClusterSequence::constituents (
const PseudoJet & jet)
const {
940 vector<PseudoJet> subjets;
941 add_constituents(jet, subjets);
954 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets,
955 ostream & ostr)
const {
956 for (
unsigned i = 0; i < jets.size(); i++) {
958 << jets[i].px() <<
" " 959 << jets[i].py() <<
" " 960 << jets[i].pz() <<
" " 961 << jets[i].E() << endl;
962 vector<PseudoJet> cst = constituents(jets[i]);
963 for (
unsigned j = 0; j < cst.size() ; j++) {
964 ostr <<
" " << j <<
" " 965 << cst[j].rap() <<
" " 966 << cst[j].phi() <<
" " 967 << cst[j].perp() << endl;
969 ostr <<
"#END" << endl;
973 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets,
974 const std::string & filename,
975 const std::string & comment )
const {
976 std::ofstream ostr(filename.c_str());
977 if (comment !=
"") ostr <<
"# " << comment << endl;
978 print_jets_for_root(jets, ostr);
999 vector<int> ClusterSequence::particle_jet_indices(
1000 const vector<PseudoJet> & jets)
const {
1002 vector<int> indices(n_particles());
1005 for (
unsigned ipart = 0; ipart < n_particles(); ipart++)
1006 indices[ipart] = -1;
1010 for (
unsigned ijet = 0; ijet < jets.size(); ijet++) {
1012 vector<PseudoJet> jet_constituents(constituents(jets[ijet]));
1014 for (
unsigned ip = 0; ip < jet_constituents.size(); ip++) {
1018 unsigned iclust = jet_constituents[ip].cluster_hist_index();
1019 unsigned ipart = history()[iclust].jetp_index;
1020 indices[ipart] = ijet;
1030 void ClusterSequence::add_constituents (
1031 const PseudoJet & jet, vector<PseudoJet> & subjet_vector)
const {
1033 int i = jet.cluster_hist_index();
1034 int parent1 = _history[i].parent1;
1035 int parent2 = _history[i].parent2;
1037 if (parent1 == InexistentParent) {
1043 subjet_vector.push_back(_jets[i]);
1048 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
1051 if (parent2 != BeamJet) {
1052 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
1060 void ClusterSequence::_add_step_to_history (
1061 const int & step_number,
const int & parent1,
1062 const int & parent2,
const int & jetp_index,
1063 const double & dij) {
1065 history_element element;
1066 element.parent1 = parent1;
1067 element.parent2 = parent2;
1068 element.jetp_index = jetp_index;
1069 element.child = Invalid;
1071 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
1072 _history.push_back(element);
1074 int local_step = _history.size()-1;
1075 assert(local_step == step_number);
1077 assert(parent1 >= 0);
1078 _history[parent1].child = local_step;
1079 if (parent2 >= 0) {_history[parent2].child = local_step;}
1082 if (jetp_index != Invalid) {
1083 assert(jetp_index >= 0);
1085 _jets[jetp_index].set_cluster_hist_index(local_step);
1086 _set_structure_shared_ptr(_jets[jetp_index]);
1089 if (_writeout_combinations) {
1090 cout << local_step <<
": " 1091 << parent1 <<
" with " << parent2
1092 <<
"; y = "<< dij<<endl;
1105 vector<int> ClusterSequence::unique_history_order()
const {
1111 valarray<int> lowest_constituent(_history.size());
1112 int hist_n = _history.size();
1113 lowest_constituent = hist_n;
1114 for (
int i = 0; i < hist_n; i++) {
1116 lowest_constituent[i] = min(lowest_constituent[i],i);
1118 if (_history[i].child > 0) lowest_constituent[_history[i].child]
1119 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
1123 valarray<bool> extracted(_history.size()); extracted =
false;
1124 vector<int> unique_tree;
1125 unique_tree.reserve(_history.size());
1128 for (
unsigned i = 0; i < n_particles(); i++) {
1129 if (!extracted[i]) {
1130 unique_tree.push_back(i);
1131 extracted[i] =
true;
1132 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
1141 void ClusterSequence::_extract_tree_children(
1143 valarray<bool> & extracted,
1144 const valarray<int> & lowest_constituent,
1145 vector<int> & unique_tree)
const {
1146 if (!extracted[position]) {
1149 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
1153 int child = _history[position].child;
1154 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
1160 vector<PseudoJet> ClusterSequence::unclustered_particles()
const {
1161 vector<PseudoJet> unclustered;
1162 for (
unsigned i = 0; i < n_particles() ; i++) {
1163 if (_history[i].child == Invalid)
1164 unclustered.push_back(_jets[_history[i].jetp_index]);
1175 bool ClusterSequence::contains(
const PseudoJet & jet)
const {
1176 return jet.cluster_hist_index() >= 0
1177 && jet.cluster_hist_index() < int(_history.size())
1178 && jet.structure_shared_ptr() == structure_shared_ptr();
1185 void ClusterSequence::_extract_tree_parents(
1187 valarray<bool> & extracted,
1188 const valarray<int> & lowest_constituent,
1189 vector<int> & unique_tree)
const {
1191 if (!extracted[position]) {
1192 int parent1 = _history[position].parent1;
1193 int parent2 = _history[position].parent2;
1196 if (parent1 >= 0 && parent2 >= 0) {
1197 if (lowest_constituent[parent1] > lowest_constituent[parent2])
1198 std::swap(parent1, parent2);
1201 if (parent1 >= 0 && !extracted[parent1])
1202 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
1203 if (parent2 >= 0 && !extracted[parent2])
1204 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
1207 unique_tree.push_back(position);
1208 extracted[position] =
true;
1217 void ClusterSequence::_do_ij_recombination_step(
1218 const int & jet_i,
const int & jet_j,
1224 _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
1225 _jets.push_back(newjet);
1230 newjet_k = _jets.size()-1;
1233 int newstep_k = _history.size();
1235 _jets[newjet_k].set_cluster_hist_index(newstep_k);
1238 int hist_i = _jets[jet_i].cluster_hist_index();
1239 int hist_j = _jets[jet_j].cluster_hist_index();
1241 _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
1250 void ClusterSequence::_do_iB_recombination_step(
1251 const int & jet_i,
const double & diB) {
1253 int newstep_k = _history.size();
1256 _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
1267 void ClusterSequence::boost(
const PseudoJet & prest){
1269 for (vector<PseudoJet>::iterator jit=_jets.begin(); jit!=_jets.end(); jit++)
1275 void ClusterSequence::unboost(
const PseudoJet & prest){
1277 for (vector<PseudoJet>::iterator jit=_jets.begin(); jit!=_jets.end(); jit++)
1278 jit->unboost(prest);
1283 LimitedWarning ClusterSequence::_changed_strategy_warning;
1287 void ClusterSequence::_set_structure_shared_ptr(PseudoJet & j) {
1288 j.set_structure_shared_ptr(_structure_shared_ptr);
1291 _update_structure_use_count();
1296 void ClusterSequence::_update_structure_use_count() {
1299 _structure_use_count_after_construction = _structure_shared_ptr.use_count();
1306 void ClusterSequence::delete_self_when_unused() {
1314 int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
1315 if (new_count <= 0) {
1316 throw Error(
"delete_self_when_unused may only be called if at least one object outside the CS (e.g. a jet) is already associated with the CS");
1319 _structure_shared_ptr.set_count(new_count);
1320 _deletes_self_when_unused =
true;
1324 FASTJET_END_NAMESPACE
like the k_t but with distance measures dij = min(kti^{2p},ktj^{2p}) Delta R_{ij}^2 / R^2 diB = 1/kti...
Chan's closest pair method (in a variant with 4pi coverage), for use exclusively with the Cambridge a...
best of the NlnN variants – best overall for N>10^4.
legacy N ln N using 4pi coverage of cylinder
the e+e- genkt algorithm (R > 2 and p=1 gives ee_kt)
fastest from about 50..500
the longitudinally invariant kt algorithm
Chan's closest pair method (in a variant with 2pi+minimal extra variant), for use exclusively with th...
any plugin algorithm supplied by the user
the plugin has been used...
worse even than the usual N^3 algorithms
string fastjet_version_string()
return a string containing information about the release
automatic selection of the best (based on N), including the LazyTiled strategies that are new to FJ3...
like the k_t but with distance measures dij = min(1/kti^2,1/ktj^2) Delta R_{ij}^2 / R^2 diB = 1/kti^2...
the longitudinally invariant variant of the cambridge algorithm (aka Aachen algoithm).
JetAlgorithm
the various families of jet-clustering algorithm
legacy N ln N using 3pi coverage of cylinder.
faster that N2Tiled above about 500 particles; differs from it by retainig the di(closest j) distance...
Chan's closest pair method (in a variant with 2pi+2R coverage), for use exclusively with the Cambridg...