FastJet  3.2.2
ClusterSequence.hh
1 #ifndef __FASTJET_CLUSTERSEQUENCE_HH__
2 #define __FASTJET_CLUSTERSEQUENCE_HH__
3 
4 //FJSTARTHEADER
5 // $Id: ClusterSequence.hh 4154 2016-07-20 16:20:48Z soyez $
6 //
7 // Copyright (c) 2005-2014, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
8 //
9 //----------------------------------------------------------------------
10 // This file is part of FastJet.
11 //
12 // FastJet is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16 //
17 // The algorithms that underlie FastJet have required considerable
18 // development. They are described in the original FastJet paper,
19 // hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
20 // FastJet as part of work towards a scientific publication, please
21 // quote the version you use and include a citation to the manual and
22 // optionally also to hep-ph/0512210.
23 //
24 // FastJet is distributed in the hope that it will be useful,
25 // but WITHOUT ANY WARRANTY; without even the implied warranty of
26 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 // GNU General Public License for more details.
28 //
29 // You should have received a copy of the GNU General Public License
30 // along with FastJet. If not, see <http://www.gnu.org/licenses/>.
31 //----------------------------------------------------------------------
32 //FJENDHEADER
33 
34 
35 #include<vector>
36 #include<map>
37 #include "fastjet/PseudoJet.hh"
38 #include<memory>
39 #include<cassert>
40 #include<iostream>
41 #include<string>
42 #include<set>
43 #include<cmath> // needed to get double std::abs(double)
44 #include "fastjet/Error.hh"
45 #include "fastjet/JetDefinition.hh"
46 #include "fastjet/SharedPtr.hh"
47 #include "fastjet/LimitedWarning.hh"
48 #include "fastjet/FunctionOfPseudoJet.hh"
49 #include "fastjet/ClusterSequenceStructure.hh"
50 
51 #include "fastjet/internal/deprecated.hh"
52 
53 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
54 
55 
56 // forward declarations
57 class ClusterSequenceStructure;
58 class DynamicNearestNeighbours;
59 
60 /// @ingroup basic_classes
61 /// \class ClusterSequence
62 /// deals with clustering
64 
65 
66  public:
67 
68  /// default constructor
69  ClusterSequence () : _deletes_self_when_unused(false) {}
70 
71  /// create a ClusterSequence, starting from the supplied set
72  /// of PseudoJets and clustering them with jet definition specified
73  /// by jet_def (which also specifies the clustering strategy)
74  template<class L> ClusterSequence (
75  const std::vector<L> & pseudojets,
76  const JetDefinition & jet_def,
77  const bool & writeout_combinations = false);
78 
79  /// copy constructor for a ClusterSequence
80  ClusterSequence (const ClusterSequence & cs) : _deletes_self_when_unused(false) {
81  transfer_from_sequence(cs);
82  }
83 
84  /// explicit assignment operator for a ClusterSequence
85  ClusterSequence & operator=(const ClusterSequence & cs);
86 
87  // virtual ClusterSequence destructor, in case any derived class
88  // thinks of needing a destructor at some point
89  virtual ~ClusterSequence (); //{}
90 
91  // NB: in the routines that follow, for extracting lists of jets, a
92  // list structure might be more efficient, if sometimes a little
93  // more awkward to use (at least for old fortran hands).
94 
95  /// return a vector of all jets (in the sense of the inclusive
96  /// algorithm) with pt >= ptmin. Time taken should be of the order
97  /// of the number of jets returned.
98  std::vector<PseudoJet> inclusive_jets (const double ptmin = 0.0) const;
99 
100  /// return the number of jets (in the sense of the exclusive
101  /// algorithm) that would be obtained when running the algorithm
102  /// with the given dcut.
103  int n_exclusive_jets (const double dcut) const;
104 
105  /// return a vector of all jets (in the sense of the exclusive
106  /// algorithm) that would be obtained when running the algorithm
107  /// with the given dcut.
108  std::vector<PseudoJet> exclusive_jets (const double dcut) const;
109 
110  /// return a vector of all jets when the event is clustered (in the
111  /// exclusive sense) to exactly njets.
112  ///
113  /// If there are fewer than njets particles in the ClusterSequence
114  /// an error is thrown
115  std::vector<PseudoJet> exclusive_jets (const int njets) const;
116 
117  /// return a vector of all jets when the event is clustered (in the
118  /// exclusive sense) to exactly njets.
119  ///
120  /// If there are fewer than njets particles in the ClusterSequence
121  /// the function just returns however many particles there were.
122  std::vector<PseudoJet> exclusive_jets_up_to (const int njets) const;
123 
124  /// return the dmin corresponding to the recombination that went
125  /// from n+1 to n jets (sometimes known as d_{n n+1}). If the number
126  /// of particles in the event is <= njets, the function returns 0.
127  double exclusive_dmerge (const int njets) const;
128 
129  /// return the maximum of the dmin encountered during all recombinations
130  /// up to the one that led to an n-jet final state; identical to
131  /// exclusive_dmerge, except in cases where the dmin do not increase
132  /// monotonically.
133  double exclusive_dmerge_max (const int njets) const;
134 
135  /// return the ymin corresponding to the recombination that went from
136  /// n+1 to n jets (sometimes known as y_{n n+1}).
137  double exclusive_ymerge (int njets) const {return exclusive_dmerge(njets) / Q2();}
138 
139  /// same as exclusive_dmerge_max, but normalised to squared total energy
140  double exclusive_ymerge_max (int njets) const {return exclusive_dmerge_max(njets)/Q2();}
141 
142  /// the number of exclusive jets at the given ycut
143  int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
144 
145  /// the exclusive jets obtained at the given ycut
146  std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
147  int njets = n_exclusive_jets_ycut(ycut);
148  return exclusive_jets(njets);
149  }
150 
151 
152  //int n_exclusive_jets (const PseudoJet & jet, const double dcut) const;
153 
154  /// return a vector of all subjets of the current jet (in the sense
155  /// of the exclusive algorithm) that would be obtained when running
156  /// the algorithm with the given dcut.
157  ///
158  /// Time taken is O(m ln m), where m is the number of subjets that
159  /// are found. If m gets to be of order of the total number of
160  /// constituents in the jet, this could be substantially slower than
161  /// just getting that list of constituents.
162  std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet,
163  const double dcut) const;
164 
165  /// return the size of exclusive_subjets(...); still n ln n with same
166  /// coefficient, but marginally more efficient than manually taking
167  /// exclusive_subjets.size()
168  int n_exclusive_subjets(const PseudoJet & jet,
169  const double dcut) const;
170 
171  /// return the list of subjets obtained by unclustering the supplied
172  /// jet down to nsub subjets. Throws an error if there are fewer than
173  /// nsub particles in the jet.
174  ///
175  /// This requires nsub ln nsub time
176  std::vector<PseudoJet> exclusive_subjets (const PseudoJet & jet,
177  int nsub) const;
178 
179  /// return the list of subjets obtained by unclustering the supplied
180  /// jet down to nsub subjets (or all constituents if there are fewer
181  /// than nsub).
182  ///
183  /// This requires nsub ln nsub time
184  std::vector<PseudoJet> exclusive_subjets_up_to (const PseudoJet & jet,
185  int nsub) const;
186 
187  /// returns the dij that was present in the merging nsub+1 -> nsub
188  /// subjets inside this jet.
189  ///
190  /// Returns 0 if there were nsub or fewer constituents in the jet.
191  double exclusive_subdmerge(const PseudoJet & jet, int nsub) const;
192 
193  /// returns the maximum dij that occurred in the whole event at the
194  /// stage that the nsub+1 -> nsub merge of subjets occurred inside
195  /// this jet.
196  ///
197  /// Returns 0 if there were nsub or fewer constituents in the jet.
198  double exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
199 
200  //std::vector<PseudoJet> exclusive_jets (const PseudoJet & jet,
201  // const int njets) const;
202  //double exclusive_dmerge (const PseudoJet & jet, const int njets) const;
203 
204  /// returns the sum of all energies in the event (relevant mainly for e+e-)
205  double Q() const {return _Qtot;}
206  /// return Q()^2
207  double Q2() const {return _Qtot*_Qtot;}
208 
209  /// returns true iff the object is included in the jet.
210  ///
211  /// NB: this is only sensible if the object is already registered
212  /// within the cluster sequence, so you cannot use it with an input
213  /// particle to the CS (since the particle won't have the history
214  /// index set properly).
215  ///
216  /// For nice clustering structures it should run in O(ln(N)) time
217  /// but in worst cases (certain cone plugins) it can take O(n) time,
218  /// where n is the number of particles in the jet.
219  bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) const;
220 
221  /// if the jet has parents in the clustering, it returns true
222  /// and sets parent1 and parent2 equal to them.
223  ///
224  /// if it has no parents it returns false and sets parent1 and
225  /// parent2 to zero
226  bool has_parents(const PseudoJet & jet, PseudoJet & parent1,
227  PseudoJet & parent2) const;
228 
229  /// if the jet has a child then return true and give the child jet
230  /// otherwise return false and set the child to zero
231  bool has_child(const PseudoJet & jet, PseudoJet & child) const;
232 
233  /// Version of has_child that sets a pointer to the child if the child
234  /// exists;
235  bool has_child(const PseudoJet & jet, const PseudoJet * & childp) const;
236 
237  /// if this jet has a child (and so a partner) return true
238  /// and give the partner, otherwise return false and set the
239  /// partner to zero
240  bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
241 
242 
243  /// return a vector of the particles that make up jet
244  std::vector<PseudoJet> constituents (const PseudoJet & jet) const;
245 
246 
247  /// output the supplied vector of jets in a format that can be read
248  /// by an appropriate root script; the format is:
249  /// jet-n jet-px jet-py jet-pz jet-E
250  /// particle-n particle-rap particle-phi particle-pt
251  /// particle-n particle-rap particle-phi particle-pt
252  /// ...
253  /// #END
254  /// ... [i.e. above repeated]
255  void print_jets_for_root(const std::vector<PseudoJet> & jets,
256  std::ostream & ostr = std::cout) const;
257 
258  /// print jets for root to the file labelled filename, with an
259  /// optional comment at the beginning
260  void print_jets_for_root(const std::vector<PseudoJet> & jets,
261  const std::string & filename,
262  const std::string & comment = "") const;
263 
264 // Not yet. Perhaps in a future release.
265 // /// print out all inclusive jets with pt > ptmin
266 // virtual void print_jets (const double ptmin=0.0) const;
267 
268  /// add on to subjet_vector the constituents of jet (for internal use mainly)
269  void add_constituents (const PseudoJet & jet,
270  std::vector<PseudoJet> & subjet_vector) const;
271 
272  /// return the enum value of the strategy used to cluster the event
273  inline Strategy strategy_used () const {return _strategy;}
274 
275  /// return the name of the strategy used to cluster the event
276  std::string strategy_string () const {return strategy_string(_strategy);}
277 
278  /// return the name of the strategy associated with the enum strategy_in
279  std::string strategy_string (Strategy strategy_in) const;
280 
281 
282  /// return a reference to the jet definition
283  const JetDefinition & jet_def() const {return _jet_def;}
284 
285  /// by calling this routine you tell the ClusterSequence to delete
286  /// itself when all the Pseudojets associated with it have gone out
287  /// of scope.
288  ///
289  /// At the time you call this, there must be at least one jet or
290  /// other object outside the CS that is associated with the CS
291  /// (e.g. the result of inclusive_jets()).
292  ///
293  /// NB: after having made this call, the user is still allowed to
294  /// delete the CS. Jets associated with it will then simply not be
295  /// able to access their substructure after that point.
296  void delete_self_when_unused();
297 
298  /// return true if the object has been told to delete itself
299  /// when unused
300  bool will_delete_self_when_unused() const {return _deletes_self_when_unused;}
301 
302  /// tell the ClusterSequence it's about to be self deleted (internal use only)
303  void signal_imminent_self_deletion() const;
304 
305  /// returns the scale associated with a jet as required for this
306  /// clustering algorithm (kt^2 for the kt-algorithm, 1 for the
307  /// Cambridge algorithm). Intended mainly for internal use and not
308  /// valid for plugin algorithms.
309  double jet_scale_for_algorithm(const PseudoJet & jet) const;
310 
311  ///
312 
313  //----- next follow functions designed specifically for plugins, which
314  // may only be called when plugin_activated() returns true
315 
316  /// record the fact that there has been a recombination between
317  /// jets()[jet_i] and jets()[jet_k], with the specified dij, and
318  /// return the index (newjet_k) allocated to the new jet, whose
319  /// momentum is assumed to be the 4-vector sum of that of jet_i and
320  /// jet_j
321  void plugin_record_ij_recombination(int jet_i, int jet_j, double dij,
322  int & newjet_k) {
323  assert(plugin_activated());
324  _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
325  }
326 
327  /// as for the simpler variant of plugin_record_ij_recombination,
328  /// except that the new jet is attributed the momentum and
329  /// user_index of newjet
330  void plugin_record_ij_recombination(int jet_i, int jet_j, double dij,
331  const PseudoJet & newjet,
332  int & newjet_k);
333 
334  /// record the fact that there has been a recombination between
335  /// jets()[jet_i] and the beam, with the specified diB; when looking
336  /// for inclusive jets, any iB recombination will returned to the user
337  /// as a jet.
338  void plugin_record_iB_recombination(int jet_i, double diB) {
339  assert(plugin_activated());
340  _do_iB_recombination_step(jet_i, diB);
341  }
342 
343  /// @ingroup extra_info
344  /// \class Extras
345  /// base class to store extra information that plugins may provide
346  ///
347  /// a class intended to serve as a base in case a plugin needs to
348  /// associate extra information with a ClusterSequence (see
349  /// SISConePlugin.* for an example).
350  class Extras {
351  public:
352  virtual ~Extras() {}
353  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";}
354  };
355 
356  /// the plugin can associate some extra information with the
357  /// ClusterSequence object by calling this function. The
358  /// ClusterSequence takes ownership of the pointer (and
359  /// responsibility for deleting it when the CS gets deleted).
360  inline void plugin_associate_extras(Extras * extras_in) {
361  _extras.reset(extras_in);
362  }
363 
364  /// the plugin can associate some extra information with the
365  /// ClusterSequence object by calling this function
366  ///
367  /// As of FJ v3.1, this is deprecated, in line with the deprecation
368  /// of auto_ptr in C++11
369 #ifdef FASTJET_HAVE_AUTO_PTR_INTERFACE
370  FASTJET_DEPRECATED_MSG("Please use ClusterSequence::plugin_associate_extras(Extras * extras_in)) instead")
371  inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in){
372  _extras.reset(extras_in.release());
373  }
374 #endif
375 
376  /// returns true when the plugin is allowed to run the show.
377  inline bool plugin_activated() const {return _plugin_activated;}
378 
379  /// returns a pointer to the extras object (may be null)
380  const Extras * extras() const {return _extras.get();}
381 
382  /// allows a plugin to run a templated clustering (nearest-neighbour heuristic)
383  ///
384  /// This has N^2 behaviour on "good" distance, but a worst case behaviour
385  /// of N^3 (and many algs trigger the worst case behaviour)
386  ///
387  ///
388  /// For more details on how this works, see GenBriefJet below
389  template<class GBJ> void plugin_simple_N2_cluster () {
390  assert(plugin_activated());
391  _simple_N2_cluster<GBJ>();
392  }
393 
394 
395 public:
396 //DEP /// set the default (static) jet finder across all current and future
397 //DEP /// ClusterSequence objects -- deprecated and obsolescent (i.e. may be
398 //DEP /// suppressed in a future release).
399 //DEP static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
400 //DEP /// same as above for backward compatibility
401 //DEP static void set_jet_finder (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
402 
403 
404  /// \ingroup extra_info
405  /// \struct history_element
406  /// a single element in the clustering history
407  ///
408  /// (see vector _history below).
410  int parent1; /// index in _history where first parent of this jet
411  /// was created (InexistentParent if this jet is an
412  /// original particle)
413 
414  int parent2; /// index in _history where second parent of this jet
415  /// was created (InexistentParent if this jet is an
416  /// original particle); BeamJet if this history entry
417  /// just labels the fact that the jet has recombined
418  /// with the beam)
419 
420  int child; /// index in _history where the current jet is
421  /// recombined with another jet to form its child. It
422  /// is Invalid if this jet does not further
423  /// recombine.
424 
425  int jetp_index; /// index in the _jets vector where we will find the
426  /// PseudoJet object corresponding to this jet
427  /// (i.e. the jet created at this entry of the
428  /// history). NB: if this element of the history
429  /// corresponds to a beam recombination, then
430  /// jetp_index=Invalid.
431 
432  double dij; /// the distance corresponding to the recombination
433  /// at this stage of the clustering.
434 
435  double max_dij_so_far; /// the largest recombination distance seen
436  /// so far in the clustering history.
437  };
438 
439  enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
440 
441  /// allow the user to access the internally stored _jets() array,
442  /// which contains both the initial particles and the various
443  /// intermediate and final stages of recombination.
444  ///
445  /// The first n_particles() entries are the original particles,
446  /// in the order in which they were supplied to the ClusterSequence
447  /// constructor. It can be useful to access them for example when
448  /// examining whether a given input object is part of a specific
449  /// jet, via the objects_in_jet(...) member function (which only takes
450  /// PseudoJets that are registered in the ClusterSequence).
451  ///
452  /// One of the other (internal uses) is related to the fact
453  /// because we don't seem to be able to access protected elements of
454  /// the class for an object that is not "this" (at least in case where
455  /// "this" is of a slightly different kind from the object, both
456  /// derived from ClusterSequence).
457  const std::vector<PseudoJet> & jets() const;
458 
459  /// allow the user to access the raw internal history.
460  ///
461  /// This is present (as for jets()) in part so that protected
462  /// derived classes can access this information about other
463  /// ClusterSequences.
464  ///
465  /// A user who wishes to follow the details of the ClusterSequence
466  /// can also make use of this information (and should consult the
467  /// history_element documentation for more information), but should
468  /// be aware that these internal structures may evolve in future
469  /// FastJet versions.
470  const std::vector<history_element> & history() const;
471 
472  /// returns the number of particles that were provided to the
473  /// clustering algorithm (helps the user find their way around the
474  /// history and jets objects if they weren't paying attention
475  /// beforehand).
476  unsigned int n_particles() const;
477 
478  /// returns a vector of size n_particles() which indicates, for
479  /// each of the initial particles (in the order in which they were
480  /// supplied), which of the supplied jets it belongs to; if it does
481  /// not belong to any of the supplied jets, the index is set to -1;
482  std::vector<int> particle_jet_indices(const std::vector<PseudoJet> &) const;
483 
484  /// routine that returns an order in which to read the history
485  /// such that clusterings that lead to identical jet compositions
486  /// but different histories (because of degeneracies in the
487  /// clustering order) will have matching constituents for each
488  /// matching entry in the unique_history_order.
489  ///
490  /// The order has the property that an entry's parents will always
491  /// appear prior to that entry itself.
492  ///
493  /// Roughly speaking the order is such that we first provide all
494  /// steps that lead to the final jet containing particle 1; then we
495  /// have the steps that lead to reconstruction of the jet containing
496  /// the next-lowest-numbered unclustered particle, etc...
497  /// [see GPS CCN28-12 for more info -- of course a full explanation
498  /// here would be better...]
499  std::vector<int> unique_history_order() const;
500 
501  /// return the set of particles that have not been clustered. For
502  /// kt and cam/aachen algorithms this should always be null, but for
503  /// cone type algorithms it can be non-null;
504  std::vector<PseudoJet> unclustered_particles() const;
505 
506  /// Return the list of pseudojets in the ClusterSequence that do not
507  /// have children (and are not among the inclusive jets). They may
508  /// result from a clustering step or may be one of the pseudojets
509  /// returned by unclustered_particles().
510  std::vector<PseudoJet> childless_pseudojets() const;
511 
512  /// returns true if the object (jet or particle) is contained by (ie
513  /// belongs to) this cluster sequence.
514  ///
515  /// Tests performed: if thejet's interface is this cluster sequence
516  /// and its cluster history index is in a consistent range.
517  bool contains(const PseudoJet & object) const;
518 
519  /// transfer the sequence contained in other_seq into our own;
520  /// any plugin "extras" contained in the from_seq will be lost
521  /// from there.
522  ///
523  /// It also sets the ClusterSequence pointers of the PseudoJets in
524  /// the history to point to this ClusterSequence
525  ///
526  /// When specified, the second argument is an action that will be
527  /// applied on every jets in the resulting ClusterSequence
528  void transfer_from_sequence(const ClusterSequence & from_seq,
529  const FunctionOfPseudoJet<PseudoJet> * action_on_jets = 0);
530 
531  /// retrieve a shared pointer to the wrapper to this ClusterSequence
532  ///
533  /// this may turn useful if you want to track when this
534  /// ClusterSequence goes out of scope
536  return _structure_shared_ptr;
537  }
538 
539  /// the structure type associated with a jet belonging to a ClusterSequence
541 
542  /// This is the function that is automatically called during
543  /// clustering to print the FastJet banner. Only the first call to
544  /// this function will result in the printout of the banner. Users
545  /// may wish to call this function themselves, during the
546  /// initialization phase of their program, in order to ensure that
547  /// the banner appears before other output. This call will not
548  /// affect 3rd-party banners, e.g. those from plugins.
549  static void print_banner();
550 
551  /// \cond internal_doc
552  // [this line must be left as is to hide the doxygen comment]
553  /// A call to this function modifies the stream used to print
554  /// banners (by default cout). If a null pointer is passed, banner
555  /// printout is suppressed. This affects all banners, including
556  /// those from plugins.
557  ///
558  /// Please note that if you distribute 3rd party code
559  /// that links with FastJet, that 3rd party code must not
560  /// use this call turn off the printing of FastJet banners
561  /// by default. This requirement reflects the spirit of
562  /// clause 2c of the GNU Public License (v2), under which
563  /// FastJet and its plugins are distributed.
564  static void set_fastjet_banner_stream(std::ostream * ostr) {_fastjet_banner_ostr = ostr;}
565  // [this line must be left as is to hide the doxygen comment]
566  /// \endcond
567 
568  /// returns a pointer to the stream to be used to print banners
569  /// (cout by default). This function is used by plugins to determine
570  /// where to direct their banners. Plugins should properly handle
571  /// the case where the pointer is null.
572  static std::ostream * fastjet_banner_stream() {return _fastjet_banner_ostr;}
573 
574 private:
575  /// \cond internal_doc
576 
577  /// contains the actual stream to use for banners
578  static std::ostream * _fastjet_banner_ostr;
579 
580  /// \endcond
581 
582 protected:
583 //DEP static JetAlgorithm _default_jet_algorithm;
584  JetDefinition _jet_def;
585 
586  /// transfer the vector<L> of input jets into our own vector<PseudoJet>
587  /// _jets (with some reserved space for future growth).
588  template<class L> void _transfer_input_jets(
589  const std::vector<L> & pseudojets);
590 
591  /// This is what is called to do all the initialisation and
592  /// then run the clustering (may be called by various constructors).
593  /// It assumes _jets contains the momenta to be clustered.
594  void _initialise_and_run (const JetDefinition & jet_def,
595  const bool & writeout_combinations);
596 
597  //// this performs the initialisation, minus the option-decanting
598  //// stage; for low multiplicity, initialising a few things in the
599  //// constructor, calling the decant_options_partial() and then this
600  //// is faster than going through _initialise_and_run.
601  void _initialise_and_run_no_decant();
602 
603 //DEP /// This is an alternative routine for initialising and running the
604 //DEP /// clustering, provided for legacy purposes. The jet finder is that
605 //DEP /// specified in the static member _default_jet_algorithm.
606 //DEP void _initialise_and_run (const double R,
607 //DEP const Strategy & strategy,
608 //DEP const bool & writeout_combinations);
609 
610  /// fills in the various member variables with "decanted" options from
611  /// the jet_definition and writeout_combinations variables
612  void _decant_options(const JetDefinition & jet_def,
613  const bool & writeout_combinations);
614 
615  /// assuming that the jet definition, writeout_combinations and
616  /// _structure_shared_ptr have been set (e.g. in an initialiser list
617  /// in the constructor), it handles the remaining decanting of
618  /// options.
619  void _decant_options_partial();
620 
621  /// fill out the history (and jet cross refs) related to the initial
622  /// set of jets (assumed already to have been "transferred"),
623  /// without any clustering
624  void _fill_initial_history();
625 
626  /// carry out the recombination between the jets numbered jet_i and
627  /// jet_j, at distance scale dij; return the index newjet_k of the
628  /// result of the recombination of i and j.
629  void _do_ij_recombination_step(const int jet_i, const int jet_j,
630  const double dij, int & newjet_k);
631 
632  /// carry out an recombination step in which _jets[jet_i] merges with
633  /// the beam,
634  void _do_iB_recombination_step(const int jet_i, const double diB);
635 
636  /// every time a jet is added internally during clustering, this
637  /// should be called to set the jet's structure shared ptr to point
638  /// to the CS (and the count of internally associated objects is
639  /// also updated). This should not be called outside construction of
640  /// a CS object.
641  void _set_structure_shared_ptr(PseudoJet & j);
642 
643  /// make sure that the CS's internal tally of the use count matches
644  /// that of the _structure_shared_ptr
645  void _update_structure_use_count();
646 
647  /// returns a suggestion for the best strategy to use on event
648  /// multiplicity, algorithm, R, etc.
649  Strategy _best_strategy() const;
650 
651  /// \if internal_doc
652  /// \class _Parabola
653  /// returns c*(a*R**2 + b*R + 1);
654  /// Written as a class in case we want to give names to different
655  /// parabolas
656  /// \endif
657  class _Parabola {
658  public:
659  _Parabola(double a, double b, double c) : _a(a), _b(b), _c(c) {}
660  inline double operator()(const double R) const {return _c*(_a*R*R + _b*R + 1);}
661  private:
662  double _a, _b, _c;
663  };
664 
665  /// \if internal_doc
666  /// \class _Line
667  /// operator()(R) returns a*R+b;
668  /// \endif
669  class _Line {
670  public:
671  _Line(double a, double b) : _a(a), _b(b) {}
672  inline double operator()(const double R) const {return _a*R + _b;}
673  private:
674  double _a, _b;
675  };
676 
677  /// This contains the physical PseudoJets; for each PseudoJet one
678  /// can find the corresponding position in the _history by looking
679  /// at _jets[i].cluster_hist_index().
680  std::vector<PseudoJet> _jets;
681 
682 
683  /// this vector will contain the branching history; for each stage,
684  /// _history[i].jetp_index indicates where to look in the _jets
685  /// vector to get the physical PseudoJet.
686  std::vector<history_element> _history;
687 
688  /// set subhist to be a set pointers to history entries corresponding to the
689  /// subjets of this jet; one stops going working down through the
690  /// subjets either when
691  /// - there is no further to go
692  /// - one has found maxjet entries
693  /// - max_dij_so_far <= dcut
694  /// By setting maxjet=0 one can use just dcut; by setting dcut<0
695  /// one can use jet maxjet
696  void get_subhist_set(std::set<const history_element*> & subhist,
697  const PseudoJet & jet, double dcut, int maxjet) const;
698 
699  bool _writeout_combinations;
700  int _initial_n;
701  double _Rparam, _R2, _invR2;
702  double _Qtot;
703  Strategy _strategy;
704  JetAlgorithm _jet_algorithm;
705 
706  SharedPtr<PseudoJetStructureBase> _structure_shared_ptr; //< will actually be of type ClusterSequenceStructure
707  int _structure_use_count_after_construction; //< info of use when CS handles its own memory
708  /// if true then the CS will delete itself when the last external
709  /// object referring to it disappears. It is mutable so as to ensure
710  /// that signal_imminent_self_deletion() [const] can make relevant
711  /// changes.
713 
714  private:
715 
716  bool _plugin_activated;
717  SharedPtr<Extras> _extras; // things the plugin might want to add
718 
719  void _really_dumb_cluster ();
720  void _delaunay_cluster ();
721  //void _simple_N2_cluster ();
722  template<class BJ> void _simple_N2_cluster ();
723  void _tiled_N2_cluster ();
724  void _faster_tiled_N2_cluster ();
725 
726  //
727  void _minheap_faster_tiled_N2_cluster();
728 
729  // things needed specifically for Cambridge with Chan's 2D closest
730  // pairs method
731  void _CP2DChan_cluster();
732  void _CP2DChan_cluster_2pi2R ();
733  void _CP2DChan_cluster_2piMultD ();
734  void _CP2DChan_limited_cluster(double D);
735  void _do_Cambridge_inclusive_jets();
736 
737  // NSqrtN method for C/A
738  void _fast_NsqrtN_cluster();
739 
740  void _add_step_to_history( //const int step_number,
741  const int parent1,
742  const int parent2, const int jetp_index,
743  const double dij);
744 
745  /// internal routine associated with the construction of the unique
746  /// history order (following children in the tree)
747  void _extract_tree_children(int pos, std::valarray<bool> &,
748  const std::valarray<int> &, std::vector<int> &) const;
749 
750  /// internal routine associated with the construction of the unique
751  /// history order (following parents in the tree)
752  void _extract_tree_parents (int pos, std::valarray<bool> &,
753  const std::valarray<int> &, std::vector<int> &) const;
754 
755 
756  // these will be useful shorthands in the Voronoi-based code
757  typedef std::pair<int,int> TwoVertices;
758  typedef std::pair<double,TwoVertices> DijEntry;
759  typedef std::multimap<double,TwoVertices> DistMap;
760 
761  /// currently used only in the Voronoi based code
762  void _add_ktdistance_to_map(const int ii,
763  DistMap & DijMap,
764  const DynamicNearestNeighbours * DNN);
765 
766 
767  /// will be set by default to be true for the first run
768  static bool _first_time;
769 
770  /// manage warnings related to exclusive jets access
771  static LimitedWarning _exclusive_warnings;
772 
773  /// the limited warning member for notification of user that
774  /// their requested strategy has been overridden (usually because
775  /// they have R>2pi and not all strategies work then)
776  static LimitedWarning _changed_strategy_warning;
777 
778  //----------------------------------------------------------------------
779  /// the fundamental structure which contains the minimal info about
780  /// a jet, as needed for our plain N^2 algorithm -- the idea is to
781  /// put all info that will be accessed N^2 times into an array of
782  /// BriefJets...
783  struct BriefJet {
784  double eta, phi, kt2, NN_dist;
785  BriefJet * NN;
786  int _jets_index;
787  };
788 
789  /// structure analogous to BriefJet, but with the extra information
790  /// needed for dealing with tiles
791  class TiledJet {
792  public:
793  double eta, phi, kt2, NN_dist;
794  TiledJet * NN, *previous, * next;
795  int _jets_index, tile_index, diJ_posn;
796  // routines that are useful in the minheap version of tiled
797  // clustering ("misuse" the otherwise unused diJ_posn, so as
798  // to indicate whether jets need to have their minheap entries
799  // updated).
800  inline void label_minheap_update_needed() {diJ_posn = 1;}
801  inline void label_minheap_update_done() {diJ_posn = 0;}
802  inline bool minheap_update_needed() const {return diJ_posn==1;}
803  };
804 
805  //-- some of the functions that follow are templates and will work
806  //as well for briefjet and tiled jets
807 
808  /// set the kinematic and labelling info for jeta so that it corresponds
809  /// to _jets[_jets_index]
810  template <class J> void _bj_set_jetinfo( J * const jet,
811  const int _jets_index) const;
812 
813  /// "remove" this jet, which implies updating links of neighbours and
814  /// perhaps modifying the tile structure
815  void _bj_remove_from_tiles( TiledJet * const jet) const;
816 
817  /// return the distance between two BriefJet objects
818  template <class J> double _bj_dist(const J * const jeta,
819  const J * const jetb) const;
820 
821  // return the diJ (multiplied by _R2) for this jet assuming its NN
822  // info is correct
823  template <class J> double _bj_diJ(const J * const jeta) const;
824 
825  /// for testing purposes only: if in the range head--tail-1 there is a
826  /// a jet which corresponds to hist_index in the history, then
827  /// return a pointer to that jet; otherwise return tail.
828  template <class J> inline J * _bj_of_hindex(
829  const int hist_index,
830  J * const head, J * const tail)
831  const {
832  J * res;
833  for(res = head; res<tail; res++) {
834  if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
835  }
836  return res;
837  }
838 
839 
840  //-- remaining functions are different in various cases, so we
841  // will use templates but are not sure if they're useful...
842 
843  /// updates (only towards smaller distances) the NN for jeta without checking
844  /// whether in the process jeta itself might be a new NN of one of
845  /// the jets being scanned -- span the range head to tail-1 with
846  /// assumption that jeta is not contained in that range
847  template <class J> void _bj_set_NN_nocross(J * const jeta,
848  J * const head, const J * const tail) const;
849 
850  /// reset the NN for jeta and DO check whether in the process jeta
851  /// itself might be a new NN of one of the jets being scanned --
852  /// span the range head to tail-1 with assumption that jeta is not
853  /// contained in that range
854  template <class J> void _bj_set_NN_crosscheck(J * const jeta,
855  J * const head, const J * const tail) const;
856 
857 
858 
859  /// number of neighbours that a tile will have (rectangular geometry
860  /// gives 9 neighbours).
861  static const int n_tile_neighbours = 9;
862  //----------------------------------------------------------------------
863  /// The fundamental structures to be used for the tiled N^2 algorithm
864  /// (see CCN27-44 for some discussion of pattern of tiling)
865  struct Tile {
866  /// pointers to neighbouring tiles, including self
867  Tile * begin_tiles[n_tile_neighbours];
868  /// neighbouring tiles, excluding self
869  Tile ** surrounding_tiles;
870  /// half of neighbouring tiles, no self
871  Tile ** RH_tiles;
872  /// just beyond end of tiles
873  Tile ** end_tiles;
874  /// start of list of BriefJets contained in this tile
875  TiledJet * head;
876  /// sometimes useful to be able to tag a tile
877  bool tagged;
878  };
879  std::vector<Tile> _tiles;
880  double _tiles_eta_min, _tiles_eta_max;
881  double _tile_size_eta, _tile_size_phi;
882  int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
883 
884  // reasonably robust return of tile index given ieta and iphi, in particular
885  // it works even if iphi is negative
886  inline int _tile_index (int ieta, int iphi) const {
887  // note that (-1)%n = -1 so that we have to add _n_tiles_phi
888  // before performing modulo operation
889  return (ieta-_tiles_ieta_min)*_n_tiles_phi
890  + (iphi+_n_tiles_phi) % _n_tiles_phi;
891  }
892 
893  // routines for tiled case, including some overloads of the plain
894  // BriefJet cases
895  int _tile_index(const double eta, const double phi) const;
896  void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
897  void _bj_remove_from_tiles(TiledJet * const jet);
898  void _initialise_tiles();
899  void _print_tiles(TiledJet * briefjets ) const;
900  void _add_neighbours_to_tile_union(const int tile_index,
901  std::vector<int> & tile_union, int & n_near_tiles) const;
902  void _add_untagged_neighbours_to_tile_union(const int tile_index,
903  std::vector<int> & tile_union, int & n_near_tiles);
904 
905  //----------------------------------------------------------------------
906  /// fundamental structure for e+e- clustering
907  struct EEBriefJet {
908  double NN_dist; // obligatorily present
909  double kt2; // obligatorily present == E^2 in general
910  EEBriefJet * NN; // must be present too
911  int _jets_index; // must also be present!
912  //...........................................................
913  double nx, ny, nz; // our internal storage for fast distance calcs
914  };
915 
916  /// to help instantiation (fj 2.4.0; did not quite work on gcc 33 and os x 10.3?)
917  //void _dummy_N2_cluster_instantiation();
918 
919 
920  /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
921  void _simple_N2_cluster_BriefJet();
922  /// to avoid issues with template instantiation (OS X 10.3, gcc 3.3)
923  void _simple_N2_cluster_EEBriefJet();
924 };
925 
926 
927 //**********************************************************************
928 //************** START OF INLINE MATERIAL ******************
929 //**********************************************************************
930 
931 
932 //----------------------------------------------------------------------
933 // Transfer the initial jets into our internal structure
934 template<class L> void ClusterSequence::_transfer_input_jets(
935  const std::vector<L> & pseudojets) {
936 
937  // this will ensure that we can point to jets without difficulties
938  // arising.
939  _jets.reserve(pseudojets.size()*2);
940 
941  // insert initial jets this way so that any type L that can be
942  // converted to a pseudojet will work fine (basically PseudoJet
943  // and any type that has [] subscript access to the momentum
944  // components, such as CLHEP HepLorentzVector).
945  for (unsigned int i = 0; i < pseudojets.size(); i++) {
946  _jets.push_back(pseudojets[i]);}
947 
948 }
949 
950 // //----------------------------------------------------------------------
951 // // initialise from some generic type... Has to be made available
952 // // here in order for it the template aspect of it to work...
953 // template<class L> ClusterSequence::ClusterSequence (
954 // const std::vector<L> & pseudojets,
955 // const double R,
956 // const Strategy & strategy,
957 // const bool & writeout_combinations) {
958 //
959 // // transfer the initial jets (type L) into our own array
960 // _transfer_input_jets(pseudojets);
961 //
962 // // run the clustering
963 // _initialise_and_run(R,strategy,writeout_combinations);
964 // }
965 
966 
967 //----------------------------------------------------------------------
968 /// constructor of a jet-clustering sequence from a vector of
969 /// four-momenta, with the jet definition specified by jet_def
970 template<class L> ClusterSequence::ClusterSequence (
971  const std::vector<L> & pseudojets,
972  const JetDefinition & jet_def_in,
973  const bool & writeout_combinations) :
974  _jet_def(jet_def_in), _writeout_combinations(writeout_combinations),
975  _structure_shared_ptr(new ClusterSequenceStructure(this))
976 {
977 
978  // transfer the initial jets (type L) into our own array
979  _transfer_input_jets(pseudojets);
980 
981  // transfer the remaining options
983 
984  // run the clustering
985  _initialise_and_run_no_decant();
986 }
987 
988 
989 inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
990  return _jets;
991 }
992 
993 inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
994  return _history;
995 }
996 
997 inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
998 
999 //----------------------------------------------------------------------
1000 // implementation of JetDefinition::operator() is here to avoid nasty
1001 // issues of order of implementations and includes
1002 #ifndef __CINT__
1003 template<class L>
1004 std::vector<PseudoJet> JetDefinition::operator()(const std::vector<L> & particles) const {
1005  // create a new cluster sequence
1006  ClusterSequence * cs = new ClusterSequence(particles, *this);
1007 
1008  // get the jets, and sort them according to whether the algorithm
1009  // is spherical or not
1010  std::vector<PseudoJet> jets;
1011  if (is_spherical()) {
1012  jets = sorted_by_E(cs->inclusive_jets());
1013  } else {
1014  jets = sorted_by_pt(cs->inclusive_jets());
1015  }
1016 
1017  // make sure the ClusterSequence gets deleted once it's no longer
1018  // needed
1019  if (jets.size() != 0) {
1021  } else {
1022  delete cs;
1023  }
1024 
1025  return jets;
1026 }
1027 #endif // __CINT__
1028 
1029 
1030 //----------------------------------------------------------------------
1031 template <class J> inline void ClusterSequence::_bj_set_jetinfo(
1032  J * const jetA, const int _jets_index) const {
1033  jetA->eta = _jets[_jets_index].rap();
1034  jetA->phi = _jets[_jets_index].phi_02pi();
1035  jetA->kt2 = jet_scale_for_algorithm(_jets[_jets_index]);
1036  jetA->_jets_index = _jets_index;
1037  // initialise NN info as well
1038  jetA->NN_dist = _R2;
1039  jetA->NN = NULL;
1040 }
1041 
1042 
1043 
1044 
1045 //----------------------------------------------------------------------
1046 template <class J> inline double ClusterSequence::_bj_dist(
1047  const J * const jetA, const J * const jetB) const {
1048  //#define FASTJET_NEW_DELTA_PHI
1049 #ifndef FASTJET_NEW_DELTA_PHI
1050  //GPS+MC old version of Delta phi calculation
1051  double dphi = std::abs(jetA->phi - jetB->phi);
1052  double deta = (jetA->eta - jetB->eta);
1053  if (dphi > pi) {dphi = twopi - dphi;}
1054 #else
1055  //GPS+MC testing for 2015-02-faster-deltaR2
1056  double dphi = pi-std::abs(pi-std::abs(jetA->phi - jetB->phi));
1057  double deta = (jetA->eta - jetB->eta);
1058 #endif
1059  return dphi*dphi + deta*deta;
1060 }
1061 
1062 //----------------------------------------------------------------------
1063 template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
1064  double kt2 = jet->kt2;
1065  if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
1066  return jet->NN_dist * kt2;
1067 }
1068 
1069 
1070 //----------------------------------------------------------------------
1071 // set the NN for jet without checking whether in the process you might
1072 // have discovered a new nearest neighbour for another jet
1073 template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
1074  J * const jet, J * const head, const J * const tail) const {
1075  double NN_dist = _R2;
1076  J * NN = NULL;
1077  if (head < jet) {
1078  for (J * jetB = head; jetB != jet; jetB++) {
1079  double dist = _bj_dist(jet,jetB);
1080  if (dist < NN_dist) {
1081  NN_dist = dist;
1082  NN = jetB;
1083  }
1084  }
1085  }
1086  if (tail > jet) {
1087  for (J * jetB = jet+1; jetB != tail; jetB++) {
1088  double dist = _bj_dist(jet,jetB);
1089  if (dist < NN_dist) {
1090  NN_dist = dist;
1091  NN = jetB;
1092  }
1093  }
1094  }
1095  jet->NN = NN;
1096  jet->NN_dist = NN_dist;
1097 }
1098 
1099 
1100 //----------------------------------------------------------------------
1101 template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet,
1102  J * const head, const J * const tail) const {
1103  double NN_dist = _R2;
1104  J * NN = NULL;
1105  for (J * jetB = head; jetB != tail; jetB++) {
1106  double dist = _bj_dist(jet,jetB);
1107  if (dist < NN_dist) {
1108  NN_dist = dist;
1109  NN = jetB;
1110  }
1111  if (dist < jetB->NN_dist) {
1112  jetB->NN_dist = dist;
1113  jetB->NN = jet;
1114  }
1115  }
1116  jet->NN = NN;
1117  jet->NN_dist = NN_dist;
1118 }
1119 
1120 FASTJET_END_NAMESPACE
1121 
1122 #endif // __FASTJET_CLUSTERSEQUENCE_HH__
const JetDefinition & jet_def() const
return a reference to the jet definition
ClusterSequenceStructure StructureType
the structure type associated with a jet belonging to a ClusterSequence
double exclusive_ymerge(int njets) const
return the ymin corresponding to the recombination that went from n+1 to n jets (sometimes known as y...
void plugin_associate_extras(Extras *extras_in)
the plugin can associate some extra information with the ClusterSequence object by calling this funct...
void _transfer_input_jets(const std::vector< L > &pseudojets)
transfer the vector<L> of input jets into our own vector<PseudoJet> _jets (with some reserved space f...
vector< PseudoJet > sorted_by_pt(const vector< PseudoJet > &jets)
return a vector of jets sorted into decreasing kt2
Definition: PseudoJet.cc:774
const Extras * extras() const
returns a pointer to the extras object (may be null)
deals with clustering
const std::vector< history_element > & history() const
allow the user to access the raw internal history.
void plugin_simple_N2_cluster()
allows a plugin to run a templated clustering (nearest-neighbour heuristic)
ClusterSequence()
default constructor
ClusterSequence(const ClusterSequence &cs)
copy constructor for a ClusterSequence
std::vector< PseudoJet > inclusive_jets(const double ptmin=0.0) const
return a vector of all jets (in the sense of the inclusive algorithm) with pt >= ptmin.
int jetp_index
index in _history where the current jet is recombined with another jet to form its child...
base class to store extra information that plugins may provide
double Q() const
returns the sum of all energies in the event (relevant mainly for e+e-)
double Q2() const
return Q()^2
Contains any information related to the clustering that should be directly accessible to PseudoJet...
void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, int &newjet_k)
record the fact that there has been a recombination between jets()[jet_i] and jets()[jet_k], with the specified dij, and return the index (newjet_k) allocated to the new jet, whose momentum is assumed to be the 4-vector sum of that of jet_i and jet_j
std::vector< PseudoJet > _jets
This contains the physical PseudoJets; for each PseudoJet one can find the corresponding position in ...
std::vector< history_element > _history
this vector will contain the branching history; for each stage, _history[i].jetp_index indicates wher...
bool plugin_activated() const
returns true when the plugin is allowed to run the show.
class to provide facilities for giving warnings up to some maximum number of times and to provide glo...
int parent2
index in _history where first parent of this jet was created (InexistentParent if this jet is an orig...
std::vector< PseudoJet > operator()(const std::vector< L > &particles) const
cluster the supplied particles and returns a vector of resulting jets, sorted by pt (or energy in the...
double dij
index in the _jets vector where we will find the
void plugin_record_iB_recombination(int jet_i, double diB)
record the fact that there has been a recombination between jets()[jet_i] and the beam...
std::vector< PseudoJet > exclusive_jets_ycut(double ycut) const
the exclusive jets obtained at the given ycut
double exclusive_ymerge_max(int njets) const
same as exclusive_dmerge_max, but normalised to squared total energy
vector< PseudoJet > sorted_by_E(const vector< PseudoJet > &jets)
return a vector of jets sorted into decreasing energy
Definition: PseudoJet.cc:790
Strategy strategy_used() const
return the enum value of the strategy used to cluster the event
int child
index in _history where second parent of this jet was created (InexistentParent if this jet is an ori...
const SharedPtr< PseudoJetStructureBase > & structure_shared_ptr() const
retrieve a shared pointer to the wrapper to this ClusterSequence
an implementation of C++0x shared pointers (or boost&#39;s)
Definition: SharedPtr.hh:121
std::string strategy_string() const
return the name of the strategy used to cluster the event
a single element in the clustering history
int n_exclusive_jets_ycut(double ycut) const
the number of exclusive jets at the given ycut
bool will_delete_self_when_unused() const
return true if the object has been told to delete itself when unused
static std::ostream * fastjet_banner_stream()
returns a pointer to the stream to be used to print banners (cout by default).
void _decant_options_partial()
assuming that the jet definition, writeout_combinations and _structure_shared_ptr have been set (e...
JetAlgorithm
the various families of jet-clustering algorithm
void delete_self_when_unused()
by calling this routine you tell the ClusterSequence to delete itself when all the Pseudojets associa...
Strategy
the various options for the algorithmic strategy to adopt in clustering events with kt and cambridge ...
bool _deletes_self_when_unused
if true then the CS will delete itself when the last external object referring to it disappears...
Class to contain pseudojets, including minimal information of use to jet-clustering routines...
Definition: PseudoJet.hh:67
double max_dij_so_far
the distance corresponding to the recombination at this stage of the clustering.
const std::vector< PseudoJet > & jets() const
allow the user to access the internally stored _jets() array, which contains both the initial particl...
double jet_scale_for_algorithm(const PseudoJet &jet) const
returns the scale associated with a jet as required for this clustering algorithm (kt^2 for the kt-al...
class that is intended to hold a full definition of the jet clusterer
unsigned int n_particles() const
returns the number of particles that were provided to the clustering algorithm (helps the user find t...