Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

fastjet::ClusterSequence Class Reference

deals with clustering More...

#include <ClusterSequence.hh>

Inheritance diagram for fastjet::ClusterSequence:

Inheritance graph
[legend]
Collaboration diagram for fastjet::ClusterSequence:

Collaboration graph
[legend]
List of all members.

Public Types

enum  JetType { Invalid = -3, InexistentParent = -2, BeamJet = -1 }

Public Member Functions

 ClusterSequence ()
 default constructor
template<class L>
 ClusterSequence (const std::vector< L > &pseudojets, const double &R=1.0, const Strategy &strategy=Best, const bool &writeout_combinations=false)
 create a clustersequence starting from the supplied set of pseudojets and clustering them with the long-invariant kt algorithm (E-scheme recombination) with the supplied value for R.
template<class L>
 ClusterSequence (const std::vector< L > &pseudojets, const JetDefinition &jet_def, const bool &writeout_combinations=false)
 constructor of a jet-clustering sequence from a vector of four-momenta, with the jet definition specified by jet_def
std::vector< PseudoJetinclusive_jets (const double &ptmin=0.0) const
 return a vector of all jets (in the sense of the inclusive algorithm) with pt >= ptmin.
int n_exclusive_jets (const double &dcut) const
 return the number of jets (in the sense of the exclusive algorithm) that would be obtained when running the algorithm with the given dcut.
std::vector< PseudoJetexclusive_jets (const double &dcut) const
 return a vector of all jets (in the sense of the exclusive algorithm) that would be obtained when running the algorithm with the given dcut.
std::vector< PseudoJetexclusive_jets (const int &njets) const
 return a vector of all jets when the event is clustered (in the exclusive sense) to exactly njets.
double exclusive_dmerge (const int &njets) const
 return the dmin corresponding to the recombination that went from n+1 to n jets
double exclusive_dmerge_max (const int &njets) const
 return the maximum of the dmin encountered during all recombinations up to the one that led to an n-jet final state; identical to exclusive_dmerge, except in cases where the dmin do not increase monotonically.
std::vector< PseudoJetconstituents (const PseudoJet &jet) const
 return a vector of the particles that make up jet
void add_constituents (const PseudoJet &jet, std::vector< PseudoJet > &subjet_vector) const
 add on to subjet_vector the subjets of jet.
Strategy strategy_used () const
 return the enum value of the strategy used to cluster the event
std::string strategy_string () const
double jet_scale_for_algorithm (const PseudoJet &jet) const
 returns the scale associated with a jet as required for this clustering algorithm (kt^2 for the kt-algorithm, 1 for the Cambridge algorithm).
const std::vector< PseudoJet > & jets () const
 allow the user to access the jets in this raw manner (needed because we don't seem to be able to access protected elements of the class for an object that is not "this" (at least in case where "this" is of a slightly different kind from the object, both derived from ClusterSequence).
const std::vector< history_element > & history () const
 allow the user to access the history in this raw manner (see above for motivation).
unsigned int n_particles () const
 returns the number of particles that were provided to the clustering algorithm (helps the user find their way around the history and jets objects if they weren't paying attention beforehand).
std::vector< int > unique_history_order () const
 routine that returns a an order in which to read the history such that clusterings that lead to identical jet compositions but different histories (because of degeneracies in the clustering order) will have matching constituents for each matching entry in the unique_history_order.

Static Public Member Functions

static void set_jet_finder (JetFinder jet_finder)
 set the default (static) jet finder across all current and future ClusterSequence objects -- deprecated.

Protected Member Functions

template<class L>
void _transfer_input_jets (const std::vector< L > &pseudojets)
 transfer the vector<L> of input jets into our own vector<PseudoJet> _jets (with some reserved space for future growth).
void _initialise_and_run (const JetDefinition &jet_def, const bool &writeout_combinations)
 This is the routine that will do all the initialisation and then run the clustering (may be called by various constructors).
void _initialise_and_run (const double &R, const Strategy &strategy, const bool &writeout_combinations)
 This is an alternative routine for initialising and running the clustering, provided for legacy purposes.
void _decant_options (const JetDefinition &jet_def, const bool &writeout_combinations)
 fills in the various member variables with "decanted" options from the jet_definition and writeout_combinations variables
void _fill_initial_history ()
 fill out the history (and jet cross refs) related to the initial set of jets (assumed already to have been "transferred"), without any clustering
void _do_ij_recombination_step (const int &jet_i, const int &jet_j, const double &dij, int &newjet_k)
 carries out the bookkeeping associated with the step of recombining jet_i and jet_j (assuming a distance dij) and returns the index of the recombined jet, newjet_k.
void _do_iB_recombination_step (const int &jet_i, const double &diB)
 carries out the bookkeeping associated with the step of recombining jet_i with the beam

Protected Attributes

JetDefinition _jet_def
std::vector< PseudoJet_jets
 This contains the physical PseudoJets; for each PseudoJet one can find the corresponding position in the _history by looking at _jets[i].cluster_hist_index().
std::vector< history_element_history
 this vector will contain the branching history; for each stage, _history[i].jetp_index indicates where to look in the _jets vector to get the physical PseudoJet.
bool _writeout_combinations
int _initial_n
double _Rparam
double _R2
double _invR2
Strategy _strategy
JetFinder _jet_finder

Static Protected Attributes

static JetFinder _default_jet_finder = kt_algorithm

Private Types

typedef std::pair< int, int > TwoVertices
typedef std::pair< double,
TwoVertices
DijEntry
typedef std::multimap< double,
TwoVertices
DistMap

Private Member Functions

void _really_dumb_cluster ()
 Run the clustering in a very slow variant of the N^3 algorithm.
void _delaunay_cluster ()
 Run the clustering using a Hierarchical Delaunay triangulation and STL maps to achieve O(N*ln N) behaviour.
void _simple_N2_cluster ()
 Order(N^2) clustering.
void _tiled_N2_cluster ()
 run a tiled clustering
void _faster_tiled_N2_cluster ()
 run a tiled clustering
void _minheap_faster_tiled_N2_cluster ()
 run a tiled clustering, with our minheap for keeping track of the smallest dij
void _CP2DChan_cluster ()
 a 4pi variant of the closest pair clustering
void _CP2DChan_cluster_2pi2R ()
 a variant of the closest pair clustering which uses a region of size 2pi+2R in phi.
void _CP2DChan_cluster_2piMultD ()
 a variant of the closest pair clustering which uses a region of size 2pi + 2*0.3 and then carries on with 2pi+2*R
void _CP2DChan_limited_cluster (double D)
 clusters only up to a distance Dlim -- does not deal with "inclusive" jets -- these are left to some other part of the program
void _do_Cambridge_inclusive_jets ()
void _add_step_to_history (const int &step_number, const int &parent1, const int &parent2, const int &jetp_index, const double &dij)
void _extract_tree_children (int pos, std::valarray< bool > &, const std::valarray< int > &, std::vector< int > &) const
 internal routine associated with the construction of the unique history order (following children in the tree)
void _extract_tree_parents (int pos, std::valarray< bool > &, const std::valarray< int > &, std::vector< int > &) const
 internal routine associated with the construction of the unique history order (following parents in the tree)
void _add_ktdistance_to_map (const int &ii, DistMap &DijMap, const DynamicNearestNeighbours *DNN)
 Add the current kt distance for particle ii to the map (DijMap) using information from the DNN object.
void _print_banner ()
 for making sure the user knows what it is they're running...
template<class J>
void _bj_set_jetinfo (J *const jet, const int _jets_index) const
 set the kinematic and labelling info for jeta so that it corresponds to _jets[_jets_index]
void _bj_remove_from_tiles (TiledJet *const jet) const
 "remove" this jet, which implies updating links of neighbours and perhaps modifying the tile structure
template<class J>
double _bj_dist (const J *const jeta, const J *const jetb) const
 return the distance between two BriefJet objects
template<class J>
double _bj_diJ (const J *const jeta) const
template<class J>
J * _bj_of_hindex (const int hist_index, J *const head, J *const tail) const
 for testing purposes only: if in the range head--tail-1 there is a a jet which corresponds to hist_index in the history, then return a pointer to that jet; otherwise return tail.
template<class J>
void _bj_set_NN_nocross (J *const jeta, J *const head, const J *const tail) const
 updates (only towards smaller distances) the NN for jeta without checking whether in the process jeta itself might be a new NN of one of the jets being scanned -- span the range head to tail-1 with assumption that jeta is not contained in that range
template<class J>
void _bj_set_NN_crosscheck (J *const jeta, J *const head, const J *const tail) const
 reset the NN for jeta and DO check whether in the process jeta itself might be a new NN of one of the jets being scanned -- span the range head to tail-1 with assumption that jeta is not contained in that range
int _tile_index (int ieta, int iphi) const
int _tile_index (const double &eta, const double &phi) const
 return the tile index corresponding to the given eta,phi point
void _tj_set_jetinfo (TiledJet *const jet, const int _jets_index)
void _bj_remove_from_tiles (TiledJet *const jet)
void _initialise_tiles ()
 Set up the tiles:
  • decide the range in eta
  • allocate the tiles
  • set up the cross-referencing info between tiles.

void _print_tiles (TiledJet *briefjets) const
 output the contents of the tiles
void _add_neighbours_to_tile_union (const int tile_index, std::vector< int > &tile_union, int &n_near_tiles) const
 Add to the vector tile_union the tiles that are in the neighbourhood of the specified tile_index, including itself -- start adding from position n_near_tiles-1, and increase n_near_tiles as you go along (could have done it more C++ like with vector with reserved space, but fear is that it would have been slower, e.g.
void _add_untagged_neighbours_to_tile_union (const int tile_index, std::vector< int > &tile_union, int &n_near_tiles)
 Like _add_neighbours_to_tile_union, but only adds neighbours if their "tagged" status is false; when a neighbour is added its tagged status is set to true.

Private Attributes

std::vector< Tile_tiles
double _tiles_eta_min
double _tiles_eta_max
double _tile_size_eta
double _tile_size_phi
int _n_tiles_phi
int _tiles_ieta_min
int _tiles_ieta_max

Static Private Attributes

static bool _first_time = true
 will be set by default to be true for the first run
static const int n_tile_neighbours = 9
 number of neighbours that a tile will have (rectangular geometry gives 9 neighbours).

Classes

struct  BriefJet
 the fundamental structure which contains the minimal info about a jet, as needed for our plain N^2 algorithm -- the idea is to put all info that will be accessed N^2 times into an array of BriefJets. More...
struct  history_element
 a single element in the clustering history (see vector _history below). More...
struct  Tile
 The fundamental structures to be used for the tiled N^2 algorithm (see CCN27-44 for some discussion of pattern of tiling). More...
class  TiledJet
 structure analogous to BriefJet, but with the extra information needed for dealing with tiles More...

Detailed Description

deals with clustering

Definition at line 64 of file ClusterSequence.hh.


Member Typedef Documentation

typedef std::pair<double,TwoVertices> fastjet::ClusterSequence::DijEntry [private]
 

Definition at line 322 of file ClusterSequence.hh.

typedef std::multimap<double,TwoVertices> fastjet::ClusterSequence::DistMap [private]
 

Definition at line 323 of file ClusterSequence.hh.

typedef std::pair<int,int> fastjet::ClusterSequence::TwoVertices [private]
 

Definition at line 321 of file ClusterSequence.hh.


Member Enumeration Documentation

enum fastjet::ClusterSequence::JetType
 

Enumeration values:
Invalid 
InexistentParent 
BeamJet 

Definition at line 187 of file ClusterSequence.hh.

00187 {Invalid=-3, InexistentParent = -2, BeamJet = -1};


Constructor & Destructor Documentation

fastjet::ClusterSequence::ClusterSequence  )  [inline]
 

default constructor

Definition at line 70 of file ClusterSequence.hh.

00070 {};

template<class L>
fastjet::ClusterSequence::ClusterSequence const std::vector< L > &  pseudojets,
const double &  R = 1.0,
const Strategy strategy = Best,
const bool &  writeout_combinations = false
 

create a clustersequence starting from the supplied set of pseudojets and clustering them with the long-invariant kt algorithm (E-scheme recombination) with the supplied value for R.

If strategy=DumbN3 a very stupid N^3 algorithm is used for the clustering; otherwise strategy = NlnN* uses cylinders algorithms with some number of pi coverage. If writeout_combinations=true a summary of the recombination sequence is written out

Definition at line 493 of file ClusterSequence.hh.

References _initialise_and_run(), and _transfer_input_jets().

00497                                                                       {
00498 
00499   // transfer the initial jets (type L) into our own array
00500   _transfer_input_jets(pseudojets);
00501 
00502   // run the clustering
00503   _initialise_and_run(R,strategy,writeout_combinations);
00504 }

template<class L>
fastjet::ClusterSequence::ClusterSequence const std::vector< L > &  pseudojets,
const JetDefinition jet_def,
const bool &  writeout_combinations = false
 

constructor of a jet-clustering sequence from a vector of four-momenta, with the jet definition specified by jet_def

Definition at line 510 of file ClusterSequence.hh.

References _initialise_and_run(), and _transfer_input_jets().

00513                                                                       {
00514 
00515   // transfer the initial jets (type L) into our own array
00516   _transfer_input_jets(pseudojets);
00517 
00518   // run the clustering
00519   _initialise_and_run(jet_def,writeout_combinations);
00520 }


Member Function Documentation

void fastjet::ClusterSequence::_add_ktdistance_to_map const int &  ii,
DistMap DijMap,
const DynamicNearestNeighbours DNN
[private]
 

Add the current kt distance for particle ii to the map (DijMap) using information from the DNN object.

Work as follows:

. if the kt is zero then it's nearest neighbour is taken to be the the beam jet and the distance is zero.

. if cylinder distance to nearest neighbour > _Rparam then it is yiB that is smallest and this is added to map.

. otherwise if the nearest neighbour jj has a larger kt then add dij to the map.

. otherwise do nothing

Definition at line 220 of file ClusterSequence_Delaunay.cc.

References _invR2, _jets, jet_scale_for_algorithm(), fastjet::DynamicNearestNeighbours::NearestNeighbourDistance(), and fastjet::DynamicNearestNeighbours::NearestNeighbourIndex().

Referenced by _delaunay_cluster().

00223                                                                 {
00224   
00225   double yiB = jet_scale_for_algorithm(_jets[ii]);
00226   if (yiB == 0.0) {
00227     // in this case convention is that we do not worry about distances
00228     // but directly state that nearest neighbour is beam
00229     DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
00230   } else {
00231     double DeltaR2 = DNN->NearestNeighbourDistance(ii) * _invR2;
00232     // Logic of following bit is: only add point to map if it has
00233     // smaller kt2 than nearest neighbour j (if it has larger kt,
00234     // then: either it is j's nearest neighbour and then we will
00235     // include dij when we come to j; or it is not j's nearest
00236     // neighbour and j will recombine with someone else).
00237     
00238     // If DeltaR2 > 1.0 then in any case it will recombine with beam rather
00239     // than with any neighbours.
00240     // (put general normalisation here at some point)
00241     if (DeltaR2 > 1.0) {
00242       DijMap.insert(DijEntry(yiB,  TwoVertices(ii,-1)));
00243     } else {
00244       double kt2i = jet_scale_for_algorithm(_jets[ii]);
00245       int jj = DNN->NearestNeighbourIndex(ii);
00246       if (kt2i <= jet_scale_for_algorithm(_jets[jj])) {
00247         double dij = DeltaR2 * kt2i;
00248         DijMap.insert(DijEntry(dij, TwoVertices(ii,jj)));
00249       }
00250     }
00251   }
00252 }

void fastjet::ClusterSequence::_add_neighbours_to_tile_union const int  tile_index,
std::vector< int > &  tile_union,
int &  n_near_tiles
const [private]
 

Add to the vector tile_union the tiles that are in the neighbourhood of the specified tile_index, including itself -- start adding from position n_near_tiles-1, and increase n_near_tiles as you go along (could have done it more C++ like with vector with reserved space, but fear is that it would have been slower, e.g.

checking for end of vector at each stage to decide whether to resize it)

Definition at line 232 of file ClusterSequence_TiledN2.cc.

References _tiles.

Referenced by _tiled_N2_cluster().

00233                                                                    {
00234   for (Tile * const * near_tile = _tiles[tile_index].begin_tiles; 
00235        near_tile != _tiles[tile_index].end_tiles; near_tile++){
00236     // get the tile number
00237     tile_union[n_near_tiles] = *near_tile - & _tiles[0];
00238     n_near_tiles++;
00239   }
00240 }

void fastjet::ClusterSequence::_add_step_to_history const int &  step_number,
const int &  parent1,
const int &  parent2,
const int &  jetp_index,
const double &  dij
[private]
 

Definition at line 428 of file ClusterSequence.cc.

References _history, _jets, _writeout_combinations, fastjet::ClusterSequence::history_element::child, fastjet::ClusterSequence::history_element::dij, Invalid, fastjet::ClusterSequence::history_element::jetp_index, fastjet::ClusterSequence::history_element::max_dij_so_far, fastjet::ClusterSequence::history_element::parent1, and fastjet::ClusterSequence::history_element::parent2.

Referenced by _do_iB_recombination_step(), and _do_ij_recombination_step().

00431                                    {
00432 
00433   history_element element;
00434   element.parent1 = parent1;
00435   element.parent2 = parent2;
00436   element.jetp_index = jetp_index;
00437   element.child = Invalid;
00438   element.dij   = dij;
00439   element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00440   _history.push_back(element);
00441 
00442   int local_step = _history.size()-1;
00443   assert(local_step == step_number);
00444 
00445   assert(parent1 >= 0);
00446   _history[parent1].child = local_step;
00447   if (parent2 >= 0) {_history[parent2].child = local_step;}
00448 
00449   // get cross-referencing right from PseudoJets
00450   if (jetp_index != Invalid) {
00451     assert(jetp_index >= 0);
00452     //cout << _jets.size() <<" "<<jetp_index<<"\n";
00453     _jets[jetp_index].set_cluster_hist_index(local_step);
00454   }
00455 
00456   if (_writeout_combinations) {
00457     cout << local_step << ": " 
00458          << parent1 << " with " << parent2
00459          << "; y = "<< dij<<endl;
00460   }
00461 
00462 }

void fastjet::ClusterSequence::_add_untagged_neighbours_to_tile_union const int  tile_index,
std::vector< int > &  tile_union,
int &  n_near_tiles
[inline, private]
 

Like _add_neighbours_to_tile_union, but only adds neighbours if their "tagged" status is false; when a neighbour is added its tagged status is set to true.

Definition at line 247 of file ClusterSequence_TiledN2.cc.

References _tiles.

Referenced by _faster_tiled_N2_cluster(), and _minheap_faster_tiled_N2_cluster().

00249                                                               {
00250   for (Tile ** near_tile = _tiles[tile_index].begin_tiles; 
00251        near_tile != _tiles[tile_index].end_tiles; near_tile++){
00252     if (! (*near_tile)->tagged) {
00253       (*near_tile)->tagged = true;
00254       // get the tile number
00255       tile_union[n_near_tiles] = *near_tile - & _tiles[0];
00256       n_near_tiles++;
00257     }
00258   }
00259 }

template<class J>
double fastjet::ClusterSequence::_bj_diJ const J *const   jeta  )  const [inline, private]
 

Definition at line 568 of file ClusterSequence.hh.

Referenced by _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), _simple_N2_cluster(), and _tiled_N2_cluster().

