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 (not doublets or 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
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:112
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
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
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
edm::ESGetToken< ClusterShapeHitFilter, CkfComponentsRecord > clusterShapeHitFilterESToken_
void initES(const edm::EventSetup &es) override
double f[11][100]
ALPAKA_FN_ACC ALPAKA_FN_INLINE void uint32_t const uint32_t CACellT< TrackerTraits > uint32_t CellNeighborsVector< TrackerTraits > CellTracksVector< TrackerTraits > HitsConstView< TrackerTraits > hh
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)
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