From 35bf7286b81ed4b71dbe8dc6c05345e99d936293 Mon Sep 17 00:00:00 2001 From: mmusich Date: Tue, 2 Jan 2024 17:01:10 +0100 Subject: [PATCH 1/3] - Update SingleLongTrackProducer: changes to run on ALCARECO and setComments in fillDescriptions - ShortenedTrackResolution: improve histogram titles - implement unit tests --- .../plugins/ShortenedTrackResolution.cc | 11 +- DQM/TrackingMonitorSource/test/BuildFile.xml | 1 + .../test/testTrackResolutionHarvesting_cfg.py | 91 ++++++++++ .../test/testTrackResolution_cfg.py | 157 ++++++++++++++++++ .../test/testTrackingResolution.sh | 15 ++ .../plugins/SingleLongTrackProducer.cc | 52 +++--- 6 files changed, 301 insertions(+), 26 deletions(-) create mode 100644 DQM/TrackingMonitorSource/test/testTrackResolutionHarvesting_cfg.py create mode 100644 DQM/TrackingMonitorSource/test/testTrackResolution_cfg.py create mode 100755 DQM/TrackingMonitorSource/test/testTrackingResolution.sh diff --git a/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc b/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc index cfdc15789c633..ab6dbc45e8411 100644 --- a/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc +++ b/DQM/TrackingMonitorSource/plugins/ShortenedTrackResolution.cc @@ -13,6 +13,9 @@ // ROOT includes #include "TLorentzVector.h" +// standard includes +#include + class ShortenedTrackResolution : public DQMEDAnalyzer { public: ShortenedTrackResolution(const edm::ParameterSet &); @@ -67,7 +70,13 @@ void ShortenedTrackResolution::bookHistograms(DQMStore::IBooker &iBook, 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)); + fmt::sprintf("trackPtRatio_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} / Full Track p_{T} - %s layers;p_{T}^{short}/p_{T}^{full};n. tracks", + hitsRemain_[i]) + .c_str(), + 101, + -0.05, + 2.05)); } } diff --git a/DQM/TrackingMonitorSource/test/BuildFile.xml b/DQM/TrackingMonitorSource/test/BuildFile.xml index 80f374037d92c..5d606b7bfcc91 100644 --- a/DQM/TrackingMonitorSource/test/BuildFile.xml +++ b/DQM/TrackingMonitorSource/test/BuildFile.xml @@ -1 +1,2 @@ + diff --git a/DQM/TrackingMonitorSource/test/testTrackResolutionHarvesting_cfg.py b/DQM/TrackingMonitorSource/test/testTrackResolutionHarvesting_cfg.py new file mode 100644 index 0000000000000..3a399aae2523f --- /dev/null +++ b/DQM/TrackingMonitorSource/test/testTrackResolutionHarvesting_cfg.py @@ -0,0 +1,91 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.ParameterSet.VarParsing as VarParsing + +options = VarParsing.VarParsing() +options.register('maxEvents', + -1, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "maximum events") +options.register('globalTag', + '125X_mcRun3_2022_design_v6', + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "conditions") +options.register('inputFile', + 'step1_DQM_LayerRot_9p43e-6_fromRECO.root', + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "input file") +options.parseArguments() + +from Configuration.Eras.Era_Run3_cff import Run3 +process = cms.Process('HARVESTING',Run3) + +# import of standard configurations +process.load('Configuration.StandardSequences.Services_cff') +process.load('SimGeneral.HepPDTESSource.pythiapdt_cfi') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.load('Configuration.EventContent.EventContent_cff') +process.load('SimGeneral.MixingModule.mixNoPU_cfi') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.DQMSaverAtRunEnd_cff') +process.load('Configuration.StandardSequences.Harvesting_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(options.maxEvents), + output = cms.optional.untracked.allowed(cms.int32,cms.PSet) +) + +# Input source +process.source = cms.Source("DQMRootSource", + fileNames = cms.untracked.vstring('file:'+options.inputFile) + ) + +process.options = cms.untracked.PSet( + IgnoreCompletely = cms.untracked.vstring(), + Rethrow = cms.untracked.vstring('ProductNotFound'), + accelerators = cms.untracked.vstring('*'), + allowUnscheduled = cms.obsolete.untracked.bool, + canDeleteEarly = cms.untracked.vstring(), + deleteNonConsumedUnscheduledModules = cms.untracked.bool(True), + dumpOptions = cms.untracked.bool(False), + emptyRunLumiMode = cms.obsolete.untracked.string, + eventSetup = cms.untracked.PSet( + forceNumberOfConcurrentIOVs = cms.untracked.PSet( + allowAnyLabel_=cms.required.untracked.uint32 + ), + numberOfConcurrentIOVs = cms.untracked.uint32(0) + ), + fileMode = cms.untracked.string('FULLMERGE'), + forceEventSetupCacheClearOnNewRun = cms.untracked.bool(False), + makeTriggerResults = cms.obsolete.untracked.bool, + numberOfConcurrentLuminosityBlocks = cms.untracked.uint32(0), + numberOfConcurrentRuns = cms.untracked.uint32(1), + numberOfStreams = cms.untracked.uint32(0), + numberOfThreads = cms.untracked.uint32(1), + printDependencies = cms.untracked.bool(False), + sizeOfStackForThreadsInKB = cms.optional.untracked.uint32, + throwIfIllegalParameter = cms.untracked.bool(True), + wantSummary = cms.untracked.bool(False) +) + +# Other statements +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, options.globalTag, '') + +process.dqmsave_step = cms.Path(process.DQMSaver) + +# Schedule definition +process.schedule = cms.Schedule(process.alcaHarvesting,process.dqmsave_step) +from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask +associatePatAlgosToolsTask(process) + +# Customisation from command line + +# Add early deletion of temporary data products to reduce peak memory need +from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete +process = customiseEarlyDelete(process) +# End adding early deletion diff --git a/DQM/TrackingMonitorSource/test/testTrackResolution_cfg.py b/DQM/TrackingMonitorSource/test/testTrackResolution_cfg.py new file mode 100644 index 0000000000000..49ef4149d18de --- /dev/null +++ b/DQM/TrackingMonitorSource/test/testTrackResolution_cfg.py @@ -0,0 +1,157 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.Utilities.FileUtils as FileUtils +from FWCore.ParameterSet.VarParsing import VarParsing + +options = VarParsing('analysis') +options.register('inputTag', + 'LayerRot_9p43e-6', + VarParsing.multiplicity.singleton, + VarParsing.varType.string, + "input tag") +options.register('inputFile', + '/store/relval/CMSSW_14_0_0_pre1/RelValZMM_14/GEN-SIM-RECO/133X_mcRun3_2023_realistic_v3-v1/2590000/586487a4-71be-4b23-b5a4-5662fab803c9.root', + VarParsing.multiplicity.singleton, + VarParsing.varType.string, + "input file") +options.register('isAlCaReco', + False, + VarParsing.multiplicity.singleton, + VarParsing.varType.bool, + "is alcareco input file?") +options.register('isUnitTest', + False, + VarParsing.multiplicity.singleton, + VarParsing.varType.bool, + "is this configuration run in unit test?") +options.parseArguments() + +from Configuration.Eras.Era_Run3_cff import Run3 +process = cms.Process("TrackingResolution", Run3) + +##################################################################### +# import of standard configurations +##################################################################### +process.load('Configuration.StandardSequences.Services_cff') +process.load('SimGeneral.HepPDTESSource.pythiapdt_cfi') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = (100 if options.isUnitTest else 100000) +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('DQMOffline.Configuration.DQMOffline_cff') +process.load('Configuration.StandardSequences.EndOfProcess_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +##################################################################### +## BeamSpot from database (i.e. GlobalTag), needed for Refitter +##################################################################### +process.load("RecoVertex.BeamSpotProducer.BeamSpot_cfi") + +##################################################################### +# Load and Configure Measurement Tracker Event +##################################################################### +process.load("RecoTracker.MeasurementDet.MeasurementTrackerEventProducer_cfi") +if(options.isAlCaReco): + # customize MeasurementTrackerEvent for ALCARECO + process.MeasurementTrackerEvent.pixelClusterProducer = "ALCARECOTkAlDiMuon" + process.MeasurementTrackerEvent.stripClusterProducer = "ALCARECOTkAlDiMuon" + process.MeasurementTrackerEvent.inactivePixelDetectorLabels = cms.VInputTag() + process.MeasurementTrackerEvent.inactiveStripDetectorLabels = cms.VInputTag() + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(10 if options.isUnitTest else -1) +) + +##################################################################### +# Input source +##################################################################### +#filelist = FileUtils.loadListFromFile("listOfFiles_idealMC_GEN-SIM-RECO.txt") +#filelist = FileUtils.loadListFromFile("listOfFiles_idealMC_TkAlDiMuonAndVertex.txt") +#readFiles = cms.untracked.vstring( *filelist) + +readFiles = cms.untracked.vstring(options.inputFile) +process.source = cms.Source("PoolSource",fileNames = readFiles) + +process.options = cms.untracked.PSet() + +##################################################################### +# Output +##################################################################### +process.DQMoutput = cms.OutputModule("DQMRootOutputModule", + dataset = cms.untracked.PSet( + dataTier = cms.untracked.string('DQMIO'), + filterName = cms.untracked.string('') + ), + fileName = cms.untracked.string('file:step1_DQM_'+options.inputTag+'_'+('fromALCA' if options.isAlCaReco else 'fromRECO' )+'.root'), + outputCommands = process.DQMEventContent.outputCommands, + splitLevel = cms.untracked.int32(0) +) + +##################################################################### +# Other statements +##################################################################### +from Configuration.AlCa.GlobalTag import GlobalTag +#process.GlobalTag = GlobalTag(process.GlobalTag,"133X_mcRun3_2023_realistic_v3", '') +process.GlobalTag = GlobalTag(process.GlobalTag, "125X_mcRun3_2022_design_v6", '') +process.GlobalTag.toGet = cms.VPSet(cms.PSet(connect = cms.string("frontier://FrontierProd/CMS_CONDITIONS"), + record = cms.string('TrackerAlignmentRcd'), + tag = cms.string(options.inputTag))) + +##################################################################### +# The DQM analysis sequence +##################################################################### +process.load("DQM.TrackingMonitorSource.shortTrackResolution_cff") +process.load("RecoTracker.TrackProducer.TrackRefitters_cff") +import RecoTracker.TrackProducer.TrackRefitters_cff +process.LongTracksRefit = process.TrackRefitter.clone( + src = 'SingleLongTrackProducer', + TrajectoryInEvent = True, + TTRHBuilder = "WithAngleAndTemplate", + NavigationSchool = '' +) + +process.ShortTrackCandidates3.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates4.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates5.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates6.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates7.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates8.src = cms.InputTag("LongTracksRefit") + +process.SingleLongTrackProducer.matchMuons = cms.InputTag("muons") +if(options.isAlCaReco): + process.SingleLongTrackProducer.requiredDr = cms.double(-9999.) # do not require any matchings + process.SingleLongTrackProducer.allTracks = cms.InputTag("ALCARECOTkAlDiMuon") + +##################################################################### +# Path +##################################################################### +process.analysis_step = cms.Path(process.offlineBeamSpot * + process.MeasurementTrackerEvent * + process.SingleLongTrackProducer * + process.LongTracksRefit * + process.ShortTrackCandidates3 * + process.ShortTrackCandidates4 * + process.ShortTrackCandidates5 * + process.ShortTrackCandidates6 * + process.ShortTrackCandidates7 * + process.ShortTrackCandidates8 * + process.RefittedShortTracks3 * + process.RefittedShortTracks4 * + process.RefittedShortTracks5 * + process.RefittedShortTracks6 * + process.RefittedShortTracks7 * + process.RefittedShortTracks8 * + process.trackingResolution) + +##################################################################### +# Path and EndPath definitions +##################################################################### +process.endjob_step = cms.EndPath(process.endOfProcess) +process.DQMoutput_step = cms.EndPath(process.DQMoutput) + +process.schedule = cms.Schedule(process.analysis_step, process.endjob_step, process.DQMoutput_step) + +################################################################### +# Set the process to run multi-threaded +################################################################### +process.options.numberOfThreads = 8 diff --git a/DQM/TrackingMonitorSource/test/testTrackingResolution.sh b/DQM/TrackingMonitorSource/test/testTrackingResolution.sh new file mode 100755 index 0000000000000..25c44a8fdc3d7 --- /dev/null +++ b/DQM/TrackingMonitorSource/test/testTrackingResolution.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +function die { echo $1: status $2 ; exit $2; } + +echo -e "TESTING step1 with RECO inputs ...\n\n" +cmsRun ${SCRAM_TEST_PATH}/testTrackResolution_cfg.py isUnitTest=True || die "Failure running testTrackResolution_cfg.py isUnitTest=True" $? + +echo -e "TESTING step1 with ALCARECO inputs ...\n\n" +cmsRun ${SCRAM_TEST_PATH}/testTrackResolution_cfg.py isUnitTest=True isAlCaReco=True inputFile=/store/mc/Run3Winter23Reco/DYJetsToMuMu_M-50_TuneCP5_13p6TeV-madgraphMLM-pythia8/ALCARECO/TkAlDiMuonAndVertex-TRKDesignNoPU_AlcaRecoTRKMu_designGaussSigmaZ4cm_125X_mcRun3_2022_design_v6-v1/60000/93401af5-0da6-40ce-82e4-d5571c93dd97.root || die "Failure running testTrackResolution_cfg.py isUnitTest=True isAlCaReco=True" $? + +echo -e "TESTING harvesting with RECO inputs ...\n\n" +cmsRun ${SCRAM_TEST_PATH}/testTrackResolutionHarvesting_cfg.py || die "Failure running testTrackResolutionHarvesting_cfg.py" $? + +echo -e "TESTING harvesting with ALCARECO inputs ...\n\n" +cmsRun ${SCRAM_TEST_PATH}/testTrackResolutionHarvesting_cfg.py inputFile=step1_DQM_LayerRot_9p43e-6_fromALCA.root || die "Failure running testTrackResolutionHarvesting_cfg.py inputFile=step1_DQM_LayerRot_9p43e-6_fromALCA.root" $? diff --git a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc index a9b8141f423ac..4301dac1e511e 100644 --- a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc +++ b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc @@ -67,7 +67,7 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup } const auto &muons = iEvent.getHandle(muonsToken); - if (!muons.isValid()) { + if (!muons.isValid() && matchInDr > 0.) { edm::LogError("SingleLongTrackProducer") << "Input muon collection is not valid.\n Returning empty output track collection."; iEvent.put(std::move(goodTracks), ""); @@ -108,21 +108,22 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup 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; + // Long track needs to be close to a good muon (only if requested) + if (matchInDr > 0.) { + 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; } - - if (dRmin >= matchInDr) - continue; // do vertex consistency: bool vertex_match = dxy < maxDxy && dz < maxDz; if (!(vertex_match)) @@ -226,17 +227,18 @@ 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("earlyMuons")); - 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); + desc.add("allTracks", edm::InputTag("generalTracks"))->setComment("input track collection"); + desc.add("matchMuons", edm::InputTag("earlyMuons"))->setComment("input muon collection for matching"); + desc.add("PrimaryVertex", edm::InputTag("offlinePrimaryVertices")) + ->setComment("input primary vertex collection"); + desc.add("minNumberOfLayers", 10)->setComment("minimum number of layers"); + desc.add("requiredDr", 0.01)->setComment("matching muons deltaR. If negative do not match"); + desc.add("onlyValidHits", true)->setComment("use only valid hits"); + desc.add("debug", false)->setComment("verbose?"); + desc.add("minPt", 15.0)->setComment("minimum pT"); + desc.add("maxEta", 2.2)->setComment("maximum pseudorapidity (absolute value)"); + desc.add("maxDxy", 0.02)->setComment("maximum transverse impact parameter"); + desc.add("maxDz", 0.5)->setComment("maximum longitudinal impact parameter"); descriptions.addWithDefaultLabel(desc); } From 3be3e25aa7e232fe84c1e3b86428c402a6299b3e Mon Sep 17 00:00:00 2001 From: mmusich Date: Thu, 4 Jan 2024 12:26:46 +0100 Subject: [PATCH 2/3] add ShortenedTrackValidation and related configuration --- .../plugins/ShortenedTrackValidation.cc | 600 ++++++++++++++++++ .../test/testShortenedTrackValidation_cfg.py | 153 +++++ 2 files changed, 753 insertions(+) create mode 100644 Alignment/OfflineValidation/plugins/ShortenedTrackValidation.cc create mode 100644 Alignment/OfflineValidation/test/testShortenedTrackValidation_cfg.py diff --git a/Alignment/OfflineValidation/plugins/ShortenedTrackValidation.cc b/Alignment/OfflineValidation/plugins/ShortenedTrackValidation.cc new file mode 100644 index 0000000000000..d606dd6f2704d --- /dev/null +++ b/Alignment/OfflineValidation/plugins/ShortenedTrackValidation.cc @@ -0,0 +1,600 @@ +// -*- C++ -*- +// +// Package: Alignment/OfflineValidation +// Class: ShortenedTrackValidation +// +/* + *\class ShortenedTrackValidation ShortenedTrackValidation.cc Alignment/OfflineValidation/plugins/ShortenedTrackValidation.cc + + Description: This module is meant to monitor the track pT resolution using the amputated tracks method, by comparing the performance using different alignments. + + Implementation: The implemenation takes advantage of the existing implementation in the DQM/TrackingMonitorSource. + +*/ +// +// Original Author: Marco Musich +// Created: Fri, 05 Jan 2023 11:41:00 GMT +// +// + +// ROOT includes files +#include "TMath.h" +#include "TFile.h" +#include "TH1D.h" +#include "TH1I.h" +#include "TH2D.h" +#include "TProfile.h" +#include "TLorentzVector.h" + +// standard includes +#include + +// user includes +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/SiStripDetId/interface/SiStripDetId.h" +#include "DataFormats/TrackerRecHit2D/interface/ProjectedSiStripRecHit2D.h" +#include "DataFormats/TrackerRecHit2D/interface/SiStripMatchedRecHit2D.h" +#include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit1D.h" +#include "DataFormats/TrackerRecHit2D/interface/SiTrackerMultiRecHit.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/transform.h" // for edm::vector_transform + +#define CREATE_HIST_1D(varname, nbins, first, last, fs) fs.make(#varname, #varname, nbins, first, last) + +#define CREATE_HIST_2D(varname, nbins, first, last, fs) \ + fs.make(#varname, #varname, nbins, first, last, nbins, first, last) + +const int kBPIX = PixelSubdetector::PixelBarrel; +const int kFPIX = PixelSubdetector::PixelEndcap; + +class ShortenedTrackValidation : public edm::one::EDAnalyzer { + class trackingMon { + public: + trackingMon() {} + ~trackingMon() = default; + + void book(const TFileDirectory &fs) { + h_chi2ndof = CREATE_HIST_1D(h_chi2ndof, 100, 0.0, 10.0, fs); + h_trkQuality = CREATE_HIST_1D(h_trkQuality, 6, -1, 5, fs); + h_trkAlgo = CREATE_HIST_1D(h_trkAlgo, reco::TrackBase::algoSize, 0.0, double(reco::TrackBase::algoSize), fs); + h_trkOriAlgo = + CREATE_HIST_1D(h_trkOriAlgo, reco::TrackBase::algoSize, 0.0, double(reco::TrackBase::algoSize), fs); + h_P = CREATE_HIST_1D(h_P, 100, 0.0, 200.0, fs); + h_Pt = CREATE_HIST_1D(h_Pt, 100, 0.0, 100.0, fs); + h_nHit = CREATE_HIST_1D(h_nHit, 50, -0.5, 49.5, fs); + h_nHit2D = CREATE_HIST_1D(h_nHit2D, 20, -0.5, 19.5, fs); + h_Charge = CREATE_HIST_1D(h_Charge, 3, -1.5, 1.5, fs); + h_QoverP = CREATE_HIST_1D(h_QoverP, 100, -1.0, 1.0, fs); + h_QoverPZoom = CREATE_HIST_1D(h_QoverPZoom, 100, -0.1, 0.1, fs); + h_Eta = CREATE_HIST_1D(h_Eta, 100, -3., 3., fs); + h_Phi = CREATE_HIST_1D(h_Phi, 100, -M_PI, M_PI, fs); + h_vx = CREATE_HIST_1D(h_vx, 100, -0.5, 0.5, fs); + h_vy = CREATE_HIST_1D(h_vy, 100, -0.5, 0.5, fs); + h_vz = CREATE_HIST_1D(h_vz, 100, -20.0, 20.0, fs); + h_d0 = CREATE_HIST_1D(h_d0, 100, -0.5, 0.5, fs); + h_dz = CREATE_HIST_1D(h_dz, 100, -20.0, 20.0, fs); + h_dxy = CREATE_HIST_1D(h_dxy, 100, -0.5, 0.5, fs); + h_nhpxb = CREATE_HIST_1D(h_nhpxb, 10, -0.5, 9.5, fs); + h_nhpxe = CREATE_HIST_1D(h_nhpxe, 10, -0.5, 9.5, fs); + h_nhTIB = CREATE_HIST_1D(h_nhTIB, 20, -0.5, 19.5, fs); + h_nhTID = CREATE_HIST_1D(h_nhTID, 20, -0.5, 19.5, fs); + h_nhTOB = CREATE_HIST_1D(h_nhTOB, 20, -0.5, 19.5, fs); + h_nhTEC = CREATE_HIST_1D(h_nhTEC, 20, -0.5, 19.5, fs); + h_dxyBS = CREATE_HIST_1D(h_dxyBS, 100, -0.05, 0.05, fs); + h_d0BS = CREATE_HIST_1D(h_d0BS, 100, -0.05, 0.05, fs); + h_dzBS = CREATE_HIST_1D(h_dzBS, 100, -20.0, 20., fs); + h_dxyPV = CREATE_HIST_1D(h_dxyPV, 100, -0.05, 0.05, fs); + h_d0PV = CREATE_HIST_1D(h_d0PV, 100, -0.05, 0.05, fs); + h_dzPV = CREATE_HIST_1D(h_dzPV, 100, -0.05, 0.05, fs); + + edm::LogInfo("trackingMonitoring") << "done booking"; + } + + //____________________________________________________________ + int trackQual(const reco::Track &track) { + int myquality = -99; + if (track.quality(reco::TrackBase::undefQuality)) + myquality = -1; + if (track.quality(reco::TrackBase::loose)) + myquality = 0; + if (track.quality(reco::TrackBase::tight)) + myquality = 1; + if (track.quality(reco::TrackBase::highPurity)) + myquality = 2; + if (track.quality(reco::TrackBase::goodIterative)) + myquality = 3; + + return myquality; + } + + //____________________________________________________________ + static bool isHit2D(const TrackingRecHit &hit) { + if (hit.dimension() < 2) { + return false; // some (muon...) stuff really has RecHit1D + } else { + const DetId detId(hit.geographicalId()); + if (detId.det() == DetId::Tracker) { + if (detId.subdetId() == kBPIX || detId.subdetId() == kFPIX) { + return true; // pixel is always 2D + } else { // should be SiStrip now + if (dynamic_cast(&hit)) + return false; // normal hit + else if (dynamic_cast(&hit)) + return true; // matched is 2D + else if (dynamic_cast(&hit)) + return false; // crazy hit... + else { + edm::LogError("UnknownType") << "@SUB=CalibrationTrackSelector::isHit2D" + << "Tracker hit not in pixel and neither SiStripRecHit2D nor " + << "SiStripMatchedRecHit2D nor ProjectedSiStripRecHit2D."; + return false; + } + } + } else { // not tracker?? + edm::LogWarning("DetectorMismatch") << "@SUB=CalibrationTrackSelector::isHit2D" + << "Hit not in tracker with 'official' dimension >=2."; + return true; // dimension() >= 2 so accept that... + } + } + // never reached... + } + + //____________________________________________________________ + unsigned int count2DHits(const reco::Track &track) { + unsigned int nHit2D = 0; + for (auto iHit = track.recHitsBegin(); iHit != track.recHitsEnd(); ++iHit) { + if (isHit2D(**iHit)) { + ++nHit2D; + } + } + return nHit2D; + } + + //____________________________________________________________ + void fill(const reco::Track &track, const reco::BeamSpot &beamSpot, const reco::Vertex &pvtx) { + h_chi2ndof->Fill(track.normalizedChi2()); + h_trkQuality->Fill(trackQual(track)); + h_trkAlgo->Fill(static_cast(track.algo())); + h_trkOriAlgo->Fill(static_cast(track.originalAlgo())); + h_P->Fill(track.p()); + h_Pt->Fill(track.pt()); + h_nHit->Fill(track.numberOfValidHits()); + h_nHit2D->Fill(count2DHits(track)); + h_Charge->Fill(track.charge()); + h_QoverP->Fill(track.qoverp()); + h_QoverPZoom->Fill(track.qoverp()); + h_Eta->Fill(track.eta()); + h_Phi->Fill(track.phi()); + h_vx->Fill(track.vx()); + h_vy->Fill(track.vy()); + h_vz->Fill(track.vz()); + h_d0->Fill(track.d0()); + h_dz->Fill(track.dz()); + h_dxy->Fill(track.dxy()); + h_nhpxb->Fill(track.hitPattern().numberOfValidPixelBarrelHits()); + h_nhpxe->Fill(track.hitPattern().numberOfValidPixelEndcapHits()); + h_nhTIB->Fill(track.hitPattern().numberOfValidStripTIBHits()); + h_nhTID->Fill(track.hitPattern().numberOfValidStripTIDHits()); + h_nhTOB->Fill(track.hitPattern().numberOfValidStripTOBHits()); + h_nhTEC->Fill(track.hitPattern().numberOfValidStripTECHits()); + + math::XYZPoint BS(beamSpot.x0(), beamSpot.y0(), beamSpot.z0()); + h_dxyBS->Fill(track.dxy(BS)); + h_d0BS->Fill(-track.dxy(BS)); + h_dzBS->Fill(track.dz(BS)); + + math::XYZPoint PV(pvtx.x(), pvtx.y(), pvtx.z()); + h_dxyPV->Fill(track.dxy(PV)); + h_d0PV->Fill(-track.dxy(PV)); + h_dzPV->Fill(track.dz(PV)); + } + + private: + TH1D *h_chi2ndof; + TH1D *h_trkQuality; + TH1D *h_trkAlgo; + TH1D *h_trkOriAlgo; + TH1D *h_P; + TH1D *h_Pt; + TH1D *h_nHit; + TH1D *h_nHit2D; + TH1D *h_Charge; + TH1D *h_QoverP; + TH1D *h_QoverPZoom; + TH1D *h_Eta; + TH1D *h_Phi; + TH1D *h_vx; + TH1D *h_vy; + TH1D *h_vz; + TH1D *h_d0; + TH1D *h_dz; + TH1D *h_dxy; + TH1D *h_nhpxb; + TH1D *h_nhpxe; + TH1D *h_nhTIB; + TH1D *h_nhTID; + TH1D *h_nhTOB; + TH1D *h_nhTEC; + TH1D *h_dxyBS; + TH1D *h_d0BS; + TH1D *h_dzBS; + TH1D *h_dxyPV; + TH1D *h_d0PV; + TH1D *h_dzPV; + }; + + class trackComparator { + public: + trackComparator() {} + ~trackComparator() = default; + + //__________________________________________________ + void book(const TFileDirectory &fs) { + h2_chi2ndof = CREATE_HIST_2D(h2_chi2ndof, 100, 0.0, 10.0, fs); + h2_trkAlgo = CREATE_HIST_2D(h2_trkAlgo, reco::TrackBase::algoSize, 0.0, double(reco::TrackBase::algoSize), fs); + h2_trkOriAlgo = + CREATE_HIST_2D(h2_trkOriAlgo, reco::TrackBase::algoSize, 0.0, double(reco::TrackBase::algoSize), fs); + h2_P = CREATE_HIST_2D(h2_P, 100, 0.0, 200.0, fs); + h2_Pt = CREATE_HIST_2D(h2_Pt, 100, 0.0, 100.0, fs); + h2_nHit = CREATE_HIST_2D(h2_nHit, 50, -0.5, 49.5, fs); + h2_Charge = CREATE_HIST_2D(h2_Charge, 3, -1.5, 1.5, fs); + h2_QoverPZoom = CREATE_HIST_2D(h2_QoverPZoom, 100, -0.1, 0.1, fs); + h2_Eta = CREATE_HIST_2D(h2_Eta, 100, -3., 3., fs); + h2_Phi = CREATE_HIST_2D(h2_Phi, 100, -M_PI, M_PI, fs); + h2_vx = CREATE_HIST_2D(h2_vx, 100, -0.5, 0.5, fs); + h2_vy = CREATE_HIST_2D(h2_vy, 100, -0.5, 0.5, fs); + h2_vz = CREATE_HIST_2D(h2_vz, 100, -20.0, 20.0, fs); + h2_d0 = CREATE_HIST_2D(h2_d0, 100, -0.5, 0.5, fs); + h2_dz = CREATE_HIST_2D(h2_dz, 100, -20.0, 20.0, fs); + h2_nhpxb = CREATE_HIST_2D(h2_nhpxb, 10, -0.5, 9.5, fs); + h2_nhpxe = CREATE_HIST_2D(h2_nhpxe, 10, -0.5, 9.5, fs); + h2_nhTIB = CREATE_HIST_2D(h2_nhTIB, 20, -0.5, 19.5, fs); + h2_nhTID = CREATE_HIST_2D(h2_nhTID, 20, -0.5, 19.5, fs); + h2_nhTOB = CREATE_HIST_2D(h2_nhTOB, 20, -0.5, 19.5, fs); + h2_nhTEC = CREATE_HIST_2D(h2_nhTEC, 20, -0.5, 19.5, fs); + } + + //__________________________________________________ + void fill(const reco::Track &tk1, const reco::Track &tk2) { + h2_chi2ndof->Fill(tk1.normalizedChi2(), tk2.normalizedChi2()); + h2_trkAlgo->Fill(static_cast(tk1.algo()), static_cast(tk2.algo())); + h2_trkOriAlgo->Fill(static_cast(tk1.originalAlgo()), static_cast(tk2.originalAlgo())); + h2_P->Fill(tk1.p(), tk2.p()); + h2_Pt->Fill(tk1.pt(), tk2.p()); + h2_nHit->Fill(tk1.numberOfValidHits(), tk2.numberOfValidHits()); + h2_Charge->Fill(tk1.charge(), tk2.charge()); + h2_QoverPZoom->Fill(tk1.qoverp(), tk2.qoverp()); + h2_Eta->Fill(tk1.eta(), tk2.eta()); + h2_Phi->Fill(tk1.phi(), tk2.phi()); + h2_vx->Fill(tk1.vx(), tk2.vx()); + h2_vy->Fill(tk1.vy(), tk2.vy()); + h2_vz->Fill(tk1.vz(), tk2.vz()); + h2_d0->Fill(tk1.d0(), tk2.d0()); + h2_dz->Fill(tk2.dz(), tk2.dz()); + h2_nhpxb->Fill(tk1.hitPattern().numberOfValidPixelBarrelHits(), tk2.hitPattern().numberOfValidPixelBarrelHits()); + h2_nhpxe->Fill(tk1.hitPattern().numberOfValidPixelEndcapHits(), tk2.hitPattern().numberOfValidPixelEndcapHits()); + h2_nhTIB->Fill(tk1.hitPattern().numberOfValidStripTIBHits(), tk2.hitPattern().numberOfValidStripTIBHits()); + h2_nhTID->Fill(tk1.hitPattern().numberOfValidStripTIDHits(), tk2.hitPattern().numberOfValidStripTIDHits()); + h2_nhTOB->Fill(tk1.hitPattern().numberOfValidStripTOBHits(), tk2.hitPattern().numberOfValidStripTOBHits()); + h2_nhTEC->Fill(tk1.hitPattern().numberOfValidStripTECHits(), tk2.hitPattern().numberOfValidStripTECHits()); + } + + private: + TH2D *h2_chi2ndof; + TH2D *h2_trkAlgo; + TH2D *h2_trkOriAlgo; + TH2D *h2_P; + TH2D *h2_Pt; + TH2D *h2_nHit; + TH2D *h2_Charge; + TH2D *h2_QoverPZoom; + TH2D *h2_Eta; + TH2D *h2_Phi; + TH2D *h2_vx; + TH2D *h2_vy; + TH2D *h2_vz; + TH2D *h2_d0; + TH2D *h2_dz; + TH2D *h2_nhpxb; + TH2D *h2_nhpxe; + TH2D *h2_nhTIB; + TH2D *h2_nhTID; + TH2D *h2_nhTOB; + TH2D *h2_nhTEC; + }; + +public: + explicit ShortenedTrackValidation(const edm::ParameterSet &); + ~ShortenedTrackValidation() override = default; + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + +private: + template + T *book(const TFileDirectory &dir, const Args &...args) const; + void beginJob() override; + void analyze(edm::Event const &iEvent, edm::EventSetup const &iSetup) override; + + // ----------member data --------------------------- + edm::Service fs_; + 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::InputTag BeamSpotTag_; + const edm::InputTag VerticesTag_; + const edm::EDGetTokenT> tracksToken_; + const std::vector>> tracksRerecoToken_; + const edm::EDGetTokenT beamspotToken_; + const edm::EDGetTokenT vertexToken_; + + // monitoring histograms + std::vector histsPtRatioAll_; + std::vector histsPtDiffAll_; + std::vector histsEtaDiffAll_; + std::vector histsPhiDiffAll_; + std::vector histsPtRatioVsDeltaRAll_; + std::vector histsDeltaPtOverPtAll_; + std::vector histsPtAll_; + std::vector histsNhitsAll_; + std::vector histsDeltaRAll_; + + trackingMon originalTrack; + std::vector comparators_; + static constexpr double muMass = 0.105658; +}; + +// ----------------------------- +// constructors and destructor +// ----------------------------- +ShortenedTrackValidation::ShortenedTrackValidation(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")), + BeamSpotTag_(ps.getUntrackedParameter("BeamSpotTag", edm::InputTag("offlineBeamSpot"))), + VerticesTag_(ps.getUntrackedParameter("VerticesTag", edm::InputTag("offlinePrimaryVertices"))), + tracksToken_(consumes>(tracksTag_)), + tracksRerecoToken_(edm::vector_transform( + tracksRerecoTag_, [this](edm::InputTag const &tag) { return consumes>(tag); })), + beamspotToken_(consumes(BeamSpotTag_)), + vertexToken_(consumes(VerticesTag_)) { + usesResource(TFileService::kSharedResource); + histsPtRatioAll_.clear(); + histsPtDiffAll_.clear(); + histsEtaDiffAll_.clear(); + histsPhiDiffAll_.clear(); + histsPtRatioVsDeltaRAll_.clear(); + histsDeltaPtOverPtAll_.clear(); + histsPtAll_.clear(); + histsNhitsAll_.clear(); + histsDeltaRAll_.clear(); + comparators_.clear(); + + comparators_.reserve(hitsRemain_.size()); + for (unsigned int i = 0; i < hitsRemain_.size(); ++i) { + comparators_.push_back(new trackComparator()); + } +} + +//__________________________________________________________________________________ +template +T *ShortenedTrackValidation::book(const TFileDirectory &dir, const Args &...args) const { + T *t = dir.make(args...); + return t; +} + +//__________________________________________________________________________________ +void ShortenedTrackValidation::beginJob() { + std::string currentFolder = folderName_ + "/Resolutions"; + TFileDirectory ShortTrackResolution = fs_->mkdir(currentFolder); + currentFolder = folderName_ + "/Tracks"; + TFileDirectory TrackQuals = fs_->mkdir(currentFolder); + + for (unsigned int i = 0; i < hitsRemain_.size(); ++i) { + histsPtRatioAll_.push_back( + book(ShortTrackResolution, + fmt::sprintf("trackPtRatio_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} / Full Track p_{T} - %s layers;p_{T}^{short}/p_{T}^{full};n. tracks", + hitsRemain_[i]) + .c_str(), + 101, + -0.05, + 2.05)); + + histsPtDiffAll_.push_back(book( + ShortTrackResolution, + fmt::sprintf("trackPtDiff_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} - Full Track p_{T} - %s layers;p_{T}^{short} - p_{T}^{full} [GeV];n. tracks", + hitsRemain_[i]) + .c_str(), + 100, + -10., + 10.)); + + histsEtaDiffAll_.push_back( + book(ShortTrackResolution, + fmt::sprintf("trackEtaDiff_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track #eta - Full Track #eta - %s layers;#eta^{short} - #eta^{full};n. tracks", + hitsRemain_[i]) + .c_str(), + 100, + -0.01, + 0.01)); + + histsPhiDiffAll_.push_back( + book(ShortTrackResolution, + fmt::sprintf("trackPhiDiff_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track #phi - Full Track #phi - %s layers;#phi^{short} - #phi^{full};n. tracks", + hitsRemain_[i]) + .c_str(), + 100, + -0.01, + 0.01)); + + histsPtRatioVsDeltaRAll_.push_back( + book(ShortTrackResolution, + fmt::sprintf("trackPtRatioVsDeltaR_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} / Full Track p_{T} - %s layers vs " + "#DeltaR;#DeltaR(short,full);p_{T}^{short}/p_{T}^{full} [GeV];n. tracks", + hitsRemain_[i]) + .c_str(), + 100, + 0., + 0.01, + 101, + -0.05, + 2.05)); + + histsDeltaPtOverPtAll_.push_back( + book(ShortTrackResolution, + fmt::sprintf("trackDeltaPtOverPt_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} - Full Track p_{T} / Full Track p_{T} - %s layers;p_{T}^{short} - " + "p_{T}^{full} / p^{full}_{T};n. tracks", + hitsRemain_[i]) + .c_str(), + 101, + -10., + 10.)); + + histsPtAll_.push_back( + book(TrackQuals, + fmt::sprintf("trackPt_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track p_{T} - %s layers;p_{T}^{short} [GeV];n. tracks", hitsRemain_[i]).c_str(), + 101, + -0.05, + 200.5)); + + histsNhitsAll_.push_back( + book(TrackQuals, + fmt::sprintf("trackNhits_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track n. hits - %s layers; n. hits per track;n. tracks", hitsRemain_[i]).c_str(), + 20, + -0.5, + 19.5)); + + histsDeltaRAll_.push_back(book( + TrackQuals, + fmt::sprintf("trackDeltaR_%s", hitsRemain_[i]).c_str(), + fmt::sprintf("Short Track / Long Track #DeltaR %s layers;#DeltaR(short,long);n. tracks", hitsRemain_[i]).c_str(), + 100, + 0., + 0.01)); + + currentFolder = fmt::sprintf("%s/Compare_%sHit", folderName_, hitsRemain_[i]); + comparators_[i]->book(fs_->mkdir(currentFolder)); + } + + currentFolder = folderName_ + "/OriginalTrack"; + TFileDirectory original = fs_->mkdir(currentFolder); + originalTrack.book(original); +} + +//__________________________________________________________________________________ +void ShortenedTrackValidation::analyze(edm::Event const &iEvent, edm::EventSetup const &iSetup) { + const auto &tracks = iEvent.getHandle(tracksToken_); + + if (!tracks.isValid()) { + edm::LogError("ShortenedTrackValidation") << "Missing input track collection " << tracksTag_.encode() << std::endl; + return; + } + + reco::BeamSpot beamSpot; + edm::Handle beamSpotHandle = iEvent.getHandle(beamspotToken_); + if (beamSpotHandle.isValid()) { + beamSpot = *beamSpotHandle; + } else { + beamSpot = reco::BeamSpot(); + } + + reco::Vertex pvtx; + edm::Handle vertexHandle = iEvent.getHandle(vertexToken_); + if (vertexHandle.isValid()) { + pvtx = (*vertexHandle).at(0); + } else { + pvtx = reco::Vertex(); + } + + // the original long track + 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; + } + + // fill the original track properties monitoring + originalTrack.fill(track, beamSpot, pvtx); + + TLorentzVector tvec; + tvec.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), muMass); + + int i = 0; // token index + // loop on the re-recoed shortened track collections + 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_) { + // fill the 2D comparisons per track + comparators_[i]->fill(track, track_rereco); + + histsPtRatioAll_[i]->Fill(1.0 * track_rereco.pt() / track.pt()); + histsPtDiffAll_[i]->Fill(track_rereco.pt() - track.pt()); + histsDeltaPtOverPtAll_[i]->Fill((track_rereco.pt() - track.pt()) / track.pt()); + histsEtaDiffAll_[i]->Fill(track_rereco.eta() - track.eta()); + histsPhiDiffAll_[i]->Fill(track_rereco.phi() - track.phi()); + histsPtRatioVsDeltaRAll_[i]->Fill(deltaR, track_rereco.pt() / track.pt()); + histsPtAll_[i]->Fill(track_rereco.pt()); + histsNhitsAll_[i]->Fill(track_rereco.numberOfValidHits()); + histsDeltaRAll_[i]->Fill(deltaR); + } + } + } + ++i; + } + } +} + +//__________________________________________________________________________________ +void ShortenedTrackValidation::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", {}); + desc.addUntracked("BeamSpotTag", edm::InputTag("offlineBeamSpot")); + desc.addUntracked("VerticesTag", edm::InputTag("offlinePrimaryVertices")); + descriptions.addWithDefaultLabel(desc); +} + +// Define this as a plug-in +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(ShortenedTrackValidation); diff --git a/Alignment/OfflineValidation/test/testShortenedTrackValidation_cfg.py b/Alignment/OfflineValidation/test/testShortenedTrackValidation_cfg.py new file mode 100644 index 0000000000000..2901ef5a7fc83 --- /dev/null +++ b/Alignment/OfflineValidation/test/testShortenedTrackValidation_cfg.py @@ -0,0 +1,153 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.Utilities.FileUtils as FileUtils +from FWCore.ParameterSet.VarParsing import VarParsing + +options = VarParsing('analysis') +options.register('scenario', + '0', + VarParsing.multiplicity.singleton, + VarParsing.varType.string, + "Name of input misalignment scenario") +options.parseArguments() + +valid_scenarios = ['-10e-6','-8e-6','-6e-6','-4e-6','-2e-6','0','2e-6','4e-6','6e-6','8e-6','10e-6'] + +if options.scenario not in valid_scenarios: + print("Error: Invalid scenario specified. Please choose from the following list: ") + print(valid_scenarios) + exit(1) + +process = cms.Process("TrackingResolution") + +##################################################################### +# import of standard configurations +##################################################################### +process.load('Configuration.StandardSequences.Services_cff') +process.load('SimGeneral.HepPDTESSource.pythiapdt_cfi') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 100000 +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +##################################################################### +## BeamSpot from database (i.e. GlobalTag), needed for Refitter +##################################################################### +process.load("RecoVertex.BeamSpotProducer.BeamSpot_cfi") + +##################################################################### +# Load and Configure Measurement Tracker Event +##################################################################### +process.load("RecoTracker.MeasurementDet.MeasurementTrackerEventProducer_cfi") +process.MeasurementTrackerEvent.pixelClusterProducer = "ALCARECOTkAlDiMuon" +process.MeasurementTrackerEvent.stripClusterProducer = "ALCARECOTkAlDiMuon" +process.MeasurementTrackerEvent.inactivePixelDetectorLabels = cms.VInputTag() +process.MeasurementTrackerEvent.inactiveStripDetectorLabels = cms.VInputTag() + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(1000000) +) + +##################################################################### +# Input source +##################################################################### +# filelist = FileUtils.loadListFromFile("listOfFiles_idealMC_TkAlDiMuonAndVertex.txt") +# readFiles = cms.untracked.vstring( *filelist) +# events taken from /DYJetsToMuMu_M-50_TuneCP5_13p6TeV-madgraphMLM-pythia8/Run3Winter23Reco-TkAlDiMuonAndVertex-TRKDesignNoPU_AlcaRecoTRKMu_designGaussSigmaZ4cm_125X_mcRun3_2022_design_v6-v1/ALCARECO +readFiles = cms.untracked.vstring('/store/mc/Run3Winter23Reco/DYJetsToMuMu_M-50_TuneCP5_13p6TeV-madgraphMLM-pythia8/ALCARECO/TkAlDiMuonAndVertex-TRKDesignNoPU_AlcaRecoTRKMu_designGaussSigmaZ4cm_125X_mcRun3_2022_design_v6-v1/60000/d3af17a5-2409-4551-9c3d-00deb2f3f64f.root') +process.source = cms.Source("PoolSource",fileNames = readFiles) + +process.options = cms.untracked.PSet() + +#################################################################### +# Output file +#################################################################### +process.TFileService = cms.Service("TFileService", + fileName = cms.string("shortenedTrackResolution_LayerRotation_"+options.scenario+".root")) + +##################################################################### +# Other statements +##################################################################### +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, "125X_mcRun3_2022_design_v6", '') +if (options.scenario=='null'): + print("null scenario, do nothing") + pass +else: + process.GlobalTag.toGet = cms.VPSet(cms.PSet(connect = cms.string("frontier://FrontierPrep/CMS_CONDITIONS"), + record = cms.string('TrackerAlignmentRcd'), + tag = cms.string("LayerRotation_"+options.scenario))) + +##################################################################### +# The DQM analysis sequence +##################################################################### +process.load("DQM.TrackingMonitorSource.shortTrackResolution_cff") + +##################################################################### +# The changes to cope with ALCARECO data format +##################################################################### +process.load("RecoTracker.TrackProducer.TrackRefitters_cff") +import RecoTracker.TrackProducer.TrackRefitters_cff +process.LongTracksRefit = process.TrackRefitter.clone( + src = 'SingleLongTrackProducer', + TrajectoryInEvent = True, + TTRHBuilder = "WithAngleAndTemplate", + NavigationSchool = '' +) + +process.ShortTrackCandidates3.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates4.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates5.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates6.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates7.src = cms.InputTag("LongTracksRefit") +process.ShortTrackCandidates8.src = cms.InputTag("LongTracksRefit") + +process.SingleLongTrackProducer.requiredDr = cms.double(-9999.) # do not require any matchings +process.SingleLongTrackProducer.matchMuons = cms.InputTag("muons") # for ALCA irrelevant (see above) +process.SingleLongTrackProducer.allTracks = cms.InputTag("ALCARECOTkAlDiMuon") + +##################################################################### +# The Analysis module +##################################################################### +from Alignment.OfflineValidation.shortenedTrackValidation_cfi import shortenedTrackValidation as _shortenedTrackValidation +process.ShortenedTrackValidation = _shortenedTrackValidation.clone(folderName = "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 = ["RefittedShortTracks3", + "RefittedShortTracks4", + "RefittedShortTracks5", + "RefittedShortTracks6", + "RefittedShortTracks7", + "RefittedShortTracks8"]) + +##################################################################### +# Path +##################################################################### +process.analysis_step = cms.Path(process.offlineBeamSpot * + process.MeasurementTrackerEvent * + process.SingleLongTrackProducer * + process.LongTracksRefit * + process.ShortTrackCandidates3 * + process.ShortTrackCandidates4 * + process.ShortTrackCandidates5 * + process.ShortTrackCandidates6 * + process.ShortTrackCandidates7 * + process.ShortTrackCandidates8 * + process.RefittedShortTracks3 * + process.RefittedShortTracks4 * + process.RefittedShortTracks5 * + process.RefittedShortTracks6 * + process.RefittedShortTracks7 * + process.RefittedShortTracks8 * + process.ShortenedTrackValidation) + +################################################################### +# Set the process to run multi-threaded +################################################################### +process.options.numberOfThreads = 8 From 3da22f135cede8946c5fb127de8f66bbd4905ba0 Mon Sep 17 00:00:00 2001 From: mmusich Date: Wed, 17 Jan 2024 17:24:26 +0100 Subject: [PATCH 3/3] use deltaR2 for muon / track matching computation in SingleLongTrackProducer --- .../plugins/SingleLongTrackProducer.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc index 4301dac1e511e..8430385347ae4 100644 --- a/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc +++ b/RecoTracker/FinalTrackSelectors/plugins/SingleLongTrackProducer.cc @@ -1,4 +1,5 @@ // user includes +#include "DataFormats/Math/interface/deltaR.h" #include "DataFormats/MuonReco/interface/Muon.h" #include "DataFormats/TrackReco/interface/Track.h" #include "DataFormats/VertexReco/interface/Vertex.h" @@ -92,7 +93,7 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup for (const auto &track : *tracks) { const reco::HitPattern &hitpattern = track.hitPattern(); - double dRmin = 10; + double dR2min = 100.; double chiNdof = track.normalizedChi2(); double dxy = std::abs(track.dxy(vtx.position())); double dz = std::abs(track.dz(vtx.position())); @@ -106,22 +107,20 @@ void SingleLongTrackProducer::produce(edm::Event &iEvent, const edm::EventSetup 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 (only if requested) if (matchInDr > 0.) { 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; + double dr2 = reco::deltaR2(track, matchedTrack); + if (dr2 < dR2min) + dR2min = dr2; } } - if (dRmin >= matchInDr) + // matchInDr here is defined positive + if (dR2min >= matchInDr * matchInDr) continue; } // do vertex consistency: @@ -137,7 +136,7 @@ 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; + edm::LogPrint("SingleLongTrackProducer") << " deltaR2 (general) track to matched Track: " << dR2min; if (debug) edm::LogPrint("SingleLongTrackProducer") << "chi2Ndof:" << chiNdof << " best Track: " << fitProb; }