CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/Framework/src/EventSelector.cc

Go to the documentation of this file.
00001 // Change Log
00002 //
00003 // 1 - M Fischler 2/8/08 Enable partial wildcards, as in HLT* or !CAL*
00004 //                       A version of this code with cerr debugging traces has
00005 //                       been placed in the doc area.  
00006 //                       See ../doc/EventSelector-behavior.doc for details of
00007 //                       reactions to Ready or Exception states.
00008 // 1a M Fischler 2/13/08 Clear the all_must_fail_ array at the start of init.
00009 //                       This is needed in the case of paths with wildcards,
00010 //                       on explicit processes other than a current process
00011 //                       (in which case init() is called whenever the trigger
00012 //                       PSetID changes, and we don't want the old array
00013 //                       contents to stick around.
00014 //
00015 // 2 - M Fischler 2/21/08 (In preparation for "exception-awareness" features):
00016 //                       Factored out the decision making logic from the 
00017 //                       two forms of acceptEvent, into the single routine
00018 //                       selectionDecision().
00019 //
00020 // 3 - M Fischler 2/25/08 (Toward commit of "exception-awareness" features):
00021 //                       @exception and noexception& features 
00022 //
00023 // 4- M Fischler 2/28/08 Repair ommision in selectionIsValid when pathspecs
00024 //                      is just "!*"
00025 //
00026 // 5- M Fischler 3/3/08 testSelectionOverlap and maskTriggerResults appropriate
00027 //                      for the new forms of pathspecs
00028 //
00029 // 6 - K Biery 03/24/08 modified maskTriggerResults (no longer static) to
00030 //                      avoid performance penalty of creating a new
00031 //                      EventSelector instance for each call (in static case)
00032 //
00033 
00034 
00035 #include "FWCore/Framework/interface/EventSelector.h"
00036 #include "FWCore/ServiceRegistry/interface/Service.h"
00037 #include "FWCore/Framework/interface/TriggerNamesService.h"
00038 #include "FWCore/Utilities/interface/RegexMatch.h"
00039 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00040 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00041 
00042 #include "boost/algorithm/string.hpp"
00043 
00044 #include <algorithm>
00045 #include <cassert>
00046 
00047 namespace edm
00048 {
00049   EventSelector::EventSelector(Strings const& pathspecs,
00050                                Strings const& names):
00051     accept_all_(false),
00052     absolute_acceptors_(),
00053     conditional_acceptors_(),
00054     exception_acceptors_(),
00055     all_must_fail_(),
00056     all_must_fail_noex_(),
00057     results_from_current_process_(true),
00058     psetID_initialized_(false),
00059     psetID_(),
00060     paths_(),
00061     nTriggerNames_(0),
00062     notStarPresent_(false)
00063   {
00064     init(pathspecs, names);
00065   }
00066 
00067   EventSelector::EventSelector(Strings const& pathspecs):
00068     accept_all_(false),
00069     absolute_acceptors_(),
00070     conditional_acceptors_(),
00071     exception_acceptors_(),
00072     all_must_fail_(),
00073     all_must_fail_noex_(),
00074     results_from_current_process_(false),
00075     psetID_initialized_(false),
00076     psetID_(),
00077     paths_(pathspecs),
00078     nTriggerNames_(0),
00079     notStarPresent_(false)
00080   {
00081   }
00082 
00083   EventSelector::EventSelector(ParameterSet const& config,
00084                                Strings const& triggernames):
00085     accept_all_(false),
00086     absolute_acceptors_(),
00087     conditional_acceptors_(),
00088     exception_acceptors_(),
00089     all_must_fail_(),
00090     all_must_fail_noex_(),
00091     results_from_current_process_(true),
00092     psetID_initialized_(false),
00093     psetID_(),
00094     paths_(),
00095     nTriggerNames_(0),
00096     notStarPresent_(false)
00097   {
00098     Strings paths; // default is empty...
00099 
00100     if (!config.empty())
00101       paths = config.getParameter<Strings>("SelectEvents");
00102 
00103     init(paths, triggernames);
00104   }
00105 
00106   void
00107   EventSelector::init(Strings const& paths,
00108                       Strings const& triggernames)
00109   {
00110     // std::cerr << "### init entered\n";
00111     accept_all_ = false;
00112     absolute_acceptors_.clear(),
00113     conditional_acceptors_.clear(),
00114     exception_acceptors_.clear(),
00115     all_must_fail_.clear();
00116     all_must_fail_noex_.clear();
00117     nTriggerNames_ = triggernames.size();
00118     notStarPresent_ = false;
00119 
00120     if (paths.empty())
00121       {
00122         accept_all_ = true;
00123         return;
00124       }
00125 
00126     // The following are for the purpose of establishing accept_all_ by 
00127     // virtue of an inclusive set of paths:
00128     bool unrestricted_star = false;
00129     bool negated_star      = false;
00130     bool exception_star    = false;
00131     
00132     for (Strings::const_iterator i(paths.begin()), end(paths.end()); 
00133          i!=end; ++i)
00134     {
00135       std::string pathSpecifier(*i);
00136       boost::erase_all(pathSpecifier, " \t"); // whitespace eliminated
00137       if (pathSpecifier == "*")           unrestricted_star = true;
00138       if (pathSpecifier == "!*")          negated_star = true;
00139       if (pathSpecifier == "exception@*") exception_star = true;
00140 
00141       std::string basePathSpec(pathSpecifier);
00142       bool noex_demanded = false;
00143       std::string::size_type 
00144               and_noexception = pathSpecifier.find("&noexception");
00145       if (and_noexception != std::string::npos) {
00146         basePathSpec = pathSpecifier.substr(0,and_noexception);
00147         noex_demanded = true;
00148       }
00149       std::string::size_type and_noex = pathSpecifier.find("&noex");
00150       if (and_noex != std::string::npos) {
00151         basePathSpec = pathSpecifier.substr(0,and_noexception);
00152         noex_demanded = true;
00153       }
00154       and_noexception = basePathSpec.find("&noexception");
00155       and_noex = basePathSpec.find("&noex");    
00156       if (and_noexception != std::string::npos ||
00157            and_noex != std::string::npos)
00158           throw edm::Exception(errors::Configuration)
00159             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00160                "to request a trigger name, but specifying &noexceptions twice\n"
00161             << "The improper trigger name is: " << pathSpecifier << "\n";  
00162 
00163       std::string realname(basePathSpec);
00164       bool negative_criterion = false;
00165       if (basePathSpec[0] == '!') {
00166         negative_criterion = true;
00167         realname = basePathSpec.substr(1,std::string::npos);
00168       }
00169       bool exception_spec = false;
00170       if (realname.find("exception@") == 0) {
00171         exception_spec = true;  
00172         realname = realname.substr(10, std::string::npos); 
00173         // strip off 10 chars, which is length of "exception@" 
00174       } 
00175       if (negative_criterion &&  exception_spec)
00176           throw edm::Exception(errors::Configuration)
00177             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00178                "to request a trigger name starting with !exception@.\n"
00179                "This is not supported.\n"
00180             << "The improper trigger name is: " << pathSpecifier << "\n";  
00181       if (noex_demanded &&  exception_spec)
00182           throw edm::Exception(errors::Configuration)
00183             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00184                "to request a trigger name starting with exception@ "
00185                "and also demanding no &exceptions.\n"
00186             << "The improper trigger name is: " << pathSpecifier << "\n";  
00187 
00188 
00189       // instead of "see if the name can be found in the full list of paths"
00190       // we want to find all paths that match this name.        
00191       std::vector<Strings::const_iterator> matches =
00192               regexMatch(triggernames, realname);
00193 
00194       if (matches.empty() && !is_glob(realname)) 
00195       {
00196           throw edm::Exception(errors::Configuration)
00197             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00198                "to request a trigger name that does not exist\n"
00199             << "The unknown trigger name is: " << realname << "\n";  
00200       }
00201       if (matches.empty() && is_glob(realname)) 
00202       {
00203           LogWarning("Configuration")
00204             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00205                "to request a wildcarded trigger name that does not match any trigger \n"
00206             << "The wildcarded trigger name is: " << realname << "\n";  
00207       }
00208 
00209       if (!negative_criterion && !noex_demanded && !exception_spec) {
00210         for (unsigned int t = 0; t != matches.size(); ++t) {
00211           BitInfo bi(distance(triggernames.begin(),matches[t]), true);
00212           absolute_acceptors_.push_back(bi);
00213         }
00214       } else if (!negative_criterion && noex_demanded) {
00215         for (unsigned int t = 0; t != matches.size(); ++t) {
00216           BitInfo bi(distance(triggernames.begin(),matches[t]), true);
00217           conditional_acceptors_.push_back(bi);
00218         }
00219       } else if (exception_spec) {
00220         for (unsigned int t = 0; t != matches.size(); ++t) {
00221           BitInfo bi(distance(triggernames.begin(),matches[t]), true);
00222           exception_acceptors_.push_back(bi);
00223         }
00224       } else if (negative_criterion && !noex_demanded) {
00225         if (matches.empty()) {
00226             throw edm::Exception(errors::Configuration)
00227             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00228                "to request all fails on a set of trigger names that do not exist\n"
00229             << "The problematic name is: " << pathSpecifier << "\n";  
00230 
00231         } else if (matches.size() == 1) {
00232           BitInfo bi(distance(triggernames.begin(),matches[0]), false);
00233           absolute_acceptors_.push_back(bi);
00234         } else {
00235           Bits mustfail;
00236           for (unsigned int t = 0; t != matches.size(); ++t) {
00237             BitInfo bi(distance(triggernames.begin(),matches[t]), false);
00238             // We set this to false because that will demand bits are Fail. 
00239             mustfail.push_back(bi);
00240           }
00241           all_must_fail_.push_back(mustfail);
00242         }       
00243       } else if (negative_criterion && noex_demanded) {
00244         if (matches.empty()) {
00245             throw edm::Exception(errors::Configuration)
00246             << "EventSelector::init, An OutputModule is using SelectEvents\n"
00247                "to request all fails on a set of trigger names that do not exist\n"
00248             << "The problematic name is: " << pathSpecifier << "\n";  
00249 
00250         } else if (matches.size() == 1) {
00251           BitInfo bi(distance(triggernames.begin(),matches[0]), false);
00252           conditional_acceptors_.push_back(bi);
00253         } else {
00254           Bits mustfail;
00255           for (unsigned int t = 0; t != matches.size(); ++t) {
00256             BitInfo bi(distance(triggernames.begin(),matches[t]), false);
00257             mustfail.push_back(bi);
00258           }
00259           all_must_fail_noex_.push_back(mustfail);
00260         }
00261       } 
00262     } // end of the for loop on i(paths.begin()), end(paths.end())
00263 
00264     if (unrestricted_star && negated_star && exception_star) accept_all_ = true;
00265 
00266     // std::cerr << "### init exited\n";
00267 
00268   } // EventSelector::init
00269   
00270   bool EventSelector::acceptEvent(TriggerResults const& tr)
00271   {
00272     if (accept_all_) return true;
00273     
00274     // For the current process we already initialized in the constructor,
00275     // The trigger names will not change so we can skip initialization.
00276     if (!results_from_current_process_) {
00277   
00278       // For previous processes we need to get the trigger names that
00279       // correspond to the bits in TriggerResults from the ParameterSet
00280       // set registry, which is stored once per file.  The ParameterSetID
00281       // stored in TriggerResults is the key used to find the info in the
00282       // registry.  We optimize using the fact the ID is unique. If the ID
00283       // has not changed since the last time we initialized with new triggernames,
00284       // then the names have not changed and we can skip this initialization.
00285       if (!(psetID_initialized_ && psetID_ == tr.parameterSetID())) {
00286 
00287         Strings triggernames;
00288         bool fromPSetRegistry;
00289 
00290         Service<service::TriggerNamesService> tns;
00291         if (tns->getTrigPaths(tr, triggernames, fromPSetRegistry)) {
00292 
00293           init(paths_, triggernames);
00294 
00295           if (fromPSetRegistry) {
00296             psetID_ = tr.parameterSetID();
00297             psetID_initialized_ = true;
00298           }
00299           else {
00300             psetID_initialized_ = false;
00301           }
00302         }
00303         // This should never happen
00304         else {
00305           throw edm::Exception(errors::Unknown)
00306             << "EventSelector::acceptEvent cannot find the trigger names for\n"
00307                "a process for which the configuration has requested that the\n"
00308                "OutputModule use TriggerResults to select events from.  This should\n"
00309                "be impossible, please send information to reproduce this problem to\n"
00310                "the edm developers.\n"; 
00311         }
00312       }
00313     }
00314 
00315     // Now make the decision, based on the supplied TriggerResults tr,
00316     // which of course can be treated as an HLTGlobalStatus by inheritance
00317     
00318     return selectionDecision(tr);
00319     
00320   } // acceptEvent(TriggerResults const& tr)
00321 
00322   bool 
00323   EventSelector::acceptEvent(unsigned char const* array_of_trigger_results, 
00324                              int number_of_trigger_paths) const
00325   {
00326 
00327     // This should never occur unless someone uses this function in
00328     // an incorrect way ...
00329     if (!results_from_current_process_) {
00330       throw edm::Exception(errors::Configuration)
00331         << "\nEventSelector.cc::acceptEvent, you are attempting to\n"
00332         << "use a bit array for trigger results instead of the\n"
00333         << "TriggerResults object for a previous process.  This\n"
00334         << "will not work and ought to be impossible\n";
00335     }
00336 
00337     if (accept_all_) return true;
00338 
00339     // Form HLTGlobalStatus object to represent the array_of_trigger_results
00340     HLTGlobalStatus tr(number_of_trigger_paths);
00341     int byteIndex = 0;
00342     int subIndex  = 0;
00343     for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex)
00344     {
00345       int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
00346       state &= 0x3;
00347       HLTPathStatus pathStatus(static_cast<hlt::HLTState>(state));
00348       tr[pathIndex] = pathStatus;
00349       ++subIndex;
00350       if (subIndex == 4)
00351       { ++byteIndex;
00352         subIndex = 0;
00353       }
00354     }    
00355 
00356     // Now make the decision, based on the HLTGlobalStatus tr,
00357     // which we have created from the supplied array of results
00358     
00359     return selectionDecision(tr);
00360 
00361   } // acceptEvent(array_of_trigger_results, number_of_trigger_paths)
00362 
00363   bool 
00364   EventSelector::selectionDecision(HLTGlobalStatus const& tr) const
00365   {
00366     if (accept_all_) return true;
00367 
00368     bool exceptionPresent = false;
00369     bool exceptionsLookedFor = false;
00370     
00371     if (acceptOneBit(absolute_acceptors_, tr)) return true;
00372     if (acceptOneBit(conditional_acceptors_, tr)) {
00373       exceptionPresent = containsExceptions(tr);
00374       if (!exceptionPresent) return true;
00375       exceptionsLookedFor = true;
00376     }
00377     if (acceptOneBit(exception_acceptors_, tr, hlt::Exception)) return true;
00378 
00379     for (std::vector<Bits>::const_iterator f =  all_must_fail_.begin();
00380                                            f != all_must_fail_.end(); ++f)
00381     {
00382       if (acceptAllBits(*f, tr)) return true;
00383     }
00384     for (std::vector<Bits>::const_iterator fn =  all_must_fail_noex_.begin();
00385                                            fn != all_must_fail_noex_.end(); ++fn)
00386     {
00387       if (acceptAllBits(*fn, tr)) {
00388         if (!exceptionsLookedFor) exceptionPresent = containsExceptions(tr);
00389         return (!exceptionPresent);
00390       }
00391     }
00392     
00393     // If we have not accepted based on any of the acceptors, nor on any one of
00394     // the all_must_fail_ collections, then we reject this event.
00395     
00396     return false;
00397   
00398   }  // selectionDecision()
00399 
00400 // Obsolete...
00401   bool EventSelector::acceptTriggerPath(HLTPathStatus const& pathStatus,
00402                                         BitInfo const& pathInfo) const
00403   {
00404     return (((pathStatus.state()==hlt::Pass) && (pathInfo.accept_state_)) ||
00405             ((pathStatus.state()==hlt::Fail) && !(pathInfo.accept_state_)) ||
00406             ((pathStatus.state()==hlt::Exception)));
00407   }
00408 
00409   // Indicate if any bit in the trigger results matches the desired value
00410   // at that position, based on the Bits array.  If s is Exception, this
00411   // looks for a Exceptionmatch; otherwise, true-->Pass, false-->Fail.
00412   bool 
00413   EventSelector::acceptOneBit(Bits const& b, 
00414                                HLTGlobalStatus const& tr, 
00415                                hlt::HLTState const& s) const
00416   {
00417     bool lookForException = (s == hlt::Exception);
00418     Bits::const_iterator i(b.begin());
00419     Bits::const_iterator e(b.end());
00420     for(;i!=e;++i) {
00421       hlt::HLTState bstate = 
00422           lookForException ? hlt::Exception
00423                            : i->accept_state_ ? hlt::Pass
00424                                               : hlt::Fail;
00425       if (tr[i->pos_].state() == bstate) return true;
00426     }
00427     return false;    
00428   } // acceptOneBit                            
00429 
00430   // Indicate if *every* bit in the trigger results matches the desired value
00431   // at that position, based on the Bits array: true-->Pass, false-->Fail.
00432   bool 
00433   EventSelector::acceptAllBits(Bits const& b, 
00434                                 HLTGlobalStatus const& tr) const
00435   {
00436     Bits::const_iterator i(b.begin());
00437     Bits::const_iterator e(b.end());
00438     for(;i!=e;++i) {
00439       hlt::HLTState bstate = i->accept_state_ ? hlt::Pass : hlt::Fail;
00440       if (tr[i->pos_].state() != bstate) return false;
00441     }
00442     return true;    
00443   } // acceptAllBits                           
00444 
00460   bool EventSelector::selectionIsValid(Strings const& pathspec,
00461                                        Strings const& fullTriggerList)
00462   {
00463     // an empty selection list is not valid
00464     // (we default an empty "SelectEvents" parameter to {"*","!*"} in
00465     // the getEventSelectionVString method below to help avoid this)
00466     if (pathspec.size() == 0)
00467     {
00468       return false;
00469     }
00470 
00471     // loop over each element in the selection list
00472     for (unsigned int idx = 0; idx < pathspec.size(); idx++)
00473     {
00474       Strings workingList;
00475       workingList.push_back(pathspec[idx]);
00476 
00477       // catch exceptions from the EventSelector constructor
00478       // (and anywhere else) and mark those as failures.
00479       // The EventSelector constructor seems to do the work of
00480       // checking if the selection is outside the full trigger list.
00481       try
00482       {
00483         // create an EventSelector instance for this selection
00484         EventSelector evtSelector(workingList, fullTriggerList);
00485 
00486         // create the TriggerResults instance that we'll use for testing
00487         unsigned int fullTriggerCount = fullTriggerList.size();
00488         HLTGlobalStatus hltGS(fullTriggerCount);
00489         TriggerResults sampleResults(hltGS, fullTriggerList);
00490 
00491         // loop over each path
00492         bool oneResultMatched = false;
00493         for (unsigned int iPath = 0; iPath < fullTriggerCount; iPath++)
00494         {
00495           // loop over the possible values for the path status
00496           for (int iState = static_cast<int>(hlt::Pass);
00497                iState <= static_cast<int>(hlt::Exception);
00498                iState++)
00499           {
00500             sampleResults[iPath] = HLTPathStatus(static_cast<hlt::HLTState>(iState), 0);
00501             if (evtSelector.wantAll() || evtSelector.acceptEvent(sampleResults))
00502             {
00503               oneResultMatched = true;
00504               break;
00505             }
00506 
00507             sampleResults.reset(iPath);
00508           }
00509 
00510           if (oneResultMatched) break;
00511         }
00512 
00513         // Finally, check in case the selection element was a wildcarded 
00514         // negative such as "!*":
00515         
00516         if (!oneResultMatched)  {
00517           for (unsigned int iPath = 0; iPath < fullTriggerCount; iPath++) {
00518             sampleResults[iPath] = HLTPathStatus(hlt::Fail, 0);
00519           }
00520           if (evtSelector.acceptEvent(sampleResults)) {
00521               oneResultMatched = true;
00522           }
00523         }
00524         
00525         // if none of the possible trigger results matched the
00526         // selection element, then we declare the whole selection
00527         // list invalid
00528         if (!oneResultMatched)
00529         {
00530           return false;
00531         }
00532       }
00533       catch (edm::Exception const& excpt)
00534       {
00535         return false;
00536       }
00537     }
00538 
00539     // if we made it to this point, then it must have been possible
00540     // to satisfy every selection element one way or another
00541     return true;
00542   }
00543 
00544 
00555   evtSel::OverlapResult
00556   EventSelector::testSelectionOverlap(Strings const& pathspec1,
00557                                       Strings const& pathspec2,
00558                                       Strings const& fullTriggerList)
00559   {
00560     bool overlap = false;
00561     
00562     // first, test that the selection lists are valid
00563     if (!selectionIsValid(pathspec1, fullTriggerList) ||
00564         !selectionIsValid(pathspec2, fullTriggerList))
00565     {
00566       return evtSel::InvalidSelection;
00567     }
00568  
00569     // catch exceptions from the EventSelector constructor
00570     // (and anywhere else) and mark those as failures
00571     try
00572     {
00573       // create an EventSelector instance for each selection list
00574       EventSelector a(pathspec1, fullTriggerList);
00575       EventSelector b(pathspec2, fullTriggerList);
00576 
00577       unsigned int N = fullTriggerList.size();
00578 
00579       // create the expanded masks for the various decision lists in a and b
00580       std::vector<bool> 
00581         aPassAbs = expandDecisionList(a.absolute_acceptors_,true,N);
00582       std::vector<bool> 
00583         aPassCon = expandDecisionList(a.conditional_acceptors_,true,N);
00584       std::vector<bool> 
00585         aFailAbs = expandDecisionList(a.absolute_acceptors_,false,N);
00586       std::vector<bool> 
00587         aFailCon = expandDecisionList(a.conditional_acceptors_,false,N);
00588       std::vector<bool> 
00589         aExc = expandDecisionList(a.exception_acceptors_,true,N);
00590       std::vector< std::vector<bool> > aMustFail;
00591       for (unsigned int m = 0; m != a.all_must_fail_.size(); ++m) {
00592         aMustFail.push_back(expandDecisionList(a.all_must_fail_[m],false,N));
00593       }
00594       std::vector< std::vector<bool> > aMustFailNoex;
00595       for (unsigned int m = 0; m != a.all_must_fail_noex_.size(); ++m) {
00596         aMustFailNoex.push_back 
00597                 (expandDecisionList(a.all_must_fail_noex_[m],false,N));
00598       }
00599 
00600       std::vector<bool> 
00601         bPassAbs = expandDecisionList(b.absolute_acceptors_,true,N);
00602       std::vector<bool> 
00603         bPassCon = expandDecisionList(b.conditional_acceptors_,true,N);
00604       std::vector<bool> 
00605         bFailAbs = expandDecisionList(b.absolute_acceptors_,false,N);
00606       std::vector<bool> 
00607         bFailCon = expandDecisionList(b.conditional_acceptors_,false,N);
00608       std::vector<bool> 
00609         bExc = expandDecisionList(b.exception_acceptors_,true,N);
00610       std::vector< std::vector<bool> > bMustFail;
00611       for (unsigned int m = 0; m != b.all_must_fail_.size(); ++m) {
00612         bMustFail.push_back(expandDecisionList(b.all_must_fail_[m],false,N));
00613       }
00614       std::vector< std::vector<bool> > bMustFailNoex;
00615       for (unsigned int m = 0; m != b.all_must_fail_noex_.size(); ++m) {
00616         bMustFailNoex.push_back 
00617                 (expandDecisionList(b.all_must_fail_noex_[m],false,N));
00618       }
00619 
00620       std::vector<bool> aPass = combine(aPassAbs, aPassCon);
00621       std::vector<bool> bPass = combine(bPassAbs, bPassCon);
00622       std::vector<bool> aFail = combine(aFailAbs, aFailCon);
00623       std::vector<bool> bFail = combine(bFailAbs, bFailCon);
00624 
00625       // Check for overlap in the primary masks
00626       overlap = overlapping(aPass, bPass) || 
00627                 overlapping(aFail, bFail) || 
00628                 overlapping(aExc, bExc);
00629       if (overlap) return identical(a,b,N) ? evtSel::ExactMatch 
00630                                              : evtSel::PartialOverlap;
00631 
00632       // Check for overlap of a primary fail mask with a must fail mask
00633       for (unsigned int f = 0; f != aMustFail.size(); ++f) {
00634         overlap = overlapping(aMustFail[f], bFail);
00635         if (overlap) return evtSel::PartialOverlap;
00636         for (unsigned int g = 0; g != bMustFail.size(); ++g) {
00637           overlap = subset(aMustFail[f], bMustFail[g]);
00638           if (overlap) return evtSel::PartialOverlap;
00639         } 
00640         for (unsigned int g = 0; g != bMustFailNoex.size(); ++g) {
00641           overlap = subset(aMustFail[f], bMustFailNoex[g]);
00642           if (overlap) return evtSel::PartialOverlap;
00643         }
00644       }
00645       for (unsigned int f = 0; f != aMustFailNoex.size(); ++f) {
00646         overlap = overlapping(aMustFailNoex[f], bFail);
00647         if (overlap) return evtSel::PartialOverlap;
00648         for (unsigned int g = 0; g != bMustFail.size(); ++g) {
00649           overlap = subset(aMustFailNoex[f], bMustFail[g]);
00650           if (overlap) return evtSel::PartialOverlap;
00651         } 
00652         for (unsigned int g = 0; g != bMustFailNoex.size(); ++g) {
00653           overlap = subset(aMustFailNoex[f], bMustFailNoex[g]);
00654           if (overlap) return evtSel::PartialOverlap;
00655         }
00656       }
00657       for (unsigned int g = 0; g != bMustFail.size(); ++g) {
00658         overlap = overlapping(bMustFail[g], aFail);
00659         if (overlap) return evtSel::PartialOverlap;
00660       }
00661       for (unsigned int g = 0; g != bMustFailNoex.size(); ++g) {
00662         overlap = overlapping(bMustFail[g], aFail);
00663         if (overlap) return evtSel::PartialOverlap;
00664       }
00665 
00666     }
00667     catch (edm::Exception const& excpt)
00668     {
00669       return evtSel::InvalidSelection;
00670     }
00671 
00672     // If we get to here without overlap becoming true, there is no overlap
00673 
00674     return evtSel::NoOverlap;
00675 
00676   } // testSelectionOverlap
00677 
00678 #ifdef REMOVE
00679 
00689   evtSel::OverlapResult
00690   EventSelector::testSelectionOverlap(Strings const& pathspec1,
00691                                       Strings const& pathspec2,
00692                                       Strings const& fullTriggerList)
00693   {
00694     // first, test that the selection lists are valid
00695     if (!selectionIsValid(pathspec1, fullTriggerList) ||
00696         !selectionIsValid(pathspec2, fullTriggerList))
00697     {
00698       return evtSel::InvalidSelection;
00699     }
00700 
00701     // initialize possible states
00702     bool noOverlap = true;
00703     bool exactMatch = true;
00704 
00705     // catch exceptions from the EventSelector constructor
00706     // (and anywhere else) and mark those as failures
00707     try
00708     {
00709       // create an EventSelector instance for each selection list
00710       EventSelector selector1(pathspec1, fullTriggerList);
00711       EventSelector selector2(pathspec2, fullTriggerList);
00712 
00713       // create the TriggerResults instance that we'll use for testing
00714       unsigned int fullTriggerCount = fullTriggerList.size();
00715       HLTGlobalStatus hltGS(fullTriggerCount);
00716       TriggerResults sampleResults(hltGS, fullTriggerList);
00717 
00718       // loop over each path
00719       for (unsigned int iPath = 0; iPath < fullTriggerCount; iPath++)
00720       {
00721         // loop over the possible values for the path status
00722         for (int iState = static_cast<int>(hlt::Pass);
00723              iState <= static_cast<int>(hlt::Exception);
00724              iState++)
00725         {
00726           sampleResults[iPath] =
00727             HLTPathStatus(static_cast<hlt::HLTState>(iState), 0);
00728           bool accept1 = selector1.wantAll() ||
00729             selector1.acceptEvent(sampleResults);
00730           bool accept2 = selector2.wantAll() ||
00731             selector2.acceptEvent(sampleResults);
00732           if (accept1 != accept2)
00733           {
00734             exactMatch = false;
00735           }
00736           if (accept1 && accept2)
00737           {
00738             noOverlap = false;
00739           }
00740           sampleResults.reset(iPath);
00741         }
00742       }
00743     }
00744     catch (edm::Exception const& excpt)
00745     {
00746       return evtSel::InvalidSelection;
00747     }
00748 
00749     if (exactMatch) {return evtSel::ExactMatch;}
00750     if (noOverlap) {return evtSel::NoOverlap;}
00751     return evtSel::PartialOverlap;
00752   }
00753 #endif
00754 
00771   boost::shared_ptr<TriggerResults>
00772   EventSelector::maskTriggerResults(TriggerResults const& inputResults)
00773   {
00774     // fetch and validate the total number of paths
00775     unsigned int fullTriggerCount = nTriggerNames_;
00776     unsigned int N = fullTriggerCount;
00777     if (fullTriggerCount != inputResults.size())
00778     {
00779       throw edm::Exception(errors::EventCorruption)
00780         << "EventSelector::maskTriggerResults, the TriggerResults\n"
00781         << "size (" << inputResults.size()
00782         << ") does not match the number of paths in the\n"
00783         << "full trigger list (" << fullTriggerCount << ").\n";
00784     }
00785 
00786     // create a suitable global status object to work with, all in Ready state
00787     HLTGlobalStatus mask(fullTriggerCount);
00788     
00789     // Deal with must_fail acceptors that would cause selection
00790     for (unsigned int m = 0; m < this->all_must_fail_.size(); ++m) {
00791       std::vector<bool>  
00792         f = expandDecisionList(this->all_must_fail_[m],false,N);
00793       bool all_fail = true;
00794       for (unsigned int ipath = 0; ipath < N; ++ipath) {        
00795         if  ((f[ipath]) && (inputResults [ipath].state() != hlt::Fail)) { 
00796           all_fail = false;
00797           break;
00798         }
00799       }
00800       if (all_fail) {
00801         for (unsigned int ipath = 0; ipath < N; ++ipath) {
00802           if  (f[ipath]) { 
00803             mask[ipath] = hlt::Fail;
00804           }
00805         }
00806       }
00807     }
00808     for (unsigned int m = 0; m < this->all_must_fail_noex_.size(); ++m) {
00809       std::vector<bool>  
00810         f = expandDecisionList(this->all_must_fail_noex_[m],false,N);
00811       bool all_fail = true;
00812       for (unsigned int ipath = 0; ipath < N; ++ipath) {        
00813         if ((f[ipath]) && (inputResults [ipath].state() != hlt::Fail)) { 
00814           all_fail = false;
00815           break;
00816         }
00817       }
00818       if (all_fail) {
00819         for (unsigned int ipath = 0; ipath < N; ++ipath) {
00820           if  (f[ipath]) { 
00821             mask[ipath] = hlt::Fail;
00822           }
00823         }
00824       }
00825     } // factoring opportunity - work done for fail_noex_ is same as for fail_
00826     
00827     // Deal with normal acceptors that would cause selection
00828     std::vector<bool> 
00829       aPassAbs = expandDecisionList(this->absolute_acceptors_,true,N);
00830     std::vector<bool> 
00831       aPassCon = expandDecisionList(this->conditional_acceptors_,true,N);
00832     std::vector<bool> 
00833       aFailAbs = expandDecisionList(this->absolute_acceptors_,false,N);
00834     std::vector<bool> 
00835       aFailCon = expandDecisionList(this->conditional_acceptors_,false,N);
00836     std::vector<bool> 
00837       aExc = expandDecisionList(this->exception_acceptors_,true,N);
00838     for (unsigned int ipath = 0; ipath < N; ++ipath) {
00839       hlt::HLTState s = inputResults [ipath].state();  
00840       if (((aPassAbs[ipath]) && (s == hlt::Pass))
00841                 ||
00842           ((aPassCon[ipath]) && (s == hlt::Pass))               
00843                 ||
00844           ((aFailAbs[ipath]) && (s == hlt::Fail))               
00845                 ||
00846           ((aFailCon[ipath]) && (s == hlt::Fail))
00847                 ||
00848           ((aExc[ipath]) && (s == hlt::Exception)))
00849       {
00850         mask[ipath] = s;
00851       }         
00852     }
00853  
00854     // Based on the global status for the mask, create and return a 
00855     // TriggerResults
00856     boost::shared_ptr<TriggerResults>
00857       maskedResults(new TriggerResults(mask, inputResults.parameterSetID()));
00858     return maskedResults;
00859   }  // maskTriggerResults
00860 
00861 
00862 
00863 
00864 
00865 #ifdef REMOVE
00866 
00884   boost::shared_ptr<TriggerResults>
00885   EventSelector::maskTriggerResults(Strings const& pathspecs,
00886                                     TriggerResults const& inputResults,
00887                                     Strings const& fullTriggerList)
00888   {
00889     // fetch and validate the total number of paths
00890     unsigned int fullTriggerCount = fullTriggerList.size();
00891     if (fullTriggerCount != inputResults.size())
00892     {
00893       throw edm::Exception(errors::EventCorruption)
00894         << "EventSelector::maskTriggerResults, the TriggerResults\n"
00895         << "size (" << inputResults.size()
00896         << ") does not match the number of paths in the\n"
00897         << "full trigger list (" << fullTriggerCount << ").\n";
00898     }
00899 
00900     // create a working copy of the TriggerResults object
00901     HLTGlobalStatus hltGS(fullTriggerCount);
00902     boost::shared_ptr<TriggerResults>
00903       maskedResults(new TriggerResults(hltGS, inputResults.parameterSetID()));
00904     for (unsigned int iPath = 0; iPath < fullTriggerCount; iPath++)
00905     {
00906       (*maskedResults)[iPath] = inputResults[iPath];
00907     }
00908 
00909     // create an EventSelector to use when testing if a path status passes
00910     EventSelector selector(pathspecs, fullTriggerList);
00911 
00912     // create the TriggerResults instance that we'll use for testing
00913     HLTGlobalStatus hltGS2(fullTriggerCount);
00914     TriggerResults sampleResults(hltGS2, fullTriggerList);
00915 
00916     // loop over each path and reset the path status if needed
00917     for (unsigned int iPath = 0; iPath < fullTriggerCount; iPath++)
00918     {
00919       sampleResults[iPath] = (*maskedResults)[iPath];
00920       if (!selector.wantAll() && !selector.acceptEvent(sampleResults))
00921       {
00922         maskedResults->reset(iPath);
00923       }
00924       sampleResults.reset(iPath);
00925     }
00926     return maskedResults;
00927   }
00928 #endif
00929 
00938   std::vector<std::string>
00939   EventSelector::getEventSelectionVString(ParameterSet const& pset)
00940   {
00941     // default the selection to everything (wildcard)
00942     Strings selection;
00943     selection.push_back("*");
00944     selection.push_back("!*");
00945     selection.push_back("exception@*");
00946 
00947     // the SelectEvents parameter is a ParameterSet within
00948     // a ParameterSet, so we have to pull it out twice
00949     ParameterSet selectEventsParamSet =
00950       pset.getUntrackedParameter("SelectEvents", ParameterSet());
00951     if (!selectEventsParamSet.empty()) {
00952       Strings path_specs = 
00953         selectEventsParamSet.getParameter<Strings>("SelectEvents");
00954       if (!path_specs.empty()) {
00955         selection = path_specs;
00956       }
00957     }
00958 
00959     // return the result
00960     return selection;
00961   }
00962 
00963   bool EventSelector::containsExceptions(HLTGlobalStatus const& tr) const
00964   {
00965     unsigned int e = tr.size();
00966     for (unsigned int i = 0; i < e; ++i) {
00967       if (tr[i].state() == hlt::Exception) return true;
00968     }
00969     return false;
00970   }
00971 
00972   // The following routines are helpers for testSelectionOverlap
00973   
00974   bool 
00975   EventSelector::identical(std::vector<bool> const& a, 
00976                            std::vector<bool> const& b) {
00977      unsigned int n = a.size();
00978      if (n != b.size()) return false;
00979      for (unsigned int i=0; i!=n; ++i) {
00980        if (a[i] != b[i]) return false;
00981      }
00982      return true;
00983   }
00984   
00985   bool 
00986   EventSelector::identical(EventSelector const& a, 
00987                            EventSelector const& b,
00988                            unsigned int N) 
00989   {
00990         // create the expanded masks for the various decision lists in a and b
00991     if (!identical(expandDecisionList(a.absolute_acceptors_,true,N),
00992                    expandDecisionList(b.absolute_acceptors_,true,N))) 
00993                    return false;
00994     if (!identical(expandDecisionList(a.conditional_acceptors_,true,N),
00995                    expandDecisionList(b.conditional_acceptors_,true,N))) 
00996                    return false;
00997     if (!identical(expandDecisionList(a.absolute_acceptors_,false,N),
00998                    expandDecisionList(b.absolute_acceptors_,false,N)))
00999                    return false;
01000     if (!identical(expandDecisionList(a.conditional_acceptors_,false,N),
01001                    expandDecisionList(b.conditional_acceptors_,false,N))) 
01002                    return false;
01003     if (!identical(expandDecisionList(a.exception_acceptors_,true,N),
01004                    expandDecisionList(b.exception_acceptors_,true,N)))
01005                    return false;
01006     if (a.all_must_fail_.size() != b.all_must_fail_.size()) return false;
01007     
01008     std::vector< std::vector<bool> > aMustFail;
01009     for (unsigned int m = 0; m != a.all_must_fail_.size(); ++m) {
01010       aMustFail.push_back(expandDecisionList(a.all_must_fail_[m],false,N));
01011     }
01012     std::vector< std::vector<bool> > aMustFailNoex;
01013     for (unsigned int m = 0; m != a.all_must_fail_noex_.size(); ++m) {
01014       aMustFailNoex.push_back 
01015               (expandDecisionList(a.all_must_fail_noex_[m],false,N));
01016     }
01017     std::vector< std::vector<bool> > bMustFail;
01018     for (unsigned int m = 0; m != b.all_must_fail_.size(); ++m) {
01019       bMustFail.push_back(expandDecisionList(b.all_must_fail_[m],false,N));
01020     }
01021     std::vector< std::vector<bool> > bMustFailNoex;
01022     for (unsigned int m = 0; m != b.all_must_fail_noex_.size(); ++m) {
01023       bMustFailNoex.push_back 
01024               (expandDecisionList(b.all_must_fail_noex_[m],false,N));
01025     }
01026     
01027     for (unsigned int m = 0; m != aMustFail.size(); ++m) {
01028       bool match = false;
01029       for (unsigned int k = 0; k != bMustFail.size(); ++k) {
01030         if (identical(aMustFail[m],bMustFail[k])) {
01031           match = true;
01032           break;
01033         }
01034       }
01035       if (!match) return false;
01036     }
01037     for (unsigned int m = 0; m != aMustFailNoex.size(); ++m) {
01038       bool match = false;
01039       for (unsigned int k = 0; k != bMustFailNoex.size(); ++k) {
01040          if (identical(aMustFailNoex[m],bMustFailNoex[k])) {
01041           match = true;
01042           break;
01043         }
01044       }
01045       if (!match) return false;
01046     }
01047 
01048     return true;
01049     
01050   } // identical (EventSelector, EventSelector, N);
01051   
01052   std::vector<bool> 
01053   EventSelector::expandDecisionList(Bits const& b,  
01054                                       bool PassOrFail,
01055                                       unsigned int n)
01056   {
01057     std::vector<bool> x(n, false);
01058     for (unsigned int i = 0; i != b.size(); ++i) {
01059       if (b[i].accept_state_ == PassOrFail) x[b[i].pos_] = true;
01060     }
01061     return x;
01062   } // expandDecisionList       
01063   
01064   // Determines whether a and b share a true bit at any position
01065   bool EventSelector::overlapping(std::vector<bool> const& a, 
01066                                      std::vector<bool> const& b)
01067   {
01068     if (a.size() != b.size()) return false;
01069     for (unsigned int i = 0; i != a.size(); ++i) {
01070       if (a[i] && b[i]) return true;
01071     }
01072     return false;
01073   } // overlapping
01074   
01075   // determines whether the true bits of a are a non-empty subset of those of b,
01076   // or vice-versa.  The subset need not be proper.
01077   bool EventSelector::subset(std::vector<bool> const& a, 
01078                                std::vector<bool> const& b)
01079   {
01080     if (a.size() != b.size()) return false;
01081     // First test whether a is a non-empty subset of b 
01082     bool aPresent = false;
01083     bool aSubset = true;
01084     for (unsigned int i = 0; i != a.size(); ++i) {
01085       if (a[i]) {
01086         aPresent = true;
01087         if (!b[i]) {
01088           aSubset = false;
01089           break; 
01090         }
01091       }
01092     }   
01093     if (!aPresent) return false;
01094     if (aSubset) return true;
01095     
01096     // Now test whether b is a non-empty subset of a 
01097     bool bPresent = false;
01098     bool bSubset = true;
01099     for (unsigned int i = 0; i != b.size(); ++i) {
01100       if (b[i]) {
01101         bPresent = true;
01102         if (!a[i]) {
01103           bSubset = false;
01104           break; 
01105         }
01106       }
01107     }   
01108     if (!bPresent) return false;
01109     if (bSubset) return true;
01110  
01111     return false;                                    
01112   } // subset
01113   
01114   // Creates a vector of bits which is the OR of a and b
01115   std::vector<bool> 
01116   EventSelector::combine(std::vector<bool> const& a, 
01117                           std::vector<bool> const& b)
01118   {
01119     assert(a.size() == b.size());
01120     std::vector<bool> x(a.size());
01121     for (unsigned int i = 0; i != a.size(); ++i) {
01122       x[i] = a[i] || b[i];
01123     } // a really sharp compiler will optimize the hell out of this, 
01124       // exploiting word-size OR operations.
01125     return x;
01126   } // combine                                                
01127 
01128   void
01129   EventSelector::fillDescription(ParameterSetDescription& desc) {
01130     ParameterSetDescription selector;
01131     selector.addOptional<std::vector<std::string> >("SelectEvents");
01132     desc.addUntracked<ParameterSetDescription>("SelectEvents", selector);
01133   }
01134 
01135 }