CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoParticleFlow/Benchmark/interface/PFBenchmarkAlgo.h

Go to the documentation of this file.
00001 #ifndef RecoParticleFlow_Benchmark_PFBenchmarkAlgo_h
00002 #define RecoParticleFlow_Benchmark_PFBenchmarkAlgo_h
00003 
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 #include "DataFormats/Common/interface/OwnVector.h"
00006 
00007 #include <cmath>
00008 #include <vector>
00009 
00010 // Notes on template implementation:
00011 // - T, U are arbitrary types (must have et(), eta(), etc. defined)
00012 //   support for Candidate-derived objects is explicit
00013 // - Collection is a generic container class. Support for edm::OwnVector
00014 //   and std::vector is explicit.
00015 
00016 class PFBenchmarkAlgo {
00017 public:
00018 
00019   // Calculate Delta-Et for the pair of Candidates (T - U)
00020   template <typename T, typename U>
00021   static double deltaEt(const T *, const U *);
00022 
00023   // Calculate Delta-Eta for the pair of Candidates (T - U)
00024   template <typename T, typename U>
00025   static double deltaEta(const T *, const U *);
00026 
00027   // Calculate Delta-Phi for the pair of Candidates (T - U)
00028   template <typename T, typename U>
00029   static double deltaPhi(const T *, const U *);
00030 
00031   // Calculate Delta-R for the pair of Candidates 
00032   template <typename T, typename U>
00033   static double deltaR(const T *, const U *);
00034 
00035   // Match Candidate T to a Candidate in the Collection based on minimum Delta-R
00036   template <typename T, typename Collection>
00037   static const typename Collection::value_type *matchByDeltaR(const T *, const Collection *);
00038   
00039   // Match Candidate T to a Candidate U in the Collection based on minimum Delta-Et
00040   template <typename T, typename Collection>
00041   static const typename Collection::value_type *matchByDeltaEt(const T *, const Collection *);
00042 
00043   // Copy the input Collection (useful when sorting)
00044   template <typename T, typename Collection>
00045   static Collection copyCollection(const Collection *);
00046 
00047   // Sort the U Candidates to the T Candidate based on minimum Delta-R
00048   template <typename T, typename Collection>
00049   static void sortByDeltaR(const T *, Collection &);
00050 
00051   // Sort the U Candidates to the T Candidate based on minimum Delta-Et
00052   template <typename T, typename Collection>
00053   static void sortByDeltaEt(const T *, Collection &);
00054 
00055   // Constrain the U Candidates to the T Candidate based on Delta-R to T
00056   template <typename T, typename Collection>
00057   static Collection findAllInCone(const T *, const Collection *, double);
00058 
00059   // Constrain the U Candidates to the T Candidate based on Delta-Et to T
00060   template <typename T, typename Collection>
00061   static Collection findAllInEtWindow(const T *, const Collection *, double);
00062 
00063 private:
00064 
00065   // std::vector sort helper function
00066   template <typename T, typename U, template <typename,typename> class Sorter>
00067   static void vector_sort(std::vector<T> &candidates, Sorter<T,U> S) {
00068     sort(candidates.begin(),candidates.end(),S);
00069   }
00070 
00071   // std::vector push_back helper function
00072   template <typename T>
00073   static void vector_add(const T *c1, std::vector<T> &candidates) {
00074     candidates.push_back(*c1);
00075   }
00076 
00077   // edm::OwnVector sort helper functions
00078   template <typename T, typename U, template <typename,typename> class Sorter>
00079   static void vector_sort(edm::OwnVector<T> &candidates, Sorter<T,U> S) {
00080     candidates.sort(S);
00081   }
00082 
00083   // edm::OwnVector push_back helper function
00084   template <typename T>
00085   static void vector_add(const T *c1, edm::OwnVector<T> &candidates) {
00086     candidates.push_back((T *const)c1->clone());
00087   }
00088 
00089 };
00090 
00091 // ========================================================================
00092 // implementation follows (required to be in header for templates)
00093 // ========================================================================
00094 
00095 // Helper class for sorting U Collections by Delta-R to a Candidate T
00096 template <typename T, typename U> class deltaRSorter {
00097 public:
00098 
00099   deltaRSorter(const T *Ref) { cref = Ref; }
00100   bool operator()(const U &c1, const U &c2) const {
00101     return PFBenchmarkAlgo::deltaR(cref,&c1) < PFBenchmarkAlgo::deltaR(cref,&c2);
00102   }
00103 
00104 private:
00105 
00106   const T *cref;
00107 
00108 };
00109 
00110 // Helper class for sorting U Collections by Delta-Et to a Candidate T
00111 template <typename T, typename U> class deltaEtSorter {
00112 public:
00113 
00114   deltaEtSorter(const T *Ref) { cref = Ref; }
00115   bool operator()(const U &c1, const U &c2) const {
00116     return fabs(PFBenchmarkAlgo::deltaEt(cref,&c1)) < fabs(PFBenchmarkAlgo::deltaEt(cref,&c2));
00117   }
00118 
00119 private:
00120 
00121   const T *cref;
00122 
00123 };
00124 
00125 // Calculate Delta-Et for Candidates (T - U)
00126 template <typename T, typename U>
00127 double PFBenchmarkAlgo::deltaEt(const T *c1, const U *c2) {
00128 
00129   if (c1 == NULL || c2 == NULL)
00130     throw cms::Exception("Invalid Arg") << "attempted to calculate deltaEt for invalid Candidate(s)";
00131 
00132   return c1->et() - c2->et();
00133 
00134 }
00135 
00136 // Calculate Delta-Eta for Candidates (T - U)
00137 template <typename T, typename U>
00138 double PFBenchmarkAlgo::deltaEta(const T *c1, const U *c2) {
00139 
00140   if (c1 == NULL || c2 == NULL)
00141     throw cms::Exception("Invalid Arg") << "attempted to calculate deltaEta for invalid Candidate(s)";
00142 
00143   return c1->eta() - c2->eta();
00144 
00145 }
00146 
00147 // Calculate Delta-Phi for Candidates (T - U)
00148 template <typename T, typename U>
00149 double PFBenchmarkAlgo::deltaPhi(const T *c1, const U *c2) {
00150 
00151   if (c1 == NULL || c2 == NULL)
00152     throw cms::Exception("Invalid Arg") << "attempted to calculate deltaPhi for invalid Candidate(s)";
00153 
00154   
00155   double phi1 = c1->phi();
00156   if (phi1 > M_PI) phi1 -= ceil((phi1 - M_PI) / (2 * M_PI)) * 2 * M_PI;
00157   if (phi1 <= - M_PI) phi1 += ceil((phi1 + M_PI) / (-2. * M_PI)) * 2. * M_PI;
00158 
00159   double phi2 = c2->phi();
00160   if (phi2 > M_PI) phi2 -= ceil((phi2 - M_PI) / (2 * M_PI)) * 2 * M_PI;
00161   if (phi2 <= - M_PI) phi2 += ceil((phi2 + M_PI) / (-2. * M_PI)) * 2 * M_PI;
00162 
00163   // alternative method:
00164   // while (phi > M_PI) phi -= 2 * M_PI;
00165   // while (phi <= - M_PI) phi += 2 * M_PI;
00166 
00167   double deltaphi=-999.0;
00168   if (fabs(phi1 - phi2)<M_PI)
00169   {
00170     deltaphi=(phi1-phi2);
00171   }
00172   else
00173   {
00174     if ((phi1-phi2)>0.0)
00175     {
00176       deltaphi=(2*M_PI - fabs(phi1 - phi2));
00177     }
00178     else
00179     {
00180       deltaphi=-(2*M_PI - fabs(phi1 - phi2));
00181     }
00182   }
00183   return deltaphi;
00184   //return ( (fabs(phi1 - phi2)<M_PI)?(phi1-phi2):(2*M_PI - fabs(phi1 - phi2) ) ); // FL: wrong
00185 }
00186  
00187 // Calculate Delta-R for Candidates 
00188 template <typename T, typename U>
00189 double PFBenchmarkAlgo::deltaR(const T *c1, const U *c2) {
00190 
00191   if (c1 == NULL || c2 == NULL)
00192     throw cms::Exception("Invalid Arg") << "attempted to calculate deltaR for invalid Candidate(s)";
00193 
00194   return sqrt(std::pow(deltaPhi(c1,c2),2) + std::pow(deltaEta(c1,c2),2));
00195 
00196 }
00197 
00198 // Match Candidate T to a Candidate in the Collection based on minimum Delta-R
00199 template <typename T, typename Collection>
00200 const typename Collection::value_type *PFBenchmarkAlgo::matchByDeltaR(const T *c1, const Collection *candidates) {
00201 
00202   typedef typename Collection::value_type U;
00203 
00204   // Try to verify the validity of the Candidate and Collection
00205   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to match invalid Candidate";
00206   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to match to invalid Collection";
00207 
00208   double minDeltaR = 9999.;
00209   const U *match = NULL;
00210   
00211   // Loop Over the Candidates...
00212   for (unsigned int i = 0; i < candidates->size(); i++) {
00213 
00214     const U *c2 = &(*candidates)[i];
00215     if (!c2) throw cms::Exception("Invalid Arg") << "attempted to match to invalid Candidate";
00216 
00217     // Find Minimal Delta-R
00218     double dR = deltaR(c1,c2);
00219     if (dR <= minDeltaR) { match = c2; minDeltaR = dR; }
00220   
00221   }
00222 
00223   // Return the Candidate with the smallest dR
00224   return match;
00225 
00226 }
00227 
00228 // Match Candidate T to a Candidate U in the Collection based on minimum Delta-Et
00229 template <typename T, typename Collection>
00230 const typename Collection::value_type *PFBenchmarkAlgo::matchByDeltaEt(const T *c1, const Collection *candidates) {
00231 
00232   typedef typename Collection::value_type U;
00233 
00234   // Try to verify the validity of the Candidate and Collection
00235   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to match invalid Candidate";
00236   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to match to invalid Collection";
00237 
00238   double minDeltaEt = 9999.;
00239   const U *match = NULL;
00240 
00241   // Loop Over the Candidates...
00242   for (unsigned int i = 0; i < candidates->size(); i++) {
00243 
00244     const T *c2 = &(*candidates)[i];
00245     if (!c2) throw cms::Exception("Invalid Arg") << "attempted to match to invalid Candidate";
00246 
00247     // Find Minimal Delta-R
00248     double dEt = fabs(deltaEt(c1,c2));
00249     if (dEt <= minDeltaEt) { match = c2; minDeltaEt = dEt; }
00250 
00251   }
00252 
00253   // Return the Candidate with the smallest dR
00254   return match;
00255 
00256 }
00257 
00258 // Copy the Collection (useful when sorting)
00259 template <typename T, typename Collection>
00260 Collection PFBenchmarkAlgo::copyCollection(const Collection *candidates) {
00261 
00262   typedef typename Collection::value_type U;
00263 
00264   // Try to verify the validity of the Collection
00265   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to copy invalid Collection";
00266 
00267   Collection copy;
00268 
00269   for (unsigned int i = 0; i < candidates->size(); i++)
00270     vector_add(&(*candidates)[i],copy);
00271 
00272   return copy;
00273 
00274 }
00275 
00276 
00277 // Sort the U Candidates to the Candidate T based on minimum Delta-R
00278 template <typename T, typename Collection>
00279 void PFBenchmarkAlgo::sortByDeltaR(const T *c1, Collection &candidates) {
00280 
00281   typedef typename Collection::value_type U;
00282 
00283   // Try to verify the validity of Candidate and Collection
00284   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to sort by invalid Candidate";
00285   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to sort invalid Candidates";
00286 
00287   // Sort the collection
00288   vector_sort(candidates,deltaRSorter<T,U>(c1));
00289 
00290 }
00291 
00292 // Sort the U Candidates to the Candidate T based on minimum Delta-Et
00293 template <typename T, typename Collection>
00294 void PFBenchmarkAlgo::sortByDeltaEt(const T *c1, Collection &candidates) {
00295 
00296   typedef typename Collection::value_type U;
00297 
00298   // Try to verify the validity of Candidate and Collection
00299   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to sort by invalid Candidate";
00300   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to sort invalid Candidates";
00301 
00302   // Sort the collection
00303   vector_sort(candidates,deltaEtSorter<T,U>(c1));
00304 
00305 }
00306 
00307 // Constrain the U Candidates to the T Candidate based on Delta-R to T
00308 template <typename T, typename Collection>
00309 Collection PFBenchmarkAlgo::findAllInCone(const T *c1, const Collection *candidates, double ConeSize) {
00310 
00311   typedef typename Collection::value_type U;
00312 
00313   // Try to verify the validity of Candidate and the Collection
00314   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to constrain to invalid Candidate";
00315   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to constrain invalid Collection";
00316   if (ConeSize <= 0) throw cms::Exception("Invalid Arg") << "zero or negative cone size specified";
00317 
00318   Collection constrained;
00319 
00320   for (unsigned int i = 0; i < candidates->size(); i++) {
00321 
00322     const U *c2 = &(*candidates)[i];
00323 
00324     // Add in-cone Candidates to the new Collection
00325     double dR = deltaR(c1,c2);
00326     if (dR < ConeSize) vector_add(c2,constrained);
00327 
00328   }
00329 
00330   // Sort and return Collection
00331   sortByDeltaR(c1,constrained);
00332   return constrained;
00333 
00334 }
00335 
00336 // Constrain the U Candidates to the T Candidate based on Delta-Et to T
00337 template <typename T, typename Collection>
00338 Collection PFBenchmarkAlgo::findAllInEtWindow(const T *c1, const Collection *candidates, double EtWindow) {
00339 
00340   typedef typename Collection::value_type U;
00341 
00342   // Try to verify the validity of Candidate and the Collection
00343   if (!c1) throw cms::Exception("Invalid Arg") << "attempted to constrain to invalid Candidate";
00344   if (!candidates) throw cms::Exception("Invalid Arg") << "attempted to constrain invalid Collection";
00345   if (EtWindow <= 0) throw cms::Exception("Invalid Arg") << "zero or negative cone size specified";
00346 
00347   Collection constrained;
00348 
00349   //CandidateCollection::const_iterator candidate;
00350   //for (candidate = candidates->begin(); candidate != candidates->end(); candidate++) {
00351   for (unsigned int i = 0; i < candidates->size(); i++) {
00352 
00353     const U *c2 = &(*candidates)[i];
00354 
00355     // Add in-cone Candidates to the new Collection
00356     double dEt = fabs(deltaEt(c1,c2));
00357     if (dEt < EtWindow) vector_add(c2,constrained);
00358 
00359   }
00360 
00361   // Sort and return Collection
00362   sortByDeltaEt(c1,constrained);
00363   return constrained;
00364 
00365 }
00366 
00367 #endif // RecoParticleFlow_Benchmark_PFBenchmarkAlgo_h