CMS 3D CMS Logo

TriggerOutputFields.cc
Go to the documentation of this file.
1 #include "TriggerOutputFields.h"
2 
3 #include "RNTupleFieldPtr.h"
4 
13 
14 #include <algorithm>
15 
16 namespace {
17 
18  void trimVersionSuffix(std::string& trigger_name) {
19  // HLT and L1 triggers have version suffixes we trim before filling the RNTuple
20  if (trigger_name.compare(0, 3, "HLT") != 0 && trigger_name.compare(0, 2, "L1") != 0) {
21  return;
22  }
23  auto vfound = trigger_name.rfind("_v");
24  if (vfound == std::string::npos) {
25  return;
26  }
27  trigger_name.replace(vfound, trigger_name.size() - vfound, "");
28  }
29 
30  bool isNanoaodTrigger(const std::string& name) {
31  return name.compare(0, 3, "HLT") == 0 || name.compare(0, 4, "Flag") == 0 || name.compare(0, 2, "L1") == 0;
32  }
33 
34 } // anonymous namespace
35 
37  std::string name, int index, std::string fieldName, std::string fieldDesc, RNTupleModel& model)
38  : m_triggerName(name), m_triggerIndex(index) {
39  m_field = RNTupleFieldPtr<bool>(fieldName, fieldDesc, model);
40 }
41 
43  if (m_triggerIndex == -1) {
44  m_field.fill(false);
45  }
46  m_field.fill(triggers.accept(m_triggerIndex));
47 }
48 
50  // Trigger names are either stored in the TriggerResults object (e.g. L1) or
51  // need to be looked up in the registry (e.g. HLT)
52  auto triggerNames = triggerResults.getTriggerNames();
53  if (!triggerNames.empty()) {
54  return triggerNames;
55  }
57  edm::ParameterSet const* pset = psetRegistry->getMapped(triggerResults.parameterSetID());
58  if (nullptr == pset || !pset->existsAs<std::vector<std::string>>("@trigger_paths", true)) {
59  return {};
60  }
62  if (names.size() != triggerResults.size()) {
63  throw cms::Exception("LogicError") << "TriggerOutputFields::getTriggerNames "
64  "Encountered vector\n of trigger names and a TriggerResults object with\n"
65  "different sizes. This should be impossible.\n"
66  "Please send information to reproduce this problem to\nthe edm developers.\n";
67  }
68  return names.triggerNames();
69 }
70 
72  m_lastRun = event.id().run();
74  event.getByToken(m_token, handle);
77  m_triggerFields.reserve(triggerNames.size());
78  for (std::size_t i = 0; i < triggerNames.size(); i++) {
79  auto& name = triggerNames[i];
80  if (!isNanoaodTrigger(name)) {
81  continue;
82  }
83  trimVersionSuffix(name);
86  std::string desc = std::string("Trigger/flag bit (process: ") + m_processName + ")";
88  }
89 }
90 
91 // Worst case O(n^2) to adjust the triggers
93  std::vector<std::string> newNames(TriggerOutputFields::getTriggerNames(triggers));
94  // adjust existing trigger indices
95  for (auto& t : m_triggerFields) {
96  t.setIndex(-1);
97  for (std::size_t j = 0; j < newNames.size(); j++) {
98  auto& name = newNames[j];
99  if (!isNanoaodTrigger(name)) {
100  continue;
101  }
102  trimVersionSuffix(name);
103  if (name == t.getTriggerName()) {
104  t.setIndex(j);
105  }
106  }
107  }
108  // find new triggers
109  for (std::size_t j = 0; j < newNames.size(); j++) {
110  auto& name = newNames[j];
111  if (!isNanoaodTrigger(name)) {
112  continue;
113  }
114  trimVersionSuffix(name);
115  if (std::none_of(m_triggerFields.cbegin(), m_triggerFields.cend(), [&](const TriggerFieldPtr& t) {
116  return t.getTriggerName() == name;
117  })) {
118  // TODO backfill / friend ntuples
119  edm::LogWarning("TriggerOutputFields") << "Skipping output of TriggerField " << name << "\n";
120  }
121  }
122 }
123 
125  // Could also use a cache of names in a higher-level object, don't ask the RNTupleModel each time
126 #if ROOT_VERSION_CODE < ROOT_VERSION(6, 31, 0)
127  auto existing_field = model.Get<bool>(name);
128 #else
129  auto existing_field = model.GetDefaultEntry().GetPtr<bool>(name);
130 #endif
131  if (!existing_field) {
132  return;
133  }
134  edm::LogWarning("TriggerOutputFields") << "Found a branch with name " << name
135  << " already present. Will add suffix _p" << m_processName
136  << " to the new branch.\n";
137  name += std::string("_p") + m_processName;
138 }
139 
142  event.getByToken(m_token, handle);
143  const edm::TriggerResults& triggers = *handle;
144  if (m_lastRun != event.id().run()) {
145  m_lastRun = event.id().run();
146  updateTriggerFields(triggers);
147  }
148  for (auto& t : m_triggerFields) {
149  t.fill(triggers);
150  }
151 }
void makeUniqueFieldName(RNTupleModel &model, std::string &name)
bool accept() const
Has at least one path accepted the event?
void fill(const edm::EventForOutput &event)
void updateTriggerFields(const edm::TriggerResults &triggerResults)
bool getMapped(key_type const &k, value_type &result) const
Definition: Registry.cc:17
TriggerFieldPtr()=default
void fill(const T &value)
const std::string names[nVars_]
std::vector< TriggerFieldPtr > m_triggerFields
void fill(const edm::TriggerResults &triggers)
static std::string const triggerResults
Definition: EdmProvDump.cc:47
void createFields(const edm::EventForOutput &event, RNTupleModel &model)
static std::vector< std::string > getTriggerNames(const edm::TriggerResults &triggerResults)
edm::EDGetToken m_token
Log< level::Warning, false > LogWarning
static Registry * instance()
Definition: Registry.cc:12
Definition: event.py:1
RNTupleFieldPtr< bool > m_field