CMS 3D CMS Logo

TriggerObjectStandAlone.cc
Go to the documentation of this file.
1 #include <oneapi/tbb/concurrent_unordered_map.h>
2 #include <boost/algorithm/string.hpp>
3 
14 
15 using namespace pat;
16 
17 // Const data members' definitions
18 
20 
21 // Constructors and Destructor
22 
23 // Default constructor
25  filterLabels_.clear();
26  filterLabelIndices_.clear();
27  pathNames_.clear();
29  pathL3FilterAccepted_.clear();
30 }
31 
32 // Constructor from pat::TriggerObject
34  filterLabels_.clear();
35  filterLabelIndices_.clear();
36  pathNames_.clear();
38  pathL3FilterAccepted_.clear();
39 }
40 
41 // Constructor from trigger::TriggerObject
43  filterLabels_.clear();
44  filterLabelIndices_.clear();
45  pathNames_.clear();
47  pathL3FilterAccepted_.clear();
48 }
49 
50 // Constructor from reco::Candidate
52  filterLabels_.clear();
53  filterLabelIndices_.clear();
54  pathNames_.clear();
56  pathL3FilterAccepted_.clear();
57 }
58 
59 // Constructors from Lorentz-vectors and (optional) PDG ID
61  : TriggerObject(vec, id) {
62  filterLabels_.clear();
63  filterLabelIndices_.clear();
64  pathNames_.clear();
66  pathL3FilterAccepted_.clear();
67 }
69  : TriggerObject(vec, id) {
70  filterLabels_.clear();
71  filterLabelIndices_.clear();
72  pathNames_.clear();
74  pathL3FilterAccepted_.clear();
75 }
76 
77 // Private methods
78 
79 // Checks a string vector for occurence of a certain string, incl. wild-card mechanism
80 bool TriggerObjectStandAlone::hasAnyName(const std::string &name, const std::vector<std::string> &nameVec) const {
81  // Special cases first
82  // Always false for empty vector to check
83  if (nameVec.empty())
84  return false;
85  // Always true for general wild-card(s)
86  if (name.find_first_not_of(wildcard_) == std::string::npos)
87  return true;
88  // Split name to evaluate in parts, seperated by wild-cards
89  std::vector<std::string> namePartsVec;
90  boost::split(namePartsVec, name, boost::is_any_of(std::string(1, wildcard_)), boost::token_compress_on);
91  // Iterate over vector of names to search
92  for (std::vector<std::string>::const_iterator iVec = nameVec.begin(); iVec != nameVec.end(); ++iVec) {
93  // Not failed yet
94  bool failed(false);
95  // Start searching at the first character
96  size_type index(0);
97  // Iterate over evaluation name parts
98  for (std::vector<std::string>::const_iterator iName = namePartsVec.begin(); iName != namePartsVec.end(); ++iName) {
99  // Empty parts due to
100  // - wild-card at beginning/end or
101  // - multiple wild-cards (should be supressed by 'boost::token_compress_on')
102  if (iName->length() == 0)
103  continue;
104  // Search from current index and
105  // set index to found occurence
106  index = iVec->find(*iName, index);
107  // Failed and exit loop, if
108  // - part not found
109  // - part at beginning not found there
110  if (index == std::string::npos || (iName == namePartsVec.begin() && index > 0)) {
111  failed = true;
112  break;
113  }
114  // Increase index by length of found part
115  index += iName->length();
116  }
117  // Failed, if end of name not reached
118  if (index < iVec->length() && namePartsVec.back().length() != 0)
119  failed = true;
120  // Match found!
121  if (!failed)
122  return true;
123  }
124  // No match found!
125  return false;
126 }
127 
128 // Adds a new HLT path or L1 algorithm name
130  bool pathLastFilterAccepted,
131  bool pathL3FilterAccepted) {
133 
134  // Check, if path is already assigned
135  if (!hasPathOrAlgorithm(name, false, false)) {
136  // The path itself
137  pathNames_.push_back(name);
138  // The corresponding usage of the trigger objects
139  pathLastFilterAccepted_.push_back(pathLastFilterAccepted);
140  pathL3FilterAccepted_.push_back(pathL3FilterAccepted);
141  // Enable status updates
142  } else if (pathLastFilterAccepted || pathL3FilterAccepted) {
143  // Search for path
144  unsigned index(0);
145  while (index < pathNames_.size()) {
146  if (pathNames_.at(index) == name)
147  break;
148  ++index;
149  }
150  // Status update
151  if (index < pathNames_.size()) {
152  pathLastFilterAccepted_.at(index) = pathLastFilterAccepted_.at(index) || pathLastFilterAccepted;
153  pathL3FilterAccepted_.at(index) = pathL3FilterAccepted_.at(index) || pathL3FilterAccepted;
154  }
155  }
156 }
157 
158 // Gets all HLT path or L1 algorithm names
159 std::vector<std::string> TriggerObjectStandAlone::pathsOrAlgorithms(bool pathLastFilterAccepted,
160  bool pathL3FilterAccepted) const {
162 
163  // Deal with older PAT-tuples, where trigger object usage is not available
164  if (!hasLastFilter())
165  pathLastFilterAccepted = false;
166  if (!hasL3Filter())
167  pathL3FilterAccepted = false;
168  // All path names, if usage not restricted (not required or not available)
169  if (!pathLastFilterAccepted && !pathL3FilterAccepted)
170  return pathNames_;
171  // Temp vector of path names
172  std::vector<std::string> paths;
173  // Loop over usage vector and fill corresponding paths into temp vector
174  for (unsigned iPath = 0; iPath < pathNames_.size(); ++iPath) {
175  if ((!pathLastFilterAccepted || pathLastFilterAccepted_.at(iPath)) &&
176  (!pathL3FilterAccepted || pathL3FilterAccepted_.at(iPath)))
177  paths.push_back(pathNames_.at(iPath)); // order matters in order to protect from empty vectors in old data
178  }
179  // Return temp vector
180  return paths;
181 }
182 
183 // Checks, if a certain HLT filter label or L1 condition name is assigned
186 
187  // Move to wild-card parser, if needed
188  if (name.find(wildcard_) != std::string::npos)
189  return hasAnyName(name, filterLabels_);
190  // Return, if filter label is assigned
191  return (std::find(filterLabels_.begin(), filterLabels_.end(), name) != filterLabels_.end());
192 }
193 
194 // Checks, if a certain path name is assigned
196  bool pathLastFilterAccepted,
197  bool pathL3FilterAccepted) const {
199 
200  // Move to wild-card parser, if needed
201  if (name.find(wildcard_) != std::string::npos)
202  return hasAnyName(name, pathsOrAlgorithms(pathLastFilterAccepted, pathL3FilterAccepted));
203  // Deal with older PAT-tuples, where trigger object usage is not available
204  if (!hasLastFilter())
205  pathLastFilterAccepted = false;
206  if (!hasL3Filter())
207  pathL3FilterAccepted = false;
208  // Check, if path name is assigned at all
209  std::vector<std::string>::const_iterator match(std::find(pathNames_.begin(), pathNames_.end(), name));
210  // False, if path name not assigned
211  if (match == pathNames_.end())
212  return false;
213  if (!pathLastFilterAccepted && !pathL3FilterAccepted)
214  return true;
215  bool foundLastFilter(pathLastFilterAccepted ? pathLastFilterAccepted_.at(match - pathNames_.begin()) : true);
216  bool foundL3Filter(pathL3FilterAccepted ? pathL3FilterAccepted_.at(match - pathNames_.begin()) : true);
217  // Return for assigned path name, if trigger object usage meets requirement
218  return (foundLastFilter && foundL3Filter);
219 }
220 
221 // Methods
222 
223 // Gets the pat::TriggerObject (parent class)
225  // Create a TriggerObjects
226  TriggerObject theObj(p4(), pdgId());
227  // Set its collection and trigger objects types (no c'tor for that)
228  theObj.setCollection(collection());
229  for (size_t i = 0; i < triggerObjectTypes().size(); ++i)
231  // Return TriggerObject
232  return theObj;
233 }
234 
235 // Checks, if a certain label of original collection is assigned (method overrides)
237  // Move to wild-card parser, if needed only
238  if (collName.find(wildcard_) != std::string::npos) {
239  // True, if collection name is simply fine
240  if (hasAnyName(collName, std::vector<std::string>(1, collection())))
241  return true;
242  // Check, if collection name possibly fits in an edm::InputTag approach
243  const edm::InputTag collectionTag(collection());
244  const edm::InputTag collTag(collName);
245  // If evaluated collection tag contains a process name, it must have been found already by identity check
246  if (collTag.process().empty()) {
247  // Check instance ...
248  if ((collTag.instance().empty() && collectionTag.instance().empty()) ||
249  hasAnyName(collTag.instance(), std::vector<std::string>(1, collectionTag.instance()))) {
250  // ... and label
251  return hasAnyName(collTag.label(), std::vector<std::string>(1, collectionTag.label()));
252  }
253  }
254  return false;
255  }
256  // Use parent class's method otherwise
258 }
259 
260 bool TriggerObjectStandAlone::checkIfPathsAreUnpacked(bool throwIfPacked) const {
261  bool unpacked = (!pathNames_.empty() || pathIndices_.empty());
262  if (!unpacked && throwIfPacked)
263  throw cms::Exception("RuntimeError",
264  "This TriggerObjectStandAlone object has packed trigger path names. Before accessing path "
265  "names you must call unpackPathNames with an edm::TriggerNames object. You can get the latter "
266  "from the edm::Event or fwlite::Event and the TriggerResults\n");
267  return unpacked;
268 }
270  bool unpacked = filterLabelIndices_.empty();
271  if (!unpacked && throwIfPacked)
272  throw cms::Exception("RuntimeError",
273  "This TriggerObjectStandAlone object has packed trigger filter labels. Before accessing path "
274  "names you must call unpackFilterLabels with an edm::EventBase object. Both the edm::Event or "
275  "fwlite::Event are derived from edm::EventBase and can be passed\n");
276  return unpacked;
277 }
278 
280  if (!pathIndices_.empty()) {
281  if (!pathNames_.empty()) {
282  throw cms::Exception("RuntimeError", "Error, trying to pack a partially packed TriggerObjectStandAlone");
283  } else {
284  return;
285  }
286  }
287  bool ok = true;
288  unsigned int n = pathNames_.size(), end = names.size();
289  std::vector<uint16_t> indices(n);
290  for (unsigned int i = 0; i < n; ++i) {
291  uint16_t id = names.triggerIndex(pathNames_[i]);
292  if (id >= end) {
293  static std::atomic<int> _warn(0);
294  if (++_warn < 5)
295  edm::LogWarning("TriggerObjectStandAlone::packPathNames()")
296  << "Warning: can't resolve '" << pathNames_[i] << "' to a path index" << std::endl;
297  ok = false;
298  break;
299  } else {
300  indices[i] = id;
301  }
302  }
303  if (ok) {
304  pathIndices_.swap(indices);
305  pathNames_.clear();
306  }
307 }
308 
310  if (!pathNames_.empty()) {
311  if (!pathIndices_.empty()) {
312  throw cms::Exception("RuntimeError", "Error, trying to unpack a partially unpacked TriggerObjectStandAlone");
313  } else {
314  return;
315  }
316  }
317  unsigned int n = pathIndices_.size(), end = names.size();
318  std::vector<std::string> paths(n);
319  for (unsigned int i = 0; i < n; ++i) {
320  if (pathIndices_[i] >= end)
321  throw cms::Exception("RuntimeError", "Error, path index out of bounds");
322  paths[i] = names.triggerName(pathIndices_[i]);
323  }
324  pathIndices_.clear();
325  pathNames_.swap(paths);
326 }
327 
328 void TriggerObjectStandAlone::packFilterLabels(const std::vector<std::string> &names) {
329  if (!filterLabelIndices_.empty()) {
330  throw cms::Exception("RuntimeError",
331  "Error, trying to pack filter labels for an already packed TriggerObjectStandAlone");
332  }
333  std::vector<std::string> unmatched;
334  std::vector<uint16_t> indices;
335  indices.reserve(filterLabels_.size());
336 
337  auto nStart = names.begin(), nEnd = names.end();
338  for (unsigned int i = 0, n = filterLabels_.size(); i < n; ++i) {
339  auto match = std::lower_bound(nStart, nEnd, filterLabels_[i]);
340  if (match != nEnd && *match == filterLabels_[i]) {
341  indices.push_back(match - nStart);
342  } else {
343  static std::atomic<int> _warn(0);
344  if (++_warn < 5)
345  edm::LogWarning("TriggerObjectStandAlone::packFilterLabels()")
346  << "Warning: can't resolve '" << filterLabels_[i] << "' to a label index. idx: " << i << std::endl;
347  unmatched.push_back(std::move(filterLabels_[i]));
348  }
349  }
350  std::sort(indices.begin(), indices.end()); // try reduce enthropy
352  filterLabels_.swap(unmatched);
353 }
354 
356  unpackPathNames(event.triggerNames(res));
358 }
359 
362 }
363 
364 void TriggerObjectStandAlone::unpackFilterLabels(const std::vector<std::string> &labels) {
365  if (filterLabelIndices_.empty())
366  return;
367 
368  std::vector<std::string> mylabels(filterLabels_);
369  for (unsigned int i = 0, n = filterLabelIndices_.size(), m = labels.size(); i < n; ++i) {
370  if (filterLabelIndices_[i] >= m)
371  throw cms::Exception("RuntimeError", "Error, filter label index out of bounds");
372  mylabels.push_back(labels[filterLabelIndices_[i]]);
373  }
374  filterLabelIndices_.clear();
375  filterLabels_.swap(mylabels);
376 }
379 }
380 
382  setP4(reco::Particle::PolarLorentzVector(MiniFloatConverter::reduceMantissaToNbitsRounding<14>(pt()),
383  MiniFloatConverter::reduceMantissaToNbitsRounding<11>(eta()),
384  MiniFloatConverter::reduceMantissaToNbits<11>(phi()),
385  MiniFloatConverter::reduceMantissaToNbitsRounding<8>(mass())));
386 }
387 
388 namespace {
389  struct key_hash {
390  std::size_t operator()(edm::ParameterSetID const &iKey) const { return iKey.smallHash(); }
391  };
392  typedef tbb::concurrent_unordered_map<edm::ParameterSetID, std::vector<std::string>, key_hash> AllLabelsMap;
393  CMS_THREAD_SAFE AllLabelsMap allLabelsMap;
394 } // namespace
395 
396 std::vector<std::string> const *TriggerObjectStandAlone::allLabels(edm::ParameterSetID const &psetid,
397  const edm::EventBase &event,
398  const edm::TriggerResults &res) const {
399  // If TriggerNames was already created and cached here in the map,
400  // then look it up and return that one
401  AllLabelsMap::const_iterator iter = allLabelsMap.find(psetid);
402  if (iter != allLabelsMap.end()) {
403  return &iter->second;
404  }
405 
406  const auto &triggerNames = event.triggerNames(res);
407  edm::ParameterSet const *pset = nullptr;
408  //getting the ParameterSet from the event ensures that the registry is filled
409  if (nullptr != (pset = event.parameterSet(psetid))) {
410  using namespace std;
411  using namespace edm;
412  using namespace trigger;
413 
414  const unsigned int n(triggerNames.size());
415  std::set<std::string> saveTags;
416  for (unsigned int i = 0; i != n; ++i) {
417  if (pset->existsAs<vector<string>>(triggerNames.triggerName(i), true)) {
418  auto const &modules = pset->getParameter<vector<string>>(triggerNames.triggerName(i));
419  for (auto const &module : modules) {
421  if (pset->exists(moduleStrip)) {
422  const auto &modulePSet = pset->getParameterSet(moduleStrip);
423  if (modulePSet.existsAs<bool>("saveTags", true) and modulePSet.getParameter<bool>("saveTags")) {
424  saveTags.insert(moduleStrip);
425  }
426  }
427  }
428  }
429  }
430  std::vector<std::string> allModules(saveTags.begin(), saveTags.end());
431  std::pair<AllLabelsMap::iterator, bool> ret =
432  allLabelsMap.insert(std::pair<edm::ParameterSetID, std::vector<std::string>>(psetid, allModules));
433  return &(ret.first->second);
434  }
435  return nullptr;
436 }
void packFilterLabels(const edm::EventBase &event, const edm::TriggerResults &res)
std::vector< int > triggerObjectTypes() const
Get all trigger object type identifiers.
std::vector< std::string > const * allLabels(edm::ParameterSetID const &psetid, const edm::EventBase &event, const edm::TriggerResults &res) const
double pt() const final
transverse momentum
void packP4()
reduce the precision on the 4-vector
size_t size_type
Definition: Candidate.h:29
std::vector< uint16_t > filterLabelIndices_
static const char wildcard_
Constants.
ret
prodAgent to be discontinued
std::string const & instance() const
Definition: InputTag.h:37
size_t smallHash() const
returns a short hash which can be used with hashing containers
Definition: Hash.h:191
std::string removeSchedulingTokensFromModuleLabel(std::string iLabel)
virtual bool hasCollection(const std::string &collName) const
Checks, if a certain label of original collection is assigned.
bool hasAnyName(const std::string &name, const std::vector< std::string > &nameVec) const
Private methods.
std::string const & label() const
Definition: InputTag.h:36
void unpackPathNames(const edm::TriggerNames &names)
unpack trigger names into indices
bool checkIfFiltersAreUnpacked(bool throwIfPacked=true) const
Check if trigger names have been packed by calling packFilterLabels() and not yet unpacked...
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
const std::string names[nVars_]
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: Electron.h:6
Definition: HeavyIon.h:7
void addPathOrAlgorithm(const std::string &name, bool pathLastFilterAccepted, bool pathL3FilterAccepted)
Adds a new HLT path or L1 algorithm name.
int pdgId() const final
PDG identifier.
Single trigger physics object (e.g., an isolated muon)
Definition: TriggerObject.h:21
TriggerObject triggerObject()
Gets the pat::TriggerObject (parent class)
void setCollection(const std::string &collName)
Methods.
Definition: TriggerObject.h:79
const std::string & collection() const
Get the label of the collection the trigger object originates from.
Definition: TriggerObject.h:96
bool hasCollection(const std::string &collName) const override
Checks, if a certain label of original collection is assigned (method overrides)
TriggerObjectStandAlone()
Constructors and Destructor.
const_iterator end() const
last daughter const_iterator
Definition: Candidate.h:145
#define CMS_THREAD_SAFE
bool checkIfPathsAreUnpacked(bool throwIfPacked=true) const
Check if trigger names have been packed by calling packPathNames() and not yet unpacked.
unsigned int index
Definition: LeafCandidate.h:31
bool id(trigger::TriggerObjectType triggerObjectType) const
std::vector< bool > pathLastFilterAccepted_
unsigned int index
index type
Definition: Candidate.h:50
void unpackFilterLabels(const std::vector< std::string > &labels)
unpack filter labels from indices
bool hasLastFilter() const
Check, if the usage indicator vectors have been filled.
void packPathNames(const edm::TriggerNames &names)
pack trigger names into indices
std::vector< std::string > pathNames_
Vector of names of all HLT paths or L1 algorithms the trigger objects has been used in...
bool hasPathOrAlgorithm(const std::string &name, bool pathLastFilterAccepted, bool pathL3FilterAccepted) const
Checks, if a certain HLT path or L1 algorithm name is assigned.
std::vector< std::string > filterLabels_
Vector of labels of all HLT filters or names of L1 conditions the trigger objects has been used in...
bool hasFilterOrCondition(const std::string &name) const
Checks, if a certain HLT filter label or L1 condition name is assigned.
HLT enums.
double mass() const final
mass
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Particle.h:23
Log< level::Warning, false > LogWarning
std::string const & process() const
Definition: InputTag.h:40
void addTriggerObjectType(trigger::TriggerObjectType triggerObjectType)
Add a new trigger object type identifier.
Definition: TriggerObject.h:82
double phi() const final
momentum azimuthal angle
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Particle.h:21
std::vector< std::string > pathsOrAlgorithms(bool pathLastFilterAccepted, bool pathL3FilterAccepted) const
Gets all HLT path or L1 algorithm names.
std::vector< uint16_t > pathIndices_
void setP4(const LorentzVector &p4) final
set 4-momentum
void unpackNamesAndLabels(const edm::EventBase &event, const edm::TriggerResults &res)
unpack both filter labels and trigger names
def move(src, dest)
Definition: eostools.py:511
std::vector< bool > pathL3FilterAccepted_
Definition: event.py:1
double eta() const final
momentum pseudorapidity