File indexing completed on 2024-04-06 12:18:31
0001 #ifndef HLTrigger_JetMET_HLTL1TMatchedJetsVBFFilter_h
0002 #define HLTrigger_JetMET_HLTL1TMatchedJetsVBFFilter_h
0003
0004 #include "FWCore/Framework/interface/Frameworkfwd.h"
0005 #include "FWCore/Framework/interface/Event.h"
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0008 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0010 #include "FWCore/Utilities/interface/Exception.h"
0011 #include "DataFormats/Common/interface/Ref.h"
0012 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
0013 #include "DataFormats/HLTReco/interface/TriggerTypeDefs.h"
0014 #include "DataFormats/Math/interface/deltaR.h"
0015 #include "HLTrigger/HLTcore/interface/HLTFilter.h"
0016
0017 #include <vector>
0018 #include <utility>
0019 #include <string>
0020
0021 template <typename T>
0022 class HLTL1TMatchedJetsVBFFilter : public HLTFilter {
0023 public:
0024 explicit HLTL1TMatchedJetsVBFFilter(const edm::ParameterSet&);
0025 ~HLTL1TMatchedJetsVBFFilter() override = default;
0026
0027 bool hltFilter(edm::Event& iEvent,
0028 const edm::EventSetup& iSetup,
0029 trigger::TriggerFilterObjectWithRefs& filterproduct) const override;
0030
0031 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0032
0033 private:
0034 auto logTrace() const {
0035 auto const& moduleType = moduleDescription().moduleName();
0036 auto const& moduleLabel = moduleDescription().moduleLabel();
0037 return LogTrace(moduleType) << "[" << moduleType << "] (" << moduleLabel << ") ";
0038 }
0039
0040 enum Algorithm { VBF = 0, VBFPlus2CentralJets = 1 };
0041
0042 Algorithm getAlgorithmFromString(std::string const& str) const;
0043 void fillJetIndices(std::vector<unsigned int>& outputJetIndices,
0044 std::vector<T> const& jets,
0045 std::vector<unsigned int> const& jetIndices,
0046 double const pt1,
0047 double const pt3,
0048 double const mjj) const;
0049
0050
0051 edm::InputTag const jetTag_;
0052 edm::EDGetTokenT<std::vector<T>> const jetToken_;
0053
0054
0055 bool const matchJetsByDeltaR_;
0056 double const maxJetDeltaR_, maxJetDeltaR2_;
0057 edm::EDGetTokenT<trigger::TriggerFilterObjectWithRefs> const l1tJetRefsToken_;
0058
0059
0060 Algorithm const algorithm_;
0061 double const minPt1_;
0062 double const minPt2_;
0063 double const minPt3_;
0064 double const minInvMass_;
0065
0066
0067 int const minNJets_;
0068 int const maxNJets_;
0069 int const triggerType_;
0070 };
0071
0072 template <typename T>
0073 void HLTL1TMatchedJetsVBFFilter<T>::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0074 edm::ParameterSetDescription desc;
0075 makeHLTFilterDescription(desc);
0076 desc.add<edm::InputTag>("src", edm::InputTag("hltJets"))->setComment("InputTag of input HLT jets");
0077
0078 desc.add<bool>("matchJetsByDeltaR", true)
0079 ->setComment("Enable delta-R matching between HLT jets ('src') and L1T jets ('l1tJetRefs')");
0080 desc.add<double>("maxJetDeltaR", 0.5)
0081 ->setComment(
0082 "Maximum delta-R distance to match HLT jets ('src') and L1T jets ('l1tJetRefs'), "
0083 "used only if 'matchJetsByDeltaR == true'.");
0084 desc.add<edm::InputTag>("l1tJetRefs", edm::InputTag("hltL1sJetSeed"))
0085 ->setComment("InputTag of references to L1T jets");
0086
0087 desc.add<std::string>("algorithm", "VBF")
0088 ->setComment("Keyword to choose the algorithm used to select jets compatible with the VBF topology");
0089 desc.add<double>("minPt1", 110.)
0090 ->setComment("Minimum pT threshold 'pt1' in algorithm to select VBF jets (must respect 'pt2 <= pt3 <= pt1')");
0091 desc.add<double>("minPt2", 35.)->setComment("Minimum pT of all selected VBF jets (must respect 'pt2 <= pt3 <= pt1')");
0092 desc.add<double>("minPt3", 110.)
0093 ->setComment("Minimum pT threshold 'pt3' in algorithm to select VBF jets (must respect 'pt2 <= pt3 <= pt1')");
0094 desc.add<double>("minInvMass", 650.)->setComment("Minimum jet invariant mass");
0095
0096 desc.add<int>("minNJets", 0)->setComment("Minimum number of output jets to accept the event (ignored if negative)");
0097 desc.add<int>("maxNJets", -1)->setComment("Maximum number of output jets to accept the event (ignored if negative)");
0098
0099 desc.add<int>("triggerType", trigger::TriggerJet);
0100
0101 descriptions.setComment(
0102 "This HLTFilter selects events with HLT jets compatible with the VBF topology. "
0103 "These HLT jets can be required to be matched to L1T jets by delta-R distance.");
0104 descriptions.addWithDefaultLabel(desc);
0105 }
0106
0107 template <typename T>
0108 HLTL1TMatchedJetsVBFFilter<T>::HLTL1TMatchedJetsVBFFilter(const edm::ParameterSet& iConfig)
0109 : HLTFilter(iConfig),
0110 jetTag_(iConfig.getParameter<edm::InputTag>("src")),
0111 jetToken_(consumes(jetTag_)),
0112 matchJetsByDeltaR_(iConfig.getParameter<bool>("matchJetsByDeltaR")),
0113 maxJetDeltaR_(iConfig.getParameter<double>("maxJetDeltaR")),
0114 maxJetDeltaR2_(maxJetDeltaR_ * maxJetDeltaR_),
0115 l1tJetRefsToken_(matchJetsByDeltaR_ ? consumes<trigger::TriggerFilterObjectWithRefs>(
0116 iConfig.getParameter<edm::InputTag>("l1tJetRefs"))
0117 : edm::EDGetTokenT<trigger::TriggerFilterObjectWithRefs>()),
0118 algorithm_(getAlgorithmFromString(iConfig.getParameter<std::string>("algorithm"))),
0119 minPt1_(iConfig.getParameter<double>("minPt1")),
0120 minPt2_(iConfig.getParameter<double>("minPt2")),
0121 minPt3_(iConfig.getParameter<double>("minPt3")),
0122 minInvMass_(iConfig.getParameter<double>("minInvMass")),
0123 minNJets_(iConfig.getParameter<int>("minNJets")),
0124 maxNJets_(iConfig.getParameter<int>("maxNJets")),
0125 triggerType_(iConfig.getParameter<int>("triggerType")) {
0126
0127 if (matchJetsByDeltaR_ and maxJetDeltaR_ < 0) {
0128 throw cms::Exception("InvalidConfigurationParameter")
0129 << "invalid value for parameter \"maxJetDeltaR\" (must be > 0): " << maxJetDeltaR_;
0130 }
0131
0132
0133 if (minPt2_ > minPt1_) {
0134 throw cms::Exception("InvalidConfigurationParameter")
0135 << "minPt1 (" << minPt1_ << ") must not be smaller than minPt2 (" << minPt2_ << ")";
0136 } else if (minPt3_ > minPt1_) {
0137 throw cms::Exception("InvalidConfigurationParameter")
0138 << "minPt1 (" << minPt1_ << ") must not be smaller than minPt3 (" << minPt3_ << ")";
0139 } else if (minPt2_ > minPt3_) {
0140 throw cms::Exception("InvalidConfigurationParameter")
0141 << "minPt3 (" << minPt3_ << ") must not be smaller than minPt2 (" << minPt2_ << ")";
0142 }
0143 }
0144
0145 template <typename T>
0146 typename HLTL1TMatchedJetsVBFFilter<T>::Algorithm HLTL1TMatchedJetsVBFFilter<T>::getAlgorithmFromString(
0147 std::string const& str) const {
0148 if (str == "VBF") {
0149 return Algorithm::VBF;
0150 } else if (str == "VBFPlus2CentralJets") {
0151 return Algorithm::VBFPlus2CentralJets;
0152 }
0153
0154 throw cms::Exception("HLTL1TMatchedJetsVBFFilterInvalidAlgorithmName")
0155 << "invalid value for argument of getAlgorithmFromString method: " << str
0156 << " (valid values are \"VBF\" and \"VBFPlus2CentralJets\")";
0157 }
0158
0159 template <typename T>
0160 void HLTL1TMatchedJetsVBFFilter<T>::fillJetIndices(std::vector<unsigned int>& outputJetIndices,
0161 std::vector<T> const& jets,
0162 std::vector<unsigned int> const& jetIndices,
0163 double const pt1,
0164 double const pt3,
0165 double const mjj) const {
0166
0167 outputJetIndices.clear();
0168
0169
0170 int i1 = -1;
0171 int i2 = -1;
0172 double m2jj_max = -1;
0173
0174 for (unsigned int i = 0; i < jetIndices.size(); i++) {
0175 auto const& jet1 = jets[jetIndices[i]];
0176
0177 for (unsigned int j = i + 1; j < jetIndices.size(); j++) {
0178 auto const& jet2 = jets[jetIndices[j]];
0179
0180 double const m2jj_tmp = (jet1.p4() + jet2.p4()).M2();
0181
0182 if (m2jj_tmp > m2jj_max) {
0183 m2jj_max = m2jj_tmp;
0184 i1 = jetIndices[i];
0185 i2 = jetIndices[j];
0186 }
0187 }
0188 }
0189
0190
0191 if (i1 >= 0 and i2 >= 0) {
0192 logTrace() << "dijet pair with highest invariant mass: indices={" << i1 << "," << i2 << "} mjj^2=" << m2jj_max;
0193
0194 unsigned int const j1 = i1;
0195 unsigned int const j2 = i2;
0196
0197 auto const& jet1 = jets[j1];
0198 double const m2jj = (mjj >= 0. ? mjj * mjj : -1.);
0199
0200
0201 if (algorithm_ == Algorithm::VBF) {
0202 if (m2jj_max > m2jj) {
0203 if (jet1.pt() >= pt1) {
0204 outputJetIndices = {j1, j2};
0205 } else if (jet1.pt() < pt3 and jets[jetIndices[0]].pt() > pt3) {
0206 outputJetIndices = {j1, j2, jetIndices[0]};
0207 }
0208 }
0209 } else if (algorithm_ == Algorithm::VBFPlus2CentralJets) {
0210 if (jetIndices.size() > 3 and m2jj_max > m2jj) {
0211
0212 std::vector<unsigned int> idx_jets;
0213 idx_jets.reserve(jetIndices.size() - 2);
0214
0215 for (auto const idx : jetIndices) {
0216 if (idx == j1 or idx == j2)
0217 continue;
0218 idx_jets.emplace_back(idx);
0219 }
0220
0221 if (jet1.pt() >= pt3) {
0222 outputJetIndices.emplace_back(j1);
0223 outputJetIndices.emplace_back(j2);
0224
0225 for (auto const idx : idx_jets) {
0226 if (outputJetIndices.size() > 3)
0227 break;
0228 outputJetIndices.emplace_back(idx);
0229 }
0230 } else if (idx_jets.size() >= 3) {
0231 outputJetIndices.emplace_back(j1);
0232 outputJetIndices.emplace_back(j2);
0233 outputJetIndices.emplace_back(idx_jets[0]);
0234 outputJetIndices.emplace_back(idx_jets[1]);
0235 outputJetIndices.emplace_back(idx_jets[2]);
0236
0237 if (idx_jets.size() > 3) {
0238 outputJetIndices.emplace_back(idx_jets[3]);
0239 }
0240 }
0241 }
0242 }
0243 }
0244 }
0245
0246 template <typename T>
0247 bool HLTL1TMatchedJetsVBFFilter<T>::hltFilter(edm::Event& iEvent,
0248 const edm::EventSetup&,
0249 trigger::TriggerFilterObjectWithRefs& filterproduct) const {
0250 if (saveTags())
0251 filterproduct.addCollectionTag(jetTag_);
0252
0253
0254 auto const& jetsHandle = iEvent.getHandle(jetToken_);
0255
0256
0257 std::vector<unsigned int> jetIndices;
0258
0259 if (matchJetsByDeltaR_) {
0260
0261 l1t::JetVectorRef l1tJetRefs;
0262 iEvent.get(l1tJetRefsToken_).getObjects(trigger::TriggerL1Jet, l1tJetRefs);
0263
0264 jetIndices.reserve(jetsHandle->size());
0265 for (unsigned int iJet = 0; iJet < jetsHandle->size(); ++iJet) {
0266 auto const& jet = (*jetsHandle)[iJet];
0267
0268 if (jet.pt() <= minPt2_)
0269 continue;
0270
0271 for (unsigned int l1tJetIdx = 0; l1tJetIdx < l1tJetRefs.size(); ++l1tJetIdx) {
0272 if (reco::deltaR2(jet.p4(), l1tJetRefs[l1tJetIdx]->p4()) < maxJetDeltaR2_) {
0273 logTrace() << "input jet: index=" << iJet << " pt=" << jet.pt() << " eta=" << jet.eta()
0274 << " phi=" << jet.phi() << " mass=" << jet.mass()
0275 << " (matched to L1T jet with pt=" << l1tJetRefs[l1tJetIdx]->pt()
0276 << " eta=" << l1tJetRefs[l1tJetIdx]->eta() << " phi=" << l1tJetRefs[l1tJetIdx]->phi()
0277 << " mass=" << l1tJetRefs[l1tJetIdx]->mass() << ")";
0278
0279 jetIndices.emplace_back(iJet);
0280 break;
0281 }
0282 }
0283 }
0284 } else {
0285 jetIndices.reserve(jetsHandle->size());
0286 for (unsigned int iJet = 0; iJet < jetsHandle->size(); ++iJet) {
0287 auto const& jet = (*jetsHandle)[iJet];
0288
0289 if (jet.pt() <= minPt2_)
0290 continue;
0291
0292 logTrace() << "input jet: index=" << iJet << " pt=" << jet.pt() << " eta=" << jet.eta() << " phi=" << jet.phi()
0293 << " mass=" << jet.mass();
0294
0295 jetIndices.emplace_back(iJet);
0296 }
0297 }
0298
0299
0300 std::sort(jetIndices.begin(), jetIndices.end(), [&jetsHandle](unsigned int const i1, unsigned int const i2) {
0301 return (*jetsHandle)[i1].pt() > (*jetsHandle)[i2].pt();
0302 });
0303
0304
0305 std::vector<unsigned int> outputJetIndices;
0306 fillJetIndices(outputJetIndices, *jetsHandle, jetIndices, minPt1_, minPt3_, minInvMass_);
0307
0308
0309 for (auto const idx : outputJetIndices) {
0310 filterproduct.addObject(triggerType_, edm::Ref<std::vector<T>>(jetsHandle, idx));
0311
0312 logTrace() << "output jet: index=" << idx << " pt=" << (*jetsHandle)[idx].pt()
0313 << " eta=" << (*jetsHandle)[idx].eta() << " phi=" << (*jetsHandle)[idx].phi()
0314 << " mass=" << (*jetsHandle)[idx].mass();
0315 }
0316
0317
0318 auto const ret = ((minNJets_ < 0 or outputJetIndices.size() >= (unsigned int)minNJets_) and
0319 (maxNJets_ < 0 or outputJetIndices.size() <= (unsigned int)maxNJets_));
0320
0321 logTrace() << "filter decision = " << ret << " (trigger objects = " << outputJetIndices.size() << ")";
0322
0323 return ret;
0324 }
0325
0326 #endif