00001 #include "RecoJets/JetProducers/interface/BackgroundEstimator.h" 00002 #include <fastjet/ClusterSequenceAreaBase.hh> 00003 #include <iostream> 00004 00005 using namespace fastjet; 00006 using namespace std; 00007 00008 //--------------------------------------------------------------------- 00009 // \class BackgroundEstimator 00010 // Class to estimate the density of the background per unit area 00011 // 00012 // The default behaviour of this class is to compute the global 00013 // properties of the background as it is done in ClusterSequenceArea. 00014 // On top of that, we provide methods to specify an explicit set of 00015 // jets to use or a list of jets to exclude. 00016 // We also provide all sorts of additional information regarding 00017 // the background estimation like the jets that have been used or 00018 // the number of pure-ghost jets. 00019 //--------------------------------------------------------------------- 00020 00021 // default ctor 00022 // - csa the ClusterSequenceArea to use 00023 // - range the range over which jets will be considered 00024 BackgroundEstimator::BackgroundEstimator(const ClusterSequenceAreaBase &csa, const RangeDefinition &range) 00025 : _csa(csa), _range(range){ 00026 reset(); 00027 } 00028 00029 // default dtor 00030 BackgroundEstimator::~BackgroundEstimator(){ 00031 00032 } 00033 00034 // reset to default values 00035 // set the list of included jets to the inclusive jets and clear the excluded ones 00036 void BackgroundEstimator::reset(){ 00037 // set the list of included jets to the inclusive jets 00038 _included_jets = _csa.inclusive_jets(); 00039 _all_from_inclusive = true; 00040 //set_included_jets(_csa.inclusive_jets()); 00041 00042 // clear the list of explicitly excluded jets 00043 _excluded_jets.clear(); 00044 //set_excluded_jets(vector<PseudoJet>()); 00045 00046 // set the remaining default parameters 00047 set_use_area_4vector(); // true by default 00048 00049 // reset the computed values 00050 _median_rho = _sigma = _mean_area = 0.0; 00051 _n_jets_used = _n_jets_excluded = _n_empty_jets = 0; 00052 _empty_area = 0.0; 00053 _uptodate = false; 00054 } 00055 00056 00057 // do the actual job 00058 void BackgroundEstimator::_compute(){ 00059 //TODO: check that the alg is OK for median computation 00060 //_check_jet_alg_good_for_median(); 00061 00062 // fill the vector of pt/area with the jets 00063 // - in included_jets 00064 // - not in excluded_jets 00065 // - in the range 00066 vector<double> pt_over_areas; 00067 double total_area = 0.0; 00068 00069 _n_jets_used = 0; 00070 _n_jets_excluded = 0; 00071 00072 for (unsigned i = 0; i < _included_jets.size(); i++) { 00073 const PseudoJet & current_jet = _included_jets[i]; 00074 00075 // check that the jet is not explicitly excluded 00076 // we'll compare them using their cluster_history_index 00077 bool excluded = false; 00078 int ref_idx = current_jet.cluster_hist_index(); 00079 for (unsigned int j = 0; j < _excluded_jets.size(); j++) 00080 excluded |= (_excluded_jets[j].cluster_hist_index() == ref_idx); 00081 00082 // check if the jet is in the range 00083 if (_range.is_in_range(current_jet)){ 00084 if (excluded){ 00085 // keep track of the explicitly excluded jets 00086 _n_jets_excluded++; 00087 } else { 00088 double this_area = (_use_area_4vector) 00089 ? _csa.area_4vector(current_jet).perp() 00090 : _csa.area(current_jet); 00091 00092 pt_over_areas.push_back(current_jet.perp()/this_area); 00093 total_area += this_area; 00094 _n_jets_used++; 00095 } 00096 } 00097 } 00098 00099 // there is nothing inside our region, so answer will always be zero 00100 if (pt_over_areas.size() == 0) { 00101 _median_rho = 0.0; 00102 _sigma = 0.0; 00103 _mean_area = 0.0; 00104 return; 00105 } 00106 00107 // get median (pt/area) [this is the "old" median definition. It considers 00108 // only the "real" jets in calculating the median, i.e. excluding the 00109 // only-ghost ones; it will be supplemented with more info below] 00110 sort(pt_over_areas.begin(), pt_over_areas.end()); 00111 00112 // determine the number of empty jets 00113 _empty_area = 0.0; 00114 _n_empty_jets = 0.0; 00115 if (_csa.has_explicit_ghosts()) { 00116 _empty_area = 0.0; 00117 _n_empty_jets = 0; 00118 } else if (_all_from_inclusive) { 00119 _empty_area = _csa.empty_area(_range); 00120 _n_empty_jets = _csa.n_empty_jets(_range); 00121 } else { 00122 _empty_area = _csa.empty_area_from_jets(_included_jets, _range); 00123 _mean_area = total_area / _n_jets_used; // temporary value 00124 _n_empty_jets = _empty_area / _mean_area; 00125 } 00126 00127 double total_njets = _n_jets_used + _n_empty_jets; 00128 total_area += _empty_area; 00129 00130 00131 // now get the median & error, accounting for empty jets 00132 // define the fractions of distribution at median, median-1sigma 00133 double posn[2] = {0.5, (1.0-0.6827)/2.0}; 00134 double res[2]; 00135 00136 for (int i = 0; i < 2; i++) { 00137 double nj_median_pos = (total_njets-1)*posn[i] - _n_empty_jets; 00138 double nj_median_ratio; 00139 if (nj_median_pos >= 0 && pt_over_areas.size() > 1) { 00140 int int_nj_median = int(nj_median_pos); 00141 nj_median_ratio = 00142 pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos) 00143 + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median); 00144 } else { 00145 nj_median_ratio = 0.0; 00146 } 00147 res[i] = nj_median_ratio; 00148 } 00149 00150 // store the results 00151 double error = res[0] - res[1]; 00152 _median_rho = res[0]; 00153 _mean_area = total_area / total_njets; 00154 _sigma = error * sqrt(_mean_area); 00155 00156 // record that the computation has been performed 00157 _uptodate = true; 00158 } 00159 00160 00161 00162