From 06a002f2e6529231f9d4ec65d7b16af5c42bf9f7 Mon Sep 17 00:00:00 2001 From: Breno Orzari Date: Thu, 21 Sep 2023 18:54:55 +0200 Subject: [PATCH 1/3] Adding short track resolution to DQM tracking sequence Co-authored-by: mmusich --- .../plugins/ShortenedTrackResolution.cc | 130 +++++++++++ .../python/TrackingSourceConfig_Tier0_cff.py | 4 + .../python/shortTrackResolution_cff.py | 65 ++++++ .../plugins/SingleLongTrackProducer.cc | 217 ++++++++++++++++++ .../plugins/TrackerTrackHitFilter.cc | 87 ++++++- .../python/SingleLongTrackProducer_cfi.py | 16 ++ 6 files changed, 518 insertions(+), 1 deletion(-) create mode 100644 DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc create mode 100644 DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py create mode 100644 RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc create mode 100644 RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py diff --git a/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc b/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc new file mode 100644 index 0000000000000..cfdc15789c633 --- /dev/null +++ b/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc @@ -0,0 +1,130 @@ +// user includes +#include "DQMServices/Core/interface/DQMEDAnalyzer.h" +#include "DQMServices/Core/interface/DQMStore.h" +#include "DQMServices/Core/interface/MonitorElement.h" +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/Utilities/interface/transform.h" // for edm::vector_transform + +// ROOT includes +#include "TLorentzVector.h" + +class ShortenedTrackResolution : public DQMEDAnalyzer { +public: + ShortenedTrackResolution(const edm::ParameterSet &); + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + +protected: + void analyze(edm::Event const &iEvent, edm::EventSetup const &iSetup) override; + void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override; + +private: + const std::string folderName_; + const std::vector hitsRemain_; + const double minTracksEta_; + const double maxTracksEta_; + const double minTracksPt_; + const double maxTracksPt_; + + const double maxDr_; + const edm::InputTag tracksTag_; + const std::vector tracksRerecoTag_; + const edm::EDGetTokenT> tracksToken_; + const std::vector>> tracksRerecoToken_; + + std::vector histsPtAll_; +}; + +// ----------------------------- +// constructors and destructor +// ----------------------------- +ShortenedTrackResolution::ShortenedTrackResolution(const edm::ParameterSet &ps) + : folderName_(ps.getUntrackedParameter("folderName", "TrackRefitting")), + hitsRemain_(ps.getUntrackedParameter>("hitsRemainInput")), + minTracksEta_(ps.getUntrackedParameter("minTracksEtaInput", 0.0)), + maxTracksEta_(ps.getUntrackedParameter("maxTracksEtaInput", 2.2)), + minTracksPt_(ps.getUntrackedParameter("minTracksPtInput", 15.0)), + maxTracksPt_(ps.getUntrackedParameter("maxTracksPtInput", 99999.9)), + maxDr_(ps.getUntrackedParameter("maxDrInput", 0.01)), + tracksTag_(ps.getUntrackedParameter("tracksInputTag", edm::InputTag("generalTracks", "", "DQM"))), + tracksRerecoTag_(ps.getUntrackedParameter>("tracksRerecoInputTag")), + tracksToken_(consumes>(tracksTag_)), + tracksRerecoToken_(edm::vector_transform( + tracksRerecoTag_, [this](edm::InputTag const &tag) { return consumes>(tag); })) { + histsPtAll_.clear(); +} + +//__________________________________________________________________________________ +void ShortenedTrackResolution::bookHistograms(DQMStore::IBooker &iBook, + edm::Run const &iRun, + edm::EventSetup const &iSetup) { + std::string currentFolder = folderName_ + "/"; + iBook.setCurrentFolder(currentFolder); + + for (int i = 0; i < int(hitsRemain_.size()); ++i) { + histsPtAll_.push_back(iBook.book1D( + "trackPt" + hitsRemain_[i] + "lAllPt", "Track p_{T} - " + hitsRemain_[i] + " layers", 41, 0.0, 2.0)); + } +} + +//__________________________________________________________________________________ +void ShortenedTrackResolution::analyze(edm::Event const &iEvent, edm::EventSetup const &iSetup) { + const auto &tracks = iEvent.getHandle(tracksToken_); + + if (!tracks.isValid()) { + edm::LogError("ShortenedTrackResolution") << "Missing input track collection " << tracksTag_.encode() << std::endl; + return; + } + + for (const auto &track : *tracks) { + const reco::HitPattern &hp = track.hitPattern(); + if (int(int(hp.numberOfValidHits()) - int(hp.numberOfAllHits(reco::HitPattern::TRACK_HITS))) != 0) { + break; + } + + TLorentzVector tvec; + tvec.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), 0.0); + + int i = 0; // token index + for (const auto &token : tracksRerecoToken_) { + const auto &tracks_rereco = iEvent.getHandle(token); + + for (const auto &track_rereco : *tracks_rereco) { + TLorentzVector trerecovec; + trerecovec.SetPtEtaPhiM(track_rereco.pt(), track_rereco.eta(), track_rereco.phi(), 0.0); + double deltaR = tvec.DeltaR(trerecovec); + + if (deltaR < maxDr_) { + if (track_rereco.pt() >= minTracksPt_ && track_rereco.pt() <= maxTracksPt_ && + std::abs(track_rereco.eta()) >= minTracksEta_ && std::abs(track_rereco.eta()) <= maxTracksEta_) { + histsPtAll_[i]->Fill(1.0 * track_rereco.pt() / track.pt()); + } + } + } + ++i; + } + } +} + +//__________________________________________________________________________________ +void ShortenedTrackResolution::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.addUntracked("folderName", "TrackRefitting"); + desc.addUntracked>("hitsRemainInput", {}); + desc.addUntracked("minTracksEtaInput", 0.0); + desc.addUntracked("maxTracksEtaInput", 2.2); + desc.addUntracked("minTracksPtInput", 15.0); + desc.addUntracked("maxTracksPtInput", 99999.9); + desc.addUntracked("maxDrInput", 0.01); + desc.addUntracked("tracksInputTag", edm::InputTag("generalTracks", "", "DQM")); + desc.addUntracked>("tracksRerecoInputTag", {}); + descriptions.addWithDefaultLabel(desc); +} + +// Define this as a plug-in +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(ShortenedTrackResolution); diff --git a/DQM/TrackingMonitorSource/python/TrackingSourceConfig_Tier0_cff.py b/DQM/TrackingMonitorSource/python/TrackingSourceConfig_Tier0_cff.py index 02d3da248a109..faef9e465b492 100644 --- a/DQM/TrackingMonitorSource/python/TrackingSourceConfig_Tier0_cff.py +++ b/DQM/TrackingMonitorSource/python/TrackingSourceConfig_Tier0_cff.py @@ -397,6 +397,8 @@ def _copyIfExists(mod, pset, name): TrackingDQMSourceTier0 += TrackSeedMonSequence +from DQM.TrackingMonitorSource.shortTrackResolution_cff import * + # MessageLog for module in selectedModules : label = str(module)+'LogMessageMonCommon' @@ -404,6 +406,7 @@ def _copyIfExists(mod, pset, name): TrackingDQMSourceTier0 += voMonitoringSequence TrackingDQMSourceTier0 += voWcutMonitoringSequence TrackingDQMSourceTier0 += primaryVertexResolution +TrackingDQMSourceTier0 += shortTrackResolution3to8 TrackingDQMSourceTier0 += dqmInfoTracking @@ -426,6 +429,7 @@ def _copyIfExists(mod, pset, name): TrackingDQMSourceTier0Common += voMonitoringCommonSequence TrackingDQMSourceTier0Common += voWcutMonitoringCommonSequence TrackingDQMSourceTier0Common += primaryVertexResolution +TrackingDQMSourceTier0Common += shortTrackResolution3to8 TrackingDQMSourceTier0Common += dqmInfoTracking TrackingDQMSourceTier0MinBias = cms.Sequence(cms.ignore(trackingDQMgoodOfflinePrimaryVertices)) diff --git a/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py new file mode 100644 index 0000000000000..7c7047c6bfa75 --- /dev/null +++ b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py @@ -0,0 +1,65 @@ +import FWCore.ParameterSet.Config as cms +from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer + +from RecoTracker.FinalTrackSelectors.SingleLongTrackProducer_cfi import * + +from RecoTracker.FinalTrackSelectors.trackerTrackHitFilter_cfi import trackerTrackHitFilter as _trackerTrackHitFilter +TrackerTrackHitFilter = _trackerTrackHitFilter.clone(src = "SingleLongTrackProducer", + truncateTracks = True, + replaceWithInactiveHits = True, + rejectBadStoNHits = True, + usePixelQualityFlag = True) + +TrackerTrackHitFilter3 = TrackerTrackHitFilter.clone(minimumHits = 3, + layersRemaining = 3) + +TrackerTrackHitFilter4 = TrackerTrackHitFilter.clone(minimumHits = 4, + layersRemaining = 4) + +TrackerTrackHitFilter5 = TrackerTrackHitFilter.clone(minimumHits = 5, + layersRemaining = 5) + +TrackerTrackHitFilter6 = TrackerTrackHitFilter.clone(minimumHits = 6, + layersRemaining = 6) + +TrackerTrackHitFilter7 = TrackerTrackHitFilter.clone(minimumHits = 7, + layersRemaining = 7) + +TrackerTrackHitFilter8 = TrackerTrackHitFilter.clone(minimumHits = 8, + layersRemaining = 8) + +import RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff +HitFilteredTracks = RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff.ctfWithMaterialTracks.clone(src = 'TrackerTrackHitFilter') + +HitFilteredTracks3 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter3') +HitFilteredTracks4 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter4') +HitFilteredTracks5 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter5') +HitFilteredTracks6 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter6') +HitFilteredTracks7 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter7') +HitFilteredTracks8 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter8') + +from DQM.TrackingMonitorSource.shortenedTrackResolution_cfi import shortenedTrackResolution as _shortenedTrackResolution +trackingResolution = _shortenedTrackResolution.clone(folderName = "Tracking/ShortTrackResolution", + hitsRemainInput = ["3","4","5","6","7","8"], + minTracksEtaInput = 0.0, + maxTracksEtaInput = 2.2, + minTracksPtInput = 15.0, + maxTracksPtInput = 99999.9, + maxDrInput = 0.01, + tracksInputTag = "SingleLongTrackProducer", + tracksRerecoInputTag = ["HitFilteredTracks3","HitFilteredTracks4","HitFilteredTracks5","HitFilteredTracks6","HitFilteredTracks7","HitFilteredTracks8"]) + +shortTrackResolution3to8 = cms.Sequence(SingleLongTrackProducer * + TrackerTrackHitFilter3 * + TrackerTrackHitFilter4 * + TrackerTrackHitFilter5 * + TrackerTrackHitFilter6 * + TrackerTrackHitFilter7 * + TrackerTrackHitFilter8 * + HitFilteredTracks3 * + HitFilteredTracks4 * + HitFilteredTracks5 * + HitFilteredTracks6 * + HitFilteredTracks7 * + HitFilteredTracks8 * + trackingResolution) diff --git a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc new file mode 100644 index 0000000000000..7af6c8c97145b --- /dev/null +++ b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc @@ -0,0 +1,217 @@ +// user includes +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +// ROOT includes +#include "TLorentzVector.h" + +class SingleLongTrackProducer : public edm::stream::EDProducer<> { +public: + explicit SingleLongTrackProducer(const edm::ParameterSet &); + ~SingleLongTrackProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + +private: + void produce(edm::Event &, const edm::EventSetup &) override; + + const edm::EDGetTokenT> tracksToken; + const edm::EDGetTokenT> muonsToken; + const edm::EDGetTokenT PrimVtxToken; + + const int minNumberOfLayers; + const double matchInDr; + const bool onlyValidHits; + const bool debug; + const double minPt; + const double maxEta; + const double maxDxy; + const double maxDz; +}; + +SingleLongTrackProducer::SingleLongTrackProducer(const edm::ParameterSet &iConfig) + : tracksToken{consumes(iConfig.getParameter("allTracks"))}, + muonsToken{consumes>(iConfig.getParameter("matchMuons"))}, + PrimVtxToken{consumes(iConfig.getParameter("PrimaryVertex"))}, + minNumberOfLayers{iConfig.getParameter("minNumberOfLayers")}, + matchInDr{iConfig.getParameter("requiredDr")}, + onlyValidHits{iConfig.getParameter("onlyValidHits")}, + debug{iConfig.getParameter("debug")}, + minPt{iConfig.getParameter("minPt")}, + maxEta{iConfig.getParameter("maxEta")}, + maxDxy{iConfig.getParameter("maxDxy")}, + maxDz{iConfig.getParameter("maxDz")} { + produces("").setBranchAlias(""); +} + +void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + using namespace edm; + + // register input collections: + const auto &tracks = iEvent.getHandle(tracksToken); + const auto &muons = iEvent.getHandle(muonsToken); + + const auto &vtx_h = iEvent.getHandle(PrimVtxToken); + const reco::Vertex vtx = vtx_h->at(0); + + // register output collection: + std::unique_ptr goodTracks(new reco::TrackCollection); + + // Preselection of long quality tracks + std::vector selTracks; + reco::Track bestTrack; + unsigned int tMuon = 0; + double fitProb = 100; + + for (const auto &track : *tracks) { + const reco::HitPattern &hitpattern = track.hitPattern(); + double dRmin = 10; + double chiNdof = track.normalizedChi2(); + double dxy = std::abs(track.dxy(vtx.position())); + double dz = std::abs(track.dz(vtx.position())); + + if (track.pt() < minPt) + continue; + + if (abs(track.eta()) > maxEta) + continue; + + if (hitpattern.trackerLayersWithMeasurement() < minNumberOfLayers) + continue; + + TLorentzVector pTrack(track.px(), track.py(), track.pz(), track.pt()); + + // Long track needs to be close to a good muon + for (const auto &m : *muons) { + if (m.isTrackerMuon()) { + tMuon++; + reco::Track matchedTrack = *(m.innerTrack()); + TLorentzVector pMatched(matchedTrack.px(), matchedTrack.py(), matchedTrack.pz(), matchedTrack.pt()); + // match to general track in deltaR + double dr = pTrack.DeltaR(pMatched); + if (dr < dRmin) + dRmin = dr; + } + } + + if (dRmin >= matchInDr) + continue; + // do vertex consistency: + bool vertex_match = dxy < maxDxy && dz < maxDz; + if (!(vertex_match)) + continue; + if (track.validFraction() < 1.0) + continue; + // only save the track with the smallest chiNdof + if (chiNdof < fitProb) { + fitProb = chiNdof; + bestTrack = track; + bestTrack.setExtra(track.extra()); + } + if (debug) + edm::LogPrint("SingleLongTrackProducer") << " deltaR (general) track to matched Track: " << dRmin << std::endl; + if (debug) + edm::LogPrint("SingleLongTrackProducer") << "chi2Ndof:" << chiNdof << " best Track: " << fitProb << std::endl; + } + + selTracks.push_back(bestTrack); + + if (debug) + edm::LogPrint("SingleLongTrackProducer") << " number of Tracker Muons: " << tMuon << ", thereof " + << selTracks.size() << " tracks passed preselection." << std::endl; + + // check hits validity in preselected tracks + bool hitIsNotValid{false}; + + for (const auto &track : selTracks) { + reco::HitPattern hitpattern = track.hitPattern(); + int deref{0}; + + // this checks track recHits + try { // (Un)Comment this line with /* to (not) allow for events with not valid hits + auto hb = track.recHitsBegin(); + + for (unsigned int h = 0; h < track.recHitsSize(); h++) { + auto recHit = *(hb + h); + auto const &hit = *recHit; + + if (onlyValidHits && !hit.isValid()) { + hitIsNotValid = true; + continue; + } + } + } catch (cms::Exception const &e) { + deref += 1; + if (debug) + std::cerr << e.explainSelf() << std::endl; + } + + if (hitIsNotValid == true) + break; // (Un)Comment this line with */ to (not) allow for events with not valid hits + + int deref2{0}; + + // this checks track hitPattern hits + try { + auto hb = track.recHitsBegin(); + + for (unsigned int h = 0; h < track.recHitsSize(); h++) { + uint32_t pHit = hitpattern.getHitPattern(reco::HitPattern::TRACK_HITS, h); + + auto recHit = *(hb + h); + auto const &hit = *recHit; + + if (onlyValidHits && !hit.isValid()) { + if (debug) + edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h << std::endl; + continue; + } + + // loop over the hits of the track. + if (onlyValidHits && !(hitpattern.validHitFilter(pHit))) { + if (debug) + edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h << std::endl; + continue; + } + } + goodTracks->push_back(track); + } catch (cms::Exception const &e) { + deref2 += 1; + if (debug) + std::cerr << e.explainSelf() << std::endl; + } + + if (debug) + edm::LogPrint("SingleLongTrackProducer") + << "found tracks with " << deref << "missing valid hits and " << deref2 << " missing hit pattern"; + } + + // save track collection in event: + iEvent.put(std::move(goodTracks), ""); +} + +void SingleLongTrackProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.add("allTracks", edm::InputTag("generalTracks")); + desc.add("matchMuons", edm::InputTag("muons")); + desc.add("PrimaryVertex", edm::InputTag("offlinePrimaryVertices")); + desc.add("minNumberOfLayers", 10); + desc.add("requiredDr", 0.01); + desc.add("onlyValidHits", true); + desc.add("debug", false); + desc.add("minPt", 15.0); + desc.add("maxEta", 2.2); + desc.add("maxDxy", 0.02); + desc.add("maxDz", 0.5); + descriptions.addWithDefaultLabel(desc); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(SingleLongTrackProducer); diff --git a/RecoTracker/FinalTrackSelectors/plugins/TrackerTrackHitFilter.cc b/RecoTracker/FinalTrackSelectors/plugins/TrackerTrackHitFilter.cc index c6341cd9d19a2..c03ecb6c92ebb 100644 --- a/RecoTracker/FinalTrackSelectors/plugins/TrackerTrackHitFilter.cc +++ b/RecoTracker/FinalTrackSelectors/plugins/TrackerTrackHitFilter.cc @@ -62,6 +62,9 @@ * minimumHits = Minimum hits that the output TrackCandidate must have to be saved * replaceWithInactiveHits = instead of discarding hits, replace them with a invalid "inactive" hits, * so multiple scattering is accounted for correctly. + * truncateTracks = determines if recHits collection is to be truncated to provide tracks with + * layersRemaining number of layers after refitting + * layersRemaining = number of tracker layers with measurement remaining after truncating track * stripFrontInvalidHits = strip invalid hits at the beginning of the track * stripBackInvalidHits = strip invalid hits at the end of the track * stripAllInvalidHits = remove ALL invald hits (might be a problem for multiple scattering, use with care!) @@ -87,6 +90,8 @@ namespace reco { const Trajectory *itt, std::vector &hits); void produceFromTrack(const edm::EventSetup &iSetup, const Track *itt, std::vector &hits); + unsigned int getSequLayer(const reco::Track &tk, unsigned int prevSequLayers, std::vector isNotValidVec); + bool isFirstValidHitInLayer(const reco::Track &tk, std::vector isNotValidVec); static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); @@ -125,6 +130,9 @@ namespace reco { size_t minimumHits_; + unsigned int layersRemaining_; + bool truncateTracks_; + bool replaceWithInactiveHits_; bool stripFrontInvalidHits_; bool stripBackInvalidHits_; @@ -301,6 +309,8 @@ namespace reco { TrackerTrackHitFilter::TrackerTrackHitFilter(const edm::ParameterSet &iConfig) : src_(iConfig.getParameter("src")), minimumHits_(iConfig.getParameter("minimumHits")), + layersRemaining_(iConfig.getParameter("layersRemaining")), + truncateTracks_(iConfig.getParameter("truncateTracks")), replaceWithInactiveHits_(iConfig.getParameter("replaceWithInactiveHits")), stripFrontInvalidHits_(iConfig.getParameter("stripFrontInvalidHits")), stripBackInvalidHits_(iConfig.getParameter("stripBackInvalidHits")), @@ -561,6 +571,54 @@ namespace reco { iEvent.put(std::move(output)); } + bool TrackerTrackHitFilter::isFirstValidHitInLayer(const reco::Track &tk, std::vector isNotValidVec) { + reco::HitPattern hp = tk.hitPattern(); + + int vecSize = static_cast(isNotValidVec.size()); + // If hit is not valid, it will not count as a tracker layer with measurement -> don't increase sequLayers + if (isNotValidVec[vecSize - 1]) + return false; + + // If very first valid layer -> increase sequLayers + if (vecSize == 1) + return true; + + uint32_t pHit = hp.getHitPattern(reco::HitPattern::TRACK_HITS, vecSize - 1); + uint32_t thisLayer = hp.getLayer(pHit); + uint32_t thisSubStruct = hp.getSubStructure(pHit); + + // This loop compares the previous hits substructure and layer with current hit. If hits in the same layer + // and substructure and previous hit is valid, skip layer. If previous hit is not valid, even if in same layer + // and substructure, check the previous previous hit. Repeat process for every previous hit until reaching + // a valid hit or different layer/substructure + for (int j = 0; j < vecSize; ++j) { + if (vecSize > (j + 1)) { + uint32_t nHit = hp.getHitPattern(reco::HitPattern::TRACK_HITS, vecSize - (j + 2)); + uint32_t prevLayer = hp.getLayer(nHit); + uint32_t prevSubStruct = hp.getSubStructure(nHit); + if ((thisLayer == prevLayer) && (thisSubStruct == prevSubStruct)) { + if (isNotValidVec[vecSize - (j + 2)] == false) { + return false; + } + } else { + return true; + } + } else { + return true; + } + } + return false; + } + + unsigned int TrackerTrackHitFilter::getSequLayer(const reco::Track &tk, + unsigned int prevSequLayers, + std::vector isNotValidVec) { + unsigned int sequLayers = 0; + sequLayers = isFirstValidHitInLayer(tk, isNotValidVec) ? prevSequLayers + 1 : prevSequLayers; + + return sequLayers; + } + TrackCandidate TrackerTrackHitFilter::makeCandidate(const reco::Track &tk, std::vector::iterator hitsBegin, std::vector::iterator hitsEnd) { @@ -586,8 +644,29 @@ namespace reco { TrajectorySeed seed(state, TrackCandidate::RecHitContainer(), pdir); TrackCandidate::RecHitContainer ownHits; ownHits.reserve(hitsEnd - hitsBegin); + const reco::HitPattern &hp = tk.hitPattern(); + unsigned int sequLayers = 0; + std::vector isNotValidVec; + isNotValidVec.clear(); + bool breakHitLoop = false; + if (int(int(hp.numberOfValidHits()) - int(hp.numberOfAllHits(reco::HitPattern::TRACK_HITS))) != 0) { + breakHitLoop = true; + } for (; hitsBegin != hitsEnd; ++hitsBegin) { - //if(! (*hitsBegin)->isValid() ) std::cout<<"Putting in the trackcandidate an INVALID HIT !"<isValid()) { + isNotValidVec.push_back(true); + } else { + isNotValidVec.push_back(false); + } + sequLayers = getSequLayer(tk, sequLayers, isNotValidVec); + if (sequLayers > layersRemaining_) + break; + } ownHits.push_back(*hitsBegin); } @@ -1040,6 +1119,12 @@ namespace reco { ->setComment( " instead of removing hits replace them with inactive hits, so you still consider the multiple " "scattering"); + desc.add("truncateTracks", false) + ->setComment( + "determines if recHits collection is to be truncated to provide tracks with layersRemaining number of " + "layers after refitting"); + desc.add("layersRemaining", 8) + ->setComment("number of tracker layers with measurement remaining after truncating track"); desc.add("stripFrontInvalidHits", false) ->setComment("strip invalid & inactive hits from any end of the track"); desc.add("stripBackInvalidHits", false) diff --git a/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py b/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py new file mode 100644 index 0000000000000..181a536038cfe --- /dev/null +++ b/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py @@ -0,0 +1,16 @@ +import FWCore.ParameterSet.Config as cms + +from RecoTracker.FinalTrackSelectors.singleLongTrackProducer_cfi import singleLongTrackProducer + +SingleLongTrackProducer = singleLongTrackProducer.clone( + allTracks = "generalTracks", + matchMuons = "muons", + requiredDr= 0.01, + minNumberOfLayers = 10, + onlyValidHits = True, + debug = False, + minPt = 15.0, + maxEta = 2.2, + maxDxy = 0.02, + maxDz = 0.5, + PrimaryVertex = "offlinePrimaryVertices") From 3fa895ec3772b34a78d21bf736d59c39afd5947f Mon Sep 17 00:00:00 2001 From: Breno Orzari Date: Fri, 22 Dec 2023 16:30:37 +0100 Subject: [PATCH 2/3] Renaming and fix for phase2 --- .../python/shortTrackResolution_cff.py | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py index 7c7047c6bfa75..e38489adb17f9 100644 --- a/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py +++ b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py @@ -4,39 +4,43 @@ from RecoTracker.FinalTrackSelectors.SingleLongTrackProducer_cfi import * from RecoTracker.FinalTrackSelectors.trackerTrackHitFilter_cfi import trackerTrackHitFilter as _trackerTrackHitFilter -TrackerTrackHitFilter = _trackerTrackHitFilter.clone(src = "SingleLongTrackProducer", +ShortTrackCandidates = _trackerTrackHitFilter.clone(src = "SingleLongTrackProducer", truncateTracks = True, replaceWithInactiveHits = True, rejectBadStoNHits = True, usePixelQualityFlag = True) -TrackerTrackHitFilter3 = TrackerTrackHitFilter.clone(minimumHits = 3, +from Configuration.Eras.Modifier_phase2_tracker_cff import phase2_tracker +phase2_tracker.toModify(ShortTrackCandidates, + isPhase2 = True) + +ShortTrackCandidates3 = ShortTrackCandidates.clone(minimumHits = 3, layersRemaining = 3) -TrackerTrackHitFilter4 = TrackerTrackHitFilter.clone(minimumHits = 4, +ShortTrackCandidates4 = ShortTrackCandidates.clone(minimumHits = 4, layersRemaining = 4) -TrackerTrackHitFilter5 = TrackerTrackHitFilter.clone(minimumHits = 5, +ShortTrackCandidates5 = ShortTrackCandidates.clone(minimumHits = 5, layersRemaining = 5) -TrackerTrackHitFilter6 = TrackerTrackHitFilter.clone(minimumHits = 6, +ShortTrackCandidates6 = ShortTrackCandidates.clone(minimumHits = 6, layersRemaining = 6) -TrackerTrackHitFilter7 = TrackerTrackHitFilter.clone(minimumHits = 7, +ShortTrackCandidates7 = ShortTrackCandidates.clone(minimumHits = 7, layersRemaining = 7) -TrackerTrackHitFilter8 = TrackerTrackHitFilter.clone(minimumHits = 8, +ShortTrackCandidates8 = ShortTrackCandidates.clone(minimumHits = 8, layersRemaining = 8) import RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff -HitFilteredTracks = RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff.ctfWithMaterialTracks.clone(src = 'TrackerTrackHitFilter') +RefittedShortTracks = RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff.ctfWithMaterialTracks.clone(src = 'ShortTrackCandidates') -HitFilteredTracks3 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter3') -HitFilteredTracks4 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter4') -HitFilteredTracks5 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter5') -HitFilteredTracks6 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter6') -HitFilteredTracks7 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter7') -HitFilteredTracks8 = HitFilteredTracks.clone(src = 'TrackerTrackHitFilter8') +RefittedShortTracks3 = RefittedShortTracks.clone(src = 'ShortTrackCandidates3') +RefittedShortTracks4 = RefittedShortTracks.clone(src = 'ShortTrackCandidates4') +RefittedShortTracks5 = RefittedShortTracks.clone(src = 'ShortTrackCandidates5') +RefittedShortTracks6 = RefittedShortTracks.clone(src = 'ShortTrackCandidates6') +RefittedShortTracks7 = RefittedShortTracks.clone(src = 'ShortTrackCandidates7') +RefittedShortTracks8 = RefittedShortTracks.clone(src = 'ShortTrackCandidates8') from DQM.TrackingMonitorSource.shortenedTrackResolution_cfi import shortenedTrackResolution as _shortenedTrackResolution trackingResolution = _shortenedTrackResolution.clone(folderName = "Tracking/ShortTrackResolution", @@ -47,19 +51,19 @@ maxTracksPtInput = 99999.9, maxDrInput = 0.01, tracksInputTag = "SingleLongTrackProducer", - tracksRerecoInputTag = ["HitFilteredTracks3","HitFilteredTracks4","HitFilteredTracks5","HitFilteredTracks6","HitFilteredTracks7","HitFilteredTracks8"]) + tracksRerecoInputTag = ["RefittedShortTracks3","RefittedShortTracks4","RefittedShortTracks5","RefittedShortTracks6","RefittedShortTracks7","RefittedShortTracks8"]) shortTrackResolution3to8 = cms.Sequence(SingleLongTrackProducer * - TrackerTrackHitFilter3 * - TrackerTrackHitFilter4 * - TrackerTrackHitFilter5 * - TrackerTrackHitFilter6 * - TrackerTrackHitFilter7 * - TrackerTrackHitFilter8 * - HitFilteredTracks3 * - HitFilteredTracks4 * - HitFilteredTracks5 * - HitFilteredTracks6 * - HitFilteredTracks7 * - HitFilteredTracks8 * + ShortTrackCandidates3 * + ShortTrackCandidates4 * + ShortTrackCandidates5 * + ShortTrackCandidates6 * + ShortTrackCandidates7 * + ShortTrackCandidates8 * + RefittedShortTracks3 * + RefittedShortTracks4 * + RefittedShortTracks5 * + RefittedShortTracks6 * + RefittedShortTracks7 * + RefittedShortTracks8 * trackingResolution) From f61b144d5bc13c963299934b0eefd55972f2e853 Mon Sep 17 00:00:00 2001 From: mmusich Date: Tue, 2 Jan 2024 16:46:46 +0100 Subject: [PATCH 3/3] miscellaneous improvements to SingleLongTrackProducer. Also use earlyMuons collections in order to comply with the trackingOnly DQM sequence --- .../python/shortTrackResolution_cff.py | 27 ++++++---- .../plugins/SingleLongTrackProducer.cc | 51 ++++++++++++++----- .../python/SingleLongTrackProducer_cfi.py | 2 +- 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py index e38489adb17f9..b07c24d88cb99 100644 --- a/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py +++ b/DQM/TrackingMonitorSource/python/shortTrackResolution_cff.py @@ -5,32 +5,32 @@ from RecoTracker.FinalTrackSelectors.trackerTrackHitFilter_cfi import trackerTrackHitFilter as _trackerTrackHitFilter ShortTrackCandidates = _trackerTrackHitFilter.clone(src = "SingleLongTrackProducer", - truncateTracks = True, - replaceWithInactiveHits = True, - rejectBadStoNHits = True, - usePixelQualityFlag = True) + truncateTracks = True, + replaceWithInactiveHits = True, + rejectBadStoNHits = True, + usePixelQualityFlag = True) from Configuration.Eras.Modifier_phase2_tracker_cff import phase2_tracker phase2_tracker.toModify(ShortTrackCandidates, isPhase2 = True) ShortTrackCandidates3 = ShortTrackCandidates.clone(minimumHits = 3, - layersRemaining = 3) + layersRemaining = 3) ShortTrackCandidates4 = ShortTrackCandidates.clone(minimumHits = 4, - layersRemaining = 4) + layersRemaining = 4) ShortTrackCandidates5 = ShortTrackCandidates.clone(minimumHits = 5, - layersRemaining = 5) + layersRemaining = 5) ShortTrackCandidates6 = ShortTrackCandidates.clone(minimumHits = 6, - layersRemaining = 6) + layersRemaining = 6) ShortTrackCandidates7 = ShortTrackCandidates.clone(minimumHits = 7, - layersRemaining = 7) + layersRemaining = 7) ShortTrackCandidates8 = ShortTrackCandidates.clone(minimumHits = 8, - layersRemaining = 8) + layersRemaining = 8) import RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff RefittedShortTracks = RecoTracker.TrackProducer.CTFFinalFitWithMaterial_cff.ctfWithMaterialTracks.clone(src = 'ShortTrackCandidates') @@ -51,7 +51,12 @@ maxTracksPtInput = 99999.9, maxDrInput = 0.01, tracksInputTag = "SingleLongTrackProducer", - tracksRerecoInputTag = ["RefittedShortTracks3","RefittedShortTracks4","RefittedShortTracks5","RefittedShortTracks6","RefittedShortTracks7","RefittedShortTracks8"]) + tracksRerecoInputTag = ["RefittedShortTracks3", + "RefittedShortTracks4", + "RefittedShortTracks5", + "RefittedShortTracks6", + "RefittedShortTracks7", + "RefittedShortTracks8"]) shortTrackResolution3to8 = cms.Sequence(SingleLongTrackProducer * ShortTrackCandidates3 * diff --git a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc index 7af6c8c97145b..a9b8141f423ac 100644 --- a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc +++ b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc @@ -54,15 +54,35 @@ SingleLongTrackProducer::SingleLongTrackProducer(const edm::ParameterSet &iConfi void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { using namespace edm; + // register output collection: + std::unique_ptr goodTracks(new reco::TrackCollection); + // register input collections: const auto &tracks = iEvent.getHandle(tracksToken); + if (!tracks.isValid()) { + edm::LogError("SingleLongTrackProducer") + << "Input track collection is not valid.\n Returning empty output track collection."; + iEvent.put(std::move(goodTracks), ""); + return; + } + const auto &muons = iEvent.getHandle(muonsToken); + if (!muons.isValid()) { + edm::LogError("SingleLongTrackProducer") + << "Input muon collection is not valid.\n Returning empty output track collection."; + iEvent.put(std::move(goodTracks), ""); + return; + } - const auto &vtx_h = iEvent.getHandle(PrimVtxToken); - const reco::Vertex vtx = vtx_h->at(0); + const auto &vertices = iEvent.getHandle(PrimVtxToken); + if (!vertices.isValid()) { + edm::LogError("SingleLongTrackProducer") + << "Input vertex collection is not valid.\n Returning empty output track collection."; + iEvent.put(std::move(goodTracks), ""); + return; + } - // register output collection: - std::unique_ptr goodTracks(new reco::TrackCollection); + const reco::Vertex vtx = vertices->at(0); // Preselection of long quality tracks std::vector selTracks; @@ -80,7 +100,7 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup if (track.pt() < minPt) continue; - if (abs(track.eta()) > maxEta) + if (std::abs(track.eta()) > maxEta) continue; if (hitpattern.trackerLayersWithMeasurement() < minNumberOfLayers) @@ -116,16 +136,16 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup bestTrack.setExtra(track.extra()); } if (debug) - edm::LogPrint("SingleLongTrackProducer") << " deltaR (general) track to matched Track: " << dRmin << std::endl; + edm::LogPrint("SingleLongTrackProducer") << " deltaR (general) track to matched Track: " << dRmin; if (debug) - edm::LogPrint("SingleLongTrackProducer") << "chi2Ndof:" << chiNdof << " best Track: " << fitProb << std::endl; + edm::LogPrint("SingleLongTrackProducer") << "chi2Ndof:" << chiNdof << " best Track: " << fitProb; } selTracks.push_back(bestTrack); if (debug) - edm::LogPrint("SingleLongTrackProducer") << " number of Tracker Muons: " << tMuon << ", thereof " - << selTracks.size() << " tracks passed preselection." << std::endl; + edm::LogPrint("SingleLongTrackProducer") + << " number of Tracker Muons: " << tMuon << ", thereof " << selTracks.size() << " tracks passed preselection."; // check hits validity in preselected tracks bool hitIsNotValid{false}; @@ -170,14 +190,14 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup if (onlyValidHits && !hit.isValid()) { if (debug) - edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h << std::endl; + edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h; continue; } // loop over the hits of the track. if (onlyValidHits && !(hitpattern.validHitFilter(pHit))) { if (debug) - edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h << std::endl; + edm::LogPrint("SingleLongTrackProducer") << "hit not valid: " << h; continue; } } @@ -193,6 +213,13 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup << "found tracks with " << deref << "missing valid hits and " << deref2 << " missing hit pattern"; } + if (debug) { + auto const &moduleType = moduleDescription().moduleName(); + auto const &moduleLabel = moduleDescription().moduleLabel(); + edm::LogPrint("SingleLongTrackProducer") << "[" << moduleType << "] (" << moduleLabel << ") " + << " output track size: " << goodTracks.get()->size(); + } + // save track collection in event: iEvent.put(std::move(goodTracks), ""); } @@ -200,7 +227,7 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup void SingleLongTrackProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { edm::ParameterSetDescription desc; desc.add("allTracks", edm::InputTag("generalTracks")); - desc.add("matchMuons", edm::InputTag("muons")); + desc.add("matchMuons", edm::InputTag("earlyMuons")); desc.add("PrimaryVertex", edm::InputTag("offlinePrimaryVertices")); desc.add("minNumberOfLayers", 10); desc.add("requiredDr", 0.01); diff --git a/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py b/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py index 181a536038cfe..1f97050cea9ba 100644 --- a/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py +++ b/RecoTracker/FinalTrackSelectors/python/SingleLongTrackProducer_cfi.py @@ -4,7 +4,7 @@ SingleLongTrackProducer = singleLongTrackProducer.clone( allTracks = "generalTracks", - matchMuons = "muons", + matchMuons = "earlyMuons", requiredDr= 0.01, minNumberOfLayers = 10, onlyValidHits = True,