CMS 3D CMS Logo

GlobalMuonTrackMatcher.cc

Go to the documentation of this file.
00001 
00014 #include "RecoMuon/GlobalTrackingTools/interface/GlobalMuonTrackMatcher.h"
00015 
00016 //---------------
00017 // C++ Headers --
00018 //---------------
00019 
00020 
00021 //-------------------------------
00022 // Collaborating Class Headers --
00023 //-------------------------------
00024 
00025 #include "FWCore/ServiceRegistry/interface/Service.h"
00026 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00028 
00029 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00030 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00031 #include "TrackingTools/GeomPropagators/interface/StateOnTrackerBound.h"
00032 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00033 #include "TrackingTools/PatternTools/interface/Trajectory.h"
00034 
00035 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00036 
00037 #include "DataFormats/TrackReco/interface/Track.h"
00038 #include "DataFormats/TrajectoryState/interface/LocalTrajectoryParameters.h"
00039 
00040 #include "DataFormats/GeometrySurface/interface/TangentPlane.h"
00041 #include "DataFormats/Math/interface/deltaR.h"
00042 
00043 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00044 
00045 using namespace std;
00046 using namespace reco;
00047 
00048 //
00049 // constructor
00050 //
00051 GlobalMuonTrackMatcher::GlobalMuonTrackMatcher(const edm::ParameterSet& par, 
00052                                                const MuonServiceProxy* service) : 
00053    theService(service) {
00054   
00055   theMaxChi2 = par.getParameter<double>("Chi2Cut");
00056   theDeltaD = par.getParameter<double>("DeltaDCut");
00057   theDeltaR = par.getParameter<double>("DeltaRCut");
00058   theMinP = par.getParameter<double>("MinP");
00059   theMinPt = par.getParameter<double>("MinPt");
00060  
00061   theOutPropagatorName = par.getParameter<string>("Propagator");
00062 
00063 }
00064 
00065 
00066 //
00067 // destructor
00068 //
00069 GlobalMuonTrackMatcher::~GlobalMuonTrackMatcher() {
00070 
00071 }
00072 
00073 
00074 //
00075 // check if two tracks are compatible
00076 //
00077 bool 
00078 GlobalMuonTrackMatcher::match(const TrackCand& sta,
00079                               const TrackCand& track) const {
00080 
00081   std::pair<TrajectoryStateOnSurface, TrajectoryStateOnSurface> tsosPair
00082       = convertToTSOSMuHit(sta,track);
00083 
00084   double chi2 = match_Chi2(tsosPair.first,tsosPair.second);
00085   if ( chi2 > 0. && chi2 < theMaxChi2 ) return true;
00086 
00087   double distance = match_D(tsosPair.first,tsosPair.second);
00088   if ( distance > 0. && distance < theDeltaD ) return true;
00089 
00090   double deltaR = match_Rpos(tsosPair.first,tsosPair.second);
00091   if ( deltaR > 0. && deltaR < theDeltaR ) return true;
00092 
00093   return false;
00094 
00095 }
00096 
00097 
00098 //
00099 // check if two tracks are compatible
00100 //
00101 double
00102 GlobalMuonTrackMatcher::match(const TrackCand& sta,
00103                               const TrackCand& track,
00104                               int matchOption,
00105                               int surfaceOption) const {
00106 
00107   std::pair<TrajectoryStateOnSurface, TrajectoryStateOnSurface> tsosPair;
00108   if ( surfaceOption == 0 ) tsosPair = convertToTSOSMuHit(sta,track);
00109   if ( surfaceOption == 1 ) tsosPair = convertToTSOSTkHit(sta,track);
00110   if ( surfaceOption != 0 && surfaceOption != 1 ) return -1.0;
00111 
00112   if ( matchOption == 0 ) {
00113     // chi^2
00114     return  match_Chi2(tsosPair.first,tsosPair.second);
00115   }
00116   else if ( matchOption == 1 ) {
00117     // distance
00118     return match_d(tsosPair.first,tsosPair.second);
00119   }
00120   else if ( matchOption == 2 ) {
00121     // deltaR
00122     return match_Rpos(tsosPair.first,tsosPair.second);
00123   }
00124   else {
00125     return -1.0;
00126   }
00127 
00128 }
00129 
00130 
00131 //
00132 // choose the track from a TrackCollection which best
00133 // matches a given standalone muon track
00134 //
00135 std::vector<GlobalMuonTrackMatcher::TrackCand>::const_iterator 
00136 GlobalMuonTrackMatcher::matchOne(const TrackCand& sta,
00137                                  const std::vector<TrackCand>& tracks) const {
00138 
00139   if ( tracks.empty() ) return tracks.end();
00140 
00141   double minChi2 = 1000.0;
00142   vector<TrackCand>::const_iterator result = tracks.end();
00143   for (vector<TrackCand>::const_iterator is = tracks.begin(); is != tracks.end(); ++is) {
00144     // propagate to common surface
00145     std::pair<TrajectoryStateOnSurface, TrajectoryStateOnSurface> tsosPair
00146       = convertToTSOSMuHit(sta,*is);
00147 
00148     // calculate chi^2 of local track parameters
00149     double chi2 = match_Chi2(tsosPair.first,tsosPair.second);
00150     if ( chi2 > 0. && chi2 <= minChi2 ) {
00151       minChi2 = chi2;
00152       result = is;
00153     }
00154 
00155   }
00156 
00157   return result;
00158 
00159 }
00160 
00161 
00162 //
00163 // choose a vector of tracks from a TrackCollection that are compatible
00164 // with a given standalone track. The order of checks for compatability are
00165 // * matching-chi2 less than MaxChi2
00166 // * gloabl position of TSOS on tracker bound
00167 // * global momentum direction
00168 //
00169 vector<GlobalMuonTrackMatcher::TrackCand>
00170 GlobalMuonTrackMatcher::match(const TrackCand& sta, 
00171                               const vector<TrackCand>& tracks) const {
00172   
00173   const string category = "GlobalMuonTrackMatcher";
00174 
00175   vector<TrackCand> result;
00176   
00177   if ( tracks.empty() ) return result;
00178 
00179   typedef std::pair<TrackCand, TrajectoryStateOnSurface> TrackCandWithTSOS;
00180   vector<TrackCandWithTSOS> cands;
00181 
00182   TrajectoryStateOnSurface muonTSOS;
00183 
00184   for (vector<TrackCand>::const_iterator is = tracks.begin(); is != tracks.end(); ++is) {
00185 
00186     // propagate to common surface
00187     std::pair<TrajectoryStateOnSurface, TrajectoryStateOnSurface> tsosPair
00188       = convertToTSOSMuHit(sta,*is);
00189 
00190     if(tsosPair.first.isValid()) muonTSOS = tsosPair.first;
00191     cands.push_back(TrackCandWithTSOS(*is,tsosPair.second));
00192   }
00193 
00194   // try various matching criteria
00195   for (vector<TrackCandWithTSOS>::const_iterator is = cands.begin(); is != cands.end(); ++is) {
00196 
00197     double chi2 = match_Chi2(muonTSOS,(*is).second);
00198  
00199     if ( chi2 > 0. && chi2 < theMaxChi2 ) {
00200       result.push_back((*is).first);
00201     }
00202   }
00203  
00204   if ( result.empty() ) {
00205     LogDebug(category) << "MatchChi2 returned 0 results";
00206     for (vector<TrackCandWithTSOS>::const_iterator is = cands.begin(); is != cands.end(); ++is) {
00207 
00208       double distance = match_d(muonTSOS,(*is).second);
00209       double Distance = match_D(muonTSOS,(*is).second);
00210       double distanceWithError = match_dist(muonTSOS,(*is).second);
00211 
00212       LogDebug(category) << "match_d - match_D = " << distance << " - " << Distance << " = " << distance - Distance << " match_dist: " << distanceWithError;
00213 
00214       if ( distance > 0. && distance < theDeltaD ) {
00215         result.push_back((*is).first);
00216       }
00217     }
00218   }
00219   
00220   if ( result.empty() ) {
00221     LogDebug(category) << "MatchD returned 0 results";
00222     for (vector<TrackCandWithTSOS>::const_iterator is = cands.begin(); is != cands.end(); ++is) {
00223 
00224       double deltaR = match_Rpos(muonTSOS,(*is).second);
00225 
00226       if ( deltaR > 0. && deltaR < theDeltaR ) {
00227         result.push_back((*is).first);
00228       }
00229     }
00230   }
00231  
00232   if ( result.empty() ) {
00233     LogDebug(category) << "MatchPos returned 0 results";
00234     TrackCand returnVal;
00235     double dR = 10.0;
00236     for (vector<TrackCandWithTSOS>::const_iterator is = cands.begin(); is != cands.end(); ++is) {
00237       double tmpR = match_R_IP(sta,(*is).first);
00238       if (tmpR < dR) {
00239         dR = tmpR;
00240         returnVal = (*is).first;
00241       }
00242     }
00243     result.push_back(returnVal);
00244   }
00245 
00246   return result;
00247  
00248 }
00249 
00250 
00251 //
00252 // propagate the two track candidates to the tracker bound surface
00253 //
00254 std::pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>
00255 GlobalMuonTrackMatcher::convertToTSOSTk(const TrackCand& staCand,
00256                                         const TrackCand& tkCand) const {
00257   
00258   const string category = "GlobalMuonTrackMatcher";
00259 
00260   TrajectoryStateOnSurface empty; 
00261   
00262   TransientTrack muTT(*staCand.second,&*theService->magneticField(),theService->trackingGeometry());
00263   TrajectoryStateOnSurface impactMuTSOS = muTT.impactPointState();
00264 
00265   TrajectoryStateOnSurface outerTkTsos;
00266   if (tkCand.second.isNonnull()) {
00267     // make sure the tracker track has enough momentum to reach the muon chambers
00268     if ( !(tkCand.second->p() < theMinP || tkCand.second->pt() < theMinPt )) {
00269       TrajectoryStateTransform tsTransform;
00270       outerTkTsos = tsTransform.outerStateOnSurface(*tkCand.second,*theService->trackingGeometry(),&*theService->magneticField());
00271     }
00272   } else {
00273     const GlobalVector& mom = tkCand.first->firstMeasurement().updatedState().globalMomentum();
00274     if ( !(mom.mag() < theMinP || mom.perp() < theMinPt)) {
00275       outerTkTsos = tkCand.first->lastMeasurement().updatedState();
00276     }
00277   }
00278   
00279   if ( !impactMuTSOS.isValid() || !outerTkTsos.isValid() ) return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty,empty);
00280   
00281   // define StateOnTrackerBound object
00282   StateOnTrackerBound fromInside(&*theService->propagator(theOutPropagatorName));
00283   
00284   // extrapolate to outer tracker surface
00285   TrajectoryStateOnSurface tkTsosFromMu = fromInside(impactMuTSOS);
00286   TrajectoryStateOnSurface tkTsosFromTk = fromInside(outerTkTsos);
00287 
00288   if ( !samePlane(tkTsosFromMu,tkTsosFromTk) ) {
00289     // propagate tracker track to same surface as muon
00290     bool same1, same2;
00291     TrajectoryStateOnSurface newTkTsosFromTk, newTkTsosFromMu;
00292     if ( tkTsosFromMu.isValid() ) newTkTsosFromTk = theService->propagator(theOutPropagatorName)->propagate(outerTkTsos,tkTsosFromMu.surface());
00293     same1 = samePlane(newTkTsosFromTk,tkTsosFromMu);
00294     LogDebug(category) << "Propagating to same tracker surface (Mu):" << same1;
00295     if ( !same1 ) {
00296       if ( tkTsosFromTk.isValid() ) newTkTsosFromMu = theService->propagator(theOutPropagatorName)->propagate(impactMuTSOS,tkTsosFromTk.surface());
00297       same2 = samePlane(newTkTsosFromMu,tkTsosFromTk);
00298       LogDebug(category) << "Propagating to same tracker surface (Tk):" << same2;
00299     }
00300     if (same1) tkTsosFromTk = newTkTsosFromTk;
00301     else if (same2) tkTsosFromMu = newTkTsosFromMu;
00302     else  {
00303       LogDebug(category) << "Could not propagate Muon and Tracker track to the same tracker bound!";
00304       return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty, empty);
00305     }
00306   }
00307  
00308   return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(tkTsosFromMu, tkTsosFromTk);
00309 
00310 }
00311 
00312 
00313 //
00314 // propagate the two track candidates to the surface of the innermost muon hit
00315 //
00316 std::pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>
00317 GlobalMuonTrackMatcher::convertToTSOSMuHit(const TrackCand& staCand,
00318                                            const TrackCand& tkCand) const {
00319   
00320   const string category = "GlobalMuonTrackMatcher";
00321 
00322   TrajectoryStateOnSurface empty; 
00323 
00324   TransientTrack muTT(*staCand.second,&*theService->magneticField(),theService->trackingGeometry());
00325   TrajectoryStateOnSurface innerMuTSOS = muTT.innermostMeasurementState();
00326 
00327   TrajectoryStateOnSurface outerTkTsos;
00328   if ( tkCand.second.isNonnull() ) {
00329     // make sure the tracker track has enough momentum to reach the muon chambers
00330     if ( !(tkCand.second->p() < theMinP || tkCand.second->pt() < theMinPt ) ) {
00331       TrajectoryStateTransform tsTransform;
00332       outerTkTsos = tsTransform.outerStateOnSurface(*tkCand.second,*theService->trackingGeometry(),&*theService->magneticField());
00333     }
00334   } else {
00335     const GlobalVector& mom = tkCand.first->lastMeasurement().updatedState().globalMomentum();
00336     if  ( !(mom.mag() < theMinP || mom.perp() < theMinPt) ) {
00337       outerTkTsos = tkCand.first->lastMeasurement().updatedState();
00338     }
00339   }
00340 
00341   if ( !innerMuTSOS.isValid() || !outerTkTsos.isValid() ) {
00342     LogDebug(category) << "A TSOS validity problem! MuTSOS " << innerMuTSOS.isValid() << " TkTSOS " << outerTkTsos.isValid();
00343     return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty,empty);
00344   }
00345   
00346   const Surface& refSurface = innerMuTSOS.surface();
00347   TrajectoryStateOnSurface tkAtMu = theService->propagator(theOutPropagatorName)->propagate(*outerTkTsos.freeState(),refSurface);
00348   
00349   if ( !tkAtMu.isValid() ) {
00350     LogDebug(category) << "Could not propagate Muon and Tracker track to the same muon hit surface!";
00351     return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty,empty);    
00352   }
00353   
00354   return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(innerMuTSOS, tkAtMu);
00355 
00356 }
00357 
00358 
00359 //
00360 // propagate the two track candidates to the surface of the outermost tracker hit
00361 //
00362 std::pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>
00363 GlobalMuonTrackMatcher::convertToTSOSTkHit(const TrackCand& staCand,
00364                                            const TrackCand& tkCand) const {
00365   
00366   const string category = "GlobalMuonTrackMatcher";
00367 
00368   TrajectoryStateOnSurface empty; 
00369 
00370   TransientTrack muTT(*staCand.second,&*theService->magneticField(),theService->trackingGeometry());
00371   TrajectoryStateOnSurface impactMuTSOS = muTT.impactPointState();
00372 
00373   TrajectoryStateOnSurface outerTkTsos;
00374   if ( tkCand.second.isNonnull() ) {
00375     // make sure the tracker track has enough momentum to reach the muon chambers
00376     if ( !(tkCand.second->p() < theMinP || tkCand.second->pt() < theMinPt )) {
00377       TrajectoryStateTransform tsTransform;
00378       outerTkTsos = tsTransform.outerStateOnSurface(*tkCand.second,*theService->trackingGeometry(),&*theService->magneticField());
00379     }
00380   } else {
00381     const GlobalVector& mom = tkCand.first->lastMeasurement().updatedState().globalMomentum();
00382     if (!(mom.mag() < theMinP || mom.perp() < theMinPt)) {
00383       outerTkTsos = tkCand.first->lastMeasurement().updatedState();
00384     }
00385   }
00386 
00387   if ( !impactMuTSOS.isValid() || !outerTkTsos.isValid() ) {
00388     LogDebug(category) << "A TSOS validity problem! MuTSOS " << impactMuTSOS.isValid() << " TkTSOS " << outerTkTsos.isValid();
00389     return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty,empty);
00390   }
00391 
00392   const Surface& refSurface = outerTkTsos.surface();
00393   TrajectoryStateOnSurface muAtTk = theService->propagator(theOutPropagatorName)->propagate(*impactMuTSOS.freeState(),refSurface);
00394   
00395   if ( !muAtTk.isValid() ) {
00396     LogDebug(category) << "Could not propagate Muon and Tracker track to the same tracker hit surface!";
00397     return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(empty,empty);    
00398   }
00399 
00400   return pair<TrajectoryStateOnSurface,TrajectoryStateOnSurface>(muAtTk, outerTkTsos);
00401 
00402 }
00403 
00404 
00405 //
00406 //
00407 //
00408 bool
00409 GlobalMuonTrackMatcher::samePlane(const TrajectoryStateOnSurface& tsos1,
00410                                   const TrajectoryStateOnSurface& tsos2) const {
00411 
00412   if ( !tsos1.isValid() || !tsos2.isValid() ) return false;
00413 
00414   if ( abs(match_D(tsos1,tsos2) - match_d(tsos1,tsos2)) > 0.1 ) return false;
00415 
00416   const float maxtilt = 0.999;
00417   const float maxdist = 0.01; // in cm
00418 
00419   ReferenceCountingPointer<TangentPlane> p1(tsos1.surface().tangentPlane(tsos1.localPosition()));
00420   ReferenceCountingPointer<TangentPlane> p2(tsos2.surface().tangentPlane(tsos2.localPosition()));
00421 
00422   bool returnValue = ( (fabs(p1->normalVector().dot(p2->normalVector())) > maxtilt) || (fabs((p1->toLocal(p2->position())).z()) < maxdist) ) ? true : false;
00423 
00424   return returnValue; 
00425  
00426 }
00427 
00428 
00429 //
00430 // calculate Chi^2 of two trajectory states
00431 //
00432 double 
00433 GlobalMuonTrackMatcher::match_Chi2(const TrajectoryStateOnSurface& tsos1, 
00434                                    const TrajectoryStateOnSurface& tsos2) const {
00435   
00436   const string category = "GlobalMuonTrackMatcher";
00437   LogDebug(category) << "match_Chi2 sanity check: " << tsos1.isValid() << " " << tsos2.isValid();
00438   if ( !tsos1.isValid() || !tsos2.isValid() ) return -1.;
00439   
00440   AlgebraicVector5 v(tsos1.localParameters().vector() - tsos2.localParameters().vector());
00441   AlgebraicSymMatrix55 m(tsos1.localError().matrix() + tsos2.localError().matrix());
00442   
00443   LogDebug(category) << "vector v " << v;
00444 
00445   bool ierr = !m.Invert();
00446  
00447   if ( ierr ) { 
00448     edm::LogInfo(category) << "Error inverting covariance matrix";
00449     return -1;
00450   }
00451  
00452   double est = ROOT::Math::Similarity(v,m);
00453  
00454   LogDebug(category) << "Chi2 " << est;
00455 
00456   return est;
00457 
00458 }
00459 
00460 
00461 //
00462 // calculate Delta_R of two track candidates at the IP
00463 //
00464 double
00465 GlobalMuonTrackMatcher::match_R_IP(const TrackCand& staCand, 
00466                                    const TrackCand& tkCand) const {
00467 
00468   double dR = 99.0;
00469   if (tkCand.second.isNonnull()) {
00470     dR = (deltaR<double>(staCand.second->eta(),staCand.second->phi(),
00471                          tkCand.second->eta(),tkCand.second->phi()));
00472   } else {
00473     dR = (deltaR<double>(staCand.second->eta(),staCand.second->phi(),
00474                          tkCand.first->firstMeasurement().updatedState().globalMomentum().eta(),
00475                          tkCand.first->firstMeasurement().updatedState().globalMomentum().phi()));
00476   }
00477 
00478   return dR;
00479 
00480 }
00481 
00482 
00483 //
00484 // calculate Delta_R of two trajectory states
00485 //
00486 double
00487 GlobalMuonTrackMatcher::match_Rmom(const TrajectoryStateOnSurface& sta, 
00488                                    const TrajectoryStateOnSurface& tk) const {
00489 
00490   if( !sta.isValid() || !tk.isValid() ) return -1;
00491   return (deltaR<double>(sta.globalMomentum().eta(),sta.globalMomentum().phi(),
00492                          tk.globalMomentum().eta(),tk.globalMomentum().phi()));
00493 
00494 }
00495 
00496 
00497 //
00498 // calculate Delta_R of two trajectory states
00499 //
00500 double
00501 GlobalMuonTrackMatcher::match_Rpos(const TrajectoryStateOnSurface& sta, 
00502                                    const TrajectoryStateOnSurface& tk) const {
00503 
00504   if ( !sta.isValid() || !tk.isValid() ) return -1;
00505   return (deltaR<double>(sta.globalPosition().eta(),sta.globalPosition().phi(),
00506                          tk.globalPosition().eta(),tk.globalPosition().phi()));
00507 
00508 }
00509 
00510 
00511 //
00512 // calculate the distance in global position of two trajectory states
00513 //
00514 double
00515 GlobalMuonTrackMatcher::match_D(const TrajectoryStateOnSurface& sta, 
00516                                 const TrajectoryStateOnSurface& tk) const {
00517 
00518   if ( !sta.isValid() || !tk.isValid() ) return -1;
00519   return (sta.globalPosition() - tk.globalPosition()).mag();
00520 
00521 }
00522 
00523 
00524 //
00525 // calculate the distance in local position of two trajectory states
00526 //
00527 double
00528 GlobalMuonTrackMatcher::match_d(const TrajectoryStateOnSurface& sta, 
00529                                 const TrajectoryStateOnSurface& tk) const {
00530 
00531   if ( !sta.isValid() || !tk.isValid() ) return -1;
00532   return (sta.localPosition() - tk.localPosition()).mag();
00533 
00534 }
00535 
00536 
00537 //
00538 // calculate the chi2 of the distance in local position of two 
00539 // trajectory states including local errors
00540 //
00541 double
00542 GlobalMuonTrackMatcher::match_dist(const TrajectoryStateOnSurface& sta, 
00543                                    const TrajectoryStateOnSurface& tk) const {
00544   
00545   const string category = "GlobalMuonTrackMatcher";
00546   
00547   if ( !sta.isValid() || !tk.isValid() ) return -1;
00548   
00549   AlgebraicMatrix22 m;
00550   m(0,0) = tk.localError().positionError().xx() + sta.localError().positionError().xx();
00551   m(1,0) = m(0,1) = tk.localError().positionError().xy() + sta.localError().positionError().xy();
00552   m(1,1) = tk.localError().positionError().yy() + sta.localError().positionError().yy();
00553   AlgebraicVector2 v;
00554   v[0] = tk.localDirection().x() - sta.localDirection().x();
00555   v[1] = tk.localDirection().y() - sta.localDirection().y();
00556   
00557   if ( !m.Invert() ) {
00558     LogDebug(category) << "Error inverting local matrix ";
00559     return -1;
00560   }
00561   
00562   return ROOT::Math::Similarity(v,m);
00563 
00564 }

Generated on Tue Jun 9 17:44:15 2009 for CMSSW by  doxygen 1.5.4