CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 //
52 SiStripElectronAlgo::SiStripElectronAlgo(unsigned int maxHitsOnDetId,
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
371  SiStripRecHit2DCollection::DetSet hits = *itdet;
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  int theLayer = -999;
390  bool isStereoDet = false ;
391  if(tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB) {
392  theDet = "TIB" ;
393  theLayer = tTopo->tibLayer(id);
394  if(tTopo->tibStereo(id)==1) { isStereoDet = true ; }
395  } else if
396  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB) {
397  theDet = "TOB" ;
398  theLayer = tTopo->tobLayer(id);
399  if(tTopo->tobStereo(id)==1) { isStereoDet = true ; }
400  }else if
401  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TID) {
402  theDet = "TID" ;
403  theLayer = tTopo->tidWheel(id); // or ring ?
404  if(tTopo->tidStereo(id)==1) { isStereoDet = true ; }
405  }else if
406  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TEC) {
407  theDet = "TEC" ;
408  theLayer = tTopo->tecWheel(id); // or ring or petal ?
409  if(tTopo->tecStereo(id)==1) { isStereoDet = true ; }
410  } else {
411  LogDebug("") << " UHOH BIG PROBLEM - Unrecognized SI Layer" ;
412  LogDebug("") << " Det "<< theDet << " Lay " << theLayer ;
413  assert(1!=1) ;
414  }
415 
416  if ((endcap && stereo && (theDet=="TID" || theDet== "TEC") && isStereoDet ) ||
417  (endcap && !stereo && (theDet=="TID" || theDet== "TEC") && !isStereoDet ) ||
418  (!endcap && stereo && (theDet=="TIB" || theDet=="TOB") && isStereoDet ) ||
419  (!endcap && !stereo && (theDet=="TIB" || theDet=="TOB" )&& !isStereoDet )
420  ) {
421 
422 
423  hitPointersOut.push_back(&(*hit));
424 
425  } // end if this is the right subdetector
426  } // end loop over hits
427  } // end if this detector id doesn't have too many hits on it
428  } // end loop over detector ids
429 }
430 
431 // select all matched hits for now
432 
433 void SiStripElectronAlgo::coarseMatchedHitSelection(std::vector<const SiStripMatchedRecHit2D*>& coarseMatchedHitPointersOut)
434 {
435 
436  // Loop over the detector ids
438  for (; itdet != eddet; ++itdet) {
439 
440  // Get the hits on this detector id
442 
443  // Count the number of hits on this detector id
444  unsigned int numberOfHits = 0;
446  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
447  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
448  numberOfHits++;
449  if (numberOfHits > maxHitsOnDetId_) { break; }
450  }
451 
452  // Only take the hits if there aren't too many
453  if (numberOfHits <= maxHitsOnDetId_) {
455  if(!(*hit).isValid()) {
456  LogDebug("") << " InValid hit skipped in coarseMatchedHitSelection " << std::endl ;
457  continue ;
458  }
459  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
460  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
461 
462  coarseMatchedHitPointersOut.push_back(&(*hit));
463  } // end loop over hits
464 
465  } // end if this detector id doesn't have too many hits on it
466  } // end loop over detector ids
467 
468 
469 }// end of matchedHitSelection
470 
471 
472 
473 
474 // projects a phi band of width phiBandWidth_ from supercluster into tracker (given a chargeHypothesis)
475 // fills *_pos_ or *_neg_ member data with the results
476 // returns true iff the electron/positron passes cuts
477 bool SiStripElectronAlgo::projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef& superclusterIn,
478  const TrackerTopology *tTopo)
479 {
480  // This algorithm projects a phi band into the tracker three times:
481  // (a) for all stereo hits, (b) for barrel rphi hits, and (c) for
482  // endcap zphi hits. While accumulating stereo hits in step (a),
483  // we fit r vs z to a line. This resolves the ambiguity in z for
484  // rphi hits and the ambiguity in r for zphi hits. We can then cut
485  // on the z of rphi hits (a little wider than one strip length),
486  // and we can convert the z of zphi hits into r to apply the phi
487  // band cut. (We don't take advantage of the endcap strips'
488  // segmentation in r.)
489  //
490  // As we project a phi band into the tracker, we count hits within
491  // that band and performs a linear fit for phi vs r. The number of
492  // hits and reduced chi^2 from the fit are used to select a good
493  // candidate.
494 
495  // set limits on Si hits - smallest error that makes sense = 1 micron ?
496  static const double rphiHitSmallestError = 0.0001 ;
497  static const double stereoHitSmallestError = 0.0001 ;
498  //not used since endcap is not implemented
499  // static const double zphiHitSmallestError = 0.0001 ;
500 
501 
502  static const double stereoPitchAngle = 0.100 ; // stereo angle in rad
503  static const double cos2SiPitchAngle = cos(stereoPitchAngle)*cos(stereoPitchAngle) ;
504  static const double sin2SiPitchAngle = sin(stereoPitchAngle)*sin(stereoPitchAngle) ;
505  // overall misalignment fudge to be added in quad to position errors.
506  // this is a rough approx to values reported in tracking meet 5/16/2007
507  static const double rphiErrFudge = 0.0200 ;
508  static const double stereoErrFudge = 0.0200 ;
509 
510  // max chi2 of a hit on an SiDet relative to the prediction
511  static const double chi2HitMax = 25.0 ;
512 
513  // Minimum number of hits to consider on a candidate
514  static const unsigned int nHitsLeftMinimum = 3 ;
515 
516  // Create and fill vectors of pointers to hits
517  std::vector<const SiStripRecHit2D*> stereoHits;
518  std::vector<const SiStripRecHit2D*> rphiBarrelHits;
519  std::vector<const SiStripRecHit2D*> zphiEndcapHits;
520 
521  // stereo? endcap?
522  coarseHitSelection(stereoHits, tTopo, true, false);
523 
524  // skip endcap stereo for now
525  // LogDebug("") << " Getting endcap stereo hits " ;
526  // coarseHitSelection(stereoHits, true, true);
527 
528  std::ostringstream debugstr1;
529  debugstr1 << " Getting barrel rphi hits " << " \n" ;
530 
531  coarseHitSelection(rphiBarrelHits, tTopo, false, false);
532 
533  // LogDebug("") << " Getting endcap zphi hits " ;
534  // coarseHitSelection(zphiEndcapHits, false, true);
535 
536  debugstr1 << " Getting matched hits " << " \n" ;
537  std::vector<const SiStripMatchedRecHit2D*> matchedHits;
538  coarseMatchedHitSelection(matchedHits);
539 
540 
541  // Determine how to project from the supercluster into the tracker
542  double energy = superclusterIn->energy();
543  double pT = energy * superclusterIn->position().rho()/sqrt(superclusterIn->x()*superclusterIn->x() +
544  superclusterIn->y()*superclusterIn->y() +
545  superclusterIn->z()*superclusterIn->z());
546  // cf Jackson p. 581-2, a little geometry
547  double phiVsRSlope = -3.00e-3 * chargeHypothesis * magneticField_p_->inTesla(GlobalPoint(superclusterIn->x(), superclusterIn->y(), 0.)).z() / pT / 2.;
548 
549  // Shorthand for supercluster radius, z
550  const double scr = superclusterIn->position().rho();
551  const double scz = superclusterIn->position().z();
552 
553  // These are used to fit all hits to a line in phi(r)
554  std::vector<bool> uselist;
555  std::vector<double> rlist, philist, w2list;
556  std::vector<int> typelist; // stereo = 0, rphi barrel = 1, and zphi disk = 2 (only used in this function)
557  std::vector<const SiStripRecHit2D*> hitlist;
558 
559  std::vector<bool> matcheduselist;
560  std::vector<const SiStripMatchedRecHit2D*> matchedhitlist;
561 
562  // These are used to fit the stereo hits to a line in z(r), constrained to pass through supercluster
563  double zSlopeFitNumer = 0.;
564  double zSlopeFitDenom = 0.;
565 
566 
567  debugstr1 << " There are a total of " << stereoHits.size() << " stereoHits in this event " << " \n"
568  << " There are a total of " << rphiBarrelHits.size() << " rphiBarrelHits in this event " << " \n"
569  << " There are a total of " << zphiEndcapHits.size() << " zphiEndcapHits in this event " << " \n\n";
570 
571 
572  LogDebug("") << debugstr1.str() ;
573 
575 
576 
577  // Loop over all matched hits
578  // make a list of good matched rechits.
579  // in the stereo and rphi loops check to see if the hit is associated with a matchedhit
580  LogDebug("") << " Loop over matched hits " << " \n";
581 
582  for (std::vector<const SiStripMatchedRecHit2D*>::const_iterator hit = matchedHits.begin() ;
583  hit != matchedHits.end() ; ++ hit) {
584 
585  assert(matchedHitUsed_.find(*hit) != matchedHitUsed_.end());
586 
587  if (!matchedHitUsed_[*hit]) {
588 
589  // Calculate the 3-D position of this hit
590  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
591  double r = sqrt(position.x()*position.x() + position.y()*position.y());
592  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
593  double z = position.z();
594 
595  // Cut a triangle in the z-r plane using the supercluster's eta/dip angle information
596  // and the fact that the electron originated *near* the origin
597  if ((-originUncertainty_ + (scz + originUncertainty_)*(r/scr)) < z && z < (originUncertainty_ + (scz - originUncertainty_)*(r/scr))) {
598 
599  // Cut a narrow band around the supercluster's projection in phi
600  if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
601 
602 
603  matcheduselist.push_back(true);
604  matchedhitlist.push_back(*hit);
605 
606 
607 
608  // Use this hit to fit z(r)
609  zSlopeFitNumer += -(scr - r) * (z - scz);
610  zSlopeFitDenom += (scr - r) * (scr - r);
611 
612  } // end cut on phi band
613  } // end cut on electron originating *near* the origin
614  } // end assign disjoint sets of hits to electrons
615  } // end loop over matched hits
616 
617  // Calculate the linear fit for z(r)
618  double zVsRSlope;
619  if (zSlopeFitDenom > 0.) {
620  zVsRSlope = zSlopeFitNumer / zSlopeFitDenom;
621  }
622  else {
623  // zVsRSlope assumes electron is from origin if there were no stereo hits
624  zVsRSlope = scz/scr;
625  }
626 
627  // // Loop over all stereo hits
628  LogDebug("") << " Loop over stereo hits" << " \n";
629 
630  // check if the stereo hit is matched to one of the matched hit
631  unsigned int numberOfStereoHits = 0;
632  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = stereoHits.begin(); hit != stereoHits.end(); ++hit) {
633  assert(hitUsed_.find(*hit) != hitUsed_.end());
634 
635  // Calculate the 3-D position of this hit
636  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
637  double r_stereo = sqrt(position.x()*position.x() + position.y()*position.y());
638  double phi_stereo = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
639  // double z_stereo = position.z();
640 
641  // stereo is has a pitch of 100 mrad - so consider both components
642  double r_stereo_err = sqrt((*hit)->localPositionError().xx()*cos2SiPitchAngle +
643  (*hit)->localPositionError().yy()*sin2SiPitchAngle ) ;
644 
645 
646 
647  // make sure that the error for this hit is sensible, ie > 1 micron
648  // otherwise skip this hit
649  if(r_stereo_err > stereoHitSmallestError ) {
650  r_stereo_err = sqrt(r_stereo_err*r_stereo_err+stereoErrFudge*stereoErrFudge);
651 
652  OmniClusterRef const & stereocluster=(*hit)->omniClusterRef();
653 
654  bool thisHitIsMatched = false ;
655 
656  if (!hitUsed_[*hit]) {
657 
658  unsigned int matcheduselist_size = matcheduselist.size();
659  for (unsigned int i = 0; i < matcheduselist_size; i++) {
660  if (matcheduselist[i]) {
661  OmniClusterRef const & mystereocluster = matchedhitlist[i]->stereoClusterRef();
662  if( stereocluster == mystereocluster ) {
663  thisHitIsMatched = true ;
664  // LogDebug("")<< " This hit is matched " << tracker_p_->idToDet(matchedhitlist[i]->stereoHit()->geographicalId())->surface().toGlobal(matchedhitlist[i]->stereoHit()->localPosition()) << std::endl;
665  // break ;
666  }
667  } // check if matcheduselist okay
668  }// loop over matched hits
669 
670  if(thisHitIsMatched) {
671  // Use this hit to fit phi(r)
672  uselist.push_back(true);
673  rlist.push_back(r_stereo);
674  philist.push_back(phi_stereo);
675  w2list.push_back(1./(r_stereo_err/r_stereo)/(r_stereo_err/r_stereo)); // weight**2 == 1./uncertainty**2
676  typelist.push_back(0);
677  hitlist.push_back(*hit);
678  } // thisHitIsMatched
679  } // if(!hitUsed)
680 
681  } // end of check on hit position error size
682 
683  } // end loop over stereo hits
684 
685  LogDebug("") << " There are " << uselist.size() << " good hits after stereo loop " ;
686 
687 
688  // Loop over barrel rphi hits
689  LogDebug("") << " Looping over barrel rphi hits " ;
690  unsigned int rphiMatchedCounter = 0 ;
691  unsigned int rphiUnMatchedCounter = 0 ;
692  unsigned int numberOfBarrelRphiHits = 0;
693  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = rphiBarrelHits.begin(); hit != rphiBarrelHits.end(); ++hit) {
694  assert(hitUsed_.find(*hit) != hitUsed_.end());
695  // Calculate the 2.5-D position of this hit
696  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
697  double r = sqrt(position.x()*position.x() + position.y()*position.y());
698  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
699  double z = position.z();
700  double r_mono_err = sqrt((*hit)->localPositionError().xx()) ;
701 
702  // only consider hits with errors that make sense
703  if( r_mono_err > rphiHitSmallestError) {
704  // inflate the reported error
705  r_mono_err=sqrt(r_mono_err*r_mono_err+rphiErrFudge*rphiErrFudge);
706 
707  OmniClusterRef const & monocluster=(*hit)->omniClusterRef();
708 
709 
710  if (!hitUsed_[*hit]) {
711  if( (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB &&
712  (tTopo->tibLayer((*hit)->geographicalId())==1 || tTopo->tibLayer((*hit)->geographicalId())==2)) ||
713  (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB
714  && (tTopo->tobLayer((*hit)->geographicalId())==1 || tTopo->tobLayer((*hit)->geographicalId())==2)) ) {
715  bool thisHitIsMatched = false ;
716  unsigned int matcheduselist_size = matcheduselist.size();
717  for (unsigned int i = 0; i < matcheduselist_size; i++) {
718  if (matcheduselist[i]) {
719  OmniClusterRef const & mymonocluster = matchedhitlist[i]->monoClusterRef();
720  if( monocluster == mymonocluster ) {
721  thisHitIsMatched = true ;
722  }
723  } // check if matcheduselist okay
724  }// loop over matched hits
725 
726 
727  if( thisHitIsMatched ) {
728  // Use this hit to fit phi(r)
729  uselist.push_back(true);
730  rlist.push_back(r);
731  philist.push_back(phi);
732  w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r)); // weight**2 == 1./uncertainty**2
733  typelist.push_back(1);
734  hitlist.push_back(*hit);
735  rphiMatchedCounter++;
736  } // end of matched hit check
737 
738  } else {
739 
740 
741  // The expected z position of this hit, according to the z(r) fit
742  double zFit = zVsRSlope * (r - scr) + scz;
743 
744  // Cut on the Z of the strip
745  // TIB strips are 11 cm long, TOB strips are 19 cm long (can I get these from a function?)
746  if ((tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB &&
747  std::abs(z - zFit) < 12.) ||
748  (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB &&
749  std::abs(z - zFit) < 20.) ) {
750 
751  // Cut a narrow band around the supercluster's projection in phi
752  if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
753 
754  // Use this hit to fit phi(r)
755  uselist.push_back(true);
756  rlist.push_back(r);
757  philist.push_back(phi);
758  w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r)); // weight**2 == 1./uncertainty**2
759  typelist.push_back(1);
760  hitlist.push_back(*hit);
761  rphiUnMatchedCounter++;
762 
763  } // end cut on phi band
764  } // end cut on strip z
765  } // loop over TIB/TOB layer 1,2
766  } // end assign disjoint sets of hits to electrons
767  } // end of check on rphi hit position error size
768  } // end loop over barrel rphi hits
769 
770  LogDebug("") << " There are " << rphiMatchedCounter <<" matched rphi hits";
771  LogDebug("") << " There are " << rphiUnMatchedCounter <<" unmatched rphi hits";
772  LogDebug("") << " There are " << uselist.size() << " good stereo+rphi hits " ;
773 
774 
775 
776 
777 
778 
780 
781  // Loop over endcap zphi hits
782  LogDebug("") << " Looping over barrel zphi hits " ;
783 
784 
785  unsigned int numberOfEndcapZphiHits = 0;
786  for (std::vector<const SiStripRecHit2D*>::const_iterator hit = zphiEndcapHits.begin();
787  hit != zphiEndcapHits.end(); ++hit) {
788  assert(hitUsed_.find(*hit) != hitUsed_.end());
789  if (!hitUsed_[*hit]) {
790  // Calculate the 2.5-D position of this hit
791  GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
792  double z = position.z();
793  double phi = unwrapPhi(position.phi() - superclusterIn->position().phi()); // phi is relative to supercluster
794  // double r=sqrt(position.x()*position.x()+position.y()*position.y()) ;
795 
796  // The expected r position of this hit, according to the z(r) fit
797  double rFit = (z - scz)/zVsRSlope + scr;
798 
799  // I don't know the r widths of the endcap strips, otherwise I
800  // would apply a cut on r similar to the rphi z cut
801 
802  // Cut a narrow band around the supercluster's projection in phi,
803  // and be sure the hit isn't in a reflected band (extrapolation of large z differences into negative r)
804  if (rFit > 0. &&
805  unwrapPhi((rFit-scr)*phiVsRSlope - phiBandWidth_) < phi && phi < unwrapPhi((rFit-scr)*phiVsRSlope + phiBandWidth_)) {
806 
807  // Use this hit to fit phi(r)
808  uselist.push_back(true);
809  rlist.push_back(rFit);
810  philist.push_back(phi);
811  w2list.push_back(1./(0.05/rFit)/(0.05/rFit)); // weight**2 == 1./uncertainty**2
812  typelist.push_back(2);
813  hitlist.push_back(*hit);
814 
815  } // end cut on phi band
816  } // end assign disjoint sets of hits to electrons
817  } // end loop over endcap zphi hits
818 
819  LogDebug("") << " There are " << uselist.size() << " good stereo+rphi+zphi hits " ;
821 
822 #ifdef EDM_ML_DEBUG
823  std::ostringstream debugstr5;
824  debugstr5 << " List of hits before uniqification " << " \n" ;
825  for (unsigned int i = 0; i < uselist.size(); i++) {
826  if ( uselist[i] ) {
827  const SiStripRecHit2D* hit = hitlist[i];
828  debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
829  << " R " << rlist[i]
830  << " Phi " << philist[i]
831  << " Weight " << w2list[i]
832  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
833  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
834  << " \n" ;
835  }
836  }
837  debugstr5 << " \n\n\n" ;
838 
839  debugstr5 << " Counting number of unique detectors " << " \n" ;
840 
841  debugstr5 << " These are all the detectors with hits " << " \n";
842 #endif
843  // Loop over hits, and find the best hit for each SiDetUnit - keep only those
844  // get a list of DetIds in uselist
845  std::vector<uint32_t> detIdList ;
846 
847  for (unsigned int i = 0; i < uselist.size(); i++) {
848  if (uselist[i]) {
849  const SiStripRecHit2D* hit = hitlist[i];
850  uint32_t detIDUsed = ((hit)->geographicalId()).rawId() ;
851 #ifdef EDM_ML_DEBUG
852  debugstr5<< " DetId " << detIDUsed << "\n";
853 #endif
854  detIdList.push_back(detIDUsed) ;
855  }
856  }
857 
858 #ifdef EDM_ML_DEBUG
859  debugstr5 << " There are " << detIdList.size() << " hits on detectors \n";
860 #endif
861  // now sort and then uniq this list of detId
862  std::sort(detIdList.begin(), detIdList.end());
863  detIdList.erase(
864  std::unique(detIdList.begin(), detIdList.end()), detIdList.end());
865 #ifdef EDM_ML_DEBUG
866  debugstr5 << " There are " << detIdList.size() << " unique detectors \n";
867 #endif
868  //now we have a list of unique detectors used
869 
870 
871 #ifdef EDM_ML_DEBUG
872  debugstr5 << " Looping over detectors to choose best hit " << " \n";
873 #endif
874  // Loop over detectors ID and hits to create list of hits on same DetId
875  for (unsigned int idet = 0 ; idet < detIdList.size() ; idet++ ) {
876  for (unsigned int i = 0; i+1 < uselist.size(); i++) {
877  if (uselist[i]) {
878  // Get Chi2 of this hit relative to predicted hit
879  const SiStripRecHit2D* hit1 = hitlist[i];
880  double r_hit1 = rlist[i];
881  double phi_hit1 = philist[i];
882  double w2_hit1 = w2list[i] ;
883  double phi_pred1 = (r_hit1-scr)*phiVsRSlope ;
884  double chi1 = (phi_hit1-phi_pred1)*(phi_hit1-phi_pred1)*w2_hit1;
885  if(detIdList[idet]== ((hit1)->geographicalId()).rawId()) {
886  for (unsigned int j = i+1; j < uselist.size(); j++) {
887  if (uselist[j]) {
888  const SiStripRecHit2D* hit2 = hitlist[j];
889  if(detIdList[idet]== ((hit2)->geographicalId()).rawId()) {
890 #ifdef EDM_ML_DEBUG
891  debugstr5 << " Found 2 hits on same Si Detector "
892  << ((hit2)->geographicalId()).rawId() << "\n";
893 #endif
894  // Get Chi2 of this hit relative to predicted hit
895  double r_hit2 = rlist[j];
896  double phi_hit2 = philist[j];
897  double w2_hit2 = w2list[j] ;
898  double phi_pred2 = (r_hit2-scr)*phiVsRSlope ;
899  double chi2 = (phi_hit2-phi_pred2)*(phi_hit2-phi_pred2)*w2_hit2;
900 #ifdef EDM_ML_DEBUG
901  debugstr5 << " Chi1 " << chi1 << " Chi2 " << chi2 <<"\n";
902 #endif
903  if( chi1< chi2 ){
904  uselist[j] = 0;
905  }else{
906  uselist[i] = 0;
907  }
908 
909  } // end of Det check
910  } // end of j- usehit check
911  } // end of j hit list loop
912 
913  } // end of detector check
914  } // end of uselist check
915  } // end of i-hit list loop
916 
917 
918  } // end of DetId loop
919 
920 
921 
922  // now let's through out hits with a predicted chi > chi2HitMax
923  for ( unsigned int i = 0; i < uselist.size(); i++ ) {
924  if ( uselist[i] ) {
925  double localchi2 = (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i] ;
926  if(localchi2 > chi2HitMax ) {
927 #ifdef EDM_ML_DEBUG
928  const SiStripRecHit2D* hit = hitlist[i];
929  debugstr5 << " Throwing out "
930  <<" DetID " << ((hit)->geographicalId()).rawId()
931  << " R " << rlist[i]
932  << " Phi " << philist[i]
933  << " Weight " << w2list[i]
934  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
935  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
936  << " \n" ;
937 #endif
938  uselist[i]=0 ;
939  }
940  }
941  }
942 
943 #ifdef EDM_ML_DEBUG
944  debugstr5 << " List of hits after uniqification " << " \n" ;
945  for (unsigned int i = 0; i < uselist.size(); i++) {
946  if ( uselist[i] ) {
947  const SiStripRecHit2D* hit = hitlist[i];
948  debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
949  << " R " << rlist[i]
950  << " Phi " << philist[i]
951  << " Weight " << w2list[i]
952  << " PhiPred " << (rlist[i]-scr)*phiVsRSlope
953  << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
954  << " \n" ;
955  }
956  }
957  debugstr5 << " \n\n\n" ;
958 #endif
959 
960  // need to check that there are more than 2 hits left here!
961  unsigned int nHitsLeft =0;
962  for (unsigned int i = 0; i < uselist.size(); i++) {
963  if ( uselist[i] ) {
964  nHitsLeft++;
965  }
966  }
967  if(nHitsLeft < nHitsLeftMinimum ) {
968 #ifdef EDM_ML_DEBUG
969  debugstr5 << " Too few hits "<< nHitsLeft
970  << " left - return false " << " \n";
971 #endif
972  return false ;
973  }
974 #ifdef EDM_ML_DEBUG
975  LogDebug("") << debugstr5.str();
976 #endif
977 
979  // Calculate a linear phi(r) fit and drop hits until the biggest contributor to chi^2 is less than maxNormResid_
980  bool done = false;
981  double intercept = 0 ;
982  double slope = 0 ;
983  double chi2 = 0;
984 
985  std::ostringstream debugstr4;
986  debugstr4 <<" Calc of phi(r) "<<" \n";
987 
988  while (!done) {
989  // Use an iterative update of <psi>, <r> etc instead in an
990  // attempt to minize divisions of large numbers
991  // The linear fit psi = slope*r + intercept
992  // slope is (<psi*r>-<psi>*<r>) / (<r^2>-<r>^2>)
993  // intercept is <psi> - slope*<r>
994 
995  double phiBar = 0.;
996  double phiBarOld = 0.;
997  double rBar = 0.;
998  double rBarOld = 0.;
999  double r2Bar = 0.;
1000  double r2BarOld = 0.;
1001  double phirBar = 0.;
1002  double phirBarOld = 0.;
1003  double totalWeight = 0.;
1004  double totalWeightOld = 0.;
1005  unsigned int uselist_size = uselist.size();
1006  for (unsigned int i = 0; i < uselist_size; i++) {
1007  if (uselist[i]) {
1008  double r = rlist[i];
1009  double phi = philist[i];
1010  double weight2 = w2list[i];
1011 
1012  totalWeight = totalWeightOld + weight2 ;
1013 
1014  //weight2 is 1/sigma^2. Typically sigma is 100micron pitch
1015  // over root(12) = 30 microns so weight2 is about 10^5-10^6
1016 
1017  double totalWeightRatio = totalWeightOld/totalWeight ;
1018  double localWeightRatio = weight2/totalWeight ;
1019 
1020  phiBar = phiBarOld*totalWeightRatio + phi*localWeightRatio ;
1021  rBar = rBarOld*totalWeightRatio + r*localWeightRatio ;
1022  r2Bar= r2BarOld*totalWeightRatio + r*r*localWeightRatio ;
1023  phirBar = phirBarOld*totalWeightRatio + phi*r*localWeightRatio ;
1024 
1025  totalWeightOld = totalWeight ;
1026  phiBarOld = phiBar ;
1027  rBarOld = rBar ;
1028  r2BarOld = r2Bar ;
1029  phirBarOld = phirBar ;
1030 #ifdef EDM_ML_DEBUG
1031  debugstr4 << " totalWeight " << totalWeight
1032  << " totalWeightRatio " << totalWeightRatio
1033  << " localWeightRatio "<< localWeightRatio
1034  << " phiBar " << phiBar
1035  << " rBar " << rBar
1036  << " r2Bar " << r2Bar
1037  << " phirBar " << phirBar
1038  << " \n ";
1039 #endif
1040 
1041  } // end of use hit loop
1042  } // end of hit loop to calculate a linear fit
1043  slope = (phirBar-phiBar*rBar)/(r2Bar-rBar*rBar);
1044  intercept = phiBar-slope*rBar ;
1045 
1046  debugstr4 << " end of loop slope " << slope
1047  << " intercept " << intercept << " \n";
1048 
1049  // Calculate chi^2
1050  chi2 = 0.;
1051  double biggest_normresid = -1.;
1052  unsigned int biggest_index = 0;
1053  for (unsigned int i = 0; i < uselist_size; i++) {
1054  if (uselist[i]) {
1055  double r = rlist[i];
1056  double phi = philist[i];
1057  double weight2 = w2list[i];
1058 
1059  double normresid = weight2 * (phi - intercept - slope*r)*(phi - intercept - slope*r);
1060  chi2 += normresid;
1061 
1062  if (normresid > biggest_normresid) {
1063  biggest_normresid = normresid;
1064  biggest_index = i;
1065  }
1066  }
1067  } // end loop over hits to calculate chi^2 and find its biggest contributer
1068 
1069  if (biggest_normresid > maxNormResid_) {
1070 #ifdef EDM_ML_DEBUG
1071  debugstr4 << "Dropping hit from fit due to Chi2 " << " \n" ;
1072  const SiStripRecHit2D* hit = hitlist[biggest_index];
1073  debugstr4 << " DetID " << ((hit)->geographicalId()).rawId()
1074  << " R " << rlist[biggest_index]
1075  << " Phi " << philist[biggest_index]
1076  << " Weight " << w2list[biggest_index]
1077  << " PhiPred " << (rlist[biggest_index]-scr)*phiVsRSlope
1078  << " Chi2 " << (philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*(philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*w2list[biggest_index]
1079  << " normresid " << biggest_normresid
1080  << " \n\n";
1081 #endif
1082  uselist[biggest_index] = false;
1083  }
1084  else {
1085  done = true;
1086  }
1087  } // end loop over trial fits
1088 #ifdef EDM_ML_DEBUG
1089  debugstr4 <<" Fit "
1090  << " Intercept " << intercept
1091  << " slope " << slope
1092  << " chi2 " << chi2
1093  << " \n" ;
1094 
1095  LogDebug("") << debugstr4.str() ;
1096 #endif
1097 
1098  // Now we have intercept, slope, and chi2; uselist to tell us which hits are used, and hitlist for the hits
1099 
1100  // Identify the innermost hit
1101  const SiStripRecHit2D* innerhit = (SiStripRecHit2D*)(0);
1102  double innerhitRadius = -1.; // meaningless until innerhit is defined
1103 
1104  // Copy hits into an OwnVector, which we put in the TrackCandidate
1105  std::vector<const TrackingRecHit*> outputHits;
1106  // Reference rphi and stereo hits into RefVectors, which we put in the SiStripElectron
1107  std::vector<SiStripRecHit2D> outputRphiHits;
1108  std::vector<SiStripRecHit2D> outputStereoHits;
1109 
1110  typedef edm::Ref<SiStripRecHit2DCollection,SiStripRecHit2D> SiStripRecHit2DRef;
1111 
1112 
1113  for (unsigned int i = 0; i < uselist.size(); i++) {
1114  if (uselist[i]) {
1115  double r = rlist[i];
1116  const SiStripRecHit2D* hit = hitlist[i];
1117 
1118  // Keep track of the innermost hit
1119  if (innerhit == (SiStripRecHit2D*)(0) || r < innerhitRadius) {
1120  innerhit = hit;
1121  innerhitRadius = r;
1122  }
1123 
1124  if (typelist[i] == 0) {
1125  numberOfStereoHits++;
1126 
1127  // Copy this hit for the TrajectorySeed
1128  outputHits.push_back(hit);
1129  outputStereoHits.push_back(*hit);
1130  }
1131  else if (typelist[i] == 1) {
1132  numberOfBarrelRphiHits++;
1133 
1134  // Copy this hit for the TrajectorySeed
1135  outputHits.push_back(hit);
1136  outputRphiHits.push_back(*hit);
1137  }
1138  else if (typelist[i] == 2) {
1139  numberOfEndcapZphiHits++;
1140 
1141  // Copy this hit for the TrajectorySeed
1142  outputHits.push_back(hit);
1143  outputRphiHits.push_back(*hit);
1144  }
1145  }
1146  } // end loop over all hits, after having culled the ones with big residuals
1147 
1148  unsigned int totalNumberOfHits = numberOfStereoHits + numberOfBarrelRphiHits + numberOfEndcapZphiHits;
1149  double reducedChi2 = (totalNumberOfHits > 2 ? chi2 / (totalNumberOfHits - 2) : 1e10);
1150 
1151  // Select this candidate if it passes minHits_ and maxReducedChi2_ cuts
1152  if (totalNumberOfHits >= minHits_ && reducedChi2 <= maxReducedChi2_) {
1153  // GlobalTrajectoryParameters evaluated at the position of the innerhit
1154  GlobalPoint position = tracker_p_->idToDet(innerhit->geographicalId())->surface().toGlobal(innerhit->localPosition());
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
virtual const TrackerGeomDet * idToDetUnit(DetId) const
Return the pointer to the GeomDetUnit corresponding to a given DetId.
int i
Definition: DBlmapReader.cc:9
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_
virtual GlobalVector inTesla(const GlobalPoint &gp) const =0
Field value ad specified global point, in Tesla.
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:52
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
assert(m_qm.get())
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
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
T y() const
Definition: PV3DBase.h:63
unsigned int tidWheel(const DetId &id) const
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
const SiStripRecHit2D * innerhit_pos_
uint32_t rawId() const
get the raw id
Definition: DetId.h:43
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
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
int j
Definition: DBlmapReader.cc:9
double unwrapPhi(double phi) const
std::map< const SiStripRecHit2D *, unsigned int > stereoKey_
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_
T const * product() const
Definition: ESHandle.h:86
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
std::map< const TrackingRecHit *, bool > hitUsed_
void coarseMatchedHitSelection(std::vector< const SiStripMatchedRecHit2D * > &coarseMatchedHitPointersOut)
const MagneticField * magneticField_p_
DetId geographicalId() const
volatile std::atomic< bool > shutdown_flag false
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 tecWheel(const DetId &id) const
unsigned int numberOfEndcapZphiHits_pos_
virtual LocalPoint localPosition() const final
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_
virtual const TrackerGeomDet * idToDet(DetId) const
iterator begin()
Definition: DetSetNew.h:67