CMS 3D CMS Logo

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