Back to home page

Project CMSSW displayed by LXR

 
 

    


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   // compatibility constructor
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       // old mode forced
0026       acceptAll_ = false;
0027       eventSelector_.reset(new edm::EventSelector(config, triggernames));
0028       return;
0029     }
0030     if (!config.empty()) {
0031       // let's see if non empty TriggerSelector is present
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       // now try with the SelectEvents
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     // if selection parameters aren't present, don't do selection
0054     // log
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     // debug_ = true;
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     // replace all possible alternate operators (.AND. and .OR.)
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     // build decision tree
0084     masterElement_.reset(new TreeElement(expression_, triggernames));
0085   }
0086 
0087   /*
0088       Obsolete
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     // Form HLTGlobalStatus object to represent the array_of_trigger_results
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     // Now make the decision, based on the HLTGlobalStatus tr,
0128     // which we have created from the supplied array of results
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           // right side element
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           // count bracket in preceeding part
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             // operator is inside brackets, find another
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               // look for another operator
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                     // counting check of brackets from last position to operator
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;  // a bracket
0285       return;
0286     } else if (!found_lbracket && !found_rbracket)  // assume single trigger or wildcard (parsing)
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)  // && !edm::is_glob(str_))
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         // Single Trigger match
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("&amp;");
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       // else if ((trStatus[trigBit]).state() == edm::hlt::Fail) return false;
0362 
0363       return false;
0364     }
0365     if (op_ == NOT) {  // NEGATION
0366       return !children_[0]->returnStatus(trStatus);
0367     }
0368     if (op_ == BR) {  // BRACKET
0369       return children_[0]->returnStatus(trStatus);
0370     }
0371     if (op_ == AND) {  // 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) {  // 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 }  // namespace dqmservices