ClusterSequence.hh

Go to the documentation of this file.
00001 //STARTHEADER
00002 // $Id: ClusterSequence.hh 1435 2009-02-12 21:11:04Z 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<memory>
00054 #include<cassert>
00055 #include<iostream>
00056 #include<string>
00057 #include<set>
00058 #include<cmath> // needed to get double std::abs(double)
00059 #include "fastjet/Error.hh"
00060 #include "fastjet/JetDefinition.hh"
00061 
00062 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00063 
00064 
00066 class ClusterSequence {
00067 
00068 
00069  public: 
00070 
00072   ClusterSequence () {}
00073 
00083   template<class L> ClusterSequence (const std::vector<L> & pseudojets, 
00084                    const double & R = 1.0,
00085                    const Strategy & strategy = Best,
00086                    const bool & writeout_combinations = false);
00087 
00088 
00092   template<class L> ClusterSequence (
00093                                   const std::vector<L> & pseudojets,
00094                                   const JetDefinition & jet_def,
00095                                   const bool & writeout_combinations = false);
00096 
00097   // virtual ClusterSequence destructor, in case any derived class
00098   // thinks of needing a destructor at some point
00099   virtual ~ClusterSequence (); //{}
00100 
00101   // NB: in the routines that follow, for extracting lists of jets, a
00102   //     list structure might be more efficient, if sometimes a little
00103   //     more awkward to use (at least for old fortran hands).
00104 
00108   std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) const;
00109 
00113   int n_exclusive_jets (const double & dcut) const;
00114 
00118   std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
00119 
00122   std::vector<PseudoJet> exclusive_jets (const int & njets) const;
00123 
00126   double exclusive_dmerge (const int & njets) const;
00127 
00132   double exclusive_dmerge_max (const int & njets) const;
00133 
00136   double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
00137 
00139   double exclusive_ymerge_max (int njets) const {return exclusive_ymerge_max(njets)/Q2();}
00140 
00142   int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
00143 
00145   std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
00146     int njets = n_exclusive_jets_ycut(ycut);
00147     return exclusive_jets(njets);
00148   }
00149 
00150 
00151   //int n_exclusive_jets (const PseudoJet & jet, const double & dcut) const;
00152 
00161   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
00162                                             const double & dcut) const;
00163 
00167   int n_exclusive_subjets(const PseudoJet & jet, 
00168                           const double & dcut) const;
00169 
00175   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
00176                                             int nsub) const;
00177 
00180   double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
00181 
00185   double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
00186 
00187   //std::vector<PseudoJet> exclusive_jets (const PseudoJet & jet, 
00188   //                                       const int & njets) const;
00189   //double exclusive_dmerge (const PseudoJet & jet, const int & njets) const;
00190 
00192   double Q() const {return _Q;}
00194   double Q2() const {return _Q*_Q;}
00195 
00206   bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
00207 
00213   bool has_parents(const PseudoJet & jet, PseudoJet & parent1, 
00214                PseudoJet & parent2) const;
00215 
00218   bool has_child(const PseudoJet & jet, PseudoJet & child) const;
00219 
00222   bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
00223 
00227   bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
00228 
00229   
00231   std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
00232 
00233 
00242   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
00243                            std::ostream & ostr = std::cout) const;
00244 
00247   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
00248                            const std::string & filename,
00249                            const std::string & comment = "") const;
00250 
00251 // Not yet. Perhaps in a future release.
00252 //   /// print out all inclusive jets with pt > ptmin
00253 //   virtual void print_jets (const double & ptmin=0.0) const;
00254 
00256   void add_constituents (const PseudoJet & jet, 
00257                          std::vector<PseudoJet> & subjet_vector) const;
00258 
00260   inline Strategy strategy_used () const {return _strategy;}
00261   std::string strategy_string () const;
00262 
00264   const JetDefinition & jet_def() const {return _jet_def;}
00265 
00269   double jet_scale_for_algorithm(const PseudoJet & jet) const;
00270 
00271   //----- next follow functions designed specifically for plugins, which
00272   //      may only be called when plugin_activated() returns true
00273 
00279   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
00280                                       int & newjet_k) {
00281     assert(plugin_activated());
00282     _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
00283   }
00284 
00288   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
00289                                       const PseudoJet & newjet, 
00290                                       int & newjet_k);
00291 
00296   void plugin_record_iB_recombination(int jet_i, double diB) {
00297     assert(plugin_activated());
00298     _do_iB_recombination_step(jet_i, diB);
00299   }
00300 
00304   class Extras {
00305   public:
00306     virtual ~Extras() {}
00307     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";}
00308   };
00309 
00312   inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in) {
00313     _extras = extras_in;
00314   }
00315 
00317   inline bool plugin_activated() const {return _plugin_activated;}
00318 
00320   const Extras * extras() const {return _extras.get();}
00321 
00329   template<class GBJ> void plugin_simple_N2_cluster () {
00330     assert(plugin_activated());
00331     _simple_N2_cluster<GBJ>();
00332   }
00333 
00334   //----------------------------------------------------------------------
00336   class GenBriefJet {
00337   public:
00350     virtual void init(const PseudoJet & jet) = 0;
00351     
00354     virtual double geom_ij(const GenBriefJet * jet_j) const = 0;
00355 
00356     void set_scale_squared(double scale_squared) {kt2 = scale_squared;}
00357     void set_geom_iB(double diB) {NN_dist = diB; NN = NULL;}
00358     
00359   public: // formally public: but users should think of it as private!
00360     double NN_dist;  // dij
00361     double kt2;      // squared scale
00362     GenBriefJet * NN; // pointer to nearest neighbour
00363     int    _jets_index; // index of this jet
00364   };
00365 
00366 
00367 public:
00371   static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
00373   static void set_jet_finder (JetAlgorithm jet_algorithm)    {_default_jet_algorithm = jet_algorithm;}
00374 
00375 
00378   struct history_element{
00379     int parent1; 
00380 
00381 
00382 
00383     int parent2; 
00384 
00385 
00386 
00387 
00388 
00389     int child;   
00390 
00391 
00392 
00393 
00394     int jetp_index; 
00395 
00396 
00397 
00398 
00399 
00400 
00401     double dij;  
00402 
00403 
00404     double max_dij_so_far; 
00405 
00406   };
00407 
00408   enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
00409 
00426   const std::vector<PseudoJet> & jets()    const;
00427 
00439   const std::vector<history_element> & history() const;
00440 
00445   unsigned int n_particles() const;
00446 
00451   std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
00452 
00468   std::vector<int> unique_history_order() const;
00469 
00473   std::vector<PseudoJet> unclustered_particles() const;
00474 
00478   void transfer_from_sequence(ClusterSequence & from_seq);
00479 
00480 
00481 protected:
00482   static JetAlgorithm _default_jet_algorithm;
00483   JetDefinition _jet_def;
00484 
00487   bool _potentially_valid(const PseudoJet & jet) const {
00488     return jet.cluster_hist_index() >= 0 
00489       && jet.cluster_hist_index() < int(_history.size());
00490   }
00491 
00494   template<class L> void _transfer_input_jets(
00495                                      const std::vector<L> & pseudojets);
00496 
00500   void _initialise_and_run (const JetDefinition & jet_def,
00501                             const bool & writeout_combinations);
00502 
00506   void _initialise_and_run (const double & R,
00507                             const Strategy & strategy,
00508                             const bool & writeout_combinations);
00509 
00512   void _decant_options(const JetDefinition & jet_def,
00513                        const bool & writeout_combinations);
00514 
00518   void _fill_initial_history();
00519 
00523   void _do_ij_recombination_step(const int & jet_i, const int & jet_j, 
00524                                  const double & dij, int & newjet_k);
00525 
00528   void _do_iB_recombination_step(const int & jet_i, const double & diB);
00529 
00530 
00534   std::vector<PseudoJet> _jets;
00535 
00536 
00540   std::vector<history_element> _history;
00541 
00550   void get_subhist_set(std::set<const history_element*> & subhist,
00551                        const  PseudoJet & jet, double dcut, int maxjet) const;
00552 
00553   bool _writeout_combinations;
00554   int  _initial_n;
00555   double _Rparam, _R2, _invR2;
00556   double _Q;
00557   Strategy    _strategy;
00558   JetAlgorithm  _jet_algorithm;
00559 
00560 
00561  private:
00562 
00563   bool _plugin_activated;
00564   std::auto_ptr<Extras> _extras; // things the plugin might want to add
00565 
00566   void _really_dumb_cluster ();
00567   void _delaunay_cluster ();
00568   //void _simple_N2_cluster ();
00569   template<class BJ> void _simple_N2_cluster ();
00570   void _tiled_N2_cluster ();
00571   void _faster_tiled_N2_cluster ();
00572 
00573   //
00574   void _minheap_faster_tiled_N2_cluster();
00575 
00576   // things needed specifically for Cambridge with Chan's 2D closest
00577   // pairs method
00578   void _CP2DChan_cluster();
00579   void _CP2DChan_cluster_2pi2R ();
00580   void _CP2DChan_cluster_2piMultD ();
00581   void _CP2DChan_limited_cluster(double D);
00582   void _do_Cambridge_inclusive_jets();
00583 
00584   void _add_step_to_history(const int & step_number, const int & parent1, 
00585                                const int & parent2, const int & jetp_index,
00586                                const double & dij);
00587 
00590   void _extract_tree_children(int pos, std::valarray<bool> &, 
00591                 const std::valarray<int> &, std::vector<int> &) const;
00592 
00595   void _extract_tree_parents (int pos, std::valarray<bool> &, 
00596                 const std::valarray<int> &,  std::vector<int> &) const;
00597 
00598 
00599   // these will be useful shorthands in the Voronoi-based code
00600   typedef std::pair<int,int> TwoVertices;
00601   typedef std::pair<double,TwoVertices> DijEntry;
00602   typedef std::multimap<double,TwoVertices> DistMap;
00603 
00605   void _add_ktdistance_to_map(const int & ii, 
00606                               DistMap & DijMap,
00607                               const DynamicNearestNeighbours * DNN);
00608 
00610   void _print_banner();
00612   static bool _first_time;
00613 
00617   static int _n_exclusive_warnings;
00618 
00619   //----------------------------------------------------------------------
00624   struct BriefJet {
00625     double     eta, phi, kt2, NN_dist;
00626     BriefJet * NN;
00627     int        _jets_index;
00628   };
00629 
00630 
00633   class TiledJet {
00634   public:
00635     double     eta, phi, kt2, NN_dist;
00636     TiledJet * NN, *previous, * next; 
00637     int        _jets_index, tile_index, diJ_posn;
00638     // routines that are useful in the minheap version of tiled
00639     // clustering ("misuse" the otherwise unused diJ_posn, so as
00640     // to indicate whether jets need to have their minheap entries
00641     // updated).
00642     inline void label_minheap_update_needed() {diJ_posn = 1;}
00643     inline void label_minheap_update_done()   {diJ_posn = 0;}
00644     inline bool minheap_update_needed() const {return diJ_posn==1;}
00645   };
00646 
00647   //-- some of the functions that follow are templates and will work
00648   //as well for briefjet and tiled jets
00649 
00652   template <class J> void _bj_set_jetinfo( J * const jet, 
00653                                                  const int _jets_index) const;
00654 
00657   void _bj_remove_from_tiles( TiledJet * const jet) const;
00658 
00660   template <class J> double _bj_dist(const J * const jeta, 
00661                         const J * const jetb) const;
00662 
00663   // return the diJ (multiplied by _R2) for this jet assuming its NN
00664   // info is correct
00665   template <class J> double _bj_diJ(const J * const jeta) const;
00666 
00670   template <class J> inline J * _bj_of_hindex(
00671                           const int hist_index, 
00672                           J * const head, J * const tail) 
00673     const {
00674     J * res;
00675     for(res = head; res<tail; res++) {
00676       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00677     }
00678     return res;
00679   }
00680 
00681 
00682   //-- remaining functions are different in various cases, so we
00683   //   will use templates but are not sure if they're useful...
00684 
00689   template <class J> void _bj_set_NN_nocross(J * const jeta, 
00690             J * const head, const J * const tail) const;
00691 
00696   template <class J> void _bj_set_NN_crosscheck(J * const jeta, 
00697             J * const head, const J * const tail) const;
00698   
00699 
00700 
00703   static const int n_tile_neighbours = 9;
00704   //----------------------------------------------------------------------
00707   struct Tile {
00709     Tile *   begin_tiles[n_tile_neighbours]; 
00711     Tile **  surrounding_tiles; 
00713     Tile **  RH_tiles;  
00715     Tile **  end_tiles; 
00717     TiledJet * head;    
00719     bool     tagged;    
00720   };
00721   std::vector<Tile> _tiles;
00722   double _tiles_eta_min, _tiles_eta_max;
00723   double _tile_size_eta, _tile_size_phi;
00724   int    _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
00725 
00726   // reasonably robust return of tile index given ieta and iphi, in particular
00727   // it works even if iphi is negative
00728   inline int _tile_index (int ieta, int iphi) const {
00729     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00730     // before performing modulo operation
00731     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00732                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00733   }
00734 
00735   // routines for tiled case, including some overloads of the plain
00736   // BriefJet cases
00737   int  _tile_index(const double & eta, const double & phi) const;
00738   void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
00739   void  _bj_remove_from_tiles(TiledJet * const jet);
00740   void _initialise_tiles();
00741   void _print_tiles(TiledJet * briefjets ) const;
00742   void _add_neighbours_to_tile_union(const int tile_index, 
00743                  std::vector<int> & tile_union, int & n_near_tiles) const;
00744   void _add_untagged_neighbours_to_tile_union(const int tile_index, 
00745                  std::vector<int> & tile_union, int & n_near_tiles);
00746 
00747 
00748   //----------------------------------------------------------------------
00750   struct EEBriefJet {
00751     double NN_dist;  // obligatorily present
00752     double kt2;      // obligatorily present == E^2 in general
00753     EEBriefJet * NN; // must be present too
00754     int    _jets_index; // must also be present!
00755     //...........................................................
00756     double nx, ny, nz;  // our internal storage for fast distance calcs
00757   };
00758 
00760   void _dummy_N2_cluster_instantiation();
00761 
00762 };
00763 
00764 
00765 //**********************************************************************
00766 //**************    START   OF   INLINE   MATERIAL    ******************
00767 //**********************************************************************
00768 
00769 
00770 //----------------------------------------------------------------------
00771 // Transfer the initial jets into our internal structure
00772 template<class L> void ClusterSequence::_transfer_input_jets(
00773                                        const std::vector<L> & pseudojets) {
00774 
00775   // this will ensure that we can point to jets without difficulties
00776   // arising.
00777   _jets.reserve(pseudojets.size()*2);
00778 
00779   // insert initial jets this way so that any type L that can be
00780   // converted to a pseudojet will work fine (basically PseudoJet
00781   // and any type that has [] subscript access to the momentum
00782   // components, such as CLHEP HepLorentzVector).
00783   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00784     _jets.push_back(pseudojets[i]);}
00785   
00786 }
00787 
00788 //----------------------------------------------------------------------
00789 // initialise from some generic type... Has to be made available
00790 // here in order for it the template aspect of it to work...
00791 template<class L> ClusterSequence::ClusterSequence (
00792                                   const std::vector<L> & pseudojets,
00793                                   const double & R,
00794                                   const Strategy & strategy,
00795                                   const bool & writeout_combinations) {
00796 
00797   // transfer the initial jets (type L) into our own array
00798   _transfer_input_jets(pseudojets);
00799 
00800   // run the clustering
00801   _initialise_and_run(R,strategy,writeout_combinations);
00802 }
00803 
00804 
00805 //----------------------------------------------------------------------
00808 template<class L> ClusterSequence::ClusterSequence (
00809                                   const std::vector<L> & pseudojets,
00810                                   const JetDefinition & jet_def,
00811                                   const bool & writeout_combinations) {
00812 
00813   // transfer the initial jets (type L) into our own array
00814   _transfer_input_jets(pseudojets);
00815 
00816   // run the clustering
00817   _initialise_and_run(jet_def,writeout_combinations);
00818 }
00819 
00820 
00821 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
00822   return _jets;
00823 }
00824 
00825 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
00826   return _history;
00827 }
00828 
00829 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
00830 
00831 
00832 
00833 //----------------------------------------------------------------------
00834 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
00835                             J * const jetA, const int _jets_index) const {
00836     jetA->eta  = _jets[_jets_index].rap();
00837     jetA->phi  = _jets[_jets_index].phi_02pi();
00838     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
00839     jetA->_jets_index = _jets_index;
00840     // initialise NN info as well
00841     jetA->NN_dist = _R2;
00842     jetA->NN      = NULL;
00843 }
00844 
00845 
00846 
00847 
00848 //----------------------------------------------------------------------
00849 template <class J> inline double ClusterSequence::_bj_dist(
00850                 const J * const jetA, const J * const jetB) const {
00851   double dphi = std::abs(jetA->phi - jetB->phi);
00852   double deta = (jetA->eta - jetB->eta);
00853   if (dphi > pi) {dphi = twopi - dphi;}
00854   return dphi*dphi + deta*deta;
00855 }
00856 
00857 //----------------------------------------------------------------------
00858 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
00859   double kt2 = jet->kt2;
00860   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00861   return jet->NN_dist * kt2;
00862 }
00863 
00864 
00865 //----------------------------------------------------------------------
00866 // set the NN for jet without checking whether in the process you might
00867 // have discovered a new nearest neighbour for another jet
00868 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
00869                  J * const jet, J * const head, const J * const tail) const {
00870   double NN_dist = _R2;
00871   J * NN  = NULL;
00872   if (head < jet) {
00873     for (J * jetB = head; jetB != jet; jetB++) {
00874       double dist = _bj_dist(jet,jetB);
00875       if (dist < NN_dist) {
00876         NN_dist = dist;
00877         NN = jetB;
00878       }
00879     }
00880   }
00881   if (tail > jet) {
00882     for (J * jetB = jet+1; jetB != tail; jetB++) {
00883       double dist = _bj_dist(jet,jetB);
00884       if (dist < NN_dist) {
00885         NN_dist = dist;
00886         NN = jetB;
00887       }
00888     }
00889   }
00890   jet->NN = NN;
00891   jet->NN_dist = NN_dist;
00892 }
00893 
00894 
00895 //----------------------------------------------------------------------
00896 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet, 
00897                     J * const head, const J * const tail) const {
00898   double NN_dist = _R2;
00899   J * NN  = NULL;
00900   for (J * jetB = head; jetB != tail; jetB++) {
00901     double dist = _bj_dist(jet,jetB);
00902     if (dist < NN_dist) {
00903       NN_dist = dist;
00904       NN = jetB;
00905     }
00906     if (dist < jetB->NN_dist) {
00907       jetB->NN_dist = dist;
00908       jetB->NN = jet;
00909     }
00910   }
00911   jet->NN = NN;
00912   jet->NN_dist = NN_dist;
00913 }
00914 
00915 
00916 
00917 FASTJET_END_NAMESPACE
00918 
00919 #endif // __FASTJET_CLUSTERSEQUENCE_HH__

Generated on Fri Apr 17 16:15:09 2009 for fastjet by  doxygen 1.5.7.1