test
CMS 3D CMS Logo

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