CMS 3D CMS Logo

SiStripElectronAlgo.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: EgammaElectronAlgos
4 // Class : SiStripElectronAlgo
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Jim Pivarski
10 // Created: Fri May 26 16:12:04 EDT 2006
11 //
12 
13 // system include files
14 
15 // user include files
19 
20 
23 
27 
28 
29 //
30 // constants, enums and typedefs
31 //
32 
33 //
34 // static data member definitions
35 //
36 namespace {
37  struct CompareHits {
38  CompareHits( const TrackingRecHitLessFromGlobalPosition& iLess ) :
39  less_(iLess) {}
40  bool operator()(const TrackingRecHit* iLHS, const TrackingRecHit* iRHS) {
41  return less_(*iLHS,*iRHS);
42  }
43 
45  };
46 }
47 
48 
49 //
50 // constructors and destructor
51 //
53  double originUncertainty,
54  double phiBandWidth,
55  double maxNormResid,
56  unsigned int minHits,
57  double maxReducedChi2)
58  : maxHitsOnDetId_(maxHitsOnDetId)
59  , originUncertainty_(originUncertainty)
60  , phiBandWidth_(phiBandWidth)
61  , maxNormResid_(maxNormResid)
62  , minHits_(minHits)
63  , maxReducedChi2_(maxReducedChi2)
64 {
65 }
66 
67 // SiStripElectronAlgo::SiStripElectronAlgo(const SiStripElectronAlgo& rhs)
68 // {
69 // // do actual copying here;
70 // }
71 
73 {
74 }
75 
76 //
77 // assignment operators
78 //
79 // const SiStripElectronAlgo& SiStripElectronAlgo::operator=(const SiStripElectronAlgo& rhs)
80 // {
81 // //An exception safe implementation is
82 // SiStripElectronAlgo temp(rhs);
83 // swap(rhs);
84 //
85 // return *this;
86 // }
87 
88 //
89 // member functions
90 //
91 
97 {
98  LogDebug("") << " In prepareEvent " ;
99 
100  tracker_p_ = tracker.product();
101  rphiHits_p_ = rphiHits.product();
102  stereoHits_p_ = stereoHits.product();
103  matchedHits_p_ = matchedHits.product();
104  magneticField_p_ = magneticField.product();
105 
106  rphiHits_hp_ = &rphiHits;
107  stereoHits_hp_ = &stereoHits;
108 
109  // Keep a table that relates hit pointers to their index (key) in the collections
110  rphiKey_.clear();
111  stereoKey_.clear();
112  // Keep track of which hits have been used already (so a hit is assigned to only one electron)
113  hitUsed_.clear();
114  matchedHitUsed_.clear();
115 
116  unsigned int counter = 0;
118  rphiKey_[&(*it)] = counter;
119  hitUsed_[&(*it)] = false;
120  counter++;
121  }
122 
123  counter = 0;
125  stereoKey_[&(*it)] = counter;
126  hitUsed_[&(*it)] = false;
127  counter++;
128  }
129 
130  counter = 0;
132  matchedKey_[&(*it)] = counter;
133  matchedHitUsed_[&(*it)] = false;
134  counter++;
135  }
136 
137  LogDebug("") << " Leaving prepareEvent " ;
138 }
139 
140 
141 
142 // returns true iff an electron was found
143 // inserts electrons and trackcandiates into electronOut and trackCandidateOut
145  TrackCandidateCollection& trackCandidateOut,
146  const reco::SuperClusterRef& superclusterIn,
147  const TrackerTopology *tTopo)
148 {
149  // Try each of the two charge hypotheses, but only take one
150  bool electronSuccess = projectPhiBand(-1., superclusterIn, tTopo);
151  bool positronSuccess = projectPhiBand( 1., superclusterIn, tTopo);
152 
153  // electron hypothesis did better than electron
154  if ((electronSuccess && !positronSuccess) ||
155  (electronSuccess && positronSuccess && redchi2_neg_ <= redchi2_pos_)) {
156 
157  // Initial uncertainty for tracking
158  AlgebraicSymMatrix55 errors; // makes 5x5 matrix, indexed from (0,0) to (44)
159  errors(0,0) = 3.; // uncertainty**2 in 1/momentum
160  errors(1,1) = 0.01; // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
161  errors(2,2) = 0.0001; // uncertainty**2 in phi
162  errors(3,3) = 0.01; // uncertainty**2 in x_transverse (where x is in cm)
163  errors(4,4) = 0.01; // uncertainty**2 in y_transverse (where y is in cm)
164 
165 #ifdef EDM_ML_DEBUG
166  // JED Debugging possible double hit sort problem
167  std::ostringstream debugstr6;
168  debugstr6 << " HERE BEFORE SORT electron case " << " \n" ;
169  for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin();
170  itHit != outputHits_neg_.end(); ++itHit) {
171  debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
172  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
173  <<" Global Rho: "
174  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
175  <<" Phi "
176  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
177  << " Z "
178  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
179  }
180  // end of dump
181 
182 
183 
184  // JED call dump
185  debugstr6 << " Calling sort alongMomentum " << " \n";
186 #endif
187 
188  std::sort(outputHits_neg_.begin(), outputHits_neg_.end(),
190 
191 #ifdef EDM_ML_DEBUG
192  debugstr6 << " Done with sort " << " \n";
193 
194  debugstr6 << " HERE AFTER SORT electron case " << " \n";
195  for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin();
196  itHit != outputHits_neg_.end(); ++itHit) {
197  debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
198  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
199  <<" Global Rho: "
200  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
201  <<" Phi "
202  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
203  << " Z "
204  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";;
205  }
206  // end of dump
207 
208  LogDebug("")<< debugstr6.str();
209 #endif
210 
211  //create an OwnVector needed by the classes which will be stored to the Event
213  for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_neg_.begin();
214  itHit != outputHits_neg_.end();
215  ++itHit) {
216  hits.push_back( (*itHit)->clone());
217  if( !(hitUsed_.find(*itHit) != hitUsed_.end()) ) {
218  LogDebug("") << " Assert failure " ;
219  assert(hitUsed_.find(*itHit) != hitUsed_.end());
220  }
221  hitUsed_[*itHit] = true;
222  }
223 
228 
229 
231  TrajectorySeed trajectorySeed(PTraj, hits, alongMomentum);
232  trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, PTraj));
233 
234  electronOut.push_back(reco::SiStripElectron(superclusterIn,
235  -1,
239  slope_neg_,
240  intercept_neg_ + superclusterIn->position().phi(),
241  chi2_neg_,
242  ndof_neg_,
244  pZ_neg_,
249 
250  return true;
251  }
252 
253  // positron hypothesis did better than electron
254  if ((!electronSuccess && positronSuccess) ||
255  (electronSuccess && positronSuccess && redchi2_neg_ > redchi2_pos_)) {
256 
257  // Initial uncertainty for tracking
258  AlgebraicSymMatrix55 errors; // same as abovr
259  errors(0,0) = 3.; // uncertainty**2 in 1/momentum
260  errors(1,1) = 0.01; // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
261  errors(2,2) = 0.0001; // uncertainty**2 in phi
262  errors(3,3) = 0.01; // uncertainty**2 in x_transverse (where x is in cm)
263  errors(4,4) = 0.01; // uncertainty**2 in y_transverse (where y is in cm)
264 
265 #ifdef EDM_ML_DEBUG
266  // JED Debugging possible double hit sort problem
267  std::ostringstream debugstr7;
268  debugstr7 << " HERE BEFORE SORT Positron case " << " \n";
269  for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin();
270  itHit != outputHits_pos_.end(); ++itHit) {
271  debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
272  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
273  <<" Global Rho: "
274  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
275  <<" Phi "
276  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
277  << " Z "
278  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
279  }
280  // end of dump
281 
282  debugstr7 << " Calling sort alongMomentum " << " \n";
283 #endif
284 
285  std::sort(outputHits_pos_.begin(), outputHits_pos_.end(),
287 
288 #ifdef EDM_ML_DEBUG
289  debugstr7 << " Done with sort " << " \n";
290 
291  // JED Debugging possible double hit sort problem
292  debugstr7 << " HERE AFTER SORT Positron case " << " \n";
293  for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin();
294  itHit != outputHits_pos_.end(); ++itHit) {
295  debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
296  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
297  <<" Global Rho: "
298  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
299  <<" Phi "
300  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
301  << " Z "
302  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
303  }
304  // end of dump
305  LogDebug("") << debugstr7.str();
306 #endif
307 
308  //create an OwnVector needed by the classes which will be stored to the Event
310  for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_pos_.begin();
311  itHit != outputHits_pos_.end();
312  ++itHit) {
313  hits.push_back( (*itHit)->clone());
314  assert(hitUsed_.find(*itHit) != hitUsed_.end());
315  hitUsed_[*itHit] = true;
316  }
317 
322 
323 
325  TrajectorySeed trajectorySeed(PTraj, hits, alongMomentum);
326  trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, PTraj));
327 
328  electronOut.push_back(reco::SiStripElectron(superclusterIn,
329  1,
333  slope_pos_,
334  intercept_pos_ + superclusterIn->position().phi(),
335  chi2_pos_,
336  ndof_pos_,
338  pZ_pos_,
343 
344  return true;
345  }
346 
347  return false;
348 }
349 
350 // inserts pointers to good hits into hitPointersOut
351 // selects hits on DetIds that have no more than maxHitsOnDetId_
352 // selects from stereo if stereo == true, rphi otherwise
353 // selects from TID or TEC if endcap == true, TIB or TOB otherwise
354 void SiStripElectronAlgo::coarseHitSelection(std::vector<const SiStripRecHit2D*>& hitPointersOut,
355  const TrackerTopology *tTopo,
356  bool stereo, bool endcap)
357 {
358  // This function is not time-efficient. If you want to improve the
359  // speed of the algorithm, you'll probably want to change this
360  // function. There may be a more efficienct way to extract hits,
361  // and it would definitely help to put a geographical cut on the
362  // DetIds. (How does one determine the global position of a given
363  // DetId? Is tracker_p_->idToDet(id)->surface().toGlobal(LocalPosition(0,0,0))
364  // expensive?)
365 
366  // Loop over the detector ids
369  for (; itdet != eddet; ++itdet) {
370  // Get the hits on this detector id
372  DetId id(hits.detId());
373 
374  // Count the number of hits on this detector id
375  unsigned int numberOfHits = hits.size();
376 
377  // Only take the hits if there aren't too many
378  // (Would it be better to loop only once, fill a temporary list,
379  // and copy that if numberOfHits <= maxHitsOnDetId_?)
380  if (numberOfHits <= maxHitsOnDetId_) {
382  hit != hits.end(); ++hit) {
383  // check that hit is valid first !
384  if(!(*hit).isValid()) {
385  LogDebug("") << " InValid hit skipped in coarseHitSelection " << std::endl ;
386  continue ;
387  }
388  std::string theDet = "null";
389  bool isStereoDet = false ;
390  if(tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB) {
391  theDet = "TIB" ;
392  if(tTopo->tibStereo(id)==1) { isStereoDet = true ; }
393  } else if
394  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB) {
395  theDet = "TOB" ;
396  if(tTopo->tobStereo(id)==1) { isStereoDet = true ; }
397  }else if
398  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TID) {
399  theDet = "TID" ;
400  if(tTopo->tidStereo(id)==1) { isStereoDet = true ; }
401  }else if
402  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TEC) {
403  theDet = "TEC" ;
404  if(tTopo->tecStereo(id)==1) { isStereoDet = true ; }
405  } else {
406  LogDebug("") << " UHOH BIG PROBLEM - Unrecognized SI Layer" ;
407  LogDebug("") << " Det "<< theDet ;
408  assert(1!=1) ;
409  }
410 
411  if ((endcap && stereo && (theDet=="TID" || theDet== "TEC") && isStereoDet ) ||
412  (endcap && !stereo && (theDet=="TID" || theDet== "TEC") && !isStereoDet ) ||
413  (!endcap && stereo && (theDet=="TIB" || theDet=="TOB") && isStereoDet ) ||
414  (!endcap && !stereo && (theDet=="TIB" || theDet=="TOB" )&& !isStereoDet )
415  ) {
416 
417 
418  hitPointersOut.push_back(&(*hit));
419 
420  } // end if this is the right subdetector
421  } // end loop over hits
422  } // end if this detector id doesn't have too many hits on it
423  } // end loop over detector ids
424 }
425 
426 // select all matched hits for now
427 
428 void SiStripElectronAlgo::coarseMatchedHitSelection(std::vector<const SiStripMatchedRecHit2D*>& coarseMatchedHitPointersOut)
429 {
430 
431  // Loop over the detector ids
433  for (; itdet != eddet; ++itdet) {
434 
435  // Get the hits on this detector id
437 
438  // Count the number of hits on this detector id
439  unsigned int numberOfHits = 0;
441  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
442  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
443  numberOfHits++;
444  if (numberOfHits > maxHitsOnDetId_) { break; }
445  }
446 
447  // Only take the hits if there aren't too many
448  if (numberOfHits <= maxHitsOnDetId_) {
450  if(!(*hit).isValid()) {
451  LogDebug("") << " InValid hit skipped in coarseMatchedHitSelection " << std::endl ;
452  continue ;
453  }
454  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
455  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
456 
457  coarseMatchedHitPointersOut.push_back(&(*hit));
458  } // end loop over hits
459 
460  } // end if this detector id doesn't have too many hits on it
461  } // end loop over detector ids
462 
463 
464 }// end of matchedHitSelection
465 
466 
467 
468 
469 // projects a phi band of width phiBandWidth_ from supercluster into tracker (given a chargeHypothesis)
470 // fills *_pos_ or *_neg_ member data with the results
471 // returns true iff the electron/positron passes cuts
472 bool SiStripElectronAlgo::projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef& superclusterIn,
473  const TrackerTopology *tTopo)
474 {
475  // This algorithm projects a phi band into the tracker three times:
476  // (a) for all stereo hits, (b) for barrel rphi hits, and (c) for
477  // endcap zphi hits. While accumulating stereo hits in step (a),
478  // we fit r vs z to a line. This resolves the ambiguity in z for
479  // rphi hits and the ambiguity in r for zphi hits. We can then cut
480  // on the z of rphi hits (a little wider than one strip length),
481  // and we can convert the z of zphi hits into r to apply the phi
482  // band cut. (We don't take advantage of the endcap strips'
483  // segmentation in r.)
484  //
485  // As we project a phi band into the tracker, we count hits within
486  // that band and performs a linear fit for phi vs r. The number of
487  // hits and reduced chi^2 from the fit are used to select a good
488  // candidate.
489 
490  // set limits on Si hits - smallest error that makes sense = 1 micron ?
491  static const double rphiHitSmallestError = 0.0001 ;
492  static const double stereoHitSmallestError = 0.0001 ;
493  //not used since endcap is not implemented
494  // static const double zphiHitSmallestError = 0.0001 ;
495 
496 
497  static const double stereoPitchAngle = 0.100 ; // stereo angle in rad
498  static const double cos2SiPitchAngle = cos(stereoPitchAngle)*cos(stereoPitchAngle) ;
499  static const double sin2SiPitchAngle = sin(stereoPitchAngle)*sin(stereoPitchAngle) ;
500  // overall misalignment fudge to be added in quad to position errors.
501  // this is a rough approx to values reported in tracking meet 5/16/2007
502  static const double rphiErrFudge = 0.0200 ;
503  static const double stereoErrFudge = 0.0200 ;
504 
505  // max chi2 of a hit on an SiDet relative to the prediction
506  static const double chi2HitMax = 25.0 ;
507 
508  // Minimum number of hits to consider on a candidate
509  static const unsigned int nHitsLeftMinimum = 3 ;
510 
511  // Create and fill vectors of pointers to hits
512  std::vector<const SiStripRecHit2D*> stereoHits;
513  std::vector<const SiStripRecHit2D*> rphiBarrelHits;
514  std::vector<const SiStripRecHit2D*> zphiEndcapHits;
515 
516  // stereo? endcap?
517  coarseHitSelection(stereoHits, tTopo, true, false);
518 
519  // skip endcap stereo for now
520  // LogDebug("") << " Getting endcap stereo hits " ;
521  // coarseHitSelection(stereoHits, true, true);
522 
523  std::ostringstream debugstr1;
524  debugstr1 << " Getting barrel rphi hits " << " \n" ;
525 
526  coarseHitSelection(rphiBarrelHits, tTopo, false, false);
527 
528  // LogDebug("") << " Getting endcap zphi hits " ;
529  // coarseHitSelection(zphiEndcapHits, false, true);
530 
531  debugstr1 << " Getting matched hits " << " \n" ;
532  std::vector<const SiStripMatchedRecHit2D*> matchedHits;
533  coarseMatchedHitSelection(matchedHits);
534 
535 
536  // Determine how to project from the supercluster into the tracker
537  double energy = superclusterIn->energy();
538  double pT = energy * superclusterIn->position().rho()/sqrt(superclusterIn->x()*superclusterIn->x() +
539  superclusterIn->y()*superclusterIn->y() +
540  superclusterIn->z()*superclusterIn->z());
541  // cf Jackson p. 581-2, a little geometry
542  double phiVsRSlope = -3.00e-3 * chargeHypothesis * magneticField_p_->inTesla(GlobalPoint(superclusterIn->x(), superclusterIn->y(), 0.)).z() / pT / 2.;
543 
544  // Shorthand for supercluster radius, z
545  const double scr = superclusterIn->position().rho();
546  const double scz = superclusterIn->position().z();
547 
548  // These are used to fit all hits to a line in phi(r)
549  std::vector<bool> uselist;
550  std::vector<double> rlist, philist, w2list;
551  std::vector<int> typelist; // stereo = 0, rphi barrel = 1, and zphi disk = 2 (only used in this function)
552  std::vector<const SiStripRecHit2D*> hitlist;
553 
554  std::vector<bool> matcheduselist;
555  std::vector<const SiStripMatchedRecHit2D*> matchedhitlist;
556 
557  // These are used to fit the stereo hits to a line in z(r), constrained to pass through supercluster
558  double zSlopeFitNumer = 0.;
559  double zSlopeFitDenom = 0.;
560 
561 
562  debugstr1 << " There are a total of " << stereoHits.size() << " stereoHits in this event " << " \n"
563  << " There are a total of " << rphiBarrelHits.size() << " rphiBarrelHits in this event " << " \n"
564  << " There are a total of " << zphiEndcapHits.size() << " zphiEndcapHits in this event " << " \n\n";
565 
566 
567  LogDebug("") << debugstr1.str() ;
568 
570 
571 
572  // Loop over all matched hits
573  // make a list of good matched rechits.
574  // in the stereo and rphi loops check to see if the hit is associated with a matchedhit
575  LogDebug("") << " Loop over matched hits " << " \n";
576 
577  for (std::vector<const SiStripMatchedRecHit2D*>::const_iterator hit = matchedHits.begin() ;
578  hit != matchedHits.end() ; ++ hit) {
579 
580  assert(matchedHitUsed_.find(*hit) != matchedHitUsed_.end());
581 
582  if (!matchedHitUsed_[*hit]) {
583 
584  // Calculate the 3-D position of this hit
585  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
586  double r = sqrt(position.x()*position.x() + position.y()*position.y());
587  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
588  double z = position.z();
589 
590  // Cut a triangle in the z-r plane using the supercluster's eta/dip angle information
591  // and the fact that the electron originated *near* the origin
592  if ((-originUncertainty_ + (scz + originUncertainty_)*(r/scr)) < z && z < (originUncertainty_ + (scz - originUncertainty_)*(r/scr))) {
593 
594  // Cut a narrow band around the supercluster's projection in phi
595  if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
596 
597 
598  matcheduselist.push_back(true);
599  matchedhitlist.push_back(*hit);
600 
601 
602 
603  // Use this hit to fit z(r)
604  zSlopeFitNumer += -(scr - r) * (z - scz);
605  zSlopeFitDenom += (scr - r) * (scr - r);
606 
607  } // end cut on phi band
608  } // end cut on electron originating *near* the origin
609  } // end assign disjoint sets of hits to electrons
610  } // end loop over matched hits
611 
612  // Calculate the linear fit for z(r)
613  double zVsRSlope;
614  if (zSlopeFitDenom > 0.) {
615  zVsRSlope = zSlopeFitNumer / zSlopeFitDenom;
616  }
617  else {
618  // zVsRSlope assumes electron is from origin if there were no stereo hits
619  zVsRSlope = scz/scr;
620  }
621 
622  // // Loop over all stereo hits
623  LogDebug("") << " Loop over stereo hits" << " \n";
624 
625  // check if the stereo hit is matched to one of the matched hit
626  unsigned int numberOfStereoHits = 0;
627  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = stereoHits.begin(); hit != stereoHits.end(); ++hit) {
628  assert(hitUsed_.find(*hit) != hitUsed_.end());
629 
630  // Calculate the 3-D position of this hit
631  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
632  double r_stereo = sqrt(position.x()*position.x() + position.y()*position.y());
633  double phi_stereo = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
634  // double z_stereo = position.z();
635 
636  // stereo is has a pitch of 100 mrad - so consider both components
637  double r_stereo_err = sqrt((*hit)->localPositionError().xx()*cos2SiPitchAngle +
638  (*hit)->localPositionError().yy()*sin2SiPitchAngle ) ;
639 
640 
641 
642  // make sure that the error for this hit is sensible, ie > 1 micron
643  // otherwise skip this hit
644  if(r_stereo_err > stereoHitSmallestError ) {
645  r_stereo_err = sqrt(r_stereo_err*r_stereo_err+stereoErrFudge*stereoErrFudge);
646 
647  OmniClusterRef const & stereocluster=(*hit)->omniClusterRef();
648 
649  bool thisHitIsMatched = false ;
650 
651  if (!hitUsed_[*hit]) {
652 
653  unsigned int matcheduselist_size = matcheduselist.size();
654  for (unsigned int i = 0; i < matcheduselist_size; i++) {
655  if (matcheduselist[i]) {
656  OmniClusterRef const & mystereocluster = matchedhitlist[i]->stereoClusterRef();
657  if( stereocluster == mystereocluster ) {
658  thisHitIsMatched = true ;
659  // LogDebug("")<< " This hit is matched " << tracker_p_->idToDet(matchedhitlist[i]->stereoHit()->geographicalId())->surface().toGlobal(matchedhitlist[i]->stereoHit()->localPosition()) << std::endl;
660  // break ;
661  }
662  } // check if matcheduselist okay
663  }// loop over matched hits
664 
665  if(thisHitIsMatched) {
666  // Use this hit to fit phi(r)
667  uselist.push_back(true);
668  rlist.push_back(r_stereo);
669  philist.push_back(phi_stereo);
670  w2list.push_back(1./(r_stereo_err/r_stereo)/(r_stereo_err/r_stereo)); // weight**2 == 1./uncertainty**2
671  typelist.push_back(0);
672  hitlist.push_back(*hit);
673  } // thisHitIsMatched
674  } // if(!hitUsed)
675 
676  } // end of check on hit position error size
677 
678  } // end loop over stereo hits
679 
680  LogDebug("") << " There are " << uselist.size() << " good hits after stereo loop " ;
681 
682 
683  // Loop over barrel rphi hits
684  LogDebug("") << " Looping over barrel rphi hits " ;
685  unsigned int rphiMatchedCounter = 0 ;
686  unsigned int rphiUnMatchedCounter = 0 ;
687  unsigned int numberOfBarrelRphiHits = 0;
688  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = rphiBarrelHits.begin(); hit != rphiBarrelHits.end(); ++hit) {
689  assert(hitUsed_.find(*hit) != hitUsed_.end());
690  // Calculate the 2.5-D position of this hit
691  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
692  double r = sqrt(position.x()*position.x() + position.y()*position.y());
693  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
694  double z = position.z();
695  double r_mono_err = sqrt((*hit)->localPositionError().xx()) ;
696 
697  // only consider hits with errors that make sense
698  if( r_mono_err > rphiHitSmallestError) {
699  // inflate the reported error
700  r_mono_err=sqrt(r_mono_err*r_mono_err+rphiErrFudge*rphiErrFudge);
701 
702  OmniClusterRef const & monocluster=(*hit)->omniClusterRef();
703 
704 
705  if (!hitUsed_[*hit]) {
706  if( (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB &&
707  (tTopo->tibLayer((*hit)->geographicalId())==1 || tTopo->tibLayer((*hit)->geographicalId())==2)) ||
708  (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB
709  && (tTopo->tobLayer((*hit)->geographicalId())==1 || tTopo->tobLayer((*hit)->geographicalId())==2)) ) {
710  bool thisHitIsMatched = false ;
711  unsigned int matcheduselist_size = matcheduselist.size();
712  for (unsigned int i = 0; i < matcheduselist_size; i++) {
713  if (matcheduselist[i]) {
714  OmniClusterRef const & mymonocluster = matchedhitlist[i]->monoClusterRef();
715  if( monocluster == mymonocluster ) {
716  thisHitIsMatched = true ;
717  }
718  } // check if matcheduselist okay
719  }// loop over matched hits
720 
721 
722  if( thisHitIsMatched ) {
723  // Use this hit to fit phi(r)
724  uselist.push_back(true);
725  rlist.push_back(r);
726  philist.push_back(phi);
727  w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r)); // weight**2 == 1./uncertainty**2
728  typelist.push_back(1);
729  hitlist.push_back(*hit);
730  rphiMatchedCounter++;
731  } // end of matched hit check
732 
733  } else {
734 
735 
736  // The expected z position of this hit, according to the z(r) fit
737  double zFit = zVsRSlope * (r - scr) + scz;
738 
739  // Cut on the Z of the strip
740  // TIB strips are 11 cm long, TOB strips are 19 cm long (can I get these from a function?)
741  if ((tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB &&
742  std::abs(z - zFit) < 12.) ||
743  (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB &&
744  std::abs(z - zFit) < 20.) ) {
745 
746  // Cut a narrow band around the supercluster's projection in phi
747  if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
748 
749  // Use this hit to fit phi(r)
750  uselist.push_back(true);
751  rlist.push_back(r);
752  philist.push_back(phi);
753  w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r)); // weight**2 == 1./uncertainty**2
754  typelist.push_back(1);
755  hitlist.push_back(*hit);
756  rphiUnMatchedCounter++;
757 
758  } // end cut on phi band
759  } // end cut on strip z
760  } // loop over TIB/TOB layer 1,2
761  } // end assign disjoint sets of hits to electrons
762  } // end of check on rphi hit position error size
763  } // end loop over barrel rphi hits
764 
765  LogDebug("") << " There are " << rphiMatchedCounter <<" matched rphi hits";
766  LogDebug("") << " There are " << rphiUnMatchedCounter <<" unmatched rphi hits";
767  LogDebug("") << " There are " << uselist.size() << " good stereo+rphi hits " ;
768 
769 
770 
771 
772 
773 
775 
776  // Loop over endcap zphi hits
777  LogDebug("") << " Looping over barrel zphi hits " ;
778 
779 
780  unsigned int numberOfEndcapZphiHits = 0;
781  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = zphiEndcapHits.begin();
782  hit != zphiEndcapHits.end(); ++hit) {
783  assert(hitUsed_.find(*hit) != hitUsed_.end());
784  if (!hitUsed_[*hit]) {
785  // Calculate the 2.5-D position of this hit
786  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
787  double z = position.z();
788  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
789  // double r=sqrt(position.x()*position.x()+position.y()*position.y()) ;
790 
791  // The expected r position of this hit, according to the z(r) fit
792  double rFit = (z - scz)/zVsRSlope + scr;
793 
794  // I don't know the r widths of the endcap strips, otherwise I
795  // would apply a cut on r similar to the rphi z cut
796 
797  // Cut a narrow band around the supercluster's projection in phi,
798  // and be sure the hit isn't in a reflected band (extrapolation of large z differences into negative r)
799  if (rFit > 0. &&
800  unwrapPhi((rFit-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((rFit-scr)*phiVsRSlope + phiBandWidth_)) {
801 
802  // Use this hit to fit phi(r)
803  uselist.push_back(true);
804  rlist.push_back(rFit);
805  philist.push_back(phi);
806  w2list.push_back(1./(0.05/rFit)/(0.05/rFit)); // weight**2 == 1./uncertainty**2
807  typelist.push_back(2);
808  hitlist.push_back(*hit);
809 
810  } // end cut on phi band
811  } // end assign disjoint sets of hits to electrons
812  } // end loop over endcap zphi hits
813 
814  LogDebug("") << " There are " << uselist.size() << " good stereo+rphi+zphi hits " ;
816 
817 #ifdef EDM_ML_DEBUG
818  std::ostringstream debugstr5;
819  debugstr5 << " List of hits before uniqification " << " \n" ;
820  for (unsigned int i = 0; i < uselist.size(); i++) {
821  if ( uselist[i] ) {
822  const SiStripRecHit2D* hit = hitlist[i];
823  debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
824  << " R " << rlist[i]
825  << " Phi " << philist[i]
826  << " Weight " << w2list[i]
827  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
828  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
829  << " \n" ;
830  }
831  }
832  debugstr5 << " \n\n\n" ;
833 
834  debugstr5 << " Counting number of unique detectors " << " \n" ;
835 
836  debugstr5 << " These are all the detectors with hits " << " \n";
837 #endif
838  // Loop over hits, and find the best hit for each SiDetUnit - keep only those
839  // get a list of DetIds in uselist
840  std::vector<uint32_t> detIdList ;
841 
842  for (unsigned int i = 0; i < uselist.size(); i++) {
843  if (uselist[i]) {
844  const SiStripRecHit2D* hit = hitlist[i];
845  uint32_t detIDUsed = ((hit)->geographicalId()).rawId() ;
846 #ifdef EDM_ML_DEBUG
847  debugstr5<< " DetId " << detIDUsed << "\n";
848 #endif
849  detIdList.push_back(detIDUsed) ;
850  }
851  }
852 
853 #ifdef EDM_ML_DEBUG
854  debugstr5 << " There are " << detIdList.size() << " hits on detectors \n";
855 #endif
856  // now sort and then uniq this list of detId
857  std::sort(detIdList.begin(), detIdList.end());
858  detIdList.erase(
859  std::unique(detIdList.begin(), detIdList.end()), detIdList.end());
860 #ifdef EDM_ML_DEBUG
861  debugstr5 << " There are " << detIdList.size() << " unique detectors \n";
862 #endif
863  //now we have a list of unique detectors used
864 
865 
866 #ifdef EDM_ML_DEBUG
867  debugstr5 << " Looping over detectors to choose best hit " << " \n";
868 #endif
869  // Loop over detectors ID and hits to create list of hits on same DetId
870  for (unsigned int idet = 0 ; idet < detIdList.size() ; idet++ ) {
871  for (unsigned int i = 0; i+1 < uselist.size(); i++) {
872  if (uselist[i]) {
873  // Get Chi2 of this hit relative to predicted hit
874  const SiStripRecHit2D* hit1 = hitlist[i];
875  double r_hit1 = rlist[i];
876  double phi_hit1 = philist[i];
877  double w2_hit1 = w2list[i] ;
878  double phi_pred1 = (r_hit1-scr)*phiVsRSlope ;
879  double chi1 = (phi_hit1-phi_pred1)*(phi_hit1-phi_pred1)*w2_hit1;
880  if(detIdList[idet]== ((hit1)->geographicalId()).rawId()) {
881  for (unsigned int j = i+1; j < uselist.size(); j++) {
882  if (uselist[j]) {
883  const SiStripRecHit2D* hit2 = hitlist[j];
884  if(detIdList[idet]== ((hit2)->geographicalId()).rawId()) {
885 #ifdef EDM_ML_DEBUG
886  debugstr5 << " Found 2 hits on same Si Detector "
887  << ((hit2)->geographicalId()).rawId() << "\n";
888 #endif
889  // Get Chi2 of this hit relative to predicted hit
890  double r_hit2 = rlist[j];
891  double phi_hit2 = philist[j];
892  double w2_hit2 = w2list[j] ;
893  double phi_pred2 = (r_hit2-scr)*phiVsRSlope ;
894  double chi2 = (phi_hit2-phi_pred2)*(phi_hit2-phi_pred2)*w2_hit2;
895 #ifdef EDM_ML_DEBUG
896  debugstr5 << " Chi1 " << chi1 << " Chi2 " << chi2 <<"\n";
897 #endif
898  if( chi1< chi2 ){
899  uselist[j] = false;
900  }else{
901  uselist[i] = false;
902  }
903 
904  } // end of Det check
905  } // end of j- usehit check
906  } // end of j hit list loop
907 
908  } // end of detector check
909  } // end of uselist check
910  } // end of i-hit list loop
911 
912 
913  } // end of DetId loop
914 
915 
916 
917  // now let's through out hits with a predicted chi > chi2HitMax
918  for ( unsigned int i = 0; i < uselist.size(); i++ ) {
919  if ( uselist[i] ) {
920  double localchi2 = (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i] ;
921  if(localchi2 > chi2HitMax ) {
922 #ifdef EDM_ML_DEBUG
923  const SiStripRecHit2D* hit = hitlist[i];
924  debugstr5 << " Throwing out "
925  <<" DetID " << ((hit)->geographicalId()).rawId()
926  << " R " << rlist[i]
927  << " Phi " << philist[i]
928  << " Weight " << w2list[i]
929  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
930  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
931  << " \n" ;
932 #endif
933  uselist[i]=false ;
934  }
935  }
936  }
937 
938 #ifdef EDM_ML_DEBUG
939  debugstr5 << " List of hits after uniqification " << " \n" ;
940  for (unsigned int i = 0; i < uselist.size(); i++) {
941  if ( uselist[i] ) {
942  const SiStripRecHit2D* hit = hitlist[i];
943  debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
944  << " R " << rlist[i]
945  << " Phi " << philist[i]
946  << " Weight " << w2list[i]
947  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
948  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
949  << " \n" ;
950  }
951  }
952  debugstr5 << " \n\n\n" ;
953 #endif
954 
955  // need to check that there are more than 2 hits left here!
956  unsigned int nHitsLeft =0;
957  for (unsigned int i = 0; i < uselist.size(); i++) {
958  if ( uselist[i] ) {
959  nHitsLeft++;
960  }
961  }
962  if(nHitsLeft < nHitsLeftMinimum ) {
963 #ifdef EDM_ML_DEBUG
964  debugstr5 << " Too few hits "<< nHitsLeft
965  << " left - return false " << " \n";
966 #endif
967  return false ;
968  }
969 #ifdef EDM_ML_DEBUG
970  LogDebug("") << debugstr5.str();
971 #endif
972 
974  // Calculate a linear phi(r) fit and drop hits until the biggest contributor to chi^2 is less than maxNormResid_
975  bool done = false;
976  double intercept = 0 ;
977  double slope = 0 ;
978  double chi2 = 0;
979 
980  std::ostringstream debugstr4;
981  debugstr4 <<" Calc of phi(r) "<<" \n";
982 
983  while (!done) {
984  // Use an iterative update of <psi>, <r> etc instead in an
985  // attempt to minize divisions of large numbers
986  // The linear fit psi = slope*r + intercept
987  // slope is (<psi*r>-<psi>*<r>) / (<r^2>-<r>^2>)
988  // intercept is <psi> - slope*<r>
989 
990  double phiBar = 0.;
991  double phiBarOld = 0.;
992  double rBar = 0.;
993  double rBarOld = 0.;
994  double r2Bar = 0.;
995  double r2BarOld = 0.;
996  double phirBar = 0.;
997  double phirBarOld = 0.;
998  double totalWeight = 0.;
999  double totalWeightOld = 0.;
1000  unsigned int uselist_size = uselist.size();
1001  for (unsigned int i = 0; i < uselist_size; i++) {
1002  if (uselist[i]) {
1003  double r = rlist[i];
1004  double phi = philist[i];
1005  double weight2 = w2list[i];
1006 
1007  totalWeight = totalWeightOld + weight2 ;
1008 
1009  //weight2 is 1/sigma^2. Typically sigma is 100micron pitch
1010  // over root(12) = 30 microns so weight2 is about 10^5-10^6
1011 
1012  double totalWeightRatio = totalWeightOld/totalWeight ;
1013  double localWeightRatio = weight2/totalWeight ;
1014 
1015  phiBar = phiBarOld*totalWeightRatio + phi*localWeightRatio ;
1016  rBar = rBarOld*totalWeightRatio + r*localWeightRatio ;
1017  r2Bar= r2BarOld*totalWeightRatio + r*r*localWeightRatio ;
1018  phirBar = phirBarOld*totalWeightRatio + phi*r*localWeightRatio ;
1019 
1020  totalWeightOld = totalWeight ;
1021  phiBarOld = phiBar ;
1022  rBarOld = rBar ;
1023  r2BarOld = r2Bar ;
1024  phirBarOld = phirBar ;
1025 #ifdef EDM_ML_DEBUG
1026  debugstr4 << " totalWeight " << totalWeight
1027  << " totalWeightRatio " << totalWeightRatio
1028  << " localWeightRatio "<< localWeightRatio
1029  << " phiBar " << phiBar
1030  << " rBar " << rBar
1031  << " r2Bar " << r2Bar
1032  << " phirBar " << phirBar
1033  << " \n ";
1034 #endif
1035 
1036  } // end of use hit loop
1037  } // end of hit loop to calculate a linear fit
1038  slope = (phirBar-phiBar*rBar)/(r2Bar-rBar*rBar);
1039  intercept = phiBar-slope*rBar ;
1040 
1041  debugstr4 << " end of loop slope " << slope
1042  << " intercept " << intercept << " \n";
1043 
1044  // Calculate chi^2
1045  chi2 = 0.;
1046  double biggest_normresid = -1.;
1047  unsigned int biggest_index = 0;
1048  for (unsigned int i = 0; i < uselist_size; i++) {
1049  if (uselist[i]) {
1050  double r = rlist[i];
1051  double phi = philist[i];
1052  double weight2 = w2list[i];
1053 
1054  double normresid = weight2 * (phi - intercept - slope*r)*(phi - intercept - slope*r);
1055  chi2 += normresid;
1056 
1057  if (normresid > biggest_normresid) {
1058  biggest_normresid = normresid;
1059  biggest_index = i;
1060  }
1061  }
1062  } // end loop over hits to calculate chi^2 and find its biggest contributer
1063 
1064  if (biggest_normresid > maxNormResid_) {
1065 #ifdef EDM_ML_DEBUG
1066  debugstr4 << "Dropping hit from fit due to Chi2 " << " \n" ;
1067  const SiStripRecHit2D* hit = hitlist[biggest_index];
1068  debugstr4 << " DetID " << ((hit)->geographicalId()).rawId()
1069  << " R " << rlist[biggest_index]
1070  << " Phi " << philist[biggest_index]
1071  << " Weight " << w2list[biggest_index]
1072  << " PhiPred " << (rlist[biggest_index]-scr)*phiVsRSlope
1073  << " Chi2 " << (philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*(philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*w2list[biggest_index]
1074  << " normresid " << biggest_normresid
1075  << " \n\n";
1076 #endif
1077  uselist[biggest_index] = false;
1078  }
1079  else {
1080  done = true;
1081  }
1082  } // end loop over trial fits
1083 #ifdef EDM_ML_DEBUG
1084  debugstr4 <<" Fit "
1085  << " Intercept " << intercept
1086  << " slope " << slope
1087  << " chi2 " << chi2
1088  << " \n" ;
1089 
1090  LogDebug("") << debugstr4.str() ;
1091 #endif
1092 
1093  // Now we have intercept, slope, and chi2; uselist to tell us which hits are used, and hitlist for the hits
1094 
1095  // Identify the innermost hit
1096  const SiStripRecHit2D* innerhit = (SiStripRecHit2D*)nullptr;
1097  double innerhitRadius = -1.; // meaningless until innerhit is defined
1098 
1099  // Copy hits into an OwnVector, which we put in the TrackCandidate
1100  std::vector<const TrackingRecHit*> outputHits;
1101  // Reference rphi and stereo hits into RefVectors, which we put in the SiStripElectron
1102  std::vector<SiStripRecHit2D> outputRphiHits;
1103  std::vector<SiStripRecHit2D> outputStereoHits;
1104 
1105  typedef edm::Ref<SiStripRecHit2DCollection,SiStripRecHit2D> SiStripRecHit2DRef;
1106 
1107 
1108  for (unsigned int i = 0; i < uselist.size(); i++) {
1109  if (uselist[i]) {
1110  double r = rlist[i];
1111  const SiStripRecHit2D* hit = hitlist[i];
1112 
1113  // Keep track of the innermost hit
1114  if (innerhit == (SiStripRecHit2D*)nullptr || r < innerhitRadius) {
1115  innerhit = hit;
1116  innerhitRadius = r;
1117  }
1118 
1119  if (typelist[i] == 0) {
1120  numberOfStereoHits++;
1121 
1122  // Copy this hit for the TrajectorySeed
1123  outputHits.push_back(hit);
1124  outputStereoHits.push_back(*hit);
1125  }
1126  else if (typelist[i] == 1) {
1127  numberOfBarrelRphiHits++;
1128 
1129  // Copy this hit for the TrajectorySeed
1130  outputHits.push_back(hit);
1131  outputRphiHits.push_back(*hit);
1132  }
1133  else if (typelist[i] == 2) {
1134  numberOfEndcapZphiHits++;
1135 
1136  // Copy this hit for the TrajectorySeed
1137  outputHits.push_back(hit);
1138  outputRphiHits.push_back(*hit);
1139  }
1140  }
1141  } // end loop over all hits, after having culled the ones with big residuals
1142 
1143  unsigned int totalNumberOfHits = numberOfStereoHits + numberOfBarrelRphiHits + numberOfEndcapZphiHits;
1144  double reducedChi2 = (totalNumberOfHits > 2 ? chi2 / (totalNumberOfHits - 2) : 1e10);
1145 
1146  // Select this candidate if it passes minHits_ and maxReducedChi2_ cuts
1147  if (innerhit != nullptr && totalNumberOfHits >= minHits_ && reducedChi2 <= maxReducedChi2_) {
1148  // GlobalTrajectoryParameters evaluated at the position of the innerhit
1150  if( nullptr != tracker_p_ ) {
1151  position = tracker_p_->idToDet(innerhit->geographicalId())->surface().toGlobal(innerhit->localPosition());
1152  } else {
1153  throw cms::Exception("projectPhiBand") << "Pointer to tracker product is null!";
1154  }
1155 
1156  // Use our phi(r) linear fit to correct pT (pT is inversely proportional to slope)
1157  // (By applying a correction instead of going back to first
1158  // principles, any correction to the phiVsRSlope definition
1159  // above will be automatically propagated here.)
1160  double correct_pT = pT * phiVsRSlope / slope;
1161 
1162  // Our phi(r) linear fit returns phi relative to the supercluster phi for a given radius
1163  double phi = intercept + slope*sqrt(position.x()*position.x() + position.y()*position.y()) + superclusterIn->position().phi();
1164 
1165  // Our z(r) linear fit gives us a better measurement of eta/dip angle
1166  double pZ = correct_pT * zVsRSlope;
1167 
1168  // Now we can construct a trajectory momentum out of linear fits to hits
1169  GlobalVector momentum = GlobalVector(correct_pT*cos(phi), correct_pT*sin(phi), pZ);
1170 
1171  if (chargeHypothesis > 0.) {
1172  redchi2_pos_ = chi2 / double(totalNumberOfHits - 2);
1174  momentum_pos_ = momentum;
1175  innerhit_pos_ = innerhit;
1176  outputHits_pos_ = outputHits;
1177  outputRphiHits_pos_ = outputRphiHits;
1178  outputStereoHits_pos_ = outputStereoHits;
1179  phiVsRSlope_pos_ = phiVsRSlope;
1180  slope_pos_ = slope;
1181  intercept_pos_ = intercept;
1182  chi2_pos_ = chi2;
1183  ndof_pos_ = totalNumberOfHits - 2;
1184  correct_pT_pos_ = correct_pT;
1185  pZ_pos_ = pZ;
1186  zVsRSlope_pos_ = zVsRSlope;
1187  numberOfStereoHits_pos_ = numberOfStereoHits;
1188  numberOfBarrelRphiHits_pos_ = numberOfBarrelRphiHits;
1189  numberOfEndcapZphiHits_pos_ = numberOfEndcapZphiHits;
1190  }
1191  else {
1192  redchi2_neg_ = chi2 / double(totalNumberOfHits - 2);
1194  momentum_neg_ = momentum;
1195  innerhit_neg_ = innerhit;
1196  outputHits_neg_ = outputHits;
1197  outputRphiHits_neg_ = outputRphiHits;
1198  outputStereoHits_neg_ = outputStereoHits;
1199  phiVsRSlope_neg_ = phiVsRSlope;
1200  slope_neg_ = slope;
1201  intercept_neg_ = intercept;
1202  chi2_neg_ = chi2;
1203  ndof_neg_ = totalNumberOfHits - 2;
1204  correct_pT_neg_ = correct_pT;
1205  pZ_neg_ = pZ;
1206  zVsRSlope_neg_ = zVsRSlope;
1207  numberOfStereoHits_neg_ = numberOfStereoHits;
1208  numberOfBarrelRphiHits_neg_ = numberOfBarrelRphiHits;
1209  numberOfEndcapZphiHits_neg_ = numberOfEndcapZphiHits;
1210  }
1211 
1212  LogDebug("") << " return from projectFindBand with True \n" << std::endl ;
1213  return true;
1214  } // end if this is a good electron candidate
1215 
1216  // Signal for a failed electron candidate
1217  LogDebug("") << " return from projectFindBand with False \n" << std::endl ;
1218  return false;
1219 }
1220 
1221 //
1222 // const member functions
1223 //
1224 
1225 //
1226 // static member functions
1227 //
1228 
#define LogDebug(id)
type
Definition: HCALResponse.h:21
boost::transform_iterator< IterHelp, const_IdIter > const_iterator
const_iterator end(bool update=false) const
std::vector< const TrackingRecHit * > outputHits_pos_
unsigned int tibLayer(const DetId &id) const
std::vector< SiStripRecHit2D > outputRphiHits_pos_
const edm::Handle< SiStripRecHit2DCollection > * stereoHits_hp_
const SiStripRecHit2D * innerhit_neg_
static const double slope[3]
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:54
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::vector< TrackCandidate > TrackCandidateCollection
uint32_t tobStereo(const DetId &id) const
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:47
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
T y() const
Definition: PV3DBase.h:63
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
const SiStripRecHit2D * innerhit_pos_
const TrackerGeomDet * idToDetUnit(DetId) const override
Return the pointer to the GeomDetUnit corresponding to a given DetId.
void push_back(D *&d)
Definition: OwnVector.h:290
std::vector< SiStripRecHit2D > outputStereoHits_pos_
uint32_t tidStereo(const DetId &id) const
std::map< const TrackingRecHit *, bool > matchedHitUsed_
std::vector< SiStripElectron > SiStripElectronCollection
collectin of SiStripElectron objects
T sqrt(T t)
Definition: SSEVec.h:18
def unique(seq, keepstr=True)
Definition: tier0.py:25
T z() const
Definition: PV3DBase.h:64
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
data_type const * data(size_t cell) const
const SiStripRecHit2DCollection * rphiHits_p_
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double unwrapPhi(double phi) const
std::map< const SiStripRecHit2D *, unsigned int > stereoKey_
virtual GlobalVector inTesla(const GlobalPoint &gp) const =0
Field value ad specified global point, in Tesla.
std::vector< SiStripRecHit2D > outputRphiHits_neg_
const SiStripRecHit2DCollection * stereoHits_p_
bool findElectron(reco::SiStripElectronCollection &electronOut, TrackCandidateCollection &trackCandidateOut, const reco::SuperClusterRef &superclusterIn, const TrackerTopology *tTopo)
unsigned int numberOfStereoHits_pos_
Definition: DetId.h:18
bool projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef &superclusterIn, const TrackerTopology *tTopo)
T const * product() const
Definition: Handle.h:81
unsigned int numberOfBarrelRphiHits_pos_
std::vector< SiStripRecHit2D > outputStereoHits_neg_
void coarseHitSelection(std::vector< const SiStripRecHit2D * > &hitPointersOut, const TrackerTopology *tTopo, bool stereo, bool endcap)
const TrackerGeometry * tracker_p_
const edm::Handle< SiStripRecHit2DCollection > * rphiHits_hp_
id_type detId() const
Definition: DetSetNew.h:84
const SiStripMatchedRecHit2DCollection * matchedHits_p_
std::map< const SiStripMatchedRecHit2D *, unsigned int > matchedKey_
T perp() const
Magnitude of transverse component.
iterator end()
Definition: DetSetNew.h:70
static std::atomic< unsigned int > counter
static int position[264][3]
Definition: ReadPGInfo.cc:509
uint32_t tecStereo(const DetId &id) const
const TrackerGeomDet * idToDet(DetId) const override
std::map< const TrackingRecHit *, bool > hitUsed_
LocalPoint localPosition() const final
void coarseMatchedHitSelection(std::vector< const SiStripMatchedRecHit2D * > &coarseMatchedHitPointersOut)
const MagneticField * magneticField_p_
DetId geographicalId() const
std::map< const SiStripRecHit2D *, unsigned int > rphiKey_
uint32_t tibStereo(const DetId &id) const
size_type size() const
Definition: DetSetNew.h:87
SiStripElectronAlgo(unsigned int maxHitsOnDetId, double originUncertainty, double phiBandWidth, double maxNormResid, unsigned int minHits, double maxReducedChi2)
T x() const
Definition: PV3DBase.h:62
unsigned int numberOfEndcapZphiHits_pos_
T const * product() const
Definition: ESHandle.h:86
const_iterator begin(bool update=false) const
unsigned int tobLayer(const DetId &id) const
void prepareEvent(const edm::ESHandle< TrackerGeometry > &tracker, const edm::Handle< SiStripRecHit2DCollection > &rphiHits, const edm::Handle< SiStripRecHit2DCollection > &stereoHits, const edm::Handle< SiStripMatchedRecHit2DCollection > &matchedHits, const edm::ESHandle< MagneticField > &magneticField)
Global3DVector GlobalVector
Definition: GlobalVector.h:10
std::vector< const TrackingRecHit * > outputHits_neg_
iterator begin()
Definition: DetSetNew.h:67