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 
93 }
94 
95 // ############################################################################
96 
97 
109 
111 public:
113 
114  virtual bool filter(edm::Event& event, edm::EventSetup const& setup) override;
115 
116  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
117 
118 private:
119  enum class Mode {
120  ApplyPrescaleValues, // apply the given prescale values
121  ApplyPrescaleRatios, // apply prescales equal to ratio between the given values and the ones read from the EventSetup
122  ApplyColumnValues, // apply the prescale values from the EventSetup corresponding to the given column index
123  ApplyColumnRatios, // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
124  Invalid = -1
125  };
126 
127  static const
128  constexpr Entry<Mode> s_modes[] {
129  { Mode::ApplyPrescaleValues, "applyPrescaleValues", "apply the given prescale values" },
130  { Mode::ApplyPrescaleRatios, "applyPrescaleRatios", "apply prescales equal to ratio between the given values and the ones read from the EventSetup" },
131  { Mode::ApplyColumnValues, "applyColumnValues", "apply the prescale values from the EventSetup corresponding to the given column index" },
132  { Mode::ApplyColumnRatios, "applyColumnRatios", "apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup" },
133  { Mode::Invalid, nullptr, nullptr }
134  };
135 
136  const Mode m_mode;
138  const std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_l1tPrescales;
139  std::array<double, GlobalAlgBlk::maxPhysicsTriggers> m_prescales;
140  std::array<unsigned int, GlobalAlgBlk::maxPhysicsTriggers> m_counters;
143 
144 };
145 
146 const
147 constexpr Entry<L1TGlobalPrescaler::Mode> L1TGlobalPrescaler::s_modes[];
148 
149 
151  m_mode( get_enum_value(s_modes, config.getParameter<std::string>("mode").c_str(), Mode::Invalid) ),
152  m_l1tResultsToken( consumes<GlobalAlgBlkBxCollection>(config.getParameter<edm::InputTag>("l1tResults")) ),
153  m_l1tPrescales( m_mode == Mode::ApplyPrescaleValues or m_mode == Mode::ApplyPrescaleRatios ?
154  make_array<double, GlobalAlgBlk::maxPhysicsTriggers>(config.getParameter<std::vector<double>>("l1tPrescales")) :
155  std::array<double, GlobalAlgBlk::maxPhysicsTriggers>() ),
156  m_l1tPrescaleColumn( m_mode == Mode::ApplyColumnValues or m_mode == Mode::ApplyColumnRatios ?
157  config.getParameter<uint32_t>("l1tPrescaleColumn") : 0 ),
158  m_oldIndex(-1)
159 {
160  switch (m_mode) {
161  // if the mode is "applyPrescaleValues", use the given values
164  break;
165 
166  // otherwise we need to read the prescale values from the EventSetup
170  break;
171 
172  // this should never happen
173  case Mode::Invalid:
174  throw edm::Exception(edm::errors::Configuration) << "invalid mode \"" << config.getParameter<std::string>("mode") << "\"";
175  }
176 
177  m_counters.fill(0);
178  produces<GlobalAlgBlkBxCollection>();
179 }
180 
183  event.getByToken(m_l1tResultsToken, handle);
184 
185  // if the input collection does not have any information for bx 0,
186  // produce an empty collection, and fail
187  if (handle->isEmpty(0)) {
188  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
189  event.put(std::move(result));
190  return false;
191  }
192 
193  // read the prescale index
194  int index = handle->at(0,0).getPreScColumn();
195  assert(index >= 0);
196 
197  // Mode::ApplyPrescaleRatios
198  // apply prescales equal to ratio between the given values and the ones read from the EventSetup
199  if (m_mode == Mode::ApplyPrescaleRatios and m_oldIndex != index) {
201  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
202  auto const & prescaleTable = h->prescale_table_;
203  if (index >= (int) prescaleTable.size())
204  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();
205  auto const & prescales = prescaleTable[index];
206  unsigned long i = 0;
207  for (; i < std::min(prescales.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers); ++i)
208  if (prescales[i] == 0)
209  // if the trigger was disabled, keep it disabled
210  m_prescales[i] = 0.;
211  else
212  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
213  m_prescales[i] = m_l1tPrescales[i] < prescales[i] ? 1. : (double) m_l1tPrescales[i] / prescales[i];
214  for (; i < (unsigned long) GlobalAlgBlk::maxPhysicsTriggers; ++i)
215  // disable the triggers not included in the prescale table
216  m_prescales[i] = 0.;
217  // reset the prescales
218  m_counters.fill(0);
219  m_oldIndex = index;
220  }
221 
222  // Mode::ApplyColumnValues
223  // apply the prescale values from the EventSetup corresponding to the given column index
226  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
227  auto const & prescaleTable = h->prescale_table_;
228  if (m_l1tPrescaleColumn >= (int) prescaleTable.size())
229  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();
230  auto const & targets = prescaleTable[m_l1tPrescaleColumn];
231  unsigned long i = 0;
232  for (; i < std::min(targets.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers); ++i)
233  // read the prescales from the EventSetup
234  m_prescales[i] = targets[i];
235  for (; i < (unsigned long) GlobalAlgBlk::maxPhysicsTriggers; ++i)
236  // disable the triggers not included in the prescale table
237  m_prescales[i] = 0.;
238  // reset the prescales
239  m_counters.fill(0);
241  }
242 
243  // Mode::ApplyColumnRatios
244  // apply prescales equal to ratio between the values corresponsing to the given column index, and the ones read from the EventSetup
245  if (m_mode == Mode::ApplyColumnRatios and m_oldIndex != index) {
247  setup.get<L1TGlobalPrescalesVetosRcd>().get(h);
248  auto const & prescaleTable = h->prescale_table_;
249  if (index >= (int) prescaleTable.size())
250  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();
251  if (m_l1tPrescaleColumn >= (int) prescaleTable.size())
252  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();
253  auto const & prescales = prescaleTable[index];
254  auto const & targets = prescaleTable[m_l1tPrescaleColumn];
255  unsigned long i = 0;
256  for (; i < std::min({prescales.size(), targets.size(), (unsigned long) GlobalAlgBlk::maxPhysicsTriggers}); ++i)
257  if (prescales[i] == 0)
258  // if the trigger was disabled, keep it disabled
259  m_prescales[i] = 0.;
260  else
261  // if the target prescale is lower than the original prescale, keep the trigger unprescaled
262  m_prescales[i] = targets[i] < prescales[i] ? 1. : (double) targets[i] / prescales[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);
268  m_oldIndex = index;
269  }
270 
271  // make a copy of the GlobalAlgBlk for bx 0
272  GlobalAlgBlk algoBlock = handle->at(0,0);
273 
274  bool finalOr = false;
275 
276  for (unsigned int i = 0; i < GlobalAlgBlk::maxPhysicsTriggers; ++i) {
277  if (m_prescales[i] == 0) {
278  // mask this trigger: reset the bit
279  algoBlock.setAlgoDecisionFinal(i, false);
280  } else if (algoBlock.getAlgoDecisionFinal(i)) {
281  // prescale this trigger
282  ++m_counters[i];
283  if (std::fmod(m_counters[i], m_prescales[i]) < 1)
284  // the prescale is successful, keep the bit set
285  finalOr = true;
286  else
287  // the prescale failed, reset the bit
288  algoBlock.setAlgoDecisionFinal(i, false);
289  }
290  }
291 
292  // set the final OR
293  algoBlock.setFinalORPreVeto(finalOr);
294  if (algoBlock.getFinalORVeto())
295  finalOr = false;
296  algoBlock.setFinalOR(finalOr);
297 
298  // set the new prescale column
301 
302  // create a new GlobalAlgBlkBxCollection, and set the new prescaled decisions for bx 0
303  std::unique_ptr<GlobalAlgBlkBxCollection> result(new GlobalAlgBlkBxCollection());
304  result->push_back(0, algoBlock);
305  event.put(std::move(result));
306 
307  return finalOr;
308 }
309 
310 
312  // collection with the original uGT results
313  edm::ParameterDescription<edm::InputTag> l1tResults("l1tResults", edm::InputTag("gtStage2Digis"), true);
314  l1tResults.setComment("Collection with the original uGT results");
315 
316  // define how to apply the prescale values
317  edm::ParameterDescription<std::string> mode("mode", "applyPrescaleValues", true);
318  mode.setComment(build_comment_from_entries("Define how to apply the prescale values:", s_modes));
319 
320  // target prescale values (for modes "applyPrescaleValues" or "applyPrescaleRatios")
321  edm::ParameterDescription<std::vector<double>> l1tPrescales("l1tPrescales", std::vector<double>(GlobalAlgBlk::maxPhysicsTriggers, 1.), true);
322  l1tPrescales.setComment("Target prescale values (for modes \"applyPrescaleValues\" or \"applyPrescaleRatios\")");
323 
324  // target prescale column (for modes "applyColumnValues" or "applyColumnRatios")
325  edm::ParameterDescription<uint32_t> l1tPrescaleColumn("l1tPrescaleColumn", 0, true);
326  l1tPrescaleColumn.setComment("Target prescale column (for modes \"applyColumnValues\" or \"applyColumnRatios\")");
327 
328  // validaton of all possible configurations and applyPrescaleValues example
329  {
331  desc.addNode(l1tResults);
332  desc.ifValue(mode,
333  // if mode is "applyPrescaleValues" or "applyPrescaleRatios", read the target prescales
334  "applyPrescaleValues" >> l1tPrescales or
335  "applyPrescaleRatios" >> l1tPrescales or
336  // if mode is "applyColumnValues" or "applyColumnRatios", read the target column
337  "applyColumnValues" >> l1tPrescaleColumn or
338  "applyColumnRatios" >> l1tPrescaleColumn );
339  descriptions.add("l1tGlobalPrescaler", desc);
340  }
341 
342  // applyColumnRatios example
343  {
345  desc.addNode(l1tResults);
346  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");
347  desc.addNode(l1tPrescaleColumn);
348  descriptions.add("l1tGlobalPrescalerTargetColumn", desc);
349  }
350 }
351 
352 
353 // register as a framework plugin
T getParameter(std::string const &) const
void setComment(std::string const &value)
int i
Definition: DBlmapReader.cc:9
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
virtual 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:56
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