Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:13

0001 #ifndef __FASTJET_CONTRIB_ENERGYCORRELATOR_HH__
0002 #define __FASTJET_CONTRIB_ENERGYCORRELATOR_HH__
0003 
0004 //  EnergyCorrelator Package
0005 //  Questions/Comments?  Email the authors.
0006 //    larkoski@mit.edu, lnecib@mit.edu,
0007 //    gavin.salam@cern.ch jthaler@jthaler.net
0008 //
0009 //  Copyright (c) 2013-2016
0010 //  Andrew Larkoski, Lina Necib Gavin Salam, and Jesse Thaler
0011 //
0012 //  $Id: EnergyCorrelator.hh 1098 2018-01-07 20:17:52Z linoush $
0013 //----------------------------------------------------------------------
0014 // This file is part of FastJet contrib.
0015 //
0016 // It is free software; you can redistribute it and/or modify it under
0017 // the terms of the GNU General Public License as published by the
0018 // Free Software Foundation; either version 2 of the License, or (at
0019 // your option) any later version.
0020 //
0021 // It is distributed in the hope that it will be useful, but WITHOUT
0022 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0023 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
0024 // License for more details.
0025 //
0026 // You should have received a copy of the GNU General Public License
0027 // along with this code. If not, see <http://www.gnu.org/licenses/>.
0028 //----------------------------------------------------------------------
0029 
0030 #include <fastjet/internal/base.hh>
0031 #include "fastjet/FunctionOfPseudoJet.hh"
0032 
0033 #include <string>
0034 #include <climits>
0035 
0036 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0037 
0038 namespace contrib{
0039 
0040 /// \mainpage EnergyCorrelator contrib
0041 ///
0042 /// The EnergyCorrelator contrib provides an implementation of energy
0043 /// correlators and their ratios as described in arXiv:1305.0007 by
0044 /// Larkoski, Salam and Thaler.  Additionally, the ratio observable
0045 /// D2 described in arXiv:1409.6298 by Larkoski, Moult and Neill
0046 /// is also included in this contrib. Finally, a generalized version of
0047 /// the energy correlation functions is added, defined in
0048 /// arXiv:1609.07483 by Moult, Necib and Thaler, which allow the
0049 /// definition of the M series, N series, and U series observables.
0050 /// There is also a generalized version of D2.
0051 ///
0052 ///
0053 /// <p>There are 4 main classes:
0054 ///
0055 /// - EnergyCorrelator
0056 /// - EnergyCorrelatorRatio
0057 /// - EnergyCorrelatorDoubleRatio
0058 /// - EnergyCorrelatorGeneralized
0059 ///
0060 /// <p>There are five classes that define useful combinations of the ECFs.
0061 ///
0062 /// - EnergyCorrelatorNseries
0063 /// - EnergyCorrelatorMseries
0064 /// - EnergyCorrelatorUseries
0065 /// - EnergyCorrelatorD2
0066 /// - EnergyCorrelatorGeneralizedD2
0067 ///
0068 /// <p> There are also aliases for easier access:
0069 /// - EnergyCorrelatorCseries (same as EnergyCorrelatorDoubleRatio)
0070 /// - EnergyCorrelatorC1      (EnergyCorrelatorCseries with i=1)
0071 /// - EnergyCorrelatorC2      (EnergyCorrelatorCseries with i=2)
0072 /// - EnergyCorrelatorN2      (EnergyCorrelatorNseries with i=2)
0073 /// - EnergyCorrelatorN3      (EnergyCorrelatorNseries with i=3)
0074 /// - EnergyCorrelatorM2      (EnergyCorrelatorMseries with i=2)
0075 /// - EnergyCorrelatorU1      (EnergyCorrelatorUseries with i=1)
0076 /// - EnergyCorrelatorU2      (EnergyCorrelatorUseries with i=2)
0077 /// - EnergyCorrelatorU3      (EnergyCorrelatorUseries with i=3)
0078 ///
0079 /// Each of these classes is a FastJet FunctionOfPseudoJet.
0080 /// EnergyCorrelatorDoubleRatio (which is equivalent to EnergyCorrelatorCseries)
0081 /// is in particular is useful for quark/gluon discrimination and boosted
0082 /// object tagging.
0083 ///
0084 /// Using the original 2- and 3-point correlators, EnergyCorrelationD2 has
0085 /// been shown to be the optimal combination for boosted 2-prong tagging.
0086 ///
0087 /// The EnergyCorrelatorNseries and EnergyCorrelatorMseries use
0088 /// generalized correlation functions with different angular scaling,
0089 /// and are intended for use on 2-prong and 3-prong jets.
0090 /// The EnergyCorrelatorUseries is useful for quark/gluon discrimimation.
0091 ///
0092 /// See the file example.cc for an illustration of usage and
0093 /// example_basic_usage.cc for the most commonly used functions.
0094 
0095 //------------------------------------------------------------------------
0096 /// \class EnergyCorrelator
0097 /// ECF(N,beta) is the N-point energy correlation function, with an angular exponent beta.
0098 ///
0099 /// It is defined as follows
0100 ///
0101 ///  - \f$ \mathrm{ECF}(1,\beta)  = \sum_i E_i \f$
0102 ///  - \f$ \mathrm{ECF}(2,\beta)  = \sum_{i<j} E_i E_j \theta_{ij}^\beta \f$
0103 ///  - \f$ \mathrm{ECF}(3,\beta)  = \sum_{i<j<k} E_i E_j E_k (\theta_{ij} \theta_{ik} \theta_{jk})^\beta \f$
0104 ///  - \f$ \mathrm{ECF}(4,\beta)  = \sum_{i<j<k<l} E_i E_j E_k E_l (\theta_{ij}  \theta_{ik} \theta_{il} \theta_{jk} \theta_{jl} \theta_{kl})^\beta \f$
0105 ///  - ...
0106 ///
0107 /// The correlation can be determined with energies and angles (as
0108 /// given above) or with transverse momenta and boost invariant angles
0109 /// (the code's default). The choice is controlled by
0110 /// EnergyCorrelator::Measure provided in the constructor.
0111 ///
0112 /// The current implementation handles values of N up to and including 5.
0113 /// Run times scale as n^N/N!, where n is the number of particles in a jet.
0114 
0115     class EnergyCorrelator : public FunctionOfPseudoJet<double> {
0116         friend class EnergyCorrelatorGeneralized;  ///< This allow ECFG to access the energy and angle definitions
0117                                                   ///< of this class, which are otherwise private.
0118     public:
0119 
0120         enum Measure {
0121             pt_R,     ///< use transverse momenta and boost-invariant angles,
0122             ///< eg \f$\mathrm{ECF}(2,\beta) = \sum_{i<j} p_{ti} p_{tj} \Delta R_{ij}^{\beta} \f$
0123             E_theta,   ///  use energies and angles,
0124             ///  eg \f$\mathrm{ECF}(2,\beta) = \sum_{i<j} E_{i} E_{j}   \theta_{ij}^{\beta} \f$
0125             E_inv     ///  use energies and invariant mass,
0126             ///  eg \f$\mathrm{ECF}(2,\beta) = \sum_{i<j} E_{i} E_{j}   (\frac{2 p_{i} \cdot p_{j}}{E_{i} E_{j}})^{\beta/2} \f$
0127         };
0128 
0129         enum Strategy {
0130             slow,          ///< interparticle angles are not cached.
0131             ///< For N>=3 this leads to many expensive recomputations,
0132             ///< but has only O(n) memory usage for n particles
0133 
0134             storage_array  /// the interparticle angles are cached. This gives a significant speed
0135             /// improvement for N>=3, but has a memory requirement of (4n^2) bytes.
0136         };
0137 
0138     public:
0139 
0140         /// constructs an N-point correlator with angular exponent beta,
0141         /// using the specified choice of energy and angular measure as well
0142         /// one of two possible underlying computational Strategy
0143         EnergyCorrelator(unsigned int N,
0144                          double beta,
0145                          Measure measure = pt_R,
0146                          Strategy strategy = storage_array) :
0147                 _N(N), _beta(beta), _measure(measure), _strategy(strategy) {};
0148 
0149         /// destructor
0150         virtual ~EnergyCorrelator(){}
0151 
0152         /// returns the value of the energy correlator for a jet's
0153         /// constituents. (Normally accessed by the parent class's
0154         /// operator()).
0155         double result(const PseudoJet& jet) const;
0156 
0157         std::string description() const;
0158 
0159         /// returns the the part of the description related to the parameters
0160         std::string description_parameters() const;
0161         std::string description_no_N() const;
0162 
0163     private:
0164 
0165         unsigned int _N;
0166         double _beta;
0167         Measure _measure;
0168         Strategy _strategy;
0169 
0170         double energy(const PseudoJet& jet) const;
0171         double angleSquared(const PseudoJet& jet1, const PseudoJet& jet2) const;
0172         double multiply_angles(double angles[], int n_angles, unsigned int N_total) const;
0173         void precompute_energies_and_angles(std::vector<fastjet::PseudoJet> const &particles, double* energyStore, double** angleStore) const;
0174         double evaluate_n3(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0175         double evaluate_n4(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0176         double evaluate_n5(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0177     };
0178 
0179 // core EnergyCorrelator::result code in .cc file.
0180 
0181 
0182 //------------------------------------------------------------------------
0183 /// \class EnergyCorrelatorRatio
0184 /// A class to calculate the ratio of (N+1)-point to N-point energy correlators,
0185 ///     ECF(N+1,beta)/ECF(N,beta),
0186 /// called \f$ r_N^{(\beta)} \f$ in the publication.
0187     class EnergyCorrelatorRatio : public FunctionOfPseudoJet<double> {
0188 
0189     public:
0190 
0191         /// constructs an (N+1)-point to N-point correlator ratio with
0192         /// angular exponent beta, using the specified choice of energy and
0193         /// angular measure as well one of two possible underlying
0194         /// computational strategies
0195         EnergyCorrelatorRatio(unsigned int N,
0196                               double  beta,
0197                               EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0198                               EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0199                 : _N(N), _beta(beta), _measure(measure), _strategy(strategy) {};
0200 
0201         virtual ~EnergyCorrelatorRatio() {}
0202 
0203         /// returns the value of the energy correlator ratio for a jet's
0204         /// constituents. (Normally accessed by the parent class's
0205         /// operator()).
0206         double result(const PseudoJet& jet) const;
0207 
0208         std::string description() const;
0209 
0210     private:
0211 
0212         unsigned int _N;
0213         double _beta;
0214 
0215         EnergyCorrelator::Measure _measure;
0216         EnergyCorrelator::Strategy _strategy;
0217 
0218 
0219     };
0220 
0221     inline double EnergyCorrelatorRatio::result(const PseudoJet& jet) const {
0222 
0223         double numerator = EnergyCorrelator(_N + 1, _beta, _measure, _strategy).result(jet);
0224         double denominator = EnergyCorrelator(_N, _beta, _measure, _strategy).result(jet);
0225 
0226         return numerator/denominator;
0227 
0228     }
0229 
0230 
0231 //------------------------------------------------------------------------
0232 /// \class EnergyCorrelatorDoubleRatio
0233 /// Calculates the double ratio of energy correlators, ECF(N-1,beta)*ECF(N+1)/ECF(N,beta)^2.
0234 ///
0235 /// A class to calculate a double ratio of energy correlators,
0236 ///     ECF(N-1,beta)*ECF(N+1,beta)/ECF(N,beta)^2,
0237 /// called \f$C_N^{(\beta)}\f$ in the publication, and equal to
0238 /// \f$ r_N^{(\beta)}/r_{N-1}^{(\beta)} \f$.
0239 ///
0240 
0241     class EnergyCorrelatorDoubleRatio : public FunctionOfPseudoJet<double> {
0242 
0243     public:
0244 
0245         EnergyCorrelatorDoubleRatio(unsigned int N,
0246                                     double beta,
0247                                     EnergyCorrelator::Measure measure = EnergyCorrelator::pt_R,
0248                                     EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0249                 : _N(N), _beta(beta), _measure(measure), _strategy(strategy) {
0250                 
0251                     if (_N < 1) throw Error("EnergyCorrelatorDoubleRatio:  N must be 1 or greater.");
0252                     
0253                 };
0254 
0255         virtual ~EnergyCorrelatorDoubleRatio() {}
0256 
0257 
0258         /// returns the value of the energy correlator double-ratio for a
0259         /// jet's constituents. (Normally accessed by the parent class's
0260         /// operator()).
0261         double result(const PseudoJet& jet) const;
0262 
0263         std::string description() const;
0264 
0265     private:
0266 
0267         unsigned int _N;
0268         double _beta;
0269         EnergyCorrelator::Measure _measure;
0270         EnergyCorrelator::Strategy _strategy;
0271 
0272 
0273     };
0274 
0275 
0276     inline double EnergyCorrelatorDoubleRatio::result(const PseudoJet& jet) const {
0277         
0278         double numerator = EnergyCorrelator(_N - 1, _beta, _measure, _strategy).result(jet) * EnergyCorrelator(_N + 1, _beta, _measure, _strategy).result(jet);
0279         double denominator = pow(EnergyCorrelator(_N, _beta, _measure, _strategy).result(jet), 2.0);
0280 
0281         return numerator/denominator;
0282 
0283     }
0284 
0285 //------------------------------------------------------------------------
0286 /// \class EnergyCorrelatorC1
0287 /// A class to calculate the normalized 2-point energy correlators,
0288 ///     ECF(2,beta)/ECF(1,beta)^2,
0289 /// called \f$ C_1^{(\beta)} \f$ in the publication.
0290     class EnergyCorrelatorC1 : public FunctionOfPseudoJet<double> {
0291 
0292     public:
0293 
0294         /// constructs a 2-point correlator ratio with
0295         /// angular exponent beta, using the specified choice of energy and
0296         /// angular measure as well one of two possible underlying
0297         /// computational strategies
0298         EnergyCorrelatorC1(double  beta,
0299                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0300                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0301                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0302 
0303         virtual ~EnergyCorrelatorC1() {}
0304 
0305         /// returns the value of the energy correlator ratio for a jet's
0306         /// constituents. (Normally accessed by the parent class's
0307         /// operator()).
0308         double result(const PseudoJet& jet) const;
0309 
0310         std::string description() const;
0311 
0312     private:
0313 
0314         double _beta;
0315 
0316         EnergyCorrelator::Measure _measure;
0317         EnergyCorrelator::Strategy _strategy;
0318 
0319 
0320     };
0321 
0322 
0323     inline double EnergyCorrelatorC1::result(const PseudoJet& jet) const {
0324 
0325         double numerator = EnergyCorrelator(2, _beta, _measure, _strategy).result(jet);
0326         double denominator = EnergyCorrelator(1, _beta, _measure, _strategy).result(jet);
0327 
0328         return numerator/denominator/denominator;
0329 
0330     }
0331 
0332 
0333 //------------------------------------------------------------------------
0334 /// \class EnergyCorrelatorC2
0335 /// A class to calculate the double ratio of 3-point to 2-point
0336 /// energy correlators,
0337 ///     ECF(3,beta)*ECF(1,beta)/ECF(2,beta)^2,
0338 /// called \f$ C_2^{(\beta)} \f$ in the publication.
0339     class EnergyCorrelatorC2 : public FunctionOfPseudoJet<double> {
0340 
0341     public:
0342 
0343         /// constructs a 3-point to 2-point correlator double ratio with
0344         /// angular exponent beta, using the specified choice of energy and
0345         /// angular measure as well one of two possible underlying
0346         /// computational strategies
0347         EnergyCorrelatorC2(double  beta,
0348                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0349                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0350                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0351 
0352         virtual ~EnergyCorrelatorC2() {}
0353 
0354         /// returns the value of the energy correlator ratio for a jet's
0355         /// constituents. (Normally accessed by the parent class's
0356         /// operator()).
0357         double result(const PseudoJet& jet) const;
0358 
0359         std::string description() const;
0360 
0361     private:
0362 
0363         double _beta;
0364 
0365         EnergyCorrelator::Measure _measure;
0366         EnergyCorrelator::Strategy _strategy;
0367 
0368 
0369     };
0370 
0371 
0372     inline double EnergyCorrelatorC2::result(const PseudoJet& jet) const {
0373 
0374         double numerator3 = EnergyCorrelator(3, _beta, _measure, _strategy).result(jet);
0375         double numerator1 = EnergyCorrelator(1, _beta, _measure, _strategy).result(jet);
0376         double denominator = EnergyCorrelator(2, _beta, _measure, _strategy).result(jet);
0377 
0378         return numerator3*numerator1/denominator/denominator;
0379 
0380     }
0381 
0382 
0383 //------------------------------------------------------------------------
0384 /// \class EnergyCorrelatorD2
0385 /// A class to calculate the observable formed from the ratio of the
0386 /// 3-point and 2-point energy correlators,
0387 ///     ECF(3,beta)*ECF(1,beta)^3/ECF(2,beta)^3,
0388 /// called \f$ D_2^{(\beta)} \f$ in the publication.
0389     class EnergyCorrelatorD2 : public FunctionOfPseudoJet<double> {
0390 
0391     public:
0392 
0393         /// constructs an 3-point to 2-point correlator ratio with
0394         /// angular exponent beta, using the specified choice of energy and
0395         /// angular measure as well one of two possible underlying
0396         /// computational strategies
0397         EnergyCorrelatorD2(double  beta,
0398                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0399                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0400                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0401 
0402         virtual ~EnergyCorrelatorD2() {}
0403 
0404         /// returns the value of the energy correlator ratio for a jet's
0405         /// constituents. (Normally accessed by the parent class's
0406         /// operator()).
0407         double result(const PseudoJet& jet) const;
0408 
0409         std::string description() const;
0410 
0411     private:
0412 
0413         double _beta;
0414 
0415         EnergyCorrelator::Measure _measure;
0416         EnergyCorrelator::Strategy _strategy;
0417 
0418 
0419     };
0420 
0421 
0422     inline double EnergyCorrelatorD2::result(const PseudoJet& jet) const {
0423 
0424         double numerator3 = EnergyCorrelator(3, _beta, _measure, _strategy).result(jet);
0425         double numerator1 = EnergyCorrelator(1, _beta, _measure, _strategy).result(jet);
0426         double denominator2 = EnergyCorrelator(2, _beta, _measure, _strategy).result(jet);
0427 
0428         return numerator3*numerator1*numerator1*numerator1/denominator2/denominator2/denominator2;
0429 
0430     }
0431 
0432 
0433 //------------------------------------------------------------------------
0434 /// \class EnergyCorrelatorGeneralized
0435 /// A generalized and normalized version of the N-point energy correlators, with
0436 /// angular exponent beta and v number of pairwise angles.  When \f$v = {N \choose 2}\f$
0437 /// (or, for convenience, \f$v = -1\f$), EnergyCorrelatorGeneralized just gives normalized
0438 /// versions of EnergyCorrelator:
0439 ///  - \f$ \mathrm{ECFG}(-1,1,\beta) = \mathrm{ECFN}(N,\beta) = \mathrm{ECF}(N,\beta)/\mathrm{ECF}(1,\beta)\f$
0440 ///
0441 /// Note that there is no separate class that implements ECFN, though it is a
0442 /// notation that we will use in this documentation.  Examples of the low-point normalized
0443 /// correlators are:
0444 ///  - \f$\mathrm{ECFN}(1,\beta)  = 1\f$
0445 ///  - \f$\mathrm{ECFN}(2,\beta)  = \sum_{i<j} z_i z_j \theta_{ij}^\beta \f$
0446 ///  - \f$\mathrm{ECFN}(3,\beta)  = \sum_{i<j<k} z_i z_j z_k (\theta_{ij} \theta_{ik} \theta_{jk})^\beta \f$
0447 ///  - \f$\mathrm{ECFN}(4,\beta)  = \sum_{i<j<k<l} z_i z_j z_k z_l (\theta_{ij}  \theta_{ik} \theta_{il} \theta_{jk} \theta_{jl} \theta_{kl})^\beta \f$
0448 ///  - ...
0449 /// where the \f$z_i\f$'s are the energy fractions.
0450 ///
0451 /// When a new value of v is given, the generalized energy correlators are defined as
0452 ///  - \f$\mathrm{ECFG}(0,1,\beta)  = 1\f$
0453 ///  - \f$\mathrm{ECFG}(1,2,\beta)  = \sum_{i<j} z_i z_j \theta_{ij}^\beta \f$
0454 ///  - \f$\mathrm{ECFG}(v,3,\beta)  = \sum_{i<j<k} z_i z_j z_k \prod_{m = 1}^{v} \min^{(m)} \{ \theta_{ij}, \theta_{jk}, \theta_{ki} \}^\beta \f$
0455 ///  - \f$\mathrm{ECFG}(v,4,\beta)  = \sum_{i<j<k<l} z_i z_j z_k z_l \prod_{m = 1}^{v} \min^{(m)} \{ \theta_{ij}, \theta_{ik}, \theta_{il}, \theta_{jk}, \theta_{jl}, \theta_{kl} \}^\beta \f$
0456 ///  - \f$\mathrm{ECFG}(v,n,\beta)  = \sum_{i_1 < i_2 < \dots < i_n} z_{i_1} z_{i_2} \dots z_{i_n} \prod_{m = 1}^{v} \min^{(m)}_{s < t \in \{i_1, i_2 , \dots, i_n \}} \{ \theta_{st}^{\beta} \}\f$,
0457 ///
0458 /// where \f$\min^{(m)}\f$ means the m-th smallest element of the list.
0459 ///
0460 /// The correlation can be determined with energies and angles (as
0461 /// given above) or with transverse momenta and boost invariant angles
0462 /// (the code's default). The choice is controlled by
0463 /// EnergyCorrelator::Measure provided in the constructor.
0464 ///
0465 /// The current implementation handles values of N up to and including 5.
0466 ///
0467     class EnergyCorrelatorGeneralized : public FunctionOfPseudoJet<double> {
0468     public:
0469 
0470         /// constructs an N-point correlator with v_angles pairwise angles
0471         /// and angular exponent beta,
0472         /// using the specified choice of energy and angular measure as well
0473         /// one of two possible underlying computational Strategy
0474         EnergyCorrelatorGeneralized(int v_angles,
0475                                     unsigned int N,
0476                                     double beta,
0477                                     EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0478                                     EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0479                 :  _angles(v_angles), _N(N), _beta(beta), _measure(measure), _strategy(strategy),  _helper_correlator(1,_beta, _measure, _strategy) {};
0480 
0481         /// destructor
0482         virtual ~EnergyCorrelatorGeneralized(){}
0483 
0484         /// returns the value of the normalized energy correlator for a jet's
0485         /// constituents. (Normally accessed by the parent class's
0486         /// operator()).
0487 
0488         double result(const PseudoJet& jet) const;
0489         std::vector<double> result_all_angles(const PseudoJet& jet) const;
0490 
0491     private:
0492 
0493         int _angles;
0494         unsigned int _N;
0495         double _beta;
0496         EnergyCorrelator::Measure _measure;
0497         EnergyCorrelator::Strategy _strategy;
0498         EnergyCorrelator _helper_correlator;
0499 
0500         double energy(const PseudoJet& jet) const;
0501         double angleSquared(const PseudoJet& jet1, const PseudoJet& jet2) const;
0502         double multiply_angles(double angles[], int n_angles, unsigned int N_total) const;
0503         void precompute_energies_and_angles(std::vector<fastjet::PseudoJet> const &particles, double* energyStore, double** angleStore) const;
0504         double evaluate_n3(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0505         double evaluate_n4(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0506         double evaluate_n5(unsigned int nC, unsigned int n_angles, double* energyStore, double** angleStore) const;
0507     };
0508 
0509 
0510 
0511 //------------------------------------------------------------------------
0512 /// \class EnergyCorrelatorGeneralizedD2
0513 /// A class to calculate the observable formed from the ratio of the
0514 /// 3-point and 2-point energy correlators,
0515 ///     ECFN(3,alpha)/ECFN(2,beta)^3 alpha/beta,
0516 /// called \f$ D_2^{(\alpha, \beta)} \f$ in the publication.
0517     class EnergyCorrelatorGeneralizedD2 : public FunctionOfPseudoJet<double> {
0518 
0519     public:
0520 
0521         /// constructs an 3-point to 2-point correlator ratio with
0522         /// angular exponent beta, using the specified choice of energy and
0523         /// angular measure as well one of two possible underlying
0524         /// computational strategies
0525         EnergyCorrelatorGeneralizedD2(
0526                 double alpha,
0527                 double  beta,
0528                 EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0529                 EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0530                 : _alpha(alpha), _beta(beta), _measure(measure), _strategy(strategy) {};
0531 
0532         virtual ~EnergyCorrelatorGeneralizedD2() {}
0533 
0534         /// returns the value of the energy correlator ratio for a jet's
0535         /// constituents. (Normally accessed by the parent class's
0536         /// operator()).
0537         double result(const PseudoJet& jet) const;
0538 
0539         std::string description() const;
0540 
0541     private:
0542 
0543         double _alpha;
0544         double _beta;
0545 
0546         EnergyCorrelator::Measure _measure;
0547         EnergyCorrelator::Strategy _strategy;
0548 
0549 
0550     };
0551 
0552 
0553     inline double EnergyCorrelatorGeneralizedD2::result(const PseudoJet& jet) const {
0554 
0555         double numerator = EnergyCorrelatorGeneralized(-1, 3, _alpha, _measure, _strategy).result(jet);
0556         double denominator = EnergyCorrelatorGeneralized(-1, 2, _beta, _measure, _strategy).result(jet);
0557 
0558         return numerator/pow(denominator, 3.0*_alpha/_beta);
0559 
0560     }
0561 
0562 
0563 //------------------------------------------------------------------------
0564 /// \class EnergyCorrelatorNseries
0565 /// A class to calculate the observable formed from the ratio of the
0566 /// 3-point and 2-point energy correlators,
0567 ///     N_n = ECFG(2,n+1,beta)/ECFG(1,n,beta)^2,
0568 /// called \f$ N_i^{(\alpha, \beta)} \f$ in the publication.
0569 /// By definition, N_1^{beta} = ECFG(1, 2, 2*beta), where the angular exponent
0570 /// is twice as big since the N series should involve two pairwise angles.
0571     class EnergyCorrelatorNseries : public FunctionOfPseudoJet<double> {
0572 
0573     public:
0574 
0575         /// constructs a n 3-point to 2-point correlator ratio with
0576         /// angular exponent beta, using the specified choice of energy and
0577         /// angular measure as well one of two possible underlying
0578         /// computational strategies
0579         EnergyCorrelatorNseries(
0580                 unsigned int n,
0581                 double  beta,
0582                 EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0583                 EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0584                 : _n(n), _beta(beta), _measure(measure), _strategy(strategy) {
0585                 
0586                     if (_n < 1) throw Error("EnergyCorrelatorNseries:  n must be 1 or greater.");
0587                 
0588                 };
0589 
0590         virtual ~EnergyCorrelatorNseries() {}
0591 
0592         /// returns the value of the energy correlator ratio for a jet's
0593         /// constituents. (Normally accessed by the parent class's
0594         /// operator()).
0595         double result(const PseudoJet& jet) const;
0596 
0597         std::string description() const;
0598 
0599     private:
0600 
0601         unsigned int _n;
0602         double _beta;
0603         EnergyCorrelator::Measure _measure;
0604         EnergyCorrelator::Strategy _strategy;
0605 
0606     };
0607 
0608 
0609     inline double EnergyCorrelatorNseries::result(const PseudoJet& jet) const {
0610       
0611         if (_n == 1) return EnergyCorrelatorGeneralized(1, 2, 2*_beta, _measure, _strategy).result(jet);
0612         // By definition, N1 = ECFN(2, 2 beta)
0613         double numerator = EnergyCorrelatorGeneralized(2, _n + 1, _beta, _measure, _strategy).result(jet);
0614         double denominator = EnergyCorrelatorGeneralized(1, _n, _beta, _measure, _strategy).result(jet);
0615 
0616         return numerator/denominator/denominator;
0617 
0618     }
0619 
0620 
0621 
0622 //------------------------------------------------------------------------
0623 /// \class EnergyCorrelatorN2
0624 /// A class to calculate the observable formed from the ratio of the
0625 /// 3-point and 2-point energy correlators,
0626 ///     ECFG(2,3,beta)/ECFG(1,2,beta)^2,
0627 /// called \f$ N_2^{(\beta)} \f$ in the publication.
0628     class EnergyCorrelatorN2 : public FunctionOfPseudoJet<double> {
0629 
0630     public:
0631 
0632         /// constructs an 3-point to 2-point correlator ratio with
0633         /// angular exponent beta, using the specified choice of energy and
0634         /// angular measure as well one of two possible underlying
0635         /// computational strategies
0636         EnergyCorrelatorN2(double  beta,
0637                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0638                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0639                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0640 
0641         virtual ~EnergyCorrelatorN2() {}
0642 
0643         /// returns the value of the energy correlator ratio for a jet's
0644         /// constituents. (Normally accessed by the parent class's
0645         /// operator()).
0646         double result(const PseudoJet& jet) const;
0647 
0648         std::string description() const;
0649 
0650     private:
0651 
0652         double _beta;
0653 
0654         EnergyCorrelator::Measure _measure;
0655         EnergyCorrelator::Strategy _strategy;
0656 
0657 
0658     };
0659 
0660 
0661     inline double EnergyCorrelatorN2::result(const PseudoJet& jet) const {
0662 
0663         double numerator = EnergyCorrelatorGeneralized(2, 3, _beta, _measure, _strategy).result(jet);
0664         double denominator = EnergyCorrelatorGeneralized(1, 2, _beta, _measure, _strategy).result(jet);
0665 
0666         return numerator/denominator/denominator;
0667 
0668     }
0669 
0670 
0671 //------------------------------------------------------------------------
0672 /// \class EnergyCorrelatorN3
0673 /// A class to calculate the observable formed from the ratio of the
0674 /// 3-point and 2-point energy correlators,
0675 ///     ECFG(2,4,beta)/ECFG(1,3,beta)^2,
0676 /// called \f$ N_3^{(\beta)} \f$ in the publication.
0677     class EnergyCorrelatorN3 : public FunctionOfPseudoJet<double> {
0678 
0679     public:
0680 
0681         /// constructs an 3-point to 2-point correlator ratio with
0682         /// angular exponent beta, using the specified choice of energy and
0683         /// angular measure as well one of two possible underlying
0684         /// computational strategies
0685         EnergyCorrelatorN3(double  beta,
0686                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0687                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0688                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0689 
0690         virtual ~EnergyCorrelatorN3() {}
0691 
0692         /// returns the value of the energy correlator ratio for a jet's
0693         /// constituents. (Normally accessed by the parent class's
0694         /// operator()).
0695         double result(const PseudoJet& jet) const;
0696 
0697         std::string description() const;
0698 
0699     private:
0700 
0701         double _beta;
0702 
0703         EnergyCorrelator::Measure _measure;
0704         EnergyCorrelator::Strategy _strategy;
0705 
0706 
0707     };
0708 
0709 
0710     inline double EnergyCorrelatorN3::result(const PseudoJet& jet) const {
0711 
0712         double numerator = EnergyCorrelatorGeneralized(2, 4, _beta, _measure, _strategy).result(jet);
0713         double denominator = EnergyCorrelatorGeneralized(1, 3, _beta, _measure, _strategy).result(jet);
0714 
0715         return numerator/denominator/denominator;
0716 
0717     }
0718 
0719 
0720 //------------------------------------------------------------------------
0721 /// \class EnergyCorrelatorMseries
0722 /// A class to calculate the observable formed from the ratio of the
0723 /// 3-point and 2-point energy correlators,
0724 ///     M_n = ECFG(1,n+1,beta)/ECFG(1,n,beta),
0725 /// called \f$ M_i^{(\alpha, \beta)} \f$ in the publication.
0726 /// By definition, M_1^{beta} = ECFG(1,2,beta)
0727     class EnergyCorrelatorMseries : public FunctionOfPseudoJet<double> {
0728 
0729     public:
0730 
0731         /// constructs a n 3-point to 2-point correlator ratio with
0732         /// angular exponent beta, using the specified choice of energy and
0733         /// angular measure as well one of two possible underlying
0734         /// computational strategies
0735         EnergyCorrelatorMseries(
0736                 unsigned int n,
0737                 double  beta,
0738                 EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0739                 EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0740                 : _n(n), _beta(beta), _measure(measure), _strategy(strategy) {
0741                 
0742                     if (_n < 1) throw Error("EnergyCorrelatorMseries:  n must be 1 or greater.");
0743                     
0744                 };
0745 
0746         virtual ~EnergyCorrelatorMseries() {}
0747 
0748         /// returns the value of the energy correlator ratio for a jet's
0749         /// constituents. (Normally accessed by the parent class's
0750         /// operator()).
0751         double result(const PseudoJet& jet) const;
0752 
0753         std::string description() const;
0754 
0755     private:
0756 
0757         unsigned int _n;
0758         double _beta;
0759         EnergyCorrelator::Measure _measure;
0760         EnergyCorrelator::Strategy _strategy;
0761 
0762     };
0763 
0764 
0765     inline double EnergyCorrelatorMseries::result(const PseudoJet& jet) const {
0766 
0767         if (_n == 1) return EnergyCorrelatorGeneralized(1, 2, _beta, _measure, _strategy).result(jet);
0768 
0769         double numerator = EnergyCorrelatorGeneralized(1, _n + 1, _beta, _measure, _strategy).result(jet);
0770         double denominator = EnergyCorrelatorGeneralized(1, _n, _beta, _measure, _strategy).result(jet);
0771 
0772         return numerator/denominator;
0773 
0774     }
0775 
0776 //------------------------------------------------------------------------
0777 /// \class EnergyCorrelatorM2
0778 /// A class to calculate the observable formed from the ratio of the
0779 /// 3-point and 2-point energy correlators,
0780 ///     ECFG(1,3,beta)/ECFG(1,2,beta),
0781 /// called \f$ M_2^{(\beta)} \f$ in the publication.
0782     class EnergyCorrelatorM2 : public FunctionOfPseudoJet<double> {
0783 
0784     public:
0785 
0786         /// constructs an 3-point to 2-point correlator ratio with
0787         /// angular exponent beta, using the specified choice of energy and
0788         /// angular measure as well one of two possible underlying
0789         /// computational strategies
0790         EnergyCorrelatorM2(double  beta,
0791                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0792                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0793                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0794 
0795         virtual ~EnergyCorrelatorM2() {}
0796 
0797         /// returns the value of the energy correlator ratio for a jet's
0798         /// constituents. (Normally accessed by the parent class's
0799         /// operator()).
0800         double result(const PseudoJet& jet) const;
0801 
0802         std::string description() const;
0803 
0804     private:
0805 
0806         double _beta;
0807 
0808         EnergyCorrelator::Measure _measure;
0809         EnergyCorrelator::Strategy _strategy;
0810 
0811 
0812     };
0813 
0814 
0815     inline double EnergyCorrelatorM2::result(const PseudoJet& jet) const {
0816 
0817         double numerator = EnergyCorrelatorGeneralized(1, 3, _beta, _measure, _strategy).result(jet);
0818         double denominator = EnergyCorrelatorGeneralized(1, 2, _beta, _measure, _strategy).result(jet);
0819 
0820         return numerator/denominator;
0821 
0822     }
0823 
0824 
0825 //------------------------------------------------------------------------
0826 /// \class EnergyCorrelatorCseries
0827 /// Calculates the C series energy correlators, ECFN(N-1,beta)*ECFN(N+1,beta)/ECFN(N,beta)^2.
0828 /// This is equivalent to EnergyCorrelatorDoubleRatio
0829 ///
0830 /// A class to calculate a double ratio of energy correlators,
0831 ///     ECFN(N-1,beta)*ECFN(N+1,beta)/ECFN(N,beta)^2,
0832 /// called \f$C_N^{(\beta)}\f$ in the publication, and equal to
0833 /// \f$ r_N^{(\beta)}/r_{N-1}^{(\beta)} \f$.
0834 ///
0835 
0836     class EnergyCorrelatorCseries : public FunctionOfPseudoJet<double> {
0837 
0838     public:
0839 
0840         EnergyCorrelatorCseries(unsigned int N,
0841                                     double beta,
0842                                     EnergyCorrelator::Measure measure = EnergyCorrelator::pt_R,
0843                                     EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0844                 : _N(N), _beta(beta), _measure(measure), _strategy(strategy) {
0845                 
0846                     if (_N < 1) throw Error("EnergyCorrelatorCseries:  N must be 1 or greater.");
0847                 
0848                 };
0849 
0850         virtual ~EnergyCorrelatorCseries() {}
0851 
0852 
0853         /// returns the value of the energy correlator double-ratio for a
0854         /// jet's constituents. (Normally accessed by the parent class's
0855         /// operator()).
0856         double result(const PseudoJet& jet) const;
0857 
0858         std::string description() const;
0859 
0860     private:
0861 
0862         unsigned int _N;
0863         double _beta;
0864         EnergyCorrelator::Measure _measure;
0865         EnergyCorrelator::Strategy _strategy;
0866 
0867 
0868     };
0869 
0870 
0871     inline double EnergyCorrelatorCseries::result(const PseudoJet& jet) const {
0872       
0873         double numerator = EnergyCorrelatorGeneralized(-1, _N - 1, _beta, _measure, _strategy).result(jet) * EnergyCorrelatorGeneralized(-1, _N + 1, _beta, _measure, _strategy).result(jet);
0874         double denominator = pow(EnergyCorrelatorGeneralized(-1, _N, _beta, _measure, _strategy).result(jet), 2.0);
0875 
0876         return numerator/denominator;
0877 
0878     }
0879 
0880 //------------------------------------------------------------------------
0881 /// \class EnergyCorrelatorUseries
0882 /// A class to calculate the observable used for quark versus gluon discrimination
0883 ///     U_n = ECFG(1,n+1,beta),
0884 /// called \f$ U_i^{(\beta)} \f$ in the publication.
0885 
0886     class EnergyCorrelatorUseries : public FunctionOfPseudoJet<double> {
0887 
0888     public:
0889 
0890         /// constructs a n 3-point to 2-point correlator ratio with
0891         /// angular exponent beta, using the specified choice of energy and
0892         /// angular measure as well one of two possible underlying
0893         /// computational strategies
0894         EnergyCorrelatorUseries(
0895                 unsigned int n,
0896                 double  beta,
0897                 EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0898                 EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0899                 : _n(n), _beta(beta), _measure(measure), _strategy(strategy) {
0900                 
0901                     if (_n < 1) throw Error("EnergyCorrelatorUseries:  n must be 1 or greater.");
0902                     
0903                 };
0904 
0905         virtual ~EnergyCorrelatorUseries() {}
0906 
0907         /// returns the value of the energy correlator ratio for a jet's
0908         /// constituents. (Normally accessed by the parent class's
0909         /// operator()).
0910         double result(const PseudoJet& jet) const;
0911 
0912         std::string description() const;
0913 
0914     private:
0915 
0916         unsigned int _n;
0917         double _beta;
0918         EnergyCorrelator::Measure _measure;
0919         EnergyCorrelator::Strategy _strategy;
0920 
0921     };
0922 
0923 
0924     inline double EnergyCorrelatorUseries::result(const PseudoJet& jet) const {
0925       
0926         double answer = EnergyCorrelatorGeneralized(1, _n + 1, _beta, _measure, _strategy).result(jet);
0927         return answer;
0928 
0929     }
0930 
0931 
0932 //------------------------------------------------------------------------
0933 /// \class EnergyCorrelatorU1
0934 /// A class to calculate the observable formed from
0935 ///     ECFG(1,2,beta),
0936 /// called \f$ U_1^{(\beta)} \f$ in the publication.
0937     class EnergyCorrelatorU1 : public FunctionOfPseudoJet<double> {
0938 
0939     public:
0940 
0941         /// constructs a 2-point correlator with
0942         /// angular exponent beta, using the specified choice of energy and
0943         /// angular measure as well one of two possible underlying
0944         /// computational strategies
0945         EnergyCorrelatorU1(double  beta,
0946                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0947                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0948                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0949 
0950         virtual ~EnergyCorrelatorU1() {}
0951 
0952         /// returns the value of the energy correlator ratio for a jet's
0953         /// constituents. (Normally accessed by the parent class's
0954         /// operator()).
0955         double result(const PseudoJet& jet) const;
0956 
0957         std::string description() const;
0958 
0959     private:
0960 
0961         double _beta;
0962 
0963         EnergyCorrelator::Measure _measure;
0964         EnergyCorrelator::Strategy _strategy;
0965 
0966 
0967     };
0968 
0969 
0970     inline double EnergyCorrelatorU1::result(const PseudoJet& jet) const {
0971 
0972         double answer = EnergyCorrelatorGeneralized(1, 2, _beta, _measure, _strategy).result(jet);
0973 
0974         return answer;
0975 
0976     }
0977 
0978 
0979     //------------------------------------------------------------------------
0980     /// \class EnergyCorrelatorU2
0981     /// A class to calculate the observable formed from
0982     ///     ECFG(1,3,beta),
0983     /// called \f$ U_2^{(\beta)} \f$ in the publication.
0984     class EnergyCorrelatorU2 : public FunctionOfPseudoJet<double> {
0985 
0986     public:
0987 
0988         /// constructs a 3-point correlator with
0989         /// angular exponent beta, using the specified choice of energy and
0990         /// angular measure as well one of two possible underlying
0991         /// computational strategies
0992         EnergyCorrelatorU2(double  beta,
0993                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
0994                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
0995                 : _beta(beta), _measure(measure), _strategy(strategy) {};
0996 
0997         virtual ~EnergyCorrelatorU2() {}
0998 
0999         /// returns the value of the energy correlator ratio for a jet's
1000         /// constituents. (Normally accessed by the parent class's
1001         /// operator()).
1002         double result(const PseudoJet& jet) const;
1003 
1004         std::string description() const;
1005 
1006     private:
1007 
1008         double _beta;
1009 
1010         EnergyCorrelator::Measure _measure;
1011         EnergyCorrelator::Strategy _strategy;
1012 
1013 
1014     };
1015 
1016 
1017     inline double EnergyCorrelatorU2::result(const PseudoJet& jet) const {
1018 
1019         double answer = EnergyCorrelatorGeneralized(1, 3, _beta, _measure, _strategy).result(jet);
1020 
1021         return answer;
1022 
1023     }
1024 
1025 
1026     //------------------------------------------------------------------------
1027     /// \class EnergyCorrelatorU3
1028     /// A class to calculate the observable formed from
1029     ///     ECFG(1,4,beta),
1030     /// called \f$ U_3^{(\beta)} \f$ in the publication.
1031     class EnergyCorrelatorU3 : public FunctionOfPseudoJet<double> {
1032 
1033     public:
1034 
1035         /// constructs a 4-point correlator with
1036         /// angular exponent beta, using the specified choice of energy and
1037         /// angular measure as well one of two possible underlying
1038         /// computational strategies
1039         EnergyCorrelatorU3(double  beta,
1040                            EnergyCorrelator::Measure  measure  = EnergyCorrelator::pt_R,
1041                            EnergyCorrelator::Strategy strategy = EnergyCorrelator::storage_array)
1042                 : _beta(beta), _measure(measure), _strategy(strategy) {};
1043 
1044         virtual ~EnergyCorrelatorU3() {}
1045 
1046         /// returns the value of the energy correlator ratio for a jet's
1047         /// constituents. (Normally accessed by the parent class's
1048         /// operator()).
1049         double result(const PseudoJet& jet) const;
1050 
1051         std::string description() const;
1052 
1053     private:
1054 
1055         double _beta;
1056 
1057         EnergyCorrelator::Measure _measure;
1058         EnergyCorrelator::Strategy _strategy;
1059 
1060 
1061     };
1062 
1063 
1064     inline double EnergyCorrelatorU3::result(const PseudoJet& jet) const {
1065 
1066         double answer = EnergyCorrelatorGeneralized(1, 4, _beta, _measure, _strategy).result(jet);
1067 
1068         return answer;
1069 
1070     }
1071 
1072 
1073 
1074 } // namespace contrib
1075 
1076 FASTJET_END_NAMESPACE
1077 
1078 #endif  // __FASTJET_CONTRIB_ENERGYCORRELATOR_HH__