FastJet 3.0beta1
|
00001 //STARTHEADER 00002 // $Id: JetMedianBackgroundEstimator.cc 2472 2011-07-26 11:25:42Z cacciari $ 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 #include "fastjet/tools/JetMedianBackgroundEstimator.hh" 00032 #include <fastjet/ClusterSequenceArea.hh> 00033 #include <fastjet/ClusterSequenceStructure.hh> 00034 #include <iostream> 00035 00036 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00037 00038 using namespace std; 00039 00040 double BackgroundJetScalarPtDensity::result(const PseudoJet & jet) const { 00041 std::vector<PseudoJet> constituents = jet.constituents(); 00042 double scalar_pt = 0; 00043 for (unsigned i = 0; i < constituents.size(); i++) { 00044 scalar_pt += pow(constituents[i].perp(), _pt_power); 00045 } 00046 return scalar_pt / jet.area(); 00047 } 00048 00049 00050 //---------------------------------------------------------------------- 00051 double BackgroundRescalingYPolynomial::result(const PseudoJet & jet) const { 00052 double y = jet.rap(); 00053 double y2 = y*y; 00054 double rescaling = _a0 + _a1*y + _a2*y2 + _a3*y2*y + _a4*y2*y2; 00055 return rescaling; 00056 } 00057 00058 /// allow for warnings 00059 LimitedWarning JetMedianBackgroundEstimator::_warnings; 00060 LimitedWarning JetMedianBackgroundEstimator::_warnings_zero_area; 00061 LimitedWarning JetMedianBackgroundEstimator::_warnings_preliminary; 00062 00063 00064 //--------------------------------------------------------------------- 00065 // class JetMedianBackgroundEstimator 00066 // Class to estimate the density of the background per unit area 00067 //--------------------------------------------------------------------- 00068 00069 //---------------------------------------------------------------------- 00070 // ctors and dtors 00071 //---------------------------------------------------------------------- 00072 // ctor that allows to set only the particles later on 00073 JetMedianBackgroundEstimator::JetMedianBackgroundEstimator(const Selector &rho_range, 00074 const JetDefinition &jet_def, 00075 const AreaDefinition &area_def) 00076 : _rho_range(rho_range), _jet_def(jet_def), _area_def(area_def) { 00077 00078 // initialise things decently 00079 reset(); 00080 00081 // make a few checks 00082 _check_jet_alg_good_for_median(); 00083 } 00084 00085 00086 //---------------------------------------------------------------------- 00087 // ctor from a cluster sequence 00088 // - csa the ClusterSequenceArea to use 00089 // - rho_range the Selector specifying which jets will be considered 00090 JetMedianBackgroundEstimator::JetMedianBackgroundEstimator( const Selector &rho_range, const ClusterSequenceAreaBase &csa) 00091 : _rho_range(rho_range), _jet_def(JetDefinition()){ 00092 00093 // initialise things properly 00094 reset(); 00095 00096 // tell the BGE about the cluster sequence 00097 set_cluster_sequence(csa); 00098 } 00099 00100 00101 //---------------------------------------------------------------------- 00102 // setting a new event 00103 //---------------------------------------------------------------------- 00104 // tell the background estimator that it has a new event, composed 00105 // of the specified particles. 00106 void JetMedianBackgroundEstimator::set_particles(const vector<PseudoJet> & particles) { 00107 // make sure that we have been provided a genuine jet definition 00108 if (_jet_def.jet_algorithm() == undefined_jet_algorithm) 00109 throw Error("JetMedianBackgroundEstimator::set_particles can only be called if you set the jet (and area) definition explicitly through the class constructor"); 00110 00111 // initialise things decently (including setting uptodate to false!) 00112 reset(); 00113 00114 // cluster the particles 00115 // 00116 // One may argue that it is better to cache the particles and only 00117 // do the clustering later but clustering the particles now has 2 00118 // practical advantages: 00119 // - it allows to une only '_included_jets' in all that follows 00120 // - it avoids adding another flag to ensure particles are 00121 // clustered only once 00122 ClusterSequenceArea *csa = new ClusterSequenceArea(particles, _jet_def, _area_def); 00123 _included_jets = csa->inclusive_jets(); 00124 00125 // store the CS for later on 00126 _csi = csa->structure_shared_ptr(); 00127 csa->delete_self_when_unused(); 00128 } 00129 00130 //---------------------------------------------------------------------- 00131 // (re)set the cluster sequence (with area support) to be used by 00132 // future calls to rho() etc. 00133 // 00134 // \param csa the cluster sequence area 00135 // 00136 // Pre-conditions: 00137 // - one should be able to estimate the "empty area" (i.e. the area 00138 // not occupied by jets). This is feasible if at least one of the following 00139 // conditions is satisfied: 00140 // ( i) the ClusterSequence has explicit ghosts 00141 // (ii) the range selected has a computable area. 00142 // - the jet algorithm must be suited for median computation 00143 // (otherwise a warning will be issues) 00144 // 00145 // Note that selectors with e.g. hardest-jets exclusion do not have 00146 // a well-defined area. For this reasons, it is STRONGLY advised to 00147 // use an area with explicit ghosts. 00148 void JetMedianBackgroundEstimator::set_cluster_sequence(const ClusterSequenceAreaBase & csa) { 00149 _csi = csa.structure_shared_ptr(); 00150 00151 // sanity checks 00152 //--------------- 00153 // (i) check the alg is appropriate 00154 _check_jet_alg_good_for_median(); 00155 00156 // (ii) check that, if there are no explicit ghosts, the selector has a finite area 00157 if ((!csa.has_explicit_ghosts()) && (!_rho_range.has_finite_area())){ 00158 throw Error("JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)"); 00159 } 00160 00161 // get the initial list of jets 00162 _included_jets = csa.inclusive_jets(); 00163 00164 _uptodate = false; 00165 } 00166 00167 00168 //---------------------------------------------------------------------- 00169 // (re)set the jets (which must have area support) to be used by future 00170 // calls to rho() etc.; for the conditions that must be satisfied 00171 // by the jets, see the Constructor that takes jets. 00172 void JetMedianBackgroundEstimator::set_jets(const vector<PseudoJet> &jets) { 00173 00174 if (! jets.size()) 00175 throw Error("JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: At least one jet is needed to compute the background properties"); 00176 00177 // sanity checks 00178 //--------------- 00179 // (o) check that there is an underlying CS shared by all the jets 00180 if (! (jets[0].has_associated_cluster_sequence()) && (jets[0].has_area())) 00181 throw Error("JetMedianBackgroundEstimator::JetMedianBackgroundEstimator: the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase"); 00182 00183 _csi = jets[0].structure_shared_ptr(); 00184 ClusterSequenceStructure * csi = dynamic_cast<ClusterSequenceStructure*>(_csi()); 00185 const ClusterSequenceAreaBase * csab = csi->validated_csab(); 00186 00187 for (unsigned int i=1;i<jets.size(); i++){ 00188 if (! jets[i].has_associated_cluster_sequence()) // area automatic if the next test succeeds 00189 throw Error("JetMedianBackgroundEstimator::set_jets(...): the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase"); 00190 00191 if (jets[i].structure_shared_ptr().get() != _csi.get()) 00192 throw Error("JetMedianBackgroundEstimator::set_jets(...): all the jets used to estimate the background properties must share the same ClusterSequence"); 00193 } 00194 00195 // (i) check the alg is appropriate 00196 _check_jet_alg_good_for_median(); 00197 00198 // (ii) check that, if there are no explicit ghosts, the selector has a finite area 00199 if ((!csab->has_explicit_ghosts()) && (!_rho_range.has_finite_area())){ 00200 throw Error("JetMedianBackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)"); 00201 } 00202 00203 00204 // get the initial list of jets 00205 _included_jets = jets; 00206 00207 // ensure recalculation of quantities that need it 00208 _uptodate = false; 00209 } 00210 00211 00212 //---------------------------------------------------------------------- 00213 // retrieving fundamental information 00214 //---------------------------------------------------------------- 00215 00216 // get rho, the median background density per unit area 00217 double JetMedianBackgroundEstimator::rho() const { 00218 if (_rho_range.takes_reference()) 00219 throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case"); 00220 _recompute_if_needed(); 00221 return _rho; 00222 } 00223 00224 // get sigma, the background fluctuations per unit area 00225 double JetMedianBackgroundEstimator::sigma() const { 00226 if (_rho_range.takes_reference()) 00227 throw Error("The background estimation is obtained from a selector that takes a reference jet. rho(PseudoJet) should be used in that case"); 00228 _recompute_if_needed(); 00229 return _sigma; 00230 } 00231 00232 // get rho, the median background density per unit area, locally at 00233 // the position of a given jet. 00234 // 00235 // If the Selector associated with the range takes a reference jet 00236 // (i.e. is relocatable), then for subsequent operations the 00237 // Selector has that jet set as its reference. 00238 double JetMedianBackgroundEstimator::rho(const PseudoJet & jet) { 00239 _recompute_if_needed(jet); 00240 double our_rho = _rho; 00241 if (_rescaling_class != 0) { 00242 our_rho *= (*_rescaling_class)(jet); 00243 } 00244 return our_rho; 00245 } 00246 00247 // get sigma, the background fluctuations per unit area, 00248 // locally at the position of a given jet. 00249 // 00250 // If the Selector associated with the range takes a reference jet 00251 // (i.e. is relocatable), then for subsequent operations the 00252 // Selector has that jet set as its reference. 00253 double JetMedianBackgroundEstimator::sigma(const PseudoJet &jet) { 00254 _recompute_if_needed(jet); 00255 double our_sigma = _sigma; 00256 if (_rescaling_class != 0) { 00257 our_sigma *= (*_rescaling_class)(jet); 00258 } 00259 return our_sigma; 00260 } 00261 00262 00263 //---------------------------------------------------------------------- 00264 // configuring behaviour 00265 //---------------------------------------------------------------------- 00266 // reset to default values 00267 // 00268 // set the variou options to their default values 00269 void JetMedianBackgroundEstimator::reset(){ 00270 // set the remaining default parameters 00271 set_use_area_4vector(); // true by default 00272 set_provide_fj2_sigma(false); 00273 00274 // reset the computed values 00275 _rho = _sigma = 0.0; 00276 _n_jets_used = _n_empty_jets = 0; 00277 _empty_area = _mean_area = 0.0; 00278 00279 _included_jets.clear(); 00280 00281 _jet_density_class = 0; // null pointer 00282 _rescaling_class = 0; // null pointer 00283 00284 _uptodate = false; 00285 } 00286 00287 00288 // Set a pointer to a class that calculates the quantity whose 00289 // median will be calculated; if the pointer is null then pt/area 00290 // is used (as occurs also if this function is not called). 00291 void JetMedianBackgroundEstimator::set_jet_density_class(const FunctionOfPseudoJet<double> * jet_density_class) { 00292 _warnings_preliminary.warn("JetMedianBackgroundEstimator::set_jet_density_class: density classes are still preliminary in FastJet 3.0. Their interface may differ in future releases (without guaranteeing backward compatibility)."); 00293 _jet_density_class = jet_density_class; 00294 _uptodate = false; 00295 } 00296 00297 00298 00299 //---------------------------------------------------------------------- 00300 // description 00301 //---------------------------------------------------------------------- 00302 string JetMedianBackgroundEstimator::description() const { 00303 ostringstream desc; 00304 desc << "JetMedianBackgroundEstimator, using " << _jet_def.description() 00305 << " with " << _area_def.description() 00306 << " and selecting jets with " << _rho_range.description(); 00307 return desc.str(); 00308 } 00309 00310 00311 00312 //---------------------------------------------------------------------- 00313 // computation of the background properties 00314 //---------------------------------------------------------------------- 00315 // for estimation using a relocatable selector (i.e. local range) 00316 // this allows to set its position. Note that this HAS to be called 00317 // before any attempt to compute the background properties 00318 void JetMedianBackgroundEstimator::_recompute_if_needed(const PseudoJet &jet){ 00319 // if the range is relocatable, handles its relocation 00320 if (_rho_range.takes_reference()){ 00321 // check that the reference is not the same as the previous one 00322 // (would avoid an unnecessary recomputation) 00323 if (jet == _current_reference) return; 00324 00325 // relocate the range and make sure things get recomputed the next 00326 // time one tries to get some information 00327 _rho_range.set_reference(jet); 00328 _uptodate=false; 00329 } 00330 00331 _recompute_if_needed(); 00332 } 00333 00334 // do the actual job 00335 void JetMedianBackgroundEstimator::_compute() const { 00336 // check if the clustersequence is still valid 00337 _check_csa_alive(); 00338 00339 // fill the vector of pt/area (or the quantity from the jet density class) 00340 // - in the range 00341 vector<double> vector_for_median; 00342 double total_area = 0.0; 00343 _n_jets_used = 0; 00344 00345 // apply the selector to the included jets 00346 vector<PseudoJet> selected_jets = _rho_range(_included_jets); 00347 00348 // compute the pt/area for the selected jets 00349 for (unsigned i = 0; i < selected_jets.size(); i++) { 00350 const PseudoJet & current_jet = selected_jets[i]; 00351 00352 double this_area = (_use_area_4vector) ? current_jet.area_4vector().perp() : current_jet.area(); 00353 00354 if (this_area>0){ 00355 double median_input; 00356 if (_jet_density_class == 0) { 00357 median_input = current_jet.perp()/this_area; 00358 } else { 00359 median_input = (*_jet_density_class)(current_jet); 00360 } 00361 if (_rescaling_class != 0) { 00362 median_input /= (*_rescaling_class)(current_jet); 00363 } 00364 vector_for_median.push_back(median_input); 00365 total_area += this_area; 00366 _n_jets_used++; 00367 } else { 00368 _warnings_zero_area.warn("JetMedianBackgroundEstimator::_compute(...): discarded jet with zero area. Zero-area jets may be due to (i) too large a ghost area (ii) a jet being outside the ghost range (iii) the computation not being done using an appropriate algorithm (kt;C/A)."); 00369 } 00370 00371 } 00372 00373 // there is nothing inside our region, so answer will always be zero 00374 if (vector_for_median.size() == 0) { 00375 _rho = 0.0; 00376 _sigma = 0.0; 00377 _mean_area = 0.0; 00378 return; 00379 } 00380 00381 // determine the number of empty jets 00382 const ClusterSequenceAreaBase * csab = (dynamic_cast<ClusterSequenceStructure*>(_csi()))->validated_csab(); 00383 if (csab->has_explicit_ghosts()) { 00384 _empty_area = 0.0; 00385 _n_empty_jets = 0; 00386 } else { 00387 _empty_area = csab->empty_area(_rho_range); 00388 _n_empty_jets = csab->n_empty_jets(_rho_range); 00389 } 00390 00391 double total_njets = _n_jets_used + _n_empty_jets; 00392 total_area += _empty_area; 00393 00394 double stand_dev; 00395 _median_and_stddev(vector_for_median, _n_empty_jets, _rho, stand_dev, 00396 _provide_fj2_sigma); 00397 00398 // process and store the results (_rho was already stored above) 00399 _mean_area = total_area / total_njets; 00400 _sigma = stand_dev * sqrt(_mean_area); 00401 00402 // record that the computation has been performed 00403 _uptodate = true; 00404 } 00405 00406 00407 00408 // check that the underlying structure is still alive; 00409 // throw an error otherwise 00410 void JetMedianBackgroundEstimator::_check_csa_alive() const{ 00411 ClusterSequenceStructure* csa = dynamic_cast<ClusterSequenceStructure*>(_csi()); 00412 if (csa == 0) { 00413 throw Error("JetMedianBackgroundEstimator: there is no cluster sequence associated with the JetMedianBackgroundEstimator"); 00414 } 00415 if (! dynamic_cast<ClusterSequenceStructure*>(_csi())->has_associated_cluster_sequence()) 00416 throw Error("JetMedianBackgroundEstimator: modifications are no longer possible as the underlying ClusterSequence has gone out of scope"); 00417 } 00418 00419 00420 // check that the algorithm used for the clustering is suitable for 00421 // background estimation (i.e. either kt or C/A). 00422 // Issue a warning otherwise 00423 void JetMedianBackgroundEstimator::_check_jet_alg_good_for_median() const{ 00424 const JetDefinition * jet_def = &_jet_def; 00425 00426 // if no explicit jet def has been provided, fall back on the 00427 // cluster sequence 00428 if (_jet_def.jet_algorithm() == undefined_jet_algorithm){ 00429 const ClusterSequence * cs = dynamic_cast<ClusterSequenceStructure*>(_csi())->validated_cs(); 00430 jet_def = &(cs->jet_def()); 00431 } 00432 00433 if (jet_def->jet_algorithm() != kt_algorithm 00434 && jet_def->jet_algorithm() != cambridge_algorithm 00435 && jet_def->jet_algorithm() != cambridge_for_passive_algorithm) { 00436 _warnings.warn("JetMedianBackgroundEstimator: jet_def being used may not be suitable for estimating diffuse backgrounds (good alternatives are kt, cam)"); 00437 } 00438 } 00439 00440 00441 00442 00443 FASTJET_END_NAMESPACE 00444 00445