From 2022b462b416b370bf982a86f316f83a2c8cb33a Mon Sep 17 00:00:00 2001 From: Sebastien Wertz Date: Wed, 9 Nov 2022 16:39:33 +0100 Subject: [PATCH] restore BTagSFProducer.cc file for running V10 --- .../NanoAOD/plugins/BTagSFProducer.cc | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 PhysicsTools/NanoAOD/plugins/BTagSFProducer.cc diff --git a/PhysicsTools/NanoAOD/plugins/BTagSFProducer.cc b/PhysicsTools/NanoAOD/plugins/BTagSFProducer.cc new file mode 100644 index 0000000000000..614aa3b6afb7d --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/BTagSFProducer.cc @@ -0,0 +1,241 @@ +// -*- C++ -*- +// +// Original Author: Spandan Mondal +// Created: Tue, 13 Mar 2018 09:26:52 GMT +// +// +// NOTE: this file is deprecated and only kept for compatibility when running the +// frozen nanoAOD V10 config + +// 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/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/NanoAOD/interface/FlatTable.h" + +#include "CommonTools/Utils/interface/StringObjectFunction.h" +#include "DataFormats/Common/interface/ValueMap.h" + +#include "CondFormats/BTauObjects/interface/BTagCalibration.h" +#include "CondTools/BTau/interface/BTagCalibrationReader.h" + +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" + +#include +#include + +class BTagSFProducer : public edm::stream::EDProducer<> { +public: + BTagSFProducer(const edm::ParameterSet& iConfig) + : src_(consumes>(iConfig.getParameter("src"))), + cut_(iConfig.getParameter("cut")), + discNames_(iConfig.getParameter>("discNames")), + discShortNames_(iConfig.getParameter>("discShortNames")), + weightFiles_(iConfig.getParameter>("weightFiles")), + operatingPoints_(iConfig.getParameter>("operatingPoints")), + measurementTypesB_(iConfig.getParameter>("measurementTypesB")), + measurementTypesC_(iConfig.getParameter>("measurementTypesC")), + measurementTypesUDSG_(iConfig.getParameter>("measurementTypesUDSG")), + sysTypes_(iConfig.getParameter>("sysTypes")) { + produces(); + + nDiscs = discNames_.size(); + assert(discShortNames_.size() == nDiscs && weightFiles_.size() == nDiscs && operatingPoints_.size() == nDiscs && + measurementTypesB_.size() == nDiscs && measurementTypesC_.size() == nDiscs && + measurementTypesUDSG_.size() == nDiscs && sysTypes_.size() == nDiscs); + + bool validate = iConfig.getUntrackedParameter("validate"); + for (unsigned int iDisc = 0; iDisc < nDiscs; ++iDisc) { + if (weightFiles_[iDisc] != "unavailable") { + // setup calibration + BTagCalibration calib; + edm::FileInPath fip(weightFiles_[iDisc]); + calib = BTagCalibration(discShortNames_[iDisc], fip.fullPath(), validate); + + // determine op + std::string opname; + if (operatingPoints_[iDisc] == "0" || operatingPoints_[iDisc] == "loose") { + op = BTagEntry::OP_LOOSE; + opname = "loose"; + } else if (operatingPoints_[iDisc] == "1" || operatingPoints_[iDisc] == "medium") { + op = BTagEntry::OP_MEDIUM; + opname = "medium"; + } else if (operatingPoints_[iDisc] == "2" || operatingPoints_[iDisc] == "tight") { + op = BTagEntry::OP_TIGHT; + opname = "tight"; + } else if (operatingPoints_[iDisc] == "3" || operatingPoints_[iDisc] == "reshaping") { + op = BTagEntry::OP_RESHAPING; + opname = "discriminator reshaping"; + } + + // setup reader + BTagCalibrationReader reader; + reader = BTagCalibrationReader(op, sysTypes_[iDisc]); + reader.load(calib, BTagEntry::FLAV_B, measurementTypesB_[iDisc]); + reader.load(calib, BTagEntry::FLAV_C, measurementTypesC_[iDisc]); + reader.load(calib, BTagEntry::FLAV_UDSG, measurementTypesUDSG_[iDisc]); + + //calibs.push_back(calib); + readers.push_back(reader); + + // report + edm::LogInfo("BTagSFProducer") << "Loaded " + discShortNames_[iDisc] + " SFs from weight file " + + weightFiles_[iDisc] + " with\noperating point: " + opname + + ",\nmeasurement type: B=" + measurementTypesB_[iDisc] + + ", C=" + measurementTypesC_[iDisc] + + ", UDSG=" + measurementTypesUDSG_[iDisc] + + ",\nsystematic type: " + sysTypes_[iDisc] + ".\n" + << std::endl; + + // find if multiple MiniAOD branches need to be summed up (e.g., DeepCSV b+bb) and separate them using '+' delimiter from config + std::stringstream dName(discNames_[iDisc]); + std::string branch; + std::vector branches; + while (std::getline(dName, branch, '+')) { + branches.push_back(branch); + } + inBranchNames.push_back(branches); + } else { + //BTagCalibration calib; + BTagCalibrationReader reader; + //calibs.push_back(calib); //dummy, so that index of vectors still match + readers.push_back(reader); //dummy, so that index of vectors still match + std::vector branches; + branches.push_back(""); + inBranchNames.push_back(branches); + + // report + edm::LogWarning("BTagSFProducer") + << "Skipped loading BTagCalibration for " + discShortNames_[iDisc] + + " as it was marked as unavailable in the configuration file. Event weights will not be stored.\n" + << std::endl; + } + } + } + + ~BTagSFProducer() override{}; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("src")->setComment("input AK4 jet collection"); + desc.add("cut")->setComment("minimum pT and maximum eta cuts for jets"); + desc.add>("discNames")->setComment("name of b-tag discriminator branch in MiniAOD"); + desc.add>("discShortNames")->setComment("common name of discriminator"); + desc.add>("weightFiles")->setComment("path to the .csv file containing the SFs"); + desc.add>("operatingPoints") + ->setComment("loose = 0, medium = 1, tight = 2, disriminator reshaping = 3"); + desc.add>("measurementTypesB") + ->setComment("e.g. \"ttbar\", \"comb\", \"incl\", \"iterativefit\" for b jets"); + desc.add>("measurementTypesC") + ->setComment("e.g. \"ttbar\", \"comb\", \"incl\", \"iterativefit\" for c jets"); + desc.add>("measurementTypesUDSG") + ->setComment("e.g. \"ttbar\", \"comb\", \"incl\", \"iterativefit\" for light jets"); + desc.add>("sysTypes") + ->setComment( + "\"up\", \"central\", \"down\", but arbitrary strings possible, like \"up_generator\" or \"up_jec\""); + desc.addUntracked("validate", false)->setComment("validate the function expressions in the weightFiles"); + descriptions.add("BTagWeightTable", desc); + } + +private: + void produce(edm::Event&, const edm::EventSetup&) override; + + edm::EDGetTokenT> src_; + const StringCutObjectSelector cut_; + + std::vector discNames_; + std::vector discShortNames_; + std::vector weightFiles_; + std::vector operatingPoints_; + std::vector measurementTypesB_; + std::vector measurementTypesC_; + std::vector measurementTypesUDSG_; + std::vector sysTypes_; + + BTagEntry::OperatingPoint op; + std::vector> inBranchNames; + //std::vector calibs; + std::vector readers; + unsigned int nDiscs; +}; + +// ------------ method called to produce the data ------------ +void BTagSFProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + using namespace edm; + using namespace std; + + Handle jets; + iEvent.getByToken(src_, jets); + + double pt; + double eta; + int flavour; + double bdisc; + double SF; + + double EventWt; + + auto out = std::make_unique(1, "btagWeight", true); + out->setDoc("b-tagging event weights"); + + for (unsigned int iDisc = 0; iDisc < nDiscs; ++iDisc) { // loop over b-tagging algorithms + + if (weightFiles_[iDisc] != "unavailable") { + EventWt = 1.; + for (const pat::Jet& jet : *jets) { // loop over jets and accumulate product of SF for each jet + pt = jet.pt(); + eta = jet.eta(); + bdisc = 0.; + + if (op == BTagEntry::OP_RESHAPING) { + for (const string& inBranch : + inBranchNames[iDisc]) { //sum up the discriminator values if multiple, e.g. DeepCSV b+bb + bdisc += jet.bDiscriminator(inBranch); + } + } + + flavour = jet.hadronFlavour(); + + if (cut_(jet)) { //multiply SF of only the jets that pass the cut + if (fabs(flavour) == 5) { // b jets + SF = readers[iDisc].eval_auto_bounds(sysTypes_[iDisc], BTagEntry::FLAV_B, eta, pt, bdisc); + } else if (fabs(flavour) == 4) { // c jets + SF = readers[iDisc].eval_auto_bounds(sysTypes_[iDisc], BTagEntry::FLAV_C, eta, pt, bdisc); + } else { // others + SF = readers[iDisc].eval_auto_bounds(sysTypes_[iDisc], BTagEntry::FLAV_UDSG, eta, pt, bdisc); + } + } else { + SF = 1.; + } + + if (SF == 0.) { // default value of SF is set to 1 in case BTagCalibration returns 0 + //no need to log this as could be pretty common, leaving the cout commented in case this is needed by the author for simple debugging + //cout << discShortNames_[iDisc]+" SF not found for jet with pT="+to_string(pt)+", eta="+to_string(eta)+", discValue="+to_string(bdisc)+", flavour="+to_string(flavour) +". Setting SF to 1." << endl; + SF = 1.; + } + + EventWt *= SF; + } + + out->addColumnValue(discShortNames_[iDisc], EventWt, "b-tag event weight for " + discShortNames_[iDisc]); + } + } + + iEvent.put(move(out)); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(BTagSFProducer);