CMS 3D CMS Logo

PixelTripletLargeTipGenerator.cc
Go to the documentation of this file.
4 
6 #include "ThirdHitRZPrediction.h"
9 
15 
17 #include "RecoPixelVertexing/PixelTriplets/plugins/KDTreeLinkerAlgo.h" //amend to point at our version...
19 
20 #include <algorithm>
21 #include <iostream>
22 #include <vector>
23 #include <cmath>
24 #include <map>
25 
27 
29 
30 using namespace std;
31 
34 
35 namespace {
36  struct LayerRZPredictions {
38  ThirdHitRZPrediction<HelixRZ> helix1, helix2;
39  MatchedHitRZCorrectionFromBending rzPositionFixup;
40  ThirdHitCorrection correction;
41  };
42 }
43 
44 constexpr double nSigmaRZ = 3.4641016151377544; // sqrt(12.)
45 constexpr float nSigmaPhi = 3.;
47 
48 
51  useFixedPreFiltering(cfg.getParameter<bool>("useFixedPreFiltering")),
52  extraHitRZtolerance(cfg.getParameter<double>("extraHitRZtolerance")),
53  extraHitRPhitolerance(cfg.getParameter<double>("extraHitRPhitolerance")),
54  useMScat(cfg.getParameter<bool>("useMultScattering")),
55  useBend(cfg.getParameter<bool>("useBending")),
56  dphi(useFixedPreFiltering ? cfg.getParameter<double>("phiPreFiltering") : 0) {}
57 
59 
62  // Defaults for the extraHit*tolerance are set to 0 here since that
63  // was already the case in practice in all offline occurrances.
64  desc.add<double>("extraHitRPhitolerance", 0); // default in old python was 0.032
65  desc.add<double>("extraHitRZtolerance", 0); // default in old python was 0.037
66  desc.add<bool>("useMultScattering", true);
67  desc.add<bool>("useBending", true);
68  desc.add<bool>("useFixedPreFiltering", false);
69  desc.add<double>("phiPreFiltering", 0.3);
70 }
71 
72 namespace {
73  inline
74  bool intersect(Range &range, const Range &second)
75  {
76  if ( (range.min() > second.max()) | (range.max() < second.min()) )
77  return false;
78  if (range.first < second.min())
79  range.first = second.min();
80  if (range.second > second.max())
81  range.second = second.max();
82  return range.first < range.second;
83  }
84 }
85 
88  const edm::Event & ev,
89  const edm::EventSetup& es,
90  const SeedingLayerSetsHits::SeedingLayerSet& pairLayers,
91  const std::vector<SeedingLayerSetsHits::SeedingLayer>& thirdLayers)
92 {
93  auto const & doublets = thePairGenerator->doublets(region,ev,es, pairLayers);
94 
95  if (doublets.empty()) return;
96 
97  assert(theLayerCache);
98  hitTriplets(region, result, ev, es, doublets,thirdLayers, nullptr, *theLayerCache);
99 }
100 
102  const edm::Event& ev, const edm::EventSetup& es,
103  const HitDoublets& doublets,
104  const std::vector<SeedingLayerSetsHits::SeedingLayer>& thirdLayers,
105  std::vector<int> *tripletLastLayerIndex,
106  LayerCacheType& layerCache) {
107  int size = thirdLayers.size();
108  const RecHitsSortedInPhi * thirdHitMap[size];
109  vector<const DetLayer *> thirdLayerDetLayer(size,0);
110  for (int il=0; il<size; ++il)
111  {
112  thirdHitMap[il] = &layerCache(thirdLayers[il], region, es);
113  thirdLayerDetLayer[il] = thirdLayers[il].detLayer();
114  }
115  hitTriplets(region, result, es, doublets, thirdHitMap, thirdLayerDetLayer, size, tripletLastLayerIndex);
116 }
117 
118 
120  const TrackingRegion& region,
122  const edm::EventSetup & es,
123  const HitDoublets & doublets,
124  const RecHitsSortedInPhi ** thirdHitMap,
125  const std::vector<const DetLayer *> & thirdLayerDetLayer,
126  const int nThirdLayers)
127 {
128  hitTriplets(region, result, es, doublets, thirdHitMap, thirdLayerDetLayer, nThirdLayers, nullptr);
129 }
130 
132  const edm::EventSetup & es,
133  const HitDoublets & doublets,
134  const RecHitsSortedInPhi ** thirdHitMap,
135  const std::vector<const DetLayer *> & thirdLayerDetLayer,
136  const int nThirdLayers,
137  std::vector<int> *tripletLastLayerIndex) {
139  es.get<TrackerDigiGeometryRecord>().get(tracker);
140 
141  //Retrieve tracker topology from geometry
143  es.get<TrackerTopologyRcd>().get(tTopoHand);
144  const TrackerTopology *tTopo=tTopoHand.product();
145 
146 
147  auto outSeq = doublets.detLayer(HitDoublets::outer)->seqNum();
148 
149  using NodeInfo = KDTreeNodeInfo<unsigned int>;
150  std::vector<NodeInfo > layerTree; // re-used throughout
151  std::vector<unsigned int> foundNodes; // re-used throughout
152  foundNodes.reserve(100);
153 
154  declareDynArray(KDTreeLinkerAlgo<unsigned int>, nThirdLayers, hitTree);
155  declareDynArray(LayerRZPredictions, nThirdLayers, mapPred);
156 
157  float rzError[nThirdLayers]; //save maximum errors
158 
159  const float maxDelphi = region.ptMin() < 0.3f ? float(M_PI)/4.f : float(M_PI)/8.f; // FIXME move to config??
160  const float maxphi = M_PI+maxDelphi, minphi = -maxphi; // increase to cater for any range
161  const float safePhi = M_PI-maxDelphi; // sideband
162 
163  for(int il = 0; il < nThirdLayers; il++) {
164 
165  auto const & hits = *thirdHitMap[il];
166 
167  const DetLayer *layer = thirdLayerDetLayer[il];
168  LayerRZPredictions &predRZ = mapPred[il];
169  predRZ.line.initLayer(layer);
170  predRZ.helix1.initLayer(layer);
171  predRZ.helix2.initLayer(layer);
172  predRZ.line.initTolerance(extraHitRZtolerance);
173  predRZ.helix1.initTolerance(extraHitRZtolerance);
174  predRZ.helix2.initTolerance(extraHitRZtolerance);
175  predRZ.rzPositionFixup = MatchedHitRZCorrectionFromBending(layer,tTopo);
176  predRZ.correction.init(es, region.ptMin(), *doublets.detLayer(HitDoublets::inner), *doublets.detLayer(HitDoublets::outer), *thirdLayerDetLayer[il], useMScat, false);
177 
178 
179  layerTree.clear();
180  float minv=999999.0; float maxv = -999999.0; // Initialise to extreme values in case no hits
181  float maxErr=0.0f;
182  for (unsigned int i=0; i!=hits.size(); ++i) {
183  auto angle = hits.phi(i);
184  auto v = hits.gv(i);
185  //use (phi,r) for endcaps rather than (phi,z)
186  minv = std::min(minv,v); maxv = std::max(maxv,v);
187  float myerr = hits.dv[i];
188  maxErr = std::max(maxErr,myerr);
189  layerTree.emplace_back(i, angle, v); // save it
190  // populate side-bands
191  if (angle>safePhi) layerTree.emplace_back(i, angle-Geom::ftwoPi(), v);
192  else if (angle<-safePhi) layerTree.emplace_back(i, angle+Geom::ftwoPi(), v);
193  }
194  KDTreeBox phiZ(minphi, maxphi, minv-0.01f, maxv+0.01f); // declare our bounds
195  //add fudge factors in case only one hit and also for floating-point inaccuracy
196  hitTree[il].build(layerTree, phiZ); // make KDtree
197  rzError[il] = maxErr; //save error
198  }
199 
200  double curv = PixelRecoUtilities::curvature(1. / region.ptMin(), es);
201 
202  for (std::size_t ip =0; ip!=doublets.size(); ip++) {
203  auto xi = doublets.x(ip,HitDoublets::inner);
204  auto yi = doublets.y(ip,HitDoublets::inner);
205  auto zi = doublets.z(ip,HitDoublets::inner);
206  // auto rvi = doublets.rv(ip,HitDoublets::inner);
207  auto xo = doublets.x(ip,HitDoublets::outer);
208  auto yo = doublets.y(ip,HitDoublets::outer);
209  auto zo = doublets.z(ip,HitDoublets::outer);
210  // auto rvo = doublets.rv(ip,HitDoublets::outer);
211  GlobalPoint gp1(xi,yi,zi);
212  GlobalPoint gp2(xo,yo,zo);
213 
214  auto toPos = std::signbit(zo-zi);
215 
216  PixelRecoLineRZ line(gp1, gp2);
217  PixelRecoPointRZ point2(gp2.perp(), zo);
218  ThirdHitPredictionFromCircle predictionRPhi(gp1, gp2, extraHitRPhitolerance);
219 
220  Range generalCurvature = predictionRPhi.curvature(region.originRBound());
221  if (!intersect(generalCurvature, Range(-curv, curv))) continue;
222 
223  for(int il = 0; il < nThirdLayers; il++) {
224  if (hitTree[il].empty()) continue; // Don't bother if no hits
225  const DetLayer *layer = thirdLayerDetLayer[il];
226  bool barrelLayer = layer->isBarrel();
227 
228  if ( (!barrelLayer) & (toPos != std::signbit(layer->position().z())) ) continue;
229 
230 
231  Range curvature = generalCurvature;
232 
233  LayerRZPredictions &predRZ = mapPred[il];
234  predRZ.line.initPropagator(&line);
235 
236  auto & correction = predRZ.correction;
237  correction.init(line, point2, outSeq);
238 
239 
240  Range rzRange;
241  if (useBend) {
242  // For the barrel region:
243  // swiping the helix passing through the two points across from
244  // negative to positive bending, can give us a sort of U-shaped
245  // projection onto the phi-z (barrel) or r-z plane (forward)
246  // so we checking minimum/maximum of all three possible extrema
247  //
248  // For the endcap region:
249  // Checking minimum/maximum radius of the helix projection
250  // onto an endcap plane, here we have to guard against
251  // looping tracks, when phi(delta z) gets out of control.
252  // HelixRZ::rAtZ should not follow looping tracks, but clamp
253  // to the minimum reachable r with the next-best lower |curvature|.
254  // So same procedure as for the barrel region can be applied.
255  //
256  // In order to avoid looking for potential looping tracks at all
257  // we also clamp the allowed curvature range for this layer,
258  // and potentially fail the layer entirely
259 
260  if (!barrelLayer) {
261  Range z3s = predRZ.line.detRange();
262  double z3 = z3s.first < 0 ? std::max(z3s.first, z3s.second)
263  : std::min(z3s.first, z3s.second);
264  double maxCurvature = HelixRZ::maxCurvature(&predictionRPhi,
265  gp1.z(), gp2.z(), z3);
266  if (!intersect(curvature, Range(-maxCurvature, maxCurvature)))
267  continue;
268  }
269 
270  HelixRZ helix1(&predictionRPhi, gp1.z(), gp2.z(), curvature.first);
271  HelixRZ helix2(&predictionRPhi, gp1.z(), gp2.z(), curvature.second);
272 
273  predRZ.helix1.initPropagator(&helix1);
274  predRZ.helix2.initPropagator(&helix2);
275 
276  Range rzRanges[2] = { predRZ.helix1(), predRZ.helix2() };
277  predRZ.helix1.initPropagator(nullptr);
278  predRZ.helix2.initPropagator(nullptr);
279 
280  rzRange.first = std::min(rzRanges[0].first, rzRanges[1].first);
281  rzRange.second = std::max(rzRanges[0].second, rzRanges[1].second);
282 
283  // if the allowed curvatures include a straight line,
284  // this can give us another extremum for allowed r/z
285  if (curvature.first * curvature.second < 0.0) {
286  Range rzLineRange = predRZ.line();
287  rzRange.first = std::min(rzRange.first, rzLineRange.first);
288  rzRange.second = std::max(rzRange.second, rzLineRange.second);
289  }
290  } else {
291  rzRange = predRZ.line();
292  }
293 
294  if (rzRange.first >= rzRange.second)
295  continue;
296 
297  correction.correctRZRange(rzRange);
298 
299  Range phiRange;
300  if (useFixedPreFiltering) {
301  float phi0 = doublets.phi(ip,HitDoublets::outer);
302  phiRange = Range(phi0 - dphi, phi0 + dphi);
303  } else {
304  Range radius;
305 
306  if (barrelLayer) {
307  radius = predRZ.line.detRange();
308  if (!intersect(rzRange, predRZ.line.detSize()))
309  continue;
310  } else {
311  radius = rzRange;
312  if (!intersect(radius, predRZ.line.detSize()))
313  continue;
314  }
315 
316  //gc: predictionRPhi uses the cosine rule to find the phi of the 3rd point at radius, assuming the pairCurvature range [-c,+c]
317  if ( (curvature.first<0.0f) & (curvature.second<0.0f) ) {
318  radius.swap();
319  } else if ( (curvature.first>=0.0f) & (curvature.second>=0.0f) ) {;}
320  else {
321  radius.first=radius.second;
322  }
323  auto phi12 = predictionRPhi.phi(curvature.first,radius.first);
324  auto phi22 = predictionRPhi.phi(curvature.second,radius.second);
325  phi12 = normalizedPhi(phi12);
326  phi22 = proxim(phi22,phi12);
327  phiRange = Range(phi12,phi22); phiRange.sort();
328  auto rmean = radius.mean();
329  phiRange.first *= rmean;
330  phiRange.second *= rmean;
331  correction.correctRPhiRange(phiRange);
332  phiRange.first /= rmean;
333  phiRange.second /= rmean;
334 
335  }
336 
337  foundNodes.clear(); // Now recover hits in bounding box...
338  float prmin=phiRange.min(), prmax=phiRange.max(); //get contiguous range
339 
340  if (prmax-prmin>maxDelphi) {
341  auto prm = phiRange.mean();
342  prmin = prm - 0.5f*maxDelphi;
343  prmax = prm + 0.5f*maxDelphi;
344  }
345 
346  if (barrelLayer) {
347  Range regMax = predRZ.line.detRange();
348  Range regMin = predRZ.line(regMax.min());
349  regMax = predRZ.line(regMax.max());
350  correction.correctRZRange(regMin);
351  correction.correctRZRange(regMax);
352  if (regMax.min() < regMin.min()) { std::swap(regMax, regMin);}
353  KDTreeBox phiZ(prmin, prmax,
354  regMin.min()-fnSigmaRZ*rzError[il],
355  regMax.max()+fnSigmaRZ*rzError[il]);
356  hitTree[il].search(phiZ, foundNodes);
357  }
358  else {
359  KDTreeBox phiZ(prmin, prmax,
360  rzRange.min()-fnSigmaRZ*rzError[il],
361  rzRange.max()+fnSigmaRZ*rzError[il]);
362  hitTree[il].search(phiZ, foundNodes);
363  }
364 
365  MatchedHitRZCorrectionFromBending l2rzFixup(doublets.hit(ip,HitDoublets::outer)->det()->geographicalId(), tTopo);
366  MatchedHitRZCorrectionFromBending l3rzFixup = predRZ.rzPositionFixup;
367 
368  auto const & hits = *thirdHitMap[il];
369  for (auto KDdata : foundNodes) {
370  GlobalPoint p3 = hits.gp(KDdata);
371  double p3_r = p3.perp();
372  double p3_z = p3.z();
373  float p3_phi = hits.phi(KDdata);
374 
375  Range rangeRPhi = predictionRPhi(curvature, p3_r);
376  correction.correctRPhiRange(rangeRPhi);
377 
378  float ir = 1.f/p3_r;
379  // limit error to 90 degree
380  constexpr float maxPhiErr = 0.5*M_PI;
381  float phiErr = nSigmaPhi * hits.drphi[KDdata]*ir;
382  phiErr = std::min(maxPhiErr, phiErr);
383  if (!checkPhiInRange(p3_phi, rangeRPhi.first*ir-phiErr, rangeRPhi.second*ir+phiErr, maxPhiErr))
384  continue;
385 
386  Basic2DVector<double> thc(p3.x(), p3.y());
387 
388  auto curv_ = predictionRPhi.curvature(thc);
389  double p2_r = point2.r(); double p2_z = point2.z(); // they will be modified!
390 
391  l2rzFixup(predictionRPhi, curv_, *doublets.hit(ip,HitDoublets::outer), p2_r, p2_z, tTopo);
392  l3rzFixup(predictionRPhi, curv_, *hits.theHits[KDdata].hit(), p3_r, p3_z, tTopo);
393 
394  Range rangeRZ;
395  if (useBend) {
396  HelixRZ updatedHelix(&predictionRPhi, gp1.z(), p2_z, curv_);
397  rangeRZ = predRZ.helix1(barrelLayer ? p3_r : p3_z, updatedHelix);
398  } else {
399  float tIP = predictionRPhi.transverseIP(thc);
400  PixelRecoPointRZ updatedPoint2(p2_r, p2_z);
401  PixelRecoLineRZ updatedLine(line.origin(), point2, tIP);
402  rangeRZ = predRZ.line(barrelLayer ? p3_r : p3_z, line);
403  }
404  correction.correctRZRange(rangeRZ);
405 
406  double err = nSigmaRZ * hits.dv[KDdata];
407 
408  rangeRZ.first -= err, rangeRZ.second += err;
409 
410  if (!rangeRZ.inside(barrelLayer ? p3_z : p3_r)) continue;
411 
412  if (theMaxElement!=0 && result.size() >= theMaxElement) {
413  result.clear();
414  edm::LogError("TooManyTriplets")<<" number of triples exceed maximum. no triplets produced.";
415  return;
416  }
417  result.emplace_back( doublets.hit(ip,HitDoublets::inner), doublets.hit(ip,HitDoublets::outer), hits.theHits[KDdata].hit());
418  // to bookkeep the triplets and 3rd layers in triplet EDProducer
419  if(tripletLastLayerIndex) tripletLastLayerIndex->push_back(il);
420  }
421  }
422  }
423  // std::cout << "found triplets " << result.size() << std::endl;
424 }
425 
size
Write out results.
float originRBound() const
bounds the particle vertex in the transverse plane
static void fillDescriptions(edm::ParameterSetDescription &desc)
std::size_t size() const
T perp() const
Definition: PV3DBase.h:72
constexpr float ftwoPi()
Definition: Pi.h:36
float x(int i, layer l) const
T y() const
Definition: PV3DBase.h:63
T r() const
Radius, same as mag()
bool ev
bool checkPhiInRange(T phi, T phi1, T phi2, float maxDphi=float(M_PI))
Definition: normalizedPhi.h:34
LineOrigin origin() const
#define constexpr
float z(int i, layer l) const
U second(std::pair< T, U > const &p)
int seqNum() const
Definition: DetLayer.h:36
T curvature(T InversePt, const edm::EventSetup &iSetup)
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
static void fillDescriptions(edm::ParameterSetDescription &desc)
T z() const
Definition: PV3DBase.h:64
double f[11][100]
T min(T a, T b)
Definition: MathUtil.h:58
float y(int i, layer l) const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
#define M_PI
bool isBarrel() const
Definition: DetLayer.h:32
static double maxCurvature(const ThirdHitPredictionFromCircle *circle, double z1, double z2, double z3)
float phi(int i, layer l) const
PixelRecoRange< float > Range
std::unique_ptr< HitPairGeneratorFromLayerPair > thePairGenerator
T proxim(T b, T a)
Definition: normalizedPhi.h:14
virtual const Surface::PositionType & position() const
Returns position of the surface.
const T & get() const
Definition: EventSetup.h:56
float ptMin() const
minimal pt of interest
Hit const & hit(int i, layer l) const
PixelTripletLargeTipGenerator(const edm::ParameterSet &cfg, edm::ConsumesCollector &&iC)
#define declareDynArray(T, n, x)
Definition: DynArray.h:59
virtual unsigned int size() const
T x() const
Definition: PV3DBase.h:62
T const * product() const
Definition: ESHandle.h:86
DetLayer const * detLayer(layer l) const
T normalizedPhi(T phi)
Definition: normalizedPhi.h:9
virtual void hitTriplets(const TrackingRegion &region, OrderedHitTriplets &trs, const edm::Event &ev, const edm::EventSetup &es, const SeedingLayerSetsHits::SeedingLayerSet &pairLayers, const std::vector< SeedingLayerSetsHits::SeedingLayer > &thirdLayers) override
double p3[4]
Definition: TauolaWrapper.h:91
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11