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
00015
00016 #include "RecoPixelVertexing/PixelTriplets/plugins/KDTreeLinkerAlgo.h"
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;
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;
00093 std::vector<KDTreeLinkerAlgo<RecHitsSortedInPhi::HitIter> > hitTree(size);
00094 std::vector<float> rzError(size,0.0f);
00095 double maxphi = Geom::twoPi(), minphi = -maxphi;
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();
00112 layerTree.clear();
00113 double minz=999999.0, maxz= -999999.0;
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;
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
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));
00127 if (angle < 0)
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);
00134
00135 hitTree[il].build(layerTree, phiZ);
00136 rzError[il] = maxErr;
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;
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
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
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
00206
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();
00251 float prmin=phiRange.min(), prmax=phiRange.max();
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
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 }