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) {
25  return container != nullptr;
26 }
27 
28 
29 using namespace std::literals;
30 
31 namespace {
32 
33  template <class T>
34  struct Entry {
35  T value;
36  const char * tag;
37  const char * description;
38  };
39 
40  template <typename S, typename T, unsigned int N>
41  std::string build_comment_from_entries(S pre, const Entry<T> (&entries)[N]) {
42  std::string comment{ pre };
43  size_t length = 0;
44  for (auto entry: entries)
45  if (entry.tag)
46  length = std::max(std::strlen(entry.tag), length);
47  for (auto entry: entries)
48  if (entry.tag) {
49  comment.reserve(comment.size() + length + std::strlen(entry.description) + 8);
50  comment += "\n \"";
51  comment += entry.tag;
52  comment += "\": ";
53  for (unsigned int i = 0; i < length-std::strlen(entry.tag); ++i) comment += ' ';
54  comment += entry.description;
55  }
56  return comment;
57  }
58 
59  template <typename S1, typename S2, typename T, unsigned int N>
60  std::string build_comment_from_entries(S1 pre, const Entry<T> (&entries)[N], S2 post) {
61  std::string comment = build_comment_from_entries(pre, entries);
62  comment += '\n';
63  comment += post;
64  return comment;
65  }
66 
67 
68  template <class T>
69 #if __cplusplus > 201400
70  // extended constexpr support in C++14 and later
71  constexpr
72 #endif
73  T get_enum_value(Entry<T> const * entries, const char * tag) {
74  for (; entries->tag; ++entries)
75  if (std::strcmp(entries->tag, tag) == 0)
76  return entries->value;
77  throw std::logic_error("invalid tag "s + tag);
78  }
79 
80  template <class T>
81 #if __cplusplus > 201400
82  // extended constexpr support in C++14 and later
83  constexpr
84 #endif
85  T get_enum_value(Entry<T> const * entries, const char * tag, T default_value) {
86  for (; entries->tag; ++entries)
87  if (std::strcmp(entries->tag, tag) == 0)
88  return entries->value;
89  return default_value;
90  }
91 
92 } // anonymous
93 
94 // ############################################################################
95 
96 
109 
110 
111 namespace {
112 
113  template <typename T, std::size_t N, typename S>
114  std::array<T, N>
115  getParameterArray(edm::ParameterSet const & config, S const & name)
116  {
117  std::vector<T> values = config.getParameter<std::vector<T>>(name);
118  if (values.size() != N)
120  << "Parameter \"" << name << "\" should have " << N << " elements.\n"
121  << "The number of elements in the configuration is incorrect.";
122  std::array<T, N> ret;
123  std::copy(values.begin(), values.end(), ret.begin());
124  return ret;
125  }
126 
127 } // anonymous
128 
130 public:
132 
133  bool filter(edm::Event& event, edm::EventSetup const& setup) override;
134 
135  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
136 
137 private:
138  enum class Mode {
139  ApplyPrescaleValues, // apply the given prescale values
140  ApplyPrescaleRatios, // apply prescales equal to ratio between the given values and the ones read from the EventSetup
141  ApplyColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index
142  ApplyColumnRatios, // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
143  Invalid = -1
144  };
145 
146  static const
147  constexpr Entry<Mode> s_modes[] {
148  { Mode::ApplyPrescaleValues, "applyPrescaleValues", "apply the given prescale values" },
149  { Mode::ApplyPrescaleRatios, "applyPrescaleRatios", "apply prescales equal to ratio between the given values and the ones read from the EventSetup" },
150  { Mode::ApplyColumnValues, "applyColumnValues", "apply the prescale values from the EventSetup corresponding to the given column index" },
151  { Mode::ApplyColumnRatios, "applyColumnRatios", "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup" },
152  { Mode::Invalid, nullptr, nullptr }
153  };
154 
155  const Mode m_mode;
157  const std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_l1tPrescales;
158  std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_prescales;
159  std::array<unsigned int, GlobalAlgBlk::maxPhysicsTriggers> m_counters;
162 
163 };
164 
165 const
166 constexpr Entry<L1TGlobalPrescaler::Mode> L1TGlobalPrescaler::s_modes[];
167 
168 
170  m_mode( get_enum_value(s_modes, config.getParameter<std::string>("mode").c_str(), Mode::Invalid) ),
171  m_l1tResultsToken( consumes<GlobalAlgBlkBxCollection>(config.getParameter<edm::InputTag>("l1tResults")) ),
172  m_l1tPrescales( m_mode == Mode::ApplyPrescaleValues or m_mode == Mode::ApplyPrescaleRatios ?
173  getParameterArray<double, GlobalAlgBlk::maxPhysicsTriggers>(config, "l1tPrescales") :
174  std::array<double, GlobalAlgBlk::maxPhysicsTriggers>() ),
175  m_l1tPrescaleColumn( m_mode == Mode::ApplyColumnValues or m_mode == Mode::ApplyColumnRatios ?
176  config.getParameter<uint32_t>("l1tPrescaleColumn") : 0 ),
177  m_oldIndex(-1)
178 {
179  switch (m_mode) {
180  // if the mode is "applyPrescaleValues", use the given values
183  break;
184 
185  // otherwise we need to read the prescale values from the EventSetup
189  break;
190 
191  // this should never happen
192  case Mode::Invalid:
193  throw edm::Exception(edm::errors::Configuration) << "invalid mode \"" << config.getParameter<std::string>("mode") << "\"";
194  }
195 
196  m_counters.fill(0);
197  produces<GlobalAlgBlkBxCollection>();
198 }
199 
202  event.getByToken(m_l1tResultsToken, handle);
203 
204  // if the input collection does not have any information for bx 0,
205  // produce an empty collection, and fail
206  if (handle->isEmpty(0)) {
207  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
208  event.put(std::move(result));
209  return false;
210  }
211 
212  // read the prescale index
213  int index = handle->at(0,0).getPreScColumn();
214  assert(index >= 0);
215 
216  // Mode::ApplyPrescaleRatios
217  // apply prescales equal to ratio between the given values and the ones read from the EventSetup
218  if (m_mode == Mode::ApplyPrescaleRatios and m_oldIndex != index) {
220  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
221  auto const & prescaleTable = h->prescale_table_;
222  if (index >= (int) prescaleTable.size())
223  throw edm::Exception(edm::errors::LogicError) << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") % index % prescaleTable.size();
224  auto const & prescales = prescaleTable[index];
225  unsigned long i = 0;
226  for (; i < std::min(prescales.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers); ++i)
227  if (m_l1tPrescales[i] == 0) {
228  // if the trigger is requested to be disabled, just do it
229  m_prescales[i] = 0.;
230  } else if (prescales[i] == 0) {
231  // othersie, if the trigger was originally disabled, warn the user and keep it that way
232  m_prescales[i] = 0.;
233  edm::LogWarning("L1TGlobalPrescaler") << "Request to enable the trigger " << i << " which was originally disabled\nIt will be kept disabled.";
234  } else if (m_l1tPrescales[i] < prescales[i]) {
235  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
236  m_prescales[i] = 1.;
237  edm::LogWarning("L1TGlobalPrescaler") << "Request to prescale the trigger " << i << " less than it was originally prescaled\nNo further prescale will be applied.";
238  } else {
239  // apply the ratio of the new and old prescales
240  m_prescales[i] = (double) m_l1tPrescales[i] / prescales[i];
241  }
242  for (; i < (unsigned long) GlobalAlgBlk::maxPhysicsTriggers; ++i)
243  // disable the triggers not included in the prescale table
244  m_prescales[i] = 0.;
245  // reset the prescales
246  m_counters.fill(0);
247  m_oldIndex = index;
248  }
249 
250  // Mode::ApplyColumnValues
251  // apply the prescale values from the EventSetup corresponding to the given column index
254  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
255  auto const & prescaleTable = h->prescale_table_;
256  if (m_l1tPrescaleColumn >= (int) prescaleTable.size())
257  throw edm::Exception(edm::errors::Configuration) << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") % m_l1tPrescaleColumn % prescaleTable.size();
258  auto const & targets = prescaleTable[m_l1tPrescaleColumn];
259  unsigned long i = 0;
260  for (; i < std::min(targets.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers); ++i)
261  // read the prescales from the EventSetup
262  m_prescales[i] = targets[i];
263  for (; i < (unsigned long) GlobalAlgBlk::maxPhysicsTriggers; ++i)
264  // disable the triggers not included in the prescale table
265  m_prescales[i] = 0.;
266  // reset the prescales
267  m_counters.fill(0);
269  }
270 
271  // Mode::ApplyColumnRatios
272  // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
273  if (m_mode == Mode::ApplyColumnRatios and m_oldIndex != index) {
275  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
276  auto const & prescaleTable = h->prescale_table_;
277  if (index >= (int) prescaleTable.size())
278  throw edm::Exception(edm::errors::LogicError) << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") % index % prescaleTable.size();
279  if (m_l1tPrescaleColumn >= (int) prescaleTable.size())
280  throw edm::Exception(edm::errors::Configuration) << boost::format("The prescale index %d is invalid, it should be smaller than the prescale table size %d.") % m_l1tPrescaleColumn % prescaleTable.size();
281  auto const & prescales = prescaleTable[index];
282  auto const & targets = prescaleTable[m_l1tPrescaleColumn];
283  unsigned long i = 0;
284  for (; i < std::min({prescales.size(), targets.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers}); ++i)
285  if (prescales[i] == 0)
286  // if the trigger was disabled, keep it disabled
287  m_prescales[i] = 0.;
288  else
289  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
290  m_prescales[i] = targets[i] < prescales[i] ? 1. : (double) targets[i] / prescales[i];
291  for (; i < (unsigned long) GlobalAlgBlk::maxPhysicsTriggers; ++i)
292  // disable the triggers not included in the prescale table
293  m_prescales[i] = 0.;
294  // reset the prescales
295  m_counters.fill(0);
296  m_oldIndex = index;
297  }
298 
299  // make a copy of the GlobalAlgBlk for bx 0
300  GlobalAlgBlk algoBlock = handle->at(0,0);
301 
302  bool finalOr = false;
303 
304  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
305  if (m_prescales[i] == 0) {
306  // mask this trigger: reset the bit
307  algoBlock.setAlgoDecisionFinal(i, false);
308  } else if (algoBlock.getAlgoDecisionFinal(i)) {
309  // prescale this trigger
310  ++m_counters[i];
311  if (std::fmod(m_counters[i], m_prescales[i]) < 1)
312  // the prescale is successful, keep the bit set
313  finalOr = true;
314  else
315  // the prescale failed, reset the bit
316  algoBlock.setAlgoDecisionFinal(i, false);
317  }
318  }
319 
320  // set the final OR
321  algoBlock.setFinalORPreVeto(finalOr);
322  if (algoBlock.getFinalORVeto())
323  finalOr = false;
324  algoBlock.setFinalOR(finalOr);
325 
326  // set the new prescale column
329 
330  // create a new GlobalAlgBlkBxCollection, and set the new prescaled decisions for bx 0
331  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
332  result->push_back(0, algoBlock);
333  event.put(std::move(result));
334 
335  return finalOr;
336 }
337 
338 
340  // collection with the original uGT results
341  edm::ParameterDescription<edm::InputTag> l1tResults("l1tResults", edm::InputTag("gtStage2Digis"), true);
342  l1tResults.setComment("Collection with the original uGT results");
343 
344  // define how to apply the prescale values
345  edm::ParameterDescription<std::string> mode("mode", "applyPrescaleValues", true);
346  mode.setComment(build_comment_from_entries("Define how to apply the prescale values:", s_modes));
347 
348  // target prescale values (for modes "applyPrescaleValues" or "applyPrescaleRatios")
349  edm::ParameterDescription<std::vector<double>> l1tPrescales("l1tPrescales", std::vector<double>(GlobalAlgBlk::maxPhysicsTriggers, 1.), true);
350  l1tPrescales.setComment("Target prescale values (for modes \"applyPrescaleValues\" or \"applyPrescaleRatios\")");
351 
352  // target prescale column (for modes "applyColumnValues" or "applyColumnRatios")
353  edm::ParameterDescription<uint32_t> l1tPrescaleColumn("l1tPrescaleColumn", 0, true);
354  l1tPrescaleColumn.setComment("Target prescale column (for modes \"applyColumnValues\" or \"applyColumnRatios\")");
355 
356  // validaton of all possible configurations and applyPrescaleValues example
357  {
359  desc.addNode(l1tResults);
360  desc.ifValue(mode,
361  // if mode is "applyPrescaleValues" or "applyPrescaleRatios", read the target prescales
362  "applyPrescaleValues" >> l1tPrescales or
363  "applyPrescaleRatios" >> l1tPrescales or
364  // if mode is "applyColumnValues" or "applyColumnRatios", read the target column
365  "applyColumnValues" >> l1tPrescaleColumn or
366  "applyColumnRatios" >> l1tPrescaleColumn );
367  descriptions.add("l1tGlobalPrescaler", desc);
368  }
369 
370  // applyColumnRatios example
371  {
373  desc.addNode(l1tResults);
374  desc.add<std::string>("mode", "applyColumnRatios")->setComment("apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup");
375  desc.addNode(l1tPrescaleColumn);
376  descriptions.add("l1tGlobalPrescalerTargetColumn", desc);
377  }
378 }
379 
380 
381 // 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.
void setFinalORPreVeto(bool fOR)
Definition: GlobalAlgBlk.h:59
std::vector< bool > const & getAlgoDecisionFinal() const
Definition: GlobalAlgBlk.h:88
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
const std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_l1tPrescales
std::array< double, GlobalAlgBlk::maxPhysicsTriggers > m_prescales
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
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
#define constexpr
static const unsigned int maxPhysicsTriggers
Definition: GlobalAlgBlk.h:52
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
const int getPreScColumn() const
Definition: GlobalAlgBlk.h:70
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
ParameterDescriptionNode * ifValue(ParameterDescription< T > const &switchParameter, std::unique_ptr< ParameterDescriptionCases< T > > cases)
bool empty(T const &container)
format
Some error handling for the usage.
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
#define N
Definition: blowfish.cc:9
const T & get() const
Definition: EventSetup.h:55
std::vector< std::vector< int > > prescale_table_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
double S(const TLorentzVector &, const TLorentzVector &)
Definition: Particle.cc:99
HLT enums.
void setPreScColumn(int psC)
Definition: GlobalAlgBlk.h:61
long double T
static const Entry< Mode > s_modes[]
def move(src, dest)
Definition: eostools.py:510
void setAlgoDecisionFinal(unsigned int bit, bool val)
L1TGlobalPrescaler(edm::ParameterSet const &config)
Definition: event.py:1
#define comment(par)
Definition: vmac.h:161
const T & at(int bx, unsigned i) const