00568                                                                                    {
00569   double kt2 = jet->kt2;
00570   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00571   return jet->NN_dist * kt2;
00572 }

template<class J>
double fastjet::ClusterSequence::_bj_dist const J *const   jeta,
const J *const   jetb
const [inline, private]
 

return the distance between two BriefJet objects

Definition at line 559 of file ClusterSequence.hh.

References fastjet::pi, and fastjet::twopi.

Referenced by _bj_set_NN_crosscheck(), _bj_set_NN_nocross(), _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), _simple_N2_cluster(), and _tiled_N2_cluster().

00560                                                                   {
00561   double dphi = std::abs(jetA->phi - jetB->phi);
00562   double deta = (jetA->eta - jetB->eta);
00563   if (dphi > pi) {dphi = twopi - dphi;}
00564   return dphi*dphi + deta*deta;
00565 }

template<class J>
J* fastjet::ClusterSequence::_bj_of_hindex const int  hist_index,
J *const   head,
J *const   tail
const [inline, private]
 

for testing purposes only: if in the range head--tail-1 there is a a jet which corresponds to hist_index in the history, then return a pointer to that jet; otherwise return tail.

Definition at line 385 of file ClusterSequence.hh.

00388           {
00389     J * res;
00390     for(res = head; res<tail; res++) {
00391       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00392     }
00393     return res;
00394   };

void fastjet::ClusterSequence::_bj_remove_from_tiles TiledJet *const   jet  )  [private]
 

Definition at line 49 of file ClusterSequence_TiledN2.cc.

References _tiles, fastjet::ClusterSequence::Tile::head, fastjet::ClusterSequence::TiledJet::next, fastjet::ClusterSequence::TiledJet::previous, and fastjet::ClusterSequence::TiledJet::tile_index.

00049                                                                 {
00050   Tile * tile = & _tiles[jet->tile_index];
00051 
00052   if (jet->previous == NULL) {
00053     // we are at head of the tile, so reset it.
00054     // If this was the only jet on the tile then tile->head will now be NULL
00055     tile->head = jet->next;
00056   } else {
00057     // adjust link from previous jet in this tile
00058     jet->previous->next = jet->next;
00059   }
00060   if (jet->next != NULL) {
00061     // adjust backwards-link from next jet in this tile
00062     jet->next->previous = jet->previous;
00063   }
00064 }

void fastjet::ClusterSequence::_bj_remove_from_tiles TiledJet *const   jet  )  const [private]
 

"remove" this jet, which implies updating links of neighbours and perhaps modifying the tile structure

Referenced by _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), and _tiled_N2_cluster().

template<class J>
void fastjet::ClusterSequence::_bj_set_jetinfo J *const   jet,
const int  _jets_index
const [inline, private]
 

set the kinematic and labelling info for jeta so that it corresponds to _jets[_jets_index]

Definition at line 544 of file ClusterSequence.hh.

References _jets, _R2, and jet_scale_for_algorithm().

Referenced by _simple_N2_cluster().

00545                                                                          {
00546     jetA->eta  = _jets[_jets_index].rap();
00547     jetA->phi  = _jets[_jets_index].phi_02pi();
00548     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
00549     jetA->_jets_index = _jets_index;
00550     // initialise NN info as well
00551     jetA->NN_dist = _R2;
00552     jetA->NN      = NULL;
00553 }

template<class J>
void fastjet::ClusterSequence::_bj_set_NN_crosscheck J *const   jeta,
J *const   head,
const J *const   tail
const [inline, private]
 

reset the NN for jeta and DO check whether in the process jeta itself might be a new NN of one of the jets being scanned -- span the range head to tail-1 with assumption that jeta is not contained in that range

Definition at line 606 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

Referenced by _simple_N2_cluster().

00607                                                                 {
00608   double NN_dist = _R2;
00609   J * NN  = NULL;
00610   for (J * jetB = head; jetB != tail; jetB++) {
00611     double dist = _bj_dist(jet,jetB);
00612     if (dist < NN_dist) {
00613       NN_dist = dist;
00614       NN = jetB;
00615     }
00616     if (dist < jetB->NN_dist) {
00617       jetB->NN_dist = dist;
00618       jetB->NN = jet;
00619     }
00620   }
00621   jet->NN = NN;
00622   jet->NN_dist = NN_dist;
00623 }

template<class J>
void fastjet::ClusterSequence::_bj_set_NN_nocross J *const   jeta,
J *const   head,
const J *const   tail
const [inline, private]
 

updates (only towards smaller distances) the NN for jeta without checking whether in the process jeta itself might be a new NN of one of the jets being scanned -- span the range head to tail-1 with assumption that jeta is not contained in that range

Definition at line 578 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

Referenced by _simple_N2_cluster().

00579                                                                             {
00580   double NN_dist = _R2;
00581   J * NN  = NULL;
00582   if (head < jet) {
00583     for (J * jetB = head; jetB != jet; jetB++) {
00584       double dist = _bj_dist(jet,jetB);
00585       if (dist < NN_dist) {
00586         NN_dist = dist;
00587         NN = jetB;
00588       }
00589     }
00590   }
00591   if (tail > jet) {
00592     for (J * jetB = jet+1; jetB != tail; jetB++) {
00593       double dist = _bj_dist(jet,jetB);
00594       if (dist < NN_dist) {
00595         NN_dist = dist;
00596         NN = jetB;
00597       }
00598     }
00599   }
00600   jet->NN = NN;
00601   jet->NN_dist = NN_dist;
00602 }

void fastjet::ClusterSequence::_CP2DChan_cluster  )  [private]
 

a 4pi variant of the closest pair clustering

Definition at line 223 of file ClusterSequence_CP2DChan.cc.

References _do_Cambridge_inclusive_jets(), _do_ij_recombination_step(), _invR2, _jet_finder, _jets, BeamJet, fastjet::cambridge_algorithm, fastjet::ClosestPair2D::closest_pair(), Invalid, fastjet::ClosestPair2D::replace(), and fastjet::twopi.

Referenced by _initialise_and_run().

00223                                          {
00224 
00225   if (_jet_finder != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
00226 
00227   unsigned int n = _jets.size();
00228 
00229   vector<MirrorInfo>   coordIDs(2*n);  // link from original to mirror indices
00230   vector<int>          jetIDs(2*n);     // link from mirror to original indices
00231   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
00232 
00233   // start things off...
00234   double minrap = numeric_limits<double>::max();
00235   double maxrap = -minrap;
00236   int coord_index = 0;
00237   for (unsigned i = 0; i < n; i++) {
00238     // separate out points with infinite rapidity
00239     if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
00240       coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
00241     } else {
00242       coordIDs[i].orig   = coord_index;
00243       coordIDs[i].mirror = coord_index+1;
00244       coords[coord_index]   = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
00245       coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
00246       jetIDs[coord_index]   = i;
00247       jetIDs[coord_index+1] = i;
00248       minrap = min(coords[coord_index].x,minrap);
00249       maxrap = max(coords[coord_index].x,maxrap);
00250       coord_index += 2;
00251     }
00252   }
00253   // label remaining "mirror info" as saying that there are no jets
00254   for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
00255 
00256   // set them to their actual size...
00257   coords.resize(coord_index);
00258 
00259   // establish limits (with some leeway on rapidity)
00260   Coord2D left_edge(minrap-1.0, 0.0);
00261   Coord2D right_edge(maxrap+1.0, 2*twopi);
00262 
00263   // now create the closest pair search object
00264   ClosestPair2D cp(coords, left_edge, right_edge);
00265 
00266   // and start iterating...
00267   vector<Coord2D> new_points(2);
00268   vector<unsigned int> cIDs_to_remove(4);
00269   vector<unsigned int> new_cIDs(2);
00270   do {
00271     // find out which pair we recombine
00272     unsigned int cID1, cID2;
00273     double distance2;
00274     cp.closest_pair(cID1,cID2,distance2);
00275     distance2 *= _invR2;
00276 
00277     // if the closest distance > 1, we exit and go to "inclusive" stage
00278     if (distance2 > 1.0) {break;}
00279 
00280     // do the recombination...
00281     int jet_i = jetIDs[cID1];
00282     int jet_j = jetIDs[cID2];
00283     int newjet_k;
00284     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00285 
00286     // now prepare operations on CP structure
00287     cIDs_to_remove[0] = coordIDs[jet_i].orig;
00288     cIDs_to_remove[1] = coordIDs[jet_i].mirror;
00289     cIDs_to_remove[2] = coordIDs[jet_j].orig;
00290     cIDs_to_remove[3] = coordIDs[jet_j].mirror;
00291     new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00292     new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
00293     // carry out the CP operation
00294     //cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00295     // remarkable the following is faster...
00296     new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
00297     new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
00298     // signal that the following jets no longer exist
00299     coordIDs[jet_i].orig = Invalid;
00300     coordIDs[jet_j].orig = Invalid;
00301     // and do bookkeeping for new jet
00302     coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
00303     jetIDs[new_cIDs[0]] = newjet_k;
00304     jetIDs[new_cIDs[1]] = newjet_k;
00305 
00306     // if we've reached one jet we should exit...
00307     n--;
00308     if (n == 1) {break;}
00309 
00310   } while(true);
00311   
00312 
00313   // now do "beam" recombinations 
00314   //for (unsigned int jet_i = 0; jet_i < coordIDs.size(); jet_i++) {
00315   //  // if we have a predeclared beam jet or a valid set of mirror
00316   //  // coordinates, recombine then recombine this jet with the beam
00317   //  if (coordIDs[jet_i].orig == BeamJet || coordIDs[jet_i].orig > 0) {
00318   //    // diB = 1 _always_ (for the cambridge alg.)
00319   //    _do_iB_recombination_step(jet_i, 1.0);
00320   //  }
00321   //}
00322 
00323   _do_Cambridge_inclusive_jets();
00324 
00325   //n = _history.size();
00326   //for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00327   //  if (_history[hist_i].child == Invalid) {
00328   //    _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00329   //  }
00330   //}
00331 
00332 }

void fastjet::ClusterSequence::_CP2DChan_cluster_2pi2R  )  [private]
 

a variant of the closest pair clustering which uses a region of size 2pi+2R in phi.

Definition at line 193 of file ClusterSequence_CP2DChan.cc.

References _CP2DChan_limited_cluster(), _do_Cambridge_inclusive_jets(), _jet_finder, _Rparam, and fastjet::cambridge_algorithm.

Referenced by _CP2DChan_cluster_2piMultD(), and _initialise_and_run().

00193                                                {
00194 
00195   if (_jet_finder != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
00196 
00197   // run the clustering with mirror copies kept such that only things
00198   // within _Rparam of a border are mirrored
00199   _CP2DChan_limited_cluster(_Rparam);
00200 
00201   //
00202   _do_Cambridge_inclusive_jets();
00203 }

void fastjet::ClusterSequence::_CP2DChan_cluster_2piMultD  )  [private]
 

a variant of the closest pair clustering which uses a region of size 2pi + 2*0.3 and then carries on with 2pi+2*R

Definition at line 209 of file ClusterSequence_CP2DChan.cc.

References _CP2DChan_cluster_2pi2R(), _CP2DChan_limited_cluster(), and _Rparam.

Referenced by _initialise_and_run().

00209                                                   {
00210 
00211   // do a first run of clustering up to a small distance parameter,
00212   if (_Rparam >= 0.39) {
00213     _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
00214   }
00215 
00216   // and then the final round of clustering
00217   _CP2DChan_cluster_2pi2R ();
00218 }

void fastjet::ClusterSequence::_CP2DChan_limited_cluster double  D  )  [private]
 

clusters only up to a distance Dlim -- does not deal with "inclusive" jets -- these are left to some other part of the program

