diff --git a/DQMOffline/Trigger/plugins/BuildFile.xml b/DQMOffline/Trigger/plugins/BuildFile.xml index 4e31ae6c25743..25abaa9e8463f 100644 --- a/DQMOffline/Trigger/plugins/BuildFile.xml +++ b/DQMOffline/Trigger/plugins/BuildFile.xml @@ -13,6 +13,7 @@ + diff --git a/DQMOffline/Trigger/plugins/ParticleNetJetTagMonitor.cc b/DQMOffline/Trigger/plugins/ParticleNetJetTagMonitor.cc new file mode 100644 index 0000000000000..5816bb1bb629c --- /dev/null +++ b/DQMOffline/Trigger/plugins/ParticleNetJetTagMonitor.cc @@ -0,0 +1,1110 @@ +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" +#include "CommonTools/TriggerUtils/interface/GenericTriggerEventFlag.h" +#include "CommonTools/CandUtils/interface/AddFourMomenta.h" + +#include "DataFormats/Math/interface/deltaR.h" +#include "DataFormats/Common/interface/ValueMap.h" +#include "DataFormats/VertexReco/interface/VertexFwd.h" +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/MuonReco/interface/MuonFwd.h" +#include "DataFormats/GsfTrackReco/interface/GsfTrack.h" +#include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h" +#include "DataFormats/JetReco/interface/PFJet.h" +#include "DataFormats/JetReco/interface/PFJetCollection.h" +#include "DataFormats/METReco/interface/PFMET.h" +#include "DataFormats/METReco/interface/PFMETCollection.h" +#include "DataFormats/BTauReco/interface/JetTag.h" +#include "DataFormats/Candidate/interface/CompositeCandidate.h" +#include "DataFormats/Candidate/interface/CompositeCandidateFwd.h" +#include "DataFormats/HLTReco/interface/TriggerEvent.h" +#include "DataFormats/Common/interface/TriggerResults.h" +#include "DataFormats/BTauReco/interface/ShallowTagInfo.h" +#include "DataFormats/Math/interface/LorentzVector.h" + +#include "DQMServices/Core/interface/DQMStore.h" +#include "DQMServices/Core/interface/DQMEDAnalyzer.h" +#include "DQMOffline/Trigger/plugins/TriggerDQMBase.h" + +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/Registry.h" +#include "FWCore/Utilities/interface/transform.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "JetMETCorrections/JetCorrector/interface/JetCorrector.h" + +#include +#include +#include +#include + +class ParticleNetJetTagMonitor : public DQMEDAnalyzer, public TriggerDQMBase { +public: + typedef dqm::reco::MonitorElement MonitorElement; + typedef dqm::reco::DQMStore DQMStore; + + ParticleNetJetTagMonitor(const edm::ParameterSet&); + ~ParticleNetJetTagMonitor() throw() override; + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +protected: + void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) override; + void analyze(edm::Event const& iEvent, edm::EventSetup const& iSetup) override; + + struct JetRefCompare { + inline bool operator()(const edm::RefToBase& j1, const edm::RefToBase& j2) const { + return (j1.id() < j2.id()) || ((j1.id() == j2.id()) && (j1.key() < j2.key())); + } + }; + +private: + // folder for output histograms + const std::string folderName_; + // validity of HLT paths required for the monitoring element + const bool requireValidHLTPaths_; + const bool requireHLTOfflineJetMatching_; + bool denHLTPathsAreValid_; + bool numHLTPathsAreValid_; + // input vertex collection + const edm::EDGetTokenT vertexToken_; + // input muon collection + const edm::EDGetTokenT muonToken_; + // input electron collection and IDs + const edm::EDGetTokenT electronToken_; + const edm::EDGetTokenT> tagElectronIDToken_; + const edm::EDGetTokenT> vetoElectronIDToken_; + // input jet collection + const edm::EDGetTokenT jetToken_; + // PNET score for offline and online jets + const edm::EDGetTokenT jetPNETScoreToken_; + const edm::EDGetTokenT jetPNETScoreHLTToken_; + // Collection and PNET score for ak4 b-tagging and HT if needed + const edm::EDGetTokenT jetForHTandBTagToken_; + const edm::EDGetTokenT jetPNETScoreForHTandBTagToken_; + // Jet soft drop value map + const edm::EDGetTokenT> jetSoftDropMassToken_; + // input MET collection + const edm::EDGetTokenT metToken_; + // JEC corrections + const edm::EDGetTokenT jecMCToken_; + const edm::EDGetTokenT jecDataToken_; + // trigger conditions for numerator and denominator + std::unique_ptr numGenericTriggerEvent_; + std::unique_ptr denGenericTriggerEvent_; + // Selectors for jets, electrons, muons, and lepton pairs + StringCutObjectSelector jetSelection_; + StringCutObjectSelector jetSelectionForHTandBTag_; + StringCutObjectSelector tagMuonSelection_; + StringCutObjectSelector tagElectronSelection_; + StringCutObjectSelector vetoMuonSelection_; + StringCutObjectSelector vetoElectronSelection_; + StringCutObjectSelector vertexSelection_; + StringCutObjectSelector dileptonSelection_; + StringCutObjectSelector metSelection_; + // Number of objects used in the event selection + const int njets_; + const int nbjets_; + const int ntagleptons_; + const int ntagmuons_; + const int ntagelectrons_; + const int nvetoleptons_; + const int nvetomuons_; + const int nvetoelectrons_; + const int nemupairs_; + const unsigned int ntrigobjecttomatch_; + // delta-R for cleaning and other parameters for the event selection + const double lepJetDeltaRmin_; + const double lepJetDeltaRminForHTandBTag_; + const double hltRecoDeltaRmax_; + const double maxLeptonDxyCut_; + const double maxLeptonDzCut_; + const double minPNETScoreCut_; + const double minPNETBTagCut_; + const double minSoftDropMassCut_; + const double maxSoftDropMassCut_; + // binning for efficiency histograms (up to two jets in the final state) + std::vector leptonPtBinning; + std::vector leptonEtaBinning; + std::vector diLeptonPtBinning; + std::vector diLeptonMassBinning; + std::vector HTBinning; + std::vector NjetBinning; + std::vector jet1PtBinning; + std::vector jet2PtBinning; + std::vector jet1EtaBinning; + std::vector jet2EtaBinning; + std::vector jet1PNETscoreBinning; + std::vector jet2PNETscoreBinning; + std::vector jet1PNETscoreTransBinning; + std::vector jet2PNETscoreTransBinning; + std::vector jet1PtBinning2d; + std::vector jet2PtBinning2d; + std::vector jet1EtaBinning2d; + std::vector jet2EtaBinning2d; + std::vector jet1PNETscoreBinning2d; + std::vector jet2PNETscoreBinning2d; + std::vector jet1PNETscoreTransBinning2d; + std::vector jet2PNETscoreTransBinning2d; + + // Selections imposed + MonitorElement* selectionFlow = nullptr; + // Efficiencies + ObjME muon_pt; + ObjME electron_pt; + ObjME muon_eta; + ObjME electron_eta; + ObjME dilepton_pt; + ObjME dilepton_mass; + ObjME njets; + ObjME nbjets; + ObjME ht; + ObjME jet1_pt; + ObjME jet2_pt; + ObjME jet1_eta; + ObjME jet2_eta; + ObjME jet1_pnetscore; + ObjME jet2_pnetscore; + ObjME jet1_pnetscore_trans; + ObjME jet2_pnetscore_trans; + ObjME mean_2j_pnetscore; + ObjME mean_2j_pnetscore_trans; + + ObjME jet1_pt_eta; + ObjME jet2_pt_eta; + ObjME jet1_pt_pnetscore1; + ObjME jet2_pt_pnetscore1; + ObjME jet1_pt_pnetscore2; + ObjME jet2_pt_pnetscore2; + ObjME jet1_pt_pnetscore1_trans; + ObjME jet2_pt_pnetscore1_trans; + ObjME jet1_pt_pnetscore2_trans; + ObjME jet2_pt_pnetscore2_trans; + ObjME jet1_pt_mean2pnetscore; + ObjME jet2_pt_mean2pnetscore; + ObjME jet1_pt_mean2pnetscore_trans; + ObjME jet2_pt_mean2pnetscore_trans; +}; + +ParticleNetJetTagMonitor::ParticleNetJetTagMonitor(const edm::ParameterSet& iConfig) + : folderName_(iConfig.getParameter("FolderName")), + requireValidHLTPaths_(iConfig.getParameter("requireValidHLTPaths")), + requireHLTOfflineJetMatching_(iConfig.getParameter("requireHLTOfflineJetMatching")), + denHLTPathsAreValid_(false), + numHLTPathsAreValid_(false), + vertexToken_(consumes(iConfig.getParameter("vertices"))), + muonToken_(consumes(iConfig.getParameter("muons"))), + electronToken_(consumes(iConfig.getParameter("electrons"))), + tagElectronIDToken_(consumes>(iConfig.getParameter("tagElectronID"))), + vetoElectronIDToken_(consumes>(iConfig.getParameter("vetoElectronID"))), + jetToken_(consumes(iConfig.getParameter("jets"))), + jetPNETScoreToken_(consumes(iConfig.getParameter("jetPNETScore"))), + jetPNETScoreHLTToken_(mayConsume(iConfig.getParameter("jetPNETScoreHLT"))), + jetForHTandBTagToken_(mayConsume(iConfig.getParameter("jetsForHTandBTag"))), + jetPNETScoreForHTandBTagToken_( + mayConsume(iConfig.getParameter("jetPNETScoreForHTandBTag"))), + jetSoftDropMassToken_(mayConsume>(iConfig.getParameter("jetSoftDropMass"))), + metToken_(consumes(iConfig.getParameter("met"))), + jecMCToken_(mayConsume(iConfig.getParameter("jecForMC"))), + jecDataToken_(mayConsume(iConfig.getParameter("jecForData"))), + numGenericTriggerEvent_(new GenericTriggerEventFlag( + iConfig.getParameter("numGenericTriggerEvent"), consumesCollector(), *this)), + denGenericTriggerEvent_(new GenericTriggerEventFlag( + iConfig.getParameter("denGenericTriggerEvent"), consumesCollector(), *this)), + jetSelection_(iConfig.getParameter("jetSelection")), + jetSelectionForHTandBTag_(iConfig.existsAs("jetSelectionForHTandBTag") + ? iConfig.getParameter("jetSelectionForHTandBTag") + : ""), + tagMuonSelection_(iConfig.getParameter("tagMuonSelection")), + tagElectronSelection_(iConfig.getParameter("tagElectronSelection")), + vetoMuonSelection_(iConfig.getParameter("vetoMuonSelection")), + vetoElectronSelection_(iConfig.getParameter("vetoElectronSelection")), + vertexSelection_(iConfig.getParameter("vertexSelection")), + dileptonSelection_(iConfig.getParameter("dileptonSelection")), + metSelection_(iConfig.getParameter("metSelection")), + njets_(iConfig.getParameter("njets")), + nbjets_(iConfig.getParameter("nbjets")), + ntagleptons_(iConfig.getParameter("ntagleptons")), + ntagmuons_(iConfig.getParameter("ntagmuons")), + ntagelectrons_(iConfig.getParameter("ntagelectrons")), + nvetoleptons_(iConfig.getParameter("nvetoleptons")), + nvetomuons_(iConfig.getParameter("nvetomuons")), + nvetoelectrons_(iConfig.getParameter("nvetoelectrons")), + nemupairs_(iConfig.getParameter("nemupairs")), + ntrigobjecttomatch_(iConfig.getParameter("ntrigobjecttomatch")), + lepJetDeltaRmin_(iConfig.getParameter("lepJetDeltaRmin")), + lepJetDeltaRminForHTandBTag_(iConfig.getParameter("lepJetDeltaRminForHTandBTag")), + hltRecoDeltaRmax_(iConfig.getParameter("hltRecoDeltaRmax")), + maxLeptonDxyCut_(iConfig.getParameter("maxLeptonDxyCut")), + maxLeptonDzCut_(iConfig.getParameter("maxLeptonDzCut")), + minPNETScoreCut_(iConfig.getParameter("minPNETScoreCut")), + minPNETBTagCut_(iConfig.getParameter("minPNETBTagCut")), + minSoftDropMassCut_(iConfig.getParameter("minSoftDropMassCut")), + maxSoftDropMassCut_(iConfig.getParameter("maxSoftDropMassCut")), + leptonPtBinning(iConfig.getParameter>("leptonPtBinning")), + leptonEtaBinning(iConfig.getParameter>("leptonEtaBinning")), + diLeptonMassBinning(iConfig.getParameter>("diLeptonMassBinning")), + HTBinning(iConfig.getParameter>("HTBinning")), + NjetBinning(iConfig.getParameter>("NjetBinning")), + jet1PtBinning(iConfig.getParameter>("jet1PtBinning")), + jet2PtBinning(iConfig.getParameter>("jet2PtBinning")), + jet1EtaBinning(iConfig.getParameter>("jet1EtaBinning")), + jet2EtaBinning(iConfig.getParameter>("jet2EtaBinning")), + jet1PNETscoreBinning(iConfig.getParameter>("jet1PNETscoreBinning")), + jet2PNETscoreBinning(iConfig.getParameter>("jet2PNETscoreBinning")), + jet1PNETscoreTransBinning(iConfig.getParameter>("jet1PNETscoreTransBinning")), + jet2PNETscoreTransBinning(iConfig.getParameter>("jet2PNETscoreTransBinning")), + jet1PtBinning2d(iConfig.getParameter>("jet1PtBinning2d")), + jet2PtBinning2d(iConfig.getParameter>("jet2PtBinning2d")), + jet1EtaBinning2d(iConfig.getParameter>("jet1EtaBinning2d")), + jet2EtaBinning2d(iConfig.getParameter>("jet2EtaBinning2d")), + jet1PNETscoreBinning2d(iConfig.getParameter>("jet1PNETscoreBinning2d")), + jet2PNETscoreBinning2d(iConfig.getParameter>("jet2PNETscoreBinning2d")), + jet1PNETscoreTransBinning2d(iConfig.getParameter>("jet1PNETscoreTransBinning2d")), + jet2PNETscoreTransBinning2d(iConfig.getParameter>("jet2PNETscoreTransBinning2d")) {} + +ParticleNetJetTagMonitor::~ParticleNetJetTagMonitor() throw() { + if (numGenericTriggerEvent_) + denGenericTriggerEvent_.reset(); + if (numGenericTriggerEvent_) + denGenericTriggerEvent_.reset(); +} + +void ParticleNetJetTagMonitor::bookHistograms(DQMStore::IBooker& ibooker, + edm::Run const& iRun, + edm::EventSetup const& iSetup) { + // Initialize the GenericTriggerEventFlag + if (denGenericTriggerEvent_ and denGenericTriggerEvent_->on()) + denGenericTriggerEvent_->initRun(iRun, iSetup); + if (numGenericTriggerEvent_ and numGenericTriggerEvent_->on()) + numGenericTriggerEvent_->initRun(iRun, iSetup); + + denHLTPathsAreValid_ = + (denGenericTriggerEvent_ && denGenericTriggerEvent_->on() && denGenericTriggerEvent_->allHLTPathsAreValid()); + numHLTPathsAreValid_ = + (numGenericTriggerEvent_ && numGenericTriggerEvent_->on() && numGenericTriggerEvent_->allHLTPathsAreValid()); + + if (requireValidHLTPaths_ && (!denHLTPathsAreValid_)) + return; + if (requireValidHLTPaths_ && (!numHLTPathsAreValid_)) + return; + + ibooker.setCurrentFolder(folderName_); + + selectionFlow = ibooker.book1D("selectionFlow", "selectionFlow", 17, 0, 17); + selectionFlow->setBinLabel(1, "all"); + selectionFlow->setBinLabel(2, "denTrigSel"); + selectionFlow->setBinLabel(3, "collecttionSel"); + selectionFlow->setBinLabel(4, "vtxSel"); + selectionFlow->setBinLabel(5, "tagMuSel"); + selectionFlow->setBinLabel(6, "vetoMuSel"); + selectionFlow->setBinLabel(7, "tagEleSel"); + selectionFlow->setBinLabel(8, "vetoEleSel"); + selectionFlow->setBinLabel(9, "tagLepSel"); + selectionFlow->setBinLabel(10, "vetoLepSel"); + selectionFlow->setBinLabel(11, "diLepSel"); + selectionFlow->setBinLabel(12, "btagSel"); + selectionFlow->setBinLabel(13, "METSel"); + selectionFlow->setBinLabel(14, "jetSel"); + selectionFlow->setBinLabel(15, "pnetScoreSel"); + selectionFlow->setBinLabel(16, "trigMatchSel"); + selectionFlow->setBinLabel(17, "numTrigSel"); + + if (!NjetBinning.empty()) { + bookME(ibooker, njets, "njets", "n-jets", NjetBinning); + setMETitle(njets, "number of jets", "Entries"); + bookME(ibooker, nbjets, "nbjets", "b-jets", NjetBinning); + setMETitle(nbjets, "number of b-jets", "Entries"); + } + if (!HTBinning.empty()) { + bookME(ibooker, ht, "ht", "HT", HTBinning); + setMETitle(ht, "H_{T}", "Entries"); + } + + if (!leptonPtBinning.empty()) { + bookME(ibooker, muon_pt, "muon_pt", "muon p_{T}", leptonPtBinning); + setMETitle(muon_pt, "p_{T}(#mu)", "Entries"); + bookME(ibooker, electron_pt, "electron_pt", "electron p_{T}", leptonPtBinning); + setMETitle(electron_pt, "p_{T}(ele)", "Entries"); + } + if (!leptonEtaBinning.empty()) { + bookME(ibooker, muon_eta, "muon_eta", "muon #eta", leptonEtaBinning); + setMETitle(muon_eta, "#eta(#mu)", "Entries"); + bookME(ibooker, electron_eta, "electron_eta", "electron #eta", leptonEtaBinning); + setMETitle(electron_eta, "#eta(ele)", "Entries"); + } + if (!diLeptonPtBinning.empty()) { + bookME(ibooker, dilepton_pt, "dilepton_pt", "dilepton p_{T}", diLeptonPtBinning); + setMETitle(dilepton_pt, "p_{T}(ll)", "Entries"); + } + if (!diLeptonMassBinning.empty()) { + bookME(ibooker, dilepton_mass, "dilepton_mass", "dilepton mass", diLeptonMassBinning); + setMETitle(dilepton_mass, "m(ll)", "Entries"); + } + + if (!jet1PtBinning.empty()) { + bookME(ibooker, jet1_pt, "jet1_pt", "jet1 p_{T}", jet1PtBinning); + setMETitle(jet1_pt, "p_{T}(j1)", "Entries"); + } + if (!jet2PtBinning.empty()) { + bookME(ibooker, jet2_pt, "jet2_pt", "jet2 p_{T}", jet2PtBinning); + setMETitle(jet2_pt, "p_{T}(j2)", "Entries"); + } + if (!jet1EtaBinning.empty()) { + bookME(ibooker, jet1_eta, "jet1_eta", "jet1 #eta", jet1EtaBinning); + setMETitle(jet1_eta, "#eta(j1)", "Entries"); + } + if (!jet2EtaBinning.empty()) { + bookME(ibooker, jet2_eta, "jet2_eta", "jet2 #eta", jet2EtaBinning); + setMETitle(jet2_eta, "#eta(j2)", "Entries"); + } + if (!jet1PNETscoreBinning.empty()) { + bookME(ibooker, jet1_pnetscore, "jet1_pnetscore", "jet lead PNET-score", jet1PNETscoreBinning); + setMETitle(jet1_pnetscore, "Lead PNET-score", "Entries"); + } + + if (!jet2PNETscoreBinning.empty()) { + bookME(ibooker, jet2_pnetscore, "jet2_pnetscore", "jet train PNET-score", jet2PNETscoreBinning); + setMETitle(jet2_pnetscore, "Trail PNET-score", "Entries"); + } + if (!jet1PNETscoreBinning.empty() and !jet2PNETscoreBinning.empty()) { + bookME(ibooker, mean_2j_pnetscore, "mean_2j_pnetscore", "mean 2jet PNET-score", jet1PNETscoreBinning); + setMETitle(mean_2j_pnetscore, "Mean(PNET-score)", "Entries"); + } + + if (!jet1PNETscoreTransBinning.empty()) { + bookME(ibooker, + jet1_pnetscore_trans, + "jet1_pnetscore_trans", + "jet lead PNET-score transformed", + jet1PNETscoreTransBinning); + setMETitle(jet1_pnetscore_trans, "Lead atanh(PNET-score)", "Entries"); + } + if (!jet2PNETscoreTransBinning.empty()) { + bookME(ibooker, + jet2_pnetscore_trans, + "jet2_pnetscore_trans", + "jet trail PNET-score transformed", + jet2PNETscoreTransBinning); + setMETitle(jet2_pnetscore_trans, "Trail atanh(PNET-score)", "Entries"); + } + if (!jet1PNETscoreTransBinning.empty() and !jet2PNETscoreTransBinning.empty()) { + bookME(ibooker, + mean_2j_pnetscore_trans, + "mean_2j_pnetscore_trans", + "mean 2jet PNET-score transformed", + jet1PNETscoreTransBinning); + setMETitle(mean_2j_pnetscore_trans, "atanh(Mean(PNET-score))", "Entries"); + } + + // 2D efficiencies + if (!jet1PtBinning2d.empty() and !jet1EtaBinning2d.empty()) { + bookME(ibooker, jet1_pt_eta, "jet1_pt_eta", "jet1 p_{T} vs #eta", jet1PtBinning2d, jet1EtaBinning2d); + setMETitle(jet1_pt_eta, "p_{T}(j1)", "#eta(j1)"); + } + if (!jet2PtBinning2d.empty() and !jet2EtaBinning2d.empty()) { + bookME(ibooker, jet2_pt_eta, "jet2_pt_eta", "jet2 p_{T} vs #eta", jet2PtBinning2d, jet2EtaBinning2d); + setMETitle(jet2_pt_eta, "p_{T}(j2)", "#eta(j2)"); + } + + if (!jet1PtBinning2d.empty() and !jet1PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet1_pt_pnetscore1, + "jet1_pt_pnetscore1", + "jet1 p{T} vs lead PNET-score", + jet1PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet1_pt_pnetscore1, "p_{T}(j1)", "Lead PNET-score"); + } + if (!jet1PtBinning2d.empty() and !jet2PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet1_pt_pnetscore2, + "jet1_pt_pnetscore2", + "jet1 p_{T} vs trail PNET-score", + jet1PtBinning2d, + jet2PNETscoreBinning2d); + setMETitle(jet1_pt_pnetscore2, "p_{T}(j1)", "Trail PNET-score"); + } + if (!jet1PtBinning2d.empty() and !jet1PNETscoreBinning2d.empty() and !jet2PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet1_pt_mean2pnetscore, + "jet1_pt_mean2pnetscore", + "jet1 p_{T} vs mean 2jet PNET-score", + jet1PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet1_pt_mean2pnetscore, "p_{T}(j1)", "Mean(PNET-score)"); + } + + if (!jet2PtBinning2d.empty() and !jet1PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet2_pt_pnetscore1, + "jet2_pt_pnetscore1", + "jet2 p_{T} vs lead PNET-score", + jet2PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet2_pt_pnetscore1, "p_{T}(j2)", "Lead PNET-score"); + } + if (!jet2PtBinning2d.empty() and !jet2PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet2_pt_pnetscore2, + "jet2_pt_pnetscore2", + "jet2 p_{T} vs trail PNET-score", + jet2PtBinning2d, + jet2PNETscoreBinning2d); + setMETitle(jet2_pt_pnetscore2, "p_{T}(j2)", "Trail PNET-score"); + } + if (!jet2PtBinning2d.empty() and !jet1PNETscoreBinning2d.empty() and !jet2PNETscoreBinning2d.empty()) { + bookME(ibooker, + jet2_pt_mean2pnetscore, + "jet2_pt_mean2pnetscore", + "jet2 p_{T} vs mean 2jet PNET-score", + jet2PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet2_pt_mean2pnetscore, "p_{T}(j2)", "Mean(PNET-score)"); + } + + if (!jet1PtBinning2d.empty() and !jet1PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet1_pt_pnetscore1_trans, + "jet1_pt_pnetscore1_trans", + "jet1 p_{T} vs lead PNET-score transformed", + jet1PtBinning2d, + jet1PNETscoreTransBinning2d); + setMETitle(jet1_pt_pnetscore1_trans, "p_{T}(j1)", "Lead atanh(PNET-score)"); + } + if (!jet1PtBinning2d.empty() and !jet2PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet1_pt_pnetscore2_trans, + "jet1_pt_pnetscore2_trans", + "jet1 p_{T} vs trail PNET-score transformed", + jet1PtBinning2d, + jet2PNETscoreTransBinning2d); + setMETitle(jet1_pt_pnetscore2_trans, "p_{T}(j1)", "Trail atanh(PNET-score)"); + } + if (!jet1PtBinning2d.empty() and !jet1PNETscoreTransBinning2d.empty() and !jet2PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet1_pt_mean2pnetscore_trans, + "jet1_pt_mean2pnetscore_trans", + "jet1 p_{T} vs mean 2jet PNET-score transformed", + jet1PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet1_pt_mean2pnetscore_trans, "p_{T}(j1)", "atanh(Mean(PNET-score))"); + } + + if (!jet2PtBinning2d.empty() and !jet1PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet2_pt_pnetscore1_trans, + "jet2_pt_pnetscore1_trans", + "jet2 p_{T} vs lead PNET-score transformed", + jet2PtBinning2d, + jet1PNETscoreTransBinning2d); + setMETitle(jet2_pt_pnetscore1_trans, "p_{T}(j2)", "Lead atanh(PNET-score)"); + } + if (!jet2PtBinning2d.empty() and !jet2PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet2_pt_pnetscore2_trans, + "jet2_pt_pnetscore2_trans", + "jet2 p_{T} vs trail PNET-score transformed", + jet2PtBinning2d, + jet2PNETscoreTransBinning2d); + setMETitle(jet2_pt_pnetscore2_trans, "p_{T}(j2)", "Trail atanh(PNET-score)"); + } + if (!jet2PtBinning2d.empty() and !jet1PNETscoreTransBinning2d.empty() and !jet2PNETscoreTransBinning2d.empty()) { + bookME(ibooker, + jet2_pt_mean2pnetscore_trans, + "jet2_pt_mean2pnetscore_trans", + "jet2 p_{T} vs mean 2jet PNET-score transformed", + jet2PtBinning2d, + jet1PNETscoreBinning2d); + setMETitle(jet2_pt_mean2pnetscore_trans, "p_{T}(j2)", "atanh(Mean(PNET-score))"); + } +} + +void ParticleNetJetTagMonitor::analyze(edm::Event const& iEvent, edm::EventSetup const& iSetup) { + // abort if triggers are not valid + if (requireValidHLTPaths_ and (!denHLTPathsAreValid_ or !numHLTPathsAreValid_)) + return; + + int selectionFlowStatus = 0; + selectionFlow->Fill(selectionFlowStatus); + + // Filter out events that don't pass the denominator trigger condition + if (denGenericTriggerEvent_->on() and !denGenericTriggerEvent_->accept(iEvent, iSetup)) + return; + + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // get all input collections + edm::Handle primaryVertices; + iEvent.getByToken(vertexToken_, primaryVertices); + if (!primaryVertices.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Invalid primary vertex collection, will skip the event"; + return; + } + + edm::Handle muonHandle; + iEvent.getByToken(muonToken_, muonHandle); + if (!muonHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Muon collection not valid, will skip the event \n"; + return; + } + + edm::Handle electronHandle; + iEvent.getByToken(electronToken_, electronHandle); + if (!electronHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Electron collection not valid, will skip the event \n"; + return; + } + + edm::Handle> tagEleIDHandle; + iEvent.getByToken(tagElectronIDToken_, tagEleIDHandle); + if (!tagEleIDHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Electron ID for tag not valid, will skip the event \n"; + return; + } + + edm::Handle> vetoEleIDHandle; + iEvent.getByToken(vetoElectronIDToken_, vetoEleIDHandle); + if (!vetoEleIDHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Electron ID for veto not valid, will skip the event \n"; + return; + } + + edm::Handle jetHandle; + iEvent.getByToken(jetToken_, jetHandle); + if (!jetHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Jet collection not valid, will skip the event \n"; + return; + } + + edm::Handle metHandle; + iEvent.getByToken(metToken_, metHandle); + if (!metHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "MET collection not valid, will skip the event \n"; + return; + } + + edm::Handle jetPNETScoreHandle; + iEvent.getByToken(jetPNETScoreToken_, jetPNETScoreHandle); + if (!jetPNETScoreHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "Jet PNET score collection not valid, will skip event \n"; + return; + } + const reco::JetTagCollection& jetPNETScore = *(jetPNETScoreHandle.product()); + + // Collections that are only imported when necessary and their validity determins the selection applied (different for ak4/ak8 workflows) + edm::Handle> jetSoftDropMassHandle; + iEvent.getByToken(jetSoftDropMassToken_, jetSoftDropMassHandle); + edm::Handle jetForHTandBTagHandle; + iEvent.getByToken(jetForHTandBTagToken_, jetForHTandBTagHandle); + edm::Handle jetPNETScoreForHTandBTagHandle; + iEvent.getByToken(jetPNETScoreForHTandBTagToken_, jetPNETScoreForHTandBTagHandle); + edm::Handle jecHandle; + if (iEvent.isRealData()) + iEvent.getByToken(jecDataToken_, jecHandle); + else + iEvent.getByToken(jecMCToken_, jecHandle); + + // Start the selection part + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // primary vertex selection + const reco::Vertex* pv = nullptr; + for (auto const& v : *primaryVertices) { + if (not vertexSelection_(v)) + continue; + pv = &v; + break; + } + + if (pv == nullptr) { + edm::LogWarning("ParticleNetJetTagMonitor") << "No good vertex found in the event --> skipped"; + return; + } + + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // Muon selection + std::vector tagMuons; + std::vector vetoMuons; + for (auto const& m : *muonHandle) { + if (tagMuonSelection_(m) and std::fabs(m.muonBestTrack()->dxy(pv->position())) <= maxLeptonDxyCut_ and + std::fabs(m.muonBestTrack()->dz(pv->position())) <= maxLeptonDzCut_) + tagMuons.push_back(m); + if (vetoMuonSelection_(m) and std::fabs(m.muonBestTrack()->dxy(pv->position())) <= maxLeptonDxyCut_ and + std::fabs(m.muonBestTrack()->dz(pv->position())) <= maxLeptonDzCut_) + vetoMuons.push_back(m); + } + + if (ntagmuons_ >= 0 and int(tagMuons.size()) != ntagmuons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + if (nvetomuons_ >= 0 and int(vetoMuons.size()) != nvetomuons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // electron selection + std::vector tagElectrons; + std::vector vetoElectrons; + for (size_t index = 0; index < electronHandle->size(); index++) { + const auto e = electronHandle->at(index); + if (tagElectronSelection_(e) and (*tagEleIDHandle)[reco::GsfElectronRef(electronHandle, index)] and + std::fabs(e.gsfTrack()->dxy(pv->position())) <= maxLeptonDxyCut_ and + std::fabs(e.gsfTrack()->dz(pv->position())) <= maxLeptonDzCut_) + tagElectrons.push_back(e); + if (vetoElectronSelection_(e) and (*vetoEleIDHandle)[reco::GsfElectronRef(electronHandle, index)] and + std::fabs(e.gsfTrack()->dxy(pv->position())) <= maxLeptonDxyCut_ and + std::fabs(e.gsfTrack()->dz(pv->position())) <= maxLeptonDzCut_) + vetoElectrons.push_back(e); + } + + if (ntagelectrons_ >= 0 and int(tagElectrons.size()) != ntagelectrons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + if (nvetoelectrons_ >= 0 and int(vetoElectrons.size()) != nvetoelectrons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // Overall number of leptons for flavor composition + if (ntagleptons_ >= 0 and int(tagElectrons.size() + tagMuons.size()) != ntagleptons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + if (nvetoleptons_ >= 0 and int(vetoElectrons.size() + vetoMuons.size()) != nvetoleptons_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // Dilepton pairs + std::vector emuPairs; + for (auto const& muon : tagMuons) { + for (auto const& electron : tagElectrons) { + reco::CompositeCandidate emuPair("emPair"); + emuPair.addDaughter(*dynamic_cast(&muon), "lep1"); + emuPair.addDaughter(*dynamic_cast(&electron), "lep2"); + AddFourMomenta addp4; + addp4.set(emuPair); + if (dileptonSelection_(emuPair)) + emuPairs.push_back(emuPair); + } + } + + if (nemupairs_ >= 0 and int(emuPairs.size()) != nemupairs_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // For b-tagging requriements / content used in AK8 PNET efficiency measurement in semi-leptonic ttbar + float hT = 0; + std::vector jetsBTagged; + if (jetForHTandBTagHandle.isValid()) { + const reco::JetTagCollection& jetPNETScoreForHTandBTag = *(jetPNETScoreForHTandBTagHandle.product()); + for (auto const& j : *jetForHTandBTagHandle) { + if (not jetSelectionForHTandBTag_(j)) + continue; + float minDR_jm = 1000; + for (size_t imu = 0; imu < vetoMuons.size(); imu++) { + float dR = reco::deltaR(vetoMuons.at(imu).p4(), j.p4()); + if (dR < minDR_jm) + minDR_jm = dR; + } + if (minDR_jm < lepJetDeltaRminForHTandBTag_) + continue; + float minDR_je = 1000; + for (size_t iel = 0; iel < vetoElectrons.size(); iel++) { + float dR = reco::deltaR(vetoElectrons.at(iel).p4(), j.p4()); + if (dR < minDR_je) + minDR_je = dR; + } + if (minDR_je < lepJetDeltaRminForHTandBTag_) + continue; + hT += j.pt(); + auto const& jref = reco::JetBaseRef(reco::PFJetRef(jetForHTandBTagHandle, &j - &(*jetForHTandBTagHandle)[0])); + if (jetPNETScoreForHTandBTag[jref] < minPNETBTagCut_) + continue; + jetsBTagged.push_back(j.p4()); + } + if (int(jetsBTagged.size()) < nbjets_) + return; + } + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // MET selectiona + reco::PFMET pfMet = metHandle->front(); + if (!metSelection_(pfMet)) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // Jet selection + std::vector selectedJets; + std::vector jetPtCorrectedValues; + std::vector jetPNETScoreValues; + + for (auto const& j : *jetHandle) { + // apply or not jecs + float jec = 1; + if (jecHandle.isValid()) + jec = jecHandle->correction(j); + auto jet = *(j.clone()); + jet.setP4(j.p4() * jec); + + // Basic selection + if (not jetSelection_(jet)) + continue; + // SoftDrop mass + if (jetSoftDropMassHandle.isValid()) { + auto const& massSD = (*jetSoftDropMassHandle)[reco::PFJetRef(jetHandle, &j - &(*jetHandle)[0])]; + if (massSD < minSoftDropMassCut_ or massSD > maxSoftDropMassCut_) + continue; + } + // cleaning with leptons + float minDR_jm = 1000; + for (size_t imu = 0; imu < vetoMuons.size(); imu++) { + float dR = reco::deltaR(vetoMuons.at(imu).p4(), jet.p4()); + if (dR < minDR_jm) + minDR_jm = dR; + } + if (minDR_jm < lepJetDeltaRmin_) + continue; + float minDR_je = 1000; + for (size_t iel = 0; iel < vetoElectrons.size(); iel++) { + float dR = reco::deltaR(vetoElectrons.at(iel).p4(), jet.p4()); + if (dR < minDR_je) + minDR_je = dR; + } + if (minDR_je < lepJetDeltaRmin_) + continue; + // Compute HT + if (not jetForHTandBTagHandle.isValid()) + hT += jet.pt(); + // selected jets, pT values (post-correction), and PNET score + selectedJets.push_back(jet); + jetPtCorrectedValues.push_back(jet.pt()); + auto jref = reco::JetBaseRef(reco::PFJetRef(jetHandle, &j - &(*jetHandle)[0])); + if (jetPNETScore[jref]) + jetPNETScoreValues.push_back(jetPNETScore[jref]); + else + jetPNETScoreValues.push_back(0); + } + if (njets_ >= 0 and int(selectedJets.size()) < njets_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // count number of jets over minPNETScoreCut + if (std::count_if(jetPNETScoreValues.begin(), jetPNETScoreValues.end(), [&](float score) { + return score > minPNETScoreCut_; + }) < njets_) + return; + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // sort descending corrected pt order only if jecHandle is valid otherwise keep the current ordering + std::vector jetPtSortedIndices(jetPtCorrectedValues.size()); + std::iota(jetPtSortedIndices.begin(), jetPtSortedIndices.end(), 0); + if (jecHandle.isValid()) { + std::sort(jetPtSortedIndices.begin(), jetPtSortedIndices.end(), [&](const size_t& i1, const size_t& i2) { + return jetPtCorrectedValues[i1] > jetPtCorrectedValues[i2]; + }); + } + + // sort descending PNET score order + std::vector jetPNETScoreSortedIndices(jetPNETScoreValues.size()); + std::iota(jetPNETScoreSortedIndices.begin(), jetPNETScoreSortedIndices.end(), 0); + std::sort(jetPNETScoreSortedIndices.begin(), + jetPNETScoreSortedIndices.end(), + [&](const size_t& i1, const size_t& i2) { return jetPNETScoreValues[i1] > jetPNETScoreValues[i2]; }); + + // trigger object matching (for jets) + if (requireHLTOfflineJetMatching_) { + edm::Handle jetPNETScoreHLTHandle; + iEvent.getByToken(jetPNETScoreHLTToken_, jetPNETScoreHLTHandle); + if (!jetPNETScoreHLTHandle.isValid()) { + edm::LogWarning("ParticleNetJetTagMonitor") << "HLT Jet tags collection not valid, will skip event \n"; + return; + } + + std::vector jetPNETScoreValuesHLT; + std::vector jetHLTRefs; + for (const auto& jtag : *jetPNETScoreHLTHandle) { + jetPNETScoreValuesHLT.push_back(jtag.second); + jetHLTRefs.push_back(jtag.first); + } + + // sort in PNET score + std::vector jetPNETScoreSortedIndicesHLT(jetPNETScoreValuesHLT.size()); + std::iota(jetPNETScoreSortedIndicesHLT.begin(), jetPNETScoreSortedIndicesHLT.end(), 0); + std::sort( + jetPNETScoreSortedIndicesHLT.begin(), + jetPNETScoreSortedIndicesHLT.end(), + [&](const size_t& i1, const size_t& i2) { return jetPNETScoreValuesHLT[i1] > jetPNETScoreValuesHLT[i2]; }); + + // match reco and hlt objects considering only the first ntrigobjecttomatch jets for both reco and HLT. Each of them must be matched + std::vector matched_obj; + for (size_t jreco = 0; jreco < ntrigobjecttomatch_; jreco++) { + if (jreco >= jetPNETScoreSortedIndices.size()) + break; + float minDR = 1000; + int match_index = -1; + for (size_t jhlt = 0; jhlt < ntrigobjecttomatch_; jhlt++) { + if (jhlt >= jetPNETScoreSortedIndicesHLT.size()) + break; + if (std::find(matched_obj.begin(), matched_obj.end(), jhlt) != matched_obj.end()) + continue; + float dR = reco::deltaR(selectedJets[jetPNETScoreSortedIndices.at(jreco)].p4(), + jetHLTRefs.at(jetPNETScoreSortedIndicesHLT.at(jhlt))->p4()); + if (dR < hltRecoDeltaRmax_ and dR < minDR){ + match_index = jhlt; + minDR = dR; + } + } + if (match_index >= 0) + matched_obj.push_back(match_index); + } + if (matched_obj.size() != ntrigobjecttomatch_) + return; + } + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + + // numerator condition + const bool trg_passed = (numGenericTriggerEvent_->on() and numGenericTriggerEvent_->accept(iEvent, iSetup)); + if (trg_passed) { + selectionFlowStatus++; + selectionFlow->Fill(selectionFlowStatus); + } + + // Fill histograms for efficiency + if (njets.numerator != nullptr) + njets.fill(trg_passed, selectedJets.size()); + if (nbjets.numerator != nullptr) + nbjets.fill(trg_passed, jetsBTagged.size()); + if (ht.numerator != nullptr) + ht.fill(trg_passed, hT); + if (muon_pt.numerator != nullptr) + muon_pt.fill(trg_passed, (!tagMuons.empty()) ? tagMuons.front().pt() : 0); + if (muon_eta.numerator != nullptr) + muon_eta.fill(trg_passed, (!tagMuons.empty()) ? tagMuons.front().eta() : 0); + if (electron_pt.numerator != nullptr) + electron_pt.fill(trg_passed, (!tagElectrons.empty()) ? tagElectrons.front().pt() : -100); + if (electron_eta.numerator != nullptr) + electron_eta.fill(trg_passed, (!tagElectrons.empty()) ? tagElectrons.front().eta() : -100); + if (dilepton_pt.numerator != nullptr) + dilepton_pt.fill(trg_passed, (!emuPairs.empty()) ? emuPairs.front().pt() : 0); + if (dilepton_mass.numerator != nullptr) + dilepton_mass.fill(trg_passed, (!emuPairs.empty()) ? emuPairs.front().mass() : 0); + + if (jet1_pt.numerator != nullptr) + jet1_pt.fill(trg_passed, (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0); + if (jet2_pt.numerator != nullptr) + jet2_pt.fill(trg_passed, (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0); + if (jet1_eta.numerator != nullptr) + jet1_eta.fill(trg_passed, (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).eta() : -100); + if (jet2_eta.numerator != nullptr) + jet2_eta.fill(trg_passed, (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).eta() : -100); + if (jet1_pnetscore.numerator != nullptr) + jet1_pnetscore.fill(trg_passed, + (!selectedJets.empty()) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) : -1); + if (jet2_pnetscore.numerator != nullptr) + jet2_pnetscore.fill(trg_passed, + (selectedJets.size() > 1) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1)) : -1); + if (jet1_pnetscore_trans.numerator != nullptr) + jet1_pnetscore_trans.fill( + trg_passed, (!selectedJets.empty()) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0))) : -1); + if (jet2_pnetscore_trans.numerator != nullptr) + jet2_pnetscore_trans.fill( + trg_passed, (selectedJets.size() > 1) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) : -1); + if (mean_2j_pnetscore.numerator != nullptr) + mean_2j_pnetscore.fill(trg_passed, + (selectedJets.size() > 1) ? (jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2. + : -1); + if (mean_2j_pnetscore_trans.numerator != nullptr) + mean_2j_pnetscore_trans.fill(trg_passed, + (selectedJets.size() > 1) + ? atanh((jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2.) + : -1); + + if (jet1_pt_eta.numerator != nullptr) + jet1_pt_eta.fill(trg_passed, + (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).eta() : -1); + if (jet2_pt_eta.numerator != nullptr) + jet2_pt_eta.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).eta() : -1); + + if (jet1_pt_pnetscore1.numerator != nullptr) + jet1_pt_pnetscore1.fill(trg_passed, + (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (!selectedJets.empty()) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) : -1); + if (jet2_pt_pnetscore1.numerator != nullptr) + jet2_pt_pnetscore1.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) : -1); + if (jet1_pt_pnetscore2.numerator != nullptr) + jet1_pt_pnetscore2.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (selectedJets.size() > 1) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1)) : -1); + if (jet2_pt_pnetscore2.numerator != nullptr) + jet2_pt_pnetscore2.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) ? jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1)) : -1); + + if (jet1_pt_pnetscore1_trans.numerator != nullptr) + jet1_pt_pnetscore1_trans.fill( + trg_passed, + (!selectedJets.empty()) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (!selectedJets.empty()) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0))) : -1); + if (jet2_pt_pnetscore1_trans.numerator != nullptr) + jet2_pt_pnetscore1_trans.fill( + trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0))) : -1); + if (jet1_pt_pnetscore2_trans.numerator != nullptr) + jet1_pt_pnetscore2_trans.fill( + trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (selectedJets.size() > 1) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) : -1); + if (jet2_pt_pnetscore2_trans.numerator != nullptr) + jet2_pt_pnetscore2_trans.fill( + trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) ? atanh(jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) : -1); + + if (jet1_pt_mean2pnetscore.numerator != nullptr) + jet1_pt_mean2pnetscore.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (selectedJets.size() > 1) ? (jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2 + : -1); + if (jet2_pt_mean2pnetscore.numerator != nullptr) + jet2_pt_mean2pnetscore.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) + ? atanh((jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2) + : -1); + + if (jet1_pt_mean2pnetscore_trans.numerator != nullptr) + jet1_pt_mean2pnetscore_trans.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(0)).pt() : 0, + (selectedJets.size() > 1) + ? atanh((jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2) + : -1); + if (jet2_pt_mean2pnetscore_trans.numerator != nullptr) + jet2_pt_mean2pnetscore_trans.fill(trg_passed, + (selectedJets.size() > 1) ? selectedJets.at(jetPtSortedIndices.at(1)).pt() : 0, + (selectedJets.size() > 1) + ? atanh((jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(0)) + + jetPNETScoreValues.at(jetPNETScoreSortedIndices.at(1))) / + 2) + : -1); +} + +void ParticleNetJetTagMonitor::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("FolderName", "HLT/Higgs"); + desc.add("requireValidHLTPaths", true); + desc.add("requireHLTOfflineJetMatching", true); + desc.add("vertices", edm::InputTag("offlinePrimaryVertices")); + desc.add("muons", edm::InputTag("muons")); + desc.add("electrons", edm::InputTag("gedGsfElectrons")); + desc.add("tagElectronID", + edm::InputTag("egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V2-tight")); + desc.add("vetoElectronID", + edm::InputTag("egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V2-loose")); + desc.add("jets", edm::InputTag("ak4PFJetsCHS")); + desc.add("jetPNETScore", edm::InputTag("pfParticleNetAK4DiscriminatorsJetTags", "BvsAll")); + desc.add("jetPNETScoreHLT", edm::InputTag("hltParticleNetDiscriminatorsJetTags", "BvsAll")); + desc.add("jetsForHTandBTag", edm::InputTag("")); + desc.add("jetPNETScoreForHTandBTag", edm::InputTag("")); + desc.add("jetSoftDropMass", edm::InputTag("")); + desc.add("met", edm::InputTag("pfMetPuppi")); + desc.add("jecForMC", edm::InputTag("ak4PFCHSL1FastL2L3Corrector")); + desc.add("jecForData", edm::InputTag("ak4PFCHSL1FastL2L3ResidualCorrector")); + desc.add("tagMuonSelection", + "pt > 25 && abs(eta) < 2.4 && passed(CutBasedIdTight) && passed(PFIsoTight)"); + desc.add("tagElectronSelection", "pt > 20 && abs(eta) < 2.5"); + desc.add("vetoMuonSelection", + "pt > 10 && abs(eta) < 2.4 && passed(CutBasedIdLoose) && passed(PFIsoLoose)"); + desc.add("vetoElectronSelection", "pt > 10 && abs(eta) < 2.5"); + desc.add("jetSelection", "pt > 30 && abs(eta) < 2.5"); + desc.add("jetSelectionForHTandBTag", "pt > 30 && abs(eta) < 2.5"); + desc.add("vertexSelection", "!isFake && ndof > 4 && abs(z) <= 24 && position.Rho <= 2"); + desc.add("dileptonSelection", "((mass > 20 && mass < 75) || mass > 105) && charge == 0"); + desc.add("metSelection", "pt > 0"); + desc.add("ntagleptons", 2); + desc.add("ntagmuons", 1); + desc.add("ntagelectrons", 1); + desc.add("nvetoleptons", 2); + desc.add("nvetomuons", 1); + desc.add("nvetoelectrons", 1); + desc.add("nemupairs", 1); + desc.add("njets", 2); + desc.add("nbjets", -1); + desc.add("ntrigobjecttomatch", 2); + desc.add("lepJetDeltaRmin", 0.4); + desc.add("lepJetDeltaRminForHTandBTag", 0.4); + desc.add("hltRecoDeltaRmax", 0.4); + desc.add("maxLeptonDxyCut", 0.1); + desc.add("maxLeptonDzCut", 0.2); + desc.add("minPNETScoreCut", 0.2); + desc.add("minPNETBTagCut", 0.5); + desc.add("minSoftDropMassCut", 50); + desc.add("maxSoftDropMassCut", 110); + desc.add>("leptonPtBinning", {}); + desc.add>("leptonEtaBinning", {}); + desc.add>("diLeptonPtBinning", {}); + desc.add>("diLeptonMassBinning", {}); + desc.add>("HTBinning", {}); + desc.add>("NjetBinning", {}); + desc.add>("jet1PtBinning", {}); + desc.add>("jet2PtBinning", {}); + desc.add>("jet1EtaBinning", {}); + desc.add>("jet2EtaBinning", {}); + desc.add>("jet1PNETscoreBinning", {}); + desc.add>("jet2PNETscoreBinning", {}); + desc.add>("jet1PNETscoreTransBinning", {}); + desc.add>("jet2PNETscoreTransBinning", {}); + desc.add>("jet1PtBinning2d", {}); + desc.add>("jet2PtBinning2d", {}); + desc.add>("jet1EtaBinning2d", {}); + desc.add>("jet2EtaBinning2d", {}); + desc.add>("jet1PNETscoreBinning2d", {}); + desc.add>("jet2PNETscoreBinning2d", {}); + desc.add>("jet1PNETscoreTransBinning2d", {}); + desc.add>("jet2PNETscoreTransBinning2d", {}); + edm::ParameterSetDescription genericTriggerEventPSet; + GenericTriggerEventFlag::fillPSetDescription(genericTriggerEventPSet); + desc.add("numGenericTriggerEvent", genericTriggerEventPSet); + desc.add("denGenericTriggerEvent", genericTriggerEventPSet); + descriptions.add("ParticleNetJetTagMonitor", desc); +} + +// Define this as a plug-in +DEFINE_FWK_MODULE(ParticleNetJetTagMonitor); diff --git a/DQMOffline/Trigger/python/DQMOffline_HLT_Client_cff.py b/DQMOffline/Trigger/python/DQMOffline_HLT_Client_cff.py index 017ab681044ce..f70029c15053b 100644 --- a/DQMOffline/Trigger/python/DQMOffline_HLT_Client_cff.py +++ b/DQMOffline/Trigger/python/DQMOffline_HLT_Client_cff.py @@ -29,6 +29,8 @@ from DQMOffline.Trigger.JetMETPromptMonitoring_Client_cff import * from DQMOffline.Trigger.DiJetMonitor_Client_cff import * +from DQMOffline.Trigger.ParticleNetJetTag_Client_cff import * + hltOfflineDQMClient = cms.Sequence( # hltGeneralSeqClient sipixelHarvesterHLTsequence @@ -55,6 +57,7 @@ * bphClient * JetMetPromClient * dijetClient + * particleNetClientHLT ) hltOfflineDQMClientExtra = cms.Sequence( diff --git a/DQMOffline/Trigger/python/DQMOffline_Trigger_cff.py b/DQMOffline/Trigger/python/DQMOffline_Trigger_cff.py index 7bf0e54efa33d..6bb20a2d88d5c 100644 --- a/DQMOffline/Trigger/python/DQMOffline_Trigger_cff.py +++ b/DQMOffline/Trigger/python/DQMOffline_Trigger_cff.py @@ -34,6 +34,9 @@ from DQMOffline.Trigger.BTVHLTOfflineSource_cfi import * from DQMOffline.Trigger.BTaggingMonitoring_cff import * +# ParticleNet jet flavor tagging monitoring +from DQMOffline.Trigger.ParticleNetJetTagMonitoring_cff import * + # vertexing from DQMOffline.Trigger.PrimaryVertexMonitoring_cff import * @@ -192,7 +195,8 @@ trackingMonitorHLTDisplacedJet* # EXO : DisplacedJet Tracking egmTrackingMonitorHLT * # EGM tracking hltToOfflineTrackValidatorSequence * # Relative Online to Offline performace - vertexingMonitorHLT # vertexing + vertexingMonitorHLT * # vertexing + particleNetMonitoringHLT # HIG: monitoring of HLT PNET taggers (incl. comparisons to Offline PNET) ) # sequences run @tier0 on HLTMonitor PD diff --git a/DQMOffline/Trigger/python/ParticleNetAK4BTagClient_cfi.py b/DQMOffline/Trigger/python/ParticleNetAK4BTagClient_cfi.py new file mode 100644 index 0000000000000..7c3296f71bb1e --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetAK4BTagClient_cfi.py @@ -0,0 +1,43 @@ +import FWCore.ParameterSet.Config as cms +from DQMServices.Core.DQMEDHarvester import DQMEDHarvester + +particleNetAK4BTagEfficiency = DQMEDHarvester("DQMGenericClient", + subDirs = cms.untracked.vstring("HLT/HIG/PNETAK4/HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_PFDiJet30_PFBTagParticleNet_2BTagSum0p65/"), + verbose = cms.untracked.uint32(0), # Set to 2 for all messages + resolution = cms.vstring(), + efficiency = cms.vstring( + "eff_muon_pt 'Efficiency vs p_{T}(#mu); p_{T}(#mu); efficiency' muon_pt_numerator muon_pt_denominator", + "eff_muon_eta 'Efficiency vs #eta(#mu); #eta(#mu); efficiency' muon_eta_numerator muon_eta_denominator", + "eff_electron_pt 'Efficiency vs p_{T}(ele); p_{T}(ele); efficiency' electron_pt_numerator electron_pt_denominator", + "eff_electron_eta 'Efficiency vs #eta(ele); #eta(ele); efficiency' electron_eta_numerator electron_eta_denominator", + "eff_dilepton_pt 'Efficiency vs p_{T}(ll); p_{T}(ll); efficiency' dilepton_pt_numerator dilepton_pt_denominator", + "eff_dilepton_mass 'Efficiency vs m(ll); m(ll); efficiency' dilepton_mass_numerator dilepton_mass_denominator", + "eff_ht 'Efficiency vs H_{T}; H_{T}; efficiency' ht_numerator ht_denominator", + "eff_njets 'Efficiency vs N_{jets}; N_{jets}; efficiency' njets_numerator njets_denominator", + "eff_nbjets 'Efficiency vs N_{bjets}; N_{bjets}; efficiency' nbjets_numerator nbjets_denominator", + "eff_jet1_pt 'Efficiency vs p_{T}(j1); p_{T}(j1); efficiency' jet1_pt_numerator jet1_pt_denominator", + "eff_jet2_pt 'Efficiency vs p_{T}(j2); p_{T}(j2); efficiency' jet2_pt_numerator jet2_pt_denominator", + "eff_jet1_eta 'Efficiency vs #eta(j1); #eta(j1); efficiency' jet1_eta_numerator jet1_eta_denominator", + "eff_jet2_eta 'Efficiency vs #eta(j2); #eta(j2); efficiency' jet2_eta_numerator jet2_eta_denominator", + "eff_jet1_pnetscore 'Efficiency vs Lead PNET-score; Lead PNET-score; efficiency' jet1_pnetscore_numerator jet1_pnetscore_denominator", + "eff_jet2_pnetscore 'Efficiency vs Trail PNET-score; Trail PNET-score; efficiency' jet2_pnetscore_numerator jet2_pnetscore_denominator", + "eff_jet1_pnetscore_trans 'Efficiency vs Lead atanh(PNET-score); Lead atanh(PNET-score); efficiency' jet1_pnetscore_trans_numerator jet1_pnetscore_trans_denominator", + "eff_jet2_pnetscore_trans 'Efficiency vs Trail atanh(PNET-score); Trail atanh(PNET-score); efficiency' jet2_pnetscore_trans_numerator jet2_pnetscore_trans_denominator", + "eff_mean_2j_pnetscore 'Efficiency vs Mean(PNET-score); Mean(PNET-score); efficiency' mean_2j_pnetscore_numerator mean_2j_pnetscore_denominator", + "eff_mean_2j_pnetscore_trans 'Efficiency vs atanh(Mean(PNET-score)); atanh(Mean(PNET-score)); efficiency' mean_2j_pnetscore_trans_numerator mean_2j_pnetscore_trans_denominator", + "eff_jet1_pt_eta 'Efficiency vs j1 p_{T} and #eta; p_{T}(j1); #eta(j1); efficiency' jet1_pt_eta_numerator jet1_pt_eta_denominator", + "eff_jet2_pt_eta 'Efficiency vs j2 p_{T} and #eta; p_{T}(j2); #eta(j2); efficiency' jet2_pt_eta_numerator jet2_pt_eta_denominator", + "eff_jet1_pt_pnetscore1 'Efficiency vs j1 p_{T} and Lead PNET-score; p_{T}(j1); Lead PNET-score; efficiency' jet1_pt_pnetscore1_numerator jet1_pt_pnetscore1_denominator", + "eff_jet1_pt_pnetscore2 'Efficiency vs j1 p_{T} and Trail PNET-score; p_{T}(j1); Trail PNET-score; efficiency' jet1_pt_pnetscore2_numerator jet1_pt_pnetscore2_denominator", + "eff_jet1_pt_mean2pnetscore 'Efficiency vs j1 p_{T} and Mean(PNET-score); p_{T}(j1); Mean(PNET-score); efficiency' jet1_pt_mean2pnetscore_numerator jet1_pt_mean2pnetscore_denominator", + "eff_jet2_pt_pnetscore1 'Efficiency vs j2 p_{T} and Lead PNET-score; p_{T}(j2); Lead PNET-score; efficiency' jet2_pt_pnetscore1_numerator jet2_pt_pnetscore1_denominator", + "eff_jet2_pt_pnetscore2 'Efficiency vs j2 p_{T} and Trail PNET-score; p_{T}(j2); Trail PNET-score; efficiency' jet2_pt_pnetscore2_numerator jet2_pt_pnetscore2_denominator", + "eff_jet2_pt_mean2pnetscore 'Efficiency vs j2 p_{T} and Mean(PNET-score); p_{T}(j2); Mean(PNET-score); efficiency' jet2_pt_mean2pnetscore_numerator jet2_pt_mean2pnetscore_denominator", + "eff_jet1_pt_pnetscore1_trans 'Efficiency vs j1 p_{T} and Lead atanh(PNET-score); p_{T}(j1); Lead atanh(PNET-score); efficiency' jet1_pt_pnetscore1_trans_numerator jet1_pt_pnetscore1_trans_denominator", + "eff_jet1_pt_pnetscore2_trans 'Efficiency vs j1 p_{T} and Trail atanh(PNET-score); p_{T}(j1); Trail atanh(PNET-score); efficiency' jet1_pt_pnetscore2_trans_numerator jet1_pt_pnetscore2_trans_denominator", + "eff_jet1_pt_mean2pnetscore_trans 'Efficiency vs j1 p_{T} and atanh(Mean(PNET-score)); p_{T}(j1); atanh(Mean(PNET-score)); efficiency' jet1_pt_mean2pnetscore_trans_numerator jet1_pt_mean2pnetscore_trans_denominator", + "eff_jet2_pt_pnetscore1_trans 'Efficiency vs j2 p_{T} and Lead atanh(PNET-score); p_{T}(j2); Lead atanh(PNET-score); efficiency' jet2_pt_pnetscore1_trans_numerator jet2_pt_pnetscore1_trans_denominator", + "eff_jet2_pt_pnetscore2_trans 'Efficiency vs j2 p_{T} and Trail atanh(PNET-score); p_{T}(j2); Trail atanh(PNET-score); efficiency' jet2_pt_pnetscore2_trans_numerator jet2_pt_pnetscore2_trans_denominator", + "eff_jet2_pt_mean2pnetscore_trans 'Efficiency vs j2 p_{T} and atanh(Mean(PNET-score)); p_{T}(j2); atanh(Mean(PNET-score)); efficiency' jet2_pt_mean2pnetscore_trans_numerator jet2_pt_mean2pnetscore_trans_denominator", + ) +) diff --git a/DQMOffline/Trigger/python/ParticleNetAK4BTagMonitoring_cfi.py b/DQMOffline/Trigger/python/ParticleNetAK4BTagMonitoring_cfi.py new file mode 100644 index 0000000000000..17fab3d7c6aff --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetAK4BTagMonitoring_cfi.py @@ -0,0 +1,110 @@ +import FWCore.ParameterSet.Config as cms + +from DQMOffline.Trigger.ParticleNetJetTagMonitor_cfi import ParticleNetJetTagMonitor as _particleNetJetTagMonitor + +particleNetAK4BTagMonitoring = _particleNetJetTagMonitor.clone( + ## general options + FolderName = "HLT/HIG/PNETAK4/HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_PFDiJet30_PFBTagParticleNet_2BTagSum0p65/", + requireValidHLTPaths = True, + requireHLTOfflineJetMatching = True, + ## objects + muons = "muons", + electrons = "gedGsfElectrons", + jets = "ak4PFJetsCHS", + jetPNETScore = "pfParticleNetAK4DiscriminatorsJetTagsForRECO:BvsAll", + jetPNETScoreHLT = "hltParticleNetDiscriminatorsJetTags:BvsAll", + jetsForHTandBTag = "", + jetPNETScoreForHTandBTag = "", + jetSoftDropMass = "", + met = "pfMetPuppi", + jecForMC = "ak4PFCHSL1FastL2L3Corrector", + jecForData = "ak4PFCHSL1FastL2L3ResidualCorrector", + ## PV selection + vertexSelection = "!isFake && ndof > 4 && abs(z) <= 24 && position.Rho <= 2", + ## Muon selection (based on the definition of https://cmssdt.cern.ch/lxr/source/DataFormats/MuonReco/interface/Muon.h) + tagMuonSelection = "pt > 15 && abs(eta) < 2.4 && passed(4) && passed(256)", + vetoMuonSelection = "pt > 10 && abs(eta) < 2.4 && passed(1) && passed(128)", + maxLeptonDxyCut = 0.1, + maxLeptonDzCut = 0.2, + ntagmuons = 1, + nvetomuons = 1, + ## Electron selection + tagElectronSelection = "pt > 25 && abs(eta) < 2.5", + vetoElectronSelection = "pt > 15 && abs(eta) < 2.5", + tagElectronID = "egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V1-tight", + vetoElectronID = "egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V1-loose", + ntagelectrons = 1, + nvetoelectrons = 1, + ## Total number of leptons (electron+muons) in the event + ntagleptons = 2, + nvetoleptons = 2, + ## Emu pairs + dileptonSelection = "mass > 20 && charge == 0", + nemupairs = 1, + ## jet selection (main jet collection) + jetSelection = "pt > 30 && abs(eta) < 2.5", + minPNETScoreCut = 0.1, + minSoftDropMassCut = 0, + maxSoftDropMassCut = 10000, + njets = 2, + ## Bjet selection (ak4 jets) + jetSelectionForHTandBTag = "pt > 30 && abs(eta) < 2.5", + nbjets = -1, + ## Met selection + metSelection = "pt > 0", + ## Cleaning jet-lepton + lepJetDeltaRmin = 0.4, + ## Match reco with HLT + hltRecoDeltaRmax = 0.4, + ntrigobjecttomatch = 2, + ## binning for efficiency + NjetBinning = [0,1,2,3,4,5,6,7,8], + HTBinning = [0,50,100,150,200,250,300,350,400,500,600,750,1000], + leptonPtBinning = [20,30,40,50,60,75,90,110,135,175,225,300], + leptonEtaBinning = [-2.5,-2.25,-2.0,-1.75,-1.5,-1.25,-1.0,-0.75,-0.5,-0.25,0.,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0,2.25,2.5], + diLeptonPtBinning = [0,20,30,40,50,60,75,90,110,135,175,225,300], + diLeptonMassBinning = [20,30,40,50,60,70,80,90,100,110,120,130,140,155,170,185,200,220,240,260,300], + jet1PtBinning = [20,30,40,50,60,75,90,110,130,150,175,200,225,250,300,400,500], + jet2PtBinning = [20,30,40,50,60,75,90,110,130,150,175,200,225,250,300], + jet1EtaBinning = [-2.5,-2.25,-2.0,-1.75,-1.5,-1.25,-1.0,-0.75,-0.5,-0.25,0.,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0,2.25,2.5], + jet2EtaBinning = [-2.5,-2.25,-2.0,-1.75,-1.5,-1.25,-1.0,-0.75,-0.5,-0.25,0.,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0,2.25,2.5], + jet1PNETscoreBinning = [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.75,0.8,0.85,0.9,0.925,0.95,0.975,1], + jet2PNETscoreBinning = [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.75,0.8,0.85,0.9,0.925,0.95,0.975,1], + jet1PNETscoreTransBinning = [0,0.1,0.2,0.3,0.4,0.6,0.8,1.0,1.25,1.50,1.75,2.25,2.75,4], + jet2PNETscoreTransBinning = [0,0.1,0.2,0.3,0.4,0.6,0.8,1.0,1.25,1.50,1.75,2.25,2.75,4], + jet1PtBinning2d = [20,30,40,50,75,100,150,250,500], + jet2PtBinning2d = [20,30,40,50,75,100,125,150,250], + jet1EtaBinning2d = [-2.5,-2.0,-1.5,-1.0,-0.5,0.,0.5,1.0,1.5,2.0,2.5], + jet2EtaBinning2d = [-2.5,-2.0,-1.5,-1.0,-0.5,0.,0.5,1.0,1.5,2.0,2.5], + jet1PNETscoreBinning2d = [0,0.15,0.30,0.45,0.60,0.75,0.85,0.90,0.95,0.975,1], + jet2PNETscoreBinning2d = [0,0.15,0.30,0.45,0.60,0.75,0.85,0.90,0.95,0.975,1], + jet1PNETscoreTransBinning2d = [0,0.15,0.30,0.45,0.60,0.75,1,1.5,2,2.5,4], + jet2PNETscoreTransBinning2d = [0,0.15,0.30,0.45,0.60,0.75,1,1.5,2,2.5,4], + ## trigger for numerator and denominator + numGenericTriggerEvent = dict( + hltPaths = ["HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_PFDiJet30_PFBTagParticleNet_2BTagSum0p65_v*"], + andOr = False, + andOrHlt = True, + #hltInputTag = "TriggerResults::reHLT", ## when testing in the DQM workflow (https://twiki.cern.ch/twiki/bin/viewauth/CMS/HLTValidationAndDQM) + hltInputTag = "TriggerResults::HLT", + errorReplyHlt = False, + dcsInputTag = "scalersRawToDigi", + dcsPartitions = [24, 25, 26, 27, 28, 29], + andOrDcs = False, + errorReplyDcs = True, + verbosityLevel = 1, + ), + denGenericTriggerEvent = dict( + hltPaths = ["HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_PFDiJet30_v*"], + andOr = False, + andOrHlt = True, + #hltInputTag = "TriggerResults::reHLT", ## when testing in the DQM workflow (https://twiki.cern.ch/twiki/bin/viewauth/CMS/HLTValidationAndDQM) + hltInputTag = "TriggerResults::HLT", + errorReplyHlt = False, + dcsInputTag = "scalersRawToDigi", + dcsPartitions = [24, 25, 26, 27, 28, 29], + andOrDcs = False, + errorReplyDcs = True, + verbosityLevel = 1, + ), +) diff --git a/DQMOffline/Trigger/python/ParticleNetAK8HbbTagClient_cfi.py b/DQMOffline/Trigger/python/ParticleNetAK8HbbTagClient_cfi.py new file mode 100644 index 0000000000000..dc1b6555658d3 --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetAK8HbbTagClient_cfi.py @@ -0,0 +1,24 @@ +import FWCore.ParameterSet.Config as cms +from DQMServices.Core.DQMEDHarvester import DQMEDHarvester + +particleNetAK8HbbTagEfficiency = DQMEDHarvester("DQMGenericClient", + subDirs = cms.untracked.vstring("HLT/HIG/PNETAK8/HLT_IsoMu50_AK8PFJet230_SoftDropMass40_PFAK8ParticleNetBB0p35_or_HLT_Ele50_CaloIdVT_GsfTrkIdT_AK8PFJet230_SoftDropMass40/"), + verbose = cms.untracked.uint32(0), # Set to 2 for all messages + resolution = cms.vstring(), + efficiency = cms.vstring( + "eff_muon_pt 'Efficiency vs p_{T}(#mu); p_{T}(#mu); efficiency' muon_pt_numerator muon_pt_denominator", + "eff_muon_eta 'Efficiency vs #eta(#mu); #eta(#mu); efficiency' muon_eta_numerator muon_eta_denominator", + "eff_electron_pt 'Efficiency vs p_{T}(ele); p_{T}(ele); efficiency' electron_pt_numerator electron_pt_denominator", + "eff_electron_eta 'Efficiency vs #eta(ele); #eta(ele); efficiency' electron_eta_numerator electron_eta_denominator", + "eff_ht 'Efficiency vs H_{T}; H_{T}; efficiency' ht_numerator ht_denominator", + "eff_njets 'Efficiency vs N_{jets}; N_{jets}; efficiency' njets_numerator njets_denominator", + "eff_nbjets 'Efficiency vs N_{bjets}; N_{bjets}; efficiency' nbjets_numerator nbjets_denominator", + "eff_jet1_pt 'Efficiency vs p_{T}(j1); p_{T}(j1); efficiency' jet1_pt_numerator jet1_pt_denominator", + "eff_jet1_eta 'Efficiency vs #eta(j1); #eta(j1); efficiency' jet1_eta_numerator jet1_eta_denominator", + "eff_jet1_pnetscore 'Efficiency vs Lead PNET-score; Lead PNET-score; efficiency' jet1_pnetscore_numerator jet1_pnetscore_denominator", + "eff_jet1_pnetscore_trans 'Efficiency vs Lead atanh(PNET-score); Lead atanh(PNET-score); efficiency' jet1_pnetscore_trans_numerator jet1_pnetscore_trans_denominator", + "eff_jet1_pt_eta 'Efficiency vs j1 p_{T} and #eta; p_{T}(j1); #eta(j1); efficiency' jet1_pt_eta_numerator jet1_pt_eta_denominator", + "eff_jet1_pt_pnetscore1 'Efficiency vs j1 p_{T} and Lead PNET-score; p_{T}(j1); Lead PNET-score; efficiency' jet1_pt_pnetscore1_numerator jet1_pt_pnetscore1_denominator", + "eff_jet1_pt_pnetscore1_trans 'Efficiency vs j1 p_{T} and Lead atanh(PNET-score); p_{T}(j1); Lead atanh(PNET-score); efficiency' jet1_pt_pnetscore1_trans_numerator jet1_pt_pnetscore1_trans_denominator", + ) +) diff --git a/DQMOffline/Trigger/python/ParticleNetAK8HbbTagMonitoring_cfi.py b/DQMOffline/Trigger/python/ParticleNetAK8HbbTagMonitoring_cfi.py new file mode 100644 index 0000000000000..7c09685e4aca2 --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetAK8HbbTagMonitoring_cfi.py @@ -0,0 +1,115 @@ +import FWCore.ParameterSet.Config as cms + +from DQMOffline.Trigger.ParticleNetJetTagMonitor_cfi import ParticleNetJetTagMonitor as _particleNetJetTagMonitor + +particleNetAK8HbbTagMonitoring = _particleNetJetTagMonitor.clone( + ## general options + FolderName = "HLT/HIG/PNETAK8/HLT_IsoMu50_AK8PFJet230_SoftDropMass40_PFAK8ParticleNetBB0p35_or_HLT_Ele50_CaloIdVT_GsfTrkIdT_AK8PFJet230_SoftDropMass40/", + requireValidHLTPaths = True, + requireHLTOfflineJetMatching = True, + ## objects + muons = "muons", + electrons = "gedGsfElectrons", + jets = "ak8PFJetsPuppi", + jetPNETScore = "pfMassDecorrelatedParticleNetDiscriminatorsJetTags:XbbvsQCD", + jetPNETScoreHLT = "hltParticleNetDiscriminatorsJetTagsAK8:HbbVsQCD", + jetsForHTandBTag = "ak4PFJetsCHS", + jetPNETScoreForHTandBTag = "pfParticleNetAK4DiscriminatorsJetTagsForRECO:BvsAll", + jetSoftDropMass = "ak8PFJetsPuppiSoftDropMass", + met = "pfMetPuppi", + jecForMC = "", + jecForData = "", + ## PV selection + vertexSelection = "!isFake && ndof > 4 && abs(z) <= 24 && position.Rho <= 2", + ## Muon selection (based on the definition of https://cmssdt.cern.ch/lxr/source/DataFormats/MuonReco/interface/Muon.h) + tagMuonSelection = "pt > 60 && abs(eta) < 2.4 && passed(4) && passed(256)", + vetoMuonSelection = "pt > 10 && abs(eta) < 2.4 && passed(1) && passed(128)", + maxLeptonDxyCut = 0.1, + maxLeptonDzCut = 0.2, + ntagmuons = -1, + nvetomuons = -1, + ## Electron selection + tagElectronSelection = "pt > 60 && abs(eta) < 2.5", + vetoElectronSelection = "pt > 15 && abs(eta) < 2.5", + tagElectronID = "egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V1-tight", + vetoElectronID = "egmGsfElectronIDsForDQM:cutBasedElectronID-Fall17-94X-V1-loose", + ntagelectrons = -1, + nvetoelectrons = -1, + ## Lepton counting + ntagleptons = 1, + nvetoleptons = 1, + ## Emu pairs + dileptonSelection = "", + nemupairs = -1, + ## Jet AK8 selection + jetSelection = "pt > 180 && abs(eta) < 2.4", + minPNETScoreCut = 0.1, + minSoftDropMassCut = 50, + maxSoftDropMassCut = 110, + njets = 1, + ## B-tagged jet selection + jetSelectionForHTandBTag = "pt > 30 && abs(eta) < 2.5", + minPNETBTagCut = 0.25, + nbjets = 2, + ## PF-MET selection + metSelection = "pt > 30", + ## Jet lepton cleaning + lepJetDeltaRmin = 0.8, + lepJetDeltaRminForHTandBTag = 0.4, + ## Trigger matching + hltRecoDeltaRmax = 0.8, + ntrigobjecttomatch = 1, + ## binning for efficiency + NjetBinning = [0,1,2,3,4,5,6,7,8], + HTBinning = [100,200,300,400,500,600,700,800,1000,1250], + leptonPtBinning = [75,100,125,150,200,250,300,400,600], + leptonEtaBinning = [-2.5,-2.0,-1.5,-0.5,0.,0.5,1.0,1.5,2.0,2.5], + diLeptonPtBinning = [], + diLeptonMassBinning = [], + jet1PtBinning = [180,200,220,240,260,280,300,325,350,375,400,450,500,600,750,900], + jet2PtBinning = [], + jet1EtaBinning = [-2.5,-2.0,-1.5,-1.0,-0.5,0.,0.5,1.0,1.5,2.0,2.5], + jet2EtaBinning = [], + jet1PNETscoreBinning = [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.75,0.8,0.85,0.9,0.925,0.95,0.975,1], + jet2PNETscoreBinning = [], + jet1PNETscoreTransBinning = [0,0.1,0.2,0.3,0.4,0.6,0.8,1.0,1.25,1.50,1.75,2.25,2.75,4], + jet2PNETscoreTransBinning = [], + jet1PtBinning2d = [180,220,260,300,340,400,500,750,1250], + jet2PtBinning2d = [], + jet1EtaBinning2d = [-2.5,-2.0,-1.5,-1.0,-0.5,0.,0.5,1.0,1.5,2.0,2.5], + jet2EtaBinning2d = [], + jet1PNETscoreBinning2d = [0,0.15,0.30,0.45,0.60,0.75,0.85,0.90,0.95,0.975,1], + jet2PNETscoreBinning2d = [], + jet1PNETscoreTransBinning2d = [0,0.15,0.30,0.45,0.60,0.75,1,1.5,2,2.5,4], + jet2PNETscoreTransBinning2d = [], + ## trigger for numerator and denominator + numGenericTriggerEvent = dict( + hltPaths = ["HLT_IsoMu50_AK8PFJet230_SoftDropMass40_PFAK8ParticleNetBB0p35_v*", + "HLT_Ele50_CaloIdVT_GsfTrkIdT_AK8PFJet230_SoftDropMass40_PFAK8ParticleNetBB0p35_v*"], + andOr = False, + andOrHlt = True, + #hltInputTag = "TriggerResults::reHLT", ## when testing in the DQM workflow (https://twiki.cern.ch/twiki/bin/viewauth/CMS/HLTValidationAndDQM) + hltInputTag = "TriggerResults::HLT", + errorReplyHlt = False, + dcsInputTag = "scalersRawToDigi", + dcsPartitions = [24, 25, 26, 27, 28, 29], + andOrDcs = False, + errorReplyDcs = True, + verbosityLevel = 1, + ), + denGenericTriggerEvent = dict( + hltPaths = ["HLT_IsoMu50_AK8PFJet230_SoftDropMass40_v*", + "HLT_Ele50_CaloIdVT_GsfTrkIdT_AK8PFJet230_SoftDropMass40_v*", + ], + andOr = False, + andOrHlt = True, + #hltInputTag = "TriggerResults::reHLT", ## when testing in the DQM workflow (https://twiki.cern.ch/twiki/bin/viewauth/CMS/HLTValidationAndDQM) + hltInputTag = "TriggerResults::HLT", + errorReplyHlt = False, + dcsInputTag = "scalersRawToDigi", + dcsPartitions = [24, 25, 26, 27, 28, 29], + andOrDcs = False, + errorReplyDcs = True, + verbosityLevel = 1, + ), +) diff --git a/DQMOffline/Trigger/python/ParticleNetJetTagMonitoring_cff.py b/DQMOffline/Trigger/python/ParticleNetJetTagMonitoring_cff.py new file mode 100644 index 0000000000000..bdcf2e6461f74 --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetJetTagMonitoring_cff.py @@ -0,0 +1,15 @@ +import FWCore.ParameterSet.Config as cms + +from DQMOffline.Trigger.ParticleNetAK4BTagMonitoring_cfi import particleNetAK4BTagMonitoring +from DQMOffline.Trigger.ParticleNetAK8HbbTagMonitoring_cfi import particleNetAK8HbbTagMonitoring + +particleNetMonitoringHLT = cms.Sequence( + particleNetAK4BTagMonitoring + + particleNetAK8HbbTagMonitoring +) + +# empty particleNetMonitoringHLT sequence when using the pp_on_AA processModifier: +# HLT-PNET DQM can trigger the execution of modules to run inference +# on offline jet collections which are not present in HIon workflows +from Configuration.ProcessModifiers.pp_on_AA_cff import pp_on_AA +pp_on_AA.toReplaceWith(particleNetMonitoringHLT, cms.Sequence()) diff --git a/DQMOffline/Trigger/python/ParticleNetJetTag_Client_cff.py b/DQMOffline/Trigger/python/ParticleNetJetTag_Client_cff.py new file mode 100644 index 0000000000000..d848da30d099c --- /dev/null +++ b/DQMOffline/Trigger/python/ParticleNetJetTag_Client_cff.py @@ -0,0 +1,14 @@ +import FWCore.ParameterSet.Config as cms + +from DQMOffline.Trigger.ParticleNetAK4BTagClient_cfi import particleNetAK4BTagEfficiency +from DQMOffline.Trigger.ParticleNetAK8HbbTagClient_cfi import particleNetAK8HbbTagEfficiency + +particleNetClientHLT = cms.Sequence( + particleNetAK4BTagEfficiency + + particleNetAK8HbbTagEfficiency +) + +# empty particleNetClientHLT sequence when using the pp_on_AA processModifier: +# see DQMOffline/Trigger/python/ParticleNetJetTagMonitoring_cff.py +from Configuration.ProcessModifiers.pp_on_AA_cff import pp_on_AA +pp_on_AA.toReplaceWith(particleNetClientHLT, cms.Sequence()) diff --git a/RecoBTag/Configuration/python/RecoBTag_cff.py b/RecoBTag/Configuration/python/RecoBTag_cff.py index b04dbcbd2ad95..72e82abd8c753 100644 --- a/RecoBTag/Configuration/python/RecoBTag_cff.py +++ b/RecoBTag/Configuration/python/RecoBTag_cff.py @@ -89,3 +89,8 @@ ) btagging = cms.Sequence(btaggingTask) +## modifying b-tagging task in Run3 adding ParticleNet inferece +from Configuration.Eras.Modifier_run3_common_cff import run3_common +_pfBTaggingTask_particleNet = pfBTaggingTask.copy() +_pfBTaggingTask_particleNet.add( pfParticleNetAK4TaskForRECO, pfParticleNetTask ) +run3_common.toReplaceWith( pfBTaggingTask, _pfBTaggingTask_particleNet) diff --git a/RecoBTag/ONNXRuntime/python/pfParticleNetAK4_cff.py b/RecoBTag/ONNXRuntime/python/pfParticleNetAK4_cff.py index 03c789b10f5eb..c491818716d2f 100644 --- a/RecoBTag/ONNXRuntime/python/pfParticleNetAK4_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfParticleNetAK4_cff.py @@ -5,12 +5,18 @@ from RecoBTag.ONNXRuntime.pfParticleNetAK4DiscriminatorsJetTags_cfi import pfParticleNetAK4DiscriminatorsJetTags pfParticleNetAK4TagInfos = pfDeepBoostedJetTagInfos.clone( + jets = "ak4PFJetsCHS", jet_radius = 0.4, min_jet_pt = 15, min_puppi_wgt = -1, use_puppiP4 = False, ) +pfParticleNetAK4TagInfosForRECO = pfParticleNetAK4TagInfos.clone( + min_jet_pt = 25, + max_jet_eta = 2.5, +) + pfParticleNetAK4JetTags = boostedJetONNXJetTagsProducer.clone( src = 'pfParticleNetAK4TagInfos', preprocess_json = 'RecoBTag/Combined/data/ParticleNetAK4/CHS/V00/preprocess.json', @@ -18,6 +24,17 @@ flav_names = ["probb", "probbb", "probc", "probcc", "probuds", "probg", "probundef", "probpu"], ) +pfParticleNetAK4JetTagsForRECO = pfParticleNetAK4JetTags.clone( + src = 'pfParticleNetAK4TagInfosForRECO', +) + +pfParticleNetAK4DiscriminatorsJetTagsForRECO = pfParticleNetAK4DiscriminatorsJetTags.clone() +for discriminator in pfParticleNetAK4DiscriminatorsJetTagsForRECO.discriminators: + for num in discriminator.numerator: + num.setModuleLabel("pfParticleNetAK4JetTagsForRECO"); + for den in discriminator.denominator: + den.setModuleLabel("pfParticleNetAK4JetTagsForRECO"); + from CommonTools.PileupAlgos.Puppi_cff import puppi from CommonTools.RecoAlgos.primaryVertexAssociation_cfi import primaryVertexAssociation @@ -25,6 +42,9 @@ pfParticleNetAK4Task = cms.Task(puppi, primaryVertexAssociation, pfParticleNetAK4TagInfos, pfParticleNetAK4JetTags, pfParticleNetAK4DiscriminatorsJetTags) +pfParticleNetAK4TaskForRECO = cms.Task(puppi, primaryVertexAssociation, pfParticleNetAK4TagInfosForRECO, + pfParticleNetAK4JetTagsForRECO, pfParticleNetAK4DiscriminatorsJetTagsForRECO) + # declare all the discriminators # probs _pfParticleNetAK4JetTagsProbs = ['pfParticleNetAK4JetTags:' + flav_name