diff --git a/PhysicsTools/NanoAOD/plugins/SimpleJetConstituentTableProducer.cc b/PhysicsTools/NanoAOD/plugins/SimpleJetConstituentTableProducer.cc new file mode 100644 index 0000000000000..05565a483a912 --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/SimpleJetConstituentTableProducer.cc @@ -0,0 +1,136 @@ +#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/PatCandidates/interface/Jet.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "DataFormats/PatCandidates/interface/PackedGenParticle.h" + +#include "DataFormats/Candidate/interface/CandidateFwd.h" + +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" +#include "DataFormats/NanoAOD/interface/FlatTable.h" + +template +class SimpleJetConstituentTableProducer : public edm::stream::EDProducer<> { +public: + explicit SimpleJetConstituentTableProducer(const edm::ParameterSet &); + ~SimpleJetConstituentTableProducer() override; + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + +private: + void produce(edm::Event &, const edm::EventSetup &) override; + + const std::string name_; + const std::string candIdxName_; + const std::string candIdxDoc_; + + edm::EDGetTokenT> jet_token_; + edm::EDGetTokenT cand_token_; + + const StringCutObjectSelector jetCut_; + + edm::Handle cands_; +}; + +// +// constructors and destructor +// +template +SimpleJetConstituentTableProducer::SimpleJetConstituentTableProducer(const edm::ParameterSet &iConfig) + : name_(iConfig.getParameter("name")), + candIdxName_(iConfig.getParameter("candIdxName")), + candIdxDoc_(iConfig.getParameter("candIdxDoc")), + jet_token_(consumes>(iConfig.getParameter("jets"))), + cand_token_(consumes(iConfig.getParameter("candidates"))), + jetCut_(iConfig.getParameter("jetCut")) { + produces(name_); + produces>(); +} + +template +SimpleJetConstituentTableProducer::~SimpleJetConstituentTableProducer() {} + +template +void SimpleJetConstituentTableProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + // elements in all these collections must have the same order! + auto outCands = std::make_unique>(); + + auto jets = iEvent.getHandle(jet_token_); + + iEvent.getByToken(cand_token_, cands_); + auto candPtrs = cands_->ptrs(); + + // + // First, select jets + // + std::vector jetsPassCut; + for (unsigned jetIdx = 0; jetIdx < jets->size(); ++jetIdx) { + const auto &jet = jets->at(jetIdx); + if (!jetCut_(jet)) + continue; + jetsPassCut.push_back(jets->at(jetIdx)); + } + + // + // Then loop over selected jets + // + std::vector parentJetIdx; + std::vector candIdx; + for (unsigned jetIdx = 0; jetIdx < jetsPassCut.size(); ++jetIdx) { + const auto &jet = jetsPassCut.at(jetIdx); + + // + // Loop over jet constituents + // + std::vector const &daughters = jet.daughterPtrVector(); + for (const auto &cand : daughters) { + auto candInNewList = std::find(candPtrs.begin(), candPtrs.end(), cand); + if (candInNewList == candPtrs.end()) { + continue; + } + outCands->push_back(cand); + parentJetIdx.push_back(jetIdx); + candIdx.push_back(candInNewList - candPtrs.begin()); + } + } // 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(candIdxName_, candIdx, candIdxDoc_); + + std::string parentJetIdxName("jetIdx"); + std::string parentJetIdxDoc("Index of the parent jet"); + if constexpr (std::is_same::value) { + parentJetIdxName = "genJetIdx"; + parentJetIdxDoc = "Index of the parent gen jet"; + } + candTable->addColumn(parentJetIdxName, parentJetIdx, parentJetIdxDoc); + + iEvent.put(std::move(candTable), name_); + iEvent.put(std::move(outCands)); +} + +template +void SimpleJetConstituentTableProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.add("name", "FatJetPFCand"); + desc.add("candIdxName", "PFCandIdx"); + desc.add("candIdxDoc", "Index in PFCand table"); + desc.add("jets", edm::InputTag("finalJetsAK8")); + desc.add("candidates", edm::InputTag("packedPFCandidates")); + desc.add("jetCut", ""); + descriptions.addWithDefaultLabel(desc); +} + +typedef SimpleJetConstituentTableProducer SimplePatJetConstituentTableProducer; +typedef SimpleJetConstituentTableProducer SimpleGenJetConstituentTableProducer; + +DEFINE_FWK_MODULE(SimplePatJetConstituentTableProducer); +DEFINE_FWK_MODULE(SimpleGenJetConstituentTableProducer); \ No newline at end of file diff --git a/PhysicsTools/NanoAOD/python/jetsAK8_cff.py b/PhysicsTools/NanoAOD/python/jetsAK8_cff.py index 7915baaf4dafd..1829fdd92bf51 100644 --- a/PhysicsTools/NanoAOD/python/jetsAK8_cff.py +++ b/PhysicsTools/NanoAOD/python/jetsAK8_cff.py @@ -317,10 +317,50 @@ def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubl fatJetTable.variables.pt.precision=10 subJetTable.variables.pt.precision=10 +############################################################## +# AK8 constituents +############################################################### +finalJetsAK8PFConstituents = cms.EDProducer("PatJetConstituentPtrSelector", + src = fatJetTable.src, + cut = cms.string("abs(eta) <= 2.5") +) + +finalJetsPFConstituents = cms.EDProducer("PackedCandidatePtrMerger", + src = cms.VInputTag(cms.InputTag("finalJetsAK8PFConstituents", "constituents")), + skipNulls = cms.bool(True), + warnOnSkip = cms.bool(True) +) + +pfCandidatesTable = cms.EDProducer("SimplePATCandidateFlatTableProducer", + src = cms.InputTag("finalJetsPFConstituents"), + cut = cms.string(""), + name = cms.string("PFCand"), + doc = cms.string("PF candidate constituents of AK8 puppi jets (FatJet) with |eta| <= 2.5."), + singleton = cms.bool(False), + extension = cms.bool(False), + variables = cms.PSet( + pt = Var("pt * puppiWeight()", float, doc="Puppi-weighted pt", precision=10), + mass = Var("mass * puppiWeight()", float, doc="Puppi-weighted mass", precision=10), + eta = Var("eta", float, precision=12), + phi = Var("phi", float, precision=12), + pdgId = Var("pdgId", int, doc="PF candidate type (+/-211 = ChgHad, 130 = NeuHad, 22 = Photon, +/-11 = Electron, +/-13 = Muon, 1 = HFHad, 2 = HFEM)") + ) +) + +finalJetsAK8ConstituentsTable = cms.EDProducer("SimplePatJetConstituentTableProducer", + name = cms.string(fatJetTable.name.value()+"PFCand"), + candIdxName = cms.string("PFCandIdx"), + candIdxDoc = cms.string("Index in the PFCand table"), + jets = fatJetTable.src, + candidates = pfCandidatesTable.src, + jetCut = fatJetTable.cut +) + jetAK8UserDataTask = cms.Task(tightJetIdAK8,tightJetIdLepVetoAK8) -jetAK8Task = cms.Task(jetCorrFactorsAK8,updatedJetsAK8,jetAK8UserDataTask,updatedJetsAK8WithUserData,finalJetsAK8) +jetAK8Task = cms.Task(jetCorrFactorsAK8,updatedJetsAK8,jetAK8UserDataTask,updatedJetsAK8WithUserData,finalJetsAK8,finalJetsAK8PFConstituents,finalJetsPFConstituents) #after lepton collections have been run jetAK8LepTask = cms.Task(lepInAK8JetVars) -jetAK8TablesTask = cms.Task(fatJetTable,subJetTable) +jetAK8TablesTask = cms.Task(fatJetTable,subJetTable,pfCandidatesTable,finalJetsAK8ConstituentsTable) + diff --git a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py index 294156824b2ec..eb4a6b89945ae 100644 --- a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py +++ b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py @@ -240,6 +240,17 @@ Plot1D('tau4', 'tau4', 20, 0, 1, 'Nsubjettiness (4 axis)'), ) ), + PFCand = cms.PSet( + sels = cms.PSet(), + plots = cms.VPSet( + Count1D('_size', 10, 0, 100, 'PF candidates'), + Plot1D('pt', 'pt', 20, 0, 50, 'Puppi-weighted pt'), + Plot1D('eta', 'eta', 20, -4, 4., 'eta'), + Plot1D('phi', 'phi', 20, -3.14159, 3.14159, 'phi'), + Plot1D('mass', 'mass', 10, 0, 1., 'Puppi-weighted mass'), + Plot1D('pdgId', 'pdgId', 44, -220, 220, 'PF candidate type (+/-211 = ChgHad, 130 = NeuHad, 22 = Photon, +/-11 = Electron, +/-13 = Muon, 1 = HFHad, 2 = HFEM)'), + ) + ), Flag = cms.PSet( sels = cms.PSet(), plots = cms.VPSet( diff --git a/PhysicsTools/PatAlgos/plugins/PATObjectSelector.cc b/PhysicsTools/PatAlgos/plugins/PATObjectSelector.cc index 39a35cc98b4b0..854f3c558e2a2 100644 --- a/PhysicsTools/PatAlgos/plugins/PATObjectSelector.cc +++ b/PhysicsTools/PatAlgos/plugins/PATObjectSelector.cc @@ -3,6 +3,7 @@ #include "CommonTools/UtilAlgos/interface/SingleObjectSelector.h" #include "CommonTools/UtilAlgos/interface/StringCutObjectSelector.h" #include "DataFormats/Common/interface/RefVector.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" #include "DataFormats/PatCandidates/interface/CompositeCandidate.h" #include "DataFormats/PatCandidates/interface/Electron.h" #include "DataFormats/PatCandidates/interface/GenericParticle.h" @@ -248,6 +249,12 @@ namespace pat { typedef SingleObjectSelector, StringCutObjectSelector> PATGenericParticleSelector; + typedef SingleObjectSelector< + std::vector, + StringCutObjectSelector // true => lazy parsing => get all methods of daughters + > + PATPackedCandidateSelector; + typedef SingleObjectSelector, StringCutObjectSelector, edm::RefVector>> @@ -296,6 +303,7 @@ DEFINE_FWK_MODULE(PATPFParticleSelector); DEFINE_FWK_MODULE(PATCompositeCandidateSelector); DEFINE_FWK_MODULE(PATTriggerObjectStandAloneSelector); DEFINE_FWK_MODULE(PATGenericParticleSelector); +DEFINE_FWK_MODULE(PATPackedCandidateSelector); DEFINE_FWK_MODULE(PATElectronRefSelector); DEFINE_FWK_MODULE(PATMuonRefSelector);