File indexing completed on 2023-04-28 04:48:37
0001 #include "FWCore/Framework/interface/stream/EDProducer.h"
0002 #include "FWCore/Framework/interface/Event.h"
0003 #include "FWCore/Framework/interface/EventSetup.h"
0004 #include "FWCore/Utilities/interface/InputTag.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 #include "DataFormats/PatCandidates/interface/Tau.h"
0007 #include "DataFormats/PatCandidates/interface/Jet.h"
0008 #include "FWCore/Utilities/interface/transform.h"
0009 #include "DataFormats/JetReco/interface/GenJetCollection.h"
0010 #include "RecoTauTag/RecoTau/interface/RecoTauCommonUtilities.h"
0011 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0012 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0013
0014 class PATTauHybridProducer : public edm::stream::EDProducer<> {
0015 public:
0016 explicit PATTauHybridProducer(const edm::ParameterSet&);
0017 ~PATTauHybridProducer() override{};
0018
0019 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0020 void produce(edm::Event&, const edm::EventSetup&) override;
0021
0022 private:
0023 void fillTauFromJet(reco::PFTau& pfTau, const reco::JetBaseRef& jet);
0024
0025 edm::EDGetTokenT<pat::TauCollection> tausToken_;
0026 edm::EDGetTokenT<pat::JetCollection> jetsToken_;
0027 bool addGenJetMatch_;
0028 edm::EDGetTokenT<edm::Association<reco::GenJetCollection>> genJetMatchToken_;
0029 const float dR2Max_, jetPtMin_, jetEtaMax_;
0030 const std::string pnetLabel_;
0031 std::vector<std::string> pnetTauScoreNames_;
0032 std::vector<std::string> pnetJetScoreNames_;
0033 std::vector<std::string> pnetLepScoreNames_;
0034 std::string pnetPtCorrName_;
0035 const float tauScoreMin_, vsJetMin_, chargeAssignmentProbMin_;
0036 const bool checkTauScoreIsBest_;
0037 const bool usePFLeptonsAsChargedHadrons_;
0038
0039 const std::map<std::string, int> tagToDM_;
0040 enum class tauId_pnet_idx : size_t { dm = 0, vsjet, vse, vsmu, ptcorr, qconf, pdm0, pdm1, pdm2, pdm10, pdm11, last };
0041 enum class tauId_min_idx : size_t { hpsnew = 0, last };
0042 };
0043
0044 PATTauHybridProducer::PATTauHybridProducer(const edm::ParameterSet& cfg)
0045 : tausToken_(consumes<pat::TauCollection>(cfg.getParameter<edm::InputTag>("src"))),
0046 jetsToken_(consumes<pat::JetCollection>(cfg.getParameter<edm::InputTag>("jetSource"))),
0047 addGenJetMatch_(cfg.getParameter<bool>("addGenJetMatch")),
0048 dR2Max_(std::pow(cfg.getParameter<double>("dRMax"), 2)),
0049 jetPtMin_(cfg.getParameter<double>("jetPtMin")),
0050 jetEtaMax_(cfg.getParameter<double>("jetEtaMax")),
0051 pnetLabel_(cfg.getParameter<std::string>("pnetLabel")),
0052 pnetPtCorrName_(cfg.getParameter<std::string>("pnetPtCorrName")),
0053 tauScoreMin_(cfg.getParameter<double>("tauScoreMin")),
0054 vsJetMin_(cfg.getParameter<double>("vsJetMin")),
0055 chargeAssignmentProbMin_(cfg.getParameter<double>("chargeAssignmentProbMin")),
0056 checkTauScoreIsBest_(cfg.getParameter<bool>("checkTauScoreIsBest")),
0057 usePFLeptonsAsChargedHadrons_(cfg.getParameter<bool>("usePFLeptonsAsChargedHadrons")),
0058 tagToDM_({{"1h0p", 0}, {"1h1or2p", 1}, {"1h1p", 1}, {"1h2p", 2}, {"3h0p", 10}, {"3h1p", 11}}) {
0059
0060 std::vector<std::string> pnetScoreNames = cfg.getParameter<std::vector<std::string>>("pnetScoreNames");
0061 for (const auto& scoreName : pnetScoreNames) {
0062 size_t labelLenght = scoreName.find(':') == std::string::npos ? 0 : scoreName.find(':') + 1;
0063 std::string name = scoreName.substr(labelLenght);
0064 if (name.find("prob") == std::string::npos)
0065 continue;
0066 if (name.find("tau") != std::string::npos)
0067 pnetTauScoreNames_.push_back(name);
0068 else if (name.find("ele") != std::string::npos || name.find("mu") != std::string::npos)
0069 pnetLepScoreNames_.push_back(name);
0070 else
0071 pnetJetScoreNames_.push_back(name);
0072 if (pnetPtCorrName_.find(':') != std::string::npos)
0073 pnetPtCorrName_ = pnetPtCorrName_.substr(pnetPtCorrName_.find(':') + 1);
0074
0075 if (addGenJetMatch_) {
0076 genJetMatchToken_ =
0077 consumes<edm::Association<reco::GenJetCollection>>(cfg.getParameter<edm::InputTag>("genJetMatch"));
0078 }
0079 }
0080
0081 produces<std::vector<pat::Tau>>();
0082
0083 }
0084
0085 void PATTauHybridProducer::produce(edm::Event& evt, const edm::EventSetup& es) {
0086
0087 edm::Handle<pat::TauCollection> inputTaus;
0088 evt.getByToken(tausToken_, inputTaus);
0089
0090 auto outputTaus = std::make_unique<std::vector<pat::Tau>>();
0091 outputTaus->reserve(inputTaus->size());
0092
0093
0094 edm::Handle<pat::JetCollection> jets;
0095 evt.getByToken(jetsToken_, jets);
0096
0097
0098 if (evt.isRealData()) {
0099 addGenJetMatch_ = false;
0100 }
0101 edm::Handle<edm::Association<reco::GenJetCollection>> genJetMatch;
0102 if (addGenJetMatch_)
0103 evt.getByToken(genJetMatchToken_, genJetMatch);
0104
0105
0106 std::vector<pat::Tau::IdPair> tauIds_minimal((size_t)tauId_min_idx::last);
0107 tauIds_minimal[(size_t)tauId_min_idx::hpsnew] = std::make_pair("decayModeFindingNewDMs", -1);
0108
0109
0110 std::vector<pat::Tau::IdPair> tauIds_pnet((size_t)tauId_pnet_idx::last);
0111 tauIds_pnet[(size_t)tauId_pnet_idx::dm] = std::make_pair("byPNetDecayMode", reco::PFTau::kNull);
0112 tauIds_pnet[(size_t)tauId_pnet_idx::vsjet] = std::make_pair("byPNetVSjetraw", -1);
0113 tauIds_pnet[(size_t)tauId_pnet_idx::vse] = std::make_pair("byPNetVSeraw", -1);
0114 tauIds_pnet[(size_t)tauId_pnet_idx::vsmu] = std::make_pair("byPNetVSmuraw", -1);
0115 tauIds_pnet[(size_t)tauId_pnet_idx::ptcorr] = std::make_pair("byPNetPtCorr", 1);
0116 tauIds_pnet[(size_t)tauId_pnet_idx::qconf] = std::make_pair("byPNetQConf", 0);
0117 tauIds_pnet[(size_t)tauId_pnet_idx::pdm0] = std::make_pair("byPNetProb1h0pi0", -1);
0118 tauIds_pnet[(size_t)tauId_pnet_idx::pdm1] = std::make_pair("byPNetProb1h1pi0", -1);
0119 tauIds_pnet[(size_t)tauId_pnet_idx::pdm2] = std::make_pair("byPNetProb1h2pi0", -1);
0120 tauIds_pnet[(size_t)tauId_pnet_idx::pdm10] = std::make_pair("byPNetProb3h0pi0", -1);
0121 tauIds_pnet[(size_t)tauId_pnet_idx::pdm11] = std::make_pair("byPNetProb3h1pi0", -1);
0122
0123 std::set<unsigned int> matched_taus;
0124 size_t jet_idx = 0;
0125 for (const auto& jet : *jets) {
0126 jet_idx++;
0127 if (jet.pt() < jetPtMin_)
0128 continue;
0129 if (std::abs(jet.eta()) > jetEtaMax_)
0130 continue;
0131 size_t tau_idx = 0;
0132 bool matched = false;
0133
0134
0135 std::pair<std::string, float> bestPnetTauScore("probtauundef", -1);
0136 float sumOfPnetTauScores = 0;
0137 std::vector<float> tauPerDMScores(5);
0138 float plusChargeProb = 0;
0139 for (const auto& scoreName : pnetTauScoreNames_) {
0140 float score = jet.bDiscriminator(pnetLabel_ + ":" + scoreName);
0141 sumOfPnetTauScores += score;
0142 if (scoreName.find("taup") != std::string::npos)
0143 plusChargeProb += score;
0144 if (score > bestPnetTauScore.second) {
0145 bestPnetTauScore.second = score;
0146 bestPnetTauScore.first = scoreName;
0147 }
0148 if (scoreName.find("1h0p") != std::string::npos)
0149 tauPerDMScores[0] += score;
0150 else if (scoreName.find("1h1") !=
0151 std::string::
0152 npos)
0153 tauPerDMScores[1] += score;
0154 else if (scoreName.find("1h2p") != std::string::npos)
0155 tauPerDMScores[2] += score;
0156 else if (scoreName.find("3h0p") != std::string::npos)
0157 tauPerDMScores[3] += score;
0158 else if (scoreName.find("3h1p") != std::string::npos)
0159 tauPerDMScores[4] += score;
0160 }
0161 if (sumOfPnetTauScores > 0)
0162 plusChargeProb /= sumOfPnetTauScores;
0163
0164 float sumOfPnetEleScores = 0, sumOfPnetMuScores = 0;
0165 bool isTauScoreBest = (sumOfPnetTauScores > 0);
0166 for (const auto& scoreName : pnetLepScoreNames_) {
0167 float score = jet.bDiscriminator(pnetLabel_ + ":" + scoreName);
0168 if (scoreName.find("ele") != std::string::npos)
0169 sumOfPnetEleScores += score;
0170 else if (scoreName.find("mu") != std::string::npos)
0171 sumOfPnetMuScores += score;
0172 if (score > bestPnetTauScore.second)
0173 isTauScoreBest = false;
0174 }
0175 if (checkTauScoreIsBest_ && isTauScoreBest) {
0176 for (const auto& scoreName : pnetJetScoreNames_)
0177 if (jet.bDiscriminator(pnetLabel_ + ":" + scoreName) > bestPnetTauScore.second)
0178 isTauScoreBest = false;
0179 }
0180
0181
0182 tauIds_pnet[(size_t)tauId_pnet_idx::vsjet].second =
0183 sumOfPnetTauScores /
0184 (1. - sumOfPnetEleScores -
0185 sumOfPnetMuScores);
0186 tauIds_pnet[(size_t)tauId_pnet_idx::vse].second =
0187 sumOfPnetTauScores /
0188 (sumOfPnetTauScores + sumOfPnetEleScores);
0189 tauIds_pnet[(size_t)tauId_pnet_idx::vsmu].second =
0190 sumOfPnetTauScores / (sumOfPnetTauScores + sumOfPnetMuScores);
0191
0192
0193 int bestCharge = 0;
0194 size_t pos =
0195 bestPnetTauScore.first.find("tau") + 3;
0196 const char q = (pos < bestPnetTauScore.first.size()) ? bestPnetTauScore.first[pos] : 'u';
0197 if (q == 'm') {
0198 pos++;
0199 bestCharge = -1;
0200 } else if (q == 'p') {
0201 pos++;
0202 bestCharge = 1;
0203 }
0204 auto pNetDM = tagToDM_.find(bestPnetTauScore.first.substr(pos));
0205 if (pNetDM != tagToDM_.end())
0206 tauIds_pnet[(size_t)tauId_pnet_idx::dm].second = pNetDM->second;
0207
0208
0209 float ptcorr = jet.bDiscriminator(pnetLabel_ + ":" + pnetPtCorrName_);
0210 if (ptcorr > -1000.)
0211 tauIds_pnet[(size_t)tauId_pnet_idx::ptcorr].second = ptcorr;
0212
0213
0214 tauIds_pnet[(size_t)tauId_pnet_idx::qconf].second = (plusChargeProb - 0.5);
0215
0216
0217 tauIds_pnet[(size_t)tauId_pnet_idx::pdm0].second = tauPerDMScores[0] / sumOfPnetTauScores;
0218 tauIds_pnet[(size_t)tauId_pnet_idx::pdm1].second = tauPerDMScores[1] / sumOfPnetTauScores;
0219 tauIds_pnet[(size_t)tauId_pnet_idx::pdm2].second = tauPerDMScores[2] / sumOfPnetTauScores;
0220 tauIds_pnet[(size_t)tauId_pnet_idx::pdm10].second = tauPerDMScores[3] / sumOfPnetTauScores;
0221 tauIds_pnet[(size_t)tauId_pnet_idx::pdm11].second = tauPerDMScores[4] / sumOfPnetTauScores;
0222
0223
0224 for (const auto& inputTau : *inputTaus) {
0225 tau_idx++;
0226 if (matched_taus.count(tau_idx - 1) > 0)
0227 continue;
0228 float dR2 = deltaR2(jet, inputTau);
0229
0230 if (dR2 < dR2Max_) {
0231 matched_taus.insert(tau_idx - 1);
0232 pat::Tau outputTau(inputTau);
0233 const size_t nTauIds = inputTau.tauIDs().size();
0234 std::vector<pat::Tau::IdPair> tauIds(nTauIds + tauIds_pnet.size());
0235 for (size_t i = 0; i < nTauIds; ++i)
0236 tauIds[i] = inputTau.tauIDs()[i];
0237 for (size_t i = 0; i < tauIds_pnet.size(); ++i)
0238 tauIds[nTauIds + i] = tauIds_pnet[i];
0239 outputTau.setTauIDs(tauIds);
0240 matched = true;
0241 outputTaus->push_back(outputTau);
0242
0243 break;
0244 }
0245 }
0246 if (matched)
0247 continue;
0248
0249
0250 if ((checkTauScoreIsBest_ && !isTauScoreBest) || bestPnetTauScore.second < tauScoreMin_ ||
0251 tauIds_pnet[(size_t)tauId_pnet_idx::vsjet].second < vsJetMin_ ||
0252 std::abs(0.5 - plusChargeProb) < chargeAssignmentProbMin_)
0253 continue;
0254
0255
0256
0257 reco::PFTau pfTauFromJet(bestCharge, jet.correctedP4("Uncorrected"));
0258
0259 pfTauFromJet.setPdgId(bestCharge < 0 ? 15 : -15);
0260
0261 pfTauFromJet.setDecayMode(
0262 static_cast<const reco::PFTau::hadronicDecayMode>(int(tauIds_pnet[(size_t)tauId_pnet_idx::dm].second)));
0263
0264
0265
0266 pfTauFromJet.setSignalConeSize(
0267 std::clamp(3.6 / jet.correctedP4("Uncorrected").pt(), 0.08, 0.12));
0268 const edm::Ref<pat::JetCollection> jetRef(jets, jet_idx - 1);
0269 fillTauFromJet(pfTauFromJet, reco::JetBaseRef(jetRef));
0270
0271
0272 pat::Tau outputTauFromJet(pfTauFromJet);
0273
0274 std::vector<pat::Tau::IdPair> newtauIds(tauIds_minimal.size() + tauIds_pnet.size());
0275 for (size_t i = 0; i < tauIds_minimal.size(); ++i)
0276 newtauIds[i] = tauIds_minimal[i];
0277 for (size_t i = 0; i < tauIds_pnet.size(); ++i)
0278 newtauIds[tauIds_minimal.size() + i] = tauIds_pnet[i];
0279 outputTauFromJet.setTauIDs(newtauIds);
0280
0281 if (addGenJetMatch_) {
0282 reco::GenJetRef genJetTau = (*genJetMatch)[jetRef];
0283 if (genJetTau.isNonnull() && genJetTau.isAvailable()) {
0284 outputTauFromJet.setGenJet(genJetTau);
0285 }
0286 }
0287 outputTaus->push_back(outputTauFromJet);
0288
0289 }
0290
0291
0292 if (matched_taus.size() < inputTaus->size()) {
0293 for (size_t iTau = 0; iTau < inputTaus->size(); ++iTau) {
0294 if (matched_taus.count(iTau) > 0)
0295 continue;
0296 const pat::Tau& inputTau = inputTaus->at(iTau);
0297 pat::Tau outputTau(inputTau);
0298 const size_t nTauIds = inputTau.tauIDs().size();
0299 std::vector<pat::Tau::IdPair> tauIds(nTauIds + tauIds_pnet.size());
0300 for (size_t i = 0; i < nTauIds; ++i)
0301 tauIds[i] = inputTau.tauIDs()[i];
0302 for (size_t i = 0; i < tauIds_pnet.size(); ++i) {
0303 tauIds[nTauIds + i] = tauIds_pnet[i];
0304 tauIds[nTauIds + i].second =
0305 (i != (size_t)tauId_pnet_idx::ptcorr ? (i != (size_t)tauId_pnet_idx::qconf ? -1 : 0) : 1);
0306 }
0307 outputTau.setTauIDs(tauIds);
0308 outputTaus->push_back(outputTau);
0309 }
0310 }
0311
0312 evt.put(std::move(outputTaus));
0313 }
0314
0315 void PATTauHybridProducer::fillTauFromJet(reco::PFTau& pfTau, const reco::JetBaseRef& jet) {
0316
0317 typedef std::vector<reco::CandidatePtr> CandPtrs;
0318
0319
0320 CandPtrs pfChs, pfChsSig;
0321
0322
0323
0324 if (!usePFLeptonsAsChargedHadrons_) {
0325 pfChs = reco::tau::pfCandidatesByPdgId(*jet, 211);
0326 } else {
0327 pfChs = reco::tau::pfChargedCands(*jet);
0328 }
0329
0330 if (pfTau.charge() == 0 || pfChs.size() == 1) {
0331 pfTau.setleadChargedHadrCand(pfChs[0]);
0332 pfTau.setleadCand(pfChs[0]);
0333 pfChsSig.push_back(pfChs[0]);
0334 pfChs.erase(pfChs.begin());
0335 } else {
0336 for (CandPtrs::iterator it = pfChs.begin(); it != pfChs.end();) {
0337 if ((*it)->charge() == pfTau.charge()) {
0338 pfTau.setleadChargedHadrCand(*it);
0339 pfTau.setleadCand(*it);
0340 pfChsSig.push_back(*it);
0341 it = pfChs.erase(it);
0342 break;
0343 } else {
0344 ++it;
0345 }
0346 }
0347
0348 if (pfTau.leadChargedHadrCand().isNull() && !pfChs.empty()) {
0349 pfTau.setleadChargedHadrCand(pfChs[0]);
0350 pfTau.setleadCand(pfChs[0]);
0351 pfChsSig.push_back(pfChs[0]);
0352 pfChs.erase(pfChs.begin());
0353 }
0354 }
0355
0356
0357 const double dR2Max = std::pow(pfTau.signalConeSize(), 2);
0358 if (pfTau.decayMode() >= reco::PFTau::kThreeProng0PiZero && pfTau.leadChargedHadrCand().isNonnull()) {
0359 for (CandPtrs::iterator it = pfChs.begin(); it != pfChs.end();) {
0360 if (deltaR2((*it)->p4(), pfTau.leadChargedHadrCand()->p4()) < dR2Max) {
0361 pfChsSig.push_back(*it);
0362 it = pfChs.erase(it);
0363 } else {
0364 ++it;
0365 }
0366 }
0367 }
0368
0369 for (CandPtrs::iterator it = pfChs.begin(); it != pfChs.end();) {
0370 if ((*it)->pt() < 0.5 || std::abs((*it)->pdgId()) != 211) {
0371 it = pfChs.erase(it);
0372 } else {
0373 ++it;
0374 }
0375 }
0376
0377 pfTau.setsignalChargedHadrCands(pfChsSig);
0378 pfTau.setisolationChargedHadrCands(pfChs);
0379
0380
0381 CandPtrs pfGammas, pfGammasSig;
0382 pfGammas = reco::tau::pfCandidatesByPdgId(*jet, 22);
0383
0384 if (pfTau.leadChargedHadrCand().isNull() && !pfGammas.empty()) {
0385 pfTau.setleadChargedHadrCand(pfGammas[0]);
0386 pfTau.setleadCand(pfGammas[0]);
0387 pfGammasSig.push_back(pfGammas[0]);
0388 pfChs.erase(pfGammas.begin());
0389 }
0390
0391 for (CandPtrs::iterator it = pfGammas.begin(); it != pfGammas.end();) {
0392 if ((*it)->pt() < 0.5) {
0393 it = pfGammas.erase(it);
0394 } else {
0395 ++it;
0396 }
0397 }
0398
0399
0400 if (pfTau.decayMode() % 5 != 0 && pfTau.leadChargedHadrCand().isNonnull()) {
0401 for (CandPtrs::iterator it = pfGammas.begin(); it != pfGammas.end();) {
0402 if (std::abs((*it)->eta() - pfTau.leadChargedHadrCand()->eta()) <
0403 std::clamp(0.2 * std::pow((*it)->pt(), -0.66), 0.05, 0.15) &&
0404 deltaPhi((*it)->phi(), pfTau.leadChargedHadrCand()->phi()) <
0405 std::clamp(0.35 * std::pow((*it)->pt(), -0.71), 0.05, 0.3)) {
0406 pfGammasSig.push_back(*it);
0407 it = pfGammas.erase(it);
0408 } else {
0409 ++it;
0410 }
0411 }
0412 }
0413
0414 pfTau.setsignalGammaCands(pfGammasSig);
0415 pfTau.setisolationGammaCands(pfGammas);
0416 }
0417
0418 void PATTauHybridProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0419
0420 edm::ParameterSetDescription desc;
0421
0422 desc.add<edm::InputTag>("src", edm::InputTag("slimmedTaus"));
0423 desc.add<edm::InputTag>("jetSource", edm::InputTag("slimmedJetsUpadted"));
0424 desc.add<double>("dRMax", 0.4);
0425 desc.add<double>("jetPtMin", 20.0);
0426 desc.add<double>("jetEtaMax", 2.5);
0427 desc.add<std::string>("pnetLabel", "pfParticleNetAK4JetTags");
0428 desc.add<std::vector<std::string>>(
0429 "pnetScoreNames",
0430 {"probmu", "probele", "probtaup1h0p", "probtaup1h1p", "probtaup1h2p", "probtaup3h0p", "probtaup3h1p",
0431 "probtaum1h0p", "probtaum1h1p", "probtaum1h2p", "probtaum3h0p", "probtaum3h1p", "probb", "probc",
0432 "probuds", "probg", "ptcorr", "ptreshigh", "ptreslow", "ptnu"});
0433 desc.add<std::string>("pnetPtCorrName", "ptcorr");
0434 desc.add<double>("tauScoreMin", -1)->setComment("Minimal value of the best tau score to built recovery tau");
0435 desc.add<double>("vsJetMin", -1)->setComment("Minimal value of PNet tau-vs-jet discriminant to built recovery tau");
0436 desc.add<bool>("checkTauScoreIsBest", false)
0437 ->setComment("If true, recovery tau is built only if one of tau scores is the highest");
0438 desc.add<double>("chargeAssignmentProbMin", 0.2)
0439 ->setComment("Minimal value of charge assignment probability to built recovery tau (0,0.5)");
0440 desc.add<bool>("addGenJetMatch", true)->setComment("add MC genTauJet matching");
0441 desc.add<edm::InputTag>("genJetMatch", edm::InputTag("tauGenJetMatch"));
0442 desc.add<bool>("usePFLeptonsAsChargedHadrons", true)
0443 ->setComment("If true, all charged particles are used as charged hadron candidates");
0444
0445 descriptions.addWithDefaultLabel(desc);
0446 }
0447
0448 #include "FWCore/Framework/interface/MakerMacros.h"
0449
0450 DEFINE_FWK_MODULE(PATTauHybridProducer);