Definition at line 69 of file ClusterSequence_CP2DChan.cc.

References _do_ij_recombination_step(), _history, _initial_n, _invR2, _jets, fastjet::ClosestPair2D::closest_pair(), Invalid, fastjet::Private::make_mirror(), fastjet::pi, and fastjet::ClosestPair2D::replace_many().

Referenced by _CP2DChan_cluster_2pi2R(), and _CP2DChan_cluster_2piMultD().

00069                                                             {
00070   
00071   unsigned int n = _initial_n;
00072 
00073   vector<MirrorInfo>   coordIDs(2*n); // coord IDs of a given jetID
00074   vector<int>          jetIDs(2*n);   // jet ID for a given coord ID
00075   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
00076 
00077   // start things off...
00078   double minrap = numeric_limits<double>::max();
00079   double maxrap = -minrap;
00080   int coord_index = -1;
00081   int n_active = 0;
00082   for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
00083 
00084     // skip jets that already have children or that have infinite
00085     // rapidity
00086     if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
00087         (_jets[jet_i].E() == abs(_jets[jet_i].pz()) && 
00088          _jets[jet_i].perp2() == 0.0)
00089         ) {continue;}
00090 
00091     n_active++;
00092 
00093     coordIDs[jet_i].orig = ++coord_index;
00094     coords[coord_index]  = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
00095     jetIDs[coord_index]  = jet_i;
00096     minrap = min(coords[coord_index].x,minrap);
00097     maxrap = max(coords[coord_index].x,maxrap);
00098 
00099     Coord2D mirror_point(coords[coord_index]);
00100     if (make_mirror(mirror_point, Dlim)) {
00101       coordIDs[jet_i].mirror = ++coord_index;
00102       coords[coord_index] = mirror_point;
00103       jetIDs[coord_index] = jet_i;
00104     } else {
00105       coordIDs[jet_i].mirror = Invalid;
00106     }
00107   }
00108 
00109   // set them to their actual size...
00110   coords.resize(coord_index+1);
00111 
00112   // establish limits (with some leeway on rapidity)
00113   Coord2D left_edge(minrap-1.0, -pi);
00114   Coord2D right_edge(maxrap+1.0, 3*pi);
00115 
00116   //cerr << "minrap, maxrap = " << minrap << " " << maxrap << endl;
00117 
00118   // now create the closest pair search object
00119   ClosestPair2D cp(coords, left_edge, right_edge);
00120 
00121   // cross check to see what's going on...
00122   //cerr << "Tree depths before: ";
00123   //cp.print_tree_depths(cerr);
00124 
00125   // and start iterating...
00126   vector<Coord2D> new_points(2);
00127   vector<unsigned int> cIDs_to_remove(4);
00128   vector<unsigned int> new_cIDs(2);
00129 
00130   do {
00131     // find out which pair we recombine
00132     unsigned int cID1, cID2;
00133     double distance2;
00134     cp.closest_pair(cID1,cID2,distance2);
00135 
00136     // if the closest distance > Dlim, we exit and go to "inclusive" stage
00137     if (distance2 > Dlim*Dlim) {break;}
00138 
00139     // normalise distance as we like it
00140     distance2 *= _invR2;
00141 
00142     // do the recombination...
00143     int jet_i = jetIDs[cID1];
00144     int jet_j = jetIDs[cID2];
00145     int newjet_k;
00146     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00147 
00148     // don't bother with any further action if only one active particle
00149     // is left (also avoid closest-pair error [cannot remove last particle]).
00150     if (--n_active == 1) {break;}
00151 
00152     // now prepare operations on CP structure
00153     cIDs_to_remove.resize(0);
00154     cIDs_to_remove.push_back(coordIDs[jet_i].orig);
00155     cIDs_to_remove.push_back(coordIDs[jet_j].orig);
00156     if (coordIDs[jet_i].mirror != Invalid) 
00157       cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
00158     if (coordIDs[jet_j].mirror != Invalid) 
00159       cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
00160 
00161     Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00162     new_points.resize(0);
00163     new_points.push_back(new_point);
00164     if (make_mirror(new_point, Dlim)) new_points.push_back(new_point);
00165     
00166     // carry out actions on search tree
00167     cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00168 
00169     // now fill in info for new points...
00170     coordIDs[newjet_k].orig = new_cIDs[0];
00171     jetIDs[new_cIDs[0]]       = newjet_k;
00172     if (new_cIDs.size() == 2) {
00173       coordIDs[newjet_k].mirror = new_cIDs[1];
00174       jetIDs[new_cIDs[1]]         = newjet_k;
00175     } else {coordIDs[newjet_k].mirror = Invalid;}
00176     
00178     //n_active--;
00179     //if (n_active == 1) {break;}
00180 
00181   } while(true);
00182   
00183   // cross check to see what's going on...
00184   //cerr << "Max tree depths after: ";
00185   //cp.print_tree_depths(cerr);
00186 
00187 }

void fastjet::ClusterSequence::_decant_options const JetDefinition jet_def,
const bool &  writeout_combinations
[protected]
 

fills in the various member variables with "decanted" options from the jet_definition and writeout_combinations variables

Definition at line 175 of file ClusterSequence.cc.

References _invR2, _jet_def, _jet_finder, _print_banner(), _R2, _Rparam, _strategy, and _writeout_combinations.

Referenced by _initialise_and_run(), and fastjet::ClusterSequenceActiveArea::_initialise_and_run_AA().

00176                                                                           {
00177 
00178   // let the user know what's going on
00179   _print_banner();
00180 
00181   // make a local copy of the jet definition (for future use?)
00182   _jet_def = jet_def;
00183   
00184   _writeout_combinations = writeout_combinations;
00185   _jet_finder = jet_def.jet_finder();
00186   _Rparam = jet_def.R();  _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
00187   _strategy = jet_def.strategy();
00188 }

void fastjet::ClusterSequence::_delaunay_cluster  )  [private]
 

Run the clustering using a Hierarchical Delaunay triangulation and STL maps to achieve O(N*ln N) behaviour.

There may be internally asserted assumptions about absence of points with coincident eta-phi coordinates.

Definition at line 58 of file ClusterSequence_Delaunay.cc.

References _add_ktdistance_to_map(), _do_iB_recombination_step(), _do_ij_recombination_step(), _jets, _Rparam, _strategy, BeamJet, fastjet::NlnN, fastjet::NlnN3pi, fastjet::NlnN4pi, fastjet::DynamicNearestNeighbours::RemoveCombinedAddCombination(), fastjet::DynamicNearestNeighbours::RemovePoint(), fastjet::EtaPhi::sanitize(), strategy_string(), fastjet::twopi, and fastjet::DynamicNearestNeighbours::Valid().

Referenced by _initialise_and_run().

00058                                          {
00059 
00060   int n = _jets.size();
00061 
00062   vector<EtaPhi> points(n); // recall EtaPhi is just a typedef'd pair<double>
00063   for (int i = 0; i < n; i++) {
00064     points[i] = EtaPhi(_jets[i].rap(),_jets[i].phi_02pi());
00065     points[i].sanitize(); // make sure things are in the right range
00066   }
00067 
00068   // initialise our DNN structure with the set of points
00069   DynamicNearestNeighbours * DNN;
00070 #ifndef DROP_CGAL // strategy = NlnN* are not supported if we drop CGAL...
00071   bool verbose = false;
00072   bool ignore_nearest_is_mirror = (_Rparam < twopi);
00073   if (_strategy == NlnN4pi) {
00074     DNN = new Dnn4piCylinder(points,verbose);
00075   } else if (_strategy == NlnN3pi) {
00076     DNN = new Dnn3piCylinder(points,ignore_nearest_is_mirror,verbose);
00077   } else if (_strategy == NlnN) {
00078     DNN = new Dnn2piCylinder(points,ignore_nearest_is_mirror,verbose);
00079   } else 
00080 #else
00081   if (_strategy == NlnN4pi || _strategy == NlnN3pi || _strategy == NlnN) {
00082     ostringstream err;
00083     err << "ERROR: Requested strategy "<<strategy_string()<<" but it is not"<<endl;
00084     err << "       supported because FastJet was compiled without CGAL"<<endl;
00085     throw Error(err.str());
00086     //assert(false);
00087   }
00088 #endif // DROP_CGAL
00089   {
00090     ostringstream err;
00091     err << "ERROR: Unrecognized value for strategy: "<<_strategy<<endl;
00092     assert(false);
00093     throw Error(err.str());
00094   }
00095 
00096   // We will find nearest neighbour for each vertex, and include
00097   // distance in map (NB DistMap is a typedef given in the .h file)
00098   DistMap DijMap;
00099 
00100   // fill the map with the minimal (as far as we know) subset of Dij
00101   // distances (i.e. nearest neighbour ones).
00102   for (int ii = 0; ii < n; ii++) {
00103     _add_ktdistance_to_map(ii, DijMap, DNN);
00104   }
00105 
00106   // run the clustering (go up to i=n-1, but then will stop half-way down,
00107   // when we reach that point -- it will be the final beam jet and there
00108   // will be no nearest neighbours to find).
00109   for (int i=0;i<n;i++) {
00110     // find nearest vertices
00111     // NB: skip cases where the point is not there anymore!
00112     TwoVertices SmallestDijPair;
00113     int jet_i, jet_j;
00114     double SmallestDij;
00115     bool Valid2;
00116     bool recombine_with_beam;
00117     do { 
00118       SmallestDij = DijMap.begin()->first;
00119       SmallestDijPair = DijMap.begin()->second;
00120       jet_i = SmallestDijPair.first;
00121       jet_j = SmallestDijPair.second;
00122       // distance is immediately removed regardless of whether or not
00123       // it is used.
00124       // Some temporary testing code relating to problems with the gcc-3.2 compiler
00125       //cout << "got here and size is "<< DijMap.size()<< " and it is "<<SmallestDij <<"\n";
00126       //cout <<  jet_i << " "<< jet_j<<"\n";
00127       DijMap.erase(DijMap.begin());
00128       //cout << "got beyond here\n";
00129 
00130       // need to "prime" the validity of jet_j in such a way that 
00131       // if it corresponds to the beam then it is automatically valid.
00132       recombine_with_beam = (jet_j == BeamJet);
00133       if (!recombine_with_beam) {Valid2 = DNN->Valid(jet_j);} 
00134       else {Valid2 = true;}
00135 
00136     } while ( !DNN->Valid(jet_i) || !Valid2);
00137 
00138 
00139     // The following part acts just on jet momenta and on the history.
00140     // The action on the nearest-neighbour structures takes place
00141     // later (only if at least 2 jets are around).
00142     if (! recombine_with_beam) {
00143       int nn; // will be index of new jet
00144       _do_ij_recombination_step(jet_i, jet_j, SmallestDij, nn);
00145       //OBS // merge the two jets, add new jet, remove old ones
00146       //OBS _jets.push_back(_jets[jet_i] + _jets[jet_j]);
00147       //OBS 
00148       //OBS int nn = _jets.size()-1;
00149       //OBS _jets[nn].set_cluster_hist_index(n+i);
00150       //OBS 
00151       //OBS // get corresponding indices in history structure
00152       //OBS int hist_i = _jets[jet_i].cluster_hist_index();
00153       //OBS int hist_j = _jets[jet_j].cluster_hist_index();
00154       //OBS 
00155       //OBS 
00156       //OBS _add_step_to_history(n+i,min(hist_i,hist_j), max(hist_i,hist_j),
00157       //OBS                   _jets.size()-1, SmallestDij);
00158 
00159       // add new point to points vector
00160       EtaPhi newpoint(_jets[nn].rap(), _jets[nn].phi_02pi());
00161       newpoint.sanitize(); // make sure it is in correct range
00162       points.push_back(newpoint);
00163     } else {
00164       // recombine the jet with the beam
00165       _do_iB_recombination_step(jet_i, SmallestDij);
00166       //OBS _add_step_to_history(n+i,_jets[jet_i].cluster_hist_index(),BeamJet,
00167       //OBS                        Invalid, SmallestDij);
00168     }
00169 
00170     // exit the loop because we do not want to look for nearest neighbours
00171     // etc. of zero partons
00172     if (i == n-1) {break;}
00173 
00174     vector<int> updated_neighbours;
00175     if (! recombine_with_beam) {
00176       // update DNN
00177       int point3;
00178       DNN->RemoveCombinedAddCombination(jet_i, jet_j, 
00179                                        points[points.size()-1], point3,
00180                                        updated_neighbours);
00181       // C++ beginners' comment: static_cast to unsigned int is necessary
00182       // to do away with warnings about type mismatch between point3 (int) 
00183       // and points.size (unsigned int)
00184       if (static_cast<unsigned int> (point3) != points.size()-1) {
00185         throw Error("INTERNAL ERROR: point3 != points.size()-1");}
00186     } else {
00187       // update DNN
00188       DNN->RemovePoint(jet_i, updated_neighbours);
00189     }
00190 
00191     // update map
00192     vector<int>::iterator it = updated_neighbours.begin();
00193     for (; it != updated_neighbours.end(); ++it) {
00194       int ii = *it;
00195       _add_ktdistance_to_map(ii, DijMap, DNN);
00196     }
00197       
00198   } // end clustering loop 
00199   
00200   // remember to clean up!
00201   delete DNN;
00202 }

void fastjet::ClusterSequence::_do_Cambridge_inclusive_jets  )  [private]
 

Definition at line 336 of file ClusterSequence_CP2DChan.cc.

References _do_iB_recombination_step(), _history, and Invalid.

Referenced by _CP2DChan_cluster(), and _CP2DChan_cluster_2pi2R().

00336                                                     {
00337   unsigned int n = _history.size();
00338   for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00339     if (_history[hist_i].child == Invalid) {
00340       _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00341     }
00342   }
00343 }

void fastjet::ClusterSequence::_do_iB_recombination_step const int &  jet_i,
const double &  diB
[protected]
 

carries out the bookkeeping associated with the step of recombining jet_i with the beam

Definition at line 587 of file ClusterSequence.cc.

References _add_step_to_history(), _history, _jets, BeamJet, and Invalid.

Referenced by _delaunay_cluster(), _do_Cambridge_inclusive_jets(), _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), _really_dumb_cluster(), _simple_N2_cluster(), _tiled_N2_cluster(), and fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history().

00588                                                                          {
00589   // get history index
00590   int newstep_k = _history.size();
00591 
00592   // recombine the jet with the beam
00593   _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
00594                        Invalid, diB);
00595 
00596 }

void fastjet::ClusterSequence::_do_ij_recombination_step const int &  jet_i,
const int &  jet_j,
const double &  dij,
int &  newjet_k
[protected]
 

carries out the bookkeeping associated with the step of recombining jet_i and jet_j (assuming a distance dij) and returns the index of the recombined jet, newjet_k.

Definition at line 558 of file ClusterSequence.cc.

References _add_step_to_history(), _history, and _jets.

Referenced by _CP2DChan_cluster(), _CP2DChan_limited_cluster(), _delaunay_cluster(), _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), _really_dumb_cluster(), _simple_N2_cluster(), _tiled_N2_cluster(), and fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history().

00561                                                {
00562 
00563   // create the new jet
00564   _jets.push_back(_jets[jet_i] + _jets[jet_j]);
00565 
00566   // get its index
00567   newjet_k = _jets.size()-1;
00568 
00569   // get history index
00570   int newstep_k = _history.size();
00571   // and provide jet with the info
00572   _jets[newjet_k].set_cluster_hist_index(newstep_k);
00573 
00574   // finally sort out the history 
00575   int hist_i = _jets[jet_i].cluster_hist_index();
00576   int hist_j = _jets[jet_j].cluster_hist_index();
00577 
00578   _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
00579                        newjet_k, dij);
00580 
00581 }

void fastjet::ClusterSequence::_extract_tree_children int  pos,
std::valarray< bool > &  ,
const std::valarray< int > &  ,
std::vector< int > & 
const [private]
 

internal routine associated with the construction of the unique history order (following children in the tree)

Definition at line 508 of file ClusterSequence.cc.

References _extract_tree_parents(), and _history.

Referenced by unique_history_order().

00512                                         {
00513   if (!extracted[position]) {
00514     // that means we may have unidentified parents around, so go and
00515     // collect them (extracted[position]) will then be made true)
00516     _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
00517   } 
00518   
00519   // now look after the children...
00520   int child = _history[position].child;
00521   if (child  >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
00522 }

void fastjet::ClusterSequence::_extract_tree_parents int  pos,
std::valarray< bool > &  ,
const std::valarray< int > &  ,
std::vector< int > & 
const [private]
 

internal routine associated with the construction of the unique history order (following parents in the tree)

Definition at line 526 of file ClusterSequence.cc.

References _history.

Referenced by _extract_tree_children().

00530                                         {
00531 
00532   if (!extracted[position]) {
00533     int parent1 = _history[position].parent1;
00534     int parent2 = _history[position].parent2;
00535     // where relevant order parents so that we will first treat the
00536     // one containing the smaller "lowest_constituent"
00537     if (parent1 >= 0 && parent2 >= 0) {
00538       if (lowest_constituent[parent1] > lowest_constituent[parent2]) 
00539         swap(parent1, parent2);
00540     }
00541     // then actually run through the parents to extract the constituents...
00542     if (parent1 >= 0 && !extracted[parent1]) 
00543       _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
00544     if (parent2 >= 0 && !extracted[parent2]) 
00545       _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
00546     // finally declare this position to be accounted for and push it
00547     // onto our list.
00548     unique_tree.push_back(position);
00549     extracted[position] = true;
00550   }
00551 }

void fastjet::ClusterSequence::_faster_tiled_N2_cluster  )  [private]
 

run a tiled clustering

Definition at line 507 of file ClusterSequence_TiledN2.cc.

References _add_untagged_neighbours_to_tile_union(), _bj_diJ(), _bj_dist(), _bj_remove_from_tiles(), _do_iB_recombination_step(), _do_ij_recombination_step(), _initialise_tiles(), _invR2, _jets, fastjet::ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), fastjet::ClusterSequence::Tile::begin_tiles, fastjet::ClusterSequence::TiledJet::diJ_posn, fastjet::ClusterSequence::Tile::end_tiles, fastjet::ClusterSequence::Tile::head, n_tile_neighbours, fastjet::ClusterSequence::TiledJet::next, fastjet::ClusterSequence::TiledJet::NN, fastjet::ClusterSequence::TiledJet::NN_dist, fastjet::ClusterSequence::Tile::tagged, and fastjet::ClusterSequence::TiledJet::tile_index.

Referenced by _initialise_and_run().

00507                                                {
00508 
00509   _initialise_tiles();
00510 
00511   int n = _jets.size();
00512   TiledJet * briefjets = new TiledJet[n];
00513   TiledJet * jetA = briefjets, * jetB;
00514   TiledJet oldB;
00515   
00516 
00517   // will be used quite deep inside loops, but declare it here so that
00518   // memory (de)allocation gets done only once
00519   vector<int> tile_union(3*n_tile_neighbours);
00520   
00521   // initialise the basic jet info 
00522   for (int i = 0; i< n; i++) {
00523     _tj_set_jetinfo(jetA, i);
00524     //cout << i<<": "<<jetA->tile_index<<"\n";
00525     jetA++; // move on to next entry of briefjets
00526   }
00527   TiledJet * head = briefjets; // a nicer way of naming start
00528 
00529   // set up the initial nearest neighbour information
00530   vector<Tile>::const_iterator tile;
00531   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00532     // first do it on this tile
00533     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00534       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00535         double dist = _bj_dist(jetA,jetB);
00536         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00537         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00538       }
00539     }
00540     // then do it for RH tiles
00541     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00542       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00543         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00544           double dist = _bj_dist(jetA,jetB);
00545           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00546           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00547         }
00548       }
00549     }
00550     // no need to do it for LH tiles, since they are implicitly done
00551     // when we set NN for both jetA and jetB on the RH tiles.
00552   }
00553 
00554   
00555   // now create the diJ (where J is i's NN) table -- remember that 
00556   // we differ from standard normalisation here by a factor of R2
00557   // (corrected for at the end). 
00558   struct diJ_plus_link {
00559     double     diJ; // the distance
00560     TiledJet * jet; // the jet (i) for which we've found this distance
00561                     // (whose NN will the J).
00562   };
00563   diJ_plus_link * diJ = new diJ_plus_link[n];
00564   jetA = head;
00565   for (int i = 0; i < n; i++) {
00566     diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
00567     diJ[i].jet = jetA;  // our compact diJ table will not be in      
00568     jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
00569                         // so set up bi-directional correspondence here.
00570     jetA++; // have jetA follow i 
00571   }
00572 
00573   // now run the recombination loop
00574   int history_location = n-1;
00575   while (n > 0) {
00576 
00577     // find the minimum of the diJ on this round
00578     diJ_plus_link * best, *stop; // pointers a bit faster than indices
00579     // could use best to keep track of diJ min, but it turns out to be
00580     // marginally faster to have a separate variable (avoids n
00581     // dereferences at the expense of n/2 assignments).
00582     double diJ_min = diJ[0].diJ; // initialise the best one here.
00583     best = diJ;                  // and here
00584     stop = diJ+n;
00585     for (diJ_plus_link * here = diJ+1; here != stop; here++) {
00586       if (here->diJ < diJ_min) {best = here; diJ_min  = here->diJ;}
00587     }
00588 
00589     // do the recombination between A and B
00590     history_location++;
00591     jetA = best->jet;
00592     jetB = jetA->NN;
00593     // put the normalisation back in
00594     diJ_min *= _invR2; 
00595 
00596     if (jetB != NULL) {
00597       // jet-jet recombination
00598       // If necessary relabel A & B to ensure jetB < jetA, that way if
00599       // the larger of them == newtail then that ends up being jetA and 
00600       // the new jet that is added as jetB is inserted in a position that
00601       // has a future!
00602       if (jetA < jetB) {swap(jetA,jetB);}
00603 
00604       int nn; // new jet index
00605       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00606       
00607       //OBS// get the two history indices
00608       //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
00609       //OBSint ihstry_b = _jets[jetB->_jets_index].cluster_hist_index();
00610       //OBS// create the recombined jet
00611       //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
00612       //OBSint nn = _jets.size() - 1;
00613       //OBS_jets[nn].set_cluster_hist_index(history_location);
00614       //OBS// update history
00615       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
00616       //OBS_add_step_to_history(history_location, 
00617       //OBS                min(ihstry_a,ihstry_b),max(ihstry_a,ihstry_b),
00618       //OBS                        nn, diJ_min);
00619       // what was jetB will now become the new jet
00620       _bj_remove_from_tiles(jetA);
00621       oldB = * jetB;  // take a copy because we will need it...
00622       _bj_remove_from_tiles(jetB);
00623       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
00624                                  // (also registers the jet in the tiling)
00625     } else {
00626       // jet-beam recombination
00627       // get the hist_index
00628       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00629       //OBSint ihstry_a = _jets[jetA->_jets_index].cluster_hist_index();
00630       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
00631       //OBS_add_step_to_history(history_location,ihstry_a,BeamJet,Invalid,diJ_min); 
00632       _bj_remove_from_tiles(jetA);
00633     }
00634 
00635     // first establish the set of tiles over which we are going to
00636     // have to run searches for updated and new nearest-neighbours --
00637     // basically a combination of vicinity of the tiles of the two old
00638     // and one new jet.
00639     int n_near_tiles = 0;
00640     _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
00641                                            tile_union, n_near_tiles);
00642     if (jetB != NULL) {
00643       if (jetB->tile_index != jetA->tile_index) {
00644         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
00645                                                tile_union,n_near_tiles);
00646       }
00647       if (oldB.tile_index != jetA->tile_index && 
00648           oldB.tile_index != jetB->tile_index) {
00649         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
00650                                                tile_union,n_near_tiles);
00651       }
00652     }
00653 
00654     // now update our nearest neighbour info and diJ table
00655     // first reduce size of table
00656     n--;
00657     // then compactify the diJ by taking the last of the diJ and copying
00658     // it to the position occupied by the diJ for jetA
00659     diJ[n].jet->diJ_posn = jetA->diJ_posn;
00660     diJ[jetA->diJ_posn] = diJ[n];
00661 
00662     // Initialise jetB's NN distance as well as updating it for 
00663     // other particles.
00664     // Run over all tiles in our union 
00665     for (int itile = 0; itile < n_near_tiles; itile++) {
00666       Tile * tile = &_tiles[tile_union[itile]];
00667       tile->tagged = false; // reset tag, since we're done with unions
00668       // run over all jets in the current tile
00669       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00670         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00671         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00672           jetI->NN_dist = _R2;
00673           jetI->NN      = NULL;
00674           // now go over tiles that are neighbours of I (include own tile)
00675           for (Tile ** near_tile  = tile->begin_tiles; 
00676                        near_tile != tile->end_tiles; near_tile++) {
00677             // and then over the contents of that tile
00678             for (TiledJet * jetJ  = (*near_tile)->head; 
00679                             jetJ != NULL; jetJ = jetJ->next) {
00680               double dist = _bj_dist(jetI,jetJ);
00681               if (dist < jetI->NN_dist && jetJ != jetI) {
00682                 jetI->NN_dist = dist; jetI->NN = jetJ;
00683               }
00684             }
00685           }
00686           diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ kt-dist
00687         }
00688         // check whether new jetB is closer than jetI's current NN and
00689         // if jetI is closer than jetB's current (evolving) nearest
00690         // neighbour. Where relevant update things
00691         if (jetB != NULL) {
00692           double dist = _bj_dist(jetI,jetB);
00693           if (dist < jetI->NN_dist) {
00694             if (jetI != jetB) {
00695               jetI->NN_dist = dist;
00696               jetI->NN = jetB;
00697               diJ[jetI->diJ_posn].diJ = _bj_diJ(jetI); // update diJ...
00698             }
00699           }
00700           if (dist < jetB->NN_dist) {
00701             if (jetI != jetB) {
00702               jetB->NN_dist = dist;
00703               jetB->NN      = jetI;}
00704           }
00705         }
00706       }
00707     }
00708 
00709     // finally, register the updated kt distance for B
00710     if (jetB != NULL) {diJ[jetB->diJ_posn].diJ = _bj_diJ(jetB);}
00711 
00712   }
00713 
00714   // final cleaning up;
00715   delete[] diJ;
00716   delete[] briefjets;
00717 }

void fastjet::ClusterSequence::_fill_initial_history  )  [protected]
 

fill out the history (and jet cross refs) related to the initial set of jets (assumed already to have been "transferred"), without any clustering

Definition at line 193 of file ClusterSequence.cc.

References _history, _initial_n, _jets, fastjet::ClusterSequence::history_element::child, fastjet::ClusterSequence::history_element::dij, InexistentParent, Invalid, fastjet::ClusterSequence::history_element::jetp_index, fastjet::ClusterSequence::history_element::max_dij_so_far, fastjet::ClusterSequence::history_element::parent1, and fastjet::ClusterSequence::history_element::parent2.

Referenced by _initialise_and_run(), and fastjet::ClusterSequenceActiveArea::_initialise_and_run_AA().

00193                                              {
00194 
00195   if (_jets.size() == 0) {throw Error("Cannot run jet-finder on empty event");}
00196 
00197   // reserve sufficient space for everything
00198   _jets.reserve(_jets.size()*2);
00199   _history.reserve(_jets.size()*2);
00200 
00201   for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
00202     history_element element;
00203     element.parent1 = InexistentParent;
00204     element.parent2 = InexistentParent;
00205     element.child   = Invalid;
00206     element.jetp_index = i;
00207     element.dij     = 0.0;
00208     element.max_dij_so_far = 0.0;
00209 
00210     _history.push_back(element);
00211     
00212     // get cross-referencing right from PseudoJets
00213     _jets[i].set_cluster_hist_index(i);
00214   }
00215   _initial_n = _jets.size();
00216 }

void fastjet::ClusterSequence::_initialise_and_run const double &  R,
const Strategy strategy,
const bool &  writeout_combinations
[protected]
 

This is an alternative routine for initialising and running the clustering, provided for legacy purposes.

The jet finder is that specified in the static member _default_jet_finder.

Definition at line 51 of file ClusterSequence.cc.

References _default_jet_finder, and _initialise_and_run().

00054                                                                       {
00055 
00056   JetDefinition jet_def(_default_jet_finder, R, strategy);
00057   _initialise_and_run(jet_def, writeout_combinations);
00058 }

void fastjet::ClusterSequence::_initialise_and_run const JetDefinition jet_def,
const bool &  writeout_combinations
[protected]
 

This is the routine that will do all the initialisation and then run the clustering (may be called by various constructors).

It assumes _jets contains the momenta to be clustered.

Definition at line 62 of file ClusterSequence.cc.

References _CP2DChan_cluster(), _CP2DChan_cluster_2pi2R(), _CP2DChan_cluster_2piMultD(), _decant_options(), _delaunay_cluster(), _faster_tiled_N2_cluster(), _fill_initial_history(), _jets, _minheap_faster_tiled_N2_cluster(), _really_dumb_cluster(), _Rparam, _simple_N2_cluster(), _strategy, _tiled_N2_cluster(), fastjet::Best, fastjet::cambridge_algorithm, fastjet::JetDefinition::jet_finder(), fastjet::N2MinHeapTiled, fastjet::N2Plain, fastjet::N2PoorTiled, fastjet::N2Tiled, fastjet::N3Dumb, fastjet::NlnN, fastjet::NlnN3pi, fastjet::NlnN4pi, fastjet::NlnNCam, fastjet::NlnNCam2pi2R, and fastjet::NlnNCam4pi.

Referenced by _initialise_and_run(), fastjet::ClusterSequenceActiveArea::_initialise_and_run_AA(), and ClusterSequence().

00064                                                                       {
00065 
00066   // transfer all relevant info into internal variables
00067   _decant_options(jet_def, writeout_combinations);
00068 
00069   // set up the history entries for the initial particles (those
00070   // currently in _jets)
00071   _fill_initial_history();
00072 
00073 //  // automatically redefine the strategy according to N if that is
00074 //  // what the user requested
00075 //  if (_strategy == Best) {
00076 //    int N = _jets.size();
00077 //#ifndef DROP_CGAL
00078 //    if (N > 14500/_Rparam) { // empirical observation of how it scales with R
00079 //      _strategy = NlnN; }    // see GPS CCN27-57 (Numbers have changed since 
00080 //    else                     // introducing N2MinHeapTiled; scaling is approx.)
00081 //#endif  // DROP_CGAL
00082 //      if (N > 450) {
00083 //      _strategy = N2MinHeapTiled;
00084 //    }
00085 //    else if (N > 55*max(0.5,min(1.0,_Rparam))) {// empirical scaling with R
00086 //      _strategy = N2Tiled;
00087 //    } else {
00088 //      _strategy = N2Plain;
00089 //    }
00090 //  }
00091 
00092 
00093   // automatically redefine the strategy according to N if that is
00094   // what the user requested -- transition points (and especially
00095   // their R-dependence) are based on empirical observations for a
00096   // R=0.4, 0.7 and 1.0, running on toth (3.4GHz, Pentium IV D [dual
00097   // core] with 2MB of cache).
00098   if (_strategy == Best) {
00099     int N = _jets.size();
00100     if (N > 6200/pow(_Rparam,2.0) 
00101         && jet_def.jet_finder() == cambridge_algorithm) {
00102       _strategy = NlnNCam;}
00103     else
00104 #ifndef DROP_CGAL
00105     if (N > 16000/pow(_Rparam,1.15)) {
00106       _strategy = NlnN; }   
00107     else                    
00108 #endif  // DROP_CGAL
00109       if (N > 450) {
00110       _strategy = N2MinHeapTiled;
00111     }
00112     else if (N > 55*max(0.5,min(1.0,_Rparam))) {// empirical scaling with R
00113       _strategy = N2Tiled;
00114     } else {
00115       _strategy = N2Plain;
00116     }
00117   }
00118 
00119 
00120   // run the code containing the selected strategy
00121   if (_strategy == NlnN || _strategy == NlnN3pi 
00122       || _strategy == NlnN4pi ) {
00123     this->_delaunay_cluster();
00124   } else if (_strategy ==  N3Dumb ) {
00125     this->_really_dumb_cluster();
00126   } else if (_strategy == N2Tiled) {
00127     this->_faster_tiled_N2_cluster();
00128   } else if (_strategy == N2PoorTiled) {
00129     this->_tiled_N2_cluster();
00130   } else if (_strategy == N2Plain) {
00131     this->_simple_N2_cluster();
00132   } else if (_strategy == N2MinHeapTiled) {
00133     this->_minheap_faster_tiled_N2_cluster();
00134   } else if (_strategy == NlnNCam4pi) {
00135     this->_CP2DChan_cluster();
00136   } else if (_strategy == NlnNCam2pi2R) {
00137     this->_CP2DChan_cluster_2pi2R();
00138   } else if (_strategy == NlnNCam) {
00139     this->_CP2DChan_cluster_2piMultD();
00140   } else {
00141     ostringstream err;
00142     err << "Unrecognised value for strategy: "<<_strategy;
00143     throw Error(err.str());
00144     //assert(false);
00145   }
00146 }

void fastjet::ClusterSequence::_initialise_tiles  )  [private]
 

Set up the tiles:

  • decide the range in eta
  • allocate the tiles
  • set up the cross-referencing info between tiles.

The neighbourhood of a tile is set up as follows

LRR LXR LLR

such that tiles is an array containing XLLLLRRRR with pointers | \ RH_tiles \ surrounding_tiles

with appropriate precautions when close to the edge of the tiled region.

Definition at line 85 of file ClusterSequence_TiledN2.cc.

References _jets, _n_tiles_phi, _Rparam, _tile_index(), _tile_size_eta, _tile_size_phi, _tiles, _tiles_eta_max, _tiles_eta_min, _tiles_ieta_max, _tiles_ieta_min, fastjet::ClusterSequence::Tile::begin_tiles, fastjet::ClusterSequence::Tile::end_tiles, fastjet::ClusterSequence::Tile::head, fastjet::ClusterSequence::Tile::RH_tiles, fastjet::ClusterSequence::Tile::surrounding_tiles, fastjet::ClusterSequence::Tile::tagged, and fastjet::twopi.

Referenced by _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), and _tiled_N2_cluster().

00085                                         {
00086 
00087   // first decide tile sizes
00088   _tile_size_eta = _Rparam;
00089   _n_tiles_phi   = int(floor(twopi/_Rparam));
00090   _tile_size_phi = twopi / _n_tiles_phi; // >= _Rparam and fits in 2pi
00091 
00092   // always include zero rapidity in the tiling region
00093   _tiles_eta_min = 0.0;
00094   _tiles_eta_max = 0.0;
00095   // but go no further than following
00096   const double maxrap = 7.0;
00097 
00098   // and find out how much further one should go
00099   for(unsigned int i = 0; i < _jets.size(); i++) {
00100     double eta = _jets[i].rap();
00101     // first check if eta is in range -- to avoid taking into account
00102     // very spurious rapidities due to particles with near-zero kt.
00103     if (abs(eta) < maxrap) {
00104       if (eta < _tiles_eta_min) {_tiles_eta_min = eta;}
00105       if (eta > _tiles_eta_max) {_tiles_eta_max = eta;}
00106     }
00107   }
00108 
00109   // now adjust the values
00110   _tiles_ieta_min = int(floor(_tiles_eta_min/_tile_size_eta));
00111   _tiles_ieta_max = int(floor( _tiles_eta_max/_tile_size_eta));
00112   _tiles_eta_min = _tiles_ieta_min * _tile_size_eta;
00113   _tiles_eta_max = _tiles_ieta_max * _tile_size_eta;
00114 
00115   // allocate the tiles
00116   _tiles.resize((_tiles_ieta_max-_tiles_ieta_min+1)*_n_tiles_phi);
00117 
00118   // now set up the cross-referencing between tiles
00119   for (int ieta = _tiles_ieta_min; ieta <= _tiles_ieta_max; ieta++) {
00120     for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
00121       Tile * tile = & _tiles[_tile_index(ieta,iphi)];
00122       // no jets in this tile yet
00123       tile->head = NULL; // first element of tiles points to itself
00124       tile->begin_tiles[0] =  tile;
00125       Tile ** pptile = & (tile->begin_tiles[0]);
00126       pptile++;
00127       //
00128       // set up L's in column to the left of X
00129       tile->surrounding_tiles = pptile;
00130       if (ieta > _tiles_ieta_min) {
00131         // with the itile subroutine, we can safely run tiles from
00132         // idphi=-1 to idphi=+1, because it takes care of
00133         // negative and positive boundaries
00134         for (int idphi = -1; idphi <=+1; idphi++) {
00135           *pptile = & _tiles[_tile_index(ieta-1,iphi+idphi)];
00136           pptile++;
00137         }       
00138       }
00139       // now set up last L (below X)
00140       *pptile = & _tiles[_tile_index(ieta,iphi-1)];
00141       pptile++;
00142       // set up first R (above X)
00143       tile->RH_tiles = pptile;
00144       *pptile = & _tiles[_tile_index(ieta,iphi+1)];
00145       pptile++;
00146       // set up remaining R's, to the right of X
00147       if (ieta < _tiles_ieta_max) {
00148         for (int idphi = -1; idphi <= +1; idphi++) {
00149           *pptile = & _tiles[_tile_index(ieta+1,iphi+idphi)];
00150           pptile++;
00151         }       
00152       }
00153       // now put semaphore for end tile
00154       tile->end_tiles = pptile;
00155       // finally make sure tiles are untagged
00156       tile->tagged = false;
00157     }
00158   }
00159 
00160 }

void fastjet::ClusterSequence::_minheap_faster_tiled_N2_cluster  )  [private]
 

run a tiled clustering, with our minheap for keeping track of the smallest dij

Definition at line 724 of file ClusterSequence_TiledN2.cc.

References _add_untagged_neighbours_to_tile_union(), _bj_diJ(), _bj_dist(), _bj_remove_from_tiles(), _do_iB_recombination_step(), _do_ij_recombination_step(), _initialise_tiles(), _invR2, _jets, fastjet::ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), fastjet::ClusterSequence::Tile::begin_tiles, fastjet::ClusterSequence::Tile::end_tiles, fastjet::ClusterSequence::Tile::head, fastjet::ClusterSequence::TiledJet::label_minheap_update_done(), fastjet::MinHeap::minloc(), fastjet::MinHeap::minval(), n_tile_neighbours, fastjet::ClusterSequence::TiledJet::next, fastjet::ClusterSequence::TiledJet::NN, fastjet::ClusterSequence::TiledJet::NN_dist, fastjet::MinHeap::remove(), fastjet::ClusterSequence::Tile::tagged, fastjet::ClusterSequence::TiledJet::tile_index, and fastjet::MinHeap::update().

Referenced by _initialise_and_run().

00724                                                        {
00725 
00726   _initialise_tiles();
00727 
00728   int n = _jets.size();
00729   TiledJet * briefjets = new TiledJet[n];
00730   TiledJet * jetA = briefjets, * jetB;
00731   TiledJet oldB;
00732   
00733 
00734   // will be used quite deep inside loops, but declare it here so that
00735   // memory (de)allocation gets done only once
00736   vector<int> tile_union(3*n_tile_neighbours);
00737   
00738   // initialise the basic jet info 
00739   for (int i = 0; i< n; i++) {
00740     _tj_set_jetinfo(jetA, i);
00741     //cout << i<<": "<<jetA->tile_index<<"\n";
00742     jetA++; // move on to next entry of briefjets
00743   }
00744   TiledJet * head = briefjets; // a nicer way of naming start
00745 
00746   // set up the initial nearest neighbour information
00747   vector<Tile>::const_iterator tile;
00748   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00749     // first do it on this tile
00750     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00751       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00752         double dist = _bj_dist(jetA,jetB);
00753         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00754         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00755       }
00756     }
00757     // then do it for RH tiles
00758     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00759       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00760         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00761           double dist = _bj_dist(jetA,jetB);
00762           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00763           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00764         }
00765       }
00766     }
00767     // no need to do it for LH tiles, since they are implicitly done
00768     // when we set NN for both jetA and jetB on the RH tiles.
00769   }
00770 
00771   
00775   //struct diJ_plus_link {
00776   //  double     diJ; // the distance
00777   //  TiledJet * jet; // the jet (i) for which we've found this distance
00778   //                  // (whose NN will the J).
00779   //};
00780   //diJ_plus_link * diJ = new diJ_plus_link[n];
00781   //jetA = head;
00782   //for (int i = 0; i < n; i++) {
00783   //  diJ[i].diJ = _bj_diJ(jetA); // kt distance * R^2
00784   //  diJ[i].jet = jetA;  // our compact diJ table will not be in            
00785   //  jetA->diJ_posn = i; // one-to-one corresp. with non-compact jets,
00786   //                      // so set up bi-directional correspondence here.
00787   //  jetA++; // have jetA follow i 
00788   //}
00789 
00790   vector<double> diJs(n);
00791   for (int i = 0; i < n; i++) {
00792     diJs[i] = _bj_diJ(&briefjets[i]);
00793     briefjets[i].label_minheap_update_done();
00794   }
00795   MinHeap minheap(diJs);
00796   // have a stack telling us which jets we'll have to update on the heap
00797   vector<TiledJet *> jets_for_minheap;
00798   jets_for_minheap.reserve(n); 
00799 
00800   // now run the recombination loop
00801   int history_location = n-1;
00802   while (n > 0) {
00803 
00804     double diJ_min = minheap.minval() *_invR2;
00805     jetA = head + minheap.minloc();
00806 
00807     // do the recombination between A and B
00808     history_location++;
00809     jetB = jetA->NN;
00810 
00811     if (jetB != NULL) {
00812       // jet-jet recombination
00813       // If necessary relabel A & B to ensure jetB < jetA, that way if
00814       // the larger of them == newtail then that ends up being jetA and 
00815       // the new jet that is added as jetB is inserted in a position that
00816       // has a future!
00817       if (jetA < jetB) {swap(jetA,jetB);}
00818 
00819       int nn; // new jet index
00820       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00821       
00822       // what was jetB will now become the new jet
00823       _bj_remove_from_tiles(jetA);
00824       oldB = * jetB;  // take a copy because we will need it...
00825       _bj_remove_from_tiles(jetB);
00826       _tj_set_jetinfo(jetB, nn); // cause jetB to become _jets[nn]
00827                                  // (also registers the jet in the tiling)
00828     } else {
00829       // jet-beam recombination
00830       // get the hist_index
00831       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00832       _bj_remove_from_tiles(jetA);
00833     }
00834 
00835     // remove the minheap entry for jetA
00836     minheap.remove(jetA-head);
00837 
00838     // first establish the set of tiles over which we are going to
00839     // have to run searches for updated and new nearest-neighbours --
00840     // basically a combination of vicinity of the tiles of the two old
00841     // and one new jet.
00842     int n_near_tiles = 0;
00843     _add_untagged_neighbours_to_tile_union(jetA->tile_index, 
00844                                            tile_union, n_near_tiles);
00845     if (jetB != NULL) {
00846       if (jetB->tile_index != jetA->tile_index) {
00847         _add_untagged_neighbours_to_tile_union(jetB->tile_index,
00848                                                tile_union,n_near_tiles);
00849       }
00850       if (oldB.tile_index != jetA->tile_index && 
00851           oldB.tile_index != jetB->tile_index) {
00852         _add_untagged_neighbours_to_tile_union(oldB.tile_index,
00853                                                tile_union,n_near_tiles);
00854       }
00855       // indicate that we'll have to update jetB in the minheap
00856       jetB->label_minheap_update_needed();
00857       jets_for_minheap.push_back(jetB);
00858     }
00859 
00860 
00861     // Initialise jetB's NN distance as well as updating it for 
00862     // other particles.
00863     // Run over all tiles in our union 
00864     for (int itile = 0; itile < n_near_tiles; itile++) {
00865       Tile * tile = &_tiles[tile_union[itile]];
00866       tile->tagged = false; // reset tag, since we're done with unions
00867       // run over all jets in the current tile
00868       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00869         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00870         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00871           jetI->NN_dist = _R2;
00872           jetI->NN      = NULL;
00873           // label jetI as needing heap action...
00874           if (!jetI->minheap_update_needed()) {
00875             jetI->label_minheap_update_needed();
00876             jets_for_minheap.push_back(jetI);}
00877           // now go over tiles that are neighbours of I (include own tile)
00878           for (Tile ** near_tile  = tile->begin_tiles; 
00879                        near_tile != tile->end_tiles; near_tile++) {
00880             // and then over the contents of that tile
00881             for (TiledJet * jetJ  = (*near_tile)->head; 
00882                             jetJ != NULL; jetJ = jetJ->next) {
00883               double dist = _bj_dist(jetI,jetJ);
00884               if (dist < jetI->NN_dist && jetJ != jetI) {
00885                 jetI->NN_dist = dist; jetI->NN = jetJ;
00886               }
00887             }
00888           }
00889         }
00890         // check whether new jetB is closer than jetI's current NN and
00891         // if jetI is closer than jetB's current (evolving) nearest
00892         // neighbour. Where relevant update things
00893         if (jetB != NULL) {
00894           double dist = _bj_dist(jetI,jetB);
00895           if (dist < jetI->NN_dist) {
00896             if (jetI != jetB) {
00897               jetI->NN_dist = dist;
00898               jetI->NN = jetB;
00899               // label jetI as needing heap action...
00900               if (!jetI->minheap_update_needed()) {
00901                 jetI->label_minheap_update_needed();
00902                 jets_for_minheap.push_back(jetI);}
00903             }
00904           }
00905           if (dist < jetB->NN_dist) {
00906             if (jetI != jetB) {
00907               jetB->NN_dist = dist;
00908               jetB->NN      = jetI;}
00909           }
00910         }
00911       }
00912     }
00913 
00914     // deal with jets whose minheap entry needs updating
00915     while (jets_for_minheap.size() > 0) {
00916       TiledJet * jetI = jets_for_minheap.back(); 
00917       jets_for_minheap.pop_back();
00918       minheap.update(jetI-head, _bj_diJ(jetI));
00919       jetI->label_minheap_update_done();
00920     }
00921     n--;
00922   }
00923 
00924   // final cleaning up;
00925   delete[] briefjets;
00926 }

