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
00032
00033
00034
00035
00044
00045
00046 #ifndef __FASTJET_CLUSTERSEQUENCE_HH__
00047 #define __FASTJET_CLUSTERSEQUENCE_HH__
00048
00049 #include<vector>
00050 #include<map>
00051 #include "fastjet/internal/DynamicNearestNeighbours.hh"
00052 #include "fastjet/PseudoJet.hh"
00053 #include<cassert>
00054 #include<iostream>
00055 #include<string>
00056 #include<cmath>
00057 #include "fastjet/Error.hh"
00058 #include "fastjet/JetDefinition.hh"
00059
00060 FASTJET_BEGIN_NAMESPACE
00061
00062
00064 class ClusterSequence {
00065
00066
00067 public:
00068
00070 ClusterSequence () {};
00071
00081 template<class L> ClusterSequence (const std::vector<L> & pseudojets,
00082 const double & R = 1.0,
00083 const Strategy & strategy = Best,
00084 const bool & writeout_combinations = false);
00085
00086
00090 template<class L> ClusterSequence (
00091 const std::vector<L> & pseudojets,
00092 const JetDefinition & jet_def,
00093 const bool & writeout_combinations = false);
00094
00095
00096
00097
00098
00099
00103 std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) const;
00104
00108 int n_exclusive_jets (const double & dcut) const;
00109
00113 std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
00114
00117 std::vector<PseudoJet> exclusive_jets (const int & njets) const;
00118
00121 double exclusive_dmerge (const int & njets) const;
00122
00127 double exclusive_dmerge_max (const int & njets) const;
00128
00130 std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
00132 void add_constituents (const PseudoJet & jet,
00133 std::vector<PseudoJet> & subjet_vector) const;
00134
00136 inline Strategy strategy_used () const {return _strategy;};
00137 std::string strategy_string () const;
00138
00139
00143 double jet_scale_for_algorithm(const PseudoJet & jet) const;
00144
00145
00146
00147
00148
00149 public:
00152 static void set_jet_finder (JetFinder jet_finder) {_default_jet_finder = jet_finder;};
00153
00154
00157 struct history_element{
00158 int parent1;
00159
00160
00161
00162 int parent2;
00163
00164
00165
00166
00167
00168 int child;
00169
00170
00171
00172
00173 int jetp_index;
00174
00175
00176
00177
00178
00179
00180 double dij;
00181
00182
00183 double max_dij_so_far;
00184
00185 };
00186
00187 enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
00188
00194 const std::vector<PseudoJet> & jets() const;
00195
00198 const std::vector<history_element> & history() const;
00199
00204 unsigned int n_particles() const;
00205
00206
00222 std::vector<int> unique_history_order() const;
00223
00224
00225 protected:
00226 static JetFinder _default_jet_finder;
00227 JetDefinition _jet_def;
00228
00231 template<class L> void _transfer_input_jets(
00232 const std::vector<L> & pseudojets);
00233
00237 void _initialise_and_run (const JetDefinition & jet_def,
00238 const bool & writeout_combinations);
00239
00243 void _initialise_and_run (const double & R,
00244 const Strategy & strategy,
00245 const bool & writeout_combinations);
00246
00249 void _decant_options(const JetDefinition & jet_def,
00250 const bool & writeout_combinations);
00251
00255 void _fill_initial_history();
00256
00260 void _do_ij_recombination_step(const int & jet_i, const int & jet_j,
00261 const double & dij, int & newjet_k);
00262
00265 void _do_iB_recombination_step(const int & jet_i, const double & diB);
00266
00267
00271 std::vector<PseudoJet> _jets;
00272
00273
00277 std::vector<history_element> _history;
00278
00279 bool _writeout_combinations;
00280 int _initial_n;
00281 double _Rparam, _R2, _invR2;
00282 Strategy _strategy;
00283 JetFinder _jet_finder;
00284
00285 private:
00286
00287
00288 void _really_dumb_cluster ();
00289 void _delaunay_cluster ();
00290 void _simple_N2_cluster ();
00291 void _tiled_N2_cluster ();
00292 void _faster_tiled_N2_cluster ();
00293
00294
00295 void _minheap_faster_tiled_N2_cluster();
00296
00297
00298
00299 void _CP2DChan_cluster();
00300 void _CP2DChan_cluster_2pi2R ();
00301 void _CP2DChan_cluster_2piMultD ();
00302 void _CP2DChan_limited_cluster(double D);
00303 void _do_Cambridge_inclusive_jets();
00304
00305 void _add_step_to_history(const int & step_number, const int & parent1,
00306 const int & parent2, const int & jetp_index,
00307 const double & dij);
00308
00311 void _extract_tree_children(int pos, std::valarray<bool> &,
00312 const std::valarray<int> &, std::vector<int> &) const;
00313
00316 void _extract_tree_parents (int pos, std::valarray<bool> &,
00317 const std::valarray<int> &, std::vector<int> &) const;
00318
00319
00320
00321 typedef std::pair<int,int> TwoVertices;
00322 typedef std::pair<double,TwoVertices> DijEntry;
00323 typedef std::multimap<double,TwoVertices> DistMap;
00324
00326 void _add_ktdistance_to_map(const int & ii,
00327 DistMap & DijMap,
00328 const DynamicNearestNeighbours * DNN);
00329
00331 void _print_banner();
00333 static bool _first_time;
00334
00335
00336
00341 struct BriefJet {
00342 double eta, phi, kt2, NN_dist;
00343 BriefJet * NN;
00344 int _jets_index;
00345 };
00348 class TiledJet {
00349 public:
00350 double eta, phi, kt2, NN_dist;
00351 TiledJet * NN, *previous, * next;
00352 int _jets_index, tile_index, diJ_posn;
00353
00354
00355
00356
00357 inline void label_minheap_update_needed() {diJ_posn = 1;};
00358 inline void label_minheap_update_done() {diJ_posn = 0;};
00359 inline bool minheap_update_needed() const {return diJ_posn==1;};
00360 };
00361
00362
00363
00364
00367 template <class J> void _bj_set_jetinfo( J * const jet,
00368 const int _jets_index) const;
00369
00372 void _bj_remove_from_tiles( TiledJet * const jet) const;
00373
00375 template <class J> double _bj_dist(const J * const jeta,
00376 const J * const jetb) const;
00377
00378
00379
00380 template <class J> double _bj_diJ(const J * const jeta) const;
00381
00385 template <class J> inline J * _bj_of_hindex(
00386 const int hist_index,
00387 J * const head, J * const tail)
00388 const {
00389 J * res;
00390 for(res = head; res<tail; res++) {
00391 if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00392 }
00393 return res;
00394 };
00395
00396
00397
00398
00399
00404 template <class J> void _bj_set_NN_nocross(J * const jeta,
00405 J * const head, const J * const tail) const;
00406
00411 template <class J> void _bj_set_NN_crosscheck(J * const jeta,
00412 J * const head, const J * const tail) const;
00413
00414
00415
00418 static const int n_tile_neighbours = 9;
00419
00422 struct Tile {
00424 Tile * begin_tiles[n_tile_neighbours];
00426 Tile ** surrounding_tiles;
00428 Tile ** RH_tiles;
00430 Tile ** end_tiles;
00432 TiledJet * head;
00434 bool tagged;
00435 };
00436 std::vector<Tile> _tiles;
00437 double _tiles_eta_min, _tiles_eta_max;
00438 double _tile_size_eta, _tile_size_phi;
00439 int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
00440
00441
00442
00443 inline int _tile_index (int ieta, int iphi) const {
00444
00445
00446 return (ieta-_tiles_ieta_min)*_n_tiles_phi
00447 + (iphi+_n_tiles_phi) % _n_tiles_phi;
00448 }
00449
00450
00451
00452 int _tile_index(const double & eta, const double & phi) const;
00453 void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
00454 void _bj_remove_from_tiles(TiledJet * const jet);
00455 void _initialise_tiles();
00456 void _print_tiles(TiledJet * briefjets ) const;
00457 void _add_neighbours_to_tile_union(const int tile_index,
00458 std::vector<int> & tile_union, int & n_near_tiles) const;
00459 void _add_untagged_neighbours_to_tile_union(const int tile_index,
00460 std::vector<int> & tile_union, int & n_near_tiles);
00461
00462
00463 };
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 template<class L> void ClusterSequence::_transfer_input_jets(
00475 const std::vector<L> & pseudojets) {
00476
00477
00478
00479 _jets.reserve(pseudojets.size()*2);
00480
00481
00482
00483
00484
00485 for (unsigned int i = 0; i < pseudojets.size(); i++) {
00486 _jets.push_back(pseudojets[i]);}
00487
00488 }
00489
00490
00491
00492
00493 template<class L> ClusterSequence::ClusterSequence (
00494 const std::vector<L> & pseudojets,
00495 const double & R,
00496 const Strategy & strategy,
00497 const bool & writeout_combinations) {
00498
00499
00500 _transfer_input_jets(pseudojets);
00501
00502
00503 _initialise_and_run(R,strategy,writeout_combinations);
00504 }
00505
00506
00507
00510 template<class L> ClusterSequence::ClusterSequence (
00511 const std::vector<L> & pseudojets,
00512 const JetDefinition & jet_def,
00513 const bool & writeout_combinations) {
00514
00515
00516 _transfer_input_jets(pseudojets);
00517
00518
00519 _initialise_and_run(jet_def,writeout_combinations);
00520 }
00521
00522
00523 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
00524 return _jets;
00525 }
00526
00527 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
00528 return _history;
00529 }
00530
00531 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
00532
00533
00534
00535 inline double ClusterSequence::jet_scale_for_algorithm(
00536 const PseudoJet & jet) const {
00537 if (_jet_finder == kt_algorithm) {return jet.kt2();}
00538 else if (_jet_finder == cambridge_algorithm) {return 1.0;}
00539 else {throw Error("Unrecognised jet finder");}
00540 }
00541
00542
00543
00544 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
00545 J * const jetA, const int _jets_index) const {
00546 jetA->eta = _jets[_jets_index].rap();
00547 jetA->phi = _jets[_jets_index].phi_02pi();
00548 jetA->kt2 = jet_scale_for_algorithm(_jets[_jets_index]);
00549 jetA->_jets_index = _jets_index;
00550
00551 jetA->NN_dist = _R2;
00552 jetA->NN = NULL;
00553 }
00554
00555
00556
00557
00558
00559 template <class J> inline double ClusterSequence::_bj_dist(
00560 const J * const jetA, const J * const jetB) const {
00561 double dphi = std::abs(jetA->phi - jetB->phi);
00562 double deta = (jetA->eta - jetB->eta);
00563 if (dphi > pi) {dphi = twopi - dphi;}
00564 return dphi*dphi + deta*deta;
00565 }
00566
00567
00568 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
00569 double kt2 = jet->kt2;
00570 if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00571 return jet->NN_dist * kt2;
00572 }
00573
00574
00575
00576
00577
00578 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
00579 J * const jet, J * const head, const J * const tail) const {
00580 double NN_dist = _R2;
00581 J * NN = NULL;
00582 if (head < jet) {
00583 for (J * jetB = head; jetB != jet; jetB++) {
00584 double dist = _bj_dist(jet,jetB);
00585 if (dist < NN_dist) {
00586 NN_dist = dist;
00587 NN = jetB;
00588 }
00589 }
00590 }
00591 if (tail > jet) {
00592 for (J * jetB = jet+1; jetB != tail; jetB++) {
00593 double dist = _bj_dist(jet,jetB);
00594 if (dist < NN_dist) {
00595 NN_dist = dist;
00596 NN = jetB;
00597 }
00598 }
00599 }
00600 jet->NN = NN;
00601 jet->NN_dist = NN_dist;
00602 }
00603
00604
00605
00606 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet,
00607 J * const head, const J * const tail) const {
00608 double NN_dist = _R2;
00609 J * NN = NULL;
00610 for (J * jetB = head; jetB != tail; jetB++) {
00611 double dist = _bj_dist(jet,jetB);
00612 if (dist < NN_dist) {
00613 NN_dist = dist;
00614 NN = jetB;
00615 }
00616 if (dist < jetB->NN_dist) {
00617 jetB->NN_dist = dist;
00618 jetB->NN = jet;
00619 }
00620 }
00621 jet->NN = NN;
00622 jet->NN_dist = NN_dist;
00623 }
00624
00625
00626
00627
00628 FASTJET_END_NAMESPACE
00629
00630 #endif // __FASTJET_CLUSTERSEQUENCE_HH__