00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "fastjet/ClusterSequenceAreaBase.hh"
00036 #include <algorithm>
00037
00038 FASTJET_BEGIN_NAMESPACE
00039
00040 using namespace std;
00041
00042
00044 LimitedWarning ClusterSequenceAreaBase::_warnings;
00045
00046
00051 double ClusterSequenceAreaBase::empty_area(const RangeDefinition & range) const {
00052 double empty = range.area();
00053 vector<PseudoJet> incl_jets(inclusive_jets(0.0));
00054 for (unsigned i = 0; i < incl_jets.size(); i++) {
00055 if (range.is_in_range(incl_jets[i])) empty -= area(incl_jets[i]);
00056 }
00057 return empty;
00058 }
00059
00060 double ClusterSequenceAreaBase::median_pt_per_unit_area(const RangeDefinition & range) const {
00061 return median_pt_per_unit_something(range,false);
00062 }
00063
00064 double ClusterSequenceAreaBase::median_pt_per_unit_area_4vector(const RangeDefinition & range) const {
00065 return median_pt_per_unit_something(range,true);
00066 }
00067
00068
00069
00073 double ClusterSequenceAreaBase::median_pt_per_unit_something(
00074 const RangeDefinition & range, bool use_area_4vector) const {
00075
00076 double median, sigma, mean_area;
00077 get_median_rho_and_sigma(range, use_area_4vector, median, sigma, mean_area);
00078 return median;
00079
00080 }
00081
00082
00083
00087 void ClusterSequenceAreaBase::parabolic_pt_per_unit_area(
00088 double & a, double & b, const RangeDefinition & range,
00089 double exclude_above, bool use_area_4vector) const {
00090
00091 int n=0;
00092 int n_excluded = 0;
00093 double mean_f=0, mean_x2=0, mean_x4=0, mean_fx2=0;
00094
00095 vector<PseudoJet> incl_jets = inclusive_jets();
00096
00097 for (unsigned i = 0; i < incl_jets.size(); i++) {
00098 if (range.is_in_range(incl_jets[i])) {
00099 double this_area;
00100 if ( use_area_4vector ) {
00101 this_area = area_4vector(incl_jets[i]).perp();
00102 } else {
00103 this_area = area(incl_jets[i]);
00104 }
00105 double f = incl_jets[i].perp()/this_area;
00106 if (exclude_above <= 0.0 || f < exclude_above) {
00107 double x = incl_jets[i].rap(); double x2 = x*x;
00108 mean_f += f;
00109 mean_x2 += x2;
00110 mean_x4 += x2*x2;
00111 mean_fx2 += f*x2;
00112 n++;
00113 } else {
00114 n_excluded++;
00115 }
00116 }
00117 }
00118
00119 if (n <= 1) {
00120
00121
00122
00123 a = 0.0;
00124 b = 0.0;
00125 } else {
00126 mean_f /= n;
00127 mean_x2 /= n;
00128 mean_x4 /= n;
00129 mean_fx2 /= n;
00130
00131 b = (mean_f*mean_x2 - mean_fx2)/(mean_x2*mean_x2 - mean_x4);
00132 a = mean_f - b*mean_x2;
00133 }
00134
00135 }
00136
00137
00138
00139
00140 void ClusterSequenceAreaBase::get_median_rho_and_sigma(
00141 const RangeDefinition & range, bool use_area_4vector,
00142 double & median, double & sigma, double & mean_area) const {
00143
00144 _check_jet_alg_good_for_median();
00145
00146 vector<double> pt_over_areas;
00147 vector<PseudoJet> incl_jets = inclusive_jets();
00148 double total_area = 0.0;
00149 double total_njets = 0;
00150
00151 for (unsigned i = 0; i < incl_jets.size(); i++) {
00152 if (range.is_in_range(incl_jets[i])) {
00153 double this_area;
00154 if (use_area_4vector) {
00155 this_area = area_4vector(incl_jets[i]).perp();
00156 } else {
00157 this_area = area(incl_jets[i]);
00158 }
00159 pt_over_areas.push_back(incl_jets[i].perp()/this_area);
00160 total_area += this_area;
00161 total_njets += 1.0;
00162 }
00163 }
00164
00165
00166 if (pt_over_areas.size() == 0) {
00167 median = 0.0;
00168 sigma = 0.0;
00169 mean_area = 0.0;
00170 return;
00171 }
00172
00173
00174
00175
00176 sort(pt_over_areas.begin(), pt_over_areas.end());
00177
00178
00179
00180 double posn[2] = {0.5, (1.0-0.6827)/2.0};
00181 double res[2];
00182
00183 double n_empty = n_empty_jets(range);
00184 total_njets += n_empty;
00185 total_area += empty_area(range);
00186
00187 for (int i = 0; i < 2; i++) {
00188 double nj_median_pos =
00189 (pt_over_areas.size()-1 + n_empty)*posn[i] - n_empty;
00190 double nj_median_ratio;
00191 if (nj_median_pos >= 0 && pt_over_areas.size() > 1) {
00192 int int_nj_median = int(nj_median_pos);
00193 nj_median_ratio =
00194 pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos)
00195 + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median);
00196 } else {
00197 nj_median_ratio = 0.0;
00198 }
00199 res[i] = nj_median_ratio;
00200 }
00201 median = res[0];
00202 double error = res[0] - res[1];
00203 mean_area = total_area / total_njets;
00204 sigma = error * sqrt(mean_area);
00205 }
00206
00207
00212 vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(const double rho,
00213 const double ptmin)
00214 const {
00215 vector<PseudoJet> sub_jets;
00216 vector<PseudoJet> jets = sorted_by_pt(inclusive_jets(ptmin));
00217 for (unsigned i=0; i<jets.size(); i++) {
00218 PseudoJet sub_jet = subtracted_jet(jets[i],rho);
00219 sub_jets.push_back(sub_jet);
00220 }
00221 return sub_jets;
00222 }
00223
00228 vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(
00229 const RangeDefinition & range,
00230 const double ptmin)
00231 const {
00232 double rho = median_pt_per_unit_area_4vector(range);
00233 return subtracted_jets(rho,ptmin);
00234 }
00235
00236
00238 PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
00239 const double rho) const {
00240 PseudoJet area4vect = area_4vector(jet);
00241 PseudoJet sub_jet;
00242
00243 if (rho*area4vect.perp() < jet.perp() ) {
00244 sub_jet = jet - rho*area4vect;
00245 } else { sub_jet = PseudoJet(0.0,0.0,0.0,0.0); }
00246
00247
00248
00249 sub_jet.set_cluster_hist_index(jet.cluster_hist_index());
00250
00251 return sub_jet;
00252 }
00253
00254
00258 PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
00259 const RangeDefinition & range) const {
00260 double rho = median_pt_per_unit_area_4vector(range);
00261 PseudoJet sub_jet = subtracted_jet(jet, rho);
00262 return sub_jet;
00263 }
00264
00265
00267 double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
00268 const double rho,
00269 bool use_area_4vector) const {
00270 if ( use_area_4vector ) {
00271 PseudoJet sub_jet = subtracted_jet(jet,rho);
00272 return sub_jet.perp();
00273 } else {
00274 return jet.perp() - rho*area(jet);
00275 }
00276 }
00277
00278
00282 double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
00283 const RangeDefinition & range,
00284 bool use_area_4vector) const {
00285 if ( use_area_4vector ) {
00286 PseudoJet sub_jet = subtracted_jet(jet,range);
00287 return sub_jet.perp();
00288 } else {
00289 double rho = median_pt_per_unit_area(range);
00290 return subtracted_pt(jet,rho,false);
00291 }
00292 }
00293
00294
00296 void ClusterSequenceAreaBase::_check_jet_alg_good_for_median() const {
00297 if (jet_def().jet_algorithm() != kt_algorithm
00298 && jet_def().jet_algorithm() != cambridge_algorithm
00299 && jet_def().jet_algorithm() != cambridge_for_passive_algorithm) {
00300 _warnings.warn("ClusterSequenceAreaBase: jet_def being used may not be suitable for estimating diffuse backgrounds (good options are kt, cam)");
00301 }
00302 }
00303
00304
00305
00306 FASTJET_END_NAMESPACE