void fastjet::ClusterSequence::_print_banner  )  [private]
 

for making sure the user knows what it is they're running...

Definition at line 153 of file ClusterSequence.cc.

References _first_time.

Referenced by _decant_options().

00153                                     {
00154 
00155   if (!_first_time) {return;}
00156   _first_time = false;
00157   
00158   cout << "#---------------------------------------------------------------------\n";
00159   cout << "#                        FastJet release 2.0                          \n";
00160   cout << "#            Written by Matteo Cacciari and Gavin Salam               \n"; 
00161   cout << "#            http://www.lpthe.jussieu.fr/~salam/fastjet               \n"; 
00162   cout << "#                                                                     \n";
00163   cout << "# Longitudinally invariant Kt Jet clustering, using the fast geometric\n";
00164   cout << "# algorithms of hep-ph/0512210 (please cite this if you use FastJet)  \n";
00165 #ifndef DROP_CGAL
00166   cout << "# This package makes use of the CGAL library: http://www.cgal.org/    \n";
00167 #endif  // DROP_CGAL
00168   cout << "# This package incorporates T.Chan's closest-pair algorithm, Proc. 13th     \n";
00169   cout << "# ACM-SIAM Symposium on Discrete Algorithms, pp.472-473, 2002\n";
00170   cout << "#---------------------------------------------------------------------\n";
00171 }

void fastjet::ClusterSequence::_print_tiles TiledJet briefjets  )  const [private]
 

output the contents of the tiles

Definition at line 209 of file ClusterSequence_TiledN2.cc.

References _tiles.

00209                                                               {
00210   for (vector<Tile>::const_iterator tile = _tiles.begin(); 
00211        tile < _tiles.end(); tile++) {
00212     cout << "Tile " << tile - _tiles.begin()<<" = ";
00213     vector<int> list;
00214     for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00215       list.push_back(jetI-briefjets);
00216       //cout <<" "<<jetI-briefjets;
00217     }
00218     sort(list.begin(),list.end());
00219     for (unsigned int i = 0; i < list.size(); i++) {cout <<" "<<list[i];}
00220     cout <<"\n";
00221   }
00222 }

void fastjet::ClusterSequence::_really_dumb_cluster  )  [private]
 

Run the clustering in a very slow variant of the N^3 algorithm.

The only thing this routine has going for it is that memory usage is O(N)!

Definition at line 50 of file ClusterSequence_DumbN3.cc.

References _do_iB_recombination_step(), _do_ij_recombination_step(), _invR2, _jets, BeamJet, and jet_scale_for_algorithm().

Referenced by _initialise_and_run().

00050                                             {
00051 
00052   // the array that will be overwritten here will be one
00053   // of pointers to jets.
00054   vector<PseudoJet *> jetsp(_jets.size());
00055   vector<int>         indices(_jets.size());
00056 
00057   for (size_t i = 0; i<_jets.size(); i++) {
00058     jetsp[i] = & _jets[i];
00059     indices[i] = i;
00060   }
00061 
00062   for (int n = jetsp.size(); n > 0; n--) {
00063     int ii, jj;
00064     // find smallest beam distance [remember jet_scale_for_algorithm 
00065     // will return kt^2 for the kt-algorithm and 1 for the Cambridge/Aachen]
00066     double ymin = jet_scale_for_algorithm(*(jetsp[0]));
00067     ii = 0; jj = -2;
00068     for (int i = 0; i < n; i++) {
00069       double yiB = jet_scale_for_algorithm(*(jetsp[i]));
00070       if (yiB < ymin) {
00071         ymin = yiB; ii = i; jj = -2;}
00072     }
00073 
00074     // find smallest distance between pair of jetsp
00075     for (int i = 0; i < n-1; i++) {
00076       for (int j = i+1; j < n; j++) {
00077         //double y = jetsp[i]->kt_distance(*jetsp[j])*_invR2;
00078         double y = min(jet_scale_for_algorithm(*(jetsp[i])), 
00079                        jet_scale_for_algorithm(*(jetsp[j])))
00080                     * jetsp[i]->plain_distance(*jetsp[j])*_invR2;
00081         if (y < ymin) {ymin = y; ii = i; jj = j;}
00082       }
00083     }
00084 
00085     // output recombination sequence
00086     // old "ktclus" way of labelling
00087     //cout <<n<< " "<< ii+1 << " with " << jj+1 << "; y = "<< ymin<<endl;
00088     // new delaunay way of labelling
00089     int jjindex_or_beam, iiindex;
00090     if (jj < 0) {jjindex_or_beam = BeamJet; iiindex = indices[ii];} 
00091     else {
00092       jjindex_or_beam = max(indices[ii],indices[jj]);
00093       iiindex =         min(indices[ii],indices[jj]);
00094     }
00095 
00096     // now recombine
00097     int newn = 2*jetsp.size() - n;
00098     if (jj >= 0) {
00099       // combine pair
00100       int nn; // new jet index
00101       _do_ij_recombination_step(jetsp[ii]-&_jets[0], 
00102                                 jetsp[jj]-&_jets[0], ymin, nn);
00103       
00104       // sort out internal bookkeeping
00105       jetsp[ii] = &_jets[nn];
00106       // have jj point to jet that was pointed at by n-1 
00107       // (since original jj is no longer current, so put n-1 into jj)
00108       jetsp[jj] = jetsp[n-1];
00109       indices[ii] = newn;
00110       indices[jj] = indices[n-1];
00111 
00112       //OBS_jets.push_back(*jetsp[ii] + *jetsp[jj]);
00113       //OBSjetsp[ii] = &_jets[_jets.size()-1];
00114       //OBS// have jj point to jet that was pointed at by n-1 
00115       //OBS// (since original jj is no longer current, so put n-1 into jj)
00116       //OBSjetsp[jj] = jetsp[n-1];
00117       //OBS
00118       //OBSindices[ii] = newn;
00119       //OBSindices[jj] = indices[n-1];
00120       //OBS_add_step_to_history(newn,iiindex,
00121       //OBS                           jjindex_or_beam,_jets.size()-1,ymin);
00122     } else {
00123       // combine ii with beam
00124       _do_iB_recombination_step(jetsp[ii]-&_jets[0], ymin);
00125       // put last jet (pointer) in place of ii (which has disappeared)
00126       jetsp[ii] = jetsp[n-1];
00127       indices[ii] = indices[n-1];
00128       //OBS_add_step_to_history(newn,iiindex,jjindex_or_beam,Invalid, ymin);
00129     }
00130   }
00131 
00132 }

void fastjet::ClusterSequence::_simple_N2_cluster  )  [private]
 

Order(N^2) clustering.

Definition at line 48 of file ClusterSequence_N2.cc.

References _bj_diJ(), _bj_dist(), _bj_set_jetinfo(), _bj_set_NN_crosscheck(), _bj_set_NN_nocross(), _do_iB_recombination_step(), _do_ij_recombination_step(), _invR2, _jets, fastjet::ClusterSequence::BriefJet::_jets_index, and fastjet::ClusterSequence::BriefJet::NN.

Referenced by _initialise_and_run().

00048                                          {
00049   int n = _jets.size();
00050   BriefJet * briefjets = new BriefJet[n];
00051   BriefJet * jetA = briefjets, * jetB;
00052   
00053   // initialise the basic jet info 
00054   for (int i = 0; i< n; i++) {
00055     _bj_set_jetinfo(jetA, i);
00056     jetA++; // move on to next entry of briefjets
00057   }
00058   BriefJet * tail = jetA; // a semaphore for the end of briefjets
00059   BriefJet * head = briefjets; // a nicer way of naming start
00060 
00061   // now initialise the NN distances: jetA will run from 1..n-1; and
00062   // jetB from 0..jetA-1
00063   for (jetA = head + 1; jetA != tail; jetA++) {
00064     // set NN info for jetA based on jets running from head..jetA-1,
00065     // checking in the process whether jetA itself is an undiscovered
00066     // NN of one of those jets.
00067     _bj_set_NN_crosscheck(jetA, head, jetA);
00068   }
00069 
00070 
00071   // now create the diJ (where J is i's NN) table -- remember that 
00072   // we differ from standard normalisation here by a factor of R2
00073   double * diJ = new double[n];
00074   jetA = head;
00075   for (int i = 0; i < n; i++) {
00076     diJ[i] = _bj_diJ(jetA);
00077     jetA++; // have jetA follow i
00078   }
00079 
00080   // now run the recombination loop
00081   int history_location = n-1;
00082   while (tail != head) {
00083 
00084     // find the minimum of the diJ on this round
00085     double diJ_min = diJ[0];
00086     int diJ_min_jet = 0;
00087     for (int i = 1; i < n; i++) {
00088       if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
00089     }
00090     
00091     // do the recombination between A and B
00092     history_location++;
00093     jetA = & briefjets[diJ_min_jet];
00094     jetB = jetA->NN;
00095     // put the normalisation back in
00096     diJ_min *= _invR2; 
00097     if (jetB != NULL) {
00098       // jet-jet recombination
00099       // If necessary relabel A & B to ensure jetB < jetA, that way if
00100       // the larger of them == newtail then that ends up being jetA and 
00101       // the new jet that is added as jetB is inserted in a position that
00102       // has a future!
00103       if (jetA < jetB) {swap(jetA,jetB);}
00104 
00105       int nn; // new jet index
00106       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00107 
00108       //OBS // get the two history indices
00109       //OBS int hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00110       //OBS int hist_b = _jets[jetB->_jets_index].cluster_hist_index();
00111       //OBS // create the recombined jet
00112       //OBS _jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
00113       //OBS int nn = _jets.size() - 1;
00114       //OBS _jets[nn].set_cluster_hist_index(history_location);
00115       //OBS // update history
00116       //OBS _add_step_to_history(history_location, 
00117       //OBS                min(hist_a,hist_b),max(hist_a,hist_b),
00118       //OBS                        nn, diJ_min);
00119       // what was jetB will now become the new jet
00120       _bj_set_jetinfo(jetB, nn);
00121     } else {
00122       // jet-beam recombination
00123       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00124       //OBS // get the hist_index
00125       //OBS int hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00126       //OBS _add_step_to_history(history_location,hist_a,BeamJet,Invalid,diJ_min); 
00127     }
00128 
00129     // now update our nearest neighbour info and diJ table
00130     // first reduce size of table
00131     tail--; n--;
00132     // Copy last jet contents and diJ info into position of jetA
00133     *jetA = *tail;
00134     diJ[jetA - head] = diJ[tail-head];
00135 
00136     // Initialise jetB's NN distance as well as updating it for 
00137     // other particles.
00138     // NB: by having different loops for jetB == or != NULL we could
00139     //     perhaps save a few percent (usually avoid one if inside loop),
00140     //     but will not do it for now because on laptop fluctuations are
00141     //     too large to reliably measure a few percent difference...
00142     for (BriefJet * jetI = head; jetI != tail; jetI++) {
00143       // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00144       if (jetI->NN == jetA || jetI->NN == jetB) {
00145         _bj_set_NN_nocross(jetI, head, tail);
00146         diJ[jetI-head] = _bj_diJ(jetI); // update diJ 
00147       } 
00148       // check whether new jetB is closer than jetI's current NN and
00149       // if need be update things
00150       if (jetB != NULL) {
00151         double dist = _bj_dist(jetI,jetB);
00152         if (dist < jetI->NN_dist) {
00153           if (jetI != jetB) {
00154             jetI->NN_dist = dist;
00155             jetI->NN = jetB;
00156             diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
00157           }
00158         }
00159         if (dist < jetB->NN_dist) {
00160           if (jetI != jetB) {
00161             jetB->NN_dist = dist;
00162             jetB->NN      = jetI;}
00163         }
00164       }
00165       // if jetI's NN is the new tail then relabel it so that it becomes jetA
00166       if (jetI->NN == tail) {jetI->NN = jetA;}
00167     }
00168 
00169     
00170     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
00171 
00172 
00173   }
00174   
00175 
00176   // final cleaning up;
00177   delete[] diJ;
00178   delete[] briefjets;
00179 }

int fastjet::ClusterSequence::_tile_index const double &  eta,
const double &  phi
const [private]
 

return the tile index corresponding to the given eta,phi point

Definition at line 165 of file ClusterSequence_TiledN2.cc.

References _n_tiles_phi, _tile_size_eta, _tile_size_phi, _tiles_eta_max, _tiles_eta_min, _tiles_ieta_max, _tiles_ieta_min, and fastjet::twopi.

00165                                                                              {
00166   int ieta, iphi;
00167   if      (eta <= _tiles_eta_min) {ieta = 0;}
00168   else if (eta >= _tiles_eta_max) {ieta = _tiles_ieta_max-_tiles_ieta_min;}
00169   else {
00170     //ieta = int(floor((eta - _tiles_eta_min) / _tile_size_eta));
00171     ieta = int(((eta - _tiles_eta_min) / _tile_size_eta));
00172     // following needed in case of rare but nasty rounding errors
00173     if (ieta > _tiles_ieta_max-_tiles_ieta_min) {
00174       ieta = _tiles_ieta_max-_tiles_ieta_min;} 
00175   }
00176   // allow for some extent of being beyond range in calculation of phi
00177   // as well
00178   //iphi = (int(floor(phi/_tile_size_phi)) + _n_tiles_phi) % _n_tiles_phi;
00179   // with just int and no floor, things run faster but beware
00180   iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
00181   return (iphi + ieta * _n_tiles_phi);
00182 }

int fastjet::ClusterSequence::_tile_index int  ieta,
int  iphi
const [inline, private]
 

Definition at line 443 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tj_set_jetinfo().

00443                                                     {
00444     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00445     // before performing modulo operation
00446     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00447                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00448   }

void fastjet::ClusterSequence::_tiled_N2_cluster  )  [private]
 

run a tiled clustering

Definition at line 264 of file ClusterSequence_TiledN2.cc.

References _add_neighbours_to_tile_union(), _bj_diJ(), _bj_dist(), _bj_remove_from_tiles(), _do_iB_recombination_step(), _do_ij_recombination_step(), _initialise_tiles(), _invR2, _jets, fastjet::ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), fastjet::ClusterSequence::Tile::begin_tiles, fastjet::ClusterSequence::Tile::end_tiles, fastjet::ClusterSequence::Tile::head, n_tile_neighbours, fastjet::ClusterSequence::TiledJet::next, fastjet::ClusterSequence::TiledJet::NN, fastjet::ClusterSequence::TiledJet::NN_dist, fastjet::ClusterSequence::TiledJet::previous, and fastjet::ClusterSequence::TiledJet::tile_index.

Referenced by _initialise_and_run().

00264                                         {
00265 
00266   _initialise_tiles();
00267 
00268   int n = _jets.size();
00269   TiledJet * briefjets = new TiledJet[n];
00270   TiledJet * jetA = briefjets, * jetB;
00271   TiledJet oldB;
00272   
00273 
00274   // will be used quite deep inside loops, but declare it here so that
00275   // memory (de)allocation gets done only once
00276   vector<int> tile_union(3*n_tile_neighbours);
00277   
00278   // initialise the basic jet info 
00279   for (int i = 0; i< n; i++) {
00280     _tj_set_jetinfo(jetA, i);
00281     //cout << i<<": "<<jetA->tile_index<<"\n";
00282     jetA++; // move on to next entry of briefjets
00283   }
00284   TiledJet * tail = jetA; // a semaphore for the end of briefjets
00285   TiledJet * head = briefjets; // a nicer way of naming start
00286 
00287   // set up the initial nearest neighbour information
00288   vector<Tile>::const_iterator tile;
00289   for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
00290     // first do it on this tile
00291     for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00292       for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
00293         double dist = _bj_dist(jetA,jetB);
00294         if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00295         if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00296       }
00297     }
00298     // then do it for RH tiles
00299     for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
00300       for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
00301         for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
00302           double dist = _bj_dist(jetA,jetB);
00303           if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
00304           if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
00305         }
00306       }
00307     }
00308   }
00309   
00310   // now create the diJ (where J is i's NN) table -- remember that 
00311   // we differ from standard normalisation here by a factor of R2
00312   double * diJ = new double[n];
00313   jetA = head;
00314   for (int i = 0; i < n; i++) {
00315     diJ[i] = _bj_diJ(jetA);
00316     jetA++; // have jetA follow i
00317   }
00318 
00319   // now run the recombination loop
00320   int history_location = n-1;
00321   while (tail != head) {
00322 
00323     // find the minimum of the diJ on this round
00324     double diJ_min = diJ[0];
00325     int diJ_min_jet = 0;
00326     for (int i = 1; i < n; i++) {
00327       if (diJ[i] < diJ_min) {diJ_min_jet = i; diJ_min  = diJ[i];}
00328     }
00329 
00330     // do the recombination between A and B
00331     history_location++;
00332     jetA = & briefjets[diJ_min_jet];
00333     jetB = jetA->NN;
00334     // put the normalisation back in
00335     diJ_min *= _invR2; 
00336 
00337     //if (n == 19) {cout << "Hello "<<jetA-head<<" "<<jetB-head<<"\n";}
00338 
00339     //cout <<" WILL RECOMBINE "<< jetA-briefjets<<" "<<jetB-briefjets<<"\n";
00340 
00341     if (jetB != NULL) {
00342       // jet-jet recombination
00343       // If necessary relabel A & B to ensure jetB < jetA, that way if
00344       // the larger of them == newtail then that ends up being jetA and 
00345       // the new jet that is added as jetB is inserted in a position that
00346       // has a future!
00347       if (jetA < jetB) {swap(jetA,jetB);}
00348 
00349       int nn; // new jet index
00350       _do_ij_recombination_step(jetA->_jets_index, jetB->_jets_index, diJ_min, nn);
00351 
00352       //OBS// get the two history indices
00353       //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00354       //OBSint hist_b = _jets[jetB->_jets_index].cluster_hist_index();
00355       //OBS// create the recombined jet
00356       //OBS_jets.push_back(_jets[jetA->_jets_index] + _jets[jetB->_jets_index]);
00357       //OBSint nn = _jets.size() - 1;
00358       //OBS_jets[nn].set_cluster_hist_index(history_location);
00359       //OBS// update history
00360       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<jetB-head<<"; ";
00361       //OBS_add_step_to_history(history_location, 
00362       //OBS                min(hist_a,hist_b),max(hist_a,hist_b),
00363       //OBS                        nn, diJ_min);
00364 
00365       // what was jetB will now become the new jet
00366       _bj_remove_from_tiles(jetA);
00367       oldB = * jetB;  // take a copy because we will need it...
00368       _bj_remove_from_tiles(jetB);
00369       _tj_set_jetinfo(jetB, nn); // also registers the jet in the tiling
00370     } else {
00371       // jet-beam recombination
00372       _do_iB_recombination_step(jetA->_jets_index, diJ_min);
00373             
00374       //OBS// get the hist_index
00375       //OBSint hist_a = _jets[jetA->_jets_index].cluster_hist_index();
00376       //OBS//cout <<n-1<<" "<<jetA-head<<" "<<-1<<"; ";
00377       //OBS_add_step_to_history(history_location,hist_a,BeamJet,Invalid,diJ_min); 
00378       _bj_remove_from_tiles(jetA);
00379     }
00380 
00381     // first establish the set of tiles over which we are going to 
00382     // have to run searches for updated and new nearest-neighbours
00383     int n_near_tiles = 0;
00384     _add_neighbours_to_tile_union(jetA->tile_index, tile_union, n_near_tiles);
00385     if (jetB != NULL) {
00386       bool sort_it = false;
00387       if (jetB->tile_index != jetA->tile_index) {
00388         sort_it = true;
00389         _add_neighbours_to_tile_union(jetB->tile_index,tile_union,n_near_tiles);
00390       }
00391       if (oldB.tile_index != jetA->tile_index && 
00392           oldB.tile_index != jetB->tile_index) {
00393         sort_it = true;
00394         _add_neighbours_to_tile_union(oldB.tile_index,tile_union,n_near_tiles);
00395       }
00396 
00397       if (sort_it) {
00398         // sort the tiles before then compressing the list
00399         sort(tile_union.begin(), tile_union.begin()+n_near_tiles);
00400         // and now condense the list
00401         int nnn = 1;
00402         for (int i = 1; i < n_near_tiles; i++) {
00403           if (tile_union[i] != tile_union[nnn-1]) {
00404             tile_union[nnn] = tile_union[i]; 
00405             nnn++;
00406           }
00407         }
00408         n_near_tiles = nnn;
00409       }
00410     }
00411 
00412     // now update our nearest neighbour info and diJ table
00413     // first reduce size of table
00414     tail--; n--;
00415     if (jetA == tail) {
00416       // there is nothing to be done
00417     } else {
00418       // Copy last jet contents and diJ info into position of jetA
00419       *jetA = *tail;
00420       diJ[jetA - head] = diJ[tail-head];
00421       // IN the tiling fix pointers to tail and turn them into
00422       // pointers to jetA (from predecessors, successors and the tile
00423       // head if need be)
00424       if (jetA->previous == NULL) {
00425         _tiles[jetA->tile_index].head = jetA;
00426       } else {
00427         jetA->previous->next = jetA;
00428       }
00429       if (jetA->next != NULL) {jetA->next->previous = jetA;}
00430     }
00431 
00432     // Initialise jetB's NN distance as well as updating it for 
00433     // other particles.
00434     for (int itile = 0; itile < n_near_tiles; itile++) {
00435       Tile * tile = &_tiles[tile_union[itile]];
00436       for (TiledJet * jetI = tile->head; jetI != NULL; jetI = jetI->next) {
00437         // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
00438         if (jetI->NN == jetA || (jetI->NN == jetB && jetB != NULL)) {
00439           jetI->NN_dist = _R2;
00440           jetI->NN      = NULL;
00441           // now go over tiles that are neighbours of I (include own tile)
00442           for (Tile ** near_tile  = tile->begin_tiles; 
00443                        near_tile != tile->end_tiles; near_tile++) {
00444             // and then over the contents of that tile
00445             for (TiledJet * jetJ  = (*near_tile)->head; 
00446                             jetJ != NULL; jetJ = jetJ->next) {
00447               double dist = _bj_dist(jetI,jetJ);
00448               if (dist < jetI->NN_dist && jetJ != jetI) {
00449                 jetI->NN_dist = dist; jetI->NN = jetJ;
00450               }
00451             }
00452           }
00453           diJ[jetI-head] = _bj_diJ(jetI); // update diJ 
00454         }
00455         // check whether new jetB is closer than jetI's current NN and
00456         // if need to update things
00457         if (jetB != NULL) {
00458           double dist = _bj_dist(jetI,jetB);
00459           if (dist < jetI->NN_dist) {
00460             if (jetI != jetB) {
00461               jetI->NN_dist = dist;
00462               jetI->NN = jetB;
00463               diJ[jetI-head] = _bj_diJ(jetI); // update diJ...
00464             }
00465           }
00466           if (dist < jetB->NN_dist) {
00467             if (jetI != jetB) {
00468               jetB->NN_dist = dist;
00469               jetB->NN      = jetI;}
00470           }
00471         }
00472       }
00473     }
00474 
00475 
00476     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
00477     //cout << n<<" "<<briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
00478 
00479     // remember to update pointers to tail
00480     for (Tile ** near_tile = _tiles[tail->tile_index].begin_tiles; 
00481                  near_tile!= _tiles[tail->tile_index].end_tiles; near_tile++){
00482       // and then the contents of that tile
00483       for (TiledJet * jetJ = (*near_tile)->head; 
00484                      jetJ != NULL; jetJ = jetJ->next) {
00485         if (jetJ->NN == tail) {jetJ->NN = jetA;}
00486       }
00487     }
00488 
00489     //for (int i = 0; i < n; i++) {
00490     //  if (briefjets[i].NN-briefjets >= n && briefjets[i].NN != NULL) {cout <<"YOU MUST BE CRAZY for n ="<<n<<", i = "<<i<<", NN = "<<briefjets[i].NN-briefjets<<"\n";}
00491     //}
00492 
00493 
00494     if (jetB != NULL) {diJ[jetB-head] = _bj_diJ(jetB);}
00495     //cout << briefjets[95].NN-briefjets<<" "<<briefjets[95].NN_dist <<"\n";
00496 
00497   }
00498 
00499   // final cleaning up;
00500   delete[] diJ;
00501   delete[] briefjets;
00502 }

void fastjet::ClusterSequence::_tj_set_jetinfo TiledJet *const   jet,
const int  _jets_index
[inline, private]
 

Definition at line 188 of file ClusterSequence_TiledN2.cc.

References _tile_index(), _tiles, and fastjet::ClusterSequence::Tile::head.

Referenced by _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), and _tiled_N2_cluster().

00189                                                                      {
00190   // first call the generic setup
00191   _bj_set_jetinfo<>(jet, _jets_index);
00192 
00193   // Then do the setup specific to the tiled case.
00194 
00195   // Find out which tile it belonds to
00196   jet->tile_index = _tile_index(jet->eta, jet->phi);
00197 
00198   // Insert it into the tile's linked list of jets
00199   Tile * tile = &_tiles[jet->tile_index];
00200   jet->previous   = NULL;
00201   jet->next       = tile->head;
00202   if (jet->next != NULL) {jet->next->previous = jet;}
00203   tile->head      = jet;
00204 }

template<class L>
void fastjet::ClusterSequence::_transfer_input_jets const std::vector< L > &  pseudojets  )  [protected]
 

transfer the vector<L> of input jets into our own vector<PseudoJet> _jets (with some reserved space for future growth).

Definition at line 474 of file ClusterSequence.hh.

References _jets.

Referenced by ClusterSequence().

00475                                                                         {
00476 
00477   // this will ensure that we can point to jets without difficulties
00478   // arising.
00479   _jets.reserve(pseudojets.size()*2);
00480 
00481   // insert initial jets this way so that any type L that can be
00482   // converted to a pseudojet will work fine (basically PseudoJet
00483   // and any type that has [] subscript access to the momentum
00484   // components, such as CLHEP HepLorentzVector).
00485   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00486     _jets.push_back(pseudojets[i]);}
00487   
00488 }

void fastjet::ClusterSequence::add_constituents const PseudoJet jet,
std::vector< PseudoJet > &  subjet_vector
const
 

add on to subjet_vector the subjets of jet.

Definition at line 401 of file ClusterSequence.cc.

References _history, _jets, BeamJet, fastjet::PseudoJet::cluster_hist_index(), and InexistentParent.

Referenced by constituents().

00402                                                                            {
00403   // find out position in cluster history
00404   int i = jet.cluster_hist_index();
00405   int parent1 = _history[i].parent1;
00406   int parent2 = _history[i].parent2;
00407 
00408   if (parent1 == InexistentParent) {
00409     // It is an original particle (labelled by its parent having value
00410     // InexistentParent), therefore add it on to the subjet vector
00411     subjet_vector.push_back(jet);
00412     return;
00413   } 
00414 
00415   // add parent 1
00416   add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
00417 
00418   // see if parent2 is a real jet; if it is then add its constituents
00419   if (parent2 != BeamJet) {
00420     add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
00421   }
00422 }

vector< PseudoJet > fastjet::ClusterSequence::constituents const PseudoJet jet  )  const
 

return a vector of the particles that make up jet

Definition at line 392 of file ClusterSequence.cc.

References add_constituents().

Referenced by main(), and print_jets().

00392                                                                             {
00393   vector<PseudoJet> subjets;
00394   add_constituents(jet, subjets);
00395   return subjets;
00396 }

double fastjet::ClusterSequence::exclusive_dmerge const int &  njets  )  const
 

return the dmin corresponding to the recombination that went from n+1 to n jets

Definition at line 371 of file ClusterSequence.cc.

References _history, and _initial_n.

00371                                                                  {
00372   assert(njets > 0);
00373   if (njets >= _initial_n) {return 0.0;}
00374   return _history[2*_initial_n-njets-1].dij;
00375 }

double fastjet::ClusterSequence::exclusive_dmerge_max const int &  njets  )  const
 

return the maximum of the dmin encountered during all recombinations up to the one that led to an n-jet final state; identical to exclusive_dmerge, except in cases where the dmin do not increase monotonically.

Definition at line 383 of file ClusterSequence.cc.

References _history, and _initial_n.

00383                                                                      {
00384   assert(njets > 0);
00385   if (njets >= _initial_n) {return 0.0;}
00386   return _history[2*_initial_n-njets-1].max_dij_so_far;
00387 }

vector< PseudoJet > fastjet::ClusterSequence::exclusive_jets const int &  njets  )  const
 

return a vector of all jets when the event is clustered (in the exclusive sense) to exactly njets.

Definition at line 318 of file ClusterSequence.cc.

References _history, _initial_n, _jets, and jets().

00318                                                                           {
00319 
00320   // make sure the user does not ask for more than jets than there
00321   // were particles in the first place.
00322   assert (njets <= _initial_n);
00323 
00324   // calculate the point where we have to stop the clustering.
00325   // relation between stop_point, njets assumes one extra jet disappears
00326   // at each clustering.
00327   int stop_point = 2*_initial_n - njets;
00328 
00329   // some sanity checking to make sure that e+e- does not give us
00330   // surprises (should we ever implement e+e-)...
00331   if (2*_initial_n != static_cast<int>(_history.size())) {
00332     ostringstream err;
00333     err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00334     throw Error(err.str());
00335     //assert(false);
00336   }
00337 
00338   // now go forwards and reconstitute the jets that we have --
00339   // basically for any history element, see if the parent jets to
00340   // which it refers were created before the stopping point -- if they
00341   // were then add them to the list, otherwise they are subsequent
00342   // recombinations of the jets that we are looking for.
00343   vector<PseudoJet> jets;
00344   for (unsigned int i = stop_point; i < _history.size(); i++) {
00345     int parent1 = _history[i].parent1;
00346     if (parent1 < stop_point) {
00347       jets.push_back(_jets[_history[parent1].jetp_index]);
00348     }
00349     int parent2 = _history[i].parent2;
00350     if (parent2 < stop_point && parent2 > 0) {
00351       jets.push_back(_jets[_history[parent2].jetp_index]);
00352     }
00353     
00354   }
00355 
00356   // sanity check...
00357   if (static_cast<int>(jets.size()) != njets) {
00358     ostringstream err;
00359     err << "ClusterSequence::exclusive_jets: size of returned vector ("
00360          <<jets.size()<<") does not coincide with requested number of jets ("
00361          <<njets<<")";
00362     throw Error(err.str());
00363   }
00364 
00365   return jets;
00366 }

vector< PseudoJet > fastjet::ClusterSequence::exclusive_jets const double &  dcut  )  const
 

return a vector of all jets (in the sense of the exclusive algorithm) that would be obtained when running the algorithm with the given dcut.

Definition at line 310 of file ClusterSequence.cc.

References n_exclusive_jets().

Referenced by main().

00310                                                                             {
00311   int njets = n_exclusive_jets(dcut);
00312   return exclusive_jets(njets);
00313 }

const std::vector< ClusterSequence::history_element > & fastjet::ClusterSequence::history  )  const [inline]
 

allow the user to access the history in this raw manner (see above for motivation).

Definition at line 527 of file ClusterSequence.hh.

References _history.

Referenced by fastjet::ClusterSequenceActiveArea::_transfer_areas(), fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history(), and main().

00527                                                                                          {
00528   return _history;
00529 }

vector< PseudoJet > fastjet::ClusterSequence::inclusive_jets const double &  ptmin = 0.0  )  const
 

return a vector of all jets (in the sense of the inclusive algorithm) with pt >= ptmin.

Time taken should be of the order of the number of jets returned.

Definition at line 256 of file ClusterSequence.cc.

References _history, _jet_finder, _jets, BeamJet, fastjet::cambridge_algorithm, jets(), fastjet::kt_algorithm, and fastjet::PseudoJet::perp2().

Referenced by main(), fastjet::ClusterSequenceActiveArea::parabolic_pt_per_unit_area(), and fastjet::ClusterSequenceActiveArea::pt_per_unit_area().

00256                                                                             {
00257   double dcut = ptmin*ptmin;
00258   int i = _history.size() - 1; // last jet
00259   vector<PseudoJet> jets;
00260   if (_jet_finder == kt_algorithm) {
00261     while (i >= 0) {
00262       // with our specific definition of dij and diB (i.e. R appears only in 
00263       // dij), then dij==diB is the same as the jet.perp2() and we can exploit
00264       // this in selecting the jets...
00265       if (_history[i].max_dij_so_far < dcut) {break;}
00266       if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00267         // for beam jets
00268         int parent1 = _history[i].parent1;
00269         jets.push_back(_jets[_history[parent1].jetp_index]);}
00270       i--;
00271     }
00272   } else if (_jet_finder == cambridge_algorithm) {
00273     while (i >= 0) {
00274       // inclusive jets are all at end of clustering sequence in the
00275       // Cambridge algorithm -- so if we find a non-exclusive jet, then
00276       // we can exit
00277       if (_history[i].parent2 != BeamJet) {break;}
00278       int parent1 = _history[i].parent1;
00279       const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00280       if (jet.perp2() >= dcut) {jets.push_back(jet);}
00281       i--;
00282     }
00283   } else {throw Error("Unrecognized jet algorithm");}
00284   return jets;
00285 }

double fastjet::ClusterSequence::jet_scale_for_algorithm const PseudoJet jet  )  const [inline]
 

returns the scale associated with a jet as required for this clustering algorithm (kt^2 for the kt-algorithm, 1 for the Cambridge algorithm).

[May become virtual at some point]

Definition at line 535 of file ClusterSequence.hh.

References _jet_finder, fastjet::cambridge_algorithm, fastjet::PseudoJet::kt2(), and fastjet::kt_algorithm.

Referenced by _add_ktdistance_to_map(), _bj_set_jetinfo(), and _really_dumb_cluster().

00536                                                                {
00537   if (_jet_finder == kt_algorithm)             {return jet.kt2();}
00538   else if (_jet_finder == cambridge_algorithm) {return 1.0;}
00539   else {throw Error("Unrecognised jet finder");}
00540 }

const std::vector< PseudoJet > & fastjet::ClusterSequence::jets  )  const [inline]
 

allow the user to access the jets in this raw manner (needed because we don't seem to be able to access protected elements of the class for an object that is not "this" (at least in case where "this" is of a slightly different kind from the object, both derived from ClusterSequence).

Definition at line 523 of file ClusterSequence.hh.

References _jets.

Referenced by fastjet::ClusterSequenceActiveArea::_transfer_areas(), exclusive_jets(), and inclusive_jets().

00523                                                                  {
00524   return _jets;
00525 }

int fastjet::ClusterSequence::n_exclusive_jets const double &  dcut  )  const
 

return the number of jets (in the sense of the exclusive algorithm) that would be obtained when running the algorithm with the given dcut.

Definition at line 291 of file ClusterSequence.cc.

References _history, and _initial_n.

Referenced by exclusive_jets().

00291                                                                 {
00292 
00293   // first locate the point where clustering would have stopped (i.e. the
00294   // first time max_dij_so_far > dcut)
00295   int i = _history.size() - 1; // last jet
00296   while (i >= 0) {
00297     if (_history[i].max_dij_so_far <= dcut) {break;}
00298     i--;
00299   }
00300   int stop_point = i + 1;
00301   // relation between stop_point, njets assumes one extra jet disappears
00302   // at each clustering.
00303   int njets = 2*_initial_n - stop_point;
00304   return njets;
00305 }

unsigned int fastjet::ClusterSequence::n_particles  )  const [inline]
 

returns the number of particles that were provided to the clustering algorithm (helps the user find their way around the history and jets objects if they weren't paying attention beforehand).

Definition at line 531 of file ClusterSequence.hh.

References _initial_n.

Referenced by fastjet::ClusterSequenceActiveArea::_transfer_areas(), and unique_history_order().

00531 {return _initial_n;}

static void fastjet::ClusterSequence::set_jet_finder JetFinder  jet_finder  )  [inline, static]
 

set the default (static) jet finder across all current and future ClusterSequence objects -- deprecated.

Definition at line 152 of file ClusterSequence.hh.

00152 {_default_jet_finder = jet_finder;};

string fastjet::ClusterSequence::strategy_string  )  const
 

Definition at line 222 of file ClusterSequence.cc.

References _strategy, fastjet::N2MinHeapTiled, fastjet::N2Plain, fastjet::N2PoorTiled, fastjet::N2Tiled, fastjet::N3Dumb, fastjet::NlnN, fastjet::NlnN3pi, fastjet::NlnN4pi, fastjet::NlnNCam, fastjet::NlnNCam2pi2R, and fastjet::NlnNCam4pi.

Referenced by _delaunay_cluster(), and main().

00222                                                 {
00223   string strategy;
00224   switch(_strategy) {
00225   case NlnN:
00226     strategy = "NlnN"; break;
00227   case NlnN3pi:
00228     strategy = "NlnN3pi"; break;
00229   case NlnN4pi:
00230     strategy = "NlnN4pi"; break;
00231   case N2Plain:
00232     strategy = "N2Plain"; break;
00233   case N2Tiled:
00234     strategy = "N2Tiled"; break;
00235   case N2MinHeapTiled:
00236     strategy = "N2MinHeapTiled"; break;
00237   case N2PoorTiled:
00238     strategy = "N2PoorTiled"; break;
00239   case N3Dumb:
00240     strategy = "N3Dumb"; break;
00241   case NlnNCam4pi:
00242     strategy = "NlnNCam4pi"; break;
00243   case NlnNCam2pi2R:
00244     strategy = "NlnNCam2pi2R"; break;
00245   case NlnNCam:
00246     strategy = "NlnNCam"; break; // 2piMultD
00247   default:
00248     strategy = "Unrecognized";
00249   }
00250   return strategy;
00251 }  

Strategy fastjet::ClusterSequence::strategy_used  )  const [inline]
 

return the enum value of the strategy used to cluster the event

Definition at line 136 of file ClusterSequence.hh.

Referenced by fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history().

00136 {return _strategy;};

vector< int > fastjet::ClusterSequence::unique_history_order  )  const
 

routine that returns a an order in which to read the history such that clusterings that lead to identical jet compositions but different histories (because of degeneracies in the clustering order) will have matching constituents for each matching entry in the unique_history_order.

The order has the property that an entry's parents will always appear prior to that entry itself.

Roughly speaking the order is such that we first provide all steps that lead to the final jet containing particle 1; then we have the steps that lead to reconstruction of the jet containing the next-lowest-numbered unclustered particle, etc... [see GPS CCN28-12 for more info -- of course a full explanation here would be better...]

Definition at line 472 of file ClusterSequence.cc.

References _extract_tree_children(), _history, and n_particles().

Referenced by fastjet::ClusterSequenceActiveArea::_initialise_and_run_AA(), fastjet::ClusterSequenceActiveArea::_transfer_areas(), and main().

00472                                                         {
00473 
00474   // first construct an array that will tell us the lowest constituent
00475   // of a given jet -- this will always be one of the original
00476   // particles, whose order is well defined and so will help us to
00477   // follow the tree in a unique manner.
00478   valarray<int> lowest_constituent(_history.size());
00479   int hist_n = _history.size();
00480   lowest_constituent = hist_n; // give it a large number
00481   for (int i = 0; i < hist_n; i++) {
00482     // sets things up for the initial partons
00483     lowest_constituent[i] = min(lowest_constituent[i],i); 
00484     // propagates them through to the children of this parton
00485     if (_history[i].child > 0) lowest_constituent[_history[i].child] 
00486       = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00487   }
00488 
00489   // establish an array for what we have and have not extracted so far
00490   valarray<bool> extracted(_history.size()); extracted = false;
00491   vector<int> unique_tree;
00492   unique_tree.reserve(_history.size());
00493 
00494   // now work our way through the tree
00495   for (unsigned i = 0; i < n_particles(); i++) {
00496     if (!extracted[i]) {
00497       unique_tree.push_back(i);
00498       extracted[i] = true;
00499       _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
00500     }
00501   }
00502 
00503   return unique_tree;
00504 }


Member Data Documentation

JetFinder fastjet::ClusterSequence::_default_jet_finder = kt_algorithm [static, protected]
 

Definition at line 46 of file ClusterSequence.cc.

Referenced by _initialise_and_run().

bool fastjet::ClusterSequence::_first_time = true [static, private]
 

will be set by default to be true for the first run

Definition at line 150 of file ClusterSequence.cc.

Referenced by _print_banner().

std::vector<history_element> fastjet::ClusterSequence::_history [protected]
 

this vector will contain the branching history; for each stage, _history[i].jetp_index indicates where to look in the _jets vector to get the physical PseudoJet.

Definition at line 277 of file ClusterSequence.hh.

Referenced by _add_step_to_history(), _CP2DChan_limited_cluster(), _do_Cambridge_inclusive_jets(), _do_iB_recombination_step(), _do_ij_recombination_step(), _extract_tree_children(), _extract_tree_parents(), _fill_initial_history(), fastjet::ClusterSequenceActiveAreaExplicitGhosts::_post_process(), fastjet::ClusterSequenceActiveArea::_transfer_areas(), fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history(), add_constituents(), exclusive_dmerge(), exclusive_dmerge_max(), exclusive_jets(), history(), inclusive_jets(), n_exclusive_jets(), and unique_history_order().

int fastjet::ClusterSequence::_initial_n [protected]
 

Definition at line 280 of file ClusterSequence.hh.

Referenced by _CP2DChan_limited_cluster(), _fill_initial_history(), fastjet::ClusterSequenceActiveAreaExplicitGhosts::_post_process(), fastjet::ClusterSequenceActiveArea::_transfer_areas(), exclusive_dmerge(), exclusive_dmerge_max(), exclusive_jets(), n_exclusive_jets(), and n_particles().

double fastjet::ClusterSequence::_invR2 [protected]
 

Definition at line 281 of file ClusterSequence.hh.

Referenced by _add_ktdistance_to_map(), _CP2DChan_cluster(), _CP2DChan_limited_cluster(), _decant_options(), _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), _really_dumb_cluster(), _simple_N2_cluster(), and _tiled_N2_cluster().

JetDefinition fastjet::ClusterSequence::_jet_def [protected]
 

Definition at line 227 of file ClusterSequence.hh.

Referenced by _decant_options().

JetFinder fastjet::ClusterSequence::_jet_finder [protected]
 

Definition at line 283 of file ClusterSequence.hh.

Referenced by _CP2DChan_cluster(), _CP2DChan_cluster_2pi2R(), _decant_options(), inclusive_jets(), and jet_scale_for_algorithm().

std::vector<PseudoJet> fastjet::ClusterSequence::_jets [protected]
 

This contains the physical PseudoJets; for each PseudoJet one can find the corresponding position in the _history by looking at _jets[i].cluster_hist_index().

Definition at line 271 of file ClusterSequence.hh.

Referenced by fastjet::ClusterSequenceActiveAreaExplicitGhosts::_add_ghosts(), _add_ktdistance_to_map(), _add_step_to_history(), _bj_set_jetinfo(), _CP2DChan_cluster(), _CP2DChan_limited_cluster(), _delaunay_cluster(), _do_iB_recombination_step(), _do_ij_recombination_step(), _faster_tiled_N2_cluster(), _fill_initial_history(), _initialise_and_run(), fastjet::ClusterSequenceActiveArea::_initialise_and_run_AA(), _initialise_tiles(), _minheap_faster_tiled_N2_cluster(), fastjet::ClusterSequenceActiveAreaExplicitGhosts::_post_process(), _really_dumb_cluster(), _simple_N2_cluster(), _tiled_N2_cluster(), fastjet::ClusterSequenceActiveArea::_transfer_areas(), _transfer_input_jets(), add_constituents(), exclusive_jets(), inclusive_jets(), and jets().

int fastjet::ClusterSequence::_n_tiles_phi [private]
 

Definition at line 439 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double fastjet::ClusterSequence::_R2 [protected]
 

Definition at line 281 of file ClusterSequence.hh.

Referenced by _bj_set_jetinfo(), _bj_set_NN_crosscheck(), _bj_set_NN_nocross(), _decant_options(), _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), and _tiled_N2_cluster().

double fastjet::ClusterSequence::_Rparam [protected]
 

Definition at line 281 of file ClusterSequence.hh.

Referenced by _CP2DChan_cluster_2pi2R(), _CP2DChan_cluster_2piMultD(), _decant_options(), _delaunay_cluster(), _initialise_and_run(), and _initialise_tiles().

Strategy fastjet::ClusterSequence::_strategy [protected]
 

Definition at line 282 of file ClusterSequence.hh.

Referenced by _decant_options(), _delaunay_cluster(), _initialise_and_run(), fastjet::ClusterSequenceActiveArea::_transfer_ghost_free_history(), and strategy_string().

double fastjet::ClusterSequence::_tile_size_eta [private]
 

Definition at line 438 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double fastjet::ClusterSequence::_tile_size_phi [private]
 

Definition at line 438 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

std::vector<Tile> fastjet::ClusterSequence::_tiles [private]
 

Definition at line 436 of file ClusterSequence.hh.

Referenced by _add_neighbours_to_tile_union(), _add_untagged_neighbours_to_tile_union(), _bj_remove_from_tiles(), _faster_tiled_N2_cluster(), _initialise_tiles(), _minheap_faster_tiled_N2_cluster(), _print_tiles(), _tiled_N2_cluster(), and _tj_set_jetinfo().

double fastjet::ClusterSequence::_tiles_eta_max [private]
 

Definition at line 437 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double fastjet::ClusterSequence::_tiles_eta_min [private]
 

Definition at line 437 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

int fastjet::ClusterSequence::_tiles_ieta_max [private]
 

Definition at line 439 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

int fastjet::ClusterSequence::_tiles_ieta_min [private]
 

Definition at line 439 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

bool fastjet::ClusterSequence::_writeout_combinations [protected]
 

Definition at line 279 of file ClusterSequence.hh.

Referenced by _add_step_to_history(), and _decant_options().

const int fastjet::ClusterSequence::n_tile_neighbours = 9 [static, private]
 

number of neighbours that a tile will have (rectangular geometry gives 9 neighbours).

Definition at line 418 of file ClusterSequence.hh.

Referenced by _faster_tiled_N2_cluster(), _minheap_faster_tiled_N2_cluster(), and _tiled_N2_cluster().


The documentation for this class was generated from the following files:
Generated on Thu Oct 12 17:36:36 2006 for fastjet by  doxygen 1.4.2