CMS 3D CMS Logo

SiStripElectronAlgo.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     EgammaElectronAlgos
00004 // Class  :     SiStripElectronAlgo
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Jim Pivarski
00010 //         Created:  Fri May 26 16:12:04 EDT 2006
00011 // $Id: SiStripElectronAlgo.cc,v 1.29 2008/04/10 15:33:28 uberthon Exp $
00012 //
00013 
00014 // system include files
00015 
00016 // user include files
00017 #include "DataFormats/EgammaCandidates/interface/SiStripElectronFwd.h"
00018 #include "RecoEgamma/EgammaElectronAlgos/interface/SiStripElectronAlgo.h"
00019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00020 
00021 #include "Geometry/CommonTopologies/interface/TrapezoidalStripTopology.h"
00022 #include "Geometry/CommonTopologies/interface/RectangularStripTopology.h"
00023 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00024 
00025 #include "DataFormats/TrajectorySeed/interface/PropagationDirection.h"
00026 #include "RecoTracker/TrackProducer/interface/TrackingRecHitLessFromGlobalPosition.h"
00027 
00028 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00029 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00030 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00031 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00032 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
00033 
00034 
00035 //
00036 // constants, enums and typedefs
00037 //
00038 
00039 //
00040 // static data member definitions
00041 //
00042 namespace {
00043   struct CompareHits {
00044     CompareHits( const TrackingRecHitLessFromGlobalPosition& iLess ) :
00045       less_(iLess) {}
00046     bool operator()(const TrackingRecHit* iLHS, const TrackingRecHit* iRHS) {
00047       return less_(*iLHS,*iRHS);
00048     }
00049          
00050     TrackingRecHitLessFromGlobalPosition less_;
00051   };
00052 }
00053 
00054 
00055 //
00056 // constructors and destructor
00057 //
00058 SiStripElectronAlgo::SiStripElectronAlgo(unsigned int maxHitsOnDetId,
00059                                          double originUncertainty,
00060                                          double phiBandWidth,
00061                                          double maxNormResid,
00062                                          unsigned int minHits,
00063                                          double maxReducedChi2)
00064   : maxHitsOnDetId_(maxHitsOnDetId)
00065   , originUncertainty_(originUncertainty)
00066   , phiBandWidth_(phiBandWidth)
00067   , maxNormResid_(maxNormResid)
00068   , minHits_(minHits)
00069   , maxReducedChi2_(maxReducedChi2)
00070 {
00071 }
00072 
00073 // SiStripElectronAlgo::SiStripElectronAlgo(const SiStripElectronAlgo& rhs)
00074 // {
00075 //    // do actual copying here;
00076 // }
00077 
00078 SiStripElectronAlgo::~SiStripElectronAlgo()
00079 {
00080 }
00081 
00082 //
00083 // assignment operators
00084 //
00085 // const SiStripElectronAlgo& SiStripElectronAlgo::operator=(const SiStripElectronAlgo& rhs)
00086 // {
00087 //   //An exception safe implementation is
00088 //   SiStripElectronAlgo temp(rhs);
00089 //   swap(rhs);
00090 //
00091 //   return *this;
00092 // }
00093 
00094 //
00095 // member functions
00096 //
00097 
00098 void SiStripElectronAlgo::prepareEvent(const edm::ESHandle<TrackerGeometry>& tracker,
00099                                        const edm::Handle<SiStripRecHit2DCollection>& rphiHits,
00100                                        const edm::Handle<SiStripRecHit2DCollection>& stereoHits,
00101                                        const edm::Handle<SiStripMatchedRecHit2DCollection>& matchedHits,
00102                                        const edm::ESHandle<MagneticField>& magneticField)
00103 {
00104   LogDebug("") << " In prepareEvent " ; 
00105 
00106   tracker_p_ = tracker.product();
00107   rphiHits_p_ = rphiHits.product();
00108   stereoHits_p_ = stereoHits.product();
00109   matchedHits_p_ = matchedHits.product();
00110   magneticField_p_ = magneticField.product();
00111 
00112   rphiHits_hp_ = &rphiHits;
00113   stereoHits_hp_ = &stereoHits;
00114 
00115   // Keep a table that relates hit pointers to their index (key) in the collections
00116   rphiKey_.clear();
00117   stereoKey_.clear();
00118   // Keep track of which hits have been used already (so a hit is assigned to only one electron)
00119   hitUsed_.clear();
00120   matchedHitUsed_.clear();
00121 
00122   unsigned int counter = 0;
00123   for (SiStripRecHit2DCollection::const_iterator it = rphiHits_p_->begin();  it != rphiHits_p_->end();  ++it) {
00124     rphiKey_[&(*it)] = counter;
00125     hitUsed_[&(*it)] = false;
00126     counter++;
00127   }
00128 
00129   counter = 0;
00130   for (SiStripRecHit2DCollection::const_iterator it = stereoHits_p_->begin();  it != stereoHits_p_->end();  ++it) {
00131     stereoKey_[&(*it)] = counter;
00132     hitUsed_[&(*it)] = false;
00133     counter++;
00134   }
00135 
00136   counter = 0;
00137   for (SiStripMatchedRecHit2DCollection::const_iterator it = matchedHits_p_->begin();  it != matchedHits_p_->end();  ++it) {
00138     matchedKey_[&(*it)] = counter;
00139     matchedHitUsed_[&(*it)] = false;
00140     counter++;
00141   }
00142   
00143   LogDebug("") << " Leaving prepareEvent " ;
00144 }
00145 
00146 
00147 
00148 // returns true iff an electron was found
00149 // inserts electrons and trackcandiates into electronOut and trackCandidateOut
00150 bool SiStripElectronAlgo::findElectron(reco::SiStripElectronCollection& electronOut,
00151                                        TrackCandidateCollection& trackCandidateOut,
00152                                        const reco::SuperClusterRef& superclusterIn)
00153 {
00154   // Try each of the two charge hypotheses, but only take one
00155   bool electronSuccess = projectPhiBand(-1., superclusterIn);
00156   bool positronSuccess = projectPhiBand( 1., superclusterIn);
00157 
00158   // electron hypothesis did better than electron
00159   if ((electronSuccess  &&  !positronSuccess)  ||
00160       (electronSuccess  &&  positronSuccess  &&  redchi2_neg_ <= redchi2_pos_)) {
00161       
00162     // Initial uncertainty for tracking
00163     AlgebraicSymMatrix errors(5,1);  // makes identity 5x5 matrix, indexed from (1,1) to (5,5)
00164     errors(1,1) = 3.;      // uncertainty**2 in 1/momentum
00165     errors(2,2) = 0.01;    // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
00166     errors(3,3) = 0.0001;  // uncertainty**2 in phi
00167     errors(4,4) = 0.01;    // uncertainty**2 in x_transverse (where x is in cm)
00168     errors(5,5) = 0.01;    // uncertainty**2 in y_transverse (where y is in cm)
00169 
00170     // JED Debugging possible double hit sort problem
00171     std::ostringstream debugstr6;
00172     debugstr6 << " HERE BEFORE SORT electron case " << " \n" ;
00173     for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin(); 
00174          itHit != outputHits_neg_.end(); ++itHit) {
00175       debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
00176                 <<"    Local Position: "<<(*itHit)->localPosition()<<" \n"
00177                 <<"    Global Rho:  "
00178                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
00179                 <<" Phi "
00180                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
00181                 << " Z "
00182                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
00183     }
00184     // end of dump 
00185     
00186     
00187     
00188     // JED call dump 
00189     debugstr6 << " Calling sort alongMomentum " << " \n"; 
00190     
00191     std::sort(outputHits_neg_.begin(), outputHits_neg_.end(),
00192               CompareHits(TrackingRecHitLessFromGlobalPosition(((TrackingGeometry*)(tracker_p_)), alongMomentum)));
00193     
00194 
00195     debugstr6 << " Done with sort " << " \n";
00196     
00197     debugstr6 << " HERE AFTER SORT electron case " << " \n";
00198     for (std::vector<const TrackingRecHit*>::iterator itHit=outputHits_neg_.begin(); 
00199          itHit != outputHits_neg_.end(); ++itHit) {
00200       debugstr6 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
00201                 <<"    Local Position: "<<(*itHit)->localPosition()<<" \n"
00202                 <<"    Global Rho:  "
00203                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
00204                 <<" Phi "
00205                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
00206                 << " Z "
00207                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";; 
00208     }
00209     // end of dump 
00210 
00211     LogDebug("")<< debugstr6.str();
00212 
00213     
00214     //create an OwnVector needed by the classes which will be stored to the Event
00215     edm::OwnVector<TrackingRecHit> hits;
00216     for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_neg_.begin();
00217         itHit != outputHits_neg_.end();
00218         ++itHit) {
00219       hits.push_back( (*itHit)->clone());
00220       if( !(hitUsed_.find(*itHit) != hitUsed_.end()) ) {
00221         LogDebug("") << " Assert failure " ;
00222         assert(hitUsed_.find(*itHit) != hitUsed_.end());
00223       }
00224       hitUsed_[*itHit] = true;
00225     }
00226     
00227     TrajectoryStateOnSurface state(
00228                                    GlobalTrajectoryParameters(position_neg_, momentum_neg_, -1, magneticField_p_),
00229                                    CurvilinearTrajectoryError(errors),
00230                                    tracker_p_->idToDet(innerhit_neg_->geographicalId())->surface());
00231     
00232     TrajectoryStateTransform transformer;
00233     PTrajectoryStateOnDet* PTraj = transformer.persistentState(state, innerhit_neg_->geographicalId().rawId());
00234     TrajectorySeed trajectorySeed(*PTraj, hits, alongMomentum);
00235     trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, *PTraj));
00236     
00237     electronOut.push_back(reco::SiStripElectron(superclusterIn,
00238                                                 -1,
00239                                                 outputRphiHits_neg_,
00240                                                 outputStereoHits_neg_,
00241                                                 phiVsRSlope_neg_,
00242                                                 slope_neg_,
00243                                                 intercept_neg_ + superclusterIn->position().phi(),
00244                                                 chi2_neg_,
00245                                                 ndof_neg_,
00246                                                 correct_pT_neg_,
00247                                                 pZ_neg_,
00248                                                 zVsRSlope_neg_,
00249                                                 numberOfStereoHits_neg_,
00250                                                 numberOfBarrelRphiHits_neg_,
00251                                                 numberOfEndcapZphiHits_neg_));
00252     
00253     delete PTraj; // ShR: fix memory leak reported per perfrmance task force
00254     
00255     return true;
00256   }
00257   
00258   // positron hypothesis did better than electron
00259   if ((!electronSuccess  &&  positronSuccess)  ||
00260       (electronSuccess  &&  positronSuccess  &&  redchi2_neg_ > redchi2_pos_)) {
00261       
00262     // Initial uncertainty for tracking
00263     AlgebraicSymMatrix errors(5,1);  // makes identity 5x5 matrix, indexed from (1,1) to (5,5)
00264     errors(1,1) = 3.;      // uncertainty**2 in 1/momentum
00265     errors(2,2) = 0.01;    // uncertainty**2 in lambda (lambda == pi/2 - polar angle theta)
00266     errors(3,3) = 0.0001;  // uncertainty**2 in phi
00267     errors(4,4) = 0.01;    // uncertainty**2 in x_transverse (where x is in cm)
00268     errors(5,5) = 0.01;    // uncertainty**2 in y_transverse (where y is in cm)
00269 
00270     // JED Debugging possible double hit sort problem
00271     std::ostringstream debugstr7;
00272     debugstr7 << " HERE BEFORE SORT Positron case " << " \n";
00273     for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin(); 
00274          itHit != outputHits_pos_.end(); ++itHit) {
00275       debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
00276                 <<"    Local Position: "<<(*itHit)->localPosition()<<" \n"
00277                 <<"    Global Rho:  "
00278                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
00279                 <<" Phi "
00280                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
00281                 << " Z "
00282                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n";
00283     }
00284     // end of dump 
00285     
00286     debugstr7 << " Calling sort alongMomentum " << " \n"; 
00287     
00288     std::sort(outputHits_pos_.begin(), outputHits_pos_.end(),
00289               CompareHits(TrackingRecHitLessFromGlobalPosition(((TrackingGeometry*)(tracker_p_)), alongMomentum)));
00290     
00291     debugstr7 << " Done with sort " << " \n";
00292     
00293     // JED Debugging possible double hit sort problem
00294     debugstr7 << " HERE AFTER SORT Positron case " << " \n";
00295     for (std::vector<const TrackingRecHit*>::iterator itHit = outputHits_pos_.begin(); 
00296          itHit != outputHits_pos_.end(); ++itHit) {
00297       debugstr7 <<" HIT "<<((*itHit)->geographicalId()).rawId()<<" \n"
00298                 <<"    Local Position: "<<(*itHit)->localPosition()<<" \n"
00299                 <<"    Global Rho:  "
00300                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).perp())
00301                 <<" Phi "
00302                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).phi())
00303                 << " Z "
00304                 <<(((TrackingGeometry*)(tracker_p_))->idToDet((*itHit)->geographicalId())->surface().toGlobal((*itHit)->localPosition()).z())<< " \n"; 
00305     }
00306     // end of dump 
00307     LogDebug("") << debugstr7.str();
00308 
00309     //create an OwnVector needed by the classes which will be stored to the Event
00310     edm::OwnVector<TrackingRecHit> hits;
00311     for(std::vector<const TrackingRecHit*>::iterator itHit =outputHits_pos_.begin();
00312         itHit != outputHits_pos_.end();
00313         ++itHit) {
00314       hits.push_back( (*itHit)->clone());
00315       assert(hitUsed_.find(*itHit) != hitUsed_.end());
00316       hitUsed_[*itHit] = true;
00317     }
00318     
00319     TrajectoryStateOnSurface state(
00320                                    GlobalTrajectoryParameters(position_pos_, momentum_pos_, 1, magneticField_p_),
00321                                    CurvilinearTrajectoryError(errors),
00322                                    tracker_p_->idToDet(innerhit_pos_->geographicalId())->surface());
00323     
00324     TrajectoryStateTransform transformer;
00325     PTrajectoryStateOnDet* PTraj = transformer.persistentState(state, innerhit_pos_->geographicalId().rawId());
00326     TrajectorySeed trajectorySeed(*PTraj, hits, alongMomentum);
00327     trackCandidateOut.push_back(TrackCandidate(hits, trajectorySeed, *PTraj));
00328     
00329     electronOut.push_back(reco::SiStripElectron(superclusterIn,
00330                                                 1,
00331                                                 outputRphiHits_pos_,
00332                                                 outputStereoHits_pos_,
00333                                                 phiVsRSlope_pos_,
00334                                                 slope_pos_,
00335                                                 intercept_pos_ + superclusterIn->position().phi(),
00336                                                 chi2_pos_,
00337                                                 ndof_pos_,
00338                                                 correct_pT_pos_,
00339                                                 pZ_pos_,
00340                                                 zVsRSlope_pos_,
00341                                                 numberOfStereoHits_pos_,
00342                                                 numberOfBarrelRphiHits_pos_,
00343                                                 numberOfEndcapZphiHits_pos_));
00344     
00345     delete PTraj; // JED: fix of 2nd memory leak reported per perfrmance task force
00346     
00347     return true;
00348   }
00349   
00350   return false;
00351 }
00352 
00353 // inserts pointers to good hits into hitPointersOut
00354 // selects hits on DetIds that have no more than maxHitsOnDetId_
00355 // selects from stereo if stereo == true, rphi otherwise
00356 // selects from TID or TEC if endcap == true, TIB or TOB otherwise
00357 void SiStripElectronAlgo::coarseHitSelection(std::vector<const SiStripRecHit2D*>& hitPointersOut,
00358                                              bool stereo, bool endcap)
00359 {
00360   // This function is not time-efficient.  If you want to improve the
00361   // speed of the algorithm, you'll probably want to change this
00362   // function.  There may be a more efficienct way to extract hits,
00363   // and it would definitely help to put a geographical cut on the
00364   // DetIds.  (How does one determine the global position of a given
00365   // DetId?  Is tracker_p_->idToDet(id)->surface().toGlobal(LocalPosition(0,0,0))
00366   // expensive?)
00367 
00368   // Loop over the detector ids
00369   const std::vector<DetId> ids = (stereo ? stereoHits_p_->ids() : rphiHits_p_->ids());
00370   for (std::vector<DetId>::const_iterator id = ids.begin();  id != ids.end();  ++id) {
00371 
00372     // Get the hits on this detector id
00373     SiStripRecHit2DCollection::range hits = (stereo ? stereoHits_p_->get(*id) : rphiHits_p_->get(*id));
00374 
00375     // Count the number of hits on this detector id
00376     unsigned int numberOfHits = 0;
00377     for (SiStripRecHit2DCollection::const_iterator hit = hits.first;  hit != hits.second;  ++hit) {
00378       numberOfHits++;
00379       if (numberOfHits > maxHitsOnDetId_) { break; }
00380     }
00381       
00382     // Only take the hits if there aren't too many
00383     // (Would it be better to loop only once, fill a temporary list,
00384     // and copy that if numberOfHits <= maxHitsOnDetId_?)
00385     if (numberOfHits <= maxHitsOnDetId_) {
00386       for (SiStripRecHit2DCollection::const_iterator hit = hits.first;  
00387            hit != hits.second;  ++hit) {
00388         // check that hit is valid first !
00389         if(!(*hit).isValid()) {
00390           LogDebug("") << " InValid hit skipped in coarseHitSelection " << std::endl ;
00391           continue ;
00392         }
00393         std::string theDet = "null";
00394         int theLayer = -999;
00395         bool isStereoDet = false ;
00396         if(tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB) { 
00397           theDet = "TIB" ;
00398           theLayer = TIBDetId(*id).layer(); 
00399           if(TIBDetId(*id).stereo()==1) { isStereoDet = true ; }
00400         } else if
00401           (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB) { 
00402           theDet = "TOB" ;
00403           theLayer = TOBDetId(*id).layer(); 
00404           if(TOBDetId(*id).stereo()==1) { isStereoDet = true ; }
00405         }else if
00406           (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TID) { 
00407           theDet = "TID" ;
00408           theLayer = TIDDetId(*id).wheel();  // or ring  ?
00409           if(TIDDetId(*id).stereo()==1) { isStereoDet = true ; }
00410         }else if
00411           (tracker_p_->idToDetUnit(hit->geographicalId())->type().subDetector() == GeomDetEnumerators::TEC) { 
00412           theDet = "TEC" ;
00413           theLayer = TECDetId(*id).wheel();  // or ring or petal ?
00414           if(TECDetId(*id).stereo()==1) { isStereoDet = true ; }
00415         } else {
00416           LogDebug("") << " UHOH BIG PROBLEM - Unrecognized SI Layer" ;
00417           LogDebug("") << " Det "<< theDet << " Lay " << theLayer ;
00418           assert(1!=1) ;
00419         }
00420 
00421         if ((endcap  &&  stereo && (theDet=="TID" || theDet== "TEC") && isStereoDet ) ||
00422             (endcap  &&  !stereo && (theDet=="TID" || theDet== "TEC") && !isStereoDet )  ||
00423             (!endcap  && stereo && (theDet=="TIB" || theDet=="TOB") &&  isStereoDet )    ||
00424             (!endcap  &&  !stereo && (theDet=="TIB" || theDet=="TOB" )&& !isStereoDet )
00425             ) {  
00426               
00427 
00428           hitPointersOut.push_back(&(*hit));
00429 
00430         } // end if this is the right subdetector
00431       } // end loop over hits
00432     } // end if this detector id doesn't have too many hits on it
00433   } // end loop over detector ids
00434 }
00435 
00436 // select all matched hits for now
00437 
00438 void SiStripElectronAlgo::coarseMatchedHitSelection(std::vector<const SiStripMatchedRecHit2D*>& coarseMatchedHitPointersOut)
00439 {
00440   
00441   // Loop over the detector ids
00442   const std::vector<DetId> ids = matchedHits_p_->ids() ;
00443   for (std::vector<DetId>::const_iterator id = ids.begin();  id != ids.end();  ++id) {
00444     
00445     // Get the hits on this detector id
00446     SiStripMatchedRecHit2DCollection::range hits = matchedHits_p_->get(*id) ;
00447     
00448     // Count the number of hits on this detector id
00449     unsigned int numberOfHits = 0;
00450     for (SiStripMatchedRecHit2DCollection::const_iterator hit = hits.first;  hit != hits.second;  ++hit) {
00451       if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
00452            !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
00453       numberOfHits++;
00454       if (numberOfHits > maxHitsOnDetId_) { break; }
00455     }
00456     
00457     // Only take the hits if there aren't too many
00458     if (numberOfHits <= maxHitsOnDetId_) {
00459       for (SiStripMatchedRecHit2DCollection::const_iterator hit = hits.first;  hit != hits.second;  ++hit) {
00460         if(!(*hit).isValid()) {
00461           LogDebug("") << " InValid hit skipped in coarseMatchedHitSelection " << std::endl ;
00462           continue ;
00463         }
00464         if ( !((hit->geographicalId()).subdetId() == StripSubdetector::TIB) &&
00465              !( (hit->geographicalId()).subdetId() == StripSubdetector::TOB )) { break;}
00466         
00467         coarseMatchedHitPointersOut.push_back(&(*hit));
00468       } // end loop over hits
00469       
00470     } // end if this detector id doesn't have too many hits on it
00471   } // end loop over detector ids
00472   
00473 
00474 }// end of matchedHitSelection
00475 
00476 
00477 
00478 
00479 // projects a phi band of width phiBandWidth_ from supercluster into tracker (given a chargeHypothesis)
00480 // fills *_pos_ or *_neg_ member data with the results
00481 // returns true iff the electron/positron passes cuts
00482 bool SiStripElectronAlgo::projectPhiBand(float chargeHypothesis, const reco::SuperClusterRef& superclusterIn)
00483 {
00484   // This algorithm projects a phi band into the tracker three times:
00485   // (a) for all stereo hits, (b) for barrel rphi hits, and (c) for
00486   // endcap zphi hits.  While accumulating stereo hits in step (a),
00487   // we fit r vs z to a line.  This resolves the ambiguity in z for
00488   // rphi hits and the ambiguity in r for zphi hits.  We can then cut
00489   // on the z of rphi hits (a little wider than one strip length),
00490   // and we can convert the z of zphi hits into r to apply the phi
00491   // band cut.  (We don't take advantage of the endcap strips'
00492   // segmentation in r.)
00493   // 
00494   // As we project a phi band into the tracker, we count hits within
00495   // that band and performs a linear fit for phi vs r.  The number of
00496   // hits and reduced chi^2 from the fit are used to select a good
00497   // candidate.
00498 
00499   // set limits on Si hits - smallest error that makes sense = 1 micron ?
00500   static const double rphiHitSmallestError = 0.0001 ;
00501   static const double stereoHitSmallestError = 0.0001 ;
00502   //not used since endcap is not implemented  
00503   // static const double zphiHitSmallestError = 0.0001 ;
00504 
00505 
00506   static const double stereoPitchAngle = 0.100 ; // stereo angle in rad
00507   static const double cos2SiPitchAngle = cos(stereoPitchAngle)*cos(stereoPitchAngle) ;
00508   static const double sin2SiPitchAngle = sin(stereoPitchAngle)*sin(stereoPitchAngle) ;
00509   // overall misalignment fudge to be added in quad to position errors.
00510   // this is a rough approx to values reported in tracking meet 5/16/2007
00511   static const double rphiErrFudge = 0.0200 ;
00512   static const double stereoErrFudge = 0.0200 ;
00513 
00514   // max chi2 of a hit on an SiDet relative to the prediction
00515   static const double chi2HitMax = 25.0 ;
00516 
00517   // Minimum number of hits to consider on a candidate
00518   static const unsigned int nHitsLeftMinimum = 3  ;
00519 
00520   // Create and fill vectors of pointers to hits
00521   std::vector<const SiStripRecHit2D*> stereoHits;
00522   std::vector<const SiStripRecHit2D*> rphiBarrelHits;
00523   std::vector<const SiStripRecHit2D*> zphiEndcapHits;
00524 
00525   //                                 stereo? endcap?
00526   coarseHitSelection(stereoHits,     true,   false);
00527 
00528   // skip endcap stereo for now
00529   //  LogDebug("") << " Getting endcap stereo hits " ;
00530   // coarseHitSelection(stereoHits,     true,   true);
00531   std::ostringstream debugstr1;
00532   debugstr1 << " Getting barrel rphi hits " << " \n" ;
00533 
00534   coarseHitSelection(rphiBarrelHits, false,  false);
00535 
00536   //  LogDebug("") << " Getting endcap zphi hits " ;
00537   //  coarseHitSelection(zphiEndcapHits, false,  true);
00538 
00539   debugstr1 << " Getting matched hits "  << " \n" ;
00540   std::vector<const SiStripMatchedRecHit2D*> matchedHits;
00541   coarseMatchedHitSelection(matchedHits);
00542 
00543 
00544   // Determine how to project from the supercluster into the tracker
00545   double energy = superclusterIn->energy();
00546   double pT = energy * superclusterIn->position().rho()/sqrt(superclusterIn->x()*superclusterIn->x() +
00547                                                              superclusterIn->y()*superclusterIn->y() +
00548                                                              superclusterIn->z()*superclusterIn->z());
00549   // cf Jackson p. 581-2, a little geometry
00550   double phiVsRSlope = -3.00e-3 * chargeHypothesis * magneticField_p_->inTesla(GlobalPoint(superclusterIn->x(), superclusterIn->y(), 0.)).z() / pT / 2.;
00551 
00552   // Shorthand for supercluster radius, z
00553   const double scr = superclusterIn->position().rho();
00554   const double scz = superclusterIn->position().z();
00555 
00556   // These are used to fit all hits to a line in phi(r)
00557   std::vector<bool> uselist;
00558   std::vector<double> rlist, philist, w2list;
00559   std::vector<int> typelist;  // stereo = 0, rphi barrel = 1, and zphi disk = 2 (only used in this function)
00560   std::vector<const SiStripRecHit2D*> hitlist;
00561 
00562   std::vector<bool> matcheduselist;
00563   std::vector<const SiStripMatchedRecHit2D*> matchedhitlist;
00564 
00565   // These are used to fit the stereo hits to a line in z(r), constrained to pass through supercluster
00566   double zSlopeFitNumer = 0.;
00567   double zSlopeFitDenom = 0.;
00568 
00569   
00570   debugstr1 << " There are a total of " << stereoHits.size()  << " stereoHits in this event " << " \n" 
00571             << " There are a total of " <<  rphiBarrelHits.size() << " rphiBarrelHits in this event " << " \n"
00572             << " There are a total of " <<  zphiEndcapHits.size() << " zphiEndcapHits in this event " << " \n\n";
00573 
00574 
00575   LogDebug("") << debugstr1.str() ;
00576   
00578 
00579 
00580   // Loop over all matched hits
00581   // make a list of good matched rechits.
00582   // in the stereo and rphi loops check to see if the hit is associated with a matchedhit
00583   LogDebug("") << " Loop over matched hits " << " \n";
00584 
00585   for (std::vector<const SiStripMatchedRecHit2D*>::const_iterator hit = matchedHits.begin() ;
00586        hit != matchedHits.end() ; ++ hit) {
00587     
00588     assert(matchedHitUsed_.find(*hit) != matchedHitUsed_.end());
00589 
00590     if (!matchedHitUsed_[*hit]) {
00591 
00592       // Calculate the 3-D position of this hit
00593       GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
00594       double r = sqrt(position.x()*position.x() + position.y()*position.y());
00595       double phi = unwrapPhi(position.phi() - superclusterIn->position().phi());  // phi is relative to supercluster
00596       double z = position.z();
00597 
00598       // Cut a triangle in the z-r plane using the supercluster's eta/dip angle information
00599       // and the fact that the electron originated *near* the origin
00600       if ((-originUncertainty_ + (scz + originUncertainty_)*(r/scr)) < z  &&  z < (originUncertainty_ + (scz - originUncertainty_)*(r/scr))) {
00601          
00602         // Cut a narrow band around the supercluster's projection in phi
00603         if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi  &&  phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
00604          
00605 
00606           matcheduselist.push_back(true);
00607           matchedhitlist.push_back(*hit);
00608           
00609 
00610 
00611           // Use this hit to fit z(r)
00612           zSlopeFitNumer += -(scr - r) * (z - scz);
00613           zSlopeFitDenom += (scr - r) * (scr - r);
00614             
00615         } // end cut on phi band
00616       } // end cut on electron originating *near* the origin
00617     } // end assign disjoint sets of hits to electrons
00618   } // end loop over matched hits
00619 
00620   // Calculate the linear fit for z(r)
00621   double zVsRSlope;
00622   if (zSlopeFitDenom > 0.) {
00623     zVsRSlope = zSlopeFitNumer / zSlopeFitDenom;
00624   }
00625   else {
00626     // zVsRSlope assumes electron is from origin if there were no stereo hits
00627     zVsRSlope = scz/scr;
00628   }
00629 
00630   //  // Loop over all stereo hits
00631   LogDebug("") << " Loop over stereo hits" << " \n";
00632 
00633   // check if the stereo hit is matched to one of the matched hit
00634   unsigned int numberOfStereoHits = 0;
00635   for (std::vector<const SiStripRecHit2D*>::const_iterator hit = stereoHits.begin();  hit != stereoHits.end();  ++hit) {
00636     assert(hitUsed_.find(*hit) != hitUsed_.end());
00637 
00638     // Calculate the 3-D position of this hit
00639     GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
00640     double r_stereo = sqrt(position.x()*position.x() + position.y()*position.y());
00641     double phi_stereo = unwrapPhi(position.phi() - superclusterIn->position().phi());  // phi is relative to supercluster
00642     //    double z_stereo = position.z();
00643 
00644     // stereo is has a pitch of 100 mrad - so consider both components
00645     double r_stereo_err = sqrt((*hit)->localPositionError().xx()*cos2SiPitchAngle +
00646                                (*hit)->localPositionError().yy()*sin2SiPitchAngle ) ; 
00647 
00648 
00649 
00650     // make sure that the error for this hit is sensible, ie > 1 micron
00651     // otherwise skip this hit
00652     if(r_stereo_err > stereoHitSmallestError ) {
00653       r_stereo_err = sqrt(r_stereo_err*r_stereo_err+stereoErrFudge*stereoErrFudge);
00654  
00655       const SiStripRecHit2D::ClusterRef & stereocluster=(*hit)->cluster();
00656     
00657       bool thisHitIsMatched = false ;
00658 
00659       if (!hitUsed_[*hit]) {
00660  
00661         unsigned int matcheduselist_size = matcheduselist.size();
00662         for (unsigned int i = 0;  i < matcheduselist_size;  i++) {
00663           if (matcheduselist[i]) {
00664             const SiStripRecHit2D::ClusterRef &  mystereocluster = matchedhitlist[i]->stereoHit()->cluster();
00665             if( stereocluster == mystereocluster ) {
00666               thisHitIsMatched = true ;
00667               //    LogDebug("")<< "     This hit is matched " << tracker_p_->idToDet(matchedhitlist[i]->stereoHit()->geographicalId())->surface().toGlobal(matchedhitlist[i]->stereoHit()->localPosition()) << std::endl;
00668               //      break ;
00669             }
00670           } // check if matcheduselist okay 
00671         }// loop over matched hits 
00672       
00673         if(thisHitIsMatched) {
00674           // Use this hit to fit phi(r)
00675           uselist.push_back(true);
00676           rlist.push_back(r_stereo);
00677           philist.push_back(phi_stereo);
00678           w2list.push_back(1./(r_stereo_err/r_stereo)/(r_stereo_err/r_stereo));  // weight**2 == 1./uncertainty**2
00679           typelist.push_back(0);
00680           hitlist.push_back(*hit);
00681         } // thisHitIsMatched
00682       } //  if(!hitUsed)
00683 
00684     } //  end of check on hit position error size 
00685 
00686   } // end loop over stereo hits
00687   
00688   LogDebug("") << " There are " << uselist.size()  << " good hits after stereo loop "  ;
00689  
00690 
00691   // Loop over barrel rphi hits
00692   LogDebug("") << " Looping over barrel rphi hits " ;
00693   unsigned int rphiMatchedCounter = 0 ;
00694   unsigned int rphiUnMatchedCounter = 0 ;
00695   unsigned int numberOfBarrelRphiHits = 0;
00696   for (std::vector<const SiStripRecHit2D*>::const_iterator hit = rphiBarrelHits.begin();  hit != rphiBarrelHits.end();  ++hit) {
00697     assert(hitUsed_.find(*hit) != hitUsed_.end());
00698     // Calculate the 2.5-D position of this hit
00699     GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
00700     double r = sqrt(position.x()*position.x() + position.y()*position.y());
00701     double phi = unwrapPhi(position.phi() - superclusterIn->position().phi());  // phi is relative to supercluster
00702     double z = position.z();
00703     double r_mono_err = sqrt((*hit)->localPositionError().xx()) ;
00704 
00705     // only consider hits with errors that make sense
00706     if( r_mono_err > rphiHitSmallestError) {
00707       // inflate the reported error
00708       r_mono_err=sqrt(r_mono_err*r_mono_err+rphiErrFudge*rphiErrFudge);
00709 
00710       const SiStripRecHit2D::ClusterRef &  monocluster=(*hit)->cluster();
00711     
00712 
00713       if (!hitUsed_[*hit]) {
00714         if( (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB  && 
00715              (TIBDetId((*hit)->geographicalId()).layer()==1 || TIBDetId((*hit)->geographicalId()).layer()==2)) || 
00716             (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB  
00717              && (TOBDetId((*hit)->geographicalId()).layer()==1 || TOBDetId((*hit)->geographicalId()).layer()==2)) ) {
00718           bool thisHitIsMatched = false ;
00719           unsigned int matcheduselist_size = matcheduselist.size();
00720           for (unsigned int i = 0;  i < matcheduselist_size;  i++) {
00721             if (matcheduselist[i]) {
00722               const SiStripRecHit2D::ClusterRef &  mymonocluster = matchedhitlist[i]->monoHit()->cluster();
00723               if( monocluster == mymonocluster ) {
00724                 thisHitIsMatched = true ;
00725               } 
00726             } // check if matcheduselist okay 
00727           }// loop over matched hits 
00728         
00729         
00730           if( thisHitIsMatched ) {
00731             // Use this hit to fit phi(r)
00732             uselist.push_back(true);
00733             rlist.push_back(r);
00734             philist.push_back(phi);
00735             w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r));  // weight**2 == 1./uncertainty**2
00736             typelist.push_back(1);
00737             hitlist.push_back(*hit);
00738             rphiMatchedCounter++;
00739           } // end of matched hit check
00740 
00741         } else {
00742 
00743 
00744           // The expected z position of this hit, according to the z(r) fit
00745           double zFit = zVsRSlope * (r - scr) + scz;
00746         
00747           // Cut on the Z of the strip
00748           // TIB strips are 11 cm long, TOB strips are 19 cm long (can I get these from a function?)
00749           if ((tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TIB  && 
00750                fabs(z - zFit) < 12.)  ||
00751               (tracker_p_->idToDetUnit((*hit)->geographicalId())->type().subDetector() == GeomDetEnumerators::TOB  && 
00752                fabs(z - zFit) < 20.)    ) {
00753           
00754             // Cut a narrow band around the supercluster's projection in phi
00755             if (unwrapPhi((r-scr)*phiVsRSlope - phiBandWidth_) < phi  &&  phi < unwrapPhi((r-scr)*phiVsRSlope + phiBandWidth_)) {
00756             
00757               // Use this hit to fit phi(r)
00758               uselist.push_back(true);
00759               rlist.push_back(r);
00760               philist.push_back(phi);
00761               w2list.push_back(1./(r_mono_err/r)/(r_mono_err/r));  // weight**2 == 1./uncertainty**2
00762               typelist.push_back(1);
00763               hitlist.push_back(*hit);
00764               rphiUnMatchedCounter++;
00765             
00766             } // end cut on phi band
00767           } // end cut on strip z
00768         } // loop over TIB/TOB layer 1,2 
00769       } // end assign disjoint sets of hits to electrons
00770     } // end of check on rphi hit position error size
00771   } // end loop over barrel rphi hits
00772 
00773   LogDebug("") << " There are " << rphiMatchedCounter <<" matched rphi hits"; 
00774   LogDebug("") << " There are " << rphiUnMatchedCounter <<" unmatched rphi hits";
00775   LogDebug("") << " There are " << uselist.size() << " good stereo+rphi hits " ;
00776 
00777 
00778 
00779 
00780 
00781 
00783 
00784   // Loop over endcap zphi hits
00785   LogDebug("") << " Looping over barrel zphi hits " ;
00786 
00787 
00788   unsigned int numberOfEndcapZphiHits = 0;
00789   for (std::vector<const SiStripRecHit2D*>::const_iterator hit = zphiEndcapHits.begin();  
00790        hit != zphiEndcapHits.end();  ++hit) {
00791     assert(hitUsed_.find(*hit) != hitUsed_.end());
00792     if (!hitUsed_[*hit]) {
00793       // Calculate the 2.5-D position of this hit
00794       GlobalPoint position = tracker_p_->idToDet((*hit)->geographicalId())->surface().toGlobal((*hit)->localPosition());
00795       double z = position.z();
00796       double phi = unwrapPhi(position.phi() - superclusterIn->position().phi());  // phi is relative to supercluster
00797       //      double r=sqrt(position.x()*position.x()+position.y()*position.y()) ;
00798 
00799       // The expected r position of this hit, according to the z(r) fit
00800       double rFit = (z - scz)/zVsRSlope + scr;
00801 
00802       // I don't know the r widths of the endcap strips, otherwise I
00803       // would apply a cut on r similar to the rphi z cut
00804 
00805       // Cut a narrow band around the supercluster's projection in phi,
00806       // and be sure the hit isn't in a reflected band (extrapolation of large z differences into negative r)
00807       if (rFit > 0.  &&
00808           unwrapPhi((rFit-scr)*phiVsRSlope - phiBandWidth_) < phi  &&  phi < unwrapPhi((rFit-scr)*phiVsRSlope + phiBandWidth_)) {
00809 
00810         // Use this hit to fit phi(r)
00811         uselist.push_back(true);
00812         rlist.push_back(rFit);
00813         philist.push_back(phi);
00814         w2list.push_back(1./(0.05/rFit)/(0.05/rFit));  // weight**2 == 1./uncertainty**2
00815         typelist.push_back(2);
00816         hitlist.push_back(*hit);
00817 
00818       } // end cut on phi band
00819     } // end assign disjoint sets of hits to electrons
00820   } // end loop over endcap zphi hits
00821  
00822   LogDebug("") << " There are " << uselist.size() << " good stereo+rphi+zphi hits " ;
00824 
00825   std::ostringstream debugstr5;
00826   debugstr5 << " List of hits before uniqification " << " \n" ;
00827   for (unsigned int i = 0;  i < uselist.size();  i++) {
00828     if ( uselist[i] ) {
00829       const SiStripRecHit2D* hit = hitlist[i];
00830       debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
00831                 << " R " << rlist[i] 
00832                 << " Phi " << philist[i]
00833                 << " Weight " << w2list[i] 
00834                 << " PhiPred " << (rlist[i]-scr)*phiVsRSlope  
00835                 << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
00836                 << " \n" ;
00837     }
00838   }
00839   debugstr5 << " \n\n\n" ;
00840   
00841   debugstr5 << " Counting number of unique detectors " << " \n" ;
00842 
00843   debugstr5 << " These are all the detectors with hits " << " \n";
00844   // Loop over hits, and find the best hit for each SiDetUnit - keep only those
00845   // get a list of DetIds in uselist
00846   std::vector<uint32_t> detIdList ;
00847 
00848   for (unsigned int i = 0;  i < uselist.size();  i++) {
00849     if (uselist[i]) {
00850       const SiStripRecHit2D* hit = hitlist[i];
00851       uint32_t detIDUsed = ((hit)->geographicalId()).rawId() ;
00852       debugstr5<< " DetId " << detIDUsed << "\n";
00853       detIdList.push_back(detIDUsed) ;
00854     }
00855   }
00856   debugstr5 << " There are " << detIdList.size() << " hits on detectors \n";
00857   // now sort and then uniq this list of detId
00858   std::sort(detIdList.begin(), detIdList.end());
00859   detIdList.erase(
00860                   std::unique(detIdList.begin(), detIdList.end()), detIdList.end());
00861 
00862   debugstr5 << " There are " << detIdList.size() << " unique detectors \n";
00863 
00864   //now we have a list of unique detectors used
00865 
00866 
00867 
00868   debugstr5 << " Looping over detectors to choose best hit " << " \n";
00869   // Loop over detectors ID and hits to create list of hits on same DetId
00870   for (unsigned int idet = 0 ; idet < detIdList.size() ; idet++ ) {
00871     for (unsigned int i = 0;  i+1 < uselist.size();  i++) {
00872       if (uselist[i]) {
00873         // Get Chi2 of this hit relative to predicted hit
00874         const SiStripRecHit2D* hit1 = hitlist[i];
00875         double r_hit1 = rlist[i];
00876         double phi_hit1 = philist[i];
00877         double w2_hit1 = w2list[i] ;
00878         double phi_pred1 = (r_hit1-scr)*phiVsRSlope ; 
00879         double chi1 = (phi_hit1-phi_pred1)*(phi_hit1-phi_pred1)*w2_hit1;
00880         if(detIdList[idet]== ((hit1)->geographicalId()).rawId()) {
00881           for (unsigned int j = i+1;  j < uselist.size();  j++) {
00882             if (uselist[j]) {
00883               const SiStripRecHit2D* hit2 = hitlist[j];
00884               if(detIdList[idet]== ((hit2)->geographicalId()).rawId()) {
00885                 debugstr5 << " Found 2 hits on same Si Detector " 
00886                           << ((hit2)->geographicalId()).rawId() << "\n";
00887                 // Get Chi2 of this hit relative to predicted hit
00888                 double r_hit2 = rlist[j];
00889                 double phi_hit2 = philist[j];
00890                 double w2_hit2 = w2list[j] ;
00891                 double phi_pred2 = (r_hit2-scr)*phiVsRSlope ; 
00892                 double chi2 = (phi_hit2-phi_pred2)*(phi_hit2-phi_pred2)*w2_hit2;
00893                 debugstr5 << " Chi1 " << chi1 << " Chi2 " << chi2 <<"\n";
00894                 if( chi1< chi2 ){
00895                   uselist[j] = 0;
00896                 }else{
00897                   uselist[i] = 0;
00898                 }
00899 
00900               } // end of Det check
00901             } // end of j- usehit check
00902           } // end of j hit list loop
00903           
00904         } // end of detector check
00905       } // end of uselist check
00906     } // end of i-hit list loop
00907 
00908 
00909   } // end of DetId loop
00910 
00911 
00912   
00913   // now let's through out hits with a predicted chi > chi2HitMax 
00914   for ( unsigned int i = 0;  i < uselist.size();  i++ ) { 
00915     if ( uselist[i] ) { 
00916       const SiStripRecHit2D* hit = hitlist[i];
00917       double localchi2 = (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i] ;
00918       if(localchi2 > chi2HitMax ) {
00919         debugstr5 << " Throwing out "
00920                   <<" DetID " << ((hit)->geographicalId()).rawId()
00921                   << " R " << rlist[i] 
00922                   << " Phi " << philist[i]
00923                   << " Weight " << w2list[i] 
00924                   << " PhiPred " << (rlist[i]-scr)*phiVsRSlope  
00925                   << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
00926                   << " \n" ;
00927         uselist[i]=0 ;
00928       }
00929     }
00930   }
00931 
00932   debugstr5 << " List of hits after uniqification " << " \n" ;
00933   for (unsigned int i = 0;  i < uselist.size();  i++) {
00934     if ( uselist[i] ) {
00935       const SiStripRecHit2D* hit = hitlist[i];
00936       debugstr5 << " DetID " << ((hit)->geographicalId()).rawId()
00937                 << " R " << rlist[i] 
00938                 << " Phi " << philist[i]
00939                 << " Weight " << w2list[i] 
00940                 << " PhiPred " << (rlist[i]-scr)*phiVsRSlope  
00941                 << " Chi2 " << (philist[i]-(rlist[i]-scr)*phiVsRSlope)*(philist[i]-(rlist[i]-scr)*phiVsRSlope)*w2list[i]
00942                 << " \n" ;
00943     }
00944   }
00945   debugstr5 << " \n\n\n" ;
00946 
00947 
00948   // need to check that there are more than 2 hits left here!
00949   unsigned int nHitsLeft =0;
00950   for (unsigned int i = 0;  i < uselist.size();  i++) {
00951     if ( uselist[i] ) {
00952       nHitsLeft++;
00953     }
00954   }
00955   if(nHitsLeft < nHitsLeftMinimum ) {
00956     debugstr5 << " Too few hits "<< nHitsLeft 
00957               << " left - return false " << " \n";
00958     return false ;
00959   }
00960   LogDebug("") << debugstr5.str();
00961 
00963   
00964   // Calculate a linear phi(r) fit and drop hits until the biggest contributor to chi^2 is less than maxNormResid_
00965   bool done = false;
00966   double intercept = 0 ;
00967   double slope = 0 ;
00968   double chi2 = 0;
00969 
00970   std::ostringstream debugstr4;
00971   debugstr4 <<" Calc of phi(r) "<<" \n";
00972 
00973   while (!done) {
00974     // Use an iterative update of <psi>, <r> etc instead in an
00975     // attempt to minize divisions of  large numbers
00976     // The linear fit  psi = slope*r + intercept
00977     //             slope is (<psi*r>-<psi>*<r>) / (<r^2>-<r>^2>)
00978     //             intercept is <psi> - slope*<r>
00979     
00980     double phiBar   = 0.;
00981     double phiBarOld   = 0.;
00982     double rBar  = 0.;
00983     double rBarOld  = 0.;
00984     double r2Bar = 0.;
00985     double r2BarOld = 0.;
00986     double phirBar = 0.;
00987     double phirBarOld = 0.;
00988     double totalWeight = 0.;
00989     double totalWeightOld = 0.; 
00990     unsigned int uselist_size = uselist.size();
00991     for (unsigned int i = 0;  i < uselist_size;  i++) {
00992       if (uselist[i]) {
00993         double r = rlist[i];
00994         double phi = philist[i];
00995         double weight2 = w2list[i];
00996         
00997         totalWeight = totalWeightOld + weight2 ;
00998         
00999         //weight2 is 1/sigma^2. Typically sigma is 100micron pitch
01000         // over root(12) = 30 microns so weight2 is about 10^5-10^6
01001         
01002         double totalWeightRatio = totalWeightOld/totalWeight ;
01003         double localWeightRatio = weight2/totalWeight ;
01004         
01005         phiBar = phiBarOld*totalWeightRatio + phi*localWeightRatio ; 
01006         rBar = rBarOld*totalWeightRatio + r*localWeightRatio ; 
01007         r2Bar= r2BarOld*totalWeightRatio + r*r*localWeightRatio ; 
01008         phirBar = phirBarOld*totalWeightRatio + phi*r*localWeightRatio ;
01009         
01010         totalWeightOld = totalWeight ;
01011         phiBarOld = phiBar ;
01012         rBarOld = rBar ;
01013         r2BarOld = r2Bar ;
01014         phirBarOld = phirBar ;  
01015         
01016         debugstr4 << " totalWeight " << totalWeight 
01017                   << " totalWeightRatio " << totalWeightRatio
01018                   << " localWeightRatio "<< localWeightRatio
01019                   << " phiBar " << phiBar
01020                   << " rBar " << rBar 
01021                   << " r2Bar " << r2Bar
01022                   << " phirBar " << phirBar 
01023                   << " \n ";
01024 
01025 
01026       } // end of use hit loop
01027     } // end of hit loop to calculate a linear fit
01028     slope = (phirBar-phiBar*rBar)/(r2Bar-rBar*rBar);
01029     intercept = phiBar-slope*rBar ;
01030 
01031     debugstr4 << " end of loop slope " << slope 
01032               << " intercept " << intercept << " \n";
01033 
01034     // Calculate chi^2
01035     chi2 = 0.;
01036     double biggest_normresid = -1.;
01037     unsigned int biggest_index = 0;
01038     for (unsigned int i = 0;  i < uselist_size;  i++) {
01039       if (uselist[i]) {
01040         double r = rlist[i];
01041         double phi = philist[i];
01042         double weight2 = w2list[i];
01043 
01044         double normresid = weight2 * (phi - intercept - slope*r)*(phi - intercept - slope*r);
01045         chi2 += normresid;
01046 
01047         if (normresid > biggest_normresid) {
01048           biggest_normresid = normresid;
01049           biggest_index = i;
01050         }
01051       }
01052     } // end loop over hits to calculate chi^2 and find its biggest contributer
01053 
01054     if (biggest_normresid > maxNormResid_) {
01055       debugstr4 << "Dropping hit from fit due to Chi2 " << " \n" ;
01056       const SiStripRecHit2D* hit = hitlist[biggest_index];
01057       debugstr4 << " DetID " << ((hit)->geographicalId()).rawId()
01058                 << " R " << rlist[biggest_index]
01059                 << " Phi " << philist[biggest_index]
01060                 << " Weight " << w2list[biggest_index]
01061                 << " PhiPred " << (rlist[biggest_index]-scr)*phiVsRSlope  
01062                 << " Chi2 " << (philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*(philist[biggest_index]-(rlist[biggest_index]-scr)*phiVsRSlope)*w2list[biggest_index] 
01063                 << " normresid " <<  biggest_normresid
01064                 << " \n\n";
01065       uselist[biggest_index] = false;
01066     }
01067     else {
01068       done = true;
01069     }
01070   } // end loop over trial fits
01071 
01072   debugstr4 <<" Fit " 
01073             << " Intercept  " << intercept
01074             << " slope " << slope 
01075             << " chi2 " << chi2
01076             << " \n" ;
01077 
01078   LogDebug("") <<   debugstr4.str() ;
01079 
01080 
01081   // Now we have intercept, slope, and chi2; uselist to tell us which hits are used, and hitlist for the hits
01082 
01083   // Identify the innermost hit
01084   const SiStripRecHit2D* innerhit = (SiStripRecHit2D*)(0);
01085   double innerhitRadius = -1.;  // meaningless until innerhit is defined
01086 
01087   // Copy hits into an OwnVector, which we put in the TrackCandidate
01088   std::vector<const TrackingRecHit*> outputHits;
01089   // Reference rphi and stereo hits into RefVectors, which we put in the SiStripElectron
01090   edm::RefVector<SiStripRecHit2DCollection> outputRphiHits;
01091   edm::RefVector<SiStripRecHit2DCollection> outputStereoHits;
01092 
01093   typedef edm::Ref<SiStripRecHit2DCollection> SiStripRecHit2DRef;
01094 
01095 
01096   for (unsigned int i = 0;  i < uselist.size();  i++) {
01097     if (uselist[i]) {
01098       double r = rlist[i];
01099       const SiStripRecHit2D* hit = hitlist[i];
01100 
01101       // Keep track of the innermost hit
01102       if (innerhit == (SiStripRecHit2D*)(0)  ||  r < innerhitRadius) {
01103         innerhit = hit;
01104         innerhitRadius = r;
01105       }
01106          
01107       if (typelist[i] == 0) {
01108         numberOfStereoHits++;
01109 
01110         // Copy this hit for the TrajectorySeed
01111         outputHits.push_back(hit);
01112         outputStereoHits.push_back(SiStripRecHit2DRef(*stereoHits_hp_, stereoKey_[hit]));
01113       }
01114       else if (typelist[i] == 1) {
01115         numberOfBarrelRphiHits++;
01116 
01117         // Copy this hit for the TrajectorySeed
01118         outputHits.push_back(hit);
01119         outputRphiHits.push_back(SiStripRecHit2DRef(*rphiHits_hp_, rphiKey_[hit]));
01120       }
01121       else if (typelist[i] == 2) {
01122         numberOfEndcapZphiHits++;
01123 
01124         // Copy this hit for the TrajectorySeed
01125         outputHits.push_back(hit);
01126         outputRphiHits.push_back(SiStripRecHit2DRef(*rphiHits_hp_, rphiKey_[hit]));
01127       }
01128     }
01129   } // end loop over all hits, after having culled the ones with big residuals
01130 
01131   unsigned int totalNumberOfHits = numberOfStereoHits + numberOfBarrelRphiHits + numberOfEndcapZphiHits;
01132   double reducedChi2 = (totalNumberOfHits > 2 ? chi2 / (totalNumberOfHits - 2) : 1e10);
01133 
01134   // Select this candidate if it passes minHits_ and maxReducedChi2_ cuts
01135   if (totalNumberOfHits >= minHits_  &&  reducedChi2 <= maxReducedChi2_) {
01136     // GlobalTrajectoryParameters evaluated at the position of the innerhit
01137     GlobalPoint position = tracker_p_->idToDet(innerhit->geographicalId())->surface().toGlobal(innerhit->localPosition());
01138 
01139     // Use our phi(r) linear fit to correct pT (pT is inversely proportional to slope)
01140     // (By applying a correction instead of going back to first
01141     // principles, any correction to the phiVsRSlope definition
01142     // above will be automatically propagated here.)
01143     double correct_pT = pT * phiVsRSlope / slope;
01144 
01145     // Our phi(r) linear fit returns phi relative to the supercluster phi for a given radius
01146     double phi = intercept + slope*sqrt(position.x()*position.x() + position.y()*position.y()) + superclusterIn->position().phi();
01147 
01148     // Our z(r) linear fit gives us a better measurement of eta/dip angle
01149     double pZ = correct_pT * zVsRSlope;
01150 
01151     // Now we can construct a trajectory momentum out of linear fits to hits
01152     GlobalVector momentum = GlobalVector(correct_pT*cos(phi), correct_pT*sin(phi), pZ);
01153 
01154     if (chargeHypothesis > 0.) {
01155       redchi2_pos_ = chi2 / double(totalNumberOfHits - 2);
01156       position_pos_ = position;
01157       momentum_pos_ = momentum;
01158       innerhit_pos_ = innerhit;
01159       outputHits_pos_ = outputHits;
01160       outputRphiHits_pos_ = outputRphiHits;
01161       outputStereoHits_pos_ = outputStereoHits;
01162       phiVsRSlope_pos_ = phiVsRSlope;
01163       slope_pos_ = slope;
01164       intercept_pos_ = intercept;
01165       chi2_pos_ = chi2;
01166       ndof_pos_ = totalNumberOfHits - 2;
01167       correct_pT_pos_ = correct_pT;
01168       pZ_pos_ = pZ;
01169       zVsRSlope_pos_ = zVsRSlope;
01170       numberOfStereoHits_pos_ = numberOfStereoHits;
01171       numberOfBarrelRphiHits_pos_ = numberOfBarrelRphiHits;
01172       numberOfEndcapZphiHits_pos_ = numberOfEndcapZphiHits;
01173     }
01174     else {
01175       redchi2_neg_ = chi2 / double(totalNumberOfHits - 2);
01176       position_neg_ = position;
01177       momentum_neg_ = momentum;
01178       innerhit_neg_ = innerhit;
01179       outputHits_neg_ = outputHits;
01180       outputRphiHits_neg_ = outputRphiHits;
01181       outputStereoHits_neg_ = outputStereoHits;
01182       phiVsRSlope_neg_ = phiVsRSlope;
01183       slope_neg_ = slope;
01184       intercept_neg_ = intercept;
01185       chi2_neg_ = chi2;
01186       ndof_neg_ = totalNumberOfHits - 2;
01187       correct_pT_neg_ = correct_pT;
01188       pZ_neg_ = pZ;
01189       zVsRSlope_neg_ = zVsRSlope;
01190       numberOfStereoHits_neg_ = numberOfStereoHits;
01191       numberOfBarrelRphiHits_neg_ = numberOfBarrelRphiHits;
01192       numberOfEndcapZphiHits_neg_ = numberOfEndcapZphiHits;
01193     }
01194 
01195     LogDebug("") << " return from projectFindBand with True \n" << std::endl ;
01196     return true;
01197   } // end if this is a good electron candidate
01198 
01199   // Signal for a failed electron candidate
01200   LogDebug("") << " return from projectFindBand with False \n" << std::endl ;
01201   return false;
01202 }
01203 
01204 //
01205 // const member functions
01206 //
01207 
01208 //
01209 // static member functions
01210 //
01211  

Generated on Tue Jun 9 17:43:21 2009 for CMSSW by  doxygen 1.5.4