CMS 3D CMS Logo

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