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