ClusterSequence Class Reference

deals with clustering More...

#include <ClusterSequence.hh>

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

List of all members.

Classes

struct  BriefJet
 the fundamental structure which contains the minimal info about a jet, as needed for our plain N^2 algorithm -- the idea is to put all info that will be accessed N^2 times into an array of BriefJets. More...
struct  EEBriefJet
 fundamental structure for e+e- clustering 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...

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)
 create a clustersequence starting from the supplied set of pseudojets and clustering them with jet definition specified by jet_def (which also specifies the clustering strategy)
virtual ~ClusterSequence ()
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 (sometimes known as d_{n n+1}).
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.
double exclusive_ymerge (int njets) const
 return the ymin corresponding to the recombination that went from n+1 to n jets (sometimes known as y_{n n+1}).
double exclusive_ymerge_max (int njets) const
 same as exclusive_dmerge_max, but normalised to squared total energy
int n_exclusive_jets_ycut (double ycut) const
 the number of exclusive jets at the given ycut
std::vector< PseudoJetexclusive_jets_ycut (double ycut) const
 the exclusive jets obtained at the given ycut
std::vector< PseudoJetexclusive_subjets (const PseudoJet &jet, const double &dcut) const
 return a vector of all subjets of the current jet (in the sense of the exclusive algorithm) that would be obtained when running the algorithm with the given dcut.
int n_exclusive_subjets (const PseudoJet &jet, const double &dcut) const
 return the size of exclusive_subjets(.
std::vector< PseudoJetexclusive_subjets (const PseudoJet &jet, int nsub) const
 return the list of subjets obtained by unclustering the supplied jet down to n subjets (or all constituents if there are fewer than n).
double exclusive_subdmerge (const PseudoJet &jet, int nsub) const
 return the dij that was present in the merging nsub+1 -> nsub subjets inside this jet.
double exclusive_subdmerge_max (const PseudoJet &jet, int nsub) const
 return the maximum dij that occurred in the whole event at the stage that the nsub+1 -> nsub merge of subjets occurred inside this jet.
double Q () const
 returns the sum of all energies in the event (relevant mainly for e+e-)
double Q2 () const
 return Q()^2
bool object_in_jet (const PseudoJet &object, const PseudoJet &jet) const
 returns true iff the object is included in the jet.
bool has_parents (const PseudoJet &jet, PseudoJet &parent1, PseudoJet &parent2) const
 if the jet has parents in the clustering, it returns true and sets parent1 and parent2 equal to them.
bool has_child (const PseudoJet &jet, PseudoJet &child) const
 if the jet has a child then return true and give the child jet otherwise return false and set the child to zero
bool has_child (const PseudoJet &jet, const PseudoJet *&childp) const
 Version of has_child that sets a pointer to the child if the child exists;.
bool has_partner (const PseudoJet &jet, PseudoJet &partner) const
 if this jet has a child (and so a partner) return true and give the partner, otherwise return false and set the partner to zero
std::vector< PseudoJetconstituents (const PseudoJet &jet) const
 return a vector of the particles that make up jet
void print_jets_for_root (const std::vector< PseudoJet > &jets, std::ostream &ostr=std::cout) const
 output the supplied vector of jets in a format that can be read by an appropriate root script; the format is: jet-n jet-px jet-py jet-pz jet-E particle-n particle-rap particle-phi particle-pt particle-n particle-rap particle-phi particle-pt
void print_jets_for_root (const std::vector< PseudoJet > &jets, const std::string &filename, const std::string &comment="") const
 print jets for root to the file labelled filename, with an optional comment at the beginning
void add_constituents (const PseudoJet &jet, std::vector< PseudoJet > &subjet_vector) const
 add on to subjet_vector the constituents of jet (for internal use mainly)
Strategy strategy_used () const
 return the enum value of the strategy used to cluster the event
std::string strategy_string () const
const JetDefinitionjet_def () const
 return a reference to the jet definition
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)
template<class GBJ >
void plugin_simple_N2_cluster ()
 allows a plugin to run a templated clustering (nearest-neighbour heuristic)
const std::vector< PseudoJet > & jets () const
 allow the user to access the internally stored _jets() array, which contains both the initial particles and the various intermediate and final stages of recombination.
const std::vector
< history_element > & 
history () const
 allow the user to access the raw internal history.
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.
void transfer_from_sequence (ClusterSequence &from_seq)
 transfer the sequence contained in other_seq into our own; any plugin "extras" contained in the from_seq will be lost from there.
template<>
void _bj_set_jetinfo (EEBriefJet *const jetA, const int _jets_index) const
template<>
double _bj_dist (const EEBriefJet *const jeta, const EEBriefJet *const jetb) const

Static Public Member Functions

static void set_jet_algorithm (JetAlgorithm jet_algorithm)
 set the default (static) jet finder across all current and future ClusterSequence objects -- deprecated and obsolescent (i.e.
static void set_jet_finder (JetAlgorithm jet_algorithm)
 same as above for backward compatibility

Protected Member Functions

bool _potentially_valid (const PseudoJet &jet) const
 returns true if the jet has a history index contained within the range of this CS
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)
 carry out the recombination between the jets numbered jet_i and jet_j, at distance scale dij; return the index newjet_k of the result of the recombination of i and j.
void _do_iB_recombination_step (const int &jet_i, const double &diB)
 carry out an recombination step in which _jets[jet_i] merges with the beam,
void get_subhist_set (std::set< const history_element * > &subhist, const PseudoJet &jet, double dcut, int maxjet) const
 set subhist to be a set pointers to history entries corresponding to the subjets of this jet; one stops going working down through the subjets either when

  • there is no further to go
  • one has found maxjet entries
  • max_dij_so_far <= dcut By setting maxjet=0 one can use just dcut; by setting dcut<0 one can use jet maxjet

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
double _Qtot
Strategy _strategy
JetAlgorithm _jet_algorithm

Static Protected Attributes

static JetAlgorithm _default_jet_algorithm = 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.
template<class BJ >
void _simple_N2_cluster ()
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)
 currently used only in the Voronoi based code
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
void _add_untagged_neighbours_to_tile_union (const int tile_index, std::vector< int > &tile_union, int &n_near_tiles)
void _simple_N2_cluster_BriefJet ()
 to help instantiation (fj 2.4.0; did not quite work on gcc 33 and os x 10.3?)
void _simple_N2_cluster_EEBriefJet ()
 to avoid issues with template instantiation (OS X 10.3, gcc 3.3)

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

Detailed Description

deals with clustering

Definition at line 66 of file ClusterSequence.hh.


Member Typedef Documentation

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

Definition at line 601 of file ClusterSequence.hh.

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

Definition at line 602 of file ClusterSequence.hh.

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

Definition at line 600 of file ClusterSequence.hh.


Member Enumeration Documentation

Enumerator:
Invalid 
InexistentParent 
BeamJet 

Definition at line 408 of file ClusterSequence.hh.

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


Constructor & Destructor Documentation

ClusterSequence::ClusterSequence (  )  [inline]

default constructor

Definition at line 72 of file ClusterSequence.hh.

00072 {}

template<class L >
ClusterSequence::ClusterSequence ( const std::vector< L > &  pseudojets,
const double &  R = 1.0,
const Strategy strategy = Best,
const bool &  writeout_combinations = false 
) [inline]

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

References _initialise_and_run(), and _transfer_input_jets().

00800                                                                       {
00801 
00802   // transfer the initial jets (type L) into our own array
00803   _transfer_input_jets(pseudojets);
00804 
00805   // run the clustering
00806   _initialise_and_run(R,strategy,writeout_combinations);
00807 }

template<class L >
ClusterSequence::ClusterSequence ( const std::vector< L > &  pseudojets,
const JetDefinition jet_def,
const bool &  writeout_combinations = false 
) [inline]

create a clustersequence starting from the supplied set of pseudojets and clustering them with jet definition specified by jet_def (which also specifies the clustering strategy)

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

Definition at line 813 of file ClusterSequence.hh.

References _initialise_and_run(), and _transfer_input_jets().

00816                                                                       {
00817 
00818   // transfer the initial jets (type L) into our own array
00819   _transfer_input_jets(pseudojets);
00820 
00821   // run the clustering
00822   _initialise_and_run(jet_def,writeout_combinations);
00823 }

ClusterSequence::~ClusterSequence (  )  [virtual]

Definition at line 54 of file ClusterSequence.cc.

00054 {}


Member Function Documentation

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

currently used only in the Voronoi based code

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, and jet_scale_for_algorithm().

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 ClusterSequence::_add_neighbours_to_tile_union ( const int  tile_index,
std::vector< int > &  tile_union,
int &  n_near_tiles 
) const [private]

Referenced by _tiled_N2_cluster().

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

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

Referenced by _do_iB_recombination_step(), and _do_ij_recombination_step().

00941                                    {
00942 
00943   history_element element;
00944   element.parent1 = parent1;
00945   element.parent2 = parent2;
00946   element.jetp_index = jetp_index;
00947   element.child = Invalid;
00948   element.dij   = dij;
00949   element.max_dij_so_far = max(dij,_history[_history.size()-1].max_dij_so_far);
00950   _history.push_back(element);
00951 
00952   int local_step = _history.size()-1;
00953   assert(local_step == step_number);
00954 
00955   assert(parent1 >= 0);
00956   _history[parent1].child = local_step;
00957   if (parent2 >= 0) {_history[parent2].child = local_step;}
00958 
00959   // get cross-referencing right from PseudoJets
00960   if (jetp_index != Invalid) {
00961     assert(jetp_index >= 0);
00962     //cout << _jets.size() <<" "<<jetp_index<<"\n";
00963     _jets[jetp_index].set_cluster_hist_index(local_step);
00964   }
00965 
00966   if (_writeout_combinations) {
00967     cout << local_step << ": " 
00968          << parent1 << " with " << parent2
00969          << "; y = "<< dij<<endl;
00970   }
00971 
00972 }

void ClusterSequence::_add_untagged_neighbours_to_tile_union ( const int  tile_index,
std::vector< int > &  tile_union,
int &  n_near_tiles 
) [private]
template<class J >
double ClusterSequence::_bj_diJ ( const J *const   jeta  )  const [inline, private]

Definition at line 863 of file ClusterSequence.hh.

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

00863                                                                                    {
00864   double kt2 = jet->kt2;
00865   if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
00866   return jet->NN_dist * kt2;
00867 }

template<>
double ClusterSequence::_bj_dist ( const EEBriefJet *const   jeta,
const EEBriefJet *const   jetb 
) const [inline]

Definition at line 95 of file ClusterSequence_N2.cc.

References ClusterSequence::EEBriefJet::nx, ClusterSequence::EEBriefJet::ny, and ClusterSequence::EEBriefJet::nz.

00097                                                      {
00098   double dist = 1.0 
00099     - jeta->nx*jetb->nx
00100     - jeta->ny*jetb->ny
00101     - jeta->nz*jetb->nz;
00102   dist *= 2; // distance is _2_*min(Ei^2,Ej^2)*(1-cos theta)
00103   //cout << "Dist = " << dist << ": " 
00104   //     << jeta->nx << " "
00105   //     << jeta->ny << " "
00106   //     << jeta->nz << " "
00107   //     <<endl;
00108   return dist;
00109 }

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

return the distance between two BriefJet objects

Definition at line 854 of file ClusterSequence.hh.

References fastjet::pi, and twopi.

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

00855                                                                   {
00856   double dphi = std::abs(jetA->phi - jetB->phi);
00857   double deta = (jetA->eta - jetB->eta);
00858   if (dphi > pi) {dphi = twopi - dphi;}
00859   return dphi*dphi + deta*deta;
00860 }

template<class J >
J* 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 670 of file ClusterSequence.hh.

References _jets.

00673           {
00674     J * res;
00675     for(res = head; res<tail; res++) {
00676       if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
00677     }
00678     return res;
00679   }

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

Definition at line 50 of file ClusterSequence_TiledN2.cc.

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

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

void 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<>
void ClusterSequence::_bj_set_jetinfo ( EEBriefJet *const   jetA,
const int  _jets_index 
) const [inline]

Definition at line 54 of file ClusterSequence_N2.cc.

References _jet_algorithm, _jets, ClusterSequence::EEBriefJet::_jets_index, _R2, _Rparam, ee_genkt_algorithm, ee_kt_algorithm, JetDefinition::extra_param(), jet_def(), ClusterSequence::EEBriefJet::kt2, ClusterSequence::EEBriefJet::NN, ClusterSequence::EEBriefJet::NN_dist, fastjet::norm(), ClusterSequence::EEBriefJet::nx, ClusterSequence::EEBriefJet::ny, and ClusterSequence::EEBriefJet::nz.

00055                                                                                  {
00056 
00057   double E = _jets[_jets_index].E();
00058   double scale = E*E; // the default energy scale for the kt alg
00059   double p  = jet_def().extra_param(); // in case we're ee_genkt
00060   switch (_jet_algorithm) {
00061   case ee_kt_algorithm:
00062     assert(_Rparam > 2.0); // force this to be true! [not best place, but works]
00063     // recall that _invR2 is artificially set to 1 for this alg
00064     // so that we automatically have dij = scale * 2(1-cos theta_ij)
00065     // Normally, _Rparam should be automatically set to 4 from JetDefinition
00066     break; 
00067   case ee_genkt_algorithm:
00068     if (p <= 0 && scale < 1e-300) scale = 1e-300; // same dodgy safety as genkt
00069     scale = pow(scale,p);
00070     break;
00071   default:
00072     throw Error("Unrecognised jet algorithm");
00073   }
00074   jetA->kt2  = scale; // "kt2" might one day be renamed as "scale" or some such
00075 
00076   double norm = _jets[_jets_index].modp2();
00077   if (norm > 0) {
00078     norm = 1.0/sqrt(norm);
00079     jetA->nx = norm * _jets[_jets_index].px();
00080     jetA->ny = norm * _jets[_jets_index].py();
00081     jetA->nz = norm * _jets[_jets_index].pz();
00082   } else {
00083     jetA->nx = 0.0;
00084     jetA->ny = 0.0;
00085     jetA->nz = 1.0;
00086   }
00087   jetA->_jets_index = _jets_index;
00088   // initialise NN info as well
00089   jetA->NN_dist = _R2;
00090   jetA->NN      = NULL;
00091 }

template<class J >
void 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 839 of file ClusterSequence.hh.

References _jets, _R2, and jet_scale_for_algorithm().

00840                                                                          {
00841     jetA->eta  = _jets[_jets_index].rap();
00842     jetA->phi  = _jets[_jets_index].phi_02pi();
00843     jetA->kt2  = jet_scale_for_algorithm(_jets[_jets_index]);
00844     jetA->_jets_index = _jets_index;
00845     // initialise NN info as well
00846     jetA->NN_dist = _R2;
00847     jetA->NN      = NULL;
00848 }

template<class J >
void 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 901 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

00902                                                                 {
00903   double NN_dist = _R2;
00904   J * NN  = NULL;
00905   for (J * jetB = head; jetB != tail; jetB++) {
00906     double dist = _bj_dist(jet,jetB);
00907     if (dist < NN_dist) {
00908       NN_dist = dist;
00909       NN = jetB;
00910     }
00911     if (dist < jetB->NN_dist) {
00912       jetB->NN_dist = dist;
00913       jetB->NN = jet;
00914     }
00915   }
00916   jet->NN = NN;
00917   jet->NN_dist = NN_dist;
00918 }

template<class J >
void 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 873 of file ClusterSequence.hh.

References _bj_dist(), and _R2.

00874                                                                             {
00875   double NN_dist = _R2;
00876   J * NN  = NULL;
00877   if (head < jet) {
00878     for (J * jetB = head; jetB != jet; jetB++) {
00879       double dist = _bj_dist(jet,jetB);
00880       if (dist < NN_dist) {
00881         NN_dist = dist;
00882         NN = jetB;
00883       }
00884     }
00885   }
00886   if (tail > jet) {
00887     for (J * jetB = jet+1; jetB != tail; jetB++) {
00888       double dist = _bj_dist(jet,jetB);
00889       if (dist < NN_dist) {
00890         NN_dist = dist;
00891         NN = jetB;
00892       }
00893     }
00894   }
00895   jet->NN = NN;
00896   jet->NN_dist = NN_dist;
00897 }

void 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_algorithm, _jets, BeamJet, cambridge_algorithm, Invalid, fastjet::d0::inline_maths::min(), and twopi.

Referenced by _initialise_and_run().

00223                                          {
00224 
00225   if (_jet_algorithm != 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 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_algorithm, _Rparam, and cambridge_algorithm.

Referenced by _CP2DChan_cluster_2piMultD(), and _initialise_and_run().

00193                                                {
00194 
00195   if (_jet_algorithm != 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 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(), _Rparam, and fastjet::d0::inline_maths::min().

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 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, Invalid, Private::make_mirror(), fastjet::d0::inline_maths::min(), and fastjet::pi.

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

References _invR2, _jet_algorithm, _jet_def, _plugin_activated, _print_banner(), _R2, _Rparam, _strategy, _writeout_combinations, JetDefinition::jet_algorithm(), JetDefinition::R(), and JetDefinition::strategy().

Referenced by ClusterSequenceActiveArea::_initialise_AA(), and _initialise_and_run().

00229                                                                           {
00230 
00231   // let the user know what's going on
00232   _print_banner();
00233 
00234   // make a local copy of the jet definition (for future use?)
00235   _jet_def = jet_def;
00236   
00237   _writeout_combinations = writeout_combinations;
00238   _jet_algorithm = jet_def.jet_algorithm();
00239   _Rparam = jet_def.R();  _R2 = _Rparam*_Rparam; _invR2 = 1.0/_R2;
00240   _strategy = jet_def.strategy();
00241 
00242   // disallow interference from the plugin
00243   _plugin_activated = false;
00244   
00245 }

void 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, NlnN, NlnN3pi, NlnN4pi, strategy_string(), and twopi.

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 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 ClusterSequence::_do_iB_recombination_step ( const int &  jet_i,
const double &  diB 
) [protected]

carry out an recombination step in which _jets[jet_i] merges with the beam,

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

Definition at line 1115 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(), _tiled_N2_cluster(), ClusterSequenceActiveArea::_transfer_ghost_free_history(), and plugin_record_iB_recombination().

01116                                                                          {
01117   // get history index
01118   int newstep_k = _history.size();
01119 
01120   // recombine the jet with the beam
01121   _add_step_to_history(newstep_k,_jets[jet_i].cluster_hist_index(),BeamJet,
01122                        Invalid, diB);
01123 
01124 }

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

carry out the recombination between the jets numbered jet_i and jet_j, at distance scale dij; return the index newjet_k of the result of the recombination of i and j.

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

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

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

01085                                                {
01086 
01087   // create the new jet by recombining the first two
01088   PseudoJet newjet;
01089   _jet_def.recombiner()->recombine(_jets[jet_i], _jets[jet_j], newjet);
01090   _jets.push_back(newjet);
01091   // original version...
01092   //_jets.push_back(_jets[jet_i] + _jets[jet_j]);
01093 
01094   // get its index
01095   newjet_k = _jets.size()-1;
01096 
01097   // get history index
01098   int newstep_k = _history.size();
01099   // and provide jet with the info
01100   _jets[newjet_k].set_cluster_hist_index(newstep_k);
01101 
01102   // finally sort out the history 
01103   int hist_i = _jets[jet_i].cluster_hist_index();
01104   int hist_j = _jets[jet_j].cluster_hist_index();
01105 
01106   _add_step_to_history(newstep_k, min(hist_i, hist_j), max(hist_i,hist_j),
01107                        newjet_k, dij);
01108 
01109 }

void 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)

Reimplemented in ClusterSequenceActiveArea.

Referenced by unique_history_order().

void 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)

Reimplemented in ClusterSequenceActiveArea.

void ClusterSequence::_faster_tiled_N2_cluster (  )  [private]

run a tiled clustering

Definition at line 510 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, ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), ClusterSequence::Tile::begin_tiles, ClusterSequence::TiledJet::diJ_posn, ClusterSequence::Tile::end_tiles, ClusterSequence::Tile::head, n_tile_neighbours, ClusterSequence::TiledJet::next, ClusterSequence::TiledJet::NN, ClusterSequence::TiledJet::NN_dist, ClusterSequence::Tile::tagged, and ClusterSequence::TiledJet::tile_index.

Referenced by _initialise_and_run().

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

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

References _history, _initial_n, _jet_def, _jets, _Qtot, ClusterSequence::history_element::child, ClusterSequence::history_element::dij, InexistentParent, Invalid, ClusterSequence::history_element::jetp_index, ClusterSequence::history_element::max_dij_so_far, ClusterSequence::history_element::parent1, ClusterSequence::history_element::parent2, and JetDefinition::recombiner().

Referenced by ClusterSequenceActiveArea::_initialise_AA(), and _initialise_and_run().

00250                                              {
00251 
00252   //if (_jets.size() == 0) {throw Error("Cannot run jet-finder on empty event");}
00253 
00254   // reserve sufficient space for everything
00255   _jets.reserve(_jets.size()*2);
00256   _history.reserve(_jets.size()*2);
00257 
00258   _Qtot = 0;
00259 
00260   for (int i = 0; i < static_cast<int>(_jets.size()) ; i++) {
00261     history_element element;
00262     element.parent1 = InexistentParent;
00263     element.parent2 = InexistentParent;
00264     element.child   = Invalid;
00265     element.jetp_index = i;
00266     element.dij     = 0.0;
00267     element.max_dij_so_far = 0.0;
00268 
00269     _history.push_back(element);
00270     
00271     // do any momentum preprocessing needed by the recombination scheme
00272     _jet_def.recombiner()->preprocess(_jets[i]);
00273 
00274     // get cross-referencing right from PseudoJets
00275     _jets[i].set_cluster_hist_index(i);
00276 
00277     // determine the total energy in the event
00278     _Qtot += _jets[i].E();
00279   }
00280   _initial_n = _jets.size();
00281 }

void 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_algorithm.

Definition at line 57 of file ClusterSequence.cc.

References _default_jet_algorithm, _initialise_and_run(), and jet_def().

00060                                                                       {
00061 
00062   JetDefinition jet_def(_default_jet_algorithm, R, strategy);
00063   _initialise_and_run(jet_def, writeout_combinations);
00064 }

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

References _CP2DChan_cluster(), _CP2DChan_cluster_2pi2R(), _CP2DChan_cluster_2piMultD(), _decant_options(), _delaunay_cluster(), _faster_tiled_N2_cluster(), _fill_initial_history(), _invR2, _jet_algorithm, _jet_def, _jets, _minheap_faster_tiled_N2_cluster(), _plugin_activated, _R2, _really_dumb_cluster(), _Rparam, _simple_N2_cluster_BriefJet(), _simple_N2_cluster_EEBriefJet(), _strategy, _tiled_N2_cluster(), antikt_algorithm, Best, cambridge_algorithm, ee_genkt_algorithm, ee_kt_algorithm, JetDefinition::jet_algorithm(), fastjet::d0::inline_maths::min(), N2MinHeapTiled, N2Plain, N2PoorTiled, N2Tiled, N3Dumb, n_particles(), NlnN, NlnN3pi, NlnN4pi, NlnNCam, NlnNCam2pi2R, NlnNCam4pi, fastjet::pi, JetDefinition::plugin(), and plugin_algorithm.

Referenced by ClusterSequenceActiveArea::_initialise_AA(), _initialise_and_run(), and ClusterSequence().

00070                                                                       {
00071 
00072   // transfer all relevant info into internal variables
00073   _decant_options(jet_def, writeout_combinations);
00074 
00075   // set up the history entries for the initial particles (those
00076   // currently in _jets)
00077   _fill_initial_history();
00078 
00079   // don't run anything if the event is empty
00080   if (n_particles() == 0) return;
00081 
00082   // ----- deal with special cases: plugins & e+e- ------
00083   if (_jet_algorithm == plugin_algorithm) {
00084     // allows plugin_xyz() functions to modify cluster sequence
00085     _plugin_activated = true;
00086     // let the plugin do its work here
00087     _jet_def.plugin()->run_clustering( (*this) );
00088     _plugin_activated = false;
00089     return;
00090   } else if (_jet_algorithm == ee_kt_algorithm ||
00091              _jet_algorithm == ee_genkt_algorithm) {
00092     // ignore requested strategy
00093     _strategy = N2Plain;
00094     if (_jet_algorithm == ee_kt_algorithm) {
00095       // make sure that R is large enough so that "beam" recomb only
00096       // occurs when a single particle is left
00097       // Normally, this should be automatically set to 4 from JetDefinition
00098       assert(_Rparam > 2.0); 
00099       // this is used to renormalise the dij to get a "standard" form
00100       // and our convention in e+e- will be different from that
00101       // in long.inv case; NB: _invR2 name should be changed -> _renorm_dij?
00102       _invR2 = 1.0;
00103     } else {
00104       // as of 2009-01-09, choose R to be an angular distance, in
00105       // radians.  Since the algorithm uses 2(1-cos(theta)) as its
00106       // squared angular measure, make sure that the _R2 is defined
00107       // in a similar way.
00108       if (_Rparam > pi) {
00109         // choose a value that ensures that back-to-back particles will
00110         // always recombine 
00111         //_R2 = 4.0000000000001;
00112         _R2 = 2 * ( 3.0 + cos(_Rparam) );
00113       } else {
00114         _R2    = 2 * ( 1.0 - cos(_Rparam) );
00115       }
00116       _invR2 = 1.0/_R2;
00117     }
00118     //_simple_N2_cluster<EEBriefJet>();
00119     _simple_N2_cluster_EEBriefJet();
00120     return;
00121   }
00122 
00123 
00124   // automatically redefine the strategy according to N if that is
00125   // what the user requested -- transition points (and especially
00126   // their R-dependence) are based on empirical observations for a
00127   // R=0.4, 0.7 and 1.0, running on toth (3.4GHz, Pentium IV D [dual
00128   // core] with 2MB of cache).
00129   if (_strategy == Best) {
00130     int N = _jets.size();
00131     if (N > 6200/pow(_Rparam,2.0) 
00132         && jet_def.jet_algorithm() == cambridge_algorithm) {
00133       _strategy = NlnNCam;}
00134     else
00135 #ifndef DROP_CGAL
00136       if ((N > 16000/pow(_Rparam,1.15) && jet_def.jet_algorithm() != antikt_algorithm)
00137         || N > 35000/pow(_Rparam,1.15)) {
00138       _strategy = NlnN; }   
00139     else                    
00140 #endif  // DROP_CGAL
00141       if (N > 450) {
00142       _strategy = N2MinHeapTiled;
00143     }
00144     else if (N > 55*max(0.5,min(1.0,_Rparam))) {// empirical scaling with R
00145       _strategy = N2Tiled;
00146     } else {
00147       _strategy = N2Plain;
00148     }
00149   }
00150 
00151 
00152   // run the code containing the selected strategy
00153   if (_strategy == NlnN || _strategy == NlnN3pi 
00154       || _strategy == NlnN4pi ) {
00155     this->_delaunay_cluster();
00156   } else if (_strategy ==  N3Dumb ) {
00157     this->_really_dumb_cluster();
00158   } else if (_strategy == N2Tiled) {
00159     this->_faster_tiled_N2_cluster();
00160   } else if (_strategy == N2PoorTiled) {
00161     this->_tiled_N2_cluster();
00162   } else if (_strategy == N2Plain) {
00163     // BriefJet provides standard long.invariant kt alg.
00164     //this->_simple_N2_cluster<BriefJet>();
00165     this->_simple_N2_cluster_BriefJet();
00166   } else if (_strategy == N2MinHeapTiled) {
00167     this->_minheap_faster_tiled_N2_cluster();
00168   } else if (_strategy == NlnNCam4pi) {
00169     this->_CP2DChan_cluster();
00170   } else if (_strategy == NlnNCam2pi2R) {
00171     this->_CP2DChan_cluster_2pi2R();
00172   } else if (_strategy == NlnNCam) {
00173     this->_CP2DChan_cluster_2piMultD();
00174   } else {
00175     ostringstream err;
00176     err << "Unrecognised value for strategy: "<<_strategy;
00177     throw Error(err.str());
00178     //assert(false);
00179   }
00180 }

void 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 86 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, ClusterSequence::Tile::begin_tiles, ClusterSequence::Tile::end_tiles, ClusterSequence::Tile::head, ClusterSequence::Tile::RH_tiles, ClusterSequence::Tile::surrounding_tiles, ClusterSequence::Tile::tagged, and twopi.

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

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

void ClusterSequence::_minheap_faster_tiled_N2_cluster (  )  [private]

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

Definition at line 727 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, ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), ClusterSequence::Tile::begin_tiles, ClusterSequence::Tile::end_tiles, ClusterSequence::Tile::head, ClusterSequence::TiledJet::label_minheap_update_done(), n_tile_neighbours, ClusterSequence::TiledJet::next, ClusterSequence::TiledJet::NN, ClusterSequence::TiledJet::NN_dist, ClusterSequence::Tile::tagged, and ClusterSequence::TiledJet::tile_index.

Referenced by _initialise_and_run().

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

bool ClusterSequence::_potentially_valid ( const PseudoJet jet  )  const [inline, protected]

returns true if the jet has a history index contained within the range of this CS

Definition at line 487 of file ClusterSequence.hh.

References _history, and PseudoJet::cluster_hist_index().

Referenced by object_in_jet().

00487                                                        {
00488     return jet.cluster_hist_index() >= 0 
00489       && jet.cluster_hist_index() < int(_history.size());
00490   }

void ClusterSequence::_print_banner (  )  [private]

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

Definition at line 197 of file ClusterSequence.cc.

References _first_time, and fastjet_version.

Referenced by _decant_options().

00197                                     {
00198 
00199   if (!_first_time) {return;}
00200   _first_time = false;
00201   
00202   
00203   //Symp. Discr. Alg, p.472 (2002) and  CGAL (http://www.cgal.org);
00204 
00205   cout << "#--------------------------------------------------------------------------\n";
00206   cout << "#                      FastJet release " << fastjet_version << endl;
00207   cout << "#            Written by M. Cacciari, G.P. Salam and G. Soyez            \n"; 
00208   cout << "#                         http://www.fastjet.fr                         \n"; 
00209   cout << "#                                                                       \n";
00210   cout << "# Longitudinally invariant Kt, anti-Kt, and inclusive Cambridge/Aachen  \n";
00211   cout << "# clustering using fast geometric algorithms, with area measures and optional\n";
00212   cout << "# external jet-finder plugins.                                          \n";
00213   cout << "# Please cite Phys. Lett. B641 (2006) [hep-ph/0512210] if you use this code.\n";
00214   cout << "#                                                                       \n";
00215   cout << "# This package uses T.Chan's closest pair algorithm, Proc.13th ACM-SIAM \n";
00216   cout << "# Symp. Discr. Alg, p.472 (2002), S.Fortune's Voronoi algorithm and code " ;
00217 #ifndef DROP_CGAL
00218   cout << endl << "# and CGAL: http://www.cgal.org/";
00219 #endif  // DROP_CGAL
00220   cout << ".\n";
00221   cout << "#-------------------------------------------------------------------------\n";
00222   // make sure we really have the output done.
00223   cout.flush();
00224 }

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

output the contents of the tiles

Definition at line 212 of file ClusterSequence_TiledN2.cc.

References _tiles.

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

void 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, jet_scale_for_algorithm(), fastjet::d0::inline_maths::min(), and fastjet::d0::inline_maths::y().

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 }

template<class BJ >
void ClusterSequence::_simple_N2_cluster (  )  [inline, private]
void ClusterSequence::_simple_N2_cluster_BriefJet (  )  [private]

to help instantiation (fj 2.4.0; did not quite work on gcc 33 and os x 10.3?)

to avoid issues with template instantiation (OS X 10.3, gcc 3.3)

Definition at line 115 of file ClusterSequence_N2.cc.

Referenced by _initialise_and_run().

00115                                                   {  
00116   _simple_N2_cluster<BriefJet>();
00117 }

void ClusterSequence::_simple_N2_cluster_EEBriefJet (  )  [private]

to avoid issues with template instantiation (OS X 10.3, gcc 3.3)

Definition at line 121 of file ClusterSequence_N2.cc.

Referenced by _initialise_and_run().

00121                                                     {  
00122   _simple_N2_cluster<EEBriefJet>();
00123 }

int 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 168 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 twopi.

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

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

Definition at line 728 of file ClusterSequence.hh.

References _n_tiles_phi, and _tiles_ieta_min.

Referenced by _initialise_tiles(), and _tj_set_jetinfo().

00728                                                     {
00729     // note that (-1)%n = -1 so that we have to add _n_tiles_phi
00730     // before performing modulo operation
00731     return (ieta-_tiles_ieta_min)*_n_tiles_phi
00732                   + (iphi+_n_tiles_phi) % _n_tiles_phi;
00733   }

void ClusterSequence::_tiled_N2_cluster (  )  [private]

run a tiled clustering

Definition at line 267 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, ClusterSequence::TiledJet::_jets_index, _R2, _tiles, _tj_set_jetinfo(), ClusterSequence::Tile::begin_tiles, ClusterSequence::Tile::end_tiles, ClusterSequence::Tile::head, n_tile_neighbours, ClusterSequence::TiledJet::next, ClusterSequence::TiledJet::NN, ClusterSequence::TiledJet::NN_dist, ClusterSequence::TiledJet::previous, and ClusterSequence::TiledJet::tile_index.

Referenced by _initialise_and_run().

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

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

Definition at line 191 of file ClusterSequence_TiledN2.cc.

References _tile_index(), _tiles, ClusterSequence::Tile::head, ClusterSequence::TiledJet::next, and ClusterSequence::TiledJet::previous.

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

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

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

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

Definition at line 777 of file ClusterSequence.hh.

References _jets.

Referenced by ClusterSequence().

00778                                                                         {
00779 
00780   // this will ensure that we can point to jets without difficulties
00781   // arising.
00782   _jets.reserve(pseudojets.size()*2);
00783 
00784   // insert initial jets this way so that any type L that can be
00785   // converted to a pseudojet will work fine (basically PseudoJet
00786   // and any type that has [] subscript access to the momentum
00787   // components, such as CLHEP HepLorentzVector).
00788   for (unsigned int i = 0; i < pseudojets.size(); i++) {
00789     _jets.push_back(pseudojets[i]);}
00790   
00791 }

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

add on to subjet_vector the constituents of jet (for internal use mainly)

Referenced by constituents().

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

return a vector of the particles that make up jet

Definition at line 817 of file ClusterSequence.cc.

References add_constituents().

00817                                                                             {
00818   vector<PseudoJet> subjets;
00819   add_constituents(jet, subjets);
00820   return subjets;
00821 }

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

return the dmin corresponding to the recombination that went from n+1 to n jets (sometimes known as d_{n n+1}).

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

Definition at line 537 of file ClusterSequence.cc.

References _history, and _initial_n.

Referenced by exclusive_ymerge().

00537                                                                  {
00538   assert(njets >= 0);
00539   if (njets >= _initial_n) {return 0.0;}
00540   return _history[2*_initial_n-njets-1].dij;
00541 }

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

References _history, and _initial_n.

Referenced by exclusive_ymerge_max().

00549                                                                      {
00550   assert(njets >= 0);
00551   if (njets >= _initial_n) {return 0.0;}
00552   return _history[2*_initial_n-njets-1].max_dij_so_far;
00553 }

vector< PseudoJet > 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 465 of file ClusterSequence.cc.

References _history, _initial_n, _jet_def, _jets, _n_exclusive_warnings, cambridge_algorithm, ee_genkt_algorithm, ee_kt_algorithm, JetDefinition::extra_param(), genkt_algorithm, JetDefinition::jet_algorithm(), jets(), kt_algorithm, JetDefinition::plugin(), and plugin_algorithm.

00465                                                                           {
00466 
00467   // make sure the user does not ask for more than jets than there
00468   // were particles in the first place.
00469   assert (njets <= _initial_n);
00470 
00471   // provide a warning when extracting exclusive jets for algorithms 
00472   // that does not support it explicitly.
00473   // Native algorithm that support it are: kt, ee_kt, cambridge, 
00474   //   genkt and ee_genkt (both with p>=0)
00475   // For plugins, we check Plugin::exclusive_sequence_meaningful()
00476   if (( _jet_def.jet_algorithm() != kt_algorithm) &&
00477       ( _jet_def.jet_algorithm() != cambridge_algorithm) &&
00478       ( _jet_def.jet_algorithm() != ee_kt_algorithm) &&
00479       (((_jet_def.jet_algorithm() != genkt_algorithm) && 
00480         (_jet_def.jet_algorithm() != ee_genkt_algorithm)) || 
00481        (_jet_def.extra_param() <0)) &&
00482       ((_jet_def.jet_algorithm() != plugin_algorithm) ||
00483        (!_jet_def.plugin()->exclusive_sequence_meaningful())) &&
00484       (_n_exclusive_warnings < 5)) {
00485     _n_exclusive_warnings++;
00486     cerr << "FastJet WARNING: dcut and exclusive jets for jet-finders other than kt should be interpreted with care." << endl;
00487   }
00488 
00489 
00490   // calculate the point where we have to stop the clustering.
00491   // relation between stop_point, njets assumes one extra jet disappears
00492   // at each clustering.
00493   int stop_point = 2*_initial_n - njets;
00494 
00495   // some sanity checking to make sure that e+e- does not give us
00496   // surprises (should we ever implement e+e-)...
00497   if (2*_initial_n != static_cast<int>(_history.size())) {
00498     ostringstream err;
00499     err << "2*_initial_n != _history.size() -- this endangers internal assumptions!\n";
00500     throw Error(err.str());
00501     //assert(false);
00502   }
00503 
00504   // now go forwards and reconstitute the jets that we have --
00505   // basically for any history element, see if the parent jets to
00506   // which it refers were created before the stopping point -- if they
00507   // were then add them to the list, otherwise they are subsequent
00508   // recombinations of the jets that we are looking for.
00509   vector<PseudoJet> jets;
00510   for (unsigned int i = stop_point; i < _history.size(); i++) {
00511     int parent1 = _history[i].parent1;
00512     if (parent1 < stop_point) {
00513       jets.push_back(_jets[_history[parent1].jetp_index]);
00514     }
00515     int parent2 = _history[i].parent2;
00516     if (parent2 < stop_point && parent2 > 0) {
00517       jets.push_back(_jets[_history[parent2].jetp_index]);
00518     }
00519     
00520   }
00521 
00522   // sanity check...
00523   if (static_cast<int>(jets.size()) != njets) {
00524     ostringstream err;
00525     err << "ClusterSequence::exclusive_jets: size of returned vector ("
00526          <<jets.size()<<") does not coincide with requested number of jets ("
00527          <<njets<<")";
00528     throw Error(err.str());
00529   }
00530 
00531   return jets;
00532 }

vector< PseudoJet > 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 457 of file ClusterSequence.cc.

References n_exclusive_jets().

Referenced by exclusive_jets_ycut().

00457                                                                             {
00458   int njets = n_exclusive_jets(dcut);
00459   return exclusive_jets(njets);
00460 }

std::vector<PseudoJet> ClusterSequence::exclusive_jets_ycut ( double  ycut  )  const [inline]

the exclusive jets obtained at the given ycut

Definition at line 145 of file ClusterSequence.hh.

References exclusive_jets(), and n_exclusive_jets_ycut().

00145                                                                {
00146     int njets = n_exclusive_jets_ycut(ycut);
00147     return exclusive_jets(njets);
00148   }

double ClusterSequence::exclusive_subdmerge ( const PseudoJet jet,
int  nsub 
) const

return the dij that was present in the merging nsub+1 -> nsub subjets inside this jet.

If the jet has nsub or fewer constituents, it will return 0.

will be zero if nconst <= nsub, since highest will be an original particle have zero dij

Definition at line 621 of file ClusterSequence.cc.

References get_subhist_set().

00621                                                                                  {
00622   set<const history_element*> subhist;
00623 
00624   // get the set of history elements that correspond to subjets at
00625   // scale dcut
00626   get_subhist_set(subhist, jet, -1.0, nsub);
00627   
00628   set<const history_element*>::iterator highest = subhist.end();
00629   highest--;
00632   return (*highest)->dij;
00633 }

double ClusterSequence::exclusive_subdmerge_max ( const PseudoJet jet,
int  nsub 
) const

return the maximum dij that occurred in the whole event at the stage that the nsub+1 -> nsub merge of subjets occurred inside this jet.

If the jet has nsub or fewer constituents, it will return 0.

will be zero if nconst <= nsub, since highest will be an original particle have zero dij

Definition at line 642 of file ClusterSequence.cc.

References get_subhist_set().

00642                                                                                      {
00643 
00644   set<const history_element*> subhist;
00645 
00646   // get the set of history elements that correspond to subjets at
00647   // scale dcut
00648   get_subhist_set(subhist, jet, -1.0, nsub);
00649   
00650   set<const history_element*>::iterator highest = subhist.end();
00651   highest--;
00654   return (*highest)->max_dij_so_far;
00655 }

std::vector< PseudoJet > ClusterSequence::exclusive_subjets ( const PseudoJet jet,
int  n 
) const

return the list of subjets obtained by unclustering the supplied jet down to n subjets (or all constituents if there are fewer than n).

requires n ln n time

Definition at line 597 of file ClusterSequence.cc.

00597                                         {
00598 
00599   set<const history_element*> subhist;
00600 
00601   // get the set of history elements that correspond to subjets at
00602   // scale dcut
00603   get_subhist_set(subhist, jet, -1.0, n);
00604 
00605   // now transfer this into a sequence of jets
00606   vector<PseudoJet> subjets;
00607   subjets.reserve(subhist.size());
00608   for (set<const history_element*>::iterator elem = subhist.begin(); 
00609        elem != subhist.end(); elem++) {
00610     subjets.push_back(_jets[(*elem)->jetp_index]);
00611   }
00612   return subjets;
00613 }

std::vector< PseudoJet > ClusterSequence::exclusive_subjets ( const PseudoJet jet,
const double &  dcut 
) const

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

Time taken is O(m ln m), where m is the number of subjets that are found. If m gets to be of order of the total number of constituents in the jet, this could be substantially slower than just getting that list of constituents.

Definition at line 561 of file ClusterSequence.cc.

00561                                                       {
00562 
00563   set<const history_element*> subhist;
00564 
00565   // get the set of history elements that correspond to subjets at
00566   // scale dcut
00567   get_subhist_set(subhist, jet, dcut, 0);
00568 
00569   // now transfer this into a sequence of jets
00570   vector<PseudoJet> subjets;
00571   subjets.reserve(subhist.size());
00572   for (set<const history_element*>::iterator elem = subhist.begin(); 
00573        elem != subhist.end(); elem++) {
00574     subjets.push_back(_jets[(*elem)->jetp_index]);
00575   }
00576   return subjets;
00577 }

double ClusterSequence::exclusive_ymerge ( int  njets  )  const [inline]

return the ymin corresponding to the recombination that went from n+1 to n jets (sometimes known as y_{n n+1}).

Definition at line 136 of file ClusterSequence.hh.

References exclusive_dmerge(), and Q2().

00136 {return exclusive_dmerge(njets) / Q2();}

double ClusterSequence::exclusive_ymerge_max ( int  njets  )  const [inline]

same as exclusive_dmerge_max, but normalised to squared total energy

Definition at line 139 of file ClusterSequence.hh.

References exclusive_dmerge_max(), and Q2().

00139 {return exclusive_dmerge_max(njets)/Q2();}

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

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

Definition at line 320 of file ClusterSequence.hh.

References _extras.

00320 {return _extras.get();}

void ClusterSequence::get_subhist_set ( std::set< const history_element * > &  subhist,
const PseudoJet jet,
double  dcut,
int  maxjet 
) const [protected]

set subhist to be a set pointers to history entries corresponding to the subjets of this jet; one stops going working down through the subjets either when

  • there is no further to go
  • one has found maxjet entries
  • max_dij_so_far <= dcut By setting maxjet=0 one can use just dcut; by setting dcut<0 one can use jet maxjet

Referenced by exclusive_subdmerge(), exclusive_subdmerge_max(), and n_exclusive_subjets().

bool ClusterSequence::has_child ( const PseudoJet jet,
const PseudoJet *&  childp 
) const

Version of has_child that sets a pointer to the child if the child exists;.

Definition at line 769 of file ClusterSequence.cc.

References _history, _jets, ClusterSequence::history_element::child, and PseudoJet::cluster_hist_index().

00769                                                                                        {
00770 
00771   const history_element & hist = _history[jet.cluster_hist_index()];
00772 
00773   // check that this jet has a child and that the child corresponds to
00774   // a true jet [RETHINK-IF-CHANGE-NUMBERING: what is the right
00775   // behaviour if the child is the same jet but made inclusive...?]
00776   if (hist.child >= 0 && _history[hist.child].jetp_index >= 0) {
00777     childp = &(_jets[_history[hist.child].jetp_index]);
00778     return true;
00779   } else {
00780     childp = NULL;
00781     return false;
00782   }
00783 }

bool ClusterSequence::has_child ( const PseudoJet jet,
PseudoJet child 
) const

if the jet has a child then return true and give the child jet otherwise return false and set the child to zero

Definition at line 747 of file ClusterSequence.cc.

Referenced by object_in_jet().

00747                                                                               {
00748 
00749   //const history_element & hist = _history[jet.cluster_hist_index()];
00750   //
00751   //if (hist.child >= 0) {
00752   //  child = _jets[_history[hist.child].jetp_index];
00753   //  return true;
00754   //} else {
00755   //  child = PseudoJet(0.0,0.0,0.0,0.0);
00756   //  return false;
00757   //}
00758   const PseudoJet * childp;
00759   bool res = has_child(jet, childp);
00760   if (res) {
00761     child = *childp;
00762     return true;
00763   } else {
00764     child = PseudoJet(0.0,0.0,0.0,0.0);
00765     return false;
00766   }
00767 }

bool ClusterSequence::has_parents ( const PseudoJet jet,
PseudoJet parent1,
PseudoJet parent2 
) const

if the jet has parents in the clustering, it returns true and sets parent1 and parent2 equal to them.

if it has no parents it returns false and sets parent1 and parent2 to zero

Definition at line 721 of file ClusterSequence.cc.

References _history, _jets, PseudoJet::cluster_hist_index(), ClusterSequence::history_element::parent1, ClusterSequence::history_element::parent2, and PseudoJet::perp2().

00722                                                          {
00723 
00724   const history_element & hist = _history[jet.cluster_hist_index()];
00725 
00726   // make sure we do not run into any unexpected situations --
00727   // i.e. both parents valid, or neither
00728   assert ((hist.parent1 >= 0 && hist.parent2 >= 0) || 
00729           (hist.parent1 < 0 && hist.parent2 < 0));
00730 
00731   if (hist.parent1 < 0) {
00732     parent1 = PseudoJet(0.0,0.0,0.0,0.0);
00733     parent2 = parent1;
00734     return false;
00735   } else {
00736     parent1 = _jets[_history[hist.parent1].jetp_index];
00737     parent2 = _jets[_history[hist.parent2].jetp_index];
00738     // order the parents in decreasing pt
00739     if (parent1.perp2() < parent2.perp2()) swap(parent1,parent2);
00740     return true;
00741   }
00742 }

bool ClusterSequence::has_partner ( const PseudoJet jet,
PseudoJet partner 
) const

if this jet has a child (and so a partner) return true and give the partner, otherwise return false and set the partner to zero

Definition at line 790 of file ClusterSequence.cc.

References _history, _jets, ClusterSequence::history_element::child, PseudoJet::cluster_hist_index(), ClusterSequence::history_element::parent1, and ClusterSequence::history_element::parent2.

00791                                                          {
00792 
00793   const history_element & hist = _history[jet.cluster_hist_index()];
00794 
00795   // make sure we have a child and that the child does not correspond
00796   // to a clustering with the beam (or some other invalid quantity)
00797   if (hist.child >= 0 && _history[hist.child].parent2 >= 0) {
00798     const history_element & child_hist = _history[hist.child];
00799     if (child_hist.parent1 == jet.cluster_hist_index()) {
00800       // partner will be child's parent2 -- for iB clustering
00801       // parent2 will not be valid
00802       partner = _jets[_history[child_hist.parent2].jetp_index];
00803     } else {
00804       // partner will be child's parent1
00805       partner = _jets[_history[child_hist.parent1].jetp_index];
00806     }
00807     return true;
00808   } else {
00809     partner = PseudoJet(0.0,0.0,0.0,0.0);
00810     return false;
00811   }
00812 }

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

allow the user to access the raw internal history.

This is present (as for jets()) in part so that protected derived classes can access this information about other ClusterSequences.

A user who wishes to follow the details of the ClusterSequence can also make use of this information (and should consult the history_element documentation for more information), but should be aware that these internal structures may evolve in future FastJet versions.

Definition at line 830 of file ClusterSequence.hh.

References _history.

Referenced by ClusterSequenceActiveArea::_transfer_ghost_free_history(), and fastjet::NestedDefsPlugin::run_clustering().

00830                                                                                          {
00831   return _history;
00832 }

vector< PseudoJet > 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 386 of file ClusterSequence.cc.

References _history, _jet_algorithm, _jets, antikt_algorithm, BeamJet, cambridge_algorithm, cambridge_for_passive_algorithm, ee_genkt_algorithm, ee_kt_algorithm, genkt_algorithm, jets(), kt_algorithm, PseudoJet::perp2(), and plugin_algorithm.

Referenced by ClusterSequenceAreaBase::empty_area(), ClusterSequenceAreaBase::get_median_rho_and_sigma(), ClusterSequenceAreaBase::parabolic_pt_per_unit_area(), ClusterSequenceActiveArea::pt_per_unit_area(), and ClusterSequenceAreaBase::subtracted_jets().

00386                                                                             {
00387   double dcut = ptmin*ptmin;
00388   int i = _history.size() - 1; // last jet
00389   vector<PseudoJet> jets;
00390   if (_jet_algorithm == kt_algorithm) {
00391     while (i >= 0) {
00392       // with our specific definition of dij and diB (i.e. R appears only in 
00393       // dij), then dij==diB is the same as the jet.perp2() and we can exploit
00394       // this in selecting the jets...
00395       if (_history[i].max_dij_so_far < dcut) {break;}
00396       if (_history[i].parent2 == BeamJet && _history[i].dij >= dcut) {
00397         // for beam jets
00398         int parent1 = _history[i].parent1;
00399         jets.push_back(_jets[_history[parent1].jetp_index]);}
00400       i--;
00401     }
00402   } else if (_jet_algorithm == cambridge_algorithm) {
00403     while (i >= 0) {
00404       // inclusive jets are all at end of clustering sequence in the
00405       // Cambridge algorithm -- so if we find a non-exclusive jet, then
00406       // we can exit
00407       if (_history[i].parent2 != BeamJet) {break;}
00408       int parent1 = _history[i].parent1;
00409       const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00410       if (jet.perp2() >= dcut) {jets.push_back(jet);}
00411       i--;
00412     }
00413   } else if (_jet_algorithm == plugin_algorithm 
00414              || _jet_algorithm == ee_kt_algorithm
00415              || _jet_algorithm == antikt_algorithm
00416              || _jet_algorithm == genkt_algorithm
00417              || _jet_algorithm == ee_genkt_algorithm
00418              || _jet_algorithm == cambridge_for_passive_algorithm) {
00419     // for inclusive jets with a plugin algorithm, we make no
00420     // assumptions about anything (relation of dij to momenta,
00421     // ordering of the dij, etc.)
00422     while (i >= 0) {
00423       if (_history[i].parent2 == BeamJet) {
00424         int parent1 = _history[i].parent1;
00425         const PseudoJet & jet = _jets[_history[parent1].jetp_index];
00426         if (jet.perp2() >= dcut) {jets.push_back(jet);}
00427       }
00428       i--;
00429     }
00430   } else {throw Error("cs::inclusive_jets(...): Unrecognized jet algorithm");}
00431   return jets;
00432 }

const JetDefinition& ClusterSequence::jet_def (  )  const [inline]
double ClusterSequence::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).

[May become virtual at some point]

Definition at line 321 of file ClusterSequence.cc.

References _jet_algorithm, _jet_def, antikt_algorithm, cambridge_algorithm, cambridge_for_passive_algorithm, JetDefinition::extra_param(), genkt_algorithm, jet_def(), PseudoJet::kt2(), and kt_algorithm.

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

00322                                                                {
00323   if (_jet_algorithm == kt_algorithm)             {return jet.kt2();}
00324   else if (_jet_algorithm == cambridge_algorithm) {return 1.0;}
00325   else if (_jet_algorithm == antikt_algorithm) {
00326     double kt2=jet.kt2();
00327     return kt2 > 1e-300 ? 1.0/kt2 : 1e300;
00328   } else if (_jet_algorithm == genkt_algorithm) {
00329     double kt2 = jet.kt2();
00330     double p   = jet_def().extra_param();
00331     if (p <= 0 && kt2 < 1e-300) kt2 = 1e-300; // dodgy safety check
00332     return pow(kt2, p);
00333   } else if (_jet_algorithm == cambridge_for_passive_algorithm) {
00334     double kt2 = jet.kt2();
00335     double lim = _jet_def.extra_param();
00336     if (kt2 < lim*lim && kt2 != 0.0) {
00337       return 1.0/kt2;
00338     } else {return 1.0;}
00339   } else {throw Error("Unrecognised jet algorithm");}
00340 }

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

allow the user to access the internally stored _jets() array, which contains both the initial particles and the various intermediate and final stages of recombination.

The first n_particles() entries are the original particles, in the order in which they were supplied to the ClusterSequence constructor. It can be useful to access them for example when examining whether a given input object is part of a specific jet, via the objects_in_jet(...) member function (which only takes PseudoJets that are registered in the ClusterSequence).

One of the other (internal uses) is related to the fact 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 826 of file ClusterSequence.hh.

References _jets.

Referenced by exclusive_jets(), inclusive_jets(), fastjet::TrackJetPlugin::run_clustering(), fastjet::SISConeSphericalPlugin::run_clustering(), fastjet::SISConePlugin::run_clustering(), fastjet::PxConePlugin::run_clustering(), fastjet::NestedDefsPlugin::run_clustering(), fastjet::JadePlugin::run_clustering(), fastjet::EECambridgePlugin::run_clustering(), fastjet::D0RunIIConePlugin::run_clustering(), fastjet::CMSIterativeConePlugin::run_clustering(), fastjet::CDFMidPointPlugin::run_clustering(), fastjet::CDFJetCluPlugin::run_clustering(), fastjet::ATLASConePlugin::run_clustering(), and ClusterSequenceAreaBase::subtracted_jets().

00826                                                                  {
00827   return _jets;
00828 }

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

References _history, and _initial_n.

Referenced by exclusive_jets(), and n_exclusive_jets_ycut().

00438                                                                 {
00439 
00440   // first locate the point where clustering would have stopped (i.e. the
00441   // first time max_dij_so_far > dcut)
00442   int i = _history.size() - 1; // last jet
00443   while (i >= 0) {
00444     if (_history[i].max_dij_so_far <= dcut) {break;}
00445     i--;
00446   }
00447   int stop_point = i + 1;
00448   // relation between stop_point, njets assumes one extra jet disappears
00449   // at each clustering.
00450   int njets = 2*_initial_n - stop_point;
00451   return njets;
00452 }

int ClusterSequence::n_exclusive_jets_ycut ( double  ycut  )  const [inline]

the number of exclusive jets at the given ycut

Definition at line 142 of file ClusterSequence.hh.

References n_exclusive_jets(), and Q2().

Referenced by exclusive_jets_ycut().

00142 {return n_exclusive_jets(ycut*Q2());}

int ClusterSequence::n_exclusive_subjets ( const PseudoJet jet,
const double &  dcut 
) const

return the size of exclusive_subjets(.

..); still n ln n with same coefficient, but marginally more efficient than manually taking exclusive_subjets.size()

Definition at line 583 of file ClusterSequence.cc.

References get_subhist_set().

00584                                                    {
00585   set<const history_element*> subhist;
00586   // get the set of history elements that correspond to subjets at
00587   // scale dcut
00588   get_subhist_set(subhist, jet, dcut, 0);
00589   return subhist.size();
00590 }

unsigned int 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 834 of file ClusterSequence.hh.

References _initial_n.

Referenced by _initialise_and_run(), ClusterSequenceVoronoiArea::_initializeVA(), unclustered_particles(), and unique_history_order().

00834 {return _initial_n;}

bool ClusterSequence::object_in_jet ( const PseudoJet object,
const PseudoJet jet 
) const

returns true iff the object is included in the jet.

NB: this is only sensible if the object is already registered within the cluster sequence, so you cannot use it with an input particle to the CS (since the particle won't have the history index set properly).

For nice clustering structures it should run in O(ln(N)) time but in worst cases (certain cone plugins) it can take O(n) time, where n is the number of particles in the jet.

Definition at line 698 of file ClusterSequence.cc.

References _potentially_valid(), PseudoJet::cluster_hist_index(), and has_child().

00699                                                                  {
00700 
00701   // make sure the object conceivably belongs to this clustering
00702   // sequence
00703   assert(_potentially_valid(object) && _potentially_valid(jet));
00704 
00705   const PseudoJet * this_object = &object;
00706   const PseudoJet * childp;
00707   while(true) {
00708     if (this_object->cluster_hist_index() == jet.cluster_hist_index()) {
00709       return true;
00710     } else if (has_child(*this_object, childp)) {this_object = childp;}
00711     else {return false;}
00712   }
00713 }

std::vector<int> 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;

bool ClusterSequence::plugin_activated (  )  const [inline]

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

Definition at line 317 of file ClusterSequence.hh.

References _plugin_activated.

Referenced by plugin_record_iB_recombination(), plugin_record_ij_recombination(), and plugin_simple_N2_cluster().

00317 {return _plugin_activated;}

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

References _extras.

Referenced by fastjet::SISConeSphericalPlugin::run_clustering(), and fastjet::SISConePlugin::run_clustering().

00312                                                                      {
00313     _extras = extras_in;
00314   }

void ClusterSequence::plugin_record_iB_recombination ( int  jet_i,
double  diB 
) [inline]
void 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 371 of file ClusterSequence.cc.

References _jets, and plugin_record_ij_recombination().

00373                                                      {
00374 
00375   plugin_record_ij_recombination(jet_i, jet_j, dij, newjet_k);
00376 
00377   // now transfer newjet into place
00378   int tmp_index = _jets[newjet_k].cluster_hist_index();
00379   _jets[newjet_k] = newjet;
00380   _jets[newjet_k].set_cluster_hist_index(tmp_index);
00381 }

void ClusterSequence::plugin_record_ij_recombination ( int  jet_i,
int  jet_j,
double  dij,
int &  newjet_k 
) [inline]
template<class GBJ >
void ClusterSequence::plugin_simple_N2_cluster (  )  [inline]

allows a plugin to run a templated clustering (nearest-neighbour heuristic)

This has N^2 behaviour on "good" distance, but a worst case behaviour of N^3 (and many algs trigger the worst case behaviour)

For more details on how this works, see GenBriefJet below

Definition at line 329 of file ClusterSequence.hh.

References plugin_activated().

00329                                                        {
00330     assert(plugin_activated());
00331     _simple_N2_cluster<GBJ>();
00332   }

void ClusterSequence::print_jets_for_root ( const std::vector< PseudoJet > &  jets,
const std::string &  filename,
const std::string &  comment = "" 
) const

print jets for root to the file labelled filename, with an optional comment at the beginning

Definition at line 851 of file ClusterSequence.cc.

References print_jets_for_root().

00853                                                                             {
00854   std::ofstream ostr(filename.c_str());
00855   if (comment != "") ostr << "# " << comment << endl;
00856   print_jets_for_root(jets, ostr);
00857 }

void ClusterSequence::print_jets_for_root ( const std::vector< PseudoJet > &  jets,
std::ostream &  ostr = std::cout 
) const

output the supplied vector of jets in a format that can be read by an appropriate root script; the format is: jet-n jet-px jet-py jet-pz jet-E particle-n particle-rap particle-phi particle-pt particle-n particle-rap particle-phi particle-pt

.. END ... [i.e. above repeated]

Referenced by print_jets_for_root().

double ClusterSequence::Q (  )  const [inline]

returns the sum of all energies in the event (relevant mainly for e+e-)

Definition at line 192 of file ClusterSequence.hh.

References _Qtot.

00192 {return _Qtot;}

double ClusterSequence::Q2 (  )  const [inline]

return Q()^2

Definition at line 194 of file ClusterSequence.hh.

References _Qtot.

Referenced by exclusive_ymerge(), exclusive_ymerge_max(), n_exclusive_jets_ycut(), and fastjet::EECambridgePlugin::run_clustering().

00194 {return _Qtot*_Qtot;}

static void ClusterSequence::set_jet_algorithm ( JetAlgorithm  jet_algorithm  )  [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 371 of file ClusterSequence.hh.

References _default_jet_algorithm.

00371 {_default_jet_algorithm = jet_algorithm;}

static void ClusterSequence::set_jet_finder ( JetAlgorithm  jet_algorithm  )  [inline, static]

same as above for backward compatibility

Definition at line 373 of file ClusterSequence.hh.

References _default_jet_algorithm.

00373 {_default_jet_algorithm = jet_algorithm;}

string ClusterSequence::strategy_string (  )  const

Definition at line 287 of file ClusterSequence.cc.

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

Referenced by _delaunay_cluster().

00287                                                 {
00288   string strategy;
00289   switch(_strategy) {
00290   case NlnN:
00291     strategy = "NlnN"; break;
00292   case NlnN3pi:
00293     strategy = "NlnN3pi"; break;
00294   case NlnN4pi:
00295     strategy = "NlnN4pi"; break;
00296   case N2Plain:
00297     strategy = "N2Plain"; break;
00298   case N2Tiled:
00299     strategy = "N2Tiled"; break;
00300   case N2MinHeapTiled:
00301     strategy = "N2MinHeapTiled"; break;
00302   case N2PoorTiled:
00303     strategy = "N2PoorTiled"; break;
00304   case N3Dumb:
00305     strategy = "N3Dumb"; break;
00306   case NlnNCam4pi:
00307     strategy = "NlnNCam4pi"; break;
00308   case NlnNCam2pi2R:
00309     strategy = "NlnNCam2pi2R"; break;
00310   case NlnNCam:
00311     strategy = "NlnNCam"; break; // 2piMultD
00312   case plugin_strategy:
00313     strategy = "plugin strategy"; break;
00314   default:
00315     strategy = "Unrecognized";
00316   }
00317   return strategy;
00318 }  

Strategy ClusterSequence::strategy_used (  )  const [inline]

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

Definition at line 260 of file ClusterSequence.hh.

References _strategy.

Referenced by ClusterSequenceActiveArea::_transfer_ghost_free_history().

00260 {return _strategy;}

void ClusterSequence::transfer_from_sequence ( ClusterSequence from_seq  ) 

transfer the sequence contained in other_seq into our own; any plugin "extras" contained in the from_seq will be lost from there.

Definition at line 347 of file ClusterSequence.cc.

References _extras, _history, _initial_n, _invR2, _jet_algorithm, _jet_def, _jets, _plugin_activated, _R2, _Rparam, _strategy, and _writeout_combinations.

Referenced by ClusterSequencePassiveArea::_initialise_and_run_PA(), and ClusterSequenceArea::initialize_and_run_cswa().

00347                                                                        {
00348 
00349   // the metadata
00350   _jet_def                 = from_seq._jet_def                ;
00351   _writeout_combinations   = from_seq._writeout_combinations  ;
00352   _initial_n               = from_seq._initial_n              ;
00353   _Rparam                  = from_seq._Rparam                 ;
00354   _R2                      = from_seq._R2                     ;
00355   _invR2                   = from_seq._invR2                  ;
00356   _strategy                = from_seq._strategy               ;
00357   _jet_algorithm           = from_seq._jet_algorithm          ;
00358   _plugin_activated        = from_seq._plugin_activated       ;
00359 
00360   // the data
00361   _jets     = from_seq._jets;
00362   _history  = from_seq._history;
00363   // the following transferse ownership of the extras from the from_seq
00364   _extras   = from_seq._extras;
00365 
00366 }

vector< PseudoJet > 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 1037 of file ClusterSequence.cc.

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

01037                                                                {
01038   vector<PseudoJet> unclustered;
01039   for (unsigned i = 0; i < n_particles() ; i++) {
01040     if (_history[i].child == Invalid) 
01041       unclustered.push_back(_jets[_history[i].jetp_index]);
01042   }
01043   return unclustered;
01044 }

vector< int > 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 982 of file ClusterSequence.cc.

References _extract_tree_children(), _history, fastjet::d0::inline_maths::min(), and n_particles().

Referenced by ClusterSequence1GhostPassiveArea::_run_1GPA(), and ClusterSequenceActiveArea::_run_AA().

00982                                                         {
00983 
00984   // first construct an array that will tell us the lowest constituent
00985   // of a given jet -- this will always be one of the original
00986   // particles, whose order is well defined and so will help us to
00987   // follow the tree in a unique manner.
00988   valarray<int> lowest_constituent(_history.size());
00989   int hist_n = _history.size();
00990   lowest_constituent = hist_n; // give it a large number
00991   for (int i = 0; i < hist_n; i++) {
00992     // sets things up for the initial partons
00993     lowest_constituent[i] = min(lowest_constituent[i],i); 
00994     // propagates them through to the children of this parton
00995     if (_history[i].child > 0) lowest_constituent[_history[i].child] 
00996       = min(lowest_constituent[_history[i].child],lowest_constituent[i]);
00997   }
00998 
00999   // establish an array for what we have and have not extracted so far
01000   valarray<bool> extracted(_history.size()); extracted = false;
01001   vector<int> unique_tree;
01002   unique_tree.reserve(_history.size());
01003 
01004   // now work our way through the tree
01005   for (unsigned i = 0; i < n_particles(); i++) {
01006     if (!extracted[i]) {
01007       unique_tree.push_back(i);
01008       extracted[i] = true;
01009       _extract_tree_children(i, extracted, lowest_constituent, unique_tree);
01010     }
01011   }
01012 
01013   return unique_tree;
01014 }


Member Data Documentation

JetAlgorithm ClusterSequence::_default_jet_algorithm = kt_algorithm [static, protected]

Definition at line 482 of file ClusterSequence.hh.

Referenced by _initialise_and_run(), set_jet_algorithm(), and set_jet_finder().

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

Definition at line 564 of file ClusterSequence.hh.

Referenced by extras(), plugin_associate_extras(), and transfer_from_sequence().

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

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

Definition at line 612 of file ClusterSequence.hh.

Referenced by _print_banner().

std::vector<history_element> ClusterSequence::_history [protected]
int ClusterSequence::_initial_n [protected]
double ClusterSequence::_invR2 [protected]
std::vector<PseudoJet> ClusterSequence::_jets [protected]
int 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 617 of file ClusterSequence.hh.

Referenced by exclusive_jets().

Definition at line 724 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

double ClusterSequence::_Qtot [protected]

Definition at line 556 of file ClusterSequence.hh.

Referenced by _fill_initial_history(), Q(), and Q2().

double ClusterSequence::_R2 [protected]
double ClusterSequence::_Rparam [protected]

Definition at line 723 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

Definition at line 723 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

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

Definition at line 722 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

Definition at line 722 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

Definition at line 724 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

Definition at line 724 of file ClusterSequence.hh.

Referenced by _initialise_tiles(), and _tile_index().

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

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

Definition at line 703 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 26 Feb 2010 for fastjet by  doxygen 1.6.1