|
FastJet 3.0alpha3
|
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
1.7.4