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 #ifndef __FASTJET_CLUSTERSEQUENCE_HH__
00033 #define __FASTJET_CLUSTERSEQUENCE_HH__
00034
00035 #include<vector>
00036 #include<map>
00037 #include "fastjet/internal/DynamicNearestNeighbours.hh"
00038 #include "fastjet/PseudoJet.hh"
00039 #include<memory>
00040 #include<cassert>
00041 #include<iostream>
00042 #include<string>
00043 #include<set>
00044 #include<cmath>
00045 #include "fastjet/Error.hh"
00046 #include "fastjet/JetDefinition.hh"
00047 #include "fastjet/SharedPtr.hh"
00048 #include "fastjet/internal/LimitedWarning.hh"
00049
00050
00051 FASTJET_BEGIN_NAMESPACE
00052
00053
00054
00055
00056
00057
00058
00103
00104
00105
00106
00107
00111 class ClusterSequence {
00112
00113
00114 public:
00115
00117 ClusterSequence () {}
00118
00128 template<class L> ClusterSequence (const std::vector<L> & pseudojets,
00129 const double & R = 1.0,
00130 const Strategy & strategy = Best,
00131 const bool & writeout_combinations = false);
00132
00133
00137 template<class L> ClusterSequence (
00138 const std::vector<L> & pseudojets,
00139 const JetDefinition & jet_def,
00140 const bool & writeout_combinations = false);
00141
00142
00143
00144 virtual ~ClusterSequence ();
00145
00146
00147
00148
00149
00153 std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) const;
00154
00158 int n_exclusive_jets (const double & dcut) const;
00159
00163 std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
00164
00167 std::vector<PseudoJet> exclusive_jets (const int & njets) const;
00168
00171 double exclusive_dmerge (const int & njets) const;
00172
00177 double exclusive_dmerge_max (const int & njets) const;
00178
00181 double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
00182
00184 double exclusive_ymerge_max (int njets) const {return exclusive_dmerge_max(njets)/Q2();}
00185
00187 int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
00188
00190 std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
00191 int njets = n_exclusive_jets_ycut(ycut);
00192 return exclusive_jets(njets);
00193 }
00194
00195
00196
00197
00206 std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet,
00207 const double & dcut) const;
00208
00212 int n_exclusive_subjets(const PseudoJet & jet,
00213 const double & dcut) const;
00214
00220 std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet,
00221 int nsub) const;
00222
00225 double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
00226
00230 double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
00231
00232
00233
00234
00235
00237 double Q() const {return _Qtot;}
00239 double Q2() const {return _Qtot*_Qtot;}
00240
00251 bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
00252
00258 bool has_parents(const PseudoJet & jet, PseudoJet & parent1,
00259 PseudoJet & parent2) const;
00260
00263 bool has_child(const PseudoJet & jet, PseudoJet & child) const;
00264
00267 bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
00268
00272 bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
00273
00274
00276 std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
00277
00278
00287 void print_jets_for_root(const std::vector<PseudoJet> & jets,
00288 std::ostream & ostr = std::cout) const;
00289
00292 void print_jets_for_root(const std::vector<PseudoJet> & jets,
00293 const std::string & filename,
00294 const std::string & comment = "") const;
00295
00296
00297
00298
00299
00301 void add_constituents (const PseudoJet & jet,
00302 std::vector<PseudoJet> & subjet_vector) const;
00303
00305 inline Strategy strategy_used () const {return _strategy;}
00306
00308 std::string strategy_string () const {return strategy_string(_strategy);}
00309
00311 std::string strategy_string (Strategy strategy_in) const;
00312
00313
00315 const JetDefinition & jet_def() const {return _jet_def;}
00316
00320 double jet_scale_for_algorithm(const PseudoJet & jet) const;
00321
00322
00323
00324
00330 void plugin_record_ij_recombination(int jet_i, int jet_j, double dij,
00331 int & newjet_k) {
00332 assert(plugin_activated());
00333 _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
00334 }
00335
00339 void plugin_record_ij_recombination(int jet_i, int jet_j, double dij,
00340 const PseudoJet & newjet,
00341 int & newjet_k);
00342
00347 void plugin_record_iB_recombination(int jet_i, double diB) {
00348 assert(plugin_activated());
00349 _do_iB_recombination_step(jet_i, diB);
00350 }
00351
00359 class Extras {
00360 public:
00361 virtual ~Extras() {}
00362 virtual std::string description() const {return "This is a dummy extras class that contains no extra information! Derive from it if you want to use it to provide extra information from a plugin jet finder";}
00363 };
00364
00367 inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in) {
00368 _extras = extras_in;
00369 }
00370
00372 inline bool plugin_activated() const {return _plugin_activated;}
00373
00375 const Extras * extras() const {return _extras.get();}
00376
00384 template<class GBJ> void plugin_simple_N2_cluster () {
00385 assert(plugin_activated());
00386 _simple_N2_cluster<GBJ>();
00387 }
00388
00389
00390 public:
00394 static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
00396 static void set_jet_finder (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
00397
00398
00404 struct history_element{
00405 int parent1;
00406
00407
00408
00409 int parent2;
00410
00411
00412
00413
00414
00415 int child;
00416
00417
00418
00419
00420 int jetp_index;
00421
00422
00423
00424
00425
00426
00427 double dij;
00428
00429
00430 double max_dij_so_far;
00431
00432 };
00433
00434 enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
00435
00452 const std::vector<PseudoJet> & jets() const;
00453
00465 const std::vector<history_element> & history() const;
00466
00471 unsigned int n_particles() const;
00472
00477 std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
00478
00494 std::vector<int> unique_history_order() const;
00495
00499 std::vector<PseudoJet> unclustered_particles() const;
00500
00508 void transfer_from_sequence(ClusterSequence & from_seq, bool transfer_ownership=true);
00509
00510
00511 protected:
00512 static JetAlgorithm _default_jet_algorithm;
00513 JetDefinition _jet_def;
00514
00517 bool _potentially_valid(const PseudoJet & jet) const {
00518 return jet.cluster_hist_index() >= 0
00519 && jet.cluster_hist_index() < int(_history.size());
00520 }
00521
00524 template<class L> void _transfer_input_jets(
00525 const std::vector<L> & pseudojets);
00526
00530 void _initialise_and_run (const JetDefinition & jet_def,
00531 const bool & writeout_combinations);
00532
00536 void _initialise_and_run (const double & R,
00537 const Strategy & strategy,
00538 const bool & writeout_combinations);
00539
00542 void _decant_options(const JetDefinition & jet_def,
00543 const bool & writeout_combinations);
00544
00548 void _fill_initial_history();
00549
00553 void _do_ij_recombination_step(const int & jet_i, const int & jet_j,
00554 const double & dij, int & newjet_k);
00555
00558 void _do_iB_recombination_step(const int & jet_i, const double & diB);
00559
00560
00564 std::vector<PseudoJet> _jets;
00565
00566
00570 std::vector<history_element> _history;
00571
00580 void get_subhist_set(std::set<const history_element*> & subhist,
00581 const PseudoJet & jet, double dcut, int maxjet) const;
00582
00583 bool _writeout_combinations;
00584 int _initial_n;
00585 double _Rparam, _R2, _invR2;
00586 double _Qtot;
00587 Strategy _strategy;
00588 JetAlgorithm _jet_algorithm;
00589
00590 SharedPtr<ClusterSequenceWrapper> _wrapper_to_this;
00591
00592 private:
00593
00594 bool _plugin_activated;
00595 std::auto_ptr<Extras> _extras;
00596
00597 void _really_dumb_cluster ();
00598 void _delaunay_cluster ();
00599
00600 template<class BJ> void _simple_N2_cluster ();
00601 void _tiled_N2_cluster ();
00602 void _faster_tiled_N2_cluster ();
00603
00604
00605 void _minheap_faster_tiled_N2_cluster();
00606
00607
00608
00609 void _CP2DChan_cluster();
00610 void _CP2DChan_cluster_2pi2R ();
00611 void _CP2DChan_cluster_2piMultD ();
00612 void _CP2DChan_limited_cluster(double D);
00613 void _do_Cambridge_inclusive_jets();
00614
00615
00616 void _fast_NsqrtN_cluster();
00617
00618 void _add_step_to_history(const int & step_number, const int & parent1,
00619 const int & parent2, const int & jetp_index,
00620 const double & dij);
00621
00624 void _extract_tree_children(int pos, std::valarray<bool> &,
00625 const std::valarray<int> &, std::vector<int> &) const;
00626
00629 void _extract_tree_parents (int pos, std::valarray<bool> &,
00630 const std::valarray<int> &, std::vector<int> &) const;
00631
00632
00633
00634 typedef std::pair<int,int> TwoVertices;
00635 typedef std::pair<double,TwoVertices> DijEntry;
00636 typedef std::multimap<double,TwoVertices> DistMap;
00637
00639 void _add_ktdistance_to_map(const int & ii,
00640 DistMap & DijMap,
00641 const DynamicNearestNeighbours * DNN);
00642
00644 void _print_banner();
00646 static bool _first_time;
00647
00651 static int _n_exclusive_warnings;
00652
00656 static LimitedWarning _changed_strategy_warning;
00657
00658
00663 struct BriefJet {
00664 double eta, phi, kt2, NN_dist;
00665 BriefJet * NN;
00666 int _jets_index;
00667 };
00668
00669
00672 class TiledJet {
00673 public:
00674 double eta, phi, kt2, NN_dist;
00675 TiledJet * NN, *previous, * next;
00676 int _jets_index, tile_index, diJ_posn;
00677
00678
00679
00680
00681 inline void label_minheap_update_needed() {diJ_posn = 1;}
00682 inline void label_minheap_update_done() {diJ_posn = 0;}
00683 inline bool minheap_update_needed() const {return diJ_posn==1;}
00684 };
00685
00686
00687
00688
00691 template <class J> void _bj_set_jetinfo( J * const jet,
00692 const int _jets_index) const;
00693
00696 void _bj_remove_from_tiles( TiledJet * const jet) const;
00697
00699 template <class J> double _bj_dist(const J * const jeta,
00700 const J * const jetb) const;
00701
00702
00703
00704 template <class J> double _bj_diJ(const J * const jeta) const;
00705
00709 template <class J> inline J * _bj_of_hindex(
00710 const int hist_index,
00711 J * const head, J * const tail)
00712 const {
00713 J * res;
00714 for(res = head; res<tail; res++) {
00715 if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00716 }
00717 return res;
00718 }
00719
00720
00721
00722
00723
00728 template <class J> void _bj_set_NN_nocross(J * const jeta,
00729 J * const head, const J * const tail) const;
00730
00735 template <class J> void _bj_set_NN_crosscheck(J * const jeta,
00736 J * const head, const J * const tail) const;
00737
00738
00739
00742 static const int n_tile_neighbours = 9;
00743
00746 struct Tile {
00748 Tile * begin_tiles[n_tile_neighbours];
00750 Tile ** surrounding_tiles;
00752 Tile ** RH_tiles;
00754 Tile ** end_tiles;
00756 TiledJet * head;
00758 bool tagged;
00759 };
00760 std::vector<Tile> _tiles;
00761 double _tiles_eta_min, _tiles_eta_max;
00762 double _tile_size_eta, _tile_size_phi;
00763 int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
00764
00765
00766
00767 inline int _tile_index (int ieta, int iphi) const {
00768
00769
00770 return (ieta-_tiles_ieta_min)*_n_tiles_phi
00771 + (iphi+_n_tiles_phi) % _n_tiles_phi;
00772 }
00773
00774
00775
00776 int _tile_index(const double & eta, const double & phi) const;
00777 void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
00778 void _bj_remove_from_tiles(TiledJet * const jet);
00779 void _initialise_tiles();
00780 void _print_tiles(TiledJet * briefjets ) const;
00781 void _add_neighbours_to_tile_union(const int tile_index,
00782 std::vector<int> & tile_union, int & n_near_tiles) const;
00783 void _add_untagged_neighbours_to_tile_union(const int tile_index,
00784 std::vector<int> & tile_union, int & n_near_tiles);
00785
00786
00787
00789 struct EEBriefJet {
00790 double NN_dist;
00791 double kt2;
00792 EEBriefJet * NN;
00793 int _jets_index;
00794
00795 double nx, ny, nz;
00796 };
00797
00799
00800
00801
00803 void _simple_N2_cluster_BriefJet();
00805 void _simple_N2_cluster_EEBriefJet();
00806 };
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 template<class L> void ClusterSequence::_transfer_input_jets(
00817 const std::vector<L> & pseudojets) {
00818
00819
00820
00821 _jets.reserve(pseudojets.size()*2);
00822
00823
00824
00825
00826
00827 for (unsigned int i = 0; i < pseudojets.size(); i++) {
00828 _jets.push_back(pseudojets[i]);}
00829
00830 }
00831
00832
00833
00834
00835 template<class L> ClusterSequence::ClusterSequence (
00836 const std::vector<L> & pseudojets,
00837 const double & R,
00838 const Strategy & strategy,
00839 const bool & writeout_combinations) {
00840
00841
00842 _transfer_input_jets(pseudojets);
00843
00844
00845 _initialise_and_run(R,strategy,writeout_combinations);
00846 }
00847
00848
00849
00852 template<class L> ClusterSequence::ClusterSequence (
00853 const std::vector<L> & pseudojets,
00854 const JetDefinition & jet_def,
00855 const bool & writeout_combinations) {
00856
00857
00858 _transfer_input_jets(pseudojets);
00859
00860
00861 _initialise_and_run(jet_def,writeout_combinations);
00862 }
00863
00864
00865 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
00866 return _jets;
00867 }
00868
00869 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
00870 return _history;
00871 }
00872
00873 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
00874
00875
00876
00877
00878 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
00879 J * const jetA, const int _jets_index) const {
00880 jetA->eta = _jets[_jets_index].rap();
00881 jetA->phi = _jets[_jets_index].phi_02pi();
00882 jetA->kt2 = jet_scale_for_algorithm(_jets[_jets_index]);
00883 jetA->_jets_index = _jets_index;
00884
00885 jetA->NN_dist = _R2;
00886 jetA->NN = NULL;
00887 }
00888
00889
00890
00891
00892
00893 template <class J> inline double ClusterSequence::_bj_dist(
00894 const J * const jetA, const J * const jetB) const {
00895 double dphi = std::abs(jetA->phi - jetB->phi);
00896 double deta = (jetA->eta - jetB->eta);
00897 if (dphi > pi) {dphi = twopi - dphi;}
00898 return dphi*dphi + deta*deta;
00899 }
00900
00901
00902 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
00903 double kt2 = jet->kt2;
00904 if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00905 return jet->NN_dist * kt2;
00906 }
00907
00908
00909
00910
00911
00912 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
00913 J * const jet, J * const head, const J * const tail) const {
00914 double NN_dist = _R2;
00915 J * NN = NULL;
00916 if (head < jet) {
00917 for (J * jetB = head; jetB != jet; jetB++) {
00918 double dist = _bj_dist(jet,jetB);
00919 if (dist < NN_dist) {
00920 NN_dist = dist;
00921 NN = jetB;
00922 }
00923 }
00924 }
00925 if (tail > jet) {
00926 for (J * jetB = jet+1; jetB != tail; jetB++) {
00927 double dist = _bj_dist(jet,jetB);
00928 if (dist < NN_dist) {
00929 NN_dist = dist;
00930 NN = jetB;
00931 }
00932 }
00933 }
00934 jet->NN = NN;
00935 jet->NN_dist = NN_dist;
00936 }
00937
00938
00939
00940 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet,
00941 J * const head, const J * const tail) const {
00942 double NN_dist = _R2;
00943 J * NN = NULL;
00944 for (J * jetB = head; jetB != tail; jetB++) {
00945 double dist = _bj_dist(jet,jetB);
00946 if (dist < NN_dist) {
00947 NN_dist = dist;
00948 NN = jetB;
00949 }
00950 if (dist < jetB->NN_dist) {
00951 jetB->NN_dist = dist;
00952 jetB->NN = jet;
00953 }
00954 }
00955 jet->NN = NN;
00956 jet->NN_dist = NN_dist;
00957 }
00958
00959
00960
00961 FASTJET_END_NAMESPACE
00962
00963 #endif // __FASTJET_CLUSTERSEQUENCE_HH__