File indexing completed on 2025-01-22 07:34:02
0001 #include "TriggerSelector.h"
0002
0003 #include "DataFormats/Common/interface/HLTPathStatus.h"
0004 #include "DataFormats/Common/interface/TriggerResults.h"
0005 #include "FWCore/Framework/interface/EventSelector.h"
0006 #include "FWCore/Framework/interface/TriggerNamesService.h"
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "FWCore/Utilities/interface/RegexMatch.h"
0009
0010 #include <iostream>
0011 #include <algorithm>
0012
0013 #include <boost/regex.hpp>
0014 #include <memory>
0015
0016 namespace dqmservices {
0017
0018
0019
0020 TriggerSelector::TriggerSelector(Strings const& pathspecs, Strings const& triggernames) : useOld_(true) {
0021 acceptAll_ = false;
0022 eventSelector_ = std::make_shared<edm::EventSelector>(pathspecs, triggernames);
0023 }
0024
0025 TriggerSelector::TriggerSelector(std::string const& expression, Strings const& triggernames) : useOld_(false) {
0026 init(trim(expression), triggernames);
0027 }
0028
0029 void TriggerSelector::init(std::string const& expression, Strings const& triggernames) {
0030
0031 if (expression.empty()) {
0032 acceptAll_ = true;
0033 return;
0034 }
0035 if (expression.size() == 1 && expression.at(0) == '*')
0036 acceptAll_ = true;
0037 else
0038 acceptAll_ = false;
0039
0040
0041 {
0042 using namespace boost;
0043 std::string temp;
0044 temp = regex_replace(expression, regex(".AND."), "&&");
0045 expression_ = regex_replace(temp, regex(".and."), "&&");
0046 temp = regex_replace(expression_, regex(".OR."), "||");
0047 expression_ = regex_replace(temp, regex(".or."), "||");
0048 }
0049
0050
0051 masterElement_ = std::make_shared<TreeElement>(expression_, triggernames);
0052 }
0053
0054 bool TriggerSelector::acceptEvent(edm::TriggerResults const& tr) const {
0055 if (useOld_) {
0056 return eventSelector_->acceptEvent(tr);
0057 }
0058
0059 if (acceptAll_)
0060 return true;
0061
0062 return masterElement_->returnStatus(tr);
0063 }
0064
0065 bool TriggerSelector::acceptEvent(unsigned char const* array_of_trigger_results, int number_of_trigger_paths) const {
0066 if (useOld_)
0067 return eventSelector_->acceptEvent(array_of_trigger_results, number_of_trigger_paths);
0068
0069 if (acceptAll_)
0070 return true;
0071
0072
0073 edm::HLTGlobalStatus tr(number_of_trigger_paths);
0074 int byteIndex = 0;
0075 int subIndex = 0;
0076 for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex) {
0077 int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
0078 state &= 0x3;
0079 edm::HLTPathStatus pathStatus(static_cast<edm::hlt::HLTState>(state));
0080 tr[pathIndex] = pathStatus;
0081 ++subIndex;
0082 if (subIndex == 4) {
0083 ++byteIndex;
0084 subIndex = 0;
0085 }
0086 }
0087
0088
0089 masterElement_->returnStatus(tr);
0090 return masterElement_->returnStatus(tr);
0091 }
0092
0093 TriggerSelector::TreeElement::TreeElement(std::string const& inputString,
0094 Strings const& tr,
0095 TreeElement* parentElement)
0096 : op_(NonInit), trigBit_(-1) {
0097 std::string str_ = trim(inputString);
0098 children_.clear();
0099 parent_ = parentElement;
0100
0101 size_t offset_ = 0;
0102 bool occurrences_ = false;
0103
0104 if (str_.empty())
0105 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (empty element)";
0106
0107 static const size_t bopsSize_ = 2;
0108 static const std::string binaryOperators_[bopsSize_] = {"||", "&&"};
0109
0110 for (size_t opr = 0; opr < bopsSize_; opr++) {
0111 bool exitloop_ = false;
0112 while (!exitloop_) {
0113 size_t t_end_;
0114
0115 std::string tmpStr = str_.substr(offset_);
0116 t_end_ = tmpStr.find(binaryOperators_[opr]);
0117 if (debug_)
0118 std::cout << "offset: " << offset_ << " length: " << t_end_ << " string: " << tmpStr << std::endl;
0119
0120 if (t_end_ == std::string::npos) {
0121
0122 if (occurrences_)
0123 children_.push_back(new TreeElement(tmpStr, tr, this));
0124 break;
0125 }
0126 t_end_ += offset_;
0127 if (t_end_ == 0 || t_end_ + 2 >= str_.size())
0128 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
0129 else {
0130
0131 size_t brackets_ = 0;
0132 for (size_t k = offset_; k < t_end_; k++) {
0133 if (str_.at(k) == '(') {
0134 brackets_++;
0135 } else if (str_.at(k) == ')') {
0136 if (brackets_ == 0) {
0137 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0138 } else {
0139 brackets_--;
0140 }
0141 }
0142 }
0143 if (brackets_ == 0) {
0144 std::string next = str_.substr(offset_, t_end_ - offset_);
0145 children_.push_back(new TreeElement(next, tr, this));
0146 occurrences_ = true;
0147 offset_ = t_end_ + 2;
0148 } else {
0149
0150 int bracketcnt_ = 0;
0151 for (size_t k = offset_; true; k++) {
0152 if (k >= str_.size()) {
0153 if (bracketcnt_ != 0)
0154 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0155 exitloop_ = true;
0156 if (occurrences_) {
0157 children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
0158 }
0159 break;
0160 }
0161
0162 if (k >= t_end_ + 2 && bracketcnt_ == 0) {
0163 std::string temp = str_.substr(k);
0164 size_t pos = temp.find(binaryOperators_[opr]);
0165 if (pos == std::string::npos) {
0166 exitloop_ = true;
0167 if (occurrences_) {
0168 children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
0169 }
0170 break;
0171 } else {
0172 int brcount_ = 0;
0173 for (size_t s = 0; s < pos; s++) {
0174
0175 if (temp.at(pos) == '(') {
0176 brcount_++;
0177 } else if (temp.at(pos) == ')') {
0178 if (brcount_ == 0) {
0179 throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
0180 } else {
0181 brcount_--;
0182 }
0183 }
0184 }
0185 if (brcount_ != 0)
0186 throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
0187
0188 children_.push_back(new TreeElement(str_.substr(offset_, pos + k), tr, this));
0189 offset_ = k + pos + 2;
0190 occurrences_ = true;
0191 if (offset_ >= str_.size())
0192 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
0193 break;
0194 }
0195 }
0196
0197 if (str_.at(k) == '(')
0198 bracketcnt_++;
0199 if (str_.at(k) == ')')
0200 bracketcnt_--;
0201 }
0202 }
0203 }
0204 }
0205 if (occurrences_) {
0206 if (opr == 0)
0207 op_ = OR;
0208 else
0209 op_ = AND;
0210 return;
0211 }
0212 }
0213
0214 if (str_.empty()) {
0215 op_ = AND;
0216 if (debug_)
0217 std::cout << "warning: empty element (will return true)" << std::endl;
0218 return;
0219 }
0220
0221 if (str_.at(0) == '!') {
0222 op_ = NOT;
0223 std::string next = str_.substr(1);
0224 children_.push_back(new TreeElement(next, tr, this));
0225 return;
0226 }
0227 size_t beginBlock_ = str_.find('(');
0228 size_t endBlock_ = str_.rfind(')');
0229 bool found_lbracket = (beginBlock_ != std::string::npos);
0230 bool found_rbracket = (endBlock_ != std::string::npos);
0231
0232 if (found_lbracket != found_rbracket) {
0233 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0234 } else if (found_lbracket && found_rbracket) {
0235 if (beginBlock_ >= endBlock_) {
0236 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
0237 }
0238 if (beginBlock_ != 0 || endBlock_ != str_.size() - 1)
0239 throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
0240
0241 std::string next = str_.substr(beginBlock_ + 1, endBlock_ - beginBlock_ - 1);
0242
0243 children_.push_back(new TreeElement(next, tr, this));
0244 op_ = BR;
0245 return;
0246 } else if (!found_lbracket && !found_rbracket)
0247 {
0248 bool ignore_if_missing = true;
0249 size_t chr_pos = str_.find('@');
0250 if (chr_pos != std::string::npos) {
0251 ignore_if_missing = false;
0252 str_ = str_.substr(0, chr_pos);
0253 }
0254
0255 std::vector<Strings::const_iterator> matches = edm::regexMatch(tr, str_);
0256 if (matches.empty()) {
0257 if (!ignore_if_missing)
0258 throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present";
0259 else {
0260 if (debug_)
0261 std::cout << "TriggerSelector: Couldn't match any triggers from: " << str_ << std::endl
0262 << " Node will not be added " << std::endl;
0263 op_ = OR;
0264 return;
0265 }
0266 }
0267 if (matches.size() == 1) {
0268
0269 trigBit_ = distance(tr.begin(), matches[0]);
0270 if (debug_)
0271 std::cout << "added trigger path: " << trigBit_ << std::endl;
0272 return;
0273 }
0274 if (matches.size() > 1) {
0275 op_ = OR;
0276 for (size_t l = 0; l < matches.size(); l++)
0277 children_.push_back(new TreeElement(*(matches[l]), tr, this));
0278 }
0279 }
0280 }
0281
0282 std::string TriggerSelector::trim(std::string input) {
0283 if (!input.empty()) {
0284 std::string::size_type pos = input.find_first_not_of(' ');
0285 if (pos != std::string::npos)
0286 input.erase(0, pos);
0287
0288 pos = input.find_last_not_of(' ');
0289 if (pos != std::string::npos)
0290 input.erase(pos + 1);
0291 }
0292 return input;
0293 }
0294
0295 std::string TriggerSelector::makeXMLString(std::string const& input) {
0296 std::string output;
0297 if (!input.empty()) {
0298 for (size_t pos = 0; pos < input.size(); pos++) {
0299 char ch = input.at(pos);
0300 if (ch == '&')
0301 output.append("&");
0302 else
0303 output.append(1, ch);
0304 }
0305 }
0306 return output;
0307 }
0308
0309 bool TriggerSelector::TreeElement::returnStatus(edm::HLTGlobalStatus const& trStatus) const {
0310 if (children_.empty()) {
0311 if (op_ == OR || op_ == NOT)
0312 return false;
0313 if (op_ == AND || op_ == BR)
0314 return true;
0315
0316 if (trigBit_ < 0 || (unsigned int)trigBit_ >= trStatus.size())
0317 throw edm::Exception(edm::errors::Configuration) << "Internal Error: array out of bounds.";
0318
0319 if ((trStatus[trigBit_]).state() == edm::hlt::Pass)
0320 return true;
0321
0322
0323 return false;
0324 }
0325 if (op_ == NOT) {
0326 return !children_[0]->returnStatus(trStatus);
0327 }
0328 if (op_ == BR) {
0329 return children_[0]->returnStatus(trStatus);
0330 }
0331 if (op_ == AND) {
0332 bool status = true;
0333 for (size_t i = 0; i < children_.size(); i++)
0334 status = status && children_[i]->returnStatus(trStatus);
0335 return status;
0336 } else if (op_ == OR) {
0337 bool status = false;
0338 for (size_t i = 0; i < children_.size(); i++)
0339 status = status || children_[i]->returnStatus(trStatus);
0340 return status;
0341 }
0342 throw edm::Exception(edm::errors::Configuration)
0343 << "Internal error: reached end of returnStatus(...), op:state = " << op_;
0344 return false;
0345 }
0346
0347 TriggerSelector::TreeElement::~TreeElement() {
0348 for (std::vector<TreeElement*>::iterator it = children_.begin(); it != children_.end(); it++)
0349 delete *it;
0350 children_.clear();
0351 }
0352 }