00001 #include "RecoMuon/MuonIdentification/interface/MuonIdTruthInfo.h"
00002 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
00003 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00004 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00005 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h"
00008 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00009
00010 void MuonIdTruthInfo::truthMatchMuon(const edm::Event& iEvent,
00011 const edm::EventSetup& iSetup,
00012 reco::Muon& aMuon)
00013 {
00014
00015
00016
00017
00018
00019 edm::Handle<edm::SimTrackContainer> simTracks;
00020 iEvent.getByType<edm::SimTrackContainer>(simTracks);
00021 if (! simTracks.isValid() ) {
00022 LogTrace("MuonIdentification") <<"No tracks found";
00023 return;
00024 }
00025
00026
00027 edm::ESHandle<GlobalTrackingGeometry> geometry;
00028 iSetup.get<GlobalTrackingGeometryRecord>().get(geometry);
00029 if ( ! geometry.isValid() )
00030 throw cms::Exception("FatalError") << "Unable to find GlobalTrackingGeometryRecord in event!\n";
00031
00032 float bestMatchChi2 = 9999;
00033 unsigned int bestMatch = 0;
00034 const unsigned int offset = 0;
00035
00036 for( edm::SimTrackContainer::const_iterator simTrk = simTracks->begin();
00037 simTrk != simTracks->end(); simTrk++ )
00038 {
00039 float chi2 = matchChi2(*aMuon.track().get(),*simTrk);
00040 if (chi2>bestMatchChi2) continue;
00041 bestMatchChi2 = chi2;
00042 bestMatch = simTrk->trackId();
00043 }
00044
00045 bestMatch -= offset;
00046
00047 std::vector<reco::MuonChamberMatch>& matches = aMuon.matches();
00048 int numberOfTruthMatchedChambers = 0;
00049
00050
00051 for(std::vector<reco::MuonChamberMatch>::iterator chamberMatch = matches.begin();
00052 chamberMatch != matches.end(); chamberMatch ++)
00053 {
00054 if (chamberMatch->id.det() != DetId::Muon ) {
00055 edm::LogWarning("MuonIdentification") << "Detector id of a muon chamber corresponds to not a muon detector";
00056 continue;
00057 }
00058 reco::MuonSegmentMatch bestSegmentMatch;
00059 double distance = 99999;
00060
00061 if ( chamberMatch->id.subdetId() == MuonSubdetId::DT) {
00062 DTChamberId detId(chamberMatch->id.rawId());
00063
00064 edm::Handle<edm::PSimHitContainer> simHits;
00065 iEvent.getByLabel("g4SimHits", "MuonDTHits", simHits);
00066 if ( simHits.isValid() ) {
00067 for( edm::PSimHitContainer::const_iterator hit = simHits->begin(); hit != simHits->end(); hit++)
00068 if ( hit->trackId() == bestMatch ) checkSimHitForBestMatch(bestSegmentMatch, distance, *hit, detId, geometry );
00069 }else LogTrace("MuonIdentification") <<"No DT simulated hits are found";
00070 }
00071
00072 if ( chamberMatch->id.subdetId() == MuonSubdetId::CSC) {
00073 CSCDetId detId(chamberMatch->id.rawId());
00074
00075 edm::Handle<edm::PSimHitContainer> simHits;
00076 iEvent.getByLabel("g4SimHits", "MuonCSCHits", simHits);
00077 if ( simHits.isValid() ) {
00078 for( edm::PSimHitContainer::const_iterator hit = simHits->begin(); hit != simHits->end(); hit++)
00079 if ( hit->trackId() == bestMatch ) checkSimHitForBestMatch(bestSegmentMatch, distance, *hit, detId, geometry );
00080 }else LogTrace("MuonIdentification") <<"No CSC simulated hits are found";
00081 }
00082 if (distance < 9999) {
00083 chamberMatch->truthMatches.push_back( bestSegmentMatch );
00084 numberOfTruthMatchedChambers++;
00085 LogTrace("MuonIdentification") << "Best truth matched hit:" <<
00086 "\tDetId: " << chamberMatch->id.rawId() << "\n" <<
00087 "\tprojection: ( " << bestSegmentMatch.x << ", " << bestSegmentMatch.y << " )\n";
00088 }
00089 }
00090 LogTrace("MuonIdentification") << "Truth matching summary:\n\tnumber of chambers: " << matches.size() <<
00091 "\n\tnumber of truth matched chambers: " << numberOfTruthMatchedChambers << "\n";
00092 }
00093
00094 void MuonIdTruthInfo::checkSimHitForBestMatch(reco::MuonSegmentMatch& segmentMatch,
00095 double& distance,
00096 const PSimHit& hit,
00097 const DetId& chamberId,
00098 const edm::ESHandle<GlobalTrackingGeometry>& geometry)
00099 {
00100
00101
00102
00103
00104
00105 const GeomDet* chamberGeometry = geometry->idToDet( chamberId );
00106 const GeomDet* simUnitGeometry = geometry->idToDet( DetId(hit.detUnitId()) );
00107
00108 if (chamberGeometry && simUnitGeometry ) {
00109 LocalPoint entryPoint = chamberGeometry->toLocal( simUnitGeometry->toGlobal( hit.entryPoint() ) );
00110 LocalPoint exitPoint = chamberGeometry->toLocal( simUnitGeometry->toGlobal( hit.exitPoint() ) );
00111 LocalVector direction = exitPoint - entryPoint;
00112 if ( fabs(direction.z()) > 0.001) {
00113 LocalPoint projection = entryPoint - direction*(entryPoint.z()/direction.z());
00114 if ( fabs(projection.z()) > 0.001 )
00115 edm::LogWarning("MuonIdentification") << "z coordinate of the hit projection must be zero and it's not!\n";
00116
00117 double new_distance = 99999;
00118 if( entryPoint.z()*exitPoint.z() < -1 )
00119 new_distance = 0;
00120 else {
00121 if ( fabs(entryPoint.z()) < fabs(exitPoint.z()) )
00122 new_distance = fabs(entryPoint.z());
00123 else
00124 new_distance = fabs(exitPoint.z());
00125 }
00126
00127 if (new_distance < distance) {
00128
00129 segmentMatch.x = projection.x();
00130 segmentMatch.y = projection.y();
00131 segmentMatch.xErr = 0;
00132 segmentMatch.yErr = 0;
00133 segmentMatch.dXdZ = direction.x()/direction.z();
00134 segmentMatch.dYdZ = direction.y()/direction.z();
00135 segmentMatch.dXdZErr = 0;
00136 segmentMatch.dYdZErr = 0;
00137 distance = new_distance;
00138 LogTrace("MuonIdentificationVerbose") << "Better truth matched segment found:\n" <<
00139 "\tDetId: " << chamberId.rawId() << "\n" <<
00140 "\tentry point: ( " << entryPoint.x() << ", " << entryPoint.y() << ", " << entryPoint.z() << " )\n" <<
00141 "\texit point: ( " << exitPoint.x() << ", " << exitPoint.y() << ", " << exitPoint.z() << " )\n" <<
00142 "\tprojection: ( " << projection.x() << ", " << projection.y() << ", " << projection.z() << " )\n";
00143 }
00144 }
00145 }else{
00146 if ( ! chamberGeometry ) edm::LogWarning("MuonIdentification") << "Cannot get chamber geomtry for DetId: " << chamberId.rawId();
00147 if ( ! simUnitGeometry ) edm::LogWarning("MuonIdentification") << "Cannot get detector unit geomtry for DetId: " << hit.detUnitId();
00148 }
00149 }
00150
00151 double MuonIdTruthInfo::matchChi2( const reco::Track& recoTrk, const SimTrack& simTrk)
00152 {
00153 double deltaPhi = fabs(recoTrk.phi()-simTrk.momentum().phi());
00154 if (deltaPhi>1.8*3.1416) deltaPhi = 2*3.1416-deltaPhi;
00155 return pow((recoTrk.p()-simTrk.momentum().rho())/simTrk.momentum().rho(),2)+
00156 pow(deltaPhi/(2*3.1416),2)+pow((recoTrk.theta()-simTrk.momentum().theta())/3.1416,2);
00157 }