|
fastjet 3.0alpha2
|
00001 // design questions? 00002 // 00003 // - keep the option to define things with just a Selector and a list of particles 00004 // HOWTO: 00005 // . ClusterSequenceArea: 00006 // o impose an area for the Selector 00007 // o if not relocatable, take ghosts maxrap from there 00008 // otherwise, get it from the maxrap of the particles 00009 // warn in the doc that one should set a decent maxrap 00010 // o use kt, R=0.6 00011 // o active_area_explicit_ghosts 00012 // o have functions that allow to control the maxrap, the ghost area, the alg, R 00013 // 00014 // . have a SharedPtr<ClusterSequenceArea> initialised only in that case 00015 // remove the const CSA & _csa; 00016 // . access the cs using 00017 // dynamic_cast<ClusterSequenceArea*>(_csw()->cs()); 00018 // 00019 // 00020 // - use a default Selector: SelectorStrip(2.0) * !SelectorNHardest(2) 00021 00022 #include "fastjet/tools/BackgroundEstimator.hh" 00023 #include <fastjet/ClusterSequenceAreaBase.hh> 00024 #include <fastjet/ClusterSequenceStructure.hh> 00025 #include <iostream> 00026 00027 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00028 00029 using namespace std; 00030 00031 00032 /// allow for warnings 00033 LimitedWarning BackgroundEstimator::_warnings; 00034 LimitedWarning BackgroundEstimator::_warnings_zero_area; 00035 00036 00037 //--------------------------------------------------------------------- 00038 // class BackgroundEstimator 00039 // Class to estimate the density of the background per unit area 00040 //--------------------------------------------------------------------- 00041 00042 // default ctor 00043 // - csa the ClusterSequenceArea to use 00044 // - rho_range the range over which jets will be considered 00045 BackgroundEstimator::BackgroundEstimator(const ClusterSequenceAreaBase &csa, const Selector &rho_range) 00046 : _rho_range(rho_range){ 00047 00048 _csi = csa.structure_shared_ptr(); 00049 00050 // sanity checks 00051 //--------------- 00052 // (i) check the alg is appropriate 00053 _check_jet_alg_good_for_median(); 00054 00055 // (ii) check that, if there is no explicit ghosts, the selector has an area 00056 if ((!csa.has_explicit_ghosts()) && (!_rho_range.has_area())){ 00057 throw Error("BackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)"); 00058 } 00059 00060 // get the initial list of jets 00061 _included_jets = csa.inclusive_jets(); 00062 00063 // initialise things properly 00064 reset(); 00065 } 00066 00067 00068 // ctor from a list of jets 00069 // - jets the set of jets to use for the computation 00070 // - rho_range the range over which jets will be considered 00071 BackgroundEstimator::BackgroundEstimator(const vector<PseudoJet> &jets, const Selector &rho_range) 00072 : _rho_range(rho_range){ 00073 00074 if (! jets.size()) 00075 throw Error("BackgroundEstimator::BackgroundEstimator: At least one jet is needed to compute the background properties"); 00076 00077 // sanity checks 00078 //--------------- 00079 // (o) check that there is an underlying CS shared by all the jets 00080 if (! (jets[0].has_associated_cluster_sequence()) && (jets[0].has_area())) 00081 throw Error("BackgroundEstimator::BackgroundEstimator: the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase"); 00082 00083 _csi = jets[0].structure_shared_ptr(); 00084 ClusterSequenceStructure * csi = dynamic_cast<ClusterSequenceStructure*>(_csi()); 00085 const ClusterSequenceAreaBase * csab = csi->validated_csab(); 00086 00087 for (unsigned int i=1;i<jets.size(); i++){ 00088 if (! jets[i].has_associated_cluster_sequence()) // area automatic if the next test succeeds 00089 throw Error("BackgroundEstimator::BackgroundEstimator: the jets used to estimate the background properties must be associated with a valid ClusterSequenceAreaBase"); 00090 00091 if (jets[i].structure_shared_ptr().get() != _csi.get()) 00092 throw Error("BackgroundEstimator::BackgroundEstimator: all the jets used to estimate the background properties must share the same ClusterSequence"); 00093 } 00094 00095 // (i) check the alg is appropriate 00096 _check_jet_alg_good_for_median(); 00097 00098 // (ii) check that, if there is no explicit ghosts, the selector has an area 00099 if ((!csab->has_explicit_ghosts()) && (!_rho_range.has_area())){ 00100 throw Error("BackgroundEstimator: either an area with explicit ghosts (recommended) or a Selector with finite area is needed (to allow for the computation of the empty area)"); 00101 } 00102 00103 00104 // get the initial list of jets 00105 _included_jets = jets; 00106 00107 // initialise things properly 00108 reset(); 00109 } 00110 00111 00112 // default dtor 00113 BackgroundEstimator::~BackgroundEstimator(){ 00114 00115 } 00116 00117 00118 // for estimation using a relocatable selector (i.e. local range) 00119 // this allows to set its position. Note that this HAS to be called 00120 // before any attempt to compute the background properties 00121 BackgroundEstimator & BackgroundEstimator::set_reference(const PseudoJet &jet){ 00122 // if the range is norrelocatable, do nothing 00123 if (_rho_range.takes_reference()){ 00124 // relocate the range and make sure things get recomputed the next 00125 // time one tries to get some information 00126 _rho_range.set_reference(jet); 00127 _uptodate=false; 00128 } 00129 00130 return *this; 00131 } 00132 00133 // reset to default values 00134 // 00135 // set the variou options to their default values 00136 void BackgroundEstimator::reset(){ 00137 // set the remaining default parameters 00138 set_use_area_4vector(); // true by default 00139 00140 // reset the computed values 00141 _rho = _sigma = 0.0; 00142 _n_jets_used = _n_empty_jets = 0; 00143 _empty_area = _mean_area = 0.0; 00144 00145 _uptodate = false; 00146 } 00147 00148 00149 // do the actual job 00150 void BackgroundEstimator::_compute(){ 00151 // check if the clustersequence is still valid 00152 _check_csa_alive(); 00153 00154 // fill the vector of pt/area with the jets 00155 // - in included_jets 00156 // - not in excluded_jets 00157 // - in the range 00158 vector<double> pt_over_areas; 00159 double total_area = 0.0; 00160 00161 _n_jets_used = 0; 00162 00163 // apply the selector to the included jets 00164 _selected_jets = _rho_range(_included_jets); 00165 00166 // compute the pt/area for the selected jets 00167 for (unsigned i = 0; i < _selected_jets.size(); i++) { 00168 const PseudoJet & current_jet = _selected_jets[i]; 00169 00170 double this_area = (_use_area_4vector) ? current_jet.area_4vector().perp() : current_jet.area(); 00171 00172 if (this_area>0){ 00173 pt_over_areas.push_back(current_jet.perp()/this_area); 00174 total_area += this_area; 00175 _n_jets_used++; 00176 } else { 00177 _warnings_zero_area.warn("BackgroundEstimator::get_median_rho_and_sigma(...): 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)."); 00178 } 00179 00180 } 00181 00182 // there is nothing inside our region, so answer will always be zero 00183 if (pt_over_areas.size() == 0) { 00184 _rho = 0.0; 00185 _sigma = 0.0; 00186 _mean_area = 0.0; 00187 return; 00188 } 00189 00190 // get median (pt/area) [this is the "old" median definition. It considers 00191 // only the "real" jets in calculating the median, i.e. excluding the 00192 // only-ghost ones; it will be supplemented with more info below] 00193 sort(pt_over_areas.begin(), pt_over_areas.end()); 00194 00195 // determine the number of empty jets 00196 _empty_area = 0.0; 00197 _n_empty_jets = 0.0; 00198 const ClusterSequenceAreaBase * csab = dynamic_cast<ClusterSequenceStructure*>(_csi())->validated_csab(); 00199 00200 if (csab->has_explicit_ghosts()) { 00201 _empty_area = 0.0; 00202 _n_empty_jets = 0; 00203 } else { 00204 // note that we are sure that the selector has an area 00205 _empty_area = _rho_range.area() - total_area; 00206 if (_empty_area<0) _empty_area = 0; 00207 _n_empty_jets = _empty_area / (0.55*pi*csab->jet_def().R()); 00208 } 00209 00210 double total_njets = _n_jets_used + _n_empty_jets; 00211 total_area += _empty_area; 00212 00213 // now get the median & error, accounting for empty jets 00214 // define the fractions of distribution at median, median-1sigma 00215 double posn[2] = {0.5, (1.0-0.6827)/2.0}; 00216 double res[2]; 00217 00218 for (int i = 0; i < 2; i++) { 00219 double nj_median_pos = (total_njets-1)*posn[i] - _n_empty_jets; 00220 double nj_median_ratio; 00221 if (nj_median_pos >= 0 && pt_over_areas.size() > 1) { 00222 int int_nj_median = int(nj_median_pos); 00223 nj_median_ratio = 00224 pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos) 00225 + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median); 00226 } else { 00227 nj_median_ratio = 0.0; 00228 } 00229 res[i] = nj_median_ratio; 00230 } 00231 00232 // store the results 00233 double error = res[0] - res[1]; 00234 _rho = res[0]; 00235 _mean_area = total_area / total_njets; 00236 _sigma = error * sqrt(_mean_area); 00237 00238 // record that the computation has been performed 00239 _uptodate = true; 00240 } 00241 00242 00243 // check that the underlying structure is still alive 00244 // throw an error otherwise 00245 void BackgroundEstimator::_check_csa_alive(){ 00246 if (! dynamic_cast<ClusterSequenceStructure*>(_csi())->has_associated_cluster_sequence()) 00247 throw Error("BackgroundEstimator: modifications are no longer possible as the underlying ClusterSequence has gone out of scope"); 00248 } 00249 00250 00251 // check that the algorithm used for the clustering is adapted for 00252 // background estimation (i.e. either kt or C/A) 00253 // Issue a warning otherwise 00254 void BackgroundEstimator::_check_jet_alg_good_for_median(){ 00255 const ClusterSequence * cs = dynamic_cast<ClusterSequenceStructure*>(_csi())->validated_cs(); 00256 00257 if (cs->jet_def().jet_algorithm() != kt_algorithm 00258 && cs->jet_def().jet_algorithm() != cambridge_algorithm 00259 && cs->jet_def().jet_algorithm() != cambridge_for_passive_algorithm) { 00260 _warnings.warn("BackgroundEstimator: jet_def being used may not be suitable for estimating diffuse backgrounds (good options are kt, cam)"); 00261 } 00262 } 00263 00264 FASTJET_END_NAMESPACE 00265 00266
1.7.3