CMS 3D CMS Logo

MultiHitGeneratorFromChi2.cc
Go to the documentation of this file.
3 
7 
12 
14 
20 
26 
28 
31 
32 #include <algorithm>
33 #include <iostream>
34 #include <vector>
35 #include <cmath>
36 #include <map>
37 #include <limits>
38 
39 using namespace std;
40 
42 
43 namespace {
44  struct LayerRZPredictions {
46  };
47 } // namespace
48 
51  useFixedPreFiltering(cfg.getParameter<bool>("useFixedPreFiltering")),
53  cfg.getParameter<double>("extraHitRZtolerance")), //extra window in ThirdHitRZPrediction range
54  extraHitRPhitolerance(cfg.getParameter<double>(
55  "extraHitRPhitolerance")), //extra window in ThirdHitPredictionFromCircle range (divide by R to get phi)
57  cfg.getParameter<double>("extraZKDBox")), //extra windown in Z when building the KDTree box (used in barrel)
59  cfg.getParameter<double>("extraRKDBox")), //extra windown in R when building the KDTree box (used in endcap)
60  extraPhiKDBox(cfg.getParameter<double>("extraPhiKDBox")), //extra windown in Phi when building the KDTree box
61  fnSigmaRZ(cfg.getParameter<double>(
62  "fnSigmaRZ")), //this multiplies the max hit error on the layer when building the KDTree box
63  chi2VsPtCut(cfg.getParameter<bool>("chi2VsPtCut")),
64  maxChi2(cfg.getParameter<double>("maxChi2")),
65  refitHits(cfg.getParameter<bool>("refitHits")),
66  filterName_(cfg.getParameter<std::string>("ClusterShapeHitFilterName")),
67  builderName_(cfg.getParameter<std::string>("TTRHBuilder")),
68  useSimpleMF_(false),
69  mfName_("") {
71  dphi = cfg.getParameter<double>("phiPreFiltering");
72  if (chi2VsPtCut) {
73  pt_interv = cfg.getParameter<std::vector<double> >("pt_interv");
74  chi2_cuts = cfg.getParameter<std::vector<double> >("chi2_cuts");
75  }
76 #ifdef EDM_ML_DEBUG
77  detIdsToDebug = cfg.getParameter<std::vector<int> >("detIdsToDebug");
78  //if (detIdsToDebug.size()<3) //fixme
79 #else
80  detIdsToDebug.push_back(0);
81  detIdsToDebug.push_back(0);
82  detIdsToDebug.push_back(0);
83 #endif
84  // 2014/02/11 mia:
85  // we should get rid of the boolean parameter useSimpleMF,
86  // and use only a string magneticField [instead of SimpleMagneticField]
87  // or better an edm::ESInputTag (at the moment HLT does not handle ESInputTag)
88  if (cfg.exists("SimpleMagneticField")) {
89  useSimpleMF_ = true;
90  mfName_ = cfg.getParameter<std::string>("SimpleMagneticField");
91  }
92  filter = nullptr;
93  bfield = nullptr;
94  nomField = -1.;
95 
96  if (useSimpleMF_) {
98  } else {
100  }
101  if (refitHits) {
104  }
105 }
106 
108 
111 
112  // fixed phi filtering
113  desc.add<bool>("useFixedPreFiltering", false);
114  desc.add<double>("phiPreFiltering", 0.3);
115 
116  // box properties
117  desc.add<double>("extraHitRPhitolerance", 0);
118  desc.add<double>("extraHitRZtolerance", 0);
119  desc.add<double>("extraZKDBox", 0.2);
120  desc.add<double>("extraRKDBox", 0.2);
121  desc.add<double>("extraPhiKDBox", 0.005);
122  desc.add<double>("fnSigmaRZ", 2.0);
123 
124  // refit&filter hits
125  desc.add<bool>("refitHits", true);
126  desc.add<std::string>("ClusterShapeHitFilterName", "ClusterShapeHitFilter");
127  desc.add<std::string>("TTRHBuilder", "WithTrackAngle");
128 
129  // chi2 cuts
130  desc.add<double>("maxChi2", 5.0);
131  desc.add<bool>("chi2VsPtCut", true);
132  desc.add<std::vector<double> >("pt_interv", std::vector<double>{{0.4, 0.7, 1.0, 2.0}});
133  desc.add<std::vector<double> >("chi2_cuts", std::vector<double>{{3.0, 4.0, 5.0, 5.0}});
134 
135  // debugging
136  desc.add<std::vector<int> >("detIdsToDebug", std::vector<int>{{0, 0, 0}});
137 }
138 
142  ufield.set(nomField); // more than enough (never actually used)
143 
144  if (refitHits) {
146  auto const& builderRef = es.getData(transientTrackingRecHitBuilderESToken_);
147  builder = (TkTransientTrackingRecHitBuilder const*)(&builderRef);
148  cloner = (*builder).cloner();
149  }
150 }
151 
152 namespace {
153  inline bool intersect(Range& range, const Range& second) {
154  if (range.first > second.max() || range.second < second.min())
155  return false;
156  if (range.first < second.min())
157  range.first = second.min();
158  if (range.second > second.max())
159  range.second = second.max();
160  return range.first < range.second;
161  }
162 } // namespace
163 
166  const edm::Event& ev,
167  const edm::EventSetup& es,
169  std::vector<SeedingLayerSetsHits::SeedingLayer> thirdLayers) {
170  LogDebug("MultiHitGeneratorFromChi2") << "pair: " << thePairGenerator->innerLayer(pairLayers).name() << "+"
171  << thePairGenerator->outerLayer(pairLayers).name()
172  << " 3rd lay size: " << thirdLayers.size();
173 
174  auto const& doublets = thePairGenerator->doublets(region, ev, es, pairLayers);
175  LogTrace("MultiHitGeneratorFromChi2") << "";
176  if (doublets.empty()) {
177  // LogDebug("MultiHitGeneratorFromChi2") << "empy pairs";
178  return;
179  }
180 
182  hitSets(region, result, doublets, thirdLayers, *theLayerCache, cache);
183 }
184 
187  const HitDoublets& doublets,
188  const std::vector<SeedingLayerSetsHits::SeedingLayer>& thirdLayers,
189  LayerCacheType& layerCache,
190  cacheHits& refittedHitStorage) {
191  int size = thirdLayers.size();
192  const RecHitsSortedInPhi* thirdHitMap[size];
193  vector<const DetLayer*> thirdLayerDetLayer(size, nullptr);
194  for (int il = 0; il < size; ++il) {
195  thirdHitMap[il] = &layerCache(thirdLayers[il], region);
196 
197  thirdLayerDetLayer[il] = thirdLayers[il].detLayer();
198  }
199  hitSets(region, result, doublets, thirdHitMap, thirdLayerDetLayer, size, refittedHitStorage);
200 }
201 
204  const HitDoublets& doublets,
205  const RecHitsSortedInPhi** thirdHitMap,
206  const std::vector<const DetLayer*>& thirdLayerDetLayer,
207  const int nThirdLayers) {
208  hitSets(region, result, doublets, thirdHitMap, thirdLayerDetLayer, nThirdLayers, cache);
209 }
210 
213  const HitDoublets& doublets,
214  const RecHitsSortedInPhi** thirdHitMap,
215  const std::vector<const DetLayer*>& thirdLayerDetLayer,
216  const int nThirdLayers,
217  cacheHits& refittedHitStorage) {
218 #ifdef EDM_ML_DEBUG
219  unsigned int debug_Id0 = detIdsToDebug[0];
220  unsigned int debug_Id1 = detIdsToDebug[1];
221  unsigned int debug_Id2 = detIdsToDebug[2];
222 #endif
223 
224  std::array<bool, 3> bl;
225  bl[0] = doublets.innerLayer().isBarrel;
226  bl[1] = doublets.outerLayer().isBarrel;
227 
228  //gc: these are all the layers compatible with the layer pairs (as defined in the config file)
229 
230  //gc: initialize a KDTree per each 3rd layer
231  std::vector<KDTreeNodeInfo<RecHitsSortedInPhi::HitIter, 2> > layerTree; // re-used throughout
232  std::vector<RecHitsSortedInPhi::HitIter> foundNodes; // re-used thoughout
233  foundNodes.reserve(100);
235  declareDynArray(LayerRZPredictions, nThirdLayers, mapPred);
236  float rzError[nThirdLayers]; //save maximum errors
237 
238  const float maxDelphi = region.ptMin() < 0.3f ? float(M_PI) / 4.f : float(M_PI) / 8.f; // FIXME move to config??
239  const float maxphi = M_PI + maxDelphi, minphi = -maxphi; // increase to cater for any range
240  const float safePhi = M_PI - maxDelphi; // sideband
241 
242  //gc: loop over each layer
243  for (int il = 0; il < nThirdLayers; il++) {
244  LogTrace("MultiHitGeneratorFromChi2")
245  << "considering third layer: with hits: " << thirdHitMap[il]->all().second - thirdHitMap[il]->all().first;
246  const DetLayer* layer = thirdLayerDetLayer[il];
247  LayerRZPredictions& predRZ = mapPred[il];
248  predRZ.line.initLayer(layer);
249  predRZ.line.initTolerance(extraHitRZtolerance);
250 
251  //gc: now we take all hits in the layer and fill the KDTree
252  auto const& layer3 = *thirdHitMap[il]; // Get iterators
253  layerTree.clear();
254  float minz = 999999.0f, maxz = -minz; // Initialise to extreme values in case no hits
255  float maxErr = 0.0f;
256  if (!layer3.empty()) {
257  minz = layer3.v[0];
258  maxz = minz; //In case there's only one hit on the layer
259  for (auto i = 0U; i < layer3.size(); ++i) {
260  auto hi = layer3.theHits.begin() + i;
261  auto angle = layer3.phi(i);
262  auto myz = layer3.v[i];
263 #ifdef EDM_ML_DEBUG
264  IfLogTrace(hi->hit()->rawId() == debug_Id2, "MultiHitGeneratorFromChi2")
265  << "filling KDTree with hit in id=" << debug_Id2 << " with pos: " << hi->hit()->globalPosition()
266  << " phi=" << hi->hit()->globalPosition().phi() << " z=" << hi->hit()->globalPosition().z()
267  << " r=" << hi->hit()->globalPosition().perp();
268 #endif
269  //use (phi,r) for endcaps rather than (phi,z)
270  if (myz < minz) {
271  minz = myz;
272  } else {
273  if (myz > maxz) {
274  maxz = myz;
275  }
276  }
277  auto myerr = layer3.dv[i];
278  if (myerr > maxErr) {
279  maxErr = myerr;
280  }
281  layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter, 2>(hi, angle, myz)); // save it
282  // populate side-bands
283  if (angle > safePhi)
284  layerTree.push_back(
286  else if (angle < -safePhi)
287  layerTree.push_back(
289  }
290  }
291  KDTreeBox phiZ(minphi, maxphi, minz - 0.01f, maxz + 0.01f); // declare our bounds
292  //add fudge factors in case only one hit and also for floating-point inaccuracy
293  hitTree[il].build(layerTree, phiZ); // make KDtree
294  rzError[il] = maxErr; //save error
295  }
296  //gc: now we have initialized the KDTrees and we are out of the layer loop
297 
298  //gc: this sets the minPt of the triplet
299  auto curv = PixelRecoUtilities::curvature(1. / region.ptMin(), *bfield);
300 
301  LogTrace("MultiHitGeneratorFromChi2") << "doublet size=" << doublets.size() << std::endl;
302 
303  //fixme add pixels
304  auto filterHit = [&](TrackingRecHit const* hit, GlobalVector const& dir) -> bool {
305  auto hh = reinterpret_cast<BaseTrackerRecHit const*>(hit);
306  if ( //hh->geographicalId().subdetId() > 2
307  hh->geographicalId().subdetId() == SiStripDetId::TIB || hh->geographicalId().subdetId() == SiStripDetId::TID
308  //|| hh->geographicalId().subdetId()==SiStripDetId::TOB
309  //|| hh->geographicalId().subdetId()==SiStripDetId::TEC
310  ) {
311  // carefull " for matched and projected local of tsos != local for individual clusters...
312  if (hh->isMatched()) {
313  const SiStripMatchedRecHit2D* matchedHit = reinterpret_cast<const SiStripMatchedRecHit2D*>(hh);
314  if (filter->isCompatible(DetId(matchedHit->monoId()), matchedHit->monoCluster(), dir) == 0 ||
315  filter->isCompatible(DetId(matchedHit->stereoId()), matchedHit->stereoCluster(), dir) == 0)
316  return false;
317  } else if (hh->isProjected()) {
318  const ProjectedSiStripRecHit2D* precHit = reinterpret_cast<const ProjectedSiStripRecHit2D*>(hh);
319  if (filter->isCompatible(precHit->originalHit(), dir) == 0)
320  return false; //FIXME??
321  } else if (hh->isSingle()) {
322  const SiStripRecHit2D* recHit = reinterpret_cast<const SiStripRecHit2D*>(hh);
323  if (filter->isCompatible(*recHit, dir) == 0)
324  return false;
325  }
326  }
327  return true;
328  };
329 
330  //gc: now we loop over all pairs
331  for (std::size_t ip = 0; ip != doublets.size(); ip++) {
332  int foundTripletsFromPair = 0;
333  bool usePair = false;
334  cacheHitPointer bestH2;
336 
339 
340  HitOwnPtr hit0(*oriHit0);
341  HitOwnPtr hit1(*oriHit1);
344 
345 #ifdef EDM_ML_DEBUG
346  bool debugPair = oriHit0->rawId() == debug_Id0 && oriHit1->rawId() == debug_Id1;
347 #endif
348  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << endl
349  << endl
350  << "found new pair with ids " << oriHit0->rawId() << " "
351  << oriHit1->rawId() << " with pos: " << gp0 << " " << gp1;
352 
353  if (refitHits) {
354  TrajectoryStateOnSurface tsos0, tsos1;
355  assert(!hit0.isOwn());
356  assert(!hit1.isOwn());
357 #ifdef EDM_ML_DEBUG
358  refit2Hits(hit0, hit1, tsos0, tsos1, region, nomField, debugPair);
359 #else
360  refit2Hits(hit0, hit1, tsos0, tsos1, region, nomField, false);
361 #endif
362 
363  bool passFilterHit0 = filterHit(hit0->hit(), tsos0.globalMomentum());
364  IfLogTrace(debugPair && !passFilterHit0, "MultiHitGeneratorFromChi2") << "hit0 did not pass cluster shape filter";
365  if (!passFilterHit0)
366  continue;
367  bool passFilterHit1 = filterHit(hit1->hit(), tsos1.globalMomentum());
368  IfLogTrace(debugPair && !passFilterHit1, "MultiHitGeneratorFromChi2") << "hit1 did not pass cluster shape filter";
369  if (!passFilterHit1)
370  continue;
371  // refit hits
372  hit0.reset((SeedingHitSet::RecHitPointer)(cloner(*hit0, tsos0)));
373  hit1.reset((SeedingHitSet::RecHitPointer)(cloner(*hit1, tsos1)));
374 
375 #ifdef EDM_ML_DEBUG
376  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2")
377  << "charge=" << tsos0.charge() << std::endl
378  << "state1 pt=" << tsos0.globalMomentum().perp() << " eta=" << tsos0.globalMomentum().eta()
379  << " phi=" << tsos0.globalMomentum().phi() << std::endl
380  << "state2 pt=" << tsos1.globalMomentum().perp() << " eta=" << tsos1.globalMomentum().eta()
381  << " phi=" << tsos1.globalMomentum().phi() << std::endl
382  << "positions after refitting: " << hit0->globalPosition() << " " << hit1->globalPosition();
383 #endif
384  } else {
385  // not refit clone anyhow
386  hit0.reset((BaseTrackerRecHit*)hit0->clone());
387  hit1.reset((BaseTrackerRecHit*)hit1->clone());
388  }
389 
390  assert(hit0.isOwn());
391  assert(hit1.isOwn());
392 
393  //gc: create the RZ line for the pair
394  SimpleLineRZ line(PixelRecoPointRZ(gp0.perp(), gp0.z()), PixelRecoPointRZ(gp1.perp(), gp1.z()));
395  ThirdHitPredictionFromCircle predictionRPhi(gp0, gp1, extraHitRPhitolerance);
396 
397  auto toPos = std::signbit(gp1.z() - gp0.z());
398 
399  //gc: this is the curvature of the two hits assuming the region
400  Range pairCurvature = predictionRPhi.curvature(region.originRBound());
401  //gc: intersect not only returns a bool but may change pairCurvature to intersection with curv
402  if (!intersect(pairCurvature, Range(-curv, curv))) {
403  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2")
404  << "curvature cut: curv=" << curv << " gc=(" << pairCurvature.first << ", " << pairCurvature.second << ")";
405  continue;
406  }
407 
408  std::array<GlobalPoint, 3> gp;
409  std::array<GlobalError, 3> ge;
410  gp[0] = hit0->globalPosition();
411  ge[0] = hit0->globalPositionError();
412  gp[1] = hit1->globalPosition();
413  ge[1] = hit1->globalPositionError();
414 
415  //gc: loop over all third layers compatible with the pair
416  for (int il = 0; (il < nThirdLayers) & (!usePair); il++) {
417  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2")
418  << "cosider layer:"
419  << " for this pair. Location: " << thirdLayerDetLayer[il]->location();
420 
421  if (hitTree[il].empty()) {
422  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "empty hitTree";
423  continue; // Don't bother if no hits
424  }
425 
426  cacheHitPointer bestL2;
427  float chi2FromThisLayer = std::numeric_limits<float>::max();
428 
429  const DetLayer* layer = thirdLayerDetLayer[il];
430  // bool barrelLayer = layer->location() == GeomDetEnumerators::barrel;
431  auto const& layer3 = *thirdHitMap[il];
432  bool barrelLayer = layer3.isBarrel;
433  bl[2] = layer3.isBarrel;
434 
435  if ((!barrelLayer) & (toPos != std::signbit(layer->position().z())))
436  continue;
437 
438  LayerRZPredictions& predRZ = mapPred[il];
439  predRZ.line.initPropagator(&line);
440 
441  //gc: this takes the z at R-thick/2 and R+thick/2 according to
442  // the line from the two points and the adds the extra tolerance
443  Range rzRange = predRZ.line();
444 
445  if (rzRange.first >= rzRange.second) {
446  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "rzRange empty";
447  continue;
448  }
449  //gc: check that rzRange is compatible with detector bounds
450  // note that intersect may change rzRange to intersection with bounds
451  if (!intersect(rzRange, predRZ.line.detSize())) { // theDetSize = Range(-maxZ, maxZ);
452  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "rzRange and detector do not intersect";
453  continue;
454  }
455  Range radius = barrelLayer ? predRZ.line.detRange() : rzRange;
456 
457  //gc: define the phi range of the hits
458  Range phiRange;
459  if (useFixedPreFiltering) {
460  //gc: in this case it takes as range the phi of the outer
461  // hit +/- the phiPreFiltering value from cfg
462  float phi0 = oriHit0->globalPosition().phi();
463  phiRange = Range(phi0 - dphi, phi0 + dphi);
464  } else {
465  //gc: predictionRPhi uses the cosine rule to find the phi of the 3rd point at radius, assuming the pairCurvature range [-c,+c]
466  if (pairCurvature.first < 0. && pairCurvature.second < 0.) {
467  radius.swap();
468  } else if (pairCurvature.first >= 0. && pairCurvature.second >= 0.) {
469  ;
470  } else {
471  radius.first = radius.second;
472  }
473  auto phi12 = predictionRPhi.phi(pairCurvature.first, radius.first);
474  auto phi22 = predictionRPhi.phi(pairCurvature.second, radius.second);
475  phi12 = normalizedPhi(phi12);
476  phi22 = proxim(phi22, phi12);
477  phiRange = Range(phi12, phi22);
478  phiRange.sort();
479  }
480 
481  float prmin = phiRange.min(), prmax = phiRange.max();
482 
483  if (prmax - prmin > maxDelphi) {
484  auto prm = phiRange.mean();
485  prmin = prm - 0.5f * maxDelphi;
486  prmax = prm + 0.5f * maxDelphi;
487  }
488 
489  //gc: this is the place where hits in the compatible region are put in the foundNodes
491  foundNodes.clear(); // Now recover hits in bounding box...
492 
493  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "defining kd tree box";
494 
495  if (barrelLayer) {
496  KDTreeBox phiZ(prmin - extraPhiKDBox,
497  prmax + extraPhiKDBox,
498  float(rzRange.min() - fnSigmaRZ * rzError[il] - extraZKDBox),
499  float(rzRange.max() + fnSigmaRZ * rzError[il] + extraZKDBox));
500  hitTree[il].search(phiZ, foundNodes);
501 
502  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2")
503  << "kd tree box bounds, phi: " << prmin - extraPhiKDBox << "," << prmax + extraPhiKDBox
504  << " z: " << rzRange.min() - fnSigmaRZ * rzError[il] - extraZKDBox << ","
505  << rzRange.max() + fnSigmaRZ * rzError[il] + extraZKDBox << " rzRange: " << rzRange.min() << ","
506  << rzRange.max();
507 
508  } else {
509  KDTreeBox phiR(prmin - extraPhiKDBox,
510  prmax + extraPhiKDBox,
511  float(rzRange.min() - fnSigmaRZ * rzError[il] - extraRKDBox),
512  float(rzRange.max() + fnSigmaRZ * rzError[il] + extraRKDBox));
513  hitTree[il].search(phiR, foundNodes);
514 
515  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2")
516  << "kd tree box bounds, phi: " << prmin - extraPhiKDBox << "," << prmax + extraPhiKDBox
517  << " r: " << rzRange.min() - fnSigmaRZ * rzError[il] - extraRKDBox << ","
518  << rzRange.max() + fnSigmaRZ * rzError[il] + extraRKDBox << " rzRange: " << rzRange.min() << ","
519  << rzRange.max();
520  }
521 
522  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "kd tree box size: " << foundNodes.size();
523 
524  //gc: now we loop over the hits in the box for this layer
525  for (std::vector<RecHitsSortedInPhi::HitIter>::iterator ih = foundNodes.begin();
526  ih != foundNodes.end() && !usePair;
527  ++ih) {
528  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << endl << "triplet candidate";
529 
530  const RecHitsSortedInPhi::HitIter KDdata = *ih;
531 
532  auto oriHit2 = KDdata->hit();
533  auto kk = KDdata - layer3.theHits.begin();
534  cacheHitPointer hit2;
535  auto gp2 = layer3.gp(kk);
536  if (refitHits) { //fixme
537 
538  //fitting all 3 hits takes too much time... do it quickly only for 3rd hit
539  GlobalVector initMomentum(gp2 - gp1);
540  initMomentum /= initMomentum.perp(); //set pT=1
541 
542  //fixme add pixels
543  bool passFilterHit2 = filterHit(oriHit2->hit(), initMomentum);
544  if (!passFilterHit2)
545  continue;
547  *oriHit2->surface());
548  hit2.reset((SeedingHitSet::RecHitPointer)(cloner(*oriHit2, state)));
549 
550  } else {
551  // not refit clone anyhow
552  hit2.reset((BaseTrackerRecHit*)oriHit2->clone());
553  }
554 
555  //gc: add the chi2 cut
556  gp[2] = hit2->globalPosition();
557  ge[2] = hit2->globalPositionError();
558  RZLine rzLine(gp, ge, bl);
559  float chi2 = rzLine.chi2();
560 
561 #ifdef EDM_ML_DEBUG
562  bool debugTriplet = debugPair && hit2->rawId() == debug_Id2;
563 #endif
564  IfLogTrace(debugTriplet, "MultiHitGeneratorFromChi2")
565  << endl
566  << "triplet candidate in debug id" << std::endl
567  << "hit in id=" << hit2->rawId() << " (from KDTree) with pos: " << KDdata->hit()->globalPosition()
568  << " refitted: " << hit2->globalPosition() << " chi2: " << chi2;
569  // should fix nan
570  if ((chi2 > maxChi2) | edm::isNotFinite(chi2))
571  continue;
572 
573  if (chi2VsPtCut) {
574  FastCircle theCircle(gp[2], gp[1], gp[0]);
575  float tesla0 = 0.1f * nomField;
576  float rho = theCircle.rho();
577  float cm2GeV = 0.01f * 0.3f * tesla0;
578  float pt = cm2GeV * rho;
579  IfLogTrace(debugTriplet, "MultiHitGeneratorFromChi2") << "triplet pT=" << pt;
580  if (pt < region.ptMin())
581  continue;
582 
583  if (chi2_cuts.size() == 4) {
584  if ((pt > pt_interv[0] && pt <= pt_interv[1] && chi2 > chi2_cuts[0]) ||
585  (pt > pt_interv[1] && pt <= pt_interv[2] && chi2 > chi2_cuts[1]) ||
586  (pt > pt_interv[2] && pt <= pt_interv[3] && chi2 > chi2_cuts[2]) ||
587  (pt > pt_interv[3] && chi2 > chi2_cuts[3]))
588  continue;
589  }
590 
591  // apparently this takes too much time...
592  // if (chi2_cuts.size()>1) {
593  // int ncuts = chi2_cuts.size();
594  // if ( pt<=pt_interv[0] && chi2 > chi2_cuts[0] ) continue;
595  // bool pass = true;
596  // for (int icut=1; icut<ncuts-1; icut++){
597  // if ( pt>pt_interv[icut-1] && pt<=pt_interv[icut] && chi2 > chi2_cuts[icut] ) pass=false;
598  // }
599  // if (!pass) continue;
600  // if ( pt>pt_interv[ncuts-2] && chi2 > chi2_cuts[ncuts-1] ) continue;
601  // if (hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1 && hit2->rawId()==debug_Id2) {
602  // LogTrace("MultiHitGeneratorFromChi2") << "triplet passed chi2 vs pt cut" << std::endl;
603  // }
604  // }
605  }
606 
607  if (theMaxElement != 0 && result.size() >= theMaxElement) {
608  result.clear();
609  edm::LogError("TooManyTriplets") << " number of triples exceed maximum. no triplets produced.";
610  return;
611  }
612  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "triplet made";
613  //result.push_back(SeedingHitSet(hit0, hit1, hit2));
614  /* no refit so keep only hit2
615  assert(tripletFromThisLayer.empty());
616  assert(hit0.isOwn()); assert(hit1.isOwn());assert(hit2.isOwn());
617  tripletFromThisLayer.emplace_back(std::move(hit0));
618  tripletFromThisLayer.emplace_back(std::move(hit1));
619  tripletFromThisLayer.emplace_back(std::move(hit2));
620  assert(hit0.isEmpty()); assert(hit1.isEmpty());assert(hit2.isEmpty());
621  */
622  bestL2 = std::move(hit2);
623  chi2FromThisLayer = chi2;
624  foundTripletsFromPair++;
625  if (foundTripletsFromPair >= 2) {
626  usePair = true;
627  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "using pair";
628  break;
629  }
630  } //loop over hits in KDTree
631 
632  if (usePair)
633  break;
634  else {
635  //if there is one triplet in more than one layer, try picking the one with best chi2
636  if (chi2FromThisLayer < minChi2) {
637  bestH2 = std::move(bestL2);
638  minChi2 = chi2FromThisLayer;
639  }
640  /*
641  else {
642  if (!bestH2 && foundTripletsFromPair>0)
643  LogTrace("MultiHitGeneratorFromChi2") << "what?? " << minChi2 << ' ' << chi2FromThisLayer;
644  }
645  */
646  }
647 
648  } //loop over layers
649 
650  if (foundTripletsFromPair == 0)
651  continue;
652 
653  //push back only (max) once per pair
654  IfLogTrace(debugPair, "MultiHitGeneratorFromChi2") << "Done seed #" << result.size();
655  if (usePair)
656  result.push_back(SeedingHitSet(oriHit0, oriHit1));
657  else {
658  assert(1 == foundTripletsFromPair);
659  assert(bestH2);
660  result.emplace_back(&*hit0, &*hit1, &*bestH2);
661  assert(hit0.isOwn());
662  assert(hit1.isOwn());
663  refittedHitStorage.emplace_back(const_cast<BaseTrackerRecHit*>(hit0.release()));
664  refittedHitStorage.emplace_back(const_cast<BaseTrackerRecHit*>(hit1.release()));
665  refittedHitStorage.emplace_back(std::move(bestH2));
666  assert(hit0.empty());
667  assert(hit1.empty());
668  assert(!bestH2);
669  }
670  // LogTrace("MultiHitGeneratorFromChi2") << (usePair ? "pair " : "triplet ") << minChi2 <<' ' << refittedHitStorage.size();
671 
672  } //loop over pairs
673  LogTrace("MultiHitGeneratorFromChi2") << "triplet size=" << result.size();
674  // std::cout << "MultiHitGeneratorFromChi2 " << "triplet size=" << result.size() << std::endl;
675 }
676 
678  HitOwnPtr& hit2,
679  TrajectoryStateOnSurface& state1,
680  TrajectoryStateOnSurface& state2,
681  const TrackingRegion& region,
682  float nomField,
683  bool isDebug) {
684  //these need to be sorted in R
685  const GlobalPoint& gp0 = region.origin();
686  GlobalPoint gp1 = hit1->globalPosition();
687  GlobalPoint gp2 = hit2->globalPosition();
688 
689  IfLogTrace(isDebug, "MultiHitGeneratorFromChi2")
690  << "positions before refitting: " << hit1->globalPosition() << " " << hit2->globalPosition();
691 
692  FastCircle theCircle(gp2, gp1, gp0);
693  GlobalPoint cc(theCircle.x0(), theCircle.y0(), 0);
694  float tesla0 = 0.1f * nomField;
695  float rho = theCircle.rho();
696  float cm2GeV = 0.01f * 0.3f * tesla0;
697  float pt = cm2GeV * rho;
698 
699  GlobalVector vec20 = gp2 - gp0;
700  //if (isDebug) { cout << "vec20.eta=" << vec20.eta() << endl; }
701 
702  GlobalVector p0(gp0.y() - cc.y(), -gp0.x() + cc.x(), 0.);
703  p0 = p0 * pt / p0.perp();
704  GlobalVector p1(gp1.y() - cc.y(), -gp1.x() + cc.x(), 0.);
705  p1 = p1 * pt / p1.perp();
706  GlobalVector p2(gp2.y() - cc.y(), -gp2.x() + cc.x(), 0.);
707  p2 = p2 * pt / p2.perp();
708 
709  //check sign according to scalar product
710  if ((p0.x() * (gp1.x() - gp0.x()) + p0.y() * (gp1.y() - gp0.y())) < 0) {
711  p0 *= -1.;
712  p1 *= -1.;
713  p2 *= -1.;
714  }
715 
716  //now set z component
717  auto zv = vec20.z() / vec20.perp();
718  p0 = GlobalVector(p0.x(), p0.y(), p0.perp() * zv);
719  p1 = GlobalVector(p1.x(), p1.y(), p1.perp() * zv);
720  p2 = GlobalVector(p2.x(), p2.y(), p2.perp() * zv);
721 
722  //get charge from vectorial product
723  TrackCharge q = 1;
724  if ((gp1 - cc).x() * p1.y() - (gp1 - cc).y() * p1.x() > 0)
725  q = -q;
726 
727  TrajectoryStateOnSurface(GlobalTrajectoryParameters(gp1, p1, q, &ufield), *hit1->surface()).swap(state1);
728  // hit1.reset((SeedingHitSet::RecHitPointer)(cloner(*hit1,state1)));
729 
730  TrajectoryStateOnSurface(GlobalTrajectoryParameters(gp2, p2, q, &ufield), *hit2->surface()).swap(state2);
731  // hit2.reset((SeedingHitSet::RecHitPointer)(cloner(*hit2,state2)));
732 }
733 
734 /*
735 void MultiHitGeneratorFromChi2::refit3Hits(HitOwnPtr & hit0,
736  HitOwnPtr & hit1,
737  HitOwnPtr & hit2,
738  TrajectoryStateOnSurface& state0,
739  TrajectoryStateOnSurface& state1,
740  TrajectoryStateOnSurface& state2,
741  float nomField, bool isDebug) {
742 
743  //these need to be sorted in R
744  GlobalPoint gp0 = hit0->globalPosition();
745  GlobalPoint gp1 = hit1->globalPosition();
746  GlobalPoint gp2 = hit2->globalPosition();
747 
748  IfLogTrace(isDebug, "MultiHitGeneratorFromChi2") << "positions before refitting: " << hit0->globalPosition() << " " << hit1->globalPosition() << " " << hit2->globalPosition();
749  }
750 
751  FastCircle theCircle(gp2,gp1,gp0);
752  GlobalPoint cc(theCircle.x0(),theCircle.y0(),0);
753  float tesla0 = 0.1*nomField;
754  float rho = theCircle.rho();
755  float cm2GeV = 0.01 * 0.3*tesla0;
756  float pt = cm2GeV * rho;
757 
758  GlobalVector vec20 = gp2-gp0;
759  //IfLogTrace(isDebug, "MultiHitGeneratorFromChi2") << "vec20.eta=" << vec20.eta();
760 
761  GlobalVector p0( gp0.y()-cc.y(), -gp0.x()+cc.x(), 0. );
762  p0 = p0*pt/p0.perp();
763  GlobalVector p1( gp1.y()-cc.y(), -gp1.x()+cc.x(), 0. );
764  p1 = p1*pt/p1.perp();
765  GlobalVector p2( gp2.y()-cc.y(), -gp2.x()+cc.x(), 0. );
766  p2 = p2*pt/p2.perp();
767 
768  //check sign according to scalar product
769  if ( (p0.x()*(gp1.x()-gp0.x())+p0.y()*(gp1.y()-gp0.y()) ) < 0 ) {
770  p0*=-1.;
771  p1*=-1.;
772  p2*=-1.;
773  }
774 
775  //now set z component
776  p0 = GlobalVector(p0.x(),p0.y(),p0.perp()/tan(vec20.theta()));
777  p1 = GlobalVector(p1.x(),p1.y(),p1.perp()/tan(vec20.theta()));
778  p2 = GlobalVector(p2.x(),p2.y(),p2.perp()/tan(vec20.theta()));
779 
780  //get charge from vectorial product
781  TrackCharge q = 1;
782  if ((gp1-cc).x()*p1.y() - (gp1-cc).y()*p1.x() > 0) q =-q;
783 
784  GlobalTrajectoryParameters kine0 = GlobalTrajectoryParameters(gp0, p0, q, &*bfield);
785  state0 = TrajectoryStateOnSurface(kine0,*hit0->surface());
786  hit0 = hit0->clone(state0);
787 
788  GlobalTrajectoryParameters kine1 = GlobalTrajectoryParameters(gp1, p1, q, &*bfield);
789  state1 = TrajectoryStateOnSurface(kine1,*hit1->surface());
790  hit1 = hit1->clone(state1);
791 
792  GlobalTrajectoryParameters kine2 = GlobalTrajectoryParameters(gp2, p2, q, &*bfield);
793  state2 = TrajectoryStateOnSurface(kine2,*hit2->surface());
794  hit2 = hit2->clone(state2);
795 
796  IfLogTrace(isDebug, "MultiHitGeneratorFromChi2") << "charge=" << q << std::endl
797  << "state0 pt=" << state0.globalMomentum().perp() << " eta=" << state0.globalMomentum().eta() << " phi=" << state0.globalMomentum().phi() << std::endl
798  << "state1 pt=" << state1.globalMomentum().perp() << " eta=" << state1.globalMomentum().eta() << " phi=" << state1.globalMomentum().phi() << std::endl
799  << "state2 pt=" << state2.globalMomentum().perp() << " eta=" << state2.globalMomentum().eta() << " phi=" << state2.globalMomentum().phi() << std::endl
800  << "positions after refitting: " << hit0->globalPosition() << " " << hit1->globalPosition() << " " << hit2->globalPosition();
801 }
802 */
size
Write out results.
T perp() const
Definition: PV3DBase.h:69
MultiHitGeneratorFromChi2(const edm::ParameterSet &cfg, edm::ConsumesCollector &&iC)
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
std::unique_ptr< BaseTrackerRecHit > cacheHitPointer
#define IfLogTrace(cond, cat)
T z() const
Definition: PV3DBase.h:61
constexpr bool isNotFinite(T x)
Definition: isFinite.h:9
static constexpr auto TID
Definition: SiStripDetId.h:38
TkTransientTrackingRecHitBuilder const * builder
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
const ClusterShapeHitFilter * filter
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
constexpr T normalizedPhi(T phi)
Definition: normalizedPhi.h:8
float *__restrict__ zv
T eta() const
Definition: PV3DBase.h:73
unsigned int stereoId() const
Log< level::Error, false > LogError
assert(be >=bs)
edm::ESGetToken< TransientTrackingRecHitBuilder, TransientRecHitRecord > transientTrackingRecHitBuilderESToken_
bool isCompatible(const SiPixelRecHit &recHit, const LocalVector &ldir, const SiPixelClusterShapeCache &clusterShapeCache, PixelData const *pd=nullptr) const
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:117
T curvature(T InversePt, const MagneticField &field)
#define LogTrace(id)
void reset()
Definition: mayown_ptr.h:72
constexpr T proxim(T b, T a)
Definition: normalizedPhi.h:14
T const * release()
Definition: mayown_ptr.h:67
constexpr std::array< uint8_t, layerIndexSize< TrackerTraits > > layer
U second(std::pair< T, U > const &p)
constexpr float fnSigmaRZ
int TrackCharge
Definition: TrackCharge.h:4
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
BaseTrackerRecHit const * ConstRecHitPointer
Definition: SeedingHitSet.h:14
SiStripCluster const & monoCluster() const
std::vector< HitWithPhi >::const_iterator HitIter
Definition: EPCuts.h:4
edm::ESGetToken< ClusterShapeHitFilter, CkfComponentsRecord > clusterShapeHitFilterESToken_
void initES(const edm::EventSetup &es) override
double f[11][100]
BaseTrackerRecHit const * Hit
#define M_PI
Definition: RZLine.h:12
Definition: DetId.h:17
unsigned int monoId() const
void hitSets(const TrackingRegion &region, OrderedMultiHits &trs, const edm::Event &ev, const edm::EventSetup &es, SeedingLayerSetsHits::SeedingLayerSet pairLayers, std::vector< SeedingLayerSetsHits::SeedingLayer > thirdLayers) override
double y0() const
Definition: FastCircle.h:45
float chi2() const
Definition: RZLine.h:95
constexpr float minz[nPairs]
GlobalVector globalMomentum() const
SiStripCluster const & stereoCluster() const
static constexpr auto TIB
Definition: SiStripDetId.h:37
bool empty() const
Definition: mayown_ptr.h:85
void hitTriplets(const TrackingRegion &region, OrderedMultiHits &result, const HitDoublets &doublets, const RecHitsSortedInPhi **thirdHitMap, const std::vector< const DetLayer *> &thirdLayerDetLayer, const int nThirdLayers) override
SiStripRecHit2D originalHit() const
double rho() const
Definition: FastCircle.h:47
std::unique_ptr< HitPairGeneratorFromLayerPair > thePairGenerator
static void fillDescriptions(edm::ParameterSetDescription &desc)
int nominalValue() const
The nominal field value for this map in kGauss.
Definition: MagneticField.h:49
#define declareDynArray(T, n, x)
Definition: DynArray.h:91
void set(GlobalVector value)
TupleMultiplicity< TrackerTraits > const *__restrict__ TrackingRecHitSoAConstView< TrackerTraits > hh
bool isOwn() const
Definition: mayown_ptr.h:28
constexpr float maxz[nPairs]
PixelRecoRange< float > Range
edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magneticFieldESToken_
constexpr double twoPi()
Definition: Pi.h:32
static void fillDescriptions(edm::ParameterSetDescription &desc)
float phi(float curvature, float radius) const
def move(src, dest)
Definition: eostools.py:511
double x0() const
Definition: FastCircle.h:43
Global3DVector GlobalVector
Definition: GlobalVector.h:10
Range curvature(double transverseIP) const
#define LogDebug(id)
void refit2Hits(HitOwnPtr &hit0, HitOwnPtr &hit1, TrajectoryStateOnSurface &tsos0, TrajectoryStateOnSurface &tsos1, const TrackingRegion &region, float nomField, bool isDebug)
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11