StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FJcore.cc
1 // fjcore -- extracted from FastJet v3.0.5 (http://fastjet.fr)
2 //
3 // fjcore constitutes a digest of the main FastJet functionality.
4 // The files fjcore.hh and fjcore.cc are meant to provide easy access to these
5 // core functions, in the form of single files and without the need of a full
6 // FastJet installation:
7 //
8 // g++ main.cc fjcore.cc
9 //
10 // with main.cc including fjcore.hh.
11 //
12 // The results are expected to be identical to those obtained by linking to
13 // the full FastJet distribution.
14 //
15 // NOTE THAT, IN ORDER TO MAKE IT POSSIBLE FOR FJCORE AND THE FULL FASTJET
16 // TO COEXIST, THE FORMER USES THE "fjcore" NAMESPACE INSTEAD OF "fastjet".
17 //
18 // In particular, fjcore provides:
19 //
20 // - access to all native pp and ee algorithms, kt, anti-kt, C/A.
21 // For C/A, the NlnN method is available, while anti-kt and kt
22 // are limited to the N^2 one (still the fastest for N < 20k particles)
23 // - access to selectors, for implementing cuts and selections
24 // - access to all functionalities related to pseudojets (e.g. a jet's
25 // structure or user-defined information)
26 //
27 // Instead, it does NOT provide:
28 //
29 // - jet areas functionality
30 // - background estimation
31 // - access to other algorithms via plugins
32 // - interface to CGAL
33 // - fastjet tools, e.g. filters, taggers
34 //
35 // If these functionalities are needed, the full FastJet installation must be
36 // used. The code will be fully compatible, with the sole replacement of the
37 // header files and of the fjcore namespace with the fastjet one.
38 //
39 // fjcore.hh and fjcore.cc are not meant to be human-readable.
40 // For documentation, see the full FastJet manual and doxygen at http://fastjet.fr
41 //
42 // Like FastJet, fjcore is released under the terms of the GNU General Public
43 // License version 2 (GPLv2). If you use this code as part of work towards a
44 // scientific publication, whether directly or contained within another program
45 // (e.g. Delphes, SpartyJet, Rivet, LHC collaboration software frameworks,
46 // etc.), you should include a citation to
47 //
48 // EPJC72(2012)1896 [arXiv:1111.6097] (FastJet User Manual)
49 // and, optionally, Phys.Lett.B641 (2006) 57 [arXiv:hep-ph/0512210]
50 //
51 // Copyright (c) 2005-2013, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
52 //
53 //----------------------------------------------------------------------
54 // This file is part of FastJet.
55 //
56 // FastJet is free software; you can redistribute it and/or modify
57 // it under the terms of the GNU General Public License as published by
58 // the Free Software Foundation; either version 2 of the License, or
59 // (at your option) any later version.
60 //
61 // The algorithms that underlie FastJet have required considerable
62 // development and are described in hep-ph/0512210. If you use
63 // FastJet as part of work towards a scientific publication, please
64 // include a citation to the FastJet paper.
65 //
66 // FastJet is distributed in the hope that it will be useful,
67 // but WITHOUT ANY WARRANTY; without even the implied warranty of
68 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69 // GNU General Public License for more details.
70 //
71 // You should have received a copy of the GNU General Public License
72 // along with FastJet. If not, see <http://www.gnu.org/licenses/>.
73 //----------------------------------------------------------------------
74 //
75 //#include "fjcore.hh"
76 // For inclusion in Pythia8 line above is replaced by line below.
77 #include "Pythia8/FJcore.h"
78 #ifndef __FJCORE_VERSION_HH__
79 #define __FJCORE_VERSION_HH__
80 #include<string>
81 FJCORE_BEGIN_NAMESPACE
82 const char* fastjet_version = FJCORE_PACKAGE_VERSION;
83 FJCORE_END_NAMESPACE
84 #endif // __FJCORE_VERSION_HH__
85 #ifndef __FJCORE_CLUSTERQUENCE_N2_ICC__
86 #define __FJCORE_CLUSTERQUENCE_N2_ICC__
87 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
88 template<class BJ> void ClusterSequence::_simple_N2_cluster() {
89  int n = _jets.size();
90  BJ * briefjets = new BJ[n];
91  BJ * jetA = briefjets, * jetB;
92  for (int i = 0; i< n; i++) {
93  _bj_set_jetinfo(jetA, i);
94  jetA++; // move on to next entry of briefjets
95  }
96  BJ * tail = jetA; // a semaphore for the end of briefjets
97  BJ * head = briefjets; // a nicer way of naming start
98  for (jetA = head + 1; jetA != tail; jetA++) {
99  _bj_set_NN_crosscheck(jetA, head, jetA);
100  }
101  double * diJ = new double[n];
102  jetA = head;
103  for (int i = 0; i < n; i++) {
104  diJ[i] = _bj_diJ(jetA);
105  jetA++; // have jetA follow i
106  }
107  int history_location = n-1;
108  while (tail != head) {
109  double diJ_min = diJ[0];
110  int diJ_min_jet = 0;
111  for (int i = 1; i < n; i++) {
112  if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
113  }
114  history_location++;
115  jetA = & briefjets[diJ_min_jet];
116  jetB = static_cast<BJ *>(jetA->NN);
117  diJ_min *= _invR2;
118  if (jetB != NULL) {
119  if (jetA < jetB) {std::swap(jetA,jetB);}
120  int nn; // new jet index
121  _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
122  _bj_set_jetinfo(jetB, nn);
123  } else {
124  _do_iB_recombination_step(jetA->_jets_index, diJ_min);
125  }
126  tail--; n--;
127  *jetA = *tail;
128  diJ[jetA - head] = diJ[tail-head];
129  for (BJ * jetI = head; jetI != tail; jetI++) {
130  if (jetI->NN == jetA || jetI->NN == jetB) {
131  _bj_set_NN_nocross(jetI, head, tail);
132  diJ[jetI-head] = _bj_diJ(jetI); // update diJ
133  }
134  if (jetB != NULL) {
135  double dist = _bj_dist(jetI,jetB);
136  if (dist < jetI->NN_dist) {
137  if (jetI != jetB) {
138  jetI->NN_dist = dist;
139  jetI->NN = jetB;
140  diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
141  }
142  }
143  if (dist < jetB->NN_dist) {
144  if (jetI != jetB) {
145  jetB->NN_dist = dist;
146  jetB->NN = jetI;}
147  }
148  }
149  if (jetI->NN == tail) {jetI->NN = jetA;}
150  }
151  if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
152  }
153  delete[] diJ;
154  delete[] briefjets;
155 }
156 FJCORE_END_NAMESPACE
157 #endif // __FJCORE_CLUSTERQUENCE_N2_ICC__
158 #ifndef __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
159 #define __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
160 #include<vector>
161 #include<string>
162 #include<iostream>
163 #include<sstream>
164 #include<cassert>
165 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
166 class EtaPhi {
167 public:
168  double first, second;
169  EtaPhi() {}
170  EtaPhi(double a, double b) {first = a; second = b;}
171  void sanitize() {
172  if (second < 0) second += twopi;
173  if (second >= twopi) second -= twopi;
174  }
175 };
176 class DnnError {
177 public:
178  DnnError() {;};
179  DnnError(const std::string & message_in) {
180  _message = message_in; std::cerr << message_in << std::endl;};
181  std::string message() const {return _message;};
182 private:
183  std::string _message;
184 };
186 public:
187  virtual int NearestNeighbourIndex(const int & ii) const = 0;
188  virtual double NearestNeighbourDistance(const int & ii) const = 0;
189  virtual bool Valid(const int & index) const = 0;
190  virtual void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
191  const std::vector<EtaPhi> & points_to_add,
192  std::vector<int> & indices_added,
193  std::vector<int> & indices_of_updated_neighbours) = 0;
194  inline void RemovePoint (const int & index,
195  std::vector<int> & indices_of_updated_neighbours) {
196  std::vector<int> indices_added;
197  std::vector<EtaPhi> points_to_add;
198  std::vector<int> indices_to_remove(1);
199  indices_to_remove[0] = index;
200  RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
201  indices_of_updated_neighbours
202  );};
203  inline void RemoveCombinedAddCombination(
204  const int & index1, const int & index2,
205  const EtaPhi & newpoint,
206  int & index3,
207  std::vector<int> & indices_of_updated_neighbours) {
208  std::vector<int> indices_added(1);
209  std::vector<EtaPhi> points_to_add(1);
210  std::vector<int> indices_to_remove(2);
211  indices_to_remove[0] = index1;
212  indices_to_remove[1] = index2;
213  points_to_add[0] = newpoint;
214  RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
215  indices_of_updated_neighbours
216  );
217  index3 = indices_added[0];
218  };
219  virtual ~DynamicNearestNeighbours () {}
220 };
221 FJCORE_END_NAMESPACE
222 #endif // __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
223 #ifndef __FJCORE_SEARCHTREE_HH__
224 #define __FJCORE_SEARCHTREE_HH__
225 #include<vector>
226 #include<cassert>
227 #include<cstddef>
228 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
229 template<class T> class SearchTree {
230 public:
231  class Node;
232  class circulator;
233  class const_circulator;
234  SearchTree(const std::vector<T> & init);
235  SearchTree(const std::vector<T> & init, unsigned int max_size);
236  void remove(unsigned node_index);
237  void remove(typename SearchTree::Node * node);
238  void remove(typename SearchTree::circulator & circ);
239  circulator insert(const T & value);
240  const Node & operator[](int i) const {return _nodes[i];};
241  unsigned int size() const {return _nodes.size() - _available_nodes.size();}
242  void verify_structure();
243  void verify_structure_linear() const;
244  void verify_structure_recursive(const Node * , const Node * , const Node * ) const;
245  void print_elements();
246 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
247  inline unsigned int max_depth() const {return _max_depth;};
248 #else
249  inline unsigned int max_depth() const {return 0;};
250 #endif
251  int loc(const Node * node) const ;
252  Node * _find_predecessor(const Node *);
253  Node * _find_successor(const Node *);
254  const Node & operator[](unsigned int i) const {return _nodes[i];};
255  const_circulator somewhere() const;
256  circulator somewhere();
257 private:
258  void _initialize(const std::vector<T> & init);
259  std::vector<Node> _nodes;
260  std::vector<Node *> _available_nodes;
261  Node * _top_node;
262  unsigned int _n_removes;
263  void _do_initial_connections(unsigned int this_one, unsigned int scale,
264  unsigned int left_edge, unsigned int right_edge,
265  unsigned int depth);
266 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
267  unsigned int _max_depth;
268 #endif
269 };
270 template<class T> class SearchTree<T>::Node{
271 public:
272  Node() {};
273  bool treelinks_null() const {
274  return ((parent==0) && (left==0) && (right==0));};
275  inline void nullify_treelinks() {
276  parent = NULL;
277  left = NULL;
278  right = NULL;
279  };
280  void reset_parents_link_to_me(Node * XX);
281  T value;
282  Node * left;
283  Node * right;
284  Node * parent;
285  Node * successor;
286  Node * predecessor;
287 };
288 template<class T> void SearchTree<T>::Node::reset_parents_link_to_me(typename SearchTree<T>::Node * XX) {
289  if (parent == NULL) {return;}
290  if (parent->right == this) {parent->right = XX;}
291  else {parent->left = XX;}
292 }
293 template<class T> class SearchTree<T>::circulator{
294 public:
295  template<class U> friend class SearchTree<U>::const_circulator;
296  friend class SearchTree<T>;
297  circulator() : _node(NULL) {}
298  circulator(Node * node) : _node(node) {}
299  const T * operator->() const {return &(_node->value);}
300  T * operator->() {return &(_node->value);}
301  const T & operator*() const {return _node->value;}
302  T & operator*() {return _node->value;}
303  circulator & operator++() {
304  _node = _node->successor;
305  return *this;}
306  circulator operator++(int) {
307  circulator tmp = *this;
308  _node = _node->successor;
309  return tmp;}
310  circulator & operator--() {
311  _node = _node->predecessor;
312  return *this;}
313  circulator operator--(int) {
314  circulator tmp = *this;
315  _node = _node->predecessor;
316  return tmp;}
317  circulator next() const {
318  return circulator(_node->successor);}
319  circulator previous() const {
320  return circulator(_node->predecessor);}
321  bool operator!=(const circulator & other) const {return other._node != _node;}
322  bool operator==(const circulator & other) const {return other._node == _node;}
323 private:
324  Node * _node;
325 };
326 template<class T> class SearchTree<T>::const_circulator{
327 public:
328  const_circulator() : _node(NULL) {}
329  const_circulator(const Node * node) : _node(node) {}
330  const_circulator(const circulator & circ) :_node(circ._node) {}
331  const T * operator->() {return &(_node->value);}
332  const T & operator*() const {return _node->value;}
333  const_circulator & operator++() {
334  _node = _node->successor;
335  return *this;}
336  const_circulator operator++(int) {
337  const_circulator tmp = *this;
338  _node = _node->successor;
339  return tmp;}
340  const_circulator & operator--() {
341  _node = _node->predecessor;
342  return *this;}
343  const_circulator operator--(int) {
344  const_circulator tmp = *this;
345  _node = _node->predecessor;
346  return tmp;}
347  const_circulator next() const {
348  return const_circulator(_node->successor);}
349  const_circulator previous() const {
350  return const_circulator(_node->predecessor);}
351  bool operator!=(const const_circulator & other) const {return other._node != _node;}
352  bool operator==(const const_circulator & other) const {return other._node == _node;}
353 private:
354  const Node * _node;
355 };
356 template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init,
357  unsigned int max_size) :
358  _nodes(max_size) {
359  _available_nodes.reserve(max_size);
360  _available_nodes.resize(max_size - init.size());
361  for (unsigned int i = init.size(); i < max_size; i++) {
362  _available_nodes[i-init.size()] = &(_nodes[i]);
363  }
364  _initialize(init);
365 }
366 template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init) :
367  _nodes(init.size()), _available_nodes(0) {
368  _available_nodes.reserve(init.size());
369  _initialize(init);
370 }
371 template<class T> void SearchTree<T>::_initialize(const std::vector<T> & init) {
372  _n_removes = 0;
373  unsigned n = init.size();
374  assert(n>=1);
375 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
376  _max_depth = 0;
377 #endif
378  for (unsigned int i = 1; i<n; i++) {
379  assert(!(init[i] < init[i-1]));
380  }
381  for(unsigned int i = 0; i < n; i++) {
382  _nodes[i].value = init[i];
383  _nodes[i].predecessor = (& (_nodes[i])) - 1;
384  _nodes[i].successor = (& (_nodes[i])) + 1;
385  _nodes[i].nullify_treelinks();
386  }
387  _nodes[0].predecessor = (& (_nodes[n-1]));
388  _nodes[n-1].successor = (& (_nodes[0]));
389  unsigned int scale = (n+1)/2;
390  unsigned int top = std::min(n-1,scale);
391  _nodes[top].parent = NULL;
392  _top_node = &(_nodes[top]);
393  _do_initial_connections(top, scale, 0, n, 0);
394 }
395 template<class T> inline int SearchTree<T>::loc(const Node * node) const {return node == NULL?
396  -999 : node - &(_nodes[0]);}
397 template<class T> void SearchTree<T>::_do_initial_connections(
398  unsigned int this_one,
399  unsigned int scale,
400  unsigned int left_edge,
401  unsigned int right_edge,
402  unsigned int depth
403  ) {
404 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
405  _max_depth = max(depth, _max_depth);
406 #endif
407  unsigned int ref_new_scale = (scale+1)/2;
408  unsigned new_scale = ref_new_scale;
409  bool did_child = false;
410  while(true) {
411  int left = this_one - new_scale; // be careful here to use signed int...
412  if (left >= static_cast<int>(left_edge)
413  && _nodes[left].treelinks_null() ) {
414  _nodes[left].parent = &(_nodes[this_one]);
415  _nodes[this_one].left = &(_nodes[left]);
416  _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
417  did_child = true;
418  break;
419  }
420  unsigned int old_new_scale = new_scale;
421  new_scale = (old_new_scale + 1)/2;
422  if (new_scale == old_new_scale) break;
423  }
424  if (!did_child) {_nodes[this_one].left = NULL;}
425  new_scale = ref_new_scale;
426  did_child = false;
427  while(true) {
428  unsigned int right = this_one + new_scale;
429  if (right < right_edge && _nodes[right].treelinks_null()) {
430  _nodes[right].parent = &(_nodes[this_one]);
431  _nodes[this_one].right = &(_nodes[right]);
432  _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
433  did_child = true;
434  break;
435  }
436  unsigned int old_new_scale = new_scale;
437  new_scale = (old_new_scale + 1)/2;
438  if (new_scale == old_new_scale) break;
439  }
440  if (!did_child) {_nodes[this_one].right = NULL;}
441 }
442 template<class T> void SearchTree<T>::remove(unsigned int node_index) {
443  remove(&(_nodes[node_index]));
444 }
445 template<class T> void SearchTree<T>::remove(circulator & circ) {
446  remove(circ._node);
447 }
448 template<class T> void SearchTree<T>::remove(typename SearchTree<T>::Node * node) {
449  assert(size() > 1); // switch this to throw...?
450  assert(!node->treelinks_null());
451  node->predecessor->successor = node->successor;
452  node->successor->predecessor = node->predecessor;
453  if (node->left == NULL && node->right == NULL) {
454  node->reset_parents_link_to_me(NULL);
455  } else if (node->left != NULL && node->right == NULL){
456  node->reset_parents_link_to_me(node->left);
457  node->left->parent = node->parent;
458  if (_top_node == node) {_top_node = node->left;}
459  } else if (node->left == NULL && node->right != NULL){
460  node->reset_parents_link_to_me(node->right);
461  node->right->parent = node->parent;
462  if (_top_node == node) {_top_node = node->right;}
463  } else {
464  Node * replacement;
465  bool use_predecessor = (_n_removes % 2 == 1);
466  if (use_predecessor) {
467  replacement = node->predecessor;
468  assert(replacement->right == NULL); // guaranteed if it's our predecessor
469  if (replacement != node->left) {
470  if (replacement->left != NULL) {
471  replacement->left->parent = replacement->parent;}
472  replacement->reset_parents_link_to_me(replacement->left);
473  replacement->left = node->left;
474  }
475  replacement->parent = node->parent;
476  replacement->right = node->right;
477  } else {
478  replacement = node->successor;
479  assert(replacement->left == NULL); // guaranteed if it's our successor
480  if (replacement != node->right) {
481  if (replacement->right != NULL) {
482  replacement->right->parent = replacement->parent;}
483  replacement->reset_parents_link_to_me(replacement->right);
484  replacement->right = node->right;
485  }
486  replacement->parent = node->parent;
487  replacement->left = node->left;
488  }
489  node->reset_parents_link_to_me(replacement);
490  if (node->left != replacement) {node->left->parent = replacement;}
491  if (node->right != replacement) {node->right->parent = replacement;}
492  if (_top_node == node) {_top_node = replacement;}
493  }
494  node->nullify_treelinks();
495  node->predecessor = NULL;
496  node->successor = NULL;
497  _n_removes++;
498  _available_nodes.push_back(node);
499 }
500 template<class T> typename SearchTree<T>::circulator SearchTree<T>::insert(const T & value) {
501  assert(_available_nodes.size() > 0);
502  Node * node = _available_nodes.back();
503  _available_nodes.pop_back();
504  node->value = value;
505  Node * location = _top_node;
506  Node * old_location = NULL;
507  bool on_left = true; // (init not needed -- but soothes g++4)
508 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
509  unsigned int depth = 0;
510 #endif
511  while(location != NULL) {
512 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
513  depth++;
514 #endif
515  old_location = location;
516  on_left = value < location->value;
517  if (on_left) {location = location->left;}
518  else {location = location->right;}
519  }
520 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
521  _max_depth = max(depth, _max_depth);
522 #endif
523  node->parent = old_location;
524  if (on_left) {node->parent->left = node;}
525  else {node->parent->right = node;}
526  node->left = NULL;
527  node->right = NULL;
528  node->predecessor = _find_predecessor(node);
529  if (node->predecessor != NULL) {
530  node->successor = node->predecessor->successor;
531  node->predecessor->successor = node;
532  node->successor->predecessor = node;
533  } else {
534  node->successor = _find_successor(node);
535  assert(node->successor != NULL); // can only happen if we're sole element
536  node->predecessor = node->successor->predecessor;
537  node->successor->predecessor = node;
538  node->predecessor->successor = node;
539  }
540  return circulator(node);
541 }
542 template<class T> void SearchTree<T>::verify_structure() {
543  verify_structure_linear();
544  const Node * left_limit = _top_node;
545  while (left_limit->left != NULL) {left_limit = left_limit->left;}
546  const Node * right_limit = _top_node;
547  while (right_limit->right != NULL) {right_limit = right_limit->right;}
548  verify_structure_recursive(_top_node, left_limit, right_limit);
549 }
550 template<class T> void SearchTree<T>::verify_structure_recursive(
551  const typename SearchTree<T>::Node * element,
552  const typename SearchTree<T>::Node * left_limit,
553  const typename SearchTree<T>::Node * right_limit) const {
554  assert(!(element->value < left_limit->value));
555  assert(!(right_limit->value < element->value));
556  const Node * left = element->left;
557  if (left != NULL) {
558  assert(!(element->value < left->value));
559  if (left != left_limit) {
560  verify_structure_recursive(left, left_limit, element);}
561  }
562  const Node * right = element->right;
563  if (right != NULL) {
564  assert(!(right->value < element->value));
565  if (right != right_limit) {
566  verify_structure_recursive(right, element, right_limit);}
567  }
568 }
569 template<class T> void SearchTree<T>::verify_structure_linear() const {
570  unsigned n_top = 0;
571  unsigned n_null = 0;
572  for(unsigned i = 0; i < _nodes.size(); i++) {
573  const typename SearchTree<T>::Node * node = &(_nodes[i]);
574  if (node->treelinks_null()) {n_null++; continue;}
575  if (node->parent == NULL) {
576  n_top++;
577  } else {
578  assert((node->parent->left == node) ^ (node->parent->right == node));
579  }
580  if (node->left != NULL) {
581  assert(!(node->value < node->left->value ));}
582  if (node->right != NULL) {
583  assert(!(node->right->value < node->value ));}
584  }
585  assert(n_top == 1 || (n_top == 0 && size() <= 1) );
586  assert(n_null == _available_nodes.size() ||
587  (n_null == _available_nodes.size() + 1 && size() == 1));
588 }
589 template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_predecessor(const typename SearchTree<T>::Node * node) {
590  typename SearchTree<T>::Node * newnode;
591  if (node->left != NULL) {
592  newnode = node->left;
593  while(newnode->right != NULL) {newnode = newnode->right;}
594  return newnode;
595  } else {
596  const typename SearchTree<T>::Node * lastnode = node;
597  newnode = node->parent;
598  while(newnode != NULL) {
599  if (newnode->right == lastnode) {return newnode;}
600  lastnode = newnode;
601  newnode = newnode->parent;
602  }
603  return newnode;
604  }
605 }
606 template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_successor(const typename SearchTree<T>::Node * node) {
607  typename SearchTree<T>::Node * newnode;
608  if (node->right != NULL) {
609  newnode = node->right;
610  while(newnode->left != NULL) {newnode = newnode->left;}
611  return newnode;
612  } else {
613  const typename SearchTree<T>::Node * lastnode = node;
614  newnode = node->parent;
615  while(newnode != NULL) {
616  if (newnode->left == lastnode) {return newnode;}
617  lastnode = newnode;
618  newnode = newnode->parent;
619  }
620  return newnode;
621  }
622 }
623 template<class T> void SearchTree<T>::print_elements() {
624  typename SearchTree<T>::Node * base_node = &(_nodes[0]);
625  typename SearchTree<T>::Node * node = base_node;
626  int n = _nodes.size();
627  for(; node - base_node < n ; node++) {
628  printf("%4d parent:%4d left:%4d right:%4d pred:%4d succ:%4d value:%10.6f\n",loc(node), loc(node->parent), loc(node->left), loc(node->right), loc(node->predecessor),loc(node->successor),node->value);
629  }
630 }
631 template<class T> typename SearchTree<T>::circulator SearchTree<T>::somewhere() {
632  return circulator(_top_node);
633 }
634 template<class T> typename SearchTree<T>::const_circulator SearchTree<T>::somewhere() const {
635  return const_circulator(_top_node);
636 }
637 FJCORE_END_NAMESPACE
638 #endif // __FJCORE_SEARCHTREE_HH__
639 #ifndef __FJCORE_MINHEAP__HH__
640 #define __FJCORE_MINHEAP__HH__
641 #include<vector>
642 #include<cassert>
643 #include<memory>
644 #include<limits>
645 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
646 class MinHeap {
647 public:
648  MinHeap (const std::vector<double> & values, unsigned int max_size) :
649  _heap(max_size) {_initialise(values);};
650  MinHeap (const std::vector<double> & values) :
651  _heap(values.size()) {_initialise(values);};
652  inline unsigned int minloc() const {
653  return (_heap[0].minloc) - &(_heap[0]);};
654  inline double minval() const {return _heap[0].minloc->value;};
655  inline double operator[](int i) const {return _heap[i].value;};
656  void remove(unsigned int loc) {
657  update(loc,std::numeric_limits<double>::max());};
658  void update(unsigned int, double);
659 private:
660  struct ValueLoc{
661  double value;
662  ValueLoc * minloc;
663  };
664  std::vector<ValueLoc> _heap;
665  void _initialise(const std::vector<double> & values);
666 };
667 FJCORE_END_NAMESPACE
668 #endif // __FJCORE_MINHEAP__HH__
669 #ifndef __FJCORE_CLOSESTPAIR2DBASE__HH__
670 #define __FJCORE_CLOSESTPAIR2DBASE__HH__
671 #include<vector>
672 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
673 class Coord2D {
674 public:
675  double x, y;
676  Coord2D() {};
677  Coord2D(double a, double b): x(a), y(b) {};
678  Coord2D operator-(const Coord2D & other) const {
679  return Coord2D(x - other.x, y - other.y);};
680  Coord2D operator+(const Coord2D & other) const {
681  return Coord2D(x + other.x, y + other.y);};
682  Coord2D operator*(double factor) const {return Coord2D(factor*x,factor*y);};
683  friend Coord2D operator*(double factor, const Coord2D & coord) {
684  return Coord2D(factor*coord.x,factor*coord.y);
685  }
686  Coord2D operator/(double divisor) const {
687  return Coord2D(x / divisor, y / divisor);};
688  friend double distance2(const Coord2D & a, const Coord2D & b) {
689  double dx = a.x - b.x, dy = a.y-b.y;
690  return dx*dx+dy*dy;
691  };
692  double distance2(const Coord2D & b) const {
693  double dx = x - b.x, dy = y-b.y;
694  return dx*dx+dy*dy;
695  };
696 };
698 public:
699  virtual void closest_pair(unsigned int & ID1, unsigned int & ID2,
700  double & distance2) const = 0;
701  virtual void remove(unsigned int ID) = 0;
702  virtual unsigned int insert(const Coord2D & position) = 0;
703  virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
704  const Coord2D & position) {
705  remove(ID1);
706  remove(ID2);
707  unsigned new_ID = insert(position);
708  return(new_ID);
709  };
710  virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
711  const std::vector<Coord2D> & new_positions,
712  std::vector<unsigned int> & new_IDs) {
713  for(unsigned i = 0; i < IDs_to_remove.size(); i++) {
714  remove(IDs_to_remove[i]);}
715  new_IDs.resize(0);
716  for(unsigned i = 0; i < new_positions.size(); i++) {
717  new_IDs.push_back(insert(new_positions[i]));}
718  }
719  virtual unsigned int size() = 0;
720  virtual ~ClosestPair2DBase() {};
721 };
722 FJCORE_END_NAMESPACE
723 #endif // __FJCORE_CLOSESTPAIR2DBASE__HH__
724 #ifndef __FJCORE_CLOSESTPAIR2D__HH__
725 #define __FJCORE_CLOSESTPAIR2D__HH__
726 #include<vector>
727 #include<stack>
728 #include<iostream>
729 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
731 public:
732  ClosestPair2D(const std::vector<Coord2D> & positions,
733  const Coord2D & left_corner, const Coord2D & right_corner) {
734  _initialize(positions, left_corner, right_corner, positions.size());
735  };
736  ClosestPair2D(const std::vector<Coord2D> & positions,
737  const Coord2D & left_corner, const Coord2D & right_corner,
738  const unsigned int max_size) {
739  _initialize(positions, left_corner, right_corner, max_size);
740  };
741  void closest_pair(unsigned int & ID1, unsigned int & ID2,
742  double & distance2) const;
743  void remove(unsigned int ID);
744  unsigned int insert(const Coord2D &);
745  virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
746  const Coord2D & position);
747  virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
748  const std::vector<Coord2D> & new_positions,
749  std::vector<unsigned int> & new_IDs);
750  inline void print_tree_depths(std::ostream & outdev) const {
751  outdev << _trees[0]->max_depth() << " "
752  << _trees[1]->max_depth() << " "
753  << _trees[2]->max_depth() << "\n";
754  };
755  unsigned int size();
756 private:
757  void _initialize(const std::vector<Coord2D> & positions,
758  const Coord2D & left_corner, const Coord2D & right_corner,
759  const unsigned int max_size);
760  static const unsigned int _nshift = 3;
761  class Point; // will be defined below
762  template<class T> class triplet {
763  public:
764  inline const T & operator[](unsigned int i) const {return _contents[i];};
765  inline T & operator[](unsigned int i) {return _contents[i];};
766  private:
767  T _contents[_nshift];
768  };
769  class Shuffle {
770  public:
771  unsigned int x, y;
772  Point * point;
773  bool operator<(const Shuffle &) const;
774  void operator+=(unsigned int shift) {x += shift; y+= shift;};
775  };
776  typedef SearchTree<Shuffle> Tree;
779  triplet<std::auto_ptr<Tree> > _trees;
780  std::auto_ptr<MinHeap> _heap;
781  std::vector<Point> _points;
782  std::stack<Point *> _available_points;
783  std::vector<Point *> _points_under_review;
784  static const unsigned int _remove_heap_entry = 1;
785  static const unsigned int _review_heap_entry = 2;
786  static const unsigned int _review_neighbour = 4;
787  void _add_label(Point * point, unsigned int review_flag);
788  void _set_label(Point * point, unsigned int review_flag);
789  void _deal_with_points_to_review();
790  void _remove_from_search_tree(Point * point_to_remove);
791  void _insert_into_search_tree(Point * new_point);
792  void _point2shuffle(Point & , Shuffle & , unsigned int shift);
793  Coord2D _left_corner;
794  double _range;
795  int _ID(const Point *) const;
796  triplet<unsigned int> _shifts; // absolute shifts
797  triplet<unsigned int> _rel_shifts; // shifts relative to previous shift
798  unsigned int _cp_search_range;
799 };
801 public:
802  Coord2D coord;
803  Point * neighbour;
804  double neighbour_dist2;
805  triplet<circulator> circ;
806  unsigned int review_flag;
807  double distance2(const Point & other) const {
808  return coord.distance2(other.coord);
809  };
810 };
811 inline bool floor_ln2_less(unsigned x, unsigned y) {
812  if (x>y) return false;
813  return (x < (x^y)); // beware of operator precedence...
814 }
815 inline int ClosestPair2D::_ID(const Point * point) const {
816  return point - &(_points[0]);
817 }
818 inline unsigned int ClosestPair2D::size() {
819  return _points.size() - _available_points.size();
820 }
821 FJCORE_END_NAMESPACE
822 #endif // __FJCORE_CLOSESTPAIR2D__HH__
823 #include<limits>
824 #include<iostream>
825 #include<iomanip>
826 #include<algorithm>
827 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
828 const unsigned int huge_unsigned = 4294967295U;
829 const unsigned int twopow31 = 2147483648U;
830 using namespace std;
831 void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle,
832  unsigned int shift) {
833  Coord2D renorm_point = (point.coord - _left_corner)/_range;
834  assert(renorm_point.x >=0);
835  assert(renorm_point.x <=1);
836  assert(renorm_point.y >=0);
837  assert(renorm_point.y <=1);
838  shuffle.x = static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
839  shuffle.y = static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
840  shuffle.point = &point;
841 }
842 bool ClosestPair2D::Shuffle::operator<(const Shuffle & q) const {
843  if (floor_ln2_less(x ^ q.x, y ^ q.y)) {
844  return (y < q.y);
845  } else {
846  return (x < q.x);
847  }
848 }
849 void ClosestPair2D::_initialize(const std::vector<Coord2D> & positions,
850  const Coord2D & left_corner,
851  const Coord2D & right_corner,
852  unsigned int max_size) {
853  unsigned int n_positions = positions.size();
854  assert(max_size >= n_positions);
855  _points.resize(max_size);
856  for (unsigned int i = n_positions; i < max_size; i++) {
857  _available_points.push(&(_points[i]));
858  }
859  _left_corner = left_corner;
860  _range = max((right_corner.x - left_corner.x),
861  (right_corner.y - left_corner.y));
862  vector<Shuffle> shuffles(n_positions);
863  for (unsigned int i = 0; i < n_positions; i++) {
864  _points[i].coord = positions[i];
865  _points[i].neighbour_dist2 = numeric_limits<double>::max();
866  _points[i].review_flag = 0;
867  _point2shuffle(_points[i], shuffles[i], 0);
868  }
869  for (unsigned ishift = 0; ishift < _nshift; ishift++) {
870  _shifts[ishift] = static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
871  if (ishift == 0) {_rel_shifts[ishift] = 0;}
872  else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
873  }
874  _cp_search_range = 30;
875  _points_under_review.reserve(_nshift * _cp_search_range);
876  for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
877  if (ishift > 0) {
878  unsigned rel_shift = _rel_shifts[ishift];
879  for (unsigned int i = 0; i < shuffles.size(); i++) {
880  shuffles[i] += rel_shift; }
881  }
882  sort(shuffles.begin(), shuffles.end());
883  _trees[ishift] = auto_ptr<Tree>(new Tree(shuffles, max_size));
884  circulator circ = _trees[ishift]->somewhere(), start=circ;
885  unsigned int CP_range = min(_cp_search_range, n_positions-1);
886  do {
887  Point * this_point = circ->point;
888  this_point->circ[ishift] = circ;
889  circulator other = circ;
890  for (unsigned i=0; i < CP_range; i++) {
891  ++other;
892  double dist2 = this_point->distance2(*other->point);
893  if (dist2 < this_point->neighbour_dist2) {
894  this_point->neighbour_dist2 = dist2;
895  this_point->neighbour = other->point;
896  }
897  }
898  } while (++circ != start);
899  }
900  vector<double> mindists2(n_positions);
901  for (unsigned int i = 0; i < n_positions; i++) {
902  mindists2[i] = _points[i].neighbour_dist2;}
903  _heap = auto_ptr<MinHeap>(new MinHeap(mindists2, max_size));
904 }
905 void ClosestPair2D::closest_pair(unsigned int & ID1, unsigned int & ID2,
906  double & distance2) const {
907  ID1 = _heap->minloc();
908  ID2 = _ID(_points[ID1].neighbour);
909  distance2 = _points[ID1].neighbour_dist2;
910  if (ID1 > ID2) std::swap(ID1,ID2);
911 }
912 inline void ClosestPair2D::_add_label(Point * point, unsigned int review_flag) {
913  if (point->review_flag == 0) _points_under_review.push_back(point);
914  point->review_flag |= review_flag;
915 }
916 inline void ClosestPair2D::_set_label(Point * point, unsigned int review_flag) {
917  if (point->review_flag == 0) _points_under_review.push_back(point);
918  point->review_flag = review_flag;
919 }
920 void ClosestPair2D::remove(unsigned int ID) {
921  Point * point_to_remove = & (_points[ID]);
922  _remove_from_search_tree(point_to_remove);
923  _deal_with_points_to_review();
924 }
925 void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
926  _available_points.push(point_to_remove);
927  _set_label(point_to_remove, _remove_heap_entry);
928  unsigned int CP_range = min(_cp_search_range, size()-1);
929  for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
930  circulator removed_circ = point_to_remove->circ[ishift];
931  circulator right_end = removed_circ.next();
932  _trees[ishift]->remove(removed_circ);
933  circulator left_end = right_end, orig_right_end = right_end;
934  for (unsigned int i = 0; i < CP_range; i++) {left_end--;}
935  if (size()-1 < _cp_search_range) {
936  left_end--; right_end--;
937  }
938  do {
939  Point * left_point = left_end->point;
940  if (left_point->neighbour == point_to_remove) {
941  // we'll deal with it later...
942  _add_label(left_point, _review_neighbour);
943  } else {
944  // check to see if right point has become its closest neighbour
945  double dist2 = left_point->distance2(*right_end->point);
946  if (dist2 < left_point->neighbour_dist2) {
947  left_point->neighbour = right_end->point;
948  left_point->neighbour_dist2 = dist2;
949  // NB: (LESSER) REVIEW NEEDED HERE TOO...
950  _add_label(left_point, _review_heap_entry);
951  }
952  }
953  ++right_end;
954  } while (++left_end != orig_right_end);
955  } // ishift...
956 }
957 void ClosestPair2D::_deal_with_points_to_review() {
958  unsigned int CP_range = min(_cp_search_range, size()-1);
959  while(_points_under_review.size() > 0) {
960  Point * this_point = _points_under_review.back();
961  _points_under_review.pop_back();
962  if (this_point->review_flag & _remove_heap_entry) {
963  assert(!(this_point->review_flag ^ _remove_heap_entry));
964  _heap->remove(_ID(this_point));
965  }
966  else {
967  if (this_point->review_flag & _review_neighbour) {
968  this_point->neighbour_dist2 = numeric_limits<double>::max();
969  // among all three shifts
970  for (unsigned int ishift = 0; ishift < _nshift; ishift++) {
971  circulator other = this_point->circ[ishift];
972  // among points within CP_range
973  for (unsigned i=0; i < CP_range; i++) {
974  ++other;
975  double dist2 = this_point->distance2(*other->point);
976  if (dist2 < this_point->neighbour_dist2) {
977  this_point->neighbour_dist2 = dist2;
978  this_point->neighbour = other->point;
979  }
980  }
981  }
982  }
983  _heap->update(_ID(this_point), this_point->neighbour_dist2);
984  }
985  this_point->review_flag = 0;
986  }
987 }
988 unsigned int ClosestPair2D::insert(const Coord2D & new_coord) {
989  assert(_available_points.size() > 0);
990  Point * new_point = _available_points.top();
991  _available_points.pop();
992  new_point->coord = new_coord;
993  _insert_into_search_tree(new_point);
994  _deal_with_points_to_review();
995  return _ID(new_point);
996 }
997 unsigned int ClosestPair2D::replace(unsigned int ID1, unsigned int ID2,
998  const Coord2D & position) {
999  Point * point_to_remove = & (_points[ID1]);
1000  _remove_from_search_tree(point_to_remove);
1001  point_to_remove = & (_points[ID2]);
1002  _remove_from_search_tree(point_to_remove);
1003  Point * new_point = _available_points.top();
1004  _available_points.pop();
1005  new_point->coord = position;
1006  _insert_into_search_tree(new_point);
1007  _deal_with_points_to_review();
1008  return _ID(new_point);
1009 }
1010 void ClosestPair2D::replace_many(
1011  const std::vector<unsigned int> & IDs_to_remove,
1012  const std::vector<Coord2D> & new_positions,
1013  std::vector<unsigned int> & new_IDs) {
1014  for (unsigned int i = 0; i < IDs_to_remove.size(); i++) {
1015  _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
1016  }
1017  new_IDs.resize(0);
1018  for (unsigned int i = 0; i < new_positions.size(); i++) {
1019  Point * new_point = _available_points.top();
1020  _available_points.pop();
1021  new_point->coord = new_positions[i];
1022  _insert_into_search_tree(new_point);
1023  new_IDs.push_back(_ID(new_point));
1024  }
1025  _deal_with_points_to_review();
1026 }
1027 void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
1028  _set_label(new_point, _review_heap_entry);
1029  new_point->neighbour_dist2 = numeric_limits<double>::max();
1030  unsigned int CP_range = min(_cp_search_range, size()-1);
1031  for (unsigned ishift = 0; ishift < _nshift; ishift++) {
1032  Shuffle new_shuffle;
1033  _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
1034  circulator new_circ = _trees[ishift]->insert(new_shuffle);
1035  new_point->circ[ishift] = new_circ;
1036  circulator right_edge = new_circ; right_edge++;
1037  circulator left_edge = new_circ;
1038  for (unsigned int i = 0; i < CP_range; i++) {left_edge--;}
1039  do {
1040  Point * left_point = left_edge->point;
1041  Point * right_point = right_edge->point;
1042  double new_dist2 = left_point->distance2(*new_point);
1043  if (new_dist2 < left_point->neighbour_dist2) {
1044  left_point->neighbour_dist2 = new_dist2;
1045  left_point->neighbour = new_point;
1046  _add_label(left_point, _review_heap_entry);
1047  }
1048  new_dist2 = new_point->distance2(*right_point);
1049  if (new_dist2 < new_point->neighbour_dist2) {
1050  new_point->neighbour_dist2 = new_dist2;
1051  new_point->neighbour = right_point;
1052  }
1053  if (left_point->neighbour == right_point) {
1054  _add_label(left_point, _review_neighbour);
1055  }
1056  right_edge++;
1057  } while (++left_edge != new_circ);
1058  }
1059 }
1060 FJCORE_END_NAMESPACE
1061 #include<iostream>
1062 #include<sstream>
1063 #include<fstream>
1064 #include<cmath>
1065 #include<cstdlib>
1066 #include<cassert>
1067 #include<string>
1068 #include<set>
1069 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
1070 using namespace std;
1071 std::ostream * ClusterSequence::_fastjet_banner_ostr = &cout;
1072 ClusterSequence::~ClusterSequence () {
1073  if (_structure_shared_ptr()){
1074  ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr());
1075  assert(csi != NULL);
1076  csi->set_associated_cs(NULL);
1077  if (_deletes_self_when_unused) {
1078  _structure_shared_ptr.set_count(_structure_shared_ptr.use_count()
1079  + _structure_use_count_after_construction);
1080  }
1081  }
1082 }
1083 void ClusterSequence::signal_imminent_self_deletion() const {
1084  assert(_deletes_self_when_unused);
1085  _deletes_self_when_unused = false;
1086 }
1087 void ClusterSequence::_initialise_and_run (
1088  const JetDefinition & jet_def_in,
1089  const bool & writeout_combinations) {
1090  _decant_options(jet_def_in, writeout_combinations);
1091  _initialise_and_run_no_decant();
1092 }
1093 void ClusterSequence::_initialise_and_run_no_decant () {
1094  _fill_initial_history();
1095  if (n_particles() == 0) return;
1096  if (_jet_algorithm == plugin_algorithm) {
1097  _plugin_activated = true;
1098  _jet_def.plugin()->run_clustering( (*this) );
1099  _plugin_activated = false;
1100  _update_structure_use_count();
1101  return;
1102  } else if (_jet_algorithm == ee_kt_algorithm ||
1103  _jet_algorithm == ee_genkt_algorithm) {
1104  _strategy = N2Plain;
1105  if (_jet_algorithm == ee_kt_algorithm) {
1106  assert(_Rparam > 2.0);
1107  _invR2 = 1.0;
1108  } else {
1109  if (_Rparam > pi) {
1110  // choose a value that ensures that back-to-back particles will
1111  // always recombine
1112  //_R2 = 4.0000000000001;
1113  _R2 = 2 * ( 3.0 + cos(_Rparam) );
1114  } else {
1115  _R2 = 2 * ( 1.0 - cos(_Rparam) );
1116  }
1117  _invR2 = 1.0/_R2;
1118  }
1119  _simple_N2_cluster_EEBriefJet();
1120  return;
1121  } else if (_jet_algorithm == undefined_jet_algorithm) {
1122  throw Error("A ClusterSequence cannot be created with an uninitialised JetDefinition");
1123  }
1124  if (_strategy == Best) {
1125  int N = _jets.size();
1126  if (min(1.0,max(0.1,_Rparam)*3.3)*N <= 30) {
1127  _strategy = N2Plain;
1128  } else if (N > 6200/pow(_Rparam,2.0) && _jet_def.jet_algorithm() == cambridge_algorithm) {
1129  _strategy = NlnNCam;
1130 #ifndef __FJCORE_DROP_CGAL
1131  } else if ((N > 16000/pow(_Rparam,1.15) && _jet_def.jet_algorithm() != antikt_algorithm)
1132  || N > 35000/pow(_Rparam,1.15)) {
1133  _strategy = NlnN;
1134 #endif // __FJCORE_DROP_CGAL
1135  } else if (N <= 450) {
1136  _strategy = N2Tiled;
1137  } else {
1138  _strategy = N2MinHeapTiled;
1139  }
1140  }
1141  if (_Rparam >= twopi) {
1142  if ( _strategy == NlnN
1143  || _strategy == NlnN3pi
1144  || _strategy == NlnNCam
1145  || _strategy == NlnNCam2pi2R
1146  || _strategy == NlnNCam4pi) {
1147 #ifdef __FJCORE_DROP_CGAL
1148  _strategy = N2MinHeapTiled;
1149 #else
1150  _strategy = NlnN4pi;
1151 #endif
1152  }
1153  if (_jet_def.strategy() != Best && _strategy != _jet_def.strategy()) {
1154  ostringstream oss;
1155  oss << "Cluster strategy " << strategy_string(_jet_def.strategy())
1156  << " automatically changed to " << strategy_string()
1157  << " because the former is not supported for R = " << _Rparam
1158  << " >= 2pi";
1159  _changed_strategy_warning.warn(oss.str());
1160  }
1161  }
1162  if (_strategy == N2Plain) {
1163  this->_simple_N2_cluster_BriefJet();
1164  } else if (_strategy == N2Tiled) {
1165  this->_faster_tiled_N2_cluster();
1166  } else if (_strategy == N2MinHeapTiled) {
1167  this->_minheap_faster_tiled_N2_cluster();
1168  } else if (_strategy == NlnN) {
1169  this->_delaunay_cluster();
1170  } else if (_strategy == NlnNCam) {
1171  this->_CP2DChan_cluster_2piMultD();
1172  } else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
1173  this->_delaunay_cluster();
1174  } else if (_strategy == N3Dumb ) {
1175  this->_really_dumb_cluster();
1176  } else if (_strategy == N2PoorTiled) {
1177  this->_tiled_N2_cluster();
1178  } else if (_strategy == NlnNCam4pi) {
1179  this->_CP2DChan_cluster();
1180  } else if (_strategy == NlnNCam2pi2R) {
1181  this->_CP2DChan_cluster_2pi2R();
1182  } else {
1183  ostringstream err;
1184  err << "Unrecognised value for strategy: "<<_strategy;
1185  throw Error(err.str());
1186  }
1187 }
1188 bool ClusterSequence::_first_time = true;
1189 int ClusterSequence::_n_exclusive_warnings = 0;
1190 string fastjet_version_string() {
1191  return "FastJet version "+string(fastjet_version)+" [fjcore]";
1192 }
1193 void ClusterSequence::print_banner() {
1194  if (!_first_time) {return;}
1195  _first_time = false;
1196  ostream * ostr = _fastjet_banner_ostr;
1197  if (!ostr) return;
1198  (*ostr) << "#--------------------------------------------------------------------------\n";
1199  (*ostr) << "# FastJet release " << fastjet_version << " [fjcore]" << endl;
1200  (*ostr) << "# M. Cacciari, G.P. Salam and G. Soyez \n";
1201  (*ostr) << "# A software package for jet finding and analysis at colliders \n";
1202  (*ostr) << "# http://fastjet.fr \n";
1203  (*ostr) << "# \n";
1204  (*ostr) << "# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package\n";
1205  (*ostr) << "# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210]. \n";
1206  (*ostr) << "# \n";
1207  (*ostr) << "# FastJet is provided without warranty under the terms of the GNU GPLv2.\n";
1208  (*ostr) << "# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code";
1209 #ifndef __FJCORE_DROP_CGAL
1210  (*ostr) << ",\n# CGAL ";
1211 #else
1212  (*ostr) << "\n# ";
1213 #endif // __FJCORE_DROP_CGAL
1214  (*ostr) << "and 3rd party plugin jet algorithms. See COPYING file for details.\n";
1215  (*ostr) << "#--------------------------------------------------------------------------\n";
1216  ostr->flush();
1217 }
1218 void ClusterSequence::_decant_options(const JetDefinition & jet_def_in,
1219  const bool & writeout_combinations) {
1220  _jet_def = jet_def_in;
1221  _writeout_combinations = writeout_combinations;
1222  _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
1223  _decant_options_partial();
1224 }
1225 void ClusterSequence::_decant_options_partial() {
1226  print_banner();
1227  _jet_algorithm = _jet_def.jet_algorithm();
1228  _Rparam = _jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
1229  _strategy = _jet_def.strategy();
1230  _plugin_activated = false;
1231  _update_structure_use_count(); // make sure it's correct already here
1232 }
1233 void ClusterSequence::_fill_initial_history () {
1234  _jets.reserve(_jets.size()*2);
1235  _history.reserve(_jets.size()*2);
1236  _Qtot = 0;
1237  for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
1238  history_element element;
1239  element.parent1 = InexistentParent;
1240  element.parent2 = InexistentParent;
1241  element.child = Invalid;
1242  element.jetp_index = i;
1243  element.dij = 0.0;
1244  element.max_dij_so_far = 0.0;
1245  _history.push_back(element);
1246  _jet_def.recombiner()->preprocess(_jets[i]);
1247  _jets[i].set_cluster_hist_index(i);
1248  _set_structure_shared_ptr(_jets[i]);
1249  _Qtot += _jets[i].E();
1250  }
1251  _initial_n = _jets.size();
1252  _deletes_self_when_unused = false;
1253 }
1254 string ClusterSequence::strategy_string (Strategy strategy_in) const {
1255  string strategy;
1256  switch(strategy_in) {
1257  case NlnN:
1258  strategy = "NlnN"; break;
1259  case NlnN3pi:
1260  strategy = "NlnN3pi"; break;
1261  case NlnN4pi:
1262  strategy = "NlnN4pi"; break;
1263  case N2Plain:
1264  strategy = "N2Plain"; break;
1265  case N2Tiled:
1266  strategy = "N2Tiled"; break;
1267  case N2MinHeapTiled:
1268  strategy = "N2MinHeapTiled"; break;
1269  case N2PoorTiled:
1270  strategy = "N2PoorTiled"; break;
1271  case N3Dumb:
1272  strategy = "N3Dumb"; break;
1273  case NlnNCam4pi:
1274  strategy = "NlnNCam4pi"; break;
1275  case NlnNCam2pi2R:
1276  strategy = "NlnNCam2pi2R"; break;
1277  case NlnNCam:
1278  strategy = "NlnNCam"; break; // 2piMultD
1279  case plugin_strategy:
1280  strategy = "plugin strategy"; break;
1281  default:
1282  strategy = "Unrecognized";
1283  }
1284  return strategy;
1285 }
1286 double ClusterSequence::jet_scale_for_algorithm(
1287  const PseudoJet & jet) const {
1288  if (_jet_algorithm == kt_algorithm) {return jet.kt2();}
1289  else if (_jet_algorithm == cambridge_algorithm) {return 1.0;}
1290  else if (_jet_algorithm == antikt_algorithm) {
1291  double kt2=jet.kt2();
1292  return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
1293  } else if (_jet_algorithm == genkt_algorithm) {
1294  double kt2 = jet.kt2();
1295  double p = jet_def().extra_param();
1296  if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300; // dodgy safety check
1297  return pow(kt2, p);
1298  } else if (_jet_algorithm == cambridge_for_passive_algorithm) {
1299  double kt2 = jet.kt2();
1300  double lim = _jet_def.extra_param();
1301  if (kt2 < lim*lim && kt2 != 0.0) {
1302  return 1.0/kt2;
1303  } else {return 1.0;}
1304  } else {throw Error("Unrecognised jet algorithm");}
1305 }
1306 void ClusterSequence::transfer_from_sequence(const ClusterSequence & from_seq,
1307  const FunctionOfPseudoJet<PseudoJet> * action_on_jets){
1308  if (will_delete_self_when_unused())
1309  throw(Error("cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
1310  _jet_def = from_seq._jet_def ;
1311  _writeout_combinations = from_seq._writeout_combinations ;
1312  _initial_n = from_seq._initial_n ;
1313  _Rparam = from_seq._Rparam ;
1314  _R2 = from_seq._R2 ;
1315  _invR2 = from_seq._invR2 ;
1316  _strategy = from_seq._strategy ;
1317  _jet_algorithm = from_seq._jet_algorithm ;
1318  _plugin_activated = from_seq._plugin_activated ;
1319  if (action_on_jets)
1320  _jets = (*action_on_jets)(from_seq._jets);
1321  else
1322  _jets = from_seq._jets;
1323  _history = from_seq._history;
1324  _extras = from_seq._extras;
1325  if (_structure_shared_ptr()) {
1326  if (_deletes_self_when_unused) throw Error("transfer_from_sequence cannot be used for a cluster sequence that deletes self when unused");
1327  ClusterSequenceStructure* csi = dynamic_cast<ClusterSequenceStructure*>(_structure_shared_ptr());
1328  assert(csi != NULL);
1329  csi->set_associated_cs(NULL);
1330  }
1331  _structure_shared_ptr.reset(new ClusterSequenceStructure(this));
1332  _update_structure_use_count();
1333  for (unsigned int i=0; i<_jets.size(); i++){
1334  _jets[i].set_cluster_hist_index(from_seq._jets[i].cluster_hist_index());
1335  _set_structure_shared_ptr(_jets[i]);
1336  }
1337 }
1338 void ClusterSequence::plugin_record_ij_recombination(
1339  int jet_i, int jet_j, double dij,
1340  const PseudoJet & newjet, int & newjet_k) {
1341  plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
1342  int tmp_index = _jets[newjet_k].cluster_hist_index();
1343  _jets[newjet_k] = newjet;
1344  _jets[newjet_k].set_cluster_hist_index(tmp_index);
1345  _set_structure_shared_ptr(_jets[newjet_k]);
1346 }
1347 vector<PseudoJet> ClusterSequence::inclusive_jets (const double & ptmin) const{
1348  double dcut = ptmin*ptmin;
1349  int i = _history.size() - 1; // last jet
1350  vector<PseudoJet> jets_local;
1351  if (_jet_algorithm == kt_algorithm) {
1352  while (i >= 0) {
1353  if (_history[i].max_dij_so_far < dcut) {break;}
1354  if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
1355  // for beam jets
1356  int parent1 = _history[i].parent1;
1357  jets_local.push_back(_jets[_history[parent1].jetp_index]);}
1358  i--;
1359  }
1360  } else if (_jet_algorithm == cambridge_algorithm) {
1361  while (i >= 0) {
1362  if (_history[i].parent2 != BeamJet) {break;}
1363  int parent1 = _history[i].parent1;
1364  const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1365  if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1366  i--;
1367  }
1368  } else if (_jet_algorithm == plugin_algorithm
1369  || _jet_algorithm == ee_kt_algorithm
1370  || _jet_algorithm == antikt_algorithm
1371  || _jet_algorithm == genkt_algorithm
1372  || _jet_algorithm == ee_genkt_algorithm
1373  || _jet_algorithm == cambridge_for_passive_algorithm) {
1374  while (i >= 0) {
1375  if (_history[i].parent2 == BeamJet) {
1376  int parent1 = _history[i].parent1;
1377  const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1378  if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1379  }
1380  i--;
1381  }
1382  } else {throw Error("cs::inclusive_jets(...): Unrecognized jet algorithm");}
1383  return jets_local;
1384 }
1385 int ClusterSequence::n_exclusive_jets (const double & dcut) const {
1386  int i = _history.size() - 1; // last jet
1387  while (i >= 0) {
1388  if (_history[i].max_dij_so_far <= dcut) {break;}
1389  i--;
1390  }
1391  int stop_point = i + 1;
1392  int njets = 2*_initial_n - stop_point;
1393  return njets;
1394 }
1395 vector<PseudoJet> ClusterSequence::exclusive_jets (const double & dcut) const {
1396  int njets = n_exclusive_jets(dcut);
1397  return exclusive_jets(njets);
1398 }
1399 vector<PseudoJet> ClusterSequence::exclusive_jets (const int & njets) const {
1400  if (njets > _initial_n) {
1401  ostringstream err;
1402  err << "Requested " << njets << " exclusive jets, but there were only "
1403  << _initial_n << " particles in the event";
1404  throw Error(err.str());
1405  }
1406  return exclusive_jets_up_to(njets);
1407 }
1408 vector<PseudoJet> ClusterSequence::exclusive_jets_up_to (const int & njets) const {
1409  if (( _jet_def.jet_algorithm() != kt_algorithm) &&
1410  ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
1411  ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
1412  (((_jet_def.jet_algorithm() != genkt_algorithm) &&
1413  (_jet_def.jet_algorithm() != ee_genkt_algorithm)) ||
1414  (_jet_def.extra_param() <0)) &&
1415  ((_jet_def.jet_algorithm() != plugin_algorithm) ||
1416  (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
1417  (_n_exclusive_warnings < 5)) {
1418  _n_exclusive_warnings++;
1419  cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
1420  }
1421  int stop_point = 2*_initial_n - njets;
1422  if (stop_point < _initial_n) stop_point = _initial_n;
1423  if (2*_initial_n != static_cast<int>(_history.size())) {
1424  ostringstream err;
1425  err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
1426  throw Error(err.str());
1427  }
1428  vector<PseudoJet> jets_local;
1429  for (unsigned int i = stop_point; i < _history.size(); i++) {
1430  int parent1 = _history[i].parent1;
1431  if (parent1 < stop_point) {
1432  jets_local.push_back(_jets[_history[parent1].jetp_index]);
1433  }
1434  int parent2 = _history[i].parent2;
1435  if (parent2 < stop_point && parent2 > 0) {
1436  jets_local.push_back(_jets[_history[parent2].jetp_index]);
1437  }
1438  }
1439  if (int(jets_local.size()) != min(_initial_n, njets)) {
1440  ostringstream err;
1441  err << "ClusterSequence::exclusive_jets: size of returned vector ("
1442  <<jets_local.size()<<") does not coincide with requested number of jets ("
1443  <<njets<<")";
1444  throw Error(err.str());
1445  }
1446  return jets_local;
1447 }
1448 double ClusterSequence::exclusive_dmerge (const int & njets) const {
1449  assert(njets >= 0);
1450  if (njets >= _initial_n) {return 0.0;}
1451  return _history[2*_initial_n-njets-1].dij;
1452 }
1453 double ClusterSequence::exclusive_dmerge_max (const int & njets) const {
1454  assert(njets >= 0);
1455  if (njets >= _initial_n) {return 0.0;}
1456  return _history[2*_initial_n-njets-1].max_dij_so_far;
1457 }
1458 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1459  (const PseudoJet & jet, const double & dcut) const {
1460  set<const history_element*> subhist;
1461  get_subhist_set(subhist, jet, dcut, 0);
1462  vector<PseudoJet> subjets;
1463  subjets.reserve(subhist.size());
1464  for (set<const history_element*>::iterator elem = subhist.begin();
1465  elem != subhist.end(); elem++) {
1466  subjets.push_back(_jets[(*elem)->jetp_index]);
1467  }
1468  return subjets;
1469 }
1470 int ClusterSequence::n_exclusive_subjets(const PseudoJet & jet,
1471  const double & dcut) const {
1472  set<const history_element*> subhist;
1473  get_subhist_set(subhist, jet, dcut, 0);
1474  return subhist.size();
1475 }
1476 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1477  (const PseudoJet & jet, int nsub) const {
1478  vector<PseudoJet> subjets = exclusive_subjets_up_to(jet, nsub);
1479  if (int(subjets.size()) < nsub) {
1480  ostringstream err;
1481  err << "Requested " << nsub << " exclusive subjets, but there were only "
1482  << subjets.size() << " particles in the jet";
1483  throw Error(err.str());
1484  }
1485  return subjets;
1486 }
1487 std::vector<PseudoJet> ClusterSequence::exclusive_subjets_up_to
1488  (const PseudoJet & jet, int nsub) const {
1489  set<const history_element*> subhist;
1490  vector<PseudoJet> subjets;
1491  if (nsub < 0) throw Error("Requested a negative number of subjets. This is nonsensical.");
1492  if (nsub == 0) return subjets;
1493  get_subhist_set(subhist, jet, -1.0, nsub);
1494  subjets.reserve(subhist.size());
1495  for (set<const history_element*>::iterator elem = subhist.begin();
1496  elem != subhist.end(); elem++) {
1497  subjets.push_back(_jets[(*elem)->jetp_index]);
1498  }
1499  return subjets;
1500 }
1501 double ClusterSequence::exclusive_subdmerge(const PseudoJet & jet, int nsub) const {
1502  set<const history_element*> subhist;
1503  get_subhist_set(subhist, jet, -1.0, nsub);
1504  set<const history_element*>::iterator highest = subhist.end();
1505  highest--;
1506  return (*highest)->dij;
1507 }
1508 double ClusterSequence::exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const {
1509  set<const history_element*> subhist;
1510  get_subhist_set(subhist, jet, -1.0, nsub);
1511  set<const history_element*>::iterator highest = subhist.end();
1512  highest--;
1513  return (*highest)->max_dij_so_far;
1514 }
1515 void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
1516  const PseudoJet & jet,
1517  double dcut, int maxjet) const {
1518  assert(contains(jet));
1519  subhist.clear();
1520  subhist.insert(&(_history[jet.cluster_hist_index()]));
1521  int njet = 1;
1522  while (true) {
1523  set<const history_element*>::iterator highest = subhist.end();
1524  assert (highest != subhist.begin());
1525  highest--;
1526  const history_element* elem = *highest;
1527  if (njet == maxjet) break;
1528  if (elem->parent1 < 0) break;
1529  if (elem->max_dij_so_far <= dcut) break;
1530  subhist.erase(highest);
1531  subhist.insert(&(_history[elem->parent1]));
1532  subhist.insert(&(_history[elem->parent2]));
1533  njet++;
1534  }
1535 }
1536 bool ClusterSequence::object_in_jet(const PseudoJet & object,
1537  const PseudoJet & jet) const {
1538  assert(contains(object) && contains(jet));
1539  const PseudoJet * this_object = &object;
1540  const PseudoJet * childp;
1541  while(true) {
1542  if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
1543  return true;
1544  } else if (has_child(*this_object, childp)) {
1545  this_object = childp;
1546  } else {
1547  return false;
1548  }
1549  }
1550 }
1551 bool ClusterSequence::has_parents(const PseudoJet & jet, PseudoJet & parent1,
1552  PseudoJet & parent2) const {
1553  const history_element & hist = _history[jet.cluster_hist_index()];
1554  assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
1555  (hist.parent1 < 0 && hist.parent2 < 0));
1556  if (hist.parent1 < 0) {
1557  parent1 = PseudoJet(0.0,0.0,0.0,0.0);
1558  parent2 = parent1;
1559  return false;
1560  } else {
1561  parent1 = _jets[_history[hist.parent1].jetp_index];
1562  parent2 = _jets[_history[hist.parent2].jetp_index];
1563  if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
1564  return true;
1565  }
1566 }
1567 bool ClusterSequence::has_child(const PseudoJet & jet, PseudoJet & child) const {
1568  const PseudoJet * childp;
1569  bool res = has_child(jet, childp);
1570  if (res) {
1571  child = *childp;
1572  return true;
1573  } else {
1574  child = PseudoJet(0.0,0.0,0.0,0.0);
1575  return false;
1576  }
1577 }
1578 bool ClusterSequence::has_child(const PseudoJet & jet, const PseudoJet * & childp) const {
1579  const history_element & hist = _history[jet.cluster_hist_index()];
1580  if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
1581  childp = &(_jets[_history[hist.child].jetp_index]);
1582  return true;
1583  } else {
1584  childp = NULL;
1585  return false;
1586  }
1587 }
1588 bool ClusterSequence::has_partner(const PseudoJet & jet,
1589  PseudoJet & partner) const {
1590  const history_element & hist = _history[jet.cluster_hist_index()];
1591  if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
1592  const history_element & child_hist = _history[hist.child];
1593  if (child_hist.parent1 == jet.cluster_hist_index()) {
1594  partner = _jets[_history[child_hist.parent2].jetp_index];
1595  } else {
1596  partner = _jets[_history[child_hist.parent1].jetp_index];
1597  }
1598  return true;
1599  } else {
1600  partner = PseudoJet(0.0,0.0,0.0,0.0);
1601  return false;
1602  }
1603 }
1604 vector<PseudoJet> ClusterSequence::constituents (const PseudoJet & jet) const {
1605  vector<PseudoJet> subjets;
1606  add_constituents(jet, subjets);
1607  return subjets;
1608 }
1609 void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in,
1610  ostream & ostr) const {
1611  for (unsigned i = 0; i < jets_in.size(); i++) {
1612  ostr << i << " "
1613  << jets_in[i].px() << " "
1614  << jets_in[i].py() << " "
1615  << jets_in[i].pz() << " "
1616  << jets_in[i].E() << endl;
1617  vector<PseudoJet> cst = constituents(jets_in[i]);
1618  for (unsigned j = 0; j < cst.size() ; j++) {
1619  ostr << " " << j << " "
1620  << cst[j].rap() << " "
1621  << cst[j].phi() << " "
1622  << cst[j].perp() << endl;
1623  }
1624  ostr << "#END" << endl;
1625  }
1626 }
1627 void ClusterSequence::print_jets_for_root(const std::vector<PseudoJet> & jets_in,
1628  const std::string & filename,
1629  const std::string & comment ) const {
1630  std::ofstream ostr(filename.c_str());
1631  if (comment != "") ostr << "# " << comment << endl;
1632  print_jets_for_root(jets_in, ostr);
1633 }
1634 vector<int> ClusterSequence::particle_jet_indices(
1635  const vector<PseudoJet> & jets_in) const {
1636  vector<int> indices(n_particles());
1637  for (unsigned ipart = 0; ipart < n_particles(); ipart++)
1638  indices[ipart] = -1;
1639  for (unsigned ijet = 0; ijet < jets_in.size(); ijet++) {
1640  vector<PseudoJet> jet_constituents(constituents(jets_in[ijet]));
1641  for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
1642  unsigned iclust = jet_constituents[ip].cluster_hist_index();
1643  unsigned ipart = history()[iclust].jetp_index;
1644  indices[ipart] = ijet;
1645  }
1646  }
1647  return indices;
1648 }
1649 void ClusterSequence::add_constituents (
1650  const PseudoJet & jet, vector<PseudoJet> & subjet_vector) const {
1651  int i = jet.cluster_hist_index();
1652  int parent1 = _history[i].parent1;
1653  int parent2 = _history[i].parent2;
1654  if (parent1 == InexistentParent) {
1655  subjet_vector.push_back(_jets[i]);
1656  return;
1657  }
1658  add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
1659  if (parent2 != BeamJet) {
1660  add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
1661  }
1662 }
1663 void ClusterSequence::_add_step_to_history (
1664  const int & step_number, const int & parent1,
1665  const int & parent2, const int & jetp_index,
1666  const double & dij) {
1667  history_element element;
1668  element.parent1 = parent1;
1669  element.parent2 = parent2;
1670  element.jetp_index = jetp_index;
1671  element.child = Invalid;
1672  element.dij = dij;
1673  element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
1674  _history.push_back(element);
1675  int local_step = _history.size()-1;
1676  assert(local_step == step_number);
1677  assert(parent1 >= 0);
1678  _history[parent1].child = local_step;
1679  if (parent2 >= 0) {_history[parent2].child = local_step;}
1680  if (jetp_index != Invalid) {
1681  assert(jetp_index >= 0);
1682  _jets[jetp_index].set_cluster_hist_index(local_step);
1683  _set_structure_shared_ptr(_jets[jetp_index]);
1684  }
1685  if (_writeout_combinations) {
1686  cout << local_step << ": "
1687  << parent1 << " with " << parent2
1688  << "; y = "<< dij<<endl;
1689  }
1690 }
1691 vector<int> ClusterSequence::unique_history_order() const {
1692  valarray<int> lowest_constituent(_history.size());
1693  int hist_n = _history.size();
1694  lowest_constituent = hist_n; // give it a large number
1695  for (int i = 0; i < hist_n; i++) {
1696  lowest_constituent[i] = min(lowest_constituent[i],i);
1697  if (_history[i].child > 0) lowest_constituent[_history[i].child]
1698  = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
1699  }
1700  valarray<bool> extracted(_history.size()); extracted = false;
1701  vector<int> unique_tree;
1702  unique_tree.reserve(_history.size());
1703  for (unsigned i = 0; i < n_particles(); i++) {
1704  if (!extracted[i]) {
1705  unique_tree.push_back(i);
1706  extracted[i] = true;
1707  _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
1708  }
1709  }
1710  return unique_tree;
1711 }
1712 void ClusterSequence::_extract_tree_children(
1713  int position,
1714  valarray<bool> & extracted,
1715  const valarray<int> & lowest_constituent,
1716  vector<int> & unique_tree) const {
1717  if (!extracted[position]) {
1718  _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
1719  }
1720  int child = _history[position].child;
1721  if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
1722 }
1723 vector<PseudoJet> ClusterSequence::unclustered_particles() const {
1724  vector<PseudoJet> unclustered;
1725  for (unsigned i = 0; i < n_particles() ; i++) {
1726  if (_history[i].child == Invalid)
1727  unclustered.push_back(_jets[_history[i].jetp_index]);
1728  }
1729  return unclustered;
1730 }
1731 vector<PseudoJet> ClusterSequence::childless_pseudojets() const {
1732  vector<PseudoJet> unclustered;
1733  for (unsigned i = 0; i < _history.size() ; i++) {
1734  if ((_history[i].child == Invalid) && (_history[i].parent2 != BeamJet))
1735  unclustered.push_back(_jets[_history[i].jetp_index]);
1736  }
1737  return unclustered;
1738 }
1739 bool ClusterSequence::contains(const PseudoJet & jet) const {
1740  return jet.cluster_hist_index() >= 0
1741  && jet.cluster_hist_index() < int(_history.size())
1742  && jet.has_valid_cluster_sequence()
1743  && jet.associated_cluster_sequence() == this;
1744 }
1745 void ClusterSequence::_extract_tree_parents(
1746  int position,
1747  valarray<bool> & extracted,
1748  const valarray<int> & lowest_constituent,
1749  vector<int> & unique_tree) const {
1750  if (!extracted[position]) {
1751  int parent1 = _history[position].parent1;
1752  int parent2 = _history[position].parent2;
1753  if (parent1 >= 0 && parent2 >= 0) {
1754  if (lowest_constituent[parent1] > lowest_constituent[parent2])
1755  std::swap(parent1, parent2);
1756  }
1757  if (parent1 >= 0 && !extracted[parent1])
1758  _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
1759  if (parent2 >= 0 && !extracted[parent2])
1760  _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
1761  unique_tree.push_back(position);
1762  extracted[position] = true;
1763  }
1764 }
1765 void ClusterSequence::_do_ij_recombination_step(
1766  const int & jet_i, const int & jet_j,
1767  const double & dij,
1768  int & newjet_k) {
1769  PseudoJet newjet(false);
1770  _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
1771  _jets.push_back(newjet);
1772  newjet_k = _jets.size()-1;
1773  int newstep_k = _history.size();
1774  _jets[newjet_k].set_cluster_hist_index(newstep_k);
1775  int hist_i = _jets[jet_i].cluster_hist_index();
1776  int hist_j = _jets[jet_j].cluster_hist_index();
1777  _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
1778  newjet_k, dij);
1779 }
1780 void ClusterSequence::_do_iB_recombination_step(
1781  const int & jet_i, const double & diB) {
1782  int newstep_k = _history.size();
1783  _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
1784  Invalid, diB);
1785 }
1786 LimitedWarning ClusterSequence::_changed_strategy_warning;
1787 void ClusterSequence::_set_structure_shared_ptr(PseudoJet & j) {
1788  j.set_structure_shared_ptr(_structure_shared_ptr);
1789  _update_structure_use_count();
1790 }
1791 void ClusterSequence::_update_structure_use_count() {
1792  _structure_use_count_after_construction = _structure_shared_ptr.use_count();
1793 }
1794 void ClusterSequence::delete_self_when_unused() {
1795  int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
1796  if (new_count <= 0) {
1797  throw Error("delete_self_when_unused may only be called if at least one object outside the CS (e.g. a jet) is already associated with the CS");
1798  }
1799  _structure_shared_ptr.set_count(new_count);
1800  _deletes_self_when_unused = true;
1801 }
1802 FJCORE_END_NAMESPACE
1803 #include<limits>
1804 #include<vector>
1805 #include<cmath>
1806 #include<iostream>
1807 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
1808 using namespace std;
1809 namespace Private {
1810  class MirrorInfo{
1811  public:
1812  int orig, mirror;
1813  MirrorInfo(int a, int b) : orig(a), mirror(b) {};
1814  MirrorInfo() {};
1815  };
1816  bool make_mirror(Coord2D & point, double Dlim) {
1817  if (point.y < Dlim) {point.y += twopi; return true;}
1818  if (twopi-point.y < Dlim) {point.y -= twopi; return true;}
1819  return false;
1820  }
1821 }
1822 using namespace Private;
1823 void ClusterSequence::_CP2DChan_limited_cluster (double Dlim) {
1824  unsigned int n = _initial_n;
1825  vector<MirrorInfo> coordIDs(2*n); // coord IDs of a given jetID
1826  vector<int> jetIDs(2*n); // jet ID for a given coord ID
1827  vector<Coord2D> coords(2*n); // our coordinates (and copies)
1828  double Dlim4mirror = min(Dlim,pi);
1829  double minrap = numeric_limits<double>::max();
1830  double maxrap = -minrap;
1831  int coord_index = -1;
1832  int n_active = 0;
1833  for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
1834  if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
1835  (_jets[jet_i].E() == abs(_jets[jet_i].pz()) &&
1836  _jets[jet_i].perp2() == 0.0)
1837  ) {continue;}
1838  n_active++;
1839  coordIDs[jet_i].orig = ++coord_index;
1840  coords[coord_index] = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
1841  jetIDs[coord_index] = jet_i;
1842  minrap = min(coords[coord_index].x,minrap);
1843  maxrap = max(coords[coord_index].x,maxrap);
1844  Coord2D mirror_point(coords[coord_index]);
1845  if (make_mirror(mirror_point, Dlim4mirror)) {
1846  coordIDs[jet_i].mirror = ++coord_index;
1847  coords[coord_index] = mirror_point;
1848  jetIDs[coord_index] = jet_i;
1849  } else {
1850  coordIDs[jet_i].mirror = Invalid;
1851  }
1852  }
1853  coords.resize(coord_index+1);
1854  Coord2D left_edge(minrap-1.0, -3.15); // a security margin below -pi
1855  Coord2D right_edge(maxrap+1.0, 9.45); // a security margin above 3*pi
1856  ClosestPair2D cp(coords, left_edge, right_edge);
1857  vector<Coord2D> new_points(2);
1858  vector<unsigned int> cIDs_to_remove(4);
1859  vector<unsigned int> new_cIDs(2);
1860  do {
1861  unsigned int cID1, cID2;
1862  double distance2;
1863  cp.closest_pair(cID1,cID2,distance2);
1864  if (distance2 > Dlim*Dlim) {break;}
1865  distance2 *= _invR2;
1866  int jet_i = jetIDs[cID1];
1867  int jet_j = jetIDs[cID2];
1868  assert (jet_i != jet_j); // to catch issue of recombining with mirror point
1869  int newjet_k;
1870  _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
1871  if (--n_active == 1) {break;}
1872  cIDs_to_remove.resize(0);
1873  cIDs_to_remove.push_back(coordIDs[jet_i].orig);
1874  cIDs_to_remove.push_back(coordIDs[jet_j].orig);
1875  if (coordIDs[jet_i].mirror != Invalid)
1876  cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
1877  if (coordIDs[jet_j].mirror != Invalid)
1878  cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
1879  Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
1880  new_points.resize(0);
1881  new_points.push_back(new_point);
1882  if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point); //< same warning as before concerning the mirroring
1883  cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
1884  coordIDs[newjet_k].orig = new_cIDs[0];
1885  jetIDs[new_cIDs[0]] = newjet_k;
1886  if (new_cIDs.size() == 2) {
1887  coordIDs[newjet_k].mirror = new_cIDs[1];
1888  jetIDs[new_cIDs[1]] = newjet_k;
1889  } else {coordIDs[newjet_k].mirror = Invalid;}
1890  } while(true);
1891 }
1892 void ClusterSequence::_CP2DChan_cluster_2pi2R () {
1893  if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
1894  _CP2DChan_limited_cluster(_Rparam);
1895  _do_Cambridge_inclusive_jets();
1896 }
1897 void ClusterSequence::_CP2DChan_cluster_2piMultD () {
1898  if (_Rparam >= 0.39) {
1899  _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
1900  }
1901  _CP2DChan_cluster_2pi2R ();
1902 }
1903 void ClusterSequence::_CP2DChan_cluster () {
1904  if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
1905  unsigned int n = _jets.size();
1906  vector<MirrorInfo> coordIDs(2*n); // link from original to mirror indices
1907  vector<int> jetIDs(2*n); // link from mirror to original indices
1908  vector<Coord2D> coords(2*n); // our coordinates (and copies)
1909  double minrap = numeric_limits<double>::max();
1910  double maxrap = -minrap;
1911  int coord_index = 0;
1912  for (unsigned i = 0; i < n; i++) {
1913  if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
1914  coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
1915  } else {
1916  coordIDs[i].orig = coord_index;
1917  coordIDs[i].mirror = coord_index+1;
1918  coords[coord_index] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
1919  coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
1920  jetIDs[coord_index] = i;
1921  jetIDs[coord_index+1] = i;
1922  minrap = min(coords[coord_index].x,minrap);
1923  maxrap = max(coords[coord_index].x,maxrap);
1924  coord_index += 2;
1925  }
1926  }
1927  for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
1928  coords.resize(coord_index);
1929  Coord2D left_edge(minrap-1.0, 0.0);
1930  Coord2D right_edge(maxrap+1.0, 2*twopi);
1931  ClosestPair2D cp(coords, left_edge, right_edge);
1932  vector<Coord2D> new_points(2);
1933  vector<unsigned int> cIDs_to_remove(4);
1934  vector<unsigned int> new_cIDs(2);
1935  do {
1936  unsigned int cID1, cID2;
1937  double distance2;
1938  cp.closest_pair(cID1,cID2,distance2);
1939  distance2 *= _invR2;
1940  if (distance2 > 1.0) {break;}
1941  int jet_i = jetIDs[cID1];
1942  int jet_j = jetIDs[cID2];
1943  assert (jet_i != jet_j); // to catch issue of recombining with mirror point
1944  int newjet_k;
1945  _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
1946  cIDs_to_remove[0] = coordIDs[jet_i].orig;
1947  cIDs_to_remove[1] = coordIDs[jet_i].mirror;
1948  cIDs_to_remove[2] = coordIDs[jet_j].orig;
1949  cIDs_to_remove[3] = coordIDs[jet_j].mirror;
1950  new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
1951  new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
1952  new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
1953  new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
1954  coordIDs[jet_i].orig = Invalid;
1955  coordIDs[jet_j].orig = Invalid;
1956  coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
1957  jetIDs[new_cIDs[0]] = newjet_k;
1958  jetIDs[new_cIDs[1]] = newjet_k;
1959  n--;
1960  if (n == 1) {break;}
1961  } while(true);
1962  _do_Cambridge_inclusive_jets();
1963 }
1964 void ClusterSequence::_do_Cambridge_inclusive_jets () {
1965  unsigned int n = _history.size();
1966  for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
1967  if (_history[hist_i].child == Invalid) {
1968  _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
1969  }
1970  }
1971 }
1972 FJCORE_END_NAMESPACE
1973 #include<iostream>
1974 #include<sstream>
1975 #include<cmath>
1976 #include <cstdlib>
1977 #include<cassert>
1978 #include<memory>
1979 #ifndef __FJCORE_DROP_CGAL // in case we do not have the code for CGAL
1980 #include "fastjet/internal/Dnn4piCylinder.hh"
1981 #include "fastjet/internal/Dnn3piCylinder.hh"
1982 #include "fastjet/internal/Dnn2piCylinder.hh"
1983 #endif // __FJCORE_DROP_CGAL
1984 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
1985 using namespace std;
1986 void ClusterSequence::_delaunay_cluster () {
1987  int n = _jets.size();
1988  vector<EtaPhi> points(n); // recall EtaPhi is just a typedef'd pair<double>
1989  for (int i = 0; i < n; i++) {
1990  points[i] = EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
1991  points[i].sanitize(); // make sure things are in the right range
1992  }
1993  auto_ptr<DynamicNearestNeighbours> DNN;
1994 #ifndef __FJCORE_DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
1995  bool verbose = false;
1996  bool ignore_nearest_is_mirror = (_Rparam < twopi);
1997  if (_strategy == NlnN4pi) {
1998  DNN.reset(new Dnn4piCylinder(points,verbose));
1999  } else if (_strategy == NlnN3pi) {
2000  DNN.reset(new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose));
2001  } else if (_strategy == NlnN) {
2002  DNN.reset(new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose));
2003  } else
2004 #else
2005  if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
2006  ostringstream err;
2007  err << "ERROR: Requested strategy "<<strategy_string()<<" but it is not"<<endl;
2008  err << " supported because FastJet was compiled without CGAL"<<endl;
2009  throw Error(err.str());
2010  }
2011 #endif // __FJCORE_DROP_CGAL
2012  {
2013  ostringstream err;
2014  err << "ERROR: Unrecognized value for strategy: "<<_strategy<<endl;
2015  assert(false);
2016  throw Error(err.str());
2017  }
2018  DistMap DijMap;
2019  for (int ii = 0; ii < n; ii++) {
2020  _add_ktdistance_to_map(ii, DijMap, DNN.get());
2021  }
2022  for (int i=0;i<n;i++) {
2023  TwoVertices SmallestDijPair;
2024  int jet_i, jet_j;
2025  double SmallestDij;
2026  bool Valid2;
2027  bool recombine_with_beam;
2028  do {
2029  SmallestDij = DijMap.begin()->first;
2030  SmallestDijPair = DijMap.begin()->second;
2031  jet_i = SmallestDijPair.first;
2032  jet_j = SmallestDijPair.second;
2033  DijMap.erase(DijMap.begin());
2034  recombine_with_beam = (jet_j == BeamJet);
2035  if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);}
2036  else {Valid2 = true;}
2037  } while ( !DNN->Valid(jet_i) || !Valid2);
2038  if (! recombine_with_beam) {
2039  int nn; // will be index of new jet
2040  _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
2041  EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
2042  newpoint.sanitize(); // make sure it is in correct range
2043  points.push_back(newpoint);
2044  } else {
2045  _do_iB_recombination_step(jet_i, SmallestDij);
2046  }
2047  if (i == n-1) {break;}
2048  vector<int> updated_neighbours;
2049  if (! recombine_with_beam) {
2050  int point3;
2051  DNN->RemoveCombinedAddCombination(jet_i, jet_j,
2052  points[points.size()-1], point3,
2053  updated_neighbours);
2054  if (static_cast<unsigned int> (point3) != points.size()-1) {
2055  throw Error("INTERNAL ERROR: point3 != points.size()-1");}
2056  } else {
2057  DNN->RemovePoint(jet_i, updated_neighbours);
2058  }
2059  vector<int>::iterator it = updated_neighbours.begin();
2060  for (; it != updated_neighbours.end(); ++it) {
2061  int ii = *it;
2062  _add_ktdistance_to_map(ii, DijMap, DNN.get());
2063  }
2064  } // end clustering loop
2065 }
2066 void ClusterSequence::_add_ktdistance_to_map(
2067  const int & ii,
2068  DistMap & DijMap,
2069  const DynamicNearestNeighbours * DNN) {
2070  double yiB = jet_scale_for_algorithm(_jets[ii]);
2071  if (yiB == 0.0) {
2072  DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2073  } else {
2074  double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
2075  if (DeltaR2 > 1.0) {
2076  DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2077  } else {
2078  double kt2i = jet_scale_for_algorithm(_jets[ii]);
2079  int jj = DNN->NearestNeighbourIndex(ii);
2080  if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
2081  double dij = DeltaR2 * kt2i;
2082  DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
2083  }
2084  }
2085  }
2086 }
2087 FJCORE_END_NAMESPACE
2088 #include<iostream>
2089 #include<cmath>
2090 #include <cstdlib>
2091 #include<cassert>
2092 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2093 using namespace std;
2094 void ClusterSequence::_really_dumb_cluster () {
2095  vector<PseudoJet *> jetsp(_jets.size());
2096  vector<int> indices(_jets.size());
2097  for (size_t i = 0; i<_jets.size(); i++) {
2098  jetsp[i] = & _jets[i];
2099  indices[i] = i;
2100  }
2101  for (int n = jetsp.size(); n > 0; n--) {
2102  int ii, jj;
2103  double ymin = jet_scale_for_algorithm(*(jetsp[0]));
2104  ii = 0; jj = -2;
2105  for (int i = 0; i < n; i++) {
2106  double yiB = jet_scale_for_algorithm(*(jetsp[i]));
2107  if (yiB < ymin) {
2108  ymin = yiB; ii = i; jj = -2;}
2109  }
2110  for (int i = 0; i < n-1; i++) {
2111  for (int j = i+1; j < n; j++) {
2112  //double y = jetsp[i]->kt_distance(*jetsp[j])*_invR2;
2113  double y = min(jet_scale_for_algorithm(*(jetsp[i])),
2114  jet_scale_for_algorithm(*(jetsp[j])))
2115  * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
2116  if (y < ymin) {ymin = y; ii = i; jj = j;}
2117  }
2118  }
2119  int newn = 2*jetsp.size() - n;
2120  if (jj >= 0) {
2121  int nn; // new jet index
2122  _do_ij_recombination_step(jetsp[ii]-&_jets[0],
2123  jetsp[jj]-&_jets[0], ymin, nn);
2124  jetsp[ii] = &_jets[nn];
2125  jetsp[jj] = jetsp[n-1];
2126  indices[ii] = newn;
2127  indices[jj] = indices[n-1];
2128  } else {
2129  _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
2130  jetsp[ii] = jetsp[n-1];
2131  indices[ii] = indices[n-1];
2132  }
2133  }
2134 }
2135 FJCORE_END_NAMESPACE
2136 #include<iostream>
2137 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2138 using namespace std;
2139 template<> inline void ClusterSequence::_bj_set_jetinfo(
2140  EEBriefJet * const jetA, const int _jets_index) const {
2141  double E = _jets[_jets_index].E();
2142  double scale = E*E; // the default energy scale for the kt alg
2143  double p = jet_def().extra_param(); // in case we're ee_genkt
2144  switch (_jet_algorithm) {
2145  case ee_kt_algorithm:
2146  assert(_Rparam > 2.0); // force this to be true! [not best place, but works]
2147  break;
2148  case ee_genkt_algorithm:
2149  if (p <= 0 && scale < 1e-300) scale = 1e-300; // same dodgy safety as genkt
2150  scale = pow(scale,p);
2151  break;
2152  default:
2153  throw Error("Unrecognised jet algorithm");
2154  }
2155  jetA->kt2 = scale; // "kt2" might one day be renamed as "scale" or some such
2156  double norm = _jets[_jets_index].modp2();
2157  if (norm > 0) {
2158  norm = 1.0/sqrt(norm);
2159  jetA->nx = norm * _jets[_jets_index].px();
2160  jetA->ny = norm * _jets[_jets_index].py();
2161  jetA->nz = norm * _jets[_jets_index].pz();
2162  } else {
2163  jetA->nx = 0.0;
2164  jetA->ny = 0.0;
2165  jetA->nz = 1.0;
2166  }
2167  jetA->_jets_index = _jets_index;
2168  jetA->NN_dist = _R2;
2169  jetA->NN = NULL;
2170 }
2171 template<> double ClusterSequence::_bj_dist(
2172  const EEBriefJet * const jeta,
2173  const EEBriefJet * const jetb) const {
2174  double dist = 1.0
2175  - jeta->nx*jetb->nx
2176  - jeta->ny*jetb->ny
2177  - jeta->nz*jetb->nz;
2178  dist *= 2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
2179  return dist;
2180 }
2181 void ClusterSequence::_simple_N2_cluster_BriefJet() {
2182  _simple_N2_cluster<BriefJet>();
2183 }
2184 void ClusterSequence::_simple_N2_cluster_EEBriefJet() {
2185  _simple_N2_cluster<EEBriefJet>();
2186 }
2187 FJCORE_END_NAMESPACE
2188 #include <iostream>
2189 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2190 using namespace std;
2191 ClusterSequenceStructure::~ClusterSequenceStructure(){
2192  if (_associated_cs != NULL
2193  && _associated_cs->will_delete_self_when_unused()) {
2194  _associated_cs->signal_imminent_self_deletion();
2195  delete _associated_cs;
2196  }
2197 }
2198 bool ClusterSequenceStructure::has_valid_cluster_sequence() const{
2199  return (_associated_cs != NULL);
2200 }
2201 const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence() const{
2202  return _associated_cs;
2203 }
2204 const ClusterSequence * ClusterSequenceStructure::validated_cs() const {
2205  if (!_associated_cs)
2206  throw Error("you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
2207  return _associated_cs;
2208 }
2209 bool ClusterSequenceStructure::has_partner(const PseudoJet &reference, PseudoJet &partner) const{
2210  return validated_cs()->has_partner(reference, partner);
2211 }
2212 bool ClusterSequenceStructure::has_child(const PseudoJet &reference, PseudoJet &child) const{
2213  return validated_cs()->has_child(reference, child);
2214 }
2215 bool ClusterSequenceStructure::has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const{
2216  return validated_cs()->has_parents(reference, parent1, parent2);
2217 }
2218 bool ClusterSequenceStructure::object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const{
2219  if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
2220  throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2221  if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence()) return false;
2222  return validated_cs()->object_in_jet(reference, jet);
2223 }
2224 bool ClusterSequenceStructure::has_constituents() const{
2225  if (!has_associated_cluster_sequence())
2226  throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2227  return true;
2228 }
2229 vector<PseudoJet> ClusterSequenceStructure::constituents(const PseudoJet &reference) const{
2230  return validated_cs()->constituents(reference);
2231 }
2232 bool ClusterSequenceStructure::has_exclusive_subjets() const{
2233  if (!has_associated_cluster_sequence())
2234  throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2235  return true;
2236 }
2237 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (const PseudoJet &reference, const double & dcut) const {
2238  return validated_cs()->exclusive_subjets(reference, dcut);
2239 }
2240 int ClusterSequenceStructure::n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const {
2241  return validated_cs()->n_exclusive_subjets(reference, dcut);
2242 }
2243 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const {
2244  return validated_cs()->exclusive_subjets_up_to(reference, nsub);
2245 }
2246 double ClusterSequenceStructure::exclusive_subdmerge(const PseudoJet &reference, int nsub) const {
2247  return validated_cs()->exclusive_subdmerge(reference, nsub);
2248 }
2249 double ClusterSequenceStructure::exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const {
2250  return validated_cs()->exclusive_subdmerge_max(reference, nsub);
2251 }
2252 bool ClusterSequenceStructure::has_pieces(const PseudoJet &reference) const{
2253  PseudoJet dummy1, dummy2;
2254  return has_parents(reference, dummy1, dummy2);
2255 }
2256 vector<PseudoJet> ClusterSequenceStructure::pieces(const PseudoJet &reference) const{
2257  PseudoJet j1, j2;
2258  vector<PseudoJet> res;
2259  if (has_parents(reference, j1, j2)){
2260  res.push_back(j1);
2261  res.push_back(j2);
2262  }
2263  return res;
2264 }
2265 FJCORE_END_NAMESPACE
2266 #include<iostream>
2267 #include<vector>
2268 #include<cmath>
2269 #include<algorithm>
2270 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2271 using namespace std;
2272 void ClusterSequence::_bj_remove_from_tiles(TiledJet * const jet) {
2273  Tile * tile = & _tiles[jet->tile_index];
2274  if (jet->previous == NULL) {
2275  tile->head = jet->next;
2276  } else {
2277  jet->previous->next = jet->next;
2278  }
2279  if (jet->next != NULL) {
2280  jet->next->previous = jet->previous;
2281  }
2282 }
2283 void ClusterSequence::_initialise_tiles() {
2284  double default_size = max(0.1,_Rparam);
2285  _tile_size_eta = default_size;
2286  _n_tiles_phi = max(3,int(floor(twopi/default_size)));
2287  _tile_size_phi = twopi / _n_tiles_phi; // >= _Rparam and fits in 2pi
2288  _tiles_eta_min = 0.0;
2289  _tiles_eta_max = 0.0;
2290  const double maxrap = 7.0;
2291  for(unsigned int i = 0; i < _jets.size(); i++) {
2292  double eta = _jets[i].rap();
2293  if (abs(eta) < maxrap) {
2294  if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
2295  if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
2296  }
2297  }
2298  _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
2299  _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
2300  _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
2301  _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
2302  _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
2303  for (int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
2304  for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
2305  Tile * tile = & _tiles[_tile_index(ieta,iphi)];
2306  tile->head = NULL; // first element of tiles points to itself
2307  tile->begin_tiles[0] = tile;
2308  Tile ** pptile = & (tile->begin_tiles[0]);
2309  pptile++;
2310  tile->surrounding_tiles = pptile;
2311  if (ieta > _tiles_ieta_min) {
2312  // with the itile subroutine, we can safely run tiles from
2313  // idphi=-1 to idphi=+1, because it takes care of
2314  // negative and positive boundaries
2315  for (int idphi = -1; idphi <=+1; idphi++) {
2316  *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
2317  pptile++;
2318  }
2319  }
2320  *pptile = & _tiles[_tile_index(ieta,iphi-1)];
2321  pptile++;
2322  tile->RH_tiles = pptile;
2323  *pptile = & _tiles[_tile_index(ieta,iphi+1)];
2324  pptile++;
2325  if (ieta < _tiles_ieta_max) {
2326  for (int idphi = -1; idphi <= +1; idphi++) {
2327  *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
2328  pptile++;
2329  }
2330  }
2331  tile->end_tiles = pptile;
2332  tile->tagged = false;
2333  }
2334  }
2335 }
2336 int ClusterSequence::_tile_index(const double & eta, const double & phi) const {
2337  int ieta, iphi;
2338  if (eta <= _tiles_eta_min) {ieta = 0;}
2339  else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
2340  else {
2341  ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
2342  if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
2343  ieta = _tiles_ieta_max-_tiles_ieta_min;}
2344  }
2345  iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
2346  return (iphi + ieta * _n_tiles_phi);
2347 }
2348 inline void ClusterSequence::_tj_set_jetinfo( TiledJet * const jet,
2349  const int _jets_index) {
2350  _bj_set_jetinfo<>(jet, _jets_index);
2351  jet->tile_index = _tile_index(jet->eta, jet->phi);
2352  Tile * tile = &_tiles[jet->tile_index];
2353  jet->previous = NULL;
2354  jet->next = tile->head;
2355  if (jet->next != NULL) {jet->next->previous = jet;}
2356  tile->head = jet;
2357 }
2358 void ClusterSequence::_print_tiles(TiledJet * briefjets ) const {
2359  for (vector<Tile>::const_iterator tile = _tiles.begin();
2360  tile < _tiles.end(); tile++) {
2361  cout << "Tile " << tile - _tiles.begin()<<" = ";
2362  vector<int> list;
2363  for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
2364  list.push_back(jetI-briefjets);
2365  }
2366  sort(list.begin(),list.end());
2367  for (unsigned int i = 0; i < list.size(); i++) {cout <<" "<<list[i];}
2368  cout <<"\n";
2369  }
2370 }
2371 void ClusterSequence::_add_neighbours_to_tile_union(const int tile_index,
2372  vector<int> & tile_union, int & n_near_tiles) const {
2373  for (Tile * const * near_tile = _tiles[tile_index].begin_tiles;
2374  near_tile != _tiles[tile_index].end_tiles; near_tile++){
2375  tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2376  n_near_tiles++;
2377  }
2378 }
2379 inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
2380  const int tile_index,
2381  vector<int> & tile_union, int & n_near_tiles) {
2382  for (Tile ** near_tile = _tiles[tile_index].begin_tiles;
2383  near_tile != _tiles[tile_index].end_tiles; near_tile++){
2384  if (! (*near_tile)->tagged) {
2385  (*near_tile)->tagged = true;
2386  tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2387  n_near_tiles++;
2388  }
2389  }
2390 }
2391 void ClusterSequence::_tiled_N2_cluster() {
2392  _initialise_tiles();
2393  int n = _jets.size();
2394  TiledJet * briefjets = new TiledJet[n];
2395  TiledJet * jetA = briefjets, * jetB;
2396  TiledJet oldB;
2397  oldB.tile_index=0; // prevents a gcc warning
2398  vector<int> tile_union(3*n_tile_neighbours);
2399  for (int i = 0; i< n; i++) {
2400  _tj_set_jetinfo(jetA, i);
2401  jetA++; // move on to next entry of briefjets
2402  }
2403  TiledJet * tail = jetA; // a semaphore for the end of briefjets
2404  TiledJet * head = briefjets; // a nicer way of naming start
2405  vector<Tile>::const_iterator tile;
2406  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2407  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2408  for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2409  double dist = _bj_dist(jetA,jetB);
2410  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2411  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2412  }
2413  }
2414  for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2415  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2416  for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2417  double dist = _bj_dist(jetA,jetB);
2418  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2419  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2420  }
2421  }
2422  }
2423  }
2424  double * diJ = new double[n];
2425  jetA = head;
2426  for (int i = 0; i < n; i++) {
2427  diJ[i] = _bj_diJ(jetA);
2428  jetA++; // have jetA follow i
2429  }
2430  int history_location = n-1;
2431  while (tail != head) {
2432  double diJ_min = diJ[0];
2433  int diJ_min_jet = 0;
2434  for (int i = 1; i < n; i++) {
2435  if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
2436  }
2437  history_location++;
2438  jetA = & briefjets[diJ_min_jet];
2439  jetB = jetA->NN;
2440  diJ_min *= _invR2;
2441  if (jetB != NULL) {
2442  if (jetA < jetB) {std::swap(jetA,jetB);}
2443  int nn; // new jet index
2444  _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2445  _bj_remove_from_tiles(jetA);
2446  oldB = * jetB; // take a copy because we will need it...
2447  _bj_remove_from_tiles(jetB);
2448  _tj_set_jetinfo(jetB, nn); // also registers the jet in the tiling
2449  } else {
2450  _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2451  _bj_remove_from_tiles(jetA);
2452  }
2453  int n_near_tiles = 0;
2454  _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
2455  if (jetB != NULL) {
2456  bool sort_it = false;
2457  if (jetB->tile_index != jetA->tile_index) {
2458  sort_it = true;
2459  _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
2460  }
2461  if (oldB.tile_index != jetA->tile_index &&
2462  oldB.tile_index != jetB->tile_index) {
2463  sort_it = true;
2464  _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
2465  }
2466  if (sort_it) {
2467  // sort the tiles before then compressing the list
2468  sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
2469  // and now condense the list
2470  int nnn = 1;
2471  for (int i = 1; i < n_near_tiles; i++) {
2472  if (tile_union[i] != tile_union[nnn-1]) {
2473  tile_union[nnn] = tile_union[i];
2474  nnn++;
2475  }
2476  }
2477  n_near_tiles = nnn;
2478  }
2479  }
2480  tail--; n--;
2481  if (jetA == tail) {
2482  } else {
2483  *jetA = *tail;
2484  diJ[jetA - head] = diJ[tail-head];
2485  if (jetA->previous == NULL) {
2486  _tiles[jetA->tile_index].head = jetA;
2487  } else {
2488  jetA->previous->next = jetA;
2489  }
2490  if (jetA->next != NULL) {jetA->next->previous = jetA;}
2491  }
2492  for (int itile = 0; itile < n_near_tiles; itile++) {
2493  Tile * tile_ptr = &_tiles[tile_union[itile]];
2494  for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2495  // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
2496  if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2497  jetI->NN_dist = _R2;
2498  jetI->NN = NULL;
2499  // now go over tiles that are neighbours of I (include own tile)
2500  for (Tile ** near_tile = tile_ptr->begin_tiles;
2501  near_tile != tile_ptr->end_tiles; near_tile++) {
2502  // and then over the contents of that tile
2503  for (TiledJet * jetJ = (*near_tile)->head;
2504  jetJ != NULL; jetJ = jetJ->next) {
2505  double dist = _bj_dist(jetI,jetJ);
2506  if (dist < jetI->NN_dist && jetJ != jetI) {
2507  jetI->NN_dist = dist; jetI->NN = jetJ;
2508  }
2509  }
2510  }
2511  diJ[jetI-head] = _bj_diJ(jetI); // update diJ
2512  }
2513  // check whether new jetB is closer than jetI's current NN and
2514  // if need to update things
2515  if (jetB != NULL) {
2516  double dist = _bj_dist(jetI,jetB);
2517  if (dist < jetI->NN_dist) {
2518  if (jetI != jetB) {
2519  jetI->NN_dist = dist;
2520  jetI->NN = jetB;
2521  diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
2522  }
2523  }
2524  if (dist < jetB->NN_dist) {
2525  if (jetI != jetB) {
2526  jetB->NN_dist = dist;
2527  jetB->NN = jetI;}
2528  }
2529  }
2530  }
2531  }
2532  if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
2533  for (Tile ** near_tile = _tiles[tail->tile_index].begin_tiles;
2534  near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
2535  for (TiledJet * jetJ = (*near_tile)->head;
2536  jetJ != NULL; jetJ = jetJ->next) {
2537  if (jetJ->NN == tail) {jetJ->NN = jetA;}
2538  }
2539  }
2540  if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
2541  }
2542  delete[] diJ;
2543  delete[] briefjets;
2544 }
2545 void ClusterSequence::_faster_tiled_N2_cluster() {
2546  _initialise_tiles();
2547  int n = _jets.size();
2548  TiledJet * briefjets = new TiledJet[n];
2549  TiledJet * jetA = briefjets, * jetB;
2550  TiledJet oldB;
2551  oldB.tile_index=0; // prevents a gcc warning
2552  vector<int> tile_union(3*n_tile_neighbours);
2553  for (int i = 0; i< n; i++) {
2554  _tj_set_jetinfo(jetA, i);
2555  jetA++; // move on to next entry of briefjets
2556  }
2557  TiledJet * head = briefjets; // a nicer way of naming start
2558  vector<Tile>::const_iterator tile;
2559  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2560  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2561  for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2562  double dist = _bj_dist(jetA,jetB);
2563  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2564  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2565  }
2566  }
2567  for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2568  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2569  for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2570  double dist = _bj_dist(jetA,jetB);
2571  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2572  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2573  }
2574  }
2575  }
2576  }
2577  struct diJ_plus_link {
2578  double diJ; // the distance
2579  TiledJet * jet; // the jet (i) for which we've found this distance
2580  };
2581  diJ_plus_link * diJ = new diJ_plus_link[n];
2582  jetA = head;
2583  for (int i = 0; i < n; i++) {
2584  diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
2585  diJ[i].jet = jetA; // our compact diJ table will not be in
2586  jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
2587  jetA++; // have jetA follow i
2588  }
2589  int history_location = n-1;
2590  while (n > 0) {
2591  diJ_plus_link * best, *stop; // pointers a bit faster than indices
2592  double diJ_min = diJ[0].diJ; // initialise the best one here.
2593  best = diJ; // and here
2594  stop = diJ+n;
2595  for (diJ_plus_link * here = diJ+1; here != stop; here++) {
2596  if (here->diJ < diJ_min) {best = here; diJ_min = here->diJ;}
2597  }
2598  history_location++;
2599  jetA = best->jet;
2600  jetB = jetA->NN;
2601  diJ_min *= _invR2;
2602  if (jetB != NULL) {
2603  if (jetA < jetB) {std::swap(jetA,jetB);}
2604  int nn; // new jet index
2605  _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2606  _bj_remove_from_tiles(jetA);
2607  oldB = * jetB; // take a copy because we will need it...
2608  _bj_remove_from_tiles(jetB);
2609  _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
2610  } else {
2611  _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2612  _bj_remove_from_tiles(jetA);
2613  }
2614  int n_near_tiles = 0;
2615  _add_untagged_neighbours_to_tile_union(jetA->tile_index,
2616  tile_union, n_near_tiles);
2617  if (jetB != NULL) {
2618  if (jetB->tile_index != jetA->tile_index) {
2619  _add_untagged_neighbours_to_tile_union(jetB->tile_index,
2620  tile_union,n_near_tiles);
2621  }
2622  if (oldB.tile_index != jetA->tile_index &&
2623  oldB.tile_index != jetB->tile_index) {
2624  _add_untagged_neighbours_to_tile_union(oldB.tile_index,
2625  tile_union,n_near_tiles);
2626  }
2627  }
2628  n--;
2629  diJ[n].jet->diJ_posn = jetA->diJ_posn;
2630  diJ[jetA->diJ_posn] = diJ[n];
2631  for (int itile = 0; itile < n_near_tiles; itile++) {
2632  Tile * tile_ptr = &_tiles[tile_union[itile]];
2633  tile_ptr->tagged = false; // reset tag, since we're done with unions
2634  for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2635  // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
2636  if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2637  jetI->NN_dist = _R2;
2638  jetI->NN = NULL;
2639  // now go over tiles that are neighbours of I (include own tile)
2640  for (Tile ** near_tile = tile_ptr->begin_tiles;
2641  near_tile != tile_ptr->end_tiles; near_tile++) {
2642  // and then over the contents of that tile
2643  for (TiledJet * jetJ = (*near_tile)->head;
2644  jetJ != NULL; jetJ = jetJ->next) {
2645  double dist = _bj_dist(jetI,jetJ);
2646  if (dist < jetI->NN_dist && jetJ != jetI) {
2647  jetI->NN_dist = dist; jetI->NN = jetJ;
2648  }
2649  }
2650  }
2651  diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ kt-dist
2652  }
2653  // check whether new jetB is closer than jetI's current NN and
2654  // if jetI is closer than jetB's current (evolving) nearest
2655  // neighbour. Where relevant update things
2656  if (jetB != NULL) {
2657  double dist = _bj_dist(jetI,jetB);
2658  if (dist < jetI->NN_dist) {
2659  if (jetI != jetB) {
2660  jetI->NN_dist = dist;
2661  jetI->NN = jetB;
2662  diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ...
2663  }
2664  }
2665  if (dist < jetB->NN_dist) {
2666  if (jetI != jetB) {
2667  jetB->NN_dist = dist;
2668  jetB->NN = jetI;}
2669  }
2670  }
2671  }
2672  }
2673  if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
2674  }
2675  delete[] diJ;
2676  delete[] briefjets;
2677 }
2678 void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
2679  _initialise_tiles();
2680  int n = _jets.size();
2681  TiledJet * briefjets = new TiledJet[n];
2682  TiledJet * jetA = briefjets, * jetB;
2683  TiledJet oldB;
2684  oldB.tile_index=0; // prevents a gcc warning
2685  vector<int> tile_union(3*n_tile_neighbours);
2686  for (int i = 0; i< n; i++) {
2687  _tj_set_jetinfo(jetA, i);
2688  jetA++; // move on to next entry of briefjets
2689  }
2690  TiledJet * head = briefjets; // a nicer way of naming start
2691  vector<Tile>::const_iterator tile;
2692  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2693  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2694  for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2695  double dist = _bj_dist(jetA,jetB);
2696  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2697  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2698  }
2699  }
2700  for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2701  for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2702  for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2703  double dist = _bj_dist(jetA,jetB);
2704  if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2705  if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2706  }
2707  }
2708  }
2709  }
2710  vector<double> diJs(n);
2711  for (int i = 0; i < n; i++) {
2712  diJs[i] = _bj_diJ(&briefjets[i]);
2713  briefjets[i].label_minheap_update_done();
2714  }
2715  MinHeap minheap(diJs);
2716  vector<TiledJet *> jets_for_minheap;
2717  jets_for_minheap.reserve(n);
2718  int history_location = n-1;
2719  while (n > 0) {
2720  double diJ_min = minheap.minval() *_invR2;
2721  jetA = head + minheap.minloc();
2722  history_location++;
2723  jetB = jetA->NN;
2724  if (jetB != NULL) {
2725  if (jetA < jetB) {std::swap(jetA,jetB);}
2726  int nn; // new jet index
2727  _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2728  _bj_remove_from_tiles(jetA);
2729  oldB = * jetB; // take a copy because we will need it...
2730  _bj_remove_from_tiles(jetB);
2731  _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
2732  } else {
2733  _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2734  _bj_remove_from_tiles(jetA);
2735  }
2736  minheap.remove(jetA-head);
2737  int n_near_tiles = 0;
2738  _add_untagged_neighbours_to_tile_union(jetA->tile_index,
2739  tile_union, n_near_tiles);
2740  if (jetB != NULL) {
2741  if (jetB->tile_index != jetA->tile_index) {
2742  _add_untagged_neighbours_to_tile_union(jetB->tile_index,
2743  tile_union,n_near_tiles);
2744  }
2745  if (oldB.tile_index != jetA->tile_index &&
2746  oldB.tile_index != jetB->tile_index) {
2747  // GS: the line below generates a warning that oldB.tile_index
2748  // may be used uninitialised. However, to reach this point, we
2749  // ned jetB != NULL (see test a few lines above) and is jetB
2750  // !=NULL, one would have gone through "oldB = *jetB before
2751  // (see piece of code ~20 line above), so the index is
2752  // initialised. We do not do anything to avoid the warning to
2753  // avoid any potential speed impact.
2754  _add_untagged_neighbours_to_tile_union(oldB.tile_index,
2755  tile_union,n_near_tiles);
2756  }
2757  jetB->label_minheap_update_needed();
2758  jets_for_minheap.push_back(jetB);
2759  }
2760  for (int itile = 0; itile < n_near_tiles; itile++) {
2761  Tile * tile_ptr = &_tiles[tile_union[itile]];
2762  tile_ptr->tagged = false; // reset tag, since we're done with unions
2763  for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2764  // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
2765  if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2766  jetI->NN_dist = _R2;
2767  jetI->NN = NULL;
2768  // label jetI as needing heap action...
2769  if (!jetI->minheap_update_needed()) {
2770  jetI->label_minheap_update_needed();
2771  jets_for_minheap.push_back(jetI);}
2772  // now go over tiles that are neighbours of I (include own tile)
2773  for (Tile ** near_tile = tile_ptr->begin_tiles;
2774  near_tile != tile_ptr->end_tiles; near_tile++) {
2775  // and then over the contents of that tile
2776  for (TiledJet * jetJ = (*near_tile)->head;
2777  jetJ != NULL; jetJ = jetJ->next) {
2778  double dist = _bj_dist(jetI,jetJ);
2779  if (dist < jetI->NN_dist && jetJ != jetI) {
2780  jetI->NN_dist = dist; jetI->NN = jetJ;
2781  }
2782  }
2783  }
2784  }
2785  // check whether new jetB is closer than jetI's current NN and
2786  // if jetI is closer than jetB's current (evolving) nearest
2787  // neighbour. Where relevant update things
2788  if (jetB != NULL) {
2789  double dist = _bj_dist(jetI,jetB);
2790  if (dist < jetI->NN_dist) {
2791  if (jetI != jetB) {
2792  jetI->NN_dist = dist;
2793  jetI->NN = jetB;
2794  // label jetI as needing heap action...
2795  if (!jetI->minheap_update_needed()) {
2796  jetI->label_minheap_update_needed();
2797  jets_for_minheap.push_back(jetI);}
2798  }
2799  }
2800  if (dist < jetB->NN_dist) {
2801  if (jetI != jetB) {
2802  jetB->NN_dist = dist;
2803  jetB->NN = jetI;}
2804  }
2805  }
2806  }
2807  }
2808  while (jets_for_minheap.size() > 0) {
2809  TiledJet * jetI = jets_for_minheap.back();
2810  jets_for_minheap.pop_back();
2811  minheap.update(jetI-head, _bj_diJ(jetI));
2812  jetI->label_minheap_update_done();
2813  }
2814  n--;
2815  }
2816  delete[] briefjets;
2817 }
2818 FJCORE_END_NAMESPACE
2819 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2820 using namespace std;
2821 CompositeJetStructure::CompositeJetStructure(const std::vector<PseudoJet> & initial_pieces,
2822  const JetDefinition::Recombiner * recombiner)
2823  : _pieces(initial_pieces){
2824  if (recombiner){}; // ugly trick to prevent a gcc warning
2825  _area_4vector_ptr = 0;
2826 }
2827 std::string CompositeJetStructure::description() const{
2828  string str = "Composite PseudoJet";
2829  return str;
2830 }
2831 bool CompositeJetStructure::has_constituents() const{
2832  return _pieces.size()!=0;
2833 }
2834 std::vector<PseudoJet> CompositeJetStructure::constituents(const PseudoJet & /*jet*/) const{
2835  vector<PseudoJet> all_constituents;
2836  for (unsigned i = 0; i < _pieces.size(); i++) {
2837  if (_pieces[i].has_constituents()){
2838  vector<PseudoJet> constits = _pieces[i].constituents();
2839  copy(constits.begin(), constits.end(), back_inserter(all_constituents));
2840  } else {
2841  all_constituents.push_back(_pieces[i]);
2842  }
2843  }
2844  return all_constituents;
2845 }
2846 std::vector<PseudoJet> CompositeJetStructure::pieces(const PseudoJet & /*jet*/) const{
2847  return _pieces;
2848 }
2849 FJCORE_END_NAMESPACE // defined in fastjet/internal/base.hh
2850 #include <sstream>
2851 #ifdef FJCORE_HAVE_EXECINFO_H
2852 #include <execinfo.h>
2853 #include <cstdlib>
2854 #endif
2855 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2856 using namespace std;
2857 bool Error::_print_errors = true;
2858 bool Error::_print_backtrace = false;
2859 ostream * Error::_default_ostr = & cerr;
2860 Error::Error(const std::string & message_in) {
2861  _message = message_in;
2862  if (_print_errors && _default_ostr){
2863  ostringstream oss;
2864  oss << "fjcore::Error: "<< message_in << endl;
2865 #ifdef FJCORE_HAVE_EXECINFO_H
2866  if (_print_backtrace){
2867  void * array[10];
2868  char ** messages;
2869  int size = backtrace(array, 10);
2870  messages = backtrace_symbols(array, size);
2871  oss << "stack:" << endl;
2872  for (int i = 1; i < size && messages != NULL; ++i){
2873  oss << " #" << i << ": " << messages[i] << endl;
2874  }
2875  free(messages);
2876  }
2877 #endif
2878  *_default_ostr << oss.str();
2879  _default_ostr->flush();
2880  }
2881 }
2882 FJCORE_END_NAMESPACE
2883 #include <string>
2884 #include <sstream>
2885 using namespace std;
2886 FJCORE_BEGIN_NAMESPACE
2887 FJCORE_END_NAMESPACE
2888 #include<sstream>
2889 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
2890 using namespace std;
2891 const double JetDefinition::max_allowable_R = 1000.0;
2892 JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in,
2893  double R_in,
2894  Strategy strategy_in,
2895  RecombinationScheme recomb_scheme_in,
2896  int nparameters) :
2897  _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
2898  if (_jet_algorithm == ee_kt_algorithm) {
2899  _Rparam = 4.0; // introduce a fictional R that ensures that
2900  } else {
2901  if (R_in > max_allowable_R) {
2902  ostringstream oss;
2903  oss << "Requested R = " << R_in << " for jet definition is larger than max_allowable_R = " << max_allowable_R;
2904  throw Error(oss.str());
2905  }
2906  }
2907  switch (jet_algorithm_in) {
2908  case ee_kt_algorithm:
2909  if (nparameters != 0) {
2910  ostringstream oss;
2911  oss << "ee_kt_algorithm should be constructed with 0 parameters but was called with "
2912  << nparameters << " parameter(s)\n";
2913  throw Error(oss.str());
2914  }
2915  break;
2916  case genkt_algorithm:
2917  case ee_genkt_algorithm:
2918  if (nparameters != 2) {
2919  ostringstream oss;
2920  oss << "(ee_)genkt_algorithm should be constructed with 2 parameters but was called with "
2921  << nparameters << " parameter(s)\n";
2922  throw Error(oss.str());
2923  }
2924  break;
2925  default:
2926  if (nparameters != 1) {
2927  ostringstream oss;
2928  oss << "The jet algorithm you requested ("
2929  << jet_algorithm_in << ") should be constructed with 1 parameter but was called with "
2930  << nparameters << " parameter(s)\n";
2931  throw Error(oss.str());
2932  }
2933  }
2934  assert (_strategy != plugin_strategy);
2935  _plugin = NULL;
2936  set_recombination_scheme(recomb_scheme_in);
2937  set_extra_param(0.0); // make sure it's defined
2938 }
2939 string JetDefinition::description() const {
2940  ostringstream name;
2941  if (jet_algorithm() == plugin_algorithm) {
2942  return plugin()->description();
2943  } else if (jet_algorithm() == kt_algorithm) {
2944  name << "Longitudinally invariant kt algorithm with R = " << R();
2945  name << " and " << recombiner()->description();
2946  } else if (jet_algorithm() == cambridge_algorithm) {
2947  name << "Longitudinally invariant Cambridge/Aachen algorithm with R = "
2948  << R() ;
2949  name << " and " << recombiner()->description();
2950  } else if (jet_algorithm() == antikt_algorithm) {
2951  name << "Longitudinally invariant anti-kt algorithm with R = "
2952  << R() ;
2953  name << " and " << recombiner()->description();
2954  } else if (jet_algorithm() == genkt_algorithm) {
2955  name << "Longitudinally invariant generalised kt algorithm with R = "
2956  << R() << ", p = " << extra_param();
2957  name << " and " << recombiner()->description();
2958  } else if (jet_algorithm() == cambridge_for_passive_algorithm) {
2959  name << "Longitudinally invariant Cambridge/Aachen algorithm with R = "
2960  << R() << "and a special hack whereby particles with kt < "
2961  << extra_param() << "are treated as passive ghosts";
2962  } else if (jet_algorithm() == ee_kt_algorithm) {
2963  name << "e+e- kt (Durham) algorithm (NB: no R)";
2964  name << " with " << recombiner()->description();
2965  } else if (jet_algorithm() == ee_genkt_algorithm) {
2966  name << "e+e- generalised kt algorithm with R = "
2967  << R() << ", p = " << extra_param();
2968  name << " and " << recombiner()->description();
2969  } else if (jet_algorithm() == undefined_jet_algorithm) {
2970  name << "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
2971  } else {
2972  throw Error("JetDefinition::description(): unrecognized jet_algorithm");
2973  }
2974  return name.str();
2975 }
2976 void JetDefinition::set_recombination_scheme(
2977  RecombinationScheme recomb_scheme) {
2978  _default_recombiner = JetDefinition::DefaultRecombiner(recomb_scheme);
2979  if (_recombiner_shared()) _recombiner_shared.reset();
2980  _recombiner = 0;
2981 }
2982 bool JetDefinition::has_same_recombiner(const JetDefinition &other_jd) const{
2983  const RecombinationScheme & scheme = recombination_scheme();
2984  if (other_jd.recombination_scheme() != scheme) return false;
2985  return (scheme != external_scheme)
2986  || (recombiner() == other_jd.recombiner());
2987 }
2988 void JetDefinition::delete_recombiner_when_unused(){
2989  if (_recombiner == 0){
2990  throw Error("tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
2991  }
2992  _recombiner_shared.reset(_recombiner);
2993 }
2994 void JetDefinition::delete_plugin_when_unused(){
2995  if (_plugin == 0){
2996  throw Error("tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
2997  }
2998  _plugin_shared.reset(_plugin);
2999 }
3000 string JetDefinition::DefaultRecombiner::description() const {
3001  switch(_recomb_scheme) {
3002  case E_scheme:
3003  return "E scheme recombination";
3004  case pt_scheme:
3005  return "pt scheme recombination";
3006  case pt2_scheme:
3007  return "pt2 scheme recombination";
3008  case Et_scheme:
3009  return "Et scheme recombination";
3010  case Et2_scheme:
3011  return "Et2 scheme recombination";
3012  case BIpt_scheme:
3013  return "boost-invariant pt scheme recombination";
3014  case BIpt2_scheme:
3015  return "boost-invariant pt2 scheme recombination";
3016  default:
3017  ostringstream err;
3018  err << "DefaultRecombiner: unrecognized recombination scheme "
3019  << _recomb_scheme;
3020  throw Error(err.str());
3021  }
3022 }
3023 void JetDefinition::DefaultRecombiner::recombine(
3024  const PseudoJet & pa, const PseudoJet & pb,
3025  PseudoJet & pab) const {
3026  double weighta, weightb;
3027  switch(_recomb_scheme) {
3028  case E_scheme:
3029  pab.reset(pa.px()+pb.px(),
3030  pa.py()+pb.py(),
3031  pa.pz()+pb.pz(),
3032  pa.E ()+pb.E ());
3033  return;
3034  case pt_scheme:
3035  case Et_scheme:
3036  case BIpt_scheme:
3037  weighta = pa.perp();
3038  weightb = pb.perp();
3039  break;
3040  case pt2_scheme:
3041  case Et2_scheme:
3042  case BIpt2_scheme:
3043  weighta = pa.perp2();
3044  weightb = pb.perp2();
3045  break;
3046  default:
3047  ostringstream err;
3048  err << "DefaultRecombiner: unrecognized recombination scheme "
3049  << _recomb_scheme;
3050  throw Error(err.str());
3051  }
3052  double perp_ab = pa.perp() + pb.perp();
3053  if (perp_ab != 0.0) { // weights also non-zero...
3054  double y_ab = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
3055  double phi_a = pa.phi(), phi_b = pb.phi();
3056  if (phi_a - phi_b > pi) phi_b += twopi;
3057  if (phi_a - phi_b < -pi) phi_b -= twopi;
3058  double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
3059  pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
3060  } else { // weights are zero
3061  pab.reset(0.0, 0.0, 0.0, 0.0);
3062  }
3063 }
3064 void JetDefinition::DefaultRecombiner::preprocess(PseudoJet & p) const {
3065  switch(_recomb_scheme) {
3066  case E_scheme:
3067  case BIpt_scheme:
3068  case BIpt2_scheme:
3069  break;
3070  case pt_scheme:
3071  case pt2_scheme:
3072  {
3073  double newE = sqrt(p.perp2()+p.pz()*p.pz());
3074  p.reset_momentum(p.px(), p.py(), p.pz(), newE);
3075  }
3076  break;
3077  case Et_scheme:
3078  case Et2_scheme:
3079  {
3080  double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
3081  p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
3082  }
3083  break;
3084  default:
3085  ostringstream err;
3086  err << "DefaultRecombiner: unrecognized recombination scheme "
3087  << _recomb_scheme;
3088  throw Error(err.str());
3089  }
3090 }
3091 void JetDefinition::Plugin::set_ghost_separation_scale(double /*scale*/) const {
3092  throw Error("set_ghost_separation_scale not supported");
3093 }
3094 PseudoJet join(const vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner){
3095  PseudoJet result; // automatically initialised to 0
3096  if (pieces.size()>0){
3097  result = pieces[0];
3098  for (unsigned int i=1; i<pieces.size(); i++)
3099  recombiner.plus_equal(result, pieces[i]);
3100  }
3101  CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces, &recombiner);
3102  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
3103  return result;
3104 }
3105 PseudoJet join(const PseudoJet & j1,
3106  const JetDefinition::Recombiner & recombiner){
3107  return join(vector<PseudoJet>(1,j1), recombiner);
3108 }
3109 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2,
3110  const JetDefinition::Recombiner & recombiner){
3111  vector<PseudoJet> pieces;
3112  pieces.push_back(j1);
3113  pieces.push_back(j2);
3114  return join(pieces, recombiner);
3115 }
3116 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3,
3117  const JetDefinition::Recombiner & recombiner){
3118  vector<PseudoJet> pieces;
3119  pieces.push_back(j1);
3120  pieces.push_back(j2);
3121  pieces.push_back(j3);
3122  return join(pieces, recombiner);
3123 }
3124 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4,
3125  const JetDefinition::Recombiner & recombiner){
3126  vector<PseudoJet> pieces;
3127  pieces.push_back(j1);
3128  pieces.push_back(j2);
3129  pieces.push_back(j3);
3130  pieces.push_back(j4);
3131  return join(pieces, recombiner);
3132 }
3133 FJCORE_END_NAMESPACE
3134 #include <sstream>
3135 #include <limits>
3136 using namespace std;
3137 FJCORE_BEGIN_NAMESPACE
3138 ostream * LimitedWarning::_default_ostr = &cerr;
3139 std::list< LimitedWarning::Summary > LimitedWarning::_global_warnings_summary;
3140 int LimitedWarning::_max_warn_default = 5;
3141 void LimitedWarning::warn(const std::string & warning) {
3142  warn(warning, _default_ostr);
3143 }
3144 void LimitedWarning::warn(const std::string & warning, std::ostream * ostr) {
3145  if (_this_warning_summary == 0) {
3146  _global_warnings_summary.push_back(Summary(warning, 0));
3147  _this_warning_summary = & (_global_warnings_summary.back());
3148  }
3149  if (_n_warn_so_far < _max_warn) {
3150  ostringstream warnstr;
3151  warnstr << "WARNING: ";
3152  warnstr << warning;
3153  _n_warn_so_far++;
3154  if (_n_warn_so_far == _max_warn) warnstr << " (LAST SUCH WARNING)";
3155  warnstr << std::endl;
3156  if (ostr) {
3157  (*ostr) << warnstr.str();
3158  ostr->flush(); // get something written to file even if the program aborts
3159  }
3160  }
3161  if (_this_warning_summary->second < numeric_limits<unsigned>::max()) {
3162  _this_warning_summary->second++;
3163  }
3164 }
3165 string LimitedWarning::summary() {
3166  ostringstream str;
3167  for (list<Summary>::const_iterator it = _global_warnings_summary.begin();
3168  it != _global_warnings_summary.end(); it++) {
3169  str << it->second << " times: " << it->first << endl;
3170  }
3171  return str.str();
3172 }
3173 FJCORE_END_NAMESPACE
3174 #include<iostream>
3175 #include<cmath>
3176 #include<limits>
3177 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
3178 using namespace std;
3179 void MinHeap::_initialise(const std::vector<double> & values){
3180  for (unsigned i = values.size(); i < _heap.size(); i++) {
3181  _heap[i].value = std::numeric_limits<double>::max();
3182  _heap[i].minloc = &(_heap[i]);
3183  }
3184  for (unsigned i = 0; i < values.size(); i++) {
3185  _heap[i].value = values[i];
3186  _heap[i].minloc = &(_heap[i]);
3187  }
3188  for (unsigned i = _heap.size()-1; i > 0; i--) {
3189  ValueLoc * parent = &(_heap[(i-1)/2]);
3190  ValueLoc * here = &(_heap[i]);
3191  if (here->minloc->value < parent->minloc->value) {
3192  parent->minloc = here->minloc;
3193  }
3194  }
3195 }
3196 void MinHeap::update(unsigned int loc, double new_value) {
3197  assert(loc < _heap.size());
3198  ValueLoc * start = &(_heap[loc]);
3199  if (start->minloc != start && !(new_value < start->minloc->value)) {
3200  start->value = new_value;
3201  return;
3202  }
3203  start->value = new_value;
3204  start->minloc = start;
3205  bool change_made = true;
3206  ValueLoc * heap_end = (&(_heap[0])) + _heap.size();
3207  while(change_made) {
3208  ValueLoc * here = &(_heap[loc]);
3209  change_made = false;
3210  if (here->minloc == start) {
3211  here->minloc = here; change_made = true;
3212  }
3213  ValueLoc * child = &(_heap[2*loc+1]);
3214  if (child < heap_end && child->minloc->value < here->minloc->value ) {
3215  here->minloc = child->minloc;
3216  change_made = true;}
3217  child++;
3218  if (child < heap_end && child->minloc->value < here->minloc->value ) {
3219  here->minloc = child->minloc;
3220  change_made = true;}
3221  if (loc == 0) {break;}
3222  loc = (loc-1)/2;
3223  }
3224 }
3225 FJCORE_END_NAMESPACE
3226 #include<valarray>
3227 #include<iostream>
3228 #include<sstream>
3229 #include<cmath>
3230 #include<algorithm>
3231 #include <cstdarg>
3232 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
3233 using namespace std;
3234 PseudoJet::PseudoJet(const double px_in, const double py_in, const double pz_in, const double E_in) {
3235  _E = E_in ;
3236  _px = px_in;
3237  _py = py_in;
3238  _pz = pz_in;
3239  this->_finish_init();
3240  _reset_indices();
3241 }
3242 void PseudoJet::_finish_init () {
3243  _kt2 = this->px()*this->px() + this->py()*this->py();
3244  _phi = pseudojet_invalid_phi;
3245  _rap = pseudojet_invalid_rap;
3246 }
3247 void PseudoJet::_set_rap_phi() const {
3248  if (_kt2 == 0.0) {
3249  _phi = 0.0; }
3250  else {
3251  _phi = atan2(this->py(),this->px());
3252  }
3253  if (_phi < 0.0) {_phi += twopi;}
3254  if (_phi >= twopi) {_phi -= twopi;} // can happen if phi=-|eps<1e-15|?
3255  if (this->E() == abs(this->pz()) && _kt2 == 0) {
3256  double MaxRapHere = MaxRap + abs(this->pz());
3257  if (this->pz() >= 0.0) {_rap = MaxRapHere;} else {_rap = -MaxRapHere;}
3258  } else {
3259  double effective_m2 = max(0.0,m2()); // force non tachyonic mass
3260  double E_plus_pz = _E + abs(_pz); // the safer of p+, p-
3261  _rap = 0.5*log((_kt2 + effective_m2)/(E_plus_pz*E_plus_pz));
3262  if (_pz > 0) {_rap = - _rap;}
3263  }
3264 }
3265 valarray<double> PseudoJet::four_mom() const {
3266  valarray<double> mom(4);
3267  mom[0] = _px;
3268  mom[1] = _py;
3269  mom[2] = _pz;
3270  mom[3] = _E ;
3271  return mom;
3272 }
3273 double PseudoJet::operator () (int i) const {
3274  switch(i) {
3275  case X:
3276  return px();
3277  case Y:
3278  return py();
3279  case Z:
3280  return pz();
3281  case T:
3282  return e();
3283  default:
3284  ostringstream err;
3285  err << "PseudoJet subscripting: bad index (" << i << ")";
3286  throw Error(err.str());
3287  }
3288  return 0.;
3289 }
3290 double PseudoJet::pseudorapidity() const {
3291  if (px() == 0.0 && py() ==0.0) return MaxRap;
3292  if (pz() == 0.0) return 0.0;
3293  double theta = atan(perp()/pz());
3294  if (theta < 0) theta += pi;
3295  return -log(tan(theta/2));
3296 }
3297 PseudoJet operator+ (const PseudoJet & jet1, const PseudoJet & jet2) {
3298  return PseudoJet(jet1.px()+jet2.px(),
3299  jet1.py()+jet2.py(),
3300  jet1.pz()+jet2.pz(),
3301  jet1.E() +jet2.E() );
3302 }
3303 PseudoJet operator- (const PseudoJet & jet1, const PseudoJet & jet2) {
3304  return PseudoJet(jet1.px()-jet2.px(),
3305  jet1.py()-jet2.py(),
3306  jet1.pz()-jet2.pz(),
3307  jet1.E() -jet2.E() );
3308 }
3309 PseudoJet operator* (double coeff, const PseudoJet & jet) {
3310  PseudoJet coeff_times_jet(jet);
3311  coeff_times_jet *= coeff;
3312  return coeff_times_jet;
3313 }
3314 PseudoJet operator* (const PseudoJet & jet, double coeff) {
3315  return coeff*jet;
3316 }
3317 PseudoJet operator/ (const PseudoJet & jet, double coeff) {
3318  return (1.0/coeff)*jet;
3319 }
3320 void PseudoJet::operator*=(double coeff) {
3321  _px *= coeff;
3322  _py *= coeff;
3323  _pz *= coeff;
3324  _E *= coeff;
3325  _kt2*= coeff*coeff;
3326 }
3327 void PseudoJet::operator/=(double coeff) {
3328  (*this) *= 1.0/coeff;
3329 }
3330 void PseudoJet::operator+=(const PseudoJet & other_jet) {
3331  _px += other_jet._px;
3332  _py += other_jet._py;
3333  _pz += other_jet._pz;
3334  _E += other_jet._E ;
3335  _finish_init(); // we need to recalculate phi,rap,kt2
3336 }
3337 void PseudoJet::operator-=(const PseudoJet & other_jet) {
3338  _px -= other_jet._px;
3339  _py -= other_jet._py;
3340  _pz -= other_jet._pz;
3341  _E -= other_jet._E ;
3342  _finish_init(); // we need to recalculate phi,rap,kt2
3343 }
3344 bool operator==(const PseudoJet & a, const PseudoJet & b) {
3345  if (a.px() != b.px()) return false;
3346  if (a.py() != b.py()) return false;
3347  if (a.pz() != b.pz()) return false;
3348  if (a.E () != b.E ()) return false;
3349  if (a.user_index() != b.user_index()) return false;
3350  if (a.cluster_hist_index() != b.cluster_hist_index()) return false;
3351  if (a.user_info_ptr() != b.user_info_ptr()) return false;
3352  if (a.structure_ptr() != b.structure_ptr()) return false;
3353  return true;
3354 }
3355 bool operator==(const PseudoJet & jet, const double val) {
3356  if (val != 0)
3357  throw Error("comparing a PseudoJet with a non-zero constant (double) is not allowed.");
3358  return (jet.px() == 0 && jet.py() == 0 &&
3359  jet.pz() == 0 && jet.E() == 0);
3360 }
3361 PseudoJet & PseudoJet::boost(const PseudoJet & prest) {
3362  if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3363  return *this;
3364  double m_local = prest.m();
3365  assert(m_local != 0);
3366  double pf4 = ( px()*prest.px() + py()*prest.py()
3367  + pz()*prest.pz() + E()*prest.E() )/m_local;
3368  double fn = (pf4 + E()) / (prest.E() + m_local);
3369  _px += fn*prest.px();
3370  _py += fn*prest.py();
3371  _pz += fn*prest.pz();
3372  _E = pf4;
3373  _finish_init(); // we need to recalculate phi,rap,kt2
3374  return *this;
3375 }
3376 PseudoJet & PseudoJet::unboost(const PseudoJet & prest) {
3377  if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3378  return *this;
3379  double m_local = prest.m();
3380  assert(m_local != 0);
3381  double pf4 = ( -px()*prest.px() - py()*prest.py()
3382  - pz()*prest.pz() + E()*prest.E() )/m_local;
3383  double fn = (pf4 + E()) / (prest.E() + m_local);
3384  _px -= fn*prest.px();
3385  _py -= fn*prest.py();
3386  _pz -= fn*prest.pz();
3387  _E = pf4;
3388  _finish_init(); // we need to recalculate phi,rap,kt2
3389  return *this;
3390 }
3391 bool have_same_momentum(const PseudoJet & jeta, const PseudoJet & jetb) {
3392  return jeta.px() == jetb.px()
3393  && jeta.py() == jetb.py()
3394  && jeta.pz() == jetb.pz()
3395  && jeta.E() == jetb.E();
3396 }
3397 void PseudoJet::set_cached_rap_phi(double rap_in, double phi_in) {
3398  _rap = rap_in; _phi = phi_in;
3399  if (_phi >= twopi) _phi -= twopi;
3400  if (_phi < 0) _phi += twopi;
3401 }
3402 void PseudoJet::reset_momentum_PtYPhiM(double pt_in, double y_in, double phi_in, double m_in) {
3403  assert(phi_in < 2*twopi && phi_in > -twopi);
3404  double ptm = (m_in == 0) ? pt_in : sqrt(pt_in*pt_in+m_in*m_in);
3405  double exprap = exp(y_in);
3406  double pminus = ptm/exprap;
3407  double pplus = ptm*exprap;
3408  double px_local = pt_in*cos(phi_in);
3409  double py_local = pt_in*sin(phi_in);
3410  reset_momentum(px_local,py_local,0.5*(pplus-pminus),0.5*(pplus+pminus));
3411  set_cached_rap_phi(y_in,phi_in);
3412 }
3413 PseudoJet PtYPhiM(double pt, double y, double phi, double m) {
3414  assert(phi < 2*twopi && phi > -twopi);
3415  double ptm = (m == 0) ? pt : sqrt(pt*pt+m*m);
3416  double exprap = exp(y);
3417  double pminus = ptm/exprap;
3418  double pplus = ptm*exprap;
3419  double px = pt*cos(phi);
3420  double py = pt*sin(phi);
3421  PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
3422  mom.set_cached_rap_phi(y,phi);
3423  return mom;
3424 }
3425 double PseudoJet::kt_distance(const PseudoJet & other) const {
3426  double distance = min(_kt2, other._kt2);
3427  double dphi = abs(phi() - other.phi());
3428  if (dphi > pi) {dphi = twopi - dphi;}
3429  double drap = rap() - other.rap();
3430  distance = distance * (dphi*dphi + drap*drap);
3431  return distance;
3432 }
3433 double PseudoJet::plain_distance(const PseudoJet & other) const {
3434  double dphi = abs(phi() - other.phi());
3435  if (dphi > pi) {dphi = twopi - dphi;}
3436  double drap = rap() - other.rap();
3437  return (dphi*dphi + drap*drap);
3438 }
3439 double PseudoJet::delta_phi_to(const PseudoJet & other) const {
3440  double dphi = other.phi() - phi();
3441  if (dphi > pi) dphi -= twopi;
3442  if (dphi < -pi) dphi += twopi;
3443  return dphi;
3444 }
3445 string PseudoJet::description() const{
3446  if (!_structure())
3447  return "standard PseudoJet (with no associated clustering information)";
3448  return _structure()->description();
3449 }
3450 bool PseudoJet::has_associated_cluster_sequence() const{
3451  return (_structure()) && (_structure->has_associated_cluster_sequence());
3452 }
3453 const ClusterSequence* PseudoJet::associated_cluster_sequence() const{
3454  if (! has_associated_cluster_sequence()) return NULL;
3455  return _structure->associated_cluster_sequence();
3456 }
3457 bool PseudoJet::has_valid_cluster_sequence() const{
3458  return (_structure()) && (_structure->has_valid_cluster_sequence());
3459 }
3460 const ClusterSequence * PseudoJet::validated_cs() const {
3461  return validated_structure_ptr()->validated_cs();
3462 }
3463 void PseudoJet::set_structure_shared_ptr(const SharedPtr<PseudoJetStructureBase> &structure_in){
3464  _structure = structure_in;
3465 }
3466 bool PseudoJet::has_structure() const{
3467  return _structure();
3468 }
3469 const PseudoJetStructureBase* PseudoJet::structure_ptr() const {
3470  if (!_structure()) return NULL;
3471  return _structure();
3472 }
3473 PseudoJetStructureBase* PseudoJet::structure_non_const_ptr(){
3474  if (!_structure()) return NULL;
3475  return _structure();
3476 }
3477 const PseudoJetStructureBase* PseudoJet::validated_structure_ptr() const {
3478  if (!_structure())
3479  throw Error("Trying to access the structure of a PseudoJet which has no associated structure");
3480  return _structure();
3481 }
3482 const SharedPtr<PseudoJetStructureBase> & PseudoJet::structure_shared_ptr() const {
3483  return _structure;
3484 }
3485 bool PseudoJet::has_partner(PseudoJet &partner) const{
3486  return validated_structure_ptr()->has_partner(*this, partner);
3487 }
3488 bool PseudoJet::has_child(PseudoJet &child) const{
3489  return validated_structure_ptr()->has_child(*this, child);
3490 }
3491 bool PseudoJet::has_parents(PseudoJet &parent1, PseudoJet &parent2) const{
3492  return validated_structure_ptr()->has_parents(*this, parent1, parent2);
3493 }
3494 bool PseudoJet::contains(const PseudoJet &constituent) const{
3495  return validated_structure_ptr()->object_in_jet(constituent, *this);
3496 }
3497 bool PseudoJet::is_inside(const PseudoJet &jet) const{
3498  return validated_structure_ptr()->object_in_jet(*this, jet);
3499 }
3500 bool PseudoJet::has_constituents() const{
3501  return (_structure()) && (_structure->has_constituents());
3502 }
3503 vector<PseudoJet> PseudoJet::constituents() const{
3504  return validated_structure_ptr()->constituents(*this);
3505 }
3506 bool PseudoJet::has_exclusive_subjets() const{
3507  return (_structure()) && (_structure->has_exclusive_subjets());
3508 }
3509 std::vector<PseudoJet> PseudoJet::exclusive_subjets (const double & dcut) const {
3510  return validated_structure_ptr()->exclusive_subjets(*this, dcut);
3511 }
3512 int PseudoJet::n_exclusive_subjets(const double & dcut) const {
3513  return validated_structure_ptr()->n_exclusive_subjets(*this, dcut);
3514 }
3515 std::vector<PseudoJet> PseudoJet::exclusive_subjets_up_to (int nsub) const {
3516  return validated_structure_ptr()->exclusive_subjets_up_to(*this, nsub);
3517 }
3518 std::vector<PseudoJet> PseudoJet::exclusive_subjets (int nsub) const {
3519  vector<PseudoJet> subjets = exclusive_subjets_up_to(nsub);
3520  if (int(subjets.size()) < nsub) {
3521  ostringstream err;
3522  err << "Requested " << nsub << " exclusive subjets, but there were only "
3523  << subjets.size() << " particles in the jet";
3524  throw Error(err.str());
3525  }
3526  return subjets;
3527 }
3528 double PseudoJet::exclusive_subdmerge(int nsub) const {
3529  return validated_structure_ptr()->exclusive_subdmerge(*this, nsub);
3530 }
3531 double PseudoJet::exclusive_subdmerge_max(int nsub) const {
3532  return validated_structure_ptr()->exclusive_subdmerge_max(*this, nsub);
3533 }
3534 bool PseudoJet::has_pieces() const{
3535  return ((_structure()) && (_structure->has_pieces(*this)));
3536 }
3537 std::vector<PseudoJet> PseudoJet::pieces() const{
3538  return validated_structure_ptr()->pieces(*this);
3539 }
3540 PseudoJet::InexistentUserInfo::InexistentUserInfo() : Error("you attempted to perform a dynamic cast of a PseudoJet's extra info, but the extra info pointer was null")
3541 {}
3542 void sort_indices(vector<int> & indices,
3543  const vector<double> & values) {
3544  IndexedSortHelper index_sort_helper(&values);
3545  sort(indices.begin(), indices.end(), index_sort_helper);
3546 }
3547 template<class T> vector<T> objects_sorted_by_values(
3548  const vector<T> & objects,
3549  const vector<double> & values) {
3550  assert(objects.size() == values.size());
3551  vector<int> indices(values.size());
3552  for (size_t i = 0; i < indices.size(); i++) {indices[i] = i;}
3553  sort_indices(indices, values);
3554  vector<T> objects_sorted(objects.size());
3555  for (size_t i = 0; i < indices.size(); i++) {
3556  objects_sorted[i] = objects[indices[i]];
3557  }
3558  return objects_sorted;
3559 }
3560 vector<PseudoJet> sorted_by_pt(const vector<PseudoJet> & jets) {
3561  vector<double> minus_kt2(jets.size());
3562  for (size_t i = 0; i < jets.size(); i++) {minus_kt2[i] = -jets[i].kt2();}
3563  return objects_sorted_by_values(jets, minus_kt2);
3564 }
3565 vector<PseudoJet> sorted_by_rapidity(const vector<PseudoJet> & jets) {
3566  vector<double> rapidities(jets.size());
3567  for (size_t i = 0; i < jets.size(); i++) {rapidities[i] = jets[i].rap();}
3568  return objects_sorted_by_values(jets, rapidities);
3569 }
3570 vector<PseudoJet> sorted_by_E(const vector<PseudoJet> & jets) {
3571  vector<double> energies(jets.size());
3572  for (size_t i = 0; i < jets.size(); i++) {energies[i] = -jets[i].E();}
3573  return objects_sorted_by_values(jets, energies);
3574 }
3575 vector<PseudoJet> sorted_by_pz(const vector<PseudoJet> & jets) {
3576  vector<double> pz(jets.size());
3577  for (size_t i = 0; i < jets.size(); i++) {pz[i] = jets[i].pz();}
3578  return objects_sorted_by_values(jets, pz);
3579 }
3580 PseudoJet join(const vector<PseudoJet> & pieces){
3581  PseudoJet result; // automatically initialised to 0
3582  for (unsigned int i=0; i<pieces.size(); i++)
3583  result += pieces[i];
3584  CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces);
3585  result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
3586  return result;
3587 }
3588 PseudoJet join(const PseudoJet & j1){
3589  return join(vector<PseudoJet>(1,j1));
3590 }
3591 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2){
3592  vector<PseudoJet> pieces;
3593  pieces.push_back(j1);
3594  pieces.push_back(j2);
3595  return join(pieces);
3596 }
3597 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3){
3598  vector<PseudoJet> pieces;
3599  pieces.push_back(j1);
3600  pieces.push_back(j2);
3601  pieces.push_back(j3);
3602  return join(pieces);
3603 }
3604 PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4){
3605  vector<PseudoJet> pieces;
3606  pieces.push_back(j1);
3607  pieces.push_back(j2);
3608  pieces.push_back(j3);
3609  pieces.push_back(j4);
3610  return join(pieces);
3611 }
3612 FJCORE_END_NAMESPACE
3613 using namespace std;
3614 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
3615 const ClusterSequence* PseudoJetStructureBase::associated_cluster_sequence() const{
3616  return NULL;
3617 }
3618 const ClusterSequence * PseudoJetStructureBase::validated_cs() const{
3619  throw Error("This PseudoJet structure is not associated with a valid ClusterSequence");
3620 }
3621 bool PseudoJetStructureBase::has_partner(const PseudoJet & /*reference */, PseudoJet & /*partner*/) const{
3622  throw Error("This PseudoJet structure has no implementation for has_partner");
3623 }
3624 bool PseudoJetStructureBase::has_child(const PseudoJet & /*reference*/, PseudoJet & /*child*/) const{
3625  throw Error("This PseudoJet structure has no implementation for has_child");
3626 }
3627 bool PseudoJetStructureBase::has_parents(const PseudoJet & /*reference*/, PseudoJet &/*parent1*/, PseudoJet &/*parent2*/) const{
3628  throw Error("This PseudoJet structure has no implementation for has_parents");
3629 }
3630 bool PseudoJetStructureBase::object_in_jet(const PseudoJet & /*reference*/, const PseudoJet & /*jet*/) const{
3631  throw Error("This PseudoJet structure has no implementation for is_inside");
3632 }
3633 vector<PseudoJet> PseudoJetStructureBase::constituents(const PseudoJet &/*reference*/) const{
3634  throw Error("This PseudoJet structure has no implementation for constituents");
3635 }
3636 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets (const PseudoJet & /*reference*/, const double & /*dcut*/) const{
3637  throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
3638 }
3639 int PseudoJetStructureBase::n_exclusive_subjets(const PseudoJet & /*reference*/, const double & /*dcut*/) const{
3640  throw Error("This PseudoJet structure has no implementation for n_exclusive_subjets");
3641 }
3642 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets_up_to (const PseudoJet & /*reference*/, int /*nsub*/) const{
3643  throw Error("This PseudoJet structure has no implementation for exclusive_subjets");
3644 }
3645 double PseudoJetStructureBase::exclusive_subdmerge(const PseudoJet & /*reference*/, int /*nsub*/) const{
3646  throw Error("This PseudoJet structure has no implementation for exclusive_submerge");
3647 }
3648 double PseudoJetStructureBase::exclusive_subdmerge_max(const PseudoJet & /*reference*/, int /*nsub*/) const{
3649  throw Error("This PseudoJet structure has no implementation for exclusive_submerge_max");
3650 }
3651 std::vector<PseudoJet> PseudoJetStructureBase::pieces(const PseudoJet & /*reference*/) const{
3652  throw Error("This PseudoJet structure has no implementation for pieces");
3653 }
3654 FJCORE_END_NAMESPACE
3655 #include <sstream>
3656 #include <algorithm>
3657 using namespace std;
3658 FJCORE_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
3659 std::vector<PseudoJet> Selector::operator()(const std::vector<PseudoJet> & jets) const {
3660  std::vector<PseudoJet> result;
3661  const SelectorWorker * worker_local = validated_worker();
3662  if (worker_local->applies_jet_by_jet()) {
3663  for (std::vector<PseudoJet>::const_iterator jet = jets.begin();
3664  jet != jets.end(); jet++) {
3665  if (worker_local->pass(*jet)) result.push_back(*jet);
3666  }
3667  } else {
3668  std::vector<const PseudoJet *> jetptrs(jets.size());
3669  for (unsigned i = 0; i < jets.size(); i++) {
3670  jetptrs[i] = & jets[i];
3671  }
3672  worker_local->terminator(jetptrs);
3673  for (unsigned i = 0; i < jetptrs.size(); i++) {
3674  if (jetptrs[i]) result.push_back(jets[i]);
3675  }
3676  }
3677  return result;
3678 }
3679 unsigned int Selector::count(const std::vector<PseudoJet> & jets) const {
3680  unsigned n = 0;
3681  const SelectorWorker * worker_local = validated_worker();
3682  if (worker_local->applies_jet_by_jet()) {
3683  for (unsigned i = 0; i < jets.size(); i++) {
3684  if (worker_local->pass(jets[i])) n++;
3685  }
3686  } else {
3687  std::vector<const PseudoJet *> jetptrs(jets.size());
3688  for (unsigned i = 0; i < jets.size(); i++) {
3689  jetptrs[i] = & jets[i];
3690  }
3691  worker_local->terminator(jetptrs);
3692  for (unsigned i = 0; i < jetptrs.size(); i++) {
3693  if (jetptrs[i]) n++;
3694  }
3695  }
3696  return n;
3697 }
3698 void Selector::sift(const std::vector<PseudoJet> & jets,
3699  std::vector<PseudoJet> & jets_that_pass,
3700  std::vector<PseudoJet> & jets_that_fail
3701  ) const {
3702  const SelectorWorker * worker_local = validated_worker();
3703  jets_that_pass.clear();
3704  jets_that_fail.clear();
3705  if (worker_local->applies_jet_by_jet()) {
3706  for (unsigned i = 0; i < jets.size(); i++) {
3707  if (worker_local->pass(jets[i])) {
3708  jets_that_pass.push_back(jets[i]);
3709  } else {
3710  jets_that_fail.push_back(jets[i]);
3711  }
3712  }
3713  } else {
3714  std::vector<const PseudoJet *> jetptrs(jets.size());
3715  for (unsigned i = 0; i < jets.size(); i++) {
3716  jetptrs[i] = & jets[i];
3717  }
3718  worker_local->terminator(jetptrs);
3719  for (unsigned i = 0; i < jetptrs.size(); i++) {
3720  if (jetptrs[i]) {
3721  jets_that_pass.push_back(jets[i]);
3722  } else {
3723  jets_that_fail.push_back(jets[i]);
3724  }
3725  }
3726  }
3727 }
3728 bool SelectorWorker::has_finite_area() const {
3729  if (! is_geometric()) return false;
3730  double rapmin, rapmax;
3731  get_rapidity_extent(rapmin, rapmax);
3732  return (rapmax != std::numeric_limits<double>::infinity())
3733  && (-rapmin != std::numeric_limits<double>::infinity());
3734 }
3735 class SW_Identity : public SelectorWorker {
3736 public:
3737  SW_Identity(){}
3738  virtual bool pass(const PseudoJet &) const {
3739  return true;
3740  }
3741  virtual void terminator(vector<const PseudoJet *> &) const {
3742  return;
3743  }
3744  virtual string description() const { return "Identity";}
3745  virtual bool is_geometric() const { return true;}
3746 };
3747 Selector SelectorIdentity() {
3748  return Selector(new SW_Identity);
3749 }
3750 class SW_Not : public SelectorWorker {
3751 public:
3752  SW_Not(const Selector & s) : _s(s) {}
3753  virtual SelectorWorker* copy(){ return new SW_Not(*this);}
3754  virtual bool pass(const PseudoJet & jet) const {
3755  if (!applies_jet_by_jet())
3756  throw Error("Cannot apply this selector worker to an individual jet");
3757  return ! _s.pass(jet);
3758  }
3759  virtual bool applies_jet_by_jet() const {return _s.applies_jet_by_jet();}
3760  virtual void terminator(vector<const PseudoJet *> & jets) const {
3761  if (applies_jet_by_jet()){
3762  SelectorWorker::terminator(jets);
3763  return;
3764  }
3765  vector<const PseudoJet *> s_jets = jets;
3766  _s.worker()->terminator(s_jets);
3767  for (unsigned int i=0; i<s_jets.size(); i++){
3768  if (s_jets[i]) jets[i] = NULL;
3769  }
3770  }
3771  virtual string description() const {
3772  ostringstream ostr;
3773  ostr << "!(" << _s.description() << ")";
3774  return ostr.str();
3775  }
3776  virtual bool is_geometric() const { return _s.is_geometric();}
3777  virtual bool takes_reference() const { return _s.takes_reference();}
3778  virtual void set_reference(const PseudoJet &ref) { _s.set_reference(ref);}
3779 protected:
3780  Selector _s;
3781 };
3782 Selector operator!(const Selector & s) {
3783  return Selector(new SW_Not(s));
3784 }
3786 public:
3787  SW_BinaryOperator(const Selector & s1, const Selector & s2) : _s1(s1), _s2(s2) {
3788  _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
3789  _takes_reference = _s1.takes_reference() || _s2.takes_reference();
3790  _is_geometric = _s1.is_geometric() && _s2.is_geometric();
3791  }
3792  virtual bool applies_jet_by_jet() const {return _applies_jet_by_jet;}
3793  virtual bool takes_reference() const{
3794  return _takes_reference;
3795  }
3796  virtual void set_reference(const PseudoJet &centre){
3797  _s1.set_reference(centre);
3798  _s2.set_reference(centre);
3799  }
3800  virtual bool is_geometric() const { return _is_geometric;}
3801 protected:
3802  Selector _s1, _s2;
3803  bool _applies_jet_by_jet;
3804  bool _takes_reference;
3805  bool _is_geometric;
3806 };
3807 class SW_And: public SW_BinaryOperator {
3808 public:
3809  SW_And(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2){}
3810  virtual SelectorWorker* copy(){ return new SW_And(*this);}
3811  virtual bool pass(const PseudoJet & jet) const {
3812  if (!applies_jet_by_jet())
3813  throw Error("Cannot apply this selector worker to an individual jet");
3814  return _s1.pass(jet) && _s2.pass(jet);
3815  }
3816  virtual void terminator(vector<const PseudoJet *> & jets) const {
3817  if (applies_jet_by_jet()){
3818  SelectorWorker::terminator(jets);
3819  return;
3820  }
3821  vector<const PseudoJet *> s1_jets = jets;
3822  _s1.worker()->terminator(s1_jets);
3823  _s2.worker()->terminator(jets);
3824  for (unsigned int i=0; i<jets.size(); i++){
3825  if (! s1_jets[i]) jets[i] = NULL;
3826  }
3827  }
3828  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
3829  double s1min, s1max, s2min, s2max;
3830  _s1.get_rapidity_extent(s1min, s1max);
3831  _s2.get_rapidity_extent(s2min, s2max);
3832  rapmax = min(s1max, s2max);
3833  rapmin = max(s1min, s2min);
3834  }
3835  virtual string description() const {
3836  ostringstream ostr;
3837  ostr << "(" << _s1.description() << " && " << _s2.description() << ")";
3838  return ostr.str();
3839  }
3840 };
3841 Selector operator&&(const Selector & s1, const Selector & s2) {
3842  return Selector(new SW_And(s1,s2));
3843 }
3844 class SW_Or: public SW_BinaryOperator {
3845 public:
3846  SW_Or(const Selector & s1, const Selector & s2) : SW_BinaryOperator(s1,s2) {}
3847  virtual SelectorWorker* copy(){ return new SW_Or(*this);}
3848  virtual bool pass(const PseudoJet & jet) const {
3849  if (!applies_jet_by_jet())
3850  throw Error("Cannot apply this selector worker to an individual jet");
3851  return _s1.pass(jet) || _s2.pass(jet);
3852  }
3853  virtual bool applies_jet_by_jet() const {
3854  return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
3855  }
3856  virtual void terminator(vector<const PseudoJet *> & jets) const {
3857  if (applies_jet_by_jet()){
3858  SelectorWorker::terminator(jets);
3859  return;
3860  }
3861  vector<const PseudoJet *> s1_jets = jets;
3862  _s1.worker()->terminator(s1_jets);
3863  _s2.worker()->terminator(jets);
3864  for (unsigned int i=0; i<jets.size(); i++){
3865  if (s1_jets[i]) jets[i] = s1_jets[i];
3866  }
3867  }
3868  virtual string description() const {
3869  ostringstream ostr;
3870  ostr << "(" << _s1.description() << " || " << _s2.description() << ")";
3871  return ostr.str();
3872  }
3873  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const {
3874  double s1min, s1max, s2min, s2max;
3875  _s1.get_rapidity_extent(s1min, s1max);
3876  _s2.get_rapidity_extent(s2min, s2max);
3877  rapmax = max(s1max, s2max);
3878  rapmin = min(s1min, s2min);
3879  }
3880 };
3881 Selector operator ||(const Selector & s1, const Selector & s2) {
3882  return Selector(new SW_Or(s1,s2));
3883 }
3884 class SW_Mult: public SW_And {
3885 public:
3886  SW_Mult(const Selector & s1, const Selector & s2) : SW_And(s1,s2) {}
3887  virtual SelectorWorker* copy(){ return new SW_Mult(*this);}
3888  virtual void terminator(vector<const PseudoJet *> & jets) const {
3889  if (applies_jet_by_jet()){
3890  SelectorWorker::terminator(jets);
3891  return;
3892  }
3893  _s2.worker()->terminator(jets);
3894  _s1.worker()->terminator(jets);
3895  }
3896  virtual string description() const {
3897  ostringstream ostr;
3898  ostr << "(" << _s1.description() << " * " << _s2.description() << ")";
3899  return ostr.str();
3900  }
3901 };
3902 Selector operator*(const Selector & s1, const Selector & s2) {
3903  return Selector(new SW_Mult(s1,s2));
3904 }
3906 public:
3907  QuantityBase(double q) : _q(q){}
3908  virtual ~QuantityBase(){}
3909  virtual double operator()(const PseudoJet & jet ) const =0;
3910  virtual string description() const =0;
3911  virtual bool is_geometric() const { return false;}
3912  virtual double comparison_value() const {return _q;}
3913  virtual double description_value() const {return comparison_value();}
3914 protected:
3915  double _q;
3916 };
3918 public:
3919  QuantitySquareBase(double sqrtq) : QuantityBase(sqrtq*sqrtq), _sqrtq(sqrtq){}
3920  virtual double description_value() const {return _sqrtq;}
3921 protected:
3922  double _sqrtq;
3923 };
3924 template<typename QuantityType>
3926 public:
3927  SW_QuantityMin(double qmin) : _qmin(qmin) {}
3928  virtual bool pass(const PseudoJet & jet) const {return _qmin(jet) >= _qmin.comparison_value();}
3929  virtual string description() const {
3930  ostringstream ostr;
3931  ostr << _qmin.description() << " >= " << _qmin.description_value();
3932  return ostr.str();
3933  }
3934  virtual bool is_geometric() const { return _qmin.is_geometric();}
3935 protected:
3936  QuantityType _qmin;
3937 };
3938 template<typename QuantityType>
3940 public:
3941  SW_QuantityMax(double qmax) : _qmax(qmax) {}
3942  virtual bool pass(const PseudoJet & jet) const {return _qmax(jet) <= _qmax.comparison_value();}
3943  virtual string description() const {
3944  ostringstream ostr;
3945  ostr << _qmax.description() << " <= " << _qmax.description_value();
3946  return ostr.str();
3947  }
3948  virtual bool is_geometric() const { return _qmax.is_geometric();}
3949 protected:
3950  QuantityType _qmax;
3951 };
3952 template<typename QuantityType>
3954 public:
3955  SW_QuantityRange(double qmin, double qmax) : _qmin(qmin), _qmax(qmax) {}
3956  virtual bool pass(const PseudoJet & jet) const {
3957  double q = _qmin(jet); // we could identically use _qmax
3958  return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
3959  }
3960  virtual string description() const {
3961  ostringstream ostr;
3962  ostr << _qmin.description_value() << " <= " << _qmin.description() << " <= " << _qmax.description_value();
3963  return ostr.str();
3964  }
3965  virtual bool is_geometric() const { return _qmin.is_geometric();}
3966 protected:
3967  QuantityType _qmin; // the lower cut
3968  QuantityType _qmax; // the upper cut
3969 };
3971 public:
3972  QuantityPt2(double pt) : QuantitySquareBase(pt){}
3973  virtual double operator()(const PseudoJet & jet ) const { return jet.perp2();}
3974  virtual string description() const {return "pt";}
3975 };
3976 Selector SelectorPtMin(double ptmin) {
3977  return Selector(new SW_QuantityMin<QuantityPt2>(ptmin));
3978 }
3979 Selector SelectorPtMax(double ptmax) {
3980  return Selector(new SW_QuantityMax<QuantityPt2>(ptmax));
3981 }
3982 Selector SelectorPtRange(double ptmin, double ptmax) {
3983  return Selector(new SW_QuantityRange<QuantityPt2>(ptmin, ptmax));
3984 }
3986 public:
3987  QuantityEt2(double Et) : QuantitySquareBase(Et){}
3988  virtual double operator()(const PseudoJet & jet ) const { return jet.Et2();}
3989  virtual string description() const {return "Et";}
3990 };
3991 Selector SelectorEtMin(double Etmin) {
3992  return Selector(new SW_QuantityMin<QuantityEt2>(Etmin));
3993 }
3994 Selector SelectorEtMax(double Etmax) {
3995  return Selector(new SW_QuantityMax<QuantityEt2>(Etmax));
3996 }
3997 Selector SelectorEtRange(double Etmin, double Etmax) {
3998  return Selector(new SW_QuantityRange<QuantityEt2>(Etmin, Etmax));
3999 }
4000 class QuantityE : public QuantityBase{
4001 public:
4002  QuantityE(double E) : QuantityBase(E){}
4003  virtual double operator()(const PseudoJet & jet ) const { return jet.E();}
4004  virtual string description() const {return "E";}
4005 };
4006 Selector SelectorEMin(double Emin) {
4007  return Selector(new SW_QuantityMin<QuantityE>(Emin));
4008 }
4009 Selector SelectorEMax(double Emax) {
4010  return Selector(new SW_QuantityMax<QuantityE>(Emax));
4011 }
4012 Selector SelectorERange(double Emin, double Emax) {
4013  return Selector(new SW_QuantityRange<QuantityE>(Emin, Emax));
4014 }
4016 public:
4017  QuantityM2(double m) : QuantitySquareBase(m){}
4018  virtual double operator()(const PseudoJet & jet ) const { return jet.m2();}
4019  virtual string description() const {return "mass";}
4020 };
4021 Selector SelectorMassMin(double mmin) {
4022  return Selector(new SW_QuantityMin<QuantityM2>(mmin));
4023 }
4024 Selector SelectorMassMax(double mmax) {
4025  return Selector(new SW_QuantityMax<QuantityM2>(mmax));
4026 }
4027 Selector SelectorMassRange(double mmin, double mmax) {
4028  return Selector(new SW_QuantityRange<QuantityM2>(mmin, mmax));
4029 }
4030 class QuantityRap : public QuantityBase{
4031 public:
4032  QuantityRap(double rap) : QuantityBase(rap){}
4033  virtual double operator()(const PseudoJet & jet ) const { return jet.rap();}
4034  virtual string description() const {return "rap";}
4035  virtual bool is_geometric() const { return true;}
4036 };
4037 class SW_RapMin : public SW_QuantityMin<QuantityRap>{
4038 public:
4039  SW_RapMin(double rapmin) : SW_QuantityMin<QuantityRap>(rapmin){}
4040  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
4041  rapmax = std::numeric_limits<double>::max();
4042  rapmin = _qmin.comparison_value();
4043  }
4044 };
4045 class SW_RapMax : public SW_QuantityMax<QuantityRap>{
4046 public:
4047  SW_RapMax(double rapmax) : SW_QuantityMax<QuantityRap>(rapmax){}
4048  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
4049  rapmax = _qmax.comparison_value();
4050  rapmin = -std::numeric_limits<double>::max();
4051  }
4052 };
4053 class SW_RapRange : public SW_QuantityRange<QuantityRap>{
4054 public:
4055  SW_RapRange(double rapmin, double rapmax) : SW_QuantityRange<QuantityRap>(rapmin, rapmax){
4056  assert(rapmin<=rapmax);
4057  }
4058  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
4059  rapmax = _qmax.comparison_value();
4060  rapmin = _qmin.comparison_value();
4061  }
4062  virtual bool has_known_area() const { return true;}
4063  virtual double known_area() const {
4064  return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
4065  }
4066 };
4067 Selector SelectorRapMin(double rapmin) {
4068  return Selector(new SW_RapMin(rapmin));
4069 }
4070 Selector SelectorRapMax(double rapmax) {
4071  return Selector(new SW_RapMax(rapmax));
4072 }
4073 Selector SelectorRapRange(double rapmin, double rapmax) {
4074  return Selector(new SW_RapRange(rapmin, rapmax));
4075 }
4077 public:
4078  QuantityAbsRap(double absrap) : QuantityBase(absrap){}
4079  virtual double operator()(const PseudoJet & jet ) const { return abs(jet.rap());}
4080  virtual string description() const {return "|rap|";}
4081  virtual bool is_geometric() const { return true;}
4082 };
4083 class SW_AbsRapMax : public SW_QuantityMax<QuantityAbsRap>{
4084 public:
4085  SW_AbsRapMax(double absrapmax) : SW_QuantityMax<QuantityAbsRap>(absrapmax){}
4086  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
4087  rapmax = _qmax.comparison_value();
4088  rapmin = -_qmax.comparison_value();
4089  }
4090  virtual bool has_known_area() const { return true;}
4091  virtual double known_area() const {
4092  return twopi * 2 * _qmax.comparison_value();
4093  }
4094 };
4095 class SW_AbsRapRange : public SW_QuantityRange<QuantityAbsRap>{
4096 public:
4097  SW_AbsRapRange(double absrapmin, double absrapmax) : SW_QuantityRange<QuantityAbsRap>(absrapmin, absrapmax){}
4098  virtual void get_rapidity_extent(double &rapmin, double & rapmax) const{
4099  rapmax = _qmax.comparison_value();
4100  rapmin = -_qmax.comparison_value();
4101  }
4102  virtual bool has_known_area() const { return true;}
4103  virtual double known_area() const {
4104  return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0)); // this should handle properly absrapmin<0
4105  }
4106 };
4107 Selector SelectorAbsRapMin(double absrapmin) {
4108  return Selector(new SW_QuantityMin<QuantityAbsRap>(absrapmin));
4109 }
4110 Selector SelectorAbsRapMax(double absrapmax) {
4111  return Selector(new SW_AbsRapMax(absrapmax));
4112 }
4113 Selector SelectorAbsRapRange(double rapmin, double rapmax) {
4114  return Selector(new SW_AbsRapRange(rapmin, rapmax));
4115 }
4116 class QuantityEta : public QuantityBase{
4117 public:
4118  QuantityEta(double eta) : QuantityBase(eta){}
4119  virtual double operator()(const PseudoJet & jet ) const { return jet.eta();}
4120  virtual string description() const {return "eta";}
4121 };
4122 Selector SelectorEtaMin(double etamin) {
4123  return Selector(new SW_QuantityMin<QuantityEta>(etamin));
4124 }
4125 Selector SelectorEtaMax(double etamax) {
4126  return Selector(new SW_QuantityMax<QuantityEta>(etamax));
4127 }
4128 Selector SelectorEtaRange(double etamin, double etamax) {
4129  return Selector(new SW_QuantityRange<QuantityEta>(etamin, etamax));
4130 }
4132 public:
4133  QuantityAbsEta(double abseta) : QuantityBase(abseta){}
4134  virtual double operator()(const PseudoJet & jet ) const { return abs(jet.eta());}
4135  virtual string description() const {return "|eta|";}
4136  virtual bool is_geometric() const { return true;}
4137 };
4138 Selector SelectorAbsEtaMin(double absetamin) {
4139  return Selector(new SW_QuantityMin<QuantityAbsEta>(absetamin));
4140 }
4141 Selector SelectorAbsEtaMax(double absetamax) {
4142  return Selector(new SW_QuantityMax<QuantityAbsEta>(absetamax));
4143 }
4144 Selector SelectorAbsEtaRange(double absetamin, double absetamax) {
4145  return Selector(new SW_QuantityRange<QuantityAbsEta>(absetamin, absetamax));
4146 }
4147 class SW_PhiRange : public SelectorWorker {
4148 public:
4149  SW_PhiRange(double phimin, double phimax) : _phimin(phimin), _phimax(phimax){
4150  assert(_phimin<_phimax);
4151  assert(_phimin>-twopi);
4152  assert(_phimax<2*twopi);
4153  _phispan = _phimax - _phimin;
4154  }
4155  virtual bool pass(const PseudoJet & jet) const {
4156  double dphi=jet.phi()-_phimin;
4157  if (dphi >= twopi) dphi -= twopi;
4158  if (dphi < 0) dphi += twopi;
4159  return (dphi <= _phispan);
4160  }
4161  virtual string description() const {
4162  ostringstream ostr;
4163  ostr << _phimin << " <= phi <= " << _phimax;
4164  return ostr.str();
4165  }
4166  virtual bool is_geometric() const { return true;}
4167 protected:
4168  double _phimin; // the lower cut
4169  double _phimax; // the upper cut
4170  double _phispan; // the span of the range
4171 };
4172 Selector SelectorPhiRange(double phimin, double phimax) {
4173  return Selector(new SW_PhiRange(phimin, phimax));
4174 }
4175 class SW_RapPhiRange : public SW_And{
4176 public:
4177  SW_RapPhiRange(double rapmin, double rapmax, double phimin, double phimax)
4178  : SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
4179  _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
4180  }
4181  virtual double known_area() const{
4182  return _known_area;
4183  }
4184 protected:
4185  double _known_area;
4186 };
4187 Selector SelectorRapPhiRange(double rapmin, double rapmax, double phimin, double phimax) {
4188  return Selector(new SW_RapPhiRange(rapmin, rapmax, phimin, phimax));
4189 }
4190 class SW_NHardest : public SelectorWorker {
4191 public:
4192  SW_NHardest(unsigned int n) : _n(n) {};
4193  virtual bool pass(const PseudoJet &) const {
4194  if (!applies_jet_by_jet())
4195  throw Error("Cannot apply this selector worker to an individual jet");
4196  return false;
4197  }
4198  virtual void terminator(vector<const PseudoJet *> & jets) const {
4199  if (jets.size() < _n) return;
4200  vector<double> minus_pt2(jets.size());
4201  vector<unsigned int> indices(jets.size());
4202  for (unsigned int i=0; i<jets.size(); i++){
4203  indices[i] = i;
4204  minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
4205  }
4206  IndexedSortHelper sort_helper(& minus_pt2);
4207  partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
4208  for (unsigned int i=_n; i<jets.size(); i++)
4209  jets[indices[i]] = NULL;
4210  }
4211  virtual bool applies_jet_by_jet() const {return false;}
4212  virtual string description() const {
4213  ostringstream ostr;
4214  ostr << _n << " hardest";
4215  return ostr.str();
4216  }
4217 protected:
4218  unsigned int _n;
4219 };
4220 Selector SelectorNHardest(unsigned int n) {
4221  return Selector(new SW_NHardest(n));
4222 }
4224 public:
4225  SW_WithReference() : _is_initialised(false){};
4226  virtual bool takes_reference() const { return true;}
4227  virtual void set_reference(const PseudoJet &centre){
4228  _is_initialised = true;
4229  _reference = centre;
4230  }
4231 protected:
4232  PseudoJet _reference;
4233  bool _is_initialised;
4234 };
4235 class SW_Circle : public SW_WithReference {
4236 public:
4237  SW_Circle(const double &radius) : _radius2(radius*radius) {}
4238  virtual SelectorWorker* copy(){ return new SW_Circle(*this);}
4239  virtual bool pass(const PseudoJet & jet) const {
4240  if (! _is_initialised)
4241  throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4242  return jet.squared_distance(_reference) <= _radius2;
4243  }
4244  virtual string description() const {
4245  ostringstream ostr;
4246  ostr << "distance from the centre <= " << sqrt(_radius2);
4247  return ostr.str();
4248  }
4249  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
4250  if (! _is_initialised)
4251  throw Error("To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4252  rapmax = _reference.rap()+sqrt(_radius2);
4253  rapmin = _reference.rap()-sqrt(_radius2);
4254  }
4255  virtual bool is_geometric() const { return true;}
4256  virtual bool has_finite_area() const { return true;}
4257  virtual bool has_known_area() const { return true;}
4258  virtual double known_area() const {
4259  return pi * _radius2;
4260  }
4261 protected:
4262  double _radius2;
4263 };
4264 Selector SelectorCircle(const double & radius) {
4265  return Selector(new SW_Circle(radius));
4266 }
4268 public:
4269  SW_Doughnut(const double &radius_in, const double &radius_out)
4270  : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
4271  virtual SelectorWorker* copy(){ return new SW_Doughnut(*this);}
4272  virtual bool pass(const PseudoJet & jet) const {
4273  if (! _is_initialised)
4274  throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4275  double distance2 = jet.squared_distance(_reference);
4276  return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
4277  }
4278  virtual string description() const {
4279  ostringstream ostr;
4280  ostr << sqrt(_radius_in2) << " <= distance from the centre <= " << sqrt(_radius_out2);
4281  return ostr.str();
4282  }
4283  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
4284  if (! _is_initialised)
4285  throw Error("To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4286  rapmax = _reference.rap()+sqrt(_radius_out2);
4287  rapmin = _reference.rap()-sqrt(_radius_out2);
4288  }
4289  virtual bool is_geometric() const { return true;}
4290  virtual bool has_finite_area() const { return true;}
4291  virtual bool has_known_area() const { return true;}
4292  virtual double known_area() const {
4293  return pi * (_radius_out2-_radius_in2);
4294  }
4295 protected:
4296  double _radius_in2, _radius_out2;
4297 };
4298 Selector SelectorDoughnut(const double & radius_in, const double & radius_out) {
4299  return Selector(new SW_Doughnut(radius_in, radius_out));
4300 }
4301 class SW_Strip : public SW_WithReference {
4302 public:
4303  SW_Strip(const double &delta) : _delta(delta) {}
4304  virtual SelectorWorker* copy(){ return new SW_Strip(*this);}
4305  virtual bool pass(const PseudoJet & jet) const {
4306  if (! _is_initialised)
4307  throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4308  return abs(jet.rap()-_reference.rap()) <= _delta;
4309  }
4310  virtual string description() const {
4311  ostringstream ostr;
4312  ostr << "|rap - rap_reference| <= " << _delta;
4313  return ostr.str();
4314  }
4315  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
4316  if (! _is_initialised)
4317  throw Error("To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4318  rapmax = _reference.rap()+_delta;
4319  rapmin = _reference.rap()-_delta;
4320  }
4321  virtual bool is_geometric() const { return true;}
4322  virtual bool has_finite_area() const { return true;}
4323  virtual bool has_known_area() const { return true;}
4324  virtual double known_area() const {
4325  return twopi * 2 * _delta;
4326  }
4327 protected:
4328  double _delta;
4329 };
4330 Selector SelectorStrip(const double & half_width) {
4331  return Selector(new SW_Strip(half_width));
4332 }
4334 public:
4335  SW_Rectangle(const double &delta_rap, const double &delta_phi)
4336  : _delta_rap(delta_rap), _delta_phi(delta_phi) {}
4337  virtual SelectorWorker* copy(){ return new SW_Rectangle(*this);}
4338  virtual bool pass(const PseudoJet & jet) const {
4339  if (! _is_initialised)
4340  throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4341  return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi);
4342  }
4343  virtual string description() const {
4344  ostringstream ostr;
4345  ostr << "|rap - rap_reference| <= " << _delta_rap << " && |phi - phi_reference| <= " << _delta_phi ;
4346  return ostr.str();
4347  }
4348  virtual void get_rapidity_extent(double & rapmin, double & rapmax) const{
4349  if (! _is_initialised)
4350  throw Error("To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4351  rapmax = _reference.rap()+_delta_rap;
4352  rapmin = _reference.rap()-_delta_rap;
4353  }
4354  virtual bool is_geometric() const { return true;}
4355  virtual bool has_finite_area() const { return true;}
4356  virtual bool has_known_area() const { return true;}
4357  virtual double known_area() const {
4358  return 4 * _delta_rap * _delta_phi;
4359  }
4360 protected:
4361  double _delta_rap, _delta_phi;
4362 };
4363 Selector SelectorRectangle(const double & half_rap_width, const double & half_phi_width) {
4364  return Selector(new SW_Rectangle(half_rap_width, half_phi_width));
4365 }
4367 public:
4368  SW_PtFractionMin(double fraction) : _fraction2(fraction*fraction){}
4369  virtual SelectorWorker* copy(){ return new SW_PtFractionMin(*this);}
4370  virtual bool pass(const PseudoJet & jet) const {
4371  if (! _is_initialised)
4372  throw Error("To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)");
4373  return (jet.perp2() >= _fraction2*_reference.perp2());
4374  }
4375  virtual string description() const {
4376  ostringstream ostr;
4377  ostr << "pt >= " << sqrt(_fraction2) << "* pt_ref";
4378  return ostr.str();
4379  }
4380 protected:
4381  double _fraction2;
4382 };
4383 Selector SelectorPtFractionMin(double fraction){
4384  return Selector(new SW_PtFractionMin(fraction));
4385 }
4386 class SW_IsZero : public SelectorWorker {
4387 public:
4388  SW_IsZero(){}
4389  virtual bool pass(const PseudoJet & jet) const {
4390  return jet==0;
4391  }
4392  virtual string description() const { return "zero";}
4393 };
4394 Selector SelectorIsZero(){
4395  return Selector(new SW_IsZero());
4396 }
4397 Selector & Selector::operator &=(const Selector & b){
4398  _worker.reset(new SW_And(*this, b));
4399  return *this;
4400 }
4401 Selector & Selector::operator |=(const Selector & b){
4402  _worker.reset(new SW_Or(*this, b));
4403  return *this;
4404 }
4405 FJCORE_END_NAMESPACE // defined in fastjet/internal/base.hh
Definition: FJcore.h:367
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4102
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4062
QuantityType _qmax
the cut
Definition: FJcore.cc:3950
virtual bool is_geometric() const
implies a finite area
Definition: FJcore.cc:4255
QuantityType _qmin
the cut
Definition: FJcore.cc:3936
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4090
virtual bool has_finite_area() const
regardless of the reference
Definition: FJcore.cc:4355
virtual bool is_geometric() const
implies a finite area
Definition: FJcore.cc:4321
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4257
virtual bool has_finite_area() const
regardless of the reference
Definition: FJcore.cc:4322
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4356
Definition: FJcore.cc:837
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4291
virtual bool has_finite_area() const
regardless of the reference
Definition: FJcore.cc:4256
virtual bool has_finite_area() const
regardless of the reference
Definition: FJcore.cc:4290
virtual bool has_known_area() const
the area is analytically known
Definition: FJcore.cc:4323
bool treelinks_null() const
default constructor
Definition: FJcore.cc:273
virtual bool is_geometric() const
implies a finite area
Definition: FJcore.cc:4354
Definition: dbStruct.hh:78
virtual bool is_geometric() const
implies a finite area
Definition: FJcore.cc:4289