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("chi2", sv_chi2, "chi2", 10); + svTable->addColumn("normchi2", sv_normchi2, "chi2/ndof", 10); + svTable->addColumn("dxy", sv_dxy, "", 10); + svTable->addColumn("dxysig", sv_dxysig, "", 10); + svTable->addColumn("d3d", sv_d3d, "", 10); + svTable->addColumn("d3dsig", sv_d3dsig, "", 10); + svTable->addColumn("costhetasvpv", sv_costhetasvpv, "", 10); + // Jet related + svTable->addColumn("phirel", sv_phirel, "DeltaPhi(sv, jet)", 10); + svTable->addColumn("ptrel", sv_ptrel, "pT relative to parent jet", 10); + svTable->addColumn("deltaR", sv_deltaR, "dR from parent jet", 10); + svTable->addColumn("enration", sv_enratio, "energy relative to parent jet", 10); + } + iEvent.put(std::move(svTable), nameSV_); + + iEvent.put(std::move(outCands)); +} + +template +void JetConstituentTableProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.add("name", "JetPFCands"); + desc.add("nameSV", "JetSV"); + desc.add("idx_name", "candIdx"); + desc.add("idx_nameSV", "svIdx"); + desc.add("jet_radius", true); + desc.add("readBtag", true); + desc.add("jets", edm::InputTag("slimmedJetsAK8")); + desc.add("vertices", edm::InputTag("offlineSlimmedPrimaryVertices")); + desc.add("candidates", edm::InputTag("packedPFCandidates")); + desc.add("secondary_vertices", edm::InputTag("slimmedSecondaryVertices")); + descriptions.addWithDefaultLabel(desc); +} + +typedef JetConstituentTableProducer PatJetConstituentTableProducer; +typedef JetConstituentTableProducer GenJetConstituentTableProducer; + +DEFINE_FWK_MODULE(PatJetConstituentTableProducer); +DEFINE_FWK_MODULE(GenJetConstituentTableProducer); diff --git a/PhysicsTools/NanoAOD/python/autoNANO.py b/PhysicsTools/NanoAOD/python/autoNANO.py index 1ab29fb60fa9c..f90a4768a8f67 100644 --- a/PhysicsTools/NanoAOD/python/autoNANO.py +++ b/PhysicsTools/NanoAOD/python/autoNANO.py @@ -49,4 +49,7 @@ def expandNanoMapping(seqList, mapping, key): # Add lepton time-life info tables through customize combined with PHYS 'LepTimeLife' : {'sequence': '@PHYS', 'customize': '@PHYS+PhysicsTools/NanoAOD/leptonTimeLifeInfo_common_cff.addTimeLifeInfo'}, + # Custom BTV Nano for SF measurements or tagger training + 'BTV' : {'sequence': '@PHYS', + 'customize':'@PHYS+PhysicsTools/NanoAOD/custom_btv_cff.BTVCustomNanoAOD'} } diff --git a/PhysicsTools/NanoAOD/python/btvMC_cff.py b/PhysicsTools/NanoAOD/python/btvMC_cff.py new file mode 100644 index 0000000000000..0a72694f96112 --- /dev/null +++ b/PhysicsTools/NanoAOD/python/btvMC_cff.py @@ -0,0 +1,170 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.common_cff import * +from PhysicsTools.NanoAOD.simpleCandidateFlatTableProducer_cfi import simpleCandidateFlatTableProducer +from PhysicsTools.NanoAOD.jetsAK8_cff import fatJetTable, subJetTable +from PhysicsTools.NanoAOD.jetsAK4_Puppi_cff import jetPuppiTable +from PhysicsTools.NanoAOD.genparticles_cff import * +# when storing the flat table, always do "T"able in the naming convention + + +finalGenParticles.select +=[ + "keep (4 <= abs(pdgId) <= 5) && statusFlags().isLastCopy()", # BTV: keep b/c quarks in their last copy + "keep (abs(pdgId) == 310 || abs(pdgId) == 3122) && statusFlags().isLastCopy()", # BTV: keep K0s and Lambdas in their last copy + ] + +btvGenTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=finalGenParticles.src, + name= cms.string("GenPart"), + doc = cms.string("interesting gen particles "), + singleton=cms.bool(False), + variables= + cms.PSet( + genParticleTable.variables, + vx = Var("vx", "float", doc="x coordinate of vertex position"), + vy = Var("vy", "float", doc="y coordinate of vertex position"), + vz = Var("vz", "float", doc="z coordinate of vertex position"), + genPartIdxMother2 = Var("?numberOfMothers>1?motherRef(1).key():-1", "int", doc="index of the second mother particle, if valid") + )) +genParticleTablesTask.replace(genParticleTable,btvGenTable) +btvMCTable = cms.EDProducer("BTVMCFlavourTableProducer",name=jetPuppiTable.name,src=cms.InputTag("linkedObjects","jets"),genparticles=cms.InputTag("prunedGenParticles")) + +btvAK4JetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=jetPuppiTable.src, + cut=jetPuppiTable.cut, + name=jetPuppiTable.name, + doc=jetPuppiTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for Jets + variables=cms.PSet( + nBHadrons=Var("jetFlavourInfo().getbHadrons().size()", + int, + doc="number of b-hadrons"), + nCHadrons=Var("jetFlavourInfo().getcHadrons().size()", + int, + doc="number of c-hadrons"), + )) + +btvSubJetMCExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src = subJetTable.src, + cut = subJetTable.cut, + name = subJetTable.name, + doc=subJetTable.doc, + singleton = cms.bool(False), + extension = cms.bool(True), + variables = cms.PSet( + subGenJetAK8Idx = Var("?genJetFwdRef().backRef().isNonnull()?genJetFwdRef().backRef().key():-1", + int, + doc="index of matched gen Sub jet"), + ) + ) +genJetsAK8Constituents = cms.EDProducer("GenJetPackedConstituentPtrSelector", + src = cms.InputTag("slimmedGenJetsAK8"), + cut = cms.string("pt > 100.") + ) + + +genJetsAK4Constituents = cms.EDProducer("GenJetPackedConstituentPtrSelector", + src = cms.InputTag("slimmedGenJets"), + cut = cms.string("pt > 20") + ) + + + + + +ak4onlygenJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = cms.VInputTag(cms.InputTag("genJetsAK4Constituents", "constituents")), skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + +ak8onlygenJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = cms.VInputTag(cms.InputTag("genJetsAK8Constituents", "constituents")), skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) +ak4ak8genJetsConstituents = cms.EDProducer("PackedGenParticlePtrMerger", src = cms.VInputTag(cms.InputTag("genJetsAK4Constituents", "constituents"), cms.InputTag("genJetsAK8Constituents", "constituents")), skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + +allPFParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("packedGenParticles"), + cut = cms.string(""), #we should not filter after pruning + name= cms.string("GenCands"), + doc = cms.string("interesting gen particles from PF candidates"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the AK8 constituents + variables = cms.PSet(CandVars + ) + ) +ak4onlygenJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("ak4onlygenJetsConstituents"), + cut = cms.string(""), #we should not filter after pruning + name= cms.string("GenCands"), + doc = cms.string("interesting gen particles from AK4 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the AK8 constituents + variables = cms.PSet(CandVars + ) + ) +ak8onlygenJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("ak8onlygenJetsConstituents"), + cut = cms.string(""), #we should not filter after pruning + name= cms.string("GenCands"), + doc = cms.string("interesting gen particles from AK8 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the AK8 constituents + variables = cms.PSet(CandVars + ) + ) +ak4ak8genJetsParticleTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("ak4ak8genJetsConstituents"), + cut = cms.string(""), #we should not filter after pruning + name= cms.string("GenCands"), + doc = cms.string("interesting gen particles from AK4, AK8 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the AK8 constituents + variables = cms.PSet(CandVars + ) + ) +ak8onlygenAK8ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = cms.InputTag("ak8onlygenJetsConstituents"), + jets = cms.InputTag("genJetsAK8Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenFatJetCands"), + nameSV = cms.string("GenFatJetSVs"), + idx_name = cms.string("pFCandsIdx"), + idx_nameSV = cms.string("sVIdx"), + readBtag = cms.bool(False)) +ak4onlygenAK4ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = cms.InputTag("ak4onlygenJetsConstituents"), + jets = cms.InputTag("genJetsAK4Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenJetCands"), + nameSV = cms.string("GenJetSVs"), + idx_name = cms.string("pFCandsIdx"), + idx_nameSV = cms.string("sVIdx"), + readBtag = cms.bool(False)) +ak4ak8genAK4ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = cms.InputTag("ak4ak8genJetsConstituents"), + jets = cms.InputTag("genJetsAK4Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenJetCands"), + nameSV = cms.string("GenJetSVs"), + idx_name = cms.string("pFCandsIdx"), + idx_nameSV = cms.string("sVIdx"), + readBtag = cms.bool(False)) + +ak4ak8genAK8ConstituentsTable = cms.EDProducer("GenJetConstituentTableProducer", + candidates = cms.InputTag("ak4ak8genJetsConstituents"), + jets = cms.InputTag("genJetsAK8Constituents"), # Note: The name has "Constituents" in it, but these are the jets + name = cms.string("GenFatJetCands"), + nameSV = cms.string("GenFatJetSVs"), + idx_name = cms.string("pFCandsIdx"), + idx_nameSV = cms.string("sVIdx"), + readBtag = cms.bool(False)) +btvAK4MCSequence = cms.Sequence(btvGenTable+btvAK4JetExtTable+btvMCTable) +btvAK8MCSequence = cms.Sequence(btvGenTable+btvSubJetMCExtTable) +#PF Cands of AK4 only , with cross linking to AK4 jets +ak4onlyPFCandsMCSequence=cms.Sequence(genJetsAK4Constituents+ak4onlygenJetsConstituents+ak4onlygenJetsParticleTable+ak4onlygenAK4ConstituentsTable)+btvAK4MCSequence +#PF Cands of AK8 only , with cross linking to AK8 jets +ak8onlyPFCandsMCSequence=cms.Sequence(genJetsAK8Constituents+ak8onlygenJetsConstituents+ak8onlygenJetsParticleTable+ak8onlygenAK8ConstituentsTable)+btvAK8MCSequence +#PF Cands of AK4+AK8, with cross linking to AK4,AK8 jets +ak4ak8PFCandsMCSequence=cms.Sequence(genJetsAK4Constituents+genJetsAK8Constituents+ak4ak8genJetsConstituents+ak4ak8genJetsParticleTable+ak4ak8genAK4ConstituentsTable+ak4ak8genAK8ConstituentsTable)+btvAK4MCSequence+btvAK8MCSequence +#All PFCands, with cross linking to AK4,AK8 jets +allPFPFCandsMCSequence=cms.Sequence(genJetsAK4Constituents+genJetsAK8Constituents+ak4ak8genJetsConstituents+allPFParticleTable+ak4ak8genAK4ConstituentsTable+ak4ak8genAK8ConstituentsTable)+btvAK4MCSequence+btvAK8MCSequence + + + + diff --git a/PhysicsTools/NanoAOD/python/custom_btv_cff.py b/PhysicsTools/NanoAOD/python/custom_btv_cff.py new file mode 100644 index 0000000000000..323e3e458d20a --- /dev/null +++ b/PhysicsTools/NanoAOD/python/custom_btv_cff.py @@ -0,0 +1,678 @@ +import FWCore.ParameterSet.Config as cms +from PhysicsTools.NanoAOD.common_cff import Var +from PhysicsTools.NanoAOD.jetsAK4_Puppi_cff import jetPuppiTable, jetPuppiCorrFactorsNano, updatedJetsPuppi, updatedJetsPuppiWithUserData +from PhysicsTools.NanoAOD.jetsAK8_cff import fatJetTable, subJetTable +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection +from PhysicsTools.PatAlgos.tools.helpers import addToProcessAndTask, getPatAlgosToolsTask +from PhysicsTools.NanoAOD.common_cff import Var, CandVars +from PhysicsTools.NanoAOD.simpleCandidateFlatTableProducer_cfi import simpleCandidateFlatTableProducer +from PhysicsTools.NanoAOD.btvMC_cff import allPFPFCandsMCSequence,ak4ak8PFCandsMCSequence,ak8onlyPFCandsMCSequence,ak4onlyPFCandsMCSequence +## Move PFNano (https://github.com/cms-jet/PFNano/) to NanoAOD + +## From: https://github.com/cms-jet/PFNano/blob/13_0_7_from124MiniAOD/python/addBTV.py +def update_jets_AK4(process): + # Based on ``nanoAOD_addDeepInfo`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + # DeepJet flav_names as found in + # https://github.com/cms-sw/cmssw/blob/master/RecoBTag/ONNXRuntime/plugins/DeepFlavourONNXJetTagsProducer.cc#L86 + # and https://twiki.cern.ch/twiki/bin/view/CMS/DeepJet + from RecoBTag.ONNXRuntime.pfParticleTransformerAK4_cff import _pfParticleTransformerAK4JetTagsAll as pfParticleTransformerAK4JetTagsAll + from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsAll as pfParticleNetFromMiniAODAK4PuppiCentralJetTagsAll + from RecoBTag.ONNXRuntime.pfParticleTransformerAK4_cff import _pfNegativeParticleTransformerAK4JetTagsProbs as pfNegativeParticleTransformerAK4JetTagsProbs + from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import _pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs as pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs + + _btagDiscriminators = [ + 'pfJetProbabilityBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfNegativeOnlyJetProbabilityBJetTags', + 'pfNegativeOnlyJetBProbabilityBJetTags', + 'pfDeepFlavourJetTags:probb', + 'pfDeepFlavourJetTags:probbb', + 'pfDeepFlavourJetTags:problepb', + 'pfDeepFlavourJetTags:probc', + 'pfDeepFlavourJetTags:probuds', + 'pfDeepFlavourJetTags:probg', + 'pfNegativeDeepFlavourJetTags:probb', + 'pfNegativeDeepFlavourJetTags:probbb', + 'pfNegativeDeepFlavourJetTags:problepb', + 'pfNegativeDeepFlavourJetTags:probc', + 'pfNegativeDeepFlavourJetTags:probuds', + 'pfNegativeDeepFlavourJetTags:probg', + ] + pfParticleTransformerAK4JetTagsAll + pfNegativeParticleTransformerAK4JetTagsProbs \ + + pfParticleNetFromMiniAODAK4PuppiCentralJetTagsAll + pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs + + updateJetCollection( + process, + jetSource=cms.InputTag('slimmedJetsPuppi'), + jetCorrections=('AK4PFPuppi', + cms.vstring( + ['L1FastJet', 'L2Relative', 'L3Absolute', + 'L2L3Residual']), 'None'), + btagDiscriminators=_btagDiscriminators, + postfix='PuppiWithDeepInfo', + ) + process.load("Configuration.StandardSequences.MagneticField_cff") + process.jetPuppiCorrFactorsNano.src = "selectedUpdatedPatJetsPuppiWithDeepInfo" + process.updatedJetsPuppi.jetSource = "selectedUpdatedPatJetsPuppiWithDeepInfo" + + + process.updatedPatJetsTransientCorrectedPuppiWithDeepInfo.tagInfoSources.append(cms.InputTag("pfDeepFlavourTagInfosPuppiWithDeepInfo")) + process.updatedPatJetsTransientCorrectedPuppiWithDeepInfo.addTagInfos = cms.bool(True) + + + + return process + +def update_jets_AK8(process): + # Based on ``nanoAOD_addDeepInfoAK8`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + # Care needs to be taken to make sure no discriminators from stock Nano are excluded -> would results in unfilled vars + _btagDiscriminators = [ + 'pfMassIndependentDeepDoubleBvLV2JetTags:probHbb', + 'pfMassIndependentDeepDoubleCvLV2JetTags:probHcc', + 'pfMassIndependentDeepDoubleCvBV2JetTags:probHcc', + ] + from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetJetTagsAll as pfParticleNetJetTagsAll + _btagDiscriminators += pfParticleNetJetTagsAll + updateJetCollection( + process, + jetSource=cms.InputTag('slimmedJetsAK8'), + pvSource=cms.InputTag('offlineSlimmedPrimaryVertices'), + svSource=cms.InputTag('slimmedSecondaryVertices'), + rParam=0.8, + jetCorrections=('AK8PFPuppi', + cms.vstring([ + 'L1FastJet', 'L2Relative', 'L3Absolute', + 'L2L3Residual' + ]), 'None'), + btagDiscriminators=_btagDiscriminators, + postfix='AK8WithDeepInfo', + # this should work but doesn't seem to enable the tag info with addTagInfos + # btagInfos=['pfDeepDoubleXTagInfos'], + printWarning=False) + process.jetCorrFactorsAK8.src = "selectedUpdatedPatJetsAK8WithDeepInfo" + process.updatedJetsAK8.jetSource = "selectedUpdatedPatJetsAK8WithDeepInfo" + # add DeepDoubleX taginfos + process.updatedPatJetsTransientCorrectedAK8WithDeepInfo.tagInfoSources.append(cms.InputTag("pfDeepDoubleXTagInfosAK8WithDeepInfo")) + process.updatedPatJetsTransientCorrectedAK8WithDeepInfo.addTagInfos = cms.bool(True) + return process + +def update_jets_AK8_subjet(process): + # Based on ``nanoAOD_addDeepInfoAK8`` + # in https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/python/nano_cff.py + # and https://github.com/alefisico/RecoBTag-PerformanceMeasurements/blob/10_2_X_boostedCommissioning/test/runBTagAnalyzer_cfg.py + _btagDiscriminators = [ + 'pfJetProbabilityBJetTags', + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probudsg', + ] + updateJetCollection( + process, + labelName='SoftDropSubjetsPF', + jetSource=cms.InputTag("slimmedJetsAK8PFPuppiSoftDropPacked", "SubJets"), + jetCorrections=('AK4PFPuppi', + ['L2Relative', 'L3Absolute'], 'None'), + btagDiscriminators=list(_btagDiscriminators), + explicitJTA=True, # needed for subjet b tagging + svClustering=False, # needed for subjet b tagging (IMPORTANT: Needs to be set to False to disable ghost-association which does not work with slimmed jets) + fatJets=cms.InputTag('slimmedJetsAK8'), # needed for subjet b tagging + rParam=0.8, # needed for subjet b tagging + sortByPt=False, # Don't change order (would mess with subJetIdx for FatJets) + postfix='AK8SubjetsWithDeepInfo') + + process.subJetTable.src = 'selectedUpdatedPatJetsSoftDropSubjetsPFAK8SubjetsWithDeepInfo' + + + return process + +def get_DDX_vars(): + # retreive 27 jet-level features used in double-b and deep double-x taggers + # defined in arXiv:1712.07158 + DDXVars = cms.PSet( + DDX_jetNTracks = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.jetNTracks", int, doc="number of tracks associated with the jet"), + DDX_jetNSecondaryVertices = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.jetNSecondaryVertices", int, doc="number of SVs associated with the jet"), + DDX_tau1_trackEtaRel_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_0", float, doc="1st smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackEtaRel_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_1", float, doc="2nd smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackEtaRel_2 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackEtaRel_2", float, doc="3rd smallest track pseudorapidity, relative to the jet axis, associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_0", float, doc="1st smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_1", float, doc="2nd smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackEtaRel_3 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackEtaRel_2", float, doc="3rd smallest track pseudorapidity, relative to the jet axis, associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_flightDistance2dSig = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_flightDistance2dSig", float, doc="transverse distance significance between primary and secondary vertex associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_flightDistance2dSig = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_flightDistance2dSig", float, doc="transverse distance significance between primary and secondary vertex associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_vertexDeltaR = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexDeltaR", float, doc="deltaR between the 1st N-subjettiness axis and secondary vertex direction", precision=10), + DDX_tau1_vertexEnergyRatio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexEnergyRatio", float, doc="ratio of energy at secondary vertex over total energy associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_vertexEnergyRatio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_vertexEnergyRatio", float, doc="ratio of energy at secondary vertex over total energy associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau1_vertexMass = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_vertexMass", float, doc="mass of track sum at secondary vertex associated to the 1st N-subjettiness axis", precision=10), + DDX_tau2_vertexMass = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_vertexMass", float, doc="mass of track sum at secondary vertex associated to the 2nd N-subjettiness axis", precision=10), + DDX_trackSip2dSigAboveBottom_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveBottom_0", float, doc="track 2D signed impact parameter significance of 1st track lifting mass above bottom", precision=10), + DDX_trackSip2dSigAboveBottom_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveBottom_1", float, doc="track 2D signed impact parameter significance of 2nd track lifting mass above bottom", precision=10), + DDX_trackSip2dSigAboveCharm = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip2dSigAboveCharm", float, doc="track 2D signed impact parameter significance of 1st track lifting mass above charm", precision=10), + DDX_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance", precision=10), + DDX_tau1_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance associated to the 1st N-subjettiness axis", precision=10), + DDX_tau1_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau1_trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance associated to the 1st N-subjettiness axis", precision=10), + DDX_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance", precision=10), + DDX_tau2_trackSip3dSig_0 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackSip3dSig_0", float, doc="1st largest track 3D signed impact parameter significance associated to the 2nd N-subjettiness axis", precision=10), + DDX_tau2_trackSip3dSig_1 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.tau2_trackSip3dSig_1", float, doc="2nd largest track 3D signed impact parameter significance associated to the 2nd N-subjettiness axis", precision=10), + DDX_trackSip3dSig_2 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_2", float, doc="3rd largest track 3D signed impact parameter significance", precision=10), + DDX_trackSip3dSig_3 = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.trackSip3dSig_3", float, doc="4th largest track 3D signed impact parameter significance", precision=10), + DDX_z_ratio = Var("tagInfo(\'pfDeepDoubleX\').features().tag_info_features.z_ratio", float, doc="z = deltaR(SV0,SV1)*pT(SV1)/m(SV0,SV1), defined in Eq. 7 of arXiv:1712.07158", precision=10) + ) + return DDXVars + +def get_DeepCSV_vars(): + DeepCSVVars = cms.PSet( + # Tagger inputs also include jet pt and eta + # Track based (keep only jet-based features for DeepCSV from Run 3 commissioning) + # DeepCSV_trackPtRel_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[0]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackPtRel_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[1]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackPtRel_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[2]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackPtRel_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[3]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackPtRel_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[4]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackPtRel_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRel\')[5]:-999", float, doc="track transverse momentum, relative to the jet axis", precision=10), + # DeepCSV_trackJetDistVal_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[0]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackJetDistVal_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[1]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackJetDistVal_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[2]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackJetDistVal_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[3]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackJetDistVal_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[4]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackJetDistVal_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackJetDistVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackJetDistVal\')[5]:-999", float, doc="minimum track approach distance to jet axis", precision=10), + # DeepCSV_trackDeltaR_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[0]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackDeltaR_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[1]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackDeltaR_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[2]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackDeltaR_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[3]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackDeltaR_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[4]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackDeltaR_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDeltaR\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDeltaR\')[5]:-999", float, doc="track pseudoangular distance from the jet axis", precision=10), + # DeepCSV_trackPtRatio_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[0]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackPtRatio_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[1]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackPtRatio_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[2]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackPtRatio_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[3]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackPtRatio_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[4]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackPtRatio_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackPtRatio\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackPtRatio\')[5]:-999", float, doc="track transverse momentum, relative to the jet axis, normalized to its energy", precision=10), + # DeepCSV_trackSip3dSig_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[0]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip3dSig_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[1]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip3dSig_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[2]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip3dSig_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[3]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip3dSig_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[4]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip3dSig_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip3dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip3dSig\')[5]:-999", float, doc="track 3D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[0]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[1]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[2]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[3]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[4]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackSip2dSig_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackSip2dSig\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackSip2dSig\')[5]:-999", float, doc="track 2D signed impact parameter significance", precision=10), + # DeepCSV_trackDecayLenVal_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[0]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackDecayLenVal_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[1]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackDecayLenVal_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[2]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackDecayLenVal_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[3]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackDecayLenVal_4 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[4]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackDecayLenVal_5 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackDecayLenVal\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackDecayLenVal\')[5]:-999", float, doc="track decay length", precision=10), + # DeepCSV_trackEtaRel_0 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackEtaRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackEtaRel\')[0]:-999", float, doc="track pseudorapidity, relative to the jet axis", precision=10), + # DeepCSV_trackEtaRel_1 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackEtaRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackEtaRel\')[1]:-999", float, doc="track pseudorapidity, relative to the jet axis", precision=10), + # DeepCSV_trackEtaRel_2 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackEtaRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackEtaRel\')[2]:-999", float, doc="track pseudorapidity, relative to the jet axis", precision=10), + # DeepCSV_trackEtaRel_3 = Var("?tagInfo(\'pfDeepCSV\').taggingVariables.checkTag(\'trackEtaRel\')?tagInfo(\'pfDeepCSV\').taggingVariables.getList(\'trackEtaRel\')[3]:-999", float, doc="track pseudorapidity, relative to the jet axis", precision=10), + # Jet based + DeepCSV_trackJetPt = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackJetPt\', -999)", float, doc="track-based jet transverse momentum", precision=10), + DeepCSV_vertexCategory = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'vertexCategory\', -999)", float, doc="category of secondary vertex (Reco, Pseudo, No)", precision=10), + DeepCSV_jetNSecondaryVertices = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'jetNSecondaryVertices\', -999)", int, doc="number of reconstructed possible secondary vertices in jet"), + DeepCSV_jetNSelectedTracks = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'jetNSelectedTracks\', -999)", int, doc="selected tracks in the jet"), + DeepCSV_jetNTracksEtaRel = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'jetNTracksEtaRel\', -999)", int, doc="number of tracks for which etaRel is computed"), + DeepCSV_trackSumJetEtRatio = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSumJetEtRatio\', -999)", float, doc="ratio of track sum transverse energy over jet energy", precision=10), + DeepCSV_trackSumJetDeltaR = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSumJetDeltaR\', -999)", float, doc="pseudoangular distance between jet axis and track fourvector sum", precision=10), + DeepCSV_trackSip2dValAboveCharm = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSip2dValAboveCharm\', -999)", float, doc="track 2D signed impact parameter of first track lifting mass above charm", precision=10), + DeepCSV_trackSip2dSigAboveCharm = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSip2dSigAboveCharm\', -999)", float, doc="track 2D signed impact parameter significance of first track lifting mass above charm", precision=10), + DeepCSV_trackSip3dValAboveCharm = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSip3dValAboveCharm\', -999)", float, doc="track 3D signed impact parameter of first track lifting mass above charm", precision=10), + DeepCSV_trackSip3dSigAboveCharm = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'trackSip3dSigAboveCharm\', -999)", float, doc="track 3D signed impact parameter significance of first track lifting mass above charm", precision=10), + DeepCSV_vertexMass = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'vertexMass\', -999)", float, doc="mass of track sum at secondary vertex", precision=10), + DeepCSV_vertexNTracks = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'vertexNTracks\', -999)", int, doc="number of tracks at secondary vertex"), + DeepCSV_vertexEnergyRatio = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'vertexEnergyRatio\', -999)", float, doc="ratio of energy at secondary vertex over total energy", precision=10), + DeepCSV_vertexJetDeltaR = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'vertexJetDeltaR\', -999)", float, doc="pseudoangular distance between jet axis and secondary vertex direction", precision=10), + DeepCSV_flightDistance2dVal = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'flightDistance2dVal\', -999)", float, doc="transverse distance between primary and secondary vertex", precision=10), + DeepCSV_flightDistance2dSig = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'flightDistance2dSig\', -999)", float, doc="transverse distance significance between primary and secondary vertex", precision=10), + DeepCSV_flightDistance3dVal = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'flightDistance3dVal\', -999)", float, doc="distance between primary and secondary vertex", precision=10), + DeepCSV_flightDistance3dSig = Var("tagInfo(\'pfDeepCSV\').taggingVariables.get(\'flightDistance3dSig\', -999)", float, doc="distance significance between primary and secondary vertex", precision=10), + ) + return DeepCSVVars + +## Store all output nodes, negative tagger for SF +def get_DeepJet_outputs(): + DeepJetOutputVars = cms.PSet( + btagDeepFlavB_b=Var("bDiscriminator('pfDeepFlavourJetTags:probb')", + float, + doc="DeepJet b tag probability", + precision=10), + btagDeepFlavB_bb=Var("bDiscriminator('pfDeepFlavourJetTags:probbb')", + float, + doc="DeepJet bb tag probability", + precision=10), + btagDeepFlavB_lepb=Var("bDiscriminator('pfDeepFlavourJetTags:problepb')", + float, + doc="DeepJet lepb tag probability", + precision=10), + btagDeepFlavC=Var("bDiscriminator('pfDeepFlavourJetTags:probc')", + float, + doc="DeepJet c tag probability", + precision=10), + btagDeepFlavUDS=Var("bDiscriminator('pfDeepFlavourJetTags:probuds')", + float, + doc="DeepJet uds tag probability", + precision=10), + btagDeepFlavG=Var("bDiscriminator('pfDeepFlavourJetTags:probg')", + float, + doc="DeepJet gluon tag probability", + precision=10), + # discriminators are already part of jets_cff.py from NanoAOD and therefore not added here + + # negative taggers + btagNegDeepFlavB = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probb')+bDiscriminator('pfNegativeDeepFlavourJetTags:probbb')+bDiscriminator('pfNegativeDeepFlavourJetTags:problepb')", + float, + doc="Negative DeepJet b+bb+lepb tag discriminator", + precision=10), + btagNegDeepFlavCvL = Var("?(bDiscriminator('pfNegativeDeepFlavourJetTags:probc')+bDiscriminator('pfNegativeDeepFlavourJetTags:probuds')+bDiscriminator('pfNegativeDeepFlavourJetTags:probg'))>0?bDiscriminator('pfNegativeDeepFlavourJetTags:probc')/(bDiscriminator('pfNegativeDeepFlavourJetTags:probc')+bDiscriminator('pfNegativeDeepFlavourJetTags:probuds')+bDiscriminator('pfNegativeDeepFlavourJetTags:probg')):-1", + float, + doc="Negative DeepJet c vs uds+g discriminator", + precision=10), + btagNegDeepFlavCvB = Var("?(bDiscriminator('pfNegativeDeepFlavourJetTags:probc')+bDiscriminator('pfNegativeDeepFlavourJetTags:probb')+bDiscriminator('pfNegativeDeepFlavourJetTags:probbb')+bDiscriminator('pfNegativeDeepFlavourJetTags:problepb'))>0?bDiscriminator('pfNegativeDeepFlavourJetTags:probc')/(bDiscriminator('pfNegativeDeepFlavourJetTags:probc')+bDiscriminator('pfNegativeDeepFlavourJetTags:probb')+bDiscriminator('pfNegativeDeepFlavourJetTags:probbb')+bDiscriminator('pfNegativeDeepFlavourJetTags:problepb')):-1", + float, + doc="Negative DeepJet c vs b+bb+lepb discriminator", + precision=10), + btagNegDeepFlavQG = Var("?(bDiscriminator('pfNegativeDeepFlavourJetTags:probg')+bDiscriminator('pfNegativeDeepFlavourJetTags:probuds'))>0?bDiscriminator('pfNegativeDeepFlavourJetTags:probg')/(bDiscriminator('pfNegativeDeepFlavourJetTags:probg')+bDiscriminator('pfNegativeDeepFlavourJetTags:probuds')):-1", + float, + doc="Negative DeepJet g vs uds discriminator", + precision=10), + btagNegDeepFlavB_b = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probb')", + float, + doc="Negative DeepJet b tag probability", + precision=10), + btagNegDeepFlavB_bb = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probbb')", + float, + doc="Negative DeepJet bb tag probability", + precision=10), + btagNegDeepFlavB_lepb = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:problepb')", + float, + doc="Negative DeepJet lepb tag probability", + precision=10), + btagNegDeepFlavC = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probc')", + float, + doc="Negative DeepJet c tag probability", + precision=10), + btagNegDeepFlavUDS = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probuds')", + float, + doc="Negative DeepJet uds tag probability", + precision=10), + btagNegDeepFlavG = Var("bDiscriminator('pfNegativeDeepFlavourJetTags:probg')", + float, + doc="Negative DeepJet gluon tag probability", + precision=10), + ) + return DeepJetOutputVars + +def get_ParticleNetAK4_outputs(): + ## default scores in jetAK4_Puppi_cff.py collections + ParticleNetAK4OutputVars = cms.PSet( + # raw scores + btagPNetProbB = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probb')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probb'):-1", + float, + doc="ParticleNet b tag probability", + precision=10), + btagPNetProbC = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc'):-1", + float, + doc="ParticleNet c tag probability", + precision=10), + btagPNetProbUDS = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds'):-1", + float, + doc="ParticleNet uds tag probability", + precision=10), + btagPNetProbG = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg'):-1", + float, + doc="ParticleNet gluon tag probability", + precision=10), + + # negative taggers + btagNegPNetB = Var("?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg'))>0?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb'))/(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')):-1", + float, + doc="Negative ParticleNet b vs. udscg", + precision=10), + btagNegPNetCvL = Var("?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg'))>0?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc'))/(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')):-1", + float, + doc="Negative ParticleNet c vs. udsg", + precision=10), + btagNegPNetCvB = Var("?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb'))>0?(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc'))/(bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb')):-1", + float, + doc="Negative ParticleNet c vs. b", + precision=10), + btagNegPNetProbB = Var("?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb')>0?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probb'):-1", + float, + doc="Negative ParticleNet b tag probability", + precision=10), + btagNegPNetProbC = Var("?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')>0?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probc'):-1", + float, + doc="Negative ParticleNet c tag probability", + precision=10), + btagNegPNetProbUDS = Var("?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')>0?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds'):-1", + float, + doc="Negative ParticleNet uds tag probability", + precision=10), + btagNegPNetProbG = Var("?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')>0?bDiscriminator('pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:probg'):-1", + float, + doc="Negative ParticleNet gluon tag probability", + precision=10), + ) + + return ParticleNetAK4OutputVars + +def get_ParticleTransformerAK4_outputs(): + ParticleTransformerAK4OutputVars = cms.PSet( + btagRobustParTAK4B_b=Var("bDiscriminator('pfParticleTransformerAK4JetTags:probb')", + float, + doc="RobustParTAK4 b tag probability", + precision=10), + btagRobustParTAK4B_bb=Var("bDiscriminator('pfParticleTransformerAK4JetTags:probbb')", + float, + doc="RobustParTAK4 bb tag probability", + precision=10), + btagRobustParTAK4B_lepb=Var("bDiscriminator('pfParticleTransformerAK4JetTags:problepb')", + float, + doc="RobustParTAK4 lepb tag probability", + precision=10), + btagRobustParTAK4C=Var("bDiscriminator('pfParticleTransformerAK4JetTags:probc')", + float, + doc="RobustParTAK4 c tag probability", + precision=10), + btagRobustParTAK4UDS=Var("bDiscriminator('pfParticleTransformerAK4JetTags:probuds')", + float, + doc="RobustParTAK4 uds tag probability", + precision=10), + btagRobustParTAK4G=Var("bDiscriminator('pfParticleTransformerAK4JetTags:probg')", + float, + doc="RobustParTAK4 gluon tag probability", + precision=10), + + # negative taggers + btagNegRobustParTAK4B = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probbb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:problepb')", + float, + doc="Negative RobustParTAK4 b+bb+lepb tag discriminator", + precision=10), + btagNegRobustParTAK4CvL = Var("?(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probuds')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg'))>0?bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')/(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probuds')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg')):-1", + float, + doc="Negative RobustParTAK4 c vs uds+g discriminator", + precision=10), + btagNegRobustParTAK4CvB = Var("?(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probbb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:problepb'))>0?bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')/(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probbb')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:problepb')):-1", + float, + doc="Negative RobustParTAK4 c vs b+bb+lepb discriminator", + precision=10), + btagNegRobustParTAK4QG = Var("?(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probuds'))>0?bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg')/(bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg')+bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probuds')):-1", + float, + doc="Negative RobustParTAK4 g vs uds discriminator", + precision=10), + btagNegRobustParTAK4B_b = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probb')", + float, + doc="Negative RobustParTAK4 b tag probability", + precision=10), + btagNegRobustParTAK4B_bb = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probbb')", + float, + doc="Negative RobustParTAK4 bb tag probability", + precision=10), + btagNegRobustParTAK4B_lepb = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:problepb')", + float, + doc="Negative RobustParTAK4 lepb tag probability", + precision=10), + btagNegRobustParTAK4C = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probc')", + float, + doc="Negative RobustParTAK4 c tag probability", + precision=10), + btagNegRobustParTAK4UDS = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probuds')", + float, + doc="Negative RobustParTAK4 uds tag probability", + precision=10), + btagNegRobustParTAK4G = Var("bDiscriminator('pfNegativeParticleTransformerAK4JetTags:probg')", + float, + doc="Negative RobustParTAK4 gluon tag probability", + precision=10), + ) + + return ParticleTransformerAK4OutputVars + +def add_BTV(process, addAK4=False, addAK8=False, scheme="btvSF"): + process.customizeJetTask = cms.Task() + process.schedule.associate(process.customizeJetTask) + + CommonVars = cms.PSet( + Proba=Var("bDiscriminator('pfJetProbabilityBJetTags')", + float, + doc="Jet Probability (Usage:BTV)", + precision=10), + ProbaN=Var("bDiscriminator('pfNegativeOnlyJetProbabilityBJetTags')", + float, + doc="Negative-only Jet Probability (Usage:BTV)", + precision=10), + Bprob=Var("bDiscriminator('pfJetBProbabilityBJetTags')", + float, + doc="Jet B Probability (Usage:BTV)", + precision=10), + BprobN=Var("bDiscriminator('pfNegativeOnlyJetBProbabilityBJetTags')", + float, + doc="Negative-only Jet B Probability (Usage:BTV)", + precision=10), + ) + + # decouple these from CommonVars, not relevant for data + HadronCountingVars = cms.PSet( + nBHadrons=Var("jetFlavourInfo().getbHadrons().size()", + int, + doc="number of b-hadrons"), + nCHadrons=Var("jetFlavourInfo().getcHadrons().size()", + int, + doc="number of c-hadrons") + ) + + # AK4 + if addAK4: + if scheme == "btvSF": + _n_cpf = 3 + _n_npf = 3 + _n_sv = 4 + elif scheme == "DeepJet": + _n_cpf = 25 + _n_npf = 25 + _n_sv = 4 + elif scheme == "RobustParTAK4": + _n_cpf = 25 + _n_npf = 25 + _n_sv = 12 + process = update_jets_AK4(process) + + process.customJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=jetPuppiTable.src, + cut=jetPuppiTable.cut, + name=jetPuppiTable.name, + doc=jetPuppiTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for Jets + variables=cms.PSet( + CommonVars, + get_DeepCSV_vars(), + get_DeepJet_outputs(), # outputs are added in any case, inputs only if requested + get_ParticleNetAK4_outputs(), + get_ParticleTransformerAK4_outputs(), + )) + + # disable the ParT branches in default jetPuppi table + from PhysicsTools.NanoAOD.nano_eras_cff import run3_nanoAOD_122, run3_nanoAOD_124 + (run3_nanoAOD_122 | run3_nanoAOD_124).toModify( + process.jetPuppiTable.variables, + btagRobustParTAK4B = None, + btagRobustParTAK4CvL = None, + btagRobustParTAK4CvB = None, + btagRobustParTAK4QG = None, + ) + + + # from Run3 onwards, always set storeAK4Truth to True for MC + process.customAK4ConstituentsForDeepJetTable = cms.EDProducer("PatJetDeepJetTableProducer", + jets = cms.InputTag("linkedObjects","jets"), + n_cpf=cms.uint32(_n_cpf), + n_npf=cms.uint32(_n_npf), + n_sv=cms.uint32(_n_sv) + ) + process.customizeJetTask.add(process.customJetExtTable) + process.customizeJetTask.add(process.customAK4ConstituentsForDeepJetTable) + # AK8 + if addAK8: + process = update_jets_AK8(process) + process = update_jets_AK8_subjet(process) + process.customFatJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=fatJetTable.src, + cut=fatJetTable.cut, + name=fatJetTable.name, + doc=fatJetTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for FatJets + variables=cms.PSet( + CommonVars, + #HadronCountingVars if runOnMC else cms.PSet(), # only necessary before 106x + get_DDX_vars() , + )) + + + # Subjets + process.customSubJetExtTable = cms.EDProducer( + "SimpleCandidateFlatTableProducer", + src=subJetTable.src, + cut=subJetTable.cut, + name=subJetTable.name, + doc=subJetTable.doc, + singleton=cms.bool(False), # the number of entries is variable + extension=cms.bool(True), # this is the extension table for FatJets + variables=cms.PSet( + CommonVars, + #HadronCountingVars if runOnMC else cms.PSet(), # only necessary before 106x + )) + + process.customizeJetTask.add(process.customFatJetExtTable) + process.customizeJetTask.add(process.customSubJetExtTable) + + + +# From https://github.com/cms-jet/PFNano/blob/13_0_7_from124MiniAOD/python/addPFCands_cff.py +def addPFCands(process, allPF = False, addAK4=False, addAK8=False): + process.customizedPFCandsTask = cms.Task() + process.schedule.associate(process.customizedPFCandsTask) + + process.finalJetsAK8Constituents = cms.EDProducer("PatJetConstituentPtrSelector", + src = cms.InputTag("finalJetsAK8"), + cut = cms.string("") + ) + process.finalJetsAK4Constituents = cms.EDProducer("PatJetConstituentPtrSelector", + src = cms.InputTag("finalJetsPuppi"), + cut = cms.string("") + ) + if allPF: + candInput = cms.InputTag("packedPFCandidates") + elif not addAK8: + candList = cms.VInputTag(cms.InputTag("finalJetsAK4Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK4Constituents) + process.finalJetsConstituentsTable = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituentsTable") + elif not addAK4: + candList = cms.VInputTag(cms.InputTag("finalJetsAK8Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK8Constituents) + process.finalJetsConstituentsTable = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituentsTable") + else: + candList = cms.VInputTag(cms.InputTag("finalJetsAK4Constituents", "constituents"), cms.InputTag("finalJetsAK8Constituents", "constituents")) + process.customizedPFCandsTask.add(process.finalJetsAK4Constituents) + process.customizedPFCandsTask.add(process.finalJetsAK8Constituents) + process.finalJetsConstituentsTable = cms.EDProducer("PackedCandidatePtrMerger", src = candList, skipNulls = cms.bool(True), warnOnSkip = cms.bool(True)) + candInput = cms.InputTag("finalJetsConstituentsTable") + + process.customConstituentsExtTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = candInput, + cut = cms.string(""), #we should not filter after pruning + name = cms.string("PFCands"), + doc = cms.string("interesting particles from AK4 and AK8 jets"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the extension table for the AK8 constituents + variables = cms.PSet(CandVars, + puppiWeight = Var("puppiWeight()", float, doc="Puppi weight",precision=10), + puppiWeightNoLep = Var("puppiWeightNoLep()", float, doc="Puppi weight removing leptons",precision=10), + vtxChi2 = Var("?hasTrackDetails()?vertexChi2():-1", float, doc="vertex chi2",precision=10), + trkChi2 = Var("?hasTrackDetails()?pseudoTrack().normalizedChi2():-1", float, doc="normalized trk chi2", precision=10), + dz = Var("?hasTrackDetails()?dz():-1", float, doc="pf dz", precision=10), + dzErr = Var("?hasTrackDetails()?dzError():-1", float, doc="pf dz err", precision=10), + d0 = Var("?hasTrackDetails()?dxy():-1", float, doc="pf d0", precision=10), + d0Err = Var("?hasTrackDetails()?dxyError():-1", float, doc="pf d0 err", precision=10), + pvAssocQuality = Var("pvAssociationQuality()", int, doc="primary vertex association quality. 0: NotReconstructedPrimary, 1: OtherDeltaZ, 4: CompatibilityBTag, 5: CompatibilityDz, 6: UsedInFitLoose, 7: UsedInFitTight"), + lostInnerHits = Var("lostInnerHits()", int, doc="lost inner hits. -1: validHitInFirstPixelBarrelLayer, 0: noLostInnerHits, 1: oneLostInnerHit, 2: moreLostInnerHits"), + lostOuterHits = Var("?hasTrackDetails()?pseudoTrack().hitPattern().numberOfLostHits('MISSING_OUTER_HITS'):0", int, doc="lost outer hits"), + numberOfHits = Var("numberOfHits()", int, doc="number of hits"), + numberOfPixelHits = Var("numberOfPixelHits()", int, doc="number of pixel hits"), + trkQuality = Var("?hasTrackDetails()?pseudoTrack().qualityMask():0", int, doc="track quality mask"), + trkHighPurity = Var("?hasTrackDetails()?pseudoTrack().quality('highPurity'):0", bool, doc="track is high purity"), + trkAlgo = Var("?hasTrackDetails()?pseudoTrack().algo():-1", int, doc="track algorithm"), + trkP = Var("?hasTrackDetails()?pseudoTrack().p():-1", float, doc="track momemtum", precision=-1), + trkPt = Var("?hasTrackDetails()?pseudoTrack().pt():-1", float, doc="track pt", precision=-1), + trkEta = Var("?hasTrackDetails()?pseudoTrack().eta():-1", float, doc="track pt", precision=12), + trkPhi = Var("?hasTrackDetails()?pseudoTrack().phi():-1", float, doc="track phi", precision=12), + ) + ) + process.customAK8ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", + candidates = candInput, + jets = cms.InputTag("finalJetsAK8"), + jet_radius = cms.double(0.8), + name = cms.string("FatJetPFCands"), + idx_name = cms.string("pFCandsIdx"), + nameSV = cms.string("FatJetSVs"), + idx_nameSV = cms.string("sVIdx"), + ) + process.customAK4ConstituentsTable = cms.EDProducer("PatJetConstituentTableProducer", + candidates = candInput, + jets = cms.InputTag("finalJetsPuppi"), # was finalJets before + jet_radius = cms.double(0.4), + name = cms.string("JetPFCands"), + idx_name = cms.string("pFCandsIdx"), + nameSV = cms.string("JetSVs"), + idx_nameSV = cms.string("sVIdx"), + ) + process.customizedPFCandsTask.add(process.customConstituentsExtTable) + + if not allPF: + process.customizedPFCandsTask.add(process.finalJetsConstituentsTable) + # linkedObjects are WIP for Run3 + if addAK8: + process.customizedPFCandsTask.add(process.customAK8ConstituentsTable) + if addAK4: + process.customizedPFCandsTask.add(process.customAK4ConstituentsTable) + + + return process + +## Switches for BTV nano +# Default(store SFs PFCands+TaggerInputs) for both AK4 & AK8 jets +# btvNano_addAK4_switch, btvNano_addAK8_switch True, btvNano_addPF_switch False, TaggerInput = "btvSF" + +btvNano_switch = cms.PSet( + btvNano_addAK4_switch = cms.untracked.bool(True), + btvNano_addAK8_switch = cms.untracked.bool(False), + btvNano_addallPF_switch = cms.untracked.bool(False), + TaggerInput = cms.string("btvSF") + ) + +def BTVCustomNanoAOD(process): + addPFCands(process,btvNano_switch.btvNano_addallPF_switch,btvNano_switch.btvNano_addAK4_switch,btvNano_switch.btvNano_addAK8_switch) + add_BTV(process, btvNano_switch.btvNano_addAK4_switch,btvNano_switch.btvNano_addAK8_switch,btvNano_switch.TaggerInput) + process.load("PhysicsTools.NanoAOD.btvMC_cff") + ### for MC + if btvNano_switch.btvNano_addallPF_switch: + process.nanoSequenceMC+=allPFPFCandsMCSequence + else: + if btvNano_switch.btvNano_addAK4_switch and btvNano_switch.btvNano_addAK8_switch : + process.nanoSequenceMC+=ak4ak8PFCandsMCSequence + elif btvNano_switch.btvNano_addAK4_switch and not btvNano_switch.btvNano_addAK8_switch : + process.nanoSequenceMC+=ak4onlyPFCandsMCSequence + elif not btvNano_switch.btvNano_addAK4_switch and btvNano_switch.btvNano_addAK8_switch: + process.nanoSequenceMC+=ak8onlyPFCandsMCSequence + + return process diff --git a/PhysicsTools/NanoAOD/python/jetsAK4_Puppi_cff.py b/PhysicsTools/NanoAOD/python/jetsAK4_Puppi_cff.py index 5c4673adbe732..9ca15abe8b816 100644 --- a/PhysicsTools/NanoAOD/python/jetsAK4_Puppi_cff.py +++ b/PhysicsTools/NanoAOD/python/jetsAK4_Puppi_cff.py @@ -108,6 +108,7 @@ btagRobustParTAK4CvB = Var("?(bDiscriminator('pfParticleTransformerAK4JetTags:probc')+bDiscriminator('pfParticleTransformerAK4JetTags:probb')+bDiscriminator('pfParticleTransformerAK4JetTags:probbb')+bDiscriminator('pfParticleTransformerAK4JetTags:problepb'))>0?bDiscriminator('pfParticleTransformerAK4JetTags:probc')/(bDiscriminator('pfParticleTransformerAK4JetTags:probc')+bDiscriminator('pfParticleTransformerAK4JetTags:probb')+bDiscriminator('pfParticleTransformerAK4JetTags:probbb')+bDiscriminator('pfParticleTransformerAK4JetTags:problepb')):-1",float,doc="RobustParTAK4 c vs b+bb+lepb discriminator",precision=10), btagRobustParTAK4QG = Var("?(bDiscriminator('pfParticleTransformerAK4JetTags:probg')+bDiscriminator('pfParticleTransformerAK4JetTags:probuds'))>0?bDiscriminator('pfParticleTransformerAK4JetTags:probg')/(bDiscriminator('pfParticleTransformerAK4JetTags:probg')+bDiscriminator('pfParticleTransformerAK4JetTags:probuds')):-1",float,doc="RobustParTAK4 g vs uds discriminator",precision=10), btagPNetB = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:BvsAll')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:BvsAll'):-1",float,precision=10,doc="ParticleNet b vs. udscg"), + btagPNetCvNotB = Var("?(bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probmu')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probele')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h2p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup3h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup3h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum1h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum1h2p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum3h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum3h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probq')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg'))>0?(bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc'))/(bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probc')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probuds')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probmu')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probele')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup1h2p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup3h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaup3h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum1h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum1h2p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum3h0p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probtaum3h1p')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probq')+bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralJetTags:probg')):-1",float,precision=10,doc="ParticleNet C vs notB"), btagPNetCvL = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:CvsL')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:CvsL'):-1",float,precision=10,doc="ParticleNet c vs. udsg"), btagPNetCvB = Var("?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:CvsB')>0?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:CvsB'):-1",float,precision=10,doc="ParticleNet c vs. b"), btagPNetQvG = Var("?abs(eta())<2.5?bDiscriminator('pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags:QvsG'):bDiscriminator('pfParticleNetFromMiniAODAK4PuppiForwardDiscriminatorsJetTags:QvsG')",float,precision=10,doc="ParticleNet q (udsbc) vs. g"), diff --git a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py index c9a7dccc063b5..f4992609935f3 100644 --- a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py +++ b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py @@ -420,6 +420,7 @@ Plot1D('btagPNetB', 'btagPNetB', 20, 0, 1, 'ParticleNet b tag discriminator'), Plot1D('btagPNetCvL', 'btagPNetCvL', 20, 0, 1, 'ParticleNet c vs. light (udsg) discriminator'), Plot1D('btagPNetCvB', 'btagPNetCvB', 20, 0, 1, 'ParticleNet c vs. b discriminator'), + Plot1D('btagPNetCvNotB', 'btagPNetCvNotB', 20, 0, 1, 'ParticleNet C vs notB discriminator'), Plot1D('btagPNetQvG', 'btagPNetQvG', 20, 0, 1, 'ParticleNet quark (udsbc) vs. gluon discriminator'), Plot1D('btagPNetTauVJet', 'btagPNetTauVJet', 20, 0, 1, 'ParticleNet tau vs. jet discriminator'), Plot1D('PNetRegPtRawCorr', 'PNetRegPtRawCorr', 20, 0, 2, 'ParticleNet visible pT regression, correction relative to raw pT'), diff --git a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py index 361c2fd2814ae..69a0c51b550e7 100644 --- a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py +++ b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py @@ -60,6 +60,8 @@ , 'pfParticleNetFromMiniAODAK4PuppiForwardTagInfos' , 'pfParticleNetFromMiniAODAK4CHSCentralTagInfos' , 'pfParticleNetFromMiniAODAK4CHSForwardTagInfos' + , 'pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos' + , 'pfNegativeParticleNetFromMiniAODAK4CHSCentralTagInfos' , 'pfParticleNetFromMiniAODAK8TagInfos' ] @@ -293,6 +295,7 @@ for disc in _pfNegativeParticleNetAK4JetTagsProbs: supportedBtagDiscr[disc] = [["pfNegativeParticleNetAK4TagInfos"]] # ----------------------------------- +# setup Run3 ParticleNet AK4 from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs,_pfParticleNetFromMiniAODAK4PuppiCentralJetTagsMetaDiscr for disc in _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs: supportedBtagDiscr[disc] = [["pfParticleNetFromMiniAODAK4PuppiCentralTagInfos"]] @@ -313,6 +316,16 @@ supportedBtagDiscr[disc] = [["pfParticleNetFromMiniAODAK4CHSForwardTagInfos"]] for disc in _pfParticleNetFromMiniAODAK4CHSForwardJetTagsMetaDiscr: supportedMetaDiscr[disc] = _pfParticleNetFromMiniAODAK4CHSForwardJetTagsProbs +# ----------------------------------- +# setup Negative Run3 ParticleNet AK4 (central only) +from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import _pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs +for disc in _pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs: + supportedBtagDiscr[disc] = [["pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos"]] +from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import _pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTagsProbs +for disc in _pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTagsProbs: + supportedBtagDiscr[disc] = [["pfNegativeParticleNetFromMiniAODAK4CHSCentralTagInfos"]] +# ----------------------------------- +# setup Run3 ParticleNet AK8 from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK8_cff import _pfParticleNetFromMiniAODAK8JetTagsProbs,_pfParticleNetFromMiniAODAK8JetTagsMetaDiscr for disc in _pfParticleNetFromMiniAODAK8JetTagsProbs: supportedBtagDiscr[disc] = [["pfParticleNetFromMiniAODAK8TagInfos"]] @@ -338,3 +351,8 @@ for disc in _pfParticleTransformerAK4JetTagsMetaDiscrs: supportedMetaDiscr[disc] = _pfParticleTransformerAK4JetTagsProbs # ----------------------------------- +# setup Negative ParticleTransformer AK4 +from RecoBTag.ONNXRuntime.pfParticleTransformerAK4_cff import _pfNegativeParticleTransformerAK4JetTagsProbs +# update supportedBtagDiscr +for disc in _pfNegativeParticleTransformerAK4JetTagsProbs: + supportedBtagDiscr[disc] = [["pfNegativeParticleTransformerAK4TagInfos"]] diff --git a/PhysicsTools/PatAlgos/python/tools/jetTools.py b/PhysicsTools/PatAlgos/python/tools/jetTools.py index 5854c1481c874..7270022048df3 100644 --- a/PhysicsTools/PatAlgos/python/tools/jetTools.py +++ b/PhysicsTools/PatAlgos/python/tools/jetTools.py @@ -7,9 +7,9 @@ from PhysicsTools.PatAlgos.recoLayer0.bTagging_cff import * import sys from FWCore.ParameterSet.MassReplace import MassSearchReplaceAnyInputTagVisitor -from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4PuppiCentralTagInfos,pfParticleNetFromMiniAODAK4PuppiCentralJetTags,pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags +from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4PuppiCentralTagInfos,pfParticleNetFromMiniAODAK4PuppiCentralJetTags,pfParticleNetFromMiniAODAK4PuppiCentralDiscriminatorsJetTags,pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4PuppiForwardTagInfos,pfParticleNetFromMiniAODAK4PuppiForwardJetTags,pfParticleNetFromMiniAODAK4PuppiForwardDiscriminatorsJetTags -from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4CHSCentralTagInfos,pfParticleNetFromMiniAODAK4CHSCentralJetTags,pfParticleNetFromMiniAODAK4CHSCentralDiscriminatorsJetTags +from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4CHSCentralTagInfos,pfParticleNetFromMiniAODAK4CHSCentralJetTags,pfParticleNetFromMiniAODAK4CHSCentralDiscriminatorsJetTags,pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTags from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK4_cff import pfParticleNetFromMiniAODAK4CHSForwardTagInfos,pfParticleNetFromMiniAODAK4CHSForwardJetTags,pfParticleNetFromMiniAODAK4CHSForwardDiscriminatorsJetTags from RecoBTag.ONNXRuntime.pfParticleNetFromMiniAODAK8_cff import pfParticleNetFromMiniAODAK8TagInfos,pfParticleNetFromMiniAODAK8JetTags,pfParticleNetFromMiniAODAK8DiscriminatorsJetTags @@ -684,10 +684,9 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou if 'ParticleTransformerAK4TagInfos' in btagInfo: svUsed = svSource if btagInfo == 'pfNegativeParticleTransformerAK4TagInfos': - svUsed = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix) - flip = True + svUsed, flip, max_sip3dsig_for_flip = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix), True, 10. else: - flip = False + svUsed, flip, max_sip3dsig_for_flip = svSource, False, -1. # use right input tags when running with RECO PF candidates, which actually # depends of whether jets use "particleFlow" if pfCandidates.value() == 'packedPFCandidates': @@ -709,7 +708,8 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou puppi_value_map = puppi_value_map, vertex_associator = vertex_associator, is_weighted_jet = is_weighted_jet, - flip = flip), + flip = flip, + max_sip3dsig_for_flip=max_sip3dsig_for_flip), process, task) if btagInfo == 'pfDeepDoubleXTagInfos': # can only run on PAT jets, so the updater needs to be used @@ -831,16 +831,22 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou acceptedTagInfos.append(btagInfo) elif hasattr(toptag, btagInfo) : acceptedTagInfos.append(btagInfo) - elif btagInfo == 'pfParticleNetFromMiniAODAK4PuppiCentralTagInfos': + elif btagInfo == 'pfParticleNetFromMiniAODAK4PuppiCentralTagInfos' or btagInfo == 'pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos': # ParticleNetFromMiniAOD cannot be run on RECO inputs, so need a workaround + if btagInfo == 'pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos': + svUsed, flip_ip_sign, max_sip3dsig_for_flip = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix), True, 10. + else: + svUsed, flip_ip_sign, max_sip3dsig_for_flip = svSource, False, -1. if pfCandidates.value() != 'packedPFCandidates': raise ValueError("Invalid pfCandidates collection: %s." % pfCandidates.value()) addToProcessAndTask(btagPrefix+btagInfo+labelName+postfix, pfParticleNetFromMiniAODAK4PuppiCentralTagInfos.clone( jets = jetSource, vertices = pvSource, - secondary_vertices = svSource, + secondary_vertices = svUsed, pf_candidates = pfCandidates, + flip_ip_sign = flip_ip_sign, + max_sip3dsig_for_flip = max_sip3dsig_for_flip, ), process, task) acceptedTagInfos.append(btagInfo) @@ -857,16 +863,22 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou ), process, task) acceptedTagInfos.append(btagInfo) - elif btagInfo == 'pfParticleNetFromMiniAODAK4CHSCentralTagInfos': + elif btagInfo == 'pfParticleNetFromMiniAODAK4CHSCentralTagInfos' or btagInfo == 'pfNegativeParticleNetFromMiniAODAK4PuppiForwardTagInfos': # ParticleNetFromMiniAOD cannot be run on RECO inputs, so need a workaround + if btagInfo == 'pfNegativeParticleNetFromMiniAODAK4PuppiForwardTagInfos': + svUsed, flip_ip_sign, max_sip3dsig_for_flip = cms.InputTag(btagPrefix+'inclusiveCandidateNegativeSecondaryVertices'+labelName+postfix), True, 10. + else: + svUsed, flip_ip_sign, max_sip3dsig_for_flip = svSource, False, -1. if pfCandidates.value() != 'packedPFCandidates': raise ValueError("Invalid pfCandidates collection: %s." % pfCandidates.value()) addToProcessAndTask(btagPrefix+btagInfo+labelName+postfix, pfParticleNetFromMiniAODAK4CHSCentralTagInfos.clone( jets = jetSource, vertices = pvSource, - secondary_vertices = svSource, + secondary_vertices = svUsed, pf_candidates = pfCandidates, + flip_ip_sign = flip_ip_sign, + max_sip3dsig_for_flip = max_sip3dsig_for_flip, ), process, task) acceptedTagInfos.append(btagInfo) @@ -943,6 +955,18 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou task ) acceptedBtagDiscriminators.append(discriminator_name) + elif btagDiscr=='pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags': + if hasattr(process, newDiscr): + pass + addToProcessAndTask( + newDiscr, + pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags.clone( + src = cms.InputTag(btagPrefix+supportedBtagDiscr[discriminator_name][0][0]+labelName+postfix) + ), + process, + task + ) + acceptedBtagDiscriminators.append(discriminator_name) elif btagDiscr=='pfParticleNetFromMiniAODAK4PuppiForwardJetTags': if hasattr(process, newDiscr): pass @@ -967,6 +991,18 @@ def setupBTagging(process, jetSource, pfCandidates, explicitJTA, pvSource, svSou task ) acceptedBtagDiscriminators.append(discriminator_name) + elif btagDiscr=='pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTags': + if hasattr(process, newDiscr): + pass + addToProcessAndTask( + newDiscr, + pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTags.clone( + src = cms.InputTag(btagPrefix+supportedBtagDiscr[discriminator_name][0][0]+labelName+postfix) + ), + process, + task + ) + acceptedBtagDiscriminators.append(discriminator_name) elif btagDiscr=='pfParticleNetFromMiniAODAK4CHSForwardJetTags': if hasattr(process, newDiscr): pass diff --git a/RecoBTag/FeatureTools/plugins/ParticleNetFeatureEvaluator.cc b/RecoBTag/FeatureTools/plugins/ParticleNetFeatureEvaluator.cc index 7f820b6fe4fcf..03feb93b0b1e7 100644 --- a/RecoBTag/FeatureTools/plugins/ParticleNetFeatureEvaluator.cc +++ b/RecoBTag/FeatureTools/plugins/ParticleNetFeatureEvaluator.cc @@ -63,6 +63,8 @@ class ParticleNetFeatureEvaluator : public edm::stream::EDProducer<> { const double min_pt_for_taus_; const double max_eta_for_taus_; const bool include_neutrals_; + const bool flip_ip_sign_; + const double max_sip3dsig_for_flip_; edm::EDGetTokenT muon_token_; edm::EDGetTokenT electron_token_; @@ -261,6 +263,8 @@ ParticleNetFeatureEvaluator::ParticleNetFeatureEvaluator(const edm::ParameterSet min_pt_for_taus_(iConfig.getParameter("min_pt_for_taus")), max_eta_for_taus_(iConfig.getParameter("max_eta_for_taus")), include_neutrals_(iConfig.getParameter("include_neutrals")), + flip_ip_sign_(iConfig.getParameter("flip_ip_sign")), + max_sip3dsig_for_flip_(iConfig.getParameter("max_sip3dsig_for_flip")), muon_token_(consumes(iConfig.getParameter("muons"))), electron_token_(consumes(iConfig.getParameter("electrons"))), photon_token_(consumes(iConfig.getParameter("photons"))), @@ -292,6 +296,8 @@ void ParticleNetFeatureEvaluator::fillDescriptions(edm::ConfigurationDescription desc.add("min_pt_for_taus", 20.); desc.add("max_eta_for_taus", 2.5); desc.add("include_neutrals", true); + desc.add("flip_ip_sign", false); + desc.add("max_sip3dsig_for_flip", 99999); desc.add("vertices", edm::InputTag("offlineSlimmedPrimaryVertices")); desc.add("secondary_vertices", edm::InputTag("slimmedSecondaryVertices")); desc.add("pf_candidates", edm::InputTag("packedPFCandidates")); @@ -451,6 +457,16 @@ void ParticleNetFeatureEvaluator::fillParticleFeatures(DeepBoostedJetFeatures &f TVector3 cand_direction(candP3.x(), candP3.y(), candP3.z()); + // only when computing the nagative tagger: remove charged candidates with high sip3d + if (flip_ip_sign_ && track) { + reco::TransientTrack transientTrack = track_builder_->build(*track); + Measurement1D meas_ip3d = IPTools::signedImpactParameter3D(transientTrack, jet_ref_track_dir, *pv_).second; + if (!std::isnan(meas_ip3d.significance()) && meas_ip3d.significance() > max_sip3dsig_for_flip_) { + continue; + } + } + float ip_sign = flip_ip_sign_ ? -1.f : 1.f; + fts.fill("jet_pfcand_pt_log", std::isnan(std::log(candP4.pt())) ? 0 : std::log(candP4.pt())); fts.fill("jet_pfcand_energy_log", std::isnan(std::log(candP4.energy())) ? 0 : std::log(candP4.energy())); fts.fill("jet_pfcand_eta", candP4.eta()); @@ -468,8 +484,8 @@ void ParticleNetFeatureEvaluator::fillParticleFeatures(DeepBoostedJetFeatures &f ? 0 : jet_direction.Dot(cand_direction) / cand_direction.Mag()); fts.fill("jet_pfcand_frompv", cand->fromPV()); - fts.fill("jet_pfcand_dz", std::isnan(cand->dz(pv_ass_pos)) ? 0 : cand->dz(pv_ass_pos)); - fts.fill("jet_pfcand_dxy", std::isnan(cand->dxy(pv_ass_pos)) ? 0 : cand->dxy(pv_ass_pos)); + fts.fill("jet_pfcand_dz", ip_sign * (std::isnan(cand->dz(pv_ass_pos)) ? 0 : cand->dz(pv_ass_pos))); + fts.fill("jet_pfcand_dxy", ip_sign * (std::isnan(cand->dxy(pv_ass_pos)) ? 0 : cand->dxy(pv_ass_pos))); fts.fill("jet_pfcand_puppiw", cand->puppiWeight()); fts.fill("jet_pfcand_nlostinnerhits", cand->lostInnerHits()); fts.fill("jet_pfcand_nhits", cand->numberOfHits()); @@ -515,7 +531,7 @@ void ParticleNetFeatureEvaluator::fillParticleFeatures(DeepBoostedJetFeatures &f Measurement1D meas_jetdist = IPTools::jetTrackDistance(transientTrack, jet_ref_track_dir, *pv_).second; Measurement1D meas_decayl = IPTools::signedDecayLength3D(transientTrack, jet_ref_track_dir, *pv_).second; - fts.fill("jet_pfcand_trackjet_d3d", std::isnan(meas_ip3d.value()) ? 0 : meas_ip3d.value()); + fts.fill("jet_pfcand_trackjet_d3d", ip_sign * (std::isnan(meas_ip3d.value()) ? 0 : meas_ip3d.value())); fts.fill("jet_pfcand_trackjet_d3dsig", std::isnan(fabs(meas_ip3d.significance())) ? 0 : fabs(meas_ip3d.significance())); fts.fill("jet_pfcand_trackjet_dist", std::isnan(-meas_jetdist.value()) ? 0 : -meas_jetdist.value()); @@ -684,6 +700,8 @@ void ParticleNetFeatureEvaluator::fillSVFeatures(DeepBoostedJetFeatures &fts, co GlobalVector jet_global_vec(jet.px(), jet.py(), jet.pz()); + float ip_sign = flip_ip_sign_ ? -1.f : 1.f; + for (const auto *sv : jetSVs) { fts.fill("sv_mask", 1); fts.fill("jet_sv_pt_log", std::isnan(std::log(sv->pt())) ? 0 : std::log(sv->pt())); @@ -700,12 +718,12 @@ void ParticleNetFeatureEvaluator::fillSVFeatures(DeepBoostedJetFeatures &fts, co VertexDistanceXY dxy; auto valxy = dxy.signedDistance(svtx, *pv_, jet_global_vec); - fts.fill("jet_sv_dxy", std::isnan(valxy.value()) ? 0 : valxy.value()); + fts.fill("jet_sv_dxy", ip_sign * (std::isnan(valxy.value()) ? 0 : valxy.value())); fts.fill("jet_sv_dxysig", std::isnan(fabs(valxy.significance())) ? 0 : fabs(valxy.significance())); VertexDistance3D d3d; auto val3d = d3d.signedDistance(svtx, *pv_, jet_global_vec); - fts.fill("jet_sv_d3d", std::isnan(val3d.value()) ? 0 : val3d.value()); + fts.fill("jet_sv_d3d", ip_sign * (std::isnan(val3d.value()) ? 0 : val3d.value())); fts.fill("jet_sv_d3dsig", std::isnan(fabs(val3d.significance())) ? 0 : fabs(val3d.significance())); } } @@ -734,12 +752,24 @@ void ParticleNetFeatureEvaluator::fillLostTrackFeatures(DeepBoostedJetFeatures & math::XYZPoint pv_ass_pos = pv_ass->position(); for (auto const <rack : jet_lost_tracks) { + const reco::Track *track = ltrack.bestTrack(); + + // only when computing the nagative tagger: remove charged candidates with high sip3d + if (flip_ip_sign_) { + reco::TransientTrack transientTrack = track_builder_->build(*track); + Measurement1D meas_ip3d = IPTools::signedImpactParameter3D(transientTrack, jet_ref_track_dir, *pv_).second; + if (!std::isnan(meas_ip3d.significance()) && meas_ip3d.significance() > max_sip3dsig_for_flip_) { + continue; + } + } + float ip_sign = flip_ip_sign_ ? -1.f : 1.f; + fts.fill("jet_losttrack_pt_log", std::isnan(std::log(ltrack.pt())) ? 0 : std::log(ltrack.pt())); fts.fill("jet_losttrack_eta", ltrack.eta()); fts.fill("jet_losttrack_charge", ltrack.charge()); fts.fill("jet_losttrack_frompv", ltrack.fromPV()); - fts.fill("jet_losttrack_dz", std::isnan(ltrack.dz(pv_ass_pos)) ? 0 : ltrack.dz(pv_ass_pos)); - fts.fill("jet_losttrack_dxy", std::isnan(ltrack.dxy(pv_ass_pos)) ? 0 : ltrack.dxy(pv_ass_pos)); + fts.fill("jet_losttrack_dz", ip_sign * (std::isnan(ltrack.dz(pv_ass_pos)) ? 0 : ltrack.dz(pv_ass_pos))); + fts.fill("jet_losttrack_dxy", ip_sign * (std::isnan(ltrack.dxy(pv_ass_pos)) ? 0 : ltrack.dxy(pv_ass_pos))); fts.fill("jet_losttrack_npixhits", ltrack.numberOfPixelHits()); fts.fill("jet_losttrack_nstriphits", ltrack.stripLayersWithMeasurement()); @@ -751,7 +781,6 @@ void ParticleNetFeatureEvaluator::fillLostTrackFeatures(DeepBoostedJetFeatures & ? 0 : reco::btau::etaRel(jet_dir, ltrack.momentum())); - const reco::Track *track = ltrack.bestTrack(); if (track) { fts.fill("jet_losttrack_track_chi2", track->normalizedChi2()); fts.fill("jet_losttrack_track_qual", track->qualityMask()); @@ -769,7 +798,7 @@ void ParticleNetFeatureEvaluator::fillLostTrackFeatures(DeepBoostedJetFeatures & Measurement1D meas_jetdist = IPTools::jetTrackDistance(transientTrack, jet_ref_track_dir, *pv_).second; Measurement1D meas_decayl = IPTools::signedDecayLength3D(transientTrack, jet_ref_track_dir, *pv_).second; - fts.fill("jet_losttrack_trackjet_d3d", std::isnan(meas_ip3d.value()) ? 0 : meas_ip3d.value()); + fts.fill("jet_losttrack_trackjet_d3d", ip_sign * (std::isnan(meas_ip3d.value()) ? 0 : meas_ip3d.value())); fts.fill("jet_losttrack_trackjet_d3dsig", std::isnan(fabs(meas_ip3d.significance())) ? 0 : fabs(meas_ip3d.significance())); fts.fill("jet_losttrack_trackjet_dist", std::isnan(-meas_jetdist.value()) ? 0 : -meas_jetdist.value()); diff --git a/RecoBTag/FeatureTools/plugins/ParticleTransformerAK4TagInfoProducer.cc b/RecoBTag/FeatureTools/plugins/ParticleTransformerAK4TagInfoProducer.cc index 64c50e7fdbbea..2507d14c79b74 100644 --- a/RecoBTag/FeatureTools/plugins/ParticleTransformerAK4TagInfoProducer.cc +++ b/RecoBTag/FeatureTools/plugins/ParticleTransformerAK4TagInfoProducer.cc @@ -78,6 +78,7 @@ class ParticleTransformerAK4TagInfoProducer : public edm::stream::EDProducer<> { const double jet_radius_; const double min_candidate_pt_; const bool flip_; + const double max_sip3dsig_for_flip_; const edm::EDGetTokenT> jet_token_; const edm::EDGetTokenT vtx_token_; @@ -105,6 +106,7 @@ ParticleTransformerAK4TagInfoProducer::ParticleTransformerAK4TagInfoProducer(con : jet_radius_(iConfig.getParameter("jet_radius")), min_candidate_pt_(iConfig.getParameter("min_candidate_pt")), flip_(iConfig.getParameter("flip")), + max_sip3dsig_for_flip_(iConfig.getParameter("max_sip3dsig_for_flip")), jet_token_(consumes>(iConfig.getParameter("jets"))), vtx_token_(consumes(iConfig.getParameter("vertices"))), sv_token_(consumes(iConfig.getParameter("secondary_vertices"))), @@ -150,6 +152,7 @@ void ParticleTransformerAK4TagInfoProducer::fillDescriptions(edm::ConfigurationD desc.add("jet_radius", 0.4); desc.add("min_candidate_pt", 0.95); desc.add("flip", false); + desc.add("max_sip3dsig_for_flip", 99999); desc.add("vertices", edm::InputTag("offlinePrimaryVertices")); desc.add("puppi_value_map", edm::InputTag("puppi")); desc.add("secondary_vertices", edm::InputTag("inclusiveCandidateSecondaryVertices")); @@ -350,7 +353,9 @@ void ParticleTransformerAK4TagInfoProducer::produce(edm::Event& iEvent, const ed // get cached track info auto& trackinfo = trackinfos.at(i); - + if (flip_ && (trackinfo.getTrackSip3dSig() > max_sip3dsig_for_flip_)) { + continue; + } // get_ref to vector element auto& c_pf_features = features.c_pf_features.at(entry); // fill feature structure diff --git a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py index dc3a8f746dfc1..e1ce1914c2d8d 100644 --- a/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfParticleNetFromMiniAODAK4_cff.py @@ -163,3 +163,29 @@ _pfParticleNetFromMiniAODAK4CHSForwardJetTagsAll = _pfParticleNetFromMiniAODAK4CHSForwardJetTagsProbs + _pfParticleNetFromMiniAODAK4CHSForwardJetTagsMetaDiscr _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsAll = _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs + _pfParticleNetFromMiniAODAK4PuppiCentralJetTagsMetaDiscr _pfParticleNetFromMiniAODAK4PuppiForwardJetTagsAll = _pfParticleNetFromMiniAODAK4PuppiForwardJetTagsProbs + _pfParticleNetFromMiniAODAK4PuppiForwardJetTagsMetaDiscr + + +# === Negative tags === +pfNegativeParticleNetFromMiniAODAK4CHSCentralTagInfos = pfParticleNetFromMiniAODAK4CHSCentralTagInfos.clone( + flip_ip_sign = True, + max_sip3dsig_for_flip = 10, + secondary_vertices = 'inclusiveCandidateNegativeSecondaryVertices', +) +pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos = pfParticleNetFromMiniAODAK4PuppiCentralTagInfos.clone( + flip_ip_sign = True, + max_sip3dsig_for_flip = 10, + secondary_vertices = 'inclusiveCandidateNegativeSecondaryVertices', +) + +pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTags = pfParticleNetFromMiniAODAK4CHSCentralJetTags.clone( + src = 'pfNegativeParticleNetFromMiniAODAK4CHSCentralTagInfos', +) +pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags = pfParticleNetFromMiniAODAK4PuppiCentralJetTags.clone( + src = 'pfNegativeParticleNetFromMiniAODAK4PuppiCentralTagInfos', +) + +# probs +_pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTagsProbs = ['pfNegativeParticleNetFromMiniAODAK4CHSCentralJetTags:' + flav_name + for flav_name in pfParticleNetFromMiniAODAK4CHSCentralJetTags.flav_names] +_pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTagsProbs = ['pfNegativeParticleNetFromMiniAODAK4PuppiCentralJetTags:' + flav_name + for flav_name in pfParticleNetFromMiniAODAK4PuppiCentralJetTags.flav_names] diff --git a/RecoBTag/ONNXRuntime/python/pfParticleTransformerAK4_cff.py b/RecoBTag/ONNXRuntime/python/pfParticleTransformerAK4_cff.py index 0fb1c8ceac050..9df64c14f3406 100644 --- a/RecoBTag/ONNXRuntime/python/pfParticleTransformerAK4_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfParticleTransformerAK4_cff.py @@ -27,3 +27,16 @@ pfParticleTransformerAK4FromMiniAODTask = cms.Task(pfParticleTransformerAK4TagInfos, pfParticleTransformerAK4JetTags, pfParticleTransformerAK4DiscriminatorsJetTags) + +# === Negative tags === +pfNegativeParticleTransformerAK4TagInfos = pfParticleTransformerAK4TagInfos.clone( + flip = True, + secondary_vertices = 'inclusiveCandidateNegativeSecondaryVertices', +) +pfNegativeParticleTransformerAK4JetTags = pfParticleTransformerAK4JetTags.clone( + src = 'pfNegativeParticleTransformerAK4TagInfos', +) + +# probs +_pfNegativeParticleTransformerAK4JetTagsProbs = ['pfNegativeParticleTransformerAK4JetTags:' + flav_name + for flav_name in pfParticleTransformerAK4JetTags.flav_names]