FastJet 3.0alpha3
ClusterSequence.hh
00001 //STARTHEADER
00002 // $Id: ClusterSequence.hh 2171 2011-05-19 18:46:28Z 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 #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> // needed to get double std::abs(double)
00045 #include "fastjet/Error.hh"
00046 #include "fastjet/JetDefinition.hh"
00047 #include "fastjet/SharedPtr.hh"
00048 #include "fastjet/internal/LimitedWarning.hh"
00049 #include "fastjet/FunctionOfPseudoJet.hh"
00050 
00051 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00052 
00053 //----------------------------------------------------------------------
00054 // here's where we put the main page for fastjet (as explained in the
00055 // Doxygen faq)
00056 // We put in inside te fastjet namespace to have the links without
00057 // having to specify (fastjet::)
00058 //......................................................................
00059 /** \mainpage FastJet code documentation
00060  *
00061  * These pages provide automatically generated documentation for the 
00062  * FastJet package.
00063  * 
00064  * \section useful_classes The most useful classes
00065  *
00066  * Many of the facilities of FastJet can be accessed through the three
00067  * following classes:
00068  *
00069  * - PseudoJet: the basic class for holding the 4-momentum of a
00070  *   particle or a jet.
00071  *
00072  * - JetDefinition: the combination of a #JetAlgorithm and its
00073  *   associated parameters.
00074  *
00075  * - ClusterSequence: constructed with a vector of input (PseudoJet)
00076  *   particles and a JetDefinition, it computes and stores the
00077  *   information on how the input particles are clustered into jets.
00078  *
00079  * \section advanced_classes Selected more advanced classes
00080  *
00081  * - ClusterSequenceArea: with the help of an AreaDefinition, provides
00082  *   jets that also contain information about their area.
00083  *
00084  * \section further_info Further information
00085  *
00086  * - Selected classes ordered by topics can be found under the <a
00087  * href="modules.html">modules</a> tab.
00088  *
00089  * - The complete list of classes is available under the  <a
00090  * href="annotated.html">classes</a> tab.
00091  * 
00092  * - For non-class material (<a href="namespacefastjet.html#enum-members">enums</a>,
00093  * <a href="namespacefastjet.html#typedef-members">typedefs</a>, 
00094  * <a href="namespacefastjet.html#func-members">functions</a>), see the 
00095  * #fastjet documentation
00096  * 
00097  * - For further information and normal documentation, see the main <a
00098  * href="http://www.lpthe.jussieu.fr/~salam/fastjet">FastJet</a> page.
00099  *
00100  * \section examples Examples
00101  *   See our \subpage Examples page
00102  */
00103 //----------------------------------------------------------------------
00104 
00105 // forward declaration
00106 class ClusterSequenceStructure;
00107 
00108 /// @ingroup basic_classes
00109 /// \class ClusterSequence
00110 /// deals with clustering
00111 class ClusterSequence {
00112 
00113 
00114  public: 
00115 
00116   /// default constructor
00117   ClusterSequence () : _deletes_self_when_unused(false) {}
00118 
00119   /// create a clustersequence starting from the supplied set
00120   /// of pseudojets and clustering them with the long-invariant
00121   /// kt algorithm (E-scheme recombination) with the supplied
00122   /// value for R.
00123   ///
00124   /// If strategy=DumbN3 a very stupid N^3 algorithm is used for the
00125   /// clustering; otherwise strategy = NlnN* uses cylinders algorithms
00126   /// with some number of pi coverage. If writeout_combinations=true a
00127   /// summary of the recombination sequence is written out
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 
00134   /// create a clustersequence starting from the supplied set
00135   /// of pseudojets and clustering them with jet definition specified
00136   /// by jet_def (which also specifies the clustering strategy)
00137   template<class L> ClusterSequence (
00138                                   const std::vector<L> & pseudojets,
00139                                   const JetDefinition & jet_def,
00140                                   const bool & writeout_combinations = false);
00141 
00142   // virtual ClusterSequence destructor, in case any derived class
00143   // thinks of needing a destructor at some point
00144   virtual ~ClusterSequence (); //{}
00145 
00146   // NB: in the routines that follow, for extracting lists of jets, a
00147   //     list structure might be more efficient, if sometimes a little
00148   //     more awkward to use (at least for old fortran hands).
00149 
00150   /// return a vector of all jets (in the sense of the inclusive
00151   /// algorithm) with pt >= ptmin. Time taken should be of the order
00152   /// of the number of jets returned.
00153   std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) const;
00154 
00155   /// return the number of jets (in the sense of the exclusive
00156   /// algorithm) that would be obtained when running the algorithm
00157   /// with the given dcut.
00158   int n_exclusive_jets (const double & dcut) const;
00159 
00160   /// return a vector of all jets (in the sense of the exclusive
00161   /// algorithm) that would be obtained when running the algorithm
00162   /// with the given dcut.
00163   std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
00164 
00165   /// return a vector of all jets when the event is clustered (in the
00166   /// exclusive sense) to exactly njets. 
00167   ///
00168   /// If there are fewer than njets particles in the ClusterSequence
00169   /// then FastJet crashes since it is not able to return njets
00170   /// exclusive jets.
00171   std::vector<PseudoJet> exclusive_jets (const int & njets) const;
00172 
00173   /// return the dmin corresponding to the recombination that went from
00174   /// n+1 to n jets (sometimes known as d_{n n+1}).
00175   double exclusive_dmerge (const int & njets) const;
00176 
00177   /// return the maximum of the dmin encountered during all recombinations 
00178   /// up to the one that led to an n-jet final state; identical to
00179   /// exclusive_dmerge, except in cases where the dmin do not increase
00180   /// monotonically.
00181   double exclusive_dmerge_max (const int & njets) const;
00182 
00183   /// return the ymin corresponding to the recombination that went from
00184   /// n+1 to n jets (sometimes known as y_{n n+1}).
00185   double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
00186 
00187   /// same as exclusive_dmerge_max, but normalised to squared total energy
00188   double exclusive_ymerge_max (int njets) const {return exclusive_dmerge_max(njets)/Q2();}
00189 
00190   /// the number of exclusive jets at the given ycut
00191   int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
00192 
00193   /// the exclusive jets obtained at the given ycut
00194   std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
00195     int njets = n_exclusive_jets_ycut(ycut);
00196     return exclusive_jets(njets);
00197   }
00198 
00199 
00200   //int n_exclusive_jets (const PseudoJet & jet, const double & dcut) const;
00201 
00202   /// return a vector of all subjets of the current jet (in the sense
00203   /// of the exclusive algorithm) that would be obtained when running
00204   /// the algorithm with the given dcut. 
00205   ///
00206   /// Time taken is O(m ln m), where m is the number of subjets that
00207   /// are found. If m gets to be of order of the total number of
00208   /// constituents in the jet, this could be substantially slower than
00209   /// just getting that list of constituents.
00210   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
00211                                             const double & dcut) const;
00212 
00213   /// return the size of exclusive_subjets(...); still n ln n with same
00214   /// coefficient, but marginally more efficient than manually taking
00215   /// exclusive_subjets.size()
00216   int n_exclusive_subjets(const PseudoJet & jet, 
00217                           const double & dcut) const;
00218 
00219   /// return the list of subjets obtained by unclustering the supplied
00220   /// jet down to n subjets (or all constituents if there are fewer
00221   /// than n).
00222   ///
00223   /// This requires n ln n time
00224   ///
00225   /// If the jet contains fewer than nsub particles (in which case it
00226   /// is not possible to return nsub subjets) then the vector of
00227   /// subjets that is returned is simply the list of particles (of
00228   /// size < nsub). Note that this behaviour differs from that of
00229   /// exclusive_jets().
00230   std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet, 
00231                                             int nsub) const;
00232 
00233   /// return the dij that was present in the merging nsub+1 -> nsub 
00234   /// subjets inside this jet.
00235   ///
00236   /// Returns 0 if there were nsub or fewer constituents in the jet.
00237   double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
00238 
00239   /// return the maximum dij that occurred in the whole event at the
00240   /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
00241   /// this jet.
00242   ///
00243   /// Returns 0 if there were nsub or fewer constituents in the jet.
00244   double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
00245 
00246   //std::vector<PseudoJet> exclusive_jets (const PseudoJet & jet, 
00247   //                                       const int & njets) const;
00248   //double exclusive_dmerge (const PseudoJet & jet, const int & njets) const;
00249 
00250   /// returns the sum of all energies in the event (relevant mainly for e+e-)
00251   double Q() const {return _Qtot;}
00252   /// return Q()^2
00253   double Q2() const {return _Qtot*_Qtot;}
00254 
00255   /// returns true iff the object is included in the jet. 
00256   ///
00257   /// NB: this is only sensible if the object is already registered
00258   /// within the cluster sequence, so you cannot use it with an input
00259   /// particle to the CS (since the particle won't have the history
00260   /// index set properly).
00261   ///
00262   /// For nice clustering structures it should run in O(ln(N)) time
00263   /// but in worst cases (certain cone plugins) it can take O(n) time,
00264   /// where n is the number of particles in the jet.
00265   bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
00266 
00267   /// if the jet has parents in the clustering, it returns true
00268   /// and sets parent1 and parent2 equal to them.
00269   ///
00270   /// if it has no parents it returns false and sets parent1 and
00271   /// parent2 to zero
00272   bool has_parents(const PseudoJet & jet, PseudoJet & parent1, 
00273                PseudoJet & parent2) const;
00274 
00275   /// if the jet has a child then return true and give the child jet
00276   /// otherwise return false and set the child to zero
00277   bool has_child(const PseudoJet & jet, PseudoJet & child) const;
00278 
00279   /// Version of has_child that sets a pointer to the child if the child
00280   /// exists;
00281   bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
00282 
00283   /// if this jet has a child (and so a partner) return true
00284   /// and give the partner, otherwise return false and set the
00285   /// partner to zero
00286   bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
00287 
00288   
00289   /// return a vector of the particles that make up jet
00290   std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
00291 
00292 
00293   /// output the supplied vector of jets in a format that can be read
00294   /// by an appropriate root script; the format is:
00295   /// jet-n jet-px jet-py jet-pz jet-E 
00296   ///   particle-n particle-rap particle-phi particle-pt
00297   ///   particle-n particle-rap particle-phi particle-pt
00298   ///   ...
00299   /// #END
00300   /// ... [i.e. above repeated]
00301   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
00302                            std::ostream & ostr = std::cout) const;
00303 
00304   /// print jets for root to the file labelled filename, with an
00305   /// optional comment at the beginning
00306   void print_jets_for_root(const std::vector<PseudoJet> & jets, 
00307                            const std::string & filename,
00308                            const std::string & comment = "") const;
00309 
00310 // Not yet. Perhaps in a future release.
00311 //   /// print out all inclusive jets with pt > ptmin
00312 //   virtual void print_jets (const double & ptmin=0.0) const;
00313 
00314   /// add on to subjet_vector the constituents of jet (for internal use mainly)
00315   void add_constituents (const PseudoJet & jet, 
00316                          std::vector<PseudoJet> & subjet_vector) const;
00317 
00318   /// return the enum value of the strategy used to cluster the event
00319   inline Strategy strategy_used () const {return _strategy;}
00320 
00321   /// return the name of the strategy used to cluster the event
00322   std::string strategy_string () const {return strategy_string(_strategy);}
00323 
00324   /// return the name of the strategy associated with the enum strategy_in
00325   std::string strategy_string (Strategy strategy_in) const;
00326 
00327 
00328   /// return a reference to the jet definition
00329   const JetDefinition & jet_def() const {return _jet_def;}
00330 
00331   /// by calling this routine you tell the ClusterSequence to delete
00332   /// itself when all the Pseudojets associated with it have gone out
00333   /// of scope. 
00334   ///
00335   /// At the time you call this, there must be at least one jet or
00336   /// other object outside the CS that is associated with the CS
00337   /// (e.g. the result of inclusive_jets()).
00338   ///
00339   /// NB: after having made this call, the user is still allowed to
00340   /// delete the CS or let it go out of scope. Jets associated with it
00341   /// will then simply not be able to access their substructure after
00342   /// that point.
00343   void delete_self_when_unused();
00344 
00345   /// return true if the object has been told to delete itself
00346   /// when unused
00347   bool will_delete_self_when_unused() const {return _deletes_self_when_unused;}
00348 
00349   /// tell the ClusterSequence it's about to be self deleted (internal use only)
00350   void signal_imminent_self_deletion() const;
00351 
00352   /// returns the scale associated with a jet as required for this
00353   /// clustering algorithm (kt^2 for the kt-algorithm, 1 for the 
00354   /// Cambridge algorithm). [May become virtual at some point]
00355   double jet_scale_for_algorithm(const PseudoJet & jet) const;
00356 
00357   ///
00358 
00359   //----- next follow functions designed specifically for plugins, which
00360   //      may only be called when plugin_activated() returns true
00361 
00362   /// record the fact that there has been a recombination between
00363   /// jets()[jet_i] and jets()[jet_k], with the specified dij, and
00364   /// return the index (newjet_k) allocated to the new jet, whose
00365   /// momentum is assumed to be the 4-vector sum of that of jet_i and
00366   /// jet_j
00367   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
00368                                       int & newjet_k) {
00369     assert(plugin_activated());
00370     _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
00371   }
00372 
00373   /// as for the simpler variant of plugin_record_ij_recombination,
00374   /// except that the new jet is attributed the momentum and
00375   /// user_index of newjet
00376   void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, 
00377                                       const PseudoJet & newjet, 
00378                                       int & newjet_k);
00379 
00380   /// record the fact that there has been a recombination between
00381   /// jets()[jet_i] and the beam, with the specified diB; when looking
00382   /// for inclusive jets, any iB recombination will returned to the user 
00383   /// as a jet.
00384   void plugin_record_iB_recombination(int jet_i, double diB) {
00385     assert(plugin_activated());
00386     _do_iB_recombination_step(jet_i, diB);
00387   }
00388 
00389   /// @ingroup extra_info
00390   /// \class Extras
00391   /// base class to store extra information that plugins may provide
00392   /// 
00393   /// a class intended to serve as a base in case a plugin needs to
00394   /// associate extra information with a ClusterSequence (see
00395   /// SISConePlugin.* for an example).
00396   class Extras {
00397   public:
00398     virtual ~Extras() {}
00399     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";}
00400   };
00401 
00402   /// the plugin can associated some extra information with the
00403   /// ClusterSequence object by calling this function
00404   inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in) {
00405     _extras = extras_in;
00406   }
00407 
00408   /// returns true when the plugin is allowed to run the show.
00409   inline bool plugin_activated() const {return _plugin_activated;}
00410 
00411   /// returns a pointer to the extras object (may be null)
00412   const Extras * extras() const {return _extras.get();}
00413 
00414   /// allows a plugin to run a templated clustering (nearest-neighbour heuristic)
00415   ///
00416   /// This has N^2 behaviour on "good" distance, but a worst case behaviour
00417   /// of N^3 (and many algs trigger the worst case behaviour)
00418   ///
00419   /// 
00420   /// For more details on how this works, see GenBriefJet below
00421   template<class GBJ> void plugin_simple_N2_cluster () {
00422     assert(plugin_activated());
00423     _simple_N2_cluster<GBJ>();
00424   }
00425 
00426 
00427 public:
00428   /// set the default (static) jet finder across all current and future
00429   /// ClusterSequence objects -- deprecated and obsolescent (i.e. may be
00430   /// suppressed in a future release).
00431   static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
00432   /// same as above for backward compatibility
00433   static void set_jet_finder (JetAlgorithm jet_algorithm)    {_default_jet_algorithm = jet_algorithm;}
00434 
00435 
00436   /// \ingroup extra_info
00437   /// \struct history_element
00438   /// a single element in the clustering history
00439   /// 
00440   /// (see vector _history below).
00441   struct history_element{
00442     int parent1; /// index in _history where first parent of this jet
00443                  /// was created (InexistentParent if this jet is an
00444                  /// original particle)
00445 
00446     int parent2; /// index in _history where second parent of this jet
00447                  /// was created (InexistentParent if this jet is an
00448                  /// original particle); BeamJet if this history entry
00449                  /// just labels the fact that the jet has recombined
00450                  /// with the beam)
00451 
00452     int child;   /// index in _history where the current jet is
00453                  /// recombined with another jet to form its child. It
00454                  /// is Invalid if this jet does not further
00455                  /// recombine.
00456 
00457     int jetp_index; /// index in the _jets vector where we will find the
00458                  /// PseudoJet object corresponding to this jet
00459                  /// (i.e. the jet created at this entry of the
00460                  /// history). NB: if this element of the history
00461                  /// corresponds to a beam recombination, then
00462                  /// jetp_index=Invalid.
00463 
00464     double dij;  /// the distance corresponding to the recombination
00465                  /// at this stage of the clustering.
00466 
00467     double max_dij_so_far; /// the largest recombination distance seen
00468                            /// so far in the clustering history.
00469   };
00470 
00471   enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
00472 
00473   /// allow the user to access the internally stored _jets() array,
00474   /// which contains both the initial particles and the various
00475   /// intermediate and final stages of recombination.
00476   ///
00477   /// The first n_particles() entries are the original particles,
00478   /// in the order in which they were supplied to the ClusterSequence
00479   /// constructor. It can be useful to access them for example when
00480   /// examining whether a given input object is part of a specific
00481   /// jet, via the objects_in_jet(...) member function (which only takes
00482   /// PseudoJets that are registered in the ClusterSequence).
00483   ///
00484   /// One of the other (internal uses) is related to the fact
00485   /// because we don't seem to be able to access protected elements of
00486   /// the class for an object that is not "this" (at least in case where
00487   /// "this" is of a slightly different kind from the object, both
00488   /// derived from ClusterSequence).
00489   const std::vector<PseudoJet> & jets()    const;
00490 
00491   /// allow the user to access the raw internal history.
00492   ///
00493   /// This is present (as for jets()) in part so that protected
00494   /// derived classes can access this information about other
00495   /// ClusterSequences.
00496   ///
00497   /// A user who wishes to follow the details of the ClusterSequence
00498   /// can also make use of this information (and should consult the
00499   /// history_element documentation for more information), but should
00500   /// be aware that these internal structures may evolve in future
00501   /// FastJet versions.
00502   const std::vector<history_element> & history() const;
00503 
00504   /// returns the number of particles that were provided to the
00505   /// clustering algorithm (helps the user find their way around the
00506   /// history and jets objects if they weren't paying attention
00507   /// beforehand).
00508   unsigned int n_particles() const;
00509 
00510   /// returns a vector of size n_particles() which indicates, for 
00511   /// each of the initial particles (in the order in which they were
00512   /// supplied), which of the supplied jets it belongs to; if it does
00513   /// not belong to any of the supplied jets, the index is set to -1;
00514   std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
00515 
00516   /// routine that returns an order in which to read the history
00517   /// such that clusterings that lead to identical jet compositions
00518   /// but different histories (because of degeneracies in the
00519   /// clustering order) will have matching constituents for each
00520   /// matching entry in the unique_history_order.
00521   ///
00522   /// The order has the property that an entry's parents will always
00523   /// appear prior to that entry itself. 
00524   ///
00525   /// Roughly speaking the order is such that we first provide all
00526   /// steps that lead to the final jet containing particle 1; then we
00527   /// have the steps that lead to reconstruction of the jet containing
00528   /// the next-lowest-numbered unclustered particle, etc...
00529   /// [see GPS CCN28-12 for more info -- of course a full explanation
00530   /// here would be better...]
00531   std::vector<int> unique_history_order() const;
00532 
00533   /// return the set of particles that have not been clustered. For 
00534   /// kt and cam/aachen algorithms this should always be null, but for
00535   /// cone type algorithms it can be non-null;
00536   std::vector<PseudoJet> unclustered_particles() const;
00537 
00538   /// returns true if the object (jet or particle) is contained by (ie
00539   /// belongs to) this cluster sequence.
00540   ///
00541   /// Tests performed: if thejet's interface is this cluster sequence
00542   /// and its cluster history index is in a consistent range.
00543   bool contains(const PseudoJet & object) const;
00544 
00545   /// transfer the sequence contained in other_seq into our own;
00546   /// any plugin "extras" contained in the from_seq will be lost
00547   /// from there.
00548   ///
00549   /// It also sets the ClusterSequence pointers of the PseudoJets in
00550   /// the history to point to this ClusterSequence
00551   ///
00552   /// When specified, the second argument is an action that will be
00553   /// applied on every jets in the resulting ClusterSequence
00554   void transfer_from_sequence(ClusterSequence & from_seq,
00555                               const FunctionOfPseudoJet<PseudoJet> * action_on_jets = 0);
00556 
00557   /// retrieve a shared pointer to the wrapper to this ClusterSequence
00558   ///
00559   /// this may turn useful if you want to track when this
00560   /// ClusterSequence goes out of scope
00561   const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const{
00562     return _structure_shared_ptr;
00563   }
00564 
00565   /// the structure type associated with a jet belonging to a ClusterSequence
00566   typedef ClusterSequenceStructure StructureType;
00567 
00568 
00569 protected:
00570   static JetAlgorithm _default_jet_algorithm;
00571   JetDefinition _jet_def;
00572 
00573   /// transfer the vector<L> of input jets into our own vector<PseudoJet>
00574   /// _jets (with some reserved space for future growth).
00575   template<class L> void _transfer_input_jets(
00576                                      const std::vector<L> & pseudojets);
00577 
00578   /// This is the routine that will do all the initialisation and
00579   /// then run the clustering (may be called by various constructors).
00580   /// It assumes _jets contains the momenta to be clustered.
00581   void _initialise_and_run (const JetDefinition & jet_def,
00582                             const bool & writeout_combinations);
00583 
00584   /// This is an alternative routine for initialising and running the
00585   /// clustering, provided for legacy purposes. The jet finder is that
00586   /// specified in the static member _default_jet_algorithm.
00587   void _initialise_and_run (const double & R,
00588                             const Strategy & strategy,
00589                             const bool & writeout_combinations);
00590 
00591   /// fills in the various member variables with "decanted" options from
00592   /// the jet_definition and writeout_combinations variables
00593   void _decant_options(const JetDefinition & jet_def,
00594                        const bool & writeout_combinations);
00595 
00596   /// fill out the history (and jet cross refs) related to the initial
00597   /// set of jets (assumed already to have been "transferred"),
00598   /// without any clustering
00599   void _fill_initial_history();
00600 
00601   /// carry out the recombination between the jets numbered jet_i and
00602   /// jet_j, at distance scale dij; return the index newjet_k of the
00603   /// result of the recombination of i and j.
00604   void _do_ij_recombination_step(const int & jet_i, const int & jet_j, 
00605                                  const double & dij, int & newjet_k);
00606 
00607   /// carry out an recombination step in which _jets[jet_i] merges with
00608   /// the beam, 
00609   void _do_iB_recombination_step(const int & jet_i, const double & diB);
00610 
00611   /// every time a jet is added internally during clustering, this
00612   /// should be called to set the jet's structure shared ptr to point
00613   /// to the CS (and the count of internally associated objects is
00614   /// also updated). This should not be called outside construction of
00615   /// a CS object.
00616   void _set_structure_shared_ptr(PseudoJet & j);
00617 
00618   /// make sure that the CS's internal tally of the use count matches
00619   /// that of the _structure_shared_ptr
00620   void _update_structure_use_count();
00621   
00622 
00623   /// This contains the physical PseudoJets; for each PseudoJet one
00624   /// can find the corresponding position in the _history by looking
00625   /// at _jets[i].cluster_hist_index().
00626   std::vector<PseudoJet> _jets;
00627 
00628 
00629   /// this vector will contain the branching history; for each stage,
00630   /// _history[i].jetp_index indicates where to look in the _jets
00631   /// vector to get the physical PseudoJet.
00632   std::vector<history_element> _history;
00633 
00634   /// set subhist to be a set pointers to history entries corresponding to the
00635   /// subjets of this jet; one stops going working down through the
00636   /// subjets either when 
00637   ///   - there is no further to go
00638   ///   - one has found maxjet entries
00639   ///   - max_dij_so_far <= dcut
00640   /// By setting maxjet=0 one can use just dcut; by setting dcut<0
00641   /// one can use jet maxjet
00642   void get_subhist_set(std::set<const history_element*> & subhist,
00643                        const  PseudoJet & jet, double dcut, int maxjet) const;
00644 
00645   bool _writeout_combinations;
00646   int  _initial_n;
00647   double _Rparam, _R2, _invR2;
00648   double _Qtot;
00649   Strategy    _strategy;
00650   JetAlgorithm  _jet_algorithm;
00651 
00652   SharedPtr<PseudoJetStructureBase> _structure_shared_ptr; //< will actually be of type ClusterSequenceStructure
00653   int _structure_use_count_after_construction; //< info of use when CS handles its own memory
00654   /// if true then the CS will delete itself when the last external
00655   /// object referring to it disappears. It is mutable so as to ensure
00656   /// that signal_imminent_self_deletion() [const] can make relevant
00657   /// changes.
00658   mutable bool _deletes_self_when_unused;
00659 
00660  private:
00661 
00662   bool _plugin_activated;
00663   std::auto_ptr<Extras> _extras; // things the plugin might want to add
00664 
00665   void _really_dumb_cluster ();
00666   void _delaunay_cluster ();
00667   //void _simple_N2_cluster ();
00668   template<class BJ> void _simple_N2_cluster ();
00669   void _tiled_N2_cluster ();
00670   void _faster_tiled_N2_cluster ();
00671 
00672   //
00673   void _minheap_faster_tiled_N2_cluster();
00674 
00675   // things needed specifically for Cambridge with Chan's 2D closest
00676   // pairs method
00677   void _CP2DChan_cluster();
00678   void _CP2DChan_cluster_2pi2R ();
00679   void _CP2DChan_cluster_2piMultD ();
00680   void _CP2DChan_limited_cluster(double D);
00681   void _do_Cambridge_inclusive_jets();
00682 
00683   // NSqrtN method for C/A
00684   void _fast_NsqrtN_cluster();
00685 
00686   void _add_step_to_history(const int & step_number, const int & parent1, 
00687                                const int & parent2, const int & jetp_index,
00688                                const double & dij);
00689 
00690   /// internal routine associated with the construction of the unique
00691   /// history order (following children in the tree)
00692   void _extract_tree_children(int pos, std::valarray<bool> &, 
00693                 const std::valarray<int> &, std::vector<int> &) const;
00694 
00695   /// internal routine associated with the construction of the unique
00696   /// history order (following parents in the tree)
00697   void _extract_tree_parents (int pos, std::valarray<bool> &, 
00698                 const std::valarray<int> &,  std::vector<int> &) const;
00699 
00700 
00701   // these will be useful shorthands in the Voronoi-based code
00702   typedef std::pair<int,int> TwoVertices;
00703   typedef std::pair<double,TwoVertices> DijEntry;
00704   typedef std::multimap<double,TwoVertices> DistMap;
00705 
00706   /// currently used only in the Voronoi based code
00707   void _add_ktdistance_to_map(const int & ii, 
00708                               DistMap & DijMap,
00709                               const DynamicNearestNeighbours * DNN);
00710 
00711   /// for making sure the user knows what it is they're running...
00712   void _print_banner();
00713 
00714 
00715   /// will be set by default to be true for the first run
00716   static bool _first_time;
00717 
00718   /// record the number of warnings provided about the exclusive
00719   /// algorithm -- so that we don't print it out more than a few
00720   /// times.
00721   static int _n_exclusive_warnings;
00722 
00723   /// the limited warning member for notification of user that 
00724   /// their requested strategy has been overridden (usually because
00725   /// they have R>2pi and not all strategies work then)
00726   static LimitedWarning _changed_strategy_warning;
00727 
00728   //----------------------------------------------------------------------
00729   /// the fundamental structure which contains the minimal info about
00730   /// a jet, as needed for our plain N^2 algorithm -- the idea is to
00731   /// put all info that will be accessed N^2 times into an array of
00732   /// BriefJets...
00733   struct BriefJet {
00734     double     eta, phi, kt2, NN_dist;
00735     BriefJet * NN;
00736     int        _jets_index;
00737   };
00738 
00739 
00740   /// structure analogous to BriefJet, but with the extra information
00741   /// needed for dealing with tiles
00742   class TiledJet {
00743   public:
00744     double     eta, phi, kt2, NN_dist;
00745     TiledJet * NN, *previous, * next; 
00746     int        _jets_index, tile_index, diJ_posn;
00747     // routines that are useful in the minheap version of tiled
00748     // clustering ("misuse" the otherwise unused diJ_posn, so as
00749     // to indicate whether jets need to have their minheap entries
00750     // updated).
00751     inline void label_minheap_update_needed() {diJ_posn = 1;}
00752     inline void label_minheap_update_done()   {diJ_posn = 0;}
00753     inline bool minheap_update_needed() const {return diJ_posn==1;}
00754   };
00755 
00756   //-- some of the functions that follow are templates and will work
00757   //as well for briefjet and tiled jets
00758 
00759   /// set the kinematic and labelling info for jeta so that it corresponds
00760   /// to _jets[_jets_index]
00761   template <class J> void _bj_set_jetinfo( J * const jet, 
00762                                                  const int _jets_index) const;
00763 
00764   /// "remove" this jet, which implies updating links of neighbours and
00765   /// perhaps modifying the tile structure
00766   void _bj_remove_from_tiles( TiledJet * const jet) const;
00767 
00768   /// return the distance between two BriefJet objects
00769   template <class J> double _bj_dist(const J * const jeta, 
00770                         const J * const jetb) const;
00771 
00772   // return the diJ (multiplied by _R2) for this jet assuming its NN
00773   // info is correct
00774   template <class J> double _bj_diJ(const J * const jeta) const;
00775 
00776   /// for testing purposes only: if in the range head--tail-1 there is a
00777   /// a jet which corresponds to hist_index in the history, then
00778   /// return a pointer to that jet; otherwise return tail.
00779   template <class J> inline J * _bj_of_hindex(
00780                           const int hist_index, 
00781                           J * const head, J * const tail) 
00782     const {
00783     J * res;
00784     for(res = head; res<tail; res++) {
00785       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00786     }
00787     return res;
00788   }
00789 
00790 
00791   //-- remaining functions are different in various cases, so we
00792   //   will use templates but are not sure if they're useful...
00793 
00794   /// updates (only towards smaller distances) the NN for jeta without checking
00795   /// whether in the process jeta itself might be a new NN of one of
00796   /// the jets being scanned -- span the range head to tail-1 with
00797   /// assumption that jeta is not contained in that range
00798   template <class J> void _bj_set_NN_nocross(J * const jeta, 
00799             J * const head, const J * const tail) const;
00800 
00801   /// reset the NN for jeta and DO check whether in the process jeta
00802   /// itself might be a new NN of one of the jets being scanned --
00803   /// span the range head to tail-1 with assumption that jeta is not
00804   /// contained in that range
00805   template <class J> void _bj_set_NN_crosscheck(J * const jeta, 
00806             J * const head, const J * const tail) const;
00807   
00808 
00809 
00810   /// number of neighbours that a tile will have (rectangular geometry
00811   /// gives 9 neighbours).
00812   static const int n_tile_neighbours = 9;
00813   //----------------------------------------------------------------------
00814   /// The fundamental structures to be used for the tiled N^2 algorithm
00815   /// (see CCN27-44 for some discussion of pattern of tiling)
00816   struct Tile {
00817     /// pointers to neighbouring tiles, including self
00818     Tile *   begin_tiles[n_tile_neighbours]; 
00819     /// neighbouring tiles, excluding self
00820     Tile **  surrounding_tiles; 
00821     /// half of neighbouring tiles, no self
00822     Tile **  RH_tiles;  
00823     /// just beyond end of tiles
00824     Tile **  end_tiles; 
00825     /// start of list of BriefJets contained in this tile
00826     TiledJet * head;    
00827     /// sometimes useful to be able to tag a tile
00828     bool     tagged;    
00829   };
00830   std::vector<Tile> _tiles;
00831   double _tiles_eta_min, _tiles_eta_max;
00832   double _tile_size_eta, _tile_size_phi;
00833   int    _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
00834 
00835   // reasonably robust return of tile index given ieta and iphi, in particular
00836   // it works even if iphi is negative
00837   inline int _tile_index (int ieta, int iphi) const {
00838     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00839     // before performing modulo operation
00840     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00841                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00842   }
00843 
00844   // routines for tiled case, including some overloads of the plain
00845   // BriefJet cases
00846   int  _tile_index(const double & eta, const double & phi) const;
00847   void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
00848   void  _bj_remove_from_tiles(TiledJet * const jet);
00849   void _initialise_tiles();
00850   void _print_tiles(TiledJet * briefjets ) const;
00851   void _add_neighbours_to_tile_union(const int tile_index, 
00852                  std::vector<int> & tile_union, int & n_near_tiles) const;
00853   void _add_untagged_neighbours_to_tile_union(const int tile_index, 
00854                  std::vector<int> & tile_union, int & n_near_tiles);
00855 
00856 
00857   //----------------------------------------------------------------------
00858   /// fundamental structure for e+e- clustering
00859   struct EEBriefJet {
00860     double NN_dist;  // obligatorily present
00861     double kt2;      // obligatorily present == E^2 in general
00862     EEBriefJet * NN; // must be present too
00863     int    _jets_index; // must also be present!
00864     //...........................................................
00865     double nx, ny, nz;  // our internal storage for fast distance calcs
00866   };
00867 
00868   /// to help instantiation (fj 2.4.0; did not quite work on gcc 33 and os x 10.3?)
00869   //void _dummy_N2_cluster_instantiation();
00870 
00871 
00872   /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
00873   void _simple_N2_cluster_BriefJet();
00874   /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
00875   void _simple_N2_cluster_EEBriefJet();
00876 };
00877 
00878 
00879 //**********************************************************************
00880 //**************    START   OF   INLINE   MATERIAL    ******************
00881 //**********************************************************************
00882 
00883 
00884 //----------------------------------------------------------------------
00885 // Transfer the initial jets into our internal structure
00886 template<class L> void ClusterSequence::_transfer_input_jets(
00887                                        const std::vector<L> & pseudojets) {
00888 
00889   // this will ensure that we can point to jets without difficulties
00890   // arising.
00891   _jets.reserve(pseudojets.size()*2);
00892 
00893   // insert initial jets this way so that any type L that can be
00894   // converted to a pseudojet will work fine (basically PseudoJet
00895   // and any type that has [] subscript access to the momentum
00896   // components, such as CLHEP HepLorentzVector).
00897   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00898     _jets.push_back(pseudojets[i]);}
00899   
00900 }
00901 
00902 //----------------------------------------------------------------------
00903 // initialise from some generic type... Has to be made available
00904 // here in order for it the template aspect of it to work...
00905 template<class L> ClusterSequence::ClusterSequence (
00906                                   const std::vector<L> & pseudojets,
00907                                   const double & R,
00908                                   const Strategy & strategy,
00909                                   const bool & writeout_combinations) {
00910 
00911   // transfer the initial jets (type L) into our own array
00912   _transfer_input_jets(pseudojets);
00913 
00914   // run the clustering
00915   _initialise_and_run(R,strategy,writeout_combinations);
00916 }
00917 
00918 
00919 //----------------------------------------------------------------------
00920 /// constructor of a jet-clustering sequence from a vector of
00921 /// four-momenta, with the jet definition specified by jet_def
00922 template<class L> ClusterSequence::ClusterSequence (
00923                                   const std::vector<L> & pseudojets,
00924                                   const JetDefinition & jet_def,
00925                                   const bool & writeout_combinations) {
00926 
00927   // transfer the initial jets (type L) into our own array
00928   _transfer_input_jets(pseudojets);
00929 
00930   // run the clustering
00931   _initialise_and_run(jet_def,writeout_combinations);
00932 }
00933 
00934 
00935 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
00936   return _jets;
00937 }
00938 
00939 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
00940   return _history;
00941 }
00942 
00943 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
00944 
00945 
00946 
00947 //----------------------------------------------------------------------
00948 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
00949                             J * const jetA, const int _jets_index) const {
00950     jetA->eta  = _jets[_jets_index].rap();
00951     jetA->phi  = _jets[_jets_index].phi_02pi();
00952     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
00953     jetA->_jets_index = _jets_index;
00954     // initialise NN info as well
00955     jetA->NN_dist = _R2;
00956     jetA->NN      = NULL;
00957 }
00958 
00959 
00960 
00961 
00962 //----------------------------------------------------------------------
00963 template <class J> inline double ClusterSequence::_bj_dist(
00964                 const J * const jetA, const J * const jetB) const {
00965   double dphi = std::abs(jetA->phi - jetB->phi);
00966   double deta = (jetA->eta - jetB->eta);
00967   if (dphi > pi) {dphi = twopi - dphi;}
00968   return dphi*dphi + deta*deta;
00969 }
00970 
00971 //----------------------------------------------------------------------
00972 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
00973   double kt2 = jet->kt2;
00974   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00975   return jet->NN_dist * kt2;
00976 }
00977 
00978 
00979 //----------------------------------------------------------------------
00980 // set the NN for jet without checking whether in the process you might
00981 // have discovered a new nearest neighbour for another jet
00982 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
00983                  J * const jet, J * const head, const J * const tail) const {
00984   double NN_dist = _R2;
00985   J * NN  = NULL;
00986   if (head < jet) {
00987     for (J * jetB = head; jetB != jet; jetB++) {
00988       double dist = _bj_dist(jet,jetB);
00989       if (dist < NN_dist) {
00990         NN_dist = dist;
00991         NN = jetB;
00992       }
00993     }
00994   }
00995   if (tail > jet) {
00996     for (J * jetB = jet+1; jetB != tail; jetB++) {
00997       double dist = _bj_dist(jet,jetB);
00998       if (dist < NN_dist) {
00999         NN_dist = dist;
01000         NN = jetB;
01001       }
01002     }
01003   }
01004   jet->NN = NN;
01005   jet->NN_dist = NN_dist;
01006 }
01007 
01008 
01009 //----------------------------------------------------------------------
01010 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet, 
01011                     J * const head, const J * const tail) const {
01012   double NN_dist = _R2;
01013   J * NN  = NULL;
01014   for (J * jetB = head; jetB != tail; jetB++) {
01015     double dist = _bj_dist(jet,jetB);
01016     if (dist < NN_dist) {
01017       NN_dist = dist;
01018       NN = jetB;
01019     }
01020     if (dist < jetB->NN_dist) {
01021       jetB->NN_dist = dist;
01022       jetB->NN = jet;
01023     }
01024   }
01025   jet->NN = NN;
01026   jet->NN_dist = NN_dist;
01027 }
01028 
01029 
01030 
01031 FASTJET_END_NAMESPACE
01032 
01033 #endif // __FASTJET_CLUSTERSEQUENCE_HH__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends