File indexing completed on 2024-04-06 12:23:40
0001 #include "TriggerOutputFields.h"
0002
0003 #include "RNTupleFieldPtr.h"
0004
0005 #include "DataFormats/Common/interface/TriggerResults.h"
0006 #include "FWCore/Common/interface/TriggerNames.h"
0007 #include "FWCore/Framework/interface/EventForOutput.h"
0008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 #include "FWCore/ParameterSet/interface/Registry.h"
0011 #include "FWCore/Utilities/interface/EDGetToken.h"
0012 #include "FWCore/Utilities/interface/Exception.h"
0013
0014 #include <algorithm>
0015
0016 namespace {
0017
0018 void trimVersionSuffix(std::string& trigger_name) {
0019
0020 if (trigger_name.compare(0, 3, "HLT") != 0 && trigger_name.compare(0, 2, "L1") != 0) {
0021 return;
0022 }
0023 auto vfound = trigger_name.rfind("_v");
0024 if (vfound == std::string::npos) {
0025 return;
0026 }
0027 trigger_name.replace(vfound, trigger_name.size() - vfound, "");
0028 }
0029
0030 bool isNanoaodTrigger(const std::string& name) {
0031 return name.compare(0, 3, "HLT") == 0 || name.compare(0, 4, "Flag") == 0 || name.compare(0, 2, "L1") == 0;
0032 }
0033
0034 }
0035
0036 TriggerFieldPtr::TriggerFieldPtr(
0037 std::string name, int index, std::string fieldName, std::string fieldDesc, RNTupleModel& model)
0038 : m_triggerName(name), m_triggerIndex(index) {
0039 m_field = RNTupleFieldPtr<bool>(fieldName, fieldDesc, model);
0040 }
0041
0042 void TriggerFieldPtr::fill(const edm::TriggerResults& triggers) {
0043 if (m_triggerIndex == -1) {
0044 m_field.fill(false);
0045 }
0046 m_field.fill(triggers.accept(m_triggerIndex));
0047 }
0048
0049 std::vector<std::string> TriggerOutputFields::getTriggerNames(const edm::TriggerResults& triggerResults) {
0050
0051
0052 auto triggerNames = triggerResults.getTriggerNames();
0053 if (!triggerNames.empty()) {
0054 return triggerNames;
0055 }
0056 edm::pset::Registry* psetRegistry = edm::pset::Registry::instance();
0057 edm::ParameterSet const* pset = psetRegistry->getMapped(triggerResults.parameterSetID());
0058 if (nullptr == pset || !pset->existsAs<std::vector<std::string>>("@trigger_paths", true)) {
0059 return {};
0060 }
0061 edm::TriggerNames names(*pset);
0062 if (names.size() != triggerResults.size()) {
0063 throw cms::Exception("LogicError") << "TriggerOutputFields::getTriggerNames "
0064 "Encountered vector\n of trigger names and a TriggerResults object with\n"
0065 "different sizes. This should be impossible.\n"
0066 "Please send information to reproduce this problem to\nthe edm developers.\n";
0067 }
0068 return names.triggerNames();
0069 }
0070
0071 void TriggerOutputFields::createFields(const edm::EventForOutput& event, RNTupleModel& model) {
0072 m_lastRun = event.id().run();
0073 edm::Handle<edm::TriggerResults> handle;
0074 event.getByToken(m_token, handle);
0075 const edm::TriggerResults& triggerResults = *handle;
0076 std::vector<std::string> triggerNames(TriggerOutputFields::getTriggerNames(triggerResults));
0077 m_triggerFields.reserve(triggerNames.size());
0078 for (std::size_t i = 0; i < triggerNames.size(); i++) {
0079 auto& name = triggerNames[i];
0080 if (!isNanoaodTrigger(name)) {
0081 continue;
0082 }
0083 trimVersionSuffix(name);
0084 std::string modelName = name;
0085 makeUniqueFieldName(model, modelName);
0086 std::string desc = std::string("Trigger/flag bit (process: ") + m_processName + ")";
0087 m_triggerFields.emplace_back(TriggerFieldPtr(name, i, modelName, desc, model));
0088 }
0089 }
0090
0091
0092 void TriggerOutputFields::updateTriggerFields(const edm::TriggerResults& triggers) {
0093 std::vector<std::string> newNames(TriggerOutputFields::getTriggerNames(triggers));
0094
0095 for (auto& t : m_triggerFields) {
0096 t.setIndex(-1);
0097 for (std::size_t j = 0; j < newNames.size(); j++) {
0098 auto& name = newNames[j];
0099 if (!isNanoaodTrigger(name)) {
0100 continue;
0101 }
0102 trimVersionSuffix(name);
0103 if (name == t.getTriggerName()) {
0104 t.setIndex(j);
0105 }
0106 }
0107 }
0108
0109 for (std::size_t j = 0; j < newNames.size(); j++) {
0110 auto& name = newNames[j];
0111 if (!isNanoaodTrigger(name)) {
0112 continue;
0113 }
0114 trimVersionSuffix(name);
0115 if (std::none_of(m_triggerFields.cbegin(), m_triggerFields.cend(), [&](const TriggerFieldPtr& t) {
0116 return t.getTriggerName() == name;
0117 })) {
0118
0119 edm::LogWarning("TriggerOutputFields") << "Skipping output of TriggerField " << name << "\n";
0120 }
0121 }
0122 }
0123
0124 void TriggerOutputFields::makeUniqueFieldName(RNTupleModel& model, std::string& name) {
0125
0126 #if ROOT_VERSION_CODE < ROOT_VERSION(6, 31, 0)
0127 auto existing_field = model.Get<bool>(name);
0128 #else
0129 auto existing_field = model.GetDefaultEntry().GetPtr<bool>(name);
0130 #endif
0131 if (!existing_field) {
0132 return;
0133 }
0134 edm::LogWarning("TriggerOutputFields") << "Found a branch with name " << name
0135 << " already present. Will add suffix _p" << m_processName
0136 << " to the new branch.\n";
0137 name += std::string("_p") + m_processName;
0138 }
0139
0140 void TriggerOutputFields::fill(const edm::EventForOutput& event) {
0141 edm::Handle<edm::TriggerResults> handle;
0142 event.getByToken(m_token, handle);
0143 const edm::TriggerResults& triggers = *handle;
0144 if (m_lastRun != event.id().run()) {
0145 m_lastRun = event.id().run();
0146 updateTriggerFields(triggers);
0147 }
0148 for (auto& t : m_triggerFields) {
0149 t.fill(triggers);
0150 }
0151 }