CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoMuon/DetLayers/src/PhiBorderFinder.h

Go to the documentation of this file.
00001 #ifndef PhiBorderFinder_H
00002 #define PhiBorderFinder_H
00003 
00014 #include <Geometry/CommonDetUnit/interface/GeomDet.h>
00015 
00016 #include <DataFormats/GeometrySurface/interface/BoundingBox.h>
00017 #include <DataFormats/GeometrySurface/interface/GeometricSorting.h>
00018 
00019 #include <DataFormats/GeometryVector/interface/Pi.h>
00020 #include <Utilities/General/interface/precomputed_value_sort.h>
00021 #include <TrackingTools/DetLayers/interface/simple_stat.h>
00022 #include <FWCore/Utilities/interface/Exception.h>
00023 
00024 // FIXME: remove this include
00025 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00026 
00027 #include <vector>
00028 
00029 class PhiBorderFinder {
00030 public:
00031   
00032   typedef DetRod Det; //FIXME!!!
00033   typedef geomsort::ExtractPhi<Det,float> DetPhi;
00034 
00035 
00036   PhiBorderFinder(std::vector<const Det*> theDets) 
00037     : theNbins(theDets.size()), isPhiPeriodic_(false), isPhiOverlapping_(false) {
00038     precomputed_value_sort(theDets.begin(), theDets.end(), DetPhi());
00039 
00040     const std::string metname = "Muon|RecoMuon|RecoMuonDetLayers|PhiBorderFinder";
00041 
00042     double step = 2.*Geom::pi()/theNbins;
00043 
00044     LogTrace(metname) << "RecoMuonDetLayers::PhiBorderFinder "
00045                       << "step w: " << step << " # of bins: " << theNbins;
00046     
00047     std::vector<double> spread(theNbins);
00048     std::vector<std::pair<double,double> > phiEdge;
00049     phiEdge.reserve(theNbins);
00050     thePhiBorders.reserve(theNbins);
00051     thePhiBins.reserve(theNbins);
00052     for ( unsigned int i = 0; i < theNbins; i++ ) {
00053       thePhiBins.push_back(theDets[i]->position().phi());
00054       spread.push_back(theDets[i]->position().phi()
00055         - (theDets[0]->position().phi() + i*step));
00056       
00057       LogTrace(metname) << "bin: " << i << " phi bin: " << thePhiBins[i]
00058                         << " spread: " <<  spread[i];
00059       
00060 
00061       ConstReferenceCountingPointer<BoundPlane> plane = 
00062         dynamic_cast<const BoundPlane*>(&theDets[i]->surface());
00063       if (plane==0) {
00064         //FIXME
00065         throw cms::Exception("UnexpectedState") << ("PhiBorderFinder: det surface is not a BoundPlane");
00066       }
00067       
00068       std::vector<GlobalPoint> dc = 
00069         BoundingBox().corners(*plane);
00070 
00071       float phimin(999.), phimax(-999.);
00072       for (std::vector<GlobalPoint>::const_iterator pt=dc.begin();
00073            pt!=dc.end(); pt++) {
00074         float phi = (*pt).phi();
00075 //      float z = pt->z();
00076         if (phi < phimin) phimin = phi;
00077         if (phi > phimax) phimax = phi;
00078       }
00079       if (phimin*phimax < 0. &&           //Handle pi border:
00080           phimax - phimin > Geom::pi()) { //Assume that the Det is on
00081                                           //the shortest side 
00082         std::swap(phimin,phimax);
00083       }
00084       phiEdge.push_back(std::pair<double,double>(phimin,phimax));
00085     }
00086     
00087     for (unsigned int i = 0; i < theNbins; i++) {
00088       
00089       // Put the two phi values in the [0,2pi] range
00090       double firstPhi  = positiveRange(phiEdge[i].first);
00091       double secondPhi = positiveRange(phiEdge[binIndex(i-1)].second);
00092 
00093       // Reformat them in the [-pi,pi] range
00094       Geom::Phi<double> firstEdge(firstPhi);
00095       Geom::Phi<double> secondEdge(secondPhi);
00096 
00097       // Calculate the mean and format the result in the [-pi,pi] range
00098       // Get their value in order to perform the mean in the correct way
00099       Geom::Phi<double> mean((firstEdge.value() + secondEdge.value())/2.);
00100       
00101       // Special case: at +-pi there is a discontinuity
00102       if ( phiEdge[i].first * phiEdge[binIndex(i-1)].second < 0 &&
00103            fabs(firstPhi-secondPhi) < Geom::pi() ) 
00104         mean = Geom::pi() - mean;
00105      
00106       thePhiBorders.push_back(mean);
00107     }
00108   
00109     for (unsigned int i = 0; i < theNbins; i++) {
00110       if (Geom::Phi<double>(phiEdge[i].first)
00111           - Geom::Phi<double>(phiEdge[binIndex(i-1)].second) < 0) {
00112         isPhiOverlapping_ = true;
00113         break;
00114       }
00115     }
00116 
00117     double rms = stat_RMS(spread); 
00118     if ( rms < 0.01*step) { 
00119       isPhiPeriodic_ = true;
00120     }
00121 
00122     //Check that everything is proper
00123     if (thePhiBorders.size() != theNbins || thePhiBins.size() != theNbins) 
00124       //FIXME
00125       throw cms::Exception("UnexpectedState") << "PhiBorderFinder: consistency error";
00126   }
00127   
00128 
00129   virtual ~PhiBorderFinder(){};
00130 
00131   inline unsigned int nBins() {return theNbins;}
00132 
00134   inline bool isPhiPeriodic() const { return isPhiPeriodic_; }
00135   
00137   inline bool isPhiOverlapping() const { return isPhiOverlapping_; }
00138 
00141   inline const std::vector<double>& phiBorders() const { return thePhiBorders; }
00142 
00144   inline const std::vector<double>& phiBins() const { return thePhiBins; }
00145 
00146   //  inline std::vector<double> etaBorders() {}
00147   //  inline std::vector<double> zBorders() {}
00148 
00149 private:
00150   unsigned int theNbins;
00151   bool isPhiPeriodic_;
00152   bool isPhiOverlapping_;
00153   std::vector<double> thePhiBorders;
00154   std::vector<double> thePhiBins;
00155 
00156   inline double positiveRange (double phi) const
00157   {
00158     return (phi > 0) ? phi : phi + Geom::twoPi();
00159   }
00160 
00161   int binIndex( int i) const {
00162     int ind = i % (int)theNbins;
00163     return (ind < 0) ? ind+theNbins : ind;
00164   }
00165 
00166 
00167 };
00168 #endif
00169