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).
void plugin_record_ij_recombination (int jet_i, int jet_j, double dij, int &newjet_k)
 record the fact that there has been a recombination between jets()[jet_i] and jets()[jet_k], with the specified dij, and return the index (newjet_k) allocated to the new jet, whose momentum is assumed to be the 4-vector sum of that of jet_i and jet_j
void plugin_record_ij_recombination (int jet_i, int jet_j, double dij, const PseudoJet &newjet, int &newjet_k)
 as for the simpler variant of plugin_record_ij_recombination, except that the new jet is attributed the momentum and user_index of newjet
void plugin_record_iB_recombination (int jet_i, double diB)
 record the fact that there has been a recombination between jets()[jet_i] and the beam, with the specified diB; when looking for inclusive jets, any iB recombination will returned to the user as a jet.
void plugin_associate_extras (std::auto_ptr< Extras > extras_in)
 the plugin can associated some extra information with the ClusterSequence object by calling this function
bool plugin_activated () const
 returns true when the plugin is allowed to run the show.
const Extrasextras () const
 returns a pointer to the extras object (may be null)
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 > particle_jet_indices (const std::vector< PseudoJet > &) const
 returns a vector of size n_particles() which indicates, for each of the initial particles (in the order in which they were supplied), which of the supplied jets it belongs to; if it does not belong to any of the supplied jets, the index is set to -1;
std::vector< int > unique_history_order () const
 routine that returns 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.
std::vector< PseudoJetunclustered_particles () const
 return the set of particles that have not been clustered.

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 and obsolescent (i.e.

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

bool _plugin_activated
std::auto_ptr< Extras_extras
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 int _n_exclusive_warnings = 0
 record the number of warnings provided about the exclusive algorithm -- so that we don't print it out more than a few times.
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...
class  Extras
 a class intended to serve as a base in case a plugin needs to associate extra information with a ClusterSequence (see SISConePlugin. 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 65 of file ClusterSequence.hh.


Member Typedef Documentation

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

Definition at line 383 of file ClusterSequence.hh.

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

Definition at line 384 of file ClusterSequence.hh.

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

Definition at line 382 of file ClusterSequence.hh.


Member Enumeration Documentation

enum fastjet::ClusterSequence::JetType
 

Enumeration values:
Invalid 
InexistentParent 
BeamJet 

Definition at line 236 of file ClusterSequence.hh.

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


Constructor & Destructor Documentation

fastjet::ClusterSequence::ClusterSequence  )  [inline]
 

default constructor

Definition at line 71 of file ClusterSequence.hh.

00071 {}

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 558 of file ClusterSequence.hh.

References _initialise_and_run(), and _transfer_input_jets().

00562                                                                       {
00563 
00564   // transfer the initial jets (type L) into our own array
00565   _transfer_input_jets(pseudojets);
00566 
00567   // run the clustering
00568   _initialise_and_run(R,strategy,writeout_combinations);
00569 }

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 575 of file ClusterSequence.hh.

References _initialise_and_run(), and _transfer_input_jets().

00578                                                                       {
00579 
00580   // transfer the initial jets (type L) into our own array
00581   _transfer_input_jets(pseudojets);
00582 
00583   // run the clustering
00584   _initialise_and_run(jet_def,writeout_combinations);
00585 }


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 504 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().

00507                                    {
00508 
00509   history_element element;
00510   element.parent1 = parent1;
00511   element.parent2 = parent2;
00512   element.jetp_index = jetp_index;
00513   element.child = Invalid;
00514   element.dij   = dij;
00515   element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00516   _history.push_back(element);
00517 
00518   int local_step = _history.size()-1;
00519   assert(local_step == step_number);
00520 
00521   assert(parent1 >= 0);
00522   _history[parent1].child = local_step;
00523   if (parent2 >= 0) {_history[parent2].child = local_step;}
00524 
00525   // get cross-referencing right from PseudoJets
00526   if (jetp_index != Invalid) {
00527     assert(jetp_index >= 0);
00528     //cout << _jets.size() <<" "<<jetp_index<<"\n";
00529     _jets[jetp_index].set_cluster_hist_index(local_step);
00530   }
00531 
00532   if (_writeout_combinations) {
00533     cout << local_step << ": " 
00534          << parent1 << " with " << parent2
00535          << "; y = "<< dij<<endl;
00536   }
00537 
00538 }

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 633 of file ClusterSequence.hh.

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

00633                                                                                    {
00634   double kt2 = jet->kt2;
00635   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00636   return jet->NN_dist * kt2;
00637 }

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 624 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().

00625                                                                   {
00626   double dphi = std::abs(jetA->phi - jetB->phi);
00627   double deta = (jetA->eta - jetB->eta);
00628   if (dphi > pi) {dphi = twopi - dphi;}
00629   return dphi*dphi + deta*deta;
00630 }

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 450 of file ClusterSequence.hh.

00453           {
00454     J * res;
00455     for(res = head; res<tail; res++) {
00456       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00457     }
00458     return res;
00459   }

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 609 of file ClusterSequence.hh.

References _jets, _R2, and jet_scale_for_algorithm().

Referenced by _simple_N2_cluster().

00610                                                                          {
00611     jetA->eta  = _jets[_jets_index].rap();
00612     jetA->phi  = _jets[_jets_index].phi_02pi();
00613     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
00614     jetA->_jets_index = _jets_index;
00615     // initialise NN info as well
00616     jetA->NN_dist = _R2;
00617     jetA->NN      = NULL;
00618 }

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 671 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

Referenced by _simple_N2_cluster().

00672                                                                 {
00673   double NN_dist = _R2;
00674   J * NN  = NULL;
00675   for (J * jetB = head; jetB != tail; jetB++) {
00676     double dist = _bj_dist(jet,jetB);
00677     if (dist < NN_dist) {
00678       NN_dist = dist;
00679       NN = jetB;
00680     }
00681     if (dist < jetB->NN_dist) {
00682       jetB->NN_dist = dist;
00683       jetB->NN = jet;
00684     }
00685   }
00686   jet->NN = NN;
00687   jet->NN_dist = NN_dist;
00688 }

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 643 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

Referenced by _simple_N2_cluster().

00644                                                                             {
00645   double NN_dist = _R2;
00646   J * NN  = NULL;
00647   if (head < jet) {
00648     for (J * jetB = head; jetB != jet; jetB++) {
00649       double dist = _bj_dist(jet,jetB);
00650       if (dist < NN_dist) {
00651         NN_dist = dist;
00652         NN = jetB;
00653       }
00654     }
00655   }
00656   if (tail > jet) {
00657     for (J * jetB = jet+1; jetB != tail; jetB++) {
00658       double dist = _bj_dist(jet,jetB);
00659       if (dist < NN_dist) {
00660         NN_dist = dist;
00661         NN = jetB;
00662       }
00663     }
00664   }
00665   jet->NN = NN;
00666   jet->NN_dist = NN_dist;
00667 }

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 173 of file ClusterSequence.cc.

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

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

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

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 681 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().

00682                                                                          {
00683   // get history index
00684   int newstep_k = _history.size();
00685 
00686   // recombine the jet with the beam
00687   _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
00688                        Invalid, diB);
00689 
00690 }

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 648 of file ClusterSequence.cc.

References _add_step_to_history(), _history, _jet_def, _jets, and fastjet::JetDefinition::recombiner().

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().

00651                                                {
00652 
00653   // create the new jet by recombining the first two
00654   PseudoJet newjet;
00655   _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
00656   _jets.push_back(newjet);
00657   // original version...
00658   //_jets.push_back(_jets[jet_i] + _jets[jet_j]);
00659 
00660   // get its index
00661   newjet_k = _jets.size()-1;
00662 
00663   // get history index
00664   int newstep_k = _history.size();
00665   // and provide jet with the info
00666   _jets[newjet_k].set_cluster_hist_index(newstep_k);
00667 
00668   // finally sort out the history 
00669   int hist_i = _jets[jet_i].cluster_hist_index();
00670   int hist_j = _jets[jet_j].cluster_hist_index();
00671 
00672   _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
00673                        newjet_k, dij);
00674 
00675 }

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 584 of file ClusterSequence.cc.

References _extract_tree_parents(), and _history.

Referenced by unique_history_order().

00588                                         {
00589   if (!extracted[position]) {
00590     // that means we may have unidentified parents around, so go and
00591     // collect them (extracted[position]) will then be made true)
00592     _extract_tree_parents(position,extracted,lowest_constituent,unique_tree);
00593   } 
00594   
00595   // now look after the children...
00596   int child = _history[position].child;
00597   if (child  >= 0) _extract_tree_children(child,extracted,lowest_constituent,unique_tree);
00598 }

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 616 of file ClusterSequence.cc.

References _history.

Referenced by _extract_tree_children().

00620                                         {
00621 
00622   if (!extracted[position]) {
00623     int parent1 = _history[position].parent1;
00624     int parent2 = _history[position].parent2;
00625     // where relevant order parents so that we will first treat the
00626     // one containing the smaller "lowest_constituent"
00627     if (parent1 >= 0 && parent2 >= 0) {
00628       if (lowest_constituent[parent1] > lowest_constituent[parent2]) 
00629         swap(parent1, parent2);
00630     }
00631     // then actually run through the parents to extract the constituents...
00632     if (parent1 >= 0 && !extracted[parent1]) 
00633       _extract_tree_parents(parent1,extracted,lowest_constituent,unique_tree);
00634     if (parent2 >= 0 && !extracted[parent2]) 
00635       _extract_tree_parents(parent2,extracted,lowest_constituent,unique_tree);
00636     // finally declare this position to be accounted for and push it
00637     // onto our list.
00638     unique_tree.push_back(position);
00639     extracted[position] = true;
00640   }
00641 }

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 195 of file ClusterSequence.cc.

References _history, _initial_n, _jet_def, _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, fastjet::ClusterSequence::history_element::parent2, and fastjet::JetDefinition::recombiner().

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

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

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 52 of file ClusterSequence.cc.

References _default_jet_finder, and _initialise_and_run().

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

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 63 of file ClusterSequence.cc.

References _CP2DChan_cluster(), _CP2DChan_cluster_2pi2R(), _CP2DChan_cluster_2piMultD(), _decant_options(), _delaunay_cluster(), _faster_tiled_N2_cluster(), _fill_initial_history(), _jet_def, _jet_finder, _jets, _minheap_faster_tiled_N2_cluster(), _plugin_activated, _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, fastjet::NlnNCam4pi, fastjet::JetDefinition::plugin(), and fastjet::plugin_algorithm.

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

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

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 145 of file ClusterSequence.cc.

References _first_time, and fastjet_version.

Referenced by _decant_options().

00145                                     {
00146 
00147   if (!_first_time) {return;}
00148   _first_time = false;
00149   
00150   
00151   //Symp. Discr. Alg, p.472 (2002) and  CGAL (http://www.cgal.org);
00152 
00153   cout << "#------------------------------------------------------------------------\n";
00154   cout << "#                      FastJet release " << fastjet_version << endl;
00155   cout << "#              Written by Matteo Cacciari and Gavin Salam               \n"; 
00156   cout << "#              http://www.lpthe.jussieu.fr/~salam/fastjet               \n"; 
00157   cout << "#                                                                       \n";
00158   cout << "# Longitudinally invariant Kt, and inclusive Cambridge/Aachen clustering\n";
00159   cout << "# using fast geometric algorithms, with optional external jet-finder    \n";
00160   cout << "# plugins. Please cite hep-ph/0512210 if you use this code.             \n";
00161   cout << "#                                                                       \n";
00162   cout << "# This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM \n";
00163   cout << "# Symp. Discr. Alg, p.472 (2002)";
00164 #ifndef DROP_CGAL
00165   cout << " as well as CGAL: http://www.cgal.org/";
00166 #endif  // DROP_CGAL
00167   cout << ".\n";
00168   cout << "#-----------------------------------------------------------------------\n";
00169 }

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 508 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tj_set_jetinfo().

00508                                                     {
00509     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00510     // before performing modulo operation
00511     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00512                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00513   }

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 539 of file ClusterSequence.hh.

References _jets.

Referenced by ClusterSequence().

00540                                                                         {
00541 
00542   // this will ensure that we can point to jets without difficulties
00543   // arising.
00544   _jets.reserve(pseudojets.size()*2);
00545 
00546   // insert initial jets this way so that any type L that can be
00547   // converted to a pseudojet will work fine (basically PseudoJet
00548   // and any type that has [] subscript access to the momentum
00549   // components, such as CLHEP HepLorentzVector).
00550   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00551     _jets.push_back(pseudojets[i]);}
00552   
00553 }

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 477 of file ClusterSequence.cc.

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

Referenced by constituents().

00478                                                                            {
00479   // find out position in cluster history
00480   int i = jet.cluster_hist_index();
00481   int parent1 = _history[i].parent1;
00482   int parent2 = _history[i].parent2;
00483 
00484   if (parent1 == InexistentParent) {
00485     // It is an original particle (labelled by its parent having value
00486     // InexistentParent), therefore add it on to the subjet vector
00487     subjet_vector.push_back(jet);
00488     return;
00489   } 
00490 
00491   // add parent 1
00492   add_constituents(_jets[_history[parent1].jetp_index], subjet_vector);
00493 
00494   // see if parent2 is a real jet; if it is then add its constituents
00495   if (parent2 != BeamJet) {
00496     add_constituents(_jets[_history[parent2].jetp_index], subjet_vector);
00497   }
00498 }

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

return a vector of the particles that make up jet

Definition at line 434 of file ClusterSequence.cc.

References add_constituents().

Referenced by main(), particle_jet_indices(), and print_jets().

00434                                                                             {
00435   vector<PseudoJet> subjets;
00436   add_constituents(jet, subjets);
00437   return subjets;
00438 }

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 413 of file ClusterSequence.cc.

References _history, and _initial_n.

00413                                                                  {
00414   assert(njets > 0);
00415   if (njets >= _initial_n) {return 0.0;}
00416   return _history[2*_initial_n-njets-1].dij;
00417 }

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 425 of file ClusterSequence.cc.

References _history, and _initial_n.

00425                                                                      {
00426   assert(njets > 0);
00427   if (njets >= _initial_n) {return 0.0;}
00428   return _history[2*_initial_n-njets-1].max_dij_so_far;
00429 }

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 353 of file ClusterSequence.cc.

References _history, _initial_n, _jet_def, _jets, _n_exclusive_warnings, fastjet::JetDefinition::jet_finder(), jets(), and fastjet::kt_algorithm.

00353                                                                           {
00354 
00355   // make sure the user does not ask for more than jets than there
00356   // were particles in the first place.
00357   assert (njets <= _initial_n);
00358 
00359   // provide a warning when extracting exclusive jets 
00360   if (_jet_def.jet_finder() != kt_algorithm && _n_exclusive_warnings < 5) {
00361     _n_exclusive_warnings++;
00362     cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
00363   }
00364 
00365 
00366   // calculate the point where we have to stop the clustering.
00367   // relation between stop_point, njets assumes one extra jet disappears
00368   // at each clustering.
00369   int stop_point = 2*_initial_n - njets;
00370 
00371   // some sanity checking to make sure that e+e- does not give us
00372   // surprises (should we ever implement e+e-)...
00373   if (2*_initial_n != static_cast<int>(_history.size())) {
00374     ostringstream err;
00375     err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00376     throw Error(err.str());
00377     //assert(false);
00378   }
00379 
00380   // now go forwards and reconstitute the jets that we have --
00381   // basically for any history element, see if the parent jets to
00382   // which it refers were created before the stopping point -- if they
00383   // were then add them to the list, otherwise they are subsequent
00384   // recombinations of the jets that we are looking for.
00385   vector<PseudoJet> jets;
00386   for (unsigned int i = stop_point; i < _history.size(); i++) {
00387     int parent1 = _history[i].parent1;
00388     if (parent1 < stop_point) {
00389       jets.push_back(_jets[_history[parent1].jetp_index]);
00390     }
00391     int parent2 = _history[i].parent2;
00392     if (parent2 < stop_point && parent2 > 0) {
00393       jets.push_back(_jets[_history[parent2].jetp_index]);
00394     }
00395     
00396   }
00397 
00398   // sanity check...
00399   if (static_cast<int>(jets.size()) != njets) {
00400     ostringstream err;
00401     err << "ClusterSequence::exclusive_jets: size of returned vector ("
00402          <<jets.size()<<") does not coincide with requested number of jets ("
00403          <<njets<<")";
00404     throw Error(err.str());
00405   }
00406 
00407   return jets;
00408 }

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 345 of file ClusterSequence.cc.

References n_exclusive_jets().

Referenced by main().

00345                                                                             {
00346   int njets = n_exclusive_jets(dcut);
00347   return exclusive_jets(njets);
00348 }

const Extras* fastjet::ClusterSequence::extras  )  const [inline]
 

returns a pointer to the extras object (may be null)

Definition at line 195 of file ClusterSequence.hh.

Referenced by main().

00195 {return _extras.get();}

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 592 of file ClusterSequence.hh.

References _history.

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

00592                                                                                          {
00593   return _history;
00594 }

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 279 of file ClusterSequence.cc.

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

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

00279                                                                             {
00280   double dcut = ptmin*ptmin;
00281   int i = _history.size() - 1; // last jet
00282   vector<PseudoJet> jets;
00283   if (_jet_finder == kt_algorithm) {
00284     while (i >= 0) {
00285       // with our specific definition of dij and diB (i.e. R appears only in 
00286       // dij), then dij==diB is the same as the jet.perp2() and we can exploit
00287       // this in selecting the jets...
00288       if (_history[i].max_dij_so_far < dcut) {break;}
00289       if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00290         // for beam jets
00291         int parent1 = _history[i].parent1;
00292         jets.push_back(_jets[_history[parent1].jetp_index]);}
00293       i--;
00294     }
00295   } else if (_jet_finder == cambridge_algorithm) {
00296     while (i >= 0) {
00297       // inclusive jets are all at end of clustering sequence in the
00298       // Cambridge algorithm -- so if we find a non-exclusive jet, then
00299       // we can exit
00300       if (_history[i].parent2 != BeamJet) {break;}
00301       int parent1 = _history[i].parent1;
00302       const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00303       if (jet.perp2() >= dcut) {jets.push_back(jet);}
00304       i--;
00305     }
00306   } else if (_jet_finder == plugin_algorithm) {
00307     // for inclusive jets with a plugin algorith, we make no
00308     // assumptions about anything (relation of dij to momenta,
00309     // ordering of the dij, etc.)
00310     while (i >= 0) {
00311       if (_history[i].parent2 == BeamJet) {
00312         int parent1 = _history[i].parent1;
00313         const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00314         if (jet.perp2() >= dcut) {jets.push_back(jet);}
00315       }
00316       i--;
00317     }
00318   } else {throw Error("Unrecognized jet algorithm");}
00319   return jets;
00320 }

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 600 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().

00601                                                                {
00602   if (_jet_finder == kt_algorithm)             {return jet.kt2();}
00603   else if (_jet_finder == cambridge_algorithm) {return 1.0;}
00604   else {throw Error("Unrecognised jet finder");}
00605 }

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 588 of file ClusterSequence.hh.

References _jets.

Referenced by fastjet::ClusterSequenceActiveArea::_transfer_areas(), exclusive_jets(), inclusive_jets(), fastjet::SISConePlugin::run_clustering(), fastjet::PxConePlugin::run_clustering(), fastjet::CDFMidPointPlugin::run_clustering(), and fastjet::CDFJetCluPlugin::run_clustering().

00588                                                                  {
00589   return _jets;
00590 }

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 326 of file ClusterSequence.cc.

References _history, and _initial_n.

Referenced by exclusive_jets().

00326                                                                 {
00327 
00328   // first locate the point where clustering would have stopped (i.e. the
00329   // first time max_dij_so_far > dcut)
00330   int i = _history.size() - 1; // last jet
00331   while (i >= 0) {
00332     if (_history[i].max_dij_so_far <= dcut) {break;}
00333     i--;
00334   }
00335   int stop_point = i + 1;
00336   // relation between stop_point, njets assumes one extra jet disappears
00337   // at each clustering.
00338   int njets = 2*_initial_n - stop_point;
00339   return njets;
00340 }

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 596 of file ClusterSequence.hh.

References _initial_n.

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

00596 {return _initial_n;}

vector< int > fastjet::ClusterSequence::particle_jet_indices const std::vector< PseudoJet > &   )  const
 

returns a vector of size n_particles() which indicates, for each of the initial particles (in the order in which they were supplied), which of the supplied jets it belongs to; if it does not belong to any of the supplied jets, the index is set to -1;

Definition at line 446 of file ClusterSequence.cc.

References constituents(), history(), and n_particles().

00447                                                               {
00448 
00449   vector<int> indices(n_particles());
00450 
00451   // first label all particles as not belonging to any jets
00452   for (unsigned ipart = 0; ipart < n_particles(); ipart++) 
00453     indices[ipart] = -1;
00454 
00455   // then for each of the jets relabel its consituents as belonging to
00456   // that jet
00457   for (unsigned ijet = 0; ijet < jets.size(); ijet++) {
00458 
00459     vector<PseudoJet> jet_constituents(constituents(jets[ijet]));
00460 
00461     for (unsigned ip = 0; ip < jet_constituents.size(); ip++) {
00462       // a safe (if slightly redundant) way of getting the particle
00463       // index (for initial particles it is actually safe to assume
00464       // ipart=iclust).
00465       unsigned iclust = jet_constituents[ip].cluster_hist_index();
00466       unsigned ipart = history()[iclust].jetp_index;
00467       indices[ipart] = ijet;
00468     }
00469   }
00470 
00471   return indices;
00472 }

bool fastjet::ClusterSequence::plugin_activated  )  const [inline]
 

returns true when the plugin is allowed to run the show.

Definition at line 192 of file ClusterSequence.hh.

00192 {return _plugin_activated;}

void fastjet::ClusterSequence::plugin_associate_extras std::auto_ptr< Extras extras_in  )  [inline]
 

the plugin can associated some extra information with the ClusterSequence object by calling this function

Definition at line 187 of file ClusterSequence.hh.

Referenced by fastjet::SISConePlugin::run_clustering().

00187                                                                      {
00188     _extras = extras_in;
00189   }

void fastjet::ClusterSequence::plugin_record_iB_recombination int  jet_i,
double  diB
[inline]
 

record the fact that there has been a recombination between jets()[jet_i] and the beam, with the specified diB; when looking for inclusive jets, any iB recombination will returned to the user as a jet.

Definition at line 171 of file ClusterSequence.hh.

Referenced by fastjet::SISConePlugin::run_clustering(), fastjet::PxConePlugin::run_clustering(), fastjet::CDFMidPointPlugin::run_clustering(), and fastjet::CDFJetCluPlugin::run_clustering().

00171                                                              {
00172     assert(plugin_activated());
00173     _do_iB_recombination_step(jet_i, diB);
00174   }

void fastjet::ClusterSequence::plugin_record_ij_recombination int  jet_i,
int  jet_j,
double  dij,
const PseudoJet newjet,
int &  newjet_k
 

as for the simpler variant of plugin_record_ij_recombination, except that the new jet is attributed the momentum and user_index of newjet

Definition at line 264 of file ClusterSequence.cc.

References _jets, and plugin_record_ij_recombination().

00266                                                      {
00267 
00268   plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
00269 
00270   // now transfer newjet into place
00271   int tmp_index = _jets[newjet_k].cluster_hist_index();
00272   _jets[newjet_k] = newjet;
00273   _jets[newjet_k].set_cluster_hist_index(tmp_index);
00274 }

void fastjet::ClusterSequence::plugin_record_ij_recombination int  jet_i,
int  jet_j,
double  dij,
int &  newjet_k
[inline]
 

record the fact that there has been a recombination between jets()[jet_i] and jets()[jet_k], with the specified dij, and return the index (newjet_k) allocated to the new jet, whose momentum is assumed to be the 4-vector sum of that of jet_i and jet_j

Definition at line 154 of file ClusterSequence.hh.

Referenced by plugin_record_ij_recombination(), fastjet::SISConePlugin::run_clustering(), fastjet::PxConePlugin::run_clustering(), fastjet::CDFMidPointPlugin::run_clustering(), and fastjet::CDFJetCluPlugin::run_clustering().

00155                                                       {
00156     assert(plugin_activated());
00157     _do_ij_recombination_step(jet_i, jet_j, dij, newjet_k);
00158   }

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 and obsolescent (i.e.

may be suppressed in a future release).

Definition at line 201 of file ClusterSequence.hh.

00201 {_default_jet_finder = jet_finder;}

string fastjet::ClusterSequence::strategy_string  )  const
 

Definition at line 227 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, fastjet::NlnNCam4pi, and fastjet::plugin_strategy.

Referenced by _delaunay_cluster(), and main().

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

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

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

Definition at line 137 of file ClusterSequence.hh.

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

00137 {return _strategy;}

vector< PseudoJet > fastjet::ClusterSequence::unclustered_particles  )  const
 

return the set of particles that have not been clustered.

For kt and cam/aachen algorithms this should always be null, but for cone type algorithms it can be non-null;

Definition at line 603 of file ClusterSequence.cc.

References _history, _jets, Invalid, and n_particles().

00603                                                                {
00604   vector<PseudoJet> unclustered;
00605   for (unsigned i = 0; i < n_particles() ; i++) {
00606     if (_history[i].child == Invalid) 
00607       unclustered.push_back(_jets[_history[i].jetp_index]);
00608   }
00609   return unclustered;
00610 }

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

routine that returns 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 548 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().

00548                                                         {
00549 
00550   // first construct an array that will tell us the lowest constituent
00551   // of a given jet -- this will always be one of the original
00552   // particles, whose order is well defined and so will help us to
00553   // follow the tree in a unique manner.
00554   valarray<int> lowest_constituent(_history.size());
00555   int hist_n = _history.size();
00556   lowest_constituent = hist_n; // give it a large number
00557   for (int i = 0; i < hist_n; i++) {
00558     // sets things up for the initial partons
00559     lowest_constituent[i] = min(lowest_constituent[i],i); 
00560     // propagates them through to the children of this parton
00561     if (_history[i].child > 0) lowest_constituent[_history[i].child] 
00562       = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00563   }
00564 
00565   // establish an array for what we have and have not extracted so far
00566   valarray<bool> extracted(_history.size()); extracted = false;
00567   vector<int> unique_tree;
00568   unique_tree.reserve(_history.size());
00569 
00570   // now work our way through the tree
00571   for (unsigned i = 0; i < n_particles(); i++) {
00572     if (!extracted[i]) {
00573       unique_tree.push_back(i);
00574       extracted[i] = true;
00575       _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
00576     }
00577   }
00578 
00579   return unique_tree;
00580 }


Member Data Documentation

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

Definition at line 47 of file ClusterSequence.cc.

Referenced by _initialise_and_run().

std::auto_ptr<Extras> fastjet::ClusterSequence::_extras [private]
 

Definition at line 347 of file ClusterSequence.hh.

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

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

Definition at line 140 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 336 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(), unclustered_particles(), and unique_history_order().

int fastjet::ClusterSequence::_initial_n [protected]
 

Definition at line 339 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 340 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 286 of file ClusterSequence.hh.

Referenced by _decant_options(), _do_ij_recombination_step(), _fill_initial_history(), _initialise_and_run(), fastjet::ClusterSequenceActiveAreaExplicitGhosts::_post_process(), fastjet::ClusterSequenceActiveArea::_transfer_areas(), and exclusive_jets().

JetFinder fastjet::ClusterSequence::_jet_finder [protected]
 

Definition at line 342 of file ClusterSequence.hh.

Referenced by _CP2DChan_cluster(), _CP2DChan_cluster_2pi2R(), _decant_options(), _initialise_and_run(), 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 330 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(), jets(), plugin_record_ij_recombination(), and unclustered_particles().

int fastjet::ClusterSequence::_n_exclusive_warnings = 0 [static, private]
 

record the number of warnings provided about the exclusive algorithm -- so that we don't print it out more than a few times.

Definition at line 141 of file ClusterSequence.cc.

Referenced by exclusive_jets().

int fastjet::ClusterSequence::_n_tiles_phi [private]
 

Definition at line 504 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

bool fastjet::ClusterSequence::_plugin_activated [private]
 

Definition at line 346 of file ClusterSequence.hh.

Referenced by _decant_options(), and _initialise_and_run().

double fastjet::ClusterSequence::_R2 [protected]
 

Definition at line 340 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 340 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 341 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 503 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double fastjet::ClusterSequence::_tile_size_phi [private]
 

Definition at line 503 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

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

Definition at line 501 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 502 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double fastjet::ClusterSequence::_tiles_eta_min [private]
 

Definition at line 502 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

int fastjet::ClusterSequence::_tiles_ieta_max [private]
 

Definition at line 504 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

int fastjet::ClusterSequence::_tiles_ieta_min [private]
 

Definition at line 504 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

bool fastjet::ClusterSequence::_writeout_combinations [protected]
 

Definition at line 338 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 483 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 Mon Apr 2 20:58:17 2007 for fastjet by  doxygen 1.4.2