FastJet 3.0beta1
|
00001 //STARTHEADER 00002 // $Id: Dnn2piCylinder.hh 1816 2010-11-19 11:35:52Z 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 DROP_CGAL // in case we do not have the code for CGAL 00033 #ifndef __FASTJET_DNN2PICYLINDER_HH__ 00034 #define __FASTJET_DNN2PICYLINDER_HH__ 00035 00036 #include "fastjet/internal/DynamicNearestNeighbours.hh" 00037 #include "fastjet/internal/DnnPlane.hh" 00038 #include "fastjet/internal/numconsts.hh" 00039 00040 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00041 00042 00043 /// \if internal_doc 00044 /// @ingroup internal 00045 /// \class Dnn2piCylinder 00046 /// class derived from DynamicNearestNeighbours that provides an 00047 /// implementation for the surface of cylinder (using one 00048 /// DnnPlane object spanning 0--2pi). 00049 /// \endif 00050 class Dnn2piCylinder : public DynamicNearestNeighbours { 00051 public: 00052 /// empty initaliser 00053 Dnn2piCylinder() {} 00054 00055 /// Initialiser from a set of points on an Eta-Phi plane, where 00056 /// eta can have an arbitrary ranges and phi must be in range 00057 /// 0 <= phi < 2pi; 00058 /// 00059 /// NB: this class is more efficient than the plain Dnn4piCylinder 00060 /// class, but can give wrong answers when the nearest neighbour is 00061 /// further away than 2pi (in this case a point's nearest neighbour 00062 /// becomes itself, because it is considered to be a distance 2pi 00063 /// away). For the kt-algorithm (e.g.) this is actually not a 00064 /// problem (the distance need only be accurate when it is less than 00065 /// R, assuming R<2pi [not necessarily always the case as of 00066 /// 2010-11-19, when we've removed the requirement R<pi/2 in the 00067 /// JetDefinition constructor]), so we can tell the routine to 00068 /// ignore this problem -- alternatively the routine will crash if 00069 /// it detects it occurring (only when finding the nearest neighbour 00070 /// index, not its distance). 00071 Dnn2piCylinder(const std::vector<EtaPhi> &, 00072 const bool & ignore_nearest_is_mirror = false, 00073 const bool & verbose = false ); 00074 00075 /// Returns the index of the nearest neighbour of point labelled 00076 /// by ii (assumes ii is valid) 00077 int NearestNeighbourIndex(const int & ii) const ; 00078 00079 /// Returns the distance to the nearest neighbour of point labelled 00080 /// by index ii (assumes ii is valid) 00081 double NearestNeighbourDistance(const int & ii) const ; 00082 00083 /// Returns true iff the given index corresponds to a point that 00084 /// exists in the DNN structure (meaning that it has been added, and 00085 /// not removed in the meantime) 00086 bool Valid(const int & index) const; 00087 00088 void RemoveAndAddPoints(const std::vector<int> & indices_to_remove, 00089 const std::vector<EtaPhi> & points_to_add, 00090 std::vector<int> & indices_added, 00091 std::vector<int> & indices_of_updated_neighbours); 00092 00093 ~Dnn2piCylinder(); 00094 00095 private: 00096 00097 // our extras to help us navigate, find distance, etc. 00098 const static int INEXISTENT_VERTEX=-3; 00099 00100 bool _verbose; 00101 00102 bool _ignore_nearest_is_mirror; 00103 00104 /// Picture of how things will work... Copy 0--pi part of the 0--2pi 00105 /// cylinder into a region 2pi--2pi+ a bit of a Euclidean plane. Below we 00106 /// show points labelled by + that have a mirror image in this 00107 /// manner, while points labelled by * do not have a mirror image. 00108 /// 00109 /// | . | 00110 /// | . | 00111 /// | . | 00112 /// | . | 00113 /// | 2 . | 00114 /// | * . | 00115 /// | + . + | 00116 /// | 0 . 1 | 00117 /// | . | 00118 /// 0 2pi 2pi + a bit 00119 /// 00120 /// Each "true" point has its true "cylinder" index (the index that 00121 /// is known externally to this class) as well as euclidean plane 00122 /// indices (main_index and mirror index in the MirrorVertexInfo 00123 /// structure), which are private concepts of this class. 00124 /// 00125 /// In above picture our structures would hold the following info 00126 /// (the picture shows the euclidean-plane numbering) 00127 /// 00128 /// _mirror_info[cylinder_index = 0] = (0, 1) 00129 /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX) 00130 /// 00131 /// We also need to be able to go from the euclidean plane indices 00132 /// back to the "true" cylinder index, and for this purpose we use 00133 /// the std::vector _cylinder_index_of_plane_vertex[...], which in the above example has 00134 /// the following contents 00135 /// 00136 /// _cylinder_index_of_plane_vertex[0] = 0 00137 /// _cylinder_index_of_plane_vertex[1] = 0 00138 /// _cylinder_index_of_plane_vertex[2] = 1 00139 /// 00140 00141 /// 00142 struct MirrorVertexInfo { 00143 /// index of the given point (appearing in the range 0--2pi) in the 00144 /// 0--2pi euclidean plane structure (position will coincide with 00145 /// that on the 0--2pi cylinder, but index labelling it will be 00146 /// different) 00147 int main_index; 00148 /// index of the mirror point (appearing in the range 2pi--3pi) in the 00149 /// 0--3pi euclidean plane structure 00150 int mirror_index; 00151 }; 00152 00153 // for each "true" vertex we have reference to indices in the euclidean 00154 // plane structure 00155 std::vector<MirrorVertexInfo> _mirror_info; 00156 // for each index in the euclidean 0--2pi plane structure we want to 00157 // be able to get back to the "true" vertex index on the overall 00158 // 0--2pi cylinder structure 00159 std::vector<int> _cylinder_index_of_plane_vertex; 00160 00161 // NB: we define POINTERS here because the initialisation gave 00162 // us problems (things crashed!), perhaps because in practice 00163 // we were making a copy without being careful and defining 00164 // a proper copy constructor. 00165 DnnPlane * _DNN; 00166 00167 /// given a phi value in the 0--pi range return one 00168 /// in the 2pi--3pi range; whereas if it is in the pi-2pi range then 00169 /// remap it to be inthe range (-pi)--0. 00170 inline EtaPhi _remap_phi(const EtaPhi & point) { 00171 double phi = point.second; 00172 if (phi < pi) { phi += twopi ;} else {phi -= twopi;} 00173 return EtaPhi(point.first, phi);} 00174 00175 00176 //---------------------------------------------------------------------- 00177 /// Actions here are similar to those in the 00178 /// Dnn3piCylinder::_RegisterCylinderPoint case, however here we do 00179 /// NOT create the mirror point -- instead we initialise the structure 00180 /// as if there were no need for the mirror point. 00181 /// 00182 /// ADDITIONALLY push the cylinder_point onto the vector plane_points. 00183 void _RegisterCylinderPoint (const EtaPhi & cylinder_point, 00184 std::vector<EtaPhi> & plane_points); 00185 00186 /// For each plane point specified in the vector plane_indices, 00187 /// establish whether there is a need to create a mirror point 00188 /// according to the following criteria: 00189 /// 00190 /// . phi < pi 00191 /// . mirror does not already exist 00192 /// . phi < NearestNeighbourDistance 00193 /// (if this is not true then there is no way that its mirror point 00194 /// could have a nearer neighbour). 00195 /// 00196 /// If conditions all hold, then create the mirror point, insert it 00197 /// into the _DNN structure, adjusting any nearest neighbours, and 00198 /// return the list of plane points whose nearest neighbours have 00199 /// changed (this will include the new neighbours that have just been 00200 /// added) 00201 void _CreateNecessaryMirrorPoints( 00202 const std::vector<int> & plane_indices, 00203 std::vector<int> & updated_plane_points); 00204 00205 }; 00206 00207 00208 // here follow some inline implementations of the simpler of the 00209 // functions defined above 00210 00211 //---------------------------------------------------------------------- 00212 /// Note: one of the difficulties of the 0--2pi mapping is that 00213 /// a point may have its mirror copy as its own nearest neighbour 00214 /// (if no other point is within a distance of 2pi). This does 00215 /// not matter for the kt_algorithm with 00216 /// reasonable values of radius, but might matter for a general use 00217 /// of this algorithm -- depending on whether or not the user has 00218 /// initialised the class with instructions to ignore this problem the 00219 /// program will detect and ignore it, or crash. 00220 inline int Dnn2piCylinder::NearestNeighbourIndex(const int & current) const { 00221 int main_index = _mirror_info[current].main_index; 00222 int mirror_index = _mirror_info[current].mirror_index; 00223 int plane_index; 00224 if (mirror_index == INEXISTENT_VERTEX ) { 00225 plane_index = _DNN->NearestNeighbourIndex(main_index); 00226 } else { 00227 plane_index = ( 00228 _DNN->NearestNeighbourDistance(main_index) < 00229 _DNN->NearestNeighbourDistance(mirror_index)) ? 00230 _DNN->NearestNeighbourIndex(main_index) : 00231 _DNN->NearestNeighbourIndex(mirror_index) ; 00232 } 00233 int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index]; 00234 // either the user has acknowledged the fact that they may get the 00235 // mirror copy as the closest point, or crash if it should occur 00236 // that mirror copy is the closest point. 00237 assert(_ignore_nearest_is_mirror || this_cylinder_index != current); 00238 //if (this_cylinder_index == current) { 00239 // cerr << "WARNING point "<<current<< 00240 // " has its mirror copy as its own nearest neighbour"<<endl; 00241 //} 00242 return this_cylinder_index; 00243 } 00244 00245 inline double Dnn2piCylinder::NearestNeighbourDistance(const int & current) const { 00246 int main_index = _mirror_info[current].main_index; 00247 int mirror_index = _mirror_info[current].mirror_index; 00248 if (mirror_index == INEXISTENT_VERTEX ) { 00249 return _DNN->NearestNeighbourDistance(main_index); 00250 } else { 00251 return ( 00252 _DNN->NearestNeighbourDistance(main_index) < 00253 _DNN->NearestNeighbourDistance(mirror_index)) ? 00254 _DNN->NearestNeighbourDistance(main_index) : 00255 _DNN->NearestNeighbourDistance(mirror_index) ; 00256 } 00257 00258 } 00259 00260 inline bool Dnn2piCylinder::Valid(const int & index) const { 00261 return (_DNN->Valid(_mirror_info[index].main_index)); 00262 } 00263 00264 00265 inline Dnn2piCylinder::~Dnn2piCylinder() { 00266 delete _DNN; 00267 } 00268 00269 00270 FASTJET_END_NAMESPACE 00271 00272 #endif // __FASTJET_DNN2PICYLINDER_HH__ 00273 #endif //DROP_CGAL