Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

ClusterSequence.hh

Go to the documentation of this file.
00001 //STARTHEADER
00002 // $Id: ClusterSequence.hh 329 2006-10-09 12:29:46Z salam $
00003 //
00004 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
00005 //
00006 //----------------------------------------------------------------------
00007 // This file is part of FastJet.
00008 //
00009 //  FastJet is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU General Public License as published by
00011 //  the Free Software Foundation; either version 2 of the License, or
00012 //  (at your option) any later version.
00013 //
00014 //  The algorithms that underlie FastJet have required considerable
00015 //  development and are described in hep-ph/0512210. If you use
00016 //  FastJet as part of work towards a scientific publication, please
00017 //  include a citation to the FastJet paper.
00018 //
00019 //  FastJet is distributed in the hope that it will be useful,
00020 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //  GNU General Public License for more details.
00023 //
00024 //  You should have received a copy of the GNU General Public License
00025 //  along with FastJet; if not, write to the Free Software
00026 //  Foundation, Inc.:
00027 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //----------------------------------------------------------------------
00029 //ENDHEADER
00030 
00031 
00032 //----------------------------------------------------------------------
00033 // here's where we put the main page for fastjet (as explained in the
00034 // Doxygen faq)
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> // needed to get double std::abs(double)
00057 #include "fastjet/Error.hh"
00058 #include "fastjet/JetDefinition.hh"
00059 
00060 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
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   // NB: in the routines that follow, for extracting lists of jets, a
00097   //     list structure might be more efficient, if sometimes a little
00098   //     more awkward to use (at least for old fortran hands).
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 //  /// things related to choice of algorithm
00146 //  enum JetFinder { kt_algorithm = 0, cambridge_algorithm = 1};
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   // things needed specifically for Cambridge with Chan's 2D closest
00298   // pairs method
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   // these will be useful shorthands in the Voronoi-based code
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     // routines that are useful in the minheap version of tiled
00354     // clustering ("misuse" the otherwise unused diJ_posn, so as
00355     // to indicate whether jets need to have their minheap entries
00356     // updated).
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   //-- some of the functions that follow are templates and will work
00363   //as well for briefjet and tiled jets
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   // return the diJ (multiplied by _R2) for this jet assuming its NN
00379   // info is correct
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   //-- remaining functions are different in various cases, so we
00398   //   will use templates but are not sure if they're useful...
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   // reasonably robust return of tile index given ieta and iphi, in particular
00442   // it works even if iphi is negative
00443   inline int _tile_index (int ieta, int iphi) const {
00444     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00445     // before performing modulo operation
00446     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00447                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00448   }
00449 
00450   // routines for tiled case, including some overloads of the plain
00451   // BriefJet cases
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 //**************    START   OF   INLINE   MATERIAL    ******************
00469 //**********************************************************************
00470 
00471 
00472 //----------------------------------------------------------------------
00473 // Transfer the initial jets into our internal structure
00474 template<class L> void ClusterSequence::_transfer_input_jets(
00475                                        const std::vector<L> & pseudojets) {
00476 
00477   // this will ensure that we can point to jets without difficulties
00478   // arising.
00479   _jets.reserve(pseudojets.size()*2);
00480 
00481   // insert initial jets this way so that any type L that can be
00482   // converted to a pseudojet will work fine (basically PseudoJet
00483   // and any type that has [] subscript access to the momentum
00484   // components, such as CLHEP HepLorentzVector).
00485   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00486     _jets.push_back(pseudojets[i]);}
00487   
00488 }
00489 
00490 //----------------------------------------------------------------------
00491 // initialise from some generic type... Has to be made available
00492 // here in order for it the template aspect of it to work...
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   // transfer the initial jets (type L) into our own array
00500   _transfer_input_jets(pseudojets);
00501 
00502   // run the clustering
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   // transfer the initial jets (type L) into our own array
00516   _transfer_input_jets(pseudojets);
00517 
00518   // run the clustering
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     // initialise NN info as well
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 // set the NN for jet without checking whether in the process you might
00577 // have discovered a new nearest neighbour for another jet
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__

Generated on Thu Oct 12 17:36:34 2006 for fastjet by  doxygen 1.4.2