Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 08:56:20

0001 //FJSTARTHEADER
0002 // $Id$
0003 //
0004 // Copyright (c) 2005-2025, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
0005 //
0006 //----------------------------------------------------------------------
0007 // This file is part of FastJet.
0008 //
0009 //  FastJet is free software; you can redistribute it and/or modify
0010 //  it under the terms of the GNU General Public License as published by
0011 //  the Free Software Foundation; either version 2 of the License, or
0012 //  (at your option) any later version.
0013 //
0014 //  The algorithms that underlie FastJet have required considerable
0015 //  development. They are described in the original FastJet paper,
0016 //  hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
0017 //  FastJet as part of work towards a scientific publication, please
0018 //  quote the version you use and include a citation to the manual and
0019 //  optionally also to hep-ph/0512210.
0020 //
0021 //  FastJet is distributed in the hope that it will be useful,
0022 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
0023 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0024 //  GNU General Public License for more details.
0025 //
0026 //  You should have received a copy of the GNU General Public License
0027 //  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
0028 //----------------------------------------------------------------------
0029 //FJENDHEADER
0030 
0031 #include "fastjet/config.h"
0032 
0033 #ifndef DROP_CGAL // in case we do not have the code for CGAL
0034 #ifndef __FASTJET_DNN3PICYLINDER_HH__
0035 #define __FASTJET_DNN3PICYLINDER_HH__
0036 
0037 #include "fastjet/internal/DynamicNearestNeighbours.hh"
0038 #include "fastjet/internal/DnnPlane.hh"
0039 #include "fastjet/internal/numconsts.hh"
0040 
0041 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0042 
0043 /// \if internal_doc
0044 /// @ingroup internal
0045 /// \class Dnn3piCylinder
0046 /// class derived from DynamicNearestNeighbours that provides an
0047 /// implementation for the surface of cylinder (using one 
0048 /// DnnPlane object spanning 0--3pi).
0049 /// \endif
0050 class Dnn3piCylinder : public DynamicNearestNeighbours {
0051  public:
0052   /// empty initaliser
0053   Dnn3piCylinder() {}
0054 
0055   /// Initialiser from a set of points on an Eta-Phi plane, where
0056   /// eta can have an arbitrary ranges and phi must be in range
0057   /// 0 <= phi < 2pi;
0058   /// 
0059   /// NB: this class is more efficient than the plain Dnn4piCylinder
0060   /// class, but can give wrong answers when the nearest neighbour is
0061   /// further away than 2pi (in this case a point's nearest neighbour
0062   /// becomes itself, because it is considered to be a distance 2pi
0063   /// away). For the kt-algorithm (e.g.) this is actually not a
0064   /// problem (the distance need only be accurate when it is less than
0065   /// R), so we can tell the routine to ignore this problem --
0066   /// alternatively the routine will crash if it detects it occurring
0067   /// (only when finding the nearest neighbour index, not its
0068   /// distance).
0069   Dnn3piCylinder(const std::vector<EtaPhi> &,
0070          const bool & ignore_nearest_is_mirror = false,
0071          const bool & verbose = false );
0072 
0073   /// Returns the index of  the nearest neighbour of point labelled
0074   /// by ii (assumes ii is valid)
0075   int NearestNeighbourIndex(const int ii) const ;
0076 
0077   /// Returns the distance to the nearest neighbour of point labelled
0078   /// by index ii (assumes ii is valid)
0079   double NearestNeighbourDistance(const int ii) const ;
0080 
0081   /// Returns true iff the given index corresponds to a point that
0082   /// exists in the DNN structure (meaning that it has been added, and
0083   /// not removed in the meantime)
0084   bool Valid(const int index) const;
0085 
0086   void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
0087               const std::vector<EtaPhi> & points_to_add,
0088               std::vector<int> & indices_added,
0089               std::vector<int> & indices_of_updated_neighbours);
0090 
0091   ~Dnn3piCylinder();
0092 
0093  private:
0094 
0095   // our extras to help us navigate, find distance, etc.
0096   const static int INEXISTENT_VERTEX=-3;
0097 
0098   bool _verbose;
0099 
0100   bool _ignore_nearest_is_mirror;
0101 
0102   /// Picture of how things will work... Copy 0--pi part of the 0--2pi
0103   /// cylinder into a region 2pi--3pi of a Euclidean plane. Below we
0104   /// show points labelled by + that have a mirror image in this
0105   /// manner, while points labelled by * do not have a mirror image.
0106   ///                     
0107   ///      |           .     |        
0108   ///      |           .     |        
0109   ///      |           .     |        
0110   ///      |           .     |        
0111   ///      |        2  .     |        
0112   ///      |        *  .     |        
0113   ///      | +         . +   |        
0114   ///      | 0         . 1   |
0115   ///      |           .     |
0116   ///      0          2pi   3pi
0117   ///            
0118   /// Each "true" point has its true "cylinder" index (the index that
0119   /// is known externally to this class) as well as euclidean plane
0120   /// indices (main_index and mirror index in the MirrorVertexInfo
0121   /// structure), which are private concepts of this class.
0122   /// 
0123   /// In above picture our structures would hold the following info
0124   /// (the picture shows the euclidean-plane numbering)
0125   ///
0126   /// _mirror_info[cylinder_index = 0] = (0, 1)
0127   /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX)
0128   ///
0129   /// We also need to be able to go from the euclidean plane indices
0130   /// back to the "true" cylinder index, and for this purpose we use
0131   /// the vector _cylinder_index_of_plane_vertex[...], which in the above example has
0132   /// the following contents
0133   ///
0134   /// _cylinder_index_of_plane_vertex[0] = 0
0135   /// _cylinder_index_of_plane_vertex[1] = 0
0136   /// _cylinder_index_of_plane_vertex[2] = 1
0137   ///
0138 
0139   /// 
0140   struct MirrorVertexInfo {
0141     /// index of the given point (appearing in the range 0--2pi) in the 
0142     /// 0--3pi euclidean plane structure (position will coincide with
0143     /// that on the 0--2pi cylinder, but index labelling it will be
0144     /// different)
0145     int main_index; 
0146     /// index of the mirror point (appearing in the range 2pi--3pi) in the
0147     /// 0--3pi euclidean plane structure
0148     int mirror_index; 
0149   };
0150 
0151   // for each "true" vertex we have reference to indices in the euclidean
0152   // plane structure
0153   std::vector<MirrorVertexInfo> _mirror_info;
0154   // for each index in the euclidean 0--3pi plane structure we want to
0155   // be able to get back to the "true" vertex index on the overall
0156   // 0--2pi cylinder structure
0157   std::vector<int> _cylinder_index_of_plane_vertex;
0158 
0159   // NB: we define POINTERS here because the initialisation gave
0160   //     us problems (things crashed!), perhaps because in practice
0161   //     we were making a copy without being careful and defining
0162   //     a proper copy constructor.
0163   DnnPlane * _DNN;
0164 
0165   /// given a phi value in the 0--2pi range return one 
0166   /// in the pi--3pi range.
0167   inline EtaPhi _remap_phi(const EtaPhi & point) {
0168     double phi = point.second;
0169     if (phi < pi) { phi += twopi ;}
0170     return EtaPhi(point.first, phi);}
0171 
0172 
0173   //----------------------------------------------------------------------
0174   /// What on earth does this do?
0175   ///
0176   /// Example: last true "cylinder" index was 15
0177   ///          last plane index was 23
0178   /// 
0179   /// Then: _cylinder_index_of_plane_vertex.size() = 24 and 
0180   ///       _mirror_info.size() = 16
0181   ///
0182   /// IF cylinder_point's phi < pi then
0183   ///   create:  _mirror_info[16] = (main_index = 24, mirror_index=25) 
0184   ///            _cylinder_index_of_plane_vertex[24] = 16
0185   ///            _cylinder_index_of_plane_vertex[25] = 16
0186   /// ELSE
0187   ///  create: _mirror_info[16] = (main_index = 24, mirror_index=INEXISTENT..) 
0188   ///          _cylinder_index_of_plane_vertex[24] = 16
0189   ///
0190   /// ADDITIONALLY push the cylinder_point (and if it exists the mirror
0191   /// copy) onto the vector plane_points.
0192   void _RegisterCylinderPoint (const EtaPhi & cylinder_point,
0193                    std::vector<EtaPhi> & plane_points);
0194 };
0195 
0196 
0197 // here follow some inline implementations of the simpler of the
0198 // functions defined above
0199 
0200 //----------------------------------------------------------------------
0201 /// Note: one of the difficulties of the 0--3pi mapping is that
0202 /// a point may have its mirror copy as its own nearest neighbour
0203 /// (if no other point is within a distance of 2pi). This does
0204 /// not matter for the kt_algorithm with
0205 /// reasonable values of radius, but might matter for a general use
0206 /// of this algorithm -- depending on whether or not the user has
0207 /// initialised the class with instructions to ignore this problem the
0208 /// program will detect and ignore it, or crash.
0209 inline int Dnn3piCylinder::NearestNeighbourIndex(const int current) const {
0210   int main_index = _mirror_info[current].main_index;
0211   int mirror_index = _mirror_info[current].mirror_index;
0212   int plane_index;
0213   if (mirror_index == INEXISTENT_VERTEX ) {
0214     plane_index = _DNN->NearestNeighbourIndex(main_index);
0215   } else {
0216     plane_index = (
0217     _DNN->NearestNeighbourDistance(main_index) < 
0218     _DNN->NearestNeighbourDistance(mirror_index)) ? 
0219       _DNN->NearestNeighbourIndex(main_index) : 
0220       _DNN->NearestNeighbourIndex(mirror_index) ; 
0221   }
0222   int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index];
0223   // either the user has acknowledged the fact that they may get the
0224   // mirror copy as the closest point, or crash if it should occur
0225   // that mirror copy is the closest point.
0226   assert(_ignore_nearest_is_mirror || this_cylinder_index != current);
0227   //if (this_cylinder_index == current) {
0228   //  std::cerr << "WARNING point "<<current<<
0229   //    " has its mirror copy as its own nearest neighbour"<<endl;
0230   //}
0231   return this_cylinder_index;
0232 }
0233 
0234 inline double Dnn3piCylinder::NearestNeighbourDistance(const int current) const {
0235   int main_index = _mirror_info[current].main_index;
0236   int mirror_index = _mirror_info[current].mirror_index;
0237   if (mirror_index == INEXISTENT_VERTEX ) {
0238     return _DNN->NearestNeighbourDistance(main_index);
0239   } else {
0240     return (
0241     _DNN->NearestNeighbourDistance(main_index) < 
0242     _DNN->NearestNeighbourDistance(mirror_index)) ? 
0243       _DNN->NearestNeighbourDistance(main_index) : 
0244       _DNN->NearestNeighbourDistance(mirror_index) ; 
0245   }
0246  
0247 }
0248 
0249 inline bool Dnn3piCylinder::Valid(const int index) const {
0250   return (_DNN->Valid(_mirror_info[index].main_index));
0251 }
0252 
0253 
0254 inline Dnn3piCylinder::~Dnn3piCylinder() {
0255   delete _DNN; 
0256 }
0257 
0258 
0259 FASTJET_END_NAMESPACE
0260 
0261 #endif //  __FASTJET_DNN3PICYLINDER_HH__
0262 #endif //  DROP_CGAL