00001
00014 #include "RecoMuon/GlobalTrackingTools/interface/GlobalMuonTrackMatcher.h"
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00068
00069 GlobalMuonTrackMatcher::~GlobalMuonTrackMatcher() {
00070
00071 }
00072
00073
00074
00075
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
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
00114 return match_Chi2(tsosPair.first,tsosPair.second);
00115 }
00116 else if ( matchOption == 1 ) {
00117
00118 return match_d(tsosPair.first,tsosPair.second);
00119 }
00120 else if ( matchOption == 2 ) {
00121
00122 return match_Rpos(tsosPair.first,tsosPair.second);
00123 }
00124 else {
00125 return -1.0;
00126 }
00127
00128 }
00129
00130
00131
00132
00133
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
00145 std::pair<TrajectoryStateOnSurface, TrajectoryStateOnSurface> tsosPair
00146 = convertToTSOSMuHit(sta,*is);
00147
00148
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
00164
00165
00166
00167
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
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
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
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
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
00282 StateOnTrackerBound fromInside(&*theService->propagator(theOutPropagatorName));
00283
00284
00285 TrajectoryStateOnSurface tkTsosFromMu = fromInside(impactMuTSOS);
00286 TrajectoryStateOnSurface tkTsosFromTk = fromInside(outerTkTsos);
00287
00288 if ( !samePlane(tkTsosFromMu,tkTsosFromTk) ) {
00289
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
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
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
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
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;
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
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
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
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
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
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
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
00539
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 }