ClusterSequenceAreaBase.cc

Go to the documentation of this file.
00001 
00002 //STARTHEADER
00003 // $Id: ClusterSequenceAreaBase.cc 1503 2009-04-06 11:32:52Z salam $
00004 //
00005 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
00006 //
00007 //----------------------------------------------------------------------
00008 // This file is part of FastJet.
00009 //
00010 //  FastJet is free software; you can redistribute it and/or modify
00011 //  it under the terms of the GNU General Public License as published by
00012 //  the Free Software Foundation; either version 2 of the License, or
00013 //  (at your option) any later version.
00014 //
00015 //  The algorithms that underlie FastJet have required considerable
00016 //  development and are described in hep-ph/0512210. If you use
00017 //  FastJet as part of work towards a scientific publication, please
00018 //  include a citation to the FastJet paper.
00019 //
00020 //  FastJet is distributed in the hope that it will be useful,
00021 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 //  GNU General Public License for more details.
00024 //
00025 //  You should have received a copy of the GNU General Public License
00026 //  along with FastJet; if not, write to the Free Software
00027 //  Foundation, Inc.:
00028 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029 //----------------------------------------------------------------------
00030 //ENDHEADER
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 //----------------------------------------------------------------------
00054 double ClusterSequenceAreaBase::empty_area(const RangeDefinition & range) const {
00055 
00056   if (has_explicit_ghosts()) {return 0.0;}
00057   else { return empty_area_from_jets(inclusive_jets(0.0), range);}
00058 
00059 }
00060 
00061 //----------------------------------------------------------------------
00066 double ClusterSequenceAreaBase::empty_area_from_jets(
00067                       const std::vector<PseudoJet> & all_jets,
00068                       const RangeDefinition & range) const {
00069 
00070   double empty = range.area();
00071   for (unsigned i = 0; i < all_jets.size(); i++) {
00072     if (range.is_in_range(all_jets[i])) empty -= area(all_jets[i]);
00073   }
00074   return empty;
00075 }
00076 
00077 double ClusterSequenceAreaBase::median_pt_per_unit_area(const RangeDefinition & range) const {
00078   return median_pt_per_unit_something(range,false);
00079 }
00080 
00081 double ClusterSequenceAreaBase::median_pt_per_unit_area_4vector(const RangeDefinition & range) const {
00082   return median_pt_per_unit_something(range,true);
00083 }
00084 
00085 
00086 //----------------------------------------------------------------------
00090 double ClusterSequenceAreaBase::median_pt_per_unit_something(
00091                 const RangeDefinition & range, bool use_area_4vector) const {
00092 
00093   double median, sigma, mean_area;
00094   get_median_rho_and_sigma(range, use_area_4vector, median, sigma, mean_area);
00095   return median;
00096 
00097 }
00098 
00099 
00100 //----------------------------------------------------------------------
00104 void ClusterSequenceAreaBase::parabolic_pt_per_unit_area(
00105        double & a, double & b, const RangeDefinition & range, 
00106        double exclude_above, bool use_area_4vector) const {
00107   
00108   int n=0;
00109   int n_excluded = 0;
00110   double mean_f=0, mean_x2=0, mean_x4=0, mean_fx2=0; 
00111 
00112   vector<PseudoJet> incl_jets = inclusive_jets();
00113 
00114   for (unsigned i = 0; i < incl_jets.size(); i++) {
00115     if (range.is_in_range(incl_jets[i])) {
00116       double this_area;
00117       if ( use_area_4vector ) {
00118           this_area = area_4vector(incl_jets[i]).perp();     
00119       } else {
00120           this_area = area(incl_jets[i]);
00121       }
00122       double f = incl_jets[i].perp()/this_area;
00123       if (exclude_above <= 0.0 || f < exclude_above) {
00124         double x = incl_jets[i].rap(); double x2 = x*x;
00125         mean_f   += f;
00126         mean_x2  += x2;
00127         mean_x4  += x2*x2;
00128         mean_fx2 += f*x2;
00129         n++;
00130       } else {
00131         n_excluded++;
00132       }
00133     }
00134   }
00135 
00136   if (n <= 1) {
00137     // meaningful results require at least two jets inside the
00138     // area -- mind you if there are empty jets we should be in 
00139     // any case doing something special...
00140     a = 0.0;
00141     b = 0.0;
00142   } else {
00143     mean_f   /= n;
00144     mean_x2  /= n;
00145     mean_x4  /= n;
00146     mean_fx2 /= n;
00147     
00148     b = (mean_f*mean_x2 - mean_fx2)/(mean_x2*mean_x2 - mean_x4);
00149     a = mean_f - b*mean_x2;
00150   }
00151   //cerr << "n_excluded = "<< n_excluded << endl;
00152 }
00153 
00154 
00155 
00156 void ClusterSequenceAreaBase::get_median_rho_and_sigma(
00157             const RangeDefinition & range, bool use_area_4vector,
00158             double & median, double & sigma, double & mean_area) const {
00159 
00160   vector<PseudoJet> incl_jets = inclusive_jets();
00161   get_median_rho_and_sigma(incl_jets, range, use_area_4vector,
00162                            median, sigma, mean_area, true);
00163 }
00164 
00165 
00166 void ClusterSequenceAreaBase::get_median_rho_and_sigma(
00167             const vector<PseudoJet> & all_jets,
00168             const RangeDefinition & range, bool use_area_4vector,
00169             double & median, double & sigma, double & mean_area,
00170             bool all_are_incl) const {
00171 
00172   _check_jet_alg_good_for_median();
00173 
00174   vector<double> pt_over_areas;
00175   double total_area  = 0.0;
00176   double total_njets = 0;
00177 
00178   for (unsigned i = 0; i < all_jets.size(); i++) {
00179     if (range.is_in_range(all_jets[i])) {
00180       double this_area;
00181       if (use_area_4vector) {
00182           this_area = area_4vector(all_jets[i]).perp();
00183       } else {
00184           this_area = area(all_jets[i]);
00185       }
00186       pt_over_areas.push_back(all_jets[i].perp()/this_area);
00187       total_area  += this_area;
00188       total_njets += 1.0;
00189     }
00190   }
00191 
00192   // there is nothing inside our region, so answer will always be zero
00193   if (pt_over_areas.size() == 0) {
00194     median = 0.0;
00195     sigma  = 0.0;
00196     mean_area = 0.0;
00197     return;
00198   }
00199   
00200   // get median (pt/area) [this is the "old" median definition. It considers
00201   // only the "real" jets in calculating the median, i.e. excluding the
00202   // only-ghost ones; it will be supplemented with more info below]
00203   sort(pt_over_areas.begin(), pt_over_areas.end());
00204 
00205   // now get the median & error, accounting for empty jets
00206   // define the fractions of distribution at median, median-1sigma
00207   double posn[2] = {0.5, (1.0-0.6827)/2.0};
00208   double res[2];
00209   
00210   double n_empty, empty_a;
00211   if (has_explicit_ghosts()) {
00212     // NB: the following lines of code are potentially incorrect in cases
00213     //     where there are unclustered particles (empty_area would do a better job,
00214     //     at least for active areas). This is not an issue with kt or C/A, or other
00215     //     algorithms that cluster all particles (and the median estimation should in 
00216     //     any case only be done with kt or C/A!)
00217     empty_a = 0.0;
00218     n_empty = 0;
00219   } else if (all_are_incl) {
00220     // the default case
00221     empty_a = empty_area(range);
00222     n_empty = n_empty_jets(range);
00223   } else {
00224     // this one is intended to be used when e.g. one runs C/A, then looks at its
00225     // exclusive jets in order to get an effective smaller R value, and passes those
00226     // to this routine.
00227     empty_a = empty_area_from_jets(all_jets, range);
00228     mean_area = total_area / total_njets; // temporary value
00229     n_empty   = empty_a / mean_area;
00230   }
00231   //cout << "*** tot_area = " << total_area << ", empty_a = " << empty_a << endl;
00232   //cout << "*** n_empty = " << n_empty << ", ntotal =  " << total_njets << endl;
00233   total_njets += n_empty;
00234   total_area  += empty_a;
00235 
00236   for (int i = 0; i < 2; i++) {
00237     double nj_median_pos = 
00238       (pt_over_areas.size()-1 + n_empty)*posn[i] - n_empty;
00239     double nj_median_ratio;
00240     if (nj_median_pos >= 0 && pt_over_areas.size() > 1) {
00241       int int_nj_median = int(nj_median_pos);
00242       nj_median_ratio = 
00243         pt_over_areas[int_nj_median] * (int_nj_median+1-nj_median_pos)
00244         + pt_over_areas[int_nj_median+1] * (nj_median_pos - int_nj_median);
00245     } else {
00246       nj_median_ratio = 0.0;
00247     }
00248     res[i] = nj_median_ratio;
00249   }
00250   median = res[0];
00251   double error  = res[0] - res[1];
00252   mean_area = total_area / total_njets;
00253   sigma  = error * sqrt(mean_area);
00254 }
00255 
00256 
00261 vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(const double rho,
00262                                                            const double ptmin) 
00263                                                            const {
00264   vector<PseudoJet> sub_jets;
00265   vector<PseudoJet> jets = sorted_by_pt(inclusive_jets(ptmin));
00266   for (unsigned i=0; i<jets.size(); i++) {
00267      PseudoJet sub_jet = subtracted_jet(jets[i],rho);
00268      sub_jets.push_back(sub_jet);
00269   }
00270   return sub_jets;
00271 }
00272 
00277 vector<PseudoJet> ClusterSequenceAreaBase::subtracted_jets(
00278                                                  const RangeDefinition & range, 
00279                                                  const double ptmin)
00280                                                  const {
00281   double rho = median_pt_per_unit_area_4vector(range);
00282   return subtracted_jets(rho,ptmin);
00283 }
00284 
00285 
00287 PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
00288                                                   const double rho) const {
00289   PseudoJet area4vect = area_4vector(jet);
00290   PseudoJet sub_jet;
00291   // sanity check
00292   if (rho*area4vect.perp() < jet.perp() ) { 
00293     sub_jet = jet - rho*area4vect;
00294   } else { sub_jet = PseudoJet(0.0,0.0,0.0,0.0); }
00295   
00296   // make sure the subtracted jet has the same index (cluster and user)
00297   // (i.e. "looks like") the original jet
00298   sub_jet.set_cluster_hist_index(jet.cluster_hist_index());
00299   sub_jet.set_user_index(jet.user_index());
00300   
00301   return sub_jet;
00302 }
00303 
00304 
00308 PseudoJet ClusterSequenceAreaBase::subtracted_jet(const PseudoJet & jet,
00309                                        const RangeDefinition & range) const {
00310   double rho = median_pt_per_unit_area_4vector(range);
00311   PseudoJet sub_jet = subtracted_jet(jet, rho);
00312   return sub_jet;
00313 }
00314 
00315 
00317 double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
00318                                               const double rho,
00319                                               bool use_area_4vector) const {
00320   if ( use_area_4vector ) { 
00321      PseudoJet sub_jet = subtracted_jet(jet,rho);
00322      return sub_jet.perp();
00323   } else {
00324      return jet.perp() - rho*area(jet);
00325   }
00326 }  
00327 
00328 
00332 double ClusterSequenceAreaBase::subtracted_pt(const PseudoJet & jet,
00333                                               const RangeDefinition & range,
00334                                               bool use_area_4vector) const {
00335   if ( use_area_4vector ) { 
00336      PseudoJet sub_jet = subtracted_jet(jet,range);
00337      return sub_jet.perp();
00338   } else {
00339      double rho = median_pt_per_unit_area(range);
00340      return subtracted_pt(jet,rho,false);
00341   }
00342 }  
00343 
00344 
00346 void ClusterSequenceAreaBase::_check_jet_alg_good_for_median() const {
00347   if (jet_def().jet_algorithm() != kt_algorithm
00348       && jet_def().jet_algorithm() != cambridge_algorithm
00349       && jet_def().jet_algorithm() !=  cambridge_for_passive_algorithm) {
00350     _warnings.warn("ClusterSequenceAreaBase: jet_def being used may not be suitable for estimating diffuse backgrounds (good options are kt, cam)");
00351   }
00352 }
00353 
00354 
00355 
00356 FASTJET_END_NAMESPACE

Generated on Fri Apr 17 16:15:10 2009 for fastjet by  doxygen 1.5.7.1