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 // $Id: SiStripElectronAlgo.cc,v 1.40 2012/01/16 09:28:17 innocent Exp $
12 //
13 
14 // system include files
15 
16 // user include files
20 
21 
24 
30 
31 
32 //
33 // constants, enums and typedefs
34 //
35 
36 //
37 // static data member definitions
38 //
39 namespace {
40  struct CompareHits {
41  CompareHits( const TrackingRecHitLessFromGlobalPosition& iLess ) :
42  less_(iLess) {}
43  bool operator()(const TrackingRecHit* iLHS, const TrackingRecHit* iRHS) {
44  return less_(*iLHS,*iRHS);
45  }
46 
48  };
49 }
50 
51 
52 //
53 // constructors and destructor
54 //
55 SiStripElectronAlgo::SiStripElectronAlgo(unsigned int maxHitsOnDetId,
56  double originUncertainty,
57  double phiBandWidth,
58  double maxNormResid,
59  unsigned int minHits,
60  double maxReducedChi2)
61  : maxHitsOnDetId_(maxHitsOnDetId)
62  , originUncertainty_(originUncertainty)
63  , phiBandWidth_(phiBandWidth)
64  , maxNormResid_(maxNormResid)
65  , minHits_(minHits)
66  , maxReducedChi2_(maxReducedChi2)
67 {
68 }
69 
70 // SiStripElectronAlgo::SiStripElectronAlgo(const SiStripElectronAlgo& rhs)
71 // {
72 // // do actual copying here;
73 // }
74 
76 {
77 }
78 
79 //
80 // assignment operators
81 //
82 // const SiStripElectronAlgo& SiStripElectronAlgo::operator=(const SiStripElectronAlgo& rhs)
83 // {
84 // //An exception safe implementation is
85 // SiStripElectronAlgo temp(rhs);
86 // swap(rhs);
87 //
88 // return *this;
89 // }
90 
91 //
92 // member functions
93 //
94 
99  const edm::ESHandle<MagneticField>& magneticField)
100 {
101  LogDebug("") << " In prepareEvent " ;
102 
103  tracker_p_ = tracker.product();
104  rphiHits_p_ = rphiHits.product();
105  stereoHits_p_ = stereoHits.product();
106  matchedHits_p_ = matchedHits.product();
107  magneticField_p_ = magneticField.product();
108 
109  rphiHits_hp_ = &rphiHits;
110  stereoHits_hp_ = &stereoHits;
111 
112  // Keep a table that relates hit pointers to their index (key) in the collections
113  rphiKey_.clear();
114  stereoKey_.clear();
115  // Keep track of which hits have been used already (so a hit is assigned to only one electron)
116  hitUsed_.clear();
117  matchedHitUsed_.clear();
118 
119  unsigned int counter = 0;
121  rphiKey_[&(*it)] = counter;
122  hitUsed_[&(*it)] = false;
123  counter++;
124  }
125 
126  counter = 0;
128  stereoKey_[&(*it)] = counter;
129  hitUsed_[&(*it)] = false;
130  counter++;
131  }
132 
133  counter = 0;
135  matchedKey_[&(*it)] = counter;
136  matchedHitUsed_[&(*it)] = false;
137  counter++;
138  }
139 
140  LogDebug("") << " Leaving prepareEvent " ;
141 }
142 
143 
144 
145 // returns true iff an electron was found
146 // inserts electrons and trackcandiates into electronOut and trackCandidateOut
148  TrackCandidateCollection& trackCandidateOut,
149  const reco::SuperClusterRef& superclusterIn)
150 {
151  // Try each of the two charge hypotheses, but only take one
152  bool electronSuccess = projectPhiBand(-1., superclusterIn);
153  bool positronSuccess = projectPhiBand( 1., superclusterIn);
154 
155  // electron hypothesis did better than electron
156  if ((electronSuccess && !positronSuccess) ||
157  (electronSuccess && positronSuccess && redchi2_neg_ <= redchi2_pos_)) {
158 
159  // Initial uncertainty for tracking
160  AlgebraicSymMatrix55 errors; // makes 5x5 matrix, indexed from (0,0) to (44)
161  errors(0,0) = 3.; // uncertainty**2 in 1/momentum
162  errors(1,1) = 0.01; // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
163  errors(2,2) = 0.0001; // uncertainty**2 in phi
164  errors(3,3) = 0.01; // uncertainty**2 in x_transverse (where x is in cm)
165  errors(4,4) = 0.01; // uncertainty**2 in y_transverse (where y is in cm)
166 
167 #ifdef EDM_ML_DEBUG
168  // JED Debugging possible double hit sort problem
169  std::ostringstream debugstr6;
170  debugstr6 << " HERE BEFORE SORT electron case " << " \n" ;
171  for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin();
172  itHit != outputHits_neg_.end(); ++itHit) {
173  debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
174  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
175  <<" Global Rho: "
176  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
177  <<" Phi "
178  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
179  << " Z "
180  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
181  }
182  // end of dump
183 
184 
185 
186  // JED call dump
187  debugstr6 << " Calling sort alongMomentum " << " \n";
188 #endif
189 
192 
193 #ifdef EDM_ML_DEBUG
194  debugstr6 << " Done with sort " << " \n";
195 
196  debugstr6 << " HERE AFTER SORT electron case " << " \n";
197  for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin();
198  itHit != outputHits_neg_.end(); ++itHit) {
199  debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
200  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
201  <<" Global Rho: "
202  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
203  <<" Phi "
204  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
205  << " Z "
206  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";;
207  }
208  // end of dump
209 
210  LogDebug("")<< debugstr6.str();
211 #endif
212 
213  //create an OwnVector needed by the classes which will be stored to the Event
215  for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_neg_.begin();
216  itHit != outputHits_neg_.end();
217  ++itHit) {
218  hits.push_back( (*itHit)->clone());
219  if( !(hitUsed_.find(*itHit) != hitUsed_.end()) ) {
220  LogDebug("") << " Assert failure " ;
221  assert(hitUsed_.find(*itHit) != hitUsed_.end());
222  }
223  hitUsed_[*itHit] = true;
224  }
225 
230 
231 
233  TrajectorySeed trajectorySeed(PTraj, hits, alongMomentum);
234  trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, PTraj));
235 
236  electronOut.push_back(reco::SiStripElectron(superclusterIn,
237  -1,
241  slope_neg_,
242  intercept_neg_ + superclusterIn->position().phi(),
243  chi2_neg_,
244  ndof_neg_,
246  pZ_neg_,
251 
252  return true;
253  }
254 
255  // positron hypothesis did better than electron
256  if ((!electronSuccess && positronSuccess) ||
257  (electronSuccess && positronSuccess && redchi2_neg_ > redchi2_pos_)) {
258 
259  // Initial uncertainty for tracking
260  AlgebraicSymMatrix55 errors; // same as abovr
261  errors(0,0) = 3.; // uncertainty**2 in 1/momentum
262  errors(1,1) = 0.01; // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
263  errors(2,2) = 0.0001; // uncertainty**2 in phi
264  errors(3,3) = 0.01; // uncertainty**2 in x_transverse (where x is in cm)
265  errors(4,4) = 0.01; // uncertainty**2 in y_transverse (where y is in cm)
266 
267 #ifdef EDM_ML_DEBUG
268  // JED Debugging possible double hit sort problem
269  std::ostringstream debugstr7;
270  debugstr7 << " HERE BEFORE SORT Positron case " << " \n";
271  for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin();
272  itHit != outputHits_pos_.end(); ++itHit) {
273  debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
274  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
275  <<" Global Rho: "
276  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
277  <<" Phi "
278  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
279  << " Z "
280  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
281  }
282  // end of dump
283 
284  debugstr7 << " Calling sort alongMomentum " << " \n";
285 #endif
286 
289 
290 #ifdef EDM_ML_DEBUG
291  debugstr7 << " Done with sort " << " \n";
292 
293  // JED Debugging possible double hit sort problem
294  debugstr7 << " HERE AFTER SORT Positron case " << " \n";
295  for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin();
296  itHit != outputHits_pos_.end(); ++itHit) {
297  debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
298  <<" Local Position: "<<(*itHit)->localPosition()<<" \n"
299  <<" Global Rho: "
300  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
301  <<" Phi "
302  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
303  << " Z "
304  <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
305  }
306  // end of dump
307  LogDebug("") << debugstr7.str();
308 #endif
309 
310  //create an OwnVector needed by the classes which will be stored to the Event
312  for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_pos_.begin();
313  itHit != outputHits_pos_.end();
314  ++itHit) {
315  hits.push_back( (*itHit)->clone());
316  assert(hitUsed_.find(*itHit) != hitUsed_.end());
317  hitUsed_[*itHit] = true;
318  }
319 
324 
325 
327  TrajectorySeed trajectorySeed(PTraj, hits, alongMomentum);
328  trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, PTraj));
329 
330  electronOut.push_back(reco::SiStripElectron(superclusterIn,
331  1,
335  slope_pos_,
336  intercept_pos_ + superclusterIn->position().phi(),
337  chi2_pos_,
338  ndof_pos_,
340  pZ_pos_,
345 
346  return true;
347  }
348 
349  return false;
350 }
351 
352 // inserts pointers to good hits into hitPointersOut
353 // selects hits on DetIds that have no more than maxHitsOnDetId_
354 // selects from stereo if stereo == true, rphi otherwise
355 // selects from TID or TEC if endcap == true, TIB or TOB otherwise
356 void SiStripElectronAlgo::coarseHitSelection(std::vector<const SiStripRecHit2D*>& hitPointersOut,
357  bool stereo, bool endcap)
358 {
359  // This function is not time-efficient. If you want to improve the
360  // speed of the algorithm, you'll probably want to change this
361  // function. There may be a more efficienct way to extract hits,
362  // and it would definitely help to put a geographical cut on the
363  // DetIds. (How does one determine the global position of a given
364  // DetId? Is tracker_p_->idToDet(id)->surface().toGlobal(LocalPosition(0,0,0))
365  // expensive?)
366 
367  // Loop over the detector ids
370  for (; itdet != eddet; ++itdet) {
371  // Get the hits on this detector id
372  SiStripRecHit2DCollection::DetSet hits = *itdet;
373  DetId id(hits.detId());
374 
375  // Count the number of hits on this detector id
376  unsigned int numberOfHits = hits.size();
377 
378  // Only take the hits if there aren't too many
379  // (Would it be better to loop only once, fill a temporary list,
380  // and copy that if numberOfHits <= maxHitsOnDetId_?)
381  if (numberOfHits <= maxHitsOnDetId_) {
383  hit != hits.end(); ++hit) {
384  // check that hit is valid first !
385  if(!(*hit).isValid()) {
386  LogDebug("") << " InValid hit skipped in coarseHitSelection " << std::endl ;
387  continue ;
388  }
389  std::string theDet = "null";
390  int theLayer = -999;
391  bool isStereoDet = false ;
392  if(tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB) {
393  theDet = "TIB" ;
394  theLayer = TIBDetId(id).layer();
395  if(TIBDetId(id).stereo()==1) { isStereoDet = true ; }
396  } else if
397  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB) {
398  theDet = "TOB" ;
399  theLayer = TOBDetId(id).layer();
400  if(TOBDetId(id).stereo()==1) { isStereoDet = true ; }
401  }else if
402  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TID) {
403  theDet = "TID" ;
404  theLayer = TIDDetId(id).wheel(); // or ring ?
405  if(TIDDetId(id).stereo()==1) { isStereoDet = true ; }
406  }else if
407  (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TEC) {
408  theDet = "TEC" ;
409  theLayer = TECDetId(id).wheel(); // or ring or petal ?
410  if(TECDetId(id).stereo()==1) { isStereoDet = true ; }
411  } else {
412  LogDebug("") << " UHOH BIG PROBLEM - Unrecognized SI Layer" ;
413  LogDebug("") << " Det "<< theDet << " Lay " << theLayer ;
414  assert(1!=1) ;
415  }
416 
417  if ((endcap && stereo && (theDet=="TID" || theDet== "TEC") && isStereoDet ) ||
418  (endcap && !stereo && (theDet=="TID" || theDet== "TEC") && !isStereoDet ) ||
419  (!endcap && stereo && (theDet=="TIB" || theDet=="TOB") && isStereoDet ) ||
420  (!endcap && !stereo && (theDet=="TIB" || theDet=="TOB" )&& !isStereoDet )
421  ) {
422 
423 
424  hitPointersOut.push_back(&(*hit));
425 
426  } // end if this is the right subdetector
427  } // end loop over hits
428  } // end if this detector id doesn't have too many hits on it
429  } // end loop over detector ids
430 }
431 
432 // select all matched hits for now
433 
434 void SiStripElectronAlgo::coarseMatchedHitSelection(std::vector<const SiStripMatchedRecHit2D*>& coarseMatchedHitPointersOut)
435 {
436 
437  // Loop over the detector ids
439  for (; itdet != eddet; ++itdet) {
440 
441  // Get the hits on this detector id
443 
444  // Count the number of hits on this detector id
445  unsigned int numberOfHits = 0;
447  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
448  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
449  numberOfHits++;
450  if (numberOfHits > maxHitsOnDetId_) { break; }
451  }
452 
453  // Only take the hits if there aren't too many
454  if (numberOfHits <= maxHitsOnDetId_) {
456  if(!(*hit).isValid()) {
457  LogDebug("") << " InValid hit skipped in coarseMatchedHitSelection " << std::endl ;
458  continue ;
459  }
460  if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
461  !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
462 
463  coarseMatchedHitPointersOut.push_back(&(*hit));
464  } // end loop over hits
465 
466  } // end if this detector id doesn't have too many hits on it
467  } // end loop over detector ids
468 
469 
470 }// end of matchedHitSelection
471 
472 
473 
474 
475 // projects a phi band of width phiBandWidth_ from supercluster into tracker (given a chargeHypothesis)
476 // fills *_pos_ or *_neg_ member data with the results
477 // returns true iff the electron/positron passes cuts
478 bool SiStripElectronAlgo::projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef& superclusterIn)
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, 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, 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  (TIBDetId((*hit)->geographicalId()).layer()==1 || TIBDetId((*hit)->geographicalId()).layer()==2)) ||
713  (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB
714  && (TOBDetId((*hit)->geographicalId()).layer()==1 || TOBDetId((*hit)->geographicalId()).layer()==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:22
int i
Definition: DBlmapReader.cc:9
boost::transform_iterator< IterHelp, const_IdIter > const_iterator
const_iterator begin() const
std::vector< const TrackingRecHit * > outputHits_pos_
unsigned int layer() const
layer id
Definition: TOBDetId.h:39
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:47
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::vector< TrackCandidate > TrackCandidateCollection
Geom::Phi< T > phi() const
Definition: PV3DBase.h:68
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
PTrajectoryStateOnDet persistentState(const TrajectoryStateOnSurface &ts, unsigned int detid)
T y() const
Definition: PV3DBase.h:62
#define abs(x)
Definition: mlp_lapack.h:159
ROOT::Math::SMatrix< double, 5, 5, ROOT::Math::MatRepSym< double, 5 > > AlgebraicSymMatrix55
bool findElectron(reco::SiStripElectronCollection &electronOut, TrackCandidateCollection &trackCandidateOut, const reco::SuperClusterRef &superclusterIn)
const SiStripRecHit2D * innerhit_pos_
double double double z
bool projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef &superclusterIn)
uint32_t rawId() const
get the raw id
Definition: DetId.h:45
void push_back(D *&d)
Definition: OwnVector.h:273
std::vector< SiStripRecHit2D > outputStereoHits_pos_
std::map< const TrackingRecHit *, bool > matchedHitUsed_
std::vector< SiStripElectron > SiStripElectronCollection
collectin of SiStripElectron objects
T sqrt(T t)
Definition: SSEVec.h:46
T z() const
Definition: PV3DBase.h:63
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
data_type const * data(size_t cell) const
const SiStripRecHit2DCollection * rphiHits_p_
int j
Definition: DBlmapReader.cc:9
double unwrapPhi(double phi) const
std::map< const SiStripRecHit2D *, unsigned int > stereoKey_
const_iterator end() const
virtual const GeomDet * idToDet(DetId) const
std::vector< SiStripRecHit2D > outputRphiHits_neg_
const SiStripRecHit2DCollection * stereoHits_p_
unsigned int numberOfStereoHits_pos_
Definition: DetId.h:20
virtual LocalPoint localPosition() const
unsigned int numberOfBarrelRphiHits_pos_
void coarseHitSelection(std::vector< const SiStripRecHit2D * > &hitPointersOut, bool stereo, bool endcap)
std::vector< SiStripRecHit2D > outputStereoHits_neg_
const TrackerGeometry * tracker_p_
T const * product() const
Definition: ESHandle.h:62
const edm::Handle< SiStripRecHit2DCollection > * rphiHits_hp_
id_type detId() const
Definition: DetSetNew.h:72
const SiStripMatchedRecHit2DCollection * matchedHits_p_
T const * product() const
Definition: Handle.h:74
unsigned int wheel() const
wheel id
Definition: TECDetId.h:52
char state
Definition: procUtils.cc:75
unsigned int layer() const
layer id
Definition: TIBDetId.h:41
virtual const GeomDetUnit * idToDetUnit(DetId) const
Return the pointer to the GeomDetUnit corresponding to a given DetId.
std::map< const SiStripMatchedRecHit2D *, unsigned int > matchedKey_
T perp() const
Magnitude of transverse component.
iterator end()
Definition: DetSetNew.h:59
static int position[264][3]
Definition: ReadPGInfo.cc:509
std::map< const TrackingRecHit *, bool > hitUsed_
void coarseMatchedHitSelection(std::vector< const SiStripMatchedRecHit2D * > &coarseMatchedHitPointersOut)
const MagneticField * magneticField_p_
DetId geographicalId() const
std::map< const SiStripRecHit2D *, unsigned int > rphiKey_
size_type size() const
Definition: DetSetNew.h:75
SiStripElectronAlgo(unsigned int maxHitsOnDetId, double originUncertainty, double phiBandWidth, double maxNormResid, unsigned int minHits, double maxReducedChi2)
T x() const
Definition: PV3DBase.h:61
unsigned int numberOfEndcapZphiHits_pos_
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
unsigned int wheel() const
wheel id
Definition: TIDDetId.h:50
std::vector< const TrackingRecHit * > outputHits_neg_
Definition: DDAxes.h:10
iterator begin()
Definition: DetSetNew.h:56