FastJet 3.0alpha3
PseudoJet.hh
00001 //STARTHEADER
00002 // $Id: PseudoJet.hh 2224 2011-06-03 14:22:31Z salam $
00003 //
00004 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin Salam and Gregory Soyez
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_PSEUDOJET_HH__
00033 #define __FASTJET_PSEUDOJET_HH__
00034 
00035 #include<valarray>
00036 #include<vector>
00037 #include<cassert>
00038 #include<cmath>
00039 #include<iostream>
00040 #include "fastjet/internal/numconsts.hh"
00041 #include "fastjet/internal/IsBase.hh"
00042 #include "fastjet/SharedPtr.hh"
00043 #include "fastjet/Error.hh"
00044 #include "fastjet/PseudoJetStructureBase.hh"
00045 
00046 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00047 
00048 //using namespace std;
00049 
00050 /// Used to protect against parton-level events where pt can be zero
00051 /// for some partons, giving rapidity=infinity. KtJet fails in those cases.
00052 const double MaxRap = 1e5;
00053 
00054 /// default value for phi, meaning it (and rapidity) have yet to be calculated) 
00055 const double pseudojet_invalid_phi = -100.0;
00056 
00057 // forward definition
00058 class ClusterSequenceAreaBase;
00059 
00060 /// @ingroup basic_classes
00061 /// \class PseudoJet
00062 /// Class to contain pseudojets, including minimal information of use to
00063 /// jet-clustering routines.
00064 class PseudoJet {
00065 
00066  public:
00067   //----------------------------------------------------------------------
00068   /// @name Constructors and destructor
00069   //\{
00070   /// default constructor, which as of FJ3.0 provides an object for
00071   /// which all operations are now valid and which has zero momentum
00072   ///
00073   // (cf. this is actually OK from a timing point of view and in some
00074   // cases better than just having the default constructor for the
00075   // internal shared pointer: see PJtiming.cc and the notes therein)
00076   PseudoJet() : _px(0), _py(0), _pz(0), _E(0) {_finish_init(); _reset_indices();}
00077 
00078   /// construct a pseudojet from explicit components
00079   PseudoJet(const double px, const double py, const double pz, const double E);
00080   /// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
00081   template <class L> PseudoJet(const L & some_four_vector) ;
00082 
00083   /// default (virtual) destructor
00084   virtual ~PseudoJet(){};
00085   //\} ---- end of constructors and destructors --------------------------
00086 
00087   //----------------------------------------------------------------------
00088   /// @name Kinematic access functions
00089   //\{
00090   //----------------------------------------------------------------------
00091   inline double E()   const {return _E;}
00092   inline double e()   const {return _E;} // like CLHEP
00093   inline double px()  const {return _px;}
00094   inline double py()  const {return _py;}
00095   inline double pz()  const {return _pz;}
00096 
00097   /// returns phi (in the range 0..2pi)
00098   inline double phi() const {return phi_02pi();}
00099 
00100   /// returns phi in the range -pi..pi
00101   inline double phi_std()  const {
00102     _ensure_valid_rap_phi();
00103     return _phi > pi ? _phi-twopi : _phi;}
00104 
00105   /// returns phi in the range 0..2pi
00106   inline double phi_02pi() const {
00107     _ensure_valid_rap_phi();
00108     return _phi;
00109   }
00110 
00111   /// returns the rapidity or some large value when the rapidity
00112   /// is infinite
00113   inline double rap() const {
00114     _ensure_valid_rap_phi();
00115     return _rap;
00116   }
00117 
00118   /// the same as rap()
00119   inline double rapidity() const {return rap();} // like CLHEP
00120 
00121   /// returns the pseudo-rapidity or some large value when the
00122   /// rapidity is infinite
00123   double pseudorapidity() const;
00124   double eta() const {return pseudorapidity();}
00125 
00126   /// returns the squared transverse momentum
00127   inline double kt2() const {return _kt2;}
00128   /// returns the squared transverse momentum
00129   inline double perp2() const {return _kt2;}  // like CLHEP
00130   /// returns the scalar transverse momentum
00131   inline double  perp() const {return sqrt(_kt2);}    // like CLHEP
00132   /// returns the squared invariant mass // like CLHEP
00133   inline double  m2() const {return (_E+_pz)*(_E-_pz)-_kt2;}    
00134   /// returns the squared transverse mass = kt^2+m^2
00135   inline double mperp2() const {return (_E+_pz)*(_E-_pz);}
00136   /// returns the transverse mass = sqrt(kt^2+m^2)
00137   inline double mperp() const {return sqrt(std::abs(mperp2()));}
00138   /// returns the invariant mass 
00139   /// (If m2() is negative then -sqrt(-m2()) is returned, as in CLHEP)
00140   inline double  m() const;    
00141   /// return px^2+py^2+pz^2
00142   inline double modp2() const {return _kt2+_pz*_pz;}
00143   /// return the transverse energy
00144   inline double Et() const {return (_kt2==0) ? 0.0 : _E/sqrt(1.0+_pz*_pz/_kt2);}
00145   /// return the transverse energy squared
00146   inline double Et2() const {return (_kt2==0) ? 0.0 : _E*_E/(1.0+_pz*_pz/_kt2);}
00147 
00148   /// returns component i, where X==0, Y==1, Z==2, E==3
00149   double operator () (int i) const ; 
00150   /// returns component i, where X==0, Y==1, Z==2, E==3
00151   inline double operator [] (int i) const { return (*this)(i); }; // this too
00152 
00153 
00154 
00155   /// returns kt distance (R=1) between this jet and another
00156   double kt_distance(const PseudoJet & other) const;
00157 
00158   /// returns squared cylinder (rap-phi) distance between this jet and another
00159   double plain_distance(const PseudoJet & other) const;
00160   /// returns squared cylinder (rap-phi) distance between this jet and
00161   /// another
00162   inline double squared_distance(const PseudoJet & other) const {
00163     return plain_distance(other);}
00164 
00165   /// return the cylinder (rap-phi) distance between this jet and another,
00166   /// \f$\Delta_R = \sqrt{\Delta y^2 + \Delta \phi^2}\f$.
00167   inline double delta_R(const PseudoJet & other) const {
00168     return sqrt(squared_distance(other));
00169   }
00170 
00171   /// returns other.phi() - this.phi(), constrained to be in 
00172   /// range -pi .. pi
00173   double delta_phi_to(const PseudoJet & other) const;
00174 
00175   //// this seemed to compile except if it was used
00176   //friend inline double 
00177   //  kt_distance(const PseudoJet & jet1, const PseudoJet & jet2) { 
00178   //                                      return jet1.kt_distance(jet2);}
00179 
00180   /// returns distance between this jet and the beam
00181   inline double beam_distance() const {return _kt2;}
00182 
00183   /// return a valarray containing the four-momentum (components 0-2
00184   /// are 3-mom, component 3 is energy).
00185   std::valarray<double> four_mom() const;
00186 
00187   //\}  ------- end of kinematic access functions
00188 
00189   // taken from CLHEP
00190   enum { X=0, Y=1, Z=2, T=3, NUM_COORDINATES=4, SIZE=NUM_COORDINATES };
00191 
00192 
00193   //----------------------------------------------------------------------
00194   /// @name Kinematic modification functions
00195   //\{
00196   //----------------------------------------------------------------------
00197   /// transform this jet (given in the rest frame of prest) into a jet
00198   /// in the lab frame [NOT FULLY TESTED]
00199   PseudoJet & boost(const PseudoJet & prest);
00200   /// transform this jet (given in lab) into a jet in the rest
00201   /// frame of prest  [NOT FULLY TESTED]
00202   PseudoJet & unboost(const PseudoJet & prest);
00203 
00204   void operator*=(double);
00205   void operator/=(double);
00206   void operator+=(const PseudoJet &);
00207   void operator-=(const PseudoJet &);
00208 
00209   /// reset the 4-momentum according to the supplied components and
00210   /// put the user and history indices back to their default values
00211   inline void reset(double px, double py, double pz, double E);
00212   
00213   /// reset the PseudoJet to be equal to psjet (including its
00214   /// indices); NB if the argument is derived from a PseudoJet then
00215   /// the "reset" used will be the templated version
00216   ///
00217   /// Note: this is included on top of the templated version because
00218   /// PseudoJet is not "derived" from PseudoJet, so the templated
00219   /// reset would not handle this case properly.
00220   inline void reset(const PseudoJet & psjet) {
00221     (*this) = psjet;
00222   }
00223 
00224   /// reset the 4-momentum according to the supplied generic 4-vector
00225   /// (accessible via indexing, [0]==px,...[3]==E) and put the user
00226   /// and history indices back to their default values.
00227   template <class L> inline void reset(const L & some_four_vector) {
00228     // check if some_four_vector can be cast to a PseudoJet
00229     //
00230     // Note that a regular dynamic_cast would not work here because
00231     // there is no guarantee that L is polymorphic. We use a more
00232     // complex construct here that works also in such a case. As for
00233     // dynamic_cast, NULL is returned if L is not derived from
00234     // PseudoJet
00235     const PseudoJet * pj = cast_if_derived<const PseudoJet>(&some_four_vector);
00236 
00237     if (pj){
00238       (*this) = *pj;
00239     } else {
00240       reset(some_four_vector[0], some_four_vector[1],
00241             some_four_vector[2], some_four_vector[3]);
00242     }
00243   }
00244 
00245   /// reset the 4-momentum according to the supplied components 
00246   /// but leave all other information (indices, user info, etc.)
00247   /// untouched
00248   inline void reset_momentum(double px, double py, double pz, double E);
00249 
00250   /// reset the 4-momentum according to the supplied generic 4-vector
00251   /// (accessible via indexing, [0]==px,...[3]==E), but leave all
00252   /// other information (indices, user info, etc.)  untouched
00253   template <class L> inline void reset_momentum(const L & some_four_vector) {
00254     reset_momentum(some_four_vector[0], some_four_vector[1],
00255                    some_four_vector[2], some_four_vector[3]);
00256   }
00257 
00258   /// in some cases when setting a 4-momentum, the user/program knows
00259   /// what rapidity and azimuth are associated with that 4-momentum;
00260   /// by calling this routine the user can provide the information
00261   /// directly to the PseudoJet and avoid expensive rap-phi
00262   /// recalculations.
00263   ///
00264   /// - \param rap  rapidity
00265   /// - \param phi  (in range -twopi...twopi)
00266   ///
00267   /// USE WITH CAUTION: there are no checks that the rapidity and
00268   /// azimuth supplied are sensible, nor does this reset the
00269   /// 4-momentum components if things don't match.
00270   inline void set_cached_rap_phi(double rap, double phi) {
00271     _rap = rap; _phi = phi;
00272     if (_phi < 0) _phi += twopi;
00273   }
00274 
00275 
00276   //\} --- end of kin mod functions ------------------------------------
00277 
00278   //----------------------------------------------------------------------
00279   /// @name User index functions
00280   ///
00281   /// To allow the user to set and access an integer index which can
00282   /// be exploited by the user to associate extra information with a
00283   /// particle/jet (for example pdg id, or an indication of a
00284   /// particle's origin within the user's analysis)
00285   //
00286   //\{
00287 
00288   /// return the user_index, 
00289   inline int user_index() const {return _user_index;}
00290   /// set the user_index, intended to allow the user to add simple
00291   /// identifying information to a particle/jet
00292   inline void set_user_index(const int index) {_user_index = index;}
00293 
00294   //\} ----- end of use index functions ---------------------------------
00295 
00296   //----------------------------------------------------------------------
00297   /// @name User information types and functions
00298   ///
00299   /// Allows PseudoJet to carry extra user info (as an object derived from
00300   /// UserInfoBase).
00301   //\{
00302 
00303   /// @ingroup user_info
00304   /// \class UserInfoBase
00305   /// a base class to hold extra user information in a PseudoJet
00306   ///
00307   /// This is a base class to help associate extra user information
00308   /// with a jet. The user should store their information in a class
00309   /// derived from this. This allows information of arbitrary
00310   /// complexity to be easily associated with a PseudoJet (in contrast
00311   /// to the user index). For example, in a Monte Carlo simulation,
00312   /// the user information might include the PDG ID, and the position
00313   /// of the production vertex for the particle.
00314   ///
00315   /// The PseudoJet is able to store a shared pointer to any object
00316   /// derived from UserInfo. The use of a shared pointer frees the
00317   /// user of the need to handle the memory management associated with
00318   /// the information.
00319   ///
00320   /// Having the user information derive from a common base class also
00321   /// facilitates dynamic casting, etc.
00322   ///
00323   class UserInfoBase{
00324   public:
00325     // dummy ctor
00326     UserInfoBase(){};
00327 
00328     // dummy virtual dtor
00329     // makes it polymorphic to allow for dynamic_cast
00330     virtual ~UserInfoBase(){}; 
00331   };
00332 
00333   /// error class to be thrown if accessing user info when it doesn't
00334   /// exist
00335   class InexistentUserInfo : public Error {
00336   public:
00337     InexistentUserInfo();
00338   };
00339 
00340   /// sets the internal shared pointer to the user information.
00341   ///
00342   /// Note that the PseudoJet will now _own_ the pointer, and delete
00343   /// the corresponding object when it (the jet, and any copies of the jet)
00344   /// goes out of scope. 
00345   void set_user_info(UserInfoBase * user_info_in) {
00346     _user_info.reset(user_info_in);
00347   }
00348 
00349   /// returns a reference to the dynamic cast conversion of user_info
00350   /// to type L.
00351   ///
00352   /// Usage: suppose you have previously set the user info with a pointer
00353   /// to an object of type MyInfo, 
00354   ///
00355   ///   class MyInfo: public PseudoJet::UserInfoBase {
00356   ///      MyInfo(int id) : _pdg_id(id);
00357   ///      int pdg_id() const {return _pdg_id;}
00358   ///      int _pdg_id;
00359   ///   };
00360   ///
00361   ///   PseudoJet particle(...);
00362   ///   particle.set_user_info(new MyInfo(its_pdg_id));
00363   ///
00364   /// Then you would access that pdg_id() as
00365   ///
00366   ///   particle.user_info<MyInfo>().pdg_id();
00367   ///
00368   /// It's overkill for just a single integer, but scales easily to
00369   /// more extensive information.
00370   ///
00371   /// Note that user_info() throws an InexistentUserInfo() error if
00372   /// there is no user info; throws a std::bad_cast if the conversion
00373   /// doesn't work
00374   ///
00375   /// If this behaviour does not fit your needs, use instead the the
00376   /// user_info_ptr() or user_info_shared_ptr() member functions.
00377   template<class L>
00378   const L & user_info() const{
00379     if (_user_info.get() == 0) throw InexistentUserInfo();
00380     return dynamic_cast<const L &>(* _user_info.get());
00381   }
00382 
00383   /// retrieve a pointer to the (const) user information
00384   const UserInfoBase * user_info_ptr() const{
00385     if (!_user_info()) return NULL;
00386     return _user_info.get();
00387   }
00388 
00389 
00390   /// retrieve a (const) shared pointer to the user information
00391   const SharedPtr<UserInfoBase> & user_info_shared_ptr() const{
00392     return _user_info;
00393   }
00394 
00395   /// retrieve a (non-const) shared pointer to the user information;
00396   /// you can use this, for example, to set the shared pointer, eg
00397   ///
00398   /// \code
00399   ///   p2.user_info_shared_ptr() = p1.user_info_shared_ptr();
00400   /// \endcode
00401   ///
00402   /// or 
00403   ///
00404   /// \code
00405   ///   SharedPtr<PseudoJet::UserInfoBase> info_shared(new MyInfo(...));
00406   ///   p2.user_info_shared_ptr() = info_shared;
00407   /// \endcode
00408   SharedPtr<UserInfoBase> & user_info_shared_ptr(){
00409     return _user_info;
00410   }
00411 
00412   // \} --- end of extra info functions ---------------------------------
00413 
00414   //----------------------------------------------------------------------
00415   /// @name Description
00416   ///
00417   /// Since a PseudoJet can have a structure that contains a variety
00418   /// of information, we provide a description that allows one to check
00419   /// exactly what kind of PseudoJet we are dealing with
00420   //
00421   //\{
00422 
00423   /// return a string describing what kind of PseudoJet we are dealing with 
00424   std::string description() const;
00425 
00426   //\} ----- end of description functions ---------------------------------
00427 
00428   //-------------------------------------------------------------
00429   /// @name Access to the associated ClusterSequence object.
00430   ///
00431   /// In addition to having kinematic information, jets may contain a
00432   /// reference to an associated ClusterSequence (this is the case,
00433   /// for example, if the jet has been returned by a ClusterSequence
00434   /// member function).
00435   //\{
00436   //-------------------------------------------------------------
00437   /// returns true if this PseudoJet has an associated ClusterSequence.
00438   bool has_associated_cluster_sequence() const;
00439 
00440   /// returns true if this PseudoJet has an associated and still
00441   /// valid ClusterSequence.
00442   bool has_valid_cluster_sequence() const;
00443 
00444   /// get a (const) pointer to the parent ClusterSequence (NULL if
00445   /// inexistent)
00446   const ClusterSequence* associated_cluster_sequence() const;
00447 
00448   /// if the jet has a valid associated cluster sequence then return a
00449   /// pointer to it; otherwise throw an error
00450   const ClusterSequence * validated_cs() const;
00451 
00452   /// if the jet has valid area information then return a pointer to
00453   /// the associated ClusterSequenceAreaBase object; otherwise throw an error
00454   const ClusterSequenceAreaBase * validated_csab() const;
00455 
00456   //\}
00457 
00458   //-------------------------------------------------------------
00459   /// @name Access to the associated PseudoJetStructureBase object.
00460   ///
00461   /// In addition to having kinematic information, jets may contain a
00462   /// reference to an associated ClusterSequence (this is the case,
00463   /// for example, if the jet has been returned by a ClusterSequence
00464   /// member function).
00465   //\{
00466   //-------------------------------------------------------------
00467 
00468   /// set the associated structure
00469   void set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure);
00470 
00471   /// return true if there is some structure associated with this PseudoJet
00472   bool has_structure() const;
00473 
00474   /// return a pointer to the structure (of type
00475   /// PseudoJetStructureBase*) associated with this PseudoJet.
00476   ///
00477   /// return NULL if there is no associated structure
00478   const PseudoJetStructureBase* structure_ptr() const;
00479   
00480   /// return a non-const pointer to the structure (of type
00481   /// PseudoJetStructureBase*) associated with this PseudoJet.
00482   ///
00483   /// return NULL if there is no associated structure
00484   ///
00485   /// Only use this if you know what you are doing. In any case,
00486   /// prefer the 'structure_ptr()' (the const version) to this method,
00487   /// unless you really need a write access to the PseudoJet's
00488   /// underlying structure.
00489   PseudoJetStructureBase* structure_non_const_ptr();
00490   
00491   /// return a pointer to the structure (of type
00492   /// PseudoJetStructureBase*) associated with this PseudoJet.
00493   ///
00494   /// throw an error if there is no associated structure
00495   const PseudoJetStructureBase* validated_structure_ptr() const;
00496   
00497   /// return a reference to the shared pointer to the
00498   /// PseudoJetStructureBase associated with this PseudoJet
00499   const SharedPtr<PseudoJetStructureBase> & structure_shared_ptr() const;
00500 
00501   /// returns a reference to the structure casted to the requested
00502   /// structure type
00503   ///
00504   /// If there is no sructure associated, an Error is thrown.
00505   /// If the type is not met, a std::bad_cast error is thrown.
00506   template<typename StructureType>
00507   const StructureType & structure() const;
00508 
00509   /// check if the PseudoJet has the structure resulting from a Transformer 
00510   /// (that is, its structure is compatible with a Transformer::StructureType)
00511   /// if there is no structure, false is returned
00512   template<typename TransformerType>
00513   bool has_structure_of() const;
00514 
00515   /// this is a helper to access an structuree created by a Transformer 
00516   /// (that is, of type Transformer::StructureType)
00517   /// NULL is returned if the corresponding type is not met
00518   /// if there is no structure, an error is thrown
00519   template<typename TransformerType>
00520   const typename TransformerType::StructureType & structure_of() const;
00521 
00522   //\}
00523 
00524   //-------------------------------------------------------------
00525   /// @name Methods for access to information about jet structure
00526   ///
00527   /// These allow access to jet constituents, and other jet
00528   /// subtructure information. They only work if the jet is associated
00529   /// with a ClusterSequence.
00530   //-------------------------------------------------------------
00531   //\{
00532 
00533   /// check if it has been recombined with another PseudoJet in which
00534   /// case, return its partner through the argument. Otherwise,
00535   /// 'partner' is set to 0.
00536   ///
00537   /// an Error is thrown if this PseudoJet has no currently valid
00538   /// associated ClusterSequence
00539   virtual bool has_partner(PseudoJet &partner) const;
00540 
00541   /// check if it has been recombined with another PseudoJet in which
00542   /// case, return its child through the argument. Otherwise, 'child'
00543   /// is set to 0.
00544   /// 
00545   /// an Error is thrown if this PseudoJet has no currently valid
00546   /// associated ClusterSequence
00547   virtual bool has_child(PseudoJet &child) const;
00548 
00549   /// check if it is the product of a recombination, in which case
00550   /// return the 2 parents through the 'parent1' and 'parent2'
00551   /// arguments. Otherwise, set these to 0.
00552   ///
00553   /// an Error is thrown if this PseudoJet has no currently valid
00554   /// associated ClusterSequence
00555   virtual bool has_parents(PseudoJet &parent1, PseudoJet &parent2) const;
00556 
00557   /// check if the current PseudoJet contains the one passed as
00558   /// argument.
00559   ///
00560   /// an Error is thrown if this PseudoJet has no currently valid
00561   /// associated ClusterSequence
00562   virtual bool contains(const PseudoJet &constituent) const;
00563 
00564   /// check if the current PseudoJet is contained the one passed as
00565   /// argument.
00566   ///
00567   /// an Error is thrown if this PseudoJet has no currently valid
00568   /// associated ClusterSequence
00569   virtual bool is_inside(const PseudoJet &jet) const;
00570 
00571 
00572   /// returns true if the PseudoJet has constituents
00573   virtual bool has_constituents() const;
00574 
00575   /// retrieve the constituents. 
00576   ///
00577   /// an Error is thrown if this PseudoJet has no currently valid
00578   /// associated ClusterSequence or other substructure information
00579   virtual std::vector<PseudoJet> constituents() const;
00580 
00581 
00582   /// returns true if the PseudoJet has support for exclusive subjets
00583   virtual bool has_exclusive_subjets() const;
00584 
00585   /// return a vector of all subjets of the current jet (in the sense
00586   /// of the exclusive algorithm) that would be obtained when running
00587   /// the algorithm with the given dcut. 
00588   ///
00589   /// Time taken is O(m ln m), where m is the number of subjets that
00590   /// are found. If m gets to be of order of the total number of
00591   /// constituents in the jet, this could be substantially slower than
00592   /// just getting that list of constituents.
00593   ///
00594   /// an Error is thrown if this PseudoJet has no currently valid
00595   /// associated ClusterSequence
00596   std::vector<PseudoJet> exclusive_subjets (const double & dcut) const;
00597 
00598   /// return the size of exclusive_subjets(...); still n ln n with same
00599   /// coefficient, but marginally more efficient than manually taking
00600   /// exclusive_subjets.size()
00601   ///
00602   /// an Error is thrown if this PseudoJet has no currently valid
00603   /// associated ClusterSequence
00604   int n_exclusive_subjets(const double & dcut) const;
00605 
00606   /// return the list of subjets obtained by unclustering the supplied
00607   /// jet down to n subjets (or all constituents if there are fewer
00608   /// than n).
00609   ///
00610   /// requires n ln n time
00611   ///
00612   /// an Error is thrown if this PseudoJet has no currently valid
00613   /// associated ClusterSequence
00614   std::vector<PseudoJet> exclusive_subjets (int nsub) const;
00615 
00616   /// return the dij that was present in the merging nsub+1 -> nsub 
00617   /// subjets inside this jet.
00618   ///
00619   /// an Error is thrown if this PseudoJet has no currently valid
00620   /// associated ClusterSequence
00621   double exclusive_subdmerge(int nsub) const;
00622 
00623   /// return the maximum dij that occurred in the whole event at the
00624   /// stage that the nsub+1 -> nsub merge of subjets occurred inside 
00625   /// this jet.
00626   ///
00627   /// an Error is thrown if this PseudoJet has no currently valid
00628   /// associated ClusterSequence
00629   double exclusive_subdmerge_max(int nsub) const;
00630 
00631 
00632   /// returns true if a jet has pieces
00633   ///
00634   /// By default a single particle or a jet coming from a
00635   /// ClusterSequence have no pieces and this methos will return false.
00636   ///
00637   /// In practice, this is equivalent to have an structure of type
00638   /// CompositeJetStructure.
00639   virtual bool has_pieces() const;
00640 
00641 
00642   /// retrieve the pieces that make up the jet. 
00643   ///
00644   /// If the jet does not support pieces, an error is throw
00645   virtual std::vector<PseudoJet> pieces() const;
00646 
00647 
00648   // the following ones require a computation of the area in the
00649   // parent ClusterSequence (See ClusterSequenceAreaBase for details)
00650   //------------------------------------------------------------------
00651 
00652   /// check if it has a defined area
00653   virtual bool has_area() const;
00654 
00655   /// return the jet (scalar) area.
00656   /// throws an Error if there is no support for area in the parent CS
00657   virtual double area() const;
00658 
00659   /// return the error (uncertainty) associated with the determination
00660   /// of the area of this jet.
00661   /// throws an Error if there is no support for area in the parent CS
00662   virtual double area_error() const;
00663 
00664   /// return the jet 4-vector area.
00665   /// throws an Error if there is no support for area in the parent CS
00666   virtual PseudoJet area_4vector() const;
00667 
00668   /// true if this jet is made exclusively of ghosts.
00669   /// throws an Error if there is no support for area in the parent CS
00670   virtual bool is_pure_ghost() const;
00671 
00672   //\} --- end of jet structure -------------------------------------
00673 
00674 
00675 
00676   //----------------------------------------------------------------------
00677   /// @name Members mainly intended for internal use
00678   //----------------------------------------------------------------------
00679   //\{
00680   /// return the cluster_hist_index, intended to be used by clustering
00681   /// routines.
00682   inline int cluster_hist_index() const {return _cluster_hist_index;}
00683   /// set the cluster_hist_index, intended to be used by clustering routines.
00684   inline void set_cluster_hist_index(const int index) {_cluster_hist_index = index;}
00685 
00686   /// alternative name for cluster_hist_index() [perhaps more meaningful]
00687   inline int cluster_sequence_history_index() const {
00688     return cluster_hist_index();}
00689   /// alternative name for set_cluster_hist_index(...) [perhaps more
00690   /// meaningful]
00691   inline void set_cluster_sequence_history_index(const int index) {
00692     set_cluster_hist_index(index);}
00693 
00694   //\} ---- end of internal use functions ---------------------------
00695 
00696  protected:  
00697 
00698   SharedPtr<PseudoJetStructureBase> _structure;
00699   SharedPtr<UserInfoBase> _user_info;
00700 
00701 
00702  private: 
00703   // NB: following order must be kept for things to behave sensibly...
00704   double _px,_py,_pz,_E;
00705   mutable double _phi, _rap;
00706   double _kt2; 
00707   int    _cluster_hist_index, _user_index;
00708 
00709   /// calculate phi, rap, kt2 based on the 4-momentum components
00710   void _finish_init();
00711   /// set the indices to default values
00712   void _reset_indices();
00713 
00714   /// ensure that the internal values for rapidity and phi 
00715   /// correspond to 4-momentum structure
00716   inline void _ensure_valid_rap_phi() const {
00717     if (_phi == pseudojet_invalid_phi) _set_rap_phi();
00718   }
00719 
00720   /// set cached rapidity and phi values
00721   void _set_rap_phi() const;
00722 };
00723 
00724 
00725 //----------------------------------------------------------------------
00726 // routines for basic binary operations
00727 
00728 PseudoJet operator+(const PseudoJet &, const PseudoJet &);
00729 PseudoJet operator-(const PseudoJet &, const PseudoJet &);
00730 PseudoJet operator*(double, const PseudoJet &);
00731 PseudoJet operator*(const PseudoJet &, double);
00732 PseudoJet operator/(const PseudoJet &, double);
00733 
00734 /// returns true if the 4 momentum components of the two PseudoJets
00735 /// are identical and all the internal indices (user, cluster_history)
00736 /// + structure and user-info shared pointers are too
00737 bool operator==(const PseudoJet &, const PseudoJet &);
00738 
00739 /// inequality test which is exact opposite of operator==
00740 inline bool operator!=(const PseudoJet & a, const PseudoJet & b) {return !(a==b);}
00741 
00742 /// Can only be used with val=0 and tests whether all four
00743 /// momentum components are equal to val (=0.0)
00744 bool operator==(const PseudoJet & jet, const double val);
00745 
00746 /// Can only be used with val=0 and tests whether at least one of the
00747 /// four momentum components is different from val (=0.0)
00748 inline bool operator!=(const PseudoJet & a, const double & val) {return !(a==val);}
00749 
00750 inline double dot_product(const PseudoJet & a, const PseudoJet & b) {
00751   return a.E()*b.E() - a.px()*b.px() - a.py()*b.py() - a.pz()*b.pz();
00752 }
00753 
00754 /// returns true if the momenta of the two input jets are identical
00755 bool have_same_momentum(const PseudoJet &, const PseudoJet &);
00756 
00757 /// return a pseudojet with the given pt, y, phi and mass
00758 PseudoJet PtYPhiM(double pt, double y, double phi, double m = 0.0);
00759 
00760 //----------------------------------------------------------------------
00761 // Routines to do with providing sorted arrays of vectors.
00762 
00763 /// return a vector of jets sorted into decreasing transverse momentum
00764 std::vector<PseudoJet> sorted_by_pt(const std::vector<PseudoJet> & jets);
00765 
00766 /// return a vector of jets sorted into increasing rapidity
00767 std::vector<PseudoJet> sorted_by_rapidity(const std::vector<PseudoJet> & jets);
00768 
00769 /// return a vector of jets sorted into decreasing energy
00770 std::vector<PseudoJet> sorted_by_E(const std::vector<PseudoJet> & jets);
00771 
00772 /// return a vector of jets sorted into increasing pz
00773 std::vector<PseudoJet> sorted_by_pz(const std::vector<PseudoJet> & jets);
00774 
00775 //----------------------------------------------------------------------
00776 // some code to help sorting
00777 
00778 /// sort the indices so that values[indices[0->n-1]] is sorted
00779 /// into increasing order 
00780 void sort_indices(std::vector<int> & indices, 
00781                   const std::vector<double> & values);
00782 
00783 /// given a vector of values with a one-to-one correspondence with the
00784 /// vector of objects, sort objects into an order such that the
00785 /// associated values would be in increasing order (but don't actually
00786 /// touch the values vector in the process).
00787 template<class T> std::vector<T> objects_sorted_by_values(const std::vector<T> & objects, 
00788                                               const std::vector<double> & values);
00789 
00790 /// \if internal_doc
00791 /// @ingroup internal
00792 /// \class IndexedSortHelper
00793 /// a class that helps us carry out indexed sorting.
00794 /// \endif
00795 class IndexedSortHelper {
00796 public:
00797   inline IndexedSortHelper (const std::vector<double> * reference_values) {
00798     _ref_values = reference_values;
00799   };
00800   inline int operator() (const int & i1, const int & i2) const {
00801     return  (*_ref_values)[i1] < (*_ref_values)[i2];
00802   };
00803 private:
00804   const std::vector<double> * _ref_values;
00805 };
00806 
00807 
00808 //----------------------------------------------------------------------
00809 /// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
00810 // NB: do not know if it really needs to be inline, but when it wasn't
00811 //     linking failed with g++ (who knows what was wrong...)
00812 template <class L> inline  PseudoJet::PseudoJet(const L & some_four_vector) {
00813   reset(some_four_vector);
00814 }
00815 
00816 
00817 //----------------------------------------------------------------------
00818 inline void PseudoJet::_reset_indices() { 
00819   set_cluster_hist_index(-1);
00820   set_user_index(-1);
00821   _structure.reset();
00822   _user_info.reset();
00823 }
00824 
00825 //----------------------------------------------------------------------
00826 /// specialization of the "reset" template for case where something
00827 /// is reset to a pseudojet -- it then takes the user and history
00828 /// indices from the psjet
00829 // template<> inline void PseudoJet::reset<PseudoJet>(const PseudoJet & psjet) {
00830 //   (*this) = psjet;
00831 // }
00832 
00833 ////// fun and games...
00834 ////template<class L> class FJVector : public L {
00835 //////  /** Default Constructor: create jet with no constituents */
00836 //////  Vector<L>();
00837 ////
00838 ////};
00839 ////
00840 
00841 // taken literally from CLHEP
00842 inline double PseudoJet::m() const {
00843   double mm = m2();
00844   return mm < 0.0 ? -std::sqrt(-mm) : std::sqrt(mm);
00845 }
00846 
00847 
00848 inline void PseudoJet::reset(double px, double py, double pz, double E) {
00849   _px = px;
00850   _py = py;
00851   _pz = pz;
00852   _E  = E;
00853   _finish_init();
00854   _reset_indices();
00855 }
00856 
00857 inline void PseudoJet::reset_momentum(double px, double py, double pz, double E) {
00858   _px = px;
00859   _py = py;
00860   _pz = pz;
00861   _E  = E;
00862   _finish_init();
00863 }
00864 
00865 
00866 //-------------------------------------------------------------------------------
00867 // implementation of the templated accesses to the underlying structyre
00868 //-------------------------------------------------------------------------------
00869 
00870 // returns a reference to the structure casted to the requested
00871 // structure type
00872 //
00873 // If there is no sructure associated, an Error is thrown.
00874 // If the type is not met, a std::bad_cast error is thrown.
00875 template<typename StructureType>
00876 const StructureType & PseudoJet::structure() const{
00877   return dynamic_cast<const StructureType &>(* validated_structure_ptr());
00878   
00879 }
00880 
00881 // check if the PseudoJet has the structure resulting from a Transformer 
00882 // (that is, its structure is compatible with a Transformer::StructureType)
00883 template<typename TransformerType>
00884 bool PseudoJet::has_structure_of() const{
00885   if (!_structure()) return false;
00886 
00887   return dynamic_cast<const typename TransformerType::StructureType *>(_structure.get()) != 0;
00888 }
00889 
00890 // this is a helper to access a structure created by a Transformer 
00891 // (that is, of type Transformer::StructureType)
00892 // NULL is returned if the corresponding type is not met
00893 template<typename TransformerType>
00894 const typename TransformerType::StructureType & PseudoJet::structure_of() const{
00895   if (!_structure()) 
00896     throw Error("Trying to access the structure of a PseudoJet without an associated structure");
00897 
00898   return dynamic_cast<const typename TransformerType::StructureType &>(*_structure);
00899 }
00900 
00901 
00902 
00903 //-------------------------------------------------------------------------------
00904 // helper functions to build a jet made of pieces
00905 //
00906 // Note that there are more complete versions of these functions, with
00907 // an additional argument for a recombination scheme, in
00908 // JetDefinition.hh
00909 // -------------------------------------------------------------------------------
00910 
00911 /// build a "CompositeJet" from the vector of its pieces
00912 ///
00913 /// In this case, E-scheme recombination is assumed to compute the
00914 /// total momentum
00915 PseudoJet join(const std::vector<PseudoJet> & pieces);
00916 
00917 /// build a MergedJet from a single PseudoJet
00918 PseudoJet join(const PseudoJet & j1);
00919 
00920 /// build a MergedJet from 2 PseudoJet
00921 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2);
00922 
00923 /// build a MergedJet from 3 PseudoJet
00924 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3);
00925 
00926 /// build a MergedJet from 4 PseudoJet
00927 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4);
00928 
00929 
00930 
00931 FASTJET_END_NAMESPACE
00932 
00933 #endif // __FASTJET_PSEUDOJET_HH__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends