--- /dev/null
+// for backwards compatibility fastjet/CDFJetCluPlugin.hh can also be
+// accessed through this file without specifying "fastjet/"; this is
+// however deprecated for new code, and is not guaranteed to work from
+// release 3.x onwards
+#ifndef __BACKWARD_WARNING__
+#define __BACKWARD_WARNING__
+#warning This file includes at least one deprecated FastJet header. \
+Please consider including FastJet plugins using "fastjet/...Plugin.hh" \
+For backwards compatibility fastjet/...Plugin.hh can also be accessed \
+through this file without specifying "fastjet/"; this is however \
+deprecated for new work, and is not guaranteed to work from release \
+3.x onwards.
+#endif
+
+#include "fastjet/CDFJetCluPlugin.hh"
--- /dev/null
+// for backwards compatibility fastjet/CDFMidPointPlugin.hh can also be
+// accessed through this file without specifying "fastjet/"; this is
+// however deprecated for new code, and is not guaranteed to work from
+// release 3.x onwards
+#ifndef __BACKWARD_WARNING__
+#define __BACKWARD_WARNING__
+#warning This file includes at least one deprecated FastJet header. \
+Please consider including FastJet plugins using "fastjet/...Plugin.hh" \
+For backwards compatibility fastjet/...Plugin.hh can also be accessed \
+through this file without specifying "fastjet/"; this is however \
+deprecated for new work, and is not guaranteed to work from release \
+3.x onwards.
+#endif
+
+#include "fastjet/CDFMidPointPlugin.hh"
--- /dev/null
+//STARTHEADER
+// $Id: FjClusterSequence.hh 945 2007-11-09 08:46:04Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FJCLUSTERSEQUENCE_HH__
+#define __FJCLUSTERSEQUENCE_HH__
+
+
+#ifndef __BACKWARD_WARNING_V1__
+#define __BACKWARD_WARNING_V1__
+#warning This file includes at least one deprecated FastJet header from v1. \
+All fastjet components (including plugins) should now be accessed by including fastjet/...
+#endif // __BACKWARD_WARNING_V1__
+
+#include "fastjet/ClusterSequence.hh"
+
+
+/// typedef which provides backwards compatibility for
+/// user programs based on the v1 interface
+typedef fastjet::ClusterSequence FjClusterSequence;
+
+/// typedef which provides backwards compatibility for
+/// user programs based on the v1 interface
+typedef fastjet::Strategy FjStrategy;
+
+
+// below follow redefinitions of all the strategy constants
+// to allow a v1 legacy user to access the strategy names
+// as before
+
+/// experimental ...
+const FjStrategy N2MinHeapTiled = fastjet::N2MinHeapTiled;
+/// fastest from about 50..10^4
+const FjStrategy N2Tiled = fastjet::N2Tiled;
+/// legacy
+const FjStrategy N2PoorTiled = fastjet::N2PoorTiled;
+/// fastest below 50
+const FjStrategy N2Plain = fastjet::N2Plain;
+/// worse even than the usual N^3 algorithms
+const FjStrategy N3Dumb = fastjet::N3Dumb;
+/// automatic selection of the best (based on N)
+const FjStrategy Best = fastjet::Best;
+/// best of the NlnN variants -- best overall for N>10^4
+const FjStrategy NlnN = fastjet::NlnN;
+/// legacy N ln N using 3pi coverage of cylinder
+const FjStrategy NlnN3pi = fastjet::NlnN3pi;
+/// legacy N ln N using 4pi coverage of cylinder
+const FjStrategy NlnN4pi = fastjet::NlnN4pi;
+/// Chan's closest pair method (in a variant with 4pi coverage),
+/// for use exclusively with the Cambridge algorithm
+const FjStrategy NlnNCam4pi = fastjet::NlnNCam4pi;
+const FjStrategy NlnNCam2pi2R = fastjet::NlnNCam2pi2R;
+const FjStrategy NlnNCam = fastjet::NlnNCam; // 2piMultD
+
+
+#endif //__FJCLUSTERSEQUENCE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: FjPseudoJet.hh 945 2007-11-09 08:46:04Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FJPSEUDOJET_HH__
+#define __FJPSEUDOJET_HH__
+
+#ifndef __BACKWARD_WARNING_V1__
+#define __BACKWARD_WARNING_V1__
+#warning This file includes at least one deprecated FastJet header from v1. \
+All fastjet components (including plugins) should now be accessed by including fastjet/...
+#endif // __BACKWARD_WARNING_V1__
+
+
+#include "fastjet/PseudoJet.hh"
+
+/// typedef which provides backwards compatibility for
+/// user programs based on the v1 interface
+typedef fastjet::PseudoJet FjPseudoJet;
+
+/// thought not officially "declared" in the docuementation,
+/// this was used in the v1 fastjet_timing.cc example program,
+/// so in order to ensure that it still compiles we define it...
+const double twopi = fastjet::twopi;
+
+#endif //__FJPSEUDOJET_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ActiveAreaSpec.hh 633 2007-05-10 15:59:09Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_ACTIVEAREASPEC_HH__
+#define __FASTJET_ACTIVEAREASPEC_HH__
+#include "fastjet/GhostedAreaSpec.hh"
+
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// just provide a typedef for backwards compatibility with programs
+/// based on versions 2.0 and 2.1 of fastjet
+typedef GhostedAreaSpec ActiveAreaSpec;
+
+} // fastjet namespace
+
+#endif // __FASTJET_ACTIVEAREASPEC_HH__
--- /dev/null
+//STARTHEADER
+// $Id: AreaDefinition.hh 635 2007-05-10 18:37:10Z salam $
+//
+// Copyright (c) 2006-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_AREADEFINITION_HH__
+#define __FASTJET_AREADEFINITION_HH__
+
+#include "fastjet/GhostedAreaSpec.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// class for holding a "Voronoi area" specification; an area will be
+/// assigned to each particle, which is the area of the intersection
+/// of the particle's Voronoi cell with a circle of radius
+/// R*effective_Rfact.
+///
+class VoronoiAreaSpec {
+public:
+
+ /// default constructor (effective_Rfact = 1);
+ VoronoiAreaSpec() : _effective_Rfact(1.0) {};
+
+ /// constructor that allows you to set effective_Rfact.
+ VoronoiAreaSpec(double effective_Rfact) :
+ _effective_Rfact(effective_Rfact) {};
+
+ /// return the value of effective_Rfact
+ double effective_Rfact() const {return _effective_Rfact;}
+
+ /// return a textual description of the area definition.
+ std::string description() const;
+
+private:
+ double _effective_Rfact;
+};
+
+
+/// the different types of area that are supported
+enum AreaType {invalid_area = -1,
+ active_area = 0, active_area_explicit_ghosts = 1,
+ one_ghost_passive_area = 10, passive_area = 11,
+ voronoi_area=20};
+
+
+//----------------------------------------------------------------------
+/// class that holds a generic area definition
+///
+class AreaDefinition {
+public:
+
+ /// default constructor, which provides a ghosted active area, with
+ /// sensible defaults for the ghosts.
+ AreaDefinition() {
+ _area_type = active_area;
+ _ghost_spec = GhostedAreaSpec();
+ }
+
+ /// constructor for an area definition based on an area type and a
+ /// ghosted area specification
+ AreaDefinition(AreaType type, const GhostedAreaSpec & spec) {
+ _ghost_spec = spec;
+ _area_type = type;
+ assert(type != voronoi_area);
+ }
+
+ /// constructor for an area definition based on an area type and a
+ /// voronoi area specification (type must be voronoi_area)
+ AreaDefinition(AreaType type, const VoronoiAreaSpec & spec) {
+ _voronoi_spec = spec;
+ _area_type = type;
+ assert(type == voronoi_area);
+ }
+
+ /// constructor for an area definition based on an area type and
+ /// which attempts to provide sensible defaults for everything else
+ AreaDefinition(AreaType type) {
+ _area_type = type;
+ if (type == voronoi_area) {
+ _voronoi_spec = VoronoiAreaSpec();
+ } else {
+ _ghost_spec = GhostedAreaSpec();
+ }
+ }
+
+ /// constructor for an area definition based on an ghosted area
+ /// specification, and an option to select which ghosted area you want
+ AreaDefinition(const GhostedAreaSpec & spec, AreaType type = active_area) {
+ _ghost_spec = spec;
+ _area_type = type;
+ assert(type != voronoi_area);
+ }
+
+ /// constructor for an area definition based on a voronoi area
+ /// specification
+ AreaDefinition(const VoronoiAreaSpec & spec) {
+ _voronoi_spec = spec;
+ _area_type = voronoi_area;
+ }
+
+ /// return a description of the current area definition
+ std::string description() const;
+
+ /// return info about the type of area being used by this defn
+ AreaType area_type() const {return _area_type;}
+
+ /// return a reference to the active area spec
+ const GhostedAreaSpec & ghost_spec() const {return _ghost_spec;}
+ GhostedAreaSpec & ghost_spec() {return _ghost_spec;}
+
+ /// return a reference to the voronoi area spec
+ const VoronoiAreaSpec & voronoi_spec() const {return _voronoi_spec;}
+
+private:
+
+ AreaType _area_type;
+ GhostedAreaSpec _ghost_spec;
+ VoronoiAreaSpec _voronoi_spec;
+};
+
+} // fastjet namespace
+
+
+#endif // __FASTJET_AREADEFINITION_HH__
--- /dev/null
+//STARTHEADER
+// $Id: CDFJetCluPlugin.hh 1493 2009-03-11 19:15:17Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CDFJETCLUPLUGIN_HH__
+#define __CDFJETCLUPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/PseudoJet.hh"
+#include <map>
+
+// questionable whether this should be in fastjet namespace or not...
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// a plugin for fastjet-v2.1 that provides an interface to the CDF
+/// jetclu algorithm
+class CDFJetCluPlugin : public JetDefinition::Plugin {
+public:
+ /// a compact constructor
+ CDFJetCluPlugin (double cone_radius,
+ double overlap_threshold,
+ double seed_threshold = 1.0,
+ int iratch = 1) :
+ _seed_threshold ( seed_threshold ),
+ _cone_radius ( cone_radius ),
+ _adjacency_cut ( 2 ),
+ _max_iterations ( 100 ),
+ _iratch ( iratch ),
+ _overlap_threshold ( overlap_threshold ) {}
+
+ /// a constructor that looks like the one provided by CDF
+ CDFJetCluPlugin (
+ double seed_threshold ,
+ double cone_radius ,
+ int adjacency_cut ,
+ int max_iterations ,
+ int iratch ,
+ double overlap_threshold) :
+ _seed_threshold (seed_threshold ),
+ _cone_radius (cone_radius ),
+ _adjacency_cut (adjacency_cut ),
+ _max_iterations (max_iterations ),
+ _iratch (iratch ),
+ _overlap_threshold (overlap_threshold ) {}
+
+ // some functions to return info about parameters
+ double seed_threshold () const {return _seed_threshold ;}
+ double cone_radius () const {return _cone_radius ;}
+ int adjacency_cut () const {return _adjacency_cut ;}
+ int max_iterations () const {return _max_iterations ;}
+ int iratch () const {return _iratch ;}
+ double overlap_threshold () const {return _overlap_threshold ;}
+
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const;
+ /// the plugin mechanism's standard way of accessing the jet radius
+ virtual double R() const {return cone_radius();}
+
+
+private:
+
+ double _seed_threshold ;
+ double _cone_radius ;
+ int _adjacency_cut ;
+ int _max_iterations ;
+ int _iratch ;
+ double _overlap_threshold;
+
+ /// given a jet try inserting its energy into the map -- if that
+ /// energy entry already exists, modify the jet infinitesimally so
+ /// as ensure that the jet energy is unique
+ void _insert_unique (PseudoJet & jet, std::map<double,int> & jetmap) const;
+
+};
+
+} // fastjet namespace
+
+#endif // __CDFJETCLUPLUGIN_HH__
--- /dev/null
+//STARTHEADER
+// $Id: CDFMidPointPlugin.hh 1186 2008-04-04 16:15:39Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __CDFMIDPOINTPLUGIN_HH__
+#define __CDFMIDPOINTPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+
+// questionable whether this should be in fastjet namespace or not...
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// CDFMidPointPlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides an interface to the CDF version of Run-II iterative cone
+/// algorithm with midpoint seeds (also known as the Iterative Legacy
+/// Cone Algorithm, ILCA).
+///
+/// The CDF code has been taken from Joey Huston's webpage
+/// http://www.pa.msu.edu/~huston/Les_Houches_2005/Les_Houches_SM.html
+///
+/// Note that the CDF midpoint code contains options that go beyond
+/// those described in the Tevatron run-II document (hep-ex/0005012),
+/// notably search-cones, as described in hep-ph/0111434, and
+/// midpoints bewteen multiplets of stable cones.
+///
+/// Additionally, the version of the CDF midpoint code distributed
+/// here has been modified by the FastJet authors, so as to allow one
+/// to choose the scale used in the split-merge step.
+//
+//----------------------------------------------------------------------
+class CDFMidPointPlugin : public JetDefinition::Plugin {
+public:
+ /// the choice of scale to be used in the split-merge step
+ // NB: just replicates what we've added to the CDF midpoint code
+ enum SplitMergeScale {SM_pt, SM_Et, SM_mt, SM_pttilde};
+
+ ///
+ /// A CDFMidPointPlugin constructor that looks like the one provided
+ /// by CDF. Its arguments should have the following meaning:
+ ///
+ /// - seed_threshold: minimum pt for a particle to be considered
+ /// a seed of the iteration.
+ ///
+ /// - cone_radius: standard meaning
+ ///
+ /// - cone_area_fraction: stable-cones are searched for with a
+ /// radius Rsearch = R * sqrt(cone_area_fraction), and then
+ /// expanded to size R afterwards; note (hep-ph/0610012) that this
+ /// introduces IR unsafety at NLO for X+2-jet observables (where X
+ /// any hard object).
+ ///
+ /// - max_pair_size: "midpoints" can be added between pairs of
+ /// stable cones, triplets of stable cones, etc.; max_pair_size
+ /// indicates the maximum number of stable cones that are
+ /// assembled when adding midpoints.
+ ///
+ /// - max_iterations: the maximum number of iterations to carry out
+ /// when looking for a stable cone.
+ ///
+ /// - overlap_threshold: if
+ /// (overlapping_Et)/(Et_of_softer_protojet) < overlap_threshold,
+ /// overlapping jets are split, otherwise they are merged.
+ ///
+ /// - sm_scale: a choice for the scale to be used in the split-merge
+ /// step (both for ordering the momenta and quantifying the
+ /// overlap); the three options are
+ ///
+ /// . SM_pt: pt (default -- source of small IR safety issue in purely
+ /// hadronic events)
+ ///
+ /// . SM_Et: Et (not boost invariant, reduces to mt at zero rapidity and
+ /// to pt and infinite rapidity)
+ ///
+ /// . SM_mt: transverse mass = sqrt(m^2+pt^2)
+ ///
+ CDFMidPointPlugin (
+ double seed_threshold ,
+ double cone_radius ,
+ double cone_area_fraction ,
+ int max_pair_size ,
+ int max_iterations ,
+ double overlap_threshold ,
+ SplitMergeScale sm_scale = SM_pt) :
+ _seed_threshold (seed_threshold ),
+ _cone_radius (cone_radius ),
+ _cone_area_fraction (cone_area_fraction ),
+ _max_pair_size (max_pair_size ),
+ _max_iterations (max_iterations ),
+ _overlap_threshold (overlap_threshold ),
+ _sm_scale (sm_scale) {}
+
+ /// a compact constructor
+ ///
+ /// NB: as of version 2.4, the default value for the
+ /// overlap_threshold threshold has been removed, to avoid
+ /// misleading people into using the value of 0.5 without thinking,
+ /// which is known to have adverse effects in high-noise
+ /// environments. A recommended value is 0.75.
+ CDFMidPointPlugin (double cone_radius,
+ double overlap_threshold,// = 0.5,
+ double seed_threshold = 1.0,
+ double cone_area_fraction = 1.0) :
+ _seed_threshold (seed_threshold ),
+ _cone_radius (cone_radius ),
+ _cone_area_fraction (cone_area_fraction ),
+ _max_pair_size (2 ),
+ _max_iterations (100 ),
+ _overlap_threshold (overlap_threshold ),
+ _sm_scale (SM_pt) {}
+
+
+ // some functions to return info about parameters
+ double seed_threshold () const {return _seed_threshold ;}
+ double cone_radius () const {return _cone_radius ;}
+ double cone_area_fraction () const {return _cone_area_fraction ;}
+ int max_pair_size () const {return _max_pair_size ;}
+ int max_iterations () const {return _max_iterations ;}
+ double overlap_threshold () const {return _overlap_threshold ;}
+
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const;
+ /// the plugin mechanism's standard way of accessing the jet radius
+ virtual double R() const {return cone_radius();}
+
+private:
+
+ double _seed_threshold ;
+ double _cone_radius ;
+ double _cone_area_fraction;
+ int _max_pair_size ;
+ int _max_iterations ;
+ double _overlap_threshold ;
+ SplitMergeScale _sm_scale ;
+};
+
+} // fastjet namespace
+
+#endif // __CDFMIDPOINTPLUGIN_HH__
--- /dev/null
+//STARTHEADER
+// $Id: CircularRange.hh 1502 2009-04-06 10:33:14Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_CIRCULARRANGE_HH__
+#define __FASTJET_CIRCULARRANGE_HH__
+
+#include "fastjet/RangeDefinition.hh"
+#include "fastjet/Error.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+class CircularRange : public fastjet::RangeDefinition {
+public:
+ /// constructor
+ CircularRange() {_set_invalid_rapphi();}
+
+ /// initialise CircularRange with a jet
+ CircularRange(const fastjet::PseudoJet & jet, double distance) {
+ _distance = distance;
+ _rapjet = jet.rap();
+ _phijet = jet.phi();
+ _total_area = fastjet::pi*_distance*_distance; }
+
+ /// initialise CircularRange with a (rap,phi) point
+ CircularRange(double rap, double phi, double distance) {
+ _distance = distance;
+ _rapjet = rap;
+ _phijet = phi;
+ _total_area = fastjet::pi*_distance*_distance; }
+
+ /// initialise CircularRange with just the radius parameter
+ CircularRange(double distance) {
+ _set_invalid_rapphi();
+ _distance = distance;
+ _total_area = fastjet::pi*_distance*_distance; }
+
+ /// destructor
+ virtual ~CircularRange() {}
+
+ /// return description of range
+ virtual inline std::string description() const {
+ std::ostringstream ostr;
+ ostr << "CircularRange: within distance "<< _distance << " of given jet or point." ;
+ return ostr.str(); }
+
+ /// returns true since this range is localizable (i.e. set_position
+ /// does something meaningful)
+ virtual inline bool is_localizable() const { return true; }
+
+ /// return bool according to whether (rap,phi) is in range
+ virtual inline bool is_in_range(double rap, double phi) const {
+ if (! _rapphi_are_valid()) {
+ throw Error("Circular range used without a center having being defined (use set_position())");
+ }
+ double deltaphi = _phijet - phi;
+ if ( deltaphi > pi) { deltaphi -= twopi; }
+ else if ( deltaphi < -pi) { deltaphi += twopi; }
+ bool inrange = ( (rap-_rapjet)*(rap-_rapjet) +
+ deltaphi*deltaphi <= _distance*_distance );
+ return inrange; }
+
+ /// return the minimal and maximal rapidity of this range
+ virtual inline void get_rap_limits(double & rapmin, double & rapmax) const {
+ rapmin = _rapjet - _distance;
+ rapmax = _rapjet + _distance; }
+
+private:
+ double _distance;
+
+ /// value for phi that marks it as invalid
+ const static double _invalid_phi = -1000.0;
+ /// set internal phi so as to mark things as invalid
+ void _set_invalid_rapphi() {_phijet = _invalid_phi;}
+ /// true if rap,phi are valid (tests only phi)
+ bool _rapphi_are_valid() const {return _phijet != _invalid_phi;}
+
+};
+
+} // fastjet namespace
+
+#endif // __FASTJET_CIRCULARRANGE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequence.hh 1435 2009-02-12 21:11:04Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+//----------------------------------------------------------------------
+// here's where we put the main page for fastjet (as explained in the
+// Doxygen faq)
+//......................................................................
+/*! \mainpage FastJet code documentation
+ *
+ * These pages provide automatically generated documentation for the
+ * FastJet package.
+ *
+ * For further information and normal documentation, see the main <a
+ * href="http://www.lpthe.jussieu.fr/~salam/fastjet">FastJet</a> page.
+ */
+//----------------------------------------------------------------------
+
+#ifndef __FASTJET_CLUSTERSEQUENCE_HH__
+#define __FASTJET_CLUSTERSEQUENCE_HH__
+
+#include<vector>
+#include<map>
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/PseudoJet.hh"
+#include<memory>
+#include<cassert>
+#include<iostream>
+#include<string>
+#include<set>
+#include<cmath> // needed to get double std::abs(double)
+#include "fastjet/Error.hh"
+#include "fastjet/JetDefinition.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+
+/// deals with clustering
+class ClusterSequence {
+
+
+ public:
+
+ /// default constructor
+ ClusterSequence () {}
+
+ /// 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
+ 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 jet definition specified
+ /// by jet_def (which also specifies the clustering strategy)
+ template<class L> ClusterSequence (
+ const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const bool & writeout_combinations = false);
+
+ // virtual ClusterSequence destructor, in case any derived class
+ // thinks of needing a destructor at some point
+ virtual ~ClusterSequence (); //{}
+
+ // NB: in the routines that follow, for extracting lists of jets, a
+ // list structure might be more efficient, if sometimes a little
+ // more awkward to use (at least for old fortran hands).
+
+ /// 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.
+ std::vector<PseudoJet> inclusive_jets (const double & ptmin = 0.0) 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.
+ int n_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.
+ std::vector<PseudoJet> exclusive_jets (const double & dcut) const;
+
+ /// return a vector of all jets when the event is clustered (in the
+ /// exclusive sense) to exactly njets.
+ std::vector<PseudoJet> exclusive_jets (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 (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_dmerge_max (const 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 (int njets) const {return exclusive_dmerge(njets) / Q2();}
+
+ /// same as exclusive_dmerge_max, but normalised to squared total energy
+ double exclusive_ymerge_max (int njets) const {return exclusive_ymerge_max(njets)/Q2();}
+
+ /// the number of exclusive jets at the given ycut
+ int n_exclusive_jets_ycut (double ycut) const {return n_exclusive_jets(ycut*Q2());}
+
+ /// the exclusive jets obtained at the given ycut
+ std::vector<PseudoJet> exclusive_jets_ycut (double ycut) const {
+ int njets = n_exclusive_jets_ycut(ycut);
+ return exclusive_jets(njets);
+ }
+
+
+ //int n_exclusive_jets (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.
+ std::vector<PseudoJet> 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()
+ int n_exclusive_subjets(const PseudoJet & jet,
+ const double & dcut) 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
+ std::vector<PseudoJet> exclusive_subjets (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(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 exclusive_subdmerge_max(const PseudoJet & jet, int nsub) const;
+
+ //std::vector<PseudoJet> exclusive_jets (const PseudoJet & jet,
+ // const int & njets) const;
+ //double exclusive_dmerge (const PseudoJet & jet, const int & njets) const;
+
+ /// returns the sum of all energies in the event (relevant mainly for e+e-)
+ double Q() const {return _Q;}
+ /// return Q()^2
+ double Q2() const {return _Q*_Q;}
+
+ /// 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.
+ bool object_in_jet(const PseudoJet & object, const PseudoJet & jet) 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
+ bool has_parents(const PseudoJet & jet, PseudoJet & parent1,
+ PseudoJet & parent2) 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, PseudoJet & child) const;
+
+ /// Version of has_child that sets a pointer to the child if the child
+ /// exists;
+ bool has_child(const PseudoJet & jet, const PseudoJet * & childp) 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
+ bool has_partner(const PseudoJet & jet, PseudoJet & partner) const;
+
+
+ /// return a vector of the particles that make up jet
+ std::vector<PseudoJet> constituents (const PseudoJet & jet) 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]
+ void print_jets_for_root(const std::vector<PseudoJet> & jets,
+ std::ostream & ostr = std::cout) const;
+
+ /// print jets for root to the file labelled filename, with an
+ /// optional comment at the beginning
+ void print_jets_for_root(const std::vector<PseudoJet> & jets,
+ const std::string & filename,
+ const std::string & comment = "") const;
+
+// Not yet. Perhaps in a future release.
+// /// print out all inclusive jets with pt > ptmin
+// virtual void print_jets (const double & ptmin=0.0) const;
+
+ /// add on to subjet_vector the constituents of jet (for internal use mainly)
+ void add_constituents (const PseudoJet & jet,
+ std::vector<PseudoJet> & subjet_vector) const;
+
+ /// return the enum value of the strategy used to cluster the event
+ inline Strategy strategy_used () const {return _strategy;}
+ std::string strategy_string () const;
+
+ /// return a reference to the jet definition
+ const JetDefinition & jet_def() const {return _jet_def;}
+
+ /// 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]
+ double jet_scale_for_algorithm(const PseudoJet & jet) const;
+
+ //----- next follow functions designed specifically for plugins, which
+ // may only be called when plugin_activated() returns true
+
+ /// 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,
+ int & newjet_k) {
+ assert(plugin_activated());
+ _do_ij_recombination_step(jet_i, jet_j, dij, 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_ij_recombination(int jet_i, int jet_j, double dij,
+ const PseudoJet & newjet,
+ int & newjet_k);
+
+ /// 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_record_iB_recombination(int jet_i, double diB) {
+ assert(plugin_activated());
+ _do_iB_recombination_step(jet_i, diB);
+ }
+
+ /// a class intended to serve as a base in case a plugin needs to
+ /// associate extra information with a ClusterSequence (see
+ /// SISConePlugin.* for an example).
+ class Extras {
+ public:
+ virtual ~Extras() {}
+ virtual std::string description() const {return "This is a dummy extras class that contains no extra information! Derive from it if you want to use it to provide extra information from a plugin jet finder";}
+ };
+
+ /// the plugin can associated some extra information with the
+ /// ClusterSequence object by calling this function
+ inline void plugin_associate_extras(std::auto_ptr<Extras> extras_in) {
+ _extras = extras_in;
+ }
+
+ /// returns true when the plugin is allowed to run the show.
+ inline bool plugin_activated() const {return _plugin_activated;}
+
+ /// returns a pointer to the extras object (may be null)
+ const Extras * extras() const {return _extras.get();}
+
+ /// 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
+ template<class GBJ> void plugin_simple_N2_cluster () {
+ assert(plugin_activated());
+ _simple_N2_cluster<GBJ>();
+ }
+
+ //----------------------------------------------------------------------
+ /// class to help with a generic clustering sequence
+ class GenBriefJet {
+ public:
+ /// function that initialises the GenBriefJet given a PseudoJet.
+ ///
+ /// In a derived class, this member has a responsability to call
+ ///
+ /// - set_scale_squared
+ /// - set_geom_iB
+ ///
+ /// The clustering will be performed by finding the minimum of
+ ///
+ /// diB = scale_squared[i] * geom_iB * _invR2
+ /// dij = min(scale_squared[i],scale_squared[j]) * geom_ij * _invR2
+ ///
+ virtual void init(const PseudoJet & jet) = 0;
+
+ /// Returns the "geometric" part of distance between this jet
+ /// and jet_j
+ virtual double geom_ij(const GenBriefJet * jet_j) const = 0;
+
+ void set_scale_squared(double scale_squared) {kt2 = scale_squared;}
+ void set_geom_iB(double diB) {NN_dist = diB; NN = NULL;}
+
+ public: // formally public: but users should think of it as private!
+ double NN_dist; // dij
+ double kt2; // squared scale
+ GenBriefJet * NN; // pointer to nearest neighbour
+ int _jets_index; // index of this jet
+ };
+
+
+public:
+ /// 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).
+ static void set_jet_algorithm (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
+ /// same as above for backward compatibility
+ static void set_jet_finder (JetAlgorithm jet_algorithm) {_default_jet_algorithm = jet_algorithm;}
+
+
+ /// a single element in the clustering history (see vector _history
+ /// below).
+ struct history_element{
+ int parent1; /// index in _history where first parent of this jet
+ /// was created (InexistentParent if this jet is an
+ /// original particle)
+
+ int parent2; /// index in _history where second parent of this jet
+ /// was created (InexistentParent if this jet is an
+ /// original particle); BeamJet if this history entry
+ /// just labels the fact that the jet has recombined
+ /// with the beam)
+
+ int child; /// index in _history where the current jet is
+ /// recombined with another jet to form its child. It
+ /// is Invalid if this jet does not further
+ /// recombine.
+
+ int jetp_index; /// index in the _jets vector where we will find the
+ /// PseudoJet object corresponding to this jet
+ /// (i.e. the jet created at this entry of the
+ /// history). NB: if this element of the history
+ /// corresponds to a beam recombination, then
+ /// jetp_index=Invalid.
+
+ double dij; /// the distance corresponding to the recombination
+ /// at this stage of the clustering.
+
+ double max_dij_so_far; /// the largest recombination distance seen
+ /// so far in the clustering history.
+ };
+
+ enum JetType {Invalid=-3, InexistentParent = -2, BeamJet = -1};
+
+ /// 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).
+ const std::vector<PseudoJet> & jets() const;
+
+ /// 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.
+ const std::vector<history_element> & history() 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).
+ unsigned int n_particles() 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> particle_jet_indices(const std::vector<PseudoJet> &) 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...]
+ std::vector<int> unique_history_order() 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;
+ std::vector<PseudoJet> unclustered_particles() const;
+
+ /// transfer the sequence contained in other_seq into our own;
+ /// any plugin "extras" contained in the from_seq will be lost
+ /// from there.
+ void transfer_from_sequence(ClusterSequence & from_seq);
+
+
+protected:
+ static JetAlgorithm _default_jet_algorithm;
+ JetDefinition _jet_def;
+
+ /// returns true if the jet has a history index contained within
+ /// the range of this CS
+ bool _potentially_valid(const PseudoJet & jet) const {
+ return jet.cluster_hist_index() >= 0
+ && jet.cluster_hist_index() < int(_history.size());
+ }
+
+ /// transfer the vector<L> of input jets into our own vector<PseudoJet>
+ /// _jets (with some reserved space for future growth).
+ template<class L> void _transfer_input_jets(
+ const std::vector<L> & pseudojets);
+
+ /// 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.
+ void _initialise_and_run (const JetDefinition & jet_def,
+ const bool & writeout_combinations);
+
+ /// 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.
+ void _initialise_and_run (const double & R,
+ const Strategy & strategy,
+ const bool & writeout_combinations);
+
+ /// fills in the various member variables with "decanted" options from
+ /// the jet_definition and writeout_combinations variables
+ void _decant_options(const JetDefinition & jet_def,
+ const bool & writeout_combinations);
+
+ /// 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 _fill_initial_history();
+
+ /// 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_ij_recombination_step(const int & jet_i, const int & jet_j,
+ const double & dij, int & newjet_k);
+
+ /// carry out an recombination step in which _jets[jet_i] merges with
+ /// the beam,
+ void _do_iB_recombination_step(const int & jet_i, const double & diB);
+
+
+ /// 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<PseudoJet> _jets;
+
+
+ /// 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.
+ std::vector<history_element> _history;
+
+ /// 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
+ void get_subhist_set(std::set<const history_element*> & subhist,
+ const PseudoJet & jet, double dcut, int maxjet) const;
+
+ bool _writeout_combinations;
+ int _initial_n;
+ double _Rparam, _R2, _invR2;
+ double _Q;
+ Strategy _strategy;
+ JetAlgorithm _jet_algorithm;
+
+
+ private:
+
+ bool _plugin_activated;
+ std::auto_ptr<Extras> _extras; // things the plugin might want to add
+
+ void _really_dumb_cluster ();
+ void _delaunay_cluster ();
+ //void _simple_N2_cluster ();
+ template<class BJ> void _simple_N2_cluster ();
+ void _tiled_N2_cluster ();
+ void _faster_tiled_N2_cluster ();
+
+ //
+ void _minheap_faster_tiled_N2_cluster();
+
+ // things needed specifically for Cambridge with Chan's 2D closest
+ // pairs method
+ void _CP2DChan_cluster();
+ void _CP2DChan_cluster_2pi2R ();
+ void _CP2DChan_cluster_2piMultD ();
+ void _CP2DChan_limited_cluster(double D);
+ 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);
+
+ /// internal routine associated with the construction of the unique
+ /// history order (following children in the tree)
+ 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 parents in the tree)
+ void _extract_tree_parents (int pos, std::valarray<bool> &,
+ const std::valarray<int> &, std::vector<int> &) const;
+
+
+ // these will be useful shorthands in the Voronoi-based code
+ typedef std::pair<int,int> TwoVertices;
+ typedef std::pair<double,TwoVertices> DijEntry;
+ typedef std::multimap<double,TwoVertices> DistMap;
+
+ /// currently used only in the Voronoi based code
+ void _add_ktdistance_to_map(const int & ii,
+ DistMap & DijMap,
+ const DynamicNearestNeighbours * DNN);
+
+ /// for making sure the user knows what it is they're running...
+ void _print_banner();
+ /// will be set by default to be true for the first run
+ static bool _first_time;
+
+ /// record the number of warnings provided about the exclusive
+ /// algorithm -- so that we don't print it out more than a few
+ /// times.
+ static int _n_exclusive_warnings;
+
+ //----------------------------------------------------------------------
+ /// 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...
+ struct BriefJet {
+ double eta, phi, kt2, NN_dist;
+ BriefJet * NN;
+ int _jets_index;
+ };
+
+
+ /// structure analogous to BriefJet, but with the extra information
+ /// needed for dealing with tiles
+ class TiledJet {
+ public:
+ double eta, phi, kt2, NN_dist;
+ TiledJet * NN, *previous, * next;
+ int _jets_index, tile_index, diJ_posn;
+ // routines that are useful in the minheap version of tiled
+ // clustering ("misuse" the otherwise unused diJ_posn, so as
+ // to indicate whether jets need to have their minheap entries
+ // updated).
+ inline void label_minheap_update_needed() {diJ_posn = 1;}
+ inline void label_minheap_update_done() {diJ_posn = 0;}
+ inline bool minheap_update_needed() const {return diJ_posn==1;}
+ };
+
+ //-- some of the functions that follow are templates and will work
+ //as well for briefjet and tiled jets
+
+ /// set the kinematic and labelling info for jeta so that it corresponds
+ /// to _jets[_jets_index]
+ template <class J> void _bj_set_jetinfo( J * const jet,
+ const int _jets_index) const;
+
+ /// "remove" this jet, which implies updating links of neighbours and
+ /// perhaps modifying the tile structure
+ void _bj_remove_from_tiles( TiledJet * const jet) const;
+
+ /// return the distance between two BriefJet objects
+ template <class J> double _bj_dist(const J * const jeta,
+ const J * const jetb) const;
+
+ // return the diJ (multiplied by _R2) for this jet assuming its NN
+ // info is correct
+ template <class J> double _bj_diJ(const J * const jeta) 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> inline J * _bj_of_hindex(
+ const int hist_index,
+ J * const head, J * const tail)
+ const {
+ J * res;
+ for(res = head; res<tail; res++) {
+ if (_jets[res->_jets_index].cluster_hist_index() == hist_index) {break;}
+ }
+ return res;
+ }
+
+
+ //-- remaining functions are different in various cases, so we
+ // will use templates but are not sure if they're useful...
+
+ /// 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_nocross(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
+ template <class J> void _bj_set_NN_crosscheck(J * const jeta,
+ J * const head, const J * const tail) const;
+
+
+
+ /// number of neighbours that a tile will have (rectangular geometry
+ /// gives 9 neighbours).
+ static const int n_tile_neighbours = 9;
+ //----------------------------------------------------------------------
+ /// The fundamental structures to be used for the tiled N^2 algorithm
+ /// (see CCN27-44 for some discussion of pattern of tiling)
+ struct Tile {
+ /// pointers to neighbouring tiles, including self
+ Tile * begin_tiles[n_tile_neighbours];
+ /// neighbouring tiles, excluding self
+ Tile ** surrounding_tiles;
+ /// half of neighbouring tiles, no self
+ Tile ** RH_tiles;
+ /// just beyond end of tiles
+ Tile ** end_tiles;
+ /// start of list of BriefJets contained in this tile
+ TiledJet * head;
+ /// sometimes useful to be able to tag a tile
+ bool tagged;
+ };
+ std::vector<Tile> _tiles;
+ double _tiles_eta_min, _tiles_eta_max;
+ double _tile_size_eta, _tile_size_phi;
+ int _n_tiles_phi,_tiles_ieta_min,_tiles_ieta_max;
+
+ // reasonably robust return of tile index given ieta and iphi, in particular
+ // it works even if iphi is negative
+ inline int _tile_index (int ieta, int iphi) const {
+ // note that (-1)%n = -1 so that we have to add _n_tiles_phi
+ // before performing modulo operation
+ return (ieta-_tiles_ieta_min)*_n_tiles_phi
+ + (iphi+_n_tiles_phi) % _n_tiles_phi;
+ }
+
+ // routines for tiled case, including some overloads of the plain
+ // BriefJet cases
+ int _tile_index(const double & eta, const double & phi) const;
+ void _tj_set_jetinfo ( TiledJet * const jet, const int _jets_index);
+ void _bj_remove_from_tiles(TiledJet * const jet);
+ void _initialise_tiles();
+ void _print_tiles(TiledJet * briefjets ) const;
+ 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);
+
+
+ //----------------------------------------------------------------------
+ /// fundamental structure for e+e- clustering
+ struct EEBriefJet {
+ double NN_dist; // obligatorily present
+ double kt2; // obligatorily present == E^2 in general
+ EEBriefJet * NN; // must be present too
+ int _jets_index; // must also be present!
+ //...........................................................
+ double nx, ny, nz; // our internal storage for fast distance calcs
+ };
+
+ /// to help instantiation
+ void _dummy_N2_cluster_instantiation();
+
+};
+
+
+//**********************************************************************
+//************** START OF INLINE MATERIAL ******************
+//**********************************************************************
+
+
+//----------------------------------------------------------------------
+// Transfer the initial jets into our internal structure
+template<class L> void ClusterSequence::_transfer_input_jets(
+ const std::vector<L> & pseudojets) {
+
+ // this will ensure that we can point to jets without difficulties
+ // arising.
+ _jets.reserve(pseudojets.size()*2);
+
+ // insert initial jets this way so that any type L that can be
+ // converted to a pseudojet will work fine (basically PseudoJet
+ // and any type that has [] subscript access to the momentum
+ // components, such as CLHEP HepLorentzVector).
+ for (unsigned int i = 0; i < pseudojets.size(); i++) {
+ _jets.push_back(pseudojets[i]);}
+
+}
+
+//----------------------------------------------------------------------
+// initialise from some generic type... Has to be made available
+// here in order for it the template aspect of it to work...
+template<class L> ClusterSequence::ClusterSequence (
+ const std::vector<L> & pseudojets,
+ const double & R,
+ const Strategy & strategy,
+ const bool & writeout_combinations) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering
+ _initialise_and_run(R,strategy,writeout_combinations);
+}
+
+
+//----------------------------------------------------------------------
+/// constructor of a jet-clustering sequence from a vector of
+/// four-momenta, with the jet definition specified by jet_def
+template<class L> ClusterSequence::ClusterSequence (
+ const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const bool & writeout_combinations) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering
+ _initialise_and_run(jet_def,writeout_combinations);
+}
+
+
+inline const std::vector<PseudoJet> & ClusterSequence::jets () const {
+ return _jets;
+}
+
+inline const std::vector<ClusterSequence::history_element> & ClusterSequence::history () const {
+ return _history;
+}
+
+inline unsigned int ClusterSequence::n_particles() const {return _initial_n;}
+
+
+
+//----------------------------------------------------------------------
+template <class J> inline void ClusterSequence::_bj_set_jetinfo(
+ J * const jetA, const int _jets_index) const {
+ jetA->eta = _jets[_jets_index].rap();
+ jetA->phi = _jets[_jets_index].phi_02pi();
+ jetA->kt2 = jet_scale_for_algorithm(_jets[_jets_index]);
+ jetA->_jets_index = _jets_index;
+ // initialise NN info as well
+ jetA->NN_dist = _R2;
+ jetA->NN = NULL;
+}
+
+
+
+
+//----------------------------------------------------------------------
+template <class J> inline double ClusterSequence::_bj_dist(
+ const J * const jetA, const J * const jetB) const {
+ double dphi = std::abs(jetA->phi - jetB->phi);
+ double deta = (jetA->eta - jetB->eta);
+ if (dphi > pi) {dphi = twopi - dphi;}
+ return dphi*dphi + deta*deta;
+}
+
+//----------------------------------------------------------------------
+template <class J> inline double ClusterSequence::_bj_diJ(const J * const jet) const {
+ double kt2 = jet->kt2;
+ if (jet->NN != NULL) {if (jet->NN->kt2 < kt2) {kt2 = jet->NN->kt2;}}
+ return jet->NN_dist * kt2;
+}
+
+
+//----------------------------------------------------------------------
+// set the NN for jet without checking whether in the process you might
+// have discovered a new nearest neighbour for another jet
+template <class J> inline void ClusterSequence::_bj_set_NN_nocross(
+ J * const jet, J * const head, const J * const tail) const {
+ double NN_dist = _R2;
+ J * NN = NULL;
+ if (head < jet) {
+ for (J * jetB = head; jetB != jet; jetB++) {
+ double dist = _bj_dist(jet,jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ }
+ }
+ if (tail > jet) {
+ for (J * jetB = jet+1; jetB != tail; jetB++) {
+ double dist = _bj_dist(jet,jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ }
+ }
+ jet->NN = NN;
+ jet->NN_dist = NN_dist;
+}
+
+
+//----------------------------------------------------------------------
+template <class J> inline void ClusterSequence::_bj_set_NN_crosscheck(J * const jet,
+ J * const head, const J * const tail) const {
+ double NN_dist = _R2;
+ J * NN = NULL;
+ for (J * jetB = head; jetB != tail; jetB++) {
+ double dist = _bj_dist(jet,jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ if (dist < jetB->NN_dist) {
+ jetB->NN_dist = dist;
+ jetB->NN = jet;
+ }
+ }
+ jet->NN = NN;
+ jet->NN_dist = NN_dist;
+}
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequence1GhostPassiveArea.hh 1134 2008-03-15 17:05:16Z salam $
+//
+// Copyright (c) 2005-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveArea.hh"
+#include<iostream>
+#include<vector>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds
+/// later...)
+class ClusterSequence1GhostPassiveArea : public ClusterSequenceActiveArea {
+public:
+
+ ClusterSequence1GhostPassiveArea() {}
+
+ /// constructor based on JetDefinition and 1GhostPassiveAreaSpec
+ template<class L> ClusterSequence1GhostPassiveArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false) ;
+
+ /// return an estimate for the number of empty jets -- one uses the
+ /// AreaBase one rather than the ActiveArea one (which for which we
+ /// do not have the information).
+ virtual double n_empty_jets(const RangeDefinition & range) const {
+ return ClusterSequenceAreaBase::n_empty_jets(range);
+ }
+
+protected:
+ /// does the initialisation and running specific to the passive
+ /// areas class
+ void _initialise_and_run_1GPA (const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false);
+
+private:
+
+ void _run_1GPA(const GhostedAreaSpec & area_spec);
+};
+
+
+
+
+template<class L> ClusterSequence1GhostPassiveArea::ClusterSequence1GhostPassiveArea
+(const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering for passive areas
+ _initialise_and_run_1GPA(jet_def, area_spec, writeout_combinations);
+
+}
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCE1GHOSTPASSIVEAREA_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceActiveArea.hh 1134 2008-03-15 17:05:16Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include<iostream>
+#include<vector>
+
+//------------ backwards compatibility with version 2.1 -------------
+// for backwards compatibility make ActiveAreaSpec name available
+#include "fastjet/ActiveAreaSpec.hh"
+#include "fastjet/ClusterSequenceWithArea.hh"
+//--------------------------------------------------------------------
+
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds
+/// later...)
+class ClusterSequenceActiveArea : public ClusterSequenceAreaBase {
+public:
+
+ /// default constructor
+ ClusterSequenceActiveArea() {}
+
+ /// constructor based on JetDefinition and GhostedAreaSpec
+ template<class L> ClusterSequenceActiveArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false) ;
+
+ virtual double area (const PseudoJet & jet) const {
+ return _average_area[jet.cluster_hist_index()];};
+ virtual double area_error (const PseudoJet & jet) const {
+ return _average_area2[jet.cluster_hist_index()];};
+
+ virtual PseudoJet area_4vector (const PseudoJet & jet) const {
+ return _average_area_4vector[jet.cluster_hist_index()];};
+
+ /// enum providing a variety of tentative strategies for estimating
+ /// the background (e.g. non-jet) activity in a highly populated event; the
+ /// one that has been most extensively tested is median.
+ enum mean_pt_strategies{median=0, non_ghost_median, pttot_over_areatot,
+ pttot_over_areatot_cut, mean_ratio_cut, play,
+ median_4vector};
+
+ /// return the transverse momentum per unit area according to one
+ /// of the above strategies; for some strategies (those with "cut"
+ /// in their name) the parameter "range" allows one to exclude a
+ /// subset of the jets for the background estimation, those that
+ /// have pt/area > median(pt/area)*range.
+ ///
+ /// NB: This call is OBSOLETE; use media_pt_per_unit_area from the
+ // ClusterSequenceAreaBase class instead
+ double pt_per_unit_area(mean_pt_strategies strat=median,
+ double range=2.0 ) const;
+
+ // following code removed -- now dealt with by AreaBase class (and
+ // this definition here conflicts with it).
+// /// fits a form pt_per_unit_area(y) = a + b*y^2 in the range
+// /// abs(y)<raprange (for negative raprange, it defaults to
+// /// _safe_rap_for_area).
+// void parabolic_pt_per_unit_area(double & a,double & b, double raprange=-1.0,
+// double exclude_above=-1.0,
+// bool use_area_4vector=false ) const;
+//
+ /// rewrite the empty area from the parent class, so as to use
+ /// all info at our disposal
+ /// return the total area, in the given y-phi range, that consists of ghost
+ /// jets or unclustered ghosts
+ virtual double empty_area(const RangeDefinition & range) const;
+
+ /// return the true number of empty jets (replaces
+ /// ClusterSequenceAreaBase::n_empty_jets(...))
+ virtual double n_empty_jets(const RangeDefinition & range) const;
+
+protected:
+ void _resize_and_zero_AA ();
+ void _initialise_AA(const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations,
+ bool & continue_running);
+
+ void _run_AA(const GhostedAreaSpec & area_spec);
+
+ void _postprocess_AA(const GhostedAreaSpec & area_spec);
+
+ /// does the initialisation and running specific to the active
+ /// areas class
+ void _initialise_and_run_AA (const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false);
+
+ /// transfer the history (and jet-momenta) from clust_seq to our
+ /// own internal structure while removing ghosts
+ void _transfer_ghost_free_history(
+ const ClusterSequenceActiveAreaExplicitGhosts & clust_seq);
+
+
+ /// transfer areas from the ClusterSequenceActiveAreaExplicitGhosts
+ /// object into our internal area bookkeeping...
+ void _transfer_areas(const std::vector<int> & unique_hist_order,
+ const ClusterSequenceActiveAreaExplicitGhosts & );
+
+ /// child classes benefit from having these at their disposal
+ std::valarray<double> _average_area, _average_area2;
+ std::valarray<PseudoJet> _average_area_4vector;
+
+ /// returns true if there are any particles whose transverse momentum
+ /// if so low that there's a risk of the ghosts having modified the
+ /// clustering sequence
+ bool has_dangerous_particles() const {return _has_dangerous_particles;}
+
+private:
+
+
+ double _non_jet_area, _non_jet_area2, _non_jet_number;
+
+ double _maxrap_for_area; // max rap where we put ghosts
+ double _safe_rap_for_area; // max rap where we trust jet areas
+
+ bool _has_dangerous_particles;
+
+
+ /// routine for extracting the tree in an order that will be independent
+ /// of any degeneracies in the recombination sequence that don't
+ /// affect the composition of the final jets
+ void _extract_tree(std::vector<int> &) const;
+ /// do the part of the extraction associated with pos, working
+ /// through its children and their parents
+ void _extract_tree_children(int pos, std::valarray<bool> &, const std::valarray<int> &, std::vector<int> &) const;
+ /// do the part of the extraction associated with the parents of pos.
+ void _extract_tree_parents (int pos, std::valarray<bool> &, const std::valarray<int> &, std::vector<int> &) const;
+
+ /// check if two jets have the same momentum to within the
+ /// tolerance (and if pt's are not the same we're forgiving and
+ /// look to see if the energy is the same)
+ void _throw_unless_jets_have_same_perp_or_E(const PseudoJet & jet,
+ const PseudoJet & refjet,
+ double tolerance,
+ const ClusterSequenceActiveAreaExplicitGhosts & jets_ghosted_seq
+ ) const;
+
+ /// since we are playing nasty games with seeds, we should warn
+ /// the user a few times
+ //static int _n_seed_warnings;
+ //const static int _max_seed_warnings = 10;
+
+ // record the number of repeats
+ int _area_spec_repeat;
+
+ /// a class for our internal storage of ghost jets
+ class GhostJet : public PseudoJet {
+ public:
+ GhostJet(const PseudoJet & j, double a) : PseudoJet(j), area(a){}
+ double area;
+ };
+
+ std::vector<GhostJet> _ghost_jets;
+ std::vector<GhostJet> _unclustered_ghosts;
+};
+
+
+
+
+template<class L> ClusterSequenceActiveArea::ClusterSequenceActiveArea
+(const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering for active areas
+ _initialise_and_run_AA(jet_def, area_spec, writeout_combinations);
+
+}
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEACTIVEAREA_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceActiveAreaExplicitGhosts.hh 1303 2008-10-29 16:42:09Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_
+#define __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/GhostedAreaSpec.hh"
+#include "fastjet/internal/LimitedWarning.hh"
+#include<iostream>
+#include<vector>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//======================================================================
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds
+/// later...)
+class ClusterSequenceActiveAreaExplicitGhosts :
+ public ClusterSequenceAreaBase {
+public:
+ /// constructor using a GhostedAreaSpec to specify how the area is
+ /// to be measured
+ template<class L> ClusterSequenceActiveAreaExplicitGhosts
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false)
+ : ClusterSequenceAreaBase() {
+ std::vector<L> * ghosts = NULL;
+ _initialise(pseudojets,jet_def,&area_spec,ghosts,0.0,
+ writeout_combinations); }
+
+ template<class L> ClusterSequenceActiveAreaExplicitGhosts
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const std::vector<L> & ghosts,
+ double ghost_area,
+ const bool & writeout_combinations = false)
+ : ClusterSequenceAreaBase() {
+ const GhostedAreaSpec * area_spec = NULL;
+ _initialise(pseudojets,jet_def,area_spec,&ghosts,ghost_area,
+ writeout_combinations); }
+
+
+ /// does the actual work of initialisation
+ template<class L> void _initialise
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec * area_spec,
+ const std::vector<L> * ghosts,
+ double ghost_area,
+ const bool & writeout_combinations);
+
+ //vector<PseudoJet> constituents (const PseudoJet & jet) const;
+
+ /// returns the number of hard particles (i.e. those supplied by the user).
+ unsigned int n_hard_particles() const;
+
+ /// returns the area of a jet
+ virtual double area (const PseudoJet & jet) const;
+
+ /// returns a four vector corresponding to the sum (E-scheme) of the
+ /// ghost four-vectors composing the jet area, normalised such that
+ /// for a small contiguous area the p_t of the extended_area jet is
+ /// equal to area of the jet.
+ virtual PseudoJet area_4vector (const PseudoJet & jet) const;
+
+ /// true if a jet is made exclusively of ghosts
+ virtual bool is_pure_ghost(const PseudoJet & jet) const;
+
+ /// true if the entry in the history index corresponds to a
+ /// ghost; if hist_ix does not correspond to an actual particle
+ /// (i.e. hist_ix < 0), then the result is false.
+ bool is_pure_ghost(int history_index) const;
+
+ /// this class does have explicit ghosts
+ virtual bool has_explicit_ghosts() const {return true;}
+
+ /// return the total area, up to |y|<maxrap, that consists of
+ /// unclustered ghosts
+ virtual double empty_area(const RangeDefinition & range) const;
+
+ /// returns the total area under study
+ double total_area () const;
+
+ /// returns the largest squared transverse momentum among
+ /// all ghosts
+ double max_ghost_perp2() const {return _max_ghost_perp2;}
+
+ /// returns true if there are any particles whose transverse momentum
+ /// if so low that there's a risk of the ghosts having modified the
+ /// clustering sequence
+ bool has_dangerous_particles() const {return _has_dangerous_particles;}
+
+private:
+
+ int _n_ghosts;
+ double _ghost_area;
+ std::vector<bool> _is_pure_ghost;
+ std::vector<double> _areas;
+ std::vector<PseudoJet> _area_4vectors;
+
+ // things related to checks for dangerous particles
+ double _max_ghost_perp2;
+ bool _has_dangerous_particles;
+ static LimitedWarning _warnings;
+
+ //static int _n_warn_dangerous_particles;
+ //static const int _max_warn_dangerous_particles = 5;
+
+
+ unsigned int _initial_hard_n;
+
+ /// adds the "ghost" momenta, which will be used to estimate
+ /// the jet area
+ void _add_ghosts(const GhostedAreaSpec & area_spec);
+
+ /// another way of adding ghosts
+ template<class L> void _add_ghosts (
+ const std::vector<L> & ghosts,
+ double ghost_area);
+
+ /// routine to be called after the processing is done so as to
+ /// establish summary information on all the jets (areas, whether
+ /// pure ghost, etc.)
+ void _post_process();
+
+};
+
+
+//----------------------------------------------------------------------
+// initialise from some generic type... Has to be made available
+// here in order for the template aspect of it to work...
+template<class L> void ClusterSequenceActiveAreaExplicitGhosts::_initialise
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec * area_spec,
+ const std::vector<L> * ghosts,
+ double ghost_area,
+ const bool & writeout_combinations) {
+ // don't reserve space yet -- will be done below
+
+ // insert initial jets this way so that any type L that can be
+ // converted to a pseudojet will work fine (basically PseudoJet
+ // and any type that has [] subscript access to the momentum
+ // components, such as CLHEP HepLorentzVector).
+ for (unsigned int i = 0; i < pseudojets.size(); i++) {
+ PseudoJet mom(pseudojets[i]);
+ //mom.set_user_index(0); // for user's particles (user index now lost...)
+ _jets.push_back(mom);
+ _is_pure_ghost.push_back(false);
+ }
+
+ _initial_hard_n = _jets.size();
+
+ if (area_spec != NULL) {
+ _add_ghosts(*area_spec);
+ } else {
+ _add_ghosts(*ghosts, ghost_area);
+ }
+
+ if (writeout_combinations) {
+ std::cout << "# Printing particles including ghosts\n";
+ for (unsigned j = 0; j < _jets.size(); j++) {
+ printf("%5u %20.13f %20.13f %20.13e\n",
+ j,_jets[j].rap(),_jets[j].phi_02pi(),_jets[j].kt2());
+ }
+ std::cout << "# Finished printing particles including ghosts\n";
+ }
+
+ // this will ensure that we can still point to jets without
+ // difficulties arising!
+ _jets.reserve(_jets.size()*2);
+
+ // run the clustering
+ _initialise_and_run(jet_def,writeout_combinations);
+
+ // set up all other information
+ _post_process();
+}
+
+
+inline unsigned int ClusterSequenceActiveAreaExplicitGhosts::n_hard_particles() const {return _initial_hard_n;}
+
+
+//----------------------------------------------------------------------
+/// add an explicitly specified bunch of ghosts
+template<class L> void ClusterSequenceActiveAreaExplicitGhosts::_add_ghosts (
+ const std::vector<L> & ghosts,
+ double ghost_area) {
+
+
+ for (unsigned i = 0; i < ghosts.size(); i++) {
+ _is_pure_ghost.push_back(true);
+ _jets.push_back(ghosts[i]);
+ }
+ // and record some info about ghosts
+ _ghost_area = ghost_area;
+ _n_ghosts = ghosts.size();
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEACTIVEAREAEXPLICITGHOSTS_HH_
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceArea.hh 1303 2008-10-29 16:42:09Z salam $
+//
+// Copyright (c) 2006-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEAREA_HH__
+
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include "fastjet/ClusterSequenceActiveArea.hh"
+#include "fastjet/ClusterSequenceActiveAreaExplicitGhosts.hh"
+#include "fastjet/ClusterSequencePassiveArea.hh"
+#include "fastjet/ClusterSequenceVoronoiArea.hh"
+#include "fastjet/AreaDefinition.hh"
+
+namespace fastjet {
+
+/// General class for user to obtain ClusterSequence with additional
+/// area information.
+///
+/// Based on the area_def, it automatically dispatches the work to the
+/// appropriate actual ClusterSequenceAreaBase-derived-class to do the
+/// real work.
+class ClusterSequenceArea : public ClusterSequenceAreaBase {
+public:
+ /// main constructor
+ template<class L> ClusterSequenceArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const AreaDefinition & area_def_in) : _area_def(area_def_in) {
+ initialize_and_run_cswa(pseudojets, jet_def);
+ }
+
+ /// constructor with a GhostedAreaSpec
+ template<class L> ClusterSequenceArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec) : _area_def(area_spec){
+ initialize_and_run_cswa(pseudojets, jet_def);
+ }
+
+ /// constructor with a VoronoiAreaSpec
+ template<class L> ClusterSequenceArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const VoronoiAreaSpec & area_spec) : _area_def(area_spec){
+ initialize_and_run_cswa(pseudojets, jet_def);
+ }
+
+ /// return a reference to the area definition
+ const AreaDefinition & area_def() const {return _area_def;}
+
+
+ /// return the area associated with the given jet
+ virtual double area (const PseudoJet & jet) const {
+ return _area_base->area(jet);}
+
+ /// return the error (uncertainty) associated with the determination
+ /// of the area of this jet
+ virtual double area_error (const PseudoJet & jet) const {
+ return _area_base->area_error(jet);}
+
+ /// return the 4-vector area
+ virtual PseudoJet area_4vector(const PseudoJet & jet) const {
+ return _area_base->area_4vector(jet);}
+
+ // /// return the total area, up to |y|<maxrap, that is free of jets
+ // virtual double empty_area(double maxrap) const {
+ // return _area_base->empty_area(maxrap);}
+ //
+ // /// return something similar to the number of pure ghost jets
+ // /// in the given rapidity range in an active area case.
+ // /// For the local implementation we return empty_area/(0.55 pi R^2),
+ // /// based on measured properties of ghost jets with kt and cam. Note
+ // /// that the number returned is a double.
+ // virtual double n_empty_jets(double maxrap) const {
+ // return _area_base->n_empty_jets(maxrap);
+
+ /// return the total area, in the given rap-phi range, that is free of jets
+ virtual double empty_area(const RangeDefinition & range) const {
+ return _area_base->empty_area(range);}
+
+ /// return something similar to the number of pure ghost jets
+ /// in the given rap-phi range in an active area case.
+ /// For the local implementation we return empty_area/(0.55 pi R^2),
+ /// based on measured properties of ghost jets with kt and cam. Note
+ /// that the number returned is a double.
+ virtual double n_empty_jets(const RangeDefinition & range) const {
+ return _area_base->n_empty_jets(range);
+ }
+
+ /// true if a jet is made exclusively of ghosts
+ virtual bool is_pure_ghost(const PseudoJet & jet) const {
+ return _area_base->is_pure_ghost(jet);
+ }
+
+ /// true if this ClusterSequence has explicit ghosts
+ virtual bool has_explicit_ghosts() const {
+ return _area_base->has_explicit_ghosts();
+ }
+
+
+ /// overload version of what's in the ClusterSequenceAreaBase class, which
+ /// additionally checks compatibility between "range" and region in which
+ /// ghosts are thrown.
+ virtual void get_median_rho_and_sigma(const std::vector<PseudoJet> & all_jets,
+ const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma,
+ double & mean_area,
+ bool all_are_incl = false) const {
+ _warn_if_range_unsuitable(range);
+ ClusterSequenceAreaBase::get_median_rho_and_sigma(
+ all_jets, range, use_area_4vector,
+ median, sigma, mean_area, all_are_incl);
+ }
+
+ /// overload version of what's in the ClusterSequenceAreaBase class,
+ /// which actually just does the same thing as the base version (but
+ /// since we've overridden the 5-argument version above, we have to
+ /// override the 4-argument version too.
+ virtual void get_median_rho_and_sigma(const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma) const {
+ ClusterSequenceAreaBase::get_median_rho_and_sigma(range,use_area_4vector,
+ median,sigma);
+ }
+
+ /// overload version of what's in the ClusterSequenceAreaBase class,
+ /// which actually just does the same thing as the base version (but
+ /// since we've overridden the multi-argument version above, we have to
+ /// override the 5-argument version too.
+ virtual void get_median_rho_and_sigma(const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma,
+ double & mean_area) const {
+ ClusterSequenceAreaBase::get_median_rho_and_sigma(range,use_area_4vector,
+ median,sigma, mean_area);
+ }
+
+
+ /// overload version of what's in the ClusterSequenceAreaBase class, which
+ /// additionally checks compatibility between "range" and region in which
+ /// ghosts are thrown.
+ virtual void parabolic_pt_per_unit_area(double & a, double & b,
+ const RangeDefinition & range,
+ double exclude_above=-1.0,
+ bool use_area_4vector=false) const {
+ _warn_if_range_unsuitable(range);
+ ClusterSequenceAreaBase::parabolic_pt_per_unit_area(
+ a,b,range, exclude_above, use_area_4vector);
+ }
+
+
+private:
+
+ /// print a warning if the range is unsuitable for the current
+ /// calculation of the area (e.g. because ghosts do not extend
+ /// far enough).
+ void _warn_if_range_unsuitable(const RangeDefinition & range) const;
+
+ template<class L> void initialize_and_run_cswa (
+ const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def);
+
+ std::auto_ptr<ClusterSequenceAreaBase> _area_base;
+ AreaDefinition _area_def;
+ static LimitedWarning _range_warnings;
+
+};
+
+//----------------------------------------------------------------------
+template<class L> void ClusterSequenceArea::initialize_and_run_cswa(
+ const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def)
+ {
+
+ ClusterSequenceAreaBase * _area_base_ptr;
+ switch(_area_def.area_type()) {
+ case active_area:
+ _area_base_ptr = new ClusterSequenceActiveArea(pseudojets,
+ jet_def,
+ _area_def.ghost_spec());
+ break;
+ case active_area_explicit_ghosts:
+ _area_base_ptr = new ClusterSequenceActiveAreaExplicitGhosts(pseudojets,
+ jet_def,
+ _area_def.ghost_spec());
+ break;
+ case voronoi_area:
+ _area_base_ptr = new ClusterSequenceVoronoiArea(pseudojets,
+ jet_def,
+ _area_def.voronoi_spec());
+ break;
+ case one_ghost_passive_area:
+ _area_base_ptr = new ClusterSequence1GhostPassiveArea(pseudojets,
+ jet_def,
+ _area_def.ghost_spec());
+ break;
+ case passive_area:
+ _area_base_ptr = new ClusterSequencePassiveArea(pseudojets,
+ jet_def,
+ _area_def.ghost_spec());
+ break;
+ default:
+ std::cerr << "Error: unrecognized area_type in ClusterSequenceArea:"
+ << _area_def.area_type() << std::endl;
+ exit(-1);
+ }
+ // now copy across the information from the area base class
+ _area_base = std::auto_ptr<ClusterSequenceAreaBase>(_area_base_ptr);
+ transfer_from_sequence(*_area_base);
+}
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEAREA_HH__
+
+
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceAreaBase.hh 1503 2009-04-06 11:32:52Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
+#define __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
+
+#include "fastjet/ClusterSequence.hh"
+#include "fastjet/internal/LimitedWarning.hh"
+#include "fastjet/RangeDefinition.hh"
+
+namespace fastjet {
+
+/// base class that sets interface for extensions of ClusterSequence
+/// that provide information about the area of each jet;
+///
+/// the virtual functions here all return 0, since no area determination
+/// is implemented.
+class ClusterSequenceAreaBase : public ClusterSequence {
+public:
+
+ /// a constructor which just carries out the construction of the
+ /// parent class
+ template<class L> ClusterSequenceAreaBase
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const bool & writeout_combinations = false) :
+ ClusterSequence(pseudojets, jet_def, writeout_combinations) {}
+
+
+ /// default constructor
+ ClusterSequenceAreaBase() {}
+
+
+ /// destructor
+ virtual ~ClusterSequenceAreaBase() {}
+
+
+ /// return the area associated with the given jet; this base class
+ /// returns 0.
+ virtual double area (const PseudoJet & jet) const {return 0.0;}
+
+ /// return the error (uncertainty) associated with the determination
+ /// of the area of this jet; this base class returns 0.
+ virtual double area_error (const PseudoJet & jet) const {return 0.0;}
+
+ /// return a PseudoJet whose 4-vector is defined by the following integral
+ ///
+ /// \int drap d\phi PseudoJet("rap,phi,pt=one") *
+ /// * Theta("rap,phi inside jet boundary")
+ ///
+ /// where PseudoJet("rap,phi,pt=one") is a 4-vector with the given
+ /// rapidity (rap), azimuth (phi) and pt=1, while Theta("rap,phi
+ /// inside jet boundary") is a function that is 1 when rap,phi
+ /// define a direction inside the jet boundary and 0 otherwise.
+ ///
+ /// This base class returns a null 4-vector.
+ virtual PseudoJet area_4vector(const PseudoJet & jet) const {
+ return PseudoJet(0.0,0.0,0.0,0.0);}
+
+ /// true if a jet is made exclusively of ghosts
+ ///
+ /// NB: most area classes do not give any explicit ghost jets, but
+ /// some do, and they should replace this function with their own
+ /// version.
+ virtual bool is_pure_ghost(const PseudoJet & jet) const {
+ return false;
+ }
+
+ /// returns true if ghosts are explicitly included within
+ /// jets for this ClusterSequence;
+ ///
+ /// Derived classes that do include explicit ghosts should provide
+ /// an alternative version of this routine and set it properly.
+ virtual bool has_explicit_ghosts() const {
+ return false;
+ }
+
+ /// return the total area, within range, that is free of jets, in
+ /// general based on the inclusive jets
+ virtual double empty_area(const RangeDefinition & range) const;
+
+ /// return the total area, within range, that is free of jets, based
+ /// on the supplied all_jets
+ double empty_area_from_jets(const std::vector<PseudoJet> & all_jets,
+ const RangeDefinition & range) const;
+
+ /// return something similar to the number of pure ghost jets
+ /// in the given range in an active area case.
+ /// For the local implementation we return empty_area/(0.55 pi R^2),
+ /// based on measured properties of ghost jets with kt and cam. Note
+ /// that the number returned is a double.
+ virtual double n_empty_jets(const RangeDefinition & range) const {
+ double R = jet_def().R();
+ return empty_area(range)/(0.55*pi*R*R);
+ }
+
+ /// the median of (pt/area) for jets contained within range,
+ /// making use also of the info on n_empty_jets
+ double median_pt_per_unit_area(const RangeDefinition & range) const;
+
+ /// the median of (pt/area_4vector) for jets contained within
+ /// making use also of the info on n_empty_jets
+ double median_pt_per_unit_area_4vector(const RangeDefinition & range) const;
+
+ /// the function that does the work for median_pt_per_unit_area and
+ /// median_pt_per_unit_area_4vector:
+ /// - something_is_area_4vect = false -> use plain area
+ /// - something_is_area_4vect = true -> use 4-vector area
+ double median_pt_per_unit_something(
+ const RangeDefinition & range, bool use_area_4vector) const;
+
+ /// using jets withing range (and with 4-vector areas if
+ /// use_area_4vector), calculate the median pt/area, as well as an
+ /// "error" (uncertainty), which is defined as the 1-sigma
+ /// half-width of the distribution of pt/A, obtained by looking for
+ /// the point below which we have (1-0.6827)/2 of the jets
+ /// (including empty jets).
+ ///
+ /// The subtraction for a jet with uncorrected pt pt^U and area A is
+ ///
+ /// pt^S = pt^U - median*A +- sigma*sqrt(A)
+ ///
+ /// where the error is only that associated with the fluctuations
+ /// in the noise and not that associated with the noise having
+ /// caused changes in the hard-particle content of the jet.
+ ///
+ /// NB: subtraction may also be done with 4-vector area of course,
+ /// and this is recommended for jets with larger values of R, as
+ /// long as rho has also been determined with a 4-vector area;
+ /// using a scalar area causes one to neglect terms of relative
+ /// order $R^2/8$ in the jet $p_t$.
+ virtual void get_median_rho_and_sigma(const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma,
+ double & mean_area) const;
+
+ /// a more advanced version of get_median_rho_and_sigma, which allows
+ /// one to use any "view" of the event containing all jets (so that,
+ /// e.g. one might use Cam on a different resolution scale without
+ /// have to rerun the algorithm).
+ ///
+ /// By default it will assume that "all" are not inclusive jets,
+ /// so that in dealing with empty area it has to calculate
+ /// the number of empty jets based on the empty area and the
+ /// the observed <area> of jets rather than a surmised area
+ ///
+ /// Note that for small effective radii, this can cause problems
+ /// because the harder jets get an area >> <ghost-jet-area>
+ /// and so the estimate comes out all wrong. In these situations
+ /// it is highly advisable to use an area with explicit ghosts, since
+ /// then the "empty" jets are actually visible.
+ virtual void get_median_rho_and_sigma(const std::vector<PseudoJet> & all_jets,
+ const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma,
+ double & mean_area,
+ bool all_are_inclusive = false) const;
+
+ /// same as the full version of get_median_rho_and_error, but without
+ /// access to the mean_area
+ virtual void get_median_rho_and_sigma(const RangeDefinition & range,
+ bool use_area_4vector,
+ double & median, double & sigma) const {
+ double mean_area;
+ get_median_rho_and_sigma(range, use_area_4vector,
+ median, sigma, mean_area);
+ }
+
+
+ /// fits a form pt_per_unit_area(y) = a + b*y^2 in the range "range".
+ /// exclude_above allows one to exclude large values of pt/area from fit.
+ /// (if negative, the cut is discarded)
+ /// use_area_4vector = true uses the 4vector areas.
+ virtual void parabolic_pt_per_unit_area(double & a, double & b,
+ const RangeDefinition & range,
+ double exclude_above=-1.0,
+ bool use_area_4vector=false) const;
+
+ /// return a vector of all subtracted jets, using area_4vector, given rho.
+ /// Only inclusive_jets above ptmin are subtracted and returned.
+ /// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+ /// i.e. not necessarily ordered in pt once subtracted
+ std::vector<PseudoJet> subtracted_jets(const double rho,
+ const double ptmin=0.0) const;
+
+ /// return a vector of subtracted jets, using area_4vector.
+ /// Only inclusive_jets above ptmin are subtracted and returned.
+ /// the ordering is the same as that of sorted_by_pt(cs.inclusive_jets()),
+ /// i.e. not necessarily ordered in pt once subtracted
+ std::vector<PseudoJet> subtracted_jets(const RangeDefinition & range,
+ const double ptmin=0.0) const;
+
+ /// return a subtracted jet, using area_4vector, given rho
+ PseudoJet subtracted_jet(const PseudoJet & jet,
+ const double rho) const;
+
+ /// return a subtracted jet, using area_4vector; note
+ /// that this is potentially inefficient if repeatedly used for many
+ /// different jets, because rho will be recalculated each time
+ /// around.
+ PseudoJet subtracted_jet(const PseudoJet & jet,
+ const RangeDefinition & range) const;
+
+ /// return the subtracted pt, given rho
+ double subtracted_pt(const PseudoJet & jet,
+ const double rho,
+ bool use_area_4vector=false) const;
+
+ /// return the subtracted pt; note that this is
+ /// potentially inefficient if repeatedly used for many different
+ /// jets, because rho will be recalculated each time around.
+ double subtracted_pt(const PseudoJet & jet,
+ const RangeDefinition & range,
+ bool use_area_4vector=false) const;
+
+
+private:
+ /// handle warning messages
+ static LimitedWarning _warnings;
+
+ /// check the jet algorithm is suitable (and if not issue a warning)
+ void _check_jet_alg_good_for_median() const;
+
+};
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEAREABASE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequencePassiveArea.hh 1134 2008-03-15 17:05:16Z salam $
+//
+// Copyright (c) 2005-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
+
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/ClusterSequence1GhostPassiveArea.hh"
+#include<iostream>
+#include<vector>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// Class that behaves essentially like ClusterSequence except
+/// that it also provides access to the area of a jet (which
+/// will be a random quantity... Figure out what to do about seeds
+/// later...)
+class ClusterSequencePassiveArea : public ClusterSequence1GhostPassiveArea {
+public:
+
+ /// constructor based on JetDefinition and PassiveAreaSpec
+ template<class L> ClusterSequencePassiveArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false) ;
+
+ /// return an empty area that's appropriate to the passive area
+ /// determination carried out
+ virtual double empty_area(const RangeDefinition & range) const;
+
+private:
+
+ /// does the initialisation and running specific to the passive
+ /// areas class
+ void _initialise_and_run_PA (const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations = false);
+
+};
+
+
+
+
+template<class L> ClusterSequencePassiveArea::ClusterSequencePassiveArea
+(const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const GhostedAreaSpec & area_spec,
+ const bool & writeout_combinations) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering for passive areas
+ _initialise_and_run_PA(jet_def, area_spec, writeout_combinations);
+
+}
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEPASSIVEAREA_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceVoronoiArea.hh 621 2007-05-09 10:34:30Z salam $
+//
+// Copyright (c) 2005-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/AreaDefinition.hh"
+#include "fastjet/ClusterSequenceAreaBase.hh"
+#include <memory>
+#include <vector>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/**
+ * \class ClusterSequenceVoronoiArea
+ * Handle the computation of Voronoi jet area.
+ */
+class ClusterSequenceVoronoiArea : public ClusterSequenceAreaBase {
+public:
+ /// template ctor
+ /// \param pseudojet list of jets (template type)
+ /// \param jet_def jet definition
+ /// \param effective_Rfact effective radius
+ /// \param writeout_combinations ??????
+ template<class L> ClusterSequenceVoronoiArea
+ (const std::vector<L> & pseudojets,
+ const JetDefinition & jet_def,
+ const VoronoiAreaSpec & spec = VoronoiAreaSpec(),
+ const bool & writeout_combinations = false);
+
+ /// default dtor
+ ~ClusterSequenceVoronoiArea();
+
+ /// return the area associated with the given jet
+ virtual inline double area(const PseudoJet & jet) const {
+ return _voronoi_area[jet.cluster_hist_index()];};
+
+ /// return a 4-vector area associated with the given jet -- stricly
+ /// this is not the exact 4-vector area, but rather an approximation
+ /// made of sums of centres of all Voronoi cells in jet, each
+ /// contributing with a normalisation equal to the area of the cell
+ virtual inline PseudoJet area_4vector(const PseudoJet & jet) const {
+ return _voronoi_area_4vector[jet.cluster_hist_index()];};
+
+ /// return the error of the area associated with the given jet
+ /// (0 by definition for a voronoi area)
+ virtual inline double area_error(const PseudoJet & jet) const {
+ return 0.0;};
+
+ /// passive area calculator -- to be defined in the .cc file (it will do
+ /// the true hard work)
+ class VoronoiAreaCalc;
+
+
+private:
+ /// initialisation of the Voronoi Area
+ void _initializeVA();
+
+ std::vector<double> _voronoi_area; ///< vector containing the result
+ std::vector<PseudoJet> _voronoi_area_4vector; ///< vector containing approx 4-vect areas
+ VoronoiAreaCalc *_pa_calc; ///< area calculator
+ double _effective_Rfact; ///< effective radius
+};
+
+
+
+
+/// template constructor need to be specified in the header!
+//----------------------------------------------------------------------
+template<class L> ClusterSequenceVoronoiArea::ClusterSequenceVoronoiArea
+(const std::vector<L> &pseudojets,
+ const JetDefinition &jet_def,
+ const VoronoiAreaSpec & spec,
+ const bool & writeout_combinations) :
+ _effective_Rfact(spec.effective_Rfact()) {
+
+ // transfer the initial jets (type L) into our own array
+ _transfer_input_jets(pseudojets);
+
+ // run the clustering
+ _initialise_and_run(jet_def,writeout_combinations);
+
+ // the jet clustering's already been done, now worry about areas...
+ _initializeVA();
+}
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEVORONOIAREA_HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClusterSequenceWithArea.hh 699 2007-06-04 20:20:42Z salam $
+//
+// Copyright (c) 2006-2007, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+#define __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+
+#include "fastjet/ClusterSequenceAreaBase.hh"
+
+namespace fastjet {
+
+//----- backwards compatibility with version 2.1 ---------------
+typedef ClusterSequenceAreaBase ClusterSequenceWithArea;
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLUSTERSEQUENCEWITHAREA_HH__
+
+
--- /dev/null
+#ifndef __EECAMBRIDGEPLUGIN_HH__
+#define __EECAMBRIDGEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: EECambridgePlugin.hh 1491 2009-03-11 17:04:38Z salam $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#include "fastjet/JetDefinition.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class ClusterSequence;
+
+//----------------------------------------------------------------------
+//
+/// EECambridgePlugin is a plugin for fastjet (v2.4 upwards)
+///
+/// It implements the Cambridge algorithm, as defined in
+///
+/// Better jet clustering algorithms
+/// Yuri Dokshitzer, Garth Leder, Stefano Moretti, Bryan Webber
+/// JHEP 9708 (1997) 001
+/// http://www-spires.slac.stanford.edu/spires/find/hep/www?rawcmd=FIND+j+JHEPA%2C9708%2C001
+///
+/// On construction one must supply a ycut value.
+///
+/// To get the jets at the end call ClusterSequence::inclusive_jets();
+///
+class EECambridgePlugin : public JetDefinition::Plugin {
+public:
+ /// Main constructor for the EECambridge Plugin class.
+ /// It takes the dimensionless parameter ycut (the Q value for normalisation
+ /// of the kt-distances is taken from the sum of all particle energies).
+ EECambridgePlugin (double ycut) : _ycut(ycut) {}
+
+ /// copy constructor
+ EECambridgePlugin (const EECambridgePlugin & plugin) {
+ *this = plugin;
+ }
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const;
+
+ double ycut() const {return _ycut;}
+
+ /// the plugin mechanism's standard way of accessing the jet radius.
+ /// This must be set to return something sensible, even if R
+ /// does not make sense for this algorithm!
+ virtual double R() const {return 1.0;}
+
+private:
+ double _ycut;
+};
+
+} // fastjet namespace
+
+#endif // __EECAMBRIDGEPLUGIN_HH__
+
--- /dev/null
+//STARTHEADER
+// $Id: Error.hh 389 2006-12-14 18:29:16Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+
+#ifndef __FASTJET_ERROR_HH__
+#define __FASTJET_ERROR_HH__
+
+#include<iostream>
+#include<string>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// class corresponding to errors that will be thrown by fastjet
+class Error {
+public:
+ // constructors
+ Error() {;};
+ Error(const std::string & message) {
+ _message = message;
+ if (_print_errors) std::cerr << "fastjet::Error: "<<message << std::endl;
+ };
+
+ std::string message() const {return _message;};
+
+ static void set_print_errors(bool print_errors) {
+ _print_errors = print_errors;};
+
+private:
+ std::string _message;
+ static bool _print_errors;
+};
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_ERROR_HH__
--- /dev/null
+//STARTHEADER
+// $Id: GhostedAreaSpec.hh 1273 2008-08-11 18:22:55Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_GHOSTEDAREASPEC_HH__
+#define __FASTJET_GHOSTEDAREASPEC_HH__
+
+#include<vector>
+#include<string>
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/internal/BasicRandom.hh"
+
+//
+#define STATIC_GENERATOR 1
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// namespace to hold default parameters for the active area spec
+namespace gas {
+ const double def_ghost_maxrap = 6.0;
+ const int def_repeat = 1;
+ const double def_ghost_area = 0.01;
+ const double def_grid_scatter = 1.0;
+ const double def_kt_scatter = 0.1;
+ const double def_mean_ghost_kt = 1e-100;
+}
+
+//----------------------------------------------------------------------
+/// Class that defines the parameters that go into the measurement
+/// of active jet areas.
+class GhostedAreaSpec {
+public:
+ /// default constructor
+ GhostedAreaSpec(): _ghost_maxrap (gas::def_ghost_maxrap),
+ _ghost_rap_offset(0.0),
+ _repeat (gas::def_repeat),
+ _ghost_area (gas::def_ghost_area),
+ _grid_scatter (gas::def_grid_scatter),
+ _kt_scatter (gas::def_kt_scatter),
+ _mean_ghost_kt(gas::def_mean_ghost_kt),
+ _actual_ghost_area(-1.0) {_initialize();};
+
+ /// explicit constructor
+ explicit GhostedAreaSpec(double ghost_maxrap,
+ int repeat = gas::def_repeat,
+ double ghost_area = gas::def_ghost_area,
+ double grid_scatter = gas::def_grid_scatter,
+ double kt_scatter = gas::def_kt_scatter,
+ double mean_ghost_kt = gas::def_mean_ghost_kt
+ ):
+ _ghost_maxrap(ghost_maxrap),
+ _ghost_rap_offset(0.0),
+ _repeat(repeat),
+ _ghost_area(ghost_area),
+ _grid_scatter(grid_scatter),
+ _kt_scatter(kt_scatter),
+ _mean_ghost_kt(mean_ghost_kt),
+ _actual_ghost_area(-1.0) {_initialize();};
+
+ /// explicit constructor
+ explicit GhostedAreaSpec(double ghost_minrap,
+ double ghost_maxrap,
+ int repeat = gas::def_repeat,
+ double ghost_area = gas::def_ghost_area,
+ double grid_scatter = gas::def_grid_scatter,
+ double kt_scatter = gas::def_kt_scatter,
+ double mean_ghost_kt = gas::def_mean_ghost_kt
+ ):
+ _ghost_maxrap (0.5*(ghost_maxrap - ghost_minrap)),
+ _ghost_rap_offset(0.5*(ghost_maxrap + ghost_minrap)),
+ _repeat(repeat),
+ _ghost_area(ghost_area),
+ _grid_scatter(grid_scatter),
+ _kt_scatter(kt_scatter),
+ _mean_ghost_kt(mean_ghost_kt),
+ _actual_ghost_area(-1.0) {_initialize();};
+
+
+ /// does the initialization of actual ghost parameters
+ void _initialize();
+
+ // for accessing values set by the user
+ inline double ghost_etamax() const {return _ghost_maxrap;};
+ inline double ghost_maxrap() const {return _ghost_maxrap;};
+ inline double ghost_area () const {return _ghost_area ;};
+ inline double grid_scatter() const {return _grid_scatter;};
+ inline double kt_scatter () const {return _kt_scatter ;};
+ inline double mean_ghost_kt() const {return _mean_ghost_kt ;};
+ inline int repeat () const {return _repeat ;};
+
+ // for accessing values
+ inline double actual_ghost_area() const {return _actual_ghost_area;};
+ inline int n_ghosts() const {return _n_ghosts;};
+
+ // when explicitly modifying values, sometimes call the initializer
+ inline void set_ghost_area (double val) {_ghost_area = val; _initialize();};
+ inline void set_ghost_etamax(double val) {_ghost_maxrap = val; _initialize();};
+ inline void set_ghost_maxrap(double val) {_ghost_maxrap = val; _initialize();};
+ inline void set_grid_scatter(double val) {_grid_scatter = val; };
+ inline void set_kt_scatter (double val) {_kt_scatter = val; };
+ inline void set_mean_ghost_kt(double val){_mean_ghost_kt = val; };
+ inline void set_repeat (int val) {_repeat = val; };
+
+ /// return nphi (ghosts layed out (-nrap, 0..nphi-1), (-nrap+1,0..nphi-1),
+ /// ... (nrap,0..nphi-1)
+ inline int nphi() const {return _nphi;}
+ inline int nrap() const {return _nrap;}
+
+ /// get all relevant information about the status of the
+ /// random number generator, so that it can be reset subsequently
+ /// with set_random_status.
+ inline void get_random_status(std::vector<int> & __iseed) const {
+ _random_generator.get_status(__iseed);}
+
+ /// set the status of the random number generator, as obtained
+ /// previously with get_random_status. Note that the random
+ /// generator is a static member of the class, i.e. common to all
+ /// instances of the class --- so if you modify the random for this
+ /// instance, you modify it for all instances.
+ inline void set_random_status(const std::vector<int> & __iseed) {
+ _random_generator.set_status(__iseed);}
+
+ inline void checkpoint_random() {get_random_status(_random_checkpoint);}
+ inline void restore_checkpoint_random() {set_random_status(_random_checkpoint);}
+
+ /// for a summary
+ std::string description() const;
+
+ /// push the ghost 4-momenta onto the back of the vector of PseudoJets
+ void add_ghosts(std::vector<PseudoJet> & ) const;
+
+ /// very deprecated public access to a random number
+ /// from the internal generator
+ inline double random_at_own_risk() const {return _our_rand();};
+ /// very deprecated public access to the generator itself
+ inline BasicRandom<double> & generator_at_own_risk() const {
+ return _random_generator;}
+
+private:
+
+ // quantities that determine nature and distribution of ghosts
+ double _ghost_maxrap;
+ double _ghost_rap_offset;
+ int _repeat ;
+ double _ghost_area ;
+ double _grid_scatter;
+ double _kt_scatter ;
+ double _mean_ghost_kt;
+
+ // derived quantities
+ double _actual_ghost_area, _dphi, _drap;
+ int _n_ghosts, _nphi, _nrap;
+
+
+ std::vector<int> _random_checkpoint;
+ static BasicRandom<double> _random_generator;
+ //mutable BasicRandom<double> _random_generator;
+
+ inline double _our_rand() const {return _random_generator();};
+
+};
+
+////----------------------------------------------------------------------
+//class 1GhostPassiveAreaSpec : public GhostedAreaSpec {
+//public:
+//}
+
+} // fastjet namespace
+
+#endif // __FASTJET_GHOSTEDAREASPEC_HH__
--- /dev/null
+#ifndef __JADEPLUGIN_HH__
+#define __JADEPLUGIN_HH__
+
+//STARTHEADER
+// $Id: JadePlugin.hh 1491 2009-03-11 17:04:38Z salam $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include "fastjet/JetDefinition.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+// forward declaration to reduce includes
+class ClusterSequence;
+
+//----------------------------------------------------------------------
+//
+/// JadePlugin is a plugin for fastjet (v2.4 upwards)
+///
+/// It implements the JADE algorithm, which is an e+e- sequential
+/// recombination algorithm with interparticle distance
+///
+/// dij = 2 E_i E_j (1 - cos theta_ij)
+///
+/// or equivalently
+///
+/// yij = dij/E_{vis}^2
+///
+/// This corresponds to the distance measured used in
+///
+/// "Experimental Investigation of the Energy Dependence of the Strong Coupling Strength."
+/// JADE Collaboration (S. Bethke et al.)
+/// Phys.Lett.B213:235,1988
+///
+/// The JADE article carries out particle recombinations in the
+/// E-scheme (4-vector recombination), which is the default procedure for this
+/// plugin.
+///
+/// NOTE: other widely used schemes include E0, P, P0; however they also
+/// involve modifications to the distance measure. Be sure of
+/// what you're doing before running a JADE type algorithm.
+///
+/// To access the jets with a given ycut value (clustering stops once
+/// all yij > ycut), use
+///
+/// vector<PseudoJet> jets = cluster_sequence.exclusive_jets_ycut(ycut);
+///
+/// and related routines.
+///
+class JadePlugin : public JetDefinition::Plugin {
+public:
+ /// Main constructor for the Jade Plugin class.
+ JadePlugin (){}
+
+ /// copy constructor
+ JadePlugin (const JadePlugin & plugin) {
+ *this = plugin;
+ }
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const;
+
+ /// the plugin mechanism's standard way of accessing the jet radius.
+ /// This must be set to return something sensible, even if R
+ /// does not make sense for this algorithm!
+ virtual double R() const {return 1.0;}
+
+private:
+
+};
+
+} // fastjet namespace
+
+#endif // __JADEPLUGIN_HH__
+
--- /dev/null
+//STARTHEADER
+// $Id: JetDefinition.hh 1402 2009-01-21 18:03:54Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_JETDEFINITION_HH__
+#define __FASTJET_JETDEFINITION_HH__
+
+#include<cassert>
+#include "fastjet/internal/numconsts.hh"
+#include "fastjet/PseudoJet.hh"
+#include<string>
+#include<memory>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// return a string containing information about the release
+// NB: (implemented in ClusterSequence.cc but defined here because
+// this is a visible location)
+std::string fastjet_version_string();
+
+//======================================================================
+/// the various options for the algorithmic strategy to adopt in
+/// clustering events with kt and cambridge style algorithms.
+enum Strategy {
+ /// fastest form about 500..10^4
+ N2MinHeapTiled = -4,
+ /// fastest from about 50..500
+ N2Tiled = -3,
+ /// legacy
+ N2PoorTiled = -2,
+ /// fastest below 50
+ N2Plain = -1,
+ /// worse even than the usual N^3 algorithms
+ N3Dumb = 0,
+ /// automatic selection of the best (based on N)
+ Best = 1,
+ /// best of the NlnN variants -- best overall for N>10^4
+ NlnN = 2,
+ /// legacy N ln N using 3pi coverage of cylinder
+ NlnN3pi = 3,
+ /// legacy N ln N using 4pi coverage of cylinder
+ NlnN4pi = 4,
+ /// Chan's closest pair method (in a variant with 4pi coverage),
+ /// for use exclusively with the Cambridge algorithm
+ NlnNCam4pi = 14,
+ NlnNCam2pi2R = 13,
+ NlnNCam = 12, // 2piMultD
+ /// the plugin has been used...
+ plugin_strategy = 999
+};
+
+
+//======================================================================
+/// the various families of jet-clustering algorithm
+enum JetAlgorithm {
+ /// the longitudinally invariant kt algorithm
+ kt_algorithm=0,
+ /// the longitudinally invariant variant of the cambridge algorithm
+ /// (aka Aachen algoithm).
+ cambridge_algorithm=1,
+ /// like the k_t but with distance measures
+ /// dij = min(1/kti^2,1/ktj^2) Delta R_{ij}^2 / R^2
+ /// diB = 1/kti^2
+ antikt_algorithm=2,
+ /// like the k_t but with distance measures
+ /// dij = min(kti^{2p},ktj^{2p}) Delta R_{ij}^2 / R^2
+ /// diB = 1/kti^{2p}
+ /// where p = extra_param()
+ genkt_algorithm=3,
+ /// a version of cambridge with a special distance measure for particles
+ /// whose pt is < extra_param()
+ cambridge_for_passive_algorithm=11,
+ /// a version of genkt with a special distance measure for particles
+ /// whose pt is < extra_param() [relevant for passive areas when p<=0]
+ genkt_for_passive_algorithm=13,
+ //.................................................................
+ /// the e+e- kt algorithm
+ ee_kt_algorithm=50,
+ /// the e+e- genkt algorithm (R > 2 and p=1 gives ee_kt)
+ ee_genkt_algorithm=53,
+ //.................................................................
+ /// any plugin algorithm supplied by the user
+ plugin_algorithm = 99
+};
+
+/// make standard Les Houches nomenclature JetAlgorithm (algorithm is general
+/// recipe without the parameters) backward-compatible with old JetFinder
+typedef JetAlgorithm JetFinder;
+
+/// provide other possible names for the Cambridge/Aachen algorithm?
+const JetAlgorithm aachen_algorithm = cambridge_algorithm;
+const JetAlgorithm cambridge_aachen_algorithm = cambridge_algorithm;
+
+//======================================================================
+/// the various recombination schemes
+enum RecombinationScheme {
+ /// summing the 4-momenta
+ E_scheme=0,
+ /// pt weighted recombination of y,phi (and summing of pt's)
+ /// with preprocessing to make things massless by rescaling E=|\vec p|
+ pt_scheme=1,
+ /// pt^2 weighted recombination of y,phi (and summing of pt's)
+ /// with preprocessing to make things massless by rescaling E=|\vec p|
+ pt2_scheme=2,
+ /// pt weighted recombination of y,phi (and summing of pt's)
+ /// with preprocessing to make things massless by rescaling |\vec p|->=E
+ Et_scheme=3,
+ /// pt^2 weighted recombination of y,phi (and summing of pt's)
+ /// with preprocessing to make things massless by rescaling |\vec p|->=E
+ Et2_scheme=4,
+ /// pt weighted recombination of y,phi (and summing of pt's), with
+ /// no preprocessing
+ BIpt_scheme=5,
+ /// pt^2 weighted recombination of y,phi (and summing of pt's)
+ /// no preprocessing
+ BIpt2_scheme=6,
+ /// for the user's external scheme
+ external_scheme = 99
+};
+
+
+
+
+// forward declaration, needed in order to specify interface for the
+// plugin.
+class ClusterSequence;
+
+
+
+
+//======================================================================
+/// class that is intended to hold a full definition of the jet
+/// clusterer
+class JetDefinition {
+
+public:
+
+ /// forward declaration of a class that allows the user to introduce
+ /// their own plugin
+ class Plugin;
+
+ // forward declaration of a class that will provide the
+ // recombination scheme facilities and/or allow a user to
+ // extend these facilities
+ class Recombiner;
+
+
+
+ /// constructor with alternative ordering or arguments -- note that
+ /// we have not provided a default jet finder, to avoid ambiguous
+ /// JetDefinition() constructor.
+ JetDefinition(JetAlgorithm jet_algorithm,
+ double R,
+ RecombinationScheme recomb_scheme = E_scheme,
+ Strategy strategy = Best) {
+ *this = JetDefinition(jet_algorithm, R, strategy, recomb_scheme, 1);
+ }
+
+ /// constructor for algorithms that have no free parameters
+ /// (e.g. ee_kt_algorithm)
+ JetDefinition(JetAlgorithm jet_algorithm,
+ RecombinationScheme recomb_scheme = E_scheme,
+ Strategy strategy = Best) {
+ double dummyR = 0.0;
+ *this = JetDefinition(jet_algorithm, dummyR, strategy, recomb_scheme, 0);
+ }
+
+ /// constructor for algorithms that require R + one extra parameter to be set
+ /// (the gen-kt series for example)
+ JetDefinition(JetAlgorithm jet_algorithm,
+ double R,
+ double xtra_param,
+ RecombinationScheme recomb_scheme = E_scheme,
+ Strategy strategy = Best) {
+ *this = JetDefinition(jet_algorithm, R, strategy, recomb_scheme, 2);
+ set_extra_param(xtra_param);
+ }
+
+
+ /// constructor in a form that allows the user to provide a pointer
+ /// to an external recombiner class (which must remain valid for the
+ /// life of the JetDefinition object).
+ JetDefinition(JetAlgorithm jet_algorithm,
+ double R,
+ const Recombiner * recombiner,
+ Strategy strategy = Best) {
+ *this = JetDefinition(jet_algorithm, R, external_scheme, strategy);
+ _recombiner = recombiner;
+ }
+
+
+ /// constructor for case with 0 parameters (ee_kt_algorithm) and
+ /// and external recombiner
+ JetDefinition(JetAlgorithm jet_algorithm,
+ const Recombiner * recombiner,
+ Strategy strategy = Best) {
+ *this = JetDefinition(jet_algorithm, external_scheme, strategy);
+ _recombiner = recombiner;
+ }
+
+ /// constructor allowing the extra parameter to be set and a pointer to
+ /// a recombiner
+ JetDefinition(JetAlgorithm jet_algorithm,
+ double R,
+ double xtra_param,
+ const Recombiner * recombiner,
+ Strategy strategy = Best) {
+ *this = JetDefinition(jet_algorithm, R, external_scheme, strategy);
+ _recombiner = recombiner;
+ set_extra_param(xtra_param);
+ }
+
+ /// a default constructor
+ JetDefinition() {
+ *this = JetDefinition(kt_algorithm, 1.0);
+ }
+
+ /// constructor based on a pointer to a user's plugin; the object
+ /// pointed to must remain valid for the whole duration of existence
+ /// of the JetDefinition and any related ClusterSequences
+ JetDefinition(const Plugin * plugin) {
+ _plugin = plugin;
+ _strategy = plugin_strategy;
+ _Rparam = _plugin->R();
+ _jet_algorithm = plugin_algorithm;
+ set_recombination_scheme(E_scheme);
+ }
+
+
+ /// constructor to fully specify a jet-definition (together with
+ /// information about how algorithically to run it).
+ ///
+ /// the ordering of arguments here is old and deprecated (except
+ /// as the common constructor for internal use)
+ JetDefinition(JetAlgorithm jet_algorithm,
+ double R,
+ Strategy strategy,
+ RecombinationScheme recomb_scheme = E_scheme,
+ int nparameters = 1);
+// :
+// _jet_algorithm(jet_algorithm), _Rparam(R), _strategy(strategy) {
+// // the largest sensible value for R
+// if (jet_algorithm != ee_kt_algorithm &&
+// jet_algorithm != ee_genkt_algorithm) assert(_Rparam <= 0.5*pi);
+// assert(_jet_algorithm != plugin_algorithm &&
+// _strategy != plugin_strategy);
+// _plugin = NULL;
+// set_recombination_scheme(recomb_scheme);
+// set_extra_param(0.0); // make sure it's defined
+// }
+
+
+ /// set the recombination scheme to the one provided
+ void set_recombination_scheme(RecombinationScheme);
+
+ /// set the recombiner class to the one provided
+ void set_recombiner(const Recombiner * recomb) {
+ _recombiner = recomb;
+ _default_recombiner = DefaultRecombiner(external_scheme);
+ }
+
+ /// return a pointer to the plugin
+ const Plugin * plugin() const {return _plugin;};
+
+ /// return information about the definition...
+ JetAlgorithm jet_algorithm () const {return _jet_algorithm ;}
+ /// same as above for backward compatibility
+ JetAlgorithm jet_finder () const {return _jet_algorithm ;}
+ double R () const {return _Rparam ;}
+ // a general purpose extra parameter, whose meaning depends on
+ // the algorithm, and may often be unused.
+ double extra_param () const {return _extra_param ;}
+ Strategy strategy () const {return _strategy ;}
+ RecombinationScheme recombination_scheme() const {
+ return _default_recombiner.scheme();}
+
+ /// (re)set the jet finder
+ void set_jet_algorithm(JetAlgorithm njf) {_jet_algorithm = njf;}
+ /// same as above for backward compatibility
+ void set_jet_finder(JetAlgorithm njf) {_jet_algorithm = njf;}
+ /// (re)set the general purpose extra parameter
+ void set_extra_param(double xtra_param) {_extra_param = xtra_param;}
+
+ /// return a pointer to the currently defined recombiner (it may
+ /// be the internal one)
+ const Recombiner * recombiner() const {
+ return _recombiner == 0 ? & _default_recombiner : _recombiner;}
+
+ /// return a textual description of the current jet definition
+ std::string description() const;
+
+
+public:
+ //======================================================================
+ /// An abstract base class that will provide the recombination scheme
+ /// facilities and/or allow a user to extend these facilities
+ class Recombiner {
+ public:
+ /// return a textual description of the recombination scheme
+ /// implemented here
+ virtual std::string description() const = 0;
+
+ /// recombine pa and pb and put result into pab
+ virtual void recombine(const PseudoJet & pa, const PseudoJet & pb,
+ PseudoJet & pab) const = 0;
+
+ /// routine called to preprocess each input jet (to make all input
+ /// jets compatible with the scheme requirements (e.g. massless).
+ virtual void preprocess(PseudoJet & p) const {};
+
+ /// a destructor to be replaced if necessary in derived classes...
+ virtual ~Recombiner() {};
+
+ /// pa += pb in the given recombination scheme. Not virtual -- the
+ /// user should have no reason to want to redefine this!
+ inline void plus_equal(PseudoJet & pa, const PseudoJet & pb) const {
+ // put result in a temporary location in case the recombiner
+ // does something funny (ours doesn't, but who knows about the
+ // user's)
+ PseudoJet pres;
+ recombine(pa,pb,pres);
+ pa = pres;
+ }
+
+ };
+
+
+ //======================================================================
+ /// A class that will provide the recombination scheme facilities and/or
+ /// allow a user to extend these facilities
+ class DefaultRecombiner : public Recombiner {
+ public:
+ DefaultRecombiner(RecombinationScheme recomb_scheme = E_scheme) :
+ _recomb_scheme(recomb_scheme) {}
+
+ virtual std::string description() const;
+
+ /// recombine pa and pb and put result into pab
+ virtual void recombine(const PseudoJet & pa, const PseudoJet & pb,
+ PseudoJet & pab) const;
+
+ virtual void preprocess(PseudoJet & p) const;
+
+ /// return the index of the recombination scheme
+ RecombinationScheme scheme() const {return _recomb_scheme;}
+
+ private:
+ RecombinationScheme _recomb_scheme;
+ };
+
+
+ //======================================================================
+ /// a class that allows a user to introduce their own "plugin" jet
+ /// finder
+ class Plugin{
+ public:
+ /// return a textual description of the jet-definition implemented
+ /// in this plugin
+ virtual std::string description() const = 0;
+
+ /// given a ClusterSequence that has been filled up with initial
+ /// particles, the following function should fill up the rest of the
+ /// ClusterSequence, using the following member functions of
+ /// ClusterSequence:
+ /// - plugin_do_ij_recombination(...)
+ /// - plugin_do_iB_recombination(...)
+ virtual void run_clustering(ClusterSequence &) const = 0;
+
+ virtual double R() const = 0;
+
+ /// return true if there is specific support for the measurement
+ /// of passive areas, in the sense that areas determined from all
+ /// particles below the ghost separation scale will be a passive
+ /// area. [If you don't understand this, ignore it!]
+ virtual bool supports_ghosted_passive_areas() const {return false;}
+
+ /// set the ghost separation scale for passive area determinations
+ /// in future runs (strictly speaking that makes the routine
+ /// a non const, so related internal info must be stored as a mutable)
+ virtual void set_ghost_separation_scale(double scale) const;
+ virtual double ghost_separation_scale() const {return 0.0;}
+
+ /// a destructor to be replaced if necessary in derived classes...
+ virtual ~Plugin() {};
+ };
+
+private:
+
+
+ JetAlgorithm _jet_algorithm;
+ double _Rparam;
+ double _extra_param ; ///< parameter whose meaning varies according to context
+ Strategy _strategy ;
+
+ const Plugin * _plugin;
+
+ // when we use our own recombiner it's useful to point to it here
+ // so that we don't have to worry about deleting it etc...
+ DefaultRecombiner _default_recombiner;
+ const Recombiner * _recombiner;
+
+};
+
+
+
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_JETDEFINITION_HH__
--- /dev/null
+#ifndef __NNH_HH__
+#define __NNH_HH__
+
+//STARTHEADER
+// $Id: NNH.hh 1491 2009-03-11 17:04:38Z salam $
+//
+// Copyright (c) 2009, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#include<fastjet/ClusterSequence.hh>
+
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// dummy class, used as a default template argument
+class _NoInfo {};
+
+/// template that will help initialise a BJ with a PseudoJet and extra information
+template<class I> class NNHInfo {
+public:
+ NNHInfo() : _info(NULL) {}
+ NNHInfo(I * info) : _info(info) {}
+ template<class NNBJ> void init_jet(NNBJ * briefjet, const fastjet::PseudoJet & jet, int index) { briefjet->init(jet, index, _info);}
+private:
+ I * _info;
+};
+
+/// Specialisation of NNHInfo for cases where there is no extra info
+template<> class NNHInfo<_NoInfo> {
+public:
+ NNHInfo() {}
+ NNHInfo(_NoInfo * info) {}
+ template<class NNBJ> void init_jet(NNBJ * briefjet, const fastjet::PseudoJet & jet, int index) { briefjet->init(jet, index);}
+};
+
+
+//----------------------------------------------------------------------
+/// Class to help solve closest pair problems with generic interparticle
+/// distances and a beam distance, using Anderberg's Nearest Neighbour
+/// Heuristic.
+///
+/// It is templated with a BJ (brief jet) class --- BJ should
+/// basically cache the minimal amount of information that is needed
+/// to efficient calculate interparticle distances and particle-beam
+/// distances.
+///
+/// This class can be used with or without an extra "Information" template,
+//// i.e. NNB<BJ> or NNH<BJ,I>
+///
+/// For the NNH<BJ> class to function in the case, BJ must provide three member functions
+///
+/// - void BJ::init(const PseudoJet & jet); // initialise with a PseudoJet
+/// - double BJ::distance(const BJ * other_bj_jet); // distance between this and other_bj_jet
+/// - double BJ::beam_distance() ; // distance to the beam
+///
+/// For the NNH<BJ,I> version to function, the BJ::init(...) member
+/// must accept an extra argument
+///
+/// - void BJ::init(const PseudoJet & jet, I * info); // initialise with a PseudoJet + info
+///
+/// where info might be a pointer to a class that contains, e.g., information
+/// about R, or other parameters of the jet algorithm
+///
+/// For an example of how the NNH<BJ> class is used, see the Jade (and
+/// EECambridge) plugins
+///
+/// NB: the NNH algorithm is expected N^2, but has a worst case of
+/// N^3. Many QCD problems tend to place one closer to the N^3 end of
+/// the spectrum than one would like. There is scope for further
+/// progress (cf Eppstein, Cardinal & Eppstein), nevertheless the
+/// current class is already significantly faster than standard N^3
+/// implementations.
+///
+///
+/// Implementation note: this class derives from NNHInfo, which deals
+/// with storing any information that
+
+template<class BJ, class I = _NoInfo> class NNH : public NNHInfo<I> {
+public:
+
+ /// constructor with an initial set of jets (which will be assigned indices
+ /// 0 ... jets.size()-1
+ NNH(const std::vector<PseudoJet> & jets) {start(jets);}
+ NNH(const std::vector<PseudoJet> & jets, I * info) : NNHInfo<I>(info) {start(jets);}
+
+ void start(const std::vector<PseudoJet> & jets);
+
+ /// return the dij_min and indices iA, iB, for the corresponding jets.
+ /// If iB < 0 then iA recombines with the beam
+ double dij_min(int & iA, int & iB);
+
+ /// remove the jet pointed to by index iA
+ void remove_jet(int iA);
+
+ /// merge the jets pointed to by indices A and B and replace them with
+ /// jet, assigning it an index jet_index.
+ void merge_jets(int iA, int iB, const PseudoJet & jet, int jet_index);
+
+ /// a destructor
+ ~NNH() {
+ delete[] briefjets;
+ }
+
+private:
+ class NNBJ; // forward declaration
+
+ /// establish the nearest neighbour for jet, and cross check constistency
+ /// of distances for the other jets that are encountered. Assumes
+ /// jet not contained within begin...end
+ void set_NN_crosscheck(NNBJ * jet, NNBJ * begin, NNBJ * end);
+
+ /// establish the nearest neighbour for jet; don't cross check other jets'
+ /// distances and allow jet to be contained within begin...end
+ void set_NN_nocross (NNBJ * jet, NNBJ * begin, NNBJ * end);
+
+ /// contains the briefjets
+ NNBJ * briefjets;
+
+ /// semaphores for the current extent of our structure
+ NNBJ * head, * tail;
+
+ /// currently active number of jets
+ int n;
+
+ /// where_is[i] contains a pointer to the jet with index i
+ std::vector<NNBJ *> where_is;
+
+ /// a class that wraps around the BJ, supplementing it with extra information
+ /// such as pointers to neighbours, etc.
+ class NNBJ : public BJ {
+ public:
+ void init(const PseudoJet & jet, int index) {
+ BJ::init(jet);
+ other_init(index);
+ }
+ void init(const PseudoJet & jet, int index, I * info) {
+ BJ::init(jet, info);
+ other_init(index);
+ }
+ void other_init(int index) {
+ _index = index;
+ NN_dist = BJ::beam_distance();
+ NN = NULL;
+ }
+ int index() const {return _index;}
+
+ double NN_dist;
+ NNBJ * NN;
+
+ private:
+ int _index;
+ };
+
+};
+
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> void NNH<BJ,I>::start(const std::vector<PseudoJet> & jets) {
+ n = jets.size();
+ briefjets = new NNBJ[n];
+ where_is.resize(2*n);
+
+ NNBJ * jetA = briefjets;
+
+ // initialise the basic jet info
+ for (int i = 0; i< n; i++) {
+ //jetA->init(jets[i], i);
+ init_jet(jetA, jets[i], i);
+ where_is[i] = jetA;
+ jetA++; // move on to next entry of briefjets
+ }
+ tail = jetA; // a semaphore for the end of briefjets
+ head = briefjets; // a nicer way of naming start
+
+ // now initialise the NN distances: jetA will run from 1..n-1; and
+ // jetB from 0..jetA-1
+ for (jetA = head + 1; jetA != tail; jetA++) {
+ // set NN info for jetA based on jets running from head..jetA-1,
+ // checking in the process whether jetA itself is an undiscovered
+ // NN of one of those jets.
+ set_NN_crosscheck(jetA, head, jetA);
+ }
+ //std::cout << "OOOO " << briefjets[1].NN_dist << " " << briefjets[1].NN - briefjets << std::endl;
+}
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> double NNH<BJ,I>::dij_min(int & iA, int & iB) {
+ // find the minimum of the diJ on this round
+ double diJ_min = briefjets[0].NN_dist;
+ int diJ_min_jet = 0;
+ for (int i = 1; i < n; i++) {
+ if (briefjets[i].NN_dist < diJ_min) {
+ diJ_min_jet = i;
+ diJ_min = briefjets[i].NN_dist;
+ }
+ }
+
+ // return information to user about recombination
+ NNBJ * jetA = & briefjets[diJ_min_jet];
+ //std::cout << jetA - briefjets << std::endl;
+ iA = jetA->index();
+ iB = jetA->NN ? jetA->NN->index() : -1;
+ return diJ_min;
+}
+
+
+//----------------------------------------------------------------------
+// remove jetA from the list
+template<class BJ, class I> void NNH<BJ,I>::remove_jet(int iA) {
+ NNBJ * jetA = where_is[iA];
+ // now update our nearest neighbour info and diJ table
+ // first reduce size of table
+ tail--; n--;
+ // Copy last jet contents and diJ info into position of jetA
+ *jetA = *tail;
+ // update the info on where the given index is stored
+ where_is[jetA->index()] = jetA;
+
+ for (NNBJ * jetI = head; jetI != tail; jetI++) {
+ // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+ if (jetI->NN == jetA) set_NN_nocross(jetI, head, tail);
+
+ // if jetI's NN is the new tail then relabel it so that it becomes jetA
+ if (jetI->NN == tail) {jetI->NN = jetA;}
+ }
+}
+
+
+//----------------------------------------------------------------------
+template<class BJ, class I> void NNH<BJ,I>::merge_jets(int iA, int iB,
+ const PseudoJet & jet, int index) {
+
+ NNBJ * jetA = where_is[iA];
+ NNBJ * jetB = where_is[iB];
+
+ // If necessary relabel A & B to ensure jetB < jetA, that way if
+ // the larger of them == newtail then that ends up being jetA and
+ // the new jet that is added as jetB is inserted in a position that
+ // has a future!
+ if (jetA < jetB) swap(jetA,jetB);
+
+ // initialise jetB based on the new jet
+ //jetB->init(jet, index);
+ init_jet(jetB, jet, index);
+ // and record its position (making sure we have the space)
+ if (index >= int(where_is.size())) where_is.resize(2*index);
+ where_is[jetB->index()] = jetB;
+
+ // now update our nearest neighbour info
+ // first reduce size of table
+ tail--; n--;
+ // Copy last jet contents into position of jetA
+ *jetA = *tail;
+ // update the info on where the tail's index is stored
+ where_is[jetA->index()] = jetA;
+
+ for (NNBJ * jetI = head; jetI != tail; jetI++) {
+ // see if jetI had jetA or jetB as a NN -- if so recalculate the NN
+ if (jetI->NN == jetA || jetI->NN == jetB) {
+ set_NN_nocross(jetI, head, tail);
+ }
+
+ // check whether new jetB is closer than jetI's current NN and
+ // if need be update things
+ double dist = jetI->distance(jetB);
+ if (dist < jetI->NN_dist) {
+ if (jetI != jetB) {
+ jetI->NN_dist = dist;
+ jetI->NN = jetB;
+ }
+ }
+ if (dist < jetB->NN_dist) {
+ if (jetI != jetB) {
+ jetB->NN_dist = dist;
+ jetB->NN = jetI;
+ }
+ }
+
+ // if jetI's NN is the new tail then relabel it so that it becomes jetA
+ if (jetI->NN == tail) {jetI->NN = jetA;}
+ }
+}
+
+
+//----------------------------------------------------------------------
+// this function assumes that jet is not contained within begin...end
+template <class BJ, class I> void NNH<BJ,I>::set_NN_crosscheck(NNBJ * jet,
+ NNBJ * begin, NNBJ * end) {
+ double NN_dist = jet->beam_distance();
+ NNBJ * NN = NULL;
+ for (NNBJ * jetB = begin; jetB != end; jetB++) {
+ double dist = jet->distance(jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ if (dist < jetB->NN_dist) {
+ jetB->NN_dist = dist;
+ jetB->NN = jet;
+ }
+ }
+ jet->NN = NN;
+ jet->NN_dist = NN_dist;
+}
+
+
+//----------------------------------------------------------------------
+// set the NN for jet without checking whether in the process you might
+// have discovered a new nearest neighbour for another jet
+template <class BJ, class I> void NNH<BJ,I>::set_NN_nocross(
+ NNBJ * jet, NNBJ * begin, NNBJ * end) {
+ double NN_dist = jet->beam_distance();
+ NNBJ * NN = NULL;
+ if (head < jet) {
+ for (NNBJ * jetB = head; jetB != jet; jetB++) {
+ double dist = jet->distance(jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ }
+ }
+ if (tail > jet) {
+ for (NNBJ * jetB = jet+1; jetB != tail; jetB++) {
+ double dist = jet->distance (jetB);
+ if (dist < NN_dist) {
+ NN_dist = dist;
+ NN = jetB;
+ }
+ }
+ }
+ jet->NN = NN;
+ jet->NN_dist = NN_dist;
+}
+
+
+
+
+} // fastjet namespace
+
+
+#endif // __NNH_HH__
--- /dev/null
+//STARTHEADER
+// $Id: NestedDefsPlugin.hh 1394 2009-01-17 05:08:31Z soyez $
+//
+// Copyright (c) 2007-2008, Matteo Cacciari, Gavin Salam and Gregory Soyez
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __NESTEDALGSPLUGIN_HH__
+#define __NESTEDALGSPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include <list>
+#include <memory>
+#include <cmath>
+
+// questionable whether this should be in fastjet namespace or not...
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+// another forward declaration to reduce includes
+class PseudoJet;
+
+//----------------------------------------------------------------------
+//
+/// NestedAglsPlugin is a plugin for fastjet (v2.4 upwards) that, given
+/// a list of jet definitions, performs the clustering by feeding the
+/// particles to the first algorithm and then, successively feeding the
+/// output to the next algorithm in the list.
+//
+class NestedDefsPlugin : public JetDefinition::Plugin {
+public:
+ /// Main constructor for the NestedDefs Plugin class.
+ ///
+ /// The argument is an initialised list of jet algorithms
+ NestedDefsPlugin (std::list<JetDefinition> &defs) :
+ _defs(defs){}
+
+ /// copy constructor
+ NestedDefsPlugin (const NestedDefsPlugin & plugin) {
+ *this = plugin;
+ }
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const;
+ /// the plugin mechanism's standard way of accessing the jet radius
+ /// here we return the R of the last alg in the list
+ virtual double R() const {return _defs.rbegin()->R();}
+
+private:
+ std::list<JetDefinition> _defs;
+};
+
+} // fastjet namespace
+
+#endif // __SISCONEPLUGIN_HH__
+
--- /dev/null
+//STARTHEADER
+// $Id: PseudoJet.hh 1510 2009-04-13 08:48:41Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_PSEUDOJET_HH__
+#define __FASTJET_PSEUDOJET_HH__
+
+#include<valarray>
+#include<vector>
+#include<cassert>
+#include<cmath>
+#include<iostream>
+#include "fastjet/internal/numconsts.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//using namespace std;
+
+/// Used to protect against parton-level events where pt can be zero
+/// for some partons, giving rapidity=infinity. KtJet fails in those cases.
+const double MaxRap = 1e5;
+
+/// Class to contain pseudojets, including minimal information of use to
+/// to jet-clustering routines.
+class PseudoJet {
+
+ public:
+ PseudoJet() {};
+ /// construct a pseudojet from explicit components
+ PseudoJet(const double px, const double py, const double pz, const double E);
+ /// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
+ template <class L> PseudoJet(const L & some_four_vector) ;
+
+ // first "const double &" says that result is a reference to the
+ // stored value and that we will not change that stored value.
+ //
+ // second "const" says that "this" will not be modified by these
+ // functions.
+ inline double E() const {return _E;}
+ inline double e() const {return _E;} // like CLHEP
+ inline double px() const {return _px;}
+ inline double py() const {return _py;}
+ inline double pz() const {return _pz;}
+
+ /// returns phi (in the range 0..2pi)
+ inline double phi() const {return phi_02pi();}
+
+ /// returns phi in the range -pi..pi
+ inline double phi_std() const {
+ return _phi > pi ? _phi-twopi : _phi;}
+
+ /// returns phi in the range 0..2pi
+ inline double phi_02pi() const {return _phi;}
+
+ /// returns the rapidity or some large value when the rapidity
+ /// is infinite
+ inline double rap() const {return _rap;}
+
+ /// the same as rap()
+ inline double rapidity() const {return _rap;} // like CLHEP
+
+ /// returns the pseudo-rapidity or some large value when the
+ /// rapidity is infinite
+ double pseudorapidity() const;
+ double eta() const {return pseudorapidity();}
+
+ /// returns the squared transverse momentum
+ inline double kt2() const {return _kt2;}
+ /// returns the squared transverse momentum
+ inline double perp2() const {return _kt2;} // like CLHEP
+ /// returns the scalar transverse momentum
+ inline double perp() const {return sqrt(_kt2);} // like CLHEP
+ /// returns the squared invariant mass // like CLHEP
+ inline double m2() const {return (_E+_pz)*(_E-_pz)-_kt2;}
+ /// returns the squared transverse mass = kt^2+m^2
+ inline double mperp2() const {return (_E+_pz)*(_E-_pz);}
+ /// returns the transverse mass = sqrt(kt^2+m^2)
+ inline double mperp() const {return sqrt(std::abs(mperp2()));}
+ /// returns the invariant mass
+ /// (If m2() is negative then -sqrt(-m2()) is returned, as in CLHEP)
+ inline double m() const;
+ /// return px^2+py^2+pz^2
+ inline double modp2() const {return _kt2+_pz*_pz;}
+ /// return the transverse energy
+ inline double Et() const {return (_kt2==0) ? 0.0 : _E/sqrt(1.0+_pz*_pz/_kt2);}
+ /// return the transverse energy squared
+ inline double Et2() const {return (_kt2==0) ? 0.0 : _E*_E/(1.0+_pz*_pz/_kt2);}
+
+ /// returns component i, where X==0, Y==1, Z==2, E==3
+ double operator () (int i) const ;
+ /// returns component i, where X==0, Y==1, Z==2, E==3
+ inline double operator [] (int i) const { return (*this)(i); }; // this too
+
+
+ // taken from CLHEP
+ enum { X=0, Y=1, Z=2, T=3, NUM_COORDINATES=4, SIZE=NUM_COORDINATES };
+
+
+ /// transform this jet (given in the rest frame of prest) into a jet
+ /// in the lab frame [NOT FULLY TESTED]
+ PseudoJet & boost(const PseudoJet & prest);
+ /// transform this jet (given in lab) into a jet in the rest
+ /// frame of prest [NOT FULLY TESTED]
+ PseudoJet & unboost(const PseudoJet & prest);
+
+ /// return the cluster_hist_index, intended to be used by clustering
+ /// routines.
+ inline int cluster_hist_index() const {return _cluster_hist_index;}
+ /// set the cluster_hist_index, intended to be used by clustering routines.
+ inline void set_cluster_hist_index(const int index) {_cluster_hist_index = index;}
+
+ /// alternative name for cluster_hist_index() [perhaps more meaningful]
+ inline int cluster_sequence_history_index() const {
+ return cluster_hist_index();}
+ /// alternative name for set_cluster_hist_index(...) [perhaps more
+ /// meaningful]
+ inline void set_cluster_sequence_history_index(const int index) {
+ set_cluster_hist_index(index);}
+
+
+ /// return the user_index, intended to allow the user to "add" information
+ inline int user_index() const {return _user_index;}
+ /// set the user_index, intended to allow the user to "add" information
+ inline void set_user_index(const int index) {_user_index = index;}
+
+ /// return a valarray containing the four-momentum (components 0-2
+ /// are 3-mom, component 3 is energy).
+ std::valarray<double> four_mom() const;
+
+ /// returns kt distance (R=1) between this jet and another
+ double kt_distance(const PseudoJet & other) const;
+
+ /// returns squared cylinder (rap-phi) distance between this jet and another
+ double plain_distance(const PseudoJet & other) const;
+ /// returns squared cylinder (rap-phi) distance between this jet and
+ /// another
+ inline double squared_distance(const PseudoJet & other) const {
+ return plain_distance(other);}
+
+ /// returns other.phi() - this.phi(), constrained to be in
+ /// range -pi .. pi
+ double delta_phi_to(const PseudoJet & other) const;
+
+ //// this seemed to compile except if it was used
+ //friend inline double
+ // kt_distance(const PseudoJet & jet1, const PseudoJet & jet2) {
+ // return jet1.kt_distance(jet2);}
+
+ /// returns distance between this jet and the beam
+ inline double beam_distance() const {return _kt2;}
+
+
+ void operator*=(double);
+ void operator/=(double);
+ void operator+=(const PseudoJet &);
+ void operator-=(const PseudoJet &);
+
+ /// reset the 4-momentum according to the supplied components and
+ /// put the user and history indices back to their default values
+ inline void reset(double px, double py, double pz, double E);
+
+ /// reset the PseudoJet to be equal to psjet (including its
+ /// indices); NB if the argument is derived from a PseudoJet then
+ /// the "reset" used will be the templated version (which does not
+ /// know about indices...)
+ inline void reset(const PseudoJet & psjet) {
+ (*this) = psjet;
+ }
+
+ /// reset the 4-momentum according to the supplied generic 4-vector
+ /// (accessible via indexing, [0]==px,...[3]==E) and put the user
+ /// and history indices back to their default values.
+ template <class L> inline void reset(const L & some_four_vector) {
+ reset(some_four_vector[0], some_four_vector[1],
+ some_four_vector[2], some_four_vector[3]);
+ }
+
+ private:
+ // NB: following order must be kept for things to behave sensibly...
+ double _px,_py,_pz,_E;
+ double _phi, _rap, _kt2;
+ int _cluster_hist_index, _user_index;
+ /// calculate phi, rap, kt2 based on the 4-momentum components
+ void _finish_init();
+ /// set the indices to default values
+ void _reset_indices();
+
+ //vertex_type * vertex0, vertex1;
+};
+
+
+//----------------------------------------------------------------------
+// routines for basic binary operations
+
+PseudoJet operator+(const PseudoJet &, const PseudoJet &);
+PseudoJet operator-(const PseudoJet &, const PseudoJet &);
+PseudoJet operator*(double, const PseudoJet &);
+PseudoJet operator*(const PseudoJet &, double);
+PseudoJet operator/(const PseudoJet &, double);
+
+inline double dot_product(const PseudoJet & a, const PseudoJet & b) {
+ return a.E()*b.E() - a.px()*b.px() - a.py()*b.py() - a.pz()*b.pz();
+}
+
+/// returns true if the momenta of the two input jets are identical
+bool have_same_momentum(const PseudoJet &, const PseudoJet &);
+
+/// return a pseudojet with the given pt, y, phi and mass
+PseudoJet PtYPhiM(double pt, double y, double phi, double m = 0.0);
+
+//----------------------------------------------------------------------
+// Routines to do with providing sorted arrays of vectors.
+
+/// return a vector of jets sorted into decreasing transverse momentum
+std::vector<PseudoJet> sorted_by_pt(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into increasing rapidity
+std::vector<PseudoJet> sorted_by_rapidity(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into decreasing energy
+std::vector<PseudoJet> sorted_by_E(const std::vector<PseudoJet> & jets);
+
+/// return a vector of jets sorted into increasing pz
+std::vector<PseudoJet> sorted_by_pz(const std::vector<PseudoJet> & jets);
+
+//----------------------------------------------------------------------
+// some code to help sorting
+
+/// sort the indices so that values[indices[0->n-1]] is sorted
+/// into increasing order
+void sort_indices(std::vector<int> & indices,
+ const std::vector<double> & values);
+
+/// given a vector of values with a one-to-one correspondence with the
+/// vector of objects, sort objects into an order such that the
+/// associated values would be in increasing order (but don't actually
+/// touch the values vector in the process).
+template<class T> std::vector<T> objects_sorted_by_values(const std::vector<T> & objects,
+ const std::vector<double> & values);
+
+/// a class that helps us carry out indexed sorting.
+class IndexedSortHelper {
+public:
+ inline IndexedSortHelper (const std::vector<double> * reference_values) {
+ _ref_values = reference_values;
+ };
+ inline int operator() (const int & i1, const int & i2) const {
+ return (*_ref_values)[i1] < (*_ref_values)[i2];
+ };
+private:
+ const std::vector<double> * _ref_values;
+};
+
+
+//----------------------------------------------------------------------
+/// constructor from any object that has px,py,pz,E = some_four_vector[0--3],
+// NB: do not know if it really needs to be inline, but when it wasn't
+// linking failed with g++ (who knows what was wrong...)
+template <class L> inline PseudoJet::PseudoJet(const L & some_four_vector) {
+
+ _px = some_four_vector[0];
+ _py = some_four_vector[1];
+ _pz = some_four_vector[2];
+ _E = some_four_vector[3];
+ _finish_init();
+ // some default values for these two indices
+ _reset_indices();
+}
+
+
+//----------------------------------------------------------------------
+inline void PseudoJet::_reset_indices() {
+ set_cluster_hist_index(-1);
+ set_user_index(-1);
+}
+
+//----------------------------------------------------------------------
+/// specialization of the "reset" template for case where something
+/// is reset to a pseudojet -- it then takes the user and history
+/// indices from the psjet
+// template<> inline void PseudoJet::reset<PseudoJet>(const PseudoJet & psjet) {
+// (*this) = psjet;
+// }
+
+////// fun and games...
+////template<class L> class FJVector : public L {
+////// /** Default Constructor: create jet with no constituents */
+////// Vector<L>();
+////
+////};
+////
+
+// taken literally from CLHEP
+inline double PseudoJet::m() const {
+ double mm = m2();
+ return mm < 0.0 ? -std::sqrt(-mm) : std::sqrt(mm);
+}
+
+
+inline void PseudoJet::reset(double px, double py, double pz, double E) {
+ _px = px;
+ _py = py;
+ _pz = pz;
+ _E = E;
+ _finish_init();
+ _reset_indices();
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_PSEUDOJET_HH__
--- /dev/null
+//STARTHEADER
+// $Id: RangeDefinition.hh 1404 2009-01-21 18:43:57Z salam $
+//
+// Copyright (c) 2005-2007, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_RANGEDEFINITION_HH__
+#define __FASTJET_RANGEDEFINITION_HH__
+
+#include "fastjet/PseudoJet.hh"
+#include "fastjet/Error.hh"
+#include<sstream>
+#include<iostream>
+#include<string>
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// class for holding a range definition specification, given by limits
+/// on rapidity and azimuth.
+///
+class RangeDefinition {
+public:
+ /// default constructor
+ RangeDefinition() {}
+
+ /// constructor for a range definition given by |y|<rapmax
+ RangeDefinition(double rapmax) {
+ assert ( rapmax > 0.0 );
+ _rapmax = rapmax;
+ _rapmin = -rapmax;
+ _phimin = 0.0;
+ _phimax = twopi;
+ _total_area = 2.0*rapmax*twopi;
+ _phispan = _phimax-_phimin; }
+
+ /// destructor does nothing
+ virtual ~RangeDefinition() {}
+
+ /// constructor for a range definition given by
+ /// rapmin <= y <= rapmax, phimin <= phi <= phimax
+ RangeDefinition(double rapmin, double rapmax,
+ double phimin = 0.0, double phimax = twopi) {
+ assert ( rapmin < rapmax);
+ assert ( phimin < phimax);
+ assert ( phimin > -twopi );
+ assert ( phimax < 2*twopi);
+ _rapmax = rapmax;
+ _rapmin = rapmin;
+ _phimin = phimin;
+ _phimax = phimax;
+ if (_phimax-_phimin > twopi)
+ _total_area = (_rapmax - _rapmin)*twopi;
+ else
+ _total_area = (_rapmax - _rapmin)*(_phimax - _phimin);
+ _phispan = _phimax-_phimin; }
+
+ /// returns true if the range is localizable (i.e. set_position is
+ /// meant to do something meaningful).
+ ///
+ /// This version of the class is not localizable and so it returns
+ /// false.
+ ///
+ /// For localizable classes override this function with a function
+ /// that returns true
+ virtual inline bool is_localizable() const { return false; }
+
+
+ /// place the range on the rap-phi position
+ ///
+ /// THIS DOES NOT DO ANYTHING FOR THIS CLASS AND IS ONLY THERE
+ /// TO FACILITATE DERIVED CLASSES
+ ///
+ /// DON'T NECESSARILY COUNT ON IT IN THE FUTURE EITHER???
+ inline void set_position(const double & rap, const double & phi) {
+ if (! is_localizable() ) {
+ std::ostringstream err;
+ err << description() <<
+ "\nThis range is not localizable. set_position() should not be used on it.";
+ throw fastjet::Error(err.str());
+ } else {
+ _rapjet = rap;
+ _phijet = phi;
+ }
+ }
+
+ /// place the range on the jet position
+ inline void set_position(const PseudoJet & jet) {
+ set_position(jet.rap(),jet.phi());
+ }
+
+ /// return bool according to whether the jet is within the given range
+ inline bool is_in_range(const PseudoJet & jet) const {
+ double rap = jet.rap();
+ double phi = jet.phi();
+ return is_in_range(rap,phi);
+ }
+
+ /// return bool according to whether a (rap,phi) point is in range
+ virtual inline bool is_in_range(double rap, double phi) const {
+ double dphi=phi-_phimin;
+ if (dphi >= twopi) dphi -= twopi;
+ if (dphi < 0) dphi += twopi;
+ return ( rap >= _rapmin &&
+ rap <= _rapmax &&
+ dphi <= _phispan );
+ }
+
+ /// return the minimal and maximal rapidity of this range; remember to
+ /// replace this if you write a derived class with more complex ranges;
+ virtual inline void get_rap_limits(double & rapmin, double & rapmax) const {
+ rapmin = _rapmin;
+ rapmax = _rapmax;
+ }
+
+ /// area of the range region
+ virtual inline double area() const { return _total_area; }
+
+ /// textual description of range
+ virtual inline std::string description() const {
+ std::ostringstream ostr;
+ ostr << "Range: " << _rapmin << " <= y <= " << _rapmax << ", "
+ << _phimin << " <= phi <= " << _phimax ;
+ return ostr.str();
+}
+
+protected:
+ double _total_area; // total area of specified range
+
+ /// calculate, and set _total_area, by calculating which of points on
+ /// a grid (npoints * npoints from -rapmax..rapmax,0..2pi) are contained
+ /// in the range; it takes a reasonable time with rapmax = 10,
+ /// npoints = 100.
+ void _numerical_total_area(double rapmax, int npoints) ;
+ double _rapjet,_phijet; // jet position. only used in localizable derived classes
+
+private:
+ double _rapmin,_rapmax,_phimin,_phimax,_phispan;
+
+};
+
+} // fastjet namespace
+
+#endif // __FASTJET_RANGEDEFINITION_HH__
--- /dev/null
+#ifndef __SISCONEBASEPLUGIN_HH__
+#define __SISCONEBASEPLUGIN_HH__
+
+#include "fastjet/JetDefinition.hh"
+#include "fastjet/ClusterSequence.hh"
+#include <vector>
+#include <memory>
+#include <cmath>
+
+#include <sstream>
+
+// questionable whether this should be in fastjet namespace or not...
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// SISConeBasePlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides a base interface to SISCone-type cone jet finder by
+/// Gregory Soyez and Gavin Salam.
+///
+/// This is a purely virtual class that needs to be overloaded
+/// for the specific implementations of SISCone (i.e. regular or
+/// spherical as of July 16th 2008).
+///
+/// any derived plugin MUST overload the following methods:
+/// description()
+/// run_siscone_clustering()
+/// reset_stored_plugin()
+///
+/// For further details, see the derived plugins or
+/// http://projects.hepforge.com/siscone
+//
+class SISConeBasePlugin : public JetDefinition::Plugin {
+public:
+ /// default ctor
+ SISConeBasePlugin (){
+ _use_jet_def_recombiner = false;
+ }
+
+ /// copy constructor
+ SISConeBasePlugin (const SISConeBasePlugin & plugin) {
+ *this = plugin;
+ }
+
+ /// the cone radius
+ double cone_radius () const {return _cone_radius ;}
+
+ /// Fraction of overlap energy in a jet above which jets are merged
+ /// and below which jets are split.
+ double overlap_threshold () const {return _overlap_threshold ;}
+
+ /// the maximum number of passes of stable-cone searching (<=0 is same
+ /// as infinity).
+ int n_pass_max () const {return _n_pass_max ;}
+
+ /// set the "split_merge_stopping_scale": if the scale variable for
+ /// all protojets is below this, then stop the split-merge procedure
+ /// and keep only those jets found so far. This is useful in
+ /// determination of areas of hard jets because it can be used to
+ /// avoid running the split-merging on the pure ghost-part of the
+ /// event.
+ void set_split_merge_stopping_scale(double scale) {
+ _split_merge_stopping_scale = scale;}
+
+ /// return the value of the split_merge_stopping_scale (see
+ /// set_split_merge_stopping_scale(...) for description)
+ double split_merge_stopping_scale() {return _split_merge_stopping_scale;}
+
+ /// allow the user to decide if one uses the jet_def's own recombination scheme
+ void set_use_jet_def_recombiner(bool choice) {_use_jet_def_recombiner = choice;}
+
+ /// indicate if the jet_def's recombination scheme is being used
+ bool use_jet_def_recombiner() const {return _use_jet_def_recombiner;}
+
+ /// indicates whether caching is turned on or not.
+ bool caching() const {return _caching ;}
+
+ /// the plugin mechanism's standard way of accessing the jet radius
+ virtual double R() const {return cone_radius();}
+
+ /// return true since there is specific support for the measurement
+ /// of passive areas, in the sense that areas determined from all
+ /// particles below the ghost separation scale will be a passive
+ /// area.
+ virtual bool supports_ghosted_passive_areas() const {
+ return true;
+ }
+
+ /// set the ghost separation scale for passive area determinations
+ /// _just_ in the next run (strictly speaking that makes the routine
+ /// a non const, so related internal info must be stored as a mutable)
+ virtual void set_ghost_separation_scale(double scale) const {
+ _ghost_sep_scale = scale;
+ }
+
+ virtual double ghost_separation_scale() const {
+ return _ghost_sep_scale;
+ }
+
+ // the things that one MUST overload required by base class
+ //---------------------------------------------------------
+
+ /// plugin description
+ virtual std::string description () const =0;
+
+ /// really do the clustering work
+ virtual void run_clustering(ClusterSequence &) const = 0;
+
+protected:
+ double _cone_radius, _overlap_threshold;
+ int _n_pass_max;
+ bool _caching;//, _split_merge_on_transverse_mass;
+ double _split_merge_stopping_scale;
+ bool _use_jet_def_recombiner;
+
+ mutable double _ghost_sep_scale;
+
+ // the part that HAS to be overloaded
+ /// call the re-clustering itself
+ virtual void reset_stored_plugin() const =0;
+
+};
+
+
+//======================================================================
+/// Class that provides extra information about a SISCone clustering
+/// the only thing that needs to be done for thee derived classes
+/// is to define '_jet_def_plugin', implement
+/// jet_def_plugin();
+/// and add the corresponding plugin class as a friend
+class SISConeBaseExtras : public ClusterSequence::Extras {
+public:
+
+ /// constructor
+ // it just initialises the pass information
+ SISConeBaseExtras(int nparticles) : _pass(nparticles*2,-1) {}
+
+ /// purely virtual destructor
+ inline virtual ~SISConeBaseExtras()=0;
+
+ /// returns a reference to the vector of stable cones (aka protocones)
+ const std::vector<PseudoJet> & stable_cones() const {return _protocones;}
+
+ /// an old name for getting the vector of stable cones (aka protocones)
+ const std::vector<PseudoJet> & protocones() const {return _protocones;}
+
+ /// return the # of the pass at which a given jet was found; will
+ /// return -1 if the pass is invalid
+ int pass(const PseudoJet & jet) const {return _pass[jet.cluster_hist_index()];}
+
+ /// return a brief summary of the contents of the extras object
+ /// (specifically, the number of protocones.
+ std::string description() const{
+ std::ostringstream ostr;
+ ostr << "This SISCone clustering found " << protocones().size()
+ << " stable protocones";
+ return ostr.str();
+ };
+
+ /// return the smallest difference in squared distance encountered
+ /// during splitting between a particle and two overlapping
+ /// protojets.
+ inline double most_ambiguous_split() const {return _most_ambiguous_split;}
+
+protected:
+ std::vector<PseudoJet> _protocones;
+ std::vector<int> _pass;
+ double _most_ambiguous_split;
+ const SISConeBasePlugin * _jet_def_plugin;
+};
+
+/// give the destructor its required implementation
+inline SISConeBaseExtras::~SISConeBaseExtras(){}
+
+
+} // fastjet namespace
+
+#endif // __SISCONEBASEPLUGIN_HH__
+
--- /dev/null
+#ifndef __SISCONEPLUGIN_HH__
+#define __SISCONEPLUGIN_HH__
+
+#include "SISConeBasePlugin.hh"
+
+// forward declaration of the siscone classes we'll need
+namespace siscone{
+ class Csiscone;
+}
+
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// SISConePlugin is a plugin for fastjet (v2.1 upwards) that provides
+/// an interface to the seedless infrared safe cone jet finder by
+/// Gregory Soyez and Gavin Salam.
+///
+/// SISCone uses geometrical techniques to exhaustively consider all
+/// possible distinct cones. It then finds out which ones are stable
+/// and sends the result to the Tevatron Run-II type split-merge
+/// procedure for overlapping cones.
+///
+/// Four parameters govern the "physics" of the algorithm:
+///
+/// - the cone_radius (this should be self-explanatory!)
+///
+/// - the overlap_threshold is the parameter which dictates how much
+/// two jets must overlap (pt_overlap/min(pt1,pt2)) if they are to be
+/// merged
+///
+/// - Not all particles are in stable cones in the first round of
+/// searching for stable cones; one can therefore optionally have the
+/// the jet finder carry out additional passes of searching for
+/// stable cones among particles that were in no stable cone in
+/// previous passes --- the maximum number of passes carried out is
+/// n_pass_max. If this is zero then additional passes are carried
+/// out until no new stable cones are found.
+///
+/// - Protojet ptmin: protojets that are below this ptmin
+/// (default = 0) are discarded before each iteration of the
+/// split-merge loop.
+///
+/// One parameter governs some internal algorithmic shortcuts:
+///
+/// - if "caching" is turned on then the last event clustered by
+/// siscone is stored -- if the current event is identical and the
+/// cone_radius and n_pass_mass are identical, then the only part of
+/// the clustering that needs to be rerun is the split-merge part,
+/// leading to significant speed gains; there is a small (O(N) storage
+/// and speed) penalty for caching, so it should be kept off
+/// (default) if only a single overlap_threshold is used.
+///
+/// The final jets can be accessed by requestion the
+/// inclusive_jets(...) from the ClusterSequence object. Note that
+/// these PseudoJets have their user_index() set to the index of the
+/// pass in which they were found (first pass = 0). NB: This does not
+/// currently work for jets that consist of a single particle.
+///
+/// For further information on the details of the algorithm see the
+/// SISCone paper, arXiv:0704.0292 [JHEP 0705:086,2007].
+///
+/// For documentation about the implementation, see the
+/// siscone/doc/html/index.html file.
+//
+class SISConePlugin : public SISConeBasePlugin{
+public:
+
+ /// enum for the different split-merge scale choices;
+ /// Note that order _must_ be the same as in siscone
+ enum SplitMergeScale {SM_pt, ///< transverse momentum (E-scheme), IR unsafe
+ SM_Et, ///< transverse energy (E-scheme), not long. boost invariant
+ ///< original run-II choice [may not be implemented]
+ SM_mt, ///< transverse mass (E-scheme), IR safe except
+ ///< in decays of two identical narrow heavy particles
+ SM_pttilde ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+ ///< be IR safe in all cases
+ };
+
+
+ /// Main constructor for the SISCone Plugin class.
+ ///
+ /// Note: wrt version prior to 2.4 this constructor differs in that a
+ /// the default value has been removed for overlap_threshold. The
+ /// former has been removed because the old default of 0.5 was found
+ /// to be unsuitable in high-noise environments; so the user should
+ /// now explicitly think about the value for this -- we recommend
+ /// 0.75.
+ ///
+ SISConePlugin (double cone_radius,
+ double overlap_threshold,
+ int n_pass_max = 0,
+ double protojet_ptmin = 0.0,
+ bool caching = false,
+ SplitMergeScale split_merge_scale = SM_pttilde,
+ double split_merge_stopping_scale = 0.0){
+ _cone_radius = cone_radius;
+ _overlap_threshold = overlap_threshold;
+ _n_pass_max = n_pass_max;
+ _protojet_ptmin = protojet_ptmin;
+ _caching = caching;
+ _split_merge_scale = split_merge_scale;
+ _split_merge_stopping_scale = split_merge_stopping_scale;
+ _ghost_sep_scale = 0.0;
+ _use_pt_weighted_splitting = false;}
+
+
+ /// Backwards compatible constructor for the SISCone Plugin class
+ SISConePlugin (double cone_radius,
+ double overlap_threshold,
+ int n_pass_max,
+ double protojet_ptmin,
+ bool caching ,
+ bool split_merge_on_transverse_mass){
+ _cone_radius = cone_radius;
+ _overlap_threshold = overlap_threshold;
+ _n_pass_max = n_pass_max;
+ _protojet_ptmin = protojet_ptmin;
+ _caching = caching;
+ _split_merge_stopping_scale = 0.0;
+ _split_merge_scale = split_merge_on_transverse_mass ? SM_mt : SM_pttilde;
+ _ghost_sep_scale = 0.0;}
+
+ /// backwards compatible constructor for the SISCone Plugin class
+ /// (avoid using this in future).
+ SISConePlugin (double cone_radius,
+ double overlap_threshold,
+ int n_pass_max,
+ bool caching ) {
+ _cone_radius = cone_radius;
+ _overlap_threshold = overlap_threshold;
+ _n_pass_max = n_pass_max;
+ _protojet_ptmin = 0.0;
+ _caching = caching;
+ _split_merge_scale = SM_mt;
+ _split_merge_stopping_scale = 0.0;
+ _ghost_sep_scale = 0.0;
+ _use_pt_weighted_splitting = false;}
+
+ /// minimum pt for a protojet to be considered in the split-merge step
+ /// of the algorithm
+ double protojet_ptmin () const {return _protojet_ptmin ;}
+
+ /// return the scale to be passed to SISCone as the protojet_ptmin
+ /// -- if we have a ghost separation scale that is above the
+ /// protojet_ptmin, then the ghost_separation_scale becomes the
+ /// relevant one to use here
+ double protojet_or_ghost_ptmin () const {return std::max(_protojet_ptmin,
+ _ghost_sep_scale);}
+
+ /// indicates scale used in split-merge
+ SplitMergeScale split_merge_scale() const {return _split_merge_scale;}
+ /// sets scale used in split-merge
+ void set_split_merge_scale(SplitMergeScale sms) {_split_merge_scale = sms;}
+
+ /// indicates whether the split-merge orders on transverse mass or not.
+ /// retained for backwards compatibility with 2.1.0b3
+ bool split_merge_on_transverse_mass() const {return _split_merge_scale == SM_mt ;}
+ void set_split_merge_on_transverse_mass(bool val) {
+ _split_merge_scale = val ? SM_mt : SM_pt;}
+
+ /// indicates whether the split-merge orders on transverse mass or not.
+ /// retained for backwards compatibility with 2.1.0b3
+ bool split_merge_use_pt_weighted_splitting() const {return _use_pt_weighted_splitting;}
+ void set_split_merge_use_pt_weighted_splitting(bool val) {
+ _use_pt_weighted_splitting = val;}
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const ;
+
+protected:
+ virtual void reset_stored_plugin() const;
+
+private:
+ double _protojet_ptmin;
+ SplitMergeScale _split_merge_scale;
+
+ bool _use_pt_weighted_splitting;
+
+ // part needed for the cache
+ // variables for caching the results and the input
+ static std::auto_ptr<SISConePlugin > stored_plugin;
+ static std::auto_ptr<std::vector<PseudoJet> > stored_particles;
+ static std::auto_ptr<siscone::Csiscone > stored_siscone;
+};
+
+
+//======================================================================
+/// Class that provides extra information about a SISCone clustering
+class SISConeExtras : public SISConeBaseExtras {
+public:
+ /// constructor
+ // it just initialises the pass information
+ SISConeExtras(int nparticles)
+ : SISConeBaseExtras(nparticles){}
+
+ /// access to the siscone jet def plugin (more convenient than
+ /// getting it from the original jet definition, because here it's
+ /// directly of the right type (rather than the base type)
+ const SISConePlugin* jet_def_plugin() const {
+ return dynamic_cast<const SISConePlugin*>(_jet_def_plugin);
+ }
+
+private:
+ // let us be written to by SISConePlugin
+ friend class SISConePlugin;
+};
+
+} // fastjet namespace
+
+#endif // __SISCONEPLUGIN_HH__
+
--- /dev/null
+#ifndef __SISCONESPHERICALPLUGIN_HH__
+#define __SISCONESPHERICALPLUGIN_HH__
+
+#include "SISConeBasePlugin.hh"
+
+// forward declaration of the siscone classes we'll need
+namespace siscone_spherical{
+ class CSphsiscone;
+};
+
+// questionable whether this should be in fastjet namespace or not...
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+//
+/// SISConeSphericalPlugin is a plugin for fastjet (v2.1 upwards) that
+/// provides an interface to the seedless infrared safe cone jet
+/// finder by Gregory Soyez and Gavin Salam.
+///
+/// This is the version of SISCone using spherical coordinates. Compared
+/// to the original cylindrical version:
+///
+/// - Particles are within a cone if their opening angle relative to the
+/// centre of the cone is less than R
+///
+/// - The split-merge step uses the total energy in the protojet as the
+/// ordering and overlap-measure variable
+///
+/// - The IR safety of the split-merge step is _not_ guaranteed for
+/// events consisting of two back-to-back identical heavy particles
+/// that decay. This is because of potential degeneracies in the
+/// ordering for the split-merge step.
+///
+/// For moderate values of R the problem should not be too severe
+/// (or may even be absent for some values of the overlap
+/// parameter), however the user should be aware of the issue.
+///
+/// The default split-merge scale may change at a later date to
+/// resolve this issue.
+///
+///
+/// SISCone uses geometrical techniques to exhaustively consider all
+/// possible distinct cones. It then finds out which ones are stable
+/// and sends the result to the Tevatron Run-II type split-merge
+/// procedure for overlapping cones.
+///
+/// Four parameters govern the "physics" of the algorithm:
+///
+/// - the cone_radius (this should be self-explanatory!)
+///
+/// - the overlap_threshold is the parameter which dictates how much
+/// two jets must overlap (E_overlap/min(E1,E2)) if they are to be
+/// merged
+///
+/// - Not all particles are in stable cones in the first round of
+/// searching for stable cones; one can therefore optionally have the
+/// the jet finder carry out additional passes of searching for
+/// stable cones among particles that were in no stable cone in
+/// previous passes --- the maximum number of passes carried out is
+/// n_pass_max. If this is zero then additional passes are carried
+/// out until no new stable cones are found.
+///
+/// - Protojet Emin: protojets that are below this Emin
+/// (default = 0) are discarded before each iteration of the
+/// split-merge loop.
+///
+/// One parameter governs some internal algorithmic shortcuts:
+///
+/// - if "caching" is turned on then the last event clustered by
+/// siscone is stored -- if the current event is identical and the
+/// cone_radius and n_pass_max are identical, then the only part of
+/// the clustering that needs to be rerun is the split-merge part,
+/// leading to significant speed gains; there is a small (O(N) storage
+/// and speed) penalty for caching, so it should be kept off
+/// (default) if only a single overlap_threshold is used.
+///
+/// The final jets can be accessed by requestion the
+/// inclusive_jets(...) from the ClusterSequence object. Note that
+/// these PseudoJets have their user_index() set to the index of the
+/// pass in which they were found (first pass = 0). NB: This does not
+/// currently work for jets that consist of a single particle.
+///
+/// For further information on the details of the algorithm see the
+/// SISCone paper, arXiv:0704.0292 [JHEP 0705:086,2007].
+///
+/// For documentation about the implementation, see the
+/// siscone/doc/html/index.html file.
+//
+class SISConeSphericalPlugin : public SISConeBasePlugin{
+public:
+
+ /// enum for the different split-merge scale choices;
+ /// Note that order _must_ be the same as in siscone
+ enum SplitMergeScale {SM_E, ///< Energy (IR unsafe with momentum conservation)
+ SM_Etilde ///< sum_{i \in jet} E_i [1+sin^2(theta_iJ)]
+ };
+
+
+ /// Main constructor for the SISConeSpherical Plugin class.
+ ///
+ ///
+ SISConeSphericalPlugin (double cone_radius,
+ double overlap_threshold,
+ int n_pass_max = 0,
+ double protojet_Emin = 0.0,
+ bool caching = false,
+ SplitMergeScale split_merge_scale = SM_Etilde,
+ double split_merge_stopping_scale = 0.0){
+ _cone_radius =cone_radius;
+ _overlap_threshold =overlap_threshold;
+ _n_pass_max =n_pass_max;
+ _protojet_Emin =protojet_Emin;
+ _caching =caching;
+ _split_merge_scale =split_merge_scale;
+ _split_merge_stopping_scale = split_merge_stopping_scale;
+ _ghost_sep_scale = 0.0;
+ _use_E_weighted_splitting = false;
+ }
+
+ /// minimum energy for a protojet to be considered in the split-merge step
+ /// of the algorithm
+ double protojet_Emin () const {return _protojet_Emin ;}
+
+ /// return the scale to be passed to SISCone as the protojet_Emin
+ /// -- if we have a ghost separation scale that is above the
+ /// protojet_ptmin, then the ghost_separation_scale becomes the
+ /// relevant one to use here
+ double protojet_or_ghost_Emin () const {return std::max(_protojet_Emin,
+ _ghost_sep_scale);}
+
+ /// indicates scale used in split-merge
+ SplitMergeScale split_merge_scale() const {return _split_merge_scale;}
+ /// sets scale used in split-merge
+ void set_split_merge_scale(SplitMergeScale sms) {_split_merge_scale = sms;}
+
+ /// indicate if the splittings are done using the anti-kt distance
+ bool split_merge_use_E_weighted_splitting() const {return _use_E_weighted_splitting;}
+ void set_split_merge_use_E_weighted_splitting(bool val) {
+ _use_E_weighted_splitting = val;}
+
+ /// overload the default as we don't provide support
+ /// for passive areas.
+ virtual bool supports_ghosted_passive_areas() const {return true;}
+
+ // the things that are required by base class
+ virtual std::string description () const;
+ virtual void run_clustering(ClusterSequence &) const ;
+
+protected:
+ virtual void reset_stored_plugin() const;
+
+private:
+ double _protojet_Emin;
+ SplitMergeScale _split_merge_scale;
+ bool _use_E_weighted_splitting;
+
+ // part needed for the cache
+ // variables for caching the results and the input
+ static std::auto_ptr<SISConeSphericalPlugin > stored_plugin;
+ static std::auto_ptr<std::vector<PseudoJet> > stored_particles;
+ static std::auto_ptr<siscone_spherical::CSphsiscone> stored_siscone;
+};
+
+//======================================================================
+/// Class that provides extra information about a SISCone clustering
+class SISConeSphericalExtras : public SISConeBaseExtras {
+public:
+ /// constructor
+ // it just initialises the pass information
+ SISConeSphericalExtras(int nparticles)
+ : SISConeBaseExtras(nparticles){}
+
+ /// access to the siscone jet def plugin (more convenient than
+ /// getting it from the original jet definition, because here it's
+ /// directly of the right type (rather than the base type)
+ const SISConeSphericalPlugin* jet_def_plugin() const {
+ return dynamic_cast<const SISConeSphericalPlugin*>(_jet_def_plugin);
+ }
+
+private:
+ // let us be written to by SISConePlugin
+ friend class SISConeSphericalPlugin;
+};
+
+} // fastjet namespace
+
+#endif // __SISCONEPLUGIN_HH__
+
--- /dev/null
+#ifndef __FASTJET_CONFIG_H__
+#define __FASTJET_CONFIG_H__
+
+// by default, use an automatically generated config_auto.h
+// unless it's a windows machine in which case
+#ifndef WIN32
+#include "config_auto.h"
+#else
+#include "fastjet/config_win.h"
+#endif // WIN32
+
+#endif // __FASTJET_CONFIG_H__
--- /dev/null
+/* include/fastjet/config_auto.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* The ATLASCone plugin is enabled */
+/* #undef ENABLE_PLUGIN_ATLASCONE */
+
+/* The CDFJetClu and CDFMidPoint plugins are enabled */
+#define ENABLE_PLUGIN_CDFCONES
+
+/* The CMSIterativeCone plugin is enabled */
+/* #undef ENABLE_PLUGIN_CMSITERATIVECONE */
+
+/* The D0RunIICone plugin is enabled */
+/* #undef ENABLE_PLUGIN_D0RUNIICONE */
+
+/* The EECambridge plugin is enabled */
+#define ENABLE_PLUGIN_EECAMBRIDGE
+
+/* The Jade plugin is enabled */
+#define ENABLE_PLUGIN_JADE
+
+/* The NestedDefs plugin is enabled */
+#define ENABLE_PLUGIN_NESTEDDEFS
+
+/* The PxCone plugin is enabled */
+/* #undef ENABLE_PLUGIN_PXCONE */
+
+/* The SISCone plugin is enabled */
+#define ENABLE_PLUGIN_SISCONE
+
+/* The TrackJet plugin is enabled */
+/* #undef ENABLE_PLUGIN_TRACKJET */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "fastjet"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "FastJet"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "FastJet 2.4.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "fastjet"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.4.0"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "2.4.0"
--- /dev/null
+#define PACKAGE_STRING "FastJet 2.4.0"
+#define PACKAGE_VERSION "2.4.0"
+
+/* The CDFJetClu and CDFMidPoint plugins are enabled by default*/
+#define ENABLE_PLUGIN_CDFCONES
+
+/* The PxCone plugin is disabled by default*/
+#undef ENABLE_PLUGIN_PXCONE
+
+/* The SISCone plugin is enabled by default*/
+#define ENABLE_PLUGIN_SISCONE
--- /dev/null
+// Simple random number generator class taken from nlojet++.
+// Some doxygen-style comments added by Gavin Salam, August 2006.
+// $Id: BasicRandom.hh 621 2007-05-09 10:34:30Z salam $
+//
+// Copyright (C) 2002 Zoltan Nagy
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#ifndef __FASTJET_BASICRANDOM_HH__
+#define __FASTJET_BASICRANDOM_HH__ 1
+
+// Standard includes
+#include <iostream>
+#include <vector>
+#include <cassert>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+template<typename _Tp> class BasicRandom {
+public:
+ typedef _Tp value_type;
+ typedef unsigned int size_type;
+ typedef value_type* pointer;
+
+ // give pseudo random numbers
+ value_type operator() ();
+ void operator() (size_type, pointer);
+
+ // (re)initialize the random number generator
+ void randomize(void *);
+
+ // minimum and maximum values
+ static value_type min();
+ static value_type max();
+
+ // print the informations about the generator to the stream
+ void print_info(std::ostream& __os = std::cout);
+};
+
+// default random generator
+int __default_random_generator(int *__iseed);
+
+
+// specializations
+template<>
+class BasicRandom<int>
+{
+public:
+ typedef int value_type;
+ typedef unsigned int size_type;
+ typedef value_type* pointer;
+
+ // constructors
+ explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
+ _M_iseed[0] = __s1;
+ _M_iseed[1] = __s2;
+ }
+
+ // give pseudo random numbers
+ value_type operator() () {
+ return __default_random_generator(_M_iseed);
+ }
+
+ void operator() (size_type __n, pointer __res) {
+ for(size_type __i = 0; __i < __n; __i++)
+ __res[__i] = __default_random_generator(_M_iseed);
+ }
+
+ // (re)initialize the random number generator
+ void randomize(void *__iseed) {
+ int *__new_seed = (int*) __iseed;
+ _M_iseed[0] = __new_seed[0];
+ _M_iseed[1] = __new_seed[1];
+ }
+
+ void set_status(const std::vector<int> & __iseed) {
+ assert(__iseed.size() >= 2);
+ _M_iseed[0] = __iseed[0];
+ _M_iseed[1] = __iseed[1];
+ }
+
+ void get_status(std::vector<int> & __iseed) {
+ __iseed.resize(2);
+ __iseed[0] = _M_iseed[0];
+ __iseed[1] = _M_iseed[1];
+ }
+
+ // minimum and maximum values
+ inline static value_type min() { return 0;}
+ inline static value_type max() { return 2147483647;}
+
+ // print the informations about the generator to the stream
+ void print_info(std::ostream& __os = std::cout) {
+ __os<<"BasicRandom<int> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
+ }
+
+private:
+ int _M_iseed[2];
+};
+
+
+/// template specialization (double) for the BasicRandom template class.
+template<> class BasicRandom<double> {
+public:
+ typedef double value_type;
+ typedef unsigned int size_type;
+ typedef value_type* pointer;
+
+ /// constructor that takes two integers to specify the seed
+ explicit BasicRandom(int __s1 = 12345, int __s2 = 67890) {
+ _M_iseed[0] = __s1;
+ _M_iseed[1] = __s2;
+ }
+
+ /// return a single pseudorandom double number, in the range 0.0 to 1.0
+ /// (not sure whether this range is open or closed)
+ value_type operator() () {
+ return 4.6566128752457969241e-10*__default_random_generator(_M_iseed);
+ }
+
+ /// given a pointer __res to the beginning of an array, fill that array
+ /// with __n random numbers
+ void operator() (size_type __n, pointer __res) {
+ for(size_type __i = 0; __i < __n; __i++)
+ __res[__i] = this -> operator()();
+ }
+
+ /// (re)initialize the random number generator from an array of seeds
+ void randomize(void *__iseed) {
+ int *__new_seed = (int*) __iseed;
+ _M_iseed[0] = __new_seed[0];
+ _M_iseed[1] = __new_seed[1];
+ }
+
+ void set_status(const std::vector<int> & __iseed) {
+ assert(__iseed.size() >= 2);
+ _M_iseed[0] = __iseed[0];
+ _M_iseed[1] = __iseed[1];
+ }
+
+ void get_status(std::vector<int> & __iseed) {
+ __iseed.resize(2);
+ __iseed[0] = _M_iseed[0];
+ __iseed[1] = _M_iseed[1];
+ }
+
+ /// minimum value returned by the generator
+ inline static value_type min() { return 0.0;}
+ /// maximum value returned by the generator
+ inline static value_type max() { return 1.0;}
+
+ /// print information about the generator to the stream
+ void print_info(std::ostream& __os = std::cout) {
+ __os<<"BasicRandom<double> : "<<_M_iseed[0]<<", "<<_M_iseed[1]<<std::endl;
+ }
+
+private:
+ int _M_iseed[2];
+};
+
+// globally defined random number generator
+extern BasicRandom<int> _G_random_int;
+extern BasicRandom<double> _G_random_double;
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_BASICRANDOM_HH__
+
--- /dev/null
+//STARTHEADER
+// $Id: ClosestPair2D.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLOSESTPAIR2D__HH__
+#define __FASTJET_CLOSESTPAIR2D__HH__
+
+#include<vector>
+#include<stack>
+#include<iostream>
+#include "fastjet/internal/ClosestPair2DBase.hh"
+#include "fastjet/internal/SearchTree.hh"
+#include "fastjet/internal/MinHeap.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// concrete implementation for finding closest pairs in 2D -- will
+/// use Chan's (hopefully efficient) shuffle based structures
+class ClosestPair2D : public ClosestPair2DBase {
+public:
+ /// constructor from a vector of 2D positions -- number of objects
+ /// after insertion and deletion must never exceed positions.size();
+ /// objects are given IDs that correspond to their index in the vector
+ /// of positions
+ ClosestPair2D(const std::vector<Coord2D> & positions,
+ const Coord2D & left_corner, const Coord2D & right_corner) {
+ _initialize(positions, left_corner, right_corner, positions.size());
+ };
+
+ /// constructor which allows structure to grow beyond positions.size(), up
+ /// to max_size
+ ClosestPair2D(const std::vector<Coord2D> & positions,
+ const Coord2D & left_corner, const Coord2D & right_corner,
+ const unsigned int max_size) {
+ _initialize(positions, left_corner, right_corner, max_size);
+ };
+
+ /// provides the IDs of the closest pair as well as the distance between
+ /// them
+ void closest_pair(unsigned int & ID1, unsigned int & ID2,
+ double & distance2) const;
+
+ /// removes the entry labelled by ID from the object;
+ void remove(unsigned int ID);
+
+ /// inserts the position into the closest pair structure and returns the
+ /// ID that has been allocated for the object.
+ unsigned int insert(const Coord2D &);
+
+ /// removes ID1 and ID2 and inserts position, returning the ID
+ /// corresponding to position...
+ virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
+ const Coord2D & position);
+
+ /// replaces IDs_to_remove with points at the new_positions
+ /// indicating the IDs allocated to the new points in new_IDs
+ virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
+ const std::vector<Coord2D> & new_positions,
+ std::vector<unsigned int> & new_IDs);
+
+ // mostly for checking how things are working...
+ inline void print_tree_depths(std::ostream & outdev) const {
+ outdev << _trees[0]->max_depth() << " "
+ << _trees[1]->max_depth() << " "
+ << _trees[2]->max_depth() << "\n";
+ };
+
+ unsigned int size();
+
+private:
+
+ void _initialize(const std::vector<Coord2D> & positions,
+ const Coord2D & left_corner, const Coord2D & right_corner,
+ const unsigned int max_size);
+
+ static const unsigned int _nshift = 3;
+
+ class Point; // will be defined below
+
+ /// since sets of three objects will crop up repeatedly, useful
+ /// to have a triplet class?
+ template<class T> class triplet {
+ public:
+ inline const T & operator[](unsigned int i) const {return _contents[i];};
+ inline T & operator[](unsigned int i) {return _contents[i];};
+ private:
+ T _contents[_nshift];
+ };
+
+
+ /// class that will take care of ordering of shuffles for us
+ class Shuffle {
+ public:
+ unsigned int x, y;
+ Point * point;
+ bool operator<(const Shuffle &) const;
+ void operator+=(unsigned int shift) {x += shift; y+= shift;};
+ };
+
+ typedef SearchTree<Shuffle> Tree;
+ typedef Tree::circulator circulator;
+ typedef Tree::const_circulator const_circulator;
+
+
+ triplet<std::auto_ptr<Tree> > _trees;
+ std::auto_ptr<MinHeap> _heap;
+ std::vector<Point> _points;
+ std::stack<Point *> _available_points;
+
+ /// points that are "under review" in some way
+ std::vector<Point *> _points_under_review;
+
+ // different statuses for review
+ static const unsigned int _remove_heap_entry = 1;
+ static const unsigned int _review_heap_entry = 2;
+ static const unsigned int _review_neighbour = 4;
+
+ /// add a label to a point as to the nature of review needed
+ /// (includes adding it to list of points needing review) [doesn't
+ /// affect other labels already set for the point]
+ void _add_label(Point * point, unsigned int review_flag);
+
+ /// sets the label for the point to be exclusively this
+ /// review flag (and adds it to list of points needing review
+ /// if not already there)
+ void _set_label(Point * point, unsigned int review_flag);
+
+ /// for all entries of the _points_under_review[] vector, carry out
+ /// the actions indicated by its review flag; the points are
+ /// then removed from _points_under_review[] and their flags
+ /// set to zero
+ void _deal_with_points_to_review();
+
+ /// carry out the search-tree related operations of point removal
+ void _remove_from_search_tree(Point * point_to_remove);
+
+ /// carry out the search-tree related operations of point insertion
+ void _insert_into_search_tree(Point * new_point);
+
+ /// takes a point and creates a shuffle with the given shift
+ void _point2shuffle(Point & , Shuffle & , unsigned int shift);
+
+ /// pieces needed for converting coordinates to integer
+ Coord2D _left_corner;
+ double _range;
+
+ int _ID(const Point *) const;
+
+ triplet<unsigned int> _shifts; // absolute shifts
+ triplet<unsigned int> _rel_shifts; // shifts relative to previous shift
+
+ unsigned int _cp_search_range;
+};
+
+
+//----------------------------------------------------------------------
+/// class for representing all info needed about a point
+class ClosestPair2D::Point {
+public:
+ /// the point's coordinates
+ Coord2D coord;
+ /// a pointer to its closest neighbour in our structure
+ Point * neighbour;
+ /// the corresponding squared distance
+ double neighbour_dist2;
+ /// circulators for each of the shifts of the shuffles
+ triplet<circulator> circ;
+
+ /// indicates that something special is currently happening to this point
+ unsigned int review_flag;
+
+ /// returns the distance between two of these objects
+ double distance2(const Point & other) const {
+ return coord.distance2(other.coord);
+ };
+
+ /// creates a shuffle for us with a given shift
+ //void set_shuffle(Shuffle & shuffle);
+};
+
+
+//----------------------------------------------------------------------
+/// returns true if floor(ln_base2(x)) < floor(ln_base2(y)), using
+/// Chan's neat trick...
+inline bool floor_ln2_less(unsigned x, unsigned y) {
+ if (x>y) return false;
+ return (x < (x^y)); // beware of operator precedence...
+}
+
+
+//----------------------------------------------------------------------
+/// returns the ID for the specified point...
+inline int ClosestPair2D::_ID(const Point * point) const {
+ return point - &(_points[0]);
+}
+
+
+//
+inline unsigned int ClosestPair2D::size() {
+ return _points.size() - _available_points.size();
+}
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLOSESTPAIR2D__HH__
--- /dev/null
+//STARTHEADER
+// $Id: ClosestPair2DBase.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_CLOSESTPAIR2DBASE__HH__
+#define __FASTJET_CLOSESTPAIR2DBASE__HH__
+
+#include<vector>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//----------------------------------------------------------------------
+/// class for representing 2d coordinates and carrying out some basic
+/// operations on them
+class Coord2D {
+public:
+ double x, y;
+
+ Coord2D() {};
+
+ Coord2D(double a, double b): x(a), y(b) {};
+
+ /// return the vector difference between two coordinates
+ Coord2D operator-(const Coord2D & other) const {
+ return Coord2D(x - other.x, y - other.y);};
+
+ /// return the vector sum between two coordinates
+ Coord2D operator+(const Coord2D & other) const {
+ return Coord2D(x + other.x, y + other.y);};
+
+ /// return the product of the coordinate with the factor
+ Coord2D operator*(double factor) const {return Coord2D(factor*x,factor*y);};
+ friend Coord2D operator*(double factor, const Coord2D & coord) {
+ return Coord2D(factor*coord.x,factor*coord.y);
+ }
+
+ /// division of each component of coordinate
+ Coord2D operator/(double divisor) const {
+ return Coord2D(x / divisor, y / divisor);};
+
+ /// return the squared distance between two coordinates
+ friend double distance2(const Coord2D & a, const Coord2D & b) {
+ double dx = a.x - b.x, dy = a.y-b.y;
+ return dx*dx+dy*dy;
+ };
+ /// return the squared distance between two coordinates
+ double distance2(const Coord2D & b) const {
+ double dx = x - b.x, dy = y-b.y;
+ return dx*dx+dy*dy;
+ };
+};
+
+
+//----------------------------------------------------------------------
+/// abstract base class for finding closest pairs in 2D
+class ClosestPair2DBase {
+public:
+ /// provides the IDs of the closest pair as well as the squared
+ /// distance between them
+ virtual void closest_pair(unsigned int & ID1, unsigned int & ID2,
+ double & distance2) const = 0;
+
+ /// removes the entry labelled by ID from the object;
+ virtual void remove(unsigned int ID) = 0;
+
+ /// inserts the position into the closest pair structure and returns the
+ /// ID that has been allocated for the object.
+ virtual unsigned int insert(const Coord2D & position) = 0;
+
+ /// replaces the specified ID1 and ID2 with something at a new position
+ /// assuming that ID1 and ID2 are in sequence wrt position; it returns
+ /// the ID of the new object...
+ virtual unsigned int replace(unsigned int ID1, unsigned int ID2,
+ const Coord2D & position) {
+ remove(ID1);
+ remove(ID2);
+ unsigned new_ID = insert(position);
+ return(new_ID);
+ };
+
+ /// replaces IDs_to_remove with points at the new_positions
+ /// indicating the IDs allocated to the new points in new_IDs
+ virtual void replace_many(const std::vector<unsigned int> & IDs_to_remove,
+ const std::vector<Coord2D> & new_positions,
+ std::vector<unsigned int> & new_IDs) {
+ for(unsigned i = 0; i < IDs_to_remove.size(); i++) {
+ remove(IDs_to_remove[i]);}
+ new_IDs.resize(0);
+ for(unsigned i = 0; i < new_positions.size(); i++) {
+ new_IDs.push_back(insert(new_positions[i]));}
+ }
+
+ virtual unsigned int size() = 0;
+
+ virtual ~ClosestPair2DBase() {};
+
+};
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_CLOSESTPAIR2DBASE__HH__
--- /dev/null
+//STARTHEADER
+// $Id: Dnn2piCylinder.hh 431 2007-01-20 10:44:55Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN2PICYLINDER_HH__
+#define __FASTJET_DNN2PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using one
+/// DnnPlane object spanning 0--2pi).
+class Dnn2piCylinder : public DynamicNearestNeighbours {
+ public:
+ /// empty initaliser
+ Dnn2piCylinder() {}
+
+ /// Initialiser from a set of points on an Eta-Phi plane, where
+ /// eta can have an arbitrary ranges and phi must be in range
+ /// 0 <= phi < 2pi;
+ ///
+ /// NB: this class is more efficient than the plain Dnn4piCylinder
+ /// class, but can give wrong answers when the nearest neighbour is
+ /// further away than 2pi (in this case a point's nearest neighbour
+ /// becomes itself, because it is considered to be a distance 2pi
+ /// away). For the kt-algorithm (e.g.) this is actually not a
+ /// problem (the distance need only be accurate when it is less than
+ /// R), so we can tell the routine to ignore this problem --
+ /// alternatively the routine will crash if it detects it occurring
+ /// (only when finding the nearest neighbour index, not its
+ /// distance).
+ Dnn2piCylinder(const std::vector<EtaPhi> &,
+ const bool & ignore_nearest_is_mirror = false,
+ const bool & verbose = false );
+
+ /// Returns the index of the nearest neighbour of point labelled
+ /// by ii (assumes ii is valid)
+ int NearestNeighbourIndex(const int & ii) const ;
+
+ /// Returns the distance to the nearest neighbour of point labelled
+ /// by index ii (assumes ii is valid)
+ double NearestNeighbourDistance(const int & ii) const ;
+
+ /// Returns true iff the given index corresponds to a point that
+ /// exists in the DNN structure (meaning that it has been added, and
+ /// not removed in the meantime)
+ bool Valid(const int & index) const;
+
+ void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+ const std::vector<EtaPhi> & points_to_add,
+ std::vector<int> & indices_added,
+ std::vector<int> & indices_of_updated_neighbours);
+
+ ~Dnn2piCylinder();
+
+ private:
+
+ // our extras to help us navigate, find distance, etc.
+ const static int INEXISTENT_VERTEX=-3;
+
+ bool _verbose;
+
+ bool _ignore_nearest_is_mirror;
+
+ /// Picture of how things will work... Copy 0--pi part of the 0--2pi
+ /// cylinder into a region 2pi--2pi+ a bit of a Euclidean plane. Below we
+ /// show points labelled by + that have a mirror image in this
+ /// manner, while points labelled by * do not have a mirror image.
+ ///
+ /// | . |
+ /// | . |
+ /// | . |
+ /// | . |
+ /// | 2 . |
+ /// | * . |
+ /// | + . + |
+ /// | 0 . 1 |
+ /// | . |
+ /// 0 2pi 2pi + a bit
+ ///
+ /// Each "true" point has its true "cylinder" index (the index that
+ /// is known externally to this class) as well as euclidean plane
+ /// indices (main_index and mirror index in the MirrorVertexInfo
+ /// structure), which are private concepts of this class.
+ ///
+ /// In above picture our structures would hold the following info
+ /// (the picture shows the euclidean-plane numbering)
+ ///
+ /// _mirror_info[cylinder_index = 0] = (0, 1)
+ /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX)
+ ///
+ /// We also need to be able to go from the euclidean plane indices
+ /// back to the "true" cylinder index, and for this purpose we use
+ /// the std::vector _cylinder_index_of_plane_vertex[...], which in the above example has
+ /// the following contents
+ ///
+ /// _cylinder_index_of_plane_vertex[0] = 0
+ /// _cylinder_index_of_plane_vertex[1] = 0
+ /// _cylinder_index_of_plane_vertex[2] = 1
+ ///
+
+ ///
+ struct MirrorVertexInfo {
+ /// index of the given point (appearing in the range 0--2pi) in the
+ /// 0--2pi euclidean plane structure (position will coincide with
+ /// that on the 0--2pi cylinder, but index labelling it will be
+ /// different)
+ int main_index;
+ /// index of the mirror point (appearing in the range 2pi--3pi) in the
+ /// 0--3pi euclidean plane structure
+ int mirror_index;
+ };
+
+ // for each "true" vertex we have reference to indices in the euclidean
+ // plane structure
+ std::vector<MirrorVertexInfo> _mirror_info;
+ // for each index in the euclidean 0--2pi plane structure we want to
+ // be able to get back to the "true" vertex index on the overall
+ // 0--2pi cylinder structure
+ std::vector<int> _cylinder_index_of_plane_vertex;
+
+ // NB: we define POINTERS here because the initialisation gave
+ // us problems (things crashed!), perhaps because in practice
+ // we were making a copy without being careful and defining
+ // a proper copy constructor.
+ DnnPlane * _DNN;
+
+ /// given a phi value in the 0--pi range return one
+ /// in the 2pi--3pi range; whereas if it is in the pi-2pi range then
+ /// remap it to be inthe range (-pi)--0.
+ inline EtaPhi _remap_phi(const EtaPhi & point) {
+ double phi = point.second;
+ if (phi < pi) { phi += twopi ;} else {phi -= twopi;}
+ return EtaPhi(point.first, phi);}
+
+
+ //----------------------------------------------------------------------
+ /// Actions here are similar to those in the
+ /// Dnn3piCylinder::_RegisterCylinderPoint case, however here we do
+ /// NOT create the mirror point -- instead we initialise the structure
+ /// as if there were no need for the mirror point.
+ ///
+ /// ADDITIONALLY push the cylinder_point onto the vector plane_points.
+ void _RegisterCylinderPoint (const EtaPhi & cylinder_point,
+ std::vector<EtaPhi> & plane_points);
+
+ /// For each plane point specified in the vector plane_indices,
+ /// establish whether there is a need to create a mirror point
+ /// according to the following criteria:
+ ///
+ /// . phi < pi
+ /// . mirror does not already exist
+ /// . phi < NearestNeighbourDistance
+ /// (if this is not true then there is no way that its mirror point
+ /// could have a nearer neighbour).
+ ///
+ /// If conditions all hold, then create the mirror point, insert it
+ /// into the _DNN structure, adjusting any nearest neighbours, and
+ /// return the list of plane points whose nearest neighbours have
+ /// changed (this will include the new neighbours that have just been
+ /// added)
+ void _CreateNecessaryMirrorPoints(
+ const std::vector<int> & plane_indices,
+ std::vector<int> & updated_plane_points);
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+//----------------------------------------------------------------------
+/// Note: one of the difficulties of the 0--2pi mapping is that
+/// a point may have its mirror copy as its own nearest neighbour
+/// (if no other point is within a distance of 2pi). This does
+/// not matter for the kt_algorithm with
+/// reasonable values of radius, but might matter for a general use
+/// of this algorithm -- depending on whether or not the user has
+/// initialised the class with instructions to ignore this problem the
+/// program will detect and ignore it, or crash.
+inline int Dnn2piCylinder::NearestNeighbourIndex(const int & current) const {
+ int main_index = _mirror_info[current].main_index;
+ int mirror_index = _mirror_info[current].mirror_index;
+ int plane_index;
+ if (mirror_index == INEXISTENT_VERTEX ) {
+ plane_index = _DNN->NearestNeighbourIndex(main_index);
+ } else {
+ plane_index = (
+ _DNN->NearestNeighbourDistance(main_index) <
+ _DNN->NearestNeighbourDistance(mirror_index)) ?
+ _DNN->NearestNeighbourIndex(main_index) :
+ _DNN->NearestNeighbourIndex(mirror_index) ;
+ }
+ int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index];
+ // either the user has acknowledged the fact that they may get the
+ // mirror copy as the closest point, or crash if it should occur
+ // that mirror copy is the closest point.
+ assert(_ignore_nearest_is_mirror || this_cylinder_index != current);
+ //if (this_cylinder_index == current) {
+ // cerr << "WARNING point "<<current<<
+ // " has its mirror copy as its own nearest neighbour"<<endl;
+ //}
+ return this_cylinder_index;
+}
+
+inline double Dnn2piCylinder::NearestNeighbourDistance(const int & current) const {
+ int main_index = _mirror_info[current].main_index;
+ int mirror_index = _mirror_info[current].mirror_index;
+ if (mirror_index == INEXISTENT_VERTEX ) {
+ return _DNN->NearestNeighbourDistance(main_index);
+ } else {
+ return (
+ _DNN->NearestNeighbourDistance(main_index) <
+ _DNN->NearestNeighbourDistance(mirror_index)) ?
+ _DNN->NearestNeighbourDistance(main_index) :
+ _DNN->NearestNeighbourDistance(mirror_index) ;
+ }
+
+}
+
+inline bool Dnn2piCylinder::Valid(const int & index) const {
+ return (_DNN->Valid(_mirror_info[index].main_index));
+}
+
+
+inline Dnn2piCylinder::~Dnn2piCylinder() {
+ delete _DNN;
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_DNN2PICYLINDER_HH__
+#endif //DROP_CGAL
--- /dev/null
+//STARTHEADER
+// $Id: Dnn3piCylinder.hh 431 2007-01-20 10:44:55Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN3PICYLINDER_HH__
+#define __FASTJET_DNN3PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using one
+/// DnnPlane object spanning 0--3pi).
+class Dnn3piCylinder : public DynamicNearestNeighbours {
+ public:
+ /// empty initaliser
+ Dnn3piCylinder() {}
+
+ /// Initialiser from a set of points on an Eta-Phi plane, where
+ /// eta can have an arbitrary ranges and phi must be in range
+ /// 0 <= phi < 2pi;
+ ///
+ /// NB: this class is more efficient than the plain Dnn4piCylinder
+ /// class, but can give wrong answers when the nearest neighbour is
+ /// further away than 2pi (in this case a point's nearest neighbour
+ /// becomes itself, because it is considered to be a distance 2pi
+ /// away). For the kt-algorithm (e.g.) this is actually not a
+ /// problem (the distance need only be accurate when it is less than
+ /// R), so we can tell the routine to ignore this problem --
+ /// alternatively the routine will crash if it detects it occurring
+ /// (only when finding the nearest neighbour index, not its
+ /// distance).
+ Dnn3piCylinder(const std::vector<EtaPhi> &,
+ const bool & ignore_nearest_is_mirror = false,
+ const bool & verbose = false );
+
+ /// Returns the index of the nearest neighbour of point labelled
+ /// by ii (assumes ii is valid)
+ int NearestNeighbourIndex(const int & ii) const ;
+
+ /// Returns the distance to the nearest neighbour of point labelled
+ /// by index ii (assumes ii is valid)
+ double NearestNeighbourDistance(const int & ii) const ;
+
+ /// Returns true iff the given index corresponds to a point that
+ /// exists in the DNN structure (meaning that it has been added, and
+ /// not removed in the meantime)
+ bool Valid(const int & index) const;
+
+ void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+ const std::vector<EtaPhi> & points_to_add,
+ std::vector<int> & indices_added,
+ std::vector<int> & indices_of_updated_neighbours);
+
+ ~Dnn3piCylinder();
+
+ private:
+
+ // our extras to help us navigate, find distance, etc.
+ const static int INEXISTENT_VERTEX=-3;
+
+ bool _verbose;
+
+ bool _ignore_nearest_is_mirror;
+
+ /// Picture of how things will work... Copy 0--pi part of the 0--2pi
+ /// cylinder into a region 2pi--3pi of a Euclidean plane. Below we
+ /// show points labelled by + that have a mirror image in this
+ /// manner, while points labelled by * do not have a mirror image.
+ ///
+ /// | . |
+ /// | . |
+ /// | . |
+ /// | . |
+ /// | 2 . |
+ /// | * . |
+ /// | + . + |
+ /// | 0 . 1 |
+ /// | . |
+ /// 0 2pi 3pi
+ ///
+ /// Each "true" point has its true "cylinder" index (the index that
+ /// is known externally to this class) as well as euclidean plane
+ /// indices (main_index and mirror index in the MirrorVertexInfo
+ /// structure), which are private concepts of this class.
+ ///
+ /// In above picture our structures would hold the following info
+ /// (the picture shows the euclidean-plane numbering)
+ ///
+ /// _mirror_info[cylinder_index = 0] = (0, 1)
+ /// _mirror_info[cylinder_index = 1] = (2, INEXISTENT_VERTEX)
+ ///
+ /// We also need to be able to go from the euclidean plane indices
+ /// back to the "true" cylinder index, and for this purpose we use
+ /// the vector _cylinder_index_of_plane_vertex[...], which in the above example has
+ /// the following contents
+ ///
+ /// _cylinder_index_of_plane_vertex[0] = 0
+ /// _cylinder_index_of_plane_vertex[1] = 0
+ /// _cylinder_index_of_plane_vertex[2] = 1
+ ///
+
+ ///
+ struct MirrorVertexInfo {
+ /// index of the given point (appearing in the range 0--2pi) in the
+ /// 0--3pi euclidean plane structure (position will coincide with
+ /// that on the 0--2pi cylinder, but index labelling it will be
+ /// different)
+ int main_index;
+ /// index of the mirror point (appearing in the range 2pi--3pi) in the
+ /// 0--3pi euclidean plane structure
+ int mirror_index;
+ };
+
+ // for each "true" vertex we have reference to indices in the euclidean
+ // plane structure
+ std::vector<MirrorVertexInfo> _mirror_info;
+ // for each index in the euclidean 0--3pi plane structure we want to
+ // be able to get back to the "true" vertex index on the overall
+ // 0--2pi cylinder structure
+ std::vector<int> _cylinder_index_of_plane_vertex;
+
+ // NB: we define POINTERS here because the initialisation gave
+ // us problems (things crashed!), perhaps because in practice
+ // we were making a copy without being careful and defining
+ // a proper copy constructor.
+ DnnPlane * _DNN;
+
+ /// given a phi value in the 0--2pi range return one
+ /// in the pi--3pi range.
+ inline EtaPhi _remap_phi(const EtaPhi & point) {
+ double phi = point.second;
+ if (phi < pi) { phi += twopi ;}
+ return EtaPhi(point.first, phi);}
+
+
+ //----------------------------------------------------------------------
+ /// What on earth does this do?
+ ///
+ /// Example: last true "cylinder" index was 15
+ /// last plane index was 23
+ ///
+ /// Then: _cylinder_index_of_plane_vertex.size() = 24 and
+ /// _mirror_info.size() = 16
+ ///
+ /// IF cylinder_point's phi < pi then
+ /// create: _mirror_info[16] = (main_index = 24, mirror_index=25)
+ /// _cylinder_index_of_plane_vertex[24] = 16
+ /// _cylinder_index_of_plane_vertex[25] = 16
+ /// ELSE
+ /// create: _mirror_info[16] = (main_index = 24, mirror_index=INEXISTENT..)
+ /// _cylinder_index_of_plane_vertex[24] = 16
+ ///
+ /// ADDITIONALLY push the cylinder_point (and if it exists the mirror
+ /// copy) onto the vector plane_points.
+ void _RegisterCylinderPoint (const EtaPhi & cylinder_point,
+ std::vector<EtaPhi> & plane_points);
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+//----------------------------------------------------------------------
+/// Note: one of the difficulties of the 0--3pi mapping is that
+/// a point may have its mirror copy as its own nearest neighbour
+/// (if no other point is within a distance of 2pi). This does
+/// not matter for the kt_algorithm with
+/// reasonable values of radius, but might matter for a general use
+/// of this algorithm -- depending on whether or not the user has
+/// initialised the class with instructions to ignore this problem the
+/// program will detect and ignore it, or crash.
+inline int Dnn3piCylinder::NearestNeighbourIndex(const int & current) const {
+ int main_index = _mirror_info[current].main_index;
+ int mirror_index = _mirror_info[current].mirror_index;
+ int plane_index;
+ if (mirror_index == INEXISTENT_VERTEX ) {
+ plane_index = _DNN->NearestNeighbourIndex(main_index);
+ } else {
+ plane_index = (
+ _DNN->NearestNeighbourDistance(main_index) <
+ _DNN->NearestNeighbourDistance(mirror_index)) ?
+ _DNN->NearestNeighbourIndex(main_index) :
+ _DNN->NearestNeighbourIndex(mirror_index) ;
+ }
+ int this_cylinder_index = _cylinder_index_of_plane_vertex[plane_index];
+ // either the user has acknowledged the fact that they may get the
+ // mirror copy as the closest point, or crash if it should occur
+ // that mirror copy is the closest point.
+ assert(_ignore_nearest_is_mirror || this_cylinder_index != current);
+ //if (this_cylinder_index == current) {
+ // std::cerr << "WARNING point "<<current<<
+ // " has its mirror copy as its own nearest neighbour"<<endl;
+ //}
+ return this_cylinder_index;
+}
+
+inline double Dnn3piCylinder::NearestNeighbourDistance(const int & current) const {
+ int main_index = _mirror_info[current].main_index;
+ int mirror_index = _mirror_info[current].mirror_index;
+ if (mirror_index == INEXISTENT_VERTEX ) {
+ return _DNN->NearestNeighbourDistance(main_index);
+ } else {
+ return (
+ _DNN->NearestNeighbourDistance(main_index) <
+ _DNN->NearestNeighbourDistance(mirror_index)) ?
+ _DNN->NearestNeighbourDistance(main_index) :
+ _DNN->NearestNeighbourDistance(mirror_index) ;
+ }
+
+}
+
+inline bool Dnn3piCylinder::Valid(const int & index) const {
+ return (_DNN->Valid(_mirror_info[index].main_index));
+}
+
+
+inline Dnn3piCylinder::~Dnn3piCylinder() {
+ delete _DNN;
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_DNN3PICYLINDER_HH__
+#endif // DROP_CGAL
--- /dev/null
+//STARTHEADER
+// $Id: Dnn4piCylinder.hh 431 2007-01-20 10:44:55Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_DNN4PICYLINDER_HH__
+#define __FASTJET_DNN4PICYLINDER_HH__
+
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+#include "fastjet/internal/DnnPlane.hh"
+#include "fastjet/internal/numconsts.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the surface of cylinder (using two copies of
+/// DnnPlane, one running from 0--2pi, the other from pi--3pi).
+class Dnn4piCylinder : public DynamicNearestNeighbours {
+ public:
+ /// empty initaliser
+ Dnn4piCylinder() {}
+
+ /// Initialiser from a set of points on an Eta-Phi plane, where
+ /// eta can have an arbitrary ranges and phi must be in range
+ /// 0 <= phi < 2pi
+ Dnn4piCylinder(const std::vector<EtaPhi> &, const bool & verbose = false );
+
+ /// Returns the index of the nearest neighbour of point labelled
+ /// by ii (assumes ii is valid)
+ int NearestNeighbourIndex(const int & ii) const ;
+
+ /// Returns the distance to the nearest neighbour of point labelled
+ /// by index ii (assumes ii is valid)
+ double NearestNeighbourDistance(const int & ii) const ;
+
+ /// Returns true iff the given index corresponds to a point that
+ /// exists in the DNN structure (meaning that it has been added, and
+ /// not removed in the meantime)
+ bool Valid(const int & index) const;
+
+ void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+ const std::vector<EtaPhi> & points_to_add,
+ std::vector<int> & indices_added,
+ std::vector<int> & indices_of_updated_neighbours);
+
+ ~Dnn4piCylinder();
+
+ private:
+
+ bool _verbose;
+
+ // NB: we define POINTERS here because the initialisation gave
+ // us problems (things crashed!), perhaps because in practice
+ // we were making a copy without being careful and defining
+ // a proper copy constructor.
+ DnnPlane * _DNN1, * _DNN2;
+
+ /// given a phi value in the 0--2pi range return one
+ /// in the pi--3pi range.
+ inline EtaPhi _remap_phi(const EtaPhi & point) {
+ double phi = point.second;
+ if (phi < pi) { phi += twopi ;}
+ return EtaPhi(point.first, phi);}
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+inline int Dnn4piCylinder::NearestNeighbourIndex(const int & current) const {
+ return (_DNN1->NearestNeighbourDistance(current) <
+ _DNN2->NearestNeighbourDistance(current)) ?
+ _DNN1->NearestNeighbourIndex(current) :
+ _DNN2->NearestNeighbourIndex(current) ;
+}
+
+inline double Dnn4piCylinder::NearestNeighbourDistance(const int & current) const {
+ return (_DNN1->NearestNeighbourDistance(current) <
+ _DNN2->NearestNeighbourDistance(current)) ?
+ _DNN1->NearestNeighbourDistance(current) :
+ _DNN2->NearestNeighbourDistance(current) ;
+}
+
+inline bool Dnn4piCylinder::Valid(const int & index) const {
+ return (_DNN1->Valid(index) && _DNN2->Valid(index));
+}
+
+
+inline Dnn4piCylinder::~Dnn4piCylinder() {
+ delete _DNN1;
+ delete _DNN2;
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_DNN4PICYLINDER_HH__
+#endif // DROP_CGAL
--- /dev/null
+//STARTHEADER
+// $Id: DnnPlane.hh 431 2007-01-20 10:44:55Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+
+#ifndef __FASTJET_DNNPLANE_HH__
+#define __FASTJET_DNNPLANE_HH__
+
+#include "fastjet/internal/Triangulation.hh"
+#include "fastjet/internal/DynamicNearestNeighbours.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+
+/// class derived from DynamicNearestNeighbours that provides an
+/// implementation for the Euclidean plane
+class DnnPlane : public DynamicNearestNeighbours {
+ public:
+ /// empty initaliser
+ DnnPlane() {}
+
+ /// Initialiser from a set of points on an Eta-Phi plane, where both
+ /// eta and phi can have arbitrary ranges
+ DnnPlane(const std::vector<EtaPhi> &, const bool & verbose = false );
+
+
+ /// Returns the index of the nearest neighbour of point labelled
+ /// by ii (assumes ii is valid)
+ int NearestNeighbourIndex(const int & ii) const ;
+
+ /// Returns the distance to the nearest neighbour of point labelled
+ /// by index ii (assumes ii is valid)
+ double NearestNeighbourDistance(const int & ii) const ;
+
+ /// Returns true iff the given index corresponds to a point that
+ /// exists in the DNN structure (meaning that it has been added, and
+ /// not removed in the meantime)
+ bool Valid(const int & index) const;
+
+ void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+ const std::vector<EtaPhi> & points_to_add,
+ std::vector<int> & indices_added,
+ std::vector<int> & indices_of_updated_neighbours);
+
+ /// returns the EtaPhi of point with index i.
+ EtaPhi etaphi(const int i) const;
+ /// returns the eta point with index i.
+ double eta(const int i) const;
+ /// returns the phi point with index i.
+ double phi(const int i) const;
+
+ private:
+
+ /// Structure containing a vertex_handle and cached information on
+ /// the nearest neighbour.
+ struct SuperVertex {
+ Vertex_handle vertex; // NULL indicates inexistence...
+ double NNdistance;
+ int NNindex;
+ // later on for cylinder put a second vertex?
+ };
+
+ std::vector<SuperVertex> _supervertex;
+ //set<Vertex_handle> _vertex_set;
+ bool _verbose;
+
+ static const bool _crash_on_coincidence = true;
+ //static const bool _crash_on_coincidence = false;
+
+ Triangulation _TR; /// CGAL object for dealing with triangulations
+
+ /// calculates and returns the euclidean distance between points p1
+ /// and p2
+ inline double _euclid_distance(const Point& p1, const Point& p2) const {
+ double distx= p1.x()-p2.x();
+ double disty= p1.y()-p2.y();
+ return distx*distx+disty*disty;
+ }
+
+ //----------------------------------------------------------------------
+ /// Determines the index and distance of the nearest neighbour to
+ /// point j and puts the information into the _supervertex entry for j
+ void _SetNearest(const int & j);
+
+ //----------------------------------------------------------------------
+ /// Determines and stores the nearest neighbour of j.
+ ///
+ /// For each voronoi neighbour D of j if the distance between j and D
+ /// is less than D's own nearest neighbour, then update the
+ /// nearest-neighbour info in D; push D's index onto
+ /// indices_of_updated_neighbours
+ ///
+ /// Note that j is NOT pushed onto indices_of_updated_neighbours --
+ /// if you want it there, put it there yourself.
+ void _SetAndUpdateNearest(const int & j,
+ std::vector<int> & indices_of_updated_neighbours);
+
+ /// given a vertex_handle returned by CGAL on insertion of a new
+ /// points, crash if it turns out that it corresponds to a vertex
+ /// that we already knew about (usually because two points coincide)
+ void _CrashIfVertexPresent(const Vertex_handle & vertex,
+ const int & its_index);
+
+};
+
+
+// here follow some inline implementations of the simpler of the
+// functions defined above
+
+inline int DnnPlane::NearestNeighbourIndex(const int & ii) const {
+ return _supervertex[ii].NNindex;}
+
+inline double DnnPlane::NearestNeighbourDistance(const int & ii) const {
+ return _supervertex[ii].NNdistance;}
+
+inline bool DnnPlane::Valid(const int & index) const {
+ if (index >= 0 && index < static_cast<int>(_supervertex.size())) {
+ return (_supervertex[index].vertex != NULL);} else {return false;} }
+
+inline EtaPhi DnnPlane::etaphi(const int i) const {
+ Point * p = & (_supervertex[i].vertex->point());
+ return EtaPhi(p->x(),p->y()); }
+
+inline double DnnPlane::eta(const int i) const {
+ return _supervertex[i].vertex->point().x(); }
+
+inline double DnnPlane::phi(const int i) const {
+ return _supervertex[i].vertex->point().y(); }
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_DNNPLANE_HH__
+
+#endif // DROP_CGAL
--- /dev/null
+//STARTHEADER
+// $Id: DynamicNearestNeighbours.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
+#define __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
+
+#include<vector>
+#include<string>
+#include<iostream>
+#include<sstream>
+#include<cassert>
+#include "fastjet/internal/numconsts.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// Shortcut for dealing with eta-phi coordinates.
+//typedef std::pair<double,double> EtaPhi;
+
+/// use a class instead of a pair so that phi can be sanitized
+/// and put into proper range on initialization.
+class EtaPhi {
+public:
+ double first, second;
+ EtaPhi() {}
+ EtaPhi(double a, double b) {first = a; second = b;}
+ /// put things into the desired range.
+ void sanitize() {
+ if (second < 0) second += twopi;
+ if (second >= twopi) second -= twopi;
+ }
+
+};
+
+/// class corresponding to errors that will be thrown by Dynamic
+/// Nearest Neighbours code
+class DnnError {
+public:
+ // constructors
+ DnnError() {;};
+ DnnError(const std::string & message) {
+ _message = message; std::cerr << message << std::endl;};
+
+ std::string message() const {return _message;};
+
+private:
+ std::string _message;
+};
+
+
+///
+/// Abstract base class for quick location of nearest neighbours in a set of
+/// points, with facilities for adding and removing points from the
+/// set after initialisation. Derived classes will be
+/// named according to the convention DnnSomeName (e.g. DnnPlane).
+///
+/// The main purpose of this abstract base class is to define the
+/// general interface of a whole set of classes that deal with
+/// nearest-neighbour location on different 2-d geometries and with
+/// various underlying data structures and algorithms.
+///
+class DynamicNearestNeighbours {
+
+public:
+ /// Dummy initialiser --- does nothing!
+ //virtual DynamicNearestNeighbours() {};
+
+ /// Initialiser --- sets up the necessary structures to allow efficient
+ /// nearest-neighbour finding on the std::vector<EtaPhi> of input points
+ //virtual DynamicNearestNeighbours(const std::vector<EtaPhi> &,
+ // const bool & verbose = false ) = 0;
+
+ /// Returns the index of the nearest neighbour of point labelled
+ /// by ii (assumes ii is valid)
+ virtual int NearestNeighbourIndex(const int & ii) const = 0;
+
+ /// Returns the distance to the nearest neighbour of point labelled
+ /// by index ii (assumes ii is valid)
+ virtual double NearestNeighbourDistance(const int & ii) const = 0;
+
+ /// Returns true iff the given index corresponds to a point that
+ /// exists in the DNN structure (meaning that it has been added, and
+ /// not removed in the meantime)
+ virtual bool Valid(const int & index) const = 0;
+
+ /// remove the points labelled by the std::vector indices_to_remove, and
+ /// add the points specified by the std::vector points_to_add
+ /// (corresponding indices will be calculated automatically); the
+ /// idea behind this routine is that the points to be added will
+ /// somehow be close to the one or other of the points being removed
+ /// and this can be used by the implementation to provide hints for
+ /// inserting the new points in whatever structure it is using. In a
+ /// kt-algorithm the points being added will be a result of a
+ /// combination of the points to be removed -- hence the proximity
+ /// is (more or less) guaranteed.
+ virtual void RemoveAndAddPoints(const std::vector<int> & indices_to_remove,
+ const std::vector<EtaPhi> & points_to_add,
+ std::vector<int> & indices_added,
+ std::vector<int> & indices_of_updated_neighbours) = 0;
+
+
+ /// Remove the point labelled by index and return the list of
+ /// points whose nearest neighbours have changed in the process
+ inline void RemovePoint (const int & index,
+ std::vector<int> & indices_of_updated_neighbours) {
+ std::vector<int> indices_added;
+ std::vector<EtaPhi> points_to_add;
+ std::vector<int> indices_to_remove(1);
+ indices_to_remove[0] = index;
+ RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
+ indices_of_updated_neighbours
+ );};
+
+
+ /// Removes the two points labelled by index1, index2 and adds in the
+ /// a point with coordinates newpoint; it returns an index for the new
+ /// point (index 3) and a std::vector of indices of neighbours whose
+ /// nearest neighbour has changed (the list includes index3, i.e. the new
+ /// point).
+ inline void RemoveCombinedAddCombination(
+ const int & index1, const int & index2,
+ const EtaPhi & newpoint,
+ int & index3,
+ std::vector<int> & indices_of_updated_neighbours) {
+ std::vector<int> indices_added(1);
+ std::vector<EtaPhi> points_to_add(1);
+ std::vector<int> indices_to_remove(2);
+ indices_to_remove[0] = index1;
+ indices_to_remove[1] = index2;
+ points_to_add[0] = newpoint;
+ RemoveAndAddPoints(indices_to_remove, points_to_add, indices_added,
+ indices_of_updated_neighbours
+ );
+ index3 = indices_added[0];
+ };
+
+ /// destructor -- here it is now implemented
+ virtual ~DynamicNearestNeighbours () {}
+};
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_DYNAMICNEARESTNEIGHBOURS_HH__
--- /dev/null
+//STARTHEADER
+// $Id: LimitedWarning.hh 699 2007-06-04 20:20:42Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_LIMITEDWARNING_HH__
+#define __FASTJET_LIMITEDWARNING_HH__
+
+#include<iostream>
+#include<string>
+
+/// class to provide facilities for giving warnings up to some maximum
+/// number of times
+class LimitedWarning {
+public:
+
+ /// constructor that provides a default maximum number of warnings
+ LimitedWarning() : _max_warn(_max_warn_default), _n_warn_so_far(0) {}
+
+ /// constructor that provides a used-set max number of warnings
+ LimitedWarning(int max_warn) : _max_warn(max_warn), _n_warn_so_far(0) {}
+
+ /// output a warning to ostr
+ void warn(const std::string & warning, std::ostream & ostr = std::cerr) {
+ if (_n_warn_so_far < _max_warn) {
+ ostr << "WARNING: ";
+ ostr << warning;
+ _n_warn_so_far++;
+ if (_n_warn_so_far == _max_warn) ostr << " (LAST SUCH WARNING)";
+ ostr << std::endl;
+ }
+ }
+
+private:
+ int _max_warn, _n_warn_so_far;
+ static const int _max_warn_default = 5;
+
+};
+
+#endif // __FASTJET_LIMITEDWARNING_HH__
--- /dev/null
+//STARTHEADER
+// $Id: MinHeap.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_MINHEAP__HH__
+#define __FASTJET_MINHEAP__HH__
+
+#include<vector>
+#include<cassert>
+#include<memory>
+#include<limits>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+//======================================================================
+/// A class which provides a "heap"-like structure that allows
+/// access to a the minimal value of a dynamically changing set of numbers
+class MinHeap {
+public:
+ /// construct a MinHeap from the vector of values, allowing future
+ /// expansion to a maximum size max_size;
+ MinHeap (const std::vector<double> & values, unsigned int max_size) :
+ _heap(max_size) {_initialise(values);};
+
+ /// constructor in which the the maximum size is the size of the values array
+ MinHeap (const std::vector<double> & values) :
+ _heap(values.size()) {_initialise(values);};
+
+ /// return the location of the minimal value on the heap
+ inline unsigned int minloc() const {
+ return (_heap[0].minloc) - &(_heap[0]);};
+
+ /// return the minimal value on the heap
+ inline double minval() const {return _heap[0].minloc->value;};
+
+ inline double operator[](int i) const {return _heap[i].value;};
+
+ /// remove the value at the specified location (i.e. replace it with
+ /// the largest possible value).
+ void remove(unsigned int loc) {
+ update(loc,std::numeric_limits<double>::max());};
+
+ /// update the value at the specified location
+ void update(unsigned int, double);
+
+private:
+
+ struct ValueLoc{
+ double value;
+ ValueLoc * minloc;
+ };
+
+ std::vector<ValueLoc> _heap;
+
+ void _initialise(const std::vector<double> & values);
+
+
+};
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_MINHEAP__HH__
--- /dev/null
+//STARTHEADER
+// $Id: SearchTree.hh 1203 2008-04-28 16:10:36Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef __FASTJET_SEARCHTREE_HH__
+#define __FASTJET_SEARCHTREE_HH__
+
+#include<vector>
+#include<cassert>
+#include<cstddef>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+
+//======================================================================
+/// This is the class for a search tree designed to be especially efficient
+/// when looking for successors and predecessors (to be used in Chan's
+/// CP algorithm). It has the requirement that the maximum size of the
+/// search tree must be known in advance.
+template<class T> class SearchTree {
+public:
+
+ class Node;
+ class circulator;
+ class const_circulator;
+
+ /// constructor for a search tree from an ordered vector
+ SearchTree(const std::vector<T> & init);
+
+ /// constructor for a search tree from an ordered vector allowing
+ /// for future growth beyond the current size, up to max_size
+ SearchTree(const std::vector<T> & init, unsigned int max_size);
+
+ /// remove the node corresponding to node_index from the search tree
+ void remove(unsigned node_index);
+ void remove(typename SearchTree::Node * node);
+ void remove(typename SearchTree::circulator & circ);
+
+ /// insert the supplied value into the tree and return a pointer to
+ /// the relevant SearchTreeNode.
+ //Node * insert(const T & value);
+ circulator insert(const T & value);
+
+ const Node & operator[](int i) const {return _nodes[i];};
+
+ /// return the number of elements currently in the search tree
+ unsigned int size() const {return _nodes.size() - _available_nodes.size();}
+
+ /// check that the structure we've obtained makes sense...
+ void verify_structure();
+ void verify_structure_linear() const;
+ void verify_structure_recursive(const Node * , const Node * , const Node * ) const;
+
+ /// print out all elements...
+ void print_elements();
+
+ // tracking the depth may have some speed overhead -- so leave it
+ // out for the time being...
+#ifdef TRACK_DEPTH
+ /// the max depth the tree has ever reached
+ inline unsigned int max_depth() const {return _max_depth;};
+#else
+ inline unsigned int max_depth() const {return 0;};
+#endif
+
+ int loc(const Node * node) const ;
+
+ /// return predecessor by walking through the tree
+ Node * _find_predecessor(const Node *);
+ /// return successor by walking through the tree
+ Node * _find_successor(const Node *);
+
+ const Node & operator[](unsigned int i) const {return _nodes[i];};
+
+ /// return a circulator to some place in the tree (with a circulator
+ /// you don't care where...)
+ const_circulator somewhere() const;
+ circulator somewhere();
+
+private:
+
+ void _initialize(const std::vector<T> & init);
+
+ std::vector<Node> _nodes;
+ std::vector<Node *> _available_nodes;
+ Node * _top_node;
+ unsigned int _n_removes;
+
+
+ /// recursive routine for doing the initial connections assuming things
+ /// are ordered. Assumes this_one's parent is labelled, and was
+ /// generated at a scale "scale" -- connections will be carried out
+ /// including left edge and excluding right edge
+ void _do_initial_connections(unsigned int this_one, unsigned int scale,
+ unsigned int left_edge, unsigned int right_edge,
+ unsigned int depth);
+
+
+#ifdef TRACK_DEPTH
+ unsigned int _max_depth;
+#endif
+
+};
+
+
+//======================================================================
+template<class T> class SearchTree<T>::Node{
+public:
+ Node() {}; /// default constructor
+
+
+ /// returns tree if all the tree-related links are set to null for this node
+ bool treelinks_null() const {
+ return ((parent==0) && (left==0) && (right==0));};
+
+ /// set all the tree-related links are set to null for this node
+ inline void nullify_treelinks() {
+ parent = NULL;
+ left = NULL;
+ right = NULL;
+ };
+
+ /// if my parent exists, determine whether I am it's left or right
+ /// node and set the relevant link equal to XX.
+ void reset_parents_link_to_me(Node * XX);
+
+ T value;
+ Node * left;
+ Node * right;
+ Node * parent;
+ Node * successor;
+ Node * predecessor;
+};
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::Node::reset_parents_link_to_me(typename SearchTree<T>::Node * XX) {
+ if (parent == NULL) {return;}
+ if (parent->right == this) {parent->right = XX;}
+ else {parent->left = XX;}
+}
+
+
+
+//======================================================================
+template<class T> class SearchTree<T>::circulator{
+public:
+
+ // so that it can access out _node object;
+ friend class SearchTree<T>::const_circulator;
+ friend class SearchTree<T>;
+
+ circulator() : _node(NULL) {}
+
+ circulator(Node * node) : _node(node) {}
+
+ const T * operator->() const {return &(_node->value);}
+ T * operator->() {return &(_node->value);}
+ const T & operator*() const {return _node->value;}
+ T & operator*() {return _node->value;}
+
+ /// prefix increment (structure copied from stl_bvector.h)
+ circulator & operator++() {
+ _node = _node->successor;
+ return *this;}
+
+ /// postfix increment ["int" argument tells compiler it's postfix]
+ /// (structure copied from stl_bvector.h)
+ circulator operator++(int) {
+ circulator tmp = *this;
+ _node = _node->successor;
+ return tmp;}
+
+ /// prefix decrement (structure copied from stl_bvector.h)
+ circulator & operator--() {
+ _node = _node->predecessor;
+ return *this;}
+
+ /// postfix decrement ["int" argument tells compiler it's postfix]
+ /// (structure copied from stl_bvector.h)
+ circulator operator--(int) {
+ circulator tmp = *this;
+ _node = _node->predecessor;
+ return tmp;}
+
+ /// return a circulator referring to the next node
+ circulator next() const {
+ return circulator(_node->successor);}
+
+ /// return a circulator referring to the previous node
+ circulator previous() const {
+ return circulator(_node->predecessor);}
+
+ bool operator!=(const circulator & other) const {return other._node != _node;}
+ bool operator==(const circulator & other) const {return other._node == _node;}
+
+private:
+ Node * _node;
+};
+
+
+//======================================================================
+template<class T> class SearchTree<T>::const_circulator{
+public:
+
+ const_circulator() : _node(NULL) {}
+
+ const_circulator(const Node * node) : _node(node) {}
+ const_circulator(const circulator & circ) :_node(circ._node) {}
+
+ const T * operator->() {return &(_node->value);}
+ const T & operator*() const {return _node->value;}
+
+ /// prefix increment (structure copied from stl_bvector.h)
+ const_circulator & operator++() {
+ _node = _node->successor;
+ return *this;}
+
+ /// postfix increment ["int" argument tells compiler it's postfix]
+ /// (structure copied from stl_bvector.h)
+ const_circulator operator++(int) {
+ const_circulator tmp = *this;
+ _node = _node->successor;
+ return tmp;}
+
+
+ /// prefix decrement (structure copied from stl_bvector.h)
+ const_circulator & operator--() {
+ _node = _node->predecessor;
+ return *this;}
+
+ /// postfix decrement ["int" argument tells compiler it's postfix]
+ /// (structure copied from stl_bvector.h)
+ const_circulator operator--(int) {
+ const_circulator tmp = *this;
+ _node = _node->predecessor;
+ return tmp;}
+
+ /// return a circulator referring to the next node
+ const_circulator next() const {
+ return const_circulator(_node->successor);}
+
+ /// return a circulator referring to the previous node
+ const_circulator previous() const {
+ return const_circulator(_node->predecessor);}
+
+
+
+ bool operator!=(const const_circulator & other) const {return other._node != _node;}
+ bool operator==(const const_circulator & other) const {return other._node == _node;}
+
+private:
+ const Node * _node;
+};
+
+
+
+
+//----------------------------------------------------------------------
+/// initialise from a sorted initial array allowing for a larger
+/// maximum size of the array...
+template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init,
+ unsigned int max_size) :
+ _nodes(max_size) {
+
+ _available_nodes.reserve(max_size);
+ _available_nodes.resize(max_size - init.size());
+ for (unsigned int i = init.size(); i < max_size; i++) {
+ _available_nodes[i-init.size()] = &(_nodes[i]);
+ }
+
+ _initialize(init);
+}
+
+//----------------------------------------------------------------------
+/// initialise from a sorted initial array
+template<class T> SearchTree<T>::SearchTree(const std::vector<T> & init) :
+ _nodes(init.size()), _available_nodes(0) {
+
+ // reserve space for the list of available nodes
+ _available_nodes.reserve(init.size());
+ _initialize(init);
+}
+
+//----------------------------------------------------------------------
+/// do the actual hard work of initialization
+template<class T> void SearchTree<T>::_initialize(const std::vector<T> & init) {
+
+ _n_removes = 0;
+ unsigned n = init.size();
+ assert(n>=1);
+
+ // reserve space for the list of available nodes
+ //_available_nodes.reserve();
+
+#ifdef TRACK_DEPTH
+ _max_depth = 0;
+#endif
+
+
+ // validate the input
+ for (unsigned int i = 1; i<n; i++) {
+ assert(!(init[i] < init[i-1]));
+ }
+
+ // now initialise the vector; link neighbours in the sequence
+ for(unsigned int i = 0; i < n; i++) {
+ _nodes[i].value = init[i];
+ _nodes[i].predecessor = (& (_nodes[i])) - 1;
+ _nodes[i].successor = (& (_nodes[i])) + 1;
+ _nodes[i].nullify_treelinks();
+ }
+ // make a loop structure so that we can circulate...
+ _nodes[0].predecessor = (& (_nodes[n-1]));
+ _nodes[n-1].successor = (& (_nodes[0]));
+
+ // now label the rest of the nodes
+ unsigned int scale = (n+1)/2;
+ unsigned int top = std::min(n-1,scale);
+ _nodes[top].parent = NULL;
+ _top_node = &(_nodes[top]);
+ _do_initial_connections(top, scale, 0, n, 0);
+
+ // make sure things are sensible...
+ //verify_structure();
+}
+
+
+
+//----------------------------------------------------------------------
+template<class T> inline int SearchTree<T>::loc(const Node * node) const {return node == NULL?
+ -999 : node - &(_nodes[0]);}
+
+
+//----------------------------------------------------------------------
+/// Recursive creation of connections, assuming the _nodes vector is
+/// completely filled and ordered
+template<class T> void SearchTree<T>::_do_initial_connections(
+ unsigned int this_one,
+ unsigned int scale,
+ unsigned int left_edge,
+ unsigned int right_edge,
+ unsigned int depth
+ ) {
+
+#ifdef TRACK_DEPTH
+ // keep track of tree depth for checking things stay reasonable...
+ _max_depth = max(depth, _max_depth);
+#endif
+
+ //std::cout << this_one << " "<< scale<< std::endl;
+ unsigned int ref_new_scale = (scale+1)/2;
+
+ // work through children to our left
+ unsigned new_scale = ref_new_scale;
+ bool did_child = false;
+ while(true) {
+ int left = this_one - new_scale; // be careful here to use signed int...
+ // if there is something unitialised to our left, link to it
+ if (left >= static_cast<int>(left_edge)
+ && _nodes[left].treelinks_null() ) {
+ _nodes[left].parent = &(_nodes[this_one]);
+ _nodes[this_one].left = &(_nodes[left]);
+ // create connections between left_edge and this_one
+ _do_initial_connections(left, new_scale, left_edge, this_one, depth+1);
+ did_child = true;
+ break;
+ }
+ // reduce the scale so as to try again
+ unsigned int old_new_scale = new_scale;
+ new_scale = (old_new_scale + 1)/2;
+ // unless we've reached end of tree
+ if (new_scale == old_new_scale) break;
+ }
+ if (!did_child) {_nodes[this_one].left = NULL;}
+
+
+ // work through children to our right
+ new_scale = ref_new_scale;
+ did_child = false;
+ while(true) {
+ unsigned int right = this_one + new_scale;
+ if (right < right_edge && _nodes[right].treelinks_null()) {
+ _nodes[right].parent = &(_nodes[this_one]);
+ _nodes[this_one].right = &(_nodes[right]);
+ // create connections between this_one+1 and right_edge
+ _do_initial_connections(right, new_scale, this_one+1,right_edge,depth+1);
+ did_child = true;
+ break;
+ }
+ // reduce the scale so as to try again
+ unsigned int old_new_scale = new_scale;
+ new_scale = (old_new_scale + 1)/2;
+ // unless we've reached end of tree
+ if (new_scale == old_new_scale) break;
+ }
+ if (!did_child) {_nodes[this_one].right = NULL;}
+
+}
+
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::remove(unsigned int node_index) {
+ remove(&(_nodes[node_index]));
+}
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::remove(circulator & circ) {
+ remove(circ._node);
+}
+
+//----------------------------------------------------------------------
+// Useful reference for this:
+// http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
+template<class T> void SearchTree<T>::remove(typename SearchTree<T>::Node * node) {
+
+ // we don't remove things from the tree if we've reached the last
+ // elements... (is this wise?)
+ assert(size() > 1); // switch this to throw...?
+ assert(!node->treelinks_null());
+
+ // deal with relinking predecessor and successor
+ node->predecessor->successor = node->successor;
+ node->successor->predecessor = node->predecessor;
+
+ if (node->left == NULL && node->right == NULL) {
+ // node has no children, so remove it by nullifying the pointer
+ // from the parent
+ node->reset_parents_link_to_me(NULL);
+
+ } else if (node->left != NULL && node->right == NULL){
+ // make parent point to my child
+ node->reset_parents_link_to_me(node->left);
+ // and child to parent
+ node->left->parent = node->parent;
+ // sort out the top node...
+ if (_top_node == node) {_top_node = node->left;}
+
+ } else if (node->left == NULL && node->right != NULL){
+ // make parent point to my child
+ node->reset_parents_link_to_me(node->right);
+ // and child to parent
+ node->right->parent = node->parent;
+ // sort out the top node...
+ if (_top_node == node) {_top_node = node->right;}
+
+ } else {
+ // we have two children; we will put a replacement in our place
+ Node * replacement;
+ //SearchTree<T>::Node * replacements_child;
+ // chose predecessor or successor (one, then other, then first, etc...)
+ bool use_predecessor = (_n_removes % 2 == 1);
+ if (use_predecessor) {
+ // Option 1: put predecessor in our place, and have its parent
+ // point to its left child (as a predecessor it has no right child)
+ replacement = node->predecessor;
+ assert(replacement->right == NULL); // guaranteed if it's our predecessor
+ // we have to be careful of replacing certain links when the
+ // replacement is this node's child
+ if (replacement != node->left) {
+ if (replacement->left != NULL) {
+ replacement->left->parent = replacement->parent;}
+ replacement->reset_parents_link_to_me(replacement->left);
+ replacement->left = node->left;
+ }
+ replacement->parent = node->parent;
+ replacement->right = node->right;
+ } else {
+ // Option 2: put successor in our place, and have its parent
+ // point to its right child (as a successor it has no left child)
+ replacement = node->successor;
+ assert(replacement->left == NULL); // guaranteed if it's our successor
+ if (replacement != node->right) {
+ if (replacement->right != NULL) {
+ replacement->right->parent = replacement->parent;}
+ replacement->reset_parents_link_to_me(replacement->right);
+ replacement->right = node->right;
+ }
+ replacement->parent = node->parent;
+ replacement->left = node->left;
+ }
+ node->reset_parents_link_to_me(replacement);
+
+ // make sure node's original children now point to the replacement
+ if (node->left != replacement) {node->left->parent = replacement;}
+ if (node->right != replacement) {node->right->parent = replacement;}
+
+ // sort out the top node...
+ if (_top_node == node) {_top_node = replacement;}
+ }
+
+ // make sure we leave something nice and clean...
+ node->nullify_treelinks();
+ node->predecessor = NULL;
+ node->successor = NULL;
+
+ // for bookkeeping (and choosing whether to use pred. or succ.)
+ _n_removes++;
+ // for when we next need access to a free node...
+ _available_nodes.push_back(node);
+}
+
+
+//----------------------------------------------------------------------
+//template<class T> typename SearchTree<T>::Node * SearchTree<T>::insert(const T & value) {
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::circulator SearchTree<T>::insert(const T & value) {
+ // make sure we don't exceed allowed number of nodes...
+ assert(_available_nodes.size() > 0);
+
+ Node * node = _available_nodes.back();
+ _available_nodes.pop_back();
+ node->value = value;
+
+ Node * location = _top_node;
+ Node * old_location = NULL;
+ bool on_left = true; // (init not needed -- but soothes g++4)
+ // work through tree until we reach its end
+#ifdef TRACK_DEPTH
+ unsigned int depth = 0;
+#endif
+ while(location != NULL) {
+#ifdef TRACK_DEPTH
+ depth++;
+#endif
+ old_location = location;
+ on_left = value < location->value;
+ if (on_left) {location = location->left;}
+ else {location = location->right;}
+ }
+#ifdef TRACK_DEPTH
+ _max_depth = max(depth, _max_depth);
+#endif
+ // now create tree links
+ node->parent = old_location;
+ if (on_left) {node->parent->left = node;}
+ else {node->parent->right = node;}
+ node->left = NULL;
+ node->right = NULL;
+ // and create predecessor / successor links
+ node->predecessor = _find_predecessor(node);
+ if (node->predecessor != NULL) {
+ // it exists, so make use of its info (will include a cyclic case,
+ // when successor is round the bend)
+ node->successor = node->predecessor->successor;
+ node->predecessor->successor = node;
+ node->successor->predecessor = node;
+ } else {
+ // deal with case when we are left-most edge of tree (then successor
+ // will exist...)
+ node->successor = _find_successor(node);
+ assert(node->successor != NULL); // can only happen if we're sole element
+ // (but not allowed, since tree size>=1)
+ node->predecessor = node->successor->predecessor;
+ node->successor->predecessor = node;
+ node->predecessor->successor = node;
+ }
+
+ return circulator(node);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure() {
+
+ // do a check running through all elements
+ verify_structure_linear();
+
+ // do a recursive check down tree from top
+
+ // first establish the extremities
+ const Node * left_limit = _top_node;
+ while (left_limit->left != NULL) {left_limit = left_limit->left;}
+ const Node * right_limit = _top_node;
+ while (right_limit->right != NULL) {right_limit = right_limit->right;}
+
+ // then actually do recursion
+ verify_structure_recursive(_top_node, left_limit, right_limit);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure_recursive(
+ const typename SearchTree<T>::Node * element,
+ const typename SearchTree<T>::Node * left_limit,
+ const typename SearchTree<T>::Node * right_limit) const {
+
+ assert(!(element->value < left_limit->value));
+ assert(!(right_limit->value < element->value));
+
+ const Node * left = element->left;
+ if (left != NULL) {
+ assert(!(element->value < left->value));
+ if (left != left_limit) {
+ // recurse down the tree with this element as the right-hand limit
+ verify_structure_recursive(left, left_limit, element);}
+ }
+
+ const Node * right = element->right;
+ if (right != NULL) {
+ assert(!(right->value < element->value));
+ if (right != right_limit) {
+ // recurse down the tree with this element as the left-hand limit
+ verify_structure_recursive(right, element, right_limit);}
+ }
+}
+
+//----------------------------------------------------------------------
+template<class T> void SearchTree<T>::verify_structure_linear() const {
+
+ //print_elements();
+
+ unsigned n_top = 0;
+ unsigned n_null = 0;
+ for(unsigned i = 0; i < _nodes.size(); i++) {
+ const typename SearchTree<T>::Node * node = &(_nodes[i]);
+ // make sure node is defined
+ if (node->treelinks_null()) {n_null++; continue;}
+
+ // make sure of the number of "top" nodes
+ if (node->parent == NULL) {
+ n_top++;
+ //assert(node->left != NULL);
+ //assert(node->right != NULL);
+ } else {
+ // make sure that I am a child of my parent...
+ //assert((node->parent->left == node) || (node->parent->right == node));
+ assert((node->parent->left == node) ^ (node->parent->right == node));
+ }
+
+ // when there is a left child make sure it's value is ordered
+ // (note use of !(b<a), to allow for a<=b while using just the <
+ // operator)
+ if (node->left != NULL) {
+ assert(!(node->value < node->left->value ));}
+
+ // when there is a right child make sure it's value is ordered
+ if (node->right != NULL) {
+ assert(!(node->right->value < node->value ));}
+
+ }
+ assert(n_top == 1 || (n_top == 0 && size() <= 1) );
+ assert(n_null == _available_nodes.size() ||
+ (n_null == _available_nodes.size() + 1 && size() == 1));
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_predecessor(const typename SearchTree<T>::Node * node) {
+
+ typename SearchTree<T>::Node * newnode;
+ if (node->left != NULL) {
+ // go down left, and then down right as far as possible.
+ newnode = node->left;
+ while(newnode->right != NULL) {newnode = newnode->right;}
+ return newnode;
+ } else {
+ const typename SearchTree<T>::Node * lastnode = node;
+ newnode = node->parent;
+ // go up the tree as long as we're going right (when we go left then
+ // we've found something smaller, so stop)
+ while(newnode != NULL) {
+ if (newnode->right == lastnode) {return newnode;}
+ lastnode = newnode;
+ newnode = newnode->parent;
+ }
+ return newnode;
+ }
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::Node * SearchTree<T>::_find_successor(const typename SearchTree<T>::Node * node) {
+
+ typename SearchTree<T>::Node * newnode;
+ if (node->right != NULL) {
+ // go down right, and then down left as far as possible.
+ newnode = node->right;
+ while(newnode->left != NULL) {newnode = newnode->left;}
+ return newnode;
+ } else {
+ const typename SearchTree<T>::Node * lastnode = node;
+ newnode = node->parent;
+ // go up the tree as long as we're going left (when we go right then
+ // we've found something larger, so stop)
+ while(newnode != NULL) {
+ if (newnode->left == lastnode) {return newnode;}
+ lastnode = newnode;
+ newnode = newnode->parent;
+ }
+ return newnode;
+ }
+}
+
+
+//----------------------------------------------------------------------
+// print out all the elements for visual checking...
+template<class T> void SearchTree<T>::print_elements() {
+ typename SearchTree<T>::Node * base_node = &(_nodes[0]);
+ typename SearchTree<T>::Node * node = base_node;
+
+ int n = _nodes.size();
+ for(; node - base_node < n ; node++) {
+ printf("%4d parent:%4d left:%4d right:%4d pred:%4d succ:%4d value:%10.6f\n",loc(node), loc(node->parent), loc(node->left), loc(node->right), loc(node->predecessor),loc(node->successor),node->value);
+ }
+}
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::circulator SearchTree<T>::somewhere() {
+ return circulator(_top_node);
+}
+
+
+//----------------------------------------------------------------------
+template<class T> typename SearchTree<T>::const_circulator SearchTree<T>::somewhere() const {
+ return const_circulator(_top_node);
+}
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_SEARCHTREE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: Triangulation.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+#ifndef DROP_CGAL // in case we do not have the code for CGAL
+#ifndef __FASTJET_TRIANGULATION__
+#define __FASTJET_TRIANGULATION__
+
+// file: examples/Triangulation_2/Voronoi.C
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_2.h>
+#include <CGAL/Triangulation_hierarchy_2.h>
+#include <CGAL/Triangulation_vertex_base_with_info_2.h>
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/// the basic geometrical kernel that lies at the base of all CGAL
+/// operations
+#ifdef CGAL_SIMPLE_KERNEL
+struct K : CGAL::Simple_cartesian<double> {};
+#else
+struct K : CGAL::Exact_predicates_inexact_constructions_kernel {};
+#endif // CGAL_SIMPLE_KERNEL
+
+// our extras to help us navigate, find distance, etc.
+const int INFINITE_VERTEX=-1;
+const int NEW_VERTEX=-2;
+const double HUGE_DOUBLE=1e300;
+
+/// A class to provide an "int" with an initial value.
+class InitialisedInt {
+ private:
+ int _val;
+ public:
+ inline InitialisedInt () {_val=NEW_VERTEX;};
+ inline InitialisedInt& operator= (int value) {_val = value; return *this;};
+ inline int val() const {return _val;};
+};
+
+
+// We can have triangulations with and without hierarchies -- those with
+// are able to guarantee N ln N time for the construction of a large
+// triangulation, whereas those without go as N^{3/2} for points
+// sufficiently uniformly distributed in a plane.
+//
+//#define NOHIERARCHY
+#ifdef NOHIERARCHY
+typedef CGAL::Triangulation_vertex_base_with_info_2<InitialisedInt,K> Vb;
+typedef CGAL::Triangulation_face_base_2<K> Fb;
+typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds;
+typedef CGAL::Delaunay_triangulation_2<K,Tds> Triangulation;
+#else
+typedef CGAL::Triangulation_vertex_base_with_info_2<InitialisedInt,K> Vbb;
+typedef CGAL::Triangulation_hierarchy_vertex_base_2<Vbb> Vb;
+typedef CGAL::Triangulation_face_base_2<K> Fb;
+typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds;
+typedef CGAL::Delaunay_triangulation_2<K,Tds> Dt;
+typedef CGAL::Triangulation_hierarchy_2<Dt> Triangulation;
+#endif
+
+typedef Triangulation::Vertex_handle Vertex_handle;
+typedef Triangulation::Point Point; /// CGAL Point structure
+typedef Triangulation::Vertex_circulator Vertex_circulator;
+typedef Triangulation::Face_circulator Face_circulator;
+typedef Triangulation::Face_handle Face_handle;
+
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_TRIANGULATION__
+#endif // DROP_CGAL
--- /dev/null
+#ifndef __FASTJET__VORONOI_H__
+#define __FASTJET__VORONOI_H__
+
+//STARTHEADER
+// $Id: Voronoi.hh 1161 2008-04-01 20:29:38Z soyez $
+//
+// Copyright (c) 1994 by AT&T Bell Laboratories (see below)
+//
+//
+//----------------------------------------------------------------------
+// This file is included as part of FastJet but was mostly written by
+// S. Fortune in C, put into C++ with memory management by S
+// O'Sullivan, and with further interface and memeory management
+// modifications by Gregory Soyez.
+//
+// Permission to use, copy, modify, and distribute this software for
+// any purpose without fee is hereby granted, provided that this
+// entire notice is included in all copies of any software which is or
+// includes a copy or modification of this software and in all copies
+// of the supporting documentation for such software. THIS SOFTWARE IS
+// BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY.
+// IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY REPRESENTATION
+// OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
+// SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+//
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+/*
+* The author of this software is Steven Fortune.
+* Copyright (c) 1994 by AT&T Bell Laboratories.
+* Permission to use, copy, modify, and distribute this software for any
+* purpose without fee is hereby granted, provided that this entire notice
+* is included in all copies of any software which is or includes a copy
+* or modification of this software and in all copies of the supporting
+* documentation for such software.
+* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+*/
+
+/*
+* This code was originally written by Stephan Fortune in C code. I,
+* Shane O'Sullivan, have since modified it, encapsulating it in a C++
+* class and, fixing memory leaks and adding accessors to the Voronoi
+* Edges. Permission to use, copy, modify, and distribute this
+* software for any purpose without fee is hereby granted, provided
+* that this entire notice is included in all copies of any software
+* which is or includes a copy or modification of this software and in
+* all copies of the supporting documentation for such software. THIS
+* SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+* PURPOSE.
+*/
+
+#include "fastjet/ClusterSequenceWithArea.hh"
+#include <vector>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DELETED -2
+#define le 0
+#define re 1
+
+//using namespace std;
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+/**
+ * \class Point
+ * class to handle a 2d point
+ */
+class Point{
+public:
+ /// defailt ctor
+ Point() : x(0.0), y(0.0) {}
+
+ /// ctor with initialisation
+ Point(double _x, double _y) : x(_x), y(_y) {}
+
+ /// addition
+ inline Point operator + (const Point &p) const{
+ return Point(x+p.x, y+p.y);
+ }
+
+ /// subtraction
+ inline Point operator - (const Point &p) const{
+ return Point(x-p.x, y-p.y);
+ }
+
+ /// scalar multiplication
+ inline Point operator * (const double t) const{
+ return Point(x*t, y*t);
+ }
+
+ /// vector coordinates
+ double x,y;
+};
+
+
+/// norm of a vector
+inline double norm(const Point p){
+ return p.x*p.x+p.y*p.y;
+}
+
+
+/// 2D vector product
+inline double vector_product(const Point &p1, const Point &p2){
+ return p1.x*p2.y-p1.y*p2.x;
+}
+
+
+/// scalar product
+inline double scalar_product(const Point &p1, const Point &p2){
+ return p1.x*p2.x+p1.y*p2.y;
+}
+
+
+/**
+ * \class GraphEdge
+ * handle an edge of the Voronoi Diagram.
+ */
+class GraphEdge{
+public:
+ /// coordinates of the extreme points
+ double x1,y1,x2,y2;
+
+ /// indices of the parent sites that define the edge
+ int point1, point2;
+
+ /// pointer to the next edge
+ GraphEdge* next;
+};
+
+
+/**
+ * \class Site
+ * structure used both for particle sites and for vertices.
+ */
+class Site{
+ public:
+ Point coord;
+ int sitenbr;
+ int refcnt;
+};
+
+
+
+class Freenode{
+public:
+ Freenode *nextfree;
+};
+
+
+class FreeNodeArrayList{
+public:
+ Freenode* memory;
+ FreeNodeArrayList* next;
+};
+
+
+class Freelist{
+public:
+ Freenode *head;
+ int nodesize;
+};
+
+class Edge{
+public:
+ double a,b,c;
+ Site *ep[2];
+ Site *reg[2];
+ int edgenbr;
+};
+
+
+class Halfedge{
+public:
+ Halfedge *ELleft, *ELright;
+ Edge *ELedge;
+ int ELrefcnt;
+ char ELpm;
+ Site *vertex;
+ volatile double ystar;
+ Halfedge *PQnext;
+};
+
+
+class VoronoiDiagramGenerator{
+public:
+ VoronoiDiagramGenerator();
+ ~VoronoiDiagramGenerator();
+
+ bool generateVoronoi(std::vector<Point> *_parent_sites,
+ double minX, double maxX, double minY, double maxY,
+ double minDist=0);
+
+ inline void resetIterator(){
+ iteratorEdges = allEdges;
+ }
+
+ bool getNext(GraphEdge **e){
+ if(iteratorEdges == 0)
+ return false;
+
+ *e = iteratorEdges;
+ iteratorEdges = iteratorEdges->next;
+ return true;
+ }
+
+ std::vector<Point> *parent_sites;
+ int n_parent_sites;
+
+private:
+ void cleanup();
+ void cleanupEdges();
+ char *getfree(Freelist *fl);
+ Halfedge *PQfind();
+ int PQempty();
+
+ Halfedge **ELhash;
+ Halfedge *HEcreate(), *ELleft(), *ELright(), *ELleftbnd();
+ Halfedge *HEcreate(Edge *e,int pm);
+
+ Point PQ_min();
+ Halfedge *PQextractmin();
+ void freeinit(Freelist *fl,int size);
+ void makefree(Freenode *curr,Freelist *fl);
+ void geominit();
+ void plotinit();
+ bool voronoi(int triangulate);
+ void ref(Site *v);
+ void deref(Site *v);
+ void endpoint(Edge *e,int lr,Site * s);
+
+ void ELdelete(Halfedge *he);
+ Halfedge *ELleftbnd(Point *p);
+ Halfedge *ELright(Halfedge *he);
+ void makevertex(Site *v);
+ void out_triple(Site *s1, Site *s2,Site * s3);
+
+ void PQinsert(Halfedge *he,Site * v, double offset);
+ void PQdelete(Halfedge *he);
+ bool ELinitialize();
+ void ELinsert(Halfedge *lb, Halfedge *newHe);
+ Halfedge * ELgethash(int b);
+ Halfedge *ELleft(Halfedge *he);
+ Site *leftreg(Halfedge *he);
+ void out_site(Site *s);
+ bool PQinitialize();
+ int PQbucket(Halfedge *he);
+ void clip_line(Edge *e);
+ char *myalloc(unsigned n);
+ int right_of(Halfedge *el,Point *p);
+
+ Site *rightreg(Halfedge *he);
+ Edge *bisect(Site *s1, Site *s2);
+ double dist(Site *s,Site *t);
+ Site *intersect(Halfedge *el1, Halfedge *el2, Point *p=0);
+
+ void out_bisector(Edge *e);
+ void out_ep(Edge *e);
+ void out_vertex(Site *v);
+ Site *nextone();
+
+ void pushGraphEdge(double x1, double y1, double x2, double y2,
+ Site *s1, Site *s2);
+
+ void openpl();
+ void circle(double x, double y, double radius);
+ void range(double minX, double minY, double maxX, double maxY);
+
+ Freelist hfl;
+ Halfedge *ELleftend, *ELrightend;
+ int ELhashsize;
+
+ int triangulate, sorted, plot, debug;
+ double xmin, xmax, ymin, ymax, deltax, deltay;
+
+ Site *sites;
+ int nsites;
+ int siteidx;
+ int sqrt_nsites;
+ int nvertices;
+ Freelist sfl;
+ Site *bottomsite;
+
+ int nedges;
+ Freelist efl;
+ int PQhashsize;
+ Halfedge *PQhash;
+ int PQcount;
+ int PQmin;
+
+ int ntry, totalsearch;
+ double pxmin, pxmax, pymin, pymax, cradius;
+ int total_alloc;
+
+ double borderMinX, borderMaxX, borderMinY, borderMaxY;
+
+ FreeNodeArrayList* allMemoryList;
+ FreeNodeArrayList* currentMemoryBlock;
+
+ GraphEdge* allEdges;
+ GraphEdge* iteratorEdges;
+
+ double minDistanceBetweenSites;
+};
+
+int scomp(const void *p1,const void *p2);
+
+
+} // fastjet namespace
+
+#endif
--- /dev/null
+
+//STARTHEADER
+// $Id: base.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_FASTJET_BASE_HH__
+#define __FASTJET_FASTJET_BASE_HH__
+
+// define this for easier readability (and obfuscation?) in
+// a range of places
+// #define FASTJET_BEGIN_NAMESPACE namespace fastjet {
+// #define FASTJET_END_NAMESPACE }
+
+#endif // __FASTJET_FASTJET_BASE_HH__
--- /dev/null
+//STARTHEADER
+// $Id: numconsts.hh 293 2006-08-17 19:38:38Z salam $
+//
+// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+
+
+#ifndef __FASTJET_NUMCONSTS__
+#define __FASTJET_NUMCONSTS__
+
+#include "fastjet/internal/base.hh"
+
+namespace fastjet { // defined in fastjet/internal/base.hh
+
+// some common useful constants!
+
+const double pi = 3.141592653589793238462643383279502884197;
+const double twopi = 6.283185307179586476925286766559005768394;
+const double pisq = 9.869604401089358618834490999876151135314;
+const double zeta2 = 1.644934066848226436472415166646025189219;
+const double zeta3 = 1.202056903159594285399738161511449990765;
+const double eulergamma = 0.577215664901532860606512090082402431042;
+const double ln2 = 0.693147180559945309417232121458176568076;
+
+
+} // fastjet namespace
+
+#endif // __FASTJET_NUMCONSTS__
--- /dev/null
+//STARTHEADER
+// $Id: version.hh 939 2007-11-08 12:18:08Z salam $
+//
+// Copyright (c) 2005-2007, Matteo Cacciari and Gavin Salam
+//
+//----------------------------------------------------------------------
+// This file is part of FastJet.
+//
+// FastJet is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// The algorithms that underlie FastJet have required considerable
+// development and are described in hep-ph/0512210. If you use
+// FastJet as part of work towards a scientific publication, please
+// include a citation to the FastJet paper.
+//
+// FastJet is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FastJet; if not, write to the Free Software
+// Foundation, Inc.:
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------
+//ENDHEADER
+
+#ifndef __FASTJET_VERSION_HH__
+#define __FASTJET_VERSION_HH__
+
+#include<string>
+#include "fastjet/config.h"
+
+namespace fastjet {
+
+const char* fastjet_version = PACKAGE_VERSION;
+
+} // fastjet namespace
+
+#endif // __FASTJET_VERSION_HH__
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: area.h //
+// Description: header file for the computation of jet area //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 149 $//
+// $Date:: 2007-03-15 00:13:58 +0100 (Thu, 15 Mar 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_AREA_H__
+#define __SISCONE_AREA_H__
+
+#include "momentum.h"
+#include "siscone.h"
+
+namespace siscone{
+
+/**
+ * \class Cjet_area
+ * real Jet information, including its area(s)
+ *
+ * This class contains information for one single jet.
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents.
+ * Compared to the Cjet class, it also includes the
+ * passive and active areas of the jet computed using
+ * the Carea class.
+ */
+class Cjet_area : public Cjet{
+ public:
+ /// default ctor
+ Cjet_area();
+
+ /// jet-initialised ctor
+ Cjet_area(Cjet &j);
+
+ /// default dtor
+ ~Cjet_area();
+
+ // area information
+ double passive_area; ///< passive area
+ double active_area; ///< active area
+};
+
+/**
+ * \class Carea
+ * class for the computation of jet areas.
+ *
+ * This is the class user should use whenever you want to compute
+ * the jet area (passive and active). .
+ * It uses the SISCone algorithm to perform the jet analysis.
+ */
+class Carea : public Csiscone{
+ public:
+ /// default ctor
+ Carea();
+
+ /// default dtor
+ ~Carea();
+
+ /**
+ * compute the jet areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithn.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft
+ * particles/jets and thus is used internally.
+ * \param _particles list of particles
+ * \param _radius cone radius
+ * \param _f shared energy threshold for splitting&merging
+ * \param _n_pass_max maximum number of passes (0=full search, the default)
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation.
+ * SM_Et is IR safe but not boost invariant and not implemented(!)
+ * SM_mt is IR safe for hadronic events, but not for decays of two
+ * back-to-back particles of identical mass
+ * SM_pttilde
+ * is always IR safe, and also boost invariant (default)
+ * \param _hard_only when this is set on, only hard jets are computed
+ * and not the purely ghosted jets (default: false)
+ * \return the number of jets (including pure-ghost ones if they are included)
+ */
+ int compute_areas(std::vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde,
+ bool _hard_only=false);
+
+ /**
+ * compute the jet active areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithn.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft
+ * particles/jets and thus is used internally.
+ * See compute_areas for paramters definition.
+ * \return the number of jets (including pure-ghost ones if they are included)
+ */
+ int compute_active_areas(std::vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde,
+ bool _hard_only=false);
+
+ /**
+ * compute the jet passive areas from a given particle set.
+ * The parameters of this method are the ones which control the jet clustering alghorithn.
+ * Note that the pt_min is not allowed here soince the jet-area determination involves soft
+ * particles/jets and thus is used internally.
+ * See compute_areas for paramters definition.
+ */
+ int compute_passive_areas(std::vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+ int grid_size; ///< size of the grid we add soft particles on (N_soft=(grid_size^2))
+ double grid_eta_max; ///< maximal value of eta we add soft particles on
+ double grid_shift; ///< fractional (random) displacement of the points om the grid
+
+ double pt_soft; ///< pt of the soft particles added
+ double pt_shift; ///< amplitude of the pt random shift
+ double pt_soft_min; ///< pt_min used in SM to compute passive areas
+
+ /// jets with their areas
+ std::vector<Cjet_area> jet_areas;
+};
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: circulator.h //
+// Description: header file for circulator (circulator class) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 103 $//
+// $Date:: 2007-02-18 17:07:34 +0100 (Sun, 18 Feb 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CIRCULATOR_H__
+#define __CIRCULATOR_H__
+
+namespace siscone{
+
+/// \class circulator
+/// a circulator that is foreseen to take as template member either a
+/// pointer or an iterator;
+template<class T> class circulator {
+
+public:
+ /// ctor with iniitalisation from iterators
+ /// \param here the current position
+ /// \param begin the first position
+ /// \param end the last position
+ inline circulator(T here, T begin, T end) : m_here(here), m_begin(begin), m_end(end) {}
+
+ /// copy ctor
+ /// \param other the circulator to copy
+ inline circulator(const circulator<T> & other) : m_here(other.m_here), m_begin(other.m_begin), m_end(other.m_end) {}
+
+ /// set just the position without resetting the begin and end elements
+ /// \param other the circulator to grab position from
+ void set_position(const circulator<T> & other) {m_here = other.m_here;}
+
+ /// set just the position without resetting the begin and end elements
+ /// \param pointer the iterator to use as the new position
+ void set_position(T pointer) {m_here = pointer;}
+
+ /// get the current object
+ T operator()() {return m_here;}
+
+ /// position incrementation
+ inline circulator<T> & operator++() {
+ ++m_here;
+ if (m_here == m_end) m_here = m_begin;
+ return *this;
+ }
+
+ /// position decrementation
+ inline circulator<T> & operator--() {
+ if (m_here == m_begin) m_here = m_end;
+ --m_here;
+ return *this;
+ }
+
+ /// check if the current elements are the same
+ /// NB: for efficiency, this checks only the here element
+ /// \param other the circulator to compare to the current one
+ bool operator==(const circulator & other) const {return m_here == other.m_here;}
+
+ /// check if the current elements are different
+ /// NB: for efficiency, this checks only the here element
+ /// \param other the circulator to compare to the current one
+ bool operator!=(const circulator & other) const {return m_here != other.m_here;}
+
+private:
+ T m_here, m_begin, m_end; ///< the current, beginning and ending iterators/pointers
+};
+
+}
+
+#endif // __CIRCULATOR_H__
--- /dev/null
+/* siscone/config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "siscone"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "SISCone"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "SISCone 2.0.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "siscone"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.0.0"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "2.0.0"
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: defines.h //
+// Description: header file for generic parameters definitions //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 225 $//
+// $Date:: 2008-05-20 16:59:47 +0200 (Tue, 20 May 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+//! \file defines.h
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+/// program name
+// we get "SISCone" by calling
+// siscone::siscone_package_name
+// defined in siscone.h
+// Otherwise, config.h
+// It is also defined as "PACKAGE_NAME" in config.h but this method
+// might lead to conflicts
+//#define PROGRAM PACKAGE_NAME
+
+// program version
+// we get it from
+// siscone::siscone_version
+// defined in siscone.h
+// It is also defined as "VERSION" in config.h but this method
+// might lead to conflicts
+
+/// perform final stability check using the quadtree
+/// With the following define enabled, the final check for stability
+/// is performed using the quadtree rather than the explicit list of
+/// particles (see Cstable_cone::proceed_with_stability())
+//#define USE_QUADTREE_FOR_STABILITY_TEST
+
+
+/// threshold for recomoutation of the cone (see Cstable_cones::update_cone())
+/// When traversing cone candidates along the angular ordering,
+/// the momentum of the protojet candidate is computed incrementally
+/// from the particles that enter and leave the cone.
+/// When the cumulative change in "|px|+|py|" exceeds the cone "|px|+|py|"
+/// we explicitely recompute the cone contents
+#define PT_TSHOLD 1000.0
+
+
+/// The following parameter controls collinear safety. For the set of
+/// particles used in the search of stable cones, we gather particles
+/// if their distance in eta and phi is smaller than EPSILON_COLLINEAR.
+///
+/// NB: for things to behave sensibly one requires
+/// 1e-15 << EPSILON_COCIRCULAR << EPSILON_COLLINEAR << 1
+///
+/// among the scales that appear in practice (e.g. in deciding to use
+/// special strategies), we have EPSILON_COLLINEAR, EPSILON_COCIRCULAR,
+/// sqrt(EPSILON_COCIRCULAR) and EPSILON_COLLINEAR / EPSILON_COCIRCULAR.
+///
+#define EPSILON_COLLINEAR 1e-8
+
+
+/// The following parameter controls cocircular situations.
+/// When consecutive particles in the ordered vicinity list are separated
+/// (in angle) by less that that limit, we consider that we face a situation
+/// of cocircularity.
+#define EPSILON_COCIRCULAR 1e-12
+
+
+/// The following define enables you to allow for identical protocones
+/// to be merged automatically after each split-merge step before
+/// anything else happens. Whether this happens depends on teh value
+/// of the merge_identical_protocones flag in Csplit_merge.
+///
+/// It we allow such a merging and define allow
+/// MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE then the
+/// 'merge_identical_protocones' flag in Csplit_merge to be set to
+/// 'true'. It may be manually reset to false in which case the
+/// merging of identical protocones (protojets) will be turned off.
+///
+/// Note that this merging identical protocones makes the algorithm
+/// infrared-unsafe, so it should be disabled except for testing
+/// purposes.
+//#define ALLOW_MERGE_IDENTICAL_PROTOCONES
+//#define MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
+
+
+/// if EPSILON_SPLITMERGE is defined then, during the split-merge
+/// step, when two jets are found with PTs that are identical to
+/// within a relative difference of EPSILON_SPLITMERGE they are
+/// compared element-by-element to see where the differences are, and
+/// one then uses pt1^2-pt2^2 = (pt1-pt2).(pt1+pt2) as an estimator of
+/// which is harder. NB: in unfortunate cases, this can take the split
+/// merge step up to N n * ln N time, though on normal events there
+/// don't seem to have been any major problems yet.
+#define EPSILON_SPLITMERGE 1e-12
+
+/// definition of 2*M_PI which is useful a bit everyhere!
+const double twopi = 6.283185307179586476925286766559005768394;
+
+/// debugging information
+//#define DEBUG_STABLE_CONES ///< debug messages in stable cones search
+//#define DEBUG_SPLIT_MERGE ///< debug messages in split-merge
+//#define DEBUG ///< all debug messages !
+
+// in case all debug massages allowed, allow them in practice !
+#ifdef DEBUG
+#define DEBUG_STABLE_CONES
+#define DEBUG_SPLIT_MERGE
+#endif
+
+#endif // __DEFINES_H__
+
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.h //
+// Description: header file for two-dimensional geometry tools //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __GEOM_2D_H__
+#define __GEOM_2D_H__
+
+#include <iostream>
+#include <math.h>
+#include "defines.h"
+
+#ifndef M_PI
+#define M_PI 3.141592653589793238462643383279502884197
+#endif
+
+namespace siscone{
+
+/// return a result that corresponds to phi, but in the
+/// range (-pi..pi]; the result is only correct if -3pi < phi <= 3pi
+inline double phi_in_range(double phi) {
+ if (phi <= -M_PI) phi += twopi;
+ else if (phi > M_PI) phi -= twopi;
+ return phi;
+}
+
+/// return the difference between the two phi values,
+/// placed in the correct range (-pi..pi], , assuming that phi1,phi2
+/// are already in the correct range.
+inline double dphi(double phi1, double phi2) {
+ return phi_in_range(phi1-phi2);
+}
+
+
+/// return the absolute difference between the two phi values,
+/// placed in the correct range, assuming that phi1,phi2 are already
+/// in the correct range.
+inline double abs_dphi(double phi1, double phi2) {
+ double delta = fabs(phi1-phi2);
+ return delta > M_PI ? twopi-delta : delta;
+}
+
+/// return the square of the argument
+inline double pow2(double x) {return x*x;}
+
+
+/**
+ * \class Ctwovect
+ * \brief class for holding a two-vector
+ */
+class Ctwovect {
+public:
+ /// default ctor
+ Ctwovect() : x(0.0), y(0.0) {}
+
+ /// ctor with initialisation
+ /// \param _x first coordinate
+ /// \param _y second coordinate
+ Ctwovect(double _x, double _y) : x(_x), y(_y) {}
+
+ /// vector coordinates
+ double x, y;
+
+ /// norm (modulud square) of the vector
+ inline double mod2() const {return pow2(x)+pow2(y);}
+
+ /// modulus of the vector
+ inline double modulus() const {return sqrt(mod2());}
+};
+
+
+/// dot product of two 2-vectors
+/// \param a first 2-vect
+/// \param b second 2-vect
+/// \return a.b is returned
+inline double dot_product(const Ctwovect & a, const Ctwovect & b) {
+ return a.x*b.x + a.y*b.y;
+}
+
+
+/// cross product of two 2-vectors
+/// \param a first 2-vect
+/// \param b second 2-vect
+/// \return a x b is returned
+inline double cross_product(const Ctwovect & a, const Ctwovect & b) {
+ return a.x*b.y - a.y*b.x;
+}
+
+
+/**
+ * \class Ceta_phi_range
+ * \brief class for holding a covering range in eta-phi
+ *
+ * This class deals with ranges in the eta-phi plane. It
+ * implements methods to test if two ranges overlap and
+ * to take the union of two overlapping intervals.
+ */
+class Ceta_phi_range{
+public:
+ /// default ctor
+ Ceta_phi_range();
+
+ /// ctor with initialisation
+ /// we initialise with a centre (in eta,phi) and a radius
+ /// \param c_eta eta coordinate of the centre
+ /// \param c_phi phi coordinate of the centre
+ /// \param R radius
+ Ceta_phi_range(double c_eta, double c_phi, double R);
+
+ /// assignment of range
+ /// \param r range to assign to current one
+ Ceta_phi_range& operator = (const Ceta_phi_range &r);
+
+ /// add a particle to the range
+ /// \param eta eta coordinate of the particle
+ /// \param phi phi coordinate of the particle
+ /// \return 0 on success, 1 on error
+ int add_particle(const double eta, const double phi);
+
+ /// eta range as a binary coding of covered cells
+ unsigned int eta_range;
+
+ /// phi range as a binary coding of covered cells
+ unsigned int phi_range;
+
+ // extremal value for eta
+ static double eta_min; ///< minimal value for eta
+ static double eta_max; ///< maximal value for eta
+
+private:
+ /// return the cell index corrsponding to an eta value
+ inline unsigned int get_eta_cell(double eta){
+ return (unsigned int) (1 << ((int) (32*((eta-eta_min)/(eta_max-eta_min)))));
+ }
+
+ /// return the cell index corrsponding to a phi value
+ inline unsigned int get_phi_cell(double phi){
+ return (unsigned int) (1 << ((int) (32*phi/twopi+16)%32));
+ }
+};
+
+/// test overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return true if overlap, false otherwise.
+bool is_range_overlap(const Ceta_phi_range &r1, const Ceta_phi_range &r2);
+
+/// compute union
+/// Note: we assume that the two intervals overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return union of the two ranges
+const Ceta_phi_range range_union(const Ceta_phi_range &r1, const Ceta_phi_range &r2);
+
+}
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.h //
+// Description: header file for classes hash_element and hash_cones //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 224 $//
+// $Date:: 2008-05-16 19:58:30 +0200 (Fri, 16 May 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include "momentum.h"
+#include "reference.h"
+
+namespace siscone{
+
+/**
+ * \class hash_element
+ * information on store cones candidates.
+ *
+ * We store in this class the information used to count all
+ * protocones in a first pass. This first pass only count
+ * cones with different references and test their stbility
+ * with the parent-child particles (border particles).
+ */
+class hash_element{
+ public:
+ Creference ref; ///< reference
+ double eta; ///< centre: eta coordinate
+ double phi; ///< centre: phi coordinate
+ bool is_stable; ///< true if stable w.r.t. "border particles"
+
+ hash_element *next; ///< pointer to the next element
+};
+
+/**
+ * \class hash_cones
+ * list of cones candidates.
+ *
+ * We store in this class all the hash_elements and give
+ * functions to manipulate them.
+ */
+class hash_cones{
+ public:
+ /// constructor with initialisation
+ /// \param _Np number of particles
+ /// \param _R2 cone radius (squared)
+ hash_cones(int _Np, double _R2);
+
+ /// destructor
+ ~hash_cones();
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * \param parent parent particle defining the cone
+ * \param child child particle defining the cone
+ * \param p_io whether the parent has to belong to the cone or not
+ * \param c_io whether the child has to belong to the cone or not
+ * \return 0 on success, 1 on error
+ */
+ int insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io);
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * Note, in this case, we assume stability. We also assume
+ * that eta and phi are computed for v
+ * \return 0 on success, 1 on error
+ */
+ int insert(Cmomentum *v);
+
+ /// the cone data itself
+ hash_element **hash_array;
+
+ /// number of elements
+ int n_cones;
+
+ /// number of occupied cells
+#ifdef DEBUG_STABLE_CONES
+ int n_occupied_cells;
+#endif
+
+ /// number of cells-1
+ int mask;
+
+ /// circle radius (squared)
+ /// NOTE: need to be set before any call to 'insert'
+ double R2;
+
+ /**
+ * test if a particle is inside a cone of given centre.
+ * check if the particle of coordinates 'v' is inside the circle of radius R
+ * centered at 'centre'.
+ * \param centre centre of the circle
+ * \param v particle to test
+ * \return true if inside, false if outside
+ */
+ inline bool is_inside(Cmomentum *centre, Cmomentum *v);
+};
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.h //
+// Description: header file for 4-momentum class Cmomentum //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 163 $//
+// $Date:: 2007-04-26 22:31:02 +0200 (Thu, 26 Apr 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VECTOR_H__
+#define __VECTOR_H__
+
+#include <vector>
+#include <math.h>
+#include "reference.h"
+#include "geom_2d.h"
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class Cmomentum
+ * \brief base class for dynamic coordinates management
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It includes all Lorentz properties as well as tools for summing them.
+ * Note: 'sums' over phi angles are indeed averages. This allows to
+ * deal with periodicity at each step
+ */
+class Cmomentum{
+ public:
+ /// default ctor
+ Cmomentum();
+
+ /// ctor with initialisation
+ Cmomentum(double _px, double _py, double _pz, double _E);
+
+ /// ctor with detailed initialisation
+ Cmomentum(double _eta, double _phi, Creference _ref);
+
+ /// default dtor
+ ~Cmomentum();
+
+ /// computes pT
+ inline double perp() const {return sqrt(perp2());}
+
+ /// computes pT^2
+ inline double perp2() const {return px*px+py*py;}
+
+ /// computes m
+ inline double mass() const {return sqrt(mass2());}
+
+ /// computes m^2
+ inline double mass2() const {return perpmass2()-perp2();}
+
+ /// transverse mass, mt = sqrt(pt^2+m^2) = sqrt(E^2 - pz^2)
+ inline double perpmass() const {return sqrt((E-pz)*(E+pz));}
+
+ /// transverse mass squared, mt^2 = pt^2+m^2 = E^2 - pz^2
+ inline double perpmass2() const {return (E-pz)*(E+pz);}
+
+ /// computes transverse energy
+ inline double Et() const {return E/sqrt(1.0+pz*pz/perp2());}
+
+ /// computes transverse energy (squared)
+ inline double Et2() const {return E*E/(1.0+pz*pz/perp2());}
+
+ /// assignment of vectors
+ Cmomentum& operator = (const Cmomentum &v);
+
+ /// addition of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ const Cmomentum operator + (const Cmomentum &v);
+
+ /// incrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ Cmomentum& operator += (const Cmomentum &v);
+
+ /// decrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ Cmomentum& operator -= (const Cmomentum &v);
+
+ /// build eta-phi from 4-momentum info
+ /// !!! WARNING !!!
+ /// !!! computing eta and phi is time-consuming !!!
+ /// !!! use this whenever you need eta or phi !!!
+ /// !!! automatically called for single-particle !!!
+ void build_etaphi();
+
+ double px; ///< x-momentum
+ double py; ///< y-momentum
+ double pz; ///< z-momentum
+ double E; ///< energy
+
+ double eta; ///< particle pseudo-rapidity
+ double phi; ///< particle azimuthal angle
+ int parent_index; ///< particle number in the parent list
+ int index; ///< internal particle number
+
+ //////////////////////////////////////////////
+ // the following part is used for checksums //
+ //////////////////////////////////////////////
+ Creference ref; ///< reference number for the vector
+};
+
+/// ordering of two vectors
+/// this is by default done w.r.t. their references
+bool operator < (const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in eta (e.g. used in collinear tests)
+bool momentum_eta_less(const Cmomentum &v1, const Cmomentum &v2);
+
+/// ordering of vectors in pt
+bool momentum_pt_less(const Cmomentum &v1, const Cmomentum &v2);
+
+
+//////////////////////////
+// some handy utilities //
+//////////////////////////
+
+/// get distance between to eta-phi points
+/// \param eta eta coordinate of first point
+/// \param phi phi coordinate of first point
+/// \param v vector defining the second point
+inline double get_distance(double eta, double phi, Cmomentum *v){
+ double dx, dy;
+
+ dx = eta - v->eta;
+ dy = fabs(phi - v->phi);
+ if (dy>M_PI)
+ dy -= twopi;
+
+ return dx*dx+dy*dy;
+}
+
+}
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.h //
+// Description: header file for stable cones determination (Cstable_cones) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 224 $//
+// $Date:: 2008-05-16 19:58:30 +0200 (Fri, 16 May 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PROTOCONES_H__
+#define __PROTOCONES_H__
+
+#include "momentum.h"
+#include "vicinity.h"
+#include <stdio.h>
+#include <vector>
+#include <list>
+#include "hash.h"
+
+#include "defines.h"
+
+namespace siscone{
+
+/**
+ * \class Cborder_store
+ *
+ * class for storing a border momentum (in context of co-circularity
+ * checks).
+
+ * This class essentially calculates angle of border point w.r.t.
+ * circle center (eta & phi), and provides a store of information
+ * about whether we are currently including this point in the
+ * candidate
+ */
+class Cborder_store{
+public:
+ /// default ctor
+ Cborder_store(Cmomentum * momentum, double centre_eta, double centre_phi) :
+ mom(momentum), is_in(false) {
+ angle = atan2(mom->phi - centre_phi, mom->eta - centre_eta);
+ }
+
+ Cmomentum * mom; ///< particle momentum
+ double angle; ///< angle w.r.t. circle centre
+ bool is_in; ///< inclusion status of the particle
+};
+
+
+/// allows easy sorting of Cborder_store objects (which need to be
+/// ordered in angle).
+inline bool operator<(const Cborder_store & a, const Cborder_store & b) {
+ return a.angle < b.angle;
+}
+
+
+/**
+ * \class Cstable_cones
+ * \brief Computes the list of stable comes from a particle list.
+ *
+ * This class does the first fundamental task of te cone algorithm:
+ * it is used to compute the list of stable cones given a list
+ * of particles.
+ */
+class Cstable_cones : public Cvicinity{
+ public:
+ /// default ctor
+ Cstable_cones();
+
+ /// ctor with initialisation (sse init for details)
+ Cstable_cones(std::vector<Cmomentum> &_particle_list);
+
+ /// default dtor
+ ~Cstable_cones();
+
+ /**
+ * initialisation
+ * \param _particle_list list of particles
+ */
+ void init(std::vector<Cmomentum> &_particle_list);
+
+ /**
+ * compute stable cones.
+ * This function really does the job i.e. computes
+ * the list of stable cones (in a seedless way)
+ * \param _radius radius of the cones
+ * \return The number of stable cones found is returned
+ */
+ int get_stable_cones(double _radius);
+
+ /// list of stable cones
+ std::vector<Cmomentum> protocones;
+
+ /// list of candidates
+ hash_cones *hc;
+
+ /// total number of tested cones
+ int nb_tot;
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones, nb_hash_occupied;
+#endif
+
+ protected:
+ /// cone radius
+ double R;
+
+ /// cone radius SQUARED
+ double R2;
+
+ private:
+ /// cone with a given particle as parent
+ /// this reduction to a single vector assumes we trust the checksums
+ Cmomentum cone;
+
+ /// child particle, taken in the 'vicinity' list
+ Cmomentum *child;
+
+ /// centre of the tested cone
+ Cvicinity_elm *centre;
+
+ /// index in the particle list;
+ unsigned int centre_idx;
+
+ /// first cone used in the vicinity list
+ unsigned int first_cone;
+
+ /**
+ * initialise the cone.
+ * We take the first particle in the angular ordering to compute this one
+ * \return 0 on success, 1 on error
+ */
+ int init_cone();
+
+ /**
+ * test cones.
+ * We check if the cone(s) build with the present parent and child
+ * are stable
+ * \return 0 on success 1 on error
+ */
+ int test_cone();
+
+ /**
+ * update the cone
+ * go to the next child for that parent and update 'cone' appropriately
+ * \return 0 if update candidate found, 1 otherwise
+ */
+ int update_cone();
+
+ /*
+ * run through the vicinity of the current parent and for each child
+ * indicate which members are cocircular...
+ */
+ void prepare_cocircular_lists();
+
+ /**
+ * check if we are in a situation of cocircularity.
+ * if it is the case, update and test in the corresponding way
+ * \return 'false' if no cocircularity detected, 'true' otherwise
+ * Note that if cocircularity is detected, we need to
+ * recall 'update' from 'update' !!!
+ */
+ bool cocircular_check();
+
+ /**
+ * Routine for testing cocircular configurations in p^3 time,
+ * rather than 2^p time;
+ */
+ void test_cone_cocircular(Cmomentum & borderless_cone,
+ std::list<Cmomentum *> & border_list);
+
+ /**
+ * carry out the computations needed for the stability check of the
+ * candidate, using the border_vect to indicate which particles
+ * should / should not be in the stable cone; if the cone is stable
+ * insert it into the hash.
+ */
+ void test_stability(Cmomentum & candidate,
+ const std::vector<Cborder_store> & border_vect);
+
+ /**
+ * compute the cone contents by going once around the full set of
+ * circles and tracking the entry/exit status each time -- this sets
+ * up the inclusion information, which can then be directly used to
+ * calculate the cone momentum.
+ */
+ void compute_cone_contents();
+
+ /**
+ * compute the cone momentum from particle list.
+ * in this version, we use the 'pincluded' information
+ * from the Cviinity class
+ */
+ void recompute_cone_contents();
+
+ /*
+ * if we have gone beyond the acceptable threshold of change, compute
+ * the cone momentum from particle list. in this version, we use the
+ * 'pincluded' information from the Cvicinity class, but we don't
+ * change the member cone, only the locally supplied one
+ */
+ void recompute_cone_contents_if_needed(Cmomentum & this_cone, double & this_dpt);
+
+ /**
+ * compute stability of all enumerated candidates.
+ * For all candidate cones which are stable w.r.t. their border particles,
+ * pass the last test: stability with quadtree intersection
+ */
+ int proceed_with_stability();
+
+ /*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a checkxor of the intersection's particles
+ * - cx circle centre x coordinate
+ * - cy circle centre y coordinate
+ * return the checkxor for the intersection
+ ******************************************************************/
+ Creference circle_intersect(double cx, double cy);
+
+ /// present candidate cone
+ Cmomentum cone_candidate;
+
+ /// in case of co-circular points, vector for them
+ std::vector<Cmomentum*> child_list;
+
+ /// list of cocircular enclusures already studied
+ /// first element if cone contents, second is cone border
+ std::vector< std::pair<Creference,Creference> > multiple_centre_done;
+
+ // information for updating cone contents to avoid rounding errors
+ double dpt; ///< sums of Delta P_t
+
+ /**
+ * test if a particle is inside a cone of given centre.
+ * check if the particle of coordinates 'v' is inside the circle of radius R
+ * centered at 'centre'.
+ * \param centre centre of the circle
+ * \param v particle to test
+ * \return true if inside, false if outside
+ */
+ inline bool is_inside(Cmomentum *centre, Cmomentum *v);
+};
+
+/*
+ * compute the absolute value of the difference between 2 angles.
+ * We take care of the 2pi periodicity
+ * \param angle1 first angle
+ * \param angle2 second angle
+ * \return the absolute value of the difference between the angles
+ *****************************************************************/
+inline double abs_dangle(double &angle1, double &angle2);
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: quadtree.h //
+// Description: header file for quadtree management (Cquadtree class) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 123 $//
+// $Date:: 2007-03-01 02:52:16 +0100 (Thu, 01 Mar 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __QUADTREE_H__
+#define __QUADTREE_H__
+
+#include "momentum.h"
+#include <stdio.h>
+
+namespace siscone{
+
+/**
+ * \class Cquadtree
+ * \brief Implementation of a 2D quadtree.
+ *
+ * This class implements the traditional two-dimensional quadtree.
+ * The elements at each node are of 'Cmomentum' type.
+ */
+class Cquadtree{
+ public:
+ /// default ctor
+ Cquadtree();
+
+ /// ctor with initialisation (see init for details)
+ Cquadtree(double _x, double _y, double _half_size_x, double _half_size_y);
+
+ /// default destructor
+ /// at destruction, everything is destroyed except
+ /// physical values at the leaves
+ ~Cquadtree();
+
+ /**
+ * init the tree.
+ * By initializing the tree, we mean setting the cell parameters
+ * and preparing the object to act as a seed for a new tree.
+ * \param _x x-position of the center
+ * \param _y y-position of the center
+ * \param _half_size_x x-size of the cell
+ * \param _half_size_y y-size of the cell
+ * \return 0 on success, 1 on error. Note that if the cell or its
+ * parent is already filled, we return an error.
+ */
+ int init(double _x, double _y, double _half_size_x, double _half_size_y);
+
+ /**
+ * adding a particle to the tree.
+ * This method adds one vector to the quadtree structure which
+ * is updated consequently.
+ * \param v_add vector to add
+ * \return 0 on success 1 on error
+ */
+ int add(Cmomentum *v_add);
+
+ /**
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a quadtree with all squares included
+ * in the circle.
+ * \param cx circle centre x coordinate
+ * \param cy circle centre y coordinate
+ * \param cR2 circle radius SQUARED
+ * \return the checksum for that intersection
+ */
+ Creference circle_intersect(double cx, double cy, double cR2);
+
+ /**
+ * output a data file for drawing the grid.
+ * This can be used to output a data file containing all the
+ * grid subdivisions. The file contents is as follows:
+ * first and second columns give center of the cell, the third
+ * gives the size.
+ * \param flux opened stream to write to
+ * \return 0 on success, 1 on error
+ */
+ int save(FILE *flux);
+
+ /**
+ * output a data file for drawing the tree leaves.
+ * This can be used to output a data file containing all the
+ * tree leaves. The file contents is as follows:
+ * first and second columns give center of the cell, the third
+ * gives the size.
+ * \param flux opened stream to write to
+ * \return 0 on success, 1 on error
+ */
+ int save_leaves(FILE *flux);
+
+ double centre_x; ///< x-position of the centre of the cell
+ double centre_y; ///< y-position of the centre of the cell
+ double half_size_x; ///< HALF size of the cell
+ double half_size_y; ///< HALF size of the cell
+
+ Cmomentum *v; ///< physical contents
+
+ Cquadtree* children[2][2]; ///< sub-cells ( 0,1->left-right; 0,1->bottom,top)
+ bool has_child; ///< true if not a leaf
+};
+
+}
+#endif
--- /dev/null
+//! \file ranlux.h
+
+#ifndef __RANLUX_H__
+#define __RANLUX_H__
+
+/* This is a lagged fibonacci generator with skipping developed by Luescher.
+ The sequence is a series of 24-bit integers, x_n,
+
+ x_n = d_n + b_n
+
+ where d_n = x_{n-10} - x_{n-24} - c_{n-1}, b_n = 0 if d_n >= 0 and
+ b_n = 2^24 if d_n < 0, c_n = 0 if d_n >= 0 and c_n = 1 if d_n < 0,
+ where after 24 samples a group of p integers are "skipped", to
+ reduce correlations. By default p = 199, but can be increased to
+ 365.
+
+ The period of the generator is around 10^171.
+
+ From: M. Luescher, "A portable high-quality random number generator
+ for lattice field theory calculations", Computer Physics
+ Communications, 79 (1994) 100-110.
+
+ Available on the net as hep-lat/9309020 at http://xxx.lanl.gov/
+
+ See also,
+
+ F. James, "RANLUX: A Fortran implementation of the high-quality
+ pseudo-random number generator of Luscher", Computer Physics
+ Communications, 79 (1994) 111-114
+
+ Kenneth G. Hamilton, F. James, "Acceleration of RANLUX", Computer
+ Physics Communications, 101 (1997) 241-248
+
+ Kenneth G. Hamilton, "Assembler RANLUX for PCs", Computer Physics
+ Communications, 101 (1997) 249-253 */
+
+namespace siscone{
+
+/// initialize 'ranlux' generator
+void ranlux_init();
+
+/// generate random value (24 bits)
+unsigned long int ranlux_get();
+
+/// save state of the generator
+void ranlux_print_state();
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: reference.h //
+// Description: header file for checkxor management (Creference class) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 123 $//
+// $Date:: 2007-03-01 02:52:16 +0100 (Thu, 01 Mar 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __REFERENCE_H__
+#define __REFERENCE_H__
+
+namespace siscone{
+
+/**
+ * \class Creference
+ * \brief references used for checksums.
+ *
+ * This class implements some reference variable
+ * that can be used for checksums. Those checksums
+ * are useful to disentengle between contents of two
+ * cones without looking into their explicit particle
+ * contents.
+ */
+class Creference{
+ public:
+ /// default constructor
+ Creference();
+
+ /// create a random reference
+ void randomize();
+
+ /// test emptyness
+ bool is_empty();
+
+ /// test non-emptyness
+ bool not_empty();
+
+ /// assignment of reference
+ Creference& operator = (const Creference &r);
+
+ /// addition of reference
+ Creference operator + (const Creference &r);
+
+ /// incrementation of reference
+ Creference& operator += (const Creference &r);
+
+ /// decrementation of reference
+ Creference& operator -= (const Creference &r);
+
+ /// accessing the reference
+ inline unsigned int operator[] (int i) {return ref[i];}
+
+ unsigned int ref[3]; ///< actual data for the reference
+};
+
+/// addition of two references
+Creference operator + (Creference &r1, Creference &r2);
+
+/// equality test of two references
+bool operator == (const Creference &r1, const Creference &r2);
+
+/// difference test of two references
+bool operator != (const Creference &r1, const Creference &r2);
+
+/// ordering of two references
+bool operator < (const Creference &r1, const Creference &r2);
+
+
+//=============== inline material ================
+
+// equality test for two references
+//----------------------------------
+inline bool operator == (const Creference &r1, const Creference &r2){
+ return (r1.ref[0]==r2.ref[0]) && (r1.ref[1]==r2.ref[1]) && (r1.ref[2]==r2.ref[2]);
+}
+
+// difference test for two references
+//----------------------------------
+inline bool operator != (const Creference &r1, const Creference &r2){
+ return (r1.ref[0]!=r2.ref[0]) || (r1.ref[1]!=r2.ref[1]) || (r1.ref[2]!=r2.ref[2]);
+}
+
+// difference test for two references
+//----------------------------------
+inline bool operator < (const Creference &r1, const Creference &r2){
+ return (r1.ref[0]<r2.ref[0]) || ((r1.ref[0]==r2.ref[0]) &&
+ ((r1.ref[1]<r2.ref[1]) || ((r1.ref[1]==r2.ref[1]) && (r1.ref[2]<r2.ref[2]))
+ ));
+}
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.h //
+// Description: header file for the main SISCone class //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 224 $//
+// $Date:: 2008-05-16 19:58:30 +0200 (Fri, 16 May 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_H__
+#define __SISCONE_H__
+
+#include "protocones.h"
+#include "split_merge.h"
+
+namespace siscone{
+
+/**
+ * \class Csiscone
+ * final class: gather everything to compute the jet contents.
+ *
+ * This is the class user should use.
+ * It computes the jet contents of a list of particles
+ * given a cone radius and a threshold for splitting/merging.
+ *
+ * After the call to 'perform', the vector jets is filled with
+ * the jets found. the 'contents' field of each jets contains
+ * the indices of the particles included in that jet.
+ */
+class Csiscone : public Cstable_cones, public Csplit_merge{
+ public:
+ /// default ctor
+ Csiscone();
+
+ /// default dtor
+ ~Csiscone();
+
+ /**
+ * compute the jets from a given particle set.
+ * We are doing multiple passes such pass n_pass looks for jets among
+ * all particles not put into jets during previous passes.
+ * By default the number of passes is infinite (0).
+ * \param _particles list of particles
+ * \param _radius cone radius
+ * \param _f shared energy threshold for splitting&merging
+ * \param _n_pass_max maximum number of passes (0=full search)
+ * \param _ptmin minimum pT of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: SM_pt leads to IR unsafety for some events with momentum conservation.
+ * SM_Et is IR safe but not boost invariant and not implemented(!)
+ * SM_mt is IR safe for hadronic events, but not for decays of two
+ * back-to-back particles of identical mass
+ * SM_pttilde
+ * is always IR safe, and also boost invariant (default)
+ *
+ * \return the number of jets found.
+ */
+ int compute_jets(std::vector<Cmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, double _ptmin=0.0,
+ Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+ /**
+ * recompute the jets with a different overlap parameter.
+ * we use the same particles and R as in the preceeding call.
+ * \param _f shared energy threshold for splitting&merging
+ * \param _ptmin minimum pT of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * split--merge variable
+ * NOTE: using pt leads to IR unsafety for some events with momentum
+ * conservation. So we strongly advise not to change the default
+ * value.
+ * \return the number of jets found, -1 if recomputation not allowed.
+ */
+ int recompute_jets(double _f, double _ptmin = 0.0,
+ Esplit_merge_scale _split_merge_scale=SM_pttilde);
+
+ /// list of protocones found pass-by-pass
+ std::vector<std::vector<Cmomentum> > protocones_list;
+
+ // random number initialisation
+ static bool init_done; ///< check random generator initialisation
+
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones_total, nb_hash_occupied_total;
+#endif
+
+ private:
+ bool rerun_allowed; ///< is recompute_jets allowed ?
+};
+
+
+// finally, a bunch of functions to access to
+// basic information (package name, version)
+//---------------------------------------------
+
+/**
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * \return the SISCone name as a string
+ */
+std::string siscone_package_name();
+
+/**
+ * return SISCone version number.
+ * \return a string of the form "X.Y.Z" with possible additional tag
+ * (alpha, beta, devel) to mention stability status
+ */
+std::string siscone_version();
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone_error.h //
+// Description: header file for SISCone error messages (Csiscone_error) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SISCONE_ERROR_H__
+#define __SISCONE_ERROR_H__
+
+#include<iostream>
+#include<string>
+
+namespace siscone{
+
+/// \class Csiscone_error
+/// class corresponding to errors that will be thrown by siscone
+class Csiscone_error {
+public:
+ /// default ctor
+ Csiscone_error() {;};
+
+ /// ctor with a given error message
+ /// \param message the error message to be printed
+ Csiscone_error(const std::string & message) {
+ m_message = message;
+ if (m_print_errors) std::cerr << "siscone::Csiscone_error: "<<message << std::endl;
+ };
+
+ /// access to the error message
+ std::string message() const {return m_message;};
+
+ /// switch on/off the error message printing
+ /// \param print_errors errors will be printed when true
+ static void setm_print_errors(bool print_errors) {
+ m_print_errors = print_errors;};
+
+private:
+ std::string m_message; ///< the error message
+ static bool m_print_errors; ///< do we print error messages?
+};
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: geom_2d.h //
+// Description: header file for two-dimensional geometry tools //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_GEOM_2D_H__
+#define __SPH_GEOM_2D_H__
+
+#include <iostream>
+#include <math.h>
+#include <siscone/defines.h>
+#include <siscone/geom_2d.h>
+
+#ifndef M_PI
+#define M_PI 3.141592653589793238462643383279502884197
+#endif
+
+namespace siscone_spherical{
+
+/**
+ * \class CSphtheta_phi_range
+ * \brief class for holding a covering range in eta-phi
+ *
+ * This class deals with ranges in the eta-phi plane. It
+ * implements methods to test if two ranges overlap and
+ * to take the union of two overlapping intervals.
+ */
+class CSphtheta_phi_range{
+public:
+ /// default ctor
+ CSphtheta_phi_range();
+
+ /// ctor with initialisation
+ /// we initialise with a centre (in theta,phi) and a radius
+ /// \param c_theta theta coordinate of the centre
+ /// \param c_phi phi coordinate of the centre
+ /// \param R radius
+ CSphtheta_phi_range(double c_theta, double c_phi, double R);
+
+ /// assignment of range
+ /// \param r range to assign to current one
+ CSphtheta_phi_range& operator = (const CSphtheta_phi_range &r);
+
+ /// add a particle to the range
+ /// \param theta theta coordinate of the particle
+ /// \param phi phi coordinate of the particle
+ /// \return 0 on success, 1 on error
+ int add_particle(const double theta, const double phi);
+
+ /// theta range as a binary coding of covered cells
+ unsigned int theta_range;
+
+ /// phi range as a binary coding of covered cells
+ unsigned int phi_range;
+
+ /// extremal value for theta
+ static double theta_min; ///< minimal value for theta (set to 0)
+ static double theta_max; ///< maximal value for theta (set to pi)
+
+private:
+ /// return the cell index corrsponding to an theta value
+ inline unsigned int get_theta_cell(double theta){
+ return (unsigned int) (1 << ((int) (32*((theta-theta_min)/(theta_max-theta_min)))));
+ }
+
+ /// return the cell index corrsponding to a phi value
+ inline unsigned int get_phi_cell(double phi){
+ return (unsigned int) (1 << ((int) (32*phi/twopi+16)%32));
+ }
+};
+
+/// test overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return true if overlap, false otherwise.
+bool is_range_overlap(const CSphtheta_phi_range &r1, const CSphtheta_phi_range &r2);
+
+/// compute union
+/// Note: we assume that the two intervals overlap
+/// \param r1 first range
+/// \param r2 second range
+/// \return union of the two ranges
+const CSphtheta_phi_range range_union(const CSphtheta_phi_range &r1, const CSphtheta_phi_range &r2);
+
+}
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: hash.h //
+// Description: header file for classes hash_element and hash_cones //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_HASH_H__
+#define __SPH_HASH_H__
+
+#include "momentum.h"
+
+namespace siscone_spherical{
+
+/**
+ * \class sph_hash_element
+ * information on store cones candidates.
+ *
+ * We store in this class the information used to count all
+ * protocones in a first pass. This first pass only count
+ * cones with different references and test their stbility
+ * with the parent-child particles (border particles).
+ */
+class sph_hash_element{
+ public:
+ CSph3vector centre; ///< centre of the cone
+ bool is_stable; ///< true if stable w.r.t. "border particles"
+
+ sph_hash_element *next; ///< pointer to the next element
+};
+
+/**
+ * \class sph_hash_cones
+ * list of cones candidates.
+ *
+ * We store in this class all the hash_elements and give
+ * functions to manipulate them.
+ */
+class sph_hash_cones{
+ public:
+ /// constructor with initialisation
+ /// \param _Np number of particles
+ /// \param _R2 cone radius (squared)
+ sph_hash_cones(int _Np, double _R2);
+
+ /// destructor
+ ~sph_hash_cones();
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * \param parent parent particle defining the cone
+ * \param child child particle defining the cone
+ * \param p_io whether the parent has to belong to the cone or not
+ * \param c_io whether the child has to belong to the cone or not
+ * \return 0 on success, 1 on error
+ */
+ int insert(CSphmomentum *v, CSphmomentum *parent, CSphmomentum *child, bool p_io, bool c_io);
+
+ /**
+ * insert a new candidate into the hash.
+ * \param v 4-momentum of te cone to add
+ * Note, in this case, we assume stability. We also assume
+ * that eta and phi are computed for v
+ * \return 0 on success, 1 on error
+ */
+ int insert(CSphmomentum *v);
+
+ /// the cone data itself
+ sph_hash_element **hash_array;
+
+ /// number of elements
+ int n_cones;
+
+ /// number of occupied cells
+#ifdef DEBUG_STABLE_CONES
+ int n_occupied_cells;
+#endif
+
+ /// number of cells-1
+ int mask;
+
+ /// circle radius (squared)
+ /// NOTE: need to be set before any call to 'insert'
+ double R2;
+
+ /// its squreed tangent
+ double tan2R;
+};
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: momentum.h //
+// Description: header file for 4-momentum class Cmomentum //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 256 $//
+// $Date:: 2008-07-14 13:52:16 +0200 (Mon, 14 Jul 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_VECTOR_H__
+#define __SPH_VECTOR_H__
+
+#include <vector>
+#include <math.h>
+#include <siscone/reference.h>
+#include "geom_2d.h"
+#include <siscone/defines.h>
+
+namespace siscone_spherical{
+
+/**
+ * \class CSph3vector
+ * \brief base class for managing the spatial part of Cmomentum (defined after)
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It is adapted to use spherical geometry, where, for our purposes,
+ * the only time-consuming operation we need is the computation of
+ * the norm. To compute it once-and-for-all and store it in a local
+ * variable, you should call the 'build_norm' method.
+ * On top of that, the angle phi is computed from the x-axis
+ * and theta from the "north pole".
+ */
+class CSph3vector{
+ public:
+ /// default ctor
+ CSph3vector();
+
+ /// ctor with initialisation
+ CSph3vector(double _px, double _py, double _pz);
+
+ /// default dtor
+ ~CSph3vector();
+
+ /// assignment of vectors
+ CSph3vector& operator = (const CSph3vector &v);
+
+ /// addition of vectors
+ /// WARNING= norm is not updated
+ const CSph3vector operator + (const CSph3vector &v);
+
+ /// subtraction of vectors
+ /// WARNING= norm is not updated
+ const CSph3vector operator - (const CSph3vector &v);
+
+ /// division by a constant
+ /// WARNING= norm is not updated
+ const CSph3vector operator / (const double &r);
+
+ /// incrementation of vectors
+ /// WARNING= norm is not updated
+ CSph3vector& operator += (const CSph3vector &v);
+
+ /// decrementation of vectors
+ /// WARNING= norm is not updated
+ CSph3vector& operator -= (const CSph3vector &v);
+
+ /// multiplication by a constant
+ /// WARNING= norm is not updated
+ CSph3vector& operator *= (const double &r);
+
+ /// division by a constant
+ /// WARNING= norm is not updated
+ CSph3vector& operator /= (const double &r);
+
+ /// computes pT
+ inline double perp() const {return sqrt(perp2());}
+
+ /// computes pT^2
+ inline double perp2() const {return px*px+py*py;}
+
+ /// 3-vect norm
+ inline double norm() const {return sqrt(px*px+py*py+pz*pz);}
+
+ /// 3-vect norm squared
+ inline double norm2() const {return px*px+py*py+pz*pz;}
+
+ /// 3-vect azimuthal angle
+ inline double phi() const {return atan2(py, px);}
+
+ /// 3-vect polar angle
+ inline double theta() const {return atan2(perp(),pz);}
+
+ /// build the spatial normfrom 4-momentum info
+ /// !!! WARNING !!!
+ /// !!! computing the norm is the only time-consuming !!!
+ /// !!! information we need in all computations. !!!
+ /// !!! use this whenever you need repeated access !!!
+ /// !!! to the norm to store it in the local variable !!!
+ void build_norm();
+
+ /// just a useful tool to store theta and phi
+ /// locally (in _theta and _phi) in case you need
+ /// repeated access
+ void build_thetaphi();
+
+ /// for this direction, compute the two reference directions
+ /// used to measure angles
+ void get_angular_directions(CSph3vector &angular_dir1, CSph3vector &angular_dir2);
+
+ double px; ///< x-momentum
+ double py; ///< y-momentum
+ double pz; ///< z-momentum
+
+ double _norm; ///< particle spatial norm (available ONLY after a call to build_norm)
+ double _theta; ///< particle theta angle (available ONLY after a call to build_thetaphi)
+ double _phi; ///< particle phi angle (available ONLY after a call to build_thetaphi)
+
+ //////////////////////////////////////////////
+ // the following part is used for checksums //
+ //////////////////////////////////////////////
+ siscone::Creference ref; ///< reference number for the vector
+};
+
+/**
+ * \class CSphmomentum
+ * \brief base class for dynamic coordinates management
+ *
+ * This class contains the information for particle or group of
+ * particles management.
+ * It is adapted to use spherical geometry, where, for our purposes,
+ * the only time-consuming operation we need is the computation of
+ * the norm. To compute it once-and-for-all and store it in a local
+ * variable, you should call the 'build_norm' method.
+ * On top of that, the angle phi is computed from the x-axis
+ * and theta from the "north pole".
+ */
+class CSphmomentum : public CSph3vector{
+ public:
+ /// default ctor
+ CSphmomentum();
+
+ /// init from a 3-vect
+ CSphmomentum(CSph3vector &init, double E=0.0);
+
+ /// ctor with initialisation
+ CSphmomentum(double _px, double _py, double _pz, double _E);
+
+ /// ctor with detailed initialisation
+ //CSphmomentum(double _eta, double _phi, siscone::Creference _ref);
+
+ /// default dtor
+ ~CSphmomentum();
+
+ /// computes m
+ inline double mass() const {return sqrt(mass2());}
+
+ /// computes m^2
+ inline double mass2() const {return perpmass2()-perp2();}
+
+ /// transverse mass, mt = sqrt(pt^2+m^2) = sqrt(E^2 - pz^2)
+ inline double perpmass() const {return sqrt((E-pz)*(E+pz));}
+
+ /// transverse mass squared, mt^2 = pt^2+m^2 = E^2 - pz^2
+ inline double perpmass2() const {return (E-pz)*(E+pz);}
+
+ /// computes transverse energy
+ inline double Et() const {return E/sqrt(1.0+pz*pz/perp2());}
+
+ /// computes transverse energy (squared)
+ inline double Et2() const {return E*E/(1.0+pz*pz/perp2());}
+
+ /// assignment of vectors
+ CSphmomentum& operator = (const CSphmomentum &v);
+
+ /// addition of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ const CSphmomentum operator + (const CSphmomentum &v);
+
+ /// incrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ CSphmomentum& operator += (const CSphmomentum &v);
+
+ /// decrementation of vectors
+ /// !!! WARNING !!! no updating of eta and phi !!!
+ CSphmomentum& operator -= (const CSphmomentum &v);
+
+ double E; ///< energy
+
+ int parent_index; ///< particle number in the parent list
+ int index; ///< internal particle number
+};
+
+/// ordering of two vectors
+/// this is by default done w.r.t. their references
+bool operator < (const CSphmomentum &v1, const CSphmomentum &v2);
+
+/// ordering of vectors in eta (e.g. used in collinear tests)
+bool momentum_theta_less(const CSphmomentum &v1, const CSphmomentum &v2);
+
+/// ordering of vectors in pt
+bool momentum_pt_less(const CSphmomentum &v1, const CSphmomentum &v2);
+
+
+//////////////////////////
+// some handy utilities //
+//////////////////////////
+
+/// square
+inline double sqr(double x){return x*x;}
+
+/// dot product for te spatial 3-vect
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline double dot_product3(const CSph3vector &v1, const CSph3vector &v2){
+ //double tmp = v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
+ //if (!isfinite(tmp)){
+ // std::cout << "dot_product inf: " << std::endl;
+ // std::cout << " angles: " << v1._theta << " " << v1._phi << " and " << v2._theta << " " << v2._phi << std::endl;
+ // std::cout << " moms : " << v1.px << " " << v1.py << " " << v1.pz
+ // << " and " << v2.px << " " << v2.py << " " << v2.pz << std::endl;
+ //}
+ return v1.px*v2.px + v1.py*v2.py + v1.pz*v2.pz;
+}
+
+/// cross product for the spatial 3-vect
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline CSph3vector cross_product3(const CSph3vector &v1, const CSph3vector &v2){
+ //CSph3vector tmp;
+ //tmp.px = v1.py*v2.pz-v1.pz*v2.py;
+ //tmp.py = v1.pz*v2.px-v1.px*v2.pz;
+ //tmp.pz = v1.px*v2.py-v1.py*v2.px;
+ //return tmp;
+ return CSph3vector(v1.py*v2.pz-v1.pz*v2.py,
+ v1.pz*v2.px-v1.px*v2.pz,
+ v1.px*v2.py-v1.py*v2.px);
+}
+
+/// squared norm of the cross product for the spatial 3-vect (energy is set to 0)
+/// \param v1 first 4-vect
+/// \param v2 second 4-vect
+inline double norm2_cross_product3(const CSph3vector &v1, const CSph3vector &v2){
+ return sqr(v1.py*v2.pz-v1.pz*v2.py) + sqr(v1.pz*v2.px-v1.px*v2.pz) + sqr(v1.px*v2.py-v1.py*v2.px);
+}
+
+/// get tangent squared of the spherical distance between two vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+inline double get_tan2_distance(const CSphmomentum &v1, const CSphmomentum &v2){
+ return norm2_cross_product3(v1,v2)/sqr(dot_product3(v1,v2));
+}
+
+/// get spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+inline double get_distance(const CSph3vector *v1, const CSph3vector *v2){
+ return atan2(sqrt(norm2_cross_product3(*v1,*v2)), dot_product3(*v1,*v2));
+}
+
+/// return true if the two points are distant by less than get spherical distance between two vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+/// \param tan2R tangent squared of the max distance
+/// WARNING: using the tangent here is dangerous for R>pi/2.
+/// this never happens per se for "regular R" but
+/// it may in the vicinity computation as we're using
+/// 2R there.
+inline bool is_closer(const CSph3vector *v1, const CSph3vector *v2, const double tan2R){
+ double dot = dot_product3(*v1,*v2);
+ return (dot>=0) && (norm2_cross_product3(*v1,*v2)<=tan2R*dot*dot);
+}
+
+/// return true if the two points are distant by less than get spherical distance between to vectors
+/// \param v1 vector defining the first point
+/// \param v2 vector defining the second point
+/// \param tan2R tangent squared of the max distance
+/// safer version but computes the norm
+inline bool is_closer_safer(const CSph3vector *v1, const CSph3vector *v2, const double cosR){
+ return dot_product3(*v1,*v2)>=cosR*sqrt(v1->norm2()*v2->norm2());
+ //double dot = dot_product3(*v1,*v2);
+ //return (dot>=0) && (norm2_cross_product3(*v1,*v2)<tan2R*dot*dot);
+}
+
+/// multiply a vector by a constant
+/// WARNING: norm not updated
+inline CSph3vector operator * (const double &r, const CSph3vector &v){
+ CSph3vector tmp = v;
+ return tmp*=r;
+}
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: protocones.h //
+// Description: header file for stable cones determination (Cstable_cones) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 255 $//
+// $Date:: 2008-07-12 17:40:35 +0200 (Sat, 12 Jul 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_PROTOCONES_H__
+#define __SPH_PROTOCONES_H__
+
+#include "momentum.h"
+#include "vicinity.h"
+#include <stdio.h>
+#include <vector>
+#include <list>
+#include "hash.h"
+
+#include <siscone/defines.h>
+
+namespace siscone_spherical{
+
+/**
+ * \class CSphborder_store
+ *
+ * class for storing a border momentum (in context of co-circularity
+ * checks).
+
+ * This class essentially calculates angle of border point w.r.t.
+ * circle center (eta & phi), and provides a store of information
+ * about whether we are currently including this point in the
+ * candidate
+ */
+class CSphborder_store{
+public:
+ /// default ctor
+ CSphborder_store(CSphmomentum * momentum, CSph3vector ¢re, CSph3vector &angl_dir1, CSph3vector &angl_dir2) :
+ mom(momentum), is_in(false) {
+ CSph3vector diff = (*momentum) - centre;
+ angle = atan2(dot_product3(diff, angl_dir2), dot_product3(diff, angl_dir1));
+#ifdef DEBUG_STABLE_CONES
+ std::cout << " adding point " << momentum->_theta << ", " << momentum->_phi
+ << " at an angle of " << angle << std::endl;
+#endif
+ }
+
+ CSphmomentum * mom; ///< particle momentum
+ double angle; ///< angle w.r.t. circle centre
+ bool is_in; ///< inclusion status of the particle
+};
+
+
+/// allows easy sorting of CSphborder_store objects (which need to be
+/// ordered in angle).
+inline bool operator<(const CSphborder_store & a, const CSphborder_store & b) {
+ return a.angle < b.angle;
+}
+
+
+/**
+ * \class CSphstable_cones
+ * \brief Computes the list of stable comes from a particle list.
+ *
+ * This class does the first fundamental task of te cone algorithm:
+ * it is used to compute the list of stable cones given a list
+ * of particles.
+ */
+class CSphstable_cones : public CSphvicinity{
+ public:
+ /// default ctor
+ CSphstable_cones();
+
+ /// ctor with initialisation (sse init for details)
+ CSphstable_cones(std::vector<CSphmomentum> &_particle_list);
+
+ /// default dtor
+ ~CSphstable_cones();
+
+ /**
+ * initialisation
+ * \param _particle_list list of particles
+ */
+ void init(std::vector<CSphmomentum> &_particle_list);
+
+ /**
+ * compute stable cones.
+ * This function really does the job i.e. computes
+ * the list of stable cones (in a seedless way)
+ * \param _radius radius of the cones
+ * \return The number of stable cones found is returned
+ */
+ int get_stable_cones(double _radius);
+
+ /// list of stable cones
+ std::vector<CSphmomentum> protocones;
+
+ /// list of candidates
+ sph_hash_cones *hc;
+
+ /// total number of tested cones
+ int nb_tot;
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones, nb_hash_occupied;
+#endif
+
+ protected:
+ /// cone radius
+ double R;
+
+ /// cone radius SQUARED
+ double R2;
+
+ /// squared tangent of the cone radius
+ double tan2R;
+
+ private:
+ /// cone with a given particle as parent
+ /// this reduction to a single vector assumes we trust the checksums
+ CSphmomentum cone;
+
+ /// child particle, taken in the 'vicinity' list
+ CSphmomentum *child;
+
+ /// centre of the tested cone
+ CSphvicinity_elm *centre;
+
+ /// index in the particle list;
+ unsigned int centre_idx;
+
+ /// first cone used in the vicinity list
+ unsigned int first_cone;
+
+ /**
+ * initialise the cone.
+ * We take the first particle in the angular ordering to compute this one
+ * \return 0 on success, 1 on error
+ */
+ int init_cone();
+
+ /**
+ * test cones.
+ * We check if the cone(s) build with the present parent and child
+ * are stable
+ * \return 0 on success 1 on error
+ */
+ int test_cone();
+
+ /**
+ * update the cone
+ * go to the next child for that parent and update 'cone' appropriately
+ * \return 0 if update candidate found, 1 otherwise
+ */
+ int update_cone();
+
+ /*
+ * run through the vicinity of the current parent and for each child
+ * indicate which members are cocircular...
+ */
+ void prepare_cocircular_lists();
+
+ /**
+ * check if we are in a situation of cocircularity.
+ * if it is the case, update and test in the corresponding way
+ * \return 'false' if no cocircularity detected, 'true' otherwise
+ * Note that if cocircularity is detected, we need to
+ * recall 'update' from 'update' !!!
+ */
+ bool cocircular_check();
+
+ /**
+ * Routine for testing cocircular configurations in p^3 time,
+ * rather than 2^p time;
+ */
+ void test_cone_cocircular(CSphmomentum & borderless_cone,
+ std::list<CSphmomentum *> & border_list);
+
+ /**
+ * carry out the computations needed for the stability check of the
+ * candidate, using the border_vect to indicate which particles
+ * should / should not be in the stable cone; if the cone is stable
+ * insert it into the hash.
+ */
+ void test_stability(CSphmomentum & candidate,
+ const std::vector<CSphborder_store> & border_vect);
+
+ /**
+ * compute the cone contents by going once around the full set of
+ * circles and tracking the entry/exit status each time -- this sets
+ * up the inclusion information, which can then be directly used to
+ * calculate the cone momentum.
+ */
+ void compute_cone_contents();
+
+ /**
+ * compute the cone momentum from particle list.
+ * in this version, we use the 'pincluded' information
+ * from the CSphvicinity class
+ */
+ void recompute_cone_contents();
+
+ /*
+ * if we have gone beyond the acceptable threshold of change, compute
+ * the cone momentum from particle list. in this version, we use the
+ * 'pincluded' information from the CSphvicinity class, but we don't
+ * change the member cone, only the locally supplied one
+ */
+ void recompute_cone_contents_if_needed(CSphmomentum & this_cone, double & this_dpt);
+
+ /**
+ * compute stability of all enumerated candidates.
+ * For all candidate cones which are stable w.r.t. their border particles,
+ * pass the last test: stability with quadtree intersection
+ */
+ int proceed_with_stability();
+
+ /*
+ * circle intersection.
+ * computes the intersection with a circle of given centre and radius.
+ * The output takes the form of a checkxor of the intersection's particles
+ * - cx circle centre x coordinate
+ * - cy circle centre y coordinate
+ * return the checkxor for the intersection
+ ******************************************************************/
+ siscone::Creference circle_intersect(CSph3vector &cone_centre);
+
+ /// present candidate cone
+ CSphmomentum cone_candidate;
+
+ /// in case of co-circular points, vector for them
+ std::vector<CSphmomentum*> child_list;
+
+ /// list of cocircular enclusures already studied
+ /// first element if cone contents, second is cone border
+ std::vector< std::pair<siscone::Creference,siscone::Creference> > multiple_centre_done;
+
+ // information for updating cone contents to avoid rounding errors
+ double dpt; ///< sums of Delta P_t
+};
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: siscone.h //
+// Description: header file for the main SISCone class //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 261 $//
+// $Date:: 2008-07-23 17:54:30 +0200 (Wed, 23 Jul 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_SISCONE_H__
+#define __SPH_SISCONE_H__
+
+#include "protocones.h"
+#include "split_merge.h"
+
+namespace siscone_spherical{
+
+/**
+ * \class CSphsiscone
+ * final class: gather everything to compute the jet contents.
+ *
+ * This is the class user should use.
+ * It computes the jet contents of a list of particles
+ * given a cone radius and a threshold for splitting/merging.
+ *
+ * After the call to 'perform', the vector jets is filled with
+ * the jets found. the 'contents' field of each jets contains
+ * the indices of the particles included in that jet.
+ */
+class CSphsiscone : public CSphstable_cones, public CSphsplit_merge{
+ public:
+ /// default ctor
+ CSphsiscone();
+
+ /// default dtor
+ ~CSphsiscone();
+
+ /**
+ * compute the jets from a given particle set.
+ * We are doing multiple passes such pass n_pass looks for jets among
+ * all particles not put into jets during previous passes.
+ * By default the number of passes is infinite (0).
+ * \param _particles list of particles
+ * \param _radius cone radius
+ * \param _f shared energy threshold for splitting&merging
+ * \param _n_pass_max maximum number of passes (0=full search)
+ * \param _Emin minimum energy of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * NOTE: SM_Etilde
+ * is always IR safe
+ * SM_E
+ * is IR unsafe for events with mom. conservation
+ *
+ * \return the number of jets found.
+ */
+ int compute_jets(std::vector<CSphmomentum> &_particles, double _radius, double _f,
+ int _n_pass_max=0, double _Emin=0.0,
+ Esplit_merge_scale _split_merge_scale=SM_Etilde);
+
+ /**
+ * recompute the jets with a different overlap parameter.
+ * we use the same particles and R as in the preceeding call.
+ * \param _f shared energy threshold for splitting&merging
+ * \param _Emin minimum energy of the protojets
+ * \param _split_merge_scale the scale choice for the split-merge procedure
+ * split--merge variable
+ * NOTE: using pt leads to IR unsafety for some events with momentum
+ * conservation. So we strongly advise not to change the default
+ * value.
+ * \return the number of jets found, -1 if recomputation not allowed.
+ */
+ int recompute_jets(double _f, double _Emin = 0.0,
+ Esplit_merge_scale _split_merge_scale=SM_Etilde);
+
+ /// list of protocones found pass-by-pass
+ std::vector<std::vector<CSphmomentum> > protocones_list;
+
+ // random number initialisation
+ static bool init_done; ///< check random generator initialisation
+
+#ifdef DEBUG_STABLE_CONES
+ int nb_hash_cones_total, nb_hash_occupied_total;
+#endif
+
+ private:
+ bool rerun_allowed; ///< is recompute_jets allowed ?
+};
+
+
+// finally, a bunch of functions to access to
+// basic information (package name, version)
+//---------------------------------------------
+
+/**
+ * return SISCone package name.
+ * This is nothing but "SISCone", it is a replacement to the
+ * PACKAGE_NAME string defined in config.h and which is not
+ * public by default.
+ * \return the SISCone name as a string
+ */
+std::string siscone_package_name();
+
+/**
+ * return SISCone version number.
+ * \return a string of the form "X.Y.Z" with possible additional tag
+ * (alpha, beta, devel) to mention stability status
+ */
+std::string siscone_version();
+
+}
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.h //
+// Description: header file for splitting/merging (contains the CJet class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_SPLIT_MERGE_H__
+#define __SPH_SPLIT_MERGE_H__
+
+#include <siscone/defines.h>
+#include "geom_2d.h"
+#include "momentum.h"
+#include <stdio.h>
+#include <vector>
+#include <set>
+#include <memory>
+#include <string>
+
+namespace siscone_spherical{
+
+/**
+ * \class CSphjet
+ * real Jet information.
+ *
+ * This class contains information for one single jet.
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents
+ */
+class CSphjet{
+ public:
+ /// default ctor
+ CSphjet();
+
+ /// default dtor
+ ~CSphjet();
+
+ CSphmomentum v; ///< jet momentum
+ double E_tilde; ///< sum of E_i [1+sin^2(theta_iJ)]
+ int n; ///< number of particles inside
+ std::vector<int> contents; ///< particle contents (list of indices)
+
+ /// ordering variable used for ordering and overlap in the
+ /// split--merge. This variable is automatically set either to
+ /// E_tilde or E depending on the siscone parameter.
+ ///
+ /// Note that the default behaviour is E_tilde and that other
+ /// choices may lead to infrared unsafe situations.
+ ///
+ /// Note: we use the square of the varible rather than the variable
+ /// itself
+ ///
+ /// Note 2: for the overlap computation, we shall use the jet energy!
+ double sm_var2;
+
+ /// covered range in eta-phi
+ CSphtheta_phi_range range;
+
+ /// pass at which the jet has been found
+ /// It starts at 0 (first pass), -1 means infinite rapidity
+ int pass;
+};
+
+/// ordering of jets in pt
+///bool jets_pt_less(const CSphjet &j1, const CSphjet &j2);
+
+/// ordering of jets in energy (e.g. used in final jets ordering)
+bool jets_E_less(const CSphjet &j1, const CSphjet &j2);
+
+
+/// the choices of scale variable that can be used in the split-merge
+/// step, both for ordering the protojets and for measuing their
+/// overlap; E is defined in E-scheme (4-momentum) recombination;
+/// Etilde = \sum_{i\in jet} E_i [1+sin^2(theta_{i,jet})]
+///
+/// NB: if one changes the order here, one _MUST_ also change the order
+/// in the SISCone plugin
+enum Esplit_merge_scale {
+ SM_E, ///< Energy (IR unsafe with momentum conservation)
+ SM_Etilde ///< sum_{i \in jet} E_i [1+sin^2(theta_iJ)]
+};
+
+/// return the name of the split-merge scale choice
+std::string split_merge_scale_name(Esplit_merge_scale sms);
+
+/**
+ * \class CSphsplit_merge_ptcomparison
+ * a class that allows us to carry out comparisons of pt of jets, using
+ * information from exact particle contents where necessary.
+ */
+class CSphsplit_merge_ptcomparison{
+public:
+ /// default ctor
+ CSphsplit_merge_ptcomparison() :
+ particles(0), split_merge_scale(SM_Etilde){};
+
+ /// return the name corresponding to the SM scale variable
+ std::string SM_scale_name() const {
+ return split_merge_scale_name(split_merge_scale);}
+
+ std::vector<CSphmomentum> * particles; ///< pointer to the list of particles
+ std::vector<double> * particles_norm2; ///< pointer to the particles's norm^2
+
+ /// comparison of 2 CSphjet
+ bool operator()(const CSphjet &jet1, const CSphjet &jet2) const;
+
+ /**
+ * get the difference between 2 jets, calculated such that rounding
+ * errors will not affect the result even if the two jets have
+ * almost the same content (so that the difference is below the
+ * rounding errors)
+ *
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v jet1-jet2
+ * \param E_tilde jet1-jet2 E_tilde
+ */
+ void get_difference(const CSphjet &j1, const CSphjet &j2, CSphmomentum *v, double *E_tilde) const;
+
+ /// the following parameter controls the variable we're using for
+ /// the split-merge process i.e. the variable we use for
+ /// 1. ordering jet candidates;
+ /// 2. computing the overlap fraction of two candidates.
+ /// The default value uses Etilde. The other alternative is E
+ /// NOTE: Modifying the default choice can have nasty effects:
+ /// - using E is IR-safe for QCD jets but the IR unsafety remains
+ /// for back-to-back jets of unstable narrow-width particles
+ /// (e.g. Higgs).
+ /// Therefore, keeping the default value is strongly advised.
+ Esplit_merge_scale split_merge_scale;
+};
+
+
+// iterator types
+/// iterator definition for the jet candidates structure
+typedef std::multiset<siscone_spherical::CSphjet,CSphsplit_merge_ptcomparison>::iterator cjet_iterator;
+
+/// iterator definition for the jet structure
+typedef std::vector<siscone_spherical::CSphjet>::iterator jet_iterator;
+
+
+
+/**
+ * \class CSphsplit_merge
+ * Class used to split and merge jets.
+ */
+class CSphsplit_merge{
+ public:
+ /// default ctor
+ CSphsplit_merge();
+
+ /// default dtor
+ ~CSphsplit_merge();
+
+
+ //////////////////////////////
+ // initialisation functions //
+ //////////////////////////////
+
+ /**
+ * initialisation function
+ * \param _particles list of particles
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param Emin minimal energy allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int init(std::vector<CSphmomentum> &_particles, std::vector<CSphmomentum> *protocones, double R2, double Emin=0.0);
+
+ /**
+ * initialisation function for particle list
+ * \param _particles list of particles
+ * \return 0 on success, 1 on error
+ */
+ int init_particles(std::vector<CSphmomentum> &_particles);
+
+ /**
+ * build initial list of left particles
+ */
+ int init_pleft();
+
+ /**
+ * use an energy-dependent boundary for splitting
+ * When called with true, the criterium for splitting two protojets
+ * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted
+ * distance instead of the plain distance D1^2 vs. D2^2.
+ * This can be set in order to produce more circular hard jets,
+ * with the same underlying philosophy as for the anti-kt algorithm.
+ * We thus expect a behaviour closer to the IterativeCone one.
+ * By default, we use the standard D1^2 vs. D2^2 comparison and this
+ * function is not called.
+ */
+ inline int set_E_weighted_splitting(bool _use_E_weighted_splitting){
+ use_E_weighted_splitting = _use_E_weighted_splitting;
+ return 0;
+ }
+
+ ////////////////////////
+ // cleaning functions //
+ ////////////////////////
+
+ /// partial clearance
+ int partial_clear();
+
+ /// full clearance
+ int full_clear();
+
+
+ /////////////////////////////////
+ // main parts of the algorithm //
+ /////////////////////////////////
+
+ /**
+ * build the list 'p_uncol_hard' from p_remain by clustering
+ * collinear particles
+ * note that thins in only used for stable-cone detection
+ * so the parent_index field is unnecessary
+ *
+ * Note that soft particles are not removed here
+ * This is just a remnant from the trunk version
+ */
+ int merge_collinear_and_remove_soft();
+
+ /**
+ * add a list of protocones
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param Emin minimal emergy allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int add_protocones(std::vector<CSphmomentum> *protocones, double R2, double Emin=0.0);
+
+ /**
+ * really do the splitting and merging
+ * At the end, the vector jets is filled with the jets found.
+ * the 'contents' field of each jets contains the indices
+ * of the particles included in that jet.
+ * \param overlap_tshold threshold for splitting/merging transition
+ * \param Emin minimal energy allowed for jets
+ * \return the number of jets is returned
+ */
+ int perform(double overlap_tshold, double Emin=0.0);
+
+
+ //////////////////////////////
+ // save and debug functions //
+ //////////////////////////////
+
+ /// save final jets
+ /// \param flux stream to save the jet contentss
+ int save_contents(FILE *flux);
+
+ /// show jets/candidates status
+ int show();
+
+ // particle information
+ int n; ///< number of particles
+ std::vector<CSphmomentum> particles; ///< list of particles
+ std::vector<double> particles_norm2; ///< norm^2 of the particle (3-vect part)
+ int n_left; ///< numer of particles that does not belong to any jet
+ std::vector<CSphmomentum> p_remain; ///< list of particles remaining to deal with
+ std::vector<CSphmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
+ int n_pass; ///< index of the run
+
+ /// minimal difference in squared distance between a particle and
+ /// two overlapping protojets when doing a split (useful when
+ /// testing approx. collinear safety)
+ double most_ambiguous_split;
+
+ // jets information
+ std::vector<CSphjet> jets; ///< list of jets
+
+ // working entries
+ int *indices; ///< maximal size array for indices works
+ int idx_size; ///< number of elements in indices1
+
+ /// The following flag indicates that identical protocones
+ /// are to be merged automatically each time around the split-merge
+ /// loop and before anything else happens.
+ ///
+ /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// is set in 'defines.h'
+ /// Note that this lead to infrared-unsafety so it is disabled
+ /// by default
+ bool merge_identical_protocones;
+
+ /// member used for detailed comparisons of pt's
+ CSphsplit_merge_ptcomparison ptcomparison;
+
+ /// stop split--merge when the SM_var of the hardest protojet
+ /// is below this cut-off.
+ /// This is not collinear-safe so you should not use this
+ /// variable unless you really know what you are doing
+ /// Note that the cut-off is set on the variable squared.
+ double SM_var2_hardest_cut_off;
+
+ /// Energy cutoff for the particles to put in p_uncol_hard
+ /// this is meant to allow removing soft particles in the
+ /// stable-cone search.
+ double stable_cone_soft_E2_cutoff;
+
+ private:
+ /**
+ * get the overlap between 2 jets
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v returned overlap^2 (determined by the choice of SM variable)
+ * \return true if overlapping, false if disjoint
+ */
+ bool get_overlap(const CSphjet &j1, const CSphjet &j2, double *v);
+
+
+ /**
+ * split the two given jets.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 2 new jets. Common particles are associted to the
+ * closest initial jet.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \param j1 first jet (CSphjet instance)
+ * \param j2 second jet (CSphjet instance)
+ * \return true on success, false on error
+ */
+ bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * merge the two given jet.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 1 single jets containing both of them.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \return true on success, false on error
+ */
+ bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * Check whether or not a jet has to be inserted in the
+ * list of protojets. If it has, set its sm_variable and
+ * insert it to the list of protojets.
+ * \param jet jet to insert
+ */
+ bool insert(CSphjet &jet);
+
+ /**
+ * given a 4-momentum and its associated pT, return the
+ * variable tht has to be used for SM
+ * \param v 4 momentum of the protojet
+ * \param E_tilde E_tilde of the protojet
+ */
+ double get_sm_var2(CSphmomentum &v, double &E_tilde);
+
+ /// compute Etilde for a given jet
+ void compute_Etilde(CSphjet &j);
+
+ // jet information
+ /// list of jet candidates
+ std::auto_ptr<std::multiset<CSphjet,CSphsplit_merge_ptcomparison> > candidates;
+
+ /// minimal E
+ double E_min;
+
+ /**
+ * do we have or not to use the energy-weighted splitting
+ * (see description for set_E_weighted_splitting)
+ * This will be false by default
+ */
+ bool use_E_weighted_splitting;
+
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// checkxor for the candidates (to avoid having twice the same contents)
+ std::set<siscone::Creference> cand_refs;
+#endif
+};
+
+}
+
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.h //
+// Description: header file for particle vicinity (Cvicinity class) //
+// This file is part of the SISCone project. //
+// WARNING: this is not the main SISCone trunk but //
+// an adaptation to spherical coordinates //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006-2008 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 255 $//
+// $Date:: 2008-07-12 17:40:35 +0200 (Sat, 12 Jul 2008) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPH_VICINITY_H__
+#define __SPH_VICINITY_H__
+
+#include <siscone/vicinity.h>
+#include <vector>
+#include <list>
+#include "momentum.h"
+#include <siscone/defines.h>
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+#include <siscone/quadtree.h>
+#endif
+
+namespace siscone_spherical{
+
+
+/**
+ * \class CSphvicinity_elm
+ * \brief element in the vicinity of a parent.
+ *
+ * class used to manage one points in the vicinity
+ * of a parent point.
+ */
+class CSphvicinity_elm{
+ public:
+ /// pointer to the second borderline particle
+ CSphmomentum *v;
+
+ /// variable to tell if the particle is inside or outside the cone
+ siscone::Cvicinity_inclusion *is_inside;
+
+ // centre variables
+ CSph3vector centre; ///< direction of the centre
+ double angle; ///< angle with parent
+ bool side; ///< true if angle on the positive side, false otherwise
+ double cocircular_range; ///< amount by which the angle can be varied while
+ ///< maintaining this point within co-circularity margin
+
+ /// list of elements co-circular with this one
+ /// NB: empty list uses less mem than vector
+ std::list<CSphvicinity_elm * > cocircular;
+};
+
+/// ordering pointers to CSphvicinity_elm
+bool ve_less(CSphvicinity_elm *ve1, CSphvicinity_elm *ve2);
+
+
+/**
+ * \class CSphvicinity
+ * \brief list of element in the vicinity of a parent.
+ *
+ * class used to manage the points which are in the vicinity
+ * of a parent point.
+ */
+class CSphvicinity{
+ public:
+ /// default constructor
+ CSphvicinity();
+
+ /// constructor with initialisation (see set_particle_list)
+ CSphvicinity(std::vector<CSphmomentum> &_particle_list);
+
+ /// default destructor
+ ~CSphvicinity();
+
+ /**
+ * set the particle_list
+ * \param _particle_list list of particles (type CSphmomentum)
+ */
+ void set_particle_list(std::vector<CSphmomentum> &_particle_list);
+
+ /**
+ * build the vicinity list from the list of points.
+ * \param _parent reference particle
+ * \param _VR vicinity radius
+ */
+ void build(CSphmomentum *_parent, double _VR);
+
+ // cone kinematical information
+ CSphmomentum *parent; ///< parent vector
+ double VR; ///< radius of the vicinity
+ double VR2; ///< squared radius of the vicinity
+ double cosVR; ///< cosine of the radius of the vicinity
+ double R; ///< normal radius
+ double R2; ///< squared normal radius
+ double tan2R; ///< squared tangent of the normal radius
+ double D2_R; ///< euclidian distance (squared) corresp. to the arc R
+ double inv_R_EPS_COCIRC; ///< R / EPSILON_COCIRCULAR
+ double inv_R_2EPS_COCIRC; ///< R / (2*EPSILON_COCIRCULAR)
+
+ // particle list information
+ int n_part; ///< number of particles
+ std::vector<CSphmomentum> plist; ///< the list of particles
+ /// the inclusion state of particles
+ std::vector<siscone::Cvicinity_inclusion> pincluded;
+ CSphvicinity_elm *ve_list; ///< list of vicinity elements built from particle list (size=2*n)
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ siscone::Cquadtree *quadtree; ///< quadtree used for final stability tests
+#endif
+
+ // vicinity information
+ std::vector<CSphvicinity_elm*> vicinity; ///< list of points in parent's vicinity
+ unsigned int vicinity_size; ///< number of elements in vicinity
+
+ protected:
+ /**
+ * append a particle to the 'vicinity' list after
+ * having tested it and computed the angular-ordering quantities
+ * \param v vector to test
+ */
+ void append_to_vicinity(CSphmomentum *v);
+
+ // internal variables
+ CSph3vector parent_centre; ///< parent centre
+ CSph3vector angular_dir1; ///< main direction to measure angles
+ CSph3vector angular_dir2; ///< second direction to measure angles (sign)
+};
+
+}
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: split_merge.h //
+// Description: header file for splitting/merging (contains the CJet class) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 268 $//
+// $Date:: 2009-03-12 21:24:16 +0100 (Thu, 12 Mar 2009) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SPLIT_MERGE_H__
+#define __SPLIT_MERGE_H__
+
+#include "defines.h"
+#include "geom_2d.h"
+#include "momentum.h"
+#include <stdio.h>
+#include <vector>
+#include <set>
+#include <memory>
+#include <string>
+
+namespace siscone{
+
+/**
+ * \class Cjet
+ * real Jet information.
+ *
+ * This class contains information for one single jet.
+ * That is, first, its momentum carrying information
+ * about its centre and pT, and second, its particle
+ * contents
+ */
+class Cjet{
+ public:
+ /// default ctor
+ Cjet();
+
+ /// default dtor
+ ~Cjet();
+
+ Cmomentum v; ///< jet momentum
+ double pt_tilde; ///< p-scheme pt
+ int n; ///< number of particles inside
+ std::vector<int> contents; ///< particle contents (list of indices)
+
+ /// ordering variable used for ordering and overlap in the
+ /// split--merge. This variable is automatically set either to
+ /// pt_tilde, or to mt or to pt, depending on the siscone
+ /// parameter. Note that the default behaviour is pt_tilde and that
+ /// other chices may lead to infrared unsafe situations.
+ /// Note: we use the square of the varible rather than the variable itself
+ double sm_var2;
+
+ /// covered range in eta-phi
+ Ceta_phi_range range;
+
+ /// pass at which the jet has been found
+ /// It starts at 0 (first pass), -1 means infinite rapidity
+ int pass;
+};
+
+/// ordering of jets in pt (e.g. used in final jets ordering)
+bool jets_pt_less(const Cjet &j1, const Cjet &j2);
+
+
+/// the choices of scale variable that can be used in the split-merge
+/// step, both for ordering the protojets and for measuing their
+/// overlap; pt, Et and mt=sqrt(pt^2+m^2) are all defined in E-scheme
+/// (4-momentum) recombination; pttilde = \sum_{i\in jet} |p_{t,i}|
+///
+/// NB: if one changes the order here, one _MUST_ also change the order
+/// in the SISCone plugin
+enum Esplit_merge_scale {
+ SM_pt, ///< transverse momentum (E-scheme), IR unsafe
+ SM_Et, ///< transverse energy (E-scheme), not long. boost inv.
+ ///< original run-II choice [may not be implemented]
+ SM_mt, ///< transverse mass (E-scheme), IR safe except
+ ///< in decays of two identical narrow heavy particles
+ SM_pttilde ///< pt-scheme pt = \sum_{i in jet} |p_{ti}|, should
+ ///< be IR safe in all cases
+};
+
+/// return the name of the split-merge scale choice
+std::string split_merge_scale_name(Esplit_merge_scale sms);
+
+/**
+ * \class Csplit_merge_ptcomparison
+ * comparison of jets for split--merge ordering
+ *
+ * a class that allows us to carry out comparisons of pt of jets, using
+ * information from exact particle contents where necessary.
+ */
+class Csplit_merge_ptcomparison{
+public:
+ /// default ctor
+ Csplit_merge_ptcomparison() :
+ particles(0), split_merge_scale(SM_pttilde){};
+
+ /// return the name corresponding to the SM scale variable
+ std::string SM_scale_name() const {
+ return split_merge_scale_name(split_merge_scale);}
+
+ std::vector<Cmomentum> * particles; ///< pointer to the list of particles
+ std::vector<double> * pt; ///< pointer to the pt of the particles
+
+ /// comparison between 2 jets
+ bool operator()(const Cjet &jet1, const Cjet &jet2) const;
+
+ /**
+ * get the difference between 2 jets, calculated such that rounding
+ * errors will not affect the result even if the two jets have
+ * almost the same content (so that the difference is below the
+ * rounding errors)
+ *
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v jet1-jet2
+ * \param pt_tilde jet1-jet2 pt_tilde
+ */
+ void get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const;
+
+ /// the following parameter controls the variable we're using for
+ /// the split-merge process i.e. the variable we use for
+ /// 1. ordering jet candidates;
+ /// 2. computing te overlap fraction of two candidates.
+ /// The default value uses pttile (p-scheme pt). Other alternatives are
+ /// pt, mt=sqrt(pt^2+m^2)=sqrt(E^2-pz^2) or Et.
+ /// NOTE: Modifying the default choice can have nasty effects:
+ /// - using pt leads to some IR unsafety when we have two jets,
+ /// e.g. back-to-back, with the same pt. In that case, their ordering
+ /// in pt is random and can be affected by the addition of a
+ /// soft particle. Hence, we highly recommand to keep this to
+ /// the default value i.e. to use pt only for the purpose of
+ /// investigating the IR issue
+ /// - using Et is safe but do not respect boost invariance
+ /// - using mt solves the IR unsafety issues with the pt variable
+ /// for QCD jets but the IR unsafety remains for nack-to-back
+ /// jets of unstable narrow-width particles (e.g. Higgs).
+ /// Therefore, keeping the default value is strongly advised.
+ Esplit_merge_scale split_merge_scale;
+};
+
+
+// iterator types
+/// iterator definition for the jet candidates structure
+typedef std::multiset<siscone::Cjet,Csplit_merge_ptcomparison>::iterator cjet_iterator;
+
+/// iterator definition for the jet structure
+typedef std::vector<siscone::Cjet>::iterator jet_iterator;
+
+
+
+/**
+ * \class Csplit_merge
+ * Class used to split and merge jets.
+ */
+class Csplit_merge{
+ public:
+ /// default ctor
+ Csplit_merge();
+
+ /// default dtor
+ ~Csplit_merge();
+
+
+ //////////////////////////////
+ // initialisation functions //
+ //////////////////////////////
+
+ /**
+ * initialisation function
+ * \param _particles list of particles
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param ptmin minimal pT allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int init(std::vector<Cmomentum> &_particles, std::vector<Cmomentum> *protocones, double R2, double ptmin=0.0);
+
+ /**
+ * initialisation function for particle list
+ * \param _particles list of particles
+ * \return 0 on success, 1 on error
+ */
+ int init_particles(std::vector<Cmomentum> &_particles);
+
+ /**
+ * build initial list of left particles
+ */
+ int init_pleft();
+
+ /**
+ * use a pt-dependent boundary for splitting
+ * When called with true, the criterium for splitting two protojets
+ * will be to compare D1^2/kt1^2 vs. D2^2/kt2^2, the (anti-)kt-weighted
+ * distance instead of the plain distance D1^2 vs. D2^2.
+ * This can be set in order to produce more circular hard jets,
+ * with the same underlying philosophy as for the anti-kt algorithm.
+ * We thus expect a behaviour closer to the IterativeCone one.
+ * By default, we use the standard D1^2 vs. D2^2 comparison and this
+ * function is not called.
+ */
+ inline int set_pt_weighted_splitting(bool _use_pt_weighted_splitting){
+ use_pt_weighted_splitting = _use_pt_weighted_splitting;
+ return 0;
+ }
+
+ ////////////////////////
+ // cleaning functions //
+ ////////////////////////
+
+ /// partial clearance
+ int partial_clear();
+
+ /// full clearance
+ int full_clear();
+
+
+ /////////////////////////////////
+ // main parts of the algorithm //
+ /////////////////////////////////
+
+ /**
+ * build the list 'p_uncol_hard' from p_remain by clustering
+ * collinear particles and removing particles softer than
+ * stable_cone_soft_pt2_cutoff
+ * note that thins in only used for stable-cone detection
+ * so the parent_index field is unnecessary
+ */
+ int merge_collinear_and_remove_soft();
+
+ /**
+ * add a list of protocones
+ * \param protocones list of protocones (initial jet candidates)
+ * \param R2 cone radius (squared)
+ * \param ptmin minimal pT allowed for jets
+ * \return 0 on success, 1 on error
+ */
+ int add_protocones(std::vector<Cmomentum> *protocones, double R2, double ptmin=0.0);
+
+ /**
+ * really do the splitting and merging
+ * At the end, the vector jets is filled with the jets found.
+ * the 'contents' field of each jets contains the indices
+ * of the particles included in that jet.
+ * \param overlap_tshold threshold for splitting/merging transition
+ * \param ptmin minimal pT allowed for jets
+ * \return the number of jets is returned
+ */
+ int perform(double overlap_tshold, double ptmin=0.0);
+
+
+ //////////////////////////////
+ // save and debug functions //
+ //////////////////////////////
+
+ /// save final jets
+ /// \param flux stream to save the jet contentss
+ int save_contents(FILE *flux);
+
+ /// show jets/candidates status
+ int show();
+
+ // particle information
+ int n; ///< number of particles
+ std::vector<Cmomentum> particles; ///< list of particles
+ std::vector<double> pt; ///< list of particles' pt
+ int n_left; ///< numer of particles that does not belong to any jet
+ std::vector<Cmomentum> p_remain; ///< list of particles remaining to deal with
+ std::vector<Cmomentum> p_uncol_hard; ///< list of particles remaining with collinear clustering
+ int n_pass; ///< index of the run
+
+ /// minimal difference in squared distance between a particle and
+ /// two overlapping protojets when doing a split (useful when
+ /// testing approx. collinear safety)
+ double most_ambiguous_split;
+
+ // jets information
+ std::vector<Cjet> jets; ///< list of jets
+
+ // working entries
+ int *indices; ///< maximal size array for indices works
+ int idx_size; ///< number of elements in indices1
+
+ /// The following flag indicates that identical protocones
+ /// are to be merged automatically each time around the split-merge
+ /// loop and before anything else happens.
+ ///
+ /// This flag is only effective if ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// is set in 'defines.h'
+ /// Note that this lead to infrared-unsafety so it is disabled
+ /// by default
+ bool merge_identical_protocones;
+
+ /// member used for detailed comparisons of pt's
+ Csplit_merge_ptcomparison ptcomparison;
+
+ /// stop split--merge when the SM_var of the hardest protojet
+ /// is below this cut-off.
+ /// This is not collinear-safe so you should not use this
+ /// variable unless you really know what you are doing
+ /// Note that the cut-off is set on the variable squared.
+ double SM_var2_hardest_cut_off;
+
+ /// pt cutoff for the particles to put in p_uncol_hard
+ /// this is meant to allow removing soft particles in the
+ /// stable-cone search.
+ double stable_cone_soft_pt2_cutoff;
+
+ private:
+ /**
+ * get the overlap between 2 jets
+ * \param j1 first jet
+ * \param j2 second jet
+ * \param v returned overlap^2 (determined by the choice of SM variable)
+ * \return true if overlapping, false if disjoint
+ */
+ bool get_overlap(const Cjet &j1, const Cjet &j2, double *v);
+
+
+ /**
+ * split the two given jets.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 2 new jets. Common particles are associted to the
+ * closest initial jet.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \param j1 first jet (Cjet instance)
+ * \param j2 second jet (Cjet instance)
+ * \return true on success, false on error
+ */
+ bool split(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * merge the two given jet.
+ * during this procedure, the jets j1 & j2 are replaced
+ * by 1 single jets containing both of them.
+ * \param it_j1 iterator of the first jet in 'candidates'
+ * \param it_j2 iterator of the second jet in 'candidates'
+ * \return true on success, false on error
+ */
+ bool merge(cjet_iterator &it_j1, cjet_iterator &it_j2);
+
+ /**
+ * Check whether or not a jet has to be inserted in the
+ * list of protojets. If it has, set its sm_variable and
+ * insert it to the list of protojets.
+ * \param jet jet to insert
+ */
+ bool insert(Cjet &jet);
+
+ /**
+ * given a 4-momentum and its associated pT, return the
+ * variable tht has to be used for SM
+ * \param v 4 momentum of the protojet
+ * \param pt_tilde pt_tilde of the protojet
+ */
+ double get_sm_var2(Cmomentum &v, double &pt_tilde);
+
+ // jet information
+ /// list of jet candidates
+ std::auto_ptr<std::multiset<Cjet,Csplit_merge_ptcomparison> > candidates;
+
+ /// minimal pt2
+ double pt_min2;
+
+ /**
+ * do we have or not to use the pt-weighted splitting
+ * (see description for set_pt_weighted_splitting)
+ * This will be false by default
+ */
+ bool use_pt_weighted_splitting;
+
+#ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
+ /// checkxor for the candidates (to avoid having twice the same contents)
+ std::set<Creference> cand_refs;
+#endif
+};
+
+}
+
+
+#endif
--- /dev/null
+// -*- C++ -*-
+///////////////////////////////////////////////////////////////////////////////
+// File: vicinity.h //
+// Description: header file for particle vicinity (Cvicinity class) //
+// This file is part of the SISCone project. //
+// For more details, see http://projects.hepforge.org/siscone //
+// //
+// Copyright (c) 2006 Gavin Salam and Gregory Soyez //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program; if not, write to the Free Software //
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
+// //
+// $Revision:: 123 $//
+// $Date:: 2007-03-01 02:52:16 +0100 (Thu, 01 Mar 2007) $//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef __VICINITY_H__
+#define __VICINITY_H__
+
+#include <vector>
+#include <list>
+#include "momentum.h"
+#include "defines.h"
+#include "quadtree.h"
+
+namespace siscone{
+
+
+
+/**
+ * \class Cvicinity_inclusion
+ * \brief a class to keep track of inclusion status in cone and in cocircular region
+ * while using minimal resources
+ */
+class Cvicinity_inclusion {
+public:
+ /// default ctor
+ Cvicinity_inclusion() : cone(false), cocirc(false) {}
+
+ bool cone; ///< flag for particle inclusion in the cone
+ bool cocirc; ///< flag for particle inclusion in the border
+};
+
+
+/**
+ * \class Cvicinity_elm
+ * \brief element in the vicinity of a parent.
+ *
+ * class used to manage one points in the vicinity
+ * of a parent point.
+ */
+class Cvicinity_elm{
+ public:
+ /// pointer to the second borderline particle
+ Cmomentum *v;
+
+ /// variable to tell if the particle is inside or outside the cone
+ Cvicinity_inclusion *is_inside;
+
+ // centre variables
+ double eta; ///< eta coordinate of the center
+ double phi; ///< phi coordinate of the center
+ double angle; ///< angle with parent
+ bool side; ///< true if angle on the positive side, false otherwise
+ double cocircular_range; ///< amount by which the angle can be varied while
+ ///< maintaining this point within co-circularity margin
+
+ /// list of elements co-circular with this one
+ /// NB: empty list uses less mem than vector
+ std::list<Cvicinity_elm * > cocircular;
+};
+
+/// ordering pointers to Cvicinity_elm
+bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2);
+
+
+/**
+ * \class Cvicinity
+ * \brief list of element in the vicinity of a parent.
+ *
+ * class used to manage the points which are in the vicinity
+ * of a parent point.
+ */
+class Cvicinity{
+ public:
+ /// default constructor
+ Cvicinity();
+
+ /// constructor with initialisation (see set_particle_list)
+ Cvicinity(std::vector<Cmomentum> &_particle_list);
+
+ /// default destructor
+ ~Cvicinity();
+
+ /**
+ * set the particle_list
+ * \param _particle_list list of particles (type Cmomentum)
+ */
+ void set_particle_list(std::vector<Cmomentum> &_particle_list);
+
+ /**
+ * build the vicinity list from the list of points.
+ * \param _parent reference particle
+ * \param _VR vicinity radius
+ */
+ void build(Cmomentum *_parent, double _VR);
+
+ // cone kinematical information
+ Cmomentum *parent; ///< parent vector
+ double VR; ///< radius of the vicinity
+ double VR2; ///< squared radius of the vicinity
+ double R; ///< normal radius
+ double R2; ///< squared normal radius
+ double inv_R_EPS_COCIRC; ///< R / EPSILON_COCIRCULAR
+ double inv_R_2EPS_COCIRC; ///< R / (2*EPSILON_COCIRCULAR)
+
+ // particle list information
+ int n_part; ///< number of particles
+ std::vector<Cmomentum> plist; ///< the list of particles
+ std::vector<Cvicinity_inclusion> pincluded; ///< the inclusion state of particles
+ Cvicinity_elm *ve_list; ///< list of vicinity elements built from particle list (size=2*n)
+#ifdef USE_QUADTREE_FOR_STABILITY_TEST
+ Cquadtree *quadtree; ///< quadtree used for final stability tests
+#endif
+
+ // vicinity information
+ std::vector<Cvicinity_elm*> vicinity; ///< list of points in parent's vicinity
+ unsigned int vicinity_size; ///< number of elements in vicinity
+
+ protected:
+ /**
+ * append a particle to the 'vicinity' list after
+ * having tested it and computed the angular-ordering quantities
+ * \param v vector to test
+ */
+ void append_to_vicinity(Cmomentum *v);
+
+ // internal variables
+ double pcx; ///< parent centre (eta)
+ double pcy; ///< parent centre (phi)
+};
+
+}
+
+#endif