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