Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:43

0001 // system include files
0002 #include <memory>
0003 #include <sstream>
0004 
0005 // user include files
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"),   //will be overwritten from configuration
0096           qualityBitsDoc("")  //will be created from configuration
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");  // the bit should not have been set already
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         //std::cout << "The quality bit string is :" << qualityBitsFunc.str() << std::endl;
0122         //std::cout << "The quality bit documentation is :" << qualityBitsDoc << std::endl;
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 // ------------ method called to produce the data  ------------
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   // Self-cleaning
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 && abs(obj.pt() - obj2.pt()) < 1e-6 && deltaR2(obj, obj2) < 1e-6) {
0171         selected_bits[sel.id][&obj2] |= selected_bits[sel.id][&obj];  //Keep filters from all the objects
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   // no range-based for because we want bx=0 only
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 //define this as a plug-in
0375 DEFINE_FWK_MODULE(TriggerObjectTableProducer);