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