CMS 3D CMS Logo

L1TGlobalPrescaler.cc
Go to the documentation of this file.
1 #include <array>
2 #include <cassert>
3 #include <cstring>
4 #include <memory>
5 #include <stdexcept>
6 #include <string>
7 #include <vector>
8 
9 #include <fmt/printf.h>
10 
11 using namespace std::literals;
12 
13 namespace {
14 
15  template <class T>
16  struct Entry {
17  T value;
18  const char* tag;
19  const char* description;
20  };
21 
22  template <typename S, typename T, unsigned int N>
23  std::string build_comment_from_entries(S pre, const Entry<T> (&entries)[N]) {
24  std::string comment{pre};
25  size_t length = 0;
26  for (auto entry : entries)
27  if (entry.tag)
28  length = std::max(std::strlen(entry.tag), length);
29  for (auto entry : entries)
30  if (entry.tag) {
31  comment.reserve(comment.size() + length + std::strlen(entry.description) + 8);
32  comment += "\n \"";
33  comment += entry.tag;
34  comment += "\": ";
35  for (unsigned int i = 0; i < length - std::strlen(entry.tag); ++i)
36  comment += ' ';
37  comment += entry.description;
38  }
39  return comment;
40  }
41 
42  template <typename S1, typename S2, typename T, unsigned int N>
43  std::string build_comment_from_entries(S1 pre, const Entry<T> (&entries)[N], S2 post) {
44  std::string comment = build_comment_from_entries(pre, entries);
45  comment += '\n';
46  comment += post;
47  return comment;
48  }
49 
50  template <class T>
51  constexpr T get_enum_value(Entry<T> const* entries, const char* tag) {
52  for (; entries->tag; ++entries)
53  if (std::strcmp(entries->tag, tag) == 0)
54  return entries->value;
55  throw std::logic_error("invalid tag "s + tag);
56  }
57 
58  template <class T>
59  constexpr T get_enum_value(Entry<T> const* entries, const char* tag, T default_value) {
60  for (; entries->tag; ++entries)
61  if (std::strcmp(entries->tag, tag) == 0)
62  return entries->value;
63  return default_value;
64  }
65 
66 } // namespace
67 
68 // ############################################################################
69 
83 
85 public:
87 
88  bool filter(edm::Event& event, edm::EventSetup const& setup) override;
89 
90  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
91 
92 private:
93  enum class Mode {
94  ApplyPrescaleValues, // apply the given prescale values
95  ApplyPrescaleRatios, // apply prescales equal to ratio between the given values and the ones read from the EventSetup
96  ApplyColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index
97  ApplyColumnRatios, // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
98  ForcePrescaleValues, // apply the given prescale values, ignoring the prescales and masks already applied
99  ForceColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index, ignoring the prescales and masks already applied
100  Invalid = -1
101  };
102 
103  static const constexpr Entry<Mode> s_modes[]{
104  {Mode::ApplyPrescaleValues, "applyPrescaleValues", "apply the given prescale values"},
105  {Mode::ApplyPrescaleRatios,
106  "applyPrescaleRatios",
107  "apply prescales equal to ratio between the given values and the ones read from the EventSetup"},
108  {Mode::ApplyColumnValues,
109  "applyColumnValues",
110  "apply the prescale values from the EventSetup corresponding to the given column index"},
111  {Mode::ApplyColumnRatios,
112  "applyColumnRatios",
113  "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read "
114  "from the EventSetup"},
115  {Mode::ForcePrescaleValues,
116  "forcePrescaleValues",
117  "apply the given prescale values, ignoring the prescales and masks already applied"},
118  {Mode::ForceColumnValues,
119  "forceColumnValues",
120  "apply the prescale values from the EventSetup corresponding to the given column index, ignoring the prescales "
121  "and masks already applied"},
122  {Mode::Invalid, nullptr, nullptr}};
123 
124  const Mode m_mode;
126  const std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_l1tPrescales;
127  std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_prescales;
128  std::array<unsigned int, GlobalAlgBlk::maxPhysicsTriggers> m_counters;
132 };
133 
134 const constexpr Entry<L1TGlobalPrescaler::Mode> L1TGlobalPrescaler::s_modes[];
135 
137  : m_mode(get_enum_value(s_modes, config.getParameter<std::string>("mode").c_str(), Mode::Invalid)),
138  m_l1tResultsToken(consumes<GlobalAlgBlkBxCollection>(config.getParameter<edm::InputTag>("l1tResults"))),
139  m_l1tPrescales(m_mode == Mode::ApplyPrescaleValues or m_mode == Mode::ApplyPrescaleRatios or
140  m_mode == Mode::ForcePrescaleValues
141  ? config.getParameter<std::array<double, GlobalAlgBlk::maxPhysicsTriggers>>("l1tPrescales")
142  : std::array<double, GlobalAlgBlk::maxPhysicsTriggers>{}),
143  m_l1tPrescaleColumn(m_mode == Mode::ApplyColumnValues or m_mode == Mode::ApplyColumnRatios or
144  m_mode == Mode::ForceColumnValues
145  ? config.getParameter<uint32_t>("l1tPrescaleColumn")
146  : 0),
147  m_oldIndex(-1) {
148  switch (m_mode) {
149  // if the mode is "applyPrescaleValues", use the given values
153  break;
154 
155  // otherwise we need to read the prescale values from the EventSetup
160  m_l1tGtPrescalesVetosToken = esConsumes<L1TGlobalPrescalesVetos, L1TGlobalPrescalesVetosRcd>();
161  break;
162 
163  // this should never happen
164  case Mode::Invalid:
166  << "invalid mode \"" << config.getParameter<std::string>("mode") << "\"";
167  }
168 
169  m_counters.fill(0);
170  produces<GlobalAlgBlkBxCollection>();
171 }
172 
175  event.getByToken(m_l1tResultsToken, handle);
176 
177  // if the input collection does not have any information for bx 0,
178  // produce an empty collection, and fail
179  if (handle->isEmpty(0)) {
180  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
181  event.put(std::move(result));
182  return false;
183  }
184 
185  // read the prescale index
186  int index = handle->at(0, 0).getPreScColumn();
187  assert(index >= 0);
188 
189  // Mode::ApplyPrescaleRatios
190  // apply prescales equal to ratio between the given values and the ones read from the EventSetup
193 
194  auto const& prescaleTable = h->prescale_table_;
195  if (index >= (int)prescaleTable.size())
197  << fmt::sprintf("The prescale index %d is invalid, it should be smaller than the prescale table size %d.",
198  index,
199  prescaleTable.size());
200  auto const& prescales = prescaleTable[index];
201  unsigned long i = 0;
202  for (; i < std::min(prescales.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers); ++i)
203  if (m_l1tPrescales[i] == 0) {
204  // if the trigger is requested to be disabled, just do it
205  m_prescales[i] = 0.;
206  } else if (prescales[i] == 0) {
207  // othersie, if the trigger was originally disabled, warn the user and keep it that way
208  m_prescales[i] = 0.;
209  edm::LogWarning("L1TGlobalPrescaler")
210  << "Request to enable the trigger " << i << " which was originally disabled\nIt will be kept disabled.";
211  } else if (m_l1tPrescales[i] < prescales[i]) {
212  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
213  m_prescales[i] = 1.;
214  edm::LogWarning("L1TGlobalPrescaler")
215  << "Request to prescale the trigger " << i
216  << " less than it was originally prescaled\nNo further prescale will be applied.";
217  } else {
218  // apply the ratio of the new and old prescales
219  m_prescales[i] = (double)m_l1tPrescales[i] / prescales[i];
220  }
221  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
222  // disable the triggers not included in the prescale table
223  m_prescales[i] = 0.;
224  // reset the prescales
225  m_counters.fill(0);
226  m_oldIndex = index;
227  }
228 
229  // Mode::ApplyColumnValues and Mode::ForceColumnValues
230  // apply the prescale values from the EventSetup corresponding to the given column index
233  auto const& prescaleTable = h->prescale_table_;
234  if (m_l1tPrescaleColumn >= (int)prescaleTable.size())
236  << fmt::sprintf("The prescale index %d is invalid, it should be smaller than the prescale table size %d.",
238  prescaleTable.size());
240  unsigned long i = 0;
241  for (; i < std::min(targets.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers); ++i)
242  // read the prescales from the EventSetup
243  m_prescales[i] = targets[i];
244  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
245  // disable the triggers not included in the prescale table
246  m_prescales[i] = 0.;
247  // reset the prescales
248  m_counters.fill(0);
250  }
251 
252  // Mode::ApplyColumnRatios
253  // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
256  auto const& prescaleTable = h->prescale_table_;
257  if (index >= (int)prescaleTable.size())
259  << fmt::sprintf("The prescale index %d is invalid, it should be smaller than the prescale table size %d.",
260  index,
261  prescaleTable.size());
262  if (m_l1tPrescaleColumn >= (int)prescaleTable.size())
264  << fmt::sprintf("The prescale index %d is invalid, it should be smaller than the prescale table size %d.",
266  prescaleTable.size());
267  auto const& prescales = prescaleTable[index];
269  unsigned long i = 0;
270  for (; i < std::min({prescales.size(), targets.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers}); ++i)
271  if (prescales[i] == 0)
272  // if the trigger was disabled, keep it disabled
273  m_prescales[i] = 0.;
274  else
275  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
276  m_prescales[i] = targets[i] < prescales[i] ? 1. : (double)targets[i] / prescales[i];
277  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
278  // disable the triggers not included in the prescale table
279  m_prescales[i] = 0.;
280  // reset the prescales
281  m_counters.fill(0);
282  m_oldIndex = index;
283  }
284 
285  // make a copy of the GlobalAlgBlk for bx 0
286  GlobalAlgBlk algoBlock = handle->at(0, 0);
287 
288  bool finalOr = false;
289  std::vector<bool> const& decision = (m_mode == Mode::ForceColumnValues or m_mode == Mode::ForcePrescaleValues)
290  ? algoBlock.getAlgoDecisionInitial()
291  : algoBlock.getAlgoDecisionFinal();
292 
293  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
294  if (m_prescales[i] == 0) {
295  // mask this trigger: reset the bit
296  algoBlock.setAlgoDecisionFinal(i, false);
297  } else if (decision[i]) {
298  // prescale this trigger
299  ++m_counters[i];
300  if (std::fmod(m_counters[i], m_prescales[i]) < 1) {
301  // the prescale is successful, set the bit
302  algoBlock.setAlgoDecisionFinal(i, true);
303  finalOr = true;
304  } else {
305  // the prescale failed, reset the bit
306  algoBlock.setAlgoDecisionFinal(i, false);
307  }
308  }
309  }
310 
311  // set the final OR
312  algoBlock.setFinalORPreVeto(finalOr);
313  if (algoBlock.getFinalORVeto())
314  finalOr = false;
315  algoBlock.setFinalOR(finalOr);
316 
317  // set the new prescale column
320 
321  // create a new GlobalAlgBlkBxCollection, and set the new prescaled decisions for bx 0
322  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
323  result->push_back(0, algoBlock);
324  event.put(std::move(result));
325 
326  return finalOr;
327 }
328 
330  // collection with the original uGT results
331  edm::ParameterDescription<edm::InputTag> l1tResults("l1tResults", edm::InputTag("gtStage2Digis"), true);
332  l1tResults.setComment("Collection with the original uGT results");
333 
334  // define how to apply the prescale values
335  edm::ParameterDescription<std::string> mode("mode", "applyPrescaleValues", true);
336  mode.setComment(build_comment_from_entries("Define how to apply the prescale values:", s_modes));
337 
338  // target prescale values (for modes "applyPrescaleValues" or "applyPrescaleRatios")
340  "l1tPrescales", std::vector<double>(GlobalAlgBlk::maxPhysicsTriggers, 1.), true);
341  l1tPrescales.setComment(
342  "Target prescale values (for modes \"applyPrescaleValues\", \"applyPrescaleRatios\" or \"forcePrescaleValues\")");
343 
344  // target prescale column (for modes "applyColumnValues" or "applyColumnRatios")
345  edm::ParameterDescription<uint32_t> l1tPrescaleColumn("l1tPrescaleColumn", 0, true);
346  l1tPrescaleColumn.setComment(
347  "Target prescale column (for modes \"applyColumnValues\", \"applyColumnRatios\" or \"forceColumnValues\")");
348 
349  // validaton of all possible configurations and applyPrescaleValues example
350  {
352  desc.addNode(l1tResults);
353  desc.ifValue(
354  mode,
355  // if mode is "applyPrescaleValues", "applyPrescaleRatios" or "forcePrescaleValues", read the target prescales
356  "applyPrescaleValues" >> l1tPrescales or "applyPrescaleRatios" >> l1tPrescales or
357  "forcePrescaleValues" >> l1tPrescales or
358  // if mode is "applyColumnValues", "applyColumnRatios" or "forceColumnValues", read the target column
359  "applyColumnValues" >> l1tPrescaleColumn or "applyColumnRatios" >> l1tPrescaleColumn or
360  "forceColumnValues" >> l1tPrescaleColumn);
361  descriptions.add("l1tGlobalPrescaler", desc);
362  }
363 
364  // applyColumnRatios example
365  {
367  desc.addNode(l1tResults);
368  desc.add<std::string>("mode", "applyColumnRatios")
369  ->setComment(
370  "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones "
371  "read from the EventSetup");
372  desc.addNode(l1tPrescaleColumn);
373  descriptions.add("l1tGlobalPrescalerTargetColumn", desc);
374  }
375 }
376 
377 // register as a framework plugin
static const constexpr Entry< Mode > s_modes[]
void setComment(std::string const &value)
edm::ESGetToken< L1TGlobalPrescalesVetos, L1TGlobalPrescalesVetosRcd > m_l1tGtPrescalesVetosToken
void setFinalORPreVeto(bool fOR)
Definition: GlobalAlgBlk.h:59
const std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_l1tPrescales
std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_prescales
std::array< unsigned int, GlobalAlgBlk::maxPhysicsTriggers > m_counters
BXVector< GlobalAlgBlk > GlobalAlgBlkBxCollection
Definition: GlobalAlgBlk.h:31
Definition: config.py:1
assert(be >=bs)
std::vector< bool > const & getAlgoDecisionFinal() const
Definition: GlobalAlgBlk.h:84
Entry(const ALIstring &type)
Definition: Entry.cc:22
bool filter(edm::Event &event, edm::EventSetup const &setup) override
const bool getFinalORVeto() const
Definition: GlobalAlgBlk.h:69
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void setFinalOR(bool fOR)
Definition: GlobalAlgBlk.h:60
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< GlobalAlgBlkBxCollection > m_l1tResultsToken
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
#define N
Definition: blowfish.cc:9
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::vector< bool > const & getAlgoDecisionInitial() const
Get decision bits.
Definition: GlobalAlgBlk.h:82
HLT enums.
static constexpr unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:52
void setPreScColumn(int psC)
Definition: GlobalAlgBlk.h:61
Log< level::Warning, false > LogWarning
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
long double T
def move(src, dest)
Definition: eostools.py:511
void setAlgoDecisionFinal(unsigned int bit, bool val)
Definition: GlobalAlgBlk.cc:94
L1TGlobalPrescaler(edm::ParameterSet const &config)
Definition: event.py:1