|
FastJet 3.0alpha3
|
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__
1.7.4