00001
00010 #include "RecoMuon/CosmicMuonProducer/interface/GlobalCosmicMuonTrajectoryBuilder.h"
00011 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00012 #include "FWCore/Framework/interface/Event.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014
00015 #include "TrackingTools/PatternTools/interface/TrajectoryMeasurement.h"
00016 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00017
00018 #include "DataFormats/TrackReco/interface/Track.h"
00019 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00020 #include "DataFormats/TrackReco/interface/TrackExtraFwd.h"
00021 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00022 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00023 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHitBuilder.h"
00024 #include "TrackingTools/GeomPropagators/interface/StateOnTrackerBound.h"
00025 #include "DataFormats/Math/interface/deltaPhi.h"
00026
00027 using namespace std;
00028 using namespace edm;
00029
00030
00031
00032
00033 GlobalCosmicMuonTrajectoryBuilder::GlobalCosmicMuonTrajectoryBuilder(const edm::ParameterSet& par,
00034 const MuonServiceProxy* service) : theService(service) {
00035 ParameterSet smootherPSet = par.getParameter<ParameterSet>("SmootherParameters");
00036 theSmoother = new CosmicMuonSmoother(smootherPSet,theService);
00037
00038 ParameterSet trackMatcherPSet = par.getParameter<ParameterSet>("GlobalMuonTrackMatcher");
00039 theTrackMatcher = new GlobalMuonTrackMatcher(trackMatcherPSet,theService);
00040
00041 theTkTrackLabel = par.getParameter<InputTag>("TkTrackCollectionLabel");
00042 theTrackerRecHitBuilderName = par.getParameter<string>("TrackerRecHitBuilder");
00043 theMuonRecHitBuilderName = par.getParameter<string>("MuonRecHitBuilder");
00044 thePropagatorName = par.getParameter<string>("Propagator");
00045 category_ = "Muon|RecoMuon|CosmicMuon|GlobalCosmicMuonTrajectoryBuilder";
00046
00047 }
00048
00049
00050
00051
00052
00053 GlobalCosmicMuonTrajectoryBuilder::~GlobalCosmicMuonTrajectoryBuilder() {
00054
00055 if (theSmoother) delete theSmoother;
00056
00057 }
00058
00059
00060
00061
00062 void GlobalCosmicMuonTrajectoryBuilder::setEvent(const edm::Event& event) {
00063 event.getByLabel(theTkTrackLabel,theTrackerTracks);
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 theService->eventSetup().get<TransientRecHitRecord>().get(theTrackerRecHitBuilderName,theTrackerRecHitBuilder);
00078 theService->eventSetup().get<TransientRecHitRecord>().get(theMuonRecHitBuilderName,theMuonRecHitBuilder);
00079
00080 }
00081
00082
00083
00084
00085 MuonCandidate::CandidateContainer GlobalCosmicMuonTrajectoryBuilder::trajectories(const TrackCand& muCand) {
00086
00087 MuonCandidate::CandidateContainer result;
00088
00089 if (!theTrackerTracks.isValid()) {
00090 LogTrace(category_)<< "Tracker Track collection is invalid!!!";
00091 return result;
00092 }
00093
00094 LogTrace(category_) <<"Found "<<theTrackerTracks->size()<<" tracker Tracks";
00095 if (theTrackerTracks->empty()) return result;
00096
00097 vector<TrackCand> matched = match(muCand, theTrackerTracks);
00098
00099 LogTrace(category_) <<"TrackMatcher found " << matched.size() << "tracker tracks matched";
00100
00101 if ( matched.empty()) return result;
00102 reco::TrackRef tkTrack = matched.front().second;
00103
00104 if ( tkTrack.isNull() ) return result;
00105 reco::TrackRef muTrack = muCand.second;
00106
00107 ConstRecHitContainer muRecHits;
00108
00109 if (muCand.first == 0 || !muCand.first->isValid()) {
00110 muRecHits = getTransientRecHits(*muTrack);
00111 } else {
00112 muRecHits = muCand.first->recHits();
00113 }
00114
00115 LogTrace(category_)<<"mu RecHits: "<<muRecHits.size();
00116
00117 ConstRecHitContainer tkRecHits = getTransientRecHits(*tkTrack);
00118
00119
00120
00121
00122
00123
00124
00125 ConstRecHitContainer hits;
00126 LogTrace(category_)<<"tk RecHits: "<<tkRecHits.size();
00127
00128
00129
00130
00131 sortHits(hits, muRecHits, tkRecHits);
00132
00133
00134
00135
00136
00137 TrajectoryStateTransform tsTrans;
00138
00139 TrajectoryStateOnSurface muonState1 = tsTrans.innerStateOnSurface(*muTrack, *theService->trackingGeometry(), &*theService->magneticField());
00140 TrajectoryStateOnSurface tkState1 = tsTrans.innerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00141
00142 TrajectoryStateOnSurface muonState2 = tsTrans.outerStateOnSurface(*muTrack, *theService->trackingGeometry(), &*theService->magneticField());
00143 TrajectoryStateOnSurface tkState2 = tsTrans.outerStateOnSurface(*tkTrack, *theService->trackingGeometry(), &*theService->magneticField());
00144
00145 TrajectoryStateOnSurface firstState1 =
00146 ( muonState1.globalPosition().y() > tkState1.globalPosition().y() )? muonState1 : tkState1;
00147 TrajectoryStateOnSurface firstState2 =
00148 ( muonState2.globalPosition().y() > tkState2.globalPosition().y() )? muonState2 : tkState2;
00149
00150 TrajectoryStateOnSurface firstState =
00151 ( firstState1.globalPosition().y() > firstState2.globalPosition().y() )? firstState1 : firstState2;
00152
00153 if (!firstState.isValid()) return result;
00154
00155 LogTrace(category_) <<"firstTSOS pos: "<<firstState.globalPosition()<<"mom: "<<firstState.globalMomentum();
00156
00157
00158
00159 TrajectorySeed seed;
00160 vector<Trajectory> refitted = theSmoother->trajectories(seed,hits,firstState);
00161
00162 if ( refitted.empty() ) {
00163 LogTrace(category_)<<"smoothing trajectories fail";
00164
00165 refitted = theSmoother->fit(seed,hits,firstState);
00166 }
00167
00168 if (refitted.empty()) {
00169 LogTrace(category_)<<"refit fail";
00170 return result;
00171 }
00172
00173 Trajectory* myTraj = new Trajectory(refitted.front());
00174
00175 const std::vector<TrajectoryMeasurement>& mytms = myTraj->measurements();
00176 LogTrace(category_)<<"measurements in final trajectory "<<mytms.size();
00177 LogTrace(category_) <<"Orignally there are "<<tkTrack->found()<<" tk rhs and "<<muTrack->found()<<" mu rhs.";
00178
00179 if ( mytms.size() <= tkTrack->found() ) {
00180 LogTrace(category_)<<"insufficient measurements. skip... ";
00181 return result;
00182 }
00183
00184 MuonCandidate* myCand = new MuonCandidate(myTraj,muTrack,tkTrack);
00185 result.push_back(myCand);
00186 LogTrace(category_)<<"final global cosmic muon: ";
00187 for (std::vector<TrajectoryMeasurement>::const_iterator itm = mytms.begin();
00188 itm != mytms.end(); ++itm ) {
00189 LogTrace(category_)<<"updated pos "<<itm->updatedState().globalPosition()
00190 <<"mom "<<itm->updatedState().globalMomentum();
00191 }
00192 return result;
00193 }
00194
00195 void GlobalCosmicMuonTrajectoryBuilder::sortHits(ConstRecHitContainer& hits, ConstRecHitContainer& muonHits, ConstRecHitContainer& tkHits) {
00196
00197 if ( tkHits.empty() ) {
00198 LogTrace(category_) << "No valid tracker hits";
00199 return;
00200 }
00201 if ( muonHits.empty() ) {
00202 LogTrace(category_) << "No valid muon hits";
00203 return;
00204 }
00205
00206 ConstRecHitContainer::const_iterator frontTkHit = tkHits.begin();
00207 ConstRecHitContainer::const_iterator backTkHit = tkHits.end() - 1;
00208 while ( !(*frontTkHit)->isValid() && frontTkHit != backTkHit) {frontTkHit++;}
00209 while ( !(*backTkHit)->isValid() && backTkHit != frontTkHit) {backTkHit--;}
00210
00211 ConstRecHitContainer::const_iterator frontMuHit = muonHits.begin();
00212 ConstRecHitContainer::const_iterator backMuHit = muonHits.end() - 1;
00213 while ( !(*frontMuHit)->isValid() && frontMuHit != backMuHit) {frontMuHit++;}
00214 while ( !(*backMuHit)->isValid() && backMuHit != frontMuHit) {backMuHit--;}
00215
00216 if ( frontTkHit == backTkHit ) {
00217 LogTrace(category_) << "No valid tracker hits";
00218 return;
00219 }
00220 if ( frontMuHit == backMuHit ) {
00221 LogTrace(category_) << "No valid muon hits";
00222 return;
00223 }
00224
00225 GlobalPoint frontTkPos = (*frontTkHit)->globalPosition();
00226 GlobalPoint backTkPos = (*backTkHit)->globalPosition();
00227
00228 GlobalPoint frontMuPos = (*frontMuHit)->globalPosition();
00229 GlobalPoint backMuPos = (*backMuHit)->globalPosition();
00230
00231
00232 if ( frontTkPos.y() < backTkPos.y() ) {
00233 reverse(tkHits.begin(), tkHits.end());
00234 }
00235
00236 if ( frontMuPos.y() < backMuPos.y() ) {
00237 reverse(muonHits.begin(), muonHits.end());
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 ConstRecHitContainer::iterator middlepoint = muonHits.begin();
00250 bool insertInMiddle = false;
00251
00252 for (ConstRecHitContainer::iterator ihit = muonHits.begin();
00253 ihit != muonHits.end() - 1; ihit++ ) {
00254 GlobalPoint ipos = (*ihit)->globalPosition();
00255 GlobalPoint nextpos = (*(ihit+1))->globalPosition();
00256 GlobalPoint middle((ipos.x()+nextpos.x())/2, (ipos.y()+nextpos.y())/2, (ipos.z()+nextpos.z())/2);
00257 LogTrace(category_)<<"ipos "<<ipos<<"nextpos"<<nextpos<<" middle "<<middle<<endl;
00258 if ( (middle.perp() < ipos.perp()) && (middle.perp() < nextpos.perp() ) ) {
00259 LogTrace(category_)<<"found middlepoint"<<endl;
00260 middlepoint = ihit;
00261 insertInMiddle = true;
00262 break;
00263 }
00264 }
00265
00266
00267 if ( insertInMiddle ) {
00268 GlobalPoint jointpointpos = (*middlepoint)->globalPosition();
00269 LogTrace(category_)<<"jointpoint "<<jointpointpos<<endl;
00270 if ((frontTkPos - jointpointpos).mag() > (backTkPos - jointpointpos).mag() ) {
00271 reverse(tkHits.begin(), tkHits.end());
00272 }
00273 muonHits.insert(middlepoint+1, tkHits.begin(), tkHits.end());
00274 hits = muonHits;
00275 } else {
00276 if ( frontTkPos.y() < frontMuPos.y() ) {
00277 LogTrace(category_)<<"insert at the end "<<frontTkPos << frontMuPos <<endl;
00278
00279 hits = muonHits;
00280 hits.insert(hits.end(), tkHits.begin(), tkHits.end());
00281 } else {
00282 LogTrace(category_)<<"insert at the beginning "<<frontTkPos << frontMuPos <<endl;
00283 hits = tkHits;
00284 hits.insert(hits.end(), muonHits.begin(), muonHits.end());
00285 }
00286 }
00287 }
00288
00289
00290 TransientTrackingRecHit::ConstRecHitContainer
00291 GlobalCosmicMuonTrajectoryBuilder::getTransientRecHits(const reco::Track& track) const {
00292
00293 TransientTrackingRecHit::ConstRecHitContainer result;
00294
00295 TrajectoryStateTransform tsTrans;
00296
00297 TrajectoryStateOnSurface currTsos = tsTrans.innerStateOnSurface(track, *theService->trackingGeometry(), &*theService->magneticField());
00298 for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
00299 if((*hit)->isValid()) {
00300 DetId recoid = (*hit)->geographicalId();
00301 if ( recoid.det() == DetId::Tracker ) {
00302 TransientTrackingRecHit::RecHitPointer ttrhit = theTrackerRecHitBuilder->build(&**hit);
00303 TrajectoryStateOnSurface predTsos = theService->propagator(thePropagatorName)->propagate(currTsos, theService->trackingGeometry()->idToDet(recoid)->surface());
00304 LogTrace(category_)<<"predtsos "<<predTsos.isValid();
00305 if ( predTsos.isValid() ) {
00306 currTsos = predTsos;
00307 TransientTrackingRecHit::RecHitPointer preciseHit = ttrhit->clone(currTsos);
00308 result.push_back(preciseHit);
00309 }
00310 } else if ( recoid.det() == DetId::Muon ) {
00311 result.push_back(theMuonRecHitBuilder->build(&**hit));
00312 }
00313 }
00314 }
00315 return result;
00316 }
00317
00318 std::vector<GlobalCosmicMuonTrajectoryBuilder::TrackCand> GlobalCosmicMuonTrajectoryBuilder::match(const TrackCand& mu, const edm::Handle<reco::TrackCollection>& tktracks) {
00319
00320 std::vector<TrackCand> result;
00321
00322 if ( fabs(mu.second->dxy()) > 200 ) return result;
00323
00324
00325 TrajectoryStateTransform tsTrans;
00326 TrajectoryStateOnSurface innerTsos = tsTrans.innerStateOnSurface(*(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
00327
00328 TrajectoryStateOnSurface outerTsos = tsTrans.outerStateOnSurface(*(mu.second), *theService->trackingGeometry(), &*theService->magneticField());
00329
00330 StateOnTrackerBound toTrackerBound(propagator());
00331
00332 TrajectoryStateOnSurface tkState = toTrackerBound(innerTsos);
00333 if ( !tkState.isValid() ) tkState = toTrackerBound(outerTsos);
00334 if ( !tkState.isValid() ) return result;
00335
00336
00337 vector<TrackCand> tkTrackCands;
00338 for(reco::TrackCollection::size_type i=0; i<theTrackerTracks->size(); ++i){
00339 reco::TrackRef tkTrack(theTrackerTracks,i);
00340 TrackCand tkCand = TrackCand(0,tkTrack);
00341 tkTrackCands.push_back(tkCand);
00342 LogTrace(category_) << "chisq is " << theTrackMatcher->match(mu,tkCand,0,0);
00343 LogTrace(category_) << "d is " << theTrackMatcher->match(mu,tkCand,1,0);
00344 LogTrace(category_) << "r_pos is " << theTrackMatcher->match(mu,tkCand,2,0);
00345 }
00346
00347
00348 if (tkTrackCands.size() <= 1 ) {
00349 return tkTrackCands;
00350 }
00351
00352
00353
00354
00355 GlobalPoint innerPos = innerTsos.globalPosition();
00356 GlobalPoint outerPos = outerTsos.globalPosition();
00357
00358 if ( ( innerPos.basicVector().dot( innerTsos.globalMomentum().basicVector() ) *
00359 outerPos.basicVector().dot(outerTsos.globalMomentum().basicVector() ) > 0 ) ) {
00360
00361 GlobalPoint geoInnerPos = (innerPos.mag() < outerPos.mag()) ? innerPos : outerPos;
00362 LogTrace(category_) <<"geoInnerPos Mu "<<geoInnerPos<<endl;
00363
00364
00365
00366
00367 for(vector<TrackCand>::const_iterator itkCand = tkTrackCands.begin(); itkCand != tkTrackCands.end(); ++itkCand) {
00368
00369 reco::TrackRef tkTrack = itkCand->second;
00370
00371 GlobalPoint tkInnerPos(tkTrack->innerPosition().x(), tkTrack->innerPosition().y(), tkTrack->innerPosition().z());
00372 GlobalPoint tkOuterPos(tkTrack->outerPosition().x(), tkTrack->outerPosition().y(), tkTrack->outerPosition().z());
00373 LogTrace(category_) <<"tkTrack "<<tkInnerPos<<" "<<tkOuterPos<<endl;
00374
00375 float closetDistance11 = (geoInnerPos - tkInnerPos).mag() ;
00376 float closetDistance12 = (geoInnerPos - tkOuterPos).mag() ;
00377 float closetDistance1 = (closetDistance11 < closetDistance12) ? closetDistance11 : closetDistance12;
00378 LogTrace(category_) <<"closetDistance1 "<<closetDistance1<<endl;
00379
00380 if (true || !isTraversing(*tkTrack) ) {
00381 bool keep = true;
00382 for(vector<TrackCand>::const_iterator itkCand2 = tkTrackCands.begin(); itkCand2 != tkTrackCands.end(); ++itkCand2) {
00383 if (itkCand2 == itkCand ) continue;
00384 reco::TrackRef tkTrack2 = itkCand2->second;
00385
00386 GlobalPoint tkInnerPos2(tkTrack2->innerPosition().x(), tkTrack2->innerPosition().y(), tkTrack2->innerPosition().z());
00387 GlobalPoint tkOuterPos2(tkTrack2->outerPosition().x(), tkTrack2->outerPosition().y(), tkTrack2->outerPosition().z());
00388 LogTrace(category_) <<"tkTrack2 "<< tkInnerPos2 <<" "<<tkOuterPos2 <<endl;
00389
00390 float farthestDistance21 = (geoInnerPos - tkInnerPos2).mag() ;
00391 float farthestDistance22 = (geoInnerPos - tkOuterPos2).mag() ;
00392 float farthestDistance2 = (farthestDistance21 > farthestDistance22) ? farthestDistance21 : farthestDistance22;
00393 LogTrace(category_) <<"farthestDistance2 "<<farthestDistance2<<endl;
00394
00395 if (closetDistance1 > farthestDistance2 - 1e-3) {
00396 keep = false;
00397 break;
00398 }
00399 }
00400 if (keep) result.push_back(*itkCand);
00401 else LogTrace(category_) <<"The Track is on different hemisphere"<<endl;
00402 } else {
00403 result.push_back(*itkCand);
00404 }
00405 }
00406 if ( result.empty() ) {
00407
00408 result = tkTrackCands;
00409 }
00410 } else {
00411 result = tkTrackCands;
00412 }
00413
00414
00415 vector<TrackCand> matched_trackerTracks = theTrackMatcher->match(mu, result);
00416
00417 LogTrace(category_) <<"TrackMatcher found " << matched_trackerTracks.size() << "tracker tracks matched";
00418
00419
00420 if( matched_trackerTracks.size() < 2 ) {
00421 return matched_trackerTracks;
00422 } else {
00423
00424
00425
00426 result.clear();
00427 TrackCand bestMatch;
00428
00429 double quality = 1e6;
00430 double max_quality = 1e6;
00431 for( vector<TrackCand>::const_iterator iter = matched_trackerTracks.begin(); iter != matched_trackerTracks.end(); iter++) {
00432 quality = theTrackMatcher->match(mu,*iter, 1, 0);
00433 LogTrace(category_) <<" quality of tracker track is " << quality;
00434 if( quality < max_quality ) {
00435 max_quality=quality;
00436 bestMatch = (*iter);
00437 }
00438 }
00439 LogTrace(category_) <<" Picked tracker track with quality " << max_quality;
00440 result.push_back(bestMatch);
00441 return result;
00442 }
00443 }
00444
00445
00446 bool GlobalCosmicMuonTrajectoryBuilder::isTraversing(const reco::Track& track) const {
00447
00448 trackingRecHit_iterator firstValid;
00449 for (trackingRecHit_iterator hit = track.recHitsBegin(); hit != track.recHitsEnd(); ++hit) {
00450 if((*hit)->isValid()) {
00451 firstValid = hit;
00452 break;
00453 }
00454 }
00455
00456 trackingRecHit_iterator lastValid;
00457 for (trackingRecHit_iterator hit = track.recHitsEnd() - 1; hit != track.recHitsBegin() - 1; --hit) {
00458 if((*hit)->isValid()) {
00459 lastValid = hit;
00460 break;
00461 }
00462 }
00463
00464 GlobalPoint posFirst = theService->trackingGeometry()->idToDet((*firstValid)->geographicalId())->position();
00465
00466 GlobalPoint posLast = theService->trackingGeometry()->idToDet((*lastValid)->geographicalId() )->position();
00467
00468 GlobalPoint middle((posFirst.x()+posLast.x())/2, (posFirst.y()+posLast.y())/2, (posFirst.z()+posLast.z())/2);
00469
00470 if ( (middle.mag() < posFirst.mag()) && (middle.mag() < posLast.mag() ) ) {
00471 return true;
00472 }
00473 return false;
00474
00475 }