CMS 3D CMS Logo

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