77 #include "Pythia8/FJcore.h"
78 #ifndef __FJCORE_VERSION_HH__
79 #define __FJCORE_VERSION_HH__
81 FJCORE_BEGIN_NAMESPACE
82 const char* fastjet_version = FJCORE_PACKAGE_VERSION;
84 #endif // __FJCORE_VERSION_HH__
85 #ifndef __FJCORE_CLUSTERQUENCE_N2_ICC__
86 #define __FJCORE_CLUSTERQUENCE_N2_ICC__
87 FJCORE_BEGIN_NAMESPACE
88 template<
class BJ>
void ClusterSequence::_simple_N2_cluster() {
90 BJ * briefjets =
new BJ[n];
91 BJ * jetA = briefjets, * jetB;
92 for (
int i = 0; i< n; i++) {
93 _bj_set_jetinfo(jetA, i);
97 BJ * head = briefjets;
98 for (jetA = head + 1; jetA != tail; jetA++) {
99 _bj_set_NN_crosscheck(jetA, head, jetA);
101 double * diJ =
new double[n];
103 for (
int i = 0; i < n; i++) {
104 diJ[i] = _bj_diJ(jetA);
107 int history_location = n-1;
108 while (tail != head) {
109 double diJ_min = diJ[0];
111 for (
int i = 1; i < n; i++) {
112 if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
115 jetA = & briefjets[diJ_min_jet];
116 jetB =
static_cast<BJ *
>(jetA->NN);
119 if (jetA < jetB) {std::swap(jetA,jetB);}
121 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
122 _bj_set_jetinfo(jetB, nn);
124 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
128 diJ[jetA - head] = diJ[tail-head];
129 for (BJ * jetI = head; jetI != tail; jetI++) {
130 if (jetI->NN == jetA || jetI->NN == jetB) {
131 _bj_set_NN_nocross(jetI, head, tail);
132 diJ[jetI-head] = _bj_diJ(jetI);
135 double dist = _bj_dist(jetI,jetB);
136 if (dist < jetI->NN_dist) {
138 jetI->NN_dist = dist;
140 diJ[jetI-head] = _bj_diJ(jetI);
143 if (dist < jetB->NN_dist) {
145 jetB->NN_dist = dist;
149 if (jetI->NN == tail) {jetI->NN = jetA;}
151 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
157 #endif // __FJCORE_CLUSTERQUENCE_N2_ICC__
158 #ifndef __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
159 #define __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
165 FJCORE_BEGIN_NAMESPACE
168 double first, second;
170 EtaPhi(
double a,
double b) {first = a; second = b;}
172 if (second < 0) second += twopi;
173 if (second >= twopi) second -= twopi;
179 DnnError(
const std::string & message_in) {
180 _message = message_in; std::cerr << message_in << std::endl;};
181 std::string message()
const {
return _message;};
183 std::string _message;
187 virtual int NearestNeighbourIndex(
const int & ii)
const = 0;
188 virtual double NearestNeighbourDistance(
const int & ii)
const = 0;
189 virtual bool Valid(
const int & index)
const = 0;
190 virtual void RemoveAndAddPoints(
const std::vector<int> & indices_to_remove,
191 const std::vector<EtaPhi> & points_to_add,
192 std::vector<int> & indices_added,
193 std::vector<int> & indices_of_updated_neighbours) = 0;
194 inline void RemovePoint (
const int & index,
195 std::vector<int> & indices_of_updated_neighbours) {
196 std::vector<int> indices_added;
197 std::vector<EtaPhi> points_to_add;
198 std::vector<int> indices_to_remove(1);
199 indices_to_remove[0] = index;
200 RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
201 indices_of_updated_neighbours
203 inline void RemoveCombinedAddCombination(
204 const int & index1,
const int & index2,
207 std::vector<int> & indices_of_updated_neighbours) {
208 std::vector<int> indices_added(1);
209 std::vector<EtaPhi> points_to_add(1);
210 std::vector<int> indices_to_remove(2);
211 indices_to_remove[0] = index1;
212 indices_to_remove[1] = index2;
213 points_to_add[0] = newpoint;
214 RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
215 indices_of_updated_neighbours
217 index3 = indices_added[0];
222 #endif // __FJCORE_DYNAMICNEARESTNEIGHBOURS_HH__
223 #ifndef __FJCORE_SEARCHTREE_HH__
224 #define __FJCORE_SEARCHTREE_HH__
228 FJCORE_BEGIN_NAMESPACE
235 SearchTree(
const std::vector<T> & init,
unsigned int max_size);
236 void remove(
unsigned node_index);
240 const Node & operator[](
int i)
const {
return _nodes[i];};
241 unsigned int size()
const {
return _nodes.size() - _available_nodes.size();}
242 void verify_structure();
243 void verify_structure_linear()
const;
244 void verify_structure_recursive(
const Node * ,
const Node * ,
const Node * )
const;
245 void print_elements();
246 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
247 inline unsigned int max_depth()
const {
return _max_depth;};
249 inline unsigned int max_depth()
const {
return 0;};
251 int loc(
const Node * node)
const ;
252 Node * _find_predecessor(
const Node *);
253 Node * _find_successor(
const Node *);
254 const Node & operator[](
unsigned int i)
const {
return _nodes[i];};
258 void _initialize(
const std::vector<T> & init);
259 std::vector<Node> _nodes;
260 std::vector<Node *> _available_nodes;
262 unsigned int _n_removes;
263 void _do_initial_connections(
unsigned int this_one,
unsigned int scale,
264 unsigned int left_edge,
unsigned int right_edge,
266 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
267 unsigned int _max_depth;
274 return ((parent==0) && (left==0) && (right==0));};
275 inline void nullify_treelinks() {
280 void reset_parents_link_to_me(Node * XX);
289 if (parent == NULL) {
return;}
290 if (parent->right ==
this) {parent->right = XX;}
291 else {parent->left = XX;}
299 const T * operator->()
const {
return &(_node->value);}
300 T * operator->() {
return &(_node->value);}
301 const T & operator*()
const {
return _node->value;}
302 T & operator*() {
return _node->value;}
304 _node = _node->successor;
308 _node = _node->successor;
311 _node = _node->predecessor;
315 _node = _node->predecessor;
321 bool operator!=(
const circulator & other)
const {
return other._node != _node;}
322 bool operator==(
const circulator & other)
const {
return other._node == _node;}
331 const T * operator->() {
return &(_node->value);}
332 const T & operator*()
const {
return _node->value;}
334 _node = _node->successor;
338 _node = _node->successor;
341 _node = _node->predecessor;
345 _node = _node->predecessor;
351 bool operator!=(
const const_circulator & other)
const {
return other._node != _node;}
352 bool operator==(
const const_circulator & other)
const {
return other._node == _node;}
357 unsigned int max_size) :
359 _available_nodes.reserve(max_size);
360 _available_nodes.resize(max_size - init.size());
361 for (
unsigned int i = init.size(); i < max_size; i++) {
362 _available_nodes[i-init.size()] = &(_nodes[i]);
367 _nodes(init.size()), _available_nodes(0) {
368 _available_nodes.reserve(init.size());
373 unsigned n = init.size();
375 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
378 for (
unsigned int i = 1; i<n; i++) {
379 assert(!(init[i] < init[i-1]));
381 for(
unsigned int i = 0; i < n; i++) {
382 _nodes[i].value = init[i];
383 _nodes[i].predecessor = (& (_nodes[i])) - 1;
384 _nodes[i].successor = (& (_nodes[i])) + 1;
385 _nodes[i].nullify_treelinks();
387 _nodes[0].predecessor = (& (_nodes[n-1]));
388 _nodes[n-1].successor = (& (_nodes[0]));
389 unsigned int scale = (n+1)/2;
390 unsigned int top = std::min(n-1,scale);
391 _nodes[top].parent = NULL;
392 _top_node = &(_nodes[top]);
393 _do_initial_connections(top, scale, 0, n, 0);
395 template<
class T>
inline int SearchTree<T>::loc(
const Node * node)
const {
return node == NULL?
396 -999 : node - &(_nodes[0]);}
398 unsigned int this_one,
400 unsigned int left_edge,
401 unsigned int right_edge,
404 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
405 _max_depth = max(depth, _max_depth);
407 unsigned int ref_new_scale = (scale+1)/2;
408 unsigned new_scale = ref_new_scale;
409 bool did_child =
false;
411 int left = this_one - new_scale;
412 if (left >= static_cast<int>(left_edge)
413 && _nodes[left].treelinks_null() ) {
414 _nodes[left].parent = &(_nodes[this_one]);
415 _nodes[this_one].left = &(_nodes[left]);
416 _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
420 unsigned int old_new_scale = new_scale;
421 new_scale = (old_new_scale + 1)/2;
422 if (new_scale == old_new_scale)
break;
424 if (!did_child) {_nodes[this_one].left = NULL;}
425 new_scale = ref_new_scale;
428 unsigned int right = this_one + new_scale;
429 if (right < right_edge && _nodes[right].treelinks_null()) {
430 _nodes[right].parent = &(_nodes[this_one]);
431 _nodes[this_one].right = &(_nodes[right]);
432 _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
436 unsigned int old_new_scale = new_scale;
437 new_scale = (old_new_scale + 1)/2;
438 if (new_scale == old_new_scale)
break;
440 if (!did_child) {_nodes[this_one].right = NULL;}
443 remove(&(_nodes[node_index]));
451 node->predecessor->successor = node->successor;
452 node->successor->predecessor = node->predecessor;
453 if (node->left == NULL && node->right == NULL) {
454 node->reset_parents_link_to_me(NULL);
455 }
else if (node->left != NULL && node->right == NULL){
456 node->reset_parents_link_to_me(node->left);
457 node->left->parent = node->parent;
458 if (_top_node == node) {_top_node = node->left;}
459 }
else if (node->left == NULL && node->right != NULL){
460 node->reset_parents_link_to_me(node->right);
461 node->right->parent = node->parent;
462 if (_top_node == node) {_top_node = node->right;}
465 bool use_predecessor = (_n_removes % 2 == 1);
466 if (use_predecessor) {
467 replacement = node->predecessor;
468 assert(replacement->right == NULL);
469 if (replacement != node->left) {
470 if (replacement->left != NULL) {
471 replacement->left->parent = replacement->parent;}
472 replacement->reset_parents_link_to_me(replacement->left);
473 replacement->left = node->left;
475 replacement->parent = node->parent;
476 replacement->right = node->right;
478 replacement = node->successor;
479 assert(replacement->left == NULL);
480 if (replacement != node->right) {
481 if (replacement->right != NULL) {
482 replacement->right->parent = replacement->parent;}
483 replacement->reset_parents_link_to_me(replacement->right);
484 replacement->right = node->right;
486 replacement->parent = node->parent;
487 replacement->left = node->left;
489 node->reset_parents_link_to_me(replacement);
490 if (node->left != replacement) {node->left->parent = replacement;}
491 if (node->right != replacement) {node->right->parent = replacement;}
492 if (_top_node == node) {_top_node = replacement;}
494 node->nullify_treelinks();
495 node->predecessor = NULL;
496 node->successor = NULL;
498 _available_nodes.push_back(node);
501 assert(_available_nodes.size() > 0);
502 Node * node = _available_nodes.back();
503 _available_nodes.pop_back();
505 Node * location = _top_node;
506 Node * old_location = NULL;
508 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
509 unsigned int depth = 0;
511 while(location != NULL) {
512 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
515 old_location = location;
516 on_left = value < location->value;
517 if (on_left) {location = location->left;}
518 else {location = location->right;}
520 #ifdef __FJCORE_SEARCHTREE_TRACK_DEPTH
521 _max_depth = max(depth, _max_depth);
523 node->parent = old_location;
524 if (on_left) {node->parent->left = node;}
525 else {node->parent->right = node;}
528 node->predecessor = _find_predecessor(node);
529 if (node->predecessor != NULL) {
530 node->successor = node->predecessor->successor;
531 node->predecessor->successor = node;
532 node->successor->predecessor = node;
534 node->successor = _find_successor(node);
535 assert(node->successor != NULL);
536 node->predecessor = node->successor->predecessor;
537 node->successor->predecessor = node;
538 node->predecessor->successor = node;
540 return circulator(node);
543 verify_structure_linear();
544 const Node * left_limit = _top_node;
545 while (left_limit->left != NULL) {left_limit = left_limit->left;}
546 const Node * right_limit = _top_node;
547 while (right_limit->right != NULL) {right_limit = right_limit->right;}
548 verify_structure_recursive(_top_node, left_limit, right_limit);
554 assert(!(element->value < left_limit->value));
555 assert(!(right_limit->value < element->value));
556 const Node * left = element->left;
558 assert(!(element->value < left->value));
559 if (left != left_limit) {
560 verify_structure_recursive(left, left_limit, element);}
562 const Node * right = element->right;
564 assert(!(right->value < element->value));
565 if (right != right_limit) {
566 verify_structure_recursive(right, element, right_limit);}
572 for(
unsigned i = 0; i < _nodes.size(); i++) {
575 if (node->parent == NULL) {
578 assert((node->parent->left == node) ^ (node->parent->right == node));
580 if (node->left != NULL) {
581 assert(!(node->value < node->left->value ));}
582 if (node->right != NULL) {
583 assert(!(node->right->value < node->value ));}
585 assert(n_top == 1 || (n_top == 0 && size() <= 1) );
586 assert(n_null == _available_nodes.size() ||
587 (n_null == _available_nodes.size() + 1 && size() == 1));
591 if (node->left != NULL) {
592 newnode = node->left;
593 while(newnode->right != NULL) {newnode = newnode->right;}
597 newnode = node->parent;
598 while(newnode != NULL) {
599 if (newnode->right == lastnode) {
return newnode;}
601 newnode = newnode->parent;
608 if (node->right != NULL) {
609 newnode = node->right;
610 while(newnode->left != NULL) {newnode = newnode->left;}
614 newnode = node->parent;
615 while(newnode != NULL) {
616 if (newnode->left == lastnode) {
return newnode;}
618 newnode = newnode->parent;
626 int n = _nodes.size();
627 for(; node - base_node < n ; node++) {
628 printf(
"%4d parent:%4d left:%4d right:%4d pred:%4d succ:%4d value:%10.6f\n",loc(node), loc(node->parent), loc(node->left), loc(node->right), loc(node->predecessor),loc(node->successor),node->value);
632 return circulator(_top_node);
635 return const_circulator(_top_node);
638 #endif // __FJCORE_SEARCHTREE_HH__
639 #ifndef __FJCORE_MINHEAP__HH__
640 #define __FJCORE_MINHEAP__HH__
645 FJCORE_BEGIN_NAMESPACE
648 MinHeap (
const std::vector<double> & values,
unsigned int max_size) :
649 _heap(max_size) {_initialise(values);};
650 MinHeap (
const std::vector<double> & values) :
651 _heap(values.size()) {_initialise(values);};
652 inline unsigned int minloc()
const {
653 return (_heap[0].minloc) - &(_heap[0]);};
654 inline double minval()
const {
return _heap[0].minloc->value;};
655 inline double operator[](
int i)
const {
return _heap[i].value;};
656 void remove(
unsigned int loc) {
657 update(loc,std::numeric_limits<double>::max());};
658 void update(
unsigned int,
double);
664 std::vector<ValueLoc> _heap;
665 void _initialise(
const std::vector<double> & values);
668 #endif // __FJCORE_MINHEAP__HH__
669 #ifndef __FJCORE_CLOSESTPAIR2DBASE__HH__
670 #define __FJCORE_CLOSESTPAIR2DBASE__HH__
672 FJCORE_BEGIN_NAMESPACE
677 Coord2D(
double a,
double b): x(a), y(b) {};
679 return Coord2D(x - other.x, y - other.y);};
681 return Coord2D(x + other.x, y + other.y);};
682 Coord2D operator*(
double factor)
const {
return Coord2D(factor*x,factor*y);};
684 return Coord2D(factor*coord.x,factor*coord.y);
686 Coord2D operator/(
double divisor)
const {
687 return Coord2D(x / divisor, y / divisor);};
689 double dx = a.x - b.x, dy = a.y-b.y;
692 double distance2(
const Coord2D & b)
const {
693 double dx = x - b.x, dy = y-b.y;
699 virtual void closest_pair(
unsigned int & ID1,
unsigned int & ID2,
700 double & distance2)
const = 0;
701 virtual void remove(
unsigned int ID) = 0;
702 virtual unsigned int insert(
const Coord2D & position) = 0;
703 virtual unsigned int replace(
unsigned int ID1,
unsigned int ID2,
707 unsigned new_ID = insert(position);
710 virtual void replace_many(
const std::vector<unsigned int> & IDs_to_remove,
711 const std::vector<Coord2D> & new_positions,
712 std::vector<unsigned int> & new_IDs) {
713 for(
unsigned i = 0; i < IDs_to_remove.size(); i++) {
714 remove(IDs_to_remove[i]);}
716 for(
unsigned i = 0; i < new_positions.size(); i++) {
717 new_IDs.push_back(insert(new_positions[i]));}
719 virtual unsigned int size() = 0;
723 #endif // __FJCORE_CLOSESTPAIR2DBASE__HH__
724 #ifndef __FJCORE_CLOSESTPAIR2D__HH__
725 #define __FJCORE_CLOSESTPAIR2D__HH__
729 FJCORE_BEGIN_NAMESPACE
734 _initialize(positions, left_corner, right_corner, positions.size());
738 const unsigned int max_size) {
739 _initialize(positions, left_corner, right_corner, max_size);
741 void closest_pair(
unsigned int & ID1,
unsigned int & ID2,
742 double & distance2)
const;
743 void remove(
unsigned int ID);
744 unsigned int insert(
const Coord2D &);
745 virtual unsigned int replace(
unsigned int ID1,
unsigned int ID2,
747 virtual void replace_many(
const std::vector<unsigned int> & IDs_to_remove,
748 const std::vector<Coord2D> & new_positions,
749 std::vector<unsigned int> & new_IDs);
750 inline void print_tree_depths(std::ostream & outdev)
const {
751 outdev << _trees[0]->max_depth() <<
" "
752 << _trees[1]->max_depth() <<
" "
753 << _trees[2]->max_depth() <<
"\n";
757 void _initialize(
const std::vector<Coord2D> & positions,
759 const unsigned int max_size);
760 static const unsigned int _nshift = 3;
762 template<
class T>
class triplet {
764 inline const T & operator[](
unsigned int i)
const {
return _contents[i];};
765 inline T & operator[](
unsigned int i) {
return _contents[i];};
767 T _contents[_nshift];
773 bool operator<(
const Shuffle &)
const;
774 void operator+=(
unsigned int shift) {x += shift; y+= shift;};
779 triplet<std::auto_ptr<Tree> > _trees;
780 std::auto_ptr<MinHeap> _heap;
781 std::vector<Point> _points;
782 std::stack<Point *> _available_points;
783 std::vector<Point *> _points_under_review;
784 static const unsigned int _remove_heap_entry = 1;
785 static const unsigned int _review_heap_entry = 2;
786 static const unsigned int _review_neighbour = 4;
787 void _add_label(
Point * point,
unsigned int review_flag);
788 void _set_label(
Point * point,
unsigned int review_flag);
789 void _deal_with_points_to_review();
790 void _remove_from_search_tree(
Point * point_to_remove);
791 void _insert_into_search_tree(
Point * new_point);
792 void _point2shuffle(
Point & , Shuffle & ,
unsigned int shift);
795 int _ID(
const Point *)
const;
796 triplet<unsigned int> _shifts;
797 triplet<unsigned int> _rel_shifts;
798 unsigned int _cp_search_range;
804 double neighbour_dist2;
805 triplet<circulator> circ;
806 unsigned int review_flag;
807 double distance2(
const Point & other)
const {
808 return coord.distance2(other.coord);
811 inline bool floor_ln2_less(
unsigned x,
unsigned y) {
812 if (x>y)
return false;
815 inline int ClosestPair2D::_ID(
const Point * point)
const {
816 return point - &(_points[0]);
818 inline unsigned int ClosestPair2D::size() {
819 return _points.size() - _available_points.size();
822 #endif // __FJCORE_CLOSESTPAIR2D__HH__
827 FJCORE_BEGIN_NAMESPACE
828 const unsigned int huge_unsigned = 4294967295U;
829 const unsigned int twopow31 = 2147483648U;
831 void ClosestPair2D::_point2shuffle(Point & point, Shuffle & shuffle,
832 unsigned int shift) {
833 Coord2D renorm_point = (point.coord - _left_corner)/_range;
834 assert(renorm_point.x >=0);
835 assert(renorm_point.x <=1);
836 assert(renorm_point.y >=0);
837 assert(renorm_point.y <=1);
838 shuffle.x =
static_cast<unsigned int>(twopow31 * renorm_point.x) + shift;
839 shuffle.y =
static_cast<unsigned int>(twopow31 * renorm_point.y) + shift;
840 shuffle.point = &point;
842 bool ClosestPair2D::Shuffle::operator<(
const Shuffle & q)
const {
843 if (floor_ln2_less(x ^ q.x, y ^ q.y)) {
849 void ClosestPair2D::_initialize(
const std::vector<Coord2D> & positions,
852 unsigned int max_size) {
853 unsigned int n_positions = positions.size();
854 assert(max_size >= n_positions);
855 _points.resize(max_size);
856 for (
unsigned int i = n_positions; i < max_size; i++) {
857 _available_points.push(&(_points[i]));
859 _left_corner = left_corner;
860 _range = max((right_corner.x - left_corner.x),
861 (right_corner.y - left_corner.y));
862 vector<Shuffle> shuffles(n_positions);
863 for (
unsigned int i = 0; i < n_positions; i++) {
864 _points[i].coord = positions[i];
865 _points[i].neighbour_dist2 = numeric_limits<double>::max();
866 _points[i].review_flag = 0;
867 _point2shuffle(_points[i], shuffles[i], 0);
869 for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
870 _shifts[ishift] =
static_cast<unsigned int>(((twopow31*1.0)*ishift)/_nshift);
871 if (ishift == 0) {_rel_shifts[ishift] = 0;}
872 else {_rel_shifts[ishift] = _shifts[ishift] - _shifts[ishift-1];}
874 _cp_search_range = 30;
875 _points_under_review.reserve(_nshift * _cp_search_range);
876 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
878 unsigned rel_shift = _rel_shifts[ishift];
879 for (
unsigned int i = 0; i < shuffles.size(); i++) {
880 shuffles[i] += rel_shift; }
882 sort(shuffles.begin(), shuffles.end());
883 _trees[ishift] = auto_ptr<Tree>(
new Tree(shuffles, max_size));
884 circulator circ = _trees[ishift]->somewhere(), start=circ;
885 unsigned int CP_range = min(_cp_search_range, n_positions-1);
887 Point * this_point = circ->point;
888 this_point->circ[ishift] = circ;
889 circulator other = circ;
890 for (
unsigned i=0; i < CP_range; i++) {
892 double dist2 = this_point->distance2(*other->point);
893 if (dist2 < this_point->neighbour_dist2) {
894 this_point->neighbour_dist2 = dist2;
895 this_point->neighbour = other->point;
898 }
while (++circ != start);
900 vector<double> mindists2(n_positions);
901 for (
unsigned int i = 0; i < n_positions; i++) {
902 mindists2[i] = _points[i].neighbour_dist2;}
903 _heap = auto_ptr<MinHeap>(
new MinHeap(mindists2, max_size));
905 void ClosestPair2D::closest_pair(
unsigned int & ID1,
unsigned int & ID2,
906 double & distance2)
const {
907 ID1 = _heap->minloc();
908 ID2 = _ID(_points[ID1].neighbour);
909 distance2 = _points[ID1].neighbour_dist2;
910 if (ID1 > ID2) std::swap(ID1,ID2);
912 inline void ClosestPair2D::_add_label(Point * point,
unsigned int review_flag) {
913 if (point->review_flag == 0) _points_under_review.push_back(point);
914 point->review_flag |= review_flag;
916 inline void ClosestPair2D::_set_label(Point * point,
unsigned int review_flag) {
917 if (point->review_flag == 0) _points_under_review.push_back(point);
918 point->review_flag = review_flag;
920 void ClosestPair2D::remove(
unsigned int ID) {
921 Point * point_to_remove = & (_points[ID]);
922 _remove_from_search_tree(point_to_remove);
923 _deal_with_points_to_review();
925 void ClosestPair2D::_remove_from_search_tree(Point * point_to_remove) {
926 _available_points.push(point_to_remove);
927 _set_label(point_to_remove, _remove_heap_entry);
928 unsigned int CP_range = min(_cp_search_range, size()-1);
929 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
930 circulator removed_circ = point_to_remove->circ[ishift];
931 circulator right_end = removed_circ.next();
932 _trees[ishift]->remove(removed_circ);
933 circulator left_end = right_end, orig_right_end = right_end;
934 for (
unsigned int i = 0; i < CP_range; i++) {left_end--;}
935 if (size()-1 < _cp_search_range) {
936 left_end--; right_end--;
939 Point * left_point = left_end->point;
940 if (left_point->neighbour == point_to_remove) {
942 _add_label(left_point, _review_neighbour);
945 double dist2 = left_point->distance2(*right_end->point);
946 if (dist2 < left_point->neighbour_dist2) {
947 left_point->neighbour = right_end->point;
948 left_point->neighbour_dist2 = dist2;
950 _add_label(left_point, _review_heap_entry);
954 }
while (++left_end != orig_right_end);
957 void ClosestPair2D::_deal_with_points_to_review() {
958 unsigned int CP_range = min(_cp_search_range, size()-1);
959 while(_points_under_review.size() > 0) {
960 Point * this_point = _points_under_review.back();
961 _points_under_review.pop_back();
962 if (this_point->review_flag & _remove_heap_entry) {
963 assert(!(this_point->review_flag ^ _remove_heap_entry));
964 _heap->remove(_ID(this_point));
967 if (this_point->review_flag & _review_neighbour) {
968 this_point->neighbour_dist2 = numeric_limits<double>::max();
970 for (
unsigned int ishift = 0; ishift < _nshift; ishift++) {
971 circulator other = this_point->circ[ishift];
973 for (
unsigned i=0; i < CP_range; i++) {
975 double dist2 = this_point->distance2(*other->point);
976 if (dist2 < this_point->neighbour_dist2) {
977 this_point->neighbour_dist2 = dist2;
978 this_point->neighbour = other->point;
983 _heap->update(_ID(this_point), this_point->neighbour_dist2);
985 this_point->review_flag = 0;
988 unsigned int ClosestPair2D::insert(
const Coord2D & new_coord) {
989 assert(_available_points.size() > 0);
990 Point * new_point = _available_points.top();
991 _available_points.pop();
992 new_point->coord = new_coord;
993 _insert_into_search_tree(new_point);
994 _deal_with_points_to_review();
995 return _ID(new_point);
997 unsigned int ClosestPair2D::replace(
unsigned int ID1,
unsigned int ID2,
999 Point * point_to_remove = & (_points[ID1]);
1000 _remove_from_search_tree(point_to_remove);
1001 point_to_remove = & (_points[ID2]);
1002 _remove_from_search_tree(point_to_remove);
1003 Point * new_point = _available_points.top();
1004 _available_points.pop();
1005 new_point->coord = position;
1006 _insert_into_search_tree(new_point);
1007 _deal_with_points_to_review();
1008 return _ID(new_point);
1010 void ClosestPair2D::replace_many(
1011 const std::vector<unsigned int> & IDs_to_remove,
1012 const std::vector<Coord2D> & new_positions,
1013 std::vector<unsigned int> & new_IDs) {
1014 for (
unsigned int i = 0; i < IDs_to_remove.size(); i++) {
1015 _remove_from_search_tree(& (_points[IDs_to_remove[i]]));
1018 for (
unsigned int i = 0; i < new_positions.size(); i++) {
1019 Point * new_point = _available_points.top();
1020 _available_points.pop();
1021 new_point->coord = new_positions[i];
1022 _insert_into_search_tree(new_point);
1023 new_IDs.push_back(_ID(new_point));
1025 _deal_with_points_to_review();
1027 void ClosestPair2D::_insert_into_search_tree(Point * new_point) {
1028 _set_label(new_point, _review_heap_entry);
1029 new_point->neighbour_dist2 = numeric_limits<double>::max();
1030 unsigned int CP_range = min(_cp_search_range, size()-1);
1031 for (
unsigned ishift = 0; ishift < _nshift; ishift++) {
1032 Shuffle new_shuffle;
1033 _point2shuffle(*new_point, new_shuffle, _shifts[ishift]);
1034 circulator new_circ = _trees[ishift]->insert(new_shuffle);
1035 new_point->circ[ishift] = new_circ;
1036 circulator right_edge = new_circ; right_edge++;
1037 circulator left_edge = new_circ;
1038 for (
unsigned int i = 0; i < CP_range; i++) {left_edge--;}
1040 Point * left_point = left_edge->point;
1041 Point * right_point = right_edge->point;
1042 double new_dist2 = left_point->distance2(*new_point);
1043 if (new_dist2 < left_point->neighbour_dist2) {
1044 left_point->neighbour_dist2 = new_dist2;
1045 left_point->neighbour = new_point;
1046 _add_label(left_point, _review_heap_entry);
1048 new_dist2 = new_point->distance2(*right_point);
1049 if (new_dist2 < new_point->neighbour_dist2) {
1050 new_point->neighbour_dist2 = new_dist2;
1051 new_point->neighbour = right_point;
1053 if (left_point->neighbour == right_point) {
1054 _add_label(left_point, _review_neighbour);
1057 }
while (++left_edge != new_circ);
1060 FJCORE_END_NAMESPACE
1069 FJCORE_BEGIN_NAMESPACE
1070 using namespace std;
1071 std::ostream * ClusterSequence::_fastjet_banner_ostr = &cout;
1072 ClusterSequence::~ClusterSequence () {
1073 if (_structure_shared_ptr()){
1075 assert(csi != NULL);
1076 csi->set_associated_cs(NULL);
1077 if (_deletes_self_when_unused) {
1078 _structure_shared_ptr.set_count(_structure_shared_ptr.use_count()
1079 + _structure_use_count_after_construction);
1083 void ClusterSequence::signal_imminent_self_deletion()
const {
1084 assert(_deletes_self_when_unused);
1085 _deletes_self_when_unused =
false;
1087 void ClusterSequence::_initialise_and_run (
1089 const bool & writeout_combinations) {
1090 _decant_options(jet_def_in, writeout_combinations);
1091 _initialise_and_run_no_decant();
1093 void ClusterSequence::_initialise_and_run_no_decant () {
1094 _fill_initial_history();
1095 if (n_particles() == 0)
return;
1096 if (_jet_algorithm == plugin_algorithm) {
1097 _plugin_activated =
true;
1098 _jet_def.plugin()->run_clustering( (*
this) );
1099 _plugin_activated =
false;
1100 _update_structure_use_count();
1102 }
else if (_jet_algorithm == ee_kt_algorithm ||
1103 _jet_algorithm == ee_genkt_algorithm) {
1104 _strategy = N2Plain;
1105 if (_jet_algorithm == ee_kt_algorithm) {
1106 assert(_Rparam > 2.0);
1113 _R2 = 2 * ( 3.0 + cos(_Rparam) );
1115 _R2 = 2 * ( 1.0 - cos(_Rparam) );
1119 _simple_N2_cluster_EEBriefJet();
1121 }
else if (_jet_algorithm == undefined_jet_algorithm) {
1122 throw Error(
"A ClusterSequence cannot be created with an uninitialised JetDefinition");
1124 if (_strategy == Best) {
1125 int N = _jets.size();
1126 if (min(1.0,max(0.1,_Rparam)*3.3)*N <= 30) {
1127 _strategy = N2Plain;
1128 }
else if (N > 6200/pow(_Rparam,2.0) && _jet_def.jet_algorithm() == cambridge_algorithm) {
1129 _strategy = NlnNCam;
1130 #ifndef __FJCORE_DROP_CGAL
1131 }
else if ((N > 16000/pow(_Rparam,1.15) && _jet_def.jet_algorithm() != antikt_algorithm)
1132 || N > 35000/pow(_Rparam,1.15)) {
1134 #endif // __FJCORE_DROP_CGAL
1135 }
else if (N <= 450) {
1136 _strategy = N2Tiled;
1138 _strategy = N2MinHeapTiled;
1141 if (_Rparam >= twopi) {
1142 if ( _strategy == NlnN
1143 || _strategy == NlnN3pi
1144 || _strategy == NlnNCam
1145 || _strategy == NlnNCam2pi2R
1146 || _strategy == NlnNCam4pi) {
1147 #ifdef __FJCORE_DROP_CGAL
1148 _strategy = N2MinHeapTiled;
1150 _strategy = NlnN4pi;
1153 if (_jet_def.strategy() != Best && _strategy != _jet_def.strategy()) {
1155 oss <<
"Cluster strategy " << strategy_string(_jet_def.strategy())
1156 <<
" automatically changed to " << strategy_string()
1157 <<
" because the former is not supported for R = " << _Rparam
1159 _changed_strategy_warning.warn(oss.str());
1162 if (_strategy == N2Plain) {
1163 this->_simple_N2_cluster_BriefJet();
1164 }
else if (_strategy == N2Tiled) {
1165 this->_faster_tiled_N2_cluster();
1166 }
else if (_strategy == N2MinHeapTiled) {
1167 this->_minheap_faster_tiled_N2_cluster();
1168 }
else if (_strategy == NlnN) {
1169 this->_delaunay_cluster();
1170 }
else if (_strategy == NlnNCam) {
1171 this->_CP2DChan_cluster_2piMultD();
1172 }
else if (_strategy == NlnN3pi || _strategy == NlnN4pi ) {
1173 this->_delaunay_cluster();
1174 }
else if (_strategy == N3Dumb ) {
1175 this->_really_dumb_cluster();
1176 }
else if (_strategy == N2PoorTiled) {
1177 this->_tiled_N2_cluster();
1178 }
else if (_strategy == NlnNCam4pi) {
1179 this->_CP2DChan_cluster();
1180 }
else if (_strategy == NlnNCam2pi2R) {
1181 this->_CP2DChan_cluster_2pi2R();
1184 err <<
"Unrecognised value for strategy: "<<_strategy;
1185 throw Error(err.str());
1188 bool ClusterSequence::_first_time =
true;
1189 int ClusterSequence::_n_exclusive_warnings = 0;
1190 string fastjet_version_string() {
1191 return "FastJet version "+string(fastjet_version)+
" [fjcore]";
1193 void ClusterSequence::print_banner() {
1194 if (!_first_time) {
return;}
1195 _first_time =
false;
1196 ostream * ostr = _fastjet_banner_ostr;
1198 (*ostr) <<
"#--------------------------------------------------------------------------\n";
1199 (*ostr) <<
"# FastJet release " << fastjet_version <<
" [fjcore]" << endl;
1200 (*ostr) <<
"# M. Cacciari, G.P. Salam and G. Soyez \n";
1201 (*ostr) <<
"# A software package for jet finding and analysis at colliders \n";
1202 (*ostr) <<
"# http://fastjet.fr \n";
1204 (*ostr) <<
"# Please cite EPJC72(2012)1896 [arXiv:1111.6097] if you use this package\n";
1205 (*ostr) <<
"# for scientific work and optionally PLB641(2006)57 [hep-ph/0512210]. \n";
1207 (*ostr) <<
"# FastJet is provided without warranty under the terms of the GNU GPLv2.\n";
1208 (*ostr) <<
"# It uses T. Chan's closest pair algorithm, S. Fortune's Voronoi code";
1209 #ifndef __FJCORE_DROP_CGAL
1210 (*ostr) <<
",\n# CGAL ";
1213 #endif // __FJCORE_DROP_CGAL
1214 (*ostr) <<
"and 3rd party plugin jet algorithms. See COPYING file for details.\n";
1215 (*ostr) <<
"#--------------------------------------------------------------------------\n";
1218 void ClusterSequence::_decant_options(
const JetDefinition & jet_def_in,
1219 const bool & writeout_combinations) {
1220 _jet_def = jet_def_in;
1221 _writeout_combinations = writeout_combinations;
1223 _decant_options_partial();
1225 void ClusterSequence::_decant_options_partial() {
1227 _jet_algorithm = _jet_def.jet_algorithm();
1228 _Rparam = _jet_def.R(); _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
1229 _strategy = _jet_def.strategy();
1230 _plugin_activated =
false;
1231 _update_structure_use_count();
1233 void ClusterSequence::_fill_initial_history () {
1234 _jets.reserve(_jets.size()*2);
1235 _history.reserve(_jets.size()*2);
1237 for (
int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
1238 history_element element;
1239 element.parent1 = InexistentParent;
1240 element.parent2 = InexistentParent;
1241 element.child = Invalid;
1242 element.jetp_index = i;
1244 element.max_dij_so_far = 0.0;
1245 _history.push_back(element);
1246 _jet_def.recombiner()->preprocess(_jets[i]);
1247 _jets[i].set_cluster_hist_index(i);
1248 _set_structure_shared_ptr(_jets[i]);
1249 _Qtot += _jets[i].E();
1251 _initial_n = _jets.size();
1252 _deletes_self_when_unused =
false;
1254 string ClusterSequence::strategy_string (Strategy strategy_in)
const {
1256 switch(strategy_in) {
1258 strategy =
"NlnN";
break;
1260 strategy =
"NlnN3pi";
break;
1262 strategy =
"NlnN4pi";
break;
1264 strategy =
"N2Plain";
break;
1266 strategy =
"N2Tiled";
break;
1267 case N2MinHeapTiled:
1268 strategy =
"N2MinHeapTiled";
break;
1270 strategy =
"N2PoorTiled";
break;
1272 strategy =
"N3Dumb";
break;
1274 strategy =
"NlnNCam4pi";
break;
1276 strategy =
"NlnNCam2pi2R";
break;
1278 strategy =
"NlnNCam";
break;
1279 case plugin_strategy:
1280 strategy =
"plugin strategy";
break;
1282 strategy =
"Unrecognized";
1286 double ClusterSequence::jet_scale_for_algorithm(
1288 if (_jet_algorithm == kt_algorithm) {
return jet.kt2();}
1289 else if (_jet_algorithm == cambridge_algorithm) {
return 1.0;}
1290 else if (_jet_algorithm == antikt_algorithm) {
1291 double kt2=jet.kt2();
1292 return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
1293 }
else if (_jet_algorithm == genkt_algorithm) {
1294 double kt2 = jet.kt2();
1295 double p = jet_def().extra_param();
1296 if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300;
1298 }
else if (_jet_algorithm == cambridge_for_passive_algorithm) {
1299 double kt2 = jet.kt2();
1300 double lim = _jet_def.extra_param();
1301 if (kt2 < lim*lim && kt2 != 0.0) {
1303 }
else {
return 1.0;}
1304 }
else {
throw Error(
"Unrecognised jet algorithm");}
1306 void ClusterSequence::transfer_from_sequence(
const ClusterSequence & from_seq,
1308 if (will_delete_self_when_unused())
1309 throw(
Error(
"cannot use CS::transfer_from_sequence after a call to delete_self_when_unused()"));
1310 _jet_def = from_seq._jet_def ;
1311 _writeout_combinations = from_seq._writeout_combinations ;
1312 _initial_n = from_seq._initial_n ;
1313 _Rparam = from_seq._Rparam ;
1314 _R2 = from_seq._R2 ;
1315 _invR2 = from_seq._invR2 ;
1316 _strategy = from_seq._strategy ;
1317 _jet_algorithm = from_seq._jet_algorithm ;
1318 _plugin_activated = from_seq._plugin_activated ;
1320 _jets = (*action_on_jets)(from_seq._jets);
1322 _jets = from_seq._jets;
1323 _history = from_seq._history;
1324 _extras = from_seq._extras;
1325 if (_structure_shared_ptr()) {
1326 if (_deletes_self_when_unused)
throw Error(
"transfer_from_sequence cannot be used for a cluster sequence that deletes self when unused");
1328 assert(csi != NULL);
1329 csi->set_associated_cs(NULL);
1332 _update_structure_use_count();
1333 for (
unsigned int i=0; i<_jets.size(); i++){
1334 _jets[i].set_cluster_hist_index(from_seq._jets[i].cluster_hist_index());
1335 _set_structure_shared_ptr(_jets[i]);
1338 void ClusterSequence::plugin_record_ij_recombination(
1339 int jet_i,
int jet_j,
double dij,
1340 const PseudoJet & newjet,
int & newjet_k) {
1341 plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
1342 int tmp_index = _jets[newjet_k].cluster_hist_index();
1343 _jets[newjet_k] = newjet;
1344 _jets[newjet_k].set_cluster_hist_index(tmp_index);
1345 _set_structure_shared_ptr(_jets[newjet_k]);
1347 vector<PseudoJet> ClusterSequence::inclusive_jets (
const double & ptmin)
const{
1348 double dcut = ptmin*ptmin;
1349 int i = _history.size() - 1;
1350 vector<PseudoJet> jets_local;
1351 if (_jet_algorithm == kt_algorithm) {
1353 if (_history[i].max_dij_so_far < dcut) {
break;}
1354 if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
1356 int parent1 = _history[i].parent1;
1357 jets_local.push_back(_jets[_history[parent1].jetp_index]);}
1360 }
else if (_jet_algorithm == cambridge_algorithm) {
1362 if (_history[i].parent2 != BeamJet) {
break;}
1363 int parent1 = _history[i].parent1;
1364 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1365 if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1368 }
else if (_jet_algorithm == plugin_algorithm
1369 || _jet_algorithm == ee_kt_algorithm
1370 || _jet_algorithm == antikt_algorithm
1371 || _jet_algorithm == genkt_algorithm
1372 || _jet_algorithm == ee_genkt_algorithm
1373 || _jet_algorithm == cambridge_for_passive_algorithm) {
1375 if (_history[i].parent2 == BeamJet) {
1376 int parent1 = _history[i].parent1;
1377 const PseudoJet & jet = _jets[_history[parent1].jetp_index];
1378 if (jet.perp2() >= dcut) {jets_local.push_back(jet);}
1382 }
else {
throw Error(
"cs::inclusive_jets(...): Unrecognized jet algorithm");}
1385 int ClusterSequence::n_exclusive_jets (
const double & dcut)
const {
1386 int i = _history.size() - 1;
1388 if (_history[i].max_dij_so_far <= dcut) {
break;}
1391 int stop_point = i + 1;
1392 int njets = 2*_initial_n - stop_point;
1395 vector<PseudoJet> ClusterSequence::exclusive_jets (
const double & dcut)
const {
1396 int njets = n_exclusive_jets(dcut);
1397 return exclusive_jets(njets);
1399 vector<PseudoJet> ClusterSequence::exclusive_jets (
const int & njets)
const {
1400 if (njets > _initial_n) {
1402 err <<
"Requested " << njets <<
" exclusive jets, but there were only "
1403 << _initial_n <<
" particles in the event";
1404 throw Error(err.str());
1406 return exclusive_jets_up_to(njets);
1408 vector<PseudoJet> ClusterSequence::exclusive_jets_up_to (
const int & njets)
const {
1409 if (( _jet_def.jet_algorithm() != kt_algorithm) &&
1410 ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
1411 ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
1412 (((_jet_def.jet_algorithm() != genkt_algorithm) &&
1413 (_jet_def.jet_algorithm() != ee_genkt_algorithm)) ||
1414 (_jet_def.extra_param() <0)) &&
1415 ((_jet_def.jet_algorithm() != plugin_algorithm) ||
1416 (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
1417 (_n_exclusive_warnings < 5)) {
1418 _n_exclusive_warnings++;
1419 cerr <<
"FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
1421 int stop_point = 2*_initial_n - njets;
1422 if (stop_point < _initial_n) stop_point = _initial_n;
1423 if (2*_initial_n != static_cast<int>(_history.size())) {
1425 err <<
"2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
1426 throw Error(err.str());
1428 vector<PseudoJet> jets_local;
1429 for (
unsigned int i = stop_point; i < _history.size(); i++) {
1430 int parent1 = _history[i].parent1;
1431 if (parent1 < stop_point) {
1432 jets_local.push_back(_jets[_history[parent1].jetp_index]);
1434 int parent2 = _history[i].parent2;
1435 if (parent2 < stop_point && parent2 > 0) {
1436 jets_local.push_back(_jets[_history[parent2].jetp_index]);
1439 if (
int(jets_local.size()) != min(_initial_n, njets)) {
1441 err <<
"ClusterSequence::exclusive_jets: size of returned vector ("
1442 <<jets_local.size()<<
") does not coincide with requested number of jets ("
1444 throw Error(err.str());
1448 double ClusterSequence::exclusive_dmerge (
const int & njets)
const {
1450 if (njets >= _initial_n) {
return 0.0;}
1451 return _history[2*_initial_n-njets-1].dij;
1453 double ClusterSequence::exclusive_dmerge_max (
const int & njets)
const {
1455 if (njets >= _initial_n) {
return 0.0;}
1456 return _history[2*_initial_n-njets-1].max_dij_so_far;
1458 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1459 (
const PseudoJet & jet,
const double & dcut)
const {
1460 set<const history_element*> subhist;
1461 get_subhist_set(subhist, jet, dcut, 0);
1462 vector<PseudoJet> subjets;
1463 subjets.reserve(subhist.size());
1464 for (set<const history_element*>::iterator
elem = subhist.begin();
1466 subjets.push_back(_jets[(*elem)->jetp_index]);
1470 int ClusterSequence::n_exclusive_subjets(
const PseudoJet & jet,
1471 const double & dcut)
const {
1472 set<const history_element*> subhist;
1473 get_subhist_set(subhist, jet, dcut, 0);
1474 return subhist.size();
1476 std::vector<PseudoJet> ClusterSequence::exclusive_subjets
1477 (
const PseudoJet & jet,
int nsub)
const {
1478 vector<PseudoJet> subjets = exclusive_subjets_up_to(jet, nsub);
1479 if (
int(subjets.size()) < nsub) {
1481 err <<
"Requested " << nsub <<
" exclusive subjets, but there were only "
1482 << subjets.size() <<
" particles in the jet";
1483 throw Error(err.str());
1487 std::vector<PseudoJet> ClusterSequence::exclusive_subjets_up_to
1488 (
const PseudoJet & jet,
int nsub)
const {
1489 set<const history_element*> subhist;
1490 vector<PseudoJet> subjets;
1491 if (nsub < 0)
throw Error(
"Requested a negative number of subjets. This is nonsensical.");
1492 if (nsub == 0)
return subjets;
1493 get_subhist_set(subhist, jet, -1.0, nsub);
1494 subjets.reserve(subhist.size());
1495 for (set<const history_element*>::iterator
elem = subhist.begin();
1497 subjets.push_back(_jets[(*elem)->jetp_index]);
1501 double ClusterSequence::exclusive_subdmerge(
const PseudoJet & jet,
int nsub)
const {
1502 set<const history_element*> subhist;
1503 get_subhist_set(subhist, jet, -1.0, nsub);
1504 set<const history_element*>::iterator highest = subhist.end();
1506 return (*highest)->dij;
1508 double ClusterSequence::exclusive_subdmerge_max(
const PseudoJet & jet,
int nsub)
const {
1509 set<const history_element*> subhist;
1510 get_subhist_set(subhist, jet, -1.0, nsub);
1511 set<const history_element*>::iterator highest = subhist.end();
1513 return (*highest)->max_dij_so_far;
1515 void ClusterSequence::get_subhist_set(set<const history_element*> & subhist,
1517 double dcut,
int maxjet)
const {
1518 assert(contains(jet));
1520 subhist.insert(&(_history[jet.cluster_hist_index()]));
1523 set<const history_element*>::iterator highest = subhist.end();
1524 assert (highest != subhist.begin());
1526 const history_element*
elem = *highest;
1527 if (njet == maxjet)
break;
1528 if (elem->parent1 < 0)
break;
1529 if (elem->max_dij_so_far <= dcut)
break;
1530 subhist.erase(highest);
1531 subhist.insert(&(_history[elem->parent1]));
1532 subhist.insert(&(_history[elem->parent2]));
1536 bool ClusterSequence::object_in_jet(
const PseudoJet &
object,
1538 assert(contains(
object) && contains(jet));
1539 const PseudoJet * this_object = &object;
1542 if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
1544 }
else if (has_child(*this_object, childp)) {
1545 this_object = childp;
1553 const history_element & hist = _history[jet.cluster_hist_index()];
1554 assert ((hist.parent1 >= 0 && hist.parent2 >= 0) ||
1555 (hist.parent1 < 0 && hist.parent2 < 0));
1556 if (hist.parent1 < 0) {
1561 parent1 = _jets[_history[hist.parent1].jetp_index];
1562 parent2 = _jets[_history[hist.parent2].jetp_index];
1563 if (parent1.perp2() < parent2.perp2()) std::swap(parent1,parent2);
1569 bool res = has_child(jet, childp);
1578 bool ClusterSequence::has_child(
const PseudoJet & jet,
const PseudoJet * & childp)
const {
1579 const history_element & hist = _history[jet.cluster_hist_index()];
1580 if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
1581 childp = &(_jets[_history[hist.child].jetp_index]);
1588 bool ClusterSequence::has_partner(
const PseudoJet & jet,
1590 const history_element & hist = _history[jet.cluster_hist_index()];
1591 if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
1592 const history_element & child_hist = _history[hist.child];
1593 if (child_hist.parent1 == jet.cluster_hist_index()) {
1594 partner = _jets[_history[child_hist.parent2].jetp_index];
1596 partner = _jets[_history[child_hist.parent1].jetp_index];
1604 vector<PseudoJet> ClusterSequence::constituents (
const PseudoJet & jet)
const {
1605 vector<PseudoJet> subjets;
1606 add_constituents(jet, subjets);
1609 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets_in,
1610 ostream & ostr)
const {
1611 for (
unsigned i = 0; i < jets_in.size(); i++) {
1613 << jets_in[i].px() <<
" "
1614 << jets_in[i].py() <<
" "
1615 << jets_in[i].pz() <<
" "
1616 << jets_in[i].E() << endl;
1617 vector<PseudoJet> cst = constituents(jets_in[i]);
1618 for (
unsigned j = 0; j < cst.size() ; j++) {
1619 ostr <<
" " << j <<
" "
1620 << cst[j].rap() <<
" "
1621 << cst[j].phi() <<
" "
1622 << cst[j].perp() << endl;
1624 ostr <<
"#END" << endl;
1627 void ClusterSequence::print_jets_for_root(
const std::vector<PseudoJet> & jets_in,
1628 const std::string & filename,
1629 const std::string & comment )
const {
1630 std::ofstream ostr(filename.c_str());
1631 if (comment !=
"") ostr <<
"# " << comment << endl;
1632 print_jets_for_root(jets_in, ostr);
1634 vector<int> ClusterSequence::particle_jet_indices(
1635 const vector<PseudoJet> & jets_in)
const {
1636 vector<int> indices(n_particles());
1637 for (
unsigned ipart = 0; ipart < n_particles(); ipart++)
1638 indices[ipart] = -1;
1639 for (
unsigned ijet = 0; ijet < jets_in.size(); ijet++) {
1640 vector<PseudoJet> jet_constituents(constituents(jets_in[ijet]));
1641 for (
unsigned ip = 0; ip < jet_constituents.size(); ip++) {
1642 unsigned iclust = jet_constituents[ip].cluster_hist_index();
1643 unsigned ipart = history()[iclust].jetp_index;
1644 indices[ipart] = ijet;
1649 void ClusterSequence::add_constituents (
1650 const PseudoJet & jet, vector<PseudoJet> & subjet_vector)
const {
1651 int i = jet.cluster_hist_index();
1652 int parent1 = _history[i].parent1;
1653 int parent2 = _history[i].parent2;
1654 if (parent1 == InexistentParent) {
1655 subjet_vector.push_back(_jets[i]);
1658 add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
1659 if (parent2 != BeamJet) {
1660 add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
1663 void ClusterSequence::_add_step_to_history (
1664 const int & step_number,
const int & parent1,
1665 const int & parent2,
const int & jetp_index,
1666 const double & dij) {
1667 history_element element;
1668 element.parent1 = parent1;
1669 element.parent2 = parent2;
1670 element.jetp_index = jetp_index;
1671 element.child = Invalid;
1673 element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
1674 _history.push_back(element);
1675 int local_step = _history.size()-1;
1676 assert(local_step == step_number);
1677 assert(parent1 >= 0);
1678 _history[parent1].child = local_step;
1679 if (parent2 >= 0) {_history[parent2].child = local_step;}
1680 if (jetp_index != Invalid) {
1681 assert(jetp_index >= 0);
1682 _jets[jetp_index].set_cluster_hist_index(local_step);
1683 _set_structure_shared_ptr(_jets[jetp_index]);
1685 if (_writeout_combinations) {
1686 cout << local_step <<
": "
1687 << parent1 <<
" with " << parent2
1688 <<
"; y = "<< dij<<endl;
1691 vector<int> ClusterSequence::unique_history_order()
const {
1692 valarray<int> lowest_constituent(_history.size());
1693 int hist_n = _history.size();
1694 lowest_constituent = hist_n;
1695 for (
int i = 0; i < hist_n; i++) {
1696 lowest_constituent[i] = min(lowest_constituent[i],i);
1697 if (_history[i].child > 0) lowest_constituent[_history[i].child]
1698 = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
1700 valarray<bool> extracted(_history.size()); extracted =
false;
1701 vector<int> unique_tree;
1702 unique_tree.reserve(_history.size());
1703 for (
unsigned i = 0; i < n_particles(); i++) {
1704 if (!extracted[i]) {
1705 unique_tree.push_back(i);
1706 extracted[i] =
true;
1707 _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
1712 void ClusterSequence::_extract_tree_children(
1714 valarray<bool> & extracted,
1715 const valarray<int> & lowest_constituent,
1716 vector<int> & unique_tree)
const {
1717 if (!extracted[position]) {
1718 _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
1720 int child = _history[position].child;
1721 if (child >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
1723 vector<PseudoJet> ClusterSequence::unclustered_particles()
const {
1724 vector<PseudoJet> unclustered;
1725 for (
unsigned i = 0; i < n_particles() ; i++) {
1726 if (_history[i].child == Invalid)
1727 unclustered.push_back(_jets[_history[i].jetp_index]);
1731 vector<PseudoJet> ClusterSequence::childless_pseudojets()
const {
1732 vector<PseudoJet> unclustered;
1733 for (
unsigned i = 0; i < _history.size() ; i++) {
1734 if ((_history[i].child == Invalid) && (_history[i].parent2 != BeamJet))
1735 unclustered.push_back(_jets[_history[i].jetp_index]);
1739 bool ClusterSequence::contains(
const PseudoJet & jet)
const {
1740 return jet.cluster_hist_index() >= 0
1741 && jet.cluster_hist_index() < int(_history.size())
1742 && jet.has_valid_cluster_sequence()
1743 && jet.associated_cluster_sequence() ==
this;
1745 void ClusterSequence::_extract_tree_parents(
1747 valarray<bool> & extracted,
1748 const valarray<int> & lowest_constituent,
1749 vector<int> & unique_tree)
const {
1750 if (!extracted[position]) {
1751 int parent1 = _history[position].parent1;
1752 int parent2 = _history[position].parent2;
1753 if (parent1 >= 0 && parent2 >= 0) {
1754 if (lowest_constituent[parent1] > lowest_constituent[parent2])
1755 std::swap(parent1, parent2);
1757 if (parent1 >= 0 && !extracted[parent1])
1758 _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
1759 if (parent2 >= 0 && !extracted[parent2])
1760 _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
1761 unique_tree.push_back(position);
1762 extracted[position] =
true;
1765 void ClusterSequence::_do_ij_recombination_step(
1766 const int & jet_i,
const int & jet_j,
1770 _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
1771 _jets.push_back(newjet);
1772 newjet_k = _jets.size()-1;
1773 int newstep_k = _history.size();
1774 _jets[newjet_k].set_cluster_hist_index(newstep_k);
1775 int hist_i = _jets[jet_i].cluster_hist_index();
1776 int hist_j = _jets[jet_j].cluster_hist_index();
1777 _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
1780 void ClusterSequence::_do_iB_recombination_step(
1781 const int & jet_i,
const double & diB) {
1782 int newstep_k = _history.size();
1783 _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
1787 void ClusterSequence::_set_structure_shared_ptr(
PseudoJet & j) {
1788 j.set_structure_shared_ptr(_structure_shared_ptr);
1789 _update_structure_use_count();
1791 void ClusterSequence::_update_structure_use_count() {
1792 _structure_use_count_after_construction = _structure_shared_ptr.use_count();
1794 void ClusterSequence::delete_self_when_unused() {
1795 int new_count = _structure_shared_ptr.use_count() - _structure_use_count_after_construction;
1796 if (new_count <= 0) {
1797 throw Error(
"delete_self_when_unused may only be called if at least one object outside the CS (e.g. a jet) is already associated with the CS");
1799 _structure_shared_ptr.set_count(new_count);
1800 _deletes_self_when_unused =
true;
1802 FJCORE_END_NAMESPACE
1807 FJCORE_BEGIN_NAMESPACE
1808 using namespace std;
1813 MirrorInfo(
int a,
int b) : orig(a), mirror(b) {};
1816 bool make_mirror(
Coord2D & point,
double Dlim) {
1817 if (point.y < Dlim) {point.y += twopi;
return true;}
1818 if (twopi-point.y < Dlim) {point.y -= twopi;
return true;}
1822 using namespace Private;
1823 void ClusterSequence::_CP2DChan_limited_cluster (
double Dlim) {
1824 unsigned int n = _initial_n;
1825 vector<MirrorInfo> coordIDs(2*n);
1826 vector<int> jetIDs(2*n);
1827 vector<Coord2D> coords(2*n);
1828 double Dlim4mirror = min(Dlim,pi);
1829 double minrap = numeric_limits<double>::max();
1830 double maxrap = -minrap;
1831 int coord_index = -1;
1833 for (
unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
1834 if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
1835 (_jets[jet_i].E() == abs(_jets[jet_i].pz()) &&
1836 _jets[jet_i].perp2() == 0.0)
1839 coordIDs[jet_i].orig = ++coord_index;
1840 coords[coord_index] =
Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
1841 jetIDs[coord_index] = jet_i;
1842 minrap = min(coords[coord_index].x,minrap);
1843 maxrap = max(coords[coord_index].x,maxrap);
1844 Coord2D mirror_point(coords[coord_index]);
1845 if (make_mirror(mirror_point, Dlim4mirror)) {
1846 coordIDs[jet_i].mirror = ++coord_index;
1847 coords[coord_index] = mirror_point;
1848 jetIDs[coord_index] = jet_i;
1850 coordIDs[jet_i].mirror = Invalid;
1853 coords.resize(coord_index+1);
1854 Coord2D left_edge(minrap-1.0, -3.15);
1855 Coord2D right_edge(maxrap+1.0, 9.45);
1857 vector<Coord2D> new_points(2);
1858 vector<unsigned int> cIDs_to_remove(4);
1859 vector<unsigned int> new_cIDs(2);
1861 unsigned int cID1, cID2;
1863 cp.closest_pair(cID1,cID2,distance2);
1864 if (distance2 > Dlim*Dlim) {
break;}
1865 distance2 *= _invR2;
1866 int jet_i = jetIDs[cID1];
1867 int jet_j = jetIDs[cID2];
1868 assert (jet_i != jet_j);
1870 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
1871 if (--n_active == 1) {
break;}
1872 cIDs_to_remove.resize(0);
1873 cIDs_to_remove.push_back(coordIDs[jet_i].orig);
1874 cIDs_to_remove.push_back(coordIDs[jet_j].orig);
1875 if (coordIDs[jet_i].mirror != Invalid)
1876 cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
1877 if (coordIDs[jet_j].mirror != Invalid)
1878 cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
1879 Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
1880 new_points.resize(0);
1881 new_points.push_back(new_point);
1882 if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point);
1883 cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
1884 coordIDs[newjet_k].orig = new_cIDs[0];
1885 jetIDs[new_cIDs[0]] = newjet_k;
1886 if (new_cIDs.size() == 2) {
1887 coordIDs[newjet_k].mirror = new_cIDs[1];
1888 jetIDs[new_cIDs[1]] = newjet_k;
1889 }
else {coordIDs[newjet_k].mirror = Invalid;}
1892 void ClusterSequence::_CP2DChan_cluster_2pi2R () {
1893 if (_jet_algorithm != cambridge_algorithm)
throw Error(
"CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
1894 _CP2DChan_limited_cluster(_Rparam);
1895 _do_Cambridge_inclusive_jets();
1897 void ClusterSequence::_CP2DChan_cluster_2piMultD () {
1898 if (_Rparam >= 0.39) {
1899 _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
1901 _CP2DChan_cluster_2pi2R ();
1903 void ClusterSequence::_CP2DChan_cluster () {
1904 if (_jet_algorithm != cambridge_algorithm)
throw Error(
"_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
1905 unsigned int n = _jets.size();
1906 vector<MirrorInfo> coordIDs(2*n);
1907 vector<int> jetIDs(2*n);
1908 vector<Coord2D> coords(2*n);
1909 double minrap = numeric_limits<double>::max();
1910 double maxrap = -minrap;
1911 int coord_index = 0;
1912 for (
unsigned i = 0; i < n; i++) {
1913 if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
1916 coordIDs[i].orig = coord_index;
1917 coordIDs[i].mirror = coord_index+1;
1918 coords[coord_index] =
Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
1919 coords[coord_index+1] =
Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
1920 jetIDs[coord_index] = i;
1921 jetIDs[coord_index+1] = i;
1922 minrap = min(coords[coord_index].x,minrap);
1923 maxrap = max(coords[coord_index].x,maxrap);
1927 for (
unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
1928 coords.resize(coord_index);
1929 Coord2D left_edge(minrap-1.0, 0.0);
1930 Coord2D right_edge(maxrap+1.0, 2*twopi);
1932 vector<Coord2D> new_points(2);
1933 vector<unsigned int> cIDs_to_remove(4);
1934 vector<unsigned int> new_cIDs(2);
1936 unsigned int cID1, cID2;
1938 cp.closest_pair(cID1,cID2,distance2);
1939 distance2 *= _invR2;
1940 if (distance2 > 1.0) {
break;}
1941 int jet_i = jetIDs[cID1];
1942 int jet_j = jetIDs[cID2];
1943 assert (jet_i != jet_j);
1945 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
1946 cIDs_to_remove[0] = coordIDs[jet_i].orig;
1947 cIDs_to_remove[1] = coordIDs[jet_i].mirror;
1948 cIDs_to_remove[2] = coordIDs[jet_j].orig;
1949 cIDs_to_remove[3] = coordIDs[jet_j].mirror;
1950 new_points[0] =
Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
1951 new_points[1] =
Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
1952 new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
1953 new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
1954 coordIDs[jet_i].orig = Invalid;
1955 coordIDs[jet_j].orig = Invalid;
1956 coordIDs[newjet_k] =
MirrorInfo(new_cIDs[0], new_cIDs[1]);
1957 jetIDs[new_cIDs[0]] = newjet_k;
1958 jetIDs[new_cIDs[1]] = newjet_k;
1960 if (n == 1) {
break;}
1962 _do_Cambridge_inclusive_jets();
1964 void ClusterSequence::_do_Cambridge_inclusive_jets () {
1965 unsigned int n = _history.size();
1966 for (
unsigned int hist_i = 0; hist_i < n; hist_i++) {
1967 if (_history[hist_i].child == Invalid) {
1968 _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
1972 FJCORE_END_NAMESPACE
1979 #ifndef __FJCORE_DROP_CGAL // in case we do not have the code for CGAL
1980 #include "fastjet/internal/Dnn4piCylinder.hh"
1981 #include "fastjet/internal/Dnn3piCylinder.hh"
1982 #include "fastjet/internal/Dnn2piCylinder.hh"
1983 #endif // __FJCORE_DROP_CGAL
1984 FJCORE_BEGIN_NAMESPACE
1985 using namespace std;
1986 void ClusterSequence::_delaunay_cluster () {
1987 int n = _jets.size();
1988 vector<EtaPhi> points(n);
1989 for (
int i = 0; i < n; i++) {
1990 points[i] =
EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
1991 points[i].sanitize();
1993 auto_ptr<DynamicNearestNeighbours> DNN;
1994 #ifndef __FJCORE_DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
1995 bool verbose =
false;
1996 bool ignore_nearest_is_mirror = (_Rparam < twopi);
1997 if (_strategy == NlnN4pi) {
1998 DNN.reset(
new Dnn4piCylinder(points,verbose));
1999 }
else if (_strategy == NlnN3pi) {
2000 DNN.reset(
new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose));
2001 }
else if (_strategy == NlnN) {
2002 DNN.reset(
new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose));
2005 if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
2007 err <<
"ERROR: Requested strategy "<<strategy_string()<<
" but it is not"<<endl;
2008 err <<
" supported because FastJet was compiled without CGAL"<<endl;
2009 throw Error(err.str());
2011 #endif // __FJCORE_DROP_CGAL
2014 err <<
"ERROR: Unrecognized value for strategy: "<<_strategy<<endl;
2016 throw Error(err.str());
2019 for (
int ii = 0; ii < n; ii++) {
2020 _add_ktdistance_to_map(ii, DijMap, DNN.get());
2022 for (
int i=0;i<n;i++) {
2023 TwoVertices SmallestDijPair;
2027 bool recombine_with_beam;
2029 SmallestDij = DijMap.begin()->first;
2030 SmallestDijPair = DijMap.begin()->second;
2031 jet_i = SmallestDijPair.first;
2032 jet_j = SmallestDijPair.second;
2033 DijMap.erase(DijMap.begin());
2034 recombine_with_beam = (jet_j == BeamJet);
2035 if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);}
2036 else {Valid2 =
true;}
2037 }
while ( !DNN->Valid(jet_i) || !Valid2);
2038 if (! recombine_with_beam) {
2040 _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
2041 EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
2042 newpoint.sanitize();
2043 points.push_back(newpoint);
2045 _do_iB_recombination_step(jet_i, SmallestDij);
2047 if (i == n-1) {
break;}
2048 vector<int> updated_neighbours;
2049 if (! recombine_with_beam) {
2051 DNN->RemoveCombinedAddCombination(jet_i, jet_j,
2052 points[points.size()-1], point3,
2053 updated_neighbours);
2054 if (static_cast<unsigned int> (point3) != points.size()-1) {
2055 throw Error(
"INTERNAL ERROR: point3 != points.size()-1");}
2057 DNN->RemovePoint(jet_i, updated_neighbours);
2059 vector<int>::iterator it = updated_neighbours.begin();
2060 for (; it != updated_neighbours.end(); ++it) {
2062 _add_ktdistance_to_map(ii, DijMap, DNN.get());
2066 void ClusterSequence::_add_ktdistance_to_map(
2070 double yiB = jet_scale_for_algorithm(_jets[ii]);
2072 DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2074 double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
2075 if (DeltaR2 > 1.0) {
2076 DijMap.insert(DijEntry(yiB, TwoVertices(ii,-1)));
2078 double kt2i = jet_scale_for_algorithm(_jets[ii]);
2079 int jj = DNN->NearestNeighbourIndex(ii);
2080 if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
2081 double dij = DeltaR2 * kt2i;
2082 DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
2087 FJCORE_END_NAMESPACE
2092 FJCORE_BEGIN_NAMESPACE
2093 using namespace std;
2094 void ClusterSequence::_really_dumb_cluster () {
2095 vector<PseudoJet *> jetsp(_jets.size());
2096 vector<int> indices(_jets.size());
2097 for (
size_t i = 0; i<_jets.size(); i++) {
2098 jetsp[i] = & _jets[i];
2101 for (
int n = jetsp.size(); n > 0; n--) {
2103 double ymin = jet_scale_for_algorithm(*(jetsp[0]));
2105 for (
int i = 0; i < n; i++) {
2106 double yiB = jet_scale_for_algorithm(*(jetsp[i]));
2108 ymin = yiB; ii = i; jj = -2;}
2110 for (
int i = 0; i < n-1; i++) {
2111 for (
int j = i+1; j < n; j++) {
2113 double y = min(jet_scale_for_algorithm(*(jetsp[i])),
2114 jet_scale_for_algorithm(*(jetsp[j])))
2115 * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
2116 if (y < ymin) {ymin = y; ii = i; jj = j;}
2119 int newn = 2*jetsp.size() - n;
2122 _do_ij_recombination_step(jetsp[ii]-&_jets[0],
2123 jetsp[jj]-&_jets[0], ymin, nn);
2124 jetsp[ii] = &_jets[nn];
2125 jetsp[jj] = jetsp[n-1];
2127 indices[jj] = indices[n-1];
2129 _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
2130 jetsp[ii] = jetsp[n-1];
2131 indices[ii] = indices[n-1];
2135 FJCORE_END_NAMESPACE
2137 FJCORE_BEGIN_NAMESPACE
2138 using namespace std;
2139 template<>
inline void ClusterSequence::_bj_set_jetinfo(
2140 EEBriefJet *
const jetA,
const int _jets_index)
const {
2141 double E = _jets[_jets_index].E();
2143 double p = jet_def().extra_param();
2144 switch (_jet_algorithm) {
2145 case ee_kt_algorithm:
2146 assert(_Rparam > 2.0);
2148 case ee_genkt_algorithm:
2149 if (p <= 0 && scale < 1e-300) scale = 1e-300;
2150 scale = pow(scale,p);
2153 throw Error(
"Unrecognised jet algorithm");
2156 double norm = _jets[_jets_index].modp2();
2158 norm = 1.0/sqrt(norm);
2159 jetA->nx = norm * _jets[_jets_index].px();
2160 jetA->ny = norm * _jets[_jets_index].py();
2161 jetA->nz = norm * _jets[_jets_index].pz();
2167 jetA->_jets_index = _jets_index;
2168 jetA->NN_dist = _R2;
2171 template<>
double ClusterSequence::_bj_dist(
2172 const EEBriefJet *
const jeta,
2173 const EEBriefJet *
const jetb)
const {
2177 - jeta->nz*jetb->nz;
2181 void ClusterSequence::_simple_N2_cluster_BriefJet() {
2182 _simple_N2_cluster<BriefJet>();
2184 void ClusterSequence::_simple_N2_cluster_EEBriefJet() {
2185 _simple_N2_cluster<EEBriefJet>();
2187 FJCORE_END_NAMESPACE
2189 FJCORE_BEGIN_NAMESPACE
2190 using namespace std;
2191 ClusterSequenceStructure::~ClusterSequenceStructure(){
2192 if (_associated_cs != NULL
2193 && _associated_cs->will_delete_self_when_unused()) {
2194 _associated_cs->signal_imminent_self_deletion();
2195 delete _associated_cs;
2198 bool ClusterSequenceStructure::has_valid_cluster_sequence()
const{
2199 return (_associated_cs != NULL);
2201 const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence()
const{
2202 return _associated_cs;
2204 const ClusterSequence * ClusterSequenceStructure::validated_cs()
const {
2205 if (!_associated_cs)
2206 throw Error(
"you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
2207 return _associated_cs;
2209 bool ClusterSequenceStructure::has_partner(
const PseudoJet &reference,
PseudoJet &partner)
const{
2210 return validated_cs()->has_partner(reference, partner);
2212 bool ClusterSequenceStructure::has_child(
const PseudoJet &reference,
PseudoJet &child)
const{
2213 return validated_cs()->has_child(reference, child);
2216 return validated_cs()->has_parents(reference, parent1, parent2);
2218 bool ClusterSequenceStructure::object_in_jet(
const PseudoJet &reference,
const PseudoJet &jet)
const{
2219 if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
2220 throw Error(
"you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2221 if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence())
return false;
2222 return validated_cs()->object_in_jet(reference, jet);
2224 bool ClusterSequenceStructure::has_constituents()
const{
2225 if (!has_associated_cluster_sequence())
2226 throw Error(
"you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2229 vector<PseudoJet> ClusterSequenceStructure::constituents(
const PseudoJet &reference)
const{
2230 return validated_cs()->constituents(reference);
2232 bool ClusterSequenceStructure::has_exclusive_subjets()
const{
2233 if (!has_associated_cluster_sequence())
2234 throw Error(
"you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
2237 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (
const PseudoJet &reference,
const double & dcut)
const {
2238 return validated_cs()->exclusive_subjets(reference, dcut);
2240 int ClusterSequenceStructure::n_exclusive_subjets(
const PseudoJet &reference,
const double & dcut)
const {
2241 return validated_cs()->n_exclusive_subjets(reference, dcut);
2243 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (
const PseudoJet &reference,
int nsub)
const {
2244 return validated_cs()->exclusive_subjets_up_to(reference, nsub);
2246 double ClusterSequenceStructure::exclusive_subdmerge(
const PseudoJet &reference,
int nsub)
const {
2247 return validated_cs()->exclusive_subdmerge(reference, nsub);
2249 double ClusterSequenceStructure::exclusive_subdmerge_max(
const PseudoJet &reference,
int nsub)
const {
2250 return validated_cs()->exclusive_subdmerge_max(reference, nsub);
2252 bool ClusterSequenceStructure::has_pieces(
const PseudoJet &reference)
const{
2254 return has_parents(reference, dummy1, dummy2);
2256 vector<PseudoJet> ClusterSequenceStructure::pieces(
const PseudoJet &reference)
const{
2258 vector<PseudoJet> res;
2259 if (has_parents(reference, j1, j2)){
2265 FJCORE_END_NAMESPACE
2270 FJCORE_BEGIN_NAMESPACE
2271 using namespace std;
2272 void ClusterSequence::_bj_remove_from_tiles(
TiledJet *
const jet) {
2273 Tile * tile = & _tiles[jet->tile_index];
2274 if (jet->previous == NULL) {
2275 tile->head = jet->next;
2277 jet->previous->next = jet->next;
2279 if (jet->next != NULL) {
2280 jet->next->previous = jet->previous;
2283 void ClusterSequence::_initialise_tiles() {
2284 double default_size = max(0.1,_Rparam);
2285 _tile_size_eta = default_size;
2286 _n_tiles_phi = max(3,
int(floor(twopi/default_size)));
2287 _tile_size_phi = twopi / _n_tiles_phi;
2288 _tiles_eta_min = 0.0;
2289 _tiles_eta_max = 0.0;
2290 const double maxrap = 7.0;
2291 for(
unsigned int i = 0; i < _jets.size(); i++) {
2292 double eta = _jets[i].rap();
2293 if (abs(eta) < maxrap) {
2294 if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
2295 if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
2298 _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
2299 _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
2300 _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
2301 _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
2302 _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
2303 for (
int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
2304 for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
2305 Tile * tile = & _tiles[_tile_index(ieta,iphi)];
2307 tile->begin_tiles[0] = tile;
2308 Tile ** pptile = & (tile->begin_tiles[0]);
2310 tile->surrounding_tiles = pptile;
2311 if (ieta > _tiles_ieta_min) {
2315 for (
int idphi = -1; idphi <=+1; idphi++) {
2316 *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
2320 *pptile = & _tiles[_tile_index(ieta,iphi-1)];
2322 tile->RH_tiles = pptile;
2323 *pptile = & _tiles[_tile_index(ieta,iphi+1)];
2325 if (ieta < _tiles_ieta_max) {
2326 for (
int idphi = -1; idphi <= +1; idphi++) {
2327 *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
2331 tile->end_tiles = pptile;
2332 tile->tagged =
false;
2336 int ClusterSequence::_tile_index(
const double & eta,
const double & phi)
const {
2338 if (eta <= _tiles_eta_min) {ieta = 0;}
2339 else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
2341 ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
2342 if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
2343 ieta = _tiles_ieta_max-_tiles_ieta_min;}
2345 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
2346 return (iphi + ieta * _n_tiles_phi);
2348 inline void ClusterSequence::_tj_set_jetinfo(
TiledJet *
const jet,
2349 const int _jets_index) {
2350 _bj_set_jetinfo<>(jet, _jets_index);
2351 jet->tile_index = _tile_index(jet->eta, jet->phi);
2352 Tile * tile = &_tiles[jet->tile_index];
2353 jet->previous = NULL;
2354 jet->next = tile->head;
2355 if (jet->next != NULL) {jet->next->previous = jet;}
2358 void ClusterSequence::_print_tiles(
TiledJet * briefjets )
const {
2359 for (vector<Tile>::const_iterator tile = _tiles.begin();
2360 tile < _tiles.end(); tile++) {
2361 cout <<
"Tile " << tile - _tiles.begin()<<
" = ";
2363 for (
TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
2364 list.push_back(jetI-briefjets);
2366 sort(list.begin(),list.end());
2367 for (
unsigned int i = 0; i < list.size(); i++) {cout <<
" "<<list[i];}
2371 void ClusterSequence::_add_neighbours_to_tile_union(
const int tile_index,
2372 vector<int> & tile_union,
int & n_near_tiles)
const {
2373 for (
Tile *
const * near_tile = _tiles[tile_index].begin_tiles;
2374 near_tile != _tiles[tile_index].end_tiles; near_tile++){
2375 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2379 inline void ClusterSequence::_add_untagged_neighbours_to_tile_union(
2380 const int tile_index,
2381 vector<int> & tile_union,
int & n_near_tiles) {
2382 for (
Tile ** near_tile = _tiles[tile_index].begin_tiles;
2383 near_tile != _tiles[tile_index].end_tiles; near_tile++){
2384 if (! (*near_tile)->tagged) {
2385 (*near_tile)->tagged =
true;
2386 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
2391 void ClusterSequence::_tiled_N2_cluster() {
2392 _initialise_tiles();
2393 int n = _jets.size();
2395 TiledJet * jetA = briefjets, * jetB;
2398 vector<int> tile_union(3*n_tile_neighbours);
2399 for (
int i = 0; i< n; i++) {
2400 _tj_set_jetinfo(jetA, i);
2405 vector<Tile>::const_iterator tile;
2406 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2407 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2408 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2409 double dist = _bj_dist(jetA,jetB);
2410 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2411 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2414 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2415 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2416 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2417 double dist = _bj_dist(jetA,jetB);
2418 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2419 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2424 double * diJ =
new double[n];
2426 for (
int i = 0; i < n; i++) {
2427 diJ[i] = _bj_diJ(jetA);
2430 int history_location = n-1;
2431 while (tail != head) {
2432 double diJ_min = diJ[0];
2433 int diJ_min_jet = 0;
2434 for (
int i = 1; i < n; i++) {
2435 if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min = diJ[i];}
2438 jetA = & briefjets[diJ_min_jet];
2442 if (jetA < jetB) {std::swap(jetA,jetB);}
2444 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2445 _bj_remove_from_tiles(jetA);
2447 _bj_remove_from_tiles(jetB);
2448 _tj_set_jetinfo(jetB, nn);
2450 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2451 _bj_remove_from_tiles(jetA);
2453 int n_near_tiles = 0;
2454 _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
2456 bool sort_it =
false;
2457 if (jetB->tile_index != jetA->tile_index) {
2459 _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
2461 if (oldB.tile_index != jetA->tile_index &&
2462 oldB.tile_index != jetB->tile_index) {
2464 _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
2468 sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
2471 for (
int i = 1; i < n_near_tiles; i++) {
2472 if (tile_union[i] != tile_union[nnn-1]) {
2473 tile_union[nnn] = tile_union[i];
2484 diJ[jetA - head] = diJ[tail-head];
2485 if (jetA->previous == NULL) {
2486 _tiles[jetA->tile_index].head = jetA;
2488 jetA->previous->next = jetA;
2490 if (jetA->next != NULL) {jetA->next->previous = jetA;}
2492 for (
int itile = 0; itile < n_near_tiles; itile++) {
2493 Tile * tile_ptr = &_tiles[tile_union[itile]];
2494 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2496 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2497 jetI->NN_dist = _R2;
2500 for (
Tile ** near_tile = tile_ptr->begin_tiles;
2501 near_tile != tile_ptr->end_tiles; near_tile++) {
2503 for (
TiledJet * jetJ = (*near_tile)->head;
2504 jetJ != NULL; jetJ = jetJ->next) {
2505 double dist = _bj_dist(jetI,jetJ);
2506 if (dist < jetI->NN_dist && jetJ != jetI) {
2507 jetI->NN_dist = dist; jetI->NN = jetJ;
2511 diJ[jetI-head] = _bj_diJ(jetI);
2516 double dist = _bj_dist(jetI,jetB);
2517 if (dist < jetI->NN_dist) {
2519 jetI->NN_dist = dist;
2521 diJ[jetI-head] = _bj_diJ(jetI);
2524 if (dist < jetB->NN_dist) {
2526 jetB->NN_dist = dist;
2532 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
2533 for (
Tile ** near_tile = _tiles[tail->tile_index].begin_tiles;
2534 near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
2535 for (
TiledJet * jetJ = (*near_tile)->head;
2536 jetJ != NULL; jetJ = jetJ->next) {
2537 if (jetJ->NN == tail) {jetJ->NN = jetA;}
2540 if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
2545 void ClusterSequence::_faster_tiled_N2_cluster() {
2546 _initialise_tiles();
2547 int n = _jets.size();
2549 TiledJet * jetA = briefjets, * jetB;
2552 vector<int> tile_union(3*n_tile_neighbours);
2553 for (
int i = 0; i< n; i++) {
2554 _tj_set_jetinfo(jetA, i);
2558 vector<Tile>::const_iterator tile;
2559 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2560 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2561 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2562 double dist = _bj_dist(jetA,jetB);
2563 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2564 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2567 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2568 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2569 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2570 double dist = _bj_dist(jetA,jetB);
2571 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2572 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2577 struct diJ_plus_link {
2581 diJ_plus_link * diJ =
new diJ_plus_link[n];
2583 for (
int i = 0; i < n; i++) {
2584 diJ[i].diJ = _bj_diJ(jetA);
2589 int history_location = n-1;
2591 diJ_plus_link * best, *stop;
2592 double diJ_min = diJ[0].diJ;
2595 for (diJ_plus_link * here = diJ+1; here != stop; here++) {
2596 if (here->diJ < diJ_min) {best = here; diJ_min = here->diJ;}
2603 if (jetA < jetB) {std::swap(jetA,jetB);}
2605 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2606 _bj_remove_from_tiles(jetA);
2608 _bj_remove_from_tiles(jetB);
2609 _tj_set_jetinfo(jetB, nn);
2611 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2612 _bj_remove_from_tiles(jetA);
2614 int n_near_tiles = 0;
2615 _add_untagged_neighbours_to_tile_union(jetA->tile_index,
2616 tile_union, n_near_tiles);
2618 if (jetB->tile_index != jetA->tile_index) {
2619 _add_untagged_neighbours_to_tile_union(jetB->tile_index,
2620 tile_union,n_near_tiles);
2622 if (oldB.tile_index != jetA->tile_index &&
2623 oldB.tile_index != jetB->tile_index) {
2624 _add_untagged_neighbours_to_tile_union(oldB.tile_index,
2625 tile_union,n_near_tiles);
2629 diJ[n].jet->diJ_posn = jetA->diJ_posn;
2630 diJ[jetA->diJ_posn] = diJ[n];
2631 for (
int itile = 0; itile < n_near_tiles; itile++) {
2632 Tile * tile_ptr = &_tiles[tile_union[itile]];
2633 tile_ptr->tagged =
false;
2634 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2636 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2637 jetI->NN_dist = _R2;
2640 for (
Tile ** near_tile = tile_ptr->begin_tiles;
2641 near_tile != tile_ptr->end_tiles; near_tile++) {
2643 for (
TiledJet * jetJ = (*near_tile)->head;
2644 jetJ != NULL; jetJ = jetJ->next) {
2645 double dist = _bj_dist(jetI,jetJ);
2646 if (dist < jetI->NN_dist && jetJ != jetI) {
2647 jetI->NN_dist = dist; jetI->NN = jetJ;
2651 diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI);
2657 double dist = _bj_dist(jetI,jetB);
2658 if (dist < jetI->NN_dist) {
2660 jetI->NN_dist = dist;
2662 diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI);
2665 if (dist < jetB->NN_dist) {
2667 jetB->NN_dist = dist;
2673 if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
2678 void ClusterSequence::_minheap_faster_tiled_N2_cluster() {
2679 _initialise_tiles();
2680 int n = _jets.size();
2682 TiledJet * jetA = briefjets, * jetB;
2685 vector<int> tile_union(3*n_tile_neighbours);
2686 for (
int i = 0; i< n; i++) {
2687 _tj_set_jetinfo(jetA, i);
2691 vector<Tile>::const_iterator tile;
2692 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
2693 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2694 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
2695 double dist = _bj_dist(jetA,jetB);
2696 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2697 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2700 for (
Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
2701 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
2702 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
2703 double dist = _bj_dist(jetA,jetB);
2704 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
2705 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
2710 vector<double> diJs(n);
2711 for (
int i = 0; i < n; i++) {
2712 diJs[i] = _bj_diJ(&briefjets[i]);
2713 briefjets[i].label_minheap_update_done();
2716 vector<TiledJet *> jets_for_minheap;
2717 jets_for_minheap.reserve(n);
2718 int history_location = n-1;
2720 double diJ_min = minheap.minval() *_invR2;
2721 jetA = head + minheap.minloc();
2725 if (jetA < jetB) {std::swap(jetA,jetB);}
2727 _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
2728 _bj_remove_from_tiles(jetA);
2730 _bj_remove_from_tiles(jetB);
2731 _tj_set_jetinfo(jetB, nn);
2733 _do_iB_recombination_step(jetA->_jets_index, diJ_min);
2734 _bj_remove_from_tiles(jetA);
2736 minheap.remove(jetA-head);
2737 int n_near_tiles = 0;
2738 _add_untagged_neighbours_to_tile_union(jetA->tile_index,
2739 tile_union, n_near_tiles);
2741 if (jetB->tile_index != jetA->tile_index) {
2742 _add_untagged_neighbours_to_tile_union(jetB->tile_index,
2743 tile_union,n_near_tiles);
2745 if (oldB.tile_index != jetA->tile_index &&
2746 oldB.tile_index != jetB->tile_index) {
2754 _add_untagged_neighbours_to_tile_union(oldB.tile_index,
2755 tile_union,n_near_tiles);
2757 jetB->label_minheap_update_needed();
2758 jets_for_minheap.push_back(jetB);
2760 for (
int itile = 0; itile < n_near_tiles; itile++) {
2761 Tile * tile_ptr = &_tiles[tile_union[itile]];
2762 tile_ptr->tagged =
false;
2763 for (
TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
2765 if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
2766 jetI->NN_dist = _R2;
2769 if (!jetI->minheap_update_needed()) {
2770 jetI->label_minheap_update_needed();
2771 jets_for_minheap.push_back(jetI);}
2773 for (
Tile ** near_tile = tile_ptr->begin_tiles;
2774 near_tile != tile_ptr->end_tiles; near_tile++) {
2776 for (
TiledJet * jetJ = (*near_tile)->head;
2777 jetJ != NULL; jetJ = jetJ->next) {
2778 double dist = _bj_dist(jetI,jetJ);
2779 if (dist < jetI->NN_dist && jetJ != jetI) {
2780 jetI->NN_dist = dist; jetI->NN = jetJ;
2789 double dist = _bj_dist(jetI,jetB);
2790 if (dist < jetI->NN_dist) {
2792 jetI->NN_dist = dist;
2795 if (!jetI->minheap_update_needed()) {
2796 jetI->label_minheap_update_needed();
2797 jets_for_minheap.push_back(jetI);}
2800 if (dist < jetB->NN_dist) {
2802 jetB->NN_dist = dist;
2808 while (jets_for_minheap.size() > 0) {
2809 TiledJet * jetI = jets_for_minheap.back();
2810 jets_for_minheap.pop_back();
2811 minheap.update(jetI-head, _bj_diJ(jetI));
2812 jetI->label_minheap_update_done();
2818 FJCORE_END_NAMESPACE
2819 FJCORE_BEGIN_NAMESPACE
2820 using namespace std;
2821 CompositeJetStructure::CompositeJetStructure(
const std::vector<PseudoJet> & initial_pieces,
2823 : _pieces(initial_pieces){
2825 _area_4vector_ptr = 0;
2827 std::string CompositeJetStructure::description()
const{
2828 string str =
"Composite PseudoJet";
2831 bool CompositeJetStructure::has_constituents()
const{
2832 return _pieces.size()!=0;
2834 std::vector<PseudoJet> CompositeJetStructure::constituents(
const PseudoJet & )
const{
2835 vector<PseudoJet> all_constituents;
2836 for (
unsigned i = 0; i < _pieces.size(); i++) {
2837 if (_pieces[i].has_constituents()){
2838 vector<PseudoJet> constits = _pieces[i].constituents();
2839 copy(constits.begin(), constits.end(), back_inserter(all_constituents));
2841 all_constituents.push_back(_pieces[i]);
2844 return all_constituents;
2846 std::vector<PseudoJet> CompositeJetStructure::pieces(
const PseudoJet & )
const{
2849 FJCORE_END_NAMESPACE
2851 #ifdef FJCORE_HAVE_EXECINFO_H
2852 #include <execinfo.h>
2855 FJCORE_BEGIN_NAMESPACE
2856 using namespace std;
2857 bool Error::_print_errors =
true;
2858 bool Error::_print_backtrace =
false;
2859 ostream * Error::_default_ostr = & cerr;
2860 Error::Error(
const std::string & message_in) {
2861 _message = message_in;
2862 if (_print_errors && _default_ostr){
2864 oss <<
"fjcore::Error: "<< message_in << endl;
2865 #ifdef FJCORE_HAVE_EXECINFO_H
2866 if (_print_backtrace){
2869 int size = backtrace(array, 10);
2870 messages = backtrace_symbols(array, size);
2871 oss <<
"stack:" << endl;
2872 for (
int i = 1; i < size && messages != NULL; ++i){
2873 oss <<
" #" << i <<
": " << messages[i] << endl;
2878 *_default_ostr << oss.str();
2879 _default_ostr->flush();
2882 FJCORE_END_NAMESPACE
2885 using namespace std;
2886 FJCORE_BEGIN_NAMESPACE
2887 FJCORE_END_NAMESPACE
2889 FJCORE_BEGIN_NAMESPACE
2890 using namespace std;
2891 const double JetDefinition::max_allowable_R = 1000.0;
2892 JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in,
2894 Strategy strategy_in,
2895 RecombinationScheme recomb_scheme_in,
2897 _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
2898 if (_jet_algorithm == ee_kt_algorithm) {
2901 if (R_in > max_allowable_R) {
2903 oss <<
"Requested R = " << R_in <<
" for jet definition is larger than max_allowable_R = " << max_allowable_R;
2904 throw Error(oss.str());
2907 switch (jet_algorithm_in) {
2908 case ee_kt_algorithm:
2909 if (nparameters != 0) {
2911 oss <<
"ee_kt_algorithm should be constructed with 0 parameters but was called with "
2912 << nparameters <<
" parameter(s)\n";
2913 throw Error(oss.str());
2916 case genkt_algorithm:
2917 case ee_genkt_algorithm:
2918 if (nparameters != 2) {
2920 oss <<
"(ee_)genkt_algorithm should be constructed with 2 parameters but was called with "
2921 << nparameters <<
" parameter(s)\n";
2922 throw Error(oss.str());
2926 if (nparameters != 1) {
2928 oss <<
"The jet algorithm you requested ("
2929 << jet_algorithm_in <<
") should be constructed with 1 parameter but was called with "
2930 << nparameters <<
" parameter(s)\n";
2931 throw Error(oss.str());
2934 assert (_strategy != plugin_strategy);
2936 set_recombination_scheme(recomb_scheme_in);
2937 set_extra_param(0.0);
2939 string JetDefinition::description()
const {
2941 if (jet_algorithm() == plugin_algorithm) {
2942 return plugin()->description();
2943 }
else if (jet_algorithm() == kt_algorithm) {
2944 name <<
"Longitudinally invariant kt algorithm with R = " << R();
2945 name <<
" and " << recombiner()->description();
2946 }
else if (jet_algorithm() == cambridge_algorithm) {
2947 name <<
"Longitudinally invariant Cambridge/Aachen algorithm with R = "
2949 name <<
" and " << recombiner()->description();
2950 }
else if (jet_algorithm() == antikt_algorithm) {
2951 name <<
"Longitudinally invariant anti-kt algorithm with R = "
2953 name <<
" and " << recombiner()->description();
2954 }
else if (jet_algorithm() == genkt_algorithm) {
2955 name <<
"Longitudinally invariant generalised kt algorithm with R = "
2956 << R() <<
", p = " << extra_param();
2957 name <<
" and " << recombiner()->description();
2958 }
else if (jet_algorithm() == cambridge_for_passive_algorithm) {
2959 name <<
"Longitudinally invariant Cambridge/Aachen algorithm with R = "
2960 << R() <<
"and a special hack whereby particles with kt < "
2961 << extra_param() <<
"are treated as passive ghosts";
2962 }
else if (jet_algorithm() == ee_kt_algorithm) {
2963 name <<
"e+e- kt (Durham) algorithm (NB: no R)";
2964 name <<
" with " << recombiner()->description();
2965 }
else if (jet_algorithm() == ee_genkt_algorithm) {
2966 name <<
"e+e- generalised kt algorithm with R = "
2967 << R() <<
", p = " << extra_param();
2968 name <<
" and " << recombiner()->description();
2969 }
else if (jet_algorithm() == undefined_jet_algorithm) {
2970 name <<
"uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
2972 throw Error(
"JetDefinition::description(): unrecognized jet_algorithm");
2976 void JetDefinition::set_recombination_scheme(
2977 RecombinationScheme recomb_scheme) {
2979 if (_recombiner_shared()) _recombiner_shared.reset();
2982 bool JetDefinition::has_same_recombiner(
const JetDefinition &other_jd)
const{
2983 const RecombinationScheme & scheme = recombination_scheme();
2984 if (other_jd.recombination_scheme() != scheme)
return false;
2985 return (scheme != external_scheme)
2986 || (recombiner() == other_jd.recombiner());
2988 void JetDefinition::delete_recombiner_when_unused(){
2989 if (_recombiner == 0){
2990 throw Error(
"tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
2992 _recombiner_shared.reset(_recombiner);
2994 void JetDefinition::delete_plugin_when_unused(){
2996 throw Error(
"tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
2998 _plugin_shared.reset(_plugin);
3000 string JetDefinition::DefaultRecombiner::description()
const {
3001 switch(_recomb_scheme) {
3003 return "E scheme recombination";
3005 return "pt scheme recombination";
3007 return "pt2 scheme recombination";
3009 return "Et scheme recombination";
3011 return "Et2 scheme recombination";
3013 return "boost-invariant pt scheme recombination";
3015 return "boost-invariant pt2 scheme recombination";
3018 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3020 throw Error(err.str());
3023 void JetDefinition::DefaultRecombiner::recombine(
3026 double weighta, weightb;
3027 switch(_recomb_scheme) {
3029 pab.reset(pa.px()+pb.px(),
3037 weighta = pa.perp();
3038 weightb = pb.perp();
3043 weighta = pa.perp2();
3044 weightb = pb.perp2();
3048 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3050 throw Error(err.str());
3052 double perp_ab = pa.perp() + pb.perp();
3053 if (perp_ab != 0.0) {
3054 double y_ab = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
3055 double phi_a = pa.phi(), phi_b = pb.phi();
3056 if (phi_a - phi_b > pi) phi_b += twopi;
3057 if (phi_a - phi_b < -pi) phi_b -= twopi;
3058 double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
3059 pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
3061 pab.reset(0.0, 0.0, 0.0, 0.0);
3064 void JetDefinition::DefaultRecombiner::preprocess(
PseudoJet & p)
const {
3065 switch(_recomb_scheme) {
3073 double newE = sqrt(p.perp2()+p.pz()*p.pz());
3074 p.reset_momentum(p.px(), p.py(), p.pz(), newE);
3080 double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
3081 p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
3086 err <<
"DefaultRecombiner: unrecognized recombination scheme "
3088 throw Error(err.str());
3091 void JetDefinition::Plugin::set_ghost_separation_scale(
double )
const {
3092 throw Error(
"set_ghost_separation_scale not supported");
3096 if (pieces.size()>0){
3098 for (
unsigned int i=1; i<pieces.size(); i++)
3099 recombiner.plus_equal(result, pieces[i]);
3107 return join(vector<PseudoJet>(1,j1), recombiner);
3111 vector<PseudoJet> pieces;
3112 pieces.push_back(j1);
3113 pieces.push_back(j2);
3114 return join(pieces, recombiner);
3118 vector<PseudoJet> pieces;
3119 pieces.push_back(j1);
3120 pieces.push_back(j2);
3121 pieces.push_back(j3);
3122 return join(pieces, recombiner);
3126 vector<PseudoJet> pieces;
3127 pieces.push_back(j1);
3128 pieces.push_back(j2);
3129 pieces.push_back(j3);
3130 pieces.push_back(j4);
3131 return join(pieces, recombiner);
3133 FJCORE_END_NAMESPACE
3136 using namespace std;
3137 FJCORE_BEGIN_NAMESPACE
3138 ostream * LimitedWarning::_default_ostr = &cerr;
3139 std::list< LimitedWarning::Summary > LimitedWarning::_global_warnings_summary;
3140 int LimitedWarning::_max_warn_default = 5;
3141 void LimitedWarning::warn(
const std::string & warning) {
3142 warn(warning, _default_ostr);
3144 void LimitedWarning::warn(
const std::string & warning, std::ostream * ostr) {
3145 if (_this_warning_summary == 0) {
3146 _global_warnings_summary.push_back(Summary(warning, 0));
3147 _this_warning_summary = & (_global_warnings_summary.back());
3149 if (_n_warn_so_far < _max_warn) {
3150 ostringstream warnstr;
3151 warnstr <<
"WARNING: ";
3154 if (_n_warn_so_far == _max_warn) warnstr <<
" (LAST SUCH WARNING)";
3155 warnstr << std::endl;
3157 (*ostr) << warnstr.str();
3161 if (_this_warning_summary->second < numeric_limits<unsigned>::max()) {
3162 _this_warning_summary->second++;
3165 string LimitedWarning::summary() {
3167 for (list<Summary>::const_iterator it = _global_warnings_summary.begin();
3168 it != _global_warnings_summary.end(); it++) {
3169 str << it->second <<
" times: " << it->first << endl;
3173 FJCORE_END_NAMESPACE
3177 FJCORE_BEGIN_NAMESPACE
3178 using namespace std;
3179 void MinHeap::_initialise(
const std::vector<double> & values){
3180 for (
unsigned i = values.size(); i < _heap.size(); i++) {
3181 _heap[i].value = std::numeric_limits<double>::max();
3182 _heap[i].minloc = &(_heap[i]);
3184 for (
unsigned i = 0; i < values.size(); i++) {
3185 _heap[i].value = values[i];
3186 _heap[i].minloc = &(_heap[i]);
3188 for (
unsigned i = _heap.size()-1; i > 0; i--) {
3189 ValueLoc * parent = &(_heap[(i-1)/2]);
3190 ValueLoc * here = &(_heap[i]);
3191 if (here->minloc->value < parent->minloc->value) {
3192 parent->minloc = here->minloc;
3196 void MinHeap::update(
unsigned int loc,
double new_value) {
3197 assert(loc < _heap.size());
3198 ValueLoc * start = &(_heap[loc]);
3199 if (start->minloc != start && !(new_value < start->minloc->value)) {
3200 start->value = new_value;
3203 start->value = new_value;
3204 start->minloc = start;
3205 bool change_made =
true;
3206 ValueLoc * heap_end = (&(_heap[0])) + _heap.size();
3207 while(change_made) {
3208 ValueLoc * here = &(_heap[loc]);
3209 change_made =
false;
3210 if (here->minloc == start) {
3211 here->minloc = here; change_made =
true;
3213 ValueLoc * child = &(_heap[2*loc+1]);
3214 if (child < heap_end && child->minloc->value < here->minloc->value ) {
3215 here->minloc = child->minloc;
3216 change_made =
true;}
3218 if (child < heap_end && child->minloc->value < here->minloc->value ) {
3219 here->minloc = child->minloc;
3220 change_made =
true;}
3221 if (loc == 0) {
break;}
3225 FJCORE_END_NAMESPACE
3232 FJCORE_BEGIN_NAMESPACE
3233 using namespace std;
3234 PseudoJet::PseudoJet(
const double px_in,
const double py_in,
const double pz_in,
const double E_in) {
3239 this->_finish_init();
3242 void PseudoJet::_finish_init () {
3243 _kt2 = this->px()*this->px() + this->py()*this->py();
3244 _phi = pseudojet_invalid_phi;
3245 _rap = pseudojet_invalid_rap;
3247 void PseudoJet::_set_rap_phi()
const {
3251 _phi = atan2(this->py(),this->px());
3253 if (_phi < 0.0) {_phi += twopi;}
3254 if (_phi >= twopi) {_phi -= twopi;}
3255 if (this->E() == abs(this->pz()) && _kt2 == 0) {
3256 double MaxRapHere = MaxRap + abs(this->pz());
3257 if (this->pz() >= 0.0) {_rap = MaxRapHere;}
else {_rap = -MaxRapHere;}
3259 double effective_m2 = max(0.0,m2());
3260 double E_plus_pz = _E + abs(_pz);
3261 _rap = 0.5*log((_kt2 + effective_m2)/(E_plus_pz*E_plus_pz));
3262 if (_pz > 0) {_rap = - _rap;}
3265 valarray<double> PseudoJet::four_mom()
const {
3266 valarray<double> mom(4);
3273 double PseudoJet::operator () (
int i)
const {
3285 err <<
"PseudoJet subscripting: bad index (" << i <<
")";
3286 throw Error(err.str());
3290 double PseudoJet::pseudorapidity()
const {
3291 if (px() == 0.0 && py() ==0.0)
return MaxRap;
3292 if (pz() == 0.0)
return 0.0;
3293 double theta = atan(perp()/pz());
3294 if (theta < 0) theta += pi;
3295 return -log(tan(theta/2));
3299 jet1.py()+jet2.py(),
3300 jet1.pz()+jet2.pz(),
3301 jet1.E() +jet2.E() );
3305 jet1.py()-jet2.py(),
3306 jet1.pz()-jet2.pz(),
3307 jet1.E() -jet2.E() );
3311 coeff_times_jet *= coeff;
3312 return coeff_times_jet;
3318 return (1.0/coeff)*jet;
3320 void PseudoJet::operator*=(
double coeff) {
3327 void PseudoJet::operator/=(
double coeff) {
3328 (*this) *= 1.0/coeff;
3330 void PseudoJet::operator+=(
const PseudoJet & other_jet) {
3331 _px += other_jet._px;
3332 _py += other_jet._py;
3333 _pz += other_jet._pz;
3334 _E += other_jet._E ;
3337 void PseudoJet::operator-=(
const PseudoJet & other_jet) {
3338 _px -= other_jet._px;
3339 _py -= other_jet._py;
3340 _pz -= other_jet._pz;
3341 _E -= other_jet._E ;
3345 if (a.px() != b.px())
return false;
3346 if (a.py() != b.py())
return false;
3347 if (a.pz() != b.pz())
return false;
3348 if (a.E () != b.E ())
return false;
3349 if (a.user_index() != b.user_index())
return false;
3350 if (a.cluster_hist_index() != b.cluster_hist_index())
return false;
3351 if (a.user_info_ptr() != b.user_info_ptr())
return false;
3352 if (a.structure_ptr() != b.structure_ptr())
return false;
3355 bool operator==(
const PseudoJet & jet,
const double val) {
3357 throw Error(
"comparing a PseudoJet with a non-zero constant (double) is not allowed.");
3358 return (jet.px() == 0 && jet.py() == 0 &&
3359 jet.pz() == 0 && jet.E() == 0);
3362 if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3364 double m_local = prest.m();
3365 assert(m_local != 0);
3366 double pf4 = ( px()*prest.px() + py()*prest.py()
3367 + pz()*prest.pz() + E()*prest.E() )/m_local;
3368 double fn = (pf4 + E()) / (prest.E() + m_local);
3369 _px += fn*prest.px();
3370 _py += fn*prest.py();
3371 _pz += fn*prest.pz();
3377 if (prest.px() == 0.0 && prest.py() == 0.0 && prest.pz() == 0.0)
3379 double m_local = prest.m();
3380 assert(m_local != 0);
3381 double pf4 = ( -px()*prest.px() - py()*prest.py()
3382 - pz()*prest.pz() + E()*prest.E() )/m_local;
3383 double fn = (pf4 + E()) / (prest.E() + m_local);
3384 _px -= fn*prest.px();
3385 _py -= fn*prest.py();
3386 _pz -= fn*prest.pz();
3392 return jeta.px() == jetb.px()
3393 && jeta.py() == jetb.py()
3394 && jeta.pz() == jetb.pz()
3395 && jeta.E() == jetb.E();
3397 void PseudoJet::set_cached_rap_phi(
double rap_in,
double phi_in) {
3398 _rap = rap_in; _phi = phi_in;
3399 if (_phi >= twopi) _phi -= twopi;
3400 if (_phi < 0) _phi += twopi;
3402 void PseudoJet::reset_momentum_PtYPhiM(
double pt_in,
double y_in,
double phi_in,
double m_in) {
3403 assert(phi_in < 2*twopi && phi_in > -twopi);
3404 double ptm = (m_in == 0) ? pt_in : sqrt(pt_in*pt_in+m_in*m_in);
3405 double exprap = exp(y_in);
3406 double pminus = ptm/exprap;
3407 double pplus = ptm*exprap;
3408 double px_local = pt_in*cos(phi_in);
3409 double py_local = pt_in*sin(phi_in);
3410 reset_momentum(px_local,py_local,0.5*(pplus-pminus),0.5*(pplus+pminus));
3411 set_cached_rap_phi(y_in,phi_in);
3413 PseudoJet PtYPhiM(
double pt,
double y,
double phi,
double m) {
3414 assert(phi < 2*twopi && phi > -twopi);
3415 double ptm = (m == 0) ? pt : sqrt(pt*pt+m*m);
3416 double exprap = exp(y);
3417 double pminus = ptm/exprap;
3418 double pplus = ptm*exprap;
3419 double px = pt*cos(phi);
3420 double py = pt*sin(phi);
3421 PseudoJet mom(px,py,0.5*(pplus-pminus),0.5*(pplus+pminus));
3422 mom.set_cached_rap_phi(y,phi);
3425 double PseudoJet::kt_distance(
const PseudoJet & other)
const {
3426 double distance = min(_kt2, other._kt2);
3427 double dphi = abs(phi() - other.phi());
3428 if (dphi > pi) {dphi = twopi - dphi;}
3429 double drap = rap() - other.rap();
3430 distance = distance * (dphi*dphi + drap*drap);
3433 double PseudoJet::plain_distance(
const PseudoJet & other)
const {
3434 double dphi = abs(phi() - other.phi());
3435 if (dphi > pi) {dphi = twopi - dphi;}
3436 double drap = rap() - other.rap();
3437 return (dphi*dphi + drap*drap);
3439 double PseudoJet::delta_phi_to(
const PseudoJet & other)
const {
3440 double dphi = other.phi() - phi();
3441 if (dphi > pi) dphi -= twopi;
3442 if (dphi < -pi) dphi += twopi;
3445 string PseudoJet::description()
const{
3447 return "standard PseudoJet (with no associated clustering information)";
3448 return _structure()->description();
3450 bool PseudoJet::has_associated_cluster_sequence()
const{
3451 return (_structure()) && (_structure->has_associated_cluster_sequence());
3453 const ClusterSequence* PseudoJet::associated_cluster_sequence()
const{
3454 if (! has_associated_cluster_sequence())
return NULL;
3455 return _structure->associated_cluster_sequence();
3457 bool PseudoJet::has_valid_cluster_sequence()
const{
3458 return (_structure()) && (_structure->has_valid_cluster_sequence());
3461 return validated_structure_ptr()->validated_cs();
3464 _structure = structure_in;
3466 bool PseudoJet::has_structure()
const{
3467 return _structure();
3470 if (!_structure())
return NULL;
3471 return _structure();
3474 if (!_structure())
return NULL;
3475 return _structure();
3479 throw Error(
"Trying to access the structure of a PseudoJet which has no associated structure");
3480 return _structure();
3485 bool PseudoJet::has_partner(
PseudoJet &partner)
const{
3486 return validated_structure_ptr()->has_partner(*
this, partner);
3488 bool PseudoJet::has_child(
PseudoJet &child)
const{
3489 return validated_structure_ptr()->has_child(*
this, child);
3492 return validated_structure_ptr()->has_parents(*
this, parent1, parent2);
3494 bool PseudoJet::contains(
const PseudoJet &constituent)
const{
3495 return validated_structure_ptr()->object_in_jet(constituent, *
this);
3497 bool PseudoJet::is_inside(
const PseudoJet &jet)
const{
3498 return validated_structure_ptr()->object_in_jet(*
this, jet);
3500 bool PseudoJet::has_constituents()
const{
3501 return (_structure()) && (_structure->has_constituents());
3503 vector<PseudoJet> PseudoJet::constituents()
const{
3504 return validated_structure_ptr()->constituents(*
this);
3506 bool PseudoJet::has_exclusive_subjets()
const{
3507 return (_structure()) && (_structure->has_exclusive_subjets());
3509 std::vector<PseudoJet> PseudoJet::exclusive_subjets (
const double & dcut)
const {
3510 return validated_structure_ptr()->exclusive_subjets(*
this, dcut);
3512 int PseudoJet::n_exclusive_subjets(
const double & dcut)
const {
3513 return validated_structure_ptr()->n_exclusive_subjets(*
this, dcut);
3515 std::vector<PseudoJet> PseudoJet::exclusive_subjets_up_to (
int nsub)
const {
3516 return validated_structure_ptr()->exclusive_subjets_up_to(*
this, nsub);
3518 std::vector<PseudoJet> PseudoJet::exclusive_subjets (
int nsub)
const {
3519 vector<PseudoJet> subjets = exclusive_subjets_up_to(nsub);
3520 if (
int(subjets.size()) < nsub) {
3522 err <<
"Requested " << nsub <<
" exclusive subjets, but there were only "
3523 << subjets.size() <<
" particles in the jet";
3524 throw Error(err.str());
3528 double PseudoJet::exclusive_subdmerge(
int nsub)
const {
3529 return validated_structure_ptr()->exclusive_subdmerge(*
this, nsub);
3531 double PseudoJet::exclusive_subdmerge_max(
int nsub)
const {
3532 return validated_structure_ptr()->exclusive_subdmerge_max(*
this, nsub);
3534 bool PseudoJet::has_pieces()
const{
3535 return ((_structure()) && (_structure->has_pieces(*
this)));
3537 std::vector<PseudoJet> PseudoJet::pieces()
const{
3538 return validated_structure_ptr()->pieces(*
this);
3540 PseudoJet::InexistentUserInfo::InexistentUserInfo() :
Error(
"you attempted to perform a dynamic cast of a PseudoJet's extra info, but the extra info pointer was null")
3542 void sort_indices(vector<int> & indices,
3543 const vector<double> & values) {
3545 sort(indices.begin(), indices.end(), index_sort_helper);
3547 template<
class T> vector<T> objects_sorted_by_values(
3548 const vector<T> & objects,
3549 const vector<double> & values) {
3550 assert(objects.size() == values.size());
3551 vector<int> indices(values.size());
3552 for (
size_t i = 0; i < indices.size(); i++) {indices[i] = i;}
3553 sort_indices(indices, values);
3554 vector<T> objects_sorted(objects.size());
3555 for (
size_t i = 0; i < indices.size(); i++) {
3556 objects_sorted[i] = objects[indices[i]];
3558 return objects_sorted;
3560 vector<PseudoJet> sorted_by_pt(
const vector<PseudoJet> & jets) {
3561 vector<double> minus_kt2(jets.size());
3562 for (
size_t i = 0; i < jets.size(); i++) {minus_kt2[i] = -jets[i].kt2();}
3563 return objects_sorted_by_values(jets, minus_kt2);
3565 vector<PseudoJet> sorted_by_rapidity(
const vector<PseudoJet> & jets) {
3566 vector<double> rapidities(jets.size());
3567 for (
size_t i = 0; i < jets.size(); i++) {rapidities[i] = jets[i].rap();}
3568 return objects_sorted_by_values(jets, rapidities);
3570 vector<PseudoJet> sorted_by_E(
const vector<PseudoJet> & jets) {
3571 vector<double> energies(jets.size());
3572 for (
size_t i = 0; i < jets.size(); i++) {energies[i] = -jets[i].E();}
3573 return objects_sorted_by_values(jets, energies);
3575 vector<PseudoJet> sorted_by_pz(
const vector<PseudoJet> & jets) {
3576 vector<double> pz(jets.size());
3577 for (
size_t i = 0; i < jets.size(); i++) {pz[i] = jets[i].pz();}
3578 return objects_sorted_by_values(jets, pz);
3580 PseudoJet join(
const vector<PseudoJet> & pieces){
3582 for (
unsigned int i=0; i<pieces.size(); i++)
3583 result += pieces[i];
3589 return join(vector<PseudoJet>(1,j1));
3592 vector<PseudoJet> pieces;
3593 pieces.push_back(j1);
3594 pieces.push_back(j2);
3595 return join(pieces);
3598 vector<PseudoJet> pieces;
3599 pieces.push_back(j1);
3600 pieces.push_back(j2);
3601 pieces.push_back(j3);
3602 return join(pieces);
3605 vector<PseudoJet> pieces;
3606 pieces.push_back(j1);
3607 pieces.push_back(j2);
3608 pieces.push_back(j3);
3609 pieces.push_back(j4);
3610 return join(pieces);
3612 FJCORE_END_NAMESPACE
3613 using namespace std;
3614 FJCORE_BEGIN_NAMESPACE
3615 const ClusterSequence* PseudoJetStructureBase::associated_cluster_sequence()
const{
3619 throw Error(
"This PseudoJet structure is not associated with a valid ClusterSequence");
3622 throw Error(
"This PseudoJet structure has no implementation for has_partner");
3625 throw Error(
"This PseudoJet structure has no implementation for has_child");
3628 throw Error(
"This PseudoJet structure has no implementation for has_parents");
3630 bool PseudoJetStructureBase::object_in_jet(
const PseudoJet & ,
const PseudoJet & )
const{
3631 throw Error(
"This PseudoJet structure has no implementation for is_inside");
3633 vector<PseudoJet> PseudoJetStructureBase::constituents(
const PseudoJet &)
const{
3634 throw Error(
"This PseudoJet structure has no implementation for constituents");
3636 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets (
const PseudoJet & ,
const double & )
const{
3637 throw Error(
"This PseudoJet structure has no implementation for exclusive_subjets");
3639 int PseudoJetStructureBase::n_exclusive_subjets(
const PseudoJet & ,
const double & )
const{
3640 throw Error(
"This PseudoJet structure has no implementation for n_exclusive_subjets");
3642 vector<PseudoJet> PseudoJetStructureBase::exclusive_subjets_up_to (
const PseudoJet & ,
int )
const{
3643 throw Error(
"This PseudoJet structure has no implementation for exclusive_subjets");
3645 double PseudoJetStructureBase::exclusive_subdmerge(
const PseudoJet & ,
int )
const{
3646 throw Error(
"This PseudoJet structure has no implementation for exclusive_submerge");
3648 double PseudoJetStructureBase::exclusive_subdmerge_max(
const PseudoJet & ,
int )
const{
3649 throw Error(
"This PseudoJet structure has no implementation for exclusive_submerge_max");
3651 std::vector<PseudoJet> PseudoJetStructureBase::pieces(
const PseudoJet & )
const{
3652 throw Error(
"This PseudoJet structure has no implementation for pieces");
3654 FJCORE_END_NAMESPACE
3656 #include <algorithm>
3657 using namespace std;
3658 FJCORE_BEGIN_NAMESPACE
3659 std::vector<PseudoJet> Selector::operator()(
const std::vector<PseudoJet> & jets)
const {
3660 std::vector<PseudoJet> result;
3662 if (worker_local->applies_jet_by_jet()) {
3663 for (std::vector<PseudoJet>::const_iterator jet = jets.begin();
3664 jet != jets.end(); jet++) {
3665 if (worker_local->pass(*jet)) result.push_back(*jet);
3668 std::vector<const PseudoJet *> jetptrs(jets.size());
3669 for (
unsigned i = 0; i < jets.size(); i++) {
3670 jetptrs[i] = & jets[i];
3672 worker_local->terminator(jetptrs);
3673 for (
unsigned i = 0; i < jetptrs.size(); i++) {
3674 if (jetptrs[i]) result.push_back(jets[i]);
3679 unsigned int Selector::count(
const std::vector<PseudoJet> & jets)
const {
3682 if (worker_local->applies_jet_by_jet()) {
3683 for (
unsigned i = 0; i < jets.size(); i++) {
3684 if (worker_local->pass(jets[i])) n++;
3687 std::vector<const PseudoJet *> jetptrs(jets.size());
3688 for (
unsigned i = 0; i < jets.size(); i++) {
3689 jetptrs[i] = & jets[i];
3691 worker_local->terminator(jetptrs);
3692 for (
unsigned i = 0; i < jetptrs.size(); i++) {
3693 if (jetptrs[i]) n++;
3698 void Selector::sift(
const std::vector<PseudoJet> & jets,
3699 std::vector<PseudoJet> & jets_that_pass,
3700 std::vector<PseudoJet> & jets_that_fail
3703 jets_that_pass.clear();
3704 jets_that_fail.clear();
3705 if (worker_local->applies_jet_by_jet()) {
3706 for (
unsigned i = 0; i < jets.size(); i++) {
3707 if (worker_local->pass(jets[i])) {
3708 jets_that_pass.push_back(jets[i]);
3710 jets_that_fail.push_back(jets[i]);
3714 std::vector<const PseudoJet *> jetptrs(jets.size());
3715 for (
unsigned i = 0; i < jets.size(); i++) {
3716 jetptrs[i] = & jets[i];
3718 worker_local->terminator(jetptrs);
3719 for (
unsigned i = 0; i < jetptrs.size(); i++) {
3721 jets_that_pass.push_back(jets[i]);
3723 jets_that_fail.push_back(jets[i]);
3728 bool SelectorWorker::has_finite_area()
const {
3729 if (! is_geometric())
return false;
3730 double rapmin, rapmax;
3731 get_rapidity_extent(rapmin, rapmax);
3732 return (rapmax != std::numeric_limits<double>::infinity())
3733 && (-rapmin != std::numeric_limits<double>::infinity());
3738 virtual bool pass(
const PseudoJet &)
const {
3741 virtual void terminator(vector<const PseudoJet *> &)
const {
3744 virtual string description()
const {
return "Identity";}
3745 virtual bool is_geometric()
const {
return true;}
3754 virtual bool pass(
const PseudoJet & jet)
const {
3755 if (!applies_jet_by_jet())
3756 throw Error(
"Cannot apply this selector worker to an individual jet");
3757 return ! _s.pass(jet);
3759 virtual bool applies_jet_by_jet()
const {
return _s.applies_jet_by_jet();}
3760 virtual void terminator(vector<const PseudoJet *> & jets)
const {
3761 if (applies_jet_by_jet()){
3762 SelectorWorker::terminator(jets);
3765 vector<const PseudoJet *> s_jets = jets;
3766 _s.worker()->terminator(s_jets);
3767 for (
unsigned int i=0; i<s_jets.size(); i++){
3768 if (s_jets[i]) jets[i] = NULL;
3771 virtual string description()
const {
3773 ostr <<
"!(" << _s.description() <<
")";
3776 virtual bool is_geometric()
const {
return _s.is_geometric();}
3777 virtual bool takes_reference()
const {
return _s.takes_reference();}
3778 virtual void set_reference(
const PseudoJet &ref) { _s.set_reference(ref);}
3788 _applies_jet_by_jet = _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
3789 _takes_reference = _s1.takes_reference() || _s2.takes_reference();
3790 _is_geometric = _s1.is_geometric() && _s2.is_geometric();
3792 virtual bool applies_jet_by_jet()
const {
return _applies_jet_by_jet;}
3793 virtual bool takes_reference()
const{
3794 return _takes_reference;
3796 virtual void set_reference(
const PseudoJet ¢re){
3797 _s1.set_reference(centre);
3798 _s2.set_reference(centre);
3800 virtual bool is_geometric()
const {
return _is_geometric;}
3803 bool _applies_jet_by_jet;
3804 bool _takes_reference;
3811 virtual bool pass(
const PseudoJet & jet)
const {
3812 if (!applies_jet_by_jet())
3813 throw Error(
"Cannot apply this selector worker to an individual jet");
3814 return _s1.pass(jet) && _s2.pass(jet);
3816 virtual void terminator(vector<const PseudoJet *> & jets)
const {
3817 if (applies_jet_by_jet()){
3818 SelectorWorker::terminator(jets);
3821 vector<const PseudoJet *> s1_jets = jets;
3822 _s1.worker()->terminator(s1_jets);
3823 _s2.worker()->terminator(jets);
3824 for (
unsigned int i=0; i<jets.size(); i++){
3825 if (! s1_jets[i]) jets[i] = NULL;
3828 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const {
3829 double s1min, s1max, s2min, s2max;
3830 _s1.get_rapidity_extent(s1min, s1max);
3831 _s2.get_rapidity_extent(s2min, s2max);
3832 rapmax = min(s1max, s2max);
3833 rapmin = max(s1min, s2min);
3835 virtual string description()
const {
3837 ostr <<
"(" << _s1.description() <<
" && " << _s2.description() <<
")";
3848 virtual bool pass(
const PseudoJet & jet)
const {
3849 if (!applies_jet_by_jet())
3850 throw Error(
"Cannot apply this selector worker to an individual jet");
3851 return _s1.pass(jet) || _s2.pass(jet);
3853 virtual bool applies_jet_by_jet()
const {
3854 return _s1.applies_jet_by_jet() && _s2.applies_jet_by_jet();
3856 virtual void terminator(vector<const PseudoJet *> & jets)
const {
3857 if (applies_jet_by_jet()){
3858 SelectorWorker::terminator(jets);
3861 vector<const PseudoJet *> s1_jets = jets;
3862 _s1.worker()->terminator(s1_jets);
3863 _s2.worker()->terminator(jets);
3864 for (
unsigned int i=0; i<jets.size(); i++){
3865 if (s1_jets[i]) jets[i] = s1_jets[i];
3868 virtual string description()
const {
3870 ostr <<
"(" << _s1.description() <<
" || " << _s2.description() <<
")";
3873 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const {
3874 double s1min, s1max, s2min, s2max;
3875 _s1.get_rapidity_extent(s1min, s1max);
3876 _s2.get_rapidity_extent(s2min, s2max);
3877 rapmax = max(s1max, s2max);
3878 rapmin = min(s1min, s2min);
3888 virtual void terminator(vector<const PseudoJet *> & jets)
const {
3889 if (applies_jet_by_jet()){
3890 SelectorWorker::terminator(jets);
3893 _s2.worker()->terminator(jets);
3894 _s1.worker()->terminator(jets);
3896 virtual string description()
const {
3898 ostr <<
"(" << _s1.description() <<
" * " << _s2.description() <<
")";
3909 virtual double operator()(
const PseudoJet & jet )
const =0;
3910 virtual string description()
const =0;
3911 virtual bool is_geometric()
const {
return false;}
3912 virtual double comparison_value()
const {
return _q;}
3913 virtual double description_value()
const {
return comparison_value();}
3920 virtual double description_value()
const {
return _sqrtq;}
3924 template<
typename QuantityType>
3928 virtual bool pass(
const PseudoJet & jet)
const {
return _qmin(jet) >= _qmin.comparison_value();}
3929 virtual string description()
const {
3931 ostr << _qmin.description() <<
" >= " << _qmin.description_value();
3934 virtual bool is_geometric()
const {
return _qmin.is_geometric();}
3938 template<
typename QuantityType>
3942 virtual bool pass(
const PseudoJet & jet)
const {
return _qmax(jet) <= _qmax.comparison_value();}
3943 virtual string description()
const {
3945 ostr << _qmax.description() <<
" <= " << _qmax.description_value();
3948 virtual bool is_geometric()
const {
return _qmax.is_geometric();}
3952 template<
typename QuantityType>
3956 virtual bool pass(
const PseudoJet & jet)
const {
3957 double q = _qmin(jet);
3958 return (q >= _qmin.comparison_value()) && (q <= _qmax.comparison_value());
3960 virtual string description()
const {
3962 ostr << _qmin.description_value() <<
" <= " << _qmin.description() <<
" <= " << _qmax.description_value();
3965 virtual bool is_geometric()
const {
return _qmin.is_geometric();}
3973 virtual double operator()(
const PseudoJet & jet )
const {
return jet.perp2();}
3974 virtual string description()
const {
return "pt";}
3976 Selector SelectorPtMin(
double ptmin) {
3979 Selector SelectorPtMax(
double ptmax) {
3982 Selector SelectorPtRange(
double ptmin,
double ptmax) {
3988 virtual double operator()(
const PseudoJet & jet )
const {
return jet.Et2();}
3989 virtual string description()
const {
return "Et";}
3991 Selector SelectorEtMin(
double Etmin) {
3994 Selector SelectorEtMax(
double Etmax) {
3997 Selector SelectorEtRange(
double Etmin,
double Etmax) {
4003 virtual double operator()(
const PseudoJet & jet )
const {
return jet.E();}
4004 virtual string description()
const {
return "E";}
4006 Selector SelectorEMin(
double Emin) {
4009 Selector SelectorEMax(
double Emax) {
4012 Selector SelectorERange(
double Emin,
double Emax) {
4018 virtual double operator()(
const PseudoJet & jet )
const {
return jet.m2();}
4019 virtual string description()
const {
return "mass";}
4021 Selector SelectorMassMin(
double mmin) {
4024 Selector SelectorMassMax(
double mmax) {
4027 Selector SelectorMassRange(
double mmin,
double mmax) {
4033 virtual double operator()(
const PseudoJet & jet )
const {
return jet.rap();}
4034 virtual string description()
const {
return "rap";}
4035 virtual bool is_geometric()
const {
return true;}
4040 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4041 rapmax = std::numeric_limits<double>::max();
4042 rapmin = _qmin.comparison_value();
4048 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4049 rapmax = _qmax.comparison_value();
4050 rapmin = -std::numeric_limits<double>::max();
4056 assert(rapmin<=rapmax);
4058 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4059 rapmax = _qmax.comparison_value();
4060 rapmin = _qmin.comparison_value();
4063 virtual double known_area()
const {
4064 return twopi * (_qmax.comparison_value()-_qmin.comparison_value());
4067 Selector SelectorRapMin(
double rapmin) {
4070 Selector SelectorRapMax(
double rapmax) {
4073 Selector SelectorRapRange(
double rapmin,
double rapmax) {
4079 virtual double operator()(
const PseudoJet & jet )
const {
return abs(jet.rap());}
4080 virtual string description()
const {
return "|rap|";}
4081 virtual bool is_geometric()
const {
return true;}
4086 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4087 rapmax = _qmax.comparison_value();
4088 rapmin = -_qmax.comparison_value();
4091 virtual double known_area()
const {
4092 return twopi * 2 * _qmax.comparison_value();
4098 virtual void get_rapidity_extent(
double &rapmin,
double & rapmax)
const{
4099 rapmax = _qmax.comparison_value();
4100 rapmin = -_qmax.comparison_value();
4103 virtual double known_area()
const {
4104 return twopi * 2 * (_qmax.comparison_value()-max(_qmin.comparison_value(),0.0));
4107 Selector SelectorAbsRapMin(
double absrapmin) {
4110 Selector SelectorAbsRapMax(
double absrapmax) {
4113 Selector SelectorAbsRapRange(
double rapmin,
double rapmax) {
4119 virtual double operator()(
const PseudoJet & jet )
const {
return jet.eta();}
4120 virtual string description()
const {
return "eta";}
4122 Selector SelectorEtaMin(
double etamin) {
4125 Selector SelectorEtaMax(
double etamax) {
4128 Selector SelectorEtaRange(
double etamin,
double etamax) {
4134 virtual double operator()(
const PseudoJet & jet )
const {
return abs(jet.eta());}
4135 virtual string description()
const {
return "|eta|";}
4136 virtual bool is_geometric()
const {
return true;}
4138 Selector SelectorAbsEtaMin(
double absetamin) {
4141 Selector SelectorAbsEtaMax(
double absetamax) {
4144 Selector SelectorAbsEtaRange(
double absetamin,
double absetamax) {
4149 SW_PhiRange(
double phimin,
double phimax) : _phimin(phimin), _phimax(phimax){
4150 assert(_phimin<_phimax);
4151 assert(_phimin>-twopi);
4152 assert(_phimax<2*twopi);
4153 _phispan = _phimax - _phimin;
4155 virtual bool pass(
const PseudoJet & jet)
const {
4156 double dphi=jet.phi()-_phimin;
4157 if (dphi >= twopi) dphi -= twopi;
4158 if (dphi < 0) dphi += twopi;
4159 return (dphi <= _phispan);
4161 virtual string description()
const {
4163 ostr << _phimin <<
" <= phi <= " << _phimax;
4166 virtual bool is_geometric()
const {
return true;}
4172 Selector SelectorPhiRange(
double phimin,
double phimax) {
4177 SW_RapPhiRange(
double rapmin,
double rapmax,
double phimin,
double phimax)
4178 :
SW_And(SelectorRapRange(rapmin, rapmax), SelectorPhiRange(phimin, phimax)){
4179 _known_area = ((phimax-phimin > twopi) ? twopi : phimax-phimin) * (rapmax-rapmin);
4181 virtual double known_area()
const{
4187 Selector SelectorRapPhiRange(
double rapmin,
double rapmax,
double phimin,
double phimax) {
4193 virtual bool pass(
const PseudoJet &)
const {
4194 if (!applies_jet_by_jet())
4195 throw Error(
"Cannot apply this selector worker to an individual jet");
4198 virtual void terminator(vector<const PseudoJet *> & jets)
const {
4199 if (jets.size() < _n)
return;
4200 vector<double> minus_pt2(jets.size());
4201 vector<unsigned int> indices(jets.size());
4202 for (
unsigned int i=0; i<jets.size(); i++){
4204 minus_pt2[i] = jets[i] ? -jets[i]->perp2() : 0.0;
4207 partial_sort(indices.begin(), indices.begin()+_n, indices.end(), sort_helper);
4208 for (
unsigned int i=_n; i<jets.size(); i++)
4209 jets[indices[i]] = NULL;
4211 virtual bool applies_jet_by_jet()
const {
return false;}
4212 virtual string description()
const {
4214 ostr << _n <<
" hardest";
4220 Selector SelectorNHardest(
unsigned int n) {
4226 virtual bool takes_reference()
const {
return true;}
4227 virtual void set_reference(
const PseudoJet ¢re){
4228 _is_initialised =
true;
4229 _reference = centre;
4233 bool _is_initialised;
4237 SW_Circle(
const double &radius) : _radius2(radius*radius) {}
4239 virtual bool pass(
const PseudoJet & jet)
const {
4240 if (! _is_initialised)
4241 throw Error(
"To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4242 return jet.squared_distance(_reference) <= _radius2;
4244 virtual string description()
const {
4246 ostr <<
"distance from the centre <= " << sqrt(_radius2);
4249 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4250 if (! _is_initialised)
4251 throw Error(
"To use a SelectorCircle (or any selector that requires a reference), you first have to call set_reference(...)");
4252 rapmax = _reference.rap()+sqrt(_radius2);
4253 rapmin = _reference.rap()-sqrt(_radius2);
4258 virtual double known_area()
const {
4259 return pi * _radius2;
4264 Selector SelectorCircle(
const double & radius) {
4269 SW_Doughnut(
const double &radius_in,
const double &radius_out)
4270 : _radius_in2(radius_in*radius_in), _radius_out2(radius_out*radius_out) {}
4272 virtual bool pass(
const PseudoJet & jet)
const {
4273 if (! _is_initialised)
4274 throw Error(
"To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4275 double distance2 = jet.squared_distance(_reference);
4276 return (distance2 <= _radius_out2) && (distance2 >= _radius_in2);
4278 virtual string description()
const {
4280 ostr << sqrt(_radius_in2) <<
" <= distance from the centre <= " << sqrt(_radius_out2);
4283 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4284 if (! _is_initialised)
4285 throw Error(
"To use a SelectorDoughnut (or any selector that requires a reference), you first have to call set_reference(...)");
4286 rapmax = _reference.rap()+sqrt(_radius_out2);
4287 rapmin = _reference.rap()-sqrt(_radius_out2);
4292 virtual double known_area()
const {
4293 return pi * (_radius_out2-_radius_in2);
4296 double _radius_in2, _radius_out2;
4298 Selector SelectorDoughnut(
const double & radius_in,
const double & radius_out) {
4303 SW_Strip(
const double &delta) : _delta(delta) {}
4305 virtual bool pass(
const PseudoJet & jet)
const {
4306 if (! _is_initialised)
4307 throw Error(
"To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4308 return abs(jet.rap()-_reference.rap()) <= _delta;
4310 virtual string description()
const {
4312 ostr <<
"|rap - rap_reference| <= " << _delta;
4315 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4316 if (! _is_initialised)
4317 throw Error(
"To use a SelectorStrip (or any selector that requires a reference), you first have to call set_reference(...)");
4318 rapmax = _reference.rap()+_delta;
4319 rapmin = _reference.rap()-_delta;
4324 virtual double known_area()
const {
4325 return twopi * 2 * _delta;
4330 Selector SelectorStrip(
const double & half_width) {
4335 SW_Rectangle(
const double &delta_rap,
const double &delta_phi)
4336 : _delta_rap(delta_rap), _delta_phi(delta_phi) {}
4338 virtual bool pass(
const PseudoJet & jet)
const {
4339 if (! _is_initialised)
4340 throw Error(
"To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4341 return (abs(jet.rap()-_reference.rap()) <= _delta_rap) && (abs(jet.delta_phi_to(_reference)) <= _delta_phi);
4343 virtual string description()
const {
4345 ostr <<
"|rap - rap_reference| <= " << _delta_rap <<
" && |phi - phi_reference| <= " << _delta_phi ;
4348 virtual void get_rapidity_extent(
double & rapmin,
double & rapmax)
const{
4349 if (! _is_initialised)
4350 throw Error(
"To use a SelectorRectangle (or any selector that requires a reference), you first have to call set_reference(...)");
4351 rapmax = _reference.rap()+_delta_rap;
4352 rapmin = _reference.rap()-_delta_rap;
4357 virtual double known_area()
const {
4358 return 4 * _delta_rap * _delta_phi;
4361 double _delta_rap, _delta_phi;
4363 Selector SelectorRectangle(
const double & half_rap_width,
const double & half_phi_width) {
4370 virtual bool pass(
const PseudoJet & jet)
const {
4371 if (! _is_initialised)
4372 throw Error(
"To use a SelectorPtFractionMin (or any selector that requires a reference), you first have to call set_reference(...)");
4373 return (jet.perp2() >= _fraction2*_reference.perp2());
4375 virtual string description()
const {
4377 ostr <<
"pt >= " << sqrt(_fraction2) <<
"* pt_ref";
4383 Selector SelectorPtFractionMin(
double fraction){
4389 virtual bool pass(
const PseudoJet & jet)
const {
4392 virtual string description()
const {
return "zero";}
4398 _worker.reset(
new SW_And(*
this, b));
4402 _worker.reset(
new SW_Or(*
this, b));
4405 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
QuantityType _qmax
the cut
virtual bool is_geometric() const
implies a finite area
QuantityType _qmin
the cut
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
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