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 
29 #include <algorithm>
30 #include <iostream>
31 #include <vector>
32 #include <cmath>
33 #include <map>
34 #include <limits>
35 
36 using namespace std;
37 
39 
41 
42 namespace {
43  struct LayerRZPredictions {
45  ThirdHitRZPrediction<HelixRZ> helix1, helix2;
46  };
47 }
48 
50  : thePairGenerator(0)
51  , theLayerCache(0)
52  , useFixedPreFiltering (cfg.getParameter<bool> ("useFixedPreFiltering") )
53  , extraHitRZtolerance (cfg.getParameter<double>("extraHitRZtolerance") )
54  , extraHitRPhitolerance(cfg.getParameter<double>("extraHitRPhitolerance") )
55  , extraPhiKDBox (cfg.getParameter<double>("extraPhiKDBox") )
56  , fnSigmaRZ (cfg.getParameter<double>("fnSigmaRZ") )
57  , chi2VsPtCut (cfg.getParameter<bool> ("chi2VsPtCut") )
58  , maxChi2 (cfg.getParameter<double>("maxChi2") )
59  , refitHits (cfg.getParameter<bool> ("refitHits") )
60  , debug (cfg.getParameter<bool> ("debug") )
61  , filterName_ (cfg.getParameter<std::string>("ClusterShapeHitFilterName"))
62  , useSimpleMF_ (false)
63  , mfName_ ("")
64 {
65  theMaxElement=cfg.getParameter<unsigned int>("maxElement");
67  dphi = cfg.getParameter<double>("phiPreFiltering");
68  if (chi2VsPtCut) {
69  pt_interv = cfg.getParameter<std::vector<double> >("pt_interv");
70  chi2_cuts = cfg.getParameter<std::vector<double> >("chi2_cuts");
71  }
72  if (debug) {
73  detIdsToDebug = cfg.getParameter<std::vector<int> >("detIdsToDebug");
74  //if (detIdsToDebug.size()<3) //fixme
75  } else {
76  detIdsToDebug.push_back(0);
77  detIdsToDebug.push_back(0);
78  detIdsToDebug.push_back(0);
79  }
80  // 2014/02/11 mia:
81  // we should get rid of the boolean parameter useSimpleMF,
82  // and use only a string magneticField [instead of SimpleMagneticField]
83  // or better an edm::ESInputTag (at the moment HLT does not handle ESInputTag)
84  if (cfg.exists("SimpleMagneticField")) {
85  useSimpleMF_ = true;
86  mfName_ = cfg.getParameter<std::string>("SimpleMagneticField");
87  }
88  bfield = 0;
89  nomField = -1.;
90 }
91 
93  LayerCacheType *layerCache)
94 {
95  thePairGenerator = pairs.clone();
96  theLayerCache = layerCache;
97 }
98 
100  std::vector<SeedingLayerSetsHits::SeedingLayer> thirdLayers) {
101  thePairGenerator->setSeedingLayers(pairLayers);
102  theLayers = thirdLayers;
103 }
104 
105 namespace {
106  inline
107  bool intersect(Range &range, const Range &second)
108  {
109  if (range.first > second.max() || range.second < second.min())
110  return false;
111  if (range.first < second.min())
112  range.first = second.min();
113  if (range.second > second.max())
114  range.second = second.max();
115  return range.first < range.second;
116  }
117 }
118 
121  const edm::Event & ev,
122  const edm::EventSetup& es)
123 {
124 
125  //gc: why is this here and not in some initialization???
127  es.get<TrackerDigiGeometryRecord>().get(tracker);
128  if (nomField<0 && bfield == 0) {
130  es.get<IdealMagneticFieldRecord>().get(mfName_, bfield_h);
131  // edm::ESInputTag mfESInputTag(mfName_);
132  // es.get<IdealMagneticFieldRecord>().get(mfESInputTag, bfield_h);
133  bfield = bfield_h.product();
135  }
136 
138  es.get<CkfComponentsRecord>().get(filterName_, filterHandle_);
139  filter = filterHandle_.product();
140 
141  //Retrieve tracker topology from geometry
142  //edm::ESHandle<TrackerTopology> tTopoHand;
143  //es.get<IdealGeometryRecord>().get(tTopoHand);
144  //const TrackerTopology *tTopo=tTopoHand.product();
145 
146  if (debug) cout << "pair: " << ((HitPairGeneratorFromLayerPair*) thePairGenerator)->innerLayer().name() << "+" << ((HitPairGeneratorFromLayerPair*) thePairGenerator)->outerLayer().name() << " 3rd lay size: " << theLayers.size() << endl;
147 
148  //gc: first get the pairs
149  OrderedHitPairs pairs;
150  pairs.reserve(30000);
151  thePairGenerator->hitPairs(region,pairs,ev,es);
152  if (pairs.empty()) {
153  //cout << "empy pairs" << endl;
154  return;
155  }
156 
157  //gc: these are all the layers compatible with the layer pairs (as defined in the config file)
158  int size = theLayers.size();
159 
160  unsigned int debug_Id0 = detIdsToDebug[0];//402664068;
161  unsigned int debug_Id1 = detIdsToDebug[1];//402666628;
162  unsigned int debug_Id2 = detIdsToDebug[2];//402669320;//470049160;
163 
164  //gc: initialize a KDTree per each 3rd layer
165  std::vector<KDTreeNodeInfo<RecHitsSortedInPhi::HitIter> > layerTree; // re-used throughout
166  std::vector<RecHitsSortedInPhi::HitIter> foundNodes; // re-used thoughout
167  foundNodes.reserve(100);
169  float rzError[size]; //save maximum errors
170  double maxphi = Geom::twoPi(), minphi = -maxphi; //increase to cater for any range
171 
172  //map<const DetLayer*, LayerRZPredictions> mapPred;//gc
173  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. TEC and OTEC)
174  const RecHitsSortedInPhi * thirdHitMap[size];//gc: this comes from theLayerCache
175 
176  //gc: loop over each layer
177  for(int il = 0; il < size; il++) {
178  thirdHitMap[il] = &(*theLayerCache)(theLayers[il], region, ev, es);
179  if (debug) cout << "considering third layer: " << theLayers[il].name() << " with hits: " << thirdHitMap[il]->all().second-thirdHitMap[il]->all().first << endl;
180  const DetLayer *layer = theLayers[il].detLayer();
181  LayerRZPredictions &predRZ = mapPred[theLayers[il].name()];
182  predRZ.line.initLayer(layer);
183  predRZ.line.initTolerance(extraHitRZtolerance);
184 
185  //gc: now we take all hits in the layer and fill the KDTree
186  RecHitsSortedInPhi::Range hitRange = thirdHitMap[il]->all(); // Get iterators
187  layerTree.clear();
188  double minz=999999.0, maxz= -999999.0; // Initialise to extreme values in case no hits
189  float maxErr=0.0f;
190  bool barrelLayer = (theLayers[il].detLayer()->location() == GeomDetEnumerators::barrel);
191  if (hitRange.first != hitRange.second)
192  { minz = barrelLayer? hitRange.first->hit()->globalPosition().z() : hitRange.first->hit()->globalPosition().perp();
193  maxz = minz; //In case there's only one hit on the layer
194  for (RecHitsSortedInPhi::HitIter hi=hitRange.first; hi != hitRange.second; ++hi)
195  { double angle = hi->phi();
196  double myz = barrelLayer? hi->hit()->globalPosition().z() : hi->hit()->globalPosition().perp();
197 
198  if (debug && hi->hit()->rawId()==debug_Id2) cout << "filling KDTree with hit in id=" << debug_Id2
199  << " with pos: " << hi->hit()->globalPosition()
200  << " phi=" << hi->hit()->globalPosition().phi()
201  << " z=" << hi->hit()->globalPosition().z()
202  << " r=" << hi->hit()->globalPosition().perp()
203  << " trans: " << hi->hit()->transientHits()[0]->globalPosition() << " "
204  << (hi->hit()->transientHits().size()>1 ? hi->hit()->transientHits()[1]->globalPosition() : GlobalPoint(0,0,0))
205  << endl;
206 
207  //use (phi,r) for endcaps rather than (phi,z)
208  if (myz < minz) { minz = myz;} else { if (myz > maxz) {maxz = myz;}}
209  float myerr = barrelLayer? hi->hit()->errorGlobalZ(): hi->hit()->errorGlobalR();
210  if (myerr > maxErr) { maxErr = myerr;}
211  layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle, myz)); // save it
212  if (angle < 0) // wrap all points in phi
213  { layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle+Geom::twoPi(), myz));}
214  else
215  { layerTree.push_back(KDTreeNodeInfo<RecHitsSortedInPhi::HitIter>(hi, angle-Geom::twoPi(), myz));}
216  }
217  }
218  KDTreeBox phiZ(minphi, maxphi, minz-0.01, maxz+0.01); // declare our bounds
219  //add fudge factors in case only one hit and also for floating-point inaccuracy
220  hitTree[il].build(layerTree, phiZ); // make KDtree
221  rzError[il] = maxErr; //save error
222  }
223  //gc: ok now we have initialized the KDTrees and we are out of the layer loop
224 
225  //gc: ok, this sets the minPt of the triplet
226  double curv = PixelRecoUtilities::curvature(1. / region.ptMin(), es);
227 
228  if (debug) std::cout << "pair size=" << pairs.size() << std::endl;
229 
230  //gc: now we loop over all pairs
231  for (OrderedHitPairs::const_iterator ip = pairs.begin(); ip != pairs.end(); ++ip) {
232 
233  int foundTripletsFromPair = 0;
234  bool usePair = false;
235  SeedingHitSet triplet;
237 
240 
241  GlobalPoint gp0 = hit0->globalPosition();//ip->inner()->globalPosition();
242  GlobalPoint gp1 = hit1->globalPosition();//ip->outer()->globalPosition();
243 
244  if (refitHits) {//fixme
245  GlobalVector pairMomentum(gp1 - gp0);
246  pairMomentum *= (1./pairMomentum.perp()); //set pT=1
247  GlobalTrajectoryParameters kinePair0 = GlobalTrajectoryParameters(hit0->globalPosition(), pairMomentum, 1, &*bfield);
248  TrajectoryStateOnSurface statePair0(kinePair0,*hit0->surface());
249  GlobalTrajectoryParameters kinePair1 = GlobalTrajectoryParameters(hit1->globalPosition(), pairMomentum, 1, &*bfield);
250  TrajectoryStateOnSurface statePair1(kinePair1,*hit1->surface());
251  hit0 = hit0->clone(statePair0);
252  hit1 = hit1->clone(statePair1);
253 
254  if (/* hit0->geographicalId().subdetId() > 2 && (*/
255  hit0->geographicalId().subdetId()==SiStripDetId::TIB /*|| hit0->geographicalId().subdetId()==SiStripDetId::TOB)*/
256  ) {
257  const std::type_info &tid = typeid(*hit0->hit());
258  if (tid == typeid(SiStripMatchedRecHit2D)) {
259  const SiStripMatchedRecHit2D* matchedHit = dynamic_cast<const SiStripMatchedRecHit2D *>(hit0->hit());
260  if (filter->isCompatible(DetId(matchedHit->monoId()), matchedHit->monoCluster(), pairMomentum)==0 ||
261  filter->isCompatible(DetId(matchedHit->stereoId()), matchedHit->stereoCluster(), pairMomentum)==0) continue;
262  } else if (tid == typeid(SiStripRecHit2D)) {
263  const SiStripRecHit2D* recHit = dynamic_cast<const SiStripRecHit2D *>(hit0->hit());
264  if (filter->isCompatible(*recHit, pairMomentum)==0) continue;
265  } else if (tid == typeid(ProjectedSiStripRecHit2D)) {
266  const ProjectedSiStripRecHit2D* precHit = dynamic_cast<const ProjectedSiStripRecHit2D *>(hit0->hit());
267  if (filter->isCompatible(precHit->originalHit(), pairMomentum)==0) continue;;
268  }
269  }
270 
271  if (/*hit1->geographicalId().subdetId() > 2 && (*/
272  hit1->geographicalId().subdetId()==SiStripDetId::TIB /*|| hit1->geographicalId().subdetId()==SiStripDetId::TOB)*/
273  ) {
274  const std::type_info &tid = typeid(*hit1->hit());
275  if (tid == typeid(SiStripMatchedRecHit2D)) {
276  const SiStripMatchedRecHit2D* matchedHit = dynamic_cast<const SiStripMatchedRecHit2D *>(hit1->hit());
277  if (filter->isCompatible(DetId(matchedHit->monoId()), matchedHit->monoCluster(), pairMomentum)==0 ||
278  filter->isCompatible(DetId(matchedHit->stereoId()), matchedHit->stereoCluster(), pairMomentum)==0) continue;
279  } else if (tid == typeid(SiStripRecHit2D)) {
280  const SiStripRecHit2D* recHit = dynamic_cast<const SiStripRecHit2D *>(hit1->hit());
281  if (filter->isCompatible(*recHit, pairMomentum)==0) continue;
282  } else if (tid == typeid(ProjectedSiStripRecHit2D)) {
283  const ProjectedSiStripRecHit2D* precHit = dynamic_cast<const ProjectedSiStripRecHit2D *>(hit1->hit());
284  if (filter->isCompatible(precHit->originalHit(), pairMomentum)==0) continue;;
285  }
286  }
287 
288 
289  }
290  //const TransientTrackingRecHit::ConstRecHitPointer& hit0 = refitHits ? ip->inner()->clone(statePair0) : ip->inner();
291  //const TransientTrackingRecHit::ConstRecHitPointer& hit1 = refitHits ? ip->outer()->clone(statePair1) : ip->outer();
292 
293  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) {
294  cout << "found new pair with ids "<<debug_Id0<<" "<<debug_Id1<<" with pos: " << gp0 << " " << gp1
295  << " trans0: " << ip->inner()->transientHits()[0]->globalPosition() << " " << ip->inner()->transientHits()[1]->globalPosition()
296  << " trans1: " << ip->outer()->transientHits()[0]->globalPosition() << " " << ip->outer()->transientHits()[1]->globalPosition()
297  << endl;
298  }
299 
300  //gc: create the RZ line for the pair
301  PixelRecoLineRZ line(gp0, gp1);
302  ThirdHitPredictionFromCircle predictionRPhi(gp0, gp1, extraHitRPhitolerance);
303 
304  //gc: this is the curvature of the two hits assuming the region
305  Range generalCurvature = predictionRPhi.curvature(region.originRBound());
306  if (!intersect(generalCurvature, Range(-curv, curv))) {
307  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) std::cout << "curvature cut: curv=" << curv << " gc=(" << generalCurvature.first << ", " << generalCurvature.second << ")" << std::endl;
308  continue;
309  }
310 
311  //gc: loop over all third layers compatible with the pair
312  for(int il = 0; il < size && !usePair; il++) {
313 
314  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1)
315  cout << "cosider layer: " << theLayers[il].name() << " for this pair. Location: " << theLayers[il].detLayer()->location() << endl;
316 
317  if (hitTree[il].empty()) {
318  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) {
319  cout << "empty hitTree" << endl;
320  }
321  continue; // Don't bother if no hits
322  }
323 
324  SeedingHitSet tripletFromThisLayer;
325  float chi2FromThisLayer = std::numeric_limits<float>::max();
326 
327  const DetLayer *layer = theLayers[il].detLayer();
328  bool barrelLayer = layer->location() == GeomDetEnumerators::barrel;
329 
330  //gc: this is the curvature of the two hits assuming the region
331  Range curvature = generalCurvature;
332 
333  //LayerRZPredictions &predRZ = mapPred.find(layer)->second;
334  LayerRZPredictions &predRZ = mapPred.find(theLayers[il].name())->second;
335  predRZ.line.initPropagator(&line);
336 
337  //gc: ok, this takes the z at R-thick/2 and R+thick/2 according to
338  // the line from the two points and the adds the extra tolerance
339  Range rzRange = predRZ.line();
340 
341  if (rzRange.first >= rzRange.second) {
342  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) {
343  cout << "rzRange empty" << endl;
344  }
345  continue;
346  }
347 
348  //gc: define the phi range of the hits
349  Range phiRange;
350  if (useFixedPreFiltering) {
351  //gc: in this case it takes as range the phi of the outer
352  // hit +/- the phiPreFiltering value from cfg
353  float phi0 = ip->outer()->globalPosition().phi();
354  phiRange = Range(phi0 - dphi, phi0 + dphi);
355  } else {
356  Range radius;
357 
358  if (barrelLayer) {
359  //gc: this is R-thick/2 and R+thick/2
360  radius = predRZ.line.detRange();
361  if (!intersect(rzRange, predRZ.line.detSize())) {// theDetSize = Range(-maxZ, maxZ);
362  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) {
363  cout << "rzRange and detector do not intersect" << endl;
364  }
365  continue;
366  }
367  } else {
368  radius = rzRange;
369  if (!intersect(radius, predRZ.line.detSize())) {
370  if (debug && ip->inner()->rawId()==debug_Id0 && ip->outer()->rawId()==debug_Id1) {
371  cout << "rzRange and detector do not intersect" << endl;
372  }
373  continue;
374  }
375  }
376 
377  //gc: predictionRPhi uses the cosine rule to find the phi of the 3rd point at radius, assuming the curvature range [-c,+c]
378  //not sure if it is really needed to do it both for radius.first and radius.second... maybe one can do it once and inflate a bit
379  Range rPhi1 = predictionRPhi(curvature, radius.first);
380  Range rPhi2 = predictionRPhi(curvature, radius.second);
381  rPhi1.first /= radius.first;
382  rPhi1.second /= radius.first;
383  rPhi2.first /= radius.second;
384  rPhi2.second /= radius.second;
385  phiRange = mergePhiRanges(rPhi1, rPhi2);
386  /*
387  //test computing predictionRPhi only once
388  float avgRad = (radius.first+radius.second)/2.;
389  phiRange = predictionRPhi(curvature, avgRad);
390  phiRange.first = phiRange.first/avgRad - 0.0;
391  phiRange.second = phiRange.second/avgRad + 0.0;
392  */
393  }
394 
395  //gc: this is the place where hits in the compatible region are put in the foundNodes
397  foundNodes.clear(); // Now recover hits in bounding box...
398  float prmin=phiRange.min(), prmax=phiRange.max(); //get contiguous range
399  if ((prmax-prmin) > Geom::twoPi())
400  { prmax=Geom::pi(); prmin = -Geom::pi();}
401  else
402  { while (prmax>maxphi) { prmin -= Geom::twoPi(); prmax -= Geom::twoPi();}
403  while (prmin<minphi) { prmin += Geom::twoPi(); prmax += Geom::twoPi();}
404  // This needs range -twoPi to +twoPi to work
405  }
406  if (barrelLayer) {
407  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) cout << "defining kd tree box" << endl;
408  //gc: this is R-thick/2 and R+thick/2 (was already computed above!)
409  Range detR = predRZ.line.detRange();
410  //gc: it seems to me the same thing done here could be obtained from predRZ.line() which has already been computed
411  Range regMin = predRZ.line(detR.min());
412  Range regMax = predRZ.line(detR.max());
413  if (regMax.min() < regMin.min()) { swap(regMax, regMin);}
414  KDTreeBox phiZ(prmin-extraPhiKDBox, prmax+extraPhiKDBox,
415  regMin.min()-fnSigmaRZ*rzError[il],
416  regMax.max()+fnSigmaRZ*rzError[il]);
417 
418  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) cout << "kd tree box bounds, phi: " << prmin <<","<< prmax
419  << " z: "<< regMin.min()-fnSigmaRZ*rzError[il] <<","<<regMax.max()+fnSigmaRZ*rzError[il]
420  << " detR: " << detR.min() <<","<<detR.max()
421  << " regMin: " << regMin.min() <<","<<regMin.max()
422  << " regMax: " << regMax.min() <<","<<regMax.max()
423  << endl;
424  hitTree[il].search(phiZ, foundNodes);
425  }
426  else {
427  KDTreeBox phiR(prmin-extraPhiKDBox, prmax+extraPhiKDBox,
428  rzRange.min()-fnSigmaRZ*rzError[il],
429  rzRange.max()+fnSigmaRZ*rzError[il]);
430  hitTree[il].search(phiR, foundNodes);
431 
432  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) cout << "kd tree box bounds, phi: " << prmin <<","<< prmax
433  << " r: "<< rzRange.min()-fnSigmaRZ*rzError[il] <<","<<rzRange.max()+fnSigmaRZ*rzError[il]
434  << " rzRange: " << rzRange.min() <<","<<rzRange.max()
435  << endl;
436 
437  }
438 
439  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) cout << "kd tree box size: " << foundNodes.size() << endl;
440 
441 
442  //gc: now we loop over the hits in the box for this layer
443  for (std::vector<RecHitsSortedInPhi::HitIter>::iterator ih = foundNodes.begin();
444  ih !=foundNodes.end() && !usePair; ++ih) {
445 
446 
447 
448  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) std::cout << "triplet candidate" << std::endl;
449 
450  const RecHitsSortedInPhi::HitIter KDdata = *ih;
451 
452  TransientTrackingRecHit::ConstRecHitPointer hit2 = KDdata->hit();
453  if (refitHits) {//fixme
454  GlobalVector initMomentum(hit2->globalPosition() - gp1);
455  initMomentum *= (1./initMomentum.perp()); //set pT=1
456  if (/*hit2->geographicalId().subdetId() > 2 && (*/
457  hit2->geographicalId().subdetId()==SiStripDetId::TIB /*|| hit2->geographicalId().subdetId()==SiStripDetId::TOB)*/
458  ) {
459  const std::type_info &tid = typeid(*hit2->hit());
460  if (tid == typeid(SiStripMatchedRecHit2D)) {
461  const SiStripMatchedRecHit2D* matchedHit = dynamic_cast<const SiStripMatchedRecHit2D *>(hit2->hit());
462  if (filterHandle_->isCompatible(DetId(matchedHit->monoId()), matchedHit->monoCluster(), initMomentum)==0 ||
463  filterHandle_->isCompatible(DetId(matchedHit->stereoId()), matchedHit->stereoCluster(), initMomentum)==0) continue;
464  } else if (tid == typeid(SiStripRecHit2D)) {
465  const SiStripRecHit2D* recHit = dynamic_cast<const SiStripRecHit2D *>(hit2->hit());
466  if (filterHandle_->isCompatible(*recHit, initMomentum)==0) continue;
467  } else if (tid == typeid(ProjectedSiStripRecHit2D)) {
468  const ProjectedSiStripRecHit2D* precHit = dynamic_cast<const ProjectedSiStripRecHit2D *>(hit2->hit());
469  if (filterHandle_->isCompatible(precHit->originalHit(), initMomentum)==0) continue;;
470  }
471  }
472  GlobalTrajectoryParameters kine = GlobalTrajectoryParameters(hit2->globalPosition(), initMomentum, 1, &*bfield);
473  TrajectoryStateOnSurface state(kine,*hit2->surface());
474  hit2 = hit2->clone(state);
475  }
476  //const TransientTrackingRecHit::ConstRecHitPointer& hit2 = refitHits ? KDdata->hit()->clone(state) : KDdata->hit();
477 
478  //gc: try to add the chi2 cut
479  vector<GlobalPoint> gp(3);
480  vector<GlobalError> ge(3);
481  vector<bool> bl(3);
482  gp[0] = hit0->globalPosition();
483  ge[0] = hit0->globalPositionError();
484  int subid0 = hit0->geographicalId().subdetId();
485  bl[0] = (subid0 == StripSubdetector::TIB || subid0 == StripSubdetector::TOB || subid0 == (int) PixelSubdetector::PixelBarrel);
486  gp[1] = hit1->globalPosition();
487  ge[1] = hit1->globalPositionError();
488  int subid1 = hit1->geographicalId().subdetId();
489  bl[1] = (subid1 == StripSubdetector::TIB || subid1 == StripSubdetector::TOB || subid1 == (int) PixelSubdetector::PixelBarrel);
490  gp[2] = hit2->globalPosition();
491  ge[2] = hit2->globalPositionError();
492  int subid2 = hit2->geographicalId().subdetId();
493  bl[2] = (subid2 == StripSubdetector::TIB || subid2 == StripSubdetector::TOB || subid2 == (int) PixelSubdetector::PixelBarrel);
494  RZLine rzLine(gp,ge,bl);
495  float cottheta, intercept, covss, covii, covsi;
496  rzLine.fit(cottheta, intercept, covss, covii, covsi);
497  float chi2 = rzLine.chi2(cottheta, intercept);
498 
499  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1) {
500  if (hit2->rawId()==debug_Id2) {
501  std::cout << endl << "triplet candidate" << std::endl;
502  cout << "hit in id="<<debug_Id2<<" (from KDTree) with pos: " << KDdata->hit()->globalPosition()
503  << " refitted: " << hit2->globalPosition()
504  << " trans2: " << hit2->transientHits()[0]->globalPosition() << " " << (hit2->transientHits().size()>1 ? hit2->transientHits()[1]->globalPosition() : GlobalPoint(0,0,0))
505  << " chi2: " << chi2
506  << endl;
507  //cout << state << endl;
508  }
509  //gc: try to add the chi2 cut OLD version
510  vector<float> r(3),z(3),errR(3);
511  r[0] = ip->inner()->globalPosition().perp();
512  z[0] = ip->inner()->globalPosition().z();
513  errR[0] = sqrt(ip->inner()->globalPositionError().cxx()+ip->inner()->globalPositionError().cyy());
514  r[1] = ip->outer()->globalPosition().perp();
515  z[1] = ip->outer()->globalPosition().z();
516  errR[1] = sqrt(ip->outer()->globalPositionError().cxx()+ip->outer()->globalPositionError().cyy());
517  r[2] = KDdata->hit()->globalPosition().perp();
518  z[2] = KDdata->hit()->globalPosition().z();
519  errR[2] = sqrt(KDdata->hit()->globalPositionError().cxx()+KDdata->hit()->globalPositionError().cxx());
520  RZLine oldLine(z,r,errR);
521  float cottheta_old, intercept_old, covss_old, covii_old, covsi_old;
522  oldLine.fit(cottheta_old, intercept_old, covss_old, covii_old, covsi_old);
523  float chi2_old = oldLine.chi2(cottheta_old, intercept_old);
524  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1 && hit2->rawId()==debug_Id2) {
525  cout << "triplet with ids: " << hit0->geographicalId().rawId() << " " << hit1->geographicalId().rawId() << " " << hit2->geographicalId().rawId()
526  << " hitpos: " << gp[0] << " " << gp[1] << " " << gp[2]
527  << " eta,phi: " << gp[0].eta() << "," << gp[0].phi() << " chi2: " << chi2 << " chi2_old: " << chi2_old << endl
528  << "trans0: " << hit0->transientHits()[0]->globalPosition() << " " << hit0->transientHits()[1]->globalPosition() << endl
529  << "trans1: " << hit1->transientHits()[0]->globalPosition() << " " << hit1->transientHits()[1]->globalPosition() << endl
530  << "trans2: " << hit2->transientHits()[0]->globalPosition() << " " << (hit2->transientHits().size()>1 ? hit2->transientHits()[1]->globalPosition() : GlobalPoint(0,0,0))
531  << endl;
532  }
533  }
534 
535  if (chi2 > maxChi2) continue;
536 
537  if (chi2VsPtCut) {
538 
539  //FastHelix helix = FastHelix(hit2->globalPosition(),hit1->globalPosition(),hit0->globalPosition(),nomField,bfield);
540  //if (helix.isValid()==0) continue;//fixme: check cases where helix fails
541  //this is to compute the status at the 3rd point
542  //FastCircle theCircle = helix.circle();
543 
544  //GlobalPoint maxRhit2(hit2->globalPosition().x()+(hit2->globalPosition().x()>0 ? sqrt(hit2->globalPositionError().cxx()) : sqrt(hit2->globalPositionError().cxx())*(-1.)),
545  //hit2->globalPosition().y()+(hit2->globalPosition().y()>0 ? sqrt(hit2->globalPositionError().cyy()) : sqrt(hit2->globalPositionError().cyy())*(-1.)),
546  //hit2->globalPosition().z());
547  FastCircle theCircle(hit2->globalPosition(),hit1->globalPosition(),hit0->globalPosition());
548  float tesla0 = 0.1*nomField;
549  float rho = theCircle.rho();
550  float cm2GeV = 0.01 * 0.3*tesla0;
551  float pt = cm2GeV * rho;
552  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1 && hit2->rawId()==debug_Id2) {
553  std::cout << "triplet pT=" << pt << std::endl;
554  }
555  if (pt<region.ptMin()) continue;
556 
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 
567  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1 && hit2->rawId()==debug_Id2) {
568  std::cout << "triplet passed chi2 vs pt cut" << std::endl;
569  }
570  }
571 
572  }
573 
574  if (theMaxElement!=0 && result.size() >= theMaxElement) {
575  result.clear();
576  edm::LogError("TooManyTriplets")<<" number of triples exceed maximum. no triplets produced.";
577  return;
578  }
579  if (debug && hit0->rawId()==debug_Id0 && hit1->rawId()==debug_Id1 && hit2->rawId()==debug_Id2) std::cout << "triplet made" << std::endl;
580  //result.push_back(SeedingHitSet(hit0, hit1, hit2));
581  tripletFromThisLayer = SeedingHitSet(hit0, hit1, hit2);
582  chi2FromThisLayer = chi2;
583  foundTripletsFromPair++;
584  if (foundTripletsFromPair>=2) {
585  usePair=true;
586  break;
587  }
588  }//loop over hits in KDTree
589 
590  if (usePair) break;
591  else {
592  //if there is one triplet in more than one layer, try picking the one with best chi2
593  if (chi2FromThisLayer<minChi2) {
594  triplet = tripletFromThisLayer;
595  minChi2 = chi2FromThisLayer;
596  }
597  }
598 
599  }//loop over layers
600 
601  if (foundTripletsFromPair==0) continue;
602 
603  //push back only (max) once per pair
604  if (usePair) result.push_back(SeedingHitSet(ip->inner(), ip->outer()));
605  else result.push_back(triplet);
606 
607  }//loop over pairs
608  if (debug) {
609  std::cout << "triplet size=" << result.size() << std::endl;
610  }
611 }
612 
613 bool MultiHitGeneratorFromChi2::checkPhiInRange(float phi, float phi1, float phi2) const
614 { while (phi > phi2) phi -= 2. * M_PI;
615  while (phi < phi1) phi += 2. * M_PI;
616  return phi <= phi2;
617 }
618 
619 std::pair<float, float>
620 MultiHitGeneratorFromChi2::mergePhiRanges(const std::pair<float, float> &r1,
621  const std::pair<float, float> &r2) const
622 { float r2Min = r2.first;
623  float r2Max = r2.second;
624  while (r1.first - r2Min > +M_PI) r2Min += 2. * M_PI, r2Max += 2. * M_PI;
625  while (r1.first - r2Min < -M_PI) r2Min -= 2. * M_PI, r2Max -= 2. * M_PI;
626  //std::cout << "mergePhiRanges " << fabs(r1.first-r2Min) << " " << fabs(r1.second-r2Max) << endl;
627  return std::make_pair(min(r1.first, r2Min), max(r1.second, r2Max));
628 }
float originRBound() const
bounds the particle vertex in the transverse plane
void swap(ora::Record &rh, ora::Record &lh)
Definition: Record.h:70
T getParameter(std::string const &) const
std::pair< float, float > mergePhiRanges(const std::pair< float, float > &r1, const std::pair< float, float > &r2) const
virtual HitPairGenerator * clone() const =0
void build(std::vector< KDTreeNodeInfo > &eltList, const KDTreeBox &region)
T perp() const
Definition: PV3DBase.h:72
virtual Location location() const =0
Which part of the detector (barrel, endcap)
ThirdHitPredictionFromCircle::HelixRZ HelixRZ
int nominalValue() const
The nominal field value for this map in kGauss.
const ClusterShapeHitFilter * filter
Definition: DDAxes.h:10
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
bool exists(std::string const &parameterName) const
checks if a parameter exists
virtual unsigned int size() const
void search(const KDTreeBox &searchBox, std::vector< KDTreeNodeInfo > &resRecHitList)
float float float z
Range curvature(double transverseIP) const
std::vector< SeedingLayerSetsHits::SeedingLayer > theLayers
static float fnSigmaRZ
U second(std::pair< T, U > const &p)
virtual unsigned int size() const
void init(const HitPairGenerator &pairs, LayerCacheType *layerCache) override
std::pair< HitIter, HitIter > Range
T curvature(T InversePt, const edm::EventSetup &iSetup)
const T & max(const T &a, const T &b)
std::vector< HitWithPhi >::const_iterator HitIter
T sqrt(T t)
Definition: SSEVec.h:48
void setSeedingLayers(SeedingLayerSetsHits::SeedingLayerSet pairLayers, std::vector< SeedingLayerSetsHits::SeedingLayer > thirdLayers) override
tuple result
Definition: query.py:137
MultiHitGeneratorFromChi2(const edm::ParameterSet &cfg)
bool isCompatible(const SiPixelRecHit &recHit, const LocalVector &ldir, PixelData const *pd=nullptr) const
Definition: RZLine.h:8
Definition: DetId.h:18
PixelRecoRange< float > Range
#define M_PI
Definition: BFit3D.cc:3
#define debug
Definition: HDRShower.cc:19
const T & get() const
Definition: EventSetup.h:55
T const * product() const
Definition: ESHandle.h:62
float ptMin() const
minimal pt of interest
double pi()
Definition: Pi.h:31
double twoPi()
Definition: Pi.h:32
TransientTrackingRecHit::ConstRecHitPointer Hit
void fit(float &cotTheta, float &intercept, float &covss, float &covii, float &covsi) const
Definition: RZLine.cc:44
tuple cout
Definition: gather_cfg.py:121
float chi2(float cotTheta, float intercept) const
Definition: RZLine.cc:50
volatile std::atomic< bool > shutdown_flag false
const SiStripRecHit2D & originalHit() const
tuple size
Write out results.
virtual void setSeedingLayers(SeedingLayerSetsHits::SeedingLayerSet layers)=0
bool checkPhiInRange(float phi, float phi1, float phi2) const
virtual void hitSets(const TrackingRegion &region, OrderedMultiHits &trs, const edm::Event &ev, const edm::EventSetup &es)
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11
Definition: DDAxes.h:10