File indexing completed on 2025-03-26 01:51:27
0001 #include "FWCore/Framework/interface/Frameworkfwd.h"
0002 #include "FWCore/Framework/interface/stream/EDProducer.h"
0003
0004 #include "FWCore/Framework/interface/Event.h"
0005 #include "FWCore/Framework/interface/MakerMacros.h"
0006
0007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0008 #include "FWCore/Utilities/interface/StreamID.h"
0009
0010 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0011 #include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
0012 #include "RecoVertex/VertexTools/interface/VertexDistanceXY.h"
0013 #include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h"
0014 #include "RecoVertex/VertexPrimitives/interface/VertexState.h"
0015
0016 #include "DataFormats/PatCandidates/interface/Jet.h"
0017 #include "DataFormats/PatCandidates/interface/PackedCandidate.h"
0018
0019 #include "DataFormats/Candidate/interface/CandidateFwd.h"
0020
0021 #include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h"
0022 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0023
0024 #include "DataFormats/BTauReco/interface/TrackIPTagInfo.h"
0025 #include "DataFormats/BTauReco/interface/SecondaryVertexTagInfo.h"
0026 #include "RecoBTag/FeatureTools/interface/deep_helpers.h"
0027 #include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h"
0028 using namespace btagbtvdeep;
0029
0030 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0031 #include "DataFormats/NanoAOD/interface/FlatTable.h"
0032
0033 namespace {
0034
0035 std::string toupper(std::string s) {
0036 std::transform(s.begin(), s.end(), s.begin(), ::toupper);
0037 return s;
0038 }
0039
0040 }
0041
0042 using std::toupper;
0043
0044 template <typename T>
0045 class JetConstituentTableProducer : public edm::stream::EDProducer<> {
0046 public:
0047 explicit JetConstituentTableProducer(const edm::ParameterSet &);
0048 ~JetConstituentTableProducer() override;
0049
0050 static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0051
0052 private:
0053 void produce(edm::Event &, const edm::EventSetup &) override;
0054
0055 typedef reco::VertexCollection VertexCollection;
0056
0057 typedef reco::VertexCompositePtrCandidateCollection SVCollection;
0058
0059 const std::string name_;
0060 const std::string nameSV_;
0061 const std::string idx_name_;
0062 const std::string idx_nameSV_;
0063 const bool readBtag_;
0064 const double jet_radius_;
0065
0066 edm::EDGetTokenT<edm::View<T>> jet_token_;
0067 edm::EDGetTokenT<VertexCollection> vtx_token_;
0068 edm::EDGetTokenT<reco::CandidateView> cand_token_;
0069 edm::EDGetTokenT<SVCollection> sv_token_;
0070
0071 edm::Handle<VertexCollection> vtxs_;
0072 edm::Handle<reco::CandidateView> cands_;
0073 edm::Handle<SVCollection> svs_;
0074 edm::ESHandle<TransientTrackBuilder> track_builder_;
0075 edm::ESGetToken<TransientTrackBuilder, TransientTrackRecord> track_builder_token_;
0076
0077 const std::string sv_sort_;
0078 const std::string pf_sort_;
0079
0080 const reco::Vertex *pv_ = nullptr;
0081 };
0082
0083
0084
0085
0086 template <typename T>
0087 JetConstituentTableProducer<T>::JetConstituentTableProducer(const edm::ParameterSet &iConfig)
0088 : name_(iConfig.getParameter<std::string>("name")),
0089 nameSV_(iConfig.getParameter<std::string>("nameSV")),
0090 idx_name_(iConfig.getParameter<std::string>("idx_name")),
0091 idx_nameSV_(iConfig.getParameter<std::string>("idx_nameSV")),
0092 readBtag_(iConfig.getParameter<bool>("readBtag")),
0093 jet_radius_(iConfig.getParameter<double>("jet_radius")),
0094 jet_token_(consumes<edm::View<T>>(iConfig.getParameter<edm::InputTag>("jets"))),
0095 vtx_token_(consumes<VertexCollection>(iConfig.getParameter<edm::InputTag>("vertices"))),
0096 cand_token_(consumes<reco::CandidateView>(iConfig.getParameter<edm::InputTag>("candidates"))),
0097 sv_token_(consumes<SVCollection>(iConfig.getParameter<edm::InputTag>("secondary_vertices"))),
0098 track_builder_token_(
0099 esConsumes<TransientTrackBuilder, TransientTrackRecord>(edm::ESInputTag("", "TransientTrackBuilder"))),
0100 sv_sort_(iConfig.getUntrackedParameter<std::string>("sv_sort")),
0101 pf_sort_(iConfig.getUntrackedParameter<std::string>("pf_sort")) {
0102 produces<nanoaod::FlatTable>(name_);
0103 produces<nanoaod::FlatTable>(nameSV_);
0104 produces<std::vector<reco::CandidatePtr>>();
0105 std::clog << "sv_sort: " << sv_sort_ << std::endl;
0106 std::clog << "pf_sort: " << pf_sort_ << std::endl;
0107 }
0108
0109 template <typename T>
0110 JetConstituentTableProducer<T>::~JetConstituentTableProducer() {}
0111
0112 template <typename T>
0113 void JetConstituentTableProducer<T>::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) {
0114
0115 auto outCands = std::make_unique<std::vector<reco::CandidatePtr>>();
0116 auto outSVs = std::make_unique<std::vector<const reco::VertexCompositePtrCandidate *>>();
0117 std::vector<int> jetIdx_pf, jetIdx_sv, pfcandIdx, svIdx;
0118
0119 std::vector<float> btagEtaRel, btagPtRatio, btagPParRatio, btagSip3dVal, btagSip3dSig, btagJetDistVal,
0120 btagDecayLenVal, cand_pt, cand_dzFromPV, cand_dxyFromPV, cand_dzErrFromPV, cand_dxyErrFromPV;
0121 std::vector<int> cand_jetSVIdx;
0122
0123 std::vector<float> sv_mass, sv_pt, sv_ntracks, sv_chi2, sv_normchi2, sv_dxy, sv_dxysig, sv_d3d, sv_d3dsig,
0124 sv_costhetasvpv;
0125 std::vector<float> sv_ptrel, sv_phirel, sv_deltaR, sv_enratio;
0126
0127 auto jets = iEvent.getHandle(jet_token_);
0128 iEvent.getByToken(vtx_token_, vtxs_);
0129 iEvent.getByToken(cand_token_, cands_);
0130 iEvent.getByToken(sv_token_, svs_);
0131
0132 if (readBtag_) {
0133 track_builder_ = iSetup.getHandle(track_builder_token_);
0134 }
0135
0136 for (unsigned i_jet = 0; i_jet < jets->size(); ++i_jet) {
0137 const auto &jet = jets->at(i_jet);
0138 math::XYZVector jet_dir = jet.momentum().Unit();
0139 GlobalVector jet_ref_track_dir(jet.px(), jet.py(), jet.pz());
0140 VertexDistance3D vdist;
0141
0142 pv_ = &vtxs_->at(0);
0143
0144
0145
0146 std::vector<const reco::VertexCompositePtrCandidate *> jetSVs;
0147 std::vector<const reco::VertexCompositePtrCandidate *> allSVs;
0148 for (const auto &sv : *svs_) {
0149
0150
0151 Measurement1D dl = vdist.distance(
0152 vtxs_->front(), VertexState(RecoVertex::convertPos(sv.position()), RecoVertex::convertError(sv.error())));
0153 if (dl.significance() > 3) {
0154 allSVs.push_back(&sv);
0155 }
0156 if (reco::deltaR2(sv, jet) < jet_radius_ * jet_radius_) {
0157 jetSVs.push_back(&sv);
0158 }
0159 }
0160 if (toupper(sv_sort_) == "IP") {
0161
0162 std::sort(jetSVs.begin(),
0163 jetSVs.end(),
0164 [this](const reco::VertexCompositePtrCandidate *sva, const reco::VertexCompositePtrCandidate *svb) {
0165 return sv_vertex_comparator(*sva, *svb, *pv_);
0166 });
0167 } else if (toupper(sv_sort_) == "PT") {
0168 std::sort(jetSVs.begin(),
0169 jetSVs.end(),
0170 [](const reco::VertexCompositePtrCandidate *sva, const reco::VertexCompositePtrCandidate *svb) {
0171 return sva->pt() > svb->pt();
0172 });
0173 } else if (!sv_sort_.empty()) {
0174 throw cms::Exception("Configuration")
0175 << "Unknown sorting option for secondary vertices: " << sv_sort_ << std::endl;
0176 }
0177
0178 for (const auto &sv : jetSVs) {
0179
0180 auto svInNewList = std::find(allSVs.begin(), allSVs.end(), sv);
0181 if (svInNewList == allSVs.end()) {
0182
0183 svIdx.push_back(-1);
0184 } else {
0185 svIdx.push_back(svInNewList - allSVs.begin());
0186 }
0187 outSVs->push_back(sv);
0188 jetIdx_sv.push_back(i_jet);
0189 if (readBtag_ && !vtxs_->empty()) {
0190
0191 sv_mass.push_back(sv->mass());
0192 sv_pt.push_back(sv->pt());
0193
0194 sv_ntracks.push_back(sv->numberOfDaughters());
0195 sv_chi2.push_back(sv->vertexChi2());
0196 sv_normchi2.push_back(catch_infs_and_bound(sv->vertexChi2() / sv->vertexNdof(), 1000, -1000, 1000));
0197 const auto &dxy_meas = vertexDxy(*sv, *pv_);
0198 sv_dxy.push_back(dxy_meas.value());
0199 sv_dxysig.push_back(catch_infs_and_bound(dxy_meas.value() / dxy_meas.error(), 0, -1, 800));
0200 const auto &d3d_meas = vertexD3d(*sv, *pv_);
0201 sv_d3d.push_back(d3d_meas.value());
0202 sv_d3dsig.push_back(catch_infs_and_bound(d3d_meas.value() / d3d_meas.error(), 0, -1, 800));
0203 sv_costhetasvpv.push_back(vertexDdotP(*sv, *pv_));
0204
0205 sv_ptrel.push_back(sv->pt() / jet.pt());
0206 sv_phirel.push_back(reco::deltaPhi(*sv, jet));
0207 sv_deltaR.push_back(catch_infs_and_bound(std::fabs(reco::deltaR(*sv, jet_dir)) - 0.5, 0, -2, 0));
0208 sv_enratio.push_back(sv->energy() / jet.energy());
0209 }
0210 }
0211
0212
0213 std::vector<reco::CandidatePtr> const &daughters = jet.daughterPtrVector();
0214 std::vector<size_t> dauidx;
0215 dauidx.reserve(daughters.size());
0216 for (size_t i = 0; i < daughters.size(); ++i)
0217 dauidx.push_back(i);
0218 if (toupper(pf_sort_) == "PT") {
0219 std::sort(dauidx.begin(), dauidx.end(), [&daughters](size_t i, size_t j) {
0220 return daughters[i]->pt() > daughters[j]->pt();
0221 });
0222 } else if (!pf_sort_.empty()) {
0223 throw cms::Exception("Configuration")
0224 << "Unknown sorting option for particle flow candidates: " << pf_sort_ << std::endl;
0225 }
0226
0227 for (size_t di : dauidx) {
0228 const auto &cand = daughters[di];
0229 auto candPtrs = cands_->ptrs();
0230 auto candInNewList = std::find(candPtrs.begin(), candPtrs.end(), cand);
0231 if (candInNewList == candPtrs.end()) {
0232
0233 continue;
0234 }
0235 outCands->push_back(cand);
0236 jetIdx_pf.push_back(i_jet);
0237 pfcandIdx.push_back(candInNewList - candPtrs.begin());
0238 cand_pt.push_back(cand->pt());
0239 auto const *packedCand = dynamic_cast<pat::PackedCandidate const *>(cand.get());
0240 if (packedCand && packedCand->hasTrackDetails()) {
0241 const reco::Track *track_ptr = &(packedCand->pseudoTrack());
0242 cand_dzFromPV.push_back(track_ptr->dz(pv_->position()));
0243 cand_dxyFromPV.push_back(track_ptr->dxy(pv_->position()));
0244 cand_dzErrFromPV.push_back(std::hypot(track_ptr->dzError(), pv_->zError()));
0245 cand_dxyErrFromPV.push_back(track_ptr->dxyError(pv_->position(), pv_->covariance()));
0246 } else {
0247 cand_dzFromPV.push_back(-1);
0248 cand_dxyFromPV.push_back(-1);
0249 cand_dzErrFromPV.push_back(-1);
0250 cand_dxyErrFromPV.push_back(-1);
0251 }
0252
0253 if (readBtag_ && !vtxs_->empty()) {
0254 if (cand.isNull())
0255 continue;
0256 auto const *packedCand = dynamic_cast<pat::PackedCandidate const *>(cand.get());
0257 if (packedCand == nullptr)
0258 continue;
0259 if (packedCand && packedCand->hasTrackDetails()) {
0260 btagbtvdeep::TrackInfoBuilder trkinfo(track_builder_);
0261 trkinfo.buildTrackInfo(&(*packedCand), jet_dir, jet_ref_track_dir, vtxs_->at(0));
0262 btagEtaRel.push_back(trkinfo.getTrackEtaRel());
0263 btagPtRatio.push_back(trkinfo.getTrackPtRatio());
0264 btagPParRatio.push_back(trkinfo.getTrackPParRatio());
0265 btagSip3dVal.push_back(trkinfo.getTrackSip3dVal());
0266 btagSip3dSig.push_back(trkinfo.getTrackSip3dSig());
0267 btagJetDistVal.push_back(trkinfo.getTrackJetDistVal());
0268
0269 const reco::Track *track_ptr = packedCand->bestTrack();
0270 reco::TransientTrack transient_track = track_builder_->build(track_ptr);
0271 double decayLength = -1;
0272 TrajectoryStateOnSurface closest = IPTools::closestApproachToJet(
0273 transient_track.impactPointState(), *pv_, jet_ref_track_dir, transient_track.field());
0274 if (closest.isValid())
0275 decayLength = (closest.globalPosition() - RecoVertex::convertPos(pv_->position())).mag();
0276 else
0277 decayLength = -1;
0278 btagDecayLenVal.push_back(decayLength);
0279
0280 int jsvMatchIndex = -1;
0281 int jsvIndex = 0;
0282 for (const auto &sv : *outSVs) {
0283 for (const auto &track : sv->daughterPtrVector()) {
0284 double eps = 1e-3;
0285 double dR = deltaR(track->eta(), track->phi(), cand->eta(), cand->phi());
0286 if (dR < eps && abs(track->pt() - cand->pt()) < eps) {
0287 jsvMatchIndex = jsvIndex;
0288 break;
0289 }
0290 }
0291 if (jsvMatchIndex >= 0)
0292 break;
0293 jsvIndex++;
0294 }
0295 cand_jetSVIdx.push_back(jsvMatchIndex);
0296 } else {
0297 btagEtaRel.push_back(0);
0298 btagPtRatio.push_back(0);
0299 btagPParRatio.push_back(0);
0300 btagSip3dVal.push_back(0);
0301 btagSip3dSig.push_back(0);
0302 btagJetDistVal.push_back(0);
0303 btagDecayLenVal.push_back(0);
0304 cand_jetSVIdx.push_back(-1);
0305 }
0306 }
0307 }
0308 }
0309
0310 auto candTable = std::make_unique<nanoaod::FlatTable>(outCands->size(), name_, false);
0311
0312 candTable->addColumn<int>(idx_name_, pfcandIdx, "Index in the candidate list");
0313 candTable->addColumn<int>("jetIdx", jetIdx_pf, "Index of the parent jet");
0314 candTable->addColumn<float>("pt", cand_pt, "pt", 10);
0315 if (readBtag_) {
0316 candTable->addColumn<float>("dzFromPV", cand_dzFromPV, "dzFromPV", 10);
0317 candTable->addColumn<float>("dxyFromPV", cand_dxyFromPV, "dxyFromPV", 10);
0318 candTable->addColumn<float>("dzErrFromPV", cand_dzErrFromPV, "dzErrFromPV", 10);
0319 candTable->addColumn<float>("dxyErrFromPV", cand_dxyErrFromPV, "dxyErrFromPV", 10);
0320 candTable->addColumn<float>("btagEtaRel", btagEtaRel, "btagEtaRel", 10);
0321 candTable->addColumn<float>("btagPtRatio", btagPtRatio, "btagPtRatio", 10);
0322 candTable->addColumn<float>("btagPParRatio", btagPParRatio, "btagPParRatio", 10);
0323 candTable->addColumn<float>("btagSip3dVal", btagSip3dVal, "btagSip3dVal", 10);
0324 candTable->addColumn<float>("btagSip3dSig", btagSip3dSig, "btagSip3dSig", 10);
0325 candTable->addColumn<float>("btagJetDistVal", btagJetDistVal, "btagJetDistVal", 10);
0326 candTable->addColumn<float>("btagDecayLenVal", btagDecayLenVal, "btagDecayLenVal", 10);
0327 candTable->addColumn<int>("jetSVIdx", cand_jetSVIdx, "Index of the parent in the " + nameSV_ + " list");
0328 }
0329 iEvent.put(std::move(candTable), name_);
0330
0331
0332 auto svTable = std::make_unique<nanoaod::FlatTable>(outSVs->size(), nameSV_, false);
0333
0334 svTable->addColumn<int>("jetIdx", jetIdx_sv, "Index of the parent jet");
0335 svTable->addColumn<int>(idx_nameSV_, svIdx, "Index in the SV list");
0336 if (readBtag_) {
0337 svTable->addColumn<float>("mass", sv_mass, "SV mass", 10);
0338 svTable->addColumn<float>("pt", sv_pt, "SV pt", 10);
0339 svTable->addColumn<float>("ntracks", sv_ntracks, "Number of tracks associated to SV", 10);
0340 svTable->addColumn<float>("chi2", sv_chi2, "chi2", 10);
0341 svTable->addColumn<float>("normchi2", sv_normchi2, "chi2/ndof", 10);
0342 svTable->addColumn<float>("dxy", sv_dxy, "", 10);
0343 svTable->addColumn<float>("dxysig", sv_dxysig, "", 10);
0344 svTable->addColumn<float>("d3d", sv_d3d, "", 10);
0345 svTable->addColumn<float>("d3dsig", sv_d3dsig, "", 10);
0346 svTable->addColumn<float>("costhetasvpv", sv_costhetasvpv, "", 10);
0347
0348 svTable->addColumn<float>("phirel", sv_phirel, "DeltaPhi(sv, jet)", 10);
0349 svTable->addColumn<float>("ptrel", sv_ptrel, "pT relative to parent jet", 10);
0350 svTable->addColumn<float>("deltaR", sv_deltaR, "dR from parent jet - 0.5", 10);
0351 svTable->addColumn<float>("enration", sv_enratio, "energy relative to parent jet", 10);
0352 }
0353 iEvent.put(std::move(svTable), nameSV_);
0354
0355 iEvent.put(std::move(outCands));
0356 }
0357
0358 template <typename T>
0359 void JetConstituentTableProducer<T>::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0360 edm::ParameterSetDescription desc;
0361 desc.add<std::string>("name", "JetPFCands");
0362 desc.add<std::string>("nameSV", "JetSV");
0363 desc.add<std::string>("idx_name", "candIdx");
0364 desc.add<std::string>("idx_nameSV", "svIdx");
0365 desc.add<double>("jet_radius", true);
0366 desc.add<bool>("readBtag", true);
0367 desc.add<edm::InputTag>("jets", edm::InputTag("slimmedJetsAK8"));
0368 desc.add<edm::InputTag>("vertices", edm::InputTag("offlineSlimmedPrimaryVertices"));
0369 desc.add<edm::InputTag>("candidates", edm::InputTag("packedPFCandidates"));
0370 desc.add<edm::InputTag>("secondary_vertices", edm::InputTag("slimmedSecondaryVertices"));
0371 desc.addUntracked<std::string>("sv_sort", "IP");
0372 desc.addUntracked<std::string>("pf_sort", "");
0373 descriptions.addWithDefaultLabel(desc);
0374 }
0375
0376 typedef JetConstituentTableProducer<pat::Jet> PatJetConstituentTableProducer;
0377 typedef JetConstituentTableProducer<reco::GenJet> GenJetConstituentTableProducer;
0378
0379 DEFINE_FWK_MODULE(PatJetConstituentTableProducer);
0380 DEFINE_FWK_MODULE(GenJetConstituentTableProducer);