diff --git a/DataFormats/VertexReco/BuildFile.xml b/DataFormats/VertexReco/BuildFile.xml
index a8c7cac35828d..6f868dcc00bcf 100644
--- a/DataFormats/VertexReco/BuildFile.xml
+++ b/DataFormats/VertexReco/BuildFile.xml
@@ -1,6 +1,7 @@
-
+
+
diff --git a/DataFormats/VertexReco/interface/TrackTimeLifeInfo.h b/DataFormats/VertexReco/interface/TrackTimeLifeInfo.h
new file mode 100644
index 0000000000000..71f69ad4d41fe
--- /dev/null
+++ b/DataFormats/VertexReco/interface/TrackTimeLifeInfo.h
@@ -0,0 +1,81 @@
+#ifndef DataFormats_VertexReco_TrackTimeLifeInfo_h
+#define DataFormats_VertexReco_TrackTimeLifeInfo_h
+
+/**
+ \class TrackTimeLifeInfo
+ \brief Structure to hold time-life information
+
+ \author Michal Bluj, NCBJ, Warsaw
+*/
+
+#include "DataFormats/GeometryCommonDetAlgo/interface/GlobalError.h"
+#include "DataFormats/GeometryCommonDetAlgo/interface/Measurement1D.h"
+#include "DataFormats/GeometryVector/interface/GlobalPoint.h"
+#include "DataFormats/GeometryVector/interface/GlobalVector.h"
+#include "DataFormats/TrackReco/interface/Track.h"
+#include "DataFormats/VertexReco/interface/Vertex.h"
+
+class TrackTimeLifeInfo {
+public:
+ TrackTimeLifeInfo();
+ ~TrackTimeLifeInfo() {}
+
+ // Secondary vertex
+ void setSV(reco::Vertex sv) {
+ sv_ = sv;
+ hasSV_ = true;
+ }
+ const reco::Vertex& sv() const { return sv_; }
+ bool hasSV() const { return hasSV_; }
+ void setFlightVector(GlobalVector flight_vec, GlobalError flight_cov) {
+ flight_vec_ = flight_vec;
+ flight_cov_ = flight_cov;
+ }
+ // Flight-path
+ const GlobalVector& flightVector() const { return flight_vec_; }
+ const GlobalError& flightCovariance() const { return flight_cov_; }
+ void setFlightLength(Measurement1D flightLength) { flightLength_ = flightLength; }
+ const Measurement1D& flightLength() const { return flightLength_; }
+ // Point of closest approach
+ void setPCA(GlobalPoint pca, GlobalError pca_cov) {
+ pca_ = pca;
+ pca_cov_ = pca_cov;
+ }
+ const GlobalPoint& pca() const { return pca_; }
+ const GlobalError& pcaCovariance() const { return pca_cov_; }
+ // Impact parameter
+ void setIP(GlobalVector ip_vec, GlobalError ip_cov) {
+ ip_vec_ = ip_vec;
+ ip_cov_ = ip_cov;
+ }
+ const GlobalVector& ipVector() const { return ip_vec_; }
+ const GlobalError& ipCovariance() const { return ip_cov_; }
+ void setIPLength(Measurement1D ipLength) { ipLength_ = ipLength; }
+ const Measurement1D& ipLength() const { return ipLength_; }
+ // Track
+ void setTrack(const reco::Track* track) {
+ if (track != nullptr) {
+ track_ = *track;
+ hasTrack_ = true;
+ } else {
+ track_ = reco::Track();
+ hasTrack_ = false;
+ }
+ }
+ const reco::Track* track() const { return &track_; }
+ bool hasTrack() const { return hasTrack_; }
+ void setBField_z(float bField_z) { bField_z_ = bField_z; }
+ float bField_z() const { return bField_z_; }
+
+private:
+ bool hasSV_, hasTrack_;
+ reco::Vertex sv_;
+ GlobalVector flight_vec_, ip_vec_;
+ GlobalPoint pca_;
+ GlobalError flight_cov_, pca_cov_, ip_cov_;
+ Measurement1D flightLength_, ipLength_;
+ reco::Track track_;
+ float bField_z_;
+};
+
+#endif
diff --git a/DataFormats/VertexReco/src/TrackTimeLifeInfo.cc b/DataFormats/VertexReco/src/TrackTimeLifeInfo.cc
new file mode 100644
index 0000000000000..75228227dae21
--- /dev/null
+++ b/DataFormats/VertexReco/src/TrackTimeLifeInfo.cc
@@ -0,0 +1,16 @@
+#include "DataFormats/VertexReco/interface/TrackTimeLifeInfo.h"
+
+TrackTimeLifeInfo::TrackTimeLifeInfo()
+ : hasSV_(false),
+ hasTrack_(false),
+ sv_(reco::Vertex()),
+ flight_vec_(GlobalVector()),
+ ip_vec_(GlobalVector()),
+ pca_(GlobalPoint()),
+ flight_cov_(GlobalError()),
+ pca_cov_(GlobalError()),
+ ip_cov_(GlobalError()),
+ flightLength_(Measurement1D()),
+ ipLength_(Measurement1D()),
+ track_(reco::Track()),
+ bField_z_(0.){};
diff --git a/DataFormats/VertexReco/src/classes.h b/DataFormats/VertexReco/src/classes.h
index 9260d5d86d8c4..6a807d89b9434 100644
--- a/DataFormats/VertexReco/src/classes.h
+++ b/DataFormats/VertexReco/src/classes.h
@@ -15,5 +15,7 @@
#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"
+#include "DataFormats/VertexReco/interface/TrackTimeLifeInfo.h"
+
#include
#include
diff --git a/DataFormats/VertexReco/src/classes_def.xml b/DataFormats/VertexReco/src/classes_def.xml
index fe68ada1742fe..f20693ec82af6 100755
--- a/DataFormats/VertexReco/src/classes_def.xml
+++ b/DataFormats/VertexReco/src/classes_def.xml
@@ -48,4 +48,9 @@
+
+
+
+
+
diff --git a/PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h b/PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h
index 2e5c20452f8e0..a544f4b484d56 100644
--- a/PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h
+++ b/PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h
@@ -101,7 +101,7 @@ class ValueMapVariableBase : public ExtVariable {
if (vmap.isValid() || !skipNonExistingSrc_) {
vals.resize(selptrs.size());
for (unsigned int i = 0, n = vals.size(); i < n; ++i) {
- // calls the overloade method to either get the valuemap value directly, or a function of the object value.
+ // calls the overloaded method to either get the valuemap value directly, or a function of the object value.
vals[i] = this->eval(vmap, selptrs[i]);
}
}
@@ -121,7 +121,7 @@ class ValueMapVariable : public ValueMapVariableBase {
edm::ConsumesCollector &&cc,
bool skipNonExistingSrc = false)
: ValueMapVariableBase(aname, cfg, std::move(cc), skipNonExistingSrc) {}
- ValType eval(const edm::Handle> &vmap, const edm::Ptr &op) const {
+ ValType eval(const edm::Handle> &vmap, const edm::Ptr &op) const override {
ValType val = (*vmap)[op];
return val;
}
@@ -139,7 +139,7 @@ class TypedValueMapVariable : public ValueMapVariableBase
precisionFunc_(cfg.existsAs("precision") ? cfg.getParameter("precision") : "23",
true) {}
- ValType eval(const edm::Handle> &vmap, const edm::Ptr &op) const {
+ ValType eval(const edm::Handle> &vmap, const edm::Ptr &op) const override {
ValType val = func_((*vmap)[op]);
if constexpr (std::is_same()) {
if (this->precision_ == -2) {
@@ -333,7 +333,7 @@ class SimpleFlatTableProducer : public SimpleFlatTableProducerBase("precision",
true,
edm::Comment("the precision with which to store the value in the "
- "flat table, as a fucntion of the object evaluated")),
+ "flat table, as a function of the object evaluated")),
false);
edm::ParameterSetDescription extvariables;
@@ -452,7 +452,7 @@ class SimpleTypedExternalFlatTableProducer : public SimpleFlatTableProducer {
edm::ParameterDescription("precision",
true,
edm::Comment("the precision with which to store the value in the "
- "flat table, as a fucntion of the object evaluated")),
+ "flat table, as a function of the object evaluated")),
false);
edm::ParameterSetDescription extvariables;
@@ -577,7 +577,7 @@ class FirstObjectSimpleFlatTableProducer : public SimpleFlatTableProducerBase>::baseDescriptions();
+ edm::ParameterSetDescription desc = SimpleFlatTableProducerBase>::baseDescriptions();
descriptions.addWithDefaultLabel(desc);
}
diff --git a/PhysicsTools/NanoAOD/plugins/SimpleFlatTableProducerPlugins.cc b/PhysicsTools/NanoAOD/plugins/SimpleFlatTableProducerPlugins.cc
index 27dbb6487a9b8..8217d13f32bab 100644
--- a/PhysicsTools/NanoAOD/plugins/SimpleFlatTableProducerPlugins.cc
+++ b/PhysicsTools/NanoAOD/plugins/SimpleFlatTableProducerPlugins.cc
@@ -60,6 +60,13 @@ typedef SimpleFlatTableProducer SimpleRun3ScoutingElectron
#include "DataFormats/Scouting/interface/Run3ScoutingTrack.h"
typedef SimpleFlatTableProducer SimpleRun3ScoutingTrackFlatTableProducer;
+#include "DataFormats/VertexReco/interface/Vertex.h"
+typedef SimpleFlatTableProducer SimpleVertexFlatTableProducer;
+
+#include "DataFormats/VertexReco/interface/TrackTimeLifeInfo.h"
+typedef SimpleTypedExternalFlatTableProducer
+ SimpleCandidate2TrackTimeLifeInfoFlatTableProducer;
+
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(SimpleCandidateFlatTableProducer);
DEFINE_FWK_MODULE(SimpleCandidate2CandidateFlatTableProducer);
@@ -81,3 +88,5 @@ DEFINE_FWK_MODULE(SimpleRun3ScoutingPhotonFlatTableProducer);
DEFINE_FWK_MODULE(SimpleRun3ScoutingMuonFlatTableProducer);
DEFINE_FWK_MODULE(SimpleRun3ScoutingElectronFlatTableProducer);
DEFINE_FWK_MODULE(SimpleRun3ScoutingTrackFlatTableProducer);
+DEFINE_FWK_MODULE(SimpleVertexFlatTableProducer);
+DEFINE_FWK_MODULE(SimpleCandidate2TrackTimeLifeInfoFlatTableProducer);
diff --git a/PhysicsTools/NanoAOD/python/autoNANO.py b/PhysicsTools/NanoAOD/python/autoNANO.py
index 358aa6bb440ff..3938f157e2540 100644
--- a/PhysicsTools/NanoAOD/python/autoNANO.py
+++ b/PhysicsTools/NanoAOD/python/autoNANO.py
@@ -35,5 +35,8 @@ def expandNanoMapping(seqList, mapping, key):
'customize': 'DPGAnalysis/MuonTools/muNtupleProducerBkg_cff.muDPGNanoBkgCustomize'},
# PromptReco config: PHYS+L1
'Prompt' : {'sequence': '@PHYS',
- 'customize': '@PHYS+@L1'}
+ 'customize': '@PHYS+@L1'},
+ # Add lepton time-life info tables through customize combined with PHYS
+ 'LepTimeLife' : {'sequence': '@PHYS',
+ 'customize': '@PHYS+PhysicsTools/NanoAOD/leptonTimeLifeInfo_common_cff.addTimeLifeInfo'},
}
diff --git a/PhysicsTools/NanoAOD/python/leptonTimeLifeInfo_common_cff.py b/PhysicsTools/NanoAOD/python/leptonTimeLifeInfo_common_cff.py
new file mode 100644
index 0000000000000..e8001da6fbab7
--- /dev/null
+++ b/PhysicsTools/NanoAOD/python/leptonTimeLifeInfo_common_cff.py
@@ -0,0 +1,268 @@
+#
+# Common definition of time-life variables for pat-leptons produced
+# with {Electron,Muon,Tau}TimeLifeInfoTableProducer
+#
+import FWCore.ParameterSet.Config as cms
+from PhysicsTools.NanoAOD.common_cff import *
+from PhysicsTools.NanoAOD.nano_eras_cff import *
+from PhysicsTools.PatAlgos.patRefitVertexProducer_cfi import patRefitVertexProducer
+from PhysicsTools.NanoAOD.simpleVertexFlatTableProducer_cfi import simpleVertexFlatTableProducer
+from PhysicsTools.PatAlgos.patElectronTimeLifeInfoProducer_cfi import patElectronTimeLifeInfoProducer
+from PhysicsTools.PatAlgos.patMuonTimeLifeInfoProducer_cfi import patMuonTimeLifeInfoProducer
+from PhysicsTools.PatAlgos.patTauTimeLifeInfoProducer_cfi import patTauTimeLifeInfoProducer
+from PhysicsTools.NanoAOD.simpleCandidate2TrackTimeLifeInfoFlatTableProducer_cfi import simpleCandidate2TrackTimeLifeInfoFlatTableProducer
+from TrackingTools.TransientTrack.TransientTrackBuilder_cfi import *
+from PhysicsTools.NanoAOD.nanoDQM_tools_cff import *
+
+# common settings of lepton life-time info producer
+prod_common = cms.PSet(
+ pvSource = cms.InputTag("offlineSlimmedPrimaryVerticesWithBS"),
+ pvChoice = cms.int32(0) #0: PV[0], 1: smallest dz
+)
+
+# impact parameter
+ipVars = cms.PSet(
+ ipLength = Var("ipLength().value()", float, doc="lenght of impact parameter (3d)", precision=10),
+ ipLengthSig = Var("ipLength().significance()", float, doc="significance of impact parameter", precision=10),
+ IPx = Var("ipVector().x()", float, doc="x coordinate of impact parameter vector", precision=10),
+ IPy = Var("ipVector().y()", float, doc="y coordinate of impact parameter vector", precision=10),
+ IPz = Var("ipVector().z()", float, doc="z coordinate of impact parameter vector", precision=10)
+)
+
+# track parameters and covariance at ref. point
+trackVars = cms.PSet(
+ track_qoverp = Var("?hasTrack()?track().parameter(0):0", float, doc="track q/p", precision=10),
+ track_lambda = Var("?hasTrack()?track().parameter(1):0", float, doc="track lambda", precision=10),
+ track_phi = Var("?hasTrack()?track().parameter(2):0", float, doc="track phi", precision=10),
+ #track_deltaPhi = Var("?hasTrack()?deltaPhi(track().parameter(2), phi):0", float, doc="track phi minus lepton phi", precision=10),
+ track_dxy = Var("?hasTrack()?track().parameter(3):0", float, doc="track dxy", precision=10),
+ track_dsz = Var("?hasTrack()?track().parameter(4):0", float, doc="track dsz", precision=10),
+ bField_z = Var("?hasTrack()?bField_z:0", float, doc="z coordinate of magnetic field at track ref. point", precision=10),
+)
+# track covariance elements (adding to trackVars)
+for i in range(0,5):
+ for j in range(i,5):
+ jistr = str(j)+str(i)
+ setattr(trackVars, 'track_cov'+jistr, Var("?hasTrack()?track().covariance("+str(j)+","+str(i)+"):0", float, doc="track covariance element ("+str(j)+","+str(i)+")", precision=10))
+
+# secondary vertex
+svVars = cms.PSet(
+ # SV
+ hasRefitSV = Var("hasSV()", bool, doc="has SV refit using miniAOD quantities"),
+ refitSVx = Var("?hasSV()?sv().x():0", float, doc="x coordinate of SV", precision=10),
+ refitSVy = Var("?hasSV()?sv().y():0", float, doc="y coordinate of SV", precision=10),
+ refitSVz = Var("?hasSV()?sv().z():0", float, doc="z coordinate of SV", precision=10),
+ refitSVchi2 = Var("?hasSV()?sv().chi2():0", float, doc="chi2 of SV fit", precision=8),
+ refitSVndof = Var("?hasSV()?sv().ndof():0", float, doc="ndof of SV fit", precision=8),
+ # flight-length
+ #refitFlightLength = Var("?hasSV()?flightLength().value():0", float, doc="flight-length,i.e. the PV to SV distance", precision=10),
+ #refitFlightLengthSig = Var("?hasSV()?flightLength().significance():0", float, doc="Significance of flight-length", precision=10)
+)
+# secondary vertex covariance elements (adding to svVars)
+for i in range(0,3):
+ for j in range(i,3):
+ jistr = str(j)+str(i)
+ setattr(svVars, 'refitSVcov'+jistr, Var("?hasSV()?sv().covariance("+str(j)+","+str(i)+"):0", float, doc="Covariance of SV ("+str(j)+","+str(i)+")", precision=10))
+
+# primary vertex covariance elements
+pvCovVars = cms.PSet()
+for i in range(0,3):
+ for j in range(i,3):
+ jistr = str(j)+str(i)
+ setattr(pvCovVars, 'cov'+jistr, Var("covariance("+str(j)+","+str(i)+")", float, doc="vertex covariance ("+str(j)+","+str(i)+")", precision=10))
+
+# Module to refit PV with beam-spot constraint that is not present in Run-2 samples
+refittedPV = patRefitVertexProducer.clone(
+ srcVertices = "offlineSlimmedPrimaryVertices",
+)
+run2_nanoAOD_ANY.toModify(
+ prod_common, pvSource = "refittedPV")
+
+# Definition of DQM plots
+ipVarsPlots = cms.VPSet(
+ Plot1D('ipLength', 'ipLength', 25, -0.25, 0.25, 'signed lenght of impact parameter (3d)'),
+ Plot1D('ipLengthSig', 'ipLengthSig', 60, -5, 10, 'signed significance of impact parameter'),
+ Plot1D('IPx', 'IPx', 40, -0.02, 0.02, 'x coordinate of impact parameter vector'),
+ Plot1D('IPy', 'IPy', 40, -0.02, 0.02, 'y coordinate of impact parameter vector'),
+ Plot1D('IPz', 'IPz', 40, -0.02, 0.02, 'z coordinate of impact parameter vector')
+)
+trackVarsPlots = cms.VPSet(
+ Plot1D('track_qoverp', 'track_qoverp', 40, -0.2, 0.2, 'track q/p'),
+ Plot1D('track_lambda', 'track_lambda', 30, -1.5, 1.5, 'track lambda'),
+ Plot1D('track_phi', 'track_phi', 20, -3.14159, 3.14159, 'track phi'),
+ Plot1D('track_dxy', 'track_dxy', 20, -0.1, 0.1, 'track dxy'),
+ Plot1D('track_dsz', 'track_dsz', 20, -10, 10, 'track dsz'),
+ NoPlot('bField_z')
+)
+#no plots for track covariance elements, but store placeholders
+for i in range(0,5):
+ for j in range(i,5):
+ trackVarsPlots.append(NoPlot('track_cov'+str(j)+str(i)))
+svVarsPlots = cms.VPSet(
+ Plot1D('hasRefitSV', 'hasRefitSV', 2, 0, 2, 'has SV refit using miniAOD quantities'),
+ Plot1D('refitSVx', 'refitSVx', 20, -0.1, 0.1, 'x coordinate of refitted SV'),
+ Plot1D('refitSVy', 'refitSVy', 20, -0.1, 0.1, 'y coordinate of refitted SV'),
+ Plot1D('refitSVz', 'refitSVz', 20, -20, 20, 'z coordinate of refitted SV'),
+ Plot1D('refitSVchi2', 'refitSVchi2', 20, 0, 100, 'chi2 of SV fit'),
+ Plot1D('refitSVndof', 'refitSVndof', 10, 0, 10, 'ndof of SV fit')
+)
+#no plots for SV covariance elements, but store placeholders
+for i in range(0,3):
+ for j in range(i,3):
+ svVarsPlots.append(NoPlot('refitSVcov'+str(j)+str(i)))
+
+#
+# Customization sequences and functions
+#
+# electrons
+electronVars = cms.PSet(
+ ipVars,
+ trackVars
+)
+for var in electronVars.parameters_():
+ setattr(getattr(electronVars, var), "src", cms.InputTag("electronTimeLifeInfos"))
+def addTimeLifeInfoToElectrons(process):
+ process.electronTimeLifeInfos = patElectronTimeLifeInfoProducer.clone(
+ src = process.electronTable.src,
+ selection = 'pt > 15',
+ pvSource = prod_common.pvSource,
+ pvChoice = prod_common.pvChoice
+ )
+ process.electronTimeLifeInfoTable = simpleCandidate2TrackTimeLifeInfoFlatTableProducer.clone(
+ name = process.electronTable.name,
+ src = process.electronTable.src,
+ doc = cms.string("Additional time-life info for non-prompt electrons"),
+ extension = True,
+ externalTypedVariables = electronVars
+ )
+ process.electronTimeLifeInfoTask = cms.Task(
+ process.electronTimeLifeInfos,
+ process.electronTimeLifeInfoTable
+ )
+ # refit PV with beam-spot constraint that is not present in Run-2 samples
+ if not hasattr(process,'refittedPV'):
+ setattr(process,'refittedPV',refittedPV)
+ _electronTimeLifeInfoTaskRun2 = process.electronTimeLifeInfoTask.copy()
+ _electronTimeLifeInfoTaskRun2.add(process.refittedPV)
+ run2_nanoAOD_ANY.toReplaceWith(process.electronTimeLifeInfoTask,
+ _electronTimeLifeInfoTaskRun2)
+ process.electronTablesTask.add(process.electronTimeLifeInfoTask)
+ # add DQM plots if needed
+ if hasattr(process,'nanoDQM'):
+ process.nanoDQM.vplots.Electron.plots.extend(ipVarsPlots)
+ process.nanoDQM.vplots.Electron.plots.extend(trackVarsPlots)
+ return process
+
+# muons
+muonVars = cms.PSet(
+ ipVars,
+ trackVars
+)
+for var in muonVars.parameters_():
+ setattr(getattr(muonVars, var), "src", cms.InputTag("muonTimeLifeInfos"))
+def addTimeLifeInfoToMuons(process):
+ process.muonTimeLifeInfos = patMuonTimeLifeInfoProducer.clone(
+ src = process.muonTable.src,
+ selection = 'pt > 15',
+ pvSource = prod_common.pvSource,
+ pvChoice = prod_common.pvChoice
+ )
+ process.muonTimeLifeInfoTable = simpleCandidate2TrackTimeLifeInfoFlatTableProducer.clone(
+ name = process.muonTable.name,
+ src = process.muonTable.src,
+ doc = cms.string("Additional time-life info for non-prompt muon"),
+ extension = True,
+ externalTypedVariables = muonVars
+ )
+ process.muonTimeLifeInfoTask = cms.Task(
+ process.muonTimeLifeInfos,
+ process.muonTimeLifeInfoTable
+ )
+ # refit PV with beam-spot constraint that is not present in Run-2 samples
+ if not hasattr(process,'refittedPV'):
+ setattr(process,'refittedPV',refittedPV)
+ _muonTimeLifeInfoTaskRun2 = process.muonTimeLifeInfoTask.copy()
+ _muonTimeLifeInfoTaskRun2.add(process.refittedPV)
+ run2_nanoAOD_ANY.toReplaceWith(process.muonTimeLifeInfoTask,
+ _muonTimeLifeInfoTaskRun2)
+ process.muonTablesTask.add(process.muonTimeLifeInfoTask)
+ # add DQM plots if needed
+ if hasattr(process,'nanoDQM'):
+ process.nanoDQM.vplots.Muon.plots.extend(ipVarsPlots)
+ process.nanoDQM.vplots.Muon.plots.extend(trackVarsPlots)
+ return process
+
+# taus
+tauVars = cms.PSet(
+ svVars,
+ ipVars,
+ trackVars
+)
+for var in tauVars.parameters_():
+ setattr(getattr(tauVars, var), "src", cms.InputTag("tauTimeLifeInfos"))
+def addTimeLifeInfoToTaus(process):
+ process.tauTimeLifeInfos = patTauTimeLifeInfoProducer.clone(
+ src = process.tauTable.src,
+ pvSource = prod_common.pvSource,
+ pvChoice = prod_common.pvChoice
+ )
+ process.tauTimeLifeInfoTable = simpleCandidate2TrackTimeLifeInfoFlatTableProducer.clone(
+ name = process.tauTable.name,
+ src = process.tauTable.src,
+ doc = cms.string("Additional tau time-life info"),
+ extension = True,
+ externalTypedVariables = tauVars
+ )
+ process.tauTimeLifeInfoTask = cms.Task(
+ process.tauTimeLifeInfos,
+ process.tauTimeLifeInfoTable
+ )
+ # refit PV with beam-spot constraint that is not present in Run-2 samples
+ if not hasattr(process,'refittedPV'):
+ setattr(process,'refittedPV',refittedPV)
+ _tauTimeLifeInfoTaskRun2 = process.tauTimeLifeInfoTask.copy()
+ _tauTimeLifeInfoTaskRun2.add(process.refittedPV)
+ run2_nanoAOD_ANY.toReplaceWith(process.tauTimeLifeInfoTask,
+ _tauTimeLifeInfoTaskRun2)
+ process.tauTablesTask.add(process.tauTimeLifeInfoTask)
+ # add DQM plots if needed
+ if hasattr(process,'nanoDQM'):
+ process.nanoDQM.vplots.Tau.plots.extend(ipVarsPlots)
+ process.nanoDQM.vplots.Tau.plots.extend(trackVarsPlots)
+ process.nanoDQM.vplots.Tau.plots.extend(svVarsPlots)
+ return process
+
+# Vertices
+def addExtendVertexInfo(process):
+ process.pvbsTable = simpleVertexFlatTableProducer.clone(
+ src = prod_common.pvSource,
+ name = "PVBS",
+ doc = "main primary vertex with beam-spot",
+ maxLen = 1,
+ variables = cms.PSet(
+ pvCovVars,
+ x = Var("position().x()", float, doc = "position x coordinate, in cm", precision = 10),
+ y = Var("position().y()", float, doc = "position y coordinate, in cm", precision = 10),
+ z = Var("position().z()", float, doc = "position z coordinate, in cm", precision = 16),
+ ndof = Var("ndof()", float, doc = "number of degrees of freedom", precision = 8),
+ chi2 = Var("normalizedChi2()", float, doc = "reduced chi2, i.e. chi2/ndof", precision = 8),
+ ),
+ )
+ process.pvbsTableTask = cms.Task(process.pvbsTable)
+ # refit PV with beam-spot constraint that is not present in Run-2 samples
+ if not hasattr(process,'refittedPV'):
+ setattr(process,'refittedPV',refittedPV)
+ _pvbsTableTaskRun2 = process.pvbsTableTask.copy()
+ _pvbsTableTaskRun2.add(process.refittedPV)
+ run2_nanoAOD_ANY.toReplaceWith(process.pvbsTableTask,
+ _pvbsTableTaskRun2)
+ process.vertexTablesTask.add(process.pvbsTableTask)
+ return process
+
+# Full
+def addTimeLifeInfo(process):
+ addTimeLifeInfoToElectrons(process)
+ addTimeLifeInfoToMuons(process)
+ addTimeLifeInfoToTaus(process)
+ addExtendVertexInfo(process)
+ return process
diff --git a/PhysicsTools/NanoAOD/python/taus_cff.py b/PhysicsTools/NanoAOD/python/taus_cff.py
index 71ef53ad63ebf..d9586ed72a404 100644
--- a/PhysicsTools/NanoAOD/python/taus_cff.py
+++ b/PhysicsTools/NanoAOD/python/taus_cff.py
@@ -6,6 +6,8 @@
from PhysicsTools.JetMCAlgos.TauGenJets_cfi import tauGenJets
from PhysicsTools.JetMCAlgos.TauGenJetsDecayModeSelectorAllHadrons_cfi import tauGenJetsSelectorAllHadrons
+from PhysicsTools.PatAlgos.patTauSignalCandidatesProducer_cfi import patTauSignalCandidatesProducer
+
##################### Updated tau collection with MVA-based tau-Ids rerun #######
# Used only in some eras
from PhysicsTools.NanoAOD.taus_updatedMVAIds_cff import *
@@ -152,9 +154,9 @@ def _tauIdWPMask(pattern, choices, doc="", from_raw=False, wp_thrs=None):
from_raw=True, wp_thrs=WORKING_POINTS_v2p5["jet"])
)
-tauSignalCands = cms.EDProducer("PATTauSignalCandidatesProducer",
+tauSignalCands = patTauSignalCandidatesProducer.clone(
src = tauTable.src,
- storeLostTracks = cms.bool(True)
+ storeLostTracks = True
)
tauSignalCandsTable = simpleCandidateFlatTableProducer.clone(
diff --git a/PhysicsTools/PatAlgos/plugins/PATLeptonTimeLifeInfoProducer.cc b/PhysicsTools/PatAlgos/plugins/PATLeptonTimeLifeInfoProducer.cc
new file mode 100644
index 0000000000000..2e41063e3f298
--- /dev/null
+++ b/PhysicsTools/PatAlgos/plugins/PATLeptonTimeLifeInfoProducer.cc
@@ -0,0 +1,270 @@
+/**
+ \class PATLeptonTimeLifeInfoProducer
+ \brief Produces lepton life-time information
+
+ \author Michal Bluj, NCBJ, Warsaw
+*/
+
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/EventSetup.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+
+#include "DataFormats/Common/interface/ValueMap.h"
+#include "DataFormats/PatCandidates/interface/Electron.h"
+#include "DataFormats/PatCandidates/interface/Muon.h"
+#include "DataFormats/PatCandidates/interface/Tau.h"
+#include "DataFormats/PatCandidates/interface/PackedCandidate.h"
+#include "DataFormats/TrackReco/interface/Track.h"
+#include "DataFormats/VertexReco/interface/Vertex.h"
+#include "DataFormats/VertexReco/interface/TrackTimeLifeInfo.h"
+
+#include "MagneticField/Engine/interface/MagneticField.h"
+#include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
+#include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
+#include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h"
+#include "RecoVertex/KalmanVertexFit/interface/KalmanVertexFitter.h"
+#include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
+#include "TrackingTools/Records/interface/TransientTrackRecord.h"
+#include "TrackingTools/GeomPropagators/interface/AnalyticalTrajectoryExtrapolatorToLine.h"
+#include "TrackingTools/GeomPropagators/interface/AnalyticalImpactPointExtrapolator.h"
+#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
+
+#include
+
+template
+class PATLeptonTimeLifeInfoProducer : public edm::stream::EDProducer<> {
+public:
+ explicit PATLeptonTimeLifeInfoProducer(const edm::ParameterSet&);
+ ~PATLeptonTimeLifeInfoProducer() override{};
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+ void produce(edm::Event&, const edm::EventSetup&) override;
+
+private:
+ //--- private utility methods
+ const reco::Track* getTrack(const T&);
+ void produceAndFillIPInfo(const T&, const TransientTrackBuilder&, const reco::Vertex&, TrackTimeLifeInfo&);
+ void produceAndFillSVInfo(const T&, const TransientTrackBuilder&, const reco::Vertex&, TrackTimeLifeInfo&);
+ static bool fitVertex(const std::vector& transTrk, TransientVertex& transVtx) {
+ if (transTrk.size() < 2)
+ return false;
+ KalmanVertexFitter kvf(true);
+ transVtx = kvf.vertex(transTrk);
+ return transVtx.hasRefittedTracks() && transVtx.refittedTracks().size() == transTrk.size();
+ }
+
+ //--- configuration parameters
+ edm::EDGetTokenT> leptonsToken_;
+ edm::EDGetTokenT pvToken_;
+ edm::ESGetToken transTrackBuilderToken_;
+ const StringCutObjectSelector selector_;
+ int pvChoice_;
+
+ enum PVChoice { useFront = 0, useClosestInDz };
+ //--- value map for TrackTimeLifeInfo (to be stored into the event)
+ using TrackTimeLifeInfoMap = edm::ValueMap;
+};
+
+template
+PATLeptonTimeLifeInfoProducer::PATLeptonTimeLifeInfoProducer(const edm::ParameterSet& cfg)
+ : leptonsToken_(consumes>(cfg.getParameter("src"))),
+ pvToken_(consumes(cfg.getParameter("pvSource"))),
+ transTrackBuilderToken_(esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))),
+ selector_(cfg.getParameter("selection")),
+ pvChoice_(cfg.getParameter("pvChoice")) {
+ produces();
+}
+
+template
+void PATLeptonTimeLifeInfoProducer::produce(edm::Event& evt, const edm::EventSetup& es) {
+ // Get leptons
+ edm::Handle> leptons;
+ evt.getByToken(leptonsToken_, leptons);
+
+ // Get the vertices
+ edm::Handle vertices;
+ evt.getByToken(pvToken_, vertices);
+
+ // Get transient track builder
+ const TransientTrackBuilder& transTrackBuilder = es.getData(transTrackBuilderToken_);
+
+ std::vector infos;
+ infos.reserve(leptons->size());
+
+ for (const auto& lepton : *leptons) {
+ TrackTimeLifeInfo info;
+
+ // Do nothing for lepton not passing selection
+ if (!selector_(lepton)) {
+ infos.push_back(info);
+ continue;
+ }
+ size_t pv_idx = 0;
+ if (pvChoice_ == useClosestInDz && getTrack(lepton) != nullptr) {
+ float dz_min = 999;
+ size_t vtx_idx = 0;
+ for (const auto& vtx : *vertices) {
+ float dz_tmp = std::abs(getTrack(lepton)->dz(vtx.position()));
+ if (dz_tmp < dz_min) {
+ dz_min = dz_tmp;
+ pv_idx = vtx_idx;
+ }
+ vtx_idx++;
+ }
+ }
+ const reco::Vertex& pv = !vertices->empty() ? (*vertices)[pv_idx] : reco::Vertex();
+
+ // Obtain IP vector and set related info into lepton
+ produceAndFillIPInfo(lepton, transTrackBuilder, pv, info);
+
+ // Fit SV and set related info for taus or do nothing for other lepton types
+ produceAndFillSVInfo(lepton, transTrackBuilder, pv, info);
+ infos.push_back(info);
+ } // end of lepton loop
+
+ // Build the valuemap
+ auto infoMap = std::make_unique();
+ TrackTimeLifeInfoMap::Filler filler(*infoMap);
+ filler.insert(leptons, infos.begin(), infos.end());
+ filler.fill();
+
+ // Store output into the event
+ evt.put(std::move(infoMap));
+}
+
+template <>
+const reco::Track* PATLeptonTimeLifeInfoProducer::getTrack(const pat::Electron& electron) {
+ return electron.gsfTrack().isNonnull() ? electron.gsfTrack().get() : nullptr;
+}
+
+template <>
+const reco::Track* PATLeptonTimeLifeInfoProducer::getTrack(const pat::Muon& muon) {
+ return muon.innerTrack().isNonnull() ? muon.innerTrack().get() : nullptr;
+}
+
+template <>
+const reco::Track* PATLeptonTimeLifeInfoProducer::getTrack(const pat::Tau& tau) {
+ const reco::Track* track = nullptr;
+ if (tau.leadChargedHadrCand().isNonnull())
+ track = tau.leadChargedHadrCand()->bestTrack();
+ return track;
+}
+
+template
+void PATLeptonTimeLifeInfoProducer::produceAndFillIPInfo(const T& lepton,
+ const TransientTrackBuilder& transTrackBuilder,
+ const reco::Vertex& pv,
+ TrackTimeLifeInfo& info) {
+ const reco::Track* track = getTrack(lepton);
+ if (track != nullptr) {
+ info.setTrack(track);
+ info.setBField_z(transTrackBuilder.field()->inInverseGeV(GlobalPoint(track->vx(), track->vy(), track->vz())).z());
+
+ // Extrapolate track to the point closest to PV
+ reco::TransientTrack transTrack = transTrackBuilder.build(track);
+ AnalyticalImpactPointExtrapolator extrapolator(transTrack.field());
+ TrajectoryStateOnSurface closestState =
+ extrapolator.extrapolate(transTrack.impactPointState(), RecoVertex::convertPos(pv.position()));
+ GlobalPoint pca = closestState.globalPosition();
+ GlobalError pca_cov = closestState.cartesianError().position();
+ GlobalVector ip_vec = GlobalVector(pca.x() - pv.x(), pca.y() - pv.y(), pca.z() - pv.z());
+ GlobalError ip_cov = pca_cov + GlobalError(pv.covariance());
+ VertexDistance3D pca_dist;
+ Measurement1D ip_mes = pca_dist.distance(pv, VertexState(pca, pca_cov));
+ if (ip_vec.dot(GlobalVector(lepton.px(), lepton.py(), lepton.pz())) < 0)
+ ip_mes = Measurement1D(-1. * ip_mes.value(), ip_mes.error());
+
+ // Store PCA info
+ info.setPCA(pca, pca_cov);
+ info.setIP(ip_vec, ip_cov);
+ info.setIPLength(ip_mes);
+ }
+}
+
+template
+void PATLeptonTimeLifeInfoProducer::produceAndFillSVInfo(const T& lepton,
+ const TransientTrackBuilder& transTrackBuilder,
+ const reco::Vertex& pv,
+ TrackTimeLifeInfo& info) {}
+
+template <>
+void PATLeptonTimeLifeInfoProducer::produceAndFillSVInfo(const pat::Tau& tau,
+ const TransientTrackBuilder& transTrackBuilder,
+ const reco::Vertex& pv,
+ TrackTimeLifeInfo& info) {
+ // Fit SV with tracks of charged tau decay products
+ int fitOK = 0;
+ if (tau.signalChargedHadrCands().size() + tau.signalLostTracks().size() > 1) {
+ // Get tracks from tau signal charged candidates
+ std::vector transTrks;
+ TransientVertex transVtx;
+ for (const auto& cand : tau.signalChargedHadrCands()) {
+ if (cand.isNull())
+ continue;
+ const reco::Track* track = cand->bestTrack();
+ if (track != nullptr)
+ transTrks.push_back(transTrackBuilder.build(track));
+ }
+ for (const auto& cand : tau.signalLostTracks()) {
+ if (cand.isNull())
+ continue;
+ const reco::Track* track = cand->bestTrack();
+ if (track != nullptr)
+ transTrks.push_back(transTrackBuilder.build(track));
+ }
+ // Fit SV with KalmanVertexFitter
+ fitOK = fitVertex(transTrks, transVtx) ? 1 : -1;
+ if (fitOK > 0) {
+ reco::Vertex sv = transVtx;
+ // Get flight-length
+ // Full PV->SV flight vector with its covariance
+ GlobalVector flight_vec = GlobalVector(sv.x() - pv.x(), sv.y() - pv.y(), sv.z() - pv.z());
+ GlobalError flight_cov = transVtx.positionError() + GlobalError(pv.covariance());
+ //MB: can be taken from tau itself (but with different fit of PV and SV) as follows:
+ //tau.flightLength().mag2());
+ //tau.flightLengthSig();
+ VertexDistance3D sv_dist;
+ Measurement1D flightLength_mes = sv_dist.signedDistance(pv, sv, GlobalVector(tau.px(), tau.py(), tau.pz()));
+
+ // Store SV info
+ info.setSV(sv);
+ info.setFlightVector(flight_vec, flight_cov);
+ info.setFlightLength(flightLength_mes);
+ }
+ }
+}
+
+template
+void PATLeptonTimeLifeInfoProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // pat{Electron,Muon,Tau}TimeLifeInfoProducer
+ edm::ParameterSetDescription desc;
+
+ std::string lepCollName;
+ if (typeid(T) == typeid(pat::Electron))
+ lepCollName = "slimmedElectrons";
+ else if (typeid(T) == typeid(pat::Muon))
+ lepCollName = "slimmedMuons";
+ else if (typeid(T) == typeid(pat::Tau))
+ lepCollName = "slimmedTaus";
+ desc.add("src", edm::InputTag(lepCollName));
+ desc.add("pvSource", edm::InputTag("offlineSlimmedPrimaryVertices"));
+ desc.add("selection", "")->setComment("Selection required to produce and store time-life information");
+ desc.add("pvChoice", useFront)
+ ->setComment(
+ "Define PV to compute IP: 0: first PV, 1: PV with the smallest dz of the tau leading track (default: " +
+ std::to_string(useFront) + ")");
+
+ descriptions.addWithDefaultLabel(desc);
+}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+typedef PATLeptonTimeLifeInfoProducer PATElectronTimeLifeInfoProducer;
+DEFINE_FWK_MODULE(PATElectronTimeLifeInfoProducer);
+typedef PATLeptonTimeLifeInfoProducer PATMuonTimeLifeInfoProducer;
+DEFINE_FWK_MODULE(PATMuonTimeLifeInfoProducer);
+typedef PATLeptonTimeLifeInfoProducer PATTauTimeLifeInfoProducer;
+DEFINE_FWK_MODULE(PATTauTimeLifeInfoProducer);
diff --git a/PhysicsTools/PatAlgos/plugins/PATRefitVertexProducer.cc b/PhysicsTools/PatAlgos/plugins/PATRefitVertexProducer.cc
new file mode 100644
index 0000000000000..a3ab1fa1120dd
--- /dev/null
+++ b/PhysicsTools/PatAlgos/plugins/PATRefitVertexProducer.cc
@@ -0,0 +1,193 @@
+/**
+ \class PATRefitVertexProducer
+
+ This producer is intended to take packedCandidates with tracks associated to
+ the PV and refit the PV (applying or not) BeamSpot constraint
+
+ \autor Michal Bluj, NCBJ Warsaw (and then others)
+
+ **/
+
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/EventSetup.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "DataFormats/PatCandidates/interface/PackedCandidate.h"
+#include "DataFormats/TrackReco/interface/Track.h"
+#include "DataFormats/VertexReco/interface/Vertex.h"
+#include "DataFormats/BeamSpot/interface/BeamSpot.h"
+#include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
+#include "TrackingTools/Records/interface/TransientTrackRecord.h"
+#include "RecoVertex/VertexPrimitives/interface/TransientVertex.h"
+#include "RecoVertex/AdaptiveVertexFit/interface/AdaptiveVertexFitter.h"
+
+#include
+
+class PATRefitVertexProducer : public edm::stream::EDProducer<> {
+public:
+ explicit PATRefitVertexProducer(const edm::ParameterSet&);
+ ~PATRefitVertexProducer() override{};
+
+ void produce(edm::Event&, const edm::EventSetup&) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions&);
+
+private:
+ //--- utility methods
+
+ //--- configuration parameters
+ edm::EDGetTokenT > srcCands_, srcLostTracks_, srcEleKfTracks_;
+ edm::EDGetTokenT srcVertices_;
+ edm::EDGetTokenT srcBeamSpot_;
+ edm::ESGetToken transTrackBuilderToken_;
+ bool useBeamSpot_;
+ bool useLostTracks_;
+ bool useEleKfTracks_;
+};
+
+PATRefitVertexProducer::PATRefitVertexProducer(const edm::ParameterSet& cfg)
+ : srcCands_(consumes >(cfg.getParameter("srcCands"))),
+ srcLostTracks_(consumes >(cfg.getParameter("srcLostTracks"))),
+ srcEleKfTracks_(consumes >(cfg.getParameter("srcEleKfTracks"))),
+ srcVertices_(consumes(cfg.getParameter("srcVertices"))),
+ srcBeamSpot_(consumes(cfg.getParameter("srcBeamSpot"))),
+ transTrackBuilderToken_(esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))),
+ useBeamSpot_(cfg.getParameter("useBeamSpot")),
+ useLostTracks_(cfg.getParameter("useLostTracks")),
+ useEleKfTracks_(cfg.getParameter("useEleKfTracks")) {
+ produces();
+}
+
+void PATRefitVertexProducer::produce(edm::Event& evt, const edm::EventSetup& es) {
+ // Obtain collections
+ edm::Handle > cands;
+ evt.getByToken(srcCands_, cands);
+
+ edm::Handle > lostTrackCands;
+ if (useLostTracks_)
+ evt.getByToken(srcLostTracks_, lostTrackCands);
+
+ edm::Handle > eleKfTrackCands;
+ if (useEleKfTracks_)
+ evt.getByToken(srcEleKfTracks_, eleKfTrackCands);
+
+ edm::Handle vertices;
+ evt.getByToken(srcVertices_, vertices);
+ const reco::Vertex& pv = vertices->front();
+ size_t vtxIdx = 0;
+
+ edm::Handle beamSpot;
+ if (useBeamSpot_)
+ evt.getByToken(srcBeamSpot_, beamSpot);
+
+ // Get transient track builder
+ const TransientTrackBuilder& transTrackBuilder = es.getData(transTrackBuilderToken_);
+
+ // Output collection
+ auto outputVertices = std::make_unique();
+ outputVertices->reserve(1);
+
+ // Create a new track collection for vertex refit
+ std::vector transTracks;
+
+ // loop over the PFCandidates
+ for (const auto& cand : (*cands)) {
+ if (cand.charge() == 0 || cand.vertexRef().isNull())
+ continue;
+ if (cand.bestTrack() == nullptr)
+ continue;
+ auto key = cand.vertexRef().key();
+ auto quality = cand.pvAssociationQuality();
+ if (key != vtxIdx ||
+ (quality != pat::PackedCandidate::UsedInFitTight && quality != pat::PackedCandidate::UsedInFitLoose))
+ continue;
+ if (useEleKfTracks_ && std::abs(cand.pdgId()) == 11)
+ continue;
+ transTracks.push_back(transTrackBuilder.build(cand.bestTrack()));
+ }
+
+ // loop over the lostTracks
+ if (useLostTracks_) {
+ for (const auto& cand : (*lostTrackCands)) {
+ if (cand.charge() == 0 || cand.vertexRef().isNull())
+ continue;
+ if (cand.bestTrack() == nullptr)
+ continue;
+ auto key = cand.vertexRef().key();
+ auto quality = cand.pvAssociationQuality();
+ if (key != vtxIdx ||
+ (quality != pat::PackedCandidate::UsedInFitTight && quality != pat::PackedCandidate::UsedInFitLoose))
+ continue;
+ transTracks.push_back(transTrackBuilder.build(cand.bestTrack()));
+ }
+ }
+
+ // loop over the electronKfTracks
+ if (useEleKfTracks_) {
+ for (const auto& cand : (*eleKfTrackCands)) {
+ if (cand.charge() == 0 || cand.vertexRef().isNull())
+ continue;
+ if (cand.bestTrack() == nullptr)
+ continue;
+ auto key = cand.vertexRef().key();
+ auto quality = cand.pvAssociationQuality();
+ if (key != vtxIdx ||
+ (quality != pat::PackedCandidate::UsedInFitTight && quality != pat::PackedCandidate::UsedInFitLoose))
+ continue;
+ transTracks.push_back(transTrackBuilder.build(cand.bestTrack()));
+ }
+ }
+
+ // Refit the vertex
+ TransientVertex transVtx;
+ reco::Vertex refitPV(pv); // initialized to the original PV
+
+ bool fitOK = true;
+ if (transTracks.size() >= 3) {
+ AdaptiveVertexFitter avf;
+ avf.setWeightThreshold(0.1); // weight per track, allow almost every fit, else --> exception
+ if (!useBeamSpot_) {
+ transVtx = avf.vertex(transTracks);
+ } else {
+ transVtx = avf.vertex(transTracks, *beamSpot);
+ }
+ if (!transVtx.isValid()) {
+ fitOK = false;
+ } else {
+ //MB: protect against rare cases when transVtx is valid but its postion is ill-defined
+ if (!std::isfinite(transVtx.position().z())) //MB: it is enough to check one coordinate (?)
+ fitOK = false;
+ }
+ } else
+ fitOK = false;
+ if (fitOK) {
+ refitPV = transVtx;
+ }
+
+ outputVertices->push_back(refitPV);
+
+ evt.put(std::move(outputVertices));
+}
+
+void PATRefitVertexProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // patRefitVertexProducer
+ edm::ParameterSetDescription desc;
+
+ desc.add("srcVertices", edm::InputTag("offlineSlimmedPrimaryVertices"));
+ desc.add("srcCands", edm::InputTag("packedPFCandidates"));
+ desc.add("srcLostTracks", edm::InputTag("lostTracks"));
+ desc.add("srcEleKfTracks", edm::InputTag("lostTracks:eleTracks"));
+ desc.add("srcBeamSpot", edm::InputTag("offlineBeamSpot"));
+ desc.add("useBeamSpot", true)->setComment("Refit PV with beam-spot constraint");
+ desc.add("useLostTracks", true)
+ ->setComment("Use collection of tracks not used by PF-candidates, aka lost-tracks");
+ desc.add("useEleKfTracks", true)
+ ->setComment("Use collection of electron KF-tracks instead of GSF-tracks of electron PF-candidates");
+
+ descriptions.addWithDefaultLabel(desc);
+}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(PATRefitVertexProducer);