CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/Geometry/TrackerNumberingBuilder/plugins/TrackerStablePhiSort.h

Go to the documentation of this file.
00001 #ifndef TrackerStablePhiSort_H
00002 #define TrackerStablePhiSort_H
00003 // #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 
00005 #include<iostream>
00006 
00007 #include <utility>
00008 #include <vector>
00009 #include <algorithm>
00010 
00011 #include <cmath>
00012 
00013 #include<boost/bind.hpp>
00014 
00015 namespace details {
00016   template<typename Object, typename Scalar> 
00017   struct PhiSortElement {
00018     typedef PhiSortElement<Object,Scalar> self;
00019     
00020     template<typename Extractor>
00021     static self 
00022     build(Object & o, Extractor const & extr) { 
00023       return self(&o, extr(o));
00024     }
00025     
00026     PhiSortElement(){}
00027     PhiSortElement(Object * p, Scalar v):
00028       pointer(p),
00029       value(v) {}
00030     
00031     Object * pointer;
00032     Scalar value;
00033     
00034     bool operator<(self const & rh) const {
00035       return value<rh.value;
00036     }
00037     Object const &
00038     obj() const { return *pointer;}
00039   };
00040   
00041   
00042 }
00043 
00044 template<typename RandomAccessIterator, typename Extractor>
00045 void TrackerStablePhiSort(RandomAccessIterator begin,
00046                           RandomAccessIterator end,
00047                           const Extractor& extr) {
00048   
00049   typedef typename Extractor::result_type        Scalar;
00050   typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
00051   
00052   typedef details::PhiSortElement<value_type, Scalar> Element;
00053   
00054   
00055   
00056   std::vector<Element> tmpvec(end-begin);
00057   std::transform(begin,end,tmpvec.begin(),
00058                  boost::bind(Element::template build<Extractor>,_1, boost::cref(extr))
00059                  );
00060   
00061   std::vector<Element> tmpcop(end-begin);
00062   
00063   std::sort(tmpvec.begin(), tmpvec.end());
00064   
00065   const unsigned int vecSize = tmpvec.size();
00066   
00067   
00068   
00069   // special tratment of the TEC modules of rings in petals near phi=0
00070   // there are at most 5 modules, no other structure has less than ~10 elements to order in phi
00071   // hence the special case in phi~0 if the size of the elements to order is <=5
00072   const unsigned int nMaxModulesPerRing = 5;
00073   bool phiZeroCase = true;
00074   //
00075   const double phiMin = M_PI_4;
00076   const double phiMax = 2*M_PI-phiMin;
00077   //
00078   if( vecSize > nMaxModulesPerRing ) {
00079     //stability check
00080     // check if the last element is too near to zero --> probably it is zero
00081     double tolerance = 0.000001;
00082     if( fabs(tmpvec.back().value - 0) < tolerance       // near 0
00083         ||
00084         fabs(tmpvec.back().value - 2*M_PI) < tolerance ) { // near 2pi
00085       // move it to front 
00086       tmpvec.insert(tmpvec.begin(),tmpvec.back());
00087       tmpvec.pop_back();
00088     }
00089   }
00090   else {
00091     // check if all the elements have phi<phiMin or phi>phiMax to be sure we are near phi~0 (angles are in [0,2pi) range)
00092     // if a phi goes out from [0,phiMin]U[phiMax,2pi) it is not the case
00093     // sorted. if first > phiMax all other will also...
00094     typename std::vector<Element>::iterator p = 
00095       std::find_if(tmpvec.begin(),tmpvec.end(), boost::bind(&Element::value,_1) > phiMin);
00096     phiZeroCase = !(p!=tmpvec.end() && (*p).value<phiMax);
00097     
00098     // go on if this is the petal phi~0 case, restricted to the case where all the |phi| are in range [0,phiMin]
00099     if(phiZeroCase) {
00100       // in this case the ordering must be: ('negative' values, >) and then ('positive' values, >) in (-pi,pi] mapping
00101       // already sorted, just swap ranges
00102       if(p!=tmpvec.end()) {
00103         tmpvec.insert(tmpvec.begin(),p,tmpvec.end());
00104         tmpvec.resize(vecSize);
00105       }
00106     }
00107   }
00108   
00109   // overwrite the input range with the sorted values
00110   // copy of input container not necessary, but tricky to avoid
00111   std::vector<value_type> tmpvecy(vecSize);
00112   std::transform(tmpvec.begin(),tmpvec.end(),tmpvecy.begin(),boost::bind(&Element::obj,_1));
00113   std::copy(tmpvecy.begin(),tmpvecy.end(),begin);
00114   
00115 }
00116 
00117 #endif
00118