CMS 3D CMS Logo

L1TGlobalPrescaler.cc
Go to the documentation of this file.
1 #include <vector>
2 #include <array>
3 #include <memory>
4 #include <cassert>
5 #include <string>
6 #include <stdexcept>
7 #include <cstring>
8 
9 #include <boost/format.hpp>
10 
11 template <class T, std::size_t N>
12 std::array<T, N> make_array(std::vector<T> const& values) {
13  assert(N == values.size());
14  std::array<T, N> ret;
15  std::copy(values.begin(), values.end(), ret.begin());
16  return ret;
17 }
18 
19 template <class T>
20 bool empty(T const& container) {
21  return container.empty();
22 }
23 
24 bool empty(const char* container) { return container != nullptr; }
25 
26 using namespace std::literals;
27 
28 namespace {
29 
30  template <class T>
31  struct Entry {
32  T value;
33  const char* tag;
34  const char* description;
35  };
36 
37  template <typename S, typename T, unsigned int N>
38  std::string build_comment_from_entries(S pre, const Entry<T> (&entries)[N]) {
39  std::string comment{pre};
40  size_t length = 0;
41  for (auto entry : entries)
42  if (entry.tag)
43  length = std::max(std::strlen(entry.tag), length);
44  for (auto entry : entries)
45  if (entry.tag) {
46  comment.reserve(comment.size() + length + std::strlen(entry.description) + 8);
47  comment += "\n \"";
48  comment += entry.tag;
49  comment += "\": ";
50  for (unsigned int i = 0; i < length - std::strlen(entry.tag); ++i)
51  comment += ' ';
52  comment += entry.description;
53  }
54  return comment;
55  }
56 
57  template <typename S1, typename S2, typename T, unsigned int N>
58  std::string build_comment_from_entries(S1 pre, const Entry<T> (&entries)[N], S2 post) {
59  std::string comment = build_comment_from_entries(pre, entries);
60  comment += '\n';
61  comment += post;
62  return comment;
63  }
64 
65  template <class T>
66 #if __cplusplus > 201400
67  // extended constexpr support in C++14 and later
68  constexpr
69 #endif
70  T
71  get_enum_value(Entry<T> const* entries, const char* tag) {
72  for (; entries->tag; ++entries)
73  if (std::strcmp(entries->tag, tag) == 0)
74  return entries->value;
75  throw std::logic_error("invalid tag "s + tag);
76  }
77 
78  template <class T>
79 #if __cplusplus > 201400
80  // extended constexpr support in C++14 and later
81  constexpr
82 #endif
83  T
84  get_enum_value(Entry<T> const* entries, const char* tag, T default_value) {
85  for (; entries->tag; ++entries)
86  if (std::strcmp(entries->tag, tag) == 0)
87  return entries->value;
88  return default_value;
89  }
90 
91 } // namespace
92 
93 // ############################################################################
94 
107 
108 namespace {
109 
110  template <typename T, std::size_t N, typename S>
111  std::array<T, N> getParameterArray(edm::ParameterSet const& config, S const& name) {
112  std::vector<T> values = config.getParameter<std::vector<T>>(name);
113  if (values.size() != N)
115  << "Parameter \"" << name << "\" should have " << N << " elements.\n"
116  << "The number of elements in the configuration is incorrect.";
117  std::array<T, N> ret;
118  std::copy(values.begin(), values.end(), ret.begin());
119  return ret;
120  }
121 
122 } // namespace
123 
125 public:
127 
128  bool filter(edm::Event& event, edm::EventSetup const& setup) override;
129 
130  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
131 
132 private:
133  enum class Mode {
134  ApplyPrescaleValues, // apply the given prescale values
135  ApplyPrescaleRatios, // apply prescales equal to ratio between the given values and the ones read from the EventSetup
136  ApplyColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index
137  ApplyColumnRatios, // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
138  ForcePrescaleValues, // apply the given prescale values, ignoring the prescales and masks already applied
139  ForceColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index, ignoring the prescales and masks already applied
140  Invalid = -1
141  };
142 
143  static const constexpr Entry<Mode> s_modes[]{
144  {Mode::ApplyPrescaleValues, "applyPrescaleValues", "apply the given prescale values"},
145  {Mode::ApplyPrescaleRatios,
146  "applyPrescaleRatios",
147  "apply prescales equal to ratio between the given values and the ones read from the EventSetup"},
148  {Mode::ApplyColumnValues,
149  "applyColumnValues",
150  "apply the prescale values from the EventSetup corresponding to the given column index"},
151  {Mode::ApplyColumnRatios,
152  "applyColumnRatios",
153  "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read "
154  "from the EventSetup"},
155  {Mode::ForcePrescaleValues,
156  "forcePrescaleValues",
157  "apply the given prescale values, ignoring the prescales and masks already applied"},
158  {Mode::ForceColumnValues,
159  "forceColumnValues",
160  "apply the prescale values from the EventSetup corresponding to the given column index, ignoring the prescales "
161  "and masks already applied"},
162  {Mode::Invalid, nullptr, nullptr}};
163 
164  const Mode m_mode;
166  const std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_l1tPrescales;
167  std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_prescales;
168  std::array<unsigned int, GlobalAlgBlk::maxPhysicsTriggers> m_counters;
171 };
172 
173 const constexpr Entry<L1TGlobalPrescaler::Mode> L1TGlobalPrescaler::s_modes[];
174 
176  : m_mode(get_enum_value(s_modes, config.getParameter<std::string>("mode").c_str(), Mode::Invalid)),
177  m_l1tResultsToken(consumes<GlobalAlgBlkBxCollection>(config.getParameter<edm::InputTag>("l1tResults"))),
178  m_l1tPrescales(m_mode == Mode::ApplyPrescaleValues or m_mode == Mode::ApplyPrescaleRatios or
179  m_mode == Mode::ForcePrescaleValues
180  ? getParameterArray<double, GlobalAlgBlk::maxPhysicsTriggers>(config, "l1tPrescales")
181  : std::array<double, GlobalAlgBlk::maxPhysicsTriggers>()),
182  m_l1tPrescaleColumn(m_mode == Mode::ApplyColumnValues or m_mode == Mode::ApplyColumnRatios or
183  m_mode == Mode::ForceColumnValues
184  ? config.getParameter<uint32_t>("l1tPrescaleColumn")
185  : 0),
186  m_oldIndex(-1) {
187  switch (m_mode) {
188  // if the mode is "applyPrescaleValues", use the given values
192  break;
193 
194  // otherwise we need to read the prescale values from the EventSetup
199  break;
200 
201  // this should never happen
202  case Mode::Invalid:
204  << "invalid mode \"" << config.getParameter<std::string>("mode") << "\"";
205  }
206 
207  m_counters.fill(0);
208  produces<GlobalAlgBlkBxCollection>();
209 }
210 
213  event.getByToken(m_l1tResultsToken, handle);
214 
215  // if the input collection does not have any information for bx 0,
216  // produce an empty collection, and fail
217  if (handle->isEmpty(0)) {
218  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
219  event.put(std::move(result));
220  return false;
221  }
222 
223  // read the prescale index
224  int index = handle->at(0, 0).getPreScColumn();
225  assert(index >= 0);
226 
227  // Mode::ApplyPrescaleRatios
228  // apply prescales equal to ratio between the given values and the ones read from the EventSetup
229  if (m_mode == Mode::ApplyPrescaleRatios and m_oldIndex != index) {
231  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
232  auto const& prescaleTable = h->prescale_table_;
233  if (index >= (int)prescaleTable.size())
235  << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") %
236  index % prescaleTable.size();
237  auto const& prescales = prescaleTable[index];
238  unsigned long i = 0;
239  for (; i < std::min(prescales.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers); ++i)
240  if (m_l1tPrescales[i] == 0) {
241  // if the trigger is requested to be disabled, just do it
242  m_prescales[i] = 0.;
243  } else if (prescales[i] == 0) {
244  // othersie, if the trigger was originally disabled, warn the user and keep it that way
245  m_prescales[i] = 0.;
246  edm::LogWarning("L1TGlobalPrescaler")
247  << "Request to enable the trigger " << i << " which was originally disabled\nIt will be kept disabled.";
248  } else if (m_l1tPrescales[i] < prescales[i]) {
249  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
250  m_prescales[i] = 1.;
251  edm::LogWarning("L1TGlobalPrescaler")
252  << "Request to prescale the trigger " << i
253  << " less than it was originally prescaled\nNo further prescale will be applied.";
254  } else {
255  // apply the ratio of the new and old prescales
256  m_prescales[i] = (double)m_l1tPrescales[i] / prescales[i];
257  }
258  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
259  // disable the triggers not included in the prescale table
260  m_prescales[i] = 0.;
261  // reset the prescales
262  m_counters.fill(0);
263  m_oldIndex = index;
264  }
265 
266  // Mode::ApplyColumnValues and Mode::ForceColumnValues
267  // apply the prescale values from the EventSetup corresponding to the given column index
270  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
271  auto const& prescaleTable = h->prescale_table_;
272  if (m_l1tPrescaleColumn >= (int)prescaleTable.size())
274  << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") %
277  unsigned long i = 0;
278  for (; i < std::min(targets.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers); ++i)
279  // read the prescales from the EventSetup
280  m_prescales[i] = targets[i];
281  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
282  // disable the triggers not included in the prescale table
283  m_prescales[i] = 0.;
284  // reset the prescales
285  m_counters.fill(0);
287  }
288 
289  // Mode::ApplyColumnRatios
290  // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
291  if (m_mode == Mode::ApplyColumnRatios and m_oldIndex != index) {
293  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
294  auto const& prescaleTable = h->prescale_table_;
295  if (index >= (int)prescaleTable.size())
297  << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") %
298  index % prescaleTable.size();
299  if (m_l1tPrescaleColumn >= (int)prescaleTable.size())
301  << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") %
303  auto const& prescales = prescaleTable[index];
305  unsigned long i = 0;
306  for (; i < std::min({prescales.size(), targets.size(), (unsigned long)GlobalAlgBlk::maxPhysicsTriggers}); ++i)
307  if (prescales[i] == 0)
308  // if the trigger was disabled, keep it disabled
309  m_prescales[i] = 0.;
310  else
311  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
312  m_prescales[i] = targets[i] < prescales[i] ? 1. : (double)targets[i] / prescales[i];
313  for (; i < (unsigned long)GlobalAlgBlk::maxPhysicsTriggers; ++i)
314  // disable the triggers not included in the prescale table
315  m_prescales[i] = 0.;
316  // reset the prescales
317  m_counters.fill(0);
318  m_oldIndex = index;
319  }
320 
321  // make a copy of the GlobalAlgBlk for bx 0
322  GlobalAlgBlk algoBlock = handle->at(0, 0);
323 
324  bool finalOr = false;
325  std::vector<bool> const& decision = (m_mode == Mode::ForceColumnValues or m_mode == Mode::ForcePrescaleValues)
326  ? algoBlock.getAlgoDecisionInitial()
327  : algoBlock.getAlgoDecisionFinal();
328 
329  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
330  if (m_prescales[i] == 0) {
331  // mask this trigger: reset the bit
332  algoBlock.setAlgoDecisionFinal(i, false);
333  } else if (decision[i]) {
334  // prescale this trigger
335  ++m_counters[i];
336  if (std::fmod(m_counters[i], m_prescales[i]) < 1) {
337  // the prescale is successful, set the bit
338  algoBlock.setAlgoDecisionFinal(i, true);
339  finalOr = true;
340  } else {
341  // the prescale failed, reset the bit
342  algoBlock.setAlgoDecisionFinal(i, false);
343  }
344  }
345  }
346 
347  // set the final OR
348  algoBlock.setFinalORPreVeto(finalOr);
349  if (algoBlock.getFinalORVeto())
350  finalOr = false;
351  algoBlock.setFinalOR(finalOr);
352 
353  // set the new prescale column
356 
357  // create a new GlobalAlgBlkBxCollection, and set the new prescaled decisions for bx 0
358  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
359  result->push_back(0, algoBlock);
360  event.put(std::move(result));
361 
362  return finalOr;
363 }
364 
366  // collection with the original uGT results
367  edm::ParameterDescription<edm::InputTag> l1tResults("l1tResults", edm::InputTag("gtStage2Digis"), true);
368  l1tResults.setComment("Collection with the original uGT results");
369 
370  // define how to apply the prescale values
371  edm::ParameterDescription<std::string> mode("mode", "applyPrescaleValues", true);
372  mode.setComment(build_comment_from_entries("Define how to apply the prescale values:", s_modes));
373 
374  // target prescale values (for modes "applyPrescaleValues" or "applyPrescaleRatios")
376  "l1tPrescales", std::vector<double>(GlobalAlgBlk::maxPhysicsTriggers, 1.), true);
377  l1tPrescales.setComment(
378  "Target prescale values (for modes \"applyPrescaleValues\", \"applyPrescaleRatios\" or \"forcePrescaleValues\")");
379 
380  // target prescale column (for modes "applyColumnValues" or "applyColumnRatios")
381  edm::ParameterDescription<uint32_t> l1tPrescaleColumn("l1tPrescaleColumn", 0, true);
382  l1tPrescaleColumn.setComment(
383  "Target prescale column (for modes \"applyColumnValues\", \"applyColumnRatios\" or \"forceColumnValues\")");
384 
385  // validaton of all possible configurations and applyPrescaleValues example
386  {
388  desc.addNode(l1tResults);
389  desc.ifValue(
390  mode,
391  // if mode is "applyPrescaleValues", "applyPrescaleRatios" or "forcePrescaleValues", read the target prescales
392  "applyPrescaleValues" >> l1tPrescales or "applyPrescaleRatios" >> l1tPrescales or
393  "forcePrescaleValues" >> l1tPrescales or
394  // if mode is "applyColumnValues", "applyColumnRatios" or "forceColumnValues", read the target column
395  "applyColumnValues" >> l1tPrescaleColumn or "applyColumnRatios" >> l1tPrescaleColumn or
396  "forceColumnValues" >> l1tPrescaleColumn);
397  descriptions.add("l1tGlobalPrescaler", desc);
398  }
399 
400  // applyColumnRatios example
401  {
403  desc.addNode(l1tResults);
404  desc.add<std::string>("mode", "applyColumnRatios")
405  ->setComment(
406  "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones "
407  "read from the EventSetup");
408  desc.addNode(l1tPrescaleColumn);
409  descriptions.add("l1tGlobalPrescalerTargetColumn", desc);
410  }
411 }
412 
413 // register as a framework plugin
T getParameter(std::string const &) const
void setComment(std::string const &value)
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
ParameterDescriptionNode * ifValue(ParameterDescription< T > const &switchParameter, std::unique_ptr< ParameterDescriptionCases< T >> cases)
std::vector< bool > const & getAlgoDecisionInitial() const
Get decision bits.
Definition: GlobalAlgBlk.h:82
void setFinalORPreVeto(bool fOR)
Definition: GlobalAlgBlk.h:59
std::vector< bool > const & getAlgoDecisionFinal() const
Definition: GlobalAlgBlk.h:84
ret
prodAgent to be discontinued
const std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_l1tPrescales
std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_prescales
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
std::array< unsigned int, GlobalAlgBlk::maxPhysicsTriggers > m_counters
bool isEmpty(int bx) const
BXVector< GlobalAlgBlk > GlobalAlgBlkBxCollection
Definition: GlobalAlgBlk.h:31
Definition: config.py:1
const bool getFinalORVeto() const
Definition: GlobalAlgBlk.h:69
std::array< T, N > make_array(std::vector< T > const &values)
Entry(const ALIstring &type)
Definition: Entry.cc:22
bool filter(edm::Event &event, edm::EventSetup const &setup) override
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
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
bool empty(T const &container)
T min(T a, T b)
Definition: MathUtil.h:58
ParameterDescriptionBase * add(U const &iLabel, T const &value)
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)
static unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:52
#define N
Definition: blowfish.cc:9
std::vector< std::vector< int > > prescale_table_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
HLT enums.
T get() const
Definition: EventSetup.h:73
void setPreScColumn(int psC)
Definition: GlobalAlgBlk.h:61
long double T
static const Entry< Mode > s_modes[]
def move(src, dest)
Definition: eostools.py:511
#define constexpr
void setAlgoDecisionFinal(unsigned int bit, bool val)
Definition: GlobalAlgBlk.cc:94
L1TGlobalPrescaler(edm::ParameterSet const &config)
Definition: event.py:1
#define comment(par)
Definition: vmac.h:163
const T & at(int bx, unsigned i) const