FastJet 3.0alpha3
BackgroundEstimator.hh
00001 //STARTHEADER
00002 // $Id: BackgroundEstimator.hh 2188 2011-05-31 15:44:46Z soyez $
00003 //
00004 // Copyright (c) 2005-2011, Matteo Cacciari, Gavin Salam and Gregory Soyez
00005 //
00006 //----------------------------------------------------------------------
00007 // This file is part of FastJet.
00008 //
00009 //  FastJet is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU General Public License as published by
00011 //  the Free Software Foundation; either version 2 of the License, or
00012 //  (at your option) any later version.
00013 //
00014 //  The algorithms that underlie FastJet have required considerable
00015 //  development and are described in hep-ph/0512210. If you use
00016 //  FastJet as part of work towards a scientific publication, please
00017 //  include a citation to the FastJet paper.
00018 //
00019 //  FastJet is distributed in the hope that it will be useful,
00020 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //  GNU General Public License for more details.
00023 //
00024 //  You should have received a copy of the GNU General Public License
00025 //  along with FastJet; if not, write to the Free Software
00026 //  Foundation, Inc.:
00027 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //----------------------------------------------------------------------
00029 //ENDHEADER
00030 
00031 #ifndef __FASTJET_BACKGROUND_ESTIMATOR_HH__
00032 #define __FASTJET_BACKGROUND_ESTIMATOR_HH__
00033 
00034 #include <fastjet/ClusterSequenceAreaBase.hh>
00035 #include <fastjet/FunctionOfPseudoJet.hh>
00036 #include <fastjet/Selector.hh>
00037 #include <iostream>
00038 
00039 FASTJET_BEGIN_NAMESPACE     // defined in fastjet/internal/base.hh
00040 
00041 
00042 
00043 //----------------------------------------------------------------------
00044 /// @ingroup tools
00045 /// A background rescaling that is a simple polynomial in y
00046 class BackgroundRescalingYPolynomial : public FunctionOfPseudoJet<double> {
00047 public:
00048   /// construct a background rescaling polynomial of the form
00049   /// a0 + a1*y + a2*y^2 + a3*y^3 + a4*y^4
00050   BackgroundRescalingYPolynomial(double a0=1, 
00051                                  double a1=0, 
00052                                  double a2=0, 
00053                                  double a3=0, 
00054                                  double a4=0) : _a0(a0), _a1(a1), _a2(a2), _a3(a3), _a4(a4) {}
00055 
00056   /// return the rescaling factor associated with this jet
00057   virtual double result(const PseudoJet & jet) const;
00058 private:
00059   double _a0, _a1, _a2, _a3, _a4;
00060 };
00061 
00062 
00063 //----------------------------------------------------------------------
00064 /// @ingroup tools
00065 /// Class that implements pt/area_4vector.perp() for background estimation
00066 class BackgroundJetPtDensity : public FunctionOfPseudoJet<double> {
00067 public:
00068   virtual double result(const PseudoJet & jet) const {
00069     return jet.perp() / jet.area_4vector().perp();
00070   }
00071   virtual std::string description() const {return "BackgroundJetPtDensity";}
00072 };
00073 
00074 
00075 //----------------------------------------------------------------------
00076 /// @ingroup tools
00077 /// Class that implements (scalar pt sum of jet)/(scalar area of jet)
00078 /// for background estimation. Optionally it can return a quantity
00079 /// based on the sum of pt^n, e.g. for use in subtracting
00080 /// fragementation function moments.
00081 class BackgroundJetScalarPtDensity : public FunctionOfPseudoJet<double> {
00082 public:
00083   /// Default constructor provides background estimation with scalar pt sum
00084   BackgroundJetScalarPtDensity() : _pt_power(1) {}
00085 
00086   /// Constructor to provide background estimation based on 
00087   /// \f$ sum_{i\in jet} p_{ti}^{n} \f$
00088   BackgroundJetScalarPtDensity(double n) : _pt_power(n) {}
00089 
00090   virtual double result(const PseudoJet & jet) const;
00091 
00092   virtual std::string description() const {return "BackgroundScalarJetPtDensity";}
00093 
00094 private:
00095   double _pt_power;
00096 };
00097 
00098 //----------------------------------------------------------------------
00099 /// @ingroup tools
00100 /// Class that implements
00101 /// \f$  \frac{1}{A} \sum_{i \in jet} (\sqrt{p_{ti}^2+m^2} - p_{ti}) \f$
00102 /// for background estimation.
00103 ///
00104 /// This is useful for correcting jet masses in cases where the event
00105 /// involves massive particles.
00106 class BackgroundJetPtMDensity : public FunctionOfPseudoJet<double> {
00107 public:
00108   virtual double result(const PseudoJet & jet) const {
00109     std::vector<PseudoJet> constituents = jet.constituents();
00110     double scalar_ptm = 0;
00111     for (unsigned i = 0; i < constituents.size(); i++) {
00112       scalar_ptm += constituents[i].mperp() - constituents[i].perp();
00113     }
00114     return scalar_ptm / jet.area();
00115   }
00116 
00117   virtual std::string description() const {return "BackgroundPtMDensity";}
00118 };
00119 
00120 
00121 
00122 
00123 /// @ingroup tools
00124 /// \class BackgroundEstimator
00125 /// Class to estimate the density of the background per unit area
00126 ///
00127 /// For a given event, this class calculated the median of the
00128 /// distribution of pt/Area for all jets in the event that pass some
00129 /// selection criterion.
00130 ///
00131 /// Events are passed either in the form of a ClusterSequenceArea (in
00132 /// which case the jets used as those returned by "inclusive_jets()")
00133 /// or directly as a set of jets.
00134 ///
00135 /// The selection criterion is typically a geometrical one (e.g. all
00136 /// jets with |y|<2) sometimes supplemented with some kinematical
00137 /// restriction (e.g. exclusion of the two hardest jets).
00138 ///
00139 /// Beware: 
00140 ///   by default, to correctly handle partially empty events, the
00141 ///   class attempts to calculate an "empty area", based
00142 ///   (schematically) on
00143 ///
00144 ///          range.total_area() - sum_{jets_in_range} jets.area()
00145 ///  
00146 ///   For ranges with small areas, this can be innacurate (particularly 
00147 ///   relevant in dense events where empty_area should be zero and ends
00148 ///   up not being zero).
00149 ///
00150 ///   This calculation of empty area can be avoided if you supply a
00151 ///   ClusterSequenceArea class with explicit ghosts
00152 ///   (ActiveAreaExplicitGhosts). This is _recommended_!
00153 ///
00154 class BackgroundEstimator {
00155 public:
00156   /// @name constructors and destructors
00157   //\{
00158   //----------------------------------------------------------------
00159   /// ctor from a ClusterSequenceAreaBase with area
00160   ///
00161   /// \param csa         the ClusterSequenceArea to use
00162   /// \param rho_range   a Selector that specifies the range over 
00163   ///                    which jets will be considered 
00164   ///
00165   /// Pre-conditions: 
00166   ///  - one should be able to estimate the "empty area" (i.e. the area
00167   ///    not occupied by jets). This is feasible if at least one of the following
00168   ///    conditions is satisfied:
00169   ///     ( i) the ClusterSequence has explicit ghosts
00170   ///     (ii) the range has a computable area.
00171   ///  - the jet algorithm must be suited for median computation
00172   ///    (otherwise a warning will be issues)
00173   ///
00174   /// Note that selectors with e.g. hardest-jets exclusion do not have
00175   /// a well-defined area. For this reasons, it is STRONGLY advised to
00176   /// use an area with explicit ghosts.
00177   BackgroundEstimator(const ClusterSequenceAreaBase &csa, const Selector &rho_range);
00178   
00179   /// ctor from a list of jets
00180   ///
00181   /// \param jets        the jets to use
00182   /// \param rho_range   the range over which jets will be considered
00183   ///
00184   /// Pre-conditions:
00185   ///  - all the jets must come from the same cluster sequence
00186   ///  - As for the above ctor, one needs to be able to estimate the
00187   ///    empty area. The conditions that the ClusterSequence must have
00188   ///    explicit ghosts is checked on the ClusterSequence shared by
00189   ///    the jets.
00190   ///  - As for the above ctor, the jet alg must be adequate
00191   BackgroundEstimator(const std::vector<PseudoJet> &jets, const Selector &rho_range);
00192   
00193   /// Constructor that just sets the rho range. The CSA or jets
00194   /// actually used for estimating the background must be passed
00195   /// later via set_cluster_sequence(...) or set_jets(...)
00196   ///
00197   /// \param rho_range   the range over which jets will be considered
00198   ///
00199   BackgroundEstimator(const Selector &rho_range) : _rho_range(rho_range) {
00200     reset();
00201   }
00202 
00203   /// default ctor. In order to use the BG estimator you then need to
00204   /// call set_selector(...) and also set_cluster_sequence(...) or
00205   /// set_jets(...)
00206   BackgroundEstimator()  {reset();}
00207   
00208 
00209   /// default dtor
00210   ~BackgroundEstimator();
00211 
00212   //\}
00213 
00214   /// @ name  retrieving fundamental information
00215   //\{
00216   //----------------------------------------------------------------
00217 
00218   /// get rho, the median background density oer unit area
00219   double rho() const {
00220     if (_rho_range.takes_reference())
00221       throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
00222     _recompute_if_needed();
00223     return _rho;
00224   }
00225 
00226   /// get sigma, the background fluctuations per unit area
00227   double sigma() const {
00228     if (_rho_range.takes_reference())
00229       throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case");
00230     _recompute_if_needed();
00231     return _sigma;
00232   }
00233 
00234   /// get rho, the median background density per unit area, locally at
00235   /// the position of a given jet.
00236   ///
00237   /// If the Selector associated with the range takes a reference jet
00238   /// (i.e. is relocatable), then for subsequent operations the
00239   /// Selector has that jet set as its reference.
00240   double rho(const PseudoJet jet) {
00241     _recompute_if_needed(jet);
00242     double our_rho = _rho;
00243     if (_rescaling_class != 0) { 
00244       our_rho *= (*_rescaling_class)(jet);
00245     }
00246     return our_rho;
00247   }
00248 
00249   /// get sigma, the background fluctuations per unit area,
00250   /// locally at the position of a given jet.
00251   ///
00252   /// If the Selector associated with the range takes a reference jet
00253   /// (i.e. is relocatable), then for subsequent operations the
00254   /// Selector has that jet set as its reference.
00255   double sigma(const PseudoJet &jet) {
00256     _recompute_if_needed(jet);
00257     double our_sigma = _sigma;
00258     if (_rescaling_class != 0) { 
00259       our_sigma *= (*_rescaling_class)(jet);
00260     }
00261     return our_sigma;
00262   }
00263 
00264   //\}
00265   
00266   /// @ name  retrieving additional useful information
00267   //\{
00268   //----------------------------------------------------------------
00269   /// Returns the mean area of the jets used to actually compute the
00270   /// background properties in the last call of rho() or sigma()
00271   double mean_area() const{
00272     _recompute_if_needed();
00273     return _mean_area;
00274   }
00275   
00276   /// returns the number of jets used to actually compute the
00277   /// background properties in the last call of rho() or sigma()
00278   unsigned int n_jets_used() const{
00279     _recompute_if_needed();
00280     return _n_jets_used;
00281   }
00282 
00283   /// Returns the estimate of the area (within the range defined by
00284   /// the selector) that is not occupied by jets. The value is that
00285   /// for the last call of rho() or sigma()
00286   ///
00287   /// The answer is defined to be zero if the area calculation
00288   /// involved explicit ghosts; if the area calculation was an active
00289   /// area, then use is made of the active area's internal list of
00290   /// pure ghost jets (taking those that pass the selector); otherwise
00291   /// it is based on the difference between the selector's total area
00292   /// and the area of the jets that pass the selector.
00293   ///
00294   /// The result here is just the cached result of the corresponding
00295   /// call to the ClusterSequenceAreaBase function.
00296   double empty_area() const{
00297     _recompute_if_needed();
00298     return _empty_area;
00299   }
00300 
00301   /// Returns the number of empty jets used when computing the
00302   /// background properties. The value is that for the last call of
00303   /// rho() or sigma().
00304   ///
00305   /// If the area has explicit ghosts the result is zero; for active
00306   /// areas it is the number of internal pure ghost jets that pass the
00307   /// selector; otherwise it is deduced from the empty area, divided by 
00308   /// \f$ 0.55 \pi R^2 \f$ (the average pure-ghost-jet area).
00309   ///
00310   /// The result here is just the cached result of the corresponding
00311   /// call to the ClusterSequenceAreaBase function.
00312   double n_empty_jets() const{
00313     _recompute_if_needed();
00314     return _n_empty_jets;
00315   }
00316 
00317   //}
00318 
00319   /// @name configuring behaviour
00320   //\{
00321   //----------------------------------------------------------------
00322 
00323   /// (re)set the cluster sequence (with area support) to be used by
00324   /// future calls to rho() etc. 
00325   ///
00326   /// \param csa  the cluster sequence area
00327   ///
00328   /// Pre-conditions: 
00329   ///  - one should be able to estimate the "empty area" (i.e. the area
00330   ///    not occupied by jets). This is feasible if at least one of the following
00331   ///    conditions is satisfied:
00332   ///     ( i) the ClusterSequence has explicit ghosts
00333   ///     (ii) the range has a computable area.
00334   ///  - the jet algorithm must be suited for median computation
00335   ///    (otherwise a warning will be issues)
00336   ///
00337   /// Note that selectors with e.g. hardest-jets exclusion do not have
00338   /// a well-defined area. For this reasons, it is STRONGLY advised to
00339   /// use an area with explicit ghosts.
00340   void set_cluster_sequence(const ClusterSequenceAreaBase & csa);
00341 
00342   /// (re)set the jets (which must have area support) to be used by future
00343   /// calls to rho() etc.; for the conditions that must be satisfied
00344   /// by the jets, see the Constructor that takes jets.
00345   void set_jets(const std::vector<PseudoJet> &jets);
00346 
00347   /// (re)set the selector to be used for future calls to rho() etc.
00348   void set_selector(const Selector & rho_range_selector) {
00349     _rho_range = rho_range_selector;
00350     _uptodate = false;
00351   }
00352 
00353 
00354   /// Resets the class to its default state, including the choice to
00355   /// use 4-vector areas.
00356   ///
00357   void reset();
00358 
00359   /// By default when calculating pt/Area for a jet, it is the
00360   /// transverse component of the 4-vector area that is used in the ratiof \f$p_t/A\f$. 
00361   /// Calling this function with a "false" argument causes the scalar area to
00362   /// be used instead. 
00363   ///
00364   /// While the difference between the two choices is usually small,
00365   /// for high-precision work it is usually the 4-vector area that is
00366   /// to be preferred.
00367   ///
00368   ///  \param use_it             whether one uses the 4-vector area or not (true by default)
00369   void set_use_area_4vector(bool use_it = true){
00370     _use_area_4vector = use_it;
00371     _uptodate = false;
00372   }  
00373 
00374   /// check if the estimator uses the 4-vector area or the scalar area
00375   bool use_area_4vector() const{ return _use_area_4vector;}
00376 
00377   /// The FastJet v2.X sigma calculation had a small spurious offset
00378   /// in the limit of a small number of jets. This is fixed by default
00379   /// in versions 3 upwards. The old behaviour can be obtained with a
00380   /// call to this function.
00381   void set_provide_fj2_sigma(bool provide_fj2_sigma = true) {
00382     _provide_fj2_sigma = provide_fj2_sigma;
00383     _uptodate = false;
00384   }
00385 
00386   /// Set a pointer to a class that calculates the quantity whose
00387   /// median will be calculated; if the pointer is null then pt/area
00388   /// is used (as occurs also if this function is not called).
00389   void set_jet_density_class(const FunctionOfPseudoJet<double> * jet_density_class) {
00390     _jet_density_class = jet_density_class;
00391     _uptodate = false;
00392   }
00393 
00394   /// return the pointer to the jet density class
00395   const FunctionOfPseudoJet<double> *  jet_density_class() {
00396     return _jet_density_class;
00397   }
00398 
00399   /// Set a pointer to a class that calculates the rescaling factor as
00400   /// a function of the jet (position). Note that the rescaling factor
00401   /// is used both in the determination of the "global" rho (the pt/A
00402   /// of each jet is divided by this factor) and when asking for a
00403   /// local rho (the result is multiplied by this factor).
00404   void set_rescaling_class(const FunctionOfPseudoJet<double> * rescaling_class) {
00405     _rescaling_class = rescaling_class;
00406     _uptodate = false;
00407   }
00408 
00409 //   /// Set the class that calculates the rescaling factor as a function
00410 //   /// of the jet (position). Usage as for set_rescaling_class, but it just
00411 //   /// take a copy of the rescaling class, which must derive from BackgroundRescalingBase
00412 //   template<class T> void set_rescaling_class(const T & rescaling_class) {
00413 //     BackgroundRescalingBase * rescaling_class_copy = new T(rescaling_class);
00414 //     _rescaling_class_sharedptr.reset(rescaling_class_copy);
00415 //     _rescaling_class = rescaling_class_copy;
00416 //     _uptodate = false;
00417 //   }
00418 // 
00419 //   /// include a template for pointers that are derived from BackgroundRescalingBase
00420 //   template<class T> void set_rescaling_class(T * rescaling_class) {
00421 //     const BackgroundRescalingBase * brb = dynamic_cast<const BackgroundRescalingBase *>(rescaling_class);
00422 //     if (brb != 0) {
00423 //       set_rescaling_class(brb);
00424 //       return;
00425 //     } else {
00426 //       throw Error("set_rescaling called with a pointer that does not dynamic cast down to const BackgroundRescalingBase");
00427 //     }
00428 //   }
00429 // 
00430 //   void set_rescaling_class(SharedPtr<BackgroundRescalingBase> & rescaling_class) {
00431 //     _rescaling_class_sharedptr = rescaling_class;
00432 //     _rescaling_class = _rescaling_class_sharedptr.get();
00433 //   }
00434 
00435   /// return the pointer to the jet density class
00436   const FunctionOfPseudoJet<double> *  rescaling_class() {
00437     return _rescaling_class;
00438   }
00439 
00440   //\}
00441 
00442 protected:
00443 
00444   /// given a quantity in a vector (e.g. pt_over_area) and knowledge
00445   /// about the number of empty jets, calculate the median and
00446   /// stand_dev_if_gaussian (roughly from the 16th percentile)
00447   ///
00448   /// If do_fj2_calculation is set to true then this performs FastJet
00449   /// 2.X estimation of the standard deviation, which has a spurious
00450   /// offset in the limit of a small number of jets.
00451   void _median_and_stddev(const std::vector<double> & quantity_vector, 
00452                           double n_empty_jets, 
00453                           double & median, 
00454                           double & stand_dev_if_gaussian,
00455                           bool do_fj2_calculation = false
00456                           ) const;
00457 
00458 
00459 private:
00460 
00461   /// do the actual job
00462   void _compute() const;
00463    
00464   /// check if the properties need to be recomputed 
00465   /// and do so if needed
00466   void _recompute_if_needed() const {
00467     if (!_uptodate) _compute();
00468     _uptodate = true;
00469   }
00470 
00471   /// for estimation using a selector that takes a reference jet
00472   /// (i.e. a selector that can be relocated) this function allows one
00473   /// to set its position.
00474   ///
00475   /// Note that this HAS to be called before any attempt to compute
00476   /// the background properties. The call is, however, performed
00477   /// automatically by the functions rho(jet) and sigma(jet).
00478   void _recompute_if_needed(const PseudoJet &jet);
00479 
00480   /// check that the underlying structure is still alive
00481   /// throw an error otherwise
00482   void _check_csa_alive() const;
00483 
00484   /// check that the algorithm used for the clustering is adapted for
00485   /// background estimation (i.e. either kt or C/A)
00486   /// Issue a warning otherwise
00487   void _check_jet_alg_good_for_median() const;
00488   
00489   // the information needed to do the computation
00490   Selector _rho_range;                      ///< range to compute the background in
00491   std::vector<PseudoJet> _included_jets;    ///< jets to be used
00492   bool _use_area_4vector;
00493   bool _provide_fj2_sigma;
00494   PseudoJet _current_reference;
00495 
00496   const FunctionOfPseudoJet<double> * _jet_density_class;
00497   const FunctionOfPseudoJet<double> * _rescaling_class;
00498   //SharedPtr<BackgroundRescalingBase> _rescaling_class_sharedptr;
00499   
00500   // the actual results of the computation
00501   mutable double _rho;                  ///< background estimated density per unit area
00502   mutable double _sigma;                ///< background estimated fluctuations
00503   mutable double _mean_area;            ///< mean area of the jets used to estimate the background
00504   mutable unsigned int _n_jets_used;    ///< number of jets used to estimate the background
00505   mutable double _n_empty_jets;         ///< number of empty (pure-ghost) jets
00506   mutable double _empty_area;           ///< the empty (pure-ghost/unclustered) area!
00507 
00508   // internal variables
00509   SharedPtr<PseudoJetStructureBase> _csi;   ///< allows to check if _csa is still valid
00510   mutable bool _uptodate;                   ///< true when the background computation is up-to-date
00511 
00512   /// handle warning messages
00513   static LimitedWarning _warnings;
00514   static LimitedWarning _warnings_zero_area;
00515   static LimitedWarning _warnings_relocation;
00516 };
00517 
00518 
00519 
00520 FASTJET_END_NAMESPACE
00521 
00522 #endif  // __BACKGROUND_ESTIMATOR_HH__
00523 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends