Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:15:28

0001 #ifndef Geometry_TrackerNumberingBuilder_trackerStablePhiSort_H
0002 #define Geometry_TrackerNumberingBuilder_trackerStablePhiSort_H
0003 
0004 #include <vector>
0005 #include <algorithm>
0006 #include <cmath>
0007 
0008 template <class RandomAccessIterator, class Extractor>
0009 void trackerStablePhiSort(RandomAccessIterator begin, RandomAccessIterator end, const Extractor& extr) {
0010   using Scalar = decltype(extr(*begin));
0011   using Value = typename std::iterator_traits<RandomAccessIterator>::value_type;
0012   using Element = std::pair<Scalar, Value*>;
0013 
0014   std::vector<Element> tmpvec(end - begin);
0015   std::transform(begin, end, tmpvec.begin(), [&extr](Value& it) { return Element(extr(it), &it); });
0016 
0017   std::sort(tmpvec.begin(), tmpvec.end());
0018 
0019   // special tratment of the TEC modules of rings in petals near phi=0 there
0020   // are at most 5 modules, no other structure has less than ~10 elements to
0021   // order in phi hence the special case in phi~0 if the size of the elements
0022   // to order is <=5
0023   constexpr unsigned int nMaxModulesPerRing = 5;
0024   constexpr double phiMin = M_PI_4;
0025   constexpr double phiMax = 2 * M_PI - phiMin;
0026   constexpr double tolerance = 0.000001;
0027 
0028   const unsigned int n = tmpvec.size();
0029 
0030   if (n > nMaxModulesPerRing) {
0031     // stability check
0032     // check if the last element is too near to zero --> probably it is zero
0033     if (std::abs(tmpvec.back().first - 0) < tolerance             // near 0
0034         || std::abs(tmpvec.back().first - 2 * M_PI) < tolerance)  // near 2pi
0035     {
0036       // move it to front
0037       tmpvec.insert(tmpvec.begin(), tmpvec.back());
0038       tmpvec.pop_back();
0039     }
0040   } else {
0041     // check if all the elements have phi<phiMin or phi>phiMax to be sure we
0042     // are near phi~0 (angles are in [0,2pi) range) if a phi goes out from
0043     // [0,phiMin]U[phiMax,2pi) it is not the case sorted. if first > phiMax all
0044     // other will also...
0045     auto p = std::find_if(tmpvec.begin(), tmpvec.end(), [&phiMin](auto const& x) { return x.first > phiMin; });
0046 
0047     // go on if this is the petal phi~0 case, restricted to the case where all
0048     // the |phi| are in range [0,phiMin]
0049     if (p == tmpvec.end() || p->first >= phiMax) {
0050       // in this case the ordering must be: ('negative' values, >) and then
0051       // ('positive' values, >) in (-pi,pi] mapping already sorted, just swap
0052       // ranges
0053       if (p != tmpvec.end()) {
0054         tmpvec.insert(tmpvec.begin(), p, tmpvec.end());
0055         tmpvec.resize(n);
0056       }
0057     }
0058   }
0059 
0060   // overwrite the input range with the sorted values
0061   // copy of input container not necessary, but tricky to avoid
0062   std::vector<Value> tmpvecy(n);
0063   std::transform(tmpvec.begin(), tmpvec.end(), tmpvecy.begin(), [](auto& x) { return *x.second; });
0064   std::copy(tmpvecy.begin(), tmpvecy.end(), begin);
0065 }
0066 
0067 #endif