CMS 3D CMS Logo

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