File indexing completed on 2024-10-08 05:11:55
0001
0002 #include <memory>
0003 #include <sstream>
0004
0005
0006 #include "FWCore/Framework/interface/Frameworkfwd.h"
0007 #include "FWCore/Framework/interface/stream/EDProducer.h"
0008
0009 #include "FWCore/Framework/interface/Event.h"
0010 #include "FWCore/Framework/interface/MakerMacros.h"
0011
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 #include "FWCore/Utilities/interface/StreamID.h"
0014
0015 #include "DataFormats/PatCandidates/interface/TriggerObjectStandAlone.h"
0016 #include "DataFormats/L1Trigger/interface/EGamma.h"
0017 #include "DataFormats/L1Trigger/interface/Tau.h"
0018 #include "DataFormats/L1Trigger/interface/Jet.h"
0019 #include "DataFormats/L1Trigger/interface/Muon.h"
0020 #include "DataFormats/L1Trigger/interface/EtSum.h"
0021 #include "DataFormats/HLTReco/interface/TriggerTypeDefs.h"
0022 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0023 #include "CommonTools/Utils/interface/StringObjectFunction.h"
0024 #include "DataFormats/Math/interface/deltaR.h"
0025 #include "DataFormats/NanoAOD/interface/FlatTable.h"
0026
0027 class TriggerObjectTableProducer : public edm::stream::EDProducer<> {
0028 public:
0029 explicit TriggerObjectTableProducer(const edm::ParameterSet &iConfig)
0030 : name_(iConfig.getParameter<std::string>("name")),
0031 src_(consumes<std::vector<pat::TriggerObjectStandAlone>>(iConfig.getParameter<edm::InputTag>("src"))),
0032 l1EG_(consumes<l1t::EGammaBxCollection>(iConfig.getParameter<edm::InputTag>("l1EG"))),
0033 l1Sum_(consumes<l1t::EtSumBxCollection>(iConfig.getParameter<edm::InputTag>("l1Sum"))),
0034 l1Jet_(consumes<l1t::JetBxCollection>(iConfig.getParameter<edm::InputTag>("l1Jet"))),
0035 l1Muon_(consumes<l1t::MuonBxCollection>(iConfig.getParameter<edm::InputTag>("l1Muon"))),
0036 l1Tau_(consumes<l1t::TauBxCollection>(iConfig.getParameter<edm::InputTag>("l1Tau"))) {
0037 edm::ParameterSet selPSet = iConfig.getParameter<edm::ParameterSet>("selections");
0038 const auto selNames = selPSet.getParameterNames();
0039 std::stringstream idstr, qualitystr;
0040 idstr << "ID of the object: ";
0041 for (const auto &name : selNames) {
0042 sels_.emplace_back(selPSet.getParameter<edm::ParameterSet>(name));
0043 const auto &sel = sels_.back();
0044 idstr << sel.id << " = " << name + sel.doc;
0045 if (sels_.size() < selNames.size())
0046 idstr << ", ";
0047 if (!sel.qualityBitsDoc.empty()) {
0048 qualitystr << sel.qualityBitsDoc << " for " << name << "; ";
0049 }
0050 }
0051 idDoc_ = idstr.str();
0052 bitsDoc_ = qualitystr.str();
0053
0054 produces<nanoaod::FlatTable>();
0055 }
0056
0057 ~TriggerObjectTableProducer() override {}
0058
0059 static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0060
0061 private:
0062 void produce(edm::Event &, edm::EventSetup const &) override;
0063
0064 std::string name_;
0065 edm::EDGetTokenT<std::vector<pat::TriggerObjectStandAlone>> src_;
0066 std::string idDoc_, bitsDoc_;
0067
0068 edm::EDGetTokenT<l1t::EGammaBxCollection> l1EG_;
0069 edm::EDGetTokenT<l1t::EtSumBxCollection> l1Sum_;
0070 edm::EDGetTokenT<l1t::JetBxCollection> l1Jet_;
0071 edm::EDGetTokenT<l1t::MuonBxCollection> l1Muon_;
0072 edm::EDGetTokenT<l1t::TauBxCollection> l1Tau_;
0073
0074 struct SelectedObject {
0075 std::string doc;
0076 int id;
0077 StringCutObjectSelector<pat::TriggerObjectStandAlone> cut;
0078 StringCutObjectSelector<pat::TriggerObjectStandAlone> l1cut, l1cut_2, l2cut;
0079 float l1DR2, l1DR2_2, l2DR2;
0080 bool skipObjectsNotPassingQualityBits;
0081 StringObjectFunction<pat::TriggerObjectStandAlone> qualityBits;
0082 std::string qualityBitsDoc;
0083
0084 SelectedObject(const edm::ParameterSet &pset)
0085 : doc(pset.getParameter<std::string>("doc")),
0086 id(pset.getParameter<int>("id")),
0087 cut(pset.getParameter<std::string>("sel")),
0088 l1cut(""),
0089 l1cut_2(""),
0090 l2cut(""),
0091 l1DR2(-1),
0092 l1DR2_2(-1),
0093 l2DR2(-1),
0094 skipObjectsNotPassingQualityBits(pset.getParameter<bool>("skipObjectsNotPassingQualityBits")),
0095 qualityBits("0"),
0096 qualityBitsDoc("")
0097 {
0098 if (!doc.empty()) {
0099 doc = "(" + doc + ")";
0100 }
0101 std::vector<edm::ParameterSet> qualityBitsConfig =
0102 pset.getParameter<std::vector<edm::ParameterSet>>("qualityBits");
0103 std::stringstream qualityBitsFunc;
0104 std::vector<bool> bits(qualityBitsConfig.size(), false);
0105 for (size_t i = 0; i != qualityBitsConfig.size(); ++i) {
0106 if (i != 0) {
0107 qualityBitsFunc << " + ";
0108 qualityBitsDoc += ", ";
0109 }
0110 unsigned int bit = i;
0111 if (qualityBitsConfig[i].existsAs<unsigned int>("bit"))
0112 bit = qualityBitsConfig[i].getParameter<unsigned int>("bit");
0113 assert(!bits[bit] && "a quality bit was inserted twice");
0114 assert(bit < 31 && "quality bits are store on 32 bit");
0115 bits[bit] = true;
0116 qualityBitsFunc << std::to_string(int(pow(2, bit))) << "*("
0117 << qualityBitsConfig[i].getParameter<std::string>("selection") << ")";
0118 qualityBitsDoc += std::to_string(bit) + " => " + qualityBitsConfig[i].getParameter<std::string>("doc");
0119 }
0120 if (!qualityBitsFunc.str().empty()) {
0121
0122
0123 qualityBits = StringObjectFunction<pat::TriggerObjectStandAlone>(qualityBitsFunc.str());
0124 }
0125 if (pset.existsAs<std::string>("l1seed")) {
0126 l1cut = StringCutObjectSelector<pat::TriggerObjectStandAlone>(pset.getParameter<std::string>("l1seed"));
0127 l1DR2 = std::pow(pset.getParameter<double>("l1deltaR"), 2);
0128 }
0129 if (pset.existsAs<std::string>("l1seed_2")) {
0130 l1cut_2 = StringCutObjectSelector<pat::TriggerObjectStandAlone>(pset.getParameter<std::string>("l1seed_2"));
0131 l1DR2_2 = std::pow(pset.getParameter<double>("l1deltaR_2"), 2);
0132 }
0133 if (pset.existsAs<std::string>("l2seed")) {
0134 l2cut = StringCutObjectSelector<pat::TriggerObjectStandAlone>(pset.getParameter<std::string>("l2seed"));
0135 l2DR2 = std::pow(pset.getParameter<double>("l2deltaR"), 2);
0136 }
0137 }
0138
0139 bool match(const pat::TriggerObjectStandAlone &obj) const { return cut(obj); }
0140 };
0141
0142 std::vector<SelectedObject> sels_;
0143 };
0144
0145
0146 void TriggerObjectTableProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) {
0147 const auto &trigObjs = iEvent.get(src_);
0148
0149 std::vector<std::pair<const pat::TriggerObjectStandAlone *, const SelectedObject *>> selected;
0150 std::map<int, std::map<const pat::TriggerObjectStandAlone *, int>> selected_bits;
0151 for (const auto &obj : trigObjs) {
0152 for (const auto &sel : sels_) {
0153 if (sel.match(obj)) {
0154 selected_bits[sel.id][&obj] = int(sel.qualityBits(obj));
0155 if (sel.skipObjectsNotPassingQualityBits ? (selected_bits[sel.id][&obj] > 0) : true) {
0156 selected.emplace_back(&obj, &sel);
0157 }
0158 }
0159 }
0160 }
0161
0162
0163 for (unsigned int i = 0; i < selected.size(); ++i) {
0164 const auto &obj = *selected[i].first;
0165 const auto &sel = *selected[i].second;
0166
0167 for (unsigned int j = 0; j < i; ++j) {
0168 const auto &obj2 = *selected[j].first;
0169 const auto &sel2 = *selected[j].second;
0170 if (sel.id == sel2.id && deltaR2(obj, obj2) < 1e-6) {
0171 selected_bits[sel.id][&obj2] |= selected_bits[sel.id][&obj];
0172 selected.erase(selected.begin() + i);
0173 i--;
0174 }
0175 }
0176 }
0177
0178 const auto &l1EG = iEvent.get(l1EG_);
0179 const auto &l1Sum = iEvent.get(l1Sum_);
0180 const auto &l1Jet = iEvent.get(l1Jet_);
0181 const auto &l1Muon = iEvent.get(l1Muon_);
0182 const auto &l1Tau = iEvent.get(l1Tau_);
0183
0184 std::vector<pair<pat::TriggerObjectStandAlone, int>> l1Objects;
0185 l1Objects.reserve(l1EG.size(0) + l1Sum.size(0) + l1Jet.size(0) + l1Muon.size(0) + l1Tau.size(0));
0186
0187
0188 for (l1t::EGammaBxCollection::const_iterator it = l1EG.begin(0); it != l1EG.end(0); it++) {
0189 pat::TriggerObjectStandAlone l1obj(it->p4());
0190 l1obj.setCollection("L1EG");
0191 l1obj.addTriggerObjectType(trigger::TriggerL1EG);
0192 l1Objects.emplace_back(l1obj, it->hwIso());
0193 }
0194
0195 for (l1t::EtSumBxCollection::const_iterator it = l1Sum.begin(0); it != l1Sum.end(0); it++) {
0196 pat::TriggerObjectStandAlone l1obj(it->p4());
0197
0198 switch (it->getType()) {
0199 case l1t::EtSum::EtSumType::kMissingEt:
0200 l1obj.addTriggerObjectType(trigger::TriggerL1ETM);
0201 l1obj.setCollection("L1ETM");
0202 break;
0203
0204 case l1t::EtSum::EtSumType::kMissingEtHF:
0205 l1obj.addTriggerObjectType(trigger::TriggerL1ETM);
0206 l1obj.setCollection("L1ETMHF");
0207 break;
0208
0209 case l1t::EtSum::EtSumType::kTotalEt:
0210 l1obj.addTriggerObjectType(trigger::TriggerL1ETT);
0211 l1obj.setCollection("L1ETT");
0212 break;
0213
0214 case l1t::EtSum::EtSumType::kTotalEtEm:
0215 l1obj.addTriggerObjectType(trigger::TriggerL1ETT);
0216 l1obj.setCollection("L1ETEm");
0217 break;
0218
0219 case l1t::EtSum::EtSumType::kTotalHt:
0220 l1obj.addTriggerObjectType(trigger::TriggerL1HTT);
0221 l1obj.setCollection("L1HTT");
0222 break;
0223
0224 case l1t::EtSum::EtSumType::kTotalHtHF:
0225 l1obj.addTriggerObjectType(trigger::TriggerL1HTT);
0226 l1obj.setCollection("L1HTTHF");
0227 break;
0228
0229 case l1t::EtSum::EtSumType::kMissingHt:
0230 l1obj.addTriggerObjectType(trigger::TriggerL1HTM);
0231 l1obj.setCollection("L1HTM");
0232 break;
0233
0234 case l1t::EtSum::EtSumType::kMissingHtHF:
0235 l1obj.addTriggerObjectType(trigger::TriggerL1HTM);
0236 l1obj.setCollection("L1HTMHF");
0237 break;
0238
0239 default:
0240 continue;
0241 }
0242
0243 l1Objects.emplace_back(l1obj, it->hwIso());
0244 }
0245
0246 for (l1t::JetBxCollection::const_iterator it = l1Jet.begin(0); it != l1Jet.end(0); it++) {
0247 pat::TriggerObjectStandAlone l1obj(it->p4());
0248 l1obj.setCollection("L1Jet");
0249 l1obj.addTriggerObjectType(trigger::TriggerL1Jet);
0250 l1Objects.emplace_back(l1obj, it->hwIso());
0251 }
0252
0253 for (l1t::MuonBxCollection::const_iterator it = l1Muon.begin(0); it != l1Muon.end(0); it++) {
0254 pat::TriggerObjectStandAlone l1obj(it->p4());
0255 l1obj.setCollection("L1Mu");
0256 l1obj.addTriggerObjectType(trigger::TriggerL1Mu);
0257 l1obj.setCharge(it->charge());
0258 l1Objects.emplace_back(l1obj, it->hwIso());
0259 }
0260
0261 for (l1t::TauBxCollection::const_iterator it = l1Tau.begin(0); it != l1Tau.end(0); it++) {
0262 pat::TriggerObjectStandAlone l1obj(it->p4());
0263 l1obj.setCollection("L1Tau");
0264 l1obj.addTriggerObjectType(trigger::TriggerL1Tau);
0265 l1Objects.emplace_back(l1obj, it->hwIso());
0266 }
0267
0268 unsigned int nobj = selected.size();
0269 std::vector<float> pt(nobj, 0), eta(nobj, 0), phi(nobj, 0), l1pt(nobj, 0), l1pt_2(nobj, 0), l2pt(nobj, 0);
0270 std::vector<int16_t> l1charge(nobj, 0);
0271 std::vector<uint16_t> id(nobj, 0);
0272 std::vector<int> bits(nobj, 0), l1iso(nobj, 0);
0273 for (unsigned int i = 0; i < nobj; ++i) {
0274 const auto &obj = *selected[i].first;
0275 const auto &sel = *selected[i].second;
0276 pt[i] = obj.pt();
0277 eta[i] = obj.eta();
0278 phi[i] = obj.phi();
0279 id[i] = sel.id;
0280 bits[i] = selected_bits[sel.id][&obj];
0281 if (sel.l1DR2 > 0) {
0282 float best = sel.l1DR2;
0283 for (const auto &l1obj : l1Objects) {
0284 const auto &seed = l1obj.first;
0285 float dr2 = deltaR2(seed, obj);
0286 if (dr2 < best && sel.l1cut(seed)) {
0287 best = dr2;
0288 l1pt[i] = seed.pt();
0289 l1iso[i] = l1obj.second;
0290 l1charge[i] = seed.charge();
0291 }
0292 }
0293 }
0294 if (sel.l1DR2_2 > 0) {
0295 float best = sel.l1DR2_2;
0296 for (const auto &l1obj : l1Objects) {
0297 const auto &seed = l1obj.first;
0298 float dr2 = deltaR2(seed, obj);
0299 if (dr2 < best && sel.l1cut_2(seed)) {
0300 best = dr2;
0301 l1pt_2[i] = seed.pt();
0302 }
0303 }
0304 }
0305 if (sel.l2DR2 > 0) {
0306 float best = sel.l2DR2;
0307 for (const auto &seed : trigObjs) {
0308 float dr2 = deltaR2(seed, obj);
0309 if (dr2 < best && sel.l2cut(seed)) {
0310 best = dr2;
0311 l2pt[i] = seed.pt();
0312 }
0313 }
0314 }
0315 }
0316
0317 auto tab = std::make_unique<nanoaod::FlatTable>(nobj, name_, false, false);
0318 tab->addColumn<uint16_t>("id", id, idDoc_);
0319 tab->addColumn<float>("pt", pt, "pt", 12);
0320 tab->addColumn<float>("eta", eta, "eta", 12);
0321 tab->addColumn<float>("phi", phi, "phi", 12);
0322 tab->addColumn<float>("l1pt", l1pt, "pt of associated L1 seed", 8);
0323 tab->addColumn<int>("l1iso", l1iso, "iso of associated L1 seed");
0324 tab->addColumn<int16_t>("l1charge", l1charge, "charge of associated L1 seed");
0325 tab->addColumn<float>("l1pt_2", l1pt_2, "pt of associated secondary L1 seed", 8);
0326 tab->addColumn<float>("l2pt", l2pt, "pt of associated 'L2' seed (i.e. HLT before tracking/PF)", 10);
0327 tab->addColumn<int>("filterBits", bits, "extra bits of associated information: " + bitsDoc_);
0328 iEvent.put(std::move(tab));
0329 }
0330
0331 void TriggerObjectTableProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0332 edm::ParameterSetDescription desc;
0333 desc.add<std::string>("name")->setComment("name of the flat table output");
0334 desc.add<edm::InputTag>("src")->setComment("pat::TriggerObjectStandAlone input collection");
0335 desc.add<edm::InputTag>("l1EG")->setComment("l1t::EGammaBxCollection input collection");
0336 desc.add<edm::InputTag>("l1Sum")->setComment("l1t::EtSumBxCollection input collection");
0337 desc.add<edm::InputTag>("l1Jet")->setComment("l1t::JetBxCollection input collection");
0338 desc.add<edm::InputTag>("l1Muon")->setComment("l1t::MuonBxCollection input collection");
0339 desc.add<edm::InputTag>("l1Tau")->setComment("l1t::TauBxCollection input collection");
0340
0341 edm::ParameterSetDescription selection;
0342 selection.setComment("a parameterset to define a trigger collection in flat table");
0343 selection.add<std::string>("doc", "")->setComment(
0344 "optional additional info to be added to the table doc for that object");
0345 selection.add<int>("id")->setComment("identifier of the trigger collection in the flat table");
0346 selection.add<std::string>("sel")->setComment("function to selection on pat::TriggerObjectStandAlone");
0347 selection.add<bool>("skipObjectsNotPassingQualityBits")->setComment("flag to skip object on quality bit");
0348
0349 edm::ParameterSetDescription bit;
0350 bit.add<std::string>("selection")->setComment("function on pat::TriggerObjectStandAlone to define quality bit");
0351 bit.add<std::string>("doc")->setComment("definition of the quality bit");
0352 bit.addOptional<uint>("bit")->setComment("value of the bit, if not the order in the VPset");
0353 bit.setComment("parameter set to define quality bit of matching object");
0354 selection.addVPSet("qualityBits", bit);
0355
0356 selection.ifExists(edm::ParameterDescription<std::string>("l1seed", "selection on pat::TriggerObjectStandAlone"),
0357 edm::ParameterDescription<double>(
0358 "l1deltaR", "deltaR criteria to match pat::TriggerObjectStandAlone to L1 primitive"));
0359 selection.ifExists(edm::ParameterDescription<std::string>("l1seed_2", "selection on pat::TriggerObjectStandAlone"),
0360 edm::ParameterDescription<double>(
0361 "l1deltaR_2", "deltaR criteria to match pat::TriggerObjectStandAlone to L1 primitive"));
0362 selection.ifExists(edm::ParameterDescription<std::string>("l2seed", "selection on pat::TriggerObjectStandAlone"),
0363 edm::ParameterDescription<double>(
0364 "l2deltaR", "deltaR criteria to match pat::TriggerObjectStandAlone to 'L2' primitive"));
0365
0366 edm::ParameterWildcard<edm::ParameterSetDescription> selectionsNode("*", edm::RequireAtLeastOne, true, selection);
0367 edm::ParameterSetDescription selections;
0368 selections.addNode(selectionsNode);
0369 desc.add<edm::ParameterSetDescription>("selections", selections);
0370
0371 descriptions.addWithDefaultLabel(desc);
0372 }
0373
0374
0375 DEFINE_FWK_MODULE(TriggerObjectTableProducer);