diff --git a/Configuration/PyReleaseValidation/python/relval_nano.py b/Configuration/PyReleaseValidation/python/relval_nano.py
index 34ce92cf0e116..07dd2ca14eb39 100644
--- a/Configuration/PyReleaseValidation/python/relval_nano.py
+++ b/Configuration/PyReleaseValidation/python/relval_nano.py
@@ -176,6 +176,9 @@ def subnext(self):
steps['EGMNano_mc13.0'] = merge([{'-s':'NANO:@EGM,DQM:@nanoAODDQM', '-n' : '1000'},
steps['NANO_mc13.0']])
+steps['BTVNANO_data13.0']=merge([{'-s' : 'NANO:@BTV',
+ '-n' : '1000'},
+ steps['NANO_data13.0']])
steps['jmeNano_data13.0'] = merge([{'-s':'NANO:@JME', '-n' : '1000'},
steps['NANO_data13.0']])
@@ -198,6 +201,11 @@ def subnext(self):
steps['EGMNano_mc13.2'] = merge([{'-s':'NANO:@EGM,DQM:@nanoAODDQM', '-n' : '1000'},
steps['NANO_mc13.2']])
+
+steps['BTVNANO_mc13.2']=merge([{'-s' : 'NANO:@BTV',
+ '-n' : '1000'},
+ steps['NANO_mc13.2']])
+
steps['lepTimeLifeNANO_mc13.2']=merge([{'-s' : 'NANO:@LepTimeLife,DQM:@nanoAODDQM', '-n' : '1000'},
steps['NANO_mc13.2']])
@@ -258,6 +266,7 @@ def subnext(self):
workflows[_wfn()] = ['muDPGNANOBkg130Xrun3', ['ZeroBias2023DRAW13.0', 'muDPGNANOBkg_data13.0']]
workflows[_wfn()] = ['muPOGNANO130Xrun3', ['MuonEG2023MINIAOD13.0', 'muPOGNANO_data13.0']]
workflows[_wfn()] = ['EGMNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'EGMNano_data13.0']]
+workflows[_wfn()] = ['BTVNANO_data13.0', ['MuonEG2023MINIAOD13.0', 'BTVNANO_data13.0']]
workflows[_wfn()] = ['jmeNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'jmeNano_data13.0']]
workflows[_wfn()] = ['lepTimeLifeNANOdata130Xrun3', ['MuonEG2023MINIAOD13.0', 'lepTimeLifeNANO_data13.0']]
@@ -267,6 +276,7 @@ def subnext(self):
workflows[_wfn()] = ['NANOmc132X', ['TTBarMINIAOD13.2', 'NANO_mc13.2', 'HRV_NANO_mc']]
workflows[_wfn()] = ['muPOGNANOmc132X', ['TTBarMINIAOD13.2', 'muPOGNANO_mc13.2']]
workflows[_wfn()] = ['EGMNANOmc132X', ['TTBarMINIAOD13.2', 'EGMNano_mc13.2']]
+workflows[_wfn()] = ['BTVNANO_mc13.2', ['TTBarMINIAOD13.2', 'BTVNANO_mc13.2']]
workflows[_wfn()] = ['jmeNANOmc132X', ['TTBarMINIAOD13.2', 'jmeNANO_mc13.2']]
workflows[_wfn()] = ['lepTimeLifeNANOmc132X', ['TTBarMINIAOD13.2', 'lepTimeLifeNANO_mc13.2']]
diff --git a/PhysicsTools/NanoAOD/BuildFile.xml b/PhysicsTools/NanoAOD/BuildFile.xml
index 20ecb336c0866..e4cfb0e7e70a9 100644
--- a/PhysicsTools/NanoAOD/BuildFile.xml
+++ b/PhysicsTools/NanoAOD/BuildFile.xml
@@ -2,6 +2,14 @@
+
+
+
+
+
+
+
+
diff --git a/PhysicsTools/NanoAOD/plugins/BTVMCFlavourTableProducer.cc b/PhysicsTools/NanoAOD/plugins/BTVMCFlavourTableProducer.cc
new file mode 100644
index 0000000000000..01454c9a2c78d
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/BTVMCFlavourTableProducer.cc
@@ -0,0 +1,273 @@
+// system include files
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+
+#include "DataFormats/PatCandidates/interface/Jet.h"
+#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
+#include "DataFormats/Math/interface/deltaR.h"
+
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+
+#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
+#include "CommonTools/Utils/interface/StringObjectFunction.h"
+
+class BTVMCFlavourTableProducer : public edm::stream::EDProducer<> {
+public:
+ explicit BTVMCFlavourTableProducer(const edm::ParameterSet& iConfig)
+ : name_(iConfig.getParameter("name")),
+ src_(consumes >(iConfig.getParameter("src"))),
+ genParticlesToken_(consumes(iConfig.getParameter("genparticles"))) {
+ produces();
+ }
+
+ ~BTVMCFlavourTableProducer() override{};
+ int jet_flavour(const pat::Jet& jet,
+ const std::vector& gToBB,
+ const std::vector& gToCC,
+ const std::vector& neutrinosLepB,
+ const std::vector& neutrinosLepB_C,
+ const std::vector& alltaus,
+ bool usePhysForLightAndUndefined) {
+ int hflav = abs(jet.hadronFlavour());
+ int pflav = abs(jet.partonFlavour());
+ int physflav = 0;
+ if (!(jet.genJet())) {
+ if (pflav == 0)
+ return 999;
+ else
+ return 1000;
+ }
+ if (jet.genParton())
+ physflav = abs(jet.genParton()->pdgId());
+ std::size_t nbs = jet.jetFlavourInfo().getbHadrons().size();
+ std::size_t ncs = jet.jetFlavourInfo().getcHadrons().size();
+
+ unsigned int nbFromGSP(0);
+ for (const reco::GenParticle& p : gToBB) {
+ double dr2(reco::deltaR2(jet, p));
+ if (dr2 < jetR_ * jetR_)
+ ++nbFromGSP;
+ }
+
+ unsigned int ncFromGSP(0);
+ for (const reco::GenParticle& p : gToCC) {
+ double dr2(reco::deltaR2(jet, p));
+ if (dr2 < jetR_ * jetR_)
+ ++ncFromGSP;
+ }
+
+ //std::cout << " jet pt = " << jet.pt() << " hfl = " << hflav << " pfl = " << pflav << " genpart = " << physflav
+ // << " nbFromGSP = " << nbFromGSP << " ncFromGSP = " << ncFromGSP
+ // << " nBhadrons " << nbs << " nCHadrons " << ncs << std::endl;
+ if (hflav == 5) { //B jet
+ if (nbs > 1) {
+ if (nbFromGSP > 0)
+ return 511;
+ else
+ return 510;
+ } else if (nbs == 1) {
+ for (std::vector::const_iterator it = neutrinosLepB.begin(); it != neutrinosLepB.end();
+ ++it) {
+ if (reco::deltaR2(it->eta(), it->phi(), jet.eta(), jet.phi()) < 0.4 * 0.4) {
+ return 520;
+ }
+ }
+ for (std::vector::const_iterator it = neutrinosLepB_C.begin(); it != neutrinosLepB_C.end();
+ ++it) {
+ if (reco::deltaR2(it->eta(), it->phi(), jet.eta(), jet.phi()) < 0.4 * 0.4) {
+ return 521;
+ }
+ }
+ return 500;
+ } else {
+ if (usePhysForLightAndUndefined) {
+ if (physflav == 21)
+ return 0;
+ else if (physflav == 3)
+ return 2;
+ else if (physflav == 2 || physflav == 1)
+ return 1;
+ else
+ return 1000;
+ } else
+ return 1000;
+ }
+ } else if (hflav == 4) { //C jet
+ if (ncs > 1) {
+ if (ncFromGSP > 0)
+ return 411;
+ else
+ return 410;
+ } else
+ return 400;
+ } else { //not a heavy jet
+ if (!alltaus.empty()) { //check for tau in a simplistic way
+ bool ishadrtaucontained = true;
+ for (const auto& p : alltaus) {
+ size_t ndau = p.numberOfDaughters();
+ for (size_t i = 0; i < ndau; i++) {
+ const reco::Candidate* dau = p.daughter(i);
+ int daupid = std::abs(dau->pdgId());
+ if (daupid == 13 || daupid == 11) {
+ ishadrtaucontained = false;
+ break;
+ }
+ if (daupid != 12 && daupid != 14 && daupid != 16 && reco::deltaR2(*dau, jet) > jetR_ * jetR_) {
+ ishadrtaucontained = false;
+ break;
+ }
+ }
+ }
+ if (ishadrtaucontained)
+ return 600;
+ }
+ if (std::abs(pflav) == 4 || std::abs(pflav) == 5 || nbs || ncs) {
+ if (usePhysForLightAndUndefined) {
+ if (physflav == 21)
+ return 0;
+ else if (physflav == 3)
+ return 2;
+ else if (physflav == 2 || physflav == 1)
+ return 1;
+ else
+ return 1000;
+ } else
+ return 1000;
+ } else if (usePhysForLightAndUndefined) {
+ if (physflav == 21)
+ return 0;
+ else if (physflav == 3)
+ return 2;
+ else if (physflav == 2 || physflav == 1)
+ return 1;
+ else
+ return 1000;
+ } else {
+ if (pflav == 21)
+ return 0;
+ else if (pflav == 3)
+ return 2;
+ else if (pflav == 2 || pflav == 1)
+ return 1;
+ else
+ return 1000;
+ }
+ }
+ }
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("src")->setComment("input Jet collection");
+ desc.add("genparticles")->setComment("input genparticles info collection");
+ desc.add("name")->setComment("name of the genJet FlatTable we are extending with flavour information");
+ descriptions.add("btvMCTable", desc);
+ }
+
+private:
+ void produce(edm::Event&, edm::EventSetup const&) override;
+
+ std::string name_;
+
+ edm::EDGetTokenT > src_;
+ constexpr static double jetR_ = 0.4;
+
+ constexpr static bool usePhysForLightAndUndefined = false;
+ edm::EDGetTokenT genParticlesToken_;
+};
+
+// ------------ method called to produce the data ------------
+void BTVMCFlavourTableProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ auto jets = iEvent.getHandle(src_);
+ // const auto& jetFlavourInfosProd = iEvent.get(genParticlesToken_);
+ edm::Handle genParticlesHandle;
+ iEvent.getByToken(genParticlesToken_, genParticlesHandle);
+ std::vector neutrinosLepB;
+ std::vector neutrinosLepB_C;
+
+ std::vector gToBB;
+ std::vector gToCC;
+ std::vector alltaus;
+
+ unsigned int nJets = jets->size();
+
+ std::vector jet_FlavSplit(nJets);
+ for (const reco::Candidate& genC : *genParticlesHandle) {
+ const reco::GenParticle& gen = static_cast(genC);
+ if (abs(gen.pdgId()) == 12 || abs(gen.pdgId()) == 14 || abs(gen.pdgId()) == 16) {
+ const reco::GenParticle* mother = static_cast(gen.mother());
+ if (mother != nullptr) {
+ if ((abs(mother->pdgId()) > 500 && abs(mother->pdgId()) < 600) ||
+ (abs(mother->pdgId()) > 5000 && abs(mother->pdgId()) < 6000)) {
+ neutrinosLepB.emplace_back(gen);
+ }
+ if ((abs(mother->pdgId()) > 400 && abs(mother->pdgId()) < 500) ||
+ (abs(mother->pdgId()) > 4000 && abs(mother->pdgId()) < 5000)) {
+ neutrinosLepB_C.emplace_back(gen);
+ }
+ } else {
+ std::cout << "No mother" << std::endl;
+ }
+ }
+
+ int id(std::abs(gen.pdgId()));
+ int status(gen.status());
+
+ if (id == 21 && status >= 21 && status <= 59) { //// Pythia8 hard scatter, ISR, or FSR
+ if (gen.numberOfDaughters() == 2) {
+ const reco::Candidate* d0 = gen.daughter(0);
+ const reco::Candidate* d1 = gen.daughter(1);
+ if (std::abs(d0->pdgId()) == 5 && std::abs(d1->pdgId()) == 5 && d0->pdgId() * d1->pdgId() < 0 &&
+ reco::deltaR2(*d0, *d1) < jetR_ * jetR_)
+ gToBB.push_back(gen);
+ if (std::abs(d0->pdgId()) == 4 && std::abs(d1->pdgId()) == 4 && d0->pdgId() * d1->pdgId() < 0 &&
+ reco::deltaR2(*d0, *d1) < jetR_ * jetR_)
+ gToCC.push_back(gen);
+ }
+ }
+
+ if (id == 15 && false) {
+ alltaus.push_back(gen);
+ }
+ }
+ for (unsigned i_jet = 0; i_jet < nJets; ++i_jet) {
+ // from DeepNTuples
+ const auto& jet = jets->at(i_jet);
+
+ jet_FlavSplit[i_jet] =
+ jet_flavour(jet, gToBB, gToCC, neutrinosLepB, neutrinosLepB_C, alltaus, usePhysForLightAndUndefined);
+ }
+ auto newtab = std::make_unique(nJets, name_, false, true);
+ newtab->addColumn("FlavSplit",
+ jet_FlavSplit,
+ "Flavour of the jet, numerical codes: "
+ "isG: 0, "
+ "isUD: 1, "
+ "isS: 2, "
+ "isC: 400, "
+ "isCC: 410, "
+ "isGCC: 411, "
+ "isB: 500, "
+ "isBB: 510, "
+ "isGBB: 511, "
+ "isLeptonicB: 520, "
+ "isLeptonicB_C: 521, "
+ "isTAU: 600, "
+ "isPU: 999,"
+ "isUndefined: 1000. "
+ "May be combined to form coarse labels for tagger training and flavour dependent attacks "
+ "using the loss surface.");
+ iEvent.put(std::move(newtab));
+}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+//define this as a plug-in
+DEFINE_FWK_MODULE(BTVMCFlavourTableProducer);
diff --git a/PhysicsTools/NanoAOD/plugins/BuildFile.xml b/PhysicsTools/NanoAOD/plugins/BuildFile.xml
index e833cd0cd4c04..e08787f2c59c3 100644
--- a/PhysicsTools/NanoAOD/plugins/BuildFile.xml
+++ b/PhysicsTools/NanoAOD/plugins/BuildFile.xml
@@ -26,6 +26,14 @@
+
+
+
+
+
+
+
+
diff --git a/PhysicsTools/NanoAOD/plugins/DeepJetTableProducer.cc b/PhysicsTools/NanoAOD/plugins/DeepJetTableProducer.cc
new file mode 100644
index 0000000000000..1c4ac5df4bd76
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/DeepJetTableProducer.cc
@@ -0,0 +1,410 @@
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+
+#include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h"
+
+using namespace btagbtvdeep;
+
+#include "DataFormats/Math/interface/deltaR.h"
+
+#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+#include
+
+// add tag info and a way to go back to the jet reference
+#include "FWCore/Framework/interface/makeRefToBaseProdFrom.h"
+#include "DataFormats/BTauReco/interface/JetTag.h"
+#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h"
+
+// To store the gen info to get the truth flavour of the jet
+#include "DataFormats/PatCandidates/interface/Jet.h"
+
+template
+class DeepJetTableProducer : public edm::stream::EDProducer<> {
+public:
+ explicit DeepJetTableProducer(const edm::ParameterSet&);
+ ~DeepJetTableProducer() override;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void produce(edm::Event&, const edm::EventSetup&) override;
+
+ const std::string nameDeepJet_;
+ const std::string idx_nameDeepJet_;
+ const unsigned int n_cpf_ = 25;
+ const unsigned int n_npf_ = 25;
+ const unsigned int n_sv_ = 12;
+
+ edm::EDGetTokenT> jet_token_;
+
+ typedef std::vector TagInfoCollection;
+ const edm::EDGetTokenT tag_info_src_;
+
+ constexpr static bool usePhysForLightAndUndefined = false;
+};
+
+//
+// constructors and destructor
+//
+template
+DeepJetTableProducer::DeepJetTableProducer(const edm::ParameterSet& iConfig)
+ : nameDeepJet_(iConfig.getParameter("nameDeepJet")),
+ idx_nameDeepJet_(iConfig.getParameter("idx_nameDeepJet")),
+ n_cpf_(iConfig.getParameter("n_cpf")),
+ n_npf_(iConfig.getParameter("n_npf")),
+ n_sv_(iConfig.getParameter("n_sv")),
+ jet_token_(consumes>(iConfig.getParameter("jets"))),
+ tag_info_src_(consumes(iConfig.getParameter("tagInfo_src"))) {
+ produces(nameDeepJet_);
+}
+
+template
+DeepJetTableProducer::~DeepJetTableProducer() {}
+
+template
+void DeepJetTableProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ // elements in all these collections must have the same order!
+
+ // only necessary to explicitly check correct matching of jets
+ // std::vector jetIdx_dj;
+
+ auto jets = iEvent.getHandle(jet_token_);
+
+ edm::Handle tag_infos;
+ iEvent.getByToken(tag_info_src_, tag_infos);
+
+ unsigned nJets = jets->size();
+
+ std::vector jet_N_CPFCands(nJets);
+ std::vector jet_N_NPFCands(nJets);
+ std::vector jet_N_PVs(nJets);
+ std::vector jet_N_SVs(nJets);
+
+ // should default to 0 if less than nCpf cpf with information
+ std::vector> Cpfcan_BtagPf_trackEtaRel_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackPtRel_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackPPar_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackDeltaR_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackPParRatio_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackSip2dVal_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackSip2dSig_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackSip3dVal_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackSip3dSig_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_BtagPf_trackJetDistVal_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_ptrel_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_drminsv_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_VTX_ass_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_puppiw_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_chi2_nCpf(n_cpf_, std::vector(nJets));
+ std::vector> Cpfcan_quality_nCpf(n_cpf_, std::vector(nJets));
+
+ // should default to 0 if less than nNpf npf with information
+ std::vector> Npfcan_ptrel_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_deltaR_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_isGamma_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_HadFrac_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_drminsv_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_puppiw_nNpf(n_npf_, std::vector(nJets));
+ /*
+ // only after dataformat updated as well
+ std::vector> Npfcan_etarel_nNpf(n_npf_, std::vector(nJets));
+ std::vector> Npfcan_phirel_nNpf(n_npf_, std::vector(nJets));
+ */
+
+ // should default to 0 if less than nSv SVs with information
+ std::vector> sv_mass_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_pt_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_ntracks_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_chi2_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_normchi2_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_dxy_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_dxysig_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_d3d_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_d3dsig_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_costhetasvpv_nSV(n_sv_, std::vector(nJets));
+ /*
+ // only after dataformat updated as well
+ std::vector> sv_etarel_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_phirel_nSV(n_sv_, std::vector(nJets));
+ */
+ std::vector> sv_deltaR_nSV(n_sv_, std::vector(nJets));
+ std::vector> sv_enratio_nSV(n_sv_, std::vector(nJets));
+
+ if (!tag_infos->empty()) {
+ for (unsigned i_jet = 0; i_jet < nJets; ++i_jet) {
+ // jet loop reads tag info instead of constituent info
+
+ const auto& taginfo = (*tag_infos)[i_jet];
+ const auto& features = taginfo.features();
+
+ // jet.pt and jet.eta as well as other jet variables (ShallowTagInfo) already included (via DeepCSV)
+ // number of elements in different collections
+ jet_N_CPFCands[i_jet] = features.c_pf_features.size();
+ jet_N_NPFCands[i_jet] = features.n_pf_features.size();
+ jet_N_SVs[i_jet] = features.sv_features.size();
+ jet_N_PVs[i_jet] = features.npv;
+
+ // c_pf candidates
+ auto max_c_pf_n = std::min(features.c_pf_features.size(), (std::size_t)n_cpf_);
+ for (std::size_t c_pf_n = 0; c_pf_n < max_c_pf_n; c_pf_n++) {
+ const auto& c_pf_features = features.c_pf_features.at(c_pf_n);
+ Cpfcan_BtagPf_trackEtaRel_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackEtaRel;
+ Cpfcan_BtagPf_trackPtRel_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackPtRel;
+ Cpfcan_BtagPf_trackPPar_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackPPar;
+ Cpfcan_BtagPf_trackDeltaR_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackDeltaR;
+ Cpfcan_BtagPf_trackPParRatio_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackPParRatio;
+ Cpfcan_BtagPf_trackSip2dVal_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackSip2dVal;
+ Cpfcan_BtagPf_trackSip2dSig_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackSip2dSig;
+ Cpfcan_BtagPf_trackSip3dVal_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackSip3dVal;
+ Cpfcan_BtagPf_trackSip3dSig_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackSip3dSig;
+ Cpfcan_BtagPf_trackJetDistVal_nCpf[c_pf_n][i_jet] = c_pf_features.btagPf_trackJetDistVal;
+ Cpfcan_ptrel_nCpf[c_pf_n][i_jet] = c_pf_features.ptrel;
+ Cpfcan_drminsv_nCpf[c_pf_n][i_jet] = c_pf_features.drminsv;
+ Cpfcan_VTX_ass_nCpf[c_pf_n][i_jet] = c_pf_features.vtx_ass;
+ Cpfcan_puppiw_nCpf[c_pf_n][i_jet] = c_pf_features.puppiw;
+ Cpfcan_chi2_nCpf[c_pf_n][i_jet] = c_pf_features.chi2;
+ Cpfcan_quality_nCpf[c_pf_n][i_jet] = c_pf_features.quality;
+ }
+
+ // n_pf candidates
+ auto max_n_pf_n = std::min(features.n_pf_features.size(), (std::size_t)n_npf_);
+ for (std::size_t n_pf_n = 0; n_pf_n < max_n_pf_n; n_pf_n++) {
+ const auto& n_pf_features = features.n_pf_features.at(n_pf_n);
+ Npfcan_ptrel_nNpf[n_pf_n][i_jet] = n_pf_features.ptrel;
+ Npfcan_deltaR_nNpf[n_pf_n][i_jet] = n_pf_features.deltaR;
+ Npfcan_isGamma_nNpf[n_pf_n][i_jet] = n_pf_features.isGamma;
+ Npfcan_HadFrac_nNpf[n_pf_n][i_jet] = n_pf_features.hadFrac;
+ Npfcan_drminsv_nNpf[n_pf_n][i_jet] = n_pf_features.drminsv;
+ Npfcan_puppiw_nNpf[n_pf_n][i_jet] = n_pf_features.puppiw;
+ /*
+ // only after dataformat updated as well
+ Npfcan_etarel_nNpf[n_pf_n][i_jet] = n_pf_features.etarel;
+ Npfcan_phirel_nNpf[n_pf_n][i_jet] = n_pf_features.phirel;
+ */
+ }
+
+ // sv candidates
+ auto max_sv_n = std::min(features.sv_features.size(), (std::size_t)n_sv_);
+ for (std::size_t sv_n = 0; sv_n < max_sv_n; sv_n++) {
+ const auto& sv_features = features.sv_features.at(sv_n);
+ sv_pt_nSV[sv_n][i_jet] = sv_features.pt;
+ sv_deltaR_nSV[sv_n][i_jet] = sv_features.deltaR;
+ sv_mass_nSV[sv_n][i_jet] = sv_features.mass;
+ sv_ntracks_nSV[sv_n][i_jet] = sv_features.ntracks;
+ sv_chi2_nSV[sv_n][i_jet] = sv_features.chi2;
+ sv_normchi2_nSV[sv_n][i_jet] = sv_features.normchi2;
+ sv_dxy_nSV[sv_n][i_jet] = sv_features.dxy;
+ sv_dxysig_nSV[sv_n][i_jet] = sv_features.dxysig;
+ sv_d3d_nSV[sv_n][i_jet] = sv_features.d3d;
+ sv_d3dsig_nSV[sv_n][i_jet] = sv_features.d3dsig;
+ sv_costhetasvpv_nSV[sv_n][i_jet] = sv_features.costhetasvpv;
+ sv_enratio_nSV[sv_n][i_jet] = sv_features.enratio;
+ /*
+ // only after dataformat updated as well
+ sv_etarel_nSV[sv_n][i_jet] = sv_features.etarel;
+ sv_phirel_nSV[sv_n][i_jet] = sv_features.phirel;
+ */
+ }
+ }
+ }
+
+ // DeepJetInputs table
+ auto djTable = std::make_unique(jet_N_CPFCands.size(), nameDeepJet_, false, true);
+ //djTable->addColumn("DeepJet_jetIdx", jetIdx_dj, "Index of the parent jet", );
+
+ djTable->addColumn("DeepJet_nCpfcand", jet_N_CPFCands, "Number of charged PF candidates in the jet");
+ djTable->addColumn("DeepJet_nNpfcand", jet_N_NPFCands, "Number of neutral PF candidates in the jet");
+ djTable->addColumn("DeepJet_nsv", jet_N_SVs, "Number of secondary vertices in the jet");
+ djTable->addColumn("DeepJet_npv", jet_N_PVs, "Number of primary vertices");
+
+ // ============================================================== Cpfs ===================================================================
+ for (unsigned int p = 0; p < n_cpf_; p++) {
+ auto s = std::to_string(p);
+
+ djTable->addColumn("DeepJet_Cpfcan_puppiw_" + s,
+ Cpfcan_puppiw_nCpf[p],
+ "charged candidate PUPPI weight of the " + s + ". cpf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Cpfcan_VTX_ass_" + s,
+ Cpfcan_VTX_ass_nCpf[p],
+ "integer flag that indicates whether the track was used in the primary vertex fit for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_drminsv_" + s,
+ Cpfcan_drminsv_nCpf[p],
+ "track pseudoangular distance from the closest secondary vertex of the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_ptrel_" + s,
+ Cpfcan_ptrel_nCpf[p],
+ "fraction of the jet momentum carried by the track for the " + s + ". cpf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Cpfcan_quality_" + s,
+ Cpfcan_quality_nCpf[p],
+ "integer flag which indicates the quality of the fitted track, based on number of detector hits used for the "
+ "reconstruction as well as the overall chi2 of the charged track fit for the " +
+ s + ". cpf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Cpfcan_chi2_" + s, Cpfcan_chi2_nCpf[p], "chi2 of the charged track fit for the " + s + ". cpf", 10);
+
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackDeltaR_" + s,
+ Cpfcan_BtagPf_trackDeltaR_nCpf[p],
+ "track pseudoangular distance from the jet axis for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackEtaRel_" + s,
+ Cpfcan_BtagPf_trackEtaRel_nCpf[p],
+ "track pseudorapidity, relative to the jet axis for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackJetDistVal_" + s,
+ Cpfcan_BtagPf_trackJetDistVal_nCpf[p],
+ "minimum track approach distance to jet axis for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackPPar_" + s,
+ Cpfcan_BtagPf_trackPPar_nCpf[p],
+ "dot product of the jet and track momentum for the " + s + ". cpf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Cpfcan_BtagPf_trackPParRatio_" + s,
+ Cpfcan_BtagPf_trackPParRatio_nCpf[p],
+ "dot product of the jet and track momentum divided by the magnitude of the jet momentum for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackPtRel_" + s,
+ Cpfcan_BtagPf_trackPtRel_nCpf[p],
+ "track transverse momentum, relative to the jet axis for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackSip2dSig_" + s,
+ Cpfcan_BtagPf_trackSip2dSig_nCpf[p],
+ "track 2D signed impact parameter significance for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackSip3dSig_" + s,
+ Cpfcan_BtagPf_trackSip3dSig_nCpf[p],
+ "track 3D signed impact parameter significance for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackSip2dVal_" + s,
+ Cpfcan_BtagPf_trackSip2dVal_nCpf[p],
+ "track 2D signed impact parameter for the " + s + ". cpf",
+ 10);
+ djTable->addColumn("DeepJet_Cpfcan_BtagPf_trackSip3dVal_" + s,
+ Cpfcan_BtagPf_trackSip3dVal_nCpf[p],
+ "track 3D signed impact parameter for the " + s + ". cpf",
+ 10);
+ }
+
+ // ============================================================== Npfs ===================================================================
+ for (unsigned int p = 0; p < n_npf_; p++) {
+ auto s = std::to_string(p);
+
+ djTable->addColumn("DeepJet_Npfcan_puppiw_" + s,
+ Npfcan_puppiw_nNpf[p],
+ "neutral candidate PUPPI weight for the " + s + ". npf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Npfcan_deltaR_" + s,
+ Npfcan_deltaR_nNpf[p],
+ "pseudoangular distance between the neutral candidate and the jet axis for the " + s + ". npf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Npfcan_drminsv_" + s,
+ Npfcan_drminsv_nNpf[p],
+ "pseudoangular distance between the neutral candidate and the closest secondary vertex for the " + s + ". npf",
+ 10);
+ djTable->addColumn(
+ "DeepJet_Npfcan_HadFrac_" + s,
+ Npfcan_HadFrac_nNpf[p],
+ "fraction of the neutral candidate energy deposited in the hadronic calorimeter for the " + s + ". npf",
+ 10);
+ djTable->addColumn("DeepJet_Npfcan_ptrel_" + s,
+ Npfcan_ptrel_nNpf[p],
+ "fraction of the jet momentum carried by the neutral candidate for the " + s + ". npf",
+ 10);
+ djTable->addColumn("DeepJet_Npfcan_isGamma_" + s,
+ Npfcan_isGamma_nNpf[p],
+ "integer flag indicating whether the neutral candidate is a photon for the " + s + ". npf",
+ 10);
+ /*
+ // only after dataformat updated as well
+ djTable->addColumn("DeepJetExtra_Npfcan_etarel_" + s,
+ Npfcan_etarel_nNpf[p],
+ "pseudorapidity relative to parent jet for the " + s + ". npf",
+ 10);
+ djTable->addColumn("DeepJetExtra_Npfcan_phirel_" + s,
+ Npfcan_phirel_nNpf[p],
+ "DeltaPhi(npf, jet) for the " + s + ". npf",
+ 10);
+ */
+ }
+
+ // ============================================================== SVs ===================================================================
+ for (unsigned int p = 0; p < n_sv_; p++) {
+ auto s = std::to_string(p);
+
+ djTable->addColumn("DeepJet_sv_mass_" + s, sv_mass_nSV[p], "SV mass of the " + s + ". SV", 10);
+ djTable->addColumn("DeepJet_sv_pt_" + s, sv_pt_nSV[p], "SV pt of the " + s + ". SV", 10);
+ djTable->addColumn(
+ "DeepJet_sv_ntracks_" + s, sv_ntracks_nSV[p], "Number of tracks asociated to the " + s + ". SV", 10);
+ djTable->addColumn("DeepJet_sv_chi2_" + s, sv_chi2_nSV[p], "chi2 of the " + s + ". SV", 10);
+ djTable->addColumn("DeepJet_sv_normchi2_" + s, sv_normchi2_nSV[p], "chi2/dof of the " + s + ". SV", 10);
+ djTable->addColumn(
+ "DeepJet_sv_dxy_" + s, sv_dxy_nSV[p], "2D impact parameter (flight distance) value of the " + s + ". SV", 10);
+ djTable->addColumn("DeepJet_sv_dxysig_" + s,
+ sv_dxysig_nSV[p],
+ "2D impact parameter (flight distance) significance of the " + s + ". SV",
+ 10);
+ djTable->addColumn(
+ "DeepJet_sv_d3d_" + s, sv_d3d_nSV[p], "3D impact parameter (flight distance) value of the " + s + ". SV", 10);
+ djTable->addColumn("DeepJet_sv_d3dsig_" + s,
+ sv_d3dsig_nSV[p],
+ "3D impact parameter (flight distance) significance of the " + s + ". SV",
+ 10);
+ djTable->addColumn("DeepJet_sv_costhetasvpv_" + s,
+ sv_costhetasvpv_nSV[p],
+ "cosine of the angle between the " + s +
+ ". SV flight direction and the direction of the " + s + ". SV momentum",
+ 10);
+ /*
+ // only after dataformat updated as well
+ djTable->addColumn("DeepJetExtra_sv_etarel_" + s,
+ sv_etarel_nSV[p],
+ "pseudorapidity relative to parent jet for the " + s + ". SV",
+ 10);
+ djTable->addColumn("DeepJetExtra_sv_phirel_" + s,
+ sv_phirel_nSV[p],
+ "DeltaPhi(sv, jet) for the " + s + ". SV",
+ 10);
+ */
+ djTable->addColumn("DeepJet_sv_deltaR_" + s,
+ sv_deltaR_nSV[p],
+ "pseudoangular distance between jet axis and the " + s + ". SV direction",
+ 10);
+ djTable->addColumn(
+ "DeepJet_sv_enratio_" + s, sv_enratio_nSV[p], "ratio of the " + s + ". SV energy ratio to the jet energy", 10);
+ }
+
+ iEvent.put(std::move(djTable), nameDeepJet_);
+}
+
+template
+void DeepJetTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("nameDeepJet", "Jet");
+ desc.add("idx_nameDeepJet", "djIdx");
+
+ desc.add("n_cpf", 3);
+ desc.add("n_npf", 3);
+ desc.add("n_sv", 4);
+ desc.add("jets", edm::InputTag("slimmedJetsPuppi"));
+ desc.add("tagInfo_src", edm::InputTag("pfDeepFlavourTagInfosPuppiWithDeepInfo"));
+ descriptions.addWithDefaultLabel(desc);
+}
+
+typedef DeepJetTableProducer PatJetDeepJetTableProducer;
+
+DEFINE_FWK_MODULE(PatJetDeepJetTableProducer);
diff --git a/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc
new file mode 100644
index 0000000000000..4ec45ef3a21ed
--- /dev/null
+++ b/PhysicsTools/NanoAOD/plugins/JetConstituentTableProducer.cc
@@ -0,0 +1,316 @@
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+
+#include "DataFormats/VertexReco/interface/VertexFwd.h"
+#include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
+#include "RecoVertex/VertexTools/interface/VertexDistanceXY.h"
+#include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h"
+#include "RecoVertex/VertexPrimitives/interface/VertexState.h"
+
+#include "DataFormats/PatCandidates/interface/Jet.h"
+#include "DataFormats/PatCandidates/interface/PackedCandidate.h"
+
+#include "DataFormats/Candidate/interface/CandidateFwd.h"
+
+#include "RecoBTag/FeatureTools/interface/TrackInfoBuilder.h"
+#include "TrackingTools/Records/interface/TransientTrackRecord.h"
+
+#include "DataFormats/BTauReco/interface/TrackIPTagInfo.h"
+#include "DataFormats/BTauReco/interface/SecondaryVertexTagInfo.h"
+#include "RecoBTag/FeatureTools/interface/deep_helpers.h"
+#include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h"
+using namespace btagbtvdeep;
+
+#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
+#include "DataFormats/NanoAOD/interface/FlatTable.h"
+
+template
+class JetConstituentTableProducer : public edm::stream::EDProducer<> {
+public:
+ explicit JetConstituentTableProducer(const edm::ParameterSet &);
+ ~JetConstituentTableProducer() override;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
+
+private:
+ void produce(edm::Event &, const edm::EventSetup &) override;
+
+ typedef reco::VertexCollection VertexCollection;
+ //=====
+ typedef reco::VertexCompositePtrCandidateCollection SVCollection;
+
+ //const std::string name_;
+ const std::string name_;
+ const std::string nameSV_;
+ const std::string idx_name_;
+ const std::string idx_nameSV_;
+ const bool readBtag_;
+ const double jet_radius_;
+
+ edm::EDGetTokenT> jet_token_;
+ edm::EDGetTokenT vtx_token_;
+ edm::EDGetTokenT cand_token_;
+ edm::EDGetTokenT sv_token_;
+
+ edm::Handle vtxs_;
+ edm::Handle cands_;
+ edm::Handle svs_;
+ edm::ESHandle track_builder_;
+ edm::ESGetToken track_builder_token_;
+
+ const reco::Vertex *pv_ = nullptr;
+};
+
+//
+// constructors and destructor
+//
+template
+JetConstituentTableProducer::JetConstituentTableProducer(const edm::ParameterSet &iConfig)
+ : name_(iConfig.getParameter("name")),
+ nameSV_(iConfig.getParameter("nameSV")),
+ idx_name_(iConfig.getParameter("idx_name")),
+ idx_nameSV_(iConfig.getParameter("idx_nameSV")),
+ readBtag_(iConfig.getParameter("readBtag")),
+ jet_radius_(iConfig.getParameter("jet_radius")),
+ jet_token_(consumes>(iConfig.getParameter("jets"))),
+ vtx_token_(consumes(iConfig.getParameter("vertices"))),
+ cand_token_(consumes(iConfig.getParameter("candidates"))),
+ sv_token_(consumes(iConfig.getParameter("secondary_vertices"))),
+ track_builder_token_(
+ esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))) {
+ produces(name_);
+ produces(nameSV_);
+ produces>();
+}
+
+template
+JetConstituentTableProducer::~JetConstituentTableProducer() {}
+
+template
+void JetConstituentTableProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) {
+ // elements in all these collections must have the same order!
+ auto outCands = std::make_unique>();
+ auto outSVs = std::make_unique>();
+ std::vector jetIdx_pf, jetIdx_sv, pfcandIdx, svIdx;
+ // PF Cands
+ std::vector btagEtaRel, btagPtRatio, btagPParRatio, btagSip3dVal, btagSip3dSig, btagJetDistVal,
+ btagDecayLenVal, cand_pt, cand_dzFromPV, cand_dxyFromPV, cand_dzErrFromPV, cand_dxyErrFromPV;
+ // Secondary vertices
+ std::vector sv_mass, sv_pt, sv_ntracks, sv_chi2, sv_normchi2, sv_dxy, sv_dxysig, sv_d3d, sv_d3dsig,
+ sv_costhetasvpv;
+ std::vector sv_ptrel, sv_phirel, sv_deltaR, sv_enratio;
+
+ auto jets = iEvent.getHandle(jet_token_);
+ iEvent.getByToken(vtx_token_, vtxs_);
+ iEvent.getByToken(cand_token_, cands_);
+ iEvent.getByToken(sv_token_, svs_);
+
+ if (readBtag_) {
+ track_builder_ = iSetup.getHandle(track_builder_token_);
+ }
+
+ for (unsigned i_jet = 0; i_jet < jets->size(); ++i_jet) {
+ const auto &jet = jets->at(i_jet);
+ math::XYZVector jet_dir = jet.momentum().Unit();
+ GlobalVector jet_ref_track_dir(jet.px(), jet.py(), jet.pz());
+ VertexDistance3D vdist;
+
+ pv_ = &vtxs_->at(0);
+
+ //////////////////////
+ // Secondary Vertices
+ std::vector jetSVs;
+ std::vector allSVs;
+ for (const auto &sv : *svs_) {
+ // Factor in cuts in NanoAOD for indexing
+ Measurement1D dl = vdist.distance(
+ vtxs_->front(), VertexState(RecoVertex::convertPos(sv.position()), RecoVertex::convertError(sv.error())));
+ if (dl.significance() > 3) {
+ allSVs.push_back(&sv);
+ }
+ if (reco::deltaR2(sv, jet) < jet_radius_ * jet_radius_) {
+ jetSVs.push_back(&sv);
+ }
+ }
+ // sort by dxy significance
+ std::sort(jetSVs.begin(),
+ jetSVs.end(),
+ [&](const reco::VertexCompositePtrCandidate *sva, const reco::VertexCompositePtrCandidate *svb) {
+ return sv_vertex_comparator(*sva, *svb, *pv_);
+ });
+
+ for (const auto &sv : jetSVs) {
+ // auto svPtrs = svs_->ptrs();
+ auto svInNewList = std::find(allSVs.begin(), allSVs.end(), sv);
+ if (svInNewList == allSVs.end()) {
+ // continue;
+ svIdx.push_back(-1);
+ } else {
+ svIdx.push_back(svInNewList - allSVs.begin());
+ }
+ outSVs->push_back(sv);
+ jetIdx_sv.push_back(i_jet);
+ if (readBtag_ && !vtxs_->empty()) {
+ // Jet independent
+ sv_mass.push_back(sv->mass());
+ sv_pt.push_back(sv->pt());
+
+ sv_ntracks.push_back(sv->numberOfDaughters());
+ sv_chi2.push_back(sv->vertexChi2());
+ sv_normchi2.push_back(catch_infs_and_bound(sv->vertexChi2() / sv->vertexNdof(), 1000, -1000, 1000));
+ const auto &dxy_meas = vertexDxy(*sv, *pv_);
+ sv_dxy.push_back(dxy_meas.value());
+ sv_dxysig.push_back(catch_infs_and_bound(dxy_meas.value() / dxy_meas.error(), 0, -1, 800));
+ const auto &d3d_meas = vertexD3d(*sv, *pv_);
+ sv_d3d.push_back(d3d_meas.value());
+ sv_d3dsig.push_back(catch_infs_and_bound(d3d_meas.value() / d3d_meas.error(), 0, -1, 800));
+ sv_costhetasvpv.push_back(vertexDdotP(*sv, *pv_));
+ // Jet related
+ sv_ptrel.push_back(sv->pt() / jet.pt());
+ sv_phirel.push_back(reco::deltaPhi(*sv, jet));
+ sv_deltaR.push_back(catch_infs_and_bound(std::fabs(reco::deltaR(*sv, jet_dir)) - 0.5, 0, -2, 0));
+ sv_enratio.push_back(sv->energy() / jet.energy());
+ }
+ }
+
+ // PF Cands
+ std::vector const &daughters = jet.daughterPtrVector();
+
+ for (const auto &cand : daughters) {
+ auto candPtrs = cands_->ptrs();
+ auto candInNewList = std::find(candPtrs.begin(), candPtrs.end(), cand);
+ if (candInNewList == candPtrs.end()) {
+ //std::cout << "Cannot find candidate : " << cand.id() << ", " << cand.key() << ", pt = " << cand->pt() << std::endl;
+ continue;
+ }
+ outCands->push_back(cand);
+ jetIdx_pf.push_back(i_jet);
+ pfcandIdx.push_back(candInNewList - candPtrs.begin());
+ cand_pt.push_back(cand->pt());
+ auto const *packedCand = dynamic_cast(cand.get());
+ if (packedCand && packedCand->hasTrackDetails()) {
+ const reco::Track *track_ptr = &(packedCand->pseudoTrack());
+ cand_dzFromPV.push_back(track_ptr->dz(pv_->position()));
+ cand_dxyFromPV.push_back(track_ptr->dxy(pv_->position()));
+ cand_dzErrFromPV.push_back(std::hypot(track_ptr->dzError(), pv_->zError()));
+ cand_dxyErrFromPV.push_back(track_ptr->dxyError(pv_->position(), pv_->covariance()));
+ } else {
+ cand_dzFromPV.push_back(-1);
+ cand_dxyFromPV.push_back(-1);
+ cand_dzErrFromPV.push_back(-1);
+ cand_dxyErrFromPV.push_back(-1);
+ }
+
+ if (readBtag_ && !vtxs_->empty()) {
+ if (cand.isNull())
+ continue;
+ auto const *packedCand = dynamic_cast(cand.get());
+ if (packedCand == nullptr)
+ continue;
+ if (packedCand && packedCand->hasTrackDetails()) {
+ btagbtvdeep::TrackInfoBuilder trkinfo(track_builder_);
+ trkinfo.buildTrackInfo(&(*packedCand), jet_dir, jet_ref_track_dir, vtxs_->at(0));
+ btagEtaRel.push_back(trkinfo.getTrackEtaRel());
+ btagPtRatio.push_back(trkinfo.getTrackPtRatio());
+ btagPParRatio.push_back(trkinfo.getTrackPParRatio());
+ btagSip3dVal.push_back(trkinfo.getTrackSip3dVal());
+ btagSip3dSig.push_back(trkinfo.getTrackSip3dSig());
+ btagJetDistVal.push_back(trkinfo.getTrackJetDistVal());
+ // decay length
+ const reco::Track *track_ptr = packedCand->bestTrack();
+ reco::TransientTrack transient_track = track_builder_->build(track_ptr);
+ double decayLength = -1;
+ TrajectoryStateOnSurface closest = IPTools::closestApproachToJet(
+ transient_track.impactPointState(), *pv_, jet_ref_track_dir, transient_track.field());
+ if (closest.isValid())
+ decayLength = (closest.globalPosition() - RecoVertex::convertPos(pv_->position())).mag();
+ else
+ decayLength = -1;
+ btagDecayLenVal.push_back(decayLength);
+ } else {
+ btagEtaRel.push_back(0);
+ btagPtRatio.push_back(0);
+ btagPParRatio.push_back(0);
+ btagSip3dVal.push_back(0);
+ btagSip3dSig.push_back(0);
+ btagJetDistVal.push_back(0);
+ btagDecayLenVal.push_back(0);
+ }
+ }
+ } // end jet loop
+ }
+
+ auto candTable = std::make_unique(outCands->size(), name_, false);
+ // We fill from here only stuff that cannot be created with the SimpleFlatTableProducer
+ candTable->addColumn(idx_name_, pfcandIdx, "Index in the candidate list");
+ candTable->addColumn("jetIdx", jetIdx_pf, "Index of the parent jet");
+ if (readBtag_) {
+ candTable->addColumn("pt", cand_pt, "pt", 10); // to check matchind down the line
+ candTable->addColumn("dzFromPV", cand_dzFromPV, "dzFromPV", 10);
+ candTable->addColumn("dxyFromPV", cand_dxyFromPV, "dxyFromPV", 10);
+ candTable->addColumn("dzErrFromPV", cand_dzErrFromPV, "dzErrFromPV", 10);
+ candTable->addColumn("dxyErrFromPV", cand_dxyErrFromPV, "dxyErrFromPV", 10);
+ candTable->addColumn("btagEtaRel", btagEtaRel, "btagEtaRel", 10);
+ candTable->addColumn("btagPtRatio", btagPtRatio, "btagPtRatio", 10);
+ candTable->addColumn("btagPParRatio", btagPParRatio, "btagPParRatio", 10);
+ candTable->addColumn("btagSip3dVal", btagSip3dVal, "btagSip3dVal", 10);
+ candTable->addColumn("btagSip3dSig", btagSip3dSig, "btagSip3dSig", 10);
+ candTable->addColumn("btagJetDistVal", btagJetDistVal, "btagJetDistVal", 10);
+ candTable->addColumn("btagDecayLenVal", btagDecayLenVal, "btagDecayLenVal", 10);
+ }
+ iEvent.put(std::move(candTable), name_);
+
+ // SV table
+ auto svTable = std::make_unique(outSVs->size(), nameSV_, false);
+ // We fill from here only stuff that cannot be created with the SimpleFlatTnameableProducer
+ svTable->addColumn("jetIdx", jetIdx_sv, "Index of the parent jet");
+ svTable->addColumn(idx_nameSV_, svIdx, "Index in the SV list");
+ if (readBtag_) {
+ svTable->addColumn("mass", sv_mass, "SV mass", 10);
+ svTable->addColumn("pt", sv_pt, "SV pt", 10);
+ svTable->addColumn("ntracks", sv_ntracks, "Number of tracks associated to SV", 10);
+ svTable->addColumn