CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/EventFilter/StorageManager/src/TriggerSelector.cc

Go to the documentation of this file.
00001 // $Id: TriggerSelector.cc,v 1.9 2011/03/07 15:31:32 mommsen Exp $
00003 
00004 #include "EventFilter/StorageManager/interface/TriggerSelector.h"
00005 
00006 #include "FWCore/Framework/interface/TriggerNamesService.h"
00007 #include "FWCore/Utilities/interface/RegexMatch.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 #include <iostream>
00011 #include <boost/regex.hpp>
00012 #include <algorithm>
00013 #include <cassert>
00014 
00015 namespace stor
00016 {
00017 
00018   //compatibility constructor
00019 
00020   TriggerSelector::TriggerSelector
00021   (
00022     Strings const& pathspecs,
00023     Strings const& names
00024   ):
00025   useOld_(true)
00026   {
00027     acceptAll_=false;
00028     eventSelector_.reset( new edm::EventSelector(pathspecs,names));
00029   }
00030 
00031   TriggerSelector::TriggerSelector
00032   (
00033     edm::ParameterSet const& config,
00034     Strings const& triggernames,
00035     bool old_
00036   ):
00037   useOld_(old_)
00038   {
00039     acceptAll_=false;
00040     if (old_) {
00041       //old mode forced
00042       eventSelector_.reset( new edm::EventSelector(config, triggernames));
00043       return;
00044     }
00045     if (!config.empty()) {
00046 
00047       //let's see if non empty TriggerSelector is present
00048       try {
00049         std::string myPath = trim(config.getParameter<std::string>("TriggerSelector"));
00050         if (!myPath.empty()) { 
00051           init(myPath, triggernames);
00052           return;
00053         }
00054       }
00055       catch(...) {}
00056 
00057       //now try with the SelectEvents 
00058       try {
00059         Strings paths;
00060         paths = config.getParameter<Strings>("SelectEvents");
00061         if (!paths.empty()) {
00062           useOld_=true;
00063           eventSelector_.reset( new edm::EventSelector(config, triggernames));
00064           return;
00065         }     
00066       }
00067       catch(...) {}
00068     }
00069     //if selection parameters aren't present, don't do selection
00070     //log
00071     acceptAll_=true;
00072   }
00073 
00074   TriggerSelector::TriggerSelector
00075   (
00076     std::string const & expression,
00077     Strings const& triggernames
00078   ):
00079   useOld_(false)
00080   {
00081     init (trim(expression),triggernames);
00082   }
00083 
00084   void
00085   TriggerSelector::init
00086   (
00087     std::string const& expression,
00088     Strings const& triggernames
00089   )
00090   {
00091     //debug_ = true;
00092     if (expression.empty())
00093     {
00094       acceptAll_ = true;
00095       return;
00096     }
00097     if (expression.size()==1 && expression.at(0)=='*') acceptAll_=true;
00098     else acceptAll_=false;
00099 
00100     //replace all possible alternate operators (.AND. and .OR.)
00101     {
00102       using namespace boost;
00103       std::string temp;
00104       temp = regex_replace( expression , regex(".AND."), "&&");
00105       expression_ = regex_replace( temp, regex(".and."), "&&");
00106       temp = regex_replace( expression_, regex(".OR."), "||"); 
00107       expression_ = regex_replace( temp, regex(".or."), "||");
00108     }
00109 
00110     //build decision tree
00111     masterElement_.reset( new TreeElement(expression_,triggernames));
00112   }
00113 
00114   /*
00115         Obsolete
00116   */
00117   std::vector<std::string>
00118   TriggerSelector::getEventSelectionVString(edm::ParameterSet const& pset)
00119   {
00120     return edm::EventSelector::getEventSelectionVString(pset);
00121   }
00122 
00123   bool TriggerSelector::acceptEvent(edm::TriggerResults const& tr) const
00124   {
00125     if (useOld_) {
00126       return eventSelector_->acceptEvent(tr);
00127     }
00128 
00129     if (acceptAll_) return true;
00130     
00131     return masterElement_->returnStatus(tr);
00132   }
00133 
00134   bool 
00135   TriggerSelector::acceptEvent
00136   (
00137     unsigned char const* array_of_trigger_results,
00138     int number_of_trigger_paths
00139   ) const
00140   {
00141 
00142     if (useOld_)
00143       return eventSelector_->acceptEvent(array_of_trigger_results,number_of_trigger_paths);
00144 
00145     if (acceptAll_) return true;
00146 
00147     // Form HLTGlobalStatus object to represent the array_of_trigger_results
00148     edm::HLTGlobalStatus tr(number_of_trigger_paths);
00149     int byteIndex = 0;
00150     int subIndex  = 0;
00151     for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex)
00152     {
00153       int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
00154       state &= 0x3;
00155       edm::HLTPathStatus pathStatus(static_cast<edm::hlt::HLTState>(state));
00156       tr[pathIndex] = pathStatus;
00157       ++subIndex;
00158       if (subIndex == 4)
00159       { ++byteIndex;
00160         subIndex = 0;
00161       }
00162     }
00163     // Now make the decision, based on the HLTGlobalStatus tr,
00164     // which we have created from the supplied array of results
00165     return masterElement_->returnStatus(tr);
00166   }
00167 
00168 
00169   TriggerSelector::TreeElement::TreeElement
00170   (
00171     std::string const& inputString,
00172     Strings const& tr,
00173     TreeElement* parentElement
00174   ) :
00175     op_(NonInit),
00176     trigBit_(-1)
00177   {
00178     std::string str_ = trim(inputString);
00179     children_.clear();
00180     parent_ = parentElement;
00181 
00182     size_t offset_=0;
00183     bool occurrences_=false;
00184 
00185     if (str_.empty())
00186       throw edm::Exception(edm::errors::Configuration)
00187         << "Syntax Error (empty element)" << std::endl;
00188 
00189     static const size_t bopsSize_ = 2;
00190     static const std::string binaryOperators_[bopsSize_] = {"||","&&"};
00191 
00192     for (size_t opr=0;opr<bopsSize_;opr++) {
00193       bool exitloop_=false;
00194       while(!exitloop_) {
00195         size_t t_end_;
00196 
00197         std::string tmpStr = str_.substr(offset_);
00198         t_end_ = tmpStr.find(binaryOperators_[opr]);
00199         if (debug_) std::cout << "offset: " << offset_ << " length: " << t_end_ <<" string: " << tmpStr << std::endl;
00200 
00201         if (t_end_ == std::string::npos) {
00202           //right side element
00203           if (occurrences_) children_.push_back(new TreeElement(tmpStr,tr,this));
00204           break;
00205         }
00206         t_end_ += offset_;
00207         if (t_end_==0 || t_end_+2>=str_.size()) 
00208           throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
00209         else {
00210           //count bracket in preceeding part
00211           int brackets_=0;
00212           for (size_t k=offset_;k<t_end_;k++) {
00213             if (str_.at(k)=='(') brackets_++;
00214             if (str_.at(k)==')') brackets_--;
00215             if (brackets_<0)
00216               throw edm::Exception(edm::errors::Configuration)
00217                 << "Syntax Error (brackets)\n";
00218           }
00219           if (brackets_==0) {
00220             std::string next = str_.substr(offset_,t_end_-offset_);
00221             children_.push_back(new TreeElement(next,tr,this));
00222             occurrences_=true;
00223             offset_ = t_end_+2;
00224           }
00225           else {
00226             //operator is inside brackets, find another
00227             int bracketcnt_ = 0;
00228             for (size_t k=offset_;true;k++) {
00229               if (k>=str_.size()) {
00230                 if (bracketcnt_!=0)
00231                   throw edm::Exception(edm::errors::Configuration)
00232                     << "Syntax Error (brackets)\n";
00233                 exitloop_=true;
00234                 if (occurrences_) {
00235                   children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00236                 }
00237                 break;
00238               }
00239               //look for another operator
00240               if (k>=t_end_+2 && bracketcnt_==0) {
00241                 std::string temp = str_.substr(k);
00242                 size_t pos = temp.find(binaryOperators_[opr]);
00243                 if (pos == std::string::npos) {
00244                   exitloop_=true;
00245                   if (occurrences_) {
00246                     children_.push_back(new TreeElement(str_.substr(offset_),tr,this));
00247                   }
00248                   break;
00249                 }
00250                 else {
00251                   int brcount_ = 0;
00252                   for (size_t s=0;s<pos;s++) {
00253                     //counting check of brackets from last position to operator
00254                     if (temp.at(pos)=='(') brcount_++;
00255                     if (temp.at(pos)==')') brcount_--;
00256                     if (brcount_<0)
00257                       throw edm::Exception(edm::errors::Configuration)
00258                         << "Syntax error (brackets)\n";
00259                   }
00260                   if (brcount_!=0) 
00261                     throw edm::Exception(edm::errors::Configuration)
00262                       << "Syntax error (brackets)\n";
00263 
00264                   children_.push_back(new TreeElement(str_.substr(offset_,pos+k),tr,this));
00265                   offset_=k+pos+2;
00266                   occurrences_=true;
00267                   if (offset_>=str_.size())
00268                     throw edm::Exception(edm::errors::Configuration) 
00269                       << "Syntax Error (operator is not unary)\n";
00270                   break;
00271                 }
00272 
00273               }
00274 
00275 
00276               if (str_.at(k)=='(') bracketcnt_++;
00277               if (str_.at(k)==')') bracketcnt_--;
00278 
00279             }
00280           }
00281         }
00282 
00283       }
00284       if (occurrences_) {
00285         if (opr==0) op_=OR;
00286         else        op_=AND;
00287         return;
00288       }
00289     }
00290 
00291     if (str_.empty()) {
00292       op_=AND;
00293       if (debug_) std::cout << "warning: empty element (will return true)"<< std::endl;
00294       return;
00295     }
00296 
00297     if (str_.at(0)=='!') {
00298       op_=NOT;
00299       std::string next = str_.substr(1);
00300       children_.push_back(new TreeElement(next,tr,this));
00301       return;
00302     }
00303     size_t beginBlock_ =str_.find('(');
00304     size_t endBlock_ =str_.rfind(')');
00305     bool found_lbracket = (beginBlock_ != std::string::npos);
00306     bool found_rbracket = (endBlock_ != std::string::npos);
00307 
00308     if (found_lbracket != found_rbracket) {
00309       throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00310     }
00311     else if (found_lbracket && found_rbracket)
00312     {
00313       if (beginBlock_>=endBlock_) {
00314         throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
00315       }
00316       if (beginBlock_!=0 || endBlock_!=str_.size()-1)
00317         throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
00318 
00319       std::string next = str_.substr(beginBlock_+1,endBlock_-beginBlock_-1);
00320 
00321       children_.push_back(new TreeElement(next,tr,this));
00322       op_=BR; //a bracket
00323       return;
00324     }
00325     else if (!found_lbracket && !found_rbracket) //assume single trigger or wildcard (parsing)
00326     {
00327       bool ignore_if_missing = true;
00328       size_t chr_pos = str_.find("@");
00329       if (chr_pos!= std::string::npos) {
00330         ignore_if_missing=false;
00331         str_=str_.substr(0,chr_pos);
00332       }
00333 
00334       std::vector<Strings::const_iterator> matches = edm::regexMatch(tr,str_);
00335       if (matches.empty()) {
00336         if (!ignore_if_missing)// && !edm::is_glob(str_)) 
00337           throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present" << std::endl;
00338         else { 
00339           if (debug_)
00340             std::cout << "TriggerSelector: Couldn't match any triggers from: "<< str_<< std::endl
00341               << "                 Node will not be added "<< std::endl;
00342           op_=OR;
00343           return;
00344         }
00345       }
00346       if (matches.size()==1) {
00347         //Single Trigger match
00348         trigBit_ = distance(tr.begin(),matches[0]);
00349         if (debug_) std::cout << "added trigger path: " << trigBit_ << std::endl;
00350         return;
00351       }
00352       if (matches.size()>1) {
00353         op_=OR;
00354         for (size_t l=0;l<matches.size();l++)
00355           children_.push_back(new TreeElement(*(matches[l]),tr,this));
00356       }
00357     }
00358   }
00359 
00360   std::string TriggerSelector::trim(std::string input) 
00361   {
00362     if (!input.empty())
00363     {
00364       std::string::size_type pos = input.find_first_not_of(" ");
00365       if (pos != std::string::npos)
00366         input.erase(0,pos);
00367 
00368       pos = input.find_last_not_of(" ");
00369       if (pos != std::string::npos)
00370         input.erase(pos+1);
00371     }
00372     return input;
00373   } 
00374 
00375   std::string TriggerSelector::makeXMLString(std::string const& input)
00376   {
00377     std::string output;
00378     if (!input.empty()) {
00379       for (size_t pos=0;pos<input.size();pos++) {
00380         char ch = input.at(pos);
00381         if (ch=='&') output.append("&amp;");
00382         else output.append(1,ch);
00383       }
00384     }
00385     return output;
00386   }
00387 
00388 
00389   bool TriggerSelector::TreeElement::returnStatus
00390   (
00391     edm::HLTGlobalStatus const& trStatus
00392   ) const 
00393   {
00394 
00395     if (children_.empty()) {
00396 
00397       if (op_==OR  || op_==NOT) return false;
00398       if (op_==AND || op_==BR) return true;
00399 
00400       if (trigBit_<0 || (unsigned int)trigBit_>=trStatus.size())
00401         throw edm::Exception(edm::errors::Configuration)
00402           << "Internal Error: array out of bounds " << std::endl;
00403 
00404       if ((trStatus[trigBit_]).state() == edm::hlt::Pass) return true;
00405       //else if ((trStatus[trigBit]).state() == edm::hlt::Fail) return false;
00406 
00407       return false;
00408     }
00409     if (op_==NOT) { //NEGATION
00410       return !children_[0]->returnStatus(trStatus);
00411     }
00412     if (op_==BR) { //BRACKET
00413       return children_[0]->returnStatus(trStatus);
00414     } 
00415     if (op_==AND) { //AND
00416       bool status = true;
00417       for (size_t i=0;i<children_.size();i++) status = status && children_[i]->returnStatus(trStatus);
00418       return status;
00419     }
00420     else if (op_==OR) { //OR
00421       bool status = false;
00422       for (size_t i=0;i<children_.size();i++) status = status || children_[i]->returnStatus(trStatus);
00423       return status;
00424     }
00425     throw edm::Exception(edm::errors::Configuration) << "Internal error: reached end of returnStatus(...)  op:state= " << op_ << std::endl;
00426     return false;
00427   }
00428 
00429 
00430   TriggerSelector::TreeElement::~TreeElement()
00431   {
00432     for (std::vector<TreeElement*>::iterator it=children_.begin();it!=children_.end();it++)
00433       delete *it;
00434     children_.clear();
00435   }
00436 
00437 } // namespace stor
00438 
00439