CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/RecoPixelVertexing/PixelTriplets/plugins/PixelTripletLargeTipGenerator.cc

Go to the documentation of this file.
00001 #include "RecoPixelVertexing/PixelTriplets/plugins/PixelTripletLargeTipGenerator.h"
00002 
00003 #include "RecoPixelVertexing/PixelTriplets/interface/ThirdHitPredictionFromCircle.h"
00004 #include "RecoPixelVertexing/PixelTriplets/interface/ThirdHitRZPrediction.h"
00005 #include "RecoTracker/TkMSParametrization/interface/PixelRecoUtilities.h"
00006 #include "FWCore/Framework/interface/ESHandle.h"
00007 
00008 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00009 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00010 #include "RecoPixelVertexing/PixelTriplets/plugins/ThirdHitCorrection.h"
00011 #include "RecoTracker/TkHitPairs/interface/RecHitsSortedInPhi.h"
00012 
00013 #include "MatchedHitRZCorrectionFromBending.h"
00014 //#include "RecoParticleFlow/PFProducer/interface/KDTreeLinkerAlgo.h"
00015 //#include "RecoParticleFlow/PFProducer/interface/KDTreeLinkerTools.h"
00016 #include "RecoPixelVertexing/PixelTriplets/plugins/KDTreeLinkerAlgo.h" //amend to point at your copy...
00017 #include "RecoPixelVertexing/PixelTriplets/plugins/KDTreeLinkerTools.h"
00018 
00019 #include <algorithm>
00020 #include <iostream>
00021 #include <vector>
00022 #include <cmath>
00023 #include <map>
00024 
00025 using namespace std;
00026 using namespace ctfseeding;
00027 
00028 typedef PixelRecoRange<float> Range;
00029 
00030 typedef ThirdHitPredictionFromCircle::HelixRZ HelixRZ;
00031 
00032 namespace {
00033   struct LayerRZPredictions {
00034     ThirdHitRZPrediction<PixelRecoLineRZ> line;
00035     ThirdHitRZPrediction<HelixRZ> helix1, helix2;
00036     MatchedHitRZCorrectionFromBending rzPositionFixup;
00037   };
00038 }
00039 
00040 constexpr double nSigmaRZ = 3.4641016151377544; // sqrt(12.)
00041 constexpr double nSigmaPhi = 3.;
00042 static float fnSigmaRZ = std::sqrt(12.f);
00043 
00044 PixelTripletLargeTipGenerator::PixelTripletLargeTipGenerator(const edm::ParameterSet& cfg)
00045   : thePairGenerator(0),
00046     theLayerCache(0),
00047     useFixedPreFiltering(cfg.getParameter<bool>("useFixedPreFiltering")),
00048     extraHitRZtolerance(cfg.getParameter<double>("extraHitRZtolerance")),
00049     extraHitRPhitolerance(cfg.getParameter<double>("extraHitRPhitolerance")),
00050     useMScat(cfg.getParameter<bool>("useMultScattering")),
00051     useBend(cfg.getParameter<bool>("useBending"))
00052 {    theMaxElement=cfg.getParameter<unsigned int>("maxElement");
00053   if (useFixedPreFiltering)
00054     dphi = cfg.getParameter<double>("phiPreFiltering");
00055 }
00056 
00057 void PixelTripletLargeTipGenerator::init(const HitPairGenerator & pairs,
00058                                          const std::vector<SeedingLayer> &layers,
00059                                          LayerCacheType *layerCache)
00060 {
00061   thePairGenerator = pairs.clone();
00062   theLayers = layers;
00063   theLayerCache = layerCache;
00064 }
00065 
00066 static bool intersect(Range &range, const Range &second)
00067 {
00068   if (range.first >= second.max() || range.second <= second.min())
00069     return false;
00070   if (range.first < second.min())
00071     range.first = second.min();
00072   if (range.second > second.max())
00073     range.second = second.max();
00074   return range.first < range.second;
00075 }
00076 
00077 void PixelTripletLargeTipGenerator::hitTriplets(const TrackingRegion& region, 
00078                                                 OrderedHitTriplets & result,
00079                                                 const edm::Event & ev,
00080                                                 const edm::EventSetup& es)
00081 { edm::ESHandle<TrackerGeometry> tracker;
00082   es.get<TrackerDigiGeometryRecord>().get(tracker);
00083   
00084   OrderedHitPairs pairs;
00085   pairs.reserve(30000);
00086   thePairGenerator->hitPairs(region,pairs,ev,es);
00087   if (pairs.empty())
00088     return;
00089   
00090   int size = theLayers.size();
00091 
00092   std::vector<KDTreeNodeInfo<RecHitsSortedInPhi::HitIter> > layerTree; // re-used throughout
00093   std::vector<KDTreeLinkerAlgo<RecHitsSortedInPhi::HitIter> > hitTree(size);
00094   std::vector<float> rzError(size,0.0f); //save maximum errors
00095   double maxphi = Geom::twoPi(), minphi = -maxphi; //increase to cater for any range
00096 
00097   map<const DetLayer*, LayerRZPredictions> mapPred;
00098   const RecHitsSortedInPhi **thirdHitMap = new const RecHitsSortedInPhi*[size];
00099   for(int il = 0; il < size; il++) {
00100     thirdHitMap[il] = &(*theLayerCache)(&theLayers[il], region, ev, es);
00101     const DetLayer *layer = theLayers[il].detLayer();
00102     LayerRZPredictions &predRZ = mapPred[layer];
00103     predRZ.line.initLayer(layer);
00104     predRZ.helix1.initLayer(layer);
00105     predRZ.helix2.initLayer(layer);
00106     predRZ.line.initTolerance(extraHitRZtolerance);
00107     predRZ.helix1.initTolerance(extraHitRZtolerance);
00108     predRZ.helix2.initTolerance(extraHitRZtolerance);
00109     predRZ.rzPositionFixup = MatchedHitRZCorrectionFromBending(layer);
00110     
00111     RecHitsSortedInPhi::Range hitRange = thirdHitMap[il]->all(); // Get iterators
00112     layerTree.clear();
00113     double minz=999999.0, maxz= -999999.0; // Initialise to extreme values in case no hits
00114     float maxErr=0.0f;
00115     bool barrelLayer = (theLayers[il].detLayer()->location() == GeomDetEnumerators::barrel);
00116     if (hitRange.first != hitRange.second)
00117       { minz = barrelLayer? hitRange.first->hit()->globalPosition().z() : hitRange.first->hit()->globalPosition().perp();
00118         maxz = minz; //In case there's only one hit on the layer
00119         for (RecHitsSortedInPhi::HitIter hi=hitRange.first; hi != hitRange.second; ++hi)
00120           { double angle = hi->phi();
00121             double myz = barrelLayer? hi->hit()->globalPosition().z() : hi->hit()->globalPosition().perp();
00122             //use (phi,r) for endcaps rather than (phi,z)
00123             if (myz < minz) { minz = myz;} else { if (myz > maxz) {maxz = myz;}}
00124             float myerr = barrelLayer? hi->hit()->errorGlobalZ(): hi->hit()->errorGlobalR();
00125             if (myerr > maxErr) { maxErr = myerr;}
00126             layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle, myz)); // save it
00127             if (angle < 0)  // wrap all points in phi
00128               { layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle+Geom::twoPi(), myz));}
00129             else
00130               { layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle-Geom::twoPi(), myz));}
00131           }
00132       }
00133     KDTreeBox phiZ(minphi, maxphi, minz-0.01, maxz+0.01);  // declare our bounds
00134     //add fudge factors in case only one hit and also for floating-point inaccuracy
00135     hitTree[il].build(layerTree, phiZ); // make KDtree
00136     rzError[il] = maxErr; //save error
00137   }
00138   
00139   double curv = PixelRecoUtilities::curvature(1. / region.ptMin(), es);
00140   
00141   for (OrderedHitPairs::const_iterator ip = pairs.begin(); ip != pairs.end(); ++ip) {
00142     GlobalPoint gp1 = ip->inner()->globalPosition();
00143     GlobalPoint gp2 = ip->outer()->globalPosition();
00144 
00145     PixelRecoLineRZ line(gp1, gp2);
00146     PixelRecoPointRZ point2(gp2.perp(), gp2.z());
00147     ThirdHitPredictionFromCircle predictionRPhi(gp1, gp2, extraHitRPhitolerance);
00148 
00149     Range generalCurvature = predictionRPhi.curvature(region.originRBound());
00150     if (!intersect(generalCurvature, Range(-curv, curv)))
00151       continue;
00152 
00153     for(int il = 0; il < size; il++) {
00154       if (hitTree[il].empty()) continue; // Don't bother if no hits
00155       const DetLayer *layer = theLayers[il].detLayer();
00156       bool barrelLayer = layer->location() == GeomDetEnumerators::barrel;
00157       
00158       Range curvature = generalCurvature;
00159       ThirdHitCorrection correction(es, region.ptMin(), layer, line, point2, useMScat);
00160       
00161       LayerRZPredictions &predRZ = mapPred.find(layer)->second;
00162       predRZ.line.initPropagator(&line);
00163       
00164       HelixRZ helix;
00165       Range rzRange;
00166       if (useBend) {
00167         // For the barrel region:
00168         // swiping the helix passing through the two points across from
00169         // negative to positive bending, can give us a sort of U-shaped
00170         // projection onto the phi-z (barrel) or r-z plane (forward)
00171         // so we checking minimum/maximum of all three possible extrema
00172         // 
00173         // For the endcap region:
00174         // Checking minimum/maximum radius of the helix projection
00175         // onto an endcap plane, here we have to guard against
00176         // looping tracks, when phi(delta z) gets out of control.
00177         // HelixRZ::rAtZ should not follow looping tracks, but clamp
00178         // to the minimum reachable r with the next-best lower |curvature|.
00179         // So same procedure as for the barrel region can be applied.
00180         //
00181         // In order to avoid looking for potential looping tracks at all
00182         // we also clamp the allowed curvature range for this layer,
00183         // and potentially fail the layer entirely
00184         
00185         if (!barrelLayer) {
00186           Range z3s = predRZ.line.detRange();
00187           double z3 = z3s.first < 0 ? max(z3s.first, z3s.second)
00188             : min(z3s.first, z3s.second);
00189           double maxCurvature = HelixRZ::maxCurvature(&predictionRPhi,
00190                                                       gp1.z(), gp2.z(), z3);
00191           if (!intersect(curvature, Range(-maxCurvature, maxCurvature)))
00192             continue;
00193         }
00194         
00195         helix = HelixRZ(&predictionRPhi, gp1.z(), gp2.z(), curvature.first);
00196         HelixRZ helix2(&predictionRPhi, gp1.z(), gp2.z(), curvature.second);
00197         
00198         predRZ.helix1.initPropagator(&helix);
00199         predRZ.helix2.initPropagator(&helix2);
00200         
00201         Range rzRanges[2] = { predRZ.helix1(), predRZ.helix2() };
00202         rzRange.first = min(rzRanges[0].first, rzRanges[1].first);
00203         rzRange.second = max(rzRanges[0].second, rzRanges[1].second);
00204         
00205         // if the allowed curvatures include a straight line,
00206         // this can give us another extremum for allowed r/z
00207         if (curvature.first * curvature.second < 0.0) {
00208           Range rzLineRange = predRZ.line();
00209           rzRange.first = min(rzRange.first, rzLineRange.first);
00210           rzRange.second = max(rzRange.second, rzLineRange.second);
00211         }
00212       } else {
00213         rzRange = predRZ.line();
00214       }
00215 
00216       if (rzRange.first >= rzRange.second)
00217         continue;
00218 
00219       correction.correctRZRange(rzRange);
00220 
00221       Range phiRange;
00222       if (useFixedPreFiltering) { 
00223         float phi0 = ip->outer()->globalPosition().phi();
00224         phiRange = Range(phi0 - dphi, phi0 + dphi);
00225       } else {
00226         Range radius;
00227         
00228         if (barrelLayer) {
00229           radius = predRZ.line.detRange();
00230           if (!intersect(rzRange, predRZ.line.detSize()))
00231             continue;
00232         } else {
00233           radius = rzRange;
00234           if (!intersect(radius, predRZ.line.detSize()))
00235             continue;
00236         }
00237         
00238         Range rPhi1 = predictionRPhi(curvature, radius.first);
00239         Range rPhi2 = predictionRPhi(curvature, radius.second);
00240         correction.correctRPhiRange(rPhi1);
00241         correction.correctRPhiRange(rPhi2);
00242         rPhi1.first  /= radius.first;
00243         rPhi1.second /= radius.first;
00244         rPhi2.first  /= radius.second;
00245         rPhi2.second /= radius.second;
00246         phiRange = mergePhiRanges(rPhi1, rPhi2);
00247       }
00248       
00249       typedef RecHitsSortedInPhi::Hit Hit;
00250       layerTree.clear(); // Now recover hits in bounding box...
00251       float prmin=phiRange.min(), prmax=phiRange.max(); //get contiguous range
00252       if ((prmax-prmin) > Geom::twoPi())
00253         { prmax=Geom::pi(); prmin = -Geom::pi();}
00254       else
00255         { while (prmax>maxphi) { prmin -= Geom::twoPi(); prmax -= Geom::twoPi();}
00256           while (prmin<minphi) { prmin += Geom::twoPi(); prmax += Geom::twoPi();}
00257           // This needs range -twoPi to +twoPi to work
00258         }
00259       if (barrelLayer) {
00260         Range regMax = predRZ.line.detRange();
00261         Range regMin = predRZ.line(regMax.min());
00262         regMax = predRZ.line(regMax.max());
00263         correction.correctRZRange(regMin);
00264         correction.correctRZRange(regMax);
00265         if (regMax.min() < regMin.min()) { swap(regMax, regMin);}
00266         KDTreeBox phiZ(prmin, prmax,
00267                        regMin.min()-fnSigmaRZ*rzError[il],
00268                        regMax.max()+fnSigmaRZ*rzError[il]);
00269         hitTree[il].search(phiZ, layerTree);
00270       }
00271       else {
00272         KDTreeBox phiZ(prmin, prmax,
00273                        rzRange.min()-fnSigmaRZ*rzError[il],
00274                        rzRange.max()+fnSigmaRZ*rzError[il]);
00275         hitTree[il].search(phiZ, layerTree);
00276       }
00277       
00278       MatchedHitRZCorrectionFromBending l2rzFixup(ip->outer()->det()->geographicalId());
00279       MatchedHitRZCorrectionFromBending l3rzFixup = predRZ.rzPositionFixup;
00280       for (std::vector<KDTreeNodeInfo<RecHitsSortedInPhi::HitIter> >::iterator ih = layerTree.begin();
00281            ih !=layerTree.end(); ++ih) {
00282         
00283         const RecHitsSortedInPhi::HitIter KDdata = (*ih).data;
00284         GlobalPoint p3 = KDdata->hit()->globalPosition();
00285         double p3_r = p3.perp();
00286         double p3_z = p3.z();
00287         double p3_phi = p3.phi();
00288 
00289         Range rangeRPhi = predictionRPhi(curvature, p3_r);
00290         correction.correctRPhiRange(rangeRPhi);
00291 
00292         double phiErr = nSigmaPhi * sqrt(KDdata->hit()->globalPositionError().phierr(p3));
00293         if (!checkPhiInRange(p3_phi, rangeRPhi.first/p3_r - phiErr, rangeRPhi.second/p3_r + phiErr))
00294           continue;
00295         
00296         const TransientTrackingRecHit::ConstRecHitPointer& hit = KDdata->hit();
00297         Basic2DVector<double> thc(p3.x(), p3.y());
00298         
00299         double curv_ = predictionRPhi.curvature(thc);
00300         double p2_r = point2.r(), p2_z = point2.z();
00301 
00302         l2rzFixup(predictionRPhi, curv_, *ip->outer(), p2_r, p2_z);
00303         l3rzFixup(predictionRPhi, curv_, *hit, p3_r, p3_z);
00304 
00305         Range rangeRZ;
00306         if (useBend) {
00307           HelixRZ updatedHelix(&predictionRPhi, gp1.z(), p2_z, curv_);
00308           rangeRZ = predRZ.helix1(barrelLayer ? p3_r : p3_z, updatedHelix);
00309         } else {
00310           float tIP = predictionRPhi.transverseIP(thc);
00311           PixelRecoPointRZ updatedPoint2(p2_r, p2_z);
00312           PixelRecoLineRZ updatedLine(line.origin(), point2, tIP);
00313           rangeRZ = predRZ.line(barrelLayer ? p3_r : p3_z, line);
00314         }
00315         correction.correctRZRange(rangeRZ);
00316         
00317         double err = nSigmaRZ * sqrt(barrelLayer
00318                                      ? hit->globalPositionError().czz()
00319                                      : hit->globalPositionError().rerr(p3));
00320         rangeRZ.first -= err, rangeRZ.second += err;
00321 
00322         if (!rangeRZ.inside(barrelLayer ? p3_z : p3_r))
00323           continue;
00324         if (theMaxElement!=0 && result.size() >= theMaxElement) {
00325           result.clear();
00326           edm::LogError("TooManyTriplets")<<" number of triples exceed maximum. no triplets produced.";
00327           delete[] thirdHitMap;
00328           return;
00329         }
00330         result.push_back(OrderedHitTriplet(ip->inner(), ip->outer(), hit)); 
00331       }
00332     }
00333   }
00334   delete[] thirdHitMap;
00335 }
00336 
00337 bool PixelTripletLargeTipGenerator::checkPhiInRange(float phi, float phi1, float phi2) const
00338 { while (phi > phi2) phi -= 2. * M_PI;
00339   while (phi < phi1) phi += 2. * M_PI;
00340   return phi <= phi2;
00341 }  
00342 
00343 std::pair<float, float>
00344 PixelTripletLargeTipGenerator::mergePhiRanges(const std::pair<float, float> &r1,
00345                                               const std::pair<float, float> &r2) const
00346 { float r2Min = r2.first;
00347   float r2Max = r2.second;
00348   while (r1.first - r2Min > +M_PI) r2Min += 2. * M_PI, r2Max += 2. * M_PI;
00349   while (r1.first - r2Min < -M_PI) r2Min -= 2. * M_PI, r2Max -= 2. * M_PI;
00350   return std::make_pair(min(r1.first, r2Min), max(r1.second, r2Max));
00351 }