80 #include "Pythia8/FJcore.h"
81 #ifndef __FJCORE_VERSION_HH__
82 #define __FJCORE_VERSION_HH__
84 FJCORE_BEGIN_NAMESPACE
85 const char* fastjet_version = FJCORE_PACKAGE_VERSION;
87 #endif // __FJCORE_VERSION_HH__
88 #ifndef __FJCORE_CLUSTERQUENCE_N2_ICC__
89 #define __FJCORE_CLUSTERQUENCE_N2_ICC__
90 FJCORE_BEGIN_NAMESPACE
91 template<
class BJ>
void ClusterSequence::_simple_N2_cluster() {
93 BJ * briefjets =
new BJ[n];
94 BJ * jetA = briefjets, * jetB;
95 for (
int i = 0; i< n; i++) {
96 _bj_set_jetinfo(jetA, i);
100 BJ * head = briefjets;
101 for (jetA = head + 1; jetA != tail; jetA++) {
102 _bj_set_NN_crosscheck(jetA, head, jetA);
104 double * diJ =
new double[n];
106 for (
int i = 0; i < n; i++) {
107 diJ[i] = _bj_diJ(jetA);
110 int history_location = n-1;
111 while (tail != head) {
112 double diJ_min = diJ[0];
114 for (
int i = 1; i < n; i++) {
115 if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
118 jetA = & briefjets[diJ_min_jet];
119 jetB =
static_cast<BJ *
>(jetA->NN);
122 if (jetA < jetB) {std::swap(jetA,jetB);}
124 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
125 _bj_set_jetinfo(jetB, nn);
127 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
131 diJ[jetA - head] = diJ[tail-head];
132 for (BJ * jetI = head; jetI != tail; jetI++) {
133 if (jetI->NN == jetA || jetI->NN == jetB) {
134 _bj_set_NN_nocross(jetI, head, tail);
135 diJ[jetI-head] = _bj_diJ(jetI);
138 double dist = _bj_dist(jetI,jetB);
139 if (dist < jetI->NN_dist) {
141 jetI->NN_dist = dist;
143 diJ[jetI-head] = _bj_diJ(jetI);
146 if (dist < jetB->NN_dist) {
148 jetB->NN_dist = dist;
152 if (jetI->NN == tail) {jetI->NN = jetA;}
154 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
160 #endif // __FJCORE_CLUSTERQUENCE_N2_ICC__
161 #ifndef __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
162 #define __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
168 FJCORE_BEGIN_NAMESPACE
171 double first, second;
173 EtaPhi(
double a,
double b) {first = a; second = b;}
175 if (second < 0) second += twopi;
176 if (second >= twopi) second -= twopi;
181 DnnError(
const std::string & message_in) :
Error(message_in) {}
185 virtual int NearestNeighbourIndex(
const int ii)
const = 0;
186 virtual double NearestNeighbourDistance(
const int ii)
const = 0;
187 virtual bool Valid(
const int index)
const = 0;
188 virtual void RemoveAndAddPoints(
const std::vector<int> & indices_to_remove,
189 const std::vector<EtaPhi> & points_to_add,
190 std::vector<int> & indices_added,
191 std::vector<int> & indices_of_updated_neighbours) = 0;
192 inline void RemovePoint (
const int index,
193 std::vector<int> & indices_of_updated_neighbours) {
194 std::vector<int> indices_added;
195 std::vector<EtaPhi> points_to_add;
196 std::vector<int> indices_to_remove(1);
197 indices_to_remove[0] = index;
198 RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
199 indices_of_updated_neighbours
201 inline void RemoveCombinedAddCombination(
202 const int index1,
const int index2,
205 std::vector<int> & indices_of_updated_neighbours) {
206 std::vector<int> indices_added(1);
207 std::vector<EtaPhi> points_to_add(1);
208 std::vector<int> indices_to_remove(2);
209 indices_to_remove[0] = index1;
210 indices_to_remove[1] = index2;
211 points_to_add[0] = newpoint;
212 RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
213 indices_of_updated_neighbours
215 index3 = indices_added[0];
220 #endif // __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
221 #ifndef __FJCORE_SEARCHTREE_HH__
222 #define __FJCORE_SEARCHTREE_HH__
226 FJCORE_BEGIN_NAMESPACE
231 class const_circulator;
233 SearchTree(
const std::vector<T> & init,
unsigned int max_size);
234 void remove(
unsigned node_index);
237 circulator insert(
const T & value);
238 const Node & operator[](
int i)
const {
return _nodes[i];};
239 unsigned int size()
const {
return _nodes.size() - _available_nodes.size();}
240 void verify_structure();
241 void verify_structure_linear()
const;
242 void verify_structure_recursive(
const Node * ,
const Node * ,
const Node * )
const;
243 void print_elements();
244 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
245 inline unsigned int max_depth()
const {
return _max_depth;};
247 inline unsigned int max_depth()
const {
return 0;};
249 int loc(
const Node * node)
const ;
250 Node * _find_predecessor(
const Node *);
251 Node * _find_successor(
const Node *);
252 const Node & operator[](
unsigned int i)
const {
return _nodes[i];};
253 const_circulator somewhere()
const;
254 circulator somewhere();
256 void _initialize(
const std::vector<T> & init);
257 std::vector<Node> _nodes;
258 std::vector<Node *> _available_nodes;
260 unsigned int _n_removes;
261 void _do_initial_connections(
unsigned int this_one,
unsigned int scale,
262 unsigned int left_edge,
unsigned int right_edge,
264 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
265 unsigned int _max_depth;
272 return ((parent==0) && (left==0) && (right==0));};
273 inline void nullify_treelinks() {
278 void reset_parents_link_to_me(Node * XX);
287 if (parent == NULL) {
return;}
288 if (parent->right ==
this) {parent->right = XX;}
289 else {parent->left = XX;}
291 template<
class T>
class SearchTree<T>::circulator{
295 circulator() : _node(NULL) {}
296 circulator(Node * node) : _node(node) {}
297 const T * operator->()
const {
return &(_node->value);}
298 T * operator->() {
return &(_node->value);}
299 const T & operator*()
const {
return _node->value;}
300 T & operator*() {
return _node->value;}
301 circulator & operator++() {
302 _node = _node->successor;
304 circulator operator++(
int) {
305 circulator tmp = *
this;
306 _node = _node->successor;
308 circulator & operator--() {
309 _node = _node->predecessor;
311 circulator operator--(
int) {
312 circulator tmp = *
this;
313 _node = _node->predecessor;
315 circulator next()
const {
316 return circulator(_node->successor);}
317 circulator previous()
const {
318 return circulator(_node->predecessor);}
319 bool operator!=(
const circulator & other)
const {
return other._node != _node;}
320 bool operator==(
const circulator & other)
const {
return other._node == _node;}
324 template<
class T>
class SearchTree<T>::const_circulator{
326 const_circulator() : _node(NULL) {}
327 const_circulator(
const Node * node) : _node(node) {}
328 const_circulator(
const circulator & circ) :_node(circ._node) {}
329 const T * operator->() {
return &(_node->value);}
330 const T & operator*()
const {
return _node->value;}
331 const_circulator & operator++() {
332 _node = _node->successor;
334 const_circulator operator++(
int) {
335 const_circulator tmp = *
this;
336 _node = _node->successor;
338 const_circulator & operator--() {
339 _node = _node->predecessor;
341 const_circulator operator--(
int) {
342 const_circulator tmp = *
this;
343 _node = _node->predecessor;
345 const_circulator next()
const {
346 return const_circulator(_node->successor);}
347 const_circulator previous()
const {
348 return const_circulator(_node->predecessor);}
349 bool operator!=(
const const_circulator & other)
const {
return other._node != _node;}
350 bool operator==(
const const_circulator & other)
const {
return other._node == _node;}
355 unsigned int max_size) :
357 _available_nodes.reserve(max_size);
358 _available_nodes.resize(max_size - init.size());
359 for (
unsigned int i = init.size(); i < max_size; i++) {
360 _available_nodes[i-init.size()] = &(_nodes[i]);
365 _nodes(init.size()), _available_nodes(0) {
366 _available_nodes.reserve(init.size());
371 unsigned n = init.size();
373 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
376 for (
unsigned int i = 1; i<n; i++) {
377 assert(!(init[i] < init[i-1]));
379 for(
unsigned int i = 0; i < n; i++) {
380 _nodes[i].value = init[i];
381 _nodes[i].predecessor = (& (_nodes[i])) - 1;
382 _nodes[i].successor = (& (_nodes[i])) + 1;
383 _nodes[i].nullify_treelinks();
385 _nodes[0].predecessor = (& (_nodes[n-1]));
386 _nodes[n-1].successor = (& (_nodes[0]));
387 unsigned int scale = (n+1)/2;
388 unsigned int top = std::min(n-1,scale);
389 _nodes[top].parent = NULL;
390 _top_node = &(_nodes[top]);
391 _do_initial_connections(top, scale, 0, n, 0);
393 template<
class T>
inline int SearchTree<T>::loc(
const Node * node)
const {
return node == NULL?
394 -999 : node - &(_nodes[0]);}
396 unsigned int this_one,
398 unsigned int left_edge,
399 unsigned int right_edge,
402 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
403 _max_depth = max(depth, _max_depth);
405 unsigned int ref_new_scale = (scale+1)/2;
406 unsigned new_scale = ref_new_scale;
407 bool did_child =
false;
409 int left = this_one - new_scale;
410 if (left >= static_cast<int>(left_edge)
411 && _nodes[left].treelinks_null() ) {
412 _nodes[left].parent = &(_nodes[this_one]);
413 _nodes[this_one].left = &(_nodes[left]);
414 _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
418 unsigned int old_new_scale = new_scale;
419 new_scale = (old_new_scale + 1)/2;
420 if (new_scale == old_new_scale)
break;
422 if (!did_child) {_nodes[this_one].left = NULL;}
423 new_scale = ref_new_scale;
426 unsigned int right = this_one + new_scale;
427 if (right < right_edge && _nodes[right].treelinks_null()) {
428 _nodes[right].parent = &(_nodes[this_one]);
429 _nodes[this_one].right = &(_nodes[right]);
430 _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
434 unsigned int old_new_scale = new_scale;
435 new_scale = (old_new_scale + 1)/2;
436 if (new_scale == old_new_scale)
break;
438 if (!did_child) {_nodes[this_one].right = NULL;}
441 remove(&(_nodes[node_index]));
449 node->predecessor->successor = node->successor;
450 node->successor->predecessor = node->predecessor;
451 if (node->left == NULL && node->right == NULL) {
452 node->reset_parents_link_to_me(NULL);
453 }
else if (node->left != NULL && node->right == NULL){
454 node->reset_parents_link_to_me(node->left);
455 node->left->parent = node->parent;
456 if (_top_node == node) {_top_node = node->left;}
457 }
else if (node->left == NULL && node->right != NULL){
458 node->reset_parents_link_to_me(node->right);
459 node->right->parent = node->parent;
460 if (_top_node == node) {_top_node = node->right;}
463 bool use_predecessor = (_n_removes % 2 == 1);
464 if (use_predecessor) {
465 replacement = node->predecessor;
466 assert(replacement->right == NULL);
467 if (replacement != node->left) {
468 if (replacement->left != NULL) {
469 replacement->left->parent = replacement->parent;}
470 replacement->reset_parents_link_to_me(replacement->left);
471 replacement->left = node->left;
473 replacement->parent = node->parent;
474 replacement->right = node->right;
476 replacement = node->successor;
477 assert(replacement->left == NULL);
478 if (replacement != node->right) {
479 if (replacement->right != NULL) {
480 replacement->right->parent = replacement->parent;}
481 replacement->reset_parents_link_to_me(replacement->right);
482 replacement->right = node->right;
484 replacement->parent = node->parent;
485 replacement->left = node->left;
487 node->reset_parents_link_to_me(replacement);
488 if (node->left != replacement) {node->left->parent = replacement;}
489 if (node->right != replacement) {node->right->parent = replacement;}
490 if (_top_node == node) {_top_node = replacement;}
492 node->nullify_treelinks();
493 node->predecessor = NULL;
494 node->successor = NULL;
496 _available_nodes.push_back(node);
499 assert(_available_nodes.size() > 0);
500 Node * node = _available_nodes.back();
501 _available_nodes.pop_back();
503 Node * location = _top_node;
504 Node * old_location = NULL;
506 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
507 unsigned int depth = 0;
509 while(location != NULL) {
510 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
513 old_location = location;
514 on_left = value < location->value;
515 if (on_left) {location = location->left;}
516 else {location = location->right;}
518 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
519 _max_depth = max(depth, _max_depth);
521 node->parent = old_location;
522 if (on_left) {node->parent->left = node;}
523 else {node->parent->right = node;}
526 node->predecessor = _find_predecessor(node);
527 if (node->predecessor != NULL) {
528 node->successor = node->predecessor->successor;
529 node->predecessor->successor = node;
530 node->successor->predecessor = node;
532 node->successor = _find_successor(node);
533 assert(node->successor != NULL);
534 node->predecessor = node->successor->predecessor;
535 node->successor->predecessor = node;
536 node->predecessor->successor = node;
538 return circulator(node);
541 verify_structure_linear();
542 const Node * left_limit = _top_node;
543 while (left_limit->left != NULL) {left_limit = left_limit->left;}
544 const Node * right_limit = _top_node;
545 while (right_limit->right != NULL) {right_limit = right_limit->right;}
546 verify_structure_recursive(_top_node, left_limit, right_limit);
552 assert(!(element->value < left_limit->value));
553 assert(!(right_limit->value < element->value));
554 const Node * left = element->left;
556 assert(!(element->value < left->value));
557 if (left != left_limit) {
558 verify_structure_recursive(left, left_limit, element);}
560 const Node * right = element->right;
562 assert(!(right->value < element->value));
563 if (right != right_limit) {
564 verify_structure_recursive(right, element, right_limit);}
570 for(
unsigned i = 0; i < _nodes.size(); i++) {
573 if (node->parent == NULL) {
576 assert((node->parent->left == node) ^ (node->parent->right == node));
578 if (node->left != NULL) {
579 assert(!(node->value < node->left->value ));}
580 if (node->right != NULL) {
581 assert(!(node->right->value < node->value ));}
583 assert(n_top == 1 || (n_top == 0 && size() <= 1) );
584 assert(n_null == _available_nodes.size() ||
585 (n_null == _available_nodes.size() + 1 && size() == 1));
589 if (node->left != NULL) {
590 newnode = node->left;
591 while(newnode->right != NULL) {newnode = newnode->right;}
595 newnode = node->parent;
596 while(newnode != NULL) {
597 if (newnode->right == lastnode) {
return newnode;}
599 newnode = newnode->parent;
606 if (node->right != NULL) {
607 newnode = node->right;
608 while(newnode->left != NULL) {newnode = newnode->left;}
612 newnode = node->parent;
613 while(newnode != NULL) {
614 if (newnode->left == lastnode) {
return newnode;}
616 newnode = newnode->parent;
624 int n = _nodes.size();
625 for(; node - base_node < n ; node++) {
626 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);
630 return circulator(_top_node);
633 return const_circulator(_top_node);
636 #endif // __FJCORE_SEARCHTREE_HH__
637 #ifndef __FJCORE_MINHEAP__HH__
638 #define __FJCORE_MINHEAP__HH__
643 FJCORE_BEGIN_NAMESPACE
646 MinHeap (
const std::vector<double> & values,
unsigned int max_size) :
647 _heap(max_size) {initialise(values);}
648 MinHeap (
unsigned int max_size) : _heap(max_size) {}
649 MinHeap (
const std::vector<double> & values) :
650 _heap(values.size()) {initialise(values);}
651 void initialise(
const std::vector<double> & 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);
664 std::vector<ValueLoc> _heap;
667 #endif // __FJCORE_MINHEAP__HH__
668 #ifndef __FJCORE_CLOSESTPAIR2DBASE__HH__
669 #define __FJCORE_CLOSESTPAIR2DBASE__HH__
671 FJCORE_BEGIN_NAMESPACE
676 Coord2D(
double a,
double b): x(a), y(b) {};
678 return Coord2D(x - other.x, y - other.y);};
680 return Coord2D(x + other.x, y + other.y);};
681 Coord2D operator*(
double factor)
const {
return Coord2D(factor*x,factor*y);};
683 return Coord2D(factor*coord.x,factor*coord.y);
685 Coord2D operator/(
double divisor)
const {
686 return Coord2D(x / divisor, y / divisor);};
688 double dx = a.x - b.x, dy = a.y-b.y;
691 double distance2(
const Coord2D & b)
const {
692 double dx = x - b.x, dy = y-b.y;
698 virtual void closest_pair(
unsigned int & ID1,
unsigned int & ID2,
699 double & distance2)
const = 0;
700 virtual void remove(
unsigned int ID) = 0;
701 virtual unsigned int insert(
const Coord2D & position) = 0;
702 virtual unsigned int replace(
unsigned int ID1,
unsigned int ID2,
706 unsigned new_ID = insert(position);
709 virtual void replace_many(
const std::vector<unsigned int> & IDs_to_remove,
710 const std::vector<Coord2D> & new_positions,
711 std::vector<unsigned int> & new_IDs) {
712 for(
unsigned i = 0; i < IDs_to_remove.size(); i++) {
713 remove(IDs_to_remove[i]);}
715 for(
unsigned i = 0; i < new_positions.size(); i++) {
716 new_IDs.push_back(insert(new_positions[i]));}
718 virtual unsigned int size() = 0;
722 #endif // __FJCORE_CLOSESTPAIR2DBASE__HH__
723 #ifndef __FJCORE_CLOSESTPAIR2D__HH__
724 #define __FJCORE_CLOSESTPAIR2D__HH__
728 FJCORE_BEGIN_NAMESPACE
733 _initialize(positions, left_corner, right_corner, positions.size());
737 const unsigned int max_size) {
738 _initialize(positions, left_corner, right_corner, max_size);
740 void closest_pair(
unsigned int & ID1,
unsigned int & ID2,
741 double & distance2)
const;
742 void remove(
unsigned int ID);
743 unsigned int insert(
const Coord2D &);
744 virtual unsigned int replace(
unsigned int ID1,
unsigned int ID2,
746 virtual void replace_many(
const std::vector<unsigned int> & IDs_to_remove,
747 const std::vector<Coord2D> & new_positions,
748 std::vector<unsigned int> & new_IDs);
749 inline void print_tree_depths(std::ostream & outdev)
const {
750 outdev << _trees[0]->max_depth() <<
" "
751 << _trees[1]->max_depth() <<
" "
752 << _trees[2]->max_depth() <<
"\n";
756 void _initialize(
const std::vector<Coord2D> & positions,
758 const unsigned int max_size);
759 static const unsigned int _nshift = 3;
761 template<
class T>
class triplet {
763 inline const T & operator[](
unsigned int i)
const {
return _contents[i];};
764 inline T & operator[](
unsigned int i) {
return _contents[i];};
766 T _contents[_nshift];
772 bool operator<(
const Shuffle &)
const;
773 void operator+=(
unsigned int shift) {x += shift; y+= shift;};
776 typedef Tree::circulator circulator;
777 typedef Tree::const_circulator const_circulator;
778 triplet<SharedPtr<Tree> > _trees;
780 std::vector<Point> _points;
781 std::stack<Point *> _available_points;
782 std::vector<Point *> _points_under_review;
783 static const unsigned int _remove_heap_entry = 1;
784 static const unsigned int _review_heap_entry = 2;
785 static const unsigned int _review_neighbour = 4;
786 void _add_label(Point * point,
unsigned int review_flag);
787 void _set_label(Point * point,
unsigned int review_flag);
788 void _deal_with_points_to_review();
789 void _remove_from_search_tree(Point * point_to_remove);
790 void _insert_into_search_tree(Point * new_point);
791 void _point2shuffle(Point & , Shuffle & ,
unsigned int shift);
794 int _ID(
const Point *)
const;
795 triplet<unsigned int> _shifts;
796 triplet<unsigned int> _rel_shifts;
797 unsigned int _cp_search_range;
803 double neighbour_dist2;
804 triplet<circulator> circ;
805 unsigned int review_flag;
806 double distance2(
const Point & other)
const {
807 return coord.distance2(other.coord);
810 inline bool floor_ln2_less(
unsigned x,
unsigned y) {
811 if (x>y)
return false;
814 inline int ClosestPair2D::_ID(
const Point * point)
const {
815 return point - &(_points[0]);
817 inline unsigned int ClosestPair2D::size() {
818 return _points.size() - _available_points.size();
821 #endif // __FJCORE_CLOSESTPAIR2D__HH__
822 #ifndef __FJCORE_LAZYTILING9ALT_HH__
823 #define __FJCORE_LAZYTILING9ALT_HH__
824 FJCORE_BEGIN_NAMESPACE
825 const double tile_edge_security_margin=1.0e-7;
828 double eta, phi, kt2, NN_dist;
830 int _jets_index, tile_index;
831 bool _minheap_update_needed;
832 inline void label_minheap_update_needed() {_minheap_update_needed =
true;}
833 inline void label_minheap_update_done() {_minheap_update_needed =
false;}
834 inline bool minheap_update_needed()
const {
return _minheap_update_needed;}
836 const int n_tile_neighbours = 9;
839 typedef double (
Tile::*DistToTileFn)(
const TiledJet*)
const;
840 typedef std::pair<Tile *, DistToTileFn> TileFnPair;
841 TileFnPair begin_tiles[n_tile_neighbours];
842 TileFnPair * surrounding_tiles;
843 TileFnPair * RH_tiles;
844 TileFnPair * end_tiles;
847 bool use_periodic_delta_phi;
849 double eta_min, eta_max, phi_min, phi_max;
850 double distance_to_centre(
const TiledJet *)
const {
return 0;}
851 double distance_to_left(
const TiledJet * jet)
const {
852 double deta = jet->eta - eta_min;
855 double distance_to_right(
const TiledJet * jet)
const {
856 double deta = jet->eta - eta_max;
859 double distance_to_bottom(
const TiledJet * jet)
const {
860 double dphi = jet->phi - phi_min;
863 double distance_to_top(
const TiledJet * jet)
const {
864 double dphi = jet->phi - phi_max;
867 double distance_to_left_top(
const TiledJet * jet)
const {
868 double deta = jet->eta - eta_min;
869 double dphi = jet->phi - phi_max;
870 return deta*deta + dphi*dphi;
872 double distance_to_left_bottom(
const TiledJet * jet)
const {
873 double deta = jet->eta - eta_min;
874 double dphi = jet->phi - phi_min;
875 return deta*deta + dphi*dphi;
877 double distance_to_right_top(
const TiledJet * jet)
const {
878 double deta = jet->eta - eta_max;
879 double dphi = jet->phi - phi_max;
880 return deta*deta + dphi*dphi;
882 double distance_to_right_bottom(
const TiledJet * jet)
const {
883 double deta = jet->eta - eta_max;
884 double dphi = jet->phi - phi_min;
885 return deta*deta + dphi*dphi;
894 const std::vector<PseudoJet> & _jets;
895 std::vector<Tile> _tiles;
896 double _Rparam, _R2, _invR2;
897 double _tiles_eta_min, _tiles_eta_max;
898 double _tile_size_eta, _tile_size_phi;
899 double _tile_half_size_eta, _tile_half_size_phi;
900 int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
901 std::vector<TiledJet *> _jets_for_minheap;
902 void _initialise_tiles();
903 inline int _tile_index (
int ieta,
int iphi)
const {
904 return (ieta-_tiles_ieta_min)*_n_tiles_phi
905 + (iphi+_n_tiles_phi) % _n_tiles_phi;
907 void _bj_remove_from_tiles(
TiledJet *
const jet);
908 int _tile_index(
const double eta,
const double phi)
const;
909 void _tj_set_jetinfo(
TiledJet *
const jet,
const int _jets_index);
910 void _print_tiles(
TiledJet * briefjets )
const;
911 void _add_neighbours_to_tile_union(
const int tile_index,
912 std::vector<int> & tile_union,
int & n_near_tiles)
const;
913 void _add_untagged_neighbours_to_tile_union(
const int tile_index,
914 std::vector<int> & tile_union,
int & n_near_tiles);
915 void _add_untagged_neighbours_to_tile_union_using_max_info(
const TiledJet *
const jet,
916 std::vector<int> & tile_union,
int & n_near_tiles);
917 void _update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
918 void _set_NN(
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
919 template <
class J>
double _bj_diJ(
const J *
const jet)
const {
920 double kt2 = jet->kt2;
921 if (jet->NN != NULL) {
if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
922 return jet->NN_dist * kt2;
924 template <
class J>
inline void _bj_set_jetinfo(
925 J *
const jetA,
const int _jets_index)
const {
926 jetA->eta = _jets[_jets_index].rap();
927 jetA->phi = _jets[_jets_index].phi_02pi();
928 jetA->kt2 = _cs.jet_scale_for_algorithm(_jets[_jets_index]);
929 jetA->_jets_index = _jets_index;
933 template <
class J>
inline double _bj_dist(
934 const J *
const jetA,
const J *
const jetB)
const {
935 double dphi = std::abs(jetA->phi - jetB->phi);
936 double deta = (jetA->eta - jetB->eta);
937 if (dphi > pi) {dphi = twopi - dphi;}
938 return dphi*dphi + deta*deta;
940 template <
class J>
inline double _bj_dist_not_periodic(
941 const J *
const jetA,
const J *
const jetB)
const {
942 double dphi = jetA->phi - jetB->phi;
943 double deta = (jetA->eta - jetB->eta);
944 return dphi*dphi + deta*deta;
948 #endif // __FJCORE_LAZYTILING9ALT_HH__
949 #ifndef __FJCORE_LAZYTILING9_HH__
950 #define __FJCORE_LAZYTILING9_HH__
951 FJCORE_BEGIN_NAMESPACE
961 bool use_periodic_delta_phi;
963 double eta_centre, phi_centre;
964 int jet_count()
const {
981 const std::vector<PseudoJet> & _jets;
982 std::vector<Tile2> _tiles;
986 #endif // INSTRUMENT2
987 double _Rparam, _R2, _invR2;
988 double _tiles_eta_min, _tiles_eta_max;
989 double _tile_size_eta, _tile_size_phi;
990 double _tile_half_size_eta, _tile_half_size_phi;
991 int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
992 std::vector<TiledJet *> _jets_for_minheap;
993 void _initialise_tiles();
994 inline int _tile_index (
int ieta,
int iphi)
const {
995 return (ieta-_tiles_ieta_min)*_n_tiles_phi
996 + (iphi+_n_tiles_phi) % _n_tiles_phi;
998 void _bj_remove_from_tiles(
TiledJet *
const jet);
999 int _tile_index(
const double eta,
const double phi)
const;
1000 void _tj_set_jetinfo(
TiledJet *
const jet,
const int _jets_index);
1001 void _print_tiles(
TiledJet * briefjets )
const;
1002 void _add_neighbours_to_tile_union(
const int tile_index,
1003 std::vector<int> & tile_union,
int & n_near_tiles)
const;
1004 void _add_untagged_neighbours_to_tile_union(
const int tile_index,
1005 std::vector<int> & tile_union,
int & n_near_tiles);
1006 void _add_untagged_neighbours_to_tile_union_using_max_info(
const TiledJet *
const jet,
1007 std::vector<int> & tile_union,
int & n_near_tiles);
1008 double _distance_to_tile(
const TiledJet * bj,
const Tile2 *)
1014 void _update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
1015 void _set_NN(
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
1016 template <
class J>
double _bj_diJ(
const J *
const jet)
const {
1017 double kt2 = jet->kt2;
1018 if (jet->NN != NULL) {
if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
1019 return jet->NN_dist * kt2;
1021 template <
class J>
inline void _bj_set_jetinfo(
1022 J *
const jetA,
const int _jets_index)
const {
1023 jetA->eta = _jets[_jets_index].rap();
1024 jetA->phi = _jets[_jets_index].phi_02pi();
1025 jetA->kt2 = _cs.jet_scale_for_algorithm(_jets[_jets_index]);
1026 jetA->_jets_index = _jets_index;
1027 jetA->NN_dist = _R2;
1030 template <
class J>
inline double _bj_dist(
1031 const J *
const jetA,
const J *
const jetB)
1038 double dphi = std::abs(jetA->phi - jetB->phi);
1039 double deta = (jetA->eta - jetB->eta);
1040 if (dphi > pi) {dphi = twopi - dphi;}
1041 return dphi*dphi + deta*deta;
1043 template <
class J>
inline double _bj_dist_not_periodic(
1044 const J *
const jetA,
const J *
const jetB)
1051 double dphi = jetA->phi - jetB->phi;
1052 double deta = (jetA->eta - jetB->eta);
1053 return dphi*dphi + deta*deta;
1056 FJCORE_END_NAMESPACE
1057 #endif // __FJCORE_LAZYTILING9_HH__
1058 #ifndef __FJCORE_LAZYTILING25_HH__
1059 #define __FJCORE_LAZYTILING25_HH__
1060 FJCORE_BEGIN_NAMESPACE
1068 const std::vector<PseudoJet> & _jets;
1069 std::vector<Tile25> _tiles;
1073 #endif // INSTRUMENT2
1074 double _Rparam, _R2, _invR2;
1075 double _tiles_eta_min, _tiles_eta_max;
1076 double _tile_size_eta, _tile_size_phi;
1077 double _tile_half_size_eta, _tile_half_size_phi;
1078 int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
1079 std::vector<TiledJet *> _jets_for_minheap;
1080 void _initialise_tiles();
1081 inline int _tile_index (
int ieta,
int iphi)
const {
1082 return (ieta-_tiles_ieta_min)*_n_tiles_phi
1083 + (iphi+_n_tiles_phi) % _n_tiles_phi;
1085 void _bj_remove_from_tiles(
TiledJet *
const jet);
1086 int _tile_index(
const double eta,
const double phi)
const;
1087 void _tj_set_jetinfo(
TiledJet *
const jet,
const int _jets_index);
1088 void _print_tiles(
TiledJet * briefjets )
const;
1089 void _add_neighbours_to_tile_union(
const int tile_index,
1090 std::vector<int> & tile_union,
int & n_near_tiles)
const;
1091 void _add_untagged_neighbours_to_tile_union(
const int tile_index,
1092 std::vector<int> & tile_union,
int & n_near_tiles);
1093 void _add_untagged_neighbours_to_tile_union_using_max_info(
const TiledJet *
const jet,
1094 std::vector<int> & tile_union,
int & n_near_tiles);
1095 double _distance_to_tile(
const TiledJet * bj,
const Tile25 *)
1101 void _update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
1102 void _set_NN(
TiledJet * jetI, std::vector<TiledJet *> & jets_for_minheap);
1103 template <
class J>
double _bj_diJ(
const J *
const jet)
const {
1104 double kt2 = jet->kt2;
1105 if (jet->NN != NULL) {
if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
1106 return jet->NN_dist * kt2;
1108 template <
class J>
inline void _bj_set_jetinfo(
1109 J *
const jetA,
const int _jets_index)
const {
1110 jetA->eta = _jets[_jets_index].rap();
1111 jetA->phi = _jets[_jets_index].phi_02pi();
1112 jetA->kt2 = _cs.jet_scale_for_algorithm(_jets[_jets_index]);
1113 jetA->_jets_index = _jets_index;
1114 jetA->NN_dist = _R2;
1117 template <
class J>
inline double _bj_dist(
1118 const J *
const jetA,
const J *
const jetB)
1125 double dphi = std::abs(jetA->phi - jetB->phi);
1126 double deta = (jetA->eta - jetB->eta);
1127 if (dphi > pi) {dphi = twopi - dphi;}
1128 return dphi*dphi + deta*deta;
1130 template <
class J>
inline double _bj_dist_not_periodic(
1131 const J *
const jetA,
const J *
const jetB)
1138 double dphi = jetA->phi - jetB->phi;
1139 double deta = (jetA->eta - jetB->eta);
1140 return dphi*dphi + deta*deta;
1143 FJCORE_END_NAMESPACE
1144 #endif // __FJCORE_LAZYTILING25_HH__
1145 #ifndef __FJCORE_TILINGEXTENT_HH__
1146 #define __FJCORE_TILINGEXTENT_HH__
1147 FJCORE_BEGIN_NAMESPACE
1152 double minrap()
const {
return _minrap;}
1153 double maxrap()
const {
return _maxrap;}
1154 double sum_of_binned_squared_multiplicity()
const {
return _cumul2;}
1156 double _minrap, _maxrap, _cumul2;
1157 void _determine_rapidity_extent(
const std::vector<PseudoJet> & particles);
1159 FJCORE_END_NAMESPACE
1160 #endif // __FJCORE_TILINGEXTENT_HH__
1165 FJCORE_BEGIN_NAMESPACE
1166 const unsigned int twopow31 = 2147483648U;
1167 using namespace std;
1168 void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle,
1169 unsigned int shift) {
1170 Coord2D renorm_point = (point.coord - _left_corner)/_range;
1171 assert(renorm_point.x >=0);
1172 assert(renorm_point.x <=1);
1173 assert(renorm_point.y >=0);
1174 assert(renorm_point.y <=1);
1175 shuffle.x =
static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
1176 shuffle.y =
static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
1177 shuffle.point = &point;
1179 bool ClosestPair2D::Shuffle::operator<(
const Shuffle & q)
const {
1180 if (floor_ln2_less(x ^ q.x, y ^ q.y)) {
1186 void ClosestPair2D::_initialize(
const std::vector<Coord2D> & positions,
1189 unsigned int max_size) {
1190 unsigned int n_positions = positions.size();
1191 assert(max_size >= n_positions);
1192 _points.resize(max_size);
1193 for (
unsigned int i = n_positions; i < max_size; i++) {
1194 _available_points.push(&(_points[i]));
1196 _left_corner = left_corner;
1197 _range = max((right_corner.x - left_corner.x),
1198 (right_corner.y - left_corner.y));
1199 vector<Shuffle> shuffles(n_positions);
1200 for (
unsigned int i = 0; i < n_positions; i++) {
1201 _points[i].coord = positions[i];
1202 _points[i].neighbour_dist2 = numeric_limits<double>::max();
1203 _points[i].review_flag = 0;
1204 _point2shuffle(_points[i], shuffles[i], 0);
1206 for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
1207 _shifts[ishift] =
static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
1208 if (ishift == 0) {_rel_shifts[ishift] = 0;}
1209 else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
1211 _cp_search_range = 30;
1212 _points_under_review.reserve(_nshift * _cp_search_range);
1213 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
1215 unsigned rel_shift = _rel_shifts[ishift];
1216 for (
unsigned int i = 0; i < shuffles.size(); i++) {
1217 shuffles[i] += rel_shift; }
1219 sort(shuffles.begin(), shuffles.end());
1221 circulator circ = _trees[ishift]->somewhere(), start=circ;
1222 unsigned int CP_range = min(_cp_search_range, n_positions-1);
1224 Point * this_point = circ->point;
1225 this_point->circ[ishift] = circ;
1226 circulator other = circ;
1227 for (
unsigned i=0; i < CP_range; i++) {
1229 double dist2 = this_point->distance2(*other->point);
1230 if (dist2 < this_point->neighbour_dist2) {
1231 this_point->neighbour_dist2 = dist2;
1232 this_point->neighbour = other->point;
1235 }
while (++circ != start);
1237 vector<double> mindists2(n_positions);
1238 for (
unsigned int i = 0; i < n_positions; i++) {
1239 mindists2[i] = _points[i].neighbour_dist2;}
1242 void ClosestPair2D::closest_pair(
unsigned int & ID1,
unsigned int & ID2,
1243 double & distance2)
const {
1244 ID1 = _heap->minloc();
1245 ID2 = _ID(_points[ID1].neighbour);
1246 distance2 = _points[ID1].neighbour_dist2;
1247 if (ID1 > ID2) std::swap(ID1,ID2);
1249 inline void ClosestPair2D::_add_label(Point * point,
unsigned int review_flag) {
1250 if (point->review_flag == 0) _points_under_review.push_back(point);
1251 point->review_flag |= review_flag;
1253 inline void ClosestPair2D::_set_label(Point * point,
unsigned int review_flag) {
1254 if (point->review_flag == 0) _points_under_review.push_back(point);
1255 point->review_flag = review_flag;
1257 void ClosestPair2D::remove(
unsigned int ID) {
1258 Point * point_to_remove = & (_points[ID]);
1259 _remove_from_search_tree(point_to_remove);
1260 _deal_with_points_to_review();
1262 void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
1263 _available_points.push(point_to_remove);
1264 _set_label(point_to_remove, _remove_heap_entry);
1265 unsigned int CP_range = min(_cp_search_range, size()-1);
1266 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
1267 circulator removed_circ = point_to_remove->circ[ishift];
1268 circulator right_end = removed_circ.next();
1269 _trees[ishift]->remove(removed_circ);
1270 circulator left_end = right_end, orig_right_end = right_end;
1271 for (
unsigned int i = 0; i < CP_range; i++) {left_end--;}
1272 if (size()-1 < _cp_search_range) {
1273 left_end--; right_end--;
1276 Point * left_point = left_end->point;
1277 if (left_point->neighbour == point_to_remove) {
1279 _add_label(left_point, _review_neighbour);
1282 double dist2 = left_point->distance2(*right_end->point);
1283 if (dist2 < left_point->neighbour_dist2) {
1284 left_point->neighbour = right_end->point;
1285 left_point->neighbour_dist2 = dist2;
1287 _add_label(left_point, _review_heap_entry);
1291 }
while (++left_end != orig_right_end);
1294 void ClosestPair2D::_deal_with_points_to_review() {
1295 unsigned int CP_range = min(_cp_search_range, size()-1);
1296 while(_points_under_review.size() > 0) {
1297 Point * this_point = _points_under_review.back();
1298 _points_under_review.pop_back();
1299 if (this_point->review_flag & _remove_heap_entry) {
1300 assert(!(this_point->review_flag ^ _remove_heap_entry));
1301 _heap->remove(_ID(this_point));
1304 if (this_point->review_flag & _review_neighbour) {
1305 this_point->neighbour_dist2 = numeric_limits<double>::max();
1307 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
1308 circulator other = this_point->circ[ishift];
1310 for (
unsigned i=0; i < CP_range; i++) {
1312 double dist2 = this_point->distance2(*other->point);
1313 if (dist2 < this_point->neighbour_dist2) {
1314 this_point->neighbour_dist2 = dist2;
1315 this_point->neighbour = other->point;
1320 _heap->update(_ID(this_point), this_point->neighbour_dist2);
1322 this_point->review_flag = 0;
1325 unsigned int ClosestPair2D::insert(
const Coord2D & new_coord) {
1326 assert(_available_points.size() > 0);
1327 Point * new_point = _available_points.top();
1328 _available_points.pop();
1329 new_point->coord = new_coord;
1330 _insert_into_search_tree(new_point);
1331 _deal_with_points_to_review();
1332 return _ID(new_point);
1334 unsigned int ClosestPair2D::replace(
unsigned int ID1,
unsigned int ID2,
1336 Point * point_to_remove = & (_points[ID1]);
1337 _remove_from_search_tree(point_to_remove);
1338 point_to_remove = & (_points[ID2]);
1339 _remove_from_search_tree(point_to_remove);
1340 Point * new_point = _available_points.top();
1341 _available_points.pop();
1342 new_point->coord = position;
1343 _insert_into_search_tree(new_point);
1344 _deal_with_points_to_review();
1345 return _ID(new_point);
1347 void ClosestPair2D::replace_many(
1348 const std::vector<unsigned int> & IDs_to_remove,
1349 const std::vector<Coord2D> & new_positions,
1350 std::vector<unsigned int> & new_IDs) {
1351 for (
unsigned int i = 0; i < IDs_to_remove.size(); i++) {
1352 _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
1355 for (
unsigned int i = 0; i < new_positions.size(); i++) {
1356 Point * new_point = _available_points.top();
1357 _available_points.pop();
1358 new_point->coord = new_positions[i];
1359 _insert_into_search_tree(new_point);
1360 new_IDs.push_back(_ID(new_point));
1362 _deal_with_points_to_review();
1364 void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
1365 _set_label(new_point, _review_heap_entry);
1366 new_point->neighbour_dist2 = numeric_limits<double>::max();
1367 unsigned int CP_range = min(_cp_search_range, size()-1);
1368 for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
1369 Shuffle new_shuffle;
1370 _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
1371 circulator new_circ = _trees[ishift]->insert(new_shuffle);
1372 new_point->circ[ishift] = new_circ;
1373 circulator right_edge = new_circ; right_edge++;
1374 circulator left_edge = new_circ;
1375 for (
unsigned int i = 0; i < CP_range; i++) {left_edge--;}
1377 Point * left_point = left_edge->point;
1378 Point * right_point = right_edge->point;
1379 double new_dist2 = left_point->distance2(*new_point);
1380 if (new_dist2 < left_point->neighbour_dist2) {
1381 left_point->neighbour_dist2 = new_dist2;
1382 left_point->neighbour = new_point;
1383 _add_label(left_point, _review_heap_entry);
1385 new_dist2 = new_point->distance2(*right_point);
1386 if (new_dist2 < new_point->neighbour_dist2) {
1387 new_point->neighbour_dist2 = new_dist2;
1388 new_point->neighbour = right_point;
1390 if (left_point->neighbour == right_point) {
1391 _add_label(left_point, _review_neighbour);
1394 }
while (++left_edge != new_circ);
1397 FJCORE_END_NAMESPACE
1406 FJCORE_BEGIN_NAMESPACE
1407 using namespace std;
1408 std::ostream * ClusterSequence::_fastjet_banner_ostr = &cout;
1409 ClusterSequence::~ClusterSequence () {
1410 if (_structure_shared_ptr){
1412 assert(csi != NULL);
1413 csi->set_associated_cs(NULL);
1414 if (_deletes_self_when_unused) {
1415 _structure_shared_ptr.set_count(_structure_shared_ptr.use_count()
1416 + _structure_use_count_after_construction);
1420 void ClusterSequence::signal_imminent_self_deletion()
const {
1421 assert(_deletes_self_when_unused);
1422 _deletes_self_when_unused =
false;
1424 void ClusterSequence::_initialise_and_run (
1426 const bool & writeout_combinations) {
1427 _decant_options(jet_def_in, writeout_combinations);
1428 _initialise_and_run_no_decant();
1430 void ClusterSequence::_initialise_and_run_no_decant () {
1431 _fill_initial_history();
1432 if (n_particles() == 0)
return;
1433 if (_jet_algorithm == plugin_algorithm) {
1434 _plugin_activated =
true;
1435 _jet_def.plugin()->run_clustering( (*
this) );
1436 _plugin_activated =
false;
1437 _update_structure_use_count();
1439 }
else if (_jet_algorithm == ee_kt_algorithm ||
1440 _jet_algorithm == ee_genkt_algorithm) {
1441 _strategy = N2Plain;
1442 if (_jet_algorithm == ee_kt_algorithm) {
1443 assert(_Rparam > 2.0);
1450 _R2 = 2 * ( 3.0 + cos(_Rparam) );
1452 _R2 = 2 * ( 1.0 - cos(_Rparam) );
1456 _simple_N2_cluster_EEBriefJet();
1458 }
else if (_jet_algorithm == undefined_jet_algorithm) {
1459 throw Error(
"A ClusterSequence cannot be created with an uninitialised JetDefinition");
1461 if (_strategy == Best) {
1462 _strategy = _best_strategy();
1463 #ifdef __FJCORE_DROP_CGAL
1464 if (_strategy == NlnN) _strategy = N2MHTLazy25;
1465 #endif // __FJCORE_DROP_CGAL
1466 }
else if (_strategy == BestFJ30) {
1467 int N = _jets.size();
1468 if (min(1.0,max(0.1,_Rparam)*3.3)*N <= 30) {
1469 _strategy = N2Plain;
1470 }
else if (N > 6200/pow(_Rparam,2.0) && _jet_def.jet_algorithm() == cambridge_algorithm) {
1471 _strategy = NlnNCam;
1472 #ifndef __FJCORE_DROP_CGAL
1473 }
else if ((N > 16000/pow(_Rparam,1.15) && _jet_def.jet_algorithm() != antikt_algorithm)
1474 || N > 35000/pow(_Rparam,1.15)) {
1476 #endif // __FJCORE_DROP_CGAL
1477 }
else if (N <= 450) {
1478 _strategy = N2Tiled;
1480 _strategy = N2MinHeapTiled;
1483 if (_Rparam >= twopi) {
1484 if ( _strategy == NlnN
1485 || _strategy == NlnN3pi
1486 || _strategy == NlnNCam
1487 || _strategy == NlnNCam2pi2R
1488 || _strategy == NlnNCam4pi) {
1489 #ifdef __FJCORE_DROP_CGAL
1490 _strategy = N2MinHeapTiled;
1492 _strategy = NlnN4pi;
1495 if (_jet_def.strategy() != Best && _strategy != _jet_def.strategy()) {
1497 oss <<
"Cluster strategy " << strategy_string(_jet_def.strategy())
1498 <<
" automatically changed to " << strategy_string()
1499 <<
" because the former is not supported for R = " << _Rparam
1501 _changed_strategy_warning.warn(oss.str());
1504 if (_strategy == N2Plain) {
1505 this->_simple_N2_cluster_BriefJet();
1506 }
else if (_strategy == N2Tiled) {
1507 this->_faster_tiled_N2_cluster();
1508 }
else if (_strategy == N2MinHeapTiled) {
1509 this->_minheap_faster_tiled_N2_cluster();
1510 }
else if (_strategy == N2MHTLazy9Alt) {
1511 _plugin_activated =
true;
1514 _plugin_activated =
false;
1515 }
else if (_strategy == N2MHTLazy25) {
1516 _plugin_activated =
true;
1519 _plugin_activated =
false;
1520 }
else if (_strategy == N2MHTLazy9) {
1521 _plugin_activated =
true;
1524 _plugin_activated =
false;
1525 }
else if (_strategy == N2MHTLazy9AntiKtSeparateGhosts) {
1526 throw Error(
"N2MHTLazy9AntiKtSeparateGhosts strategy not supported with FJCORE");
1527 }
else if (_strategy == NlnN) {
1528 this->_delaunay_cluster();
1529 }
else if (_strategy == NlnNCam) {
1530 this->_CP2DChan_cluster_2piMultD();
1531 }
else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
1532 this->_delaunay_cluster();
1533 }
else if (_strategy == N3Dumb ) {
1534 this->_really_dumb_cluster();
1535 }
else if (_strategy == N2PoorTiled) {
1536 this->_tiled_N2_cluster();
1537 }
else if (_strategy == NlnNCam4pi) {
1538 this->_CP2DChan_cluster();
1539 }
else if (_strategy == NlnNCam2pi2R) {
1540 this->_CP2DChan_cluster_2pi2R();
1543 err <<
"Unrecognised value for strategy: "<<_strategy;
1544 throw Error(err.str());
1547 bool ClusterSequence::_first_time =
true;
1549 string fastjet_version_string() {
1550 return "FastJet version "+string(fastjet_version)+
" [fjcore]";
1552 void ClusterSequence::print_banner() {
1553 if (!_first_time) {
return;}
1554 _first_time =
false;
1555 ostream * ostr = _fastjet_banner_ostr;
1557 (*ostr) <<
"#--------------------------------------------------------------------------\n";
1558 (*ostr) <<
"# FastJet release " << fastjet_version <<
" [fjcore]" << endl;
1559 (*ostr) <<
"# M. Cacciari, G.P. Salam and G. Soyez \n";
1560 (*ostr) <<
"# A software package for jet finding and analysis at colliders \n";
1561 (*ostr) <<
"# http://fastjet.fr \n";
1563 (*ostr) <<
"# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package\n";
1564 (*ostr) <<
"# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210]. \n";
1566 (*ostr) <<
"# FastJet is provided without warranty under the terms of the GNU GPLv2.\n";
1567 (*ostr) <<
"# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code";
1568 #ifndef __FJCORE_DROP_CGAL
1569 (*ostr) <<
",\n# CGAL ";
1572 #endif // __FJCORE_DROP_CGAL
1573 (*ostr) <<
"and 3rd party plugin jet algorithms. See COPYING file for details.\n";
1574 (*ostr) <<
"#--------------------------------------------------------------------------\n";
1577 void ClusterSequence::_decant_options(
const JetDefinition & jet_def_in,
1578 const bool & writeout_combinations) {
1579 _jet_def = jet_def_in;
1580 _writeout_combinations = writeout_combinations;
1582 _decant_options_partial();
1584 void ClusterSequence::_decant_options_partial() {
1586 _jet_algorithm = _jet_def.jet_algorithm();
1587 _Rparam = _jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
1588 _strategy = _jet_def.strategy();
1589 _plugin_activated =
false;
1590 _update_structure_use_count();
1592 void ClusterSequence::_fill_initial_history () {
1593 _jets.reserve(_jets.size()*2);
1594 _history.reserve(_jets.size()*2);
1596 for (
int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
1597 history_element element;
1598 element.parent1 = InexistentParent;
1599 element.parent2 = InexistentParent;
1600 element.child = Invalid;
1601 element.jetp_index = i;
1603 element.max_dij_so_far = 0.0;
1604 _history.push_back(element);
1605 _jet_def.recombiner()->preprocess(_jets[i]);
1606 _jets[i].set_cluster_hist_index(i);
1607 _set_structure_shared_ptr(_jets[i]);
1608 _Qtot += _jets[i].E();
1610 _initial_n = _jets.size();
1611 _deletes_self_when_unused =
false;
1613 string ClusterSequence::strategy_string (Strategy strategy_in)
const {
1615 switch(strategy_in) {
1617 strategy =
"NlnN";
break;
1619 strategy =
"NlnN3pi";
break;
1621 strategy =
"NlnN4pi";
break;
1623 strategy =
"N2Plain";
break;
1625 strategy =
"N2Tiled";
break;
1626 case N2MinHeapTiled:
1627 strategy =
"N2MinHeapTiled";
break;
1629 strategy =
"N2PoorTiled";
break;
1631 strategy =
"N2MHTLazy9";
break;
1633 strategy =
"N2MHTLazy9Alt";
break;
1635 strategy =
"N2MHTLazy25";
break;
1636 case N2MHTLazy9AntiKtSeparateGhosts:
1637 strategy =
"N2MHTLazy9AntiKtSeparateGhosts";
break;
1639 strategy =
"N3Dumb";
break;
1641 strategy =
"NlnNCam4pi";
break;
1643 strategy =
"NlnNCam2pi2R";
break;
1645 strategy =
"NlnNCam";
break;
1646 case plugin_strategy:
1647 strategy =
"plugin strategy";
break;
1649 strategy =
"Unrecognized";
1653 double ClusterSequence::jet_scale_for_algorithm(
1655 if (_jet_algorithm == kt_algorithm) {
return jet.kt2();}
1656 else if (_jet_algorithm == cambridge_algorithm) {
return 1.0;}
1657 else if (_jet_algorithm == antikt_algorithm) {
1658 double kt2=jet.kt2();
1659 return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
1660 }
else if (_jet_algorithm == genkt_algorithm) {
1661 double kt2 = jet.kt2();
1662 double p = jet_def().extra_param();
1663 if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300;
1665 }
else if (_jet_algorithm == cambridge_for_passive_algorithm) {
1666 double kt2 = jet.kt2();
1667 double lim = _jet_def.extra_param();
1668 if (kt2 < lim*lim && kt2 != 0.0) {
1670 }
else {
return 1.0;}
1671 }
else {
throw Error(
"Unrecognised jet algorithm");}
1673 Strategy ClusterSequence::_best_strategy()
const {
1674 int N = _jets.size();
1675 double bounded_R = max(_Rparam, 0.1);
1676 if (N <= 30 || N <= 39.0/(bounded_R + 0.6)) {
1679 const static _Parabola N_Tiled_to_MHT_lowR (-45.4947,54.3528,44.6283);
1680 const static _Parabola L_MHT_to_MHTLazy9_lowR (0.677807,-1.05006,10.6994);
1681 const static _Parabola L_MHTLazy9_to_MHTLazy25_akt_lowR(0.169967,-0.512589,12.1572);
1682 const static _Parabola L_MHTLazy9_to_MHTLazy25_kt_lowR (0.16237,-0.484612,12.3373);
1683 const static _Parabola L_MHTLazy9_to_MHTLazy25_cam_lowR = L_MHTLazy9_to_MHTLazy25_kt_lowR;
1684 const static _Parabola L_MHTLazy25_to_NlnN_akt_lowR (0.0472051,-0.22043,15.9196);
1685 const static _Parabola L_MHTLazy25_to_NlnN_kt_lowR (0.118609,-0.326811,14.8287);
1686 const static _Parabola L_MHTLazy25_to_NlnN_cam_lowR (0.10119,-0.295748,14.3924);
1687 const static _Line L_Tiled_to_MHTLazy9_medR (-1.31304,7.29621);
1688 const static _Parabola L_MHTLazy9_to_MHTLazy25_akt_medR = L_MHTLazy9_to_MHTLazy25_akt_lowR;
1689 const static _Parabola L_MHTLazy9_to_MHTLazy25_kt_medR = L_MHTLazy9_to_MHTLazy25_kt_lowR;
1690 const static _Parabola L_MHTLazy9_to_MHTLazy25_cam_medR = L_MHTLazy9_to_MHTLazy25_cam_lowR;
1691 const static _Parabola L_MHTLazy25_to_NlnN_akt_medR = L_MHTLazy25_to_NlnN_akt_lowR;
1692 const static _Parabola L_MHTLazy25_to_NlnN_kt_medR = L_MHTLazy25_to_NlnN_kt_lowR;
1693 const static _Parabola L_MHTLazy25_to_NlnN_cam_medR = L_MHTLazy25_to_NlnN_cam_lowR;
1694 const static double N_Plain_to_MHTLazy9_largeR = 75;
1695 const static double N_MHTLazy9_to_MHTLazy25_akt_largeR = 700;
1696 const static double N_MHTLazy9_to_MHTLazy25_kt_largeR = 1000;
1697 const static double N_MHTLazy9_to_MHTLazy25_cam_largeR = 1000;
1698 const static double N_MHTLazy25_to_NlnN_akt_largeR = 100000;
1699 const static double N_MHTLazy25_to_NlnN_kt_largeR = 40000;
1700 const static double N_MHTLazy25_to_NlnN_cam_largeR = 15000;
1701 JetAlgorithm jet_algorithm;
1702 if (_jet_algorithm == genkt_algorithm) {
1703 double p = jet_def().extra_param();
1704 if (p < 0.0) jet_algorithm = antikt_algorithm;
1705 else jet_algorithm = kt_algorithm;
1706 }
else if (_jet_algorithm == cambridge_for_passive_algorithm) {
1707 jet_algorithm = kt_algorithm;
1709 jet_algorithm = _jet_algorithm;
1711 if (bounded_R < 0.65) {
1712 if (N < N_Tiled_to_MHT_lowR(bounded_R))
return N2Tiled;
1713 double logN = log(
double(N));
1714 if (logN < L_MHT_to_MHTLazy9_lowR(bounded_R))
return N2MinHeapTiled;
1716 if (jet_algorithm == antikt_algorithm){
1717 if (logN < L_MHTLazy9_to_MHTLazy25_akt_lowR(bounded_R))
return N2MHTLazy9;
1718 else if (logN < L_MHTLazy25_to_NlnN_akt_lowR(bounded_R))
return N2MHTLazy25;
1720 }
else if (jet_algorithm == kt_algorithm){
1721 if (logN < L_MHTLazy9_to_MHTLazy25_kt_lowR(bounded_R))
return N2MHTLazy9;
1722 else if (logN < L_MHTLazy25_to_NlnN_kt_lowR(bounded_R))
return N2MHTLazy25;
1724 }
else if (jet_algorithm == cambridge_algorithm) {
1725 if (logN < L_MHTLazy9_to_MHTLazy25_cam_lowR(bounded_R))
return N2MHTLazy9;
1726 else if (logN < L_MHTLazy25_to_NlnN_cam_lowR(bounded_R))
return N2MHTLazy25;
1727 else return NlnNCam;
1730 }
else if (bounded_R < 0.5*pi) {
1731 double logN = log(
double(N));
1732 if (logN < L_Tiled_to_MHTLazy9_medR(bounded_R))
return N2Tiled;
1734 if (jet_algorithm == antikt_algorithm){
1735 if (logN < L_MHTLazy9_to_MHTLazy25_akt_medR(bounded_R))
return N2MHTLazy9;
1736 else if (logN < L_MHTLazy25_to_NlnN_akt_medR(bounded_R))
return N2MHTLazy25;
1738 }
else if (jet_algorithm == kt_algorithm){
1739 if (logN < L_MHTLazy9_to_MHTLazy25_kt_medR(bounded_R))
return N2MHTLazy9;
1740 else if (logN < L_MHTLazy25_to_NlnN_kt_medR(bounded_R))
return N2MHTLazy25;
1742 }
else if (jet_algorithm == cambridge_algorithm) {
1743 if (logN < L_MHTLazy9_to_MHTLazy25_cam_medR(bounded_R))
return N2MHTLazy9;
1744 else if (logN < L_MHTLazy25_to_NlnN_cam_medR(bounded_R))
return N2MHTLazy25;
1745 else return NlnNCam;
1749 if (N < N_Plain_to_MHTLazy9_largeR)
return N2Plain;
1751 if (jet_algorithm == antikt_algorithm){
1752 if (N < N_MHTLazy9_to_MHTLazy25_akt_largeR)
return N2MHTLazy9;
1753 else if (N < N_MHTLazy25_to_NlnN_akt_largeR)
return N2MHTLazy25;
1755 }
else if (jet_algorithm == kt_algorithm){
1756 if (N < N_MHTLazy9_to_MHTLazy25_kt_largeR)
return N2MHTLazy9;
1757 else if (N < N_MHTLazy25_to_NlnN_kt_largeR)
return N2MHTLazy25;
1759 }
else if (jet_algorithm == cambridge_algorithm) {
1760 if (N < N_MHTLazy9_to_MHTLazy25_cam_largeR)
return N2MHTLazy9;
1761 else if (N < N_MHTLazy25_to_NlnN_cam_largeR)
return N2MHTLazy25;
1762 else return NlnNCam;
1766 assert(0 &&
"Code should never reach here");
1771 _deletes_self_when_unused =
false;
1772 transfer_from_sequence(cs);
1776 void ClusterSequence::transfer_from_sequence(
const ClusterSequence & from_seq,
1778 if (will_delete_self_when_unused())
1779 throw(
Error(
"cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
1780 _jet_def = from_seq._jet_def ;
1781 _writeout_combinations = from_seq._writeout_combinations ;
1782 _initial_n = from_seq._initial_n ;
1783 _Rparam = from_seq._Rparam ;
1784 _R2 = from_seq._R2 ;
1785 _invR2 = from_seq._invR2 ;
1786 _strategy = from_seq._strategy ;
1787 _jet_algorithm = from_seq._jet_algorithm ;
1788 _plugin_activated = from_seq._plugin_activated ;
1790 _jets = (*action_on_jets)(from_seq._jets);
1792 _jets = from_seq._jets;
1793 _history = from_seq._history;
1794 _extras = from_seq._extras;
1795 if (_structure_shared_ptr) {
1796 if (_deletes_self_when_unused)
throw Error(
"transfer_from_sequence cannot be used for a cluster sequence that deletes self when unused");
1798 assert(csi != NULL);
1799 csi->set_associated_cs(NULL);
1802 _update_structure_use_count();
1803 for (
unsigned int i=0; i<_jets.size(); i++){
1804 _jets[i].set_cluster_hist_index(from_seq._jets[i].cluster_hist_index());
1805 _set_structure_shared_ptr(_jets[i]);
1808 void ClusterSequence::plugin_record_ij_recombination(
1809 int jet_i,
int jet_j,
double dij,
1810 const PseudoJet & newjet,
int & newjet_k) {
1811 plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
1812 int tmp_index = _jets[newjet_k].cluster_hist_index();
1813 _jets[newjet_k] = newjet;
1814 _jets[newjet_k].set_cluster_hist_index(tmp_index);
1815 _set_structure_shared_ptr(_jets[newjet_k]);
1817 vector<PseudoJet> ClusterSequence::inclusive_jets (
const double ptmin)
const{
1818 double dcut = ptmin*ptmin;
1819 int i = _history.size() - 1;
1820 vector<PseudoJet> jets_local;
1821 if (_jet_algorithm == kt_algorithm) {
1823 if (_history[i].max_dij_so_far < dcut) {
break;}
1824 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
1826 int parent1 = _history[i].parent1;
1827 jets_local.push_back(_jets[_history[parent1].jetp_index]);}
1830 }
else if (_jet_algorithm == cambridge_algorithm) {
1832 if (_history[i].parent2 != BeamJet) {
break;}
1833 int parent1 = _history[i].parent1;
1834 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1835 if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1838 }
else if (_jet_algorithm == plugin_algorithm
1839 || _jet_algorithm == ee_kt_algorithm
1840 || _jet_algorithm == antikt_algorithm
1841 || _jet_algorithm == genkt_algorithm
1842 || _jet_algorithm == ee_genkt_algorithm
1843 || _jet_algorithm == cambridge_for_passive_algorithm) {
1845 if (_history[i].parent2 == BeamJet) {
1846 int parent1 = _history[i].parent1;
1847 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1848 if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1852 }
else {
throw Error(
"cs::inclusive_jets(...): Unrecognized jet algorithm");}
1855 int ClusterSequence::n_exclusive_jets (
const double dcut)
const {
1856 int i = _history.size() - 1;
1858 if (_history[i].max_dij_so_far <= dcut) {
break;}
1861 int stop_point = i + 1;
1862 int njets = 2*_initial_n - stop_point;
1865 vector<PseudoJet> ClusterSequence::exclusive_jets (
const double dcut)
const {
1866 int njets = n_exclusive_jets(dcut);
1867 return exclusive_jets(njets);
1869 vector<PseudoJet> ClusterSequence::exclusive_jets (
const int njets)
const {
1870 if (njets > _initial_n) {
1872 err <<
"Requested " << njets <<
" exclusive jets, but there were only "
1873 << _initial_n <<
" particles in the event";
1874 throw Error(err.str());
1876 return exclusive_jets_up_to(njets);
1878 vector<PseudoJet> ClusterSequence::exclusive_jets_up_to (
const int njets)
const {
1879 if (( _jet_def.jet_algorithm() != kt_algorithm) &&
1880 ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
1881 ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
1882 (((_jet_def.jet_algorithm() != genkt_algorithm) &&
1883 (_jet_def.jet_algorithm() != ee_genkt_algorithm)) ||
1884 (_jet_def.extra_param() <0)) &&
1885 ((_jet_def.jet_algorithm() != plugin_algorithm) ||
1886 (!_jet_def.plugin()->exclusive_sequence_meaningful()))) {
1887 _exclusive_warnings.warn(
"dcut and exclusive jets for jet-finders other than kt, C/A or genkt with p>=0 should be interpreted with care.");
1889 int stop_point = 2*_initial_n - njets;
1890 if (stop_point < _initial_n) stop_point = _initial_n;
1891 if (2*_initial_n != static_cast<int>(_history.size())) {
1893 err <<
"2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
1894 throw Error(err.str());
1896 vector<PseudoJet> jets_local;
1897 for (
unsigned int i = stop_point; i < _history.size(); i++) {
1898 int parent1 = _history[i].parent1;
1899 if (parent1 < stop_point) {
1900 jets_local.push_back(_jets[_history[parent1].jetp_index]);
1902 int parent2 = _history[i].parent2;
1903 if (parent2 < stop_point && parent2 > 0) {
1904 jets_local.push_back(_jets[_history[parent2].jetp_index]);
1907 if (
int(jets_local.size()) != min(_initial_n, njets)) {
1909 err <<
"ClusterSequence::exclusive_jets: size of returned vector ("
1910 <<jets_local.size()<<
") does not coincide with requested number of jets ("
1912 throw Error(err.str());
1916 double ClusterSequence::exclusive_dmerge (
const int njets)
const {
1918 if (njets >= _initial_n) {
return 0.0;}
1919 return _history[2*_initial_n-njets-1].dij;
1921 double ClusterSequence::exclusive_dmerge_max (
const int njets)
const {
1923 if (njets >= _initial_n) {
return 0.0;}
1924 return _history[2*_initial_n-njets-1].max_dij_so_far;
1926 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1927 (
const PseudoJet & jet,
const double dcut)
const {
1928 set<const history_element*> subhist;
1929 get_subhist_set(subhist, jet, dcut, 0);
1930 vector<PseudoJet> subjets;
1931 subjets.reserve(subhist.size());
1932 for (set<const history_element*>::iterator
elem = subhist.begin();
1934 subjets.push_back(_jets[(*elem)->jetp_index]);
1938 int ClusterSequence::n_exclusive_subjets(
const PseudoJet & jet,
1939 const double dcut)
const {
1940 set<const history_element*> subhist;
1941 get_subhist_set(subhist, jet, dcut, 0);
1942 return subhist.size();
1944 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1945 (
const PseudoJet & jet,
int nsub)
const {
1946 vector<PseudoJet> subjets = exclusive_subjets_up_to(jet, nsub);
1947 if (
int(subjets.size()) < nsub) {
1949 err <<
"Requested " << nsub <<
" exclusive subjets, but there were only "
1950 << subjets.size() <<
" particles in the jet";
1951 throw Error(err.str());
1955 std::vector<PseudoJet> ClusterSequence::exclusive_subjets_up_to
1956 (
const PseudoJet & jet,
int nsub)
const {
1957 set<const history_element*> subhist;
1958 vector<PseudoJet> subjets;
1959 if (nsub < 0)
throw Error(
"Requested a negative number of subjets. This is nonsensical.");
1960 if (nsub == 0)
return subjets;
1961 get_subhist_set(subhist, jet, -1.0, nsub);
1962 subjets.reserve(subhist.size());
1963 for (set<const history_element*>::iterator
elem = subhist.begin();
1965 subjets.push_back(_jets[(*elem)->jetp_index]);
1969 double ClusterSequence::exclusive_subdmerge(
const PseudoJet & jet,
int nsub)
const {
1970 set<const history_element*> subhist;
1971 get_subhist_set(subhist, jet, -1.0, nsub);
1972 set<const history_element*>::iterator highest = subhist.end();
1974 return (*highest)->dij;
1976 double ClusterSequence::exclusive_subdmerge_max(
const PseudoJet & jet,
int nsub)
const {
1977 set<const history_element*> subhist;
1978 get_subhist_set(subhist, jet, -1.0, nsub);
1979 set<const history_element*>::iterator highest = subhist.end();
1981 return (*highest)->max_dij_so_far;
1983 void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
1985 double dcut,
int maxjet)
const {
1986 assert(contains(jet));
1988 subhist.insert(&(_history[jet.cluster_hist_index()]));
1991 set<const history_element*>::iterator highest = subhist.end();
1992 assert (highest != subhist.begin());
1994 const history_element*
elem = *highest;
1995 if (njet == maxjet)
break;
1996 if (elem->parent1 < 0)
break;
1997 if (elem->max_dij_so_far <= dcut)
break;
1998 subhist.erase(highest);
1999 subhist.insert(&(_history[elem->parent1]));
2000 subhist.insert(&(_history[elem->parent2]));
2004 bool ClusterSequence::object_in_jet(
const PseudoJet &
object,
2006 assert(contains(
object) && contains(jet));
2007 const PseudoJet * this_object = &object;
2010 if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
2012 }
else if (has_child(*this_object, childp)) {
2013 this_object = childp;
2021 const history_element & hist = _history[jet.cluster_hist_index()];
2022 assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
2023 (hist.parent1 < 0 && hist.parent2 < 0));
2024 if (hist.parent1 < 0) {
2029 parent1 = _jets[_history[hist.parent1].jetp_index];
2030 parent2 = _jets[_history[hist.parent2].jetp_index];
2031 if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
2037 bool res = has_child(jet, childp);
2046 bool ClusterSequence::has_child(
const PseudoJet & jet,
const PseudoJet * & childp)
const {
2047 const history_element & hist = _history[jet.cluster_hist_index()];
2048 if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
2049 childp = &(_jets[_history[hist.child].jetp_index]);
2056 bool ClusterSequence::has_partner(
const PseudoJet & jet,
2058 const history_element & hist = _history[jet.cluster_hist_index()];
2059 if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
2060 const history_element & child_hist = _history[hist.child];
2061 if (child_hist.parent1 == jet.cluster_hist_index()) {
2062 partner = _jets[_history[child_hist.parent2].jetp_index];
2064 partner = _jets[_history[child_hist.parent1].jetp_index];
2072 vector<PseudoJet> ClusterSequence::constituents (
const PseudoJet & jet)
const {
2073 vector<PseudoJet> subjets;
2074 add_constituents(jet, subjets);
2077 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets_in,
2078 ostream & ostr)
const {
2079 for (
unsigned i = 0; i < jets_in.size(); i++) {
2081 << jets_in[i].px() <<
" "
2082 << jets_in[i].py() <<
" "
2083 << jets_in[i].pz() <<
" "
2084 << jets_in[i].E() << endl;
2085 vector<PseudoJet> cst = constituents(jets_in[i]);
2086 for (
unsigned j = 0; j < cst.size() ; j++) {
2087 ostr <<
" " << j <<
" "
2088 << cst[j].rap() <<
" "
2089 << cst[j].phi() <<
" "
2090 << cst[j].perp() << endl;
2092 ostr <<
"#END" << endl;
2095 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets_in,
2096 const std::string & filename,
2097 const std::string & comment )
const {
2098 std::ofstream ostr(filename.c_str());
2099 if (comment !=
"") ostr <<
"# " << comment << endl;
2100 print_jets_for_root(jets_in, ostr);
2102 vector<int> ClusterSequence::particle_jet_indices(
2103 const vector<PseudoJet> & jets_in)
const {
2104 vector<int> indices(n_particles());
2105 for (
unsigned ipart = 0; ipart < n_particles(); ipart++)
2106 indices[ipart] = -1;
2107 for (
unsigned ijet = 0; ijet < jets_in.size(); ijet++) {
2108 vector<PseudoJet> jet_constituents(constituents(jets_in[ijet]));
2109 for (
unsigned ip = 0; ip < jet_constituents.size(); ip++) {
2110 unsigned iclust = jet_constituents[ip].cluster_hist_index();
2111 unsigned ipart = history()[iclust].jetp_index;
2112 indices[ipart] = ijet;
2117 void ClusterSequence::add_constituents (
2118 const PseudoJet & jet, vector<PseudoJet> & subjet_vector)
const {
2119 int i = jet.cluster_hist_index();
2120 int parent1 = _history[i].parent1;
2121 int parent2 = _history[i].parent2;
2122 if (parent1 == InexistentParent) {
2123 subjet_vector.push_back(_jets[i]);
2126 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
2127 if (parent2 != BeamJet) {
2128 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
2131 void ClusterSequence::_add_step_to_history (
2133 const int parent2,
const int jetp_index,
2135 history_element element;
2136 element.parent1 = parent1;
2137 element.parent2 = parent2;
2138 element.jetp_index = jetp_index;
2139 element.child = Invalid;
2141 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
2142 _history.push_back(element);
2143 int local_step = _history.size()-1;
2144 assert(parent1 >= 0);
2145 if (_history[parent1].child != Invalid){
2146 throw InternalError(
"trying to recomine an object that has previsously been recombined");
2148 _history[parent1].child = local_step;
2150 if (_history[parent2].child != Invalid){
2151 throw InternalError(
"trying to recomine an object that has previsously been recombined");
2153 _history[parent2].child = local_step;
2155 if (jetp_index != Invalid) {
2156 assert(jetp_index >= 0);
2157 _jets[jetp_index].set_cluster_hist_index(local_step);
2158 _set_structure_shared_ptr(_jets[jetp_index]);
2160 if (_writeout_combinations) {
2161 cout << local_step <<
": "
2162 << parent1 <<
" with " << parent2
2163 <<
"; y = "<< dij<<endl;
2166 vector<int> ClusterSequence::unique_history_order()
const {
2167 valarray<int> lowest_constituent(_history.size());
2168 int hist_n = _history.size();
2169 lowest_constituent = hist_n;
2170 for (
int i = 0; i < hist_n; i++) {
2171 lowest_constituent[i] = min(lowest_constituent[i],i);
2172 if (_history[i].child > 0) lowest_constituent[_history[i].child]
2173 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
2175 valarray<bool> extracted(_history.size()); extracted =
false;
2176 vector<int> unique_tree;
2177 unique_tree.reserve(_history.size());
2178 for (
unsigned i = 0; i < n_particles(); i++) {
2179 if (!extracted[i]) {
2180 unique_tree.push_back(i);
2181 extracted[i] =
true;
2182 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
2187 void ClusterSequence::_extract_tree_children(
2189 valarray<bool> & extracted,
2190 const valarray<int> & lowest_constituent,
2191 vector<int> & unique_tree)
const {
2192 if (!extracted[position]) {
2193 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
2195 int child = _history[position].child;
2196 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
2198 vector<PseudoJet> ClusterSequence::unclustered_particles()
const {
2199 vector<PseudoJet> unclustered;
2200 for (
unsigned i = 0; i < n_particles() ; i++) {
2201 if (_history[i].child == Invalid)
2202 unclustered.push_back(_jets[_history[i].jetp_index]);
2206 vector<PseudoJet> ClusterSequence::childless_pseudojets()
const {
2207 vector<PseudoJet> unclustered;
2208 for (
unsigned i = 0; i < _history.size() ; i++) {
2209 if ((_history[i].child == Invalid) && (_history[i].parent2 != BeamJet))
2210 unclustered.push_back(_jets[_history[i].jetp_index]);
2214 bool ClusterSequence::contains(
const PseudoJet & jet)
const {
2215 return jet.cluster_hist_index() >= 0
2216 && jet.cluster_hist_index() < int(_history.size())
2217 && jet.has_valid_cluster_sequence()
2218 && jet.associated_cluster_sequence() ==
this;
2220 void ClusterSequence::_extract_tree_parents(
2222 valarray<bool> & extracted,
2223 const valarray<int> & lowest_constituent,
2224 vector<int> & unique_tree)
const {
2225 if (!extracted[position]) {
2226 int parent1 = _history[position].parent1;
2227 int parent2 = _history[position].parent2;
2228 if (parent1 >= 0 && parent2 >= 0) {
2229 if (lowest_constituent[parent1] > lowest_constituent[parent2])
2230 std::swap(parent1, parent2);
2232 if (parent1 >= 0 && !extracted[parent1])
2233 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
2234 if (parent2 >= 0 && !extracted[parent2])
2235 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
2236 unique_tree.push_back(position);
2237 extracted[position] =
true;
2240 void ClusterSequence::_do_ij_recombination_step(
2241 const int jet_i,
const int jet_j,
2245 _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
2246 _jets.push_back(newjet);
2247 newjet_k = _jets.size()-1;
2248 int newstep_k = _history.size();
2249 _jets[newjet_k].set_cluster_hist_index(newstep_k);
2250 int hist_i = _jets[jet_i].cluster_hist_index();
2251 int hist_j = _jets[jet_j].cluster_hist_index();
2252 _add_step_to_history(min(hist_i, hist_j), max(hist_i,hist_j),
2255 void ClusterSequence::_do_iB_recombination_step(
2256 const int jet_i,
const double diB) {
2257 _add_step_to_history(_jets[jet_i].cluster_hist_index(),BeamJet,
2261 void ClusterSequence::_set_structure_shared_ptr(
PseudoJet & j) {
2262 j.set_structure_shared_ptr(_structure_shared_ptr);
2263 _update_structure_use_count();
2265 void ClusterSequence::_update_structure_use_count() {
2266 _structure_use_count_after_construction = _structure_shared_ptr.use_count();
2268 void ClusterSequence::delete_self_when_unused() {
2269 int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
2270 if (new_count <= 0) {
2271 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");
2273 _structure_shared_ptr.set_count(new_count);
2274 _deletes_self_when_unused =
true;
2276 FJCORE_END_NAMESPACE
2281 FJCORE_BEGIN_NAMESPACE
2282 using namespace std;
2287 MirrorInfo(
int a,
int b) : orig(a), mirror(b) {}
2290 bool make_mirror(
Coord2D & point,
double Dlim) {
2291 if (point.y < Dlim) {point.y += twopi;
return true;}
2292 if (twopi-point.y < Dlim) {point.y -= twopi;
return true;}
2296 using namespace Private;
2297 void ClusterSequence::_CP2DChan_limited_cluster (
double Dlim) {
2298 unsigned int n = _initial_n;
2299 vector<MirrorInfo> coordIDs(2*n);
2300 vector<int> jetIDs(2*n);
2301 vector<Coord2D> coords(2*n);
2302 double Dlim4mirror = min(Dlim,pi);
2303 double minrap = numeric_limits<double>::max();
2304 double maxrap = -minrap;
2305 int coord_index = -1;
2307 for (
unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
2308 if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
2309 (_jets[jet_i].E() == abs(_jets[jet_i].pz()) &&
2310 _jets[jet_i].perp2() == 0.0)
2313 coordIDs[jet_i].orig = ++coord_index;
2314 coords[coord_index] =
Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
2315 jetIDs[coord_index] = jet_i;
2316 minrap = min(coords[coord_index].x,minrap);
2317 maxrap = max(coords[coord_index].x,maxrap);
2318 Coord2D mirror_point(coords[coord_index]);
2319 if (make_mirror(mirror_point, Dlim4mirror)) {
2320 coordIDs[jet_i].mirror = ++coord_index;
2321 coords[coord_index] = mirror_point;
2322 jetIDs[coord_index] = jet_i;
2324 coordIDs[jet_i].mirror = Invalid;
2327 coords.resize(coord_index+1);
2328 Coord2D left_edge(minrap-1.0, -3.15);
2329 Coord2D right_edge(maxrap+1.0, 9.45);
2331 vector<Coord2D> new_points(2);
2332 vector<unsigned int> cIDs_to_remove(4);
2333 vector<unsigned int> new_cIDs(2);
2335 unsigned int cID1, cID2;
2337 cp.closest_pair(cID1,cID2,distance2);
2338 if (distance2 > Dlim*Dlim) {
break;}
2339 distance2 *= _invR2;
2340 int jet_i = jetIDs[cID1];
2341 int jet_j = jetIDs[cID2];
2342 assert (jet_i != jet_j);
2344 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
2345 if (--n_active == 1) {
break;}
2346 cIDs_to_remove.resize(0);
2347 cIDs_to_remove.push_back(coordIDs[jet_i].orig);
2348 cIDs_to_remove.push_back(coordIDs[jet_j].orig);
2349 if (coordIDs[jet_i].mirror != Invalid)
2350 cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
2351 if (coordIDs[jet_j].mirror != Invalid)
2352 cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
2353 Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
2354 new_points.resize(0);
2355 new_points.push_back(new_point);
2356 if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point);
2357 cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
2358 coordIDs[newjet_k].orig = new_cIDs[0];
2359 jetIDs[new_cIDs[0]] = newjet_k;
2360 if (new_cIDs.size() == 2) {
2361 coordIDs[newjet_k].mirror = new_cIDs[1];
2362 jetIDs[new_cIDs[1]] = newjet_k;
2363 }
else {coordIDs[newjet_k].mirror = Invalid;}
2366 void ClusterSequence::_CP2DChan_cluster_2pi2R () {
2367 if (_jet_algorithm != cambridge_algorithm)
throw Error(
"CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
2368 _CP2DChan_limited_cluster(_Rparam);
2369 _do_Cambridge_inclusive_jets();
2371 void ClusterSequence::_CP2DChan_cluster_2piMultD () {
2372 if (_Rparam >= 0.39) {
2373 _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
2375 _CP2DChan_cluster_2pi2R ();
2377 void ClusterSequence::_CP2DChan_cluster () {
2378 if (_jet_algorithm != cambridge_algorithm)
throw Error(
"_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
2379 unsigned int n = _jets.size();
2380 vector<MirrorInfo> coordIDs(2*n);
2381 vector<int> jetIDs(2*n);
2382 vector<Coord2D> coords(2*n);
2383 double minrap = numeric_limits<double>::max();
2384 double maxrap = -minrap;
2385 int coord_index = 0;
2386 for (
unsigned i = 0; i < n; i++) {
2387 if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
2390 coordIDs[i].orig = coord_index;
2391 coordIDs[i].mirror = coord_index+1;
2392 coords[coord_index] =
Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
2393 coords[coord_index+1] =
Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
2394 jetIDs[coord_index] = i;
2395 jetIDs[coord_index+1] = i;
2396 minrap = min(coords[coord_index].x,minrap);
2397 maxrap = max(coords[coord_index].x,maxrap);
2401 for (
unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
2402 coords.resize(coord_index);
2403 Coord2D left_edge(minrap-1.0, 0.0);
2404 Coord2D right_edge(maxrap+1.0, 2*twopi);
2406 vector<Coord2D> new_points(2);
2407 vector<unsigned int> cIDs_to_remove(4);
2408 vector<unsigned int> new_cIDs(2);
2410 unsigned int cID1, cID2;
2412 cp.closest_pair(cID1,cID2,distance2);
2413 distance2 *= _invR2;
2414 if (distance2 > 1.0) {
break;}
2415 int jet_i = jetIDs[cID1];
2416 int jet_j = jetIDs[cID2];
2417 assert (jet_i != jet_j);
2419 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
2420 cIDs_to_remove[0] = coordIDs[jet_i].orig;
2421 cIDs_to_remove[1] = coordIDs[jet_i].mirror;
2422 cIDs_to_remove[2] = coordIDs[jet_j].orig;
2423 cIDs_to_remove[3] = coordIDs[jet_j].mirror;
2424 new_points[0] =
Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
2425 new_points[1] =
Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
2426 new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
2427 new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
2428 coordIDs[jet_i].orig = Invalid;
2429 coordIDs[jet_j].orig = Invalid;
2430 coordIDs[newjet_k] =
MirrorInfo(new_cIDs[0], new_cIDs[1]);
2431 jetIDs[new_cIDs[0]] = newjet_k;
2432 jetIDs[new_cIDs[1]] = newjet_k;
2434 if (n == 1) {
break;}
2436 _do_Cambridge_inclusive_jets();
2438 void ClusterSequence::_do_Cambridge_inclusive_jets () {
2439 unsigned int n = _history.size();
2440 for (
unsigned int hist_i = 0; hist_i < n; hist_i++) {
2441 if (_history[hist_i].child == Invalid) {
2442 _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
2446 FJCORE_END_NAMESPACE
2453 #ifndef __FJCORE_DROP_CGAL // in case we do not have the code for CGAL
2454 #include "fastjet/internal/Dnn4piCylinder.hh"
2455 #include "fastjet/internal/Dnn3piCylinder.hh"
2456 #include "fastjet/internal/Dnn2piCylinder.hh"
2457 #endif // __FJCORE_DROP_CGAL
2458 FJCORE_BEGIN_NAMESPACE
2459 using namespace std;
2460 void ClusterSequence::_delaunay_cluster () {
2461 int n = _jets.size();
2462 vector<EtaPhi> points(n);
2463 for (
int i = 0; i < n; i++) {
2464 points[i] =
EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
2465 points[i].sanitize();
2468 const bool verbose =
false;
2469 #ifndef __FJCORE_DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
2470 bool ignore_nearest_is_mirror = (_Rparam < twopi);
2471 if (_strategy == NlnN4pi) {
2472 DNN.reset(
new Dnn4piCylinder(points,verbose));
2473 }
else if (_strategy == NlnN3pi) {
2474 DNN.reset(
new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose));
2475 }
else if (_strategy == NlnN) {
2476 DNN.reset(
new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose));
2479 if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
2481 err <<
"ERROR: Requested strategy "<<strategy_string()<<
" but it is not"<<endl;
2482 err <<
" supported because FastJet was compiled without CGAL"<<endl;
2483 throw Error(err.str());
2485 #endif // __FJCORE_DROP_CGAL
2490 for (
int ii = 0; ii < n; ii++) {
2491 _add_ktdistance_to_map(ii, DijMap, DNN.get());
2493 for (
int i=0;i<n;i++) {
2494 TwoVertices SmallestDijPair;
2498 bool recombine_with_beam;
2500 SmallestDij = DijMap.begin()->first;
2501 SmallestDijPair = DijMap.begin()->second;
2502 jet_i = SmallestDijPair.first;
2503 jet_j = SmallestDijPair.second;
2504 if (verbose) cout <<
"CS_Delaunay found recombination candidate: " << jet_i <<
" " << jet_j <<
" " << SmallestDij << endl;
2505 DijMap.erase(DijMap.begin());
2506 recombine_with_beam = (jet_j == BeamJet);
2507 if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);}
2508 else {Valid2 =
true;}
2509 if (verbose) cout <<
"CS_Delaunay validities i & j: " << DNN->Valid(jet_i) <<
" " << Valid2 << endl;
2510 }
while ( !DNN->Valid(jet_i) || !Valid2);
2511 if (! recombine_with_beam) {
2513 if (verbose) cout <<
"CS_Delaunay call _do_ij_recomb: " << jet_i <<
" " << jet_j <<
" " << SmallestDij << endl;
2514 _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
2515 EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
2516 newpoint.sanitize();
2517 points.push_back(newpoint);
2519 if (verbose) cout <<
"CS_Delaunay call _do_iB_recomb: " << jet_i <<
" " << SmallestDij << endl;
2520 _do_iB_recombination_step(jet_i, SmallestDij);
2522 if (i == n-1) {
break;}
2523 vector<int> updated_neighbours;
2524 if (! recombine_with_beam) {
2526 DNN->RemoveCombinedAddCombination(jet_i, jet_j,
2527 points[points.size()-1], point3,
2528 updated_neighbours);
2529 if (static_cast<unsigned int> (point3) != points.size()-1) {
2530 throw Error(
"INTERNAL ERROR: point3 != points.size()-1");}
2532 DNN->RemovePoint(jet_i, updated_neighbours);
2534 vector<int>::iterator it = updated_neighbours.begin();
2535 for (; it != updated_neighbours.end(); ++it) {
2537 _add_ktdistance_to_map(ii, DijMap, DNN.get());
2541 void ClusterSequence::_add_ktdistance_to_map(
2545 double yiB = jet_scale_for_algorithm(_jets[ii]);
2547 DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2549 double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
2550 if (DeltaR2 > 1.0) {
2551 DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2553 double kt2i = jet_scale_for_algorithm(_jets[ii]);
2554 int jj = DNN->NearestNeighbourIndex(ii);
2555 if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
2556 double dij = DeltaR2 * kt2i;
2557 DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
2562 FJCORE_END_NAMESPACE
2567 FJCORE_BEGIN_NAMESPACE
2568 using namespace std;
2569 void ClusterSequence::_really_dumb_cluster () {
2570 vector<PseudoJet *> jetsp(_jets.size());
2571 vector<int> indices(_jets.size());
2572 for (
size_t i = 0; i<_jets.size(); i++) {
2573 jetsp[i] = & _jets[i];
2576 for (
int n = jetsp.size(); n > 0; n--) {
2578 double ymin = jet_scale_for_algorithm(*(jetsp[0]));
2580 for (
int i = 0; i < n; i++) {
2581 double yiB = jet_scale_for_algorithm(*(jetsp[i]));
2583 ymin = yiB; ii = i; jj = -2;}
2585 for (
int i = 0; i < n-1; i++) {
2586 for (
int j = i+1; j < n; j++) {
2588 double y = min(jet_scale_for_algorithm(*(jetsp[i])),
2589 jet_scale_for_algorithm(*(jetsp[j])))
2590 * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
2591 if (y < ymin) {ymin = y; ii = i; jj = j;}
2594 int newn = 2*jetsp.size() - n;
2597 _do_ij_recombination_step(jetsp[ii]-&_jets[0],
2598 jetsp[jj]-&_jets[0], ymin, nn);
2599 jetsp[ii] = &_jets[nn];
2600 jetsp[jj] = jetsp[n-1];
2602 indices[jj] = indices[n-1];
2604 _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
2605 jetsp[ii] = jetsp[n-1];
2606 indices[ii] = indices[n-1];
2610 FJCORE_END_NAMESPACE
2612 FJCORE_BEGIN_NAMESPACE
2613 using namespace std;
2614 template<>
inline void ClusterSequence::_bj_set_jetinfo(
2615 EEBriefJet *
const jetA,
const int _jets_index)
const {
2616 double E = _jets[_jets_index].E();
2618 double p = jet_def().extra_param();
2619 switch (_jet_algorithm) {
2620 case ee_kt_algorithm:
2621 assert(_Rparam > 2.0);
2623 case ee_genkt_algorithm:
2624 if (p <= 0 && scale < 1e-300) scale = 1e-300;
2625 scale = pow(scale,p);
2628 throw Error(
"Unrecognised jet algorithm");
2631 double norm = _jets[_jets_index].modp2();
2633 norm = 1.0/sqrt(norm);
2634 jetA->nx = norm * _jets[_jets_index].px();
2635 jetA->ny = norm * _jets[_jets_index].py();
2636 jetA->nz = norm * _jets[_jets_index].pz();
2642 jetA->_jets_index = _jets_index;
2643 jetA->NN_dist = _R2;
2646 template<>
double ClusterSequence::_bj_dist(
2647 const EEBriefJet *
const jeta,
2648 const EEBriefJet *
const jetb)
const {
2652 - jeta->nz*jetb->nz;
2656 void ClusterSequence::_simple_N2_cluster_BriefJet() {
2657 _simple_N2_cluster<BriefJet>();
2659 void ClusterSequence::_simple_N2_cluster_EEBriefJet() {
2660 _simple_N2_cluster<EEBriefJet>();
2662 FJCORE_END_NAMESPACE
2664 FJCORE_BEGIN_NAMESPACE
2665 using namespace std;
2666 ClusterSequenceStructure::~ClusterSequenceStructure(){
2667 if (_associated_cs != NULL
2668 && _associated_cs->will_delete_self_when_unused()) {
2669 _associated_cs->signal_imminent_self_deletion();
2670 delete _associated_cs;
2673 bool ClusterSequenceStructure::has_valid_cluster_sequence()
const{
2674 return (_associated_cs != NULL);
2676 const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence()
const{
2677 return _associated_cs;
2679 const ClusterSequence * ClusterSequenceStructure::validated_cs()
const {
2680 if (!_associated_cs)
2681 throw Error(
"you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
2682 return _associated_cs;
2684 bool ClusterSequenceStructure::has_partner(
const PseudoJet &reference,
PseudoJet &partner)
const{
2685 return validated_cs()->has_partner(reference, partner);
2687 bool ClusterSequenceStructure::has_child(
const PseudoJet &reference,
PseudoJet &child)
const{
2688 return validated_cs()->has_child(reference, child);
2691 return validated_cs()->has_parents(reference, parent1, parent2);
2693 bool ClusterSequenceStructure::object_in_jet(
const PseudoJet &reference,
const PseudoJet &jet)
const{
2694 if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
2695 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.");
2696 if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence())
return false;
2697 return validated_cs()->object_in_jet(reference, jet);
2699 bool ClusterSequenceStructure::has_constituents()
const{
2700 if (!has_associated_cluster_sequence())
2701 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.");
2704 vector<PseudoJet> ClusterSequenceStructure::constituents(
const PseudoJet &reference)
const{
2705 return validated_cs()->constituents(reference);
2707 bool ClusterSequenceStructure::has_exclusive_subjets()
const{
2708 if (!has_associated_cluster_sequence())
2709 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.");
2712 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (
const PseudoJet &reference,
const double & dcut)
const {
2713 return validated_cs()->exclusive_subjets(reference, dcut);
2715 int ClusterSequenceStructure::n_exclusive_subjets(
const PseudoJet &reference,
const double & dcut)
const {
2716 return validated_cs()->n_exclusive_subjets(reference, dcut);
2718 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (
const PseudoJet &reference,
int nsub)
const {
2719 return validated_cs()->exclusive_subjets_up_to(reference, nsub);
2721 double ClusterSequenceStructure::exclusive_subdmerge(
const PseudoJet &reference,
int nsub)
const {
2722 return validated_cs()->exclusive_subdmerge(reference, nsub);
2724 double ClusterSequenceStructure::exclusive_subdmerge_max(
const PseudoJet &reference,
int nsub)
const {
2725 return validated_cs()->exclusive_subdmerge_max(reference, nsub);
2727 bool ClusterSequenceStructure::has_pieces(
const PseudoJet &reference)
const{
2729 return has_parents(reference, dummy1, dummy2);
2731 vector<PseudoJet> ClusterSequenceStructure::pieces(
const PseudoJet &reference)
const{
2733 vector<PseudoJet> res;
2734 if (has_parents(reference, j1, j2)){
2740 FJCORE_END_NAMESPACE
2745 FJCORE_BEGIN_NAMESPACE
2746 using namespace std;
2747 void ClusterSequence::_bj_remove_from_tiles(
TiledJet *
const jet) {
2748 Tile * tile = & _tiles[jet->tile_index];
2749 if (jet->previous == NULL) {
2750 tile->head = jet->next;
2752 jet->previous->next = jet->next;
2754 if (jet->next != NULL) {
2755 jet->next->previous = jet->previous;
2758 void ClusterSequence::_initialise_tiles() {
2759 double default_size = max(0.1,_Rparam);
2760 _tile_size_eta = default_size;
2761 _n_tiles_phi = max(3,
int(floor(twopi/default_size)));
2762 _tile_size_phi = twopi / _n_tiles_phi;
2764 _tiles_eta_min = tiling_analysis.minrap();
2765 _tiles_eta_max = tiling_analysis.maxrap();
2766 _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
2767 _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
2768 _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
2769 _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
2770 _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
2771 for (
int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
2772 for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
2773 Tile * tile = & _tiles[_tile_index(ieta,iphi)];
2775 tile->begin_tiles[0] = tile;
2776 Tile ** pptile = & (tile->begin_tiles[0]);
2778 tile->surrounding_tiles = pptile;
2779 if (ieta > _tiles_ieta_min) {
2783 for (
int idphi = -1; idphi <=+1; idphi++) {
2784 *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
2788 *pptile = & _tiles[_tile_index(ieta,iphi-1)];
2790 tile->RH_tiles = pptile;
2791 *pptile = & _tiles[_tile_index(ieta,iphi+1)];
2793 if (ieta < _tiles_ieta_max) {
2794 for (
int idphi = -1; idphi <= +1; idphi++) {
2795 *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
2799 tile->end_tiles = pptile;
2800 tile->tagged =
false;
2804 int ClusterSequence::_tile_index(
const double eta,
const double phi)
const {
2806 if (eta <= _tiles_eta_min) {ieta = 0;}
2807 else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
2809 ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
2810 if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
2811 ieta = _tiles_ieta_max-_tiles_ieta_min;}
2813 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
2814 return (iphi + ieta * _n_tiles_phi);
2816 inline void ClusterSequence::_tj_set_jetinfo(
TiledJet *
const jet,
2817 const int _jets_index) {
2818 _bj_set_jetinfo<>(jet, _jets_index);
2819 jet->tile_index = _tile_index(jet->eta, jet->phi);
2820 Tile * tile = &_tiles[jet->tile_index];
2821 jet->previous = NULL;
2822 jet->next = tile->head;
2823 if (jet->next != NULL) {jet->next->previous = jet;}
2826 void ClusterSequence::_print_tiles(
TiledJet * briefjets )
const {
2827 for (vector<Tile>::const_iterator tile = _tiles.begin();
2828 tile < _tiles.end(); tile++) {
2829 cout <<
"Tile " << tile - _tiles.begin()<<
" = ";
2831 for (
TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
2832 list.push_back(jetI-briefjets);
2834 sort(list.begin(),list.end());
2835 for (
unsigned int i = 0; i < list.size(); i++) {cout <<
" "<<list[i];}
2839 void ClusterSequence::_add_neighbours_to_tile_union(
const int tile_index,
2840 vector<int> & tile_union,
int & n_near_tiles)
const {
2841 for (
Tile *
const * near_tile = _tiles[tile_index].begin_tiles;
2842 near_tile != _tiles[tile_index].end_tiles; near_tile++){
2843 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2847 inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
2848 const int tile_index,
2849 vector<int> & tile_union,
int & n_near_tiles) {
2850 for (
Tile ** near_tile = _tiles[tile_index].begin_tiles;
2851 near_tile != _tiles[tile_index].end_tiles; near_tile++){
2852 if (! (*near_tile)->tagged) {
2853 (*near_tile)->tagged =
true;
2854 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2859 void ClusterSequence::_tiled_N2_cluster() {
2860 _initialise_tiles();
2861 int n = _jets.size();
2863 TiledJet * jetA = briefjets, * jetB;
2866 vector<int> tile_union(3*n_tile_neighbours);
2867 for (
int i = 0; i< n; i++) {
2868 _tj_set_jetinfo(jetA, i);
2873 vector<Tile>::const_iterator tile;
2874 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2875 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2876 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2877 double dist = _bj_dist(jetA,jetB);
2878 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2879 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2882 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2883 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2884 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2885 double dist = _bj_dist(jetA,jetB);
2886 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2887 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2892 double * diJ =
new double[n];
2894 for (
int i = 0; i < n; i++) {
2895 diJ[i] = _bj_diJ(jetA);
2898 int history_location = n-1;
2899 while (tail != head) {
2900 double diJ_min = diJ[0];
2901 int diJ_min_jet = 0;
2902 for (
int i = 1; i < n; i++) {
2903 if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
2906 jetA = & briefjets[diJ_min_jet];
2910 if (jetA < jetB) {std::swap(jetA,jetB);}
2912 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2913 _bj_remove_from_tiles(jetA);
2915 _bj_remove_from_tiles(jetB);
2916 _tj_set_jetinfo(jetB, nn);
2918 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2919 _bj_remove_from_tiles(jetA);
2921 int n_near_tiles = 0;
2922 _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
2924 bool sort_it =
false;
2925 if (jetB->tile_index != jetA->tile_index) {
2927 _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
2929 if (oldB.tile_index != jetA->tile_index &&
2930 oldB.tile_index != jetB->tile_index) {
2932 _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
2936 sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
2939 for (
int i = 1; i < n_near_tiles; i++) {
2940 if (tile_union[i] != tile_union[nnn-1]) {
2941 tile_union[nnn] = tile_union[i];
2952 diJ[jetA - head] = diJ[tail-head];
2953 if (jetA->previous == NULL) {
2954 _tiles[jetA->tile_index].head = jetA;
2956 jetA->previous->next = jetA;
2958 if (jetA->next != NULL) {jetA->next->previous = jetA;}
2960 for (
int itile = 0; itile < n_near_tiles; itile++) {
2961 Tile * tile_ptr = &_tiles[tile_union[itile]];
2962 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2964 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2965 jetI->NN_dist = _R2;
2968 for (
Tile ** near_tile = tile_ptr->begin_tiles;
2969 near_tile != tile_ptr->end_tiles; near_tile++) {
2971 for (
TiledJet * jetJ = (*near_tile)->head;
2972 jetJ != NULL; jetJ = jetJ->next) {
2973 double dist = _bj_dist(jetI,jetJ);
2974 if (dist < jetI->NN_dist && jetJ != jetI) {
2975 jetI->NN_dist = dist; jetI->NN = jetJ;
2979 diJ[jetI-head] = _bj_diJ(jetI);
2984 double dist = _bj_dist(jetI,jetB);
2985 if (dist < jetI->NN_dist) {
2987 jetI->NN_dist = dist;
2989 diJ[jetI-head] = _bj_diJ(jetI);
2992 if (dist < jetB->NN_dist) {
2994 jetB->NN_dist = dist;
3000 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
3001 for (
Tile ** near_tile = _tiles[tail->tile_index].begin_tiles;
3002 near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
3003 for (
TiledJet * jetJ = (*near_tile)->head;
3004 jetJ != NULL; jetJ = jetJ->next) {
3005 if (jetJ->NN == tail) {jetJ->NN = jetA;}
3008 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
3013 void ClusterSequence::_faster_tiled_N2_cluster() {
3014 _initialise_tiles();
3015 int n = _jets.size();
3017 TiledJet * jetA = briefjets, * jetB;
3020 vector<int> tile_union(3*n_tile_neighbours);
3021 for (
int i = 0; i< n; i++) {
3022 _tj_set_jetinfo(jetA, i);
3026 vector<Tile>::const_iterator tile;
3027 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
3028 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
3029 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
3030 double dist = _bj_dist(jetA,jetB);
3031 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
3032 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
3035 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
3036 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
3037 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
3038 double dist = _bj_dist(jetA,jetB);
3039 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
3040 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
3045 struct diJ_plus_link {
3049 diJ_plus_link * diJ =
new diJ_plus_link[n];
3051 for (
int i = 0; i < n; i++) {
3052 diJ[i].diJ = _bj_diJ(jetA);
3057 int history_location = n-1;
3059 diJ_plus_link * best, *stop;
3060 double diJ_min = diJ[0].diJ;
3063 for (diJ_plus_link * here = diJ+1; here != stop; here++) {
3064 if (here->diJ < diJ_min) {best = here; diJ_min = here->diJ;}
3071 if (jetA < jetB) {std::swap(jetA,jetB);}
3073 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
3074 _bj_remove_from_tiles(jetA);
3076 _bj_remove_from_tiles(jetB);
3077 _tj_set_jetinfo(jetB, nn);
3079 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
3080 _bj_remove_from_tiles(jetA);
3082 int n_near_tiles = 0;
3083 _add_untagged_neighbours_to_tile_union(jetA->tile_index,
3084 tile_union, n_near_tiles);
3086 if (jetB->tile_index != jetA->tile_index) {
3087 _add_untagged_neighbours_to_tile_union(jetB->tile_index,
3088 tile_union,n_near_tiles);
3090 if (oldB.tile_index != jetA->tile_index &&
3091 oldB.tile_index != jetB->tile_index) {
3092 _add_untagged_neighbours_to_tile_union(oldB.tile_index,
3093 tile_union,n_near_tiles);
3097 diJ[n].jet->diJ_posn = jetA->diJ_posn;
3098 diJ[jetA->diJ_posn] = diJ[n];
3099 for (
int itile = 0; itile < n_near_tiles; itile++) {
3100 Tile * tile_ptr = &_tiles[tile_union[itile]];
3101 tile_ptr->tagged =
false;
3102 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
3104 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
3105 jetI->NN_dist = _R2;
3108 for (
Tile ** near_tile = tile_ptr->begin_tiles;
3109 near_tile != tile_ptr->end_tiles; near_tile++) {
3111 for (
TiledJet * jetJ = (*near_tile)->head;
3112 jetJ != NULL; jetJ = jetJ->next) {
3113 double dist = _bj_dist(jetI,jetJ);
3114 if (dist < jetI->NN_dist && jetJ != jetI) {
3115 jetI->NN_dist = dist; jetI->NN = jetJ;
3119 diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI);
3125 double dist = _bj_dist(jetI,jetB);
3126 if (dist < jetI->NN_dist) {
3128 jetI->NN_dist = dist;
3130 diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI);
3133 if (dist < jetB->NN_dist) {
3135 jetB->NN_dist = dist;
3141 if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
3146 void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
3147 _initialise_tiles();
3148 int n = _jets.size();
3150 TiledJet * jetA = briefjets, * jetB;
3153 vector<int> tile_union(3*n_tile_neighbours);
3154 for (
int i = 0; i< n; i++) {
3155 _tj_set_jetinfo(jetA, i);
3159 vector<Tile>::const_iterator tile;
3160 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
3161 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
3162 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
3163 double dist = _bj_dist(jetA,jetB);
3164 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
3165 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
3168 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
3169 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
3170 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
3171 double dist = _bj_dist(jetA,jetB);
3172 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
3173 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
3178 vector<double> diJs(n);
3179 for (
int i = 0; i < n; i++) {
3180 diJs[i] = _bj_diJ(&briefjets[i]);
3181 briefjets[i].label_minheap_update_done();
3184 vector<TiledJet *> jets_for_minheap;
3185 jets_for_minheap.reserve(n);
3186 int history_location = n-1;
3188 double diJ_min = minheap.minval() *_invR2;
3189 jetA = head + minheap.minloc();
3193 if (jetA < jetB) {std::swap(jetA,jetB);}
3195 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
3196 _bj_remove_from_tiles(jetA);
3198 _bj_remove_from_tiles(jetB);
3199 _tj_set_jetinfo(jetB, nn);
3201 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
3202 _bj_remove_from_tiles(jetA);
3204 minheap.remove(jetA-head);
3205 int n_near_tiles = 0;
3206 _add_untagged_neighbours_to_tile_union(jetA->tile_index,
3207 tile_union, n_near_tiles);
3209 if (jetB->tile_index != jetA->tile_index) {
3210 _add_untagged_neighbours_to_tile_union(jetB->tile_index,
3211 tile_union,n_near_tiles);
3213 if (oldB.tile_index != jetA->tile_index &&
3214 oldB.tile_index != jetB->tile_index) {
3222 _add_untagged_neighbours_to_tile_union(oldB.tile_index,
3223 tile_union,n_near_tiles);
3225 jetB->label_minheap_update_needed();
3226 jets_for_minheap.push_back(jetB);
3228 for (
int itile = 0; itile < n_near_tiles; itile++) {
3229 Tile * tile_ptr = &_tiles[tile_union[itile]];
3230 tile_ptr->tagged =
false;
3231 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
3233 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
3234 jetI->NN_dist = _R2;
3237 if (!jetI->minheap_update_needed()) {
3238 jetI->label_minheap_update_needed();
3239 jets_for_minheap.push_back(jetI);}
3241 for (
Tile ** near_tile = tile_ptr->begin_tiles;
3242 near_tile != tile_ptr->end_tiles; near_tile++) {
3244 for (
TiledJet * jetJ = (*near_tile)->head;
3245 jetJ != NULL; jetJ = jetJ->next) {
3246 double dist = _bj_dist(jetI,jetJ);
3247 if (dist < jetI->NN_dist && jetJ != jetI) {
3248 jetI->NN_dist = dist; jetI->NN = jetJ;
3257 double dist = _bj_dist(jetI,jetB);
3258 if (dist < jetI->NN_dist) {
3260 jetI->NN_dist = dist;
3263 if (!jetI->minheap_update_needed()) {
3264 jetI->label_minheap_update_needed();
3265 jets_for_minheap.push_back(jetI);}
3268 if (dist < jetB->NN_dist) {
3270 jetB->NN_dist = dist;
3276 while (jets_for_minheap.size() > 0) {
3277 TiledJet * jetI = jets_for_minheap.back();
3278 jets_for_minheap.pop_back();
3279 minheap.update(jetI-head, _bj_diJ(jetI));
3280 jetI->label_minheap_update_done();
3286 FJCORE_END_NAMESPACE
3287 FJCORE_BEGIN_NAMESPACE
3288 using namespace std;
3289 CompositeJetStructure::CompositeJetStructure(
const std::vector<PseudoJet> & initial_pieces,
3291 : _pieces(initial_pieces){
3293 _area_4vector_ptr = 0;
3295 std::string CompositeJetStructure::description()
const{
3296 string str =
"Composite PseudoJet";
3299 bool CompositeJetStructure::has_constituents()
const{
3302 std::vector<PseudoJet> CompositeJetStructure::constituents(
const PseudoJet & )
const{
3303 vector<PseudoJet> all_constituents;
3304 for (
unsigned i = 0; i <
_pieces.size(); i++) {
3305 if (
_pieces[i].has_constituents()){
3306 vector<PseudoJet> constits =
_pieces[i].constituents();
3307 copy(constits.begin(), constits.end(), back_inserter(all_constituents));
3309 all_constituents.push_back(
_pieces[i]);
3312 return all_constituents;
3314 std::vector<PseudoJet> CompositeJetStructure::pieces(
const PseudoJet & )
const{
3317 FJCORE_END_NAMESPACE
3319 FJCORE_BEGIN_NAMESPACE
3320 using namespace std;
3321 bool Error::_print_errors =
true;
3322 bool Error::_print_backtrace =
false;
3323 ostream * Error::_default_ostr = & cerr;
3324 #if (!defined(FJCORE_HAVE_EXECINFO_H)) || defined(__FJCORE__)
3327 Error::Error(
const std::string & message_in) {
3328 _message = message_in;
3329 if (_print_errors && _default_ostr){
3331 oss <<
"fjcore::Error: "<< message_in << endl;
3332 *_default_ostr << oss.str();
3333 _default_ostr->flush();
3336 void Error::set_print_backtrace(
bool enabled) {
3337 #if (!defined(FJCORE_HAVE_EXECINFO_H)) || defined(__FJCORE__)
3339 _execinfo_undefined.warn(
"Error::set_print_backtrace(true) will not work with this build of FastJet");
3342 _print_backtrace = enabled;
3344 FJCORE_END_NAMESPACE
3347 using namespace std;
3348 FJCORE_BEGIN_NAMESPACE
3349 FJCORE_END_NAMESPACE
3351 FJCORE_BEGIN_NAMESPACE
3352 using namespace std;
3353 const double JetDefinition::max_allowable_R = 1000.0;
3354 JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in,
3356 RecombinationScheme recomb_scheme_in,
3357 Strategy strategy_in,
3359 _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
3360 if (_jet_algorithm == ee_kt_algorithm) {
3363 if (R_in > max_allowable_R) {
3365 oss <<
"Requested R = " << R_in <<
" for jet definition is larger than max_allowable_R = " << max_allowable_R;
3366 throw Error(oss.str());
3369 unsigned int nparameters_expected = n_parameters_for_algorithm(jet_algorithm_in);
3370 if (nparameters != (
int) nparameters_expected){
3372 oss <<
"The jet algorithm you requested ("
3373 << jet_algorithm_in <<
") should be constructed with " << nparameters_expected
3374 <<
" parameter(s) but was called with " << nparameters <<
" parameter(s)\n";
3375 throw Error(oss.str());
3377 assert (_strategy != plugin_strategy);
3379 set_recombination_scheme(recomb_scheme_in);
3380 set_extra_param(0.0);
3382 bool JetDefinition::is_spherical()
const {
3383 if (jet_algorithm() == plugin_algorithm) {
3384 return plugin()->is_spherical();
3386 return (jet_algorithm() == ee_kt_algorithm ||
3387 jet_algorithm() == ee_genkt_algorithm
3391 string JetDefinition::description()
const {
3393 name << description_no_recombiner();
3394 if ((jet_algorithm() == plugin_algorithm) || (jet_algorithm() == undefined_jet_algorithm)){
3397 if (n_parameters_for_algorithm(jet_algorithm()) == 0)
3401 name << recombiner()->description();
3404 string JetDefinition::description_no_recombiner()
const {
3406 if (jet_algorithm() == plugin_algorithm) {
3407 return plugin()->description();
3408 }
else if (jet_algorithm() == undefined_jet_algorithm) {
3409 return "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
3411 name << algorithm_description(jet_algorithm());
3412 switch (n_parameters_for_algorithm(jet_algorithm())){
3413 case 0: name <<
" (NB: no R)";
break;
3414 case 1: name <<
" with R = " << R();
break;
3416 name <<
" with R = " << R();
3417 if (jet_algorithm() == cambridge_for_passive_algorithm){
3418 name <<
"and a special hack whereby particles with kt < "
3419 << extra_param() <<
"are treated as passive ghosts";
3421 name <<
", p = " << extra_param();
3426 string JetDefinition::algorithm_description(
const JetAlgorithm jet_alg){
3429 case plugin_algorithm:
return "plugin algorithm";
3430 case kt_algorithm:
return "Longitudinally invariant kt algorithm";
3431 case cambridge_algorithm:
return "Longitudinally invariant Cambridge/Aachen algorithm";
3432 case antikt_algorithm:
return "Longitudinally invariant anti-kt algorithm";
3433 case genkt_algorithm:
return "Longitudinally invariant generalised kt algorithm";
3434 case cambridge_for_passive_algorithm:
return "Longitudinally invariant Cambridge/Aachen algorithm";
3435 case ee_kt_algorithm:
return "e+e- kt (Durham) algorithm (NB: no R)";
3436 case ee_genkt_algorithm:
return "e+e- generalised kt algorithm";
3437 case undefined_jet_algorithm:
return "undefined jet algorithm";
3439 throw Error(
"JetDefinition::algorithm_description(): unrecognized jet_algorithm");
3442 unsigned int JetDefinition::n_parameters_for_algorithm(
const JetAlgorithm jet_alg){
3444 case ee_kt_algorithm:
return 0;
3445 case genkt_algorithm:
3446 case ee_genkt_algorithm:
return 2;
3450 void JetDefinition::set_recombination_scheme(
3451 RecombinationScheme recomb_scheme) {
3453 if (_shared_recombiner) _shared_recombiner.reset();
3456 void JetDefinition::set_recombiner(
const JetDefinition &other_jet_def){
3457 assert(other_jet_def._recombiner ||
3458 other_jet_def.recombination_scheme() != external_scheme);
3459 if (other_jet_def._recombiner == 0){
3460 set_recombination_scheme(other_jet_def.recombination_scheme());
3463 _recombiner = other_jet_def._recombiner;
3464 _default_recombiner = DefaultRecombiner(external_scheme);
3465 _shared_recombiner.reset(other_jet_def._shared_recombiner);
3467 bool JetDefinition::has_same_recombiner(
const JetDefinition &other_jd)
const{
3468 const RecombinationScheme & scheme = recombination_scheme();
3469 if (other_jd.recombination_scheme() != scheme)
return false;
3470 return (scheme != external_scheme)
3471 || (recombiner() == other_jd.recombiner());
3473 void JetDefinition::delete_recombiner_when_unused(){
3474 if (_recombiner == 0){
3475 throw Error(
"tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
3476 }
else if (_shared_recombiner.get()) {
3477 throw Error(
"Error in JetDefinition::delete_recombiner_when_unused: the recombiner is already scheduled for deletion when unused (or was already set as shared)");
3479 _shared_recombiner.reset(_recombiner);
3481 void JetDefinition::delete_plugin_when_unused(){
3483 throw Error(
"tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
3485 _plugin_shared.reset(_plugin);
3487 string JetDefinition::DefaultRecombiner::description()
const {
3488 switch(_recomb_scheme) {
3490 return "E scheme recombination";
3492 return "pt scheme recombination";
3494 return "pt2 scheme recombination";
3496 return "Et scheme recombination";
3498 return "Et2 scheme recombination";
3500 return "boost-invariant pt scheme recombination";
3502 return "boost-invariant pt2 scheme recombination";
3504 return "pt-ordered Winner-Takes-All recombination";
3505 case WTA_modp_scheme:
3506 return "|3-momentum|-ordered Winner-Takes-All recombination";
3509 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3511 throw Error(err.str());
3514 void JetDefinition::DefaultRecombiner::recombine(
3517 double weighta, weightb;
3518 switch(_recomb_scheme) {
3520 pab.reset(pa.px()+pb.px(),
3528 weighta = pa.perp();
3529 weightb = pb.perp();
3534 weighta = pa.perp2();
3535 weightb = pb.perp2();
3537 case WTA_pt_scheme:{
3538 const PseudoJet & phard = (pa.pt2() >= pb.pt2()) ? pa : pb;
3539 pab.reset_PtYPhiM(pa.pt()+pb.pt(),
3540 phard.rap(), phard.phi(), phard.m());
3542 case WTA_modp_scheme:{
3543 bool a_hardest = (pa.modp2() >= pb.modp2());
3544 const PseudoJet & phard = a_hardest ? pa : pb;
3545 const PseudoJet & psoft = a_hardest ? pb : pa;
3546 double modp_hard = phard.modp();
3547 double modp_ab = modp_hard + psoft.modp();
3548 if (phard.modp2()==0.0){
3549 pab.reset(0.0, 0.0, 0.0, phard.m());
3551 double scale = modp_ab/modp_hard;
3552 pab.reset(phard.px()*scale, phard.py()*scale, phard.pz()*scale,
3553 sqrt(modp_ab*modp_ab + phard.m2()));
3558 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3560 throw Error(err.str());
3562 double perp_ab = pa.perp() + pb.perp();
3563 if (perp_ab != 0.0) {
3564 double y_ab = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
3565 double phi_a = pa.phi(), phi_b = pb.phi();
3566 if (phi_a - phi_b > pi) phi_b += twopi;
3567 if (phi_a - phi_b < -pi) phi_b -= twopi;
3568 double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
3569 pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
3571 pab.reset(0.0, 0.0, 0.0, 0.0);
3574 void JetDefinition::DefaultRecombiner::preprocess(
PseudoJet & p)
const {
3575 switch(_recomb_scheme) {
3580 case WTA_modp_scheme:
3585 double newE = sqrt(p.perp2()+p.pz()*p.pz());
3586 p.reset_momentum(p.px(), p.py(), p.pz(), newE);
3592 double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
3593 p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
3598 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3600 throw Error(err.str());
3603 void JetDefinition::Plugin::set_ghost_separation_scale(
double )
const {
3604 throw Error(
"set_ghost_separation_scale not supported");
3608 if (pieces.size()>0){
3610 for (
unsigned int i=1; i<pieces.size(); i++)
3611 recombiner.plus_equal(result, pieces[i]);
3619 return join(vector<PseudoJet>(1,j1), recombiner);
3623 vector<PseudoJet> pieces;
3624 pieces.push_back(j1);
3625 pieces.push_back(j2);
3626 return join(pieces, recombiner);
3630 vector<PseudoJet> pieces;
3631 pieces.push_back(j1);
3632 pieces.push_back(j2);
3633 pieces.push_back(j3);
3634 return join(pieces, recombiner);
3638 vector<PseudoJet> pieces;
3639 pieces.push_back(j1);
3640 pieces.push_back(j2);
3641 pieces.push_back(j3);
3642 pieces.push_back(j4);
3643 return join(pieces, recombiner);
3645 FJCORE_END_NAMESPACE
3648 using namespace std;
3649 FJCORE_BEGIN_NAMESPACE
3650 ostream * LimitedWarning::_default_ostr = &cerr;
3651 std::list< LimitedWarning::Summary > LimitedWarning::_global_warnings_summary;
3652 int LimitedWarning::_max_warn_default = 5;
3653 void LimitedWarning::warn(
const char * warning, std::ostream * ostr) {
3654 if (_this_warning_summary == 0) {
3655 _global_warnings_summary.push_back(Summary(warning, 0));
3656 _this_warning_summary = & (_global_warnings_summary.back());
3658 if (_n_warn_so_far < _max_warn) {
3659 ostringstream warnstr;
3660 warnstr <<
"WARNING from FastJet: ";
3663 if (_n_warn_so_far == _max_warn) warnstr <<
" (LAST SUCH WARNING)";
3664 warnstr << std::endl;
3666 (*ostr) << warnstr.str();
3670 if (_this_warning_summary->second < numeric_limits<unsigned>::max()) {
3671 _this_warning_summary->second++;
3674 string LimitedWarning::summary() {
3676 for (list<Summary>::const_iterator it = _global_warnings_summary.begin();
3677 it != _global_warnings_summary.end(); it++) {
3678 str << it->second <<
" times: " << it->first << endl;
3682 FJCORE_END_NAMESPACE
3686 FJCORE_BEGIN_NAMESPACE
3687 using namespace std;
3688 void MinHeap::initialise(
const std::vector<double> & values){
3689 for (
unsigned i = values.size(); i < _heap.size(); i++) {
3690 _heap[i].value = std::numeric_limits<double>::max();
3691 _heap[i].minloc = &(_heap[i]);
3693 for (
unsigned i = 0; i < values.size(); i++) {
3694 _heap[i].value = values[i];
3695 _heap[i].minloc = &(_heap[i]);
3697 for (
unsigned i = _heap.size()-1; i > 0; i--) {
3698 ValueLoc * parent = &(_heap[(i-1)/2]);
3699 ValueLoc * here = &(_heap[i]);
3700 if (here->minloc->value < parent->minloc->value) {
3701 parent->minloc = here->minloc;
3705 void MinHeap::update(
unsigned int loc,
double new_value) {
3706 assert(loc < _heap.size());
3707 ValueLoc * start = &(_heap[loc]);
3708 if (start->minloc != start && !(new_value < start->minloc->value)) {
3709 start->value = new_value;
3712 start->value = new_value;
3713 start->minloc = start;
3714 bool change_made =
true;
3715 ValueLoc * heap_end = (&(_heap[0])) + _heap.size();
3716 while(change_made) {
3717 ValueLoc * here = &(_heap[loc]);
3718 change_made =
false;
3719 if (here->minloc == start) {
3720 here->minloc = here; change_made =
true;
3722 ValueLoc * child = &(_heap[2*loc+1]);
3723 if (child < heap_end && child->minloc->value < here->minloc->value ) {
3724 here->minloc = child->minloc;
3725 change_made =
true;}
3727 if (child < heap_end && child->minloc->value < here->minloc->value ) {
3728 here->minloc = child->minloc;
3729 change_made =
true;}
3730 if (loc == 0) {
break;}
3734 FJCORE_END_NAMESPACE
3741 FJCORE_BEGIN_NAMESPACE
3742 using namespace std;
3743 PseudoJet::PseudoJet(
const double px_in,
const double py_in,
const double pz_in,
const double E_in) {
3748 this->_finish_init();
3751 void PseudoJet::_finish_init () {
3752 _kt2 = this->px()*this->px() + this->py()*this->py();
3753 _phi = pseudojet_invalid_phi;
3754 _rap = pseudojet_invalid_rap;
3756 void PseudoJet::_set_rap_phi()
const {
3760 _phi = atan2(this->py(),this->px());
3762 if (_phi < 0.0) {_phi += twopi;}
3763 if (_phi >= twopi) {_phi -= twopi;}
3764 if (this->E() == abs(this->pz()) && _kt2 == 0) {
3765 double MaxRapHere = MaxRap + abs(this->pz());
3766 if (this->pz() >= 0.0) {_rap = MaxRapHere;}
else {_rap = -MaxRapHere;}
3768 double effective_m2 = max(0.0,m2());
3769 double E_plus_pz = _E + abs(_pz);
3770 _rap = 0.5*log((_kt2 + effective_m2)/(E_plus_pz*E_plus_pz));
3771 if (_pz > 0) {_rap = - _rap;}
3774 valarray<double> PseudoJet::four_mom()
const {
3775 valarray<double> mom(4);
3782 double PseudoJet::operator () (
int i)
const {
3794 err <<
"PseudoJet subscripting: bad index (" << i <<
")";
3795 throw Error(err.str());
3799 double PseudoJet::pseudorapidity()
const {
3800 if (px() == 0.0 && py() ==0.0)
return MaxRap;
3801 if (pz() == 0.0)
return 0.0;
3802 double theta = atan(perp()/pz());
3803 if (theta < 0) theta += pi;
3804 return -log(tan(theta/2));
3808 jet1.py()+jet2.py(),
3809 jet1.pz()+jet2.pz(),
3810 jet1.E() +jet2.E() );
3814 jet1.py()-jet2.py(),
3815 jet1.pz()-jet2.pz(),
3816 jet1.E() -jet2.E() );
3819 jet._ensure_valid_rap_phi();
3821 coeff_times_jet *= coeff;
3822 return coeff_times_jet;
3828 return (1.0/coeff)*jet;
3830 void PseudoJet::operator*=(
double coeff) {
3831 _ensure_valid_rap_phi();
3838 void PseudoJet::operator/=(
double coeff) {
3839 (*this) *= 1.0/coeff;
3841 void PseudoJet::operator+=(
const PseudoJet & other_jet) {
3842 _px += other_jet._px;
3843 _py += other_jet._py;
3844 _pz += other_jet._pz;
3845 _E += other_jet._E ;
3848 void PseudoJet::operator-=(
const PseudoJet & other_jet) {
3849 _px -= other_jet._px;
3850 _py -= other_jet._py;
3851 _pz -= other_jet._pz;
3852 _E -= other_jet._E ;
3856 if (a.px() != b.px())
return false;
3857 if (a.py() != b.py())
return false;
3858 if (a.pz() != b.pz())
return false;
3859 if (a.E () != b.E ())
return false;
3860 if (a.user_index() != b.user_index())
return false;
3861 if (a.cluster_hist_index() != b.cluster_hist_index())
return false;
3862 if (a.user_info_ptr() != b.user_info_ptr())
return false;
3863 if (a.structure_ptr() != b.structure_ptr())
return false;
3866 bool operator==(
const PseudoJet & jet,
const double val) {
3868 throw Error(
"comparing a PseudoJet with a non-zero constant (double) is not allowed.");
3869 return (jet.px() == 0 && jet.py() == 0 &&
3870 jet.pz() == 0 && jet.E() == 0);
3873 if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3875 double m_local = prest.m();
3876 assert(m_local != 0);
3877 double pf4 = ( px()*prest.px() + py()*prest.py()
3878 + pz()*prest.pz() + E()*prest.E() )/m_local;
3879 double fn = (pf4 + E()) / (prest.E() + m_local);
3880 _px += fn*prest.px();
3881 _py += fn*prest.py();
3882 _pz += fn*prest.pz();
3888 if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3890 double m_local = prest.m();
3891 assert(m_local != 0);
3892 double pf4 = ( -px()*prest.px() - py()*prest.py()
3893 - pz()*prest.pz() + E()*prest.E() )/m_local;
3894 double fn = (pf4 + E()) / (prest.E() + m_local);
3895 _px -= fn*prest.px();
3896 _py -= fn*prest.py();
3897 _pz -= fn*prest.pz();
3903 return jeta.px() == jetb.px()
3904 && jeta.py() == jetb.py()
3905 && jeta.pz() == jetb.pz()
3906 && jeta.E() == jetb.E();
3908 void PseudoJet::set_cached_rap_phi(
double rap_in,
double phi_in) {
3909 _rap = rap_in; _phi = phi_in;
3910 if (_phi >= twopi) _phi -= twopi;
3911 if (_phi < 0) _phi += twopi;
3913 void PseudoJet::reset_momentum_PtYPhiM(
double pt_in,
double y_in,
double phi_in,
double m_in) {
3914 assert(phi_in < 2*twopi && phi_in > -twopi);
3915 double ptm = (m_in == 0) ? pt_in : sqrt(pt_in*pt_in+m_in*m_in);
3916 double exprap = exp(y_in);
3917 double pminus = ptm/exprap;
3918 double pplus = ptm*exprap;
3919 double px_local = pt_in*cos(phi_in);
3920 double py_local = pt_in*sin(phi_in);
3921 reset_momentum(px_local,py_local,0.5*(pplus-pminus),0.5*(pplus+pminus));
3922 set_cached_rap_phi(y_in,phi_in);
3924 PseudoJet PtYPhiM(
double pt,
double y,
double phi,
double m) {
3925 assert(phi < 2*twopi && phi > -twopi);
3926 double ptm = (m == 0) ? pt : sqrt(pt*pt+m*m);
3927 double exprap = exp(y);
3928 double pminus = ptm/exprap;
3929 double pplus = ptm*exprap;
3930 double px = pt*cos(phi);
3931 double py = pt*sin(phi);
3932 PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
3933 mom.set_cached_rap_phi(y,phi);
3936 double PseudoJet::kt_distance(
const PseudoJet & other)
const {
3937 double distance = min(_kt2, other._kt2);
3938 double dphi = abs(phi() - other.phi());
3939 if (dphi > pi) {dphi = twopi - dphi;}
3940 double drap = rap() - other.rap();
3941 distance = distance * (dphi*dphi + drap*drap);
3944 double PseudoJet::plain_distance(
const PseudoJet & other)
const {
3945 double dphi = abs(phi() - other.phi());
3946 if (dphi > pi) {dphi = twopi - dphi;}
3947 double drap = rap() - other.rap();
3948 return (dphi*dphi + drap*drap);
3950 double PseudoJet::delta_phi_to(
const PseudoJet & other)
const {
3951 double dphi = other.phi() - phi();
3952 if (dphi > pi) dphi -= twopi;
3953 if (dphi < -pi) dphi += twopi;
3956 string PseudoJet::description()
const{
3958 return "standard PseudoJet (with no associated clustering information)";
3959 return _structure->description();
3961 bool PseudoJet::has_associated_cluster_sequence()
const{
3962 return (_structure) && (_structure->has_associated_cluster_sequence());
3964 const ClusterSequence* PseudoJet::associated_cluster_sequence()
const{
3965 if (! has_associated_cluster_sequence())
return NULL;
3966 return _structure->associated_cluster_sequence();
3968 bool PseudoJet::has_valid_cluster_sequence()
const{
3969 return (_structure) && (_structure->has_valid_cluster_sequence());
3972 return validated_structure_ptr()->validated_cs();
3975 _structure = structure_in;
3977 bool PseudoJet::has_structure()
const{
3978 return bool(_structure);
3981 return _structure.get();
3984 return _structure.get();
3988 throw Error(
"Trying to access the structure of a PseudoJet which has no associated structure");
3989 return _structure.get();
3994 bool PseudoJet::has_partner(
PseudoJet &partner)
const{
3995 return validated_structure_ptr()->has_partner(*
this, partner);
3997 bool PseudoJet::has_child(
PseudoJet &child)
const{
3998 return validated_structure_ptr()->has_child(*
this, child);
4001 return validated_structure_ptr()->has_parents(*
this, parent1, parent2);
4003 bool PseudoJet::contains(
const PseudoJet &constituent)
const{
4004 return validated_structure_ptr()->object_in_jet(constituent, *
this);
4006 bool PseudoJet::is_inside(
const PseudoJet &jet)
const{
4007 return validated_structure_ptr()->object_in_jet(*
this, jet);
4009 bool PseudoJet::has_constituents()
const{
4010 return (_structure) && (_structure->has_constituents());
4012 vector<PseudoJet> PseudoJet::constituents()
const{
4013 return validated_structure_ptr()->constituents(*
this);
4015 bool PseudoJet::has_exclusive_subjets()
const{
4016 return (_structure) && (_structure->has_exclusive_subjets());
4018 std::vector<PseudoJet> PseudoJet::exclusive_subjets (
const double dcut)
const {
4019 return validated_structure_ptr()->exclusive_subjets(*
this, dcut);
4021 int PseudoJet::n_exclusive_subjets(
const double dcut)
const {
4022 return validated_structure_ptr()->n_exclusive_subjets(*
this, dcut);
4024 std::vector<PseudoJet> PseudoJet::exclusive_subjets_up_to (
int nsub)
const {
4025 return validated_structure_ptr()->exclusive_subjets_up_to(*
this, nsub);
4027 std::vector<PseudoJet> PseudoJet::exclusive_subjets (
int nsub)
const {
4028 vector<PseudoJet> subjets = exclusive_subjets_up_to(nsub);
4029 if (
int(subjets.size()) < nsub) {
4031 err <<
"Requested " << nsub <<
" exclusive subjets, but there were only "
4032 << subjets.size() <<
" particles in the jet";
4033 throw Error(err.str());
4037 double PseudoJet::exclusive_subdmerge(
int nsub)
const {
4038 return validated_structure_ptr()->exclusive_subdmerge(*
this, nsub);
4040 double PseudoJet::exclusive_subdmerge_max(
int nsub)
const {
4041 return validated_structure_ptr()->exclusive_subdmerge_max(*
this, nsub);
4043 bool PseudoJet::has_pieces()
const{
4044 return ((_structure) && (_structure->has_pieces(*
this)));
4046 std::vector<PseudoJet> PseudoJet::pieces()
const{
4047 return validated_structure_ptr()->pieces(*
this);
4049 PseudoJet::InexistentUserInfo::InexistentUserInfo() :
Error(
"you attempted to perform a dynamic cast of a PseudoJet's extra info, but the extra info pointer was null")
4051 void sort_indices(vector<int> & indices,
4052 const vector<double> & values) {
4054 sort(indices.begin(), indices.end(), index_sort_helper);
4056 vector<PseudoJet> sorted_by_pt(
const vector<PseudoJet> & jets) {
4057 vector<double> minus_kt2(jets.size());
4058 for (
size_t i = 0; i < jets.size(); i++) {minus_kt2[i] = -jets[i].kt2();}
4059 return objects_sorted_by_values(jets, minus_kt2);
4061 vector<PseudoJet> sorted_by_rapidity(
const vector<PseudoJet> & jets) {
4062 vector<double> rapidities(jets.size());
4063 for (
size_t i = 0; i < jets.size(); i++) {rapidities[i] = jets[i].rap();}
4064 return objects_sorted_by_values(jets, rapidities);
4066 vector<PseudoJet> sorted_by_E(
const vector<PseudoJet> & jets) {
4067 vector<double> energies(jets.size());
4068 for (
size_t i = 0; i < jets.size(); i++) {energies[i] = -jets[i].E();}
4069 return objects_sorted_by_values(jets, energies);
4071 vector<PseudoJet> sorted_by_pz(
const vector<PseudoJet> & jets) {
4072 vector<double> pz(jets.size());
4073 for (
size_t i = 0; i < jets.size(); i++) {pz[i] = jets[i].pz();}
4074 return objects_sorted_by_values(jets, pz);
4076 PseudoJet join(
const vector<PseudoJet> & pieces){
4078 for (
unsigned int i=0; i<pieces.size(); i++)
4079 result += pieces[i];
4085 return join(vector<PseudoJet>(1,j1));
4088 vector<PseudoJet> pieces;
4090 pieces.push_back(j1);
4091 pieces.push_back(j2);
4092 return join(pieces);
4095 vector<PseudoJet> pieces;
4097 pieces.push_back(j1);
4098 pieces.push_back(j2);
4099 pieces.push_back(j3);
4100 return join(pieces);
4103 vector<PseudoJet> pieces;
4105 pieces.push_back(j1);
4106 pieces.push_back(j2);
4107 pieces.push_back(j3);
4108 pieces.push_back(j4);
4109 return join(pieces);
4111 FJCORE_END_NAMESPACE
4112 using namespace std;
4113 FJCORE_BEGIN_NAMESPACE
4114 const ClusterSequence* PseudoJetStructureBase::associated_cluster_sequence()
const{
4118 throw Error(
"This PseudoJet structure is not associated with a valid ClusterSequence");
4121 throw Error(
"This PseudoJet structure has no implementation for has_partner");
4124 throw Error(
"This PseudoJet structure has no implementation for has_child");
4127 throw Error(
"This PseudoJet structure has no implementation for has_parents");
4129 bool PseudoJetStructureBase::object_in_jet(
const PseudoJet & ,
const PseudoJet & )
const{
4130 throw Error(
"This PseudoJet structure has no implementation for is_inside");
4132 vector<PseudoJet> PseudoJetStructureBase::constituents(
const PseudoJet &)
const{
4133 throw Error(
"This PseudoJet structure has no implementation for constituents");
4135 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets (
const PseudoJet & ,
const double & )
const{
4136 throw Error(
"This PseudoJet structure has no implementation for exclusive_subjets");
4138 int PseudoJetStructureBase::n_exclusive_subjets(
const PseudoJet & ,
const double & )
const{
4139 throw Error(
"This PseudoJet structure has no implementation for n_exclusive_subjets");
4141 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets_up_to (
const PseudoJet & ,
int )
const{
4142 throw Error(
"This PseudoJet structure has no implementation for exclusive_subjets");
4144 double PseudoJetStructureBase::exclusive_subdmerge(
const PseudoJet & ,
int )
const{
4145 throw Error(
"This PseudoJet structure has no implementation for exclusive_submerge");
4147 double PseudoJetStructureBase::exclusive_subdmerge_max(
const PseudoJet & ,
int )
const{
4148 throw Error(
"This PseudoJet structure has no implementation for exclusive_submerge_max");
4150 std::vector<PseudoJet> PseudoJetStructureBase::pieces(
const PseudoJet & )
const{
4151 throw Error(
"This PseudoJet structure has no implementation for pieces");
4153 FJCORE_END_NAMESPACE
4155 #include <algorithm>
4156 using namespace std;
4157 FJCORE_BEGIN_NAMESPACE
4158 std::vector<PseudoJet> Selector::operator()(
const std::vector<PseudoJet> & jets)
const {
4159 std::vector<PseudoJet> result;
4161 if (worker_local->applies_jet_by_jet()) {
4162 for (std::vector<PseudoJet>::const_iterator jet = jets.begin();
4163 jet != jets.end(); jet++) {
4164 if (worker_local->pass(*jet)) result.push_back(*jet);
4167 std::vector<const PseudoJet *> jetptrs(jets.size());
4168 for (
unsigned i = 0; i < jets.size(); i++) {
4169 jetptrs[i] = & jets[i];
4171 worker_local->terminator(jetptrs);
4172 for (
unsigned i = 0; i < jetptrs.size(); i++) {
4173 if (jetptrs[i]) result.push_back(jets[i]);
4178 unsigned int Selector::count(
const std::vector<PseudoJet> & jets)
const {
4181 if (worker_local->applies_jet_by_jet()) {
4182 for (
unsigned i = 0; i < jets.size(); i++) {
4183 if (worker_local->pass(jets[i])) n++;
4186 std::vector<const PseudoJet *> jetptrs(jets.size());
4187 for (
unsigned i = 0; i < jets.size(); i++) {
4188 jetptrs[i] = & jets[i];
4190 worker_local->terminator(jetptrs);
4191 for (
unsigned i = 0; i < jetptrs.size(); i++) {
4192 if (jetptrs[i]) n++;
4197 PseudoJet Selector::sum(
const std::vector<PseudoJet> & jets)
const {
4200 if (worker_local->applies_jet_by_jet()) {
4201 for (
unsigned i = 0; i < jets.size(); i++) {
4202 if (worker_local->pass(jets[i])) this_sum += jets[i];
4205 std::vector<const PseudoJet *> jetptrs(jets.size());
4206 for (
unsigned i = 0; i < jets.size(); i++) {
4207 jetptrs[i] = & jets[i];
4209 worker_local->terminator(jetptrs);
4210 for (
unsigned i = 0; i < jetptrs.size(); i++) {
4211 if (jetptrs[i]) this_sum += jets[i];
4216 double Selector::scalar_pt_sum(
const std::vector<PseudoJet> & jets)
const {
4217 double this_sum = 0.0;
4219 if (worker_local->applies_jet_by_jet()) {
4220 for (
unsigned i = 0; i < jets.size(); i++) {
4221 if (worker_local->pass(jets[i])) this_sum += jets[i].pt();
4224 std::vector<const PseudoJet *> jetptrs(jets.size());
4225 for (
unsigned i = 0; i < jets.size(); i++) {
4226 jetptrs[i] = & jets[i];
4228 worker_local->terminator(jetptrs);
4229 for (
unsigned i = 0; i < jetptrs.size(); i++) {
4230 if (jetptrs[i]) this_sum += jets[i].pt();
4235 void Selector::sift(
const std::vector<PseudoJet> & jets,
4236 std::vector<PseudoJet> & jets_that_pass,
4237 std::vector<PseudoJet> & jets_that_fail
4240 jets_that_pass.clear();
4241 jets_that_fail.clear();
4242 if (worker_local->applies_jet_by_jet()) {
4243 for (
unsigned i = 0; i < jets.size(); i++) {
4244 if (worker_local->pass(jets[i])) {
4245 jets_that_pass.push_back(jets[i]);
4247 jets_that_fail.push_back(jets[i]);
4251 std::vector<const PseudoJet *> jetptrs(jets.size());
4252 for (
unsigned i = 0; i < jets.size(); i++) {
4253 jetptrs[i] = & jets[i];
4255 worker_local->terminator(jetptrs);
4256 for (
unsigned i = 0; i < jetptrs.size(); i++) {
4258 jets_that_pass.push_back(jets[i]);
4260 jets_that_fail.push_back(jets[i]);
4265 bool SelectorWorker::has_finite_area()
const {
4266 if (! is_geometric())
return false;
4267 double rapmin, rapmax;
4268 get_rapidity_extent(rapmin, rapmax);
4269 return (rapmax != std::numeric_limits<double>::infinity())
4270 && (-rapmin != std::numeric_limits<double>::infinity());
4275 virtual bool pass(
const PseudoJet &)
const {
4278 virtual void terminator(vector<const PseudoJet *> &)
const {
4281 virtual string description()
const {
return "Identity";}
4282 virtual bool is_geometric()
const {
return true;}
4291 virtual bool pass(
const PseudoJet & jet)
const {
4292 if (!applies_jet_by_jet())
4293 throw Error(
"Cannot apply this selector worker to an individual jet");
4294 return ! _s.pass(jet);
4296 virtual bool applies_jet_by_jet()
const {
return _s.applies_jet_by_jet();}
4297 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4298 if (applies_jet_by_jet()){
4299 SelectorWorker::terminator(jets);
4302 vector<const PseudoJet *> s_jets = jets;
4303 _s.worker()->terminator(s_jets);
4304 for (
unsigned int i=0; i<s_jets.size(); i++){
4305 if (s_jets[i]) jets[i] = NULL;
4308 virtual string description()
const {
4310 ostr <<
"!(" << _s.description() <<
")";
4313 virtual bool is_geometric()
const {
return _s.is_geometric();}
4314 virtual bool takes_reference()
const {
return _s.takes_reference();}
4315 virtual void set_reference(
const PseudoJet &ref) { _s.set_reference(ref);}
4325 _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
4326 _takes_reference = _s1.takes_reference() || _s2.takes_reference();
4327 _is_geometric = _s1.is_geometric() && _s2.is_geometric();
4329 virtual bool applies_jet_by_jet()
const {
return _applies_jet_by_jet;}
4330 virtual bool takes_reference()
const{
4331 return _takes_reference;
4333 virtual void set_reference(
const PseudoJet ¢re){
4334 _s1.set_reference(centre);
4335 _s2.set_reference(centre);
4337 virtual bool is_geometric()
const {
return _is_geometric;}
4340 bool _applies_jet_by_jet;
4341 bool _takes_reference;
4348 virtual bool pass(
const PseudoJet & jet)
const {
4349 if (!applies_jet_by_jet())
4350 throw Error(
"Cannot apply this selector worker to an individual jet");
4351 return _s1.pass(jet) && _s2.pass(jet);
4353 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4354 if (applies_jet_by_jet()){
4355 SelectorWorker::terminator(jets);
4358 vector<const PseudoJet *> s1_jets = jets;
4359 _s1.worker()->terminator(s1_jets);
4360 _s2.worker()->terminator(jets);
4361 for (
unsigned int i=0; i<jets.size(); i++){
4362 if (! s1_jets[i]) jets[i] = NULL;
4365 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const {
4366 double s1min, s1max, s2min, s2max;
4367 _s1.get_rapidity_extent(s1min, s1max);
4368 _s2.get_rapidity_extent(s2min, s2max);
4369 rapmax = min(s1max, s2max);
4370 rapmin = max(s1min, s2min);
4372 virtual string description()
const {
4374 ostr <<
"(" << _s1.description() <<
" && " << _s2.description() <<
")";
4385 virtual bool pass(
const PseudoJet & jet)
const {
4386 if (!applies_jet_by_jet())
4387 throw Error(
"Cannot apply this selector worker to an individual jet");
4388 return _s1.pass(jet) || _s2.pass(jet);
4390 virtual bool applies_jet_by_jet()
const {
4391 return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
4393 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4394 if (applies_jet_by_jet()){
4395 SelectorWorker::terminator(jets);
4398 vector<const PseudoJet *> s1_jets = jets;
4399 _s1.worker()->terminator(s1_jets);
4400 _s2.worker()->terminator(jets);
4401 for (
unsigned int i=0; i<jets.size(); i++){
4402 if (s1_jets[i]) jets[i] = s1_jets[i];
4405 virtual string description()
const {
4407 ostr <<
"(" << _s1.description() <<
" || " << _s2.description() <<
")";
4410 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const {
4411 double s1min, s1max, s2min, s2max;
4412 _s1.get_rapidity_extent(s1min, s1max);
4413 _s2.get_rapidity_extent(s2min, s2max);
4414 rapmax = max(s1max, s2max);
4415 rapmin = min(s1min, s2min);
4425 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4426 if (applies_jet_by_jet()){
4427 SelectorWorker::terminator(jets);
4430 _s2.worker()->terminator(jets);
4431 _s1.worker()->terminator(jets);
4433 virtual string description()
const {
4435 ostr <<
"(" << _s1.description() <<
" * " << _s2.description() <<
")";
4446 virtual double operator()(
const PseudoJet & jet )
const =0;
4447 virtual string description()
const =0;
4448 virtual bool is_geometric()
const {
return false;}
4449 virtual double comparison_value()
const {
return _q;}
4450 virtual double description_value()
const {
return comparison_value();}
4457 virtual double description_value()
const {
return _sqrtq;}
4461 template<
typename QuantityType>
4465 virtual bool pass(
const PseudoJet & jet)
const {
return _qmin(jet) >= _qmin.comparison_value();}
4466 virtual string description()
const {
4468 ostr << _qmin.description() <<
" >= " << _qmin.description_value();
4471 virtual bool is_geometric()
const {
return _qmin.is_geometric();}
4475 template<
typename QuantityType>
4479 virtual bool pass(
const PseudoJet & jet)
const {
return _qmax(jet) <= _qmax.comparison_value();}
4480 virtual string description()
const {
4482 ostr << _qmax.description() <<
" <= " << _qmax.description_value();
4485 virtual bool is_geometric()
const {
return _qmax.is_geometric();}
4489 template<
typename QuantityType>
4493 virtual bool pass(
const PseudoJet & jet)
const {
4494 double q = _qmin(jet);
4495 return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
4497 virtual string description()
const {
4499 ostr << _qmin.description_value() <<
" <= " << _qmin.description() <<
" <= " << _qmax.description_value();
4502 virtual bool is_geometric()
const {
return _qmin.is_geometric();}
4510 virtual double operator()(
const PseudoJet & jet )
const {
return jet.perp2();}
4511 virtual string description()
const {
return "pt";}
4513 Selector SelectorPtMin(
double ptmin) {
4516 Selector SelectorPtMax(
double ptmax) {
4519 Selector SelectorPtRange(
double ptmin,
double ptmax) {
4525 virtual double operator()(
const PseudoJet & jet )
const {
return jet.Et2();}
4526 virtual string description()
const {
return "Et";}
4528 Selector SelectorEtMin(
double Etmin) {
4531 Selector SelectorEtMax(
double Etmax) {
4534 Selector SelectorEtRange(
double Etmin,
double Etmax) {
4540 virtual double operator()(
const PseudoJet & jet )
const {
return jet.E();}
4541 virtual string description()
const {
return "E";}
4543 Selector SelectorEMin(
double Emin) {
4546 Selector SelectorEMax(
double Emax) {
4549 Selector SelectorERange(
double Emin,
double Emax) {
4555 virtual double operator()(
const PseudoJet & jet )
const {
return jet.m2();}
4556 virtual string description()
const {
return "mass";}
4558 Selector SelectorMassMin(
double mmin) {
4561 Selector SelectorMassMax(
double mmax) {
4564 Selector SelectorMassRange(
double mmin,
double mmax) {
4570 virtual double operator()(
const PseudoJet & jet )
const {
return jet.rap();}
4571 virtual string description()
const {
return "rap";}
4572 virtual bool is_geometric()
const {
return true;}
4577 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4578 rapmax = std::numeric_limits<double>::max();
4579 rapmin = _qmin.comparison_value();
4585 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4586 rapmax = _qmax.comparison_value();
4587 rapmin = -std::numeric_limits<double>::max();
4593 assert(rapmin<=rapmax);
4595 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4596 rapmax = _qmax.comparison_value();
4597 rapmin = _qmin.comparison_value();
4600 virtual double known_area()
const {
4601 return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
4604 Selector SelectorRapMin(
double rapmin) {
4607 Selector SelectorRapMax(
double rapmax) {
4610 Selector SelectorRapRange(
double rapmin,
double rapmax) {
4616 virtual double operator()(
const PseudoJet & jet )
const {
return abs(jet.rap());}
4617 virtual string description()
const {
return "|rap|";}
4618 virtual bool is_geometric()
const {
return true;}
4623 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4624 rapmax = _qmax.comparison_value();
4625 rapmin = -_qmax.comparison_value();
4628 virtual double known_area()
const {
4629 return twopi * 2 * _qmax.comparison_value();
4635 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4636 rapmax = _qmax.comparison_value();
4637 rapmin = -_qmax.comparison_value();
4640 virtual double known_area()
const {
4641 return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0));
4644 Selector SelectorAbsRapMin(
double absrapmin) {
4647 Selector SelectorAbsRapMax(
double absrapmax) {
4650 Selector SelectorAbsRapRange(
double rapmin,
double rapmax) {
4656 virtual double operator()(
const PseudoJet & jet )
const {
return jet.eta();}
4657 virtual string description()
const {
return "eta";}
4659 Selector SelectorEtaMin(
double etamin) {
4662 Selector SelectorEtaMax(
double etamax) {
4665 Selector SelectorEtaRange(
double etamin,
double etamax) {
4671 virtual double operator()(
const PseudoJet & jet )
const {
return abs(jet.eta());}
4672 virtual string description()
const {
return "|eta|";}
4673 virtual bool is_geometric()
const {
return true;}
4675 Selector SelectorAbsEtaMin(
double absetamin) {
4678 Selector SelectorAbsEtaMax(
double absetamax) {
4681 Selector SelectorAbsEtaRange(
double absetamin,
double absetamax) {
4686 SW_PhiRange(
double phimin,
double phimax) : _phimin(phimin), _phimax(phimax){
4687 assert(_phimin<_phimax);
4688 assert(_phimin>-twopi);
4689 assert(_phimax<2*twopi);
4690 _phispan = _phimax - _phimin;
4692 virtual bool pass(
const PseudoJet & jet)
const {
4693 double dphi=jet.phi()-_phimin;
4694 if (dphi >= twopi) dphi -= twopi;
4695 if (dphi < 0) dphi += twopi;
4696 return (dphi <= _phispan);
4698 virtual string description()
const {
4700 ostr << _phimin <<
" <= phi <= " << _phimax;
4703 virtual bool is_geometric()
const {
return true;}
4709 Selector SelectorPhiRange(
double phimin,
double phimax) {
4714 SW_RapPhiRange(
double rapmin,
double rapmax,
double phimin,
double phimax)
4715 :
SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
4716 _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
4718 virtual double known_area()
const{
4724 Selector SelectorRapPhiRange(
double rapmin,
double rapmax,
double phimin,
double phimax) {
4730 virtual bool pass(
const PseudoJet &)
const {
4731 if (!applies_jet_by_jet())
4732 throw Error(
"Cannot apply this selector worker to an individual jet");
4735 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4736 if (jets.size() < _n)
return;
4737 vector<double> minus_pt2(jets.size());
4738 vector<unsigned int> indices(jets.size());
4739 for (
unsigned int i=0; i<jets.size(); i++){
4741 minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
4744 partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
4745 for (
unsigned int i=_n; i<jets.size(); i++)
4746 jets[indices[i]] = NULL;
4748 virtual bool applies_jet_by_jet()
const {
return false;}
4749 virtual string description()
const {
4751 ostr << _n <<
" hardest";
4757 Selector SelectorNHardest(
unsigned int n) {
4763 virtual bool takes_reference()
const {
return true;}
4764 virtual void set_reference(
const PseudoJet ¢re){
4765 _is_initialised =
true;
4766 _reference = centre;
4770 bool _is_initialised;
4774 SW_Circle(
const double radius) : _radius2(radius*radius) {}
4776 virtual bool pass(
const PseudoJet & jet)
const {
4777 if (! _is_initialised)
4778 throw Error(
"To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4779 return jet.squared_distance(_reference) <= _radius2;
4781 virtual string description()
const {
4783 ostr <<
"distance from the centre <= " << sqrt(_radius2);
4786 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4787 if (! _is_initialised)
4788 throw Error(
"To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4789 rapmax = _reference.rap()+sqrt(_radius2);
4790 rapmin = _reference.rap()-sqrt(_radius2);
4795 virtual double known_area()
const {
4796 return pi * _radius2;
4801 Selector SelectorCircle(
const double radius) {
4806 SW_Doughnut(
const double radius_in,
const double radius_out)
4807 : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
4809 virtual bool pass(
const PseudoJet & jet)
const {
4810 if (! _is_initialised)
4811 throw Error(
"To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4812 double distance2 = jet.squared_distance(_reference);
4813 return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
4815 virtual string description()
const {
4817 ostr << sqrt(_radius_in2) <<
" <= distance from the centre <= " << sqrt(_radius_out2);
4820 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4821 if (! _is_initialised)
4822 throw Error(
"To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4823 rapmax = _reference.rap()+sqrt(_radius_out2);
4824 rapmin = _reference.rap()-sqrt(_radius_out2);
4829 virtual double known_area()
const {
4830 return pi * (_radius_out2-_radius_in2);
4833 double _radius_in2, _radius_out2;
4835 Selector SelectorDoughnut(
const double radius_in,
const double radius_out) {
4840 SW_Strip(
const double delta) : _delta(delta) {}
4842 virtual bool pass(
const PseudoJet & jet)
const {
4843 if (! _is_initialised)
4844 throw Error(
"To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4845 return abs(jet.rap()-_reference.rap()) <= _delta;
4847 virtual string description()
const {
4849 ostr <<
"|rap - rap_reference| <= " << _delta;
4852 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4853 if (! _is_initialised)
4854 throw Error(
"To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4855 rapmax = _reference.rap()+_delta;
4856 rapmin = _reference.rap()-_delta;
4861 virtual double known_area()
const {
4862 return twopi * 2 * _delta;
4867 Selector SelectorStrip(
const double half_width) {
4872 SW_Rectangle(
const double delta_rap,
const double delta_phi)
4873 : _delta_rap(delta_rap), _delta_phi(delta_phi) {}
4875 virtual bool pass(
const PseudoJet & jet)
const {
4876 if (! _is_initialised)
4877 throw Error(
"To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4878 return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi);
4880 virtual string description()
const {
4882 ostr <<
"|rap - rap_reference| <= " << _delta_rap <<
" && |phi - phi_reference| <= " << _delta_phi ;
4885 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4886 if (! _is_initialised)
4887 throw Error(
"To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4888 rapmax = _reference.rap()+_delta_rap;
4889 rapmin = _reference.rap()-_delta_rap;
4894 virtual double known_area()
const {
4895 return 4 * _delta_rap * _delta_phi;
4898 double _delta_rap, _delta_phi;
4900 Selector SelectorRectangle(
const double half_rap_width,
const double half_phi_width) {
4907 virtual bool pass(
const PseudoJet & jet)
const {
4908 if (! _is_initialised)
4909 throw Error(
"To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)");
4910 return (jet.perp2() >= _fraction2*_reference.perp2());
4912 virtual string description()
const {
4914 ostr <<
"pt >= " << sqrt(_fraction2) <<
"* pt_ref";
4920 Selector SelectorPtFractionMin(
double fraction){
4926 virtual bool pass(
const PseudoJet & jet)
const {
4929 virtual string description()
const {
return "zero";}
4935 _worker.reset(
new SW_And(*
this, b));
4939 _worker.reset(
new SW_Or(*
this, b));
4942 FJCORE_END_NAMESPACE
4944 using namespace std;
4945 FJCORE_BEGIN_NAMESPACE
4947 _cs(cs), _jets(cs.jets())
4952 #endif // INSTRUMENT2
4953 _Rparam = cs.jet_def().R();
4954 _R2 = _Rparam * _Rparam;
4956 _initialise_tiles();
4958 void LazyTiling25::_initialise_tiles() {
4959 double default_size = max(0.1,_Rparam)/2;
4960 _tile_size_eta = default_size;
4961 _n_tiles_phi = max(5,
int(floor(twopi/default_size)));
4962 _tile_size_phi = twopi / _n_tiles_phi;
4963 #define _FJCORE_TILING25_USE_TILING_ANALYSIS_
4964 #ifdef _FASTJET_TILING25_USE_TILING_ANALYSIS_
4966 _tiles_eta_min = tiling_analysis.minrap();
4967 _tiles_eta_max = tiling_analysis.maxrap();
4968 #else // not _FASTJET_TILING25_USE_TILING_ANALYSIS_
4969 _tiles_eta_min = 0.0;
4970 _tiles_eta_max = 0.0;
4971 const double maxrap = 7.0;
4972 for(
unsigned int i = 0; i < _jets.size(); i++) {
4973 double eta = _jets[i].rap();
4974 if (abs(eta) < maxrap) {
4975 if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
4976 if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
4979 #endif // _FASTJET_TILING25_USE_TILING_ANALYSIS_
4980 # define FJCORE_LAZY25_MIN3TILESY
4981 #ifdef FJCORE_LAZY25_MIN3TILESY
4982 if (_tiles_eta_max - _tiles_eta_min < 3*_tile_size_eta) {
4983 _tile_size_eta = (_tiles_eta_max - _tiles_eta_min)/3;
4984 _tiles_ieta_min = 0;
4985 _tiles_ieta_max = 2;
4986 _tiles_eta_max -= _tile_size_eta;
4988 #endif //FASTJET_LAZY25_MIN3TILESY
4989 _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
4990 _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
4991 _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
4992 _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
4993 #ifdef FJCORE_LAZY25_MIN3TILESY
4996 _tile_half_size_eta = _tile_size_eta * 0.5;
4997 _tile_half_size_phi = _tile_size_phi * 0.5;
4998 vector<bool> use_periodic_delta_phi(_n_tiles_phi,
false);
4999 if (_n_tiles_phi <= 5) {
5000 fill(use_periodic_delta_phi.begin(), use_periodic_delta_phi.end(),
true);
5002 use_periodic_delta_phi[0] =
true;
5003 use_periodic_delta_phi[1] =
true;
5004 use_periodic_delta_phi[_n_tiles_phi-2] =
true;
5005 use_periodic_delta_phi[_n_tiles_phi-1] =
true;
5007 _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
5008 for (
int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
5009 for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
5010 Tile25 * tile = & _tiles[_tile_index(ieta,iphi)];
5012 tile->begin_tiles[0] = tile;
5013 Tile25 ** pptile = & (tile->begin_tiles[0]);
5015 tile->surrounding_tiles = pptile;
5016 if (ieta > _tiles_ieta_min) {
5020 for (
int idphi = -2; idphi <=+2; idphi++) {
5021 *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
5025 if (ieta > _tiles_ieta_min + 1) {
5029 for (
int idphi = -2; idphi <= +2; idphi++) {
5030 *pptile = & _tiles[_tile_index(ieta-2,iphi+idphi)];
5034 *pptile = & _tiles[_tile_index(ieta,iphi-1)];
5036 *pptile = & _tiles[_tile_index(ieta,iphi-2)];
5038 tile->RH_tiles = pptile;
5039 *pptile = & _tiles[_tile_index(ieta,iphi+1)];
5041 *pptile = & _tiles[_tile_index(ieta,iphi+2)];
5043 if (ieta < _tiles_ieta_max) {
5044 for (
int idphi = -2; idphi <= +2; idphi++) {
5045 *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
5049 if (ieta < _tiles_ieta_max - 1) {
5050 for (
int idphi = -2; idphi <= +2; idphi++) {
5051 *pptile = & _tiles[_tile_index(ieta+2,iphi+idphi)];
5055 tile->end_tiles = pptile;
5056 tile->tagged =
false;
5057 tile->use_periodic_delta_phi = use_periodic_delta_phi[iphi];
5058 tile->max_NN_dist = 0;
5059 tile->eta_centre = (ieta-_tiles_ieta_min+0.5)*_tile_size_eta + _tiles_eta_min;
5060 tile->phi_centre = (iphi+0.5)*_tile_size_phi;
5064 int LazyTiling25::_tile_index(
const double eta,
const double phi)
const {
5066 if (eta <= _tiles_eta_min) {ieta = 0;}
5067 else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
5069 ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
5070 if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
5071 ieta = _tiles_ieta_max-_tiles_ieta_min;}
5073 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
5074 return (iphi + ieta * _n_tiles_phi);
5076 inline void LazyTiling25::_tj_set_jetinfo(
TiledJet *
const jet,
5077 const int _jets_index) {
5078 _bj_set_jetinfo<>(jet, _jets_index);
5079 jet->tile_index = _tile_index(jet->eta, jet->phi);
5080 Tile25 * tile = &_tiles[jet->tile_index];
5081 jet->previous = NULL;
5082 jet->next = tile->head;
5083 if (jet->next != NULL) {jet->next->previous = jet;}
5086 void LazyTiling25::_bj_remove_from_tiles(
TiledJet *
const jet) {
5087 Tile25 * tile = & _tiles[jet->tile_index];
5088 if (jet->previous == NULL) {
5089 tile->head = jet->next;
5091 jet->previous->next = jet->next;
5093 if (jet->next != NULL) {
5094 jet->next->previous = jet->previous;
5097 void LazyTiling25::_print_tiles(
TiledJet * briefjets )
const {
5098 for (vector<Tile25>::const_iterator tile = _tiles.begin();
5099 tile < _tiles.end(); tile++) {
5100 cout <<
"Tile " << tile - _tiles.begin()
5101 <<
" at " << setw(10) << tile->eta_centre <<
"," << setw(10) << tile->phi_centre
5104 for (
TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
5105 list.push_back(jetI-briefjets);
5107 sort(list.begin(),list.end());
5108 for (
unsigned int i = 0; i < list.size(); i++) {cout <<
" "<<list[i];}
5112 void LazyTiling25::_add_neighbours_to_tile_union(
const int tile_index,
5113 vector<int> & tile_union,
int & n_near_tiles)
const {
5114 for (Tile25 *
const * near_tile = _tiles[tile_index].begin_tiles;
5115 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5116 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5120 inline void LazyTiling25::_add_untagged_neighbours_to_tile_union(
5121 const int tile_index,
5122 vector<int> & tile_union,
int & n_near_tiles) {
5123 for (Tile25 ** near_tile = _tiles[tile_index].begin_tiles;
5124 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5125 if (! (*near_tile)->tagged) {
5126 (*near_tile)->tagged =
true;
5127 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5132 inline void LazyTiling25::_add_untagged_neighbours_to_tile_union_using_max_info(
5134 vector<int> & tile_union,
int & n_near_tiles) {
5135 Tile25 & tile = _tiles[jet->tile_index];
5136 for (Tile25 ** near_tile = tile.begin_tiles; near_tile != tile.end_tiles; near_tile++){
5137 if ((*near_tile)->tagged)
continue;
5138 double dist = _distance_to_tile(jet, *near_tile) - tile_edge_security_margin;
5139 if (dist > (*near_tile)->max_NN_dist)
continue;
5140 (*near_tile)->tagged =
true;
5141 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5145 inline double LazyTiling25::_distance_to_tile(
const TiledJet * bj,
const Tile25 * tile)
5151 #endif // INSTRUMENT2
5153 if (_tiles[bj->tile_index].eta_centre == tile->eta_centre) deta = 0;
5154 else deta = std::abs(bj->eta - tile->eta_centre) - _tile_half_size_eta;
5155 double dphi = std::abs(bj->phi - tile->phi_centre);
5156 if (dphi > pi) dphi = twopi-dphi;
5157 dphi -= _tile_half_size_phi;
5158 if (dphi < 0) dphi = 0;
5159 return dphi*dphi + deta*deta;
5161 inline void LazyTiling25::_update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, vector<TiledJet *> & jets_for_minheap) {
5162 double dist = _bj_dist(jetI,jetX);
5163 if (dist < jetI->NN_dist) {
5165 jetI->NN_dist = dist;
5167 if (!jetI->minheap_update_needed()) {
5168 jetI->label_minheap_update_needed();
5169 jets_for_minheap.push_back(jetI);
5173 if (dist < jetX->NN_dist) {
5175 jetX->NN_dist = dist;
5179 inline void LazyTiling25::_set_NN(
TiledJet * jetI,
5180 vector<TiledJet *> & jets_for_minheap) {
5181 jetI->NN_dist = _R2;
5183 if (!jetI->minheap_update_needed()) {
5184 jetI->label_minheap_update_needed();
5185 jets_for_minheap.push_back(jetI);}
5186 Tile25 * tile_ptr = &_tiles[jetI->tile_index];
5187 for (Tile25 ** near_tile = tile_ptr->begin_tiles;
5188 near_tile != tile_ptr->end_tiles; near_tile++) {
5189 if (jetI->NN_dist < _distance_to_tile(jetI, *near_tile))
continue;
5190 for (
TiledJet * jetJ = (*near_tile)->head;
5191 jetJ != NULL; jetJ = jetJ->next) {
5192 double dist = _bj_dist(jetI,jetJ);
5193 if (dist < jetI->NN_dist && jetJ != jetI) {
5194 jetI->NN_dist = dist; jetI->NN = jetJ;
5199 void LazyTiling25::run() {
5200 int n = _jets.size();
5203 TiledJet * jetA = briefjets, * jetB;
5205 vector<int> tile_union(3*25);
5206 for (
int i = 0; i< n; i++) {
5207 _tj_set_jetinfo(jetA, i);
5211 vector<Tile25>::iterator tile;
5212 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5213 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5214 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
5215 double dist = _bj_dist_not_periodic(jetA,jetB);
5216 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5217 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5220 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5221 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
5224 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5225 if (tile->use_periodic_delta_phi) {
5226 for (Tile25 ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
5227 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5228 double dist_to_tile = _distance_to_tile(jetA, *RTile);
5229 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
5230 bool relevant_for_RTile = dist_to_tile <= (*RTile)->max_NN_dist;
5231 if (relevant_for_jetA || relevant_for_RTile) {
5232 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
5233 double dist = _bj_dist(jetA,jetB);
5234 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5235 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5241 for (Tile25 ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
5242 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5243 double dist_to_tile = _distance_to_tile(jetA, *RTile);
5244 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
5245 bool relevant_for_RTile = dist_to_tile <= (*RTile)->max_NN_dist;
5246 if (relevant_for_jetA || relevant_for_RTile) {
5247 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
5248 double dist = _bj_dist_not_periodic(jetA,jetB);
5249 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5250 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5257 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5258 tile->max_NN_dist = 0;
5259 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5260 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
5264 cout <<
"intermediate ncall, dtt = " << _ncall <<
" " << _ncall_dtt << endl;
5265 #endif // INSTRUMENT2
5266 vector<double> diJs(n);
5267 for (
int i = 0; i < n; i++) {
5268 diJs[i] = _bj_diJ(&briefjets[i]);
5269 briefjets[i].label_minheap_update_done();
5272 vector<TiledJet *> jets_for_minheap;
5273 jets_for_minheap.reserve(n);
5274 int history_location = n-1;
5276 double diJ_min = minheap.minval() *_invR2;
5277 jetA = head + minheap.minloc();
5281 if (jetA < jetB) {std::swap(jetA,jetB);}
5283 _cs.plugin_record_ij_recombination(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
5284 _bj_remove_from_tiles(jetA);
5286 _bj_remove_from_tiles(jetB);
5287 _tj_set_jetinfo(jetB, nn);
5289 _cs.plugin_record_iB_recombination(jetA->_jets_index, diJ_min);
5290 _bj_remove_from_tiles(jetA);
5292 minheap.remove(jetA-head);
5293 int n_near_tiles = 0;
5295 Tile25 & jetB_tile = _tiles[jetB->tile_index];
5296 for (Tile25 ** near_tile = jetB_tile.begin_tiles;
5297 near_tile != jetB_tile.end_tiles; near_tile++) {
5298 double dist_to_tile = _distance_to_tile(jetB, *near_tile);
5299 bool relevant_for_jetB = dist_to_tile <= jetB->NN_dist;
5300 bool relevant_for_near_tile = dist_to_tile <= (*near_tile)->max_NN_dist;
5301 bool relevant = relevant_for_jetB || relevant_for_near_tile;
5302 if (! relevant)
continue;
5303 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5304 (*near_tile)->tagged =
true;
5306 for (
TiledJet * jetI = (*near_tile)->head; jetI != NULL; jetI = jetI->next) {
5307 if (jetI->NN == jetA || jetI->NN == jetB) _set_NN(jetI, jets_for_minheap);
5308 _update_jetX_jetI_NN(jetB, jetI, jets_for_minheap);
5312 int n_done_tiles = n_near_tiles;
5313 _add_untagged_neighbours_to_tile_union_using_max_info(jetA,
5314 tile_union, n_near_tiles);
5316 _add_untagged_neighbours_to_tile_union_using_max_info(&oldB,
5317 tile_union,n_near_tiles);
5318 jetB->label_minheap_update_needed();
5319 jets_for_minheap.push_back(jetB);
5321 for (
int itile = 0; itile < n_done_tiles; itile++) {
5322 _tiles[tile_union[itile]].tagged =
false;
5324 for (
int itile = n_done_tiles; itile < n_near_tiles; itile++) {
5325 Tile25 * tile_ptr = &_tiles[tile_union[itile]];
5326 tile_ptr->tagged =
false;
5327 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
5328 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
5329 _set_NN(jetI, jets_for_minheap);
5333 while (jets_for_minheap.size() > 0) {
5334 TiledJet * jetI = jets_for_minheap.back();
5335 jets_for_minheap.pop_back();
5336 minheap.update(jetI-head, _bj_diJ(jetI));
5337 jetI->label_minheap_update_done();
5338 Tile25 & tile_I = _tiles[jetI->tile_index];
5339 if (tile_I.max_NN_dist < jetI->NN_dist) tile_I.max_NN_dist = jetI->NN_dist;
5345 cout <<
"ncall, dtt = " << _ncall <<
" " << _ncall_dtt << endl;
5346 #endif // INSTRUMENT2
5348 FJCORE_END_NAMESPACE
5352 using namespace std;
5353 #define _FJCORE_TILING2_USE_TILING_ANALYSIS_
5354 FJCORE_BEGIN_NAMESPACE
5356 _cs(cs), _jets(cs.jets())
5361 #endif // INSTRUMENT2
5362 _Rparam = cs.jet_def().R();
5363 _R2 = _Rparam * _Rparam;
5365 _initialise_tiles();
5367 void LazyTiling9::_initialise_tiles() {
5368 double default_size = max(0.1,_Rparam);
5369 _tile_size_eta = default_size;
5370 _n_tiles_phi = max(3,
int(floor(twopi/default_size)));
5371 _tile_size_phi = twopi / _n_tiles_phi;
5372 #ifdef _FJCORE_TILING2_USE_TILING_ANALYSIS_
5374 _tiles_eta_min = tiling_analysis.minrap();
5375 _tiles_eta_max = tiling_analysis.maxrap();
5377 _tiles_eta_min = 0.0;
5378 _tiles_eta_max = 0.0;
5379 const double maxrap = 7.0;
5380 for(
unsigned int i = 0; i < _jets.size(); i++) {
5381 double eta = _jets[i].rap();
5382 if (abs(eta) < maxrap) {
5383 if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
5384 if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
5388 # define FJCORE_LAZY9_MIN2TILESY
5389 #ifdef FJCORE_LAZY9_MIN2TILESY
5390 if (_tiles_eta_max - _tiles_eta_min < 2*_tile_size_eta) {
5391 _tile_size_eta = (_tiles_eta_max - _tiles_eta_min)/2;
5392 _tiles_ieta_min = 0;
5393 _tiles_ieta_max = 1;
5394 _tiles_eta_max -= _tile_size_eta;
5396 #endif //FASTJET_LAZY9_MIN2TILESY
5397 _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
5398 _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
5399 _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
5400 _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
5401 #ifdef FJCORE_LAZY9_MIN2TILESY
5404 _tile_half_size_eta = _tile_size_eta * 0.5;
5405 _tile_half_size_phi = _tile_size_phi * 0.5;
5406 vector<bool> use_periodic_delta_phi(_n_tiles_phi,
false);
5407 if (_n_tiles_phi <= 3) {
5408 fill(use_periodic_delta_phi.begin(), use_periodic_delta_phi.end(),
true);
5410 use_periodic_delta_phi[0] =
true;
5411 use_periodic_delta_phi[_n_tiles_phi-1] =
true;
5413 _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
5414 for (
int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
5415 for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
5416 Tile2 * tile = & _tiles[_tile_index(ieta,iphi)];
5418 tile->begin_tiles[0] = tile;
5419 Tile2 ** pptile = & (tile->begin_tiles[0]);
5421 tile->surrounding_tiles = pptile;
5422 if (ieta > _tiles_ieta_min) {
5426 for (
int idphi = -1; idphi <=+1; idphi++) {
5427 *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
5431 *pptile = & _tiles[_tile_index(ieta,iphi-1)];
5433 tile->RH_tiles = pptile;
5434 *pptile = & _tiles[_tile_index(ieta,iphi+1)];
5436 if (ieta < _tiles_ieta_max) {
5437 for (
int idphi = -1; idphi <= +1; idphi++) {
5438 *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
5442 tile->end_tiles = pptile;
5443 tile->tagged =
false;
5444 tile->use_periodic_delta_phi = use_periodic_delta_phi[iphi];
5445 tile->max_NN_dist = 0;
5446 tile->eta_centre = (ieta-_tiles_ieta_min+0.5)*_tile_size_eta + _tiles_eta_min;
5447 tile->phi_centre = (iphi+0.5)*_tile_size_phi;
5451 int LazyTiling9::_tile_index(
const double eta,
const double phi)
const {
5453 if (eta <= _tiles_eta_min) {ieta = 0;}
5454 else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
5456 ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
5457 if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
5458 ieta = _tiles_ieta_max-_tiles_ieta_min;}
5460 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
5461 return (iphi + ieta * _n_tiles_phi);
5463 inline void LazyTiling9::_tj_set_jetinfo(
TiledJet *
const jet,
5464 const int _jets_index) {
5465 _bj_set_jetinfo<>(jet, _jets_index);
5466 jet->tile_index = _tile_index(jet->eta, jet->phi);
5467 Tile2 * tile = &_tiles[jet->tile_index];
5468 jet->previous = NULL;
5469 jet->next = tile->head;
5470 if (jet->next != NULL) {jet->next->previous = jet;}
5473 void LazyTiling9::_bj_remove_from_tiles(
TiledJet *
const jet) {
5474 Tile2 * tile = & _tiles[jet->tile_index];
5475 if (jet->previous == NULL) {
5476 tile->head = jet->next;
5478 jet->previous->next = jet->next;
5480 if (jet->next != NULL) {
5481 jet->next->previous = jet->previous;
5484 void LazyTiling9::_print_tiles(
TiledJet * briefjets )
const {
5485 for (vector<Tile2>::const_iterator tile = _tiles.begin();
5486 tile < _tiles.end(); tile++) {
5487 cout <<
"Tile " << tile - _tiles.begin()<<
" = ";
5489 for (
TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
5490 list.push_back(jetI-briefjets);
5492 sort(list.begin(),list.end());
5493 for (
unsigned int i = 0; i < list.size(); i++) {cout <<
" "<<list[i];}
5497 void LazyTiling9::_add_neighbours_to_tile_union(
const int tile_index,
5498 vector<int> & tile_union,
int & n_near_tiles)
const {
5499 for (Tile2 *
const * near_tile = _tiles[tile_index].begin_tiles;
5500 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5501 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5505 inline void LazyTiling9::_add_untagged_neighbours_to_tile_union(
5506 const int tile_index,
5507 vector<int> & tile_union,
int & n_near_tiles) {
5508 for (Tile2 ** near_tile = _tiles[tile_index].begin_tiles;
5509 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5510 if (! (*near_tile)->tagged) {
5511 (*near_tile)->tagged =
true;
5512 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5517 inline void LazyTiling9::_add_untagged_neighbours_to_tile_union_using_max_info(
5519 vector<int> & tile_union,
int & n_near_tiles) {
5520 Tile2 & tile = _tiles[jet->tile_index];
5521 for (Tile2 ** near_tile = tile.begin_tiles; near_tile != tile.end_tiles; near_tile++){
5522 if ((*near_tile)->tagged)
continue;
5523 double dist = _distance_to_tile(jet, *near_tile) - tile_edge_security_margin;
5524 if (dist > (*near_tile)->max_NN_dist)
continue;
5525 (*near_tile)->tagged =
true;
5526 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5530 inline double LazyTiling9::_distance_to_tile(
const TiledJet * bj,
const Tile2 * tile)
5536 #endif // INSTRUMENT2
5538 if (_tiles[bj->tile_index].eta_centre == tile->eta_centre) deta = 0;
5539 else deta = std::abs(bj->eta - tile->eta_centre) - _tile_half_size_eta;
5540 double dphi = std::abs(bj->phi - tile->phi_centre);
5541 if (dphi > pi) dphi = twopi-dphi;
5542 dphi -= _tile_half_size_phi;
5543 if (dphi < 0) dphi = 0;
5544 return dphi*dphi + deta*deta;
5546 inline void LazyTiling9::_update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, vector<TiledJet *> & jets_for_minheap) {
5547 double dist = _bj_dist(jetI,jetX);
5548 if (dist < jetI->NN_dist) {
5550 jetI->NN_dist = dist;
5552 if (!jetI->minheap_update_needed()) {
5553 jetI->label_minheap_update_needed();
5554 jets_for_minheap.push_back(jetI);
5558 if (dist < jetX->NN_dist) {
5560 jetX->NN_dist = dist;
5564 inline void LazyTiling9::_set_NN(
TiledJet * jetI,
5565 vector<TiledJet *> & jets_for_minheap) {
5566 jetI->NN_dist = _R2;
5568 if (!jetI->minheap_update_needed()) {
5569 jetI->label_minheap_update_needed();
5570 jets_for_minheap.push_back(jetI);}
5571 Tile2 * tile_ptr = &_tiles[jetI->tile_index];
5572 for (Tile2 ** near_tile = tile_ptr->begin_tiles;
5573 near_tile != tile_ptr->end_tiles; near_tile++) {
5574 if (jetI->NN_dist < _distance_to_tile(jetI, *near_tile))
continue;
5575 for (
TiledJet * jetJ = (*near_tile)->head;
5576 jetJ != NULL; jetJ = jetJ->next) {
5577 double dist = _bj_dist(jetI,jetJ);
5578 if (dist < jetI->NN_dist && jetJ != jetI) {
5579 jetI->NN_dist = dist; jetI->NN = jetJ;
5584 void LazyTiling9::run() {
5585 int n = _jets.size();
5588 TiledJet * jetA = briefjets, * jetB;
5590 vector<int> tile_union(3*n_tile_neighbours);
5591 for (
int i = 0; i< n; i++) {
5592 _tj_set_jetinfo(jetA, i);
5596 vector<Tile2>::iterator tile;
5597 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5598 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5599 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
5600 double dist = _bj_dist_not_periodic(jetA,jetB);
5601 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5602 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5605 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5606 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
5609 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5610 if (tile->use_periodic_delta_phi) {
5611 for (Tile2 ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
5612 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5613 double dist_to_tile = _distance_to_tile(jetA, *RTile);
5614 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
5615 bool relevant_for_RTile = dist_to_tile <= (*RTile)->max_NN_dist;
5616 if (relevant_for_jetA || relevant_for_RTile) {
5617 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
5618 double dist = _bj_dist(jetA,jetB);
5619 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5620 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5626 for (Tile2 ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
5627 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5628 double dist_to_tile = _distance_to_tile(jetA, *RTile);
5629 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
5630 bool relevant_for_RTile = dist_to_tile <= (*RTile)->max_NN_dist;
5631 if (relevant_for_jetA || relevant_for_RTile) {
5632 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
5633 double dist = _bj_dist_not_periodic(jetA,jetB);
5634 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5635 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5642 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5643 tile->max_NN_dist = 0;
5644 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5645 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
5649 cout <<
"intermediate ncall, dtt = " << _ncall <<
" " << _ncall_dtt << endl;
5650 #endif // INSTRUMENT2
5651 vector<double> diJs(n);
5652 for (
int i = 0; i < n; i++) {
5653 diJs[i] = _bj_diJ(&briefjets[i]);
5654 briefjets[i].label_minheap_update_done();
5657 vector<TiledJet *> jets_for_minheap;
5658 jets_for_minheap.reserve(n);
5659 int history_location = n-1;
5661 double diJ_min = minheap.minval() *_invR2;
5662 jetA = head + minheap.minloc();
5666 if (jetA < jetB) {std::swap(jetA,jetB);}
5668 _cs.plugin_record_ij_recombination(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
5669 _bj_remove_from_tiles(jetA);
5671 _bj_remove_from_tiles(jetB);
5672 _tj_set_jetinfo(jetB, nn);
5674 _cs.plugin_record_iB_recombination(jetA->_jets_index, diJ_min);
5675 _bj_remove_from_tiles(jetA);
5677 minheap.remove(jetA-head);
5678 int n_near_tiles = 0;
5680 Tile2 & jetB_tile = _tiles[jetB->tile_index];
5681 for (Tile2 ** near_tile = jetB_tile.begin_tiles;
5682 near_tile != jetB_tile.end_tiles; near_tile++) {
5683 double dist_to_tile = _distance_to_tile(jetB, *near_tile);
5684 bool relevant_for_jetB = dist_to_tile <= jetB->NN_dist;
5685 bool relevant_for_near_tile = dist_to_tile <= (*near_tile)->max_NN_dist;
5686 bool relevant = relevant_for_jetB || relevant_for_near_tile;
5687 if (! relevant)
continue;
5688 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
5689 (*near_tile)->tagged =
true;
5691 for (
TiledJet * jetI = (*near_tile)->head; jetI != NULL; jetI = jetI->next) {
5692 if (jetI->NN == jetA || jetI->NN == jetB) _set_NN(jetI, jets_for_minheap);
5693 _update_jetX_jetI_NN(jetB, jetI, jets_for_minheap);
5697 int n_done_tiles = n_near_tiles;
5698 _add_untagged_neighbours_to_tile_union_using_max_info(jetA,
5699 tile_union, n_near_tiles);
5701 _add_untagged_neighbours_to_tile_union_using_max_info(&oldB,
5702 tile_union,n_near_tiles);
5703 jetB->label_minheap_update_needed();
5704 jets_for_minheap.push_back(jetB);
5706 for (
int itile = 0; itile < n_done_tiles; itile++) {
5707 _tiles[tile_union[itile]].tagged =
false;
5709 for (
int itile = n_done_tiles; itile < n_near_tiles; itile++) {
5710 Tile2 * tile_ptr = &_tiles[tile_union[itile]];
5711 tile_ptr->tagged =
false;
5712 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
5713 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
5714 _set_NN(jetI, jets_for_minheap);
5718 while (jets_for_minheap.size() > 0) {
5719 TiledJet * jetI = jets_for_minheap.back();
5720 jets_for_minheap.pop_back();
5721 minheap.update(jetI-head, _bj_diJ(jetI));
5722 jetI->label_minheap_update_done();
5723 Tile2 & tile_I = _tiles[jetI->tile_index];
5724 if (tile_I.max_NN_dist < jetI->NN_dist) tile_I.max_NN_dist = jetI->NN_dist;
5730 cout <<
"ncall, dtt = " << _ncall <<
" " << _ncall_dtt << endl;
5731 #endif // INSTRUMENT2
5733 FJCORE_END_NAMESPACE
5735 using namespace std;
5736 FJCORE_BEGIN_NAMESPACE
5738 _cs(cs), _jets(cs.jets())
5740 _Rparam = cs.jet_def().R();
5741 _R2 = _Rparam * _Rparam;
5743 _initialise_tiles();
5745 void LazyTiling9Alt::_initialise_tiles() {
5746 double default_size = max(0.1,_Rparam);
5747 _tile_size_eta = default_size;
5748 _n_tiles_phi = max(3,
int(floor(twopi/default_size)));
5749 _tile_size_phi = twopi / _n_tiles_phi;
5750 _tiles_eta_min = 0.0;
5751 _tiles_eta_max = 0.0;
5752 const double maxrap = 7.0;
5753 for(
unsigned int i = 0; i < _jets.size(); i++) {
5754 double eta = _jets[i].rap();
5755 if (abs(eta) < maxrap) {
5756 if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
5757 if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
5760 _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
5761 _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
5762 _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
5763 _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
5764 _tile_half_size_eta = _tile_size_eta * 0.5;
5765 _tile_half_size_phi = _tile_size_phi * 0.5;
5766 vector<bool> use_periodic_delta_phi(_n_tiles_phi,
false);
5767 if (_n_tiles_phi <= 3) {
5768 fill(use_periodic_delta_phi.begin(), use_periodic_delta_phi.end(),
true);
5770 use_periodic_delta_phi[0] =
true;
5771 use_periodic_delta_phi[_n_tiles_phi-1] =
true;
5773 _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
5774 for (
int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
5775 for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
5776 Tile * tile = & _tiles[_tile_index(ieta,iphi)];
5778 tile->begin_tiles[0] = Tile::TileFnPair(tile,&Tile::distance_to_centre);
5779 Tile::TileFnPair * pptile = & (tile->begin_tiles[0]);
5781 tile->surrounding_tiles = pptile;
5782 if (ieta > _tiles_ieta_min) {
5787 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta-1,iphi-1)],
5788 &Tile::distance_to_left_bottom);
5790 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta-1,iphi)],
5791 &Tile::distance_to_left);
5793 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta-1,iphi+1)],
5794 &Tile::distance_to_left_top);
5797 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta,iphi-1)],
5798 &Tile::distance_to_bottom);
5800 tile->RH_tiles = pptile;
5801 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta,iphi+1)],
5802 &Tile::distance_to_top);
5804 if (ieta < _tiles_ieta_max) {
5809 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta+1,iphi-1)],
5810 &Tile::distance_to_right_bottom);
5812 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta+1,iphi)],
5813 &Tile::distance_to_right);
5815 *pptile = Tile::TileFnPair(& _tiles[_tile_index(ieta+1,iphi+1)],
5816 &Tile::distance_to_right_top);
5819 tile->end_tiles = pptile;
5820 tile->tagged =
false;
5821 tile->use_periodic_delta_phi = use_periodic_delta_phi[iphi];
5822 tile->max_NN_dist = 0;
5823 tile->eta_min = ieta*_tile_size_eta;
5824 tile->eta_max = (ieta+1)*_tile_size_eta;
5825 tile->phi_min = iphi*_tile_size_phi;
5826 tile->phi_max = (iphi+1)*_tile_size_phi;
5830 int LazyTiling9Alt::_tile_index(
const double eta,
const double phi)
const {
5832 if (eta <= _tiles_eta_min) {ieta = 0;}
5833 else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
5835 ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
5836 if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
5837 ieta = _tiles_ieta_max-_tiles_ieta_min;}
5839 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
5840 return (iphi + ieta * _n_tiles_phi);
5842 inline void LazyTiling9Alt::_tj_set_jetinfo(
TiledJet *
const jet,
5843 const int _jets_index) {
5844 _bj_set_jetinfo<>(jet, _jets_index);
5845 jet->tile_index = _tile_index(jet->eta, jet->phi);
5846 Tile * tile = &_tiles[jet->tile_index];
5847 jet->previous = NULL;
5848 jet->next = tile->head;
5849 if (jet->next != NULL) {jet->next->previous = jet;}
5852 void LazyTiling9Alt::_bj_remove_from_tiles(
TiledJet *
const jet) {
5853 Tile * tile = & _tiles[jet->tile_index];
5854 if (jet->previous == NULL) {
5855 tile->head = jet->next;
5857 jet->previous->next = jet->next;
5859 if (jet->next != NULL) {
5860 jet->next->previous = jet->previous;
5863 void LazyTiling9Alt::_print_tiles(
TiledJet * briefjets )
const {
5864 for (vector<Tile>::const_iterator tile = _tiles.begin();
5865 tile < _tiles.end(); tile++) {
5866 cout <<
"Tile " << tile - _tiles.begin()<<
" = ";
5868 for (
TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
5869 list.push_back(jetI-briefjets);
5871 sort(list.begin(),list.end());
5872 for (
unsigned int i = 0; i < list.size(); i++) {cout <<
" "<<list[i];}
5876 void LazyTiling9Alt::_add_neighbours_to_tile_union(
const int tile_index,
5877 vector<int> & tile_union,
int & n_near_tiles)
const {
5878 for (Tile::TileFnPair
const * near_tile = _tiles[tile_index].begin_tiles;
5879 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5880 tile_union[n_near_tiles] = near_tile->first - & _tiles[0];
5884 inline void LazyTiling9Alt::_add_untagged_neighbours_to_tile_union(
5885 const int tile_index,
5886 vector<int> & tile_union,
int & n_near_tiles) {
5887 for (Tile::TileFnPair * near_tile = _tiles[tile_index].begin_tiles;
5888 near_tile != _tiles[tile_index].end_tiles; near_tile++){
5889 if (! (near_tile->first)->tagged) {
5890 (near_tile->first)->tagged =
true;
5891 tile_union[n_near_tiles] = near_tile->first - & _tiles[0];
5896 inline void LazyTiling9Alt::_add_untagged_neighbours_to_tile_union_using_max_info(
5898 vector<int> & tile_union,
int & n_near_tiles) {
5899 Tile & tile = _tiles[jet->tile_index];
5900 for (Tile::TileFnPair * near_tile = tile.begin_tiles; near_tile != tile.end_tiles; near_tile++){
5901 if ((near_tile->first)->tagged)
continue;
5902 double dist = (tile.*(near_tile->second))(jet) - tile_edge_security_margin;
5903 if (dist > (near_tile->first)->max_NN_dist)
continue;
5904 (near_tile->first)->tagged =
true;
5905 tile_union[n_near_tiles] = near_tile->first - & _tiles[0];
5909 ostream & operator<<(ostream & ostr,
const TiledJet & jet) {
5910 ostr <<
"j" << setw(3) << jet._jets_index <<
":pt2,rap,phi=" ; ostr.flush();
5911 ostr << jet.kt2 <<
","; ostr.flush();
5912 ostr << jet.eta <<
","; ostr.flush();
5913 ostr << jet.phi; ostr.flush();
5914 ostr <<
", tile=" << jet.tile_index; ostr.flush();
5917 inline void LazyTiling9Alt::_update_jetX_jetI_NN(
TiledJet * jetX,
TiledJet * jetI, vector<TiledJet *> & jets_for_minheap) {
5918 double dist = _bj_dist(jetI,jetX);
5919 if (dist < jetI->NN_dist) {
5921 jetI->NN_dist = dist;
5923 if (!jetI->minheap_update_needed()) {
5924 jetI->label_minheap_update_needed();
5925 jets_for_minheap.push_back(jetI);
5929 if (dist < jetX->NN_dist) {
5931 jetX->NN_dist = dist;
5935 inline void LazyTiling9Alt::_set_NN(
TiledJet * jetI,
5936 vector<TiledJet *> & jets_for_minheap) {
5937 jetI->NN_dist = _R2;
5939 if (!jetI->minheap_update_needed()) {
5940 jetI->label_minheap_update_needed();
5941 jets_for_minheap.push_back(jetI);}
5942 Tile * tile_ptr = &_tiles[jetI->tile_index];
5943 for (Tile::TileFnPair * near_tile = tile_ptr->begin_tiles;
5944 near_tile != tile_ptr->end_tiles; near_tile++) {
5945 if (jetI->NN_dist < (tile_ptr->*(near_tile->second))(jetI))
continue;
5946 for (
TiledJet * jetJ = (near_tile->first)->head;
5947 jetJ != NULL; jetJ = jetJ->next) {
5948 double dist = _bj_dist(jetI,jetJ);
5949 if (dist < jetI->NN_dist && jetJ != jetI) {
5950 jetI->NN_dist = dist; jetI->NN = jetJ;
5955 void LazyTiling9Alt::run() {
5956 int n = _jets.size();
5958 TiledJet * jetA = briefjets, * jetB;
5960 vector<int> tile_union(3*n_tile_neighbours);
5961 for (
int i = 0; i< n; i++) {
5962 _tj_set_jetinfo(jetA, i);
5966 vector<Tile>::iterator tile;
5967 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5968 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5969 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
5970 double dist = _bj_dist_not_periodic(jetA,jetB);
5971 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5972 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5975 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5976 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
5979 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
5980 if (tile->use_periodic_delta_phi) {
5981 for (Tile::TileFnPair * RTileFnPair = tile->RH_tiles;
5982 RTileFnPair != tile->end_tiles; RTileFnPair++) {
5983 Tile *RTile = RTileFnPair->first;
5984 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
5985 double dist_to_tile = ((*tile).*(RTileFnPair->second))(jetA);
5986 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
5987 bool relevant_for_RTile = dist_to_tile <= RTile->max_NN_dist;
5988 if (relevant_for_jetA || relevant_for_RTile) {
5989 for (jetB = RTile->head; jetB != NULL; jetB = jetB->next) {
5990 double dist = _bj_dist(jetA,jetB);
5991 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
5992 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
5998 for (Tile::TileFnPair* RTileFnPair = tile->RH_tiles;
5999 RTileFnPair != tile->end_tiles; RTileFnPair++) {
6000 Tile *RTile = RTileFnPair->first;
6001 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
6002 double dist_to_tile = ((*tile).*(RTileFnPair->second))(jetA);
6003 bool relevant_for_jetA = dist_to_tile <= jetA->NN_dist;
6004 bool relevant_for_RTile = dist_to_tile <= RTile->max_NN_dist;
6005 if (relevant_for_jetA || relevant_for_RTile) {
6006 for (jetB = RTile->head; jetB != NULL; jetB = jetB->next) {
6007 double dist = _bj_dist_not_periodic(jetA,jetB);
6008 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
6009 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
6016 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
6017 tile->max_NN_dist = 0;
6018 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
6019 if (jetA->NN_dist > tile->max_NN_dist) tile->max_NN_dist = jetA->NN_dist;
6022 vector<double> diJs(n);
6023 for (
int i = 0; i < n; i++) {
6024 diJs[i] = _bj_diJ(&briefjets[i]);
6025 briefjets[i].label_minheap_update_done();
6028 vector<TiledJet *> jets_for_minheap;
6029 jets_for_minheap.reserve(n);
6030 int history_location = n-1;
6032 double diJ_min = minheap.minval() *_invR2;
6033 jetA = head + minheap.minloc();
6037 if (jetA < jetB) {std::swap(jetA,jetB);}
6039 _cs.plugin_record_ij_recombination(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
6040 _bj_remove_from_tiles(jetA);
6042 _bj_remove_from_tiles(jetB);
6043 _tj_set_jetinfo(jetB, nn);
6045 _cs.plugin_record_iB_recombination(jetA->_jets_index, diJ_min);
6046 _bj_remove_from_tiles(jetA);
6048 minheap.remove(jetA-head);
6049 int n_near_tiles = 0;
6050 _add_untagged_neighbours_to_tile_union_using_max_info(jetA,
6051 tile_union, n_near_tiles);
6053 _add_untagged_neighbours_to_tile_union_using_max_info(&oldB,
6054 tile_union,n_near_tiles);
6055 jetB->label_minheap_update_needed();
6056 jets_for_minheap.push_back(jetB);
6059 Tile & jetB_tile = _tiles[jetB->tile_index];
6060 for (Tile::TileFnPair * near_tile_fn_pair = jetB_tile.begin_tiles;
6061 near_tile_fn_pair != jetB_tile.end_tiles; near_tile_fn_pair++) {
6062 Tile * near_tile = near_tile_fn_pair->first;
6063 double dist_to_tile = (jetB_tile.*(near_tile_fn_pair->second))(jetB);
6064 bool relevant_for_jetB = dist_to_tile <= jetB->NN_dist;
6065 bool relevant_for_near_tile = dist_to_tile <= near_tile->max_NN_dist;
6066 bool relevant = relevant_for_jetB || relevant_for_near_tile;
6068 if (near_tile->tagged) {
6069 for (
TiledJet * jetI = near_tile->head; jetI != NULL; jetI = jetI->next) {
6070 if (jetI->NN == jetA || jetI->NN == jetB) _set_NN(jetI, jets_for_minheap);
6071 _update_jetX_jetI_NN(jetB, jetI, jets_for_minheap);
6073 near_tile->tagged =
false;
6075 for (
TiledJet * jetI = near_tile->head; jetI != NULL; jetI = jetI->next) {
6076 _update_jetX_jetI_NN(jetB, jetI, jets_for_minheap);
6083 for (
int itile = 0; itile < n_near_tiles; itile++) {
6084 Tile * tile_ptr = &_tiles[tile_union[itile]];
6085 if (!tile_ptr->tagged)
continue;
6086 tile_ptr->tagged =
false;
6087 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
6088 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
6089 _set_NN(jetI, jets_for_minheap);
6093 while (jets_for_minheap.size() > 0) {
6094 TiledJet * jetI = jets_for_minheap.back();
6095 jets_for_minheap.pop_back();
6096 minheap.update(jetI-head, _bj_diJ(jetI));
6097 jetI->label_minheap_update_done();
6098 Tile & tile_I = _tiles[jetI->tile_index];
6099 if (tile_I.max_NN_dist < jetI->NN_dist) tile_I.max_NN_dist = jetI->NN_dist;
6105 FJCORE_END_NAMESPACE
6109 using namespace std;
6110 FJCORE_BEGIN_NAMESPACE
6112 _determine_rapidity_extent(cs.jets());
6114 TilingExtent::TilingExtent(
const vector<PseudoJet> &particles) {
6115 _determine_rapidity_extent(particles);
6117 void TilingExtent::_determine_rapidity_extent(
const vector<PseudoJet> & particles) {
6120 vector<double> counts(nbins, 0);
6121 _minrap = numeric_limits<double>::max();
6122 _maxrap = -numeric_limits<double>::max();
6124 for (
unsigned i = 0; i < particles.size(); i++) {
6125 if (particles[i].E() == abs(particles[i].pz()))
continue;
6126 double rap = particles[i].rap();
6127 if (rap < _minrap) _minrap = rap;
6128 if (rap > _maxrap) _maxrap = rap;
6129 ibin = int(rap+nrap);
6130 if (ibin < 0) ibin = 0;
6131 if (ibin >= nbins) ibin = nbins - 1;
6134 double max_in_bin = 0;
6135 for (ibin = 0; ibin < nbins; ibin++) {
6136 if (max_in_bin < counts[ibin]) max_in_bin = counts[ibin];
6138 const double allowed_max_fraction = 0.25;
6139 const double min_multiplicity = 4;
6140 double allowed_max_cumul = floor(max(max_in_bin * allowed_max_fraction, min_multiplicity));
6141 if (allowed_max_cumul > max_in_bin) allowed_max_cumul = max_in_bin;
6142 double cumul_lo = 0;
6144 for (ibin = 0; ibin < nbins; ibin++) {
6145 cumul_lo += counts[ibin];
6146 if (cumul_lo >= allowed_max_cumul) {
6147 double y = ibin-nrap;
6148 if (y > _minrap) _minrap = y;
6152 assert(ibin != nbins);
6153 _cumul2 += cumul_lo*cumul_lo;
6155 double cumul_hi = 0;
6156 for (ibin = nbins-1; ibin >= 0; ibin--) {
6157 cumul_hi += counts[ibin];
6158 if (cumul_hi >= allowed_max_cumul) {
6159 double y = ibin-nrap+1;
6160 if (y < _maxrap) _maxrap = y;
6166 assert(ibin_hi >= ibin_lo);
6167 if (ibin_hi == ibin_lo) {
6168 _cumul2 = pow(
double(cumul_lo + cumul_hi - counts[ibin_hi]), 2);
6170 _cumul2 += cumul_hi*cumul_hi;
6171 for (ibin = ibin_lo+1; ibin < ibin_hi; ibin++) {
6172 _cumul2 += counts[ibin]*counts[ibin];
6176 FJCORE_END_NAMESPACE
virtual bool has_known_area() const
the area is analytically known
virtual bool has_known_area() const
the area is analytically known
virtual bool is_geometric() const
implies a finite area
virtual bool has_known_area() const
the area is analytically known
virtual bool has_finite_area() const
regardless of the reference
virtual bool is_geometric() const
implies a finite area
virtual bool has_known_area() const
the area is analytically known
std::vector< PseudoJet > _pieces
the pieces building the jet
virtual bool has_finite_area() const
regardless of the reference
virtual bool has_known_area() const
the area is analytically known
virtual bool has_known_area() const
the area is analytically known
virtual bool has_finite_area() const
regardless of the reference
virtual bool has_finite_area() const
regardless of the reference
virtual bool has_known_area() const
the area is analytically known
bool treelinks_null() const
default constructor
virtual bool is_geometric() const
implies a finite area
virtual bool is_geometric() const
implies a finite area