From d679ecfea7818ad8a1559d16609daba2a6adc080 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Tue, 27 Jun 2017 15:38:37 +0200 Subject: [PATCH 01/24] Add best matched TP, shared hit fractions to track, number of reco hits for TP Number of reco hits for TP as implemented here is not interesting. In general the can be many clusters for a given SimHit, while my purpose was to filter out those SimHits that are not reconstructed. I guess this is the time to incorporate TrackerHitAssociator. --- .../RecoTrack/plugins/TrackingNtuple.cc | 88 ++++++++++++++++--- .../python/plotting/ntuplePrintersDiff.py | 2 +- .../RecoTrack/scripts/printTrackingNtuple.py | 4 +- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 5377cd76caad7..3af1e14ee0e60 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -351,6 +351,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { typedef TrackingParticleRefKeyToIndex TrackingVertexRefKeyToIndex; typedef std::pair SimHitFullKey; typedef std::map SimHitRefKeyToIndex; + typedef TrackingParticleRefKeyToIndex TrackingParticleRefKeyToCount; enum class HitType { Pixel = 0, @@ -449,9 +450,11 @@ class TrackingNtuple : public edm::one::EDAnalyzer { void fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, + const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const TrackerTopology& tTopo, const std::set& hitProductIds, @@ -473,7 +476,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList + const std::vector& tpHitList, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount ); void fillTrackingParticlesForSeeds(const TrackingParticleRefVector& tpCollection, @@ -884,6 +888,9 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_seedIdx ; std::vector trk_vtxIdx; std::vector trk_isTrue; + std::vector trk_bestSimTrkIdx; + std::vector trk_bestSimTrkShareFrac; + std::vector trk_bestSimTrkShareFracSimDenom; std::vector > trk_shareFrac; // second index runs through matched TrackingParticles std::vector > trk_simTrkIdx; // second index runs through matched TrackingParticles std::vector > trk_hitIdx; // second index runs through hits @@ -910,12 +917,16 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector sim_pca_dxy ; std::vector sim_pca_dz ; std::vector sim_q ; + // numbers of sim hits/layers std::vector sim_nValid ; std::vector sim_nPixel ; std::vector sim_nStrip ; std::vector sim_nLay; std::vector sim_nPixelLay; std::vector sim_n3DLay ; + // number of reco hits + std::vector sim_nRecoValid; + // links to other objects std::vector > sim_trkIdx; // second index runs through matched tracks std::vector > sim_shareFrac; // second index runs through matched tracks std::vector > sim_seedIdx; // second index runs through matched seeds @@ -1257,10 +1268,13 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeTrackingParticles_) { t->Branch("trk_shareFrac", &trk_shareFrac); t->Branch("trk_simTrkIdx", &trk_simTrkIdx ); + t->Branch("trk_bestSimTrkIdx", &trk_bestSimTrkIdx); } else { t->Branch("trk_isTrue", &trk_isTrue); } + t->Branch("trk_bestSimTrkShareFrac", &trk_bestSimTrkShareFrac); + t->Branch("trk_bestSimTrkShareFracSimDenom", &trk_bestSimTrkShareFracSimDenom); if(includeAllHits_) { t->Branch("trk_hitIdx" , &trk_hitIdx); t->Branch("trk_hitType", &trk_hitType); @@ -1292,6 +1306,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("sim_nLay" , &sim_nLay ); t->Branch("sim_nPixelLay", &sim_nPixelLay); t->Branch("sim_n3DLay" , &sim_n3DLay ); + t->Branch("sim_nRecoValid", &sim_nRecoValid); t->Branch("sim_trkIdx" , &sim_trkIdx ); t->Branch("sim_shareFrac", &sim_shareFrac); if(includeSeeds_) { @@ -1570,6 +1585,9 @@ void TrackingNtuple::clearVariables() { trk_seedIdx .clear(); trk_vtxIdx .clear(); trk_isTrue .clear(); + trk_bestSimTrkIdx.clear(); + trk_bestSimTrkShareFrac.clear(); + trk_bestSimTrkShareFracSimDenom.clear(); trk_shareFrac.clear(); trk_simTrkIdx.clear(); trk_hitIdx .clear(); @@ -1600,6 +1618,7 @@ void TrackingNtuple::clearVariables() { sim_nLay .clear(); sim_nPixelLay.clear(); sim_n3DLay .clear(); + sim_nRecoValid.clear(); sim_trkIdx .clear(); sim_seedIdx .clear(); sim_shareFrac.clear(); @@ -1855,6 +1874,12 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle simHitsTPAssoc; iEvent.getByToken(simHitTPMapToken_, simHitsTPAssoc); + // TP -> cluster count + TrackingParticleRefKeyToCount tpKeyToClusterCount; + for(const auto& clusterTP: clusterToTPMap) { + tpKeyToClusterCount[clusterTP.second.key()] += 1; + } + // SimHit key -> index mapping SimHitRefKeyToIndex simHitRefKeyToIndex; @@ -1951,12 +1976,12 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle vertices; iEvent.getByToken(vertexToken_, vertices); - fillTracks(trackRefs, tpCollection, tpKeyToIndex, bs, *vertices, associatorByHits, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); + fillTracks(trackRefs, tpCollection, tpKeyToIndex, tpKeyToClusterCount, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); //tracking particles //sort association maps with simHits std::sort( tpHitList.begin(), tpHitList.end(), tpHitIndexListLessSort ); - fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList); + fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList, tpKeyToClusterCount); // vertices fillVertices(*vertices, trackRefs); @@ -2724,9 +2749,11 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, + const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const TrackerTopology& tTopo, const std::set& hitProductIds, @@ -2743,6 +2770,17 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, for(size_t iTrack = 0; iTrackcharge(); + float pt = itTrack->pt(); + float eta = itTrack->eta(); + const double lambda = itTrack->lambda(); + float chi2 = itTrack->normalizedChi2(); + float ndof = itTrack->ndof(); + float phi = itTrack->phi(); + int nHits = itTrack->numberOfValidHits(); + const reco::HitPattern& hp = itTrack->hitPattern(); + + // Standard track-TP matching int nSimHits = 0; bool isSimMatched = false; std::vector sharedFraction; @@ -2758,15 +2796,32 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, tpIdx.push_back( tpKeyToIndex.at( tpQuality.first.key() ) ); } } - int charge = itTrack->charge(); - float pt = itTrack->pt(); - float eta = itTrack->eta(); - const double lambda = itTrack->lambda(); - float chi2 = itTrack->normalizedChi2(); - float ndof = itTrack->ndof(); - float phi = itTrack->phi(); - int nHits = itTrack->numberOfValidHits(); - const reco::HitPattern& hp = itTrack->hitPattern(); + + // Search for a best-matching TrackingParticle for a track + std::unordered_map count; + for(auto iHit = itTrack->recHitsBegin(), iEnd=itTrack->recHitsEnd(); iHit != iEnd; ++iHit) { + const TrackingRecHit& hit = **iHit; + if(hit.isValid()) { + auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); + for(auto ip=range.first; ip != range.second; ++ip) { + count[ip->second.key()] += 1; + } + } + } + int bestKey = -1; + int bestCount = 2; // require >= 3 hits for the best match + for(auto& keyCount: count) { + if(keyCount.second > bestCount) { + bestKey = keyCount.first; + bestCount = keyCount.second; + } + } + float bestShareFrac = 0; + float bestShareFracSimDenom = 0; + if(bestKey >= 0) { + bestShareFrac = static_cast(bestCount)/static_cast(nHits); + bestShareFracSimDenom = static_cast(bestCount)/static_cast(tpKeyToClusterCount.at(bestKey)); + } float chi2_1Dmod = chi2; int count1dhits = 0; @@ -2857,10 +2912,13 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, if(includeTrackingParticles_) { trk_simTrkIdx.push_back(tpIdx); trk_shareFrac.push_back(sharedFraction); + trk_bestSimTrkIdx.push_back(bestKey >= 0 ? tpKeyToIndex.at(bestKey) : -1); } else { trk_isTrue.push_back(!tpIdx.empty()); } + trk_bestSimTrkShareFrac.push_back(bestShareFrac); + trk_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); LogTrace("TrackingNtuple") << "Track #" << itTrack.key() << " with q=" << charge << ", pT=" << pt << " GeV, eta: " << eta << ", phi: " << phi << ", chi2=" << chi2 @@ -2947,7 +3005,8 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList + const std::vector& tpHitList, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount ) { edm::ESHandle parametersDefinerH; iSetup.get().get(parametersDefinerName_, parametersDefinerH); @@ -3074,6 +3133,9 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: sim_nPixelLay.push_back( nSimPixelLayers ); sim_n3DLay .push_back( nSimPixelLayers+nSimStripMonoAndStereoLayers ); + auto found = tpKeyToClusterCount.find(tp.key()); + sim_nRecoValid.push_back(found != cend(tpKeyToClusterCount) ? found->second : 0); + sim_simHitIdx.push_back(hitIdx); } } diff --git a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py index 466163b1e7a55..259d698395e14 100644 --- a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py +++ b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py @@ -1067,7 +1067,7 @@ def _printTP(self, tp): fromB = " from B hadron" return [ self._prefix+"TP %d pdgId %d%s%s ev:bx %d:%d pT %f eta %f phi %f" % (tp.index(), tp.pdgId(), genIds, fromB, tp.event(), tp.bunchCrossing(), tp.pt(), tp.eta(), tp.phi()), - self._prefix+" pixel hits %d strip hits %d dxy %f dz %f" % (tp.nPixel(), tp.nStrip(), tp.pca_dxy(), tp.pca_dz()) + self._prefix+" pixel hits %d strip hits %d tracker hits %d dxy %f dz %f" % (tp.nPixel(), tp.nStrip(), tp.nTrackerHits(), tp.pca_dxy(), tp.pca_dz()) ] diff --git a/Validation/RecoTrack/scripts/printTrackingNtuple.py b/Validation/RecoTrack/scripts/printTrackingNtuple.py index a11bbc27055d8..a5603dde6b5e9 100755 --- a/Validation/RecoTrack/scripts/printTrackingNtuple.py +++ b/Validation/RecoTrack/scripts/printTrackingNtuple.py @@ -77,7 +77,7 @@ def main(opts): printTrack(t) if hasSeeds: print "Pixel hit %d seeds" % opts.pixelHit - for t in hit.seeds(): + for s in hit.seeds(): printSeed(s) if opts.stripHit is not None: @@ -87,7 +87,7 @@ def main(opts): printTrack(t) if hasSeeds: print "Strip hit %d seeds" % opts.stripHit - for t in hit.seeds(): + for s in hit.seeds(): printSeed(s) From 6e00544f696e7071a6111233b60a0feacf7c0879 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 28 Jun 2017 10:40:18 +0200 Subject: [PATCH 02/24] Record all matching SimHits for a cluster instead of the first one --- .../RecoTrack/plugins/TrackingNtuple.cc | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 3af1e14ee0e60..88e3f3ad05ace 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -2056,9 +2056,8 @@ TrackingNtuple::SimHitData TrackingNtuple::matchCluster(const OmniClusterRef& cl //SimHit is dummy: for simHitTPAssociationListGreater sorting only the TP is needed auto range = std::equal_range(simHitsTPAssoc.begin(), simHitsTPAssoc.end(), simHitTPpairWithDummyTP, SimHitTPAssociationProducer::simHitTPAssociationListGreater); - int simHitKey = -1; + bool foundSimHit = false; bool foundElectron = false; - edm::ProductID simHitID; for(auto ip = range.first; ip != range.second; ++ip) { TrackPSimHitRef TPhit = ip->second; DetId dId = DetId(TPhit->detUnitId()); @@ -2069,12 +2068,31 @@ TrackingNtuple::SimHitData TrackingNtuple::matchCluster(const OmniClusterRef& cl continue; } - simHitKey = TPhit.key(); - simHitID = TPhit.id(); - break; + foundSimHit = true; + auto simHitKey = TPhit.key(); + auto simHitID = TPhit.id(); + + auto simHitIndex = simHitRefKeyToIndex.at(std::make_pair(simHitKey, simHitID)); + ret.matchingSimHit.push_back(simHitIndex); + + double chargeFraction = 0.; + for(const SimTrack& simtrk: trackingParticle->g4Tracks()) { + auto found = simTrackIdToChargeFraction.find(simtrk.trackId()); + if(found != simTrackIdToChargeFraction.end()) { + chargeFraction += found->second; + } + } + ret.chargeFraction.push_back(chargeFraction); + + // only for debug prints + ret.bunchCrossing.push_back(bx); + ret.event.push_back(event); + + simhit_hitIdx[simHitIndex].push_back(clusterKey); + simhit_hitType[simHitIndex].push_back(static_cast(hitType)); } } - if(simHitKey < 0) { + if(!foundSimHit) { // In case we didn't find a simhit because of filtered-out // electron SimHit, just ignore the missing SimHit. if(foundElectron) @@ -2093,24 +2111,6 @@ TrackingNtuple::SimHitData TrackingNtuple::matchCluster(const OmniClusterRef& cl } throw ex; } - auto simHitIndex = simHitRefKeyToIndex.at(std::make_pair(simHitKey, simHitID)); - ret.matchingSimHit.push_back(simHitIndex); - - double chargeFraction = 0.; - for(const SimTrack& simtrk: trackingParticle->g4Tracks()) { - auto found = simTrackIdToChargeFraction.find(simtrk.trackId()); - if(found != simTrackIdToChargeFraction.end()) { - chargeFraction += found->second; - } - } - ret.chargeFraction.push_back(chargeFraction); - - // only for debug prints - ret.bunchCrossing.push_back(bx); - ret.event.push_back(event); - - simhit_hitIdx[simHitIndex].push_back(clusterKey); - simhit_hitType[simHitIndex].push_back(static_cast(hitType)); } } From b81ee9564edeebc285e05dafc331f0cf614e2864 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 29 Jun 2017 15:14:25 +0200 Subject: [PATCH 03/24] Save TP::numberOfTrackerHits() and use that for 'SimDenom' I'm giving up on calculation of sensible "TP hits matched to clusters". TP SimHits need to be filtered (to ignore e.g. delta rays), and they are not generally available without running MixingModule in playback mode, which is something I'd prefer to not to introduce for e.g. trackingOnly workflows (since it's much easier to run pileup samples without the playback mode). --- .../RecoTrack/plugins/TrackingNtuple.cc | 82 +++++++++---------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 88e3f3ad05ace..c89e997be7b2a 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -325,6 +325,30 @@ namespace { return simTrackIdToAdc; } + std::pair findBestMatchingTrackingParticle(const reco::Track& track, + const ClusterTPAssociation& clusterToTPMap) { + std::unordered_map count; + for(auto iHit = track.recHitsBegin(), iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { + const TrackingRecHit& hit = **iHit; + if(hit.isValid()) { + auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); + for(auto ip=range.first; ip != range.second; ++ip) { + count[ip->second.key()] += 1; + } + } + } + + int bestKey = -1; + int bestCount = 2; // require >= 3 hits for the best match + for(auto& keyCount: count) { + if(keyCount.second > bestCount) { + bestKey = keyCount.first; + bestCount = keyCount.second; + } + } + + return std::make_pair(bestKey, bestKey >= 0 ? bestCount : 0); + } } // @@ -351,7 +375,6 @@ class TrackingNtuple : public edm::one::EDAnalyzer { typedef TrackingParticleRefKeyToIndex TrackingVertexRefKeyToIndex; typedef std::pair SimHitFullKey; typedef std::map SimHitRefKeyToIndex; - typedef TrackingParticleRefKeyToIndex TrackingParticleRefKeyToCount; enum class HitType { Pixel = 0, @@ -450,7 +473,6 @@ class TrackingNtuple : public edm::one::EDAnalyzer { void fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, - const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, @@ -476,8 +498,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList, - const TrackingParticleRefKeyToCount& tpKeyToClusterCount + const std::vector& tpHitList ); void fillTrackingParticlesForSeeds(const TrackingParticleRefVector& tpCollection, @@ -924,8 +945,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector sim_nLay; std::vector sim_nPixelLay; std::vector sim_n3DLay ; - // number of reco hits - std::vector sim_nRecoValid; + // number of sim hits as calculated in TrackingTruthAccumulator + std::vector sim_nTrackerHits; // links to other objects std::vector > sim_trkIdx; // second index runs through matched tracks std::vector > sim_shareFrac; // second index runs through matched tracks @@ -1306,7 +1327,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("sim_nLay" , &sim_nLay ); t->Branch("sim_nPixelLay", &sim_nPixelLay); t->Branch("sim_n3DLay" , &sim_n3DLay ); - t->Branch("sim_nRecoValid", &sim_nRecoValid); + t->Branch("sim_nTrackerHits", &sim_nTrackerHits); t->Branch("sim_trkIdx" , &sim_trkIdx ); t->Branch("sim_shareFrac", &sim_shareFrac); if(includeSeeds_) { @@ -1618,7 +1639,7 @@ void TrackingNtuple::clearVariables() { sim_nLay .clear(); sim_nPixelLay.clear(); sim_n3DLay .clear(); - sim_nRecoValid.clear(); + sim_nTrackerHits.clear(); sim_trkIdx .clear(); sim_seedIdx .clear(); sim_shareFrac.clear(); @@ -1874,12 +1895,6 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle simHitsTPAssoc; iEvent.getByToken(simHitTPMapToken_, simHitsTPAssoc); - // TP -> cluster count - TrackingParticleRefKeyToCount tpKeyToClusterCount; - for(const auto& clusterTP: clusterToTPMap) { - tpKeyToClusterCount[clusterTP.second.key()] += 1; - } - // SimHit key -> index mapping SimHitRefKeyToIndex simHitRefKeyToIndex; @@ -1976,12 +1991,12 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle vertices; iEvent.getByToken(vertexToken_, vertices); - fillTracks(trackRefs, tpCollection, tpKeyToIndex, tpKeyToClusterCount, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); + fillTracks(trackRefs, tpCollection, tpKeyToIndex, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); //tracking particles //sort association maps with simHits std::sort( tpHitList.begin(), tpHitList.end(), tpHitIndexListLessSort ); - fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList, tpKeyToClusterCount); + fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList); // vertices fillVertices(*vertices, trackRefs); @@ -2749,7 +2764,6 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, - const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, @@ -2798,29 +2812,11 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } // Search for a best-matching TrackingParticle for a track - std::unordered_map count; - for(auto iHit = itTrack->recHitsBegin(), iEnd=itTrack->recHitsEnd(); iHit != iEnd; ++iHit) { - const TrackingRecHit& hit = **iHit; - if(hit.isValid()) { - auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); - for(auto ip=range.first; ip != range.second; ++ip) { - count[ip->second.key()] += 1; - } - } - } - int bestKey = -1; - int bestCount = 2; // require >= 3 hits for the best match - for(auto& keyCount: count) { - if(keyCount.second > bestCount) { - bestKey = keyCount.first; - bestCount = keyCount.second; - } - } - float bestShareFrac = 0; + const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap); + const float bestShareFrac = static_cast(bestKeyCount.second)/static_cast(nHits); float bestShareFracSimDenom = 0; - if(bestKey >= 0) { - bestShareFrac = static_cast(bestCount)/static_cast(nHits); - bestShareFracSimDenom = static_cast(bestCount)/static_cast(tpKeyToClusterCount.at(bestKey)); + if(bestKeyCount.first >= 0) { + bestShareFracSimDenom = static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()); } float chi2_1Dmod = chi2; @@ -2912,7 +2908,7 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, if(includeTrackingParticles_) { trk_simTrkIdx.push_back(tpIdx); trk_shareFrac.push_back(sharedFraction); - trk_bestSimTrkIdx.push_back(bestKey >= 0 ? tpKeyToIndex.at(bestKey) : -1); + trk_bestSimTrkIdx.push_back(bestKeyCount.first >= 0 ? tpKeyToIndex.at(bestKeyCount.first) : -1); } else { trk_isTrue.push_back(!tpIdx.empty()); @@ -3005,8 +3001,7 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList, - const TrackingParticleRefKeyToCount& tpKeyToClusterCount + const std::vector& tpHitList ) { edm::ESHandle parametersDefinerH; iSetup.get().get(parametersDefinerName_, parametersDefinerH); @@ -3133,8 +3128,7 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: sim_nPixelLay.push_back( nSimPixelLayers ); sim_n3DLay .push_back( nSimPixelLayers+nSimStripMonoAndStereoLayers ); - auto found = tpKeyToClusterCount.find(tp.key()); - sim_nRecoValid.push_back(found != cend(tpKeyToClusterCount) ? found->second : 0); + sim_nTrackerHits.push_back(tp->numberOfTrackerHits()); sim_simHitIdx.push_back(hitIdx); } From 980eccdc5ffa322db5a82e0018dc010177a200d1 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 29 Jun 2017 16:09:33 +0200 Subject: [PATCH 04/24] Add best TP match also to seeds --- .../RecoTrack/plugins/TrackingNtuple.cc | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index c89e997be7b2a..9a2708914ac22 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -463,6 +463,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const TrackingParticleRefKeyToIndex& tpKeyToIndex, const reco::BeamSpot& bs, const reco::TrackToTrackingParticleAssociator& associatorByHits, + const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const MagneticField *theMF, const std::vector >& monoStereoClusterList, @@ -1103,6 +1104,9 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector see_nCands; std::vector see_trkIdx; std::vector see_isTrue; + std::vector see_bestSimTrkIdx; + std::vector see_bestSimTrkShareFrac; + std::vector see_bestSimTrkShareFracSimDenom; std::vector > see_shareFrac; // second index runs through matched TrackingParticles std::vector > see_simTrkIdx; // second index runs through matched TrackingParticles std::vector > see_hitIdx; // second index runs through hits @@ -1490,10 +1494,13 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeTrackingParticles_) { t->Branch("see_shareFrac", &see_shareFrac); t->Branch("see_simTrkIdx", &see_simTrkIdx ); + t->Branch("see_bestSimTrkIdx", &see_bestSimTrkIdx); } else { t->Branch("see_isTrue", &see_isTrue); } + t->Branch("see_bestSimTrkShareFrac", &see_bestSimTrkShareFrac); + t->Branch("see_bestSimTrkShareFracSimDenom", &see_bestSimTrkShareFracSimDenom); if(includeAllHits_) { t->Branch("see_hitIdx" , &see_hitIdx ); t->Branch("see_hitType", &see_hitType ); @@ -1777,10 +1784,11 @@ void TrackingNtuple::clearVariables() { see_stopReason.clear(); see_nCands .clear(); see_trkIdx .clear(); - if(includeTrackingParticles_) { - see_shareFrac.clear(); - see_simTrkIdx.clear(); - } + see_bestSimTrkIdx.clear(); + see_bestSimTrkShareFrac.clear(); + see_bestSimTrkShareFracSimDenom.clear(); + see_shareFrac.clear(); + see_simTrkIdx.clear(); see_hitIdx .clear(); see_hitType .clear(); //seed algo offset @@ -1955,7 +1963,7 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS //seeds if(includeSeeds_) { - fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, *theTTRHBuilder, theMF.product(), monoStereoClusterList, hitProductIds, seedCollToOffset); + fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, clusterToTPMap, *theTTRHBuilder, theMF.product(), monoStereoClusterList, hitProductIds, seedCollToOffset); } //tracks @@ -2487,6 +2495,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, const TrackingParticleRefKeyToIndex& tpKeyToIndex, const reco::BeamSpot& bs, const reco::TrackToTrackingParticleAssociator& associatorByHits, + const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const MagneticField *theMF, const std::vector >& monoStereoClusterList, @@ -2564,13 +2573,20 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, } } + // Search for a best-matching TrackingParticle for a seed + const int nHits = seedTrack.numberOfValidHits(); + const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap); + const float bestShareFrac = static_cast(bestKeyCount.second)/static_cast(nHits); + float bestShareFracSimDenom = 0; + if(bestKeyCount.first >= 0) { + bestShareFracSimDenom = static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()); + } const bool seedFitOk = !trackFromSeedFitFailed(seedTrack); const int charge = seedTrack.charge(); const float pt = seedFitOk ? seedTrack.pt() : 0; const float eta = seedFitOk ? seedTrack.eta() : 0; const float phi = seedFitOk ? seedTrack.phi() : 0; - const int nHits = seedTrack.numberOfValidHits(); const auto seedIndex = see_fitok.size(); @@ -2610,10 +2626,13 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, if(includeTrackingParticles_) { see_shareFrac.push_back( sharedFraction ); see_simTrkIdx.push_back( tpIdx ); + see_bestSimTrkIdx.push_back(bestKeyCount.first >= 0 ? tpKeyToIndex.at(bestKeyCount.first) : -1); } else { see_isTrue.push_back(!tpIdx.empty()); } + see_bestSimTrkShareFrac.push_back(bestShareFrac); + see_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); /// Hmm, the following could make sense instead of plain failing if propagation to beam line fails /* From 9e9c72f65df28a621379e958bf46eee72c5ddaff Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Fri, 30 Jun 2017 15:03:59 +0200 Subject: [PATCH 05/24] Add a track-TP matching score starting from the first hit of the track --- .../RecoTrack/plugins/TrackingNtuple.cc | 87 ++++++++++++++++++- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 9a2708914ac22..890902a517939 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -349,6 +349,70 @@ namespace { return std::make_pair(bestKey, bestKey >= 0 ? bestCount : 0); } + + std::pair findMatchingTrackingParticleFromFirstHit(const reco::Track& track, + const ClusterTPAssociation& clusterToTPMap) { + int bestKey = -1; + int bestCount = 0; + + std::vector validTPs; // first cluster can be associated to multiple TPs, use vector as set as this should be small + auto iHit = track.recHitsBegin(); + { + const TrackingRecHit& hit = **iHit; + if(!hit.isValid()) { + throw cms::Exception("LogicError") << "I expected first track hit to be valid, but encountered an invalid hit..."; + } + auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); + for(auto ip=range.first; ip != range.second; ++ip) { + validTPs.push_back(ip->second.key()); + } + } + if(validTPs.empty()) { + return std::make_pair(bestKey, bestCount); + } + ++iHit; + ++bestCount; + + std::vector foundTPs(validTPs.size(), false); + for(auto iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { + const TrackingRecHit& hit = **iHit; + if(hit.isValid()) { + // find out to which first-hit TPs this hit is matched to + auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); + for(auto ip=range.first; ip != range.second; ++ip) { + auto found = std::find(cbegin(validTPs), cend(validTPs), ip->second.key()); + if(found != cend(validTPs)) { + foundTPs[std::distance(cbegin(validTPs), found)] = true; + } + } + + // remove the non-found TPs + auto iTP = validTPs.size(); + do { + --iTP; + + if(!foundTPs[iTP]) { + validTPs.erase(validTPs.begin()+iTP); + foundTPs.erase(foundTPs.begin()+iTP); + } + } while(iTP > 0); + if(!validTPs.empty()) { + // for multiple TPs the "first one" is a bit arbitrary, but + // I hope it is rare that a track would have many + // consecutive hits matched to two TPs + bestKey = validTPs[0]; + } + else { + break; + } + + std::fill(begin(foundTPs), end(foundTPs), false); + ++bestCount; + } + } + + return std::make_pair(bestKey, bestCount); + } } // @@ -913,6 +977,9 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_bestSimTrkIdx; std::vector trk_bestSimTrkShareFrac; std::vector trk_bestSimTrkShareFracSimDenom; + std::vector trk_bestFromFirstHitSimTrkIdx; + std::vector trk_bestFromFirstHitSimTrkShareFrac; + std::vector trk_bestFromFirstHitSimTrkShareFracSimDenom; std::vector > trk_shareFrac; // second index runs through matched TrackingParticles std::vector > trk_simTrkIdx; // second index runs through matched TrackingParticles std::vector > trk_hitIdx; // second index runs through hits @@ -1294,12 +1361,15 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("trk_shareFrac", &trk_shareFrac); t->Branch("trk_simTrkIdx", &trk_simTrkIdx ); t->Branch("trk_bestSimTrkIdx", &trk_bestSimTrkIdx); + t->Branch("trk_bestFromFirstHitSimTrkIdx", &trk_bestFromFirstHitSimTrkIdx); } else { t->Branch("trk_isTrue", &trk_isTrue); } t->Branch("trk_bestSimTrkShareFrac", &trk_bestSimTrkShareFrac); t->Branch("trk_bestSimTrkShareFracSimDenom", &trk_bestSimTrkShareFracSimDenom); + t->Branch("trk_bestFromFirstHitSimTrkShareFrac", &trk_bestFromFirstHitSimTrkShareFrac); + t->Branch("trk_bestFromFirstHitSimTrkShareFracSimDenom", &trk_bestFromFirstHitSimTrkShareFracSimDenom); if(includeAllHits_) { t->Branch("trk_hitIdx" , &trk_hitIdx); t->Branch("trk_hitType", &trk_hitType); @@ -1616,6 +1686,9 @@ void TrackingNtuple::clearVariables() { trk_bestSimTrkIdx.clear(); trk_bestSimTrkShareFrac.clear(); trk_bestSimTrkShareFracSimDenom.clear(); + trk_bestFromFirstHitSimTrkIdx.clear(); + trk_bestFromFirstHitSimTrkShareFrac.clear(); + trk_bestFromFirstHitSimTrkShareFracSimDenom.clear(); trk_shareFrac.clear(); trk_simTrkIdx.clear(); trk_hitIdx .clear(); @@ -2833,10 +2906,12 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, // Search for a best-matching TrackingParticle for a track const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap); const float bestShareFrac = static_cast(bestKeyCount.second)/static_cast(nHits); - float bestShareFracSimDenom = 0; - if(bestKeyCount.first >= 0) { - bestShareFracSimDenom = static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()); - } + const float bestShareFracSimDenom = bestKeyCount.first >= 0 ? static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()) : 0; + // Another way starting from the first hit of the track + const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap); + const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.second)/static_cast(nHits); + const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.first >= 0 ? static_cast(bestFirstHitKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.first)]->numberOfTrackerHits()) : 0; + float chi2_1Dmod = chi2; int count1dhits = 0; @@ -2928,12 +3003,16 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, trk_simTrkIdx.push_back(tpIdx); trk_shareFrac.push_back(sharedFraction); trk_bestSimTrkIdx.push_back(bestKeyCount.first >= 0 ? tpKeyToIndex.at(bestKeyCount.first) : -1); + trk_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.first >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.first) : -1); } else { trk_isTrue.push_back(!tpIdx.empty()); } trk_bestSimTrkShareFrac.push_back(bestShareFrac); trk_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); + trk_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); + trk_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); + LogTrace("TrackingNtuple") << "Track #" << itTrack.key() << " with q=" << charge << ", pT=" << pt << " GeV, eta: " << eta << ", phi: " << phi << ", chi2=" << chi2 From 7269ed9b8deebfddd7186987a2c926baadd60009 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Mon, 3 Jul 2017 11:09:57 +0200 Subject: [PATCH 06/24] Count matched hits and clusters separately Some hits are associated to multiple clustes (e.g. strip matched hits). For those cases, the reco denominator needs the count of hits, while the sim denominator needs the count of clusters. --- .../RecoTrack/plugins/TrackingNtuple.cc | 141 +++++++++++++----- 1 file changed, 100 insertions(+), 41 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 890902a517939..45dadced293c2 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -325,35 +325,93 @@ namespace { return simTrackIdToAdc; } - std::pair findBestMatchingTrackingParticle(const reco::Track& track, - const ClusterTPAssociation& clusterToTPMap) { - std::unordered_map count; + struct TrackTPMatch { + int key = -1; + // Difference between "Hits" and "Clusters" is that + // SiStripMatchedRecHit2D etc. are counted as 1 hit but 2 + // clusters. For reco denominator the number if hits is useful, + // but for sim denominator the number of clusters. + int countHits = 0; + int countClusters = 0; + }; + + TrackTPMatch findBestMatchingTrackingParticle(const reco::Track& track, + const ClusterTPAssociation& clusterToTPMap) { + // pair: (hits, clusters) + std::unordered_map > count; + auto fillCount = [&](const auto& clusterRef) { + auto range = clusterToTPMap.equal_range(clusterRef); + for(auto ip=range.first; ip != range.second; ++ip) { + count[ip->second.key()].first += 1; + count[ip->second.key()].second += 1; + } + }; + auto fillCountAnd = [&](const auto& range1, const auto& range2) { + for(auto i1=range1.first; i1!=range1.second; ++i1) { + if(range2.second != std::find_if(range2.first, range2.second, [&](const auto& clusterTP) { + return clusterTP.second.key() == i1->second.key(); + })) { + auto& elem = count[i1->second.key()]; + elem.first += 1; // 1 hit + elem.second += 2; // 2 clusters + } + } + }; + + for(auto iHit = track.recHitsBegin(), iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { const TrackingRecHit& hit = **iHit; if(hit.isValid()) { - auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); - for(auto ip=range.first; ip != range.second; ++ip) { - count[ip->second.key()] += 1; + if(const auto *mhit = dynamic_cast(&hit)) { + auto rangeMono = clusterToTPMap.equal_range(mhit->monoClusterRef()); + auto rangeStereo = clusterToTPMap.equal_range(mhit->stereoClusterRef()); + fillCountAnd(rangeMono, rangeStereo); + } + // else if hit is VectorHit? SiTrackerMultiRecHit perhaps? + else { + fillCount(dynamic_cast(hit).firstClusterRef()); } } } - int bestKey = -1; + TrackTPMatch best; int bestCount = 2; // require >= 3 hits for the best match for(auto& keyCount: count) { - if(keyCount.second > bestCount) { - bestKey = keyCount.first; - bestCount = keyCount.second; + if(keyCount.second.first > bestCount) { + best.key = keyCount.first; + best.countHits = bestCount = keyCount.second.first; + best.countClusters = keyCount.second.second; } } - return std::make_pair(bestKey, bestKey >= 0 ? bestCount : 0); + return best; } - std::pair findMatchingTrackingParticleFromFirstHit(const reco::Track& track, - const ClusterTPAssociation& clusterToTPMap) { - int bestKey = -1; - int bestCount = 0; + TrackTPMatch findMatchingTrackingParticleFromFirstHit(const reco::Track& track, + const ClusterTPAssociation& clusterToTPMap) { + TrackTPMatch best; + + auto operateHit = [&](const TrackingRecHit& hit, const auto& func) { + if(const auto *mhit = dynamic_cast(&hit)) { + auto rangeMono = clusterToTPMap.equal_range(mhit->monoClusterRef()); + auto rangeStereo = clusterToTPMap.equal_range(mhit->stereoClusterRef()); + for(auto i1=rangeMono.first; i1!=rangeMono.second; ++i1) { + if(rangeStereo.second != std::find_if(rangeStereo.first, rangeStereo.second, [&](const auto& clusterTP) { + return clusterTP.second.key() == i1->second.key(); + })) { + func(i1->second.key()); + } + } + } + // else if hit is VectorHit? + else { + auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); + for(auto ip=range.first; ip != range.second; ++ip) { + func(ip->second.key()); + } + } + }; + std::vector validTPs; // first cluster can be associated to multiple TPs, use vector as set as this should be small auto iHit = track.recHitsBegin(); @@ -362,29 +420,28 @@ namespace { if(!hit.isValid()) { throw cms::Exception("LogicError") << "I expected first track hit to be valid, but encountered an invalid hit..."; } - auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); - for(auto ip=range.first; ip != range.second; ++ip) { - validTPs.push_back(ip->second.key()); - } + operateHit(hit, [&](unsigned int tpKey) { + validTPs.push_back(tpKey); + }); } if(validTPs.empty()) { - return std::make_pair(bestKey, bestCount); + return best; } ++iHit; - ++bestCount; + ++best.countHits; + ++best.countClusters; std::vector foundTPs(validTPs.size(), false); for(auto iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { const TrackingRecHit& hit = **iHit; if(hit.isValid()) { // find out to which first-hit TPs this hit is matched to - auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); - for(auto ip=range.first; ip != range.second; ++ip) { - auto found = std::find(cbegin(validTPs), cend(validTPs), ip->second.key()); - if(found != cend(validTPs)) { - foundTPs[std::distance(cbegin(validTPs), found)] = true; - } - } + operateHit(hit, [&](unsigned int tpKey) { + auto found = std::find(cbegin(validTPs), cend(validTPs), tpKey); + if(found != cend(validTPs)) { + foundTPs[std::distance(cbegin(validTPs), found)] = true; + } + }); // remove the non-found TPs auto iTP = validTPs.size(); @@ -400,18 +457,20 @@ namespace { // for multiple TPs the "first one" is a bit arbitrary, but // I hope it is rare that a track would have many // consecutive hits matched to two TPs - bestKey = validTPs[0]; + best.key = validTPs[0]; } else { break; } std::fill(begin(foundTPs), end(foundTPs), false); - ++bestCount; + ++best.countHits; + ++best.countClusters; } } - return std::make_pair(bestKey, bestCount); + // Reqquire >= 3 hits for a match + return best.countHits >= 3 ? best : TrackTPMatch(); } } @@ -2649,10 +2708,10 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, // Search for a best-matching TrackingParticle for a seed const int nHits = seedTrack.numberOfValidHits(); const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap); - const float bestShareFrac = static_cast(bestKeyCount.second)/static_cast(nHits); + const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); float bestShareFracSimDenom = 0; - if(bestKeyCount.first >= 0) { - bestShareFracSimDenom = static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()); + if(bestKeyCount.key >= 0) { + bestShareFracSimDenom = static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()); } const bool seedFitOk = !trackFromSeedFitFailed(seedTrack); @@ -2699,7 +2758,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, if(includeTrackingParticles_) { see_shareFrac.push_back( sharedFraction ); see_simTrkIdx.push_back( tpIdx ); - see_bestSimTrkIdx.push_back(bestKeyCount.first >= 0 ? tpKeyToIndex.at(bestKeyCount.first) : -1); + see_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); } else { see_isTrue.push_back(!tpIdx.empty()); @@ -2905,12 +2964,12 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, // Search for a best-matching TrackingParticle for a track const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap); - const float bestShareFrac = static_cast(bestKeyCount.second)/static_cast(nHits); - const float bestShareFracSimDenom = bestKeyCount.first >= 0 ? static_cast(bestKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.first)]->numberOfTrackerHits()) : 0; + const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); + const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; // Another way starting from the first hit of the track const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap); - const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.second)/static_cast(nHits); - const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.first >= 0 ? static_cast(bestFirstHitKeyCount.second)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.first)]->numberOfTrackerHits()) : 0; + const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); + const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; float chi2_1Dmod = chi2; @@ -3002,8 +3061,8 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, if(includeTrackingParticles_) { trk_simTrkIdx.push_back(tpIdx); trk_shareFrac.push_back(sharedFraction); - trk_bestSimTrkIdx.push_back(bestKeyCount.first >= 0 ? tpKeyToIndex.at(bestKeyCount.first) : -1); - trk_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.first >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.first) : -1); + trk_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); + trk_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.key >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.key) : -1); } else { trk_isTrue.push_back(!tpIdx.empty()); From f01af46ae90a83e8c984a19944a5125f8beaa706 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Mon, 3 Jul 2017 11:41:25 +0200 Subject: [PATCH 07/24] Add best TP match from first hit also to seeds --- .../RecoTrack/plugins/TrackingNtuple.cc | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 45dadced293c2..fe504b378f1d3 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -1233,6 +1233,9 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector see_bestSimTrkIdx; std::vector see_bestSimTrkShareFrac; std::vector see_bestSimTrkShareFracSimDenom; + std::vector see_bestFromFirstHitSimTrkIdx; + std::vector see_bestFromFirstHitSimTrkShareFrac; + std::vector see_bestFromFirstHitSimTrkShareFracSimDenom; std::vector > see_shareFrac; // second index runs through matched TrackingParticles std::vector > see_simTrkIdx; // second index runs through matched TrackingParticles std::vector > see_hitIdx; // second index runs through hits @@ -1624,12 +1627,15 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("see_shareFrac", &see_shareFrac); t->Branch("see_simTrkIdx", &see_simTrkIdx ); t->Branch("see_bestSimTrkIdx", &see_bestSimTrkIdx); + t->Branch("see_bestFromFirstHitSimTrkIdx", &see_bestFromFirstHitSimTrkIdx); } else { t->Branch("see_isTrue", &see_isTrue); } t->Branch("see_bestSimTrkShareFrac", &see_bestSimTrkShareFrac); t->Branch("see_bestSimTrkShareFracSimDenom", &see_bestSimTrkShareFracSimDenom); + t->Branch("see_bestFromFirstHitSimTrkShareFrac", &see_bestFromFirstHitSimTrkShareFrac); + t->Branch("see_bestFromFirstHitSimTrkShareFracSimDenom", &see_bestFromFirstHitSimTrkShareFracSimDenom); if(includeAllHits_) { t->Branch("see_hitIdx" , &see_hitIdx ); t->Branch("see_hitType", &see_hitType ); @@ -1919,6 +1925,9 @@ void TrackingNtuple::clearVariables() { see_bestSimTrkIdx.clear(); see_bestSimTrkShareFrac.clear(); see_bestSimTrkShareFracSimDenom.clear(); + see_bestFromFirstHitSimTrkIdx.clear(); + see_bestFromFirstHitSimTrkShareFrac.clear(); + see_bestFromFirstHitSimTrkShareFracSimDenom.clear(); see_shareFrac.clear(); see_simTrkIdx.clear(); see_hitIdx .clear(); @@ -2709,10 +2718,11 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, const int nHits = seedTrack.numberOfValidHits(); const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); - float bestShareFracSimDenom = 0; - if(bestKeyCount.key >= 0) { - bestShareFracSimDenom = static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()); - } + const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; + // Another way starting from the first hit of the seed + const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(seedTrack, clusterToTPMap); + const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); + const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; const bool seedFitOk = !trackFromSeedFitFailed(seedTrack); const int charge = seedTrack.charge(); @@ -2759,12 +2769,15 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, see_shareFrac.push_back( sharedFraction ); see_simTrkIdx.push_back( tpIdx ); see_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); + see_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.key >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.key) : -1); } else { see_isTrue.push_back(!tpIdx.empty()); } see_bestSimTrkShareFrac.push_back(bestShareFrac); see_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); + see_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); + see_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); /// Hmm, the following could make sense instead of plain failing if propagation to beam line fails /* From e5094b50be18ab93183f723e6378af08ef241fe8 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Mon, 3 Jul 2017 13:33:53 +0200 Subject: [PATCH 08/24] In case of multiple matches with same number of hits, select the one with innermost reco hit --- .../RecoTrack/plugins/TrackingNtuple.cc | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index fe504b378f1d3..c2bd6d16cf55d 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -337,23 +337,31 @@ namespace { TrackTPMatch findBestMatchingTrackingParticle(const reco::Track& track, const ClusterTPAssociation& clusterToTPMap) { - // pair: (hits, clusters) - std::unordered_map > count; - auto fillCount = [&](const auto& clusterRef) { + struct Count { + int hits = 0; + int clusters = 0; + int innermostHit = std::numeric_limits::max(); + }; + + std::unordered_map count; + auto fillCount = [&](int hitIndex, const auto& clusterRef) { auto range = clusterToTPMap.equal_range(clusterRef); for(auto ip=range.first; ip != range.second; ++ip) { - count[ip->second.key()].first += 1; - count[ip->second.key()].second += 1; + auto& elem = count[ip->second.key()]; + ++elem.hits; + ++elem.clusters; + elem.innermostHit = std::min(elem.innermostHit, hitIndex); } }; - auto fillCountAnd = [&](const auto& range1, const auto& range2) { + auto fillCountAnd = [&](int hitIndex, const auto& range1, const auto& range2) { for(auto i1=range1.first; i1!=range1.second; ++i1) { if(range2.second != std::find_if(range2.first, range2.second, [&](const auto& clusterTP) { return clusterTP.second.key() == i1->second.key(); })) { auto& elem = count[i1->second.key()]; - elem.first += 1; // 1 hit - elem.second += 2; // 2 clusters + elem.hits += 1; // + elem.clusters += 2; // + elem.innermostHit = std::min(elem.innermostHit, hitIndex); } } }; @@ -365,22 +373,27 @@ namespace { if(const auto *mhit = dynamic_cast(&hit)) { auto rangeMono = clusterToTPMap.equal_range(mhit->monoClusterRef()); auto rangeStereo = clusterToTPMap.equal_range(mhit->stereoClusterRef()); - fillCountAnd(rangeMono, rangeStereo); + fillCountAnd(std::distance(track.recHitsBegin(), iHit), rangeMono, rangeStereo); } // else if hit is VectorHit? SiTrackerMultiRecHit perhaps? else { - fillCount(dynamic_cast(hit).firstClusterRef()); + fillCount(std::distance(track.recHitsBegin(), iHit), dynamic_cast(hit).firstClusterRef()); } } } + // In case there are many matches with the same number of hits, + // select the one with innermost hit TrackTPMatch best; int bestCount = 2; // require >= 3 hits for the best match + int bestInnermostHit = std::numeric_limits::max(); for(auto& keyCount: count) { - if(keyCount.second.first > bestCount) { + if(keyCount.second.hits > bestCount || + (keyCount.second.hits == bestCount && keyCount.second.innermostHit < bestInnermostHit)) { best.key = keyCount.first; - best.countHits = bestCount = keyCount.second.first; - best.countClusters = keyCount.second.second; + best.countHits = bestCount = keyCount.second.hits; + best.countClusters = keyCount.second.clusters; + bestInnermostHit = keyCount.second.innermostHit; } } From c553e6b20162579cb72d0f361cada0390d790322 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Mon, 3 Jul 2017 14:38:13 +0200 Subject: [PATCH 09/24] Switch bestMatchingTrackingParticle() to use the stored index --- .../python/plotting/ntupleDataFormat.py | 45 +++++++++++-------- .../python/plotting/ntuplePrintersDiff.py | 2 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py index 9e7fa60815490..b13444e208c41 100644 --- a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py +++ b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py @@ -325,28 +325,35 @@ def bestMatchingTrackingParticle(self): fulfilling the same number of hits, the one inducing the innermost hit of the track is chosen. """ - self._checkIsValid() - if self._nMatchedTrackingParticles() == 1: - return next(self.matchedTrackingParticleInfos()).trackingParticle() + idx = self.bestSimTrkIdx() + if idx < 0: + return None + return TrackingParticle(self._tree, idx) - tps = collections.OrderedDict() - for hit in self.hits(): - if not isinstance(hit, _SimHitMatchAdaptor): - continue - for shInfo in hit.matchedSimHitInfos(): - tp = shInfo.simHit().trackingParticle() - if tp.index() in tps: - tps[tp.index()] += 1 - else: - tps[tp.index()] = 1 + def bestMatchingTrackingParticleShareFrac(self): + return self.bestSimTrkShareFrac() - best = (None, 2) - for tpIndex, nhits in tps.iteritems(): - if nhits > best[1]: - best = (tpIndex, nhits) - if best[0] is None: + def bestMatchingTrackingParticleShareFracSimDenom(self): + return self.bestSimTrkShareFracSimDenom() + + def bestMatchingTrackingParticleFromFirstHit(self): + """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle. + + Best-matching is defined as the one with largest number of + hits matched to the hits of a track (>= 3). If there are many + fulfilling the same number of hits, the one inducing the + innermost hit of the track is chosen. + """ + idx = self.bestFromFirstHitSimTrkIdx() + if idx < 0: return None - return TrackingParticles(self._tree)[best[0]] + return TrackingParticle(self._tree, idx) + + def bestMatchingTrackingParticleFromFirstHitShareFrac(self): + return self.bestFromFirstHitSimTrkShareFrac() + + def bestMatchingTrackingParticleFromFirstHitShareFracSimDenom(self): + return self.bestFromFirstHitSimTrkShareFracSimDenom() ########## class TrackingNtuple(object): diff --git a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py index 259d698395e14..808a371e31231 100644 --- a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py +++ b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py @@ -811,7 +811,7 @@ def printMatchedTrackingParticles(self, prefix, track): if self._bestMatchingTrackingParticle: bestTP = track.bestMatchingTrackingParticle() if bestTP is not None: - lst.extend(self._printTrackingParticles(pfx, [bestTP], "not matched to any TP, but a following TP with >= 3 matched hits is found")) + lst.extend(self._printTrackingParticles(pfx, [bestTP], "not matched to any TP, but a following TP with >= 3 matched hits is found (shared hit fraction %.2f)" % track.bestMatchingTrackingParticleShareFrac())) else: lst.append(prefix+"not matched to any TP") else: From eece559a9d38cf1d280671233148f4bf8a6b0ce7 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 5 Jul 2017 09:49:41 +0200 Subject: [PATCH 10/24] Exclude also SimHits if TrackingParticles are excluded --- .../RecoTrack/plugins/TrackingNtuple.cc | 163 ++++++++++-------- .../python/customiseTrackingNtuple.py | 2 +- 2 files changed, 91 insertions(+), 74 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index c2bd6d16cf55d..70ff7f5b7aeab 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -1496,9 +1496,11 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeSeeds_) { t->Branch("pix_seeIdx" , &pix_seeIdx ); } - t->Branch("pix_simHitIdx" , &pix_simHitIdx); - t->Branch("pix_chargeFraction", &pix_chargeFraction); - t->Branch("pix_simType", &pix_simType); + if(includeTrackingParticles_) { + t->Branch("pix_simHitIdx" , &pix_simHitIdx); + t->Branch("pix_chargeFraction", &pix_chargeFraction); + t->Branch("pix_simType", &pix_simType); + } t->Branch("pix_x" , &pix_x ); t->Branch("pix_y" , &pix_y ); t->Branch("pix_z" , &pix_z ); @@ -1519,9 +1521,11 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeSeeds_) { t->Branch("str_seeIdx" , &str_seeIdx ); } - t->Branch("str_simHitIdx" , &str_simHitIdx); - t->Branch("str_chargeFraction", &str_chargeFraction); - t->Branch("str_simType", &str_simType); + if(includeTrackingParticles_) { + t->Branch("str_simHitIdx" , &str_simHitIdx); + t->Branch("str_chargeFraction", &str_chargeFraction); + t->Branch("str_simType", &str_simType); + } t->Branch("str_x" , &str_x ); t->Branch("str_y" , &str_y ); t->Branch("str_z" , &str_z ); @@ -1561,8 +1565,10 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeSeeds_) { t->Branch("ph2_seeIdx" , &ph2_seeIdx ); } - t->Branch("ph2_simHitIdx" , &ph2_simHitIdx); - t->Branch("ph2_simType", &ph2_simType); + if(includeTrackingParticles_) { + t->Branch("ph2_simHitIdx" , &ph2_simHitIdx); + t->Branch("ph2_simType", &ph2_simType); + } t->Branch("ph2_x" , &ph2_x ); t->Branch("ph2_y" , &ph2_y ); t->Branch("ph2_z" , &ph2_z ); @@ -1582,19 +1588,20 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): else inv_detId_phase2.book("inv", t); t->Branch("inv_type" , &inv_type ); //simhits - if(includeStripHits_) simhit_detId.book("simhit", t); - else simhit_detId_phase2.book("simhit", t); - t->Branch("simhit_x" , &simhit_x); - t->Branch("simhit_y" , &simhit_y); - t->Branch("simhit_z" , &simhit_z); - t->Branch("simhit_particle", &simhit_particle); - t->Branch("simhit_process" , &simhit_process); - t->Branch("simhit_eloss" , &simhit_eloss); - t->Branch("simhit_tof" , &simhit_tof); - //t->Branch("simhit_simTrackId", &simhit_simTrackId); - t->Branch("simhit_simTrkIdx", &simhit_simTrkIdx); - t->Branch("simhit_hitIdx" , &simhit_hitIdx); - t->Branch("simhit_hitType" , &simhit_hitType); + if(includeTrackingParticles_) { + if(includeStripHits_) simhit_detId.book("simhit", t); + else simhit_detId_phase2.book("simhit", t); + t->Branch("simhit_x" , &simhit_x); + t->Branch("simhit_y" , &simhit_y); + t->Branch("simhit_z" , &simhit_z); + t->Branch("simhit_particle", &simhit_particle); + t->Branch("simhit_process" , &simhit_process); + t->Branch("simhit_eloss" , &simhit_eloss); + t->Branch("simhit_tof" , &simhit_tof); + t->Branch("simhit_simTrkIdx", &simhit_simTrkIdx); + t->Branch("simhit_hitIdx" , &simhit_hitIdx); + t->Branch("simhit_hitType" , &simhit_hitType); + } } //beam spot t->Branch("bsp_x" , &bsp_x , "bsp_x/F"); @@ -2092,8 +2099,10 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS //prapare list to link matched hits to collection vector > monoStereoClusterList; if(includeAllHits_) { - // simhits - fillSimHits(tracker, tpKeyToIndex, *simHitsTPAssoc, tTopo, simHitRefKeyToIndex, tpHitList); + // simhits, only if TPs are saved as well + if(includeTrackingParticles_) { + fillSimHits(tracker, tpKeyToIndex, *simHitsTPAssoc, tTopo, simHitRefKeyToIndex, tpHitList); + } //pixel hits fillPixelHits(iEvent, clusterToTPMap, tpKeyToIndex, *simHitsTPAssoc, pixelDigiSimLinks, *theTTRHBuilder, tTopo, simHitRefKeyToIndex, hitProductIds); @@ -2410,15 +2419,11 @@ void TrackingNtuple::fillPixelHits(const edm::Event& iEvent, const int key = hit->cluster().key(); const int lay = tTopo.layer(hitId); - SimHitData simHitData = matchCluster(hit->firstClusterRef(), hitId, key, ttrh, - clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Pixel); pix_isBarrel .push_back( hitId.subdetId()==1 ); pix_detId .push_back( tTopo, hitId ); pix_trkIdx .emplace_back(); // filled in fillTracks pix_seeIdx .emplace_back(); // filled in fillSeeds - pix_simHitIdx.push_back( simHitData.matchingSimHit ); - pix_simType.push_back( static_cast(simHitData.type) ); pix_x .push_back( ttrh->globalPosition().x() ); pix_y .push_back( ttrh->globalPosition().y() ); pix_z .push_back( ttrh->globalPosition().z() ); @@ -2428,24 +2433,31 @@ void TrackingNtuple::fillPixelHits(const edm::Event& iEvent, pix_yz .push_back( ttrh->globalPositionError().czy() ); pix_zz .push_back( ttrh->globalPositionError().czz() ); pix_zx .push_back( ttrh->globalPositionError().czx() ); - pix_chargeFraction.push_back( simHitData.chargeFraction ); pix_radL .push_back( ttrh->surface()->mediumProperties().radLen() ); pix_bbxi .push_back( ttrh->surface()->mediumProperties().xi() ); + LogTrace("TrackingNtuple") << "pixHit cluster=" << key << " subdId=" << hitId.subdetId() << " lay=" << lay << " rawId=" << hitId.rawId() - << " pos =" << ttrh->globalPosition() - << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); - if(!simHitData.matchingSimHit.empty()) { - const auto simHitIdx = simHitData.matchingSimHit[0]; - LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx - << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) - << " energyLoss=" << simhit_eloss[simHitIdx] - << " particleType=" << simhit_particle[simHitIdx] - << " processType=" << simhit_process[simHitIdx] - << " bunchCrossing=" << simHitData.bunchCrossing[0] - << " event=" << simHitData.event[0]; + << " pos =" << ttrh->globalPosition(); + if(includeTrackingParticles_) { + SimHitData simHitData = matchCluster(hit->firstClusterRef(), hitId, key, ttrh, + clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Pixel); + pix_simHitIdx.push_back( simHitData.matchingSimHit ); + pix_simType.push_back( static_cast(simHitData.type) ); + pix_chargeFraction.push_back( simHitData.chargeFraction ); + LogTrace("TrackingNtuple") << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); + if(!simHitData.matchingSimHit.empty()) { + const auto simHitIdx = simHitData.matchingSimHit[0]; + LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx + << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) + << " energyLoss=" << simhit_eloss[simHitIdx] + << " particleType=" << simhit_particle[simHitIdx] + << " processType=" << simhit_process[simHitIdx] + << " bunchCrossing=" << simHitData.bunchCrossing[0] + << " event=" << simHitData.event[0]; + } } } } @@ -2474,6 +2486,7 @@ void TrackingNtuple::fillStripRphiStereoHits(const edm::Event& iEvent, str_seeIdx .resize(totalStripHits); // filled in fillSeeds str_simHitIdx.resize(totalStripHits); str_simType .resize(totalStripHits); + str_chargeFraction.resize(totalStripHits); str_x .resize(totalStripHits); str_y .resize(totalStripHits); str_z .resize(totalStripHits); @@ -2483,7 +2496,6 @@ void TrackingNtuple::fillStripRphiStereoHits(const edm::Event& iEvent, str_yz .resize(totalStripHits); str_zz .resize(totalStripHits); str_zx .resize(totalStripHits); - str_chargeFraction.resize(totalStripHits); str_radL .resize(totalStripHits); str_bbxi .resize(totalStripHits); @@ -2497,12 +2509,8 @@ void TrackingNtuple::fillStripRphiStereoHits(const edm::Event& iEvent, const int key = hit.cluster().key(); const int lay = tTopo.layer(hitId); - SimHitData simHitData = matchCluster(hit.firstClusterRef(), hitId, key, ttrh, - clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Strip); str_isBarrel [key] = (hitId.subdetId()==StripSubdetector::TIB || hitId.subdetId()==StripSubdetector::TOB); str_detId.set(key, tTopo, hitId); - str_simHitIdx[key] = simHitData.matchingSimHit; - str_simType [key] = static_cast(simHitData.type); str_x [key] = ttrh->globalPosition().x(); str_y [key] = ttrh->globalPosition().y(); str_z [key] = ttrh->globalPosition().z(); @@ -2512,25 +2520,32 @@ void TrackingNtuple::fillStripRphiStereoHits(const edm::Event& iEvent, str_yz [key] = ttrh->globalPositionError().czy(); str_zz [key] = ttrh->globalPositionError().czz(); str_zx [key] = ttrh->globalPositionError().czx(); - str_chargeFraction[key] = simHitData.chargeFraction; str_radL [key] = ttrh->surface()->mediumProperties().radLen(); str_bbxi [key] = ttrh->surface()->mediumProperties().xi(); LogTrace("TrackingNtuple") << name << " cluster=" << key << " subdId=" << hitId.subdetId() << " lay=" << lay << " rawId=" << hitId.rawId() - << " pos =" << ttrh->globalPosition() - << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); - if(!simHitData.matchingSimHit.empty()) { - const auto simHitIdx = simHitData.matchingSimHit[0]; - LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx - << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) - << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) - << " energyLoss=" << simhit_eloss[simHitIdx] - << " particleType=" << simhit_particle[simHitIdx] - << " processType=" << simhit_process[simHitIdx] - << " bunchCrossing=" << simHitData.bunchCrossing[0] - << " event=" << simHitData.event[0]; + << " pos =" << ttrh->globalPosition(); + + if(includeTrackingParticles_) { + SimHitData simHitData = matchCluster(hit.firstClusterRef(), hitId, key, ttrh, + clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Strip); + str_simHitIdx[key] = simHitData.matchingSimHit; + str_simType [key] = static_cast(simHitData.type); + str_chargeFraction[key] = simHitData.chargeFraction; + LogTrace("TrackingNtuple") << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); + if(!simHitData.matchingSimHit.empty()) { + const auto simHitIdx = simHitData.matchingSimHit[0]; + LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx + << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) + << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) + << " energyLoss=" << simhit_eloss[simHitIdx] + << " particleType=" << simhit_particle[simHitIdx] + << " processType=" << simhit_process[simHitIdx] + << " bunchCrossing=" << simHitData.bunchCrossing[0] + << " event=" << simHitData.event[0]; + } } } } @@ -2601,15 +2616,11 @@ void TrackingNtuple::fillPhase2OTHits(const edm::Event& iEvent, const int key = hit->cluster().key(); const int lay = tTopo.layer(hitId); - SimHitData simHitData = matchCluster(hit->firstClusterRef(), hitId, key, ttrh, - clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Phase2OT); ph2_isBarrel .push_back( hitId.subdetId()==1 ); ph2_detId .push_back( tTopo, hitId ); ph2_trkIdx .emplace_back(); // filled in fillTracks ph2_seeIdx .emplace_back(); // filled in fillSeeds - ph2_simHitIdx.push_back( simHitData.matchingSimHit ); - ph2_simType.push_back( static_cast(simHitData.type) ); ph2_x .push_back( ttrh->globalPosition().x() ); ph2_y .push_back( ttrh->globalPosition().y() ); ph2_z .push_back( ttrh->globalPosition().z() ); @@ -2626,18 +2637,24 @@ void TrackingNtuple::fillPhase2OTHits(const edm::Event& iEvent, << " subdId=" << hitId.subdetId() << " lay=" << lay << " rawId=" << hitId.rawId() - << " pos =" << ttrh->globalPosition() - << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); - - if(!simHitData.matchingSimHit.empty()) { - const auto simHitIdx = simHitData.matchingSimHit[0]; - LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx - << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) - << " energyLoss=" << simhit_eloss[simHitIdx] - << " particleType=" << simhit_particle[simHitIdx] - << " processType=" << simhit_process[simHitIdx] - << " bunchCrossing=" << simHitData.bunchCrossing[0] - << " event=" << simHitData.event[0]; + << " pos =" << ttrh->globalPosition(); + + if(includeTrackingParticles_) { + SimHitData simHitData = matchCluster(hit->firstClusterRef(), hitId, key, ttrh, + clusterToTPMap, tpKeyToIndex, simHitsTPAssoc, digiSimLink, simHitRefKeyToIndex, HitType::Phase2OT); + ph2_simHitIdx.push_back( simHitData.matchingSimHit ); + ph2_simType.push_back( static_cast(simHitData.type) ); + LogTrace("TrackingNtuple") << " nMatchingSimHit=" << simHitData.matchingSimHit.size(); + if(!simHitData.matchingSimHit.empty()) { + const auto simHitIdx = simHitData.matchingSimHit[0]; + LogTrace("TrackingNtuple") << " firstMatchingSimHit=" << simHitIdx + << " simHitPos=" << GlobalPoint(simhit_x[simHitIdx], simhit_y[simHitIdx], simhit_z[simHitIdx]) + << " energyLoss=" << simhit_eloss[simHitIdx] + << " particleType=" << simhit_particle[simHitIdx] + << " processType=" << simhit_process[simHitIdx] + << " bunchCrossing=" << simHitData.bunchCrossing[0] + << " event=" << simHitData.event[0]; + } } } } diff --git a/Validation/RecoTrack/python/customiseTrackingNtuple.py b/Validation/RecoTrack/python/customiseTrackingNtuple.py index aca65fd8e63cd..e3c7619fd1475 100644 --- a/Validation/RecoTrack/python/customiseTrackingNtuple.py +++ b/Validation/RecoTrack/python/customiseTrackingNtuple.py @@ -27,7 +27,7 @@ def customiseTrackingNtuple(process): # process.eda = cms.EDAnalyzer("EventContentAnalyzer") ntuplePath = cms.EndPath(process.trackingNtupleSequence) - if process.trackingNtuple.includeAllHits and usePileupSimHits: + if process.trackingNtuple.includeAllHits and process.trackingNtuple.includeTrackingParticles and usePileupSimHits: ntuplePath.insert(0, cms.SequencePlaceholder("mix")) process.load("Validation.RecoTrack.crossingFramePSimHitToPSimHits_cfi") From 1eed581c45b818180bde861ccdc4a977681e8a1b Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 5 Jul 2017 10:29:23 +0200 Subject: [PATCH 11/24] Remove unused code --- Validation/RecoTrack/plugins/TrackingNtuple.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 70ff7f5b7aeab..9a6c9036420a6 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -506,7 +506,6 @@ class TrackingNtuple : public edm::one::EDAnalyzer { // This pattern is copied from QuickTrackAssociatorByHitsImpl. If // further needs arises, it wouldn't hurt to abstract it somehow. - typedef std::unordered_set TrackingParticleRefKeySet; typedef std::unordered_map TrackingParticleRefKeyToIndex; typedef TrackingParticleRefKeyToIndex TrackingVertexRefKeyToIndex; typedef std::pair SimHitFullKey; @@ -2014,7 +2013,6 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS // TrackingParticles... Unfortunately it has non-trivial // consequences on the associator/association interfaces etc. TrackingParticleRefVector tmpTP; - TrackingParticleRefKeySet tmpTPkeys; const TrackingParticleRefVector *tmpTPptr = nullptr; edm::Handle TPCollectionH; edm::Handle TPCollectionHRefVector; @@ -2029,9 +2027,6 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS else { iEvent.getByToken(trackingParticleRefToken_, TPCollectionHRefVector); tmpTPptr = TPCollectionHRefVector.product(); - for(const auto& ref: *tmpTPptr) { - tmpTPkeys.insert(ref.key()); - } } const TrackingParticleRefVector& tpCollection = *tmpTPptr; From 24e6cb1cba6aa49d949fd4c7567f1b24e19eab43 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 5 Jul 2017 11:00:05 +0200 Subject: [PATCH 12/24] Exclude non-input TrackingParticles from the best match calculation --- .../RecoTrack/plugins/TrackingNtuple.cc | 55 +++++++++++++------ 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 9a6c9036420a6..28156e3aac291 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -105,6 +105,14 @@ add local angle, path length! */ namespace { + // This pattern is copied from QuickTrackAssociatorByHitsImpl. If + // further needs arises, it wouldn't hurt to abstract it somehow. + using TrackingParticleRefKeyToIndex = std::unordered_map; + using TrackingVertexRefKeyToIndex = TrackingParticleRefKeyToIndex; + using SimHitFullKey = std::pair; + using SimHitRefKeyToIndex = std::map; + + std::string subdetstring(int subdet) { switch(subdet) { case StripSubdetector::TIB: return "- TIB"; @@ -336,7 +344,8 @@ namespace { }; TrackTPMatch findBestMatchingTrackingParticle(const reco::Track& track, - const ClusterTPAssociation& clusterToTPMap) { + const ClusterTPAssociation& clusterToTPMap, + const TrackingParticleRefKeyToIndex& tpKeyToIndex) { struct Count { int hits = 0; int clusters = 0; @@ -347,10 +356,15 @@ namespace { auto fillCount = [&](int hitIndex, const auto& clusterRef) { auto range = clusterToTPMap.equal_range(clusterRef); for(auto ip=range.first; ip != range.second; ++ip) { - auto& elem = count[ip->second.key()]; + const auto tpKey = ip->second.key(); + if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input + continue; + + auto& elem = count[tpKey]; ++elem.hits; ++elem.clusters; elem.innermostHit = std::min(elem.innermostHit, hitIndex); + //edm::LogPrint("Foo") << "key " << ip->second.key() << " event:BX " << ip->second->eventId().event() << ":" << ip->second->eventId().bunchCrossing(); } }; auto fillCountAnd = [&](int hitIndex, const auto& range1, const auto& range2) { @@ -358,7 +372,11 @@ namespace { if(range2.second != std::find_if(range2.first, range2.second, [&](const auto& clusterTP) { return clusterTP.second.key() == i1->second.key(); })) { - auto& elem = count[i1->second.key()]; + const auto tpKey = i1->second.key(); + if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input + continue; + + auto& elem = count[tpKey]; elem.hits += 1; // elem.clusters += 2; // elem.innermostHit = std::min(elem.innermostHit, hitIndex); @@ -397,11 +415,14 @@ namespace { } } + //edm::LogPrint("Foo") << "findBestMatchingTrackingParticle key " << best.key; + return best; } TrackTPMatch findMatchingTrackingParticleFromFirstHit(const reco::Track& track, - const ClusterTPAssociation& clusterToTPMap) { + const ClusterTPAssociation& clusterToTPMap, + const TrackingParticleRefKeyToIndex& tpKeyToIndex) { TrackTPMatch best; auto operateHit = [&](const TrackingRecHit& hit, const auto& func) { @@ -412,7 +433,11 @@ namespace { if(rangeStereo.second != std::find_if(rangeStereo.first, rangeStereo.second, [&](const auto& clusterTP) { return clusterTP.second.key() == i1->second.key(); })) { - func(i1->second.key()); + const auto tpKey = i1->second.key(); + if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input + continue; + + func(tpKey); } } } @@ -420,7 +445,10 @@ namespace { else { auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); for(auto ip=range.first; ip != range.second; ++ip) { - func(ip->second.key()); + const auto tpKey = ip->second.key(); + if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input + continue; + func(tpKey); } } }; @@ -504,13 +532,6 @@ class TrackingNtuple : public edm::one::EDAnalyzer { void clearVariables(); - // This pattern is copied from QuickTrackAssociatorByHitsImpl. If - // further needs arises, it wouldn't hurt to abstract it somehow. - typedef std::unordered_map TrackingParticleRefKeyToIndex; - typedef TrackingParticleRefKeyToIndex TrackingVertexRefKeyToIndex; - typedef std::pair SimHitFullKey; - typedef std::map SimHitRefKeyToIndex; - enum class HitType { Pixel = 0, Strip = 1, @@ -2741,11 +2762,11 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, // Search for a best-matching TrackingParticle for a seed const int nHits = seedTrack.numberOfValidHits(); - const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap); + const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap, tpKeyToIndex); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; // Another way starting from the first hit of the seed - const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(seedTrack, clusterToTPMap); + const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(seedTrack, clusterToTPMap, tpKeyToIndex); const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; @@ -3001,11 +3022,11 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } // Search for a best-matching TrackingParticle for a track - const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap); + const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; // Another way starting from the first hit of the track - const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap); + const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; From 0f0e88e194c880c463bd721d97036eb722bffb33 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Tue, 11 Jul 2017 11:25:59 +0200 Subject: [PATCH 13/24] Remove dead code from TrackAssociaterByChi2Impl They were essentially repeat from getChi2()... --- .../plugins/TrackAssociatorByChi2Impl.cc | 99 ------------------- .../plugins/TrackAssociatorByChi2Impl.h | 27 ----- 2 files changed, 126 deletions(-) diff --git a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc index de065a9e21d53..fb3206822c7c8 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc +++ b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc @@ -3,83 +3,12 @@ #include "DataFormats/Math/interface/deltaPhi.h" #include "DataFormats/GeometrySurface/interface/Line.h" -#include "TrackingTools/PatternTools/interface/trackingParametersAtClosestApproachToBeamSpot.h" #include "getChi2.h" using namespace edm; using namespace reco; using namespace std; -double TrackAssociatorByChi2Impl::compareTracksParam ( TrackCollection::const_iterator rt, - SimTrackContainer::const_iterator st, - const math::XYZTLorentzVectorD& vertexPosition, - const GlobalVector& magField, - const TrackBase::CovarianceMatrix& invertedCovariance, - const reco::BeamSpot& bs) const{ - - Basic3DVector momAtVtx(st->momentum().x(),st->momentum().y(),st->momentum().z()); - Basic3DVector vert = (Basic3DVector) vertexPosition; - - std::pair params = parametersAtClosestApproach(vert, momAtVtx, st->charge(), bs); - if (params.first){ - TrackBase::ParameterVector sParameters = params.second; - TrackBase::ParameterVector rParameters = rt->parameters(); - - TrackBase::ParameterVector diffParameters = rParameters - sParameters; - diffParameters[2] = reco::deltaPhi(diffParameters[2],0.f); - double chi2 = ROOT::Math::Dot(diffParameters * invertedCovariance, diffParameters); - - return chi2; - } else { - return 10000000000.; - } -} - - -TrackAssociatorByChi2Impl::RecoToSimPairAssociation -TrackAssociatorByChi2Impl::compareTracksParam(const TrackCollection& rtColl, - const SimTrackContainer& stColl, - const SimVertexContainer& svColl, - const reco::BeamSpot& bs) const{ - - RecoToSimPairAssociation outputVec; - - for (TrackCollection::const_iterator track=rtColl.begin(); track!=rtColl.end(); track++){ - Chi2SimMap outMap; - - TrackBase::ParameterVector rParameters = track->parameters(); - - TrackBase::CovarianceMatrix recoTrackCovMatrix = track->covariance(); - if (onlyDiagonal){ - for (unsigned int i=0;i<5;i++){ - for (unsigned int j=0;j<5;j++){ - if (i!=j) recoTrackCovMatrix(i,j)=0; - } - } - } - recoTrackCovMatrix.Invert(); - - for (SimTrackContainer::const_iterator st=stColl.begin(); st!=stColl.end(); st++){ - - Basic3DVector momAtVtx(st->momentum().x(),st->momentum().y(),st->momentum().z()); - Basic3DVector vert = (Basic3DVector) svColl[st->vertIndex()].position(); - - std::pair params = parametersAtClosestApproach(vert, momAtVtx, st->charge(), bs); - if (params.first){ - TrackBase::ParameterVector sParameters = params.second; - - TrackBase::ParameterVector diffParameters = rParameters - sParameters; - diffParameters[2] = reco::deltaPhi(diffParameters[2],0.f); - double chi2 = ROOT::Math::Dot(diffParameters * recoTrackCovMatrix, diffParameters); - chi2/=5; - if (chi2& momAtVtx, @@ -90,34 +19,6 @@ double TrackAssociatorByChi2Impl::getChi2(const TrackBase::ParameterVector& rPar } -double TrackAssociatorByChi2Impl::associateRecoToSim( TrackCollection::const_iterator rt, - TrackingParticleCollection::const_iterator tp, - const reco::BeamSpot& bs) const{ - TrackBase::ParameterVector rParameters = rt->parameters(); - TrackBase::CovarianceMatrix recoTrackCovMatrix = rt->covariance(); - if (onlyDiagonal){ - for (unsigned int i=0;i<5;i++){ - for (unsigned int j=0;j<5;j++){ - if (i!=j) recoTrackCovMatrix(i,j)=0; - } - } - } - - recoTrackCovMatrix.Invert(); - Basic3DVector momAtVtx(tp->momentum().x(),tp->momentum().y(),tp->momentum().z()); - Basic3DVector vert(tp->vertex().x(),tp->vertex().y(),tp->vertex().z()); - int charge = tp->charge(); - return getChi2(rParameters,recoTrackCovMatrix,momAtVtx,vert,charge,bs); -} - -pair -TrackAssociatorByChi2Impl::parametersAtClosestApproach(const Basic3DVector& vertex, - const Basic3DVector& momAtVtx, - float charge, - const BeamSpot& bs) const{ - return reco::trackingParametersAtClosestApproachToBeamSpot(vertex,momAtVtx,charge, *theMF, bs); -} - RecoToSimCollection TrackAssociatorByChi2Impl::associateRecoToSim(const edm::RefToBaseVector& tC, const edm::RefVector& tPCH) const { diff --git a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.h b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.h index 5ef9ace156a47..21582889ea812 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.h +++ b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.h @@ -88,27 +88,6 @@ class TrackAssociatorByChi2Impl : public reco::TrackToTrackingParticleAssociator } private: - - /// propagate the track parameters of TrackinParticle from production vertex to the point of closest approach to the beam line. - std::pair parametersAtClosestApproach(const Basic3DVector&,// vertex - const Basic3DVector&,// momAtVtx - float,// charge - const reco::BeamSpot&) const;//beam spot - - /// compare reco::TrackCollection and edm::SimTrackContainer iterators: returns the chi2 - double compareTracksParam(reco::TrackCollection::const_iterator, - edm::SimTrackContainer::const_iterator, - const math::XYZTLorentzVectorD&, - const GlobalVector&, - const reco::TrackBase::CovarianceMatrix&, - const reco::BeamSpot&) const; - - /// compare collections reco to sim - RecoToSimPairAssociation compareTracksParam(const reco::TrackCollection&, - const edm::SimTrackContainer&, - const edm::SimVertexContainer&, - const reco::BeamSpot&) const; - /// basic method where chi2 is computed double getChi2(const reco::TrackBase::ParameterVector& rParameters, const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, @@ -117,12 +96,6 @@ class TrackAssociatorByChi2Impl : public reco::TrackToTrackingParticleAssociator int charge, const reco::BeamSpot&) const; - /// compare reco::TrackCollection and TrackingParticleCollection iterators: returns the chi2 - double associateRecoToSim(reco::TrackCollection::const_iterator, - TrackingParticleCollection::const_iterator, - const reco::BeamSpot&) const; - - const MagneticField* theMF; const reco::BeamSpot* theBeamSpot; double chi2cut; From 9368f70ec4e7408b22bcd30fe4afe0c506191c27 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Tue, 11 Jul 2017 11:36:53 +0200 Subject: [PATCH 14/24] Rename getChi2() to trackAssociationChi2() and move to SimTracker/TrackAssociation --- .../interface/trackAssociationChi2.h | 20 +++++++++++++++++++ .../src/trackAssociationChi2.cc} | 16 +++++++-------- .../plugins/BuildFile.xml | 1 + .../plugins/TrackAssociatorByChi2Impl.cc | 5 +++-- .../plugins/TrackGenAssociatorByChi2Impl.cc | 4 ++-- .../plugins/getChi2.h | 20 ------------------- 6 files changed, 34 insertions(+), 32 deletions(-) create mode 100644 SimTracker/TrackAssociation/interface/trackAssociationChi2.h rename SimTracker/{TrackAssociatorProducers/plugins/getChi2.cc => TrackAssociation/src/trackAssociationChi2.cc} (77%) delete mode 100644 SimTracker/TrackAssociatorProducers/plugins/getChi2.h diff --git a/SimTracker/TrackAssociation/interface/trackAssociationChi2.h b/SimTracker/TrackAssociation/interface/trackAssociationChi2.h new file mode 100644 index 0000000000000..4ef599a97e6f2 --- /dev/null +++ b/SimTracker/TrackAssociation/interface/trackAssociationChi2.h @@ -0,0 +1,20 @@ +#ifndef SimTracker_TrackAssociation_trackAssociationChi2_h +#define SimTracker_TrackAssociation_trackAssociationChi2_h + +#include "DataFormats/TrackReco/interface/TrackBase.h" +#include "MagneticField/Engine/interface/MagneticField.h" +#include "DataFormats/BeamSpot/interface/BeamSpot.h" +#include "DataFormats/GeometryVector/interface/Basic3DVector.h" + +namespace track_associator { + /// basic method where chi2 is computed + double trackAssociationChi2(const reco::TrackBase::ParameterVector& rParameters, + const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, + const Basic3DVector& momAtVtx, + const Basic3DVector& vert, + int charge, + const MagneticField&, + const reco::BeamSpot&) ; +} + +#endif diff --git a/SimTracker/TrackAssociatorProducers/plugins/getChi2.cc b/SimTracker/TrackAssociation/src/trackAssociationChi2.cc similarity index 77% rename from SimTracker/TrackAssociatorProducers/plugins/getChi2.cc rename to SimTracker/TrackAssociation/src/trackAssociationChi2.cc index f6253da6da056..56b5439f01962 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/getChi2.cc +++ b/SimTracker/TrackAssociation/src/trackAssociationChi2.cc @@ -1,16 +1,16 @@ -#include "getChi2.h" +#include "SimTracker/TrackAssociation/interface/trackAssociationChi2.h" #include "DataFormats/Math/interface/deltaPhi.h" #include "TrackingTools/PatternTools/interface/trackingParametersAtClosestApproachToBeamSpot.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" namespace track_associator { - double getChi2(const reco::TrackBase::ParameterVector& rParameters, - const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, - const Basic3DVector& momAtVtx, - const Basic3DVector& vert, - int charge, - const MagneticField& magfield, - const reco::BeamSpot& bs) { + double trackAssociationChi2(const reco::TrackBase::ParameterVector& rParameters, + const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, + const Basic3DVector& momAtVtx, + const Basic3DVector& vert, + int charge, + const MagneticField& magfield, + const reco::BeamSpot& bs) { double chi2 = 10000000000.; diff --git a/SimTracker/TrackAssociatorProducers/plugins/BuildFile.xml b/SimTracker/TrackAssociatorProducers/plugins/BuildFile.xml index ca1e9b4c294f6..7acef38f407b1 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/BuildFile.xml +++ b/SimTracker/TrackAssociatorProducers/plugins/BuildFile.xml @@ -4,6 +4,7 @@ + diff --git a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc index fb3206822c7c8..d3b27276f5796 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc +++ b/SimTracker/TrackAssociatorProducers/plugins/TrackAssociatorByChi2Impl.cc @@ -3,7 +3,8 @@ #include "DataFormats/Math/interface/deltaPhi.h" #include "DataFormats/GeometrySurface/interface/Line.h" -#include "getChi2.h" +#include "SimTracker/TrackAssociation/interface/trackAssociationChi2.h" + using namespace edm; using namespace reco; @@ -15,7 +16,7 @@ double TrackAssociatorByChi2Impl::getChi2(const TrackBase::ParameterVector& rPar const Basic3DVector& vert, int charge, const reco::BeamSpot& bs) const{ - return track_associator::getChi2(rParameters, recoTrackCovMatrix,momAtVtx, vert, charge, *theMF, bs); + return track_associator::trackAssociationChi2(rParameters, recoTrackCovMatrix,momAtVtx, vert, charge, *theMF, bs); } diff --git a/SimTracker/TrackAssociatorProducers/plugins/TrackGenAssociatorByChi2Impl.cc b/SimTracker/TrackAssociatorProducers/plugins/TrackGenAssociatorByChi2Impl.cc index fcc6cc109c1f7..6a5c40087392e 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/TrackGenAssociatorByChi2Impl.cc +++ b/SimTracker/TrackAssociatorProducers/plugins/TrackGenAssociatorByChi2Impl.cc @@ -3,7 +3,7 @@ #include "DataFormats/GeometrySurface/interface/Line.h" -#include "getChi2.h" +#include "SimTracker/TrackAssociation/interface/trackAssociationChi2.h" using namespace edm; using namespace reco; @@ -15,7 +15,7 @@ double TrackGenAssociatorByChi2Impl::getChi2(const TrackBase::ParameterVector& r const Basic3DVector& vert, int charge, const reco::BeamSpot& bs) const{ - return track_associator::getChi2(rParameters, recoTrackCovMatrix,momAtVtx, vert, charge, *theMF, bs); + return track_associator::trackAssociationChi2(rParameters, recoTrackCovMatrix,momAtVtx, vert, charge, *theMF, bs); } RecoToGenCollection TrackGenAssociatorByChi2Impl::associateRecoToGen(const edm::RefToBaseVector& tC, diff --git a/SimTracker/TrackAssociatorProducers/plugins/getChi2.h b/SimTracker/TrackAssociatorProducers/plugins/getChi2.h deleted file mode 100644 index 7039d0c1607ed..0000000000000 --- a/SimTracker/TrackAssociatorProducers/plugins/getChi2.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef getChi2_h -#define getChi2_h - -#include "DataFormats/TrackReco/interface/TrackBase.h" -#include "MagneticField/Engine/interface/MagneticField.h" -#include "DataFormats/BeamSpot/interface/BeamSpot.h" -#include "DataFormats/GeometryVector/interface/Basic3DVector.h" - -namespace track_associator { - /// basic method where chi2 is computed - double getChi2(const reco::TrackBase::ParameterVector& rParameters, - const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, - const Basic3DVector& momAtVtx, - const Basic3DVector& vert, - int charge, - const MagneticField&, - const reco::BeamSpot&) ; -} - -#endif From b4593b38c49a4273458521bed646161c70e59ac3 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Tue, 11 Jul 2017 15:23:22 +0200 Subject: [PATCH 15/24] Add track-TP association chi2 to TrackingNtuple --- .../interface/trackAssociationChi2.h | 16 +++- .../src/trackAssociationChi2.cc | 31 ++++++- .../RecoTrack/plugins/TrackingNtuple.cc | 82 ++++++++++++------- .../python/plotting/ntupleDataFormat.py | 25 ++++-- 4 files changed, 116 insertions(+), 38 deletions(-) diff --git a/SimTracker/TrackAssociation/interface/trackAssociationChi2.h b/SimTracker/TrackAssociation/interface/trackAssociationChi2.h index 4ef599a97e6f2..fd4e7831b0c79 100644 --- a/SimTracker/TrackAssociation/interface/trackAssociationChi2.h +++ b/SimTracker/TrackAssociation/interface/trackAssociationChi2.h @@ -5,6 +5,7 @@ #include "MagneticField/Engine/interface/MagneticField.h" #include "DataFormats/BeamSpot/interface/BeamSpot.h" #include "DataFormats/GeometryVector/interface/Basic3DVector.h" +#include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h" namespace track_associator { /// basic method where chi2 is computed @@ -13,8 +14,19 @@ namespace track_associator { const Basic3DVector& momAtVtx, const Basic3DVector& vert, int charge, - const MagneticField&, - const reco::BeamSpot&) ; + const MagneticField& magfield, + const reco::BeamSpot& bs) ; + + double trackAssociationChi2(const reco::TrackBase::ParameterVector& rParameters, + const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, + const TrackingParticle& trackingParticle, + const MagneticField& magfield, + const reco::BeamSpot& bs); + + double trackAssociationChi2(const reco::TrackBase& track, + const TrackingParticle& trackingParticle, + const MagneticField& magfield, + const reco::BeamSpot& bs); } #endif diff --git a/SimTracker/TrackAssociation/src/trackAssociationChi2.cc b/SimTracker/TrackAssociation/src/trackAssociationChi2.cc index 56b5439f01962..493a71fd5c8a9 100644 --- a/SimTracker/TrackAssociation/src/trackAssociationChi2.cc +++ b/SimTracker/TrackAssociation/src/trackAssociationChi2.cc @@ -4,6 +4,8 @@ #include "FWCore/MessageLogger/interface/MessageLogger.h" namespace track_associator { + constexpr double invalidChi2 = 10000000000.; + double trackAssociationChi2(const reco::TrackBase::ParameterVector& rParameters, const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, const Basic3DVector& momAtVtx, @@ -12,7 +14,7 @@ namespace track_associator { const MagneticField& magfield, const reco::BeamSpot& bs) { - double chi2 = 10000000000.; + double chi2 = invalidChi2; std::pair params = reco::trackingParametersAtClosestApproachToBeamSpot(vert, momAtVtx, charge, magfield, bs); if (params.first){ @@ -41,4 +43,31 @@ namespace track_associator { } return chi2; } + + double trackAssociationChi2(const reco::TrackBase::ParameterVector& rParameters, + const reco::TrackBase::CovarianceMatrix& recoTrackCovMatrix, + const TrackingParticle& trackingParticle, + const MagneticField& magfield, + const reco::BeamSpot& bs) { + const int charge = trackingParticle.charge(); + if(charge==0) + return invalidChi2; + + const auto tpMom = trackingParticle.momentum(); + Basic3DVector momAtVtx(tpMom.x(), tpMom.y(), tpMom.z()); + Basic3DVector vert(trackingParticle.vertex()); + + return trackAssociationChi2(rParameters, recoTrackCovMatrix, momAtVtx, vert, charge, magfield, bs); + } + + + double trackAssociationChi2(const reco::TrackBase& track, + const TrackingParticle& trackingParticle, + const MagneticField& magfield, + const reco::BeamSpot& bs) { + auto cov = track.covariance(); + cov.Invert(); + + return trackAssociationChi2(track.parameters(), cov, trackingParticle, magfield, bs); + } } diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 28156e3aac291..f62544b18f6f5 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -76,6 +76,7 @@ #include "SimTracker/TrackerHitAssociation/interface/ClusterTPAssociation.h" #include "SimTracker/TrackAssociation/plugins/ParametersDefinerForTPESProducer.h" #include "SimTracker/TrackAssociation/interface/TrackingParticleIP.h" +#include "SimTracker/TrackAssociation/interface/trackAssociationChi2.h" #include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" #include "SimDataFormats/TrackerDigiSimLink/interface/StripDigiSimLink.h" @@ -621,7 +622,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const reco::TrackToTrackingParticleAssociator& associatorByHits, const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, - const MagneticField *theMF, + const MagneticField& theMF, const std::vector >& monoStereoClusterList, const std::set& hitProductIds, std::map& seedToCollIndex @@ -630,6 +631,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { void fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const MagneticField& mf, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, @@ -1069,13 +1071,16 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_bestSimTrkIdx; std::vector trk_bestSimTrkShareFrac; std::vector trk_bestSimTrkShareFracSimDenom; + std::vector trk_bestSimTrkChi2; std::vector trk_bestFromFirstHitSimTrkIdx; std::vector trk_bestFromFirstHitSimTrkShareFrac; std::vector trk_bestFromFirstHitSimTrkShareFracSimDenom; - std::vector > trk_shareFrac; // second index runs through matched TrackingParticles - std::vector > trk_simTrkIdx; // second index runs through matched TrackingParticles - std::vector > trk_hitIdx; // second index runs through hits - std::vector > trk_hitType; // second index runs through hits + std::vector trk_bestFromFirstHitSimTrkChi2; + std::vector > trk_simTrkShareFrac; // second index runs through matched TrackingParticles + std::vector > trk_simTrkChi2; // second index runs through matched TrackingParticles + std::vector > trk_simTrkIdx; // second index runs through matched TrackingParticles + std::vector > trk_hitIdx; // second index runs through hits + std::vector > trk_hitType; // second index runs through hits //////////////////// // sim tracks // (first) index runs through TrackingParticles @@ -1109,7 +1114,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector sim_nTrackerHits; // links to other objects std::vector > sim_trkIdx; // second index runs through matched tracks - std::vector > sim_shareFrac; // second index runs through matched tracks + std::vector > sim_trkShareFrac; // second index runs through matched tracks std::vector > sim_seedIdx; // second index runs through matched seeds std::vector sim_parentVtxIdx; std::vector > sim_decayVtxIdx; // second index runs through decay vertices @@ -1269,10 +1274,10 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector see_bestFromFirstHitSimTrkIdx; std::vector see_bestFromFirstHitSimTrkShareFrac; std::vector see_bestFromFirstHitSimTrkShareFracSimDenom; - std::vector > see_shareFrac; // second index runs through matched TrackingParticles - std::vector > see_simTrkIdx; // second index runs through matched TrackingParticles - std::vector > see_hitIdx; // second index runs through hits - std::vector > see_hitType; // second index runs through hits + std::vector > see_simTrkShareFrac; // second index runs through matched TrackingParticles + std::vector > see_simTrkIdx; // second index runs through matched TrackingParticles + std::vector > see_hitIdx; // second index runs through hits + std::vector > see_hitType; // second index runs through hits //seed algo offset, index runs through iterations std::vector see_offset ; @@ -1453,8 +1458,9 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): } t->Branch("trk_vtxIdx" , &trk_vtxIdx); if(includeTrackingParticles_) { - t->Branch("trk_shareFrac", &trk_shareFrac); t->Branch("trk_simTrkIdx", &trk_simTrkIdx ); + t->Branch("trk_simTrkShareFrac", &trk_simTrkShareFrac); + t->Branch("trk_simTrkChi2", &trk_simTrkChi2); t->Branch("trk_bestSimTrkIdx", &trk_bestSimTrkIdx); t->Branch("trk_bestFromFirstHitSimTrkIdx", &trk_bestFromFirstHitSimTrkIdx); } @@ -1463,8 +1469,10 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): } t->Branch("trk_bestSimTrkShareFrac", &trk_bestSimTrkShareFrac); t->Branch("trk_bestSimTrkShareFracSimDenom", &trk_bestSimTrkShareFracSimDenom); + t->Branch("trk_bestSimTrkChi2", &trk_bestSimTrkChi2); t->Branch("trk_bestFromFirstHitSimTrkShareFrac", &trk_bestFromFirstHitSimTrkShareFrac); t->Branch("trk_bestFromFirstHitSimTrkShareFracSimDenom", &trk_bestFromFirstHitSimTrkShareFracSimDenom); + t->Branch("trk_bestFromFirstHitSimTrkChi2", &trk_bestFromFirstHitSimTrkChi2); if(includeAllHits_) { t->Branch("trk_hitIdx" , &trk_hitIdx); t->Branch("trk_hitType", &trk_hitType); @@ -1498,7 +1506,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("sim_n3DLay" , &sim_n3DLay ); t->Branch("sim_nTrackerHits", &sim_nTrackerHits); t->Branch("sim_trkIdx" , &sim_trkIdx ); - t->Branch("sim_shareFrac", &sim_shareFrac); + t->Branch("sim_trkShareFrac", &sim_trkShareFrac); if(includeSeeds_) { t->Branch("sim_seedIdx" , &sim_seedIdx ); } @@ -1664,8 +1672,8 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("see_nCands" , &see_nCands ); t->Branch("see_trkIdx" , &see_trkIdx ); if(includeTrackingParticles_) { - t->Branch("see_shareFrac", &see_shareFrac); t->Branch("see_simTrkIdx", &see_simTrkIdx ); + t->Branch("see_simTrkShareFrac", &see_simTrkShareFrac); t->Branch("see_bestSimTrkIdx", &see_bestSimTrkIdx); t->Branch("see_bestFromFirstHitSimTrkIdx", &see_bestFromFirstHitSimTrkIdx); } @@ -1791,11 +1799,14 @@ void TrackingNtuple::clearVariables() { trk_bestSimTrkIdx.clear(); trk_bestSimTrkShareFrac.clear(); trk_bestSimTrkShareFracSimDenom.clear(); + trk_bestSimTrkChi2.clear(); trk_bestFromFirstHitSimTrkIdx.clear(); trk_bestFromFirstHitSimTrkShareFrac.clear(); trk_bestFromFirstHitSimTrkShareFracSimDenom.clear(); - trk_shareFrac.clear(); + trk_bestFromFirstHitSimTrkChi2.clear(); trk_simTrkIdx.clear(); + trk_simTrkShareFrac.clear(); + trk_simTrkChi2.clear(); trk_hitIdx .clear(); trk_hitType .clear(); //sim tracks @@ -1827,7 +1838,7 @@ void TrackingNtuple::clearVariables() { sim_nTrackerHits.clear(); sim_trkIdx .clear(); sim_seedIdx .clear(); - sim_shareFrac.clear(); + sim_trkShareFrac.clear(); sim_parentVtxIdx.clear(); sim_decayVtxIdx.clear(); sim_simHitIdx .clear(); @@ -1968,8 +1979,8 @@ void TrackingNtuple::clearVariables() { see_bestFromFirstHitSimTrkIdx.clear(); see_bestFromFirstHitSimTrkShareFrac.clear(); see_bestFromFirstHitSimTrkShareFracSimDenom.clear(); - see_shareFrac.clear(); see_simTrkIdx.clear(); + see_simTrkShareFrac.clear(); see_hitIdx .clear(); see_hitType .clear(); //seed algo offset @@ -2007,8 +2018,9 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS using namespace reco; using namespace std; - edm::ESHandle theMF; - iSetup.get().get(theMF); + edm::ESHandle mfHandle; + iSetup.get().get(mfHandle); + const auto& mf = *mfHandle; edm::ESHandle theTTRHBuilder; iSetup.get().get(builderName_,theTTRHBuilder); @@ -2142,7 +2154,7 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS //seeds if(includeSeeds_) { - fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, clusterToTPMap, *theTTRHBuilder, theMF.product(), monoStereoClusterList, hitProductIds, seedCollToOffset); + fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, clusterToTPMap, *theTTRHBuilder, mf, monoStereoClusterList, hitProductIds, seedCollToOffset); } //tracks @@ -2178,7 +2190,7 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle vertices; iEvent.getByToken(vertexToken_, vertices); - fillTracks(trackRefs, tpCollection, tpKeyToIndex, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); + fillTracks(trackRefs, tpCollection, tpKeyToIndex, mf, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); //tracking particles //sort association maps with simHits @@ -2684,7 +2696,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, const reco::TrackToTrackingParticleAssociator& associatorByHits, const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, - const MagneticField *theMF, + const MagneticField& theMF, const std::vector >& monoStereoClusterList, const std::set& hitProductIds, std::map& seedCollToOffset @@ -2750,13 +2762,13 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, if(seedRef.id() != id) throw cms::Exception("LogicError") << "All tracks in 'TracksFromSeeds' collection should point to seeds in the same collection. Now the element 0 had ProductID " << id << " while the element " << seedTrackRef.key() << " had " << seedTrackRef.id() << ". The source collection is " << labels.module << "."; - std::vector sharedFraction; std::vector tpIdx; + std::vector sharedFraction; auto foundTPs = recSimColl.find(seedTrackRef); if (foundTPs != recSimColl.end()) { for(const auto tpQuality: foundTPs->val) { - sharedFraction.push_back(tpQuality.second); tpIdx.push_back( tpKeyToIndex.at( tpQuality.first.key() ) ); + sharedFraction.push_back(tpQuality.second); } } @@ -2812,8 +2824,8 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, see_trkIdx .push_back(-1); // to be set correctly in fillTracks if(includeTrackingParticles_) { - see_shareFrac.push_back( sharedFraction ); see_simTrkIdx.push_back( tpIdx ); + see_simTrkShareFrac.push_back( sharedFraction ); see_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); see_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.key >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.key) : -1); } @@ -2828,7 +2840,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, /// Hmm, the following could make sense instead of plain failing if propagation to beam line fails /* TransientTrackingRecHit::RecHitPointer lastRecHit = theTTRHBuilder.build(&*(seed.recHits().second-1)); - TrajectoryStateOnSurface state = trajectoryStateTransform::transientState( itSeed->startingState(), lastRecHit->surface(), theMF); + TrajectoryStateOnSurface state = trajectoryStateTransform::transientState( itSeed->startingState(), lastRecHit->surface(), &theMF); float pt = state.globalParameters().momentum().perp(); float eta = state.globalParameters().momentum().eta(); float phi = state.globalParameters().momentum().phi(); @@ -2974,6 +2986,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const MagneticField& mf, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, const reco::TrackToTrackingParticleAssociator& associatorByHits, @@ -3004,11 +3017,16 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, int nHits = itTrack->numberOfValidHits(); const reco::HitPattern& hp = itTrack->hitPattern(); + const auto& tkParam = itTrack->parameters(); + auto tkCov = itTrack->covariance(); + tkCov.Invert(); + // Standard track-TP matching int nSimHits = 0; bool isSimMatched = false; - std::vector sharedFraction; std::vector tpIdx; + std::vector sharedFraction; + std::vector tpChi2; auto foundTPs = recSimColl.find(itTrack); if (foundTPs != recSimColl.end()) { if (!foundTPs->val.empty()) { @@ -3016,8 +3034,9 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, isSimMatched = true; } for(const auto tpQuality: foundTPs->val) { - sharedFraction.push_back(tpQuality.second); tpIdx.push_back( tpKeyToIndex.at( tpQuality.first.key() ) ); + sharedFraction.push_back(tpQuality.second); + tpChi2.push_back(track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpIdx.back()]), mf, bs)); } } @@ -3025,10 +3044,12 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; + const float bestChi2 = bestKeyCount.key >= 0 ? track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]), mf, bs) : -1; // Another way starting from the first hit of the track const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; + const float bestFirstHitChi2 = bestFirstHitKeyCount.key >= 0 ? track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]), mf, bs) : -1; float chi2_1Dmod = chi2; @@ -3119,7 +3140,8 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, trk_vtxIdx .push_back(-1); // to be set correctly in fillVertices if(includeTrackingParticles_) { trk_simTrkIdx.push_back(tpIdx); - trk_shareFrac.push_back(sharedFraction); + trk_simTrkShareFrac.push_back(sharedFraction); + trk_simTrkChi2.push_back(tpChi2); trk_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); trk_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.key >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.key) : -1); } @@ -3128,8 +3150,10 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } trk_bestSimTrkShareFrac.push_back(bestShareFrac); trk_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); + trk_bestSimTrkChi2.push_back(bestChi2); trk_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); trk_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); + trk_bestFromFirstHitSimTrkChi2.push_back(bestFirstHitChi2); LogTrace("TrackingNtuple") << "Track #" << itTrack.key() << " with q=" << charge << ", pT=" << pt << " GeV, eta: " << eta << ", phi: " << phi @@ -3283,7 +3307,7 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: sim_phi .push_back(tp->phi()); sim_q .push_back(tp->charge()); sim_trkIdx .push_back(tkIdx); - sim_shareFrac.push_back(sharedFraction); + sim_trkShareFrac.push_back(sharedFraction); sim_parentVtxIdx.push_back( tvKeyToIndex.at(tp->parentVertex().key()) ); std::vector decayIdx; for(const auto& v: tp->decayVertices()) diff --git a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py index b13444e208c41..e4ac0a4fbeef2 100644 --- a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py +++ b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py @@ -573,14 +573,18 @@ def __init__(self, tree, index, tpindex, prefix): self._tpindex = tpindex def __getattr__(self, attr): - """Custom __getattr__ because of the second index needed to access the branch.""" - val = super(TrackingParticleMatchInfo, self).__getattr__(attr)()[self._tpindex] + """Custom __getattr__ because of the second index needed to access the branch. + + Note that when mapping the 'attr' to a branch, a 'simTrk' is + prepended and the first letter of 'attr' is turned to upper + case. + """ + val = super(TrackingParticleMatchInfo, self).__getattr__("simTrk"+attr[0].upper()+attr[1:])()[self._tpindex] return lambda: val def trackingParticle(self): """Returns matched TrackingParticle.""" - self._checkIsValid() - return TrackingParticle(self._tree, getattr(self._tree, self._prefix+"_simTrkIdx")[self._index][self._tpindex]) + return TrackingParticle(self._tree, self.idx()) class TrackMatchInfo(_Object): """Class representing a match to a Track. @@ -600,10 +604,19 @@ def __init__(self, tree, index, trkindex, prefix): super(TrackMatchInfo, self).__init__(tree, index, prefix) self._trkindex = trkindex + def __getattr__(self, attr): + """Custom __getattr__ because of the second index needed to access the branch. + + Note that when mapping the 'attr' to a branch, a 'trk' is + prepended and the first letter of 'attr' is turned to upper + case. + """ + val = super(TrackMatchInfo, self).__getattr__("trk"+attr[0].upper()+attr[1:])()[self._trkindex] + return lambda: val + def track(self): """Returns matched Track.""" - self._checkIsValid() - return Track(self._tree, getattr(self._tree, self._prefix+"_trkIdx")[self._index][self._trkindex]) + return Track(self._tree, self.idx()) class SeedMatchInfo(_Object): """Class representing a match to a Seed. From ac91d91bf4e1ea19b52030ed93cdde1107e925ff Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Tue, 11 Jul 2017 16:03:34 +0200 Subject: [PATCH 16/24] Add association chi2 to printout --- Validation/RecoTrack/python/plotting/ntupleDataFormat.py | 6 ++++++ .../RecoTrack/python/plotting/ntuplePrintersDiff.py | 8 +++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py index e4ac0a4fbeef2..f70e1e425622d 100644 --- a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py +++ b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py @@ -336,6 +336,9 @@ def bestMatchingTrackingParticleShareFrac(self): def bestMatchingTrackingParticleShareFracSimDenom(self): return self.bestSimTrkShareFracSimDenom() + def bestMatchingTrackingParticleChi2(self): + return self.bestSimTrkChi2() + def bestMatchingTrackingParticleFromFirstHit(self): """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle. @@ -355,6 +358,9 @@ def bestMatchingTrackingParticleFromFirstHitShareFrac(self): def bestMatchingTrackingParticleFromFirstHitShareFracSimDenom(self): return self.bestFromFirstHitSimTrkShareFracSimDenom() + def bestMatchingTrackingParticleFromFirstHitChi2(self): + return self.bestFromFirstHitSimTrkChi2() + ########## class TrackingNtuple(object): """Class abstracting the whole ntuple/TTree. diff --git a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py index 808a371e31231..c350a34c4f927 100644 --- a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py +++ b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py @@ -925,9 +925,11 @@ def printHeader(self, track): lst.append(self._prefix+" is %s algo %s originalAlgo %s%s stopReason %s" % (hp, Algo.toString(track.algo()), Algo.toString(track.originalAlgo()), algoMaskStr, StopReason.toString(track.stopReason()))) lst.append(self._prefix+" px %f py %f pz %f p %f" % (track.px(), track.py(), track.pz(), math.sqrt(track.px()**2+track.py()**2+track.pz()**2))) if self._trackingParticleMatchPrinter.bestMatchingTrackingParticle(): - ptPull = track.ptPull() - if ptPull is not None: - lst.append(self._prefix+" pulls pt %f dxy %f dz %f" % (ptPull, track.dxyPull(), track.dzPull())) + bestTP = track.bestMatchingTrackingParticle() + if bestTP: + lst.append(self._prefix+" best-matching TP %d" % bestTP.index()) + lst.append(self._prefix+" matching chi2 %f" % track.bestMatchingTrackingParticleChi2()) + lst.append(self._prefix+" pulls pt %f theta %f phi %f dxy %f dz %f" % (track.ptPull(), track.thetaPull(), track.phiPull(), track.dxyPull(), track.dzPull())) return lst def printHits(self, track): From 575db1a03ee87412713b413fe4861c4b77e6eb40 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 12 Jul 2017 09:23:26 +0200 Subject: [PATCH 17/24] Make it explicit that trackAssociationChi2() returns normalized chi2 --- .../RecoTrack/plugins/TrackingNtuple.cc | 24 +++++++++---------- .../python/plotting/ntupleDataFormat.py | 8 +++---- .../python/plotting/ntuplePrintersDiff.py | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index f62544b18f6f5..b52bc7f0bdb32 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -1071,13 +1071,13 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_bestSimTrkIdx; std::vector trk_bestSimTrkShareFrac; std::vector trk_bestSimTrkShareFracSimDenom; - std::vector trk_bestSimTrkChi2; + std::vector trk_bestSimTrkNChi2; std::vector trk_bestFromFirstHitSimTrkIdx; std::vector trk_bestFromFirstHitSimTrkShareFrac; std::vector trk_bestFromFirstHitSimTrkShareFracSimDenom; - std::vector trk_bestFromFirstHitSimTrkChi2; + std::vector trk_bestFromFirstHitSimTrkNChi2; std::vector > trk_simTrkShareFrac; // second index runs through matched TrackingParticles - std::vector > trk_simTrkChi2; // second index runs through matched TrackingParticles + std::vector > trk_simTrkNChi2; // second index runs through matched TrackingParticles std::vector > trk_simTrkIdx; // second index runs through matched TrackingParticles std::vector > trk_hitIdx; // second index runs through hits std::vector > trk_hitType; // second index runs through hits @@ -1460,7 +1460,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): if(includeTrackingParticles_) { t->Branch("trk_simTrkIdx", &trk_simTrkIdx ); t->Branch("trk_simTrkShareFrac", &trk_simTrkShareFrac); - t->Branch("trk_simTrkChi2", &trk_simTrkChi2); + t->Branch("trk_simTrkNChi2", &trk_simTrkNChi2); t->Branch("trk_bestSimTrkIdx", &trk_bestSimTrkIdx); t->Branch("trk_bestFromFirstHitSimTrkIdx", &trk_bestFromFirstHitSimTrkIdx); } @@ -1469,10 +1469,10 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): } t->Branch("trk_bestSimTrkShareFrac", &trk_bestSimTrkShareFrac); t->Branch("trk_bestSimTrkShareFracSimDenom", &trk_bestSimTrkShareFracSimDenom); - t->Branch("trk_bestSimTrkChi2", &trk_bestSimTrkChi2); + t->Branch("trk_bestSimTrkNChi2", &trk_bestSimTrkNChi2); t->Branch("trk_bestFromFirstHitSimTrkShareFrac", &trk_bestFromFirstHitSimTrkShareFrac); t->Branch("trk_bestFromFirstHitSimTrkShareFracSimDenom", &trk_bestFromFirstHitSimTrkShareFracSimDenom); - t->Branch("trk_bestFromFirstHitSimTrkChi2", &trk_bestFromFirstHitSimTrkChi2); + t->Branch("trk_bestFromFirstHitSimTrkNChi2", &trk_bestFromFirstHitSimTrkNChi2); if(includeAllHits_) { t->Branch("trk_hitIdx" , &trk_hitIdx); t->Branch("trk_hitType", &trk_hitType); @@ -1799,14 +1799,14 @@ void TrackingNtuple::clearVariables() { trk_bestSimTrkIdx.clear(); trk_bestSimTrkShareFrac.clear(); trk_bestSimTrkShareFracSimDenom.clear(); - trk_bestSimTrkChi2.clear(); + trk_bestSimTrkNChi2.clear(); trk_bestFromFirstHitSimTrkIdx.clear(); trk_bestFromFirstHitSimTrkShareFrac.clear(); trk_bestFromFirstHitSimTrkShareFracSimDenom.clear(); - trk_bestFromFirstHitSimTrkChi2.clear(); + trk_bestFromFirstHitSimTrkNChi2.clear(); trk_simTrkIdx.clear(); trk_simTrkShareFrac.clear(); - trk_simTrkChi2.clear(); + trk_simTrkNChi2.clear(); trk_hitIdx .clear(); trk_hitType .clear(); //sim tracks @@ -3141,7 +3141,7 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, if(includeTrackingParticles_) { trk_simTrkIdx.push_back(tpIdx); trk_simTrkShareFrac.push_back(sharedFraction); - trk_simTrkChi2.push_back(tpChi2); + trk_simTrkNChi2.push_back(tpChi2); trk_bestSimTrkIdx.push_back(bestKeyCount.key >= 0 ? tpKeyToIndex.at(bestKeyCount.key) : -1); trk_bestFromFirstHitSimTrkIdx.push_back(bestFirstHitKeyCount.key >= 0 ? tpKeyToIndex.at(bestFirstHitKeyCount.key) : -1); } @@ -3150,10 +3150,10 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } trk_bestSimTrkShareFrac.push_back(bestShareFrac); trk_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); - trk_bestSimTrkChi2.push_back(bestChi2); + trk_bestSimTrkNChi2.push_back(bestChi2); trk_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); trk_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); - trk_bestFromFirstHitSimTrkChi2.push_back(bestFirstHitChi2); + trk_bestFromFirstHitSimTrkNChi2.push_back(bestFirstHitChi2); LogTrace("TrackingNtuple") << "Track #" << itTrack.key() << " with q=" << charge << ", pT=" << pt << " GeV, eta: " << eta << ", phi: " << phi diff --git a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py index f70e1e425622d..8addb7b8ed8c8 100644 --- a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py +++ b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py @@ -336,8 +336,8 @@ def bestMatchingTrackingParticleShareFrac(self): def bestMatchingTrackingParticleShareFracSimDenom(self): return self.bestSimTrkShareFracSimDenom() - def bestMatchingTrackingParticleChi2(self): - return self.bestSimTrkChi2() + def bestMatchingTrackingParticleNormalizedChi2(self): + return self.bestSimTrkNChi2() def bestMatchingTrackingParticleFromFirstHit(self): """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle. @@ -358,8 +358,8 @@ def bestMatchingTrackingParticleFromFirstHitShareFrac(self): def bestMatchingTrackingParticleFromFirstHitShareFracSimDenom(self): return self.bestFromFirstHitSimTrkShareFracSimDenom() - def bestMatchingTrackingParticleFromFirstHitChi2(self): - return self.bestFromFirstHitSimTrkChi2() + def bestMatchingTrackingParticleFromFirstHitNormalizedChi2(self): + return self.bestFromFirstHitSimTrkNChi2() ########## class TrackingNtuple(object): diff --git a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py index c350a34c4f927..127c60d4b3184 100644 --- a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py +++ b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py @@ -928,7 +928,7 @@ def printHeader(self, track): bestTP = track.bestMatchingTrackingParticle() if bestTP: lst.append(self._prefix+" best-matching TP %d" % bestTP.index()) - lst.append(self._prefix+" matching chi2 %f" % track.bestMatchingTrackingParticleChi2()) + lst.append(self._prefix+" matching chi2/ndof %f" % track.bestMatchingTrackingParticleNormalizedChi2()) lst.append(self._prefix+" pulls pt %f theta %f phi %f dxy %f dz %f" % (track.ptPull(), track.thetaPull(), track.phiPull(), track.dxyPull(), track.dzPull())) return lst From 6aeb3d8b01de39ea576b9b7d80a1f12e5b7f0bc4 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 12 Jul 2017 09:51:13 +0200 Subject: [PATCH 18/24] Add back number of clusters associated to a TrackingParticle --- .../RecoTrack/plugins/TrackingNtuple.cc | 56 ++++++++++++++++--- .../python/plotting/ntupleDataFormat.py | 21 ++++++- .../python/plotting/ntuplePrintersDiff.py | 3 +- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index b52bc7f0bdb32..e82cee64c8275 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -112,6 +112,7 @@ namespace { using TrackingVertexRefKeyToIndex = TrackingParticleRefKeyToIndex; using SimHitFullKey = std::pair; using SimHitRefKeyToIndex = std::map; + using TrackingParticleRefKeyToCount = TrackingParticleRefKeyToIndex; std::string subdetstring(int subdet) { @@ -631,6 +632,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { void fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const MagneticField& mf, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, @@ -657,7 +659,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList + const std::vector& tpHitList, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount ); void fillTrackingParticlesForSeeds(const TrackingParticleRefVector& tpCollection, @@ -1071,10 +1074,12 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_bestSimTrkIdx; std::vector trk_bestSimTrkShareFrac; std::vector trk_bestSimTrkShareFracSimDenom; + std::vector trk_bestSimTrkShareFracSimClusterDenom; std::vector trk_bestSimTrkNChi2; std::vector trk_bestFromFirstHitSimTrkIdx; std::vector trk_bestFromFirstHitSimTrkShareFrac; std::vector trk_bestFromFirstHitSimTrkShareFracSimDenom; + std::vector trk_bestFromFirstHitSimTrkShareFracSimClusterDenom; std::vector trk_bestFromFirstHitSimTrkNChi2; std::vector > trk_simTrkShareFrac; // second index runs through matched TrackingParticles std::vector > trk_simTrkNChi2; // second index runs through matched TrackingParticles @@ -1112,6 +1117,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector sim_n3DLay ; // number of sim hits as calculated in TrackingTruthAccumulator std::vector sim_nTrackerHits; + // number of clusters associated to TP + std::vector sim_nRecoClusters; // links to other objects std::vector > sim_trkIdx; // second index runs through matched tracks std::vector > sim_trkShareFrac; // second index runs through matched tracks @@ -1469,9 +1476,11 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): } t->Branch("trk_bestSimTrkShareFrac", &trk_bestSimTrkShareFrac); t->Branch("trk_bestSimTrkShareFracSimDenom", &trk_bestSimTrkShareFracSimDenom); + t->Branch("trk_bestSimTrkShareFracSimClusterDenom", &trk_bestSimTrkShareFracSimClusterDenom); t->Branch("trk_bestSimTrkNChi2", &trk_bestSimTrkNChi2); t->Branch("trk_bestFromFirstHitSimTrkShareFrac", &trk_bestFromFirstHitSimTrkShareFrac); t->Branch("trk_bestFromFirstHitSimTrkShareFracSimDenom", &trk_bestFromFirstHitSimTrkShareFracSimDenom); + t->Branch("trk_bestFromFirstHitSimTrkShareFracSimClusterDenom", &trk_bestFromFirstHitSimTrkShareFracSimClusterDenom); t->Branch("trk_bestFromFirstHitSimTrkNChi2", &trk_bestFromFirstHitSimTrkNChi2); if(includeAllHits_) { t->Branch("trk_hitIdx" , &trk_hitIdx); @@ -1505,6 +1514,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("sim_nPixelLay", &sim_nPixelLay); t->Branch("sim_n3DLay" , &sim_n3DLay ); t->Branch("sim_nTrackerHits", &sim_nTrackerHits); + t->Branch("sim_nRecoClusters", &sim_nRecoClusters); t->Branch("sim_trkIdx" , &sim_trkIdx ); t->Branch("sim_trkShareFrac", &sim_trkShareFrac); if(includeSeeds_) { @@ -1799,10 +1809,12 @@ void TrackingNtuple::clearVariables() { trk_bestSimTrkIdx.clear(); trk_bestSimTrkShareFrac.clear(); trk_bestSimTrkShareFracSimDenom.clear(); + trk_bestSimTrkShareFracSimClusterDenom.clear(); trk_bestSimTrkNChi2.clear(); trk_bestFromFirstHitSimTrkIdx.clear(); trk_bestFromFirstHitSimTrkShareFrac.clear(); trk_bestFromFirstHitSimTrkShareFracSimDenom.clear(); + trk_bestFromFirstHitSimTrkShareFracSimClusterDenom.clear(); trk_bestFromFirstHitSimTrkNChi2.clear(); trk_simTrkIdx.clear(); trk_simTrkShareFrac.clear(); @@ -1836,6 +1848,7 @@ void TrackingNtuple::clearVariables() { sim_nPixelLay.clear(); sim_n3DLay .clear(); sim_nTrackerHits.clear(); + sim_nRecoClusters.clear(); sim_trkIdx .clear(); sim_seedIdx .clear(); sim_trkShareFrac.clear(); @@ -2092,12 +2105,20 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle simHitsTPAssoc; iEvent.getByToken(simHitTPMapToken_, simHitsTPAssoc); + // TP -> cluster count + TrackingParticleRefKeyToCount tpKeyToClusterCount; + for(const auto& clusterTP: clusterToTPMap) { + tpKeyToClusterCount[clusterTP.second.key()] += 1; + } + // SimHit key -> index mapping SimHitRefKeyToIndex simHitRefKeyToIndex; //make a list to link TrackingParticles to its simhits std::vector tpHitList; + // Count the number of reco cluster per TP + std::set hitProductIds; std::map seedCollToOffset; @@ -2190,12 +2211,12 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS edm::Handle vertices; iEvent.getByToken(vertexToken_, vertices); - fillTracks(trackRefs, tpCollection, tpKeyToIndex, mf, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); + fillTracks(trackRefs, tpCollection, tpKeyToIndex, tpKeyToClusterCount, mf, bs, *vertices, associatorByHits, clusterToTPMap, *theTTRHBuilder, tTopo, hitProductIds, seedCollToOffset, mvaColls, qualColls); //tracking particles //sort association maps with simHits std::sort( tpHitList.begin(), tpHitList.end(), tpHitIndexListLessSort ); - fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList); + fillTrackingParticles(iEvent, iSetup, trackRefs, bs, tpCollection, tvKeyToIndex, associatorByHits, tpHitList, tpKeyToClusterCount); // vertices fillVertices(*vertices, trackRefs); @@ -2986,6 +3007,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, const TrackingParticleRefVector& tpCollection, const TrackingParticleRefKeyToIndex& tpKeyToIndex, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount, const MagneticField& mf, const reco::BeamSpot& bs, const reco::VertexCollection& vertices, @@ -3043,14 +3065,25 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, // Search for a best-matching TrackingParticle for a track const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); - const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; - const float bestChi2 = bestKeyCount.key >= 0 ? track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]), mf, bs) : -1; + float bestShareFracSimDenom = 0; + float bestShareFracSimClusterDenom = 0; + float bestChi2 = -1; + if(bestKeyCount.key >= 0) { + bestShareFracSimDenom = static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()); + bestShareFracSimClusterDenom = static_cast(bestKeyCount.countClusters)/static_cast(tpKeyToClusterCount.at(bestKeyCount.key)); + bestChi2 = track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]), mf, bs); + } // Another way starting from the first hit of the track const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap, tpKeyToIndex); const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); - const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; - const float bestFirstHitChi2 = bestFirstHitKeyCount.key >= 0 ? track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]), mf, bs) : -1; - + float bestFirstHitShareFracSimDenom = 0; + float bestFirstHitShareFracSimClusterDenom = 0; + float bestFirstHitChi2 = -1; + if(bestFirstHitKeyCount.key >= 0) { + bestFirstHitShareFracSimDenom = static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()); + bestFirstHitShareFracSimClusterDenom = static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpKeyToClusterCount.at(bestFirstHitKeyCount.key)); + bestFirstHitChi2 = track_associator::trackAssociationChi2(tkParam, tkCov, *(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]), mf, bs); + } float chi2_1Dmod = chi2; int count1dhits = 0; @@ -3150,9 +3183,11 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } trk_bestSimTrkShareFrac.push_back(bestShareFrac); trk_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); + trk_bestSimTrkShareFracSimClusterDenom.push_back(bestShareFracSimClusterDenom); trk_bestSimTrkNChi2.push_back(bestChi2); trk_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); trk_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); + trk_bestFromFirstHitSimTrkShareFracSimClusterDenom.push_back(bestFirstHitShareFracSimClusterDenom); trk_bestFromFirstHitSimTrkNChi2.push_back(bestFirstHitChi2); LogTrace("TrackingNtuple") << "Track #" << itTrack.key() << " with q=" << charge @@ -3241,7 +3276,8 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: const TrackingParticleRefVector& tpCollection, const TrackingVertexRefKeyToIndex& tvKeyToIndex, const reco::TrackToTrackingParticleAssociator& associatorByHits, - const std::vector& tpHitList + const std::vector& tpHitList, + const TrackingParticleRefKeyToCount& tpKeyToClusterCount ) { edm::ESHandle parametersDefinerH; iSetup.get().get(parametersDefinerName_, parametersDefinerH); @@ -3369,6 +3405,8 @@ void TrackingNtuple::fillTrackingParticles(const edm::Event& iEvent, const edm:: sim_n3DLay .push_back( nSimPixelLayers+nSimStripMonoAndStereoLayers ); sim_nTrackerHits.push_back(tp->numberOfTrackerHits()); + auto found = tpKeyToClusterCount.find(tp.key()); + sim_nRecoClusters.push_back(found != cend(tpKeyToClusterCount) ? found->second : 0); sim_simHitIdx.push_back(hitIdx); } diff --git a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py index 8addb7b8ed8c8..82fb58a2ef78b 100644 --- a/Validation/RecoTrack/python/plotting/ntupleDataFormat.py +++ b/Validation/RecoTrack/python/plotting/ntupleDataFormat.py @@ -331,21 +331,29 @@ def bestMatchingTrackingParticle(self): return TrackingParticle(self._tree, idx) def bestMatchingTrackingParticleShareFrac(self): + """Fraction of shared hits with reco hits as denominator for best-matching TrackingParticle.""" return self.bestSimTrkShareFrac() def bestMatchingTrackingParticleShareFracSimDenom(self): + """Fraction of shared hits with TrackingParticle::numberOfTrackerHits() as denominator for best-matching TrackingParticle.""" return self.bestSimTrkShareFracSimDenom() + def bestMatchingTrackingParticleShareFracSimClusterDenom(self): + """Fraction of shared hits with number of reco clusters associated to a TrackingParticle as denominator for best-matching TrackingParticle.""" + return self.bestSimTrkShareFracSimClusterDenom() + def bestMatchingTrackingParticleNormalizedChi2(self): + """Normalized chi2 calculated from track parameters+covariance matrix and TrackingParticle parameters for best-matching TrackingParticle.""" return self.bestSimTrkNChi2() def bestMatchingTrackingParticleFromFirstHit(self): """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle. Best-matching is defined as the one with largest number of - hits matched to the hits of a track (>= 3). If there are many - fulfilling the same number of hits, the one inducing the - innermost hit of the track is chosen. + hits matched to the hits of a track (>= 3) starting from the + beginning of the track. If there are many fulfilling the same + number of hits, "a first TP" is chosen (a bit arbitrary, but + should be rare". """ idx = self.bestFromFirstHitSimTrkIdx() if idx < 0: @@ -353,12 +361,19 @@ def bestMatchingTrackingParticleFromFirstHit(self): return TrackingParticle(self._tree, idx) def bestMatchingTrackingParticleFromFirstHitShareFrac(self): + """Fraction of shared hits with reco hits as denominator for best-matching TrackingParticle starting from the first hit of a track.""" return self.bestFromFirstHitSimTrkShareFrac() def bestMatchingTrackingParticleFromFirstHitShareFracSimDenom(self): + """Fraction of shared hits with TrackingParticle::numberOfTrackerHits() as denominator for best-matching TrackingParticle starting from the first hit of a track.""" return self.bestFromFirstHitSimTrkShareFracSimDenom() + def bestMatchingTrackingParticleFromFirstHitShareFracSimClusterDenom(self): + """Fraction of shared hits with number of reco clusters associated to a TrackingParticle as denominator for best-matching TrackingParticle starting from the first hit of a track.""" + return self.bestFromFirstHitSimTrkShareFracSimClusterDenom() + def bestMatchingTrackingParticleFromFirstHitNormalizedChi2(self): + """Normalized chi2 calculated from track parameters+covariance matrix and TrackingParticle parameters for best-matching TrackingParticle starting from the first hit of a track.""" return self.bestFromFirstHitSimTrkNChi2() ########## diff --git a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py index 127c60d4b3184..88f44c90a185a 100644 --- a/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py +++ b/Validation/RecoTrack/python/plotting/ntuplePrintersDiff.py @@ -928,6 +928,7 @@ def printHeader(self, track): bestTP = track.bestMatchingTrackingParticle() if bestTP: lst.append(self._prefix+" best-matching TP %d" % bestTP.index()) + lst.append(self._prefix+" shared hits %d reco denom %.3f sim denom %.3f sim cluster denom %.3f" % (track.bestMatchingTrackingParticleShareFrac()*track.nValid(), track.bestMatchingTrackingParticleShareFrac(), track.bestMatchingTrackingParticleShareFracSimDenom(), track.bestMatchingTrackingParticleShareFracSimClusterDenom())) lst.append(self._prefix+" matching chi2/ndof %f" % track.bestMatchingTrackingParticleNormalizedChi2()) lst.append(self._prefix+" pulls pt %f theta %f phi %f dxy %f dz %f" % (track.ptPull(), track.thetaPull(), track.phiPull(), track.dxyPull(), track.dzPull())) return lst @@ -1069,7 +1070,7 @@ def _printTP(self, tp): fromB = " from B hadron" return [ self._prefix+"TP %d pdgId %d%s%s ev:bx %d:%d pT %f eta %f phi %f" % (tp.index(), tp.pdgId(), genIds, fromB, tp.event(), tp.bunchCrossing(), tp.pt(), tp.eta(), tp.phi()), - self._prefix+" pixel hits %d strip hits %d tracker hits %d dxy %f dz %f" % (tp.nPixel(), tp.nStrip(), tp.nTrackerHits(), tp.pca_dxy(), tp.pca_dz()) + self._prefix+" pixel hits %d strip hits %d numberOfTrackerHits() %d associated reco clusters %d dxy %f dz %f" % (tp.nPixel(), tp.nStrip(), tp.nTrackerHits(), tp.nRecoClusters(), tp.pca_dxy(), tp.pca_dz()) ] From a066bfd5e9541ff67ecbeb0d1134d884100a5fb7 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Wed, 12 Jul 2017 09:54:12 +0200 Subject: [PATCH 19/24] Remove shared hit fractions with sim denominator for seeds as they are not interesting Seeding aim is not to find all hits of a TP, so these ratios are not interesting. --- Validation/RecoTrack/plugins/TrackingNtuple.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index e82cee64c8275..f66f29195446a 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -1277,10 +1277,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector see_isTrue; std::vector see_bestSimTrkIdx; std::vector see_bestSimTrkShareFrac; - std::vector see_bestSimTrkShareFracSimDenom; std::vector see_bestFromFirstHitSimTrkIdx; std::vector see_bestFromFirstHitSimTrkShareFrac; - std::vector see_bestFromFirstHitSimTrkShareFracSimDenom; std::vector > see_simTrkShareFrac; // second index runs through matched TrackingParticles std::vector > see_simTrkIdx; // second index runs through matched TrackingParticles std::vector > see_hitIdx; // second index runs through hits @@ -1691,9 +1689,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("see_isTrue", &see_isTrue); } t->Branch("see_bestSimTrkShareFrac", &see_bestSimTrkShareFrac); - t->Branch("see_bestSimTrkShareFracSimDenom", &see_bestSimTrkShareFracSimDenom); t->Branch("see_bestFromFirstHitSimTrkShareFrac", &see_bestFromFirstHitSimTrkShareFrac); - t->Branch("see_bestFromFirstHitSimTrkShareFracSimDenom", &see_bestFromFirstHitSimTrkShareFracSimDenom); if(includeAllHits_) { t->Branch("see_hitIdx" , &see_hitIdx ); t->Branch("see_hitType", &see_hitType ); @@ -1988,10 +1984,8 @@ void TrackingNtuple::clearVariables() { see_trkIdx .clear(); see_bestSimTrkIdx.clear(); see_bestSimTrkShareFrac.clear(); - see_bestSimTrkShareFracSimDenom.clear(); see_bestFromFirstHitSimTrkIdx.clear(); see_bestFromFirstHitSimTrkShareFrac.clear(); - see_bestFromFirstHitSimTrkShareFracSimDenom.clear(); see_simTrkIdx.clear(); see_simTrkShareFrac.clear(); see_hitIdx .clear(); @@ -2797,11 +2791,9 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, const int nHits = seedTrack.numberOfValidHits(); const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap, tpKeyToIndex); const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); - const float bestShareFracSimDenom = bestKeyCount.key >= 0 ? static_cast(bestKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestKeyCount.key)]->numberOfTrackerHits()) : 0; // Another way starting from the first hit of the seed const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(seedTrack, clusterToTPMap, tpKeyToIndex); const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); - const float bestFirstHitShareFracSimDenom = bestFirstHitKeyCount.key >= 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(tpCollection[tpKeyToIndex.at(bestFirstHitKeyCount.key)]->numberOfTrackerHits()) : 0; const bool seedFitOk = !trackFromSeedFitFailed(seedTrack); const int charge = seedTrack.charge(); @@ -2854,9 +2846,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, see_isTrue.push_back(!tpIdx.empty()); } see_bestSimTrkShareFrac.push_back(bestShareFrac); - see_bestSimTrkShareFracSimDenom.push_back(bestShareFracSimDenom); see_bestFromFirstHitSimTrkShareFrac.push_back(bestFirstHitShareFrac); - see_bestFromFirstHitSimTrkShareFracSimDenom.push_back(bestFirstHitShareFracSimDenom); /// Hmm, the following could make sense instead of plain failing if propagation to beam line fails /* From 2c8920b858e025023e356a396dbefafc21c26611 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Mon, 14 Aug 2017 16:45:48 +0200 Subject: [PATCH 20/24] Fix TrackingNtuple to include on-the-fly generated matched strip hits Not including them was actually a serious bug causing memory overwrites... --- .../RecoTrack/plugins/TrackingNtuple.cc | 93 ++++++++++++------- 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index f66f29195446a..3b966be300bc5 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -605,6 +605,12 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector >& monoStereoClusterList ); + size_t addStripMatchedHit(const SiStripMatchedRecHit2D& hit, + const TransientTrackingRecHitBuilder& theTTRHBuilder, + const TrackerTopology& tTopo, + std::vector >& monoStereoClusterList + ); + void fillPhase2OTHits(const edm::Event& iEvent, const ClusterTPAssociation& clusterToTPMap, const TrackingParticleRefKeyToIndex& tpKeyToIndex, @@ -624,7 +630,8 @@ class TrackingNtuple : public edm::one::EDAnalyzer { const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const MagneticField& theMF, - const std::vector >& monoStereoClusterList, + const TrackerTopology& tTopo, + std::vector >& monoStereoClusterList, const std::set& hitProductIds, std::map& seedToCollIndex ); @@ -2169,7 +2176,7 @@ void TrackingNtuple::analyze(const edm::Event& iEvent, const edm::EventSetup& iS //seeds if(includeSeeds_) { - fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, clusterToTPMap, *theTTRHBuilder, mf, monoStereoClusterList, hitProductIds, seedCollToOffset); + fillSeeds(iEvent, tpCollection, tpKeyToIndex, bs, associatorByHits, clusterToTPMap, *theTTRHBuilder, mf, tTopo, monoStereoClusterList, hitProductIds, seedCollToOffset); } //tracks @@ -2598,6 +2605,42 @@ void TrackingNtuple::fillStripRphiStereoHits(const edm::Event& iEvent, fill(*stereoHits, "stripStereoHit"); } + +size_t TrackingNtuple::addStripMatchedHit(const SiStripMatchedRecHit2D& hit, + const TransientTrackingRecHitBuilder& theTTRHBuilder, + const TrackerTopology& tTopo, + std::vector >& monoStereoClusterList + ) { + TransientTrackingRecHit::RecHitPointer ttrh = theTTRHBuilder.build(&hit); + const auto hitId = hit.geographicalId(); + const int lay = tTopo.layer(hitId); + monoStereoClusterList.emplace_back(hit.monoHit().cluster().key(),hit.stereoHit().cluster().key()); + glu_isBarrel .push_back( (hitId.subdetId()==StripSubdetector::TIB || hitId.subdetId()==StripSubdetector::TOB) ); + glu_detId .push_back( tTopo, hitId ); + glu_monoIdx .push_back( hit.monoHit().cluster().key() ); + glu_stereoIdx.push_back( hit.stereoHit().cluster().key() ); + glu_seeIdx .emplace_back(); // filled in fillSeeds + glu_x .push_back( ttrh->globalPosition().x() ); + glu_y .push_back( ttrh->globalPosition().y() ); + glu_z .push_back( ttrh->globalPosition().z() ); + glu_xx .push_back( ttrh->globalPositionError().cxx() ); + glu_xy .push_back( ttrh->globalPositionError().cyx() ); + glu_yy .push_back( ttrh->globalPositionError().cyy() ); + glu_yz .push_back( ttrh->globalPositionError().czy() ); + glu_zz .push_back( ttrh->globalPositionError().czz() ); + glu_zx .push_back( ttrh->globalPositionError().czx() ); + glu_radL .push_back( ttrh->surface()->mediumProperties().radLen() ); + glu_bbxi .push_back( ttrh->surface()->mediumProperties().xi() ); + LogTrace("TrackingNtuple") << "stripMatchedHit" + << " cluster0=" << hit.stereoHit().cluster().key() + << " cluster1=" << hit.monoHit().cluster().key() + << " subdId=" << hitId.subdetId() + << " lay=" << lay + << " rawId=" << hitId.rawId() + << " pos =" << ttrh->globalPosition(); + return glu_isBarrel.size()-1; +} + void TrackingNtuple::fillStripMatchedHits(const edm::Event& iEvent, const TransientTrackingRecHitBuilder& theTTRHBuilder, const TrackerTopology& tTopo, @@ -2606,34 +2649,8 @@ void TrackingNtuple::fillStripMatchedHits(const edm::Event& iEvent, edm::Handle matchedHits; iEvent.getByToken(stripMatchedRecHitToken_, matchedHits); for (auto it = matchedHits->begin(); it!=matchedHits->end(); it++ ) { - const DetId hitId = it->detId(); for (auto hit = it->begin(); hit!=it->end(); hit++ ) { - TransientTrackingRecHit::RecHitPointer ttrh = theTTRHBuilder.build(&*hit); - const int lay = tTopo.layer(hitId); - monoStereoClusterList.emplace_back(hit->monoHit().cluster().key(),hit->stereoHit().cluster().key()); - glu_isBarrel .push_back( (hitId.subdetId()==StripSubdetector::TIB || hitId.subdetId()==StripSubdetector::TOB) ); - glu_detId .push_back( tTopo, hitId ); - glu_monoIdx .push_back( hit->monoHit().cluster().key() ); - glu_stereoIdx.push_back( hit->stereoHit().cluster().key() ); - glu_seeIdx .emplace_back(); // filled in fillSeeds - glu_x .push_back( ttrh->globalPosition().x() ); - glu_y .push_back( ttrh->globalPosition().y() ); - glu_z .push_back( ttrh->globalPosition().z() ); - glu_xx .push_back( ttrh->globalPositionError().cxx() ); - glu_xy .push_back( ttrh->globalPositionError().cyx() ); - glu_yy .push_back( ttrh->globalPositionError().cyy() ); - glu_yz .push_back( ttrh->globalPositionError().czy() ); - glu_zz .push_back( ttrh->globalPositionError().czz() ); - glu_zx .push_back( ttrh->globalPositionError().czx() ); - glu_radL .push_back( ttrh->surface()->mediumProperties().radLen() ); - glu_bbxi .push_back( ttrh->surface()->mediumProperties().xi() ); - LogTrace("TrackingNtuple") << "stripMatchedHit" - << " cluster0=" << hit->stereoHit().cluster().key() - << " cluster1=" << hit->monoHit().cluster().key() - << " subdId=" << hitId.subdetId() - << " lay=" << lay - << " rawId=" << hitId.rawId() - << " pos =" << ttrh->globalPosition(); + addStripMatchedHit(*hit, theTTRHBuilder, tTopo, monoStereoClusterList); } } } @@ -2712,7 +2729,8 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, const ClusterTPAssociation& clusterToTPMap, const TransientTrackingRecHitBuilder& theTTRHBuilder, const MagneticField& theMF, - const std::vector >& monoStereoClusterList, + const TrackerTopology& tTopo, + std::vector >& monoStereoClusterList, const std::set& hitProductIds, std::map& seedCollToOffset ) { @@ -2887,8 +2905,19 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, int monoIdx = matchedHit->monoClusterRef().key(); int stereoIdx = matchedHit->stereoClusterRef().key(); - std::vector >::const_iterator pos = find( monoStereoClusterList.begin(), monoStereoClusterList.end(), std::make_pair(monoIdx,stereoIdx) ); - const auto gluedIndex = std::distance(monoStereoClusterList.begin(), pos); + std::vector >::iterator pos = find( monoStereoClusterList.begin(), monoStereoClusterList.end(), std::make_pair(monoIdx,stereoIdx) ); + size_t gluedIndex = -1; + if(pos != monoStereoClusterList.end()) { + gluedIndex = std::distance(monoStereoClusterList.begin(), pos); + } + else { + // We can encounter glued hits not in the input + // SiStripMatchedRecHit2DCollection, e.g. via muon + // outside-in seeds (or anything taking hits from + // MeasurementTrackerEvent). So let's add them here. + gluedIndex = addStripMatchedHit(*matchedHit, theTTRHBuilder, tTopo, monoStereoClusterList); + } + if(includeAllHits_) glu_seeIdx[gluedIndex].push_back(seedIndex); hitIdx.push_back( gluedIndex ); hitType.push_back( static_cast(HitType::Glued) ); From a8382861976a9954e0c8e030a65f48c8cb497b6f Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Fri, 18 Aug 2017 14:01:27 +0200 Subject: [PATCH 21/24] Add protections for collection sizes to printTrackingNtuple --- .../RecoTrack/scripts/printTrackingNtuple.py | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/Validation/RecoTrack/scripts/printTrackingNtuple.py b/Validation/RecoTrack/scripts/printTrackingNtuple.py index a5603dde6b5e9..8642438d1d83c 100755 --- a/Validation/RecoTrack/scripts/printTrackingNtuple.py +++ b/Validation/RecoTrack/scripts/printTrackingNtuple.py @@ -55,23 +55,43 @@ def main(opts): printTrackingParticle = ntuple.TrackingParticlePrinter(trackPrinter=ntuple.TrackPrinter(**trackArgs), **tpArgs) if opts.track is not None: - trk = event.tracks()[opts.track] + trks = event.tracks() + if opts.track >= len(trks): + print "You requested track %d, but this event has only %d tracks" % (opts.track, len(trks)) + return + trk = trks[opts.track] printTrack(trk) if opts.trackingParticle is not None: - tp = event.trackingParticles()[opts.trackingParticle] + tps = event.trackingParticles() + if opts.trackingParticle >= len(tps): + print "You requested TrackingParticle %d, but this event has ony %d TrackingParticles" % (opts.trackingParticle, len(tps)) + return + tp = tps[opts.trackingParticle] printTrackingParticle(tp) if opts.seed is not None: seeds = event.seeds() if opts.seedIteration is not None: - seed = seeds.seedForAlgo(getattr(ntuple.Algo, opts.seedIteration), opts.seed) + algo = getattr(ntuple.Algo, opts.seedIteration) + if opts.seed >= seeds.nSeedsForAlgo(algo): + print "You requested seed %d for algo %s, but this event has only %d seeds for that algo" % (opts.seed, opts.seedIteration, seeds.nSeedsForAlgo(algo)) + return + seed = seeds.seedForAlgo(algo, opts.seed) else: + if opts.seed >= len(seeds): + print "You requested seed %d, but this event has only %d seeds" % (opts.seed, len(seeds)) + return seed = seeds[opts.seed] printSeed(seed) if opts.pixelHit is not None: - hit = event.pixelHits()[opts.pixelHit] + hits = event.pixelHits() + if opts.pixelHit >= len(hits): + print "You requested pixel hit %d, but this event has only %d pixel hits" % (opts.pixelHit, len(hits)) + return + + hit = hits[opts.pixelHit] print "Pixel hit %d tracks" % opts.pixelHit for t in hit.tracks(): printTrack(t) @@ -81,7 +101,11 @@ def main(opts): printSeed(s) if opts.stripHit is not None: - hit = event.stripHits()[opts.stripHit] + hits = event.stripHits() + if opts.stripHit >= len(hits): + print "You requested strip hit %d, but this event has only %d strip hits" % (opts.stripHit, len(hits)) + return + hit = hits[opts.stripHit] print "Strip hit %d tracks" % opts.stripHit for t in hit.tracks(): printTrack(t) From 1db85ba3b533289f59172581b136bf67c451891b Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 2 Nov 2017 13:11:23 +0100 Subject: [PATCH 22/24] Save numbers of inactive hits --- .../RecoTrack/plugins/TrackingNtuple.cc | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index 3b966be300bc5..c9de6d757bac7 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -1061,11 +1061,14 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector> trk_qualityMasks; std::vector trk_q ; std::vector trk_nValid ; - std::vector trk_nInvalid; + std::vector trk_nLost; + std::vector trk_nInactive; std::vector trk_nPixel ; std::vector trk_nStrip ; std::vector trk_nOuterLost; std::vector trk_nInnerLost; + std::vector trk_nOuterInactive; + std::vector trk_nInnerInactive; std::vector trk_nPixelLay; std::vector trk_nStripLay; std::vector trk_n3DLay ; @@ -1451,11 +1454,14 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): } t->Branch("trk_q" , &trk_q); t->Branch("trk_nValid" , &trk_nValid ); - t->Branch("trk_nInvalid" , &trk_nInvalid); + t->Branch("trk_nLost" , &trk_nLost); + t->Branch("trk_nInactive", &trk_nInactive); t->Branch("trk_nPixel" , &trk_nPixel ); t->Branch("trk_nStrip" , &trk_nStrip ); - t->Branch("trk_nOuterLost", &trk_nOuterLost ); - t->Branch("trk_nInnerLost", &trk_nInnerLost ); + t->Branch("trk_nOuterLost", &trk_nOuterLost); + t->Branch("trk_nInnerLost", &trk_nInnerLost); + t->Branch("trk_nOuterInactive", &trk_nOuterInactive); + t->Branch("trk_nInnerInactive", &trk_nInnerInactive); t->Branch("trk_nPixelLay", &trk_nPixelLay); t->Branch("trk_nStripLay", &trk_nStripLay); t->Branch("trk_n3DLay" , &trk_n3DLay ); @@ -1792,11 +1798,14 @@ void TrackingNtuple::clearVariables() { } trk_q .clear(); trk_nValid .clear(); - trk_nInvalid .clear(); + trk_nLost .clear(); + trk_nInactive.clear(); trk_nPixel .clear(); trk_nStrip .clear(); trk_nOuterLost.clear(); trk_nInnerLost.clear(); + trk_nOuterInactive.clear(); + trk_nInnerInactive.clear(); trk_nPixelLay.clear(); trk_nStripLay.clear(); trk_n3DLay .clear(); @@ -3153,11 +3162,14 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, trk_ndof .push_back(ndof); trk_q .push_back(charge); trk_nValid .push_back(hp.numberOfValidHits()); - trk_nInvalid .push_back(hp.numberOfLostHits(reco::HitPattern::TRACK_HITS)); + trk_nLost .push_back(hp.numberOfLostHits(reco::HitPattern::TRACK_HITS)); + trk_nInactive .push_back(hp.trackerLayersTotallyOffOrBad(reco::HitPattern::TRACK_HITS)); trk_nPixel .push_back(hp.numberOfValidPixelHits()); trk_nStrip .push_back(hp.numberOfValidStripHits()); trk_nOuterLost.push_back(hp.numberOfLostTrackerHits(reco::HitPattern::MISSING_OUTER_HITS)); trk_nInnerLost.push_back(hp.numberOfLostTrackerHits(reco::HitPattern::MISSING_INNER_HITS)); + trk_nOuterInactive.push_back(hp.trackerLayersTotallyOffOrBad(reco::HitPattern::MISSING_OUTER_HITS)); + trk_nInnerInactive.push_back(hp.trackerLayersTotallyOffOrBad(reco::HitPattern::MISSING_INNER_HITS)); trk_nPixelLay.push_back(hp.pixelLayersWithMeasurement()); trk_nStripLay.push_back(hp.stripLayersWithMeasurement()); trk_n3DLay .push_back(hp.numberOfValidStripLayersWithMonoAndStereo()+hp.pixelLayersWithMeasurement()); From 868f3ab410084066dcab9639f587d3dd4b25a9f2 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 2 Nov 2017 13:12:40 +0100 Subject: [PATCH 23/24] Use Path instead of EndPath --- Validation/RecoTrack/python/customiseTrackingNtuple.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Validation/RecoTrack/python/customiseTrackingNtuple.py b/Validation/RecoTrack/python/customiseTrackingNtuple.py index e3c7619fd1475..09898a3443380 100644 --- a/Validation/RecoTrack/python/customiseTrackingNtuple.py +++ b/Validation/RecoTrack/python/customiseTrackingNtuple.py @@ -26,7 +26,7 @@ def customiseTrackingNtuple(process): usePileupSimHits = hasattr(process, "mix") and hasattr(process.mix, "input") and len(process.mix.input.fileNames) > 0 # process.eda = cms.EDAnalyzer("EventContentAnalyzer") - ntuplePath = cms.EndPath(process.trackingNtupleSequence) + ntuplePath = cms.Path(process.trackingNtupleSequence) if process.trackingNtuple.includeAllHits and process.trackingNtuple.includeTrackingParticles and usePileupSimHits: ntuplePath.insert(0, cms.SequencePlaceholder("mix")) @@ -39,10 +39,8 @@ def customiseTrackingNtuple(process): # Bit of a hack but works modifier = cms.Modifier() modifier._setChosen() - modifier.toReplaceWith(process.validation_step, ntuplePath) - - if hasattr(process, "prevalidation_step"): - modifier.toReplaceWith(process.prevalidation_step, cms.Path()) + modifier.toReplaceWith(process.prevalidation_step, ntuplePath) + modifier.toReplaceWith(process.validation_step, cms.EndPath()) # remove the validation_stepN and prevalidatin_stepN of phase2 validation... for p in [process.paths_(), process.endpaths_()]: From 4f98c647b62f928441fd8707cd4de7dd617995a5 Mon Sep 17 00:00:00 2001 From: Matti Kortelainen Date: Thu, 2 Nov 2017 21:00:37 +0100 Subject: [PATCH 24/24] Just use clusters for the matching scores following the recent changes to QuickTrackAssociatorByHits --- .../interface/trackHitsToClusterRefs.h | 78 +++++++ .../plugins/QuickTrackAssociatorByHitsImpl.cc | 87 ++------ .../plugins/QuickTrackAssociatorByHitsImpl.h | 12 +- .../RecoTrack/plugins/TrackingNtuple.cc | 207 +++++++----------- 4 files changed, 174 insertions(+), 210 deletions(-) create mode 100644 SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h diff --git a/SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h b/SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h new file mode 100644 index 0000000000000..ded9b52033b12 --- /dev/null +++ b/SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h @@ -0,0 +1,78 @@ +#ifndef SimTracker_TrackAssociation_trackHitsToClusterRefs_h +#define SimTracker_TrackAssociation_trackHitsToClusterRefs_h + +#include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHit.h" +#include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h" +#include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit2D.h" +#include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit1D.h" +#include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" +#include "DataFormats/SiStripDetId/interface/SiStripDetId.h" +#include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h" + +namespace track_associator { + const TrackingRecHit* getHitFromIter(trackingRecHit_iterator iter) { + return &(**iter); + } + + const TrackingRecHit* getHitFromIter(TrackingRecHitCollection::const_iterator iter) { + return &(*iter); + } + + template + std::vector hitsToClusterRefs(iter begin, iter end) { + std::vector returnValue; + for (iter iRecHit = begin; iRecHit != end; ++iRecHit) { + const TrackingRecHit* rhit = getHitFromIter(iRecHit); + if (rhit->isValid()) { + int subdetid = rhit->geographicalId().subdetId(); + if (subdetid==PixelSubdetector::PixelBarrel||subdetid==PixelSubdetector::PixelEndcap) { + const SiPixelRecHit* pRHit = dynamic_cast(rhit); + if (!pRHit->cluster().isNonnull()) + edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; + returnValue.push_back(pRHit->omniClusterRef()); + } + else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) { + const std::type_info &tid = typeid(*rhit); + if (tid == typeid(SiStripMatchedRecHit2D)) { + const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast(rhit); + if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull()) + edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; + returnValue.push_back(sMatchedRHit->monoClusterRef()); + returnValue.push_back(sMatchedRHit->stereoClusterRef()); + } + else if (tid == typeid(SiStripRecHit2D)) { + const SiStripRecHit2D* sRHit = dynamic_cast(rhit); + if (!sRHit->cluster().isNonnull()) + edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; + returnValue.push_back(sRHit->omniClusterRef()); + } + else if (tid == typeid(SiStripRecHit1D)) { + const SiStripRecHit1D* sRHit = dynamic_cast(rhit); + if (!sRHit->cluster().isNonnull()) + edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; + returnValue.push_back(sRHit->omniClusterRef()); + } + else if (tid == typeid(Phase2TrackerRecHit1D)) { + const Phase2TrackerRecHit1D* ph2Hit = dynamic_cast(rhit); + if (!ph2Hit->cluster().isNonnull() ) + edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; + returnValue.push_back(ph2Hit->omniClusterRef()); + } + else { + auto const & thit = static_cast(*rhit); + if ( thit.isProjected() ) { + } else { + edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid; + } + } + } + else { + edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid; + } + } + } + return returnValue; + } +} + +#endif diff --git a/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.cc b/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.cc index 7467c4219332a..fa139a65a7dca 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.cc +++ b/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.cc @@ -5,16 +5,12 @@ #include "SimTracker/TrackerHitAssociation/interface/TrackerHitAssociator.h" -#include "DataFormats/TrackerRecHit2D/interface/SiPixelRecHit.h" -#include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h" -#include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit2D.h" -#include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit1D.h" -#include "DataFormats/TrackerRecHit2D/interface/Phase2TrackerRecHit1D.h" -#include "DataFormats/SiStripDetId/interface/SiStripDetId.h" #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "DataFormats/Math/interface/deltaR.h" +#include "SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h" + // // Use the unnamed namespace for utility functions only used in this file // @@ -343,7 +339,7 @@ template std::vector< std::pair oClusters=getMatchedClusters( begin, end ); + std::vector oClusters = track_associator::hitsToClusterRefs( begin, end ); std::map < TrackingParticleRef, double > lmap; for( std::vector::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it ) @@ -394,61 +390,6 @@ template std::vector< std::pair std::vector QuickTrackAssociatorByHitsImpl::getMatchedClusters(iter begin, iter end) const -{ - std::vector returnValue; - for (iter iRecHit = begin; iRecHit != end; ++iRecHit) { - const TrackingRecHit* rhit = getHitFromIter(iRecHit); - if (rhit->isValid()) { - int subdetid = rhit->geographicalId().subdetId(); - if (subdetid==PixelSubdetector::PixelBarrel||subdetid==PixelSubdetector::PixelEndcap) { - const SiPixelRecHit* pRHit = dynamic_cast(rhit); - if (!pRHit->cluster().isNonnull()) - edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; - returnValue.push_back(pRHit->omniClusterRef()); - } - else if (subdetid==SiStripDetId::TIB||subdetid==SiStripDetId::TOB||subdetid==SiStripDetId::TID||subdetid==SiStripDetId::TEC) { - const std::type_info &tid = typeid(*rhit); - if (tid == typeid(SiStripMatchedRecHit2D)) { - const SiStripMatchedRecHit2D* sMatchedRHit = dynamic_cast(rhit); - if (!sMatchedRHit->monoHit().cluster().isNonnull() || !sMatchedRHit->stereoHit().cluster().isNonnull()) - edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; - returnValue.push_back(sMatchedRHit->monoClusterRef()); - returnValue.push_back(sMatchedRHit->stereoClusterRef()); - } - else if (tid == typeid(SiStripRecHit2D)) { - const SiStripRecHit2D* sRHit = dynamic_cast(rhit); - if (!sRHit->cluster().isNonnull()) - edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; - returnValue.push_back(sRHit->omniClusterRef()); - } - else if (tid == typeid(SiStripRecHit1D)) { - const SiStripRecHit1D* sRHit = dynamic_cast(rhit); - if (!sRHit->cluster().isNonnull()) - edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; - returnValue.push_back(sRHit->omniClusterRef()); - } - else if (tid == typeid(Phase2TrackerRecHit1D)) { - const Phase2TrackerRecHit1D* ph2Hit = dynamic_cast(rhit); - if (!ph2Hit->cluster().isNonnull() ) - edm::LogError("TrackAssociator") << ">>> RecHit does not have an associated cluster!" << " file: " << __FILE__ << " line: " << __LINE__; - returnValue.push_back(ph2Hit->omniClusterRef()); - } - else { - auto const & thit = static_cast(*rhit); - if ( thit.isProjected() ) { - } else { - edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any SiStripCluster! subdetid = " << subdetid; - } - } - } - else { - edm::LogError("TrackAssociator") << ">>> getMatchedClusters: TrackingRecHit not associated to any cluster! subdetid = " << subdetid; - } - } - } - return returnValue; -} template std::vector< std::pair > QuickTrackAssociatorByHitsImpl::getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const { @@ -460,15 +401,15 @@ template std::vector< std::pairisValid() ) + if( track_associator::getHitFromIter( iRecHit )->isValid() ) { simTrackIdentifiers.clear(); // Get the identifiers for the sim track that this hit came from. There should only be one entry unless clusters // have merged (as far as I know). - hitAssociator.associateHitId( *(getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers + hitAssociator.associateHitId( *(track_associator::getHitFromIter( iRecHit )), simTrackIdentifiers ); // This call fills simTrackIdentifiers - const auto subdetId = getHitFromIter(iRecHit)->geographicalId().subdetId(); + const auto subdetId = track_associator::getHitFromIter(iRecHit)->geographicalId().subdetId(); const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0; // Loop over each identifier, and add it to the return value only if it's not already in there @@ -530,7 +471,7 @@ template double QuickTrackAssociatorByHitsImpl::getDoubleCount( c int idcount=0; SimTrackIdsDC.clear(); - hitAssociator.associateHitId( *(getHitFromIter( iHit )), SimTrackIdsDC ); + hitAssociator.associateHitId( *(track_associator::getHitFromIter( iHit )), SimTrackIdsDC ); if( SimTrackIdsDC.size() > 1 ) { for( TrackingParticle::g4t_iterator g4T=associatedTrackingParticle->g4Track_begin(); g4T != associatedTrackingParticle->g4Track_end(); @@ -544,7 +485,7 @@ template double QuickTrackAssociatorByHitsImpl::getDoubleCount( c } } if( idcount > 1 ) { - const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId(); + const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId(); const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0; doubleCount += weight*(idcount - 1); } @@ -576,7 +517,7 @@ template double QuickTrackAssociatorByHitsImpl::getDoubleCount( c for( iter iHit=startIterator; iHit != endIterator; iHit++ ) { - std::vector < OmniClusterRef > oClusters=getMatchedClusters( iHit, iHit + 1 ); //only for the cluster being checked + std::vector < OmniClusterRef > oClusters = track_associator::hitsToClusterRefs( iHit, iHit + 1 ); //only for the cluster being checked for( std::vector::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it ) { int idcount=0; @@ -595,7 +536,7 @@ template double QuickTrackAssociatorByHitsImpl::getDoubleCount( c } if( idcount > 1 ) { - const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId(); + const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId(); const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0; doubleCount += weight*(idcount - 1); } @@ -741,7 +682,7 @@ double QuickTrackAssociatorByHitsImpl::weightedNumberOfTrackClusters(const reco: double QuickTrackAssociatorByHitsImpl::weightedNumberOfTrackClusters(const TrajectorySeed& seed, const TrackerHitAssociator&) const { double sum = 0.0; for(auto iHit=seed.recHits().first; iHit!=seed.recHits().second; ++iHit) { - const auto subdetId = getHitFromIter(iHit)->geographicalId().subdetId(); + const auto subdetId = track_associator::getHitFromIter(iHit)->geographicalId().subdetId(); const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0; sum += weight; } @@ -762,11 +703,11 @@ template double QuickTrackAssociatorByHitsImpl::weightedNumberOfT double weightedClusters = 0.0; for (iter iRecHit = begin; iRecHit != end; ++iRecHit) { - const auto subdetId = getHitFromIter(iRecHit)->geographicalId().subdetId(); + const auto subdetId = track_associator::getHitFromIter(iRecHit)->geographicalId().subdetId(); const double weight = (subdetId == PixelSubdetector::PixelBarrel || subdetId == PixelSubdetector::PixelEndcap) ? pixelHitWeight_ : 1.0; - LogTrace("QuickTrackAssociatorByHitsImpl") << " detId: " << getHitFromIter(iRecHit)->geographicalId().rawId(); + LogTrace("QuickTrackAssociatorByHitsImpl") << " detId: " << track_associator::getHitFromIter(iRecHit)->geographicalId().rawId(); LogTrace("QuickTrackAssociatorByHitsImpl") << " weight: " << weight; - std::vector < OmniClusterRef > oClusters=getMatchedClusters( iRecHit, iRecHit + 1 ); //only for the cluster being checked + std::vector < OmniClusterRef > oClusters = track_associator::hitsToClusterRefs( iRecHit, iRecHit + 1 ); //only for the cluster being checked for( std::vector::const_iterator it=oClusters.begin(); it != oClusters.end(); ++it ) { weightedClusters += weight; } diff --git a/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.h b/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.h index 6e5cf799071b4..6b62196f49f52 100644 --- a/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.h +++ b/SimTracker/TrackAssociatorProducers/plugins/QuickTrackAssociatorByHitsImpl.h @@ -160,17 +160,7 @@ class QuickTrackAssociatorByHitsImpl : public reco::TrackToTrackingParticleAssoc */ template std::vector< std::pair > getAllSimTrackIdentifiers( const TrackerHitAssociator& hitAssociator, iter begin, iter end ) const; - // Added by S. Sarkar - template std::vector< OmniClusterRef> getMatchedClusters( iter begin, iter end ) const; - - const TrackingRecHit* getHitFromIter(trackingRecHit_iterator iter) const { - return &(**iter); - } - - const TrackingRecHit* getHitFromIter(TrackingRecHitCollection::const_iterator iter) const { - return &(*iter); - } - + // The last parameter is used to decide whether we cound hits or clusters double weightedNumberOfTrackClusters(const reco::Track& track, const TrackerHitAssociator&) const; double weightedNumberOfTrackClusters(const TrajectorySeed& seed, const TrackerHitAssociator&) const; diff --git a/Validation/RecoTrack/plugins/TrackingNtuple.cc b/Validation/RecoTrack/plugins/TrackingNtuple.cc index c9de6d757bac7..92bbbc95d4290 100644 --- a/Validation/RecoTrack/plugins/TrackingNtuple.cc +++ b/Validation/RecoTrack/plugins/TrackingNtuple.cc @@ -77,6 +77,7 @@ #include "SimTracker/TrackAssociation/plugins/ParametersDefinerForTPESProducer.h" #include "SimTracker/TrackAssociation/interface/TrackingParticleIP.h" #include "SimTracker/TrackAssociation/interface/trackAssociationChi2.h" +#include "SimTracker/TrackAssociation/interface/trackHitsToClusterRefs.h" #include "SimDataFormats/TrackerDigiSimLink/interface/PixelDigiSimLink.h" #include "SimDataFormats/TrackerDigiSimLink/interface/StripDigiSimLink.h" @@ -337,11 +338,6 @@ namespace { struct TrackTPMatch { int key = -1; - // Difference between "Hits" and "Clusters" is that - // SiStripMatchedRecHit2D etc. are counted as 1 hit but 2 - // clusters. For reco denominator the number if hits is useful, - // but for sim denominator the number of clusters. - int countHits = 0; int countClusters = 0; }; @@ -349,13 +345,16 @@ namespace { const ClusterTPAssociation& clusterToTPMap, const TrackingParticleRefKeyToIndex& tpKeyToIndex) { struct Count { - int hits = 0; int clusters = 0; - int innermostHit = std::numeric_limits::max(); + size_t innermostHit = std::numeric_limits::max(); }; + std::vector clusters = track_associator::hitsToClusterRefs(track.recHitsBegin(), track.recHitsEnd()); + std::unordered_map count; - auto fillCount = [&](int hitIndex, const auto& clusterRef) { + for(size_t iCluster=0, end=clusters.size(); iClustersecond.key(); @@ -363,61 +362,26 @@ namespace { continue; auto& elem = count[tpKey]; - ++elem.hits; ++elem.clusters; - elem.innermostHit = std::min(elem.innermostHit, hitIndex); - //edm::LogPrint("Foo") << "key " << ip->second.key() << " event:BX " << ip->second->eventId().event() << ":" << ip->second->eventId().bunchCrossing(); - } - }; - auto fillCountAnd = [&](int hitIndex, const auto& range1, const auto& range2) { - for(auto i1=range1.first; i1!=range1.second; ++i1) { - if(range2.second != std::find_if(range2.first, range2.second, [&](const auto& clusterTP) { - return clusterTP.second.key() == i1->second.key(); - })) { - const auto tpKey = i1->second.key(); - if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input - continue; - - auto& elem = count[tpKey]; - elem.hits += 1; // - elem.clusters += 2; // - elem.innermostHit = std::min(elem.innermostHit, hitIndex); - } - } - }; - - - for(auto iHit = track.recHitsBegin(), iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { - const TrackingRecHit& hit = **iHit; - if(hit.isValid()) { - if(const auto *mhit = dynamic_cast(&hit)) { - auto rangeMono = clusterToTPMap.equal_range(mhit->monoClusterRef()); - auto rangeStereo = clusterToTPMap.equal_range(mhit->stereoClusterRef()); - fillCountAnd(std::distance(track.recHitsBegin(), iHit), rangeMono, rangeStereo); - } - // else if hit is VectorHit? SiTrackerMultiRecHit perhaps? - else { - fillCount(std::distance(track.recHitsBegin(), iHit), dynamic_cast(hit).firstClusterRef()); - } + elem.innermostHit = std::min(elem.innermostHit, iCluster); } } - // In case there are many matches with the same number of hits, + // In case there are many matches with the same number of clusters, // select the one with innermost hit TrackTPMatch best; - int bestCount = 2; // require >= 3 hits for the best match - int bestInnermostHit = std::numeric_limits::max(); + int bestCount = 2; // require >= 3 cluster for the best match + size_t bestInnermostHit = std::numeric_limits::max(); for(auto& keyCount: count) { - if(keyCount.second.hits > bestCount || - (keyCount.second.hits == bestCount && keyCount.second.innermostHit < bestInnermostHit)) { + if(keyCount.second.clusters > bestCount || + (keyCount.second.clusters == bestCount && keyCount.second.innermostHit < bestInnermostHit)) { best.key = keyCount.first; - best.countHits = bestCount = keyCount.second.hits; - best.countClusters = keyCount.second.clusters; + best.countClusters = bestCount = keyCount.second.clusters; bestInnermostHit = keyCount.second.innermostHit; } } - //edm::LogPrint("Foo") << "findBestMatchingTrackingParticle key " << best.key; + LogTrace("TrackingNtuple") << "findBestMatchingTrackingParticle key " << best.key; return best; } @@ -427,93 +391,71 @@ namespace { const TrackingParticleRefKeyToIndex& tpKeyToIndex) { TrackTPMatch best; - auto operateHit = [&](const TrackingRecHit& hit, const auto& func) { - if(const auto *mhit = dynamic_cast(&hit)) { - auto rangeMono = clusterToTPMap.equal_range(mhit->monoClusterRef()); - auto rangeStereo = clusterToTPMap.equal_range(mhit->stereoClusterRef()); - for(auto i1=rangeMono.first; i1!=rangeMono.second; ++i1) { - if(rangeStereo.second != std::find_if(rangeStereo.first, rangeStereo.second, [&](const auto& clusterTP) { - return clusterTP.second.key() == i1->second.key(); - })) { - const auto tpKey = i1->second.key(); - if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input - continue; - - func(tpKey); - } - } - } - // else if hit is VectorHit? - else { - auto range = clusterToTPMap.equal_range(dynamic_cast(hit).firstClusterRef()); - for(auto ip=range.first; ip != range.second; ++ip) { - const auto tpKey = ip->second.key(); - if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input - continue; - func(tpKey); - } + std::vector clusters = track_associator::hitsToClusterRefs(track.recHitsBegin(), track.recHitsEnd()); + if(clusters.empty()) { + return best; + } + + auto operateCluster = [&](const auto& clusterRef, const auto& func) { + auto range = clusterToTPMap.equal_range(clusterRef); + for(auto ip=range.first; ip != range.second; ++ip) { + const auto tpKey = ip->second.key(); + if(tpKeyToIndex.find(tpKey) == tpKeyToIndex.end()) // filter out TPs not given as an input + continue; + func(tpKey); } }; - std::vector validTPs; // first cluster can be associated to multiple TPs, use vector as set as this should be small - auto iHit = track.recHitsBegin(); - { - const TrackingRecHit& hit = **iHit; - if(!hit.isValid()) { - throw cms::Exception("LogicError") << "I expected first track hit to be valid, but encountered an invalid hit..."; - } - operateHit(hit, [&](unsigned int tpKey) { - validTPs.push_back(tpKey); - }); - } + auto iCluster = clusters.begin(); + operateCluster(*iCluster, [&](unsigned int tpKey) { + validTPs.push_back(tpKey); + }); if(validTPs.empty()) { return best; } - ++iHit; - ++best.countHits; + ++iCluster; ++best.countClusters; std::vector foundTPs(validTPs.size(), false); - for(auto iEnd=track.recHitsEnd(); iHit != iEnd; ++iHit) { - const TrackingRecHit& hit = **iHit; - if(hit.isValid()) { - // find out to which first-hit TPs this hit is matched to - operateHit(hit, [&](unsigned int tpKey) { - auto found = std::find(cbegin(validTPs), cend(validTPs), tpKey); - if(found != cend(validTPs)) { - foundTPs[std::distance(cbegin(validTPs), found)] = true; - } - }); + for(auto iEnd=clusters.end(); iCluster != iEnd; ++iCluster) { + const auto& clusterRef = *iCluster; + + // find out to which first-cluster TPs this cluster is matched to + operateCluster(clusterRef, [&](unsigned int tpKey) { + auto found = std::find(cbegin(validTPs), cend(validTPs), tpKey); + if(found != cend(validTPs)) { + foundTPs[std::distance(cbegin(validTPs), found)] = true; + } + }); + - // remove the non-found TPs - auto iTP = validTPs.size(); - do { - --iTP; + // remove the non-found TPs + auto iTP = validTPs.size(); + do { + --iTP; - if(!foundTPs[iTP]) { - validTPs.erase(validTPs.begin()+iTP); - foundTPs.erase(foundTPs.begin()+iTP); - } - } while(iTP > 0); - if(!validTPs.empty()) { - // for multiple TPs the "first one" is a bit arbitrary, but - // I hope it is rare that a track would have many - // consecutive hits matched to two TPs - best.key = validTPs[0]; - } - else { - break; + if(!foundTPs[iTP]) { + validTPs.erase(validTPs.begin()+iTP); + foundTPs.erase(foundTPs.begin()+iTP); } - - std::fill(begin(foundTPs), end(foundTPs), false); - ++best.countHits; - ++best.countClusters; + } while(iTP > 0); + if(!validTPs.empty()) { + // for multiple TPs the "first one" is a bit arbitrary, but + // I hope it is rare that a track would have many + // consecutive hits matched to two TPs + best.key = validTPs[0]; + } + else { + break; } + + std::fill(begin(foundTPs), end(foundTPs), false); + ++best.countClusters; } - // Reqquire >= 3 hits for a match - return best.countHits >= 3 ? best : TrackTPMatch(); + // Reqquire >= 3 clusters for a match + return best.countClusters >= 3 ? best : TrackTPMatch(); } } @@ -1073,6 +1015,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector trk_nStripLay; std::vector trk_n3DLay ; std::vector trk_nLostLay; + std::vector trk_nCluster; std::vector trk_algo ; std::vector trk_originalAlgo; std::vector trk_algoMask; @@ -1280,6 +1223,7 @@ class TrackingNtuple : public edm::one::EDAnalyzer { std::vector see_nGlued ; std::vector see_nStrip ; std::vector see_nPhase2OT; + std::vector see_nCluster; std::vector see_algo ; std::vector see_stopReason; std::vector see_nCands; @@ -1466,6 +1410,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("trk_nStripLay", &trk_nStripLay); t->Branch("trk_n3DLay" , &trk_n3DLay ); t->Branch("trk_nLostLay" , &trk_nLostLay ); + t->Branch("trk_nCluster" , &trk_nCluster); t->Branch("trk_algo" , &trk_algo ); t->Branch("trk_originalAlgo", &trk_originalAlgo); t->Branch("trk_algoMask" , &trk_algoMask); @@ -1688,6 +1633,7 @@ TrackingNtuple::TrackingNtuple(const edm::ParameterSet& iConfig): t->Branch("see_nGlued" , &see_nGlued ); t->Branch("see_nStrip" , &see_nStrip ); t->Branch("see_nPhase2OT", &see_nPhase2OT); + t->Branch("see_nCluster" , &see_nCluster); t->Branch("see_algo" , &see_algo ); t->Branch("see_stopReason", &see_stopReason); t->Branch("see_nCands" , &see_nCands ); @@ -1810,6 +1756,7 @@ void TrackingNtuple::clearVariables() { trk_nStripLay.clear(); trk_n3DLay .clear(); trk_nLostLay .clear(); + trk_nCluster .clear(); trk_algo .clear(); trk_originalAlgo.clear(); trk_algoMask .clear(); @@ -1994,6 +1941,7 @@ void TrackingNtuple::clearVariables() { see_nGlued .clear(); see_nStrip .clear(); see_nPhase2OT.clear(); + see_nCluster.clear(); see_algo .clear(); see_stopReason.clear(); see_nCands .clear(); @@ -2816,11 +2764,13 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, // Search for a best-matching TrackingParticle for a seed const int nHits = seedTrack.numberOfValidHits(); + const auto clusters = track_associator::hitsToClusterRefs(seedTrack.recHitsBegin(), seedTrack.recHitsEnd()); // TODO: this function is called 3 times per track, try to reduce + const int nClusters = clusters.size(); const auto bestKeyCount = findBestMatchingTrackingParticle(seedTrack, clusterToTPMap, tpKeyToIndex); - const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); + const float bestShareFrac = nClusters > 0 ? static_cast(bestKeyCount.countClusters)/static_cast(nClusters): 0; // Another way starting from the first hit of the seed const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(seedTrack, clusterToTPMap, tpKeyToIndex); - const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); + const float bestFirstHitShareFrac = nClusters > 0 ? static_cast(bestFirstHitKeyCount.countClusters)/static_cast(nClusters) : 0; const bool seedFitOk = !trackFromSeedFitFailed(seedTrack); const int charge = seedTrack.charge(); @@ -2966,6 +2916,7 @@ void TrackingNtuple::fillSeeds(const edm::Event& iEvent, see_nGlued .push_back( std::count(hitType.begin(), hitType.end(), static_cast(HitType::Glued)) ); see_nStrip .push_back( std::count(hitType.begin(), hitType.end(), static_cast(HitType::Strip)) ); see_nPhase2OT.push_back( std::count(hitType.begin(), hitType.end(), static_cast(HitType::Phase2OT)) ); + see_nCluster .push_back( nClusters ); //the part below is not strictly needed float chi2 = -1; if (nHits==2) { @@ -3091,8 +3042,11 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } // Search for a best-matching TrackingParticle for a track + const auto clusters = track_associator::hitsToClusterRefs(itTrack->recHitsBegin(), itTrack->recHitsEnd()); // TODO: this function is called 3 times per track, try to reduce + const int nClusters = clusters.size(); + const auto bestKeyCount = findBestMatchingTrackingParticle(*itTrack, clusterToTPMap, tpKeyToIndex); - const float bestShareFrac = static_cast(bestKeyCount.countHits)/static_cast(nHits); + const float bestShareFrac = static_cast(bestKeyCount.countClusters)/static_cast(nClusters); float bestShareFracSimDenom = 0; float bestShareFracSimClusterDenom = 0; float bestChi2 = -1; @@ -3103,7 +3057,7 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, } // Another way starting from the first hit of the track const auto bestFirstHitKeyCount = findMatchingTrackingParticleFromFirstHit(*itTrack, clusterToTPMap, tpKeyToIndex); - const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countHits)/static_cast(nHits); + const float bestFirstHitShareFrac = static_cast(bestFirstHitKeyCount.countClusters)/static_cast(nClusters); float bestFirstHitShareFracSimDenom = 0; float bestFirstHitShareFracSimClusterDenom = 0; float bestFirstHitChi2 = -1; @@ -3174,6 +3128,7 @@ void TrackingNtuple::fillTracks(const edm::RefToBaseVector& tracks, trk_nStripLay.push_back(hp.stripLayersWithMeasurement()); trk_n3DLay .push_back(hp.numberOfValidStripLayersWithMonoAndStereo()+hp.pixelLayersWithMeasurement()); trk_nLostLay .push_back(hp.trackerLayersWithoutMeasurement(reco::HitPattern::TRACK_HITS)); + trk_nCluster .push_back(nClusters); trk_algo .push_back(itTrack->algo()); trk_originalAlgo.push_back(itTrack->originalAlgo()); trk_algoMask .push_back(itTrack->algoMaskUL());