Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:25

0001 #ifndef Selections_H
0002 #define Selections_H
0003 
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "CommonTools/UtilAlgos/interface/EventSelector.h"
0006 #include <cstdlib>
0007 #include <iomanip>
0008 #include <iostream>
0009 #include <sstream>
0010 #include "TFormula.h"
0011 
0012 class Filter {
0013 public:
0014   Filter() = default;
0015   Filter(const edm::ParameterSet& iConfig, edm::ConsumesCollector& iC);
0016   Filter(std::string name, edm::ParameterSet& iConfig, edm::ConsumesCollector& iC)
0017       : name_(name), cached_decision_(false), eventCacheID_(0) {
0018     dump_ = iConfig.dump();
0019     if (!iConfig.empty()) {
0020       const std::string d("name");
0021       iConfig.addUntrackedParameter<std::string>(d, name);
0022       std::string componentName = iConfig.getParameter<std::string>("selector");
0023       selector_ = EventSelectorFactoryFromHelper::get()->create(componentName, iConfig, iC);
0024       if (iConfig.exists("description"))
0025         description_ = iConfig.getParameter<std::vector<std::string> >("description");
0026       else
0027         description_ = selector_->description();
0028     }
0029   }
0030   virtual ~Filter() {}
0031 
0032   Filter(const Filter&) = delete;
0033   Filter& operator=(const Filter&) = delete;
0034   Filter(Filter&&) = default;
0035   Filter& operator=(Filter&&) = default;
0036 
0037   const std::string& name() { return name_; }
0038   const std::string& dump() { return dump_; }
0039   const std::vector<std::string> description() { return description_; }
0040   const std::string descriptionText() {
0041     std::string text;
0042     for (unsigned int i = 0; i != description_.size(); ++i)
0043       text += description_[i] + "\n";
0044     text += dump() + "\n";
0045     return text;
0046   }
0047 
0048   virtual bool accept(edm::Event& iEvent) {
0049     bool decision = false;
0050     if (std::numeric_limits<edm::Event::CacheIdentifier_t>::max() != eventCacheID_ and
0051         eventCacheID_ != iEvent.cacheIdentifier()) {
0052       eventCacheID_ = iEvent.cacheIdentifier();
0053 
0054       if (selector_)
0055         decision = selector_->select(iEvent);
0056       else
0057         decision = true;
0058       cached_decision_ = decision;
0059     } else {
0060       decision = cached_decision_;
0061     }
0062     return decision;
0063   }
0064 
0065 protected:
0066   std::string name_;
0067   std::vector<std::string> description_;
0068   std::unique_ptr<EventSelector> selector_;
0069   mutable bool cached_decision_;
0070   mutable edm::Event::CacheIdentifier_t eventCacheID_ = 0;
0071   std::string dump_;
0072 };
0073 
0074 // will behave like a filter*
0075 class SFilter {
0076 public:
0077   SFilter(Filter* f, bool i) : filter_(f), inverted_(i){};
0078   ~SFilter(){};
0079 
0080   Filter& operator*() { return *filter_; }
0081   Filter* operator->() { return filter_; }
0082   bool inverted() { return inverted_; }
0083 
0084 private:
0085   Filter* filter_;
0086   bool inverted_;
0087 };
0088 
0089 class FilterOR : public Filter {
0090 public:
0091   ~FilterOR() override {}
0092   FilterOR(const std::string& filterORlist, const std::map<std::string, Filter*>& filters) {
0093     std::string filterORlistCopy = filterORlist;
0094     name_ = filterORlist;
0095     std::stringstream ss;
0096     ss << "Filter doing an OR of: ";
0097     //split the OR-separated string into vector of strings
0098     unsigned int size = 0;
0099     bool OK = true;
0100     while (OK) {
0101       size_t orPos = filterORlistCopy.find("_OR_");
0102       if (orPos == std::string::npos && !filterORlistCopy.empty()) {
0103         size = filterORlistCopy.size();
0104         OK = false;
0105       } else
0106         size = orPos;
0107 
0108       std::string filter = filterORlistCopy.substr(0, size);
0109       //remove the filter name and the OR (4 characters) from the string
0110       if (OK)
0111         filterORlistCopy = filterORlistCopy.substr(0 + size + 4);
0112 
0113       std::map<std::string, Filter*>::const_iterator it = filters.find(filter);
0114       if (it == filters.end()) {
0115         edm::LogError("FilterOR") << "cannot do an OR of: " << filter << " OR expression is: " << filterORlist;
0116         break;
0117       }
0118       filters_.push_back(std::make_pair(it->first, it->second));
0119       ss << it->first << " ";
0120     }
0121     description_.push_back(ss.str());
0122   }
0123   bool accept(edm::Event& iEvent) override {
0124     for (unsigned int i = 0; i != filters_.size(); ++i)
0125       if (filters_[i].second->accept(iEvent))
0126         return true;
0127     return false;
0128   }
0129 
0130 private:
0131   std::vector<std::pair<std::string, Filter*> > filters_;
0132 };
0133 
0134 //forward declaration for friendship
0135 class FilterSelections;
0136 
0137 class FilterSelection : public Filter {
0138 public:
0139   typedef std::vector<SFilter>::iterator iterator;
0140   friend class FilterSelections;
0141 
0142   FilterSelection(std::string name, const edm::ParameterSet& iConfig)
0143       : name_(name),
0144         ntuplize_(iConfig.getParameter<bool>("ntuplize")),
0145         makeContentPlots_(iConfig.getParameter<bool>("makeContentPlots")),
0146         makeFinalPlots_(iConfig.getParameter<bool>("makeFinalPlots")),
0147         makeCumulativePlots_(iConfig.getParameter<bool>("makeCumulativePlots")),
0148         makeAllButOnePlots_(iConfig.getParameter<bool>("makeAllButOnePlots")),
0149         nSeen_(0),
0150         makeSummaryTable_(iConfig.getParameter<bool>("makeSummaryTable")),
0151         makeDetailledPrintout_(iConfig.exists("detailledPrintoutCategory")) {
0152     Filter::name_ = name_;
0153     Filter::description_.push_back(std::string("See definition of the corresponding selection"));
0154     if (iConfig.exists("nMonitor"))
0155       nMonitor_ = iConfig.getParameter<unsigned int>("nMonitor");
0156     else
0157       nMonitor_ = 0;
0158 
0159     if (makeDetailledPrintout_)
0160       detailledPrintoutCategory_ = iConfig.getParameter<std::string>("detailledPrintoutCategory");
0161   }
0162 
0163   FilterSelection(const FilterSelection&) = delete;
0164   FilterSelection& operator=(const FilterSelection&) = delete;
0165   FilterSelection(FilterSelection&&) = default;
0166   FilterSelection& operator=(FilterSelection&&) = default;
0167 
0168   const std::string& name() { return name_; }
0169   iterator begin() { return filters_.begin(); }
0170   iterator end() { return filters_.end(); }
0171 
0172   bool accept(edm::Event& iEvent) override {
0173     if (std::numeric_limits<edm::Event::CacheIdentifier_t>::max() != eventCacheID_ and
0174         eventCacheID_ != iEvent.cacheIdentifier()) {
0175       this->acceptMap(iEvent);
0176     }
0177     return cached_decision_;
0178   }
0179 
0180   std::map<std::string, bool> acceptMap(edm::Event& iEvent) {
0181     nSeen_++;
0182     if (nMonitor_ != 0 && nSeen_ % nMonitor_ == 0) {
0183       if (nSeen_ == nMonitor_)
0184         print();
0185       else
0186         print(false);
0187     }
0188     std::map<std::string, bool> ret;
0189     bool global = true;
0190     for (iterator filter = begin(); filter != end(); ++filter) {
0191       const std::string& fName = (*filter)->name();
0192       Count& count = counts_[fName];
0193       count.nSeen_++;
0194       bool decision = (*filter)->accept(iEvent);
0195       bool inverted = (*filter).inverted();
0196       if (inverted)
0197         decision = !decision;
0198       ret[fName] = decision;
0199       if (decision)
0200         count.nPass_++;
0201       global = global && decision;
0202       if (global)
0203         count.nCumulative_++;
0204     }
0205 
0206     if (makeDetailledPrintout_) {
0207       std::stringstream summary;
0208       summary << std::setw(20) << name().substr(0, 19) << " : " << std::setw(10) << iEvent.id().run() << " : "
0209               << std::setw(10) << iEvent.id().event();
0210       for (iterator filter = begin(); filter != end(); ++filter) {
0211         const std::string& fName = (*filter)->name();
0212         summary << " : " << std::setw(10) << (ret[fName] ? "pass" : "reject");
0213       }
0214       edm::LogVerbatim(detailledPrintoutCategory_) << summary.str();
0215     }
0216 
0217     cached_decision_ = global;
0218     eventCacheID_ = iEvent.cacheIdentifier();
0219     return ret;
0220   }
0221 
0222   void printDetailledPrintoutHeader() {
0223     if (makeDetailledPrintout_) {
0224       std::stringstream summary;
0225       summary << std::setw(20) << " selection name "
0226               << " : " << std::setw(10) << " run "
0227               << " : " << std::setw(10) << " event ";
0228       for (iterator filter = begin(); filter != end(); ++filter) {
0229         summary << " : " << std::setw(10) << (*filter)->name().substr(0, 9);
0230       }
0231       edm::LogVerbatim(detailledPrintoutCategory_) << summary.str();
0232     }
0233   }
0234   //print to LogVerbatim("Selections|<name()>")
0235   void print(bool description = true) {
0236     if (!makeSummaryTable_)
0237       return;
0238 
0239     unsigned int maxFnameSize = 20;
0240     for (iterator filter = begin(); filter != end(); ++filter) {
0241       if ((*filter)->name().size() > maxFnameSize)
0242         maxFnameSize = (*filter)->name().size() + 1;
0243     }
0244 
0245     //    const std::string category ="Selections|"+name();
0246     const std::string category = "Selections";
0247     std::stringstream summary;
0248     summary << "   Summary table for selection: " << name() << " with: " << nSeen_ << " events run." << std::endl;
0249     if (nSeen_ == 0)
0250       return;
0251     if (description) {
0252       for (iterator filter = begin(); filter != end(); ++filter) {
0253         const std::string& fName = (*filter)->name();
0254         summary << "filter: " << std::right << std::setw(10) << fName << "\n" << (*filter)->descriptionText() << "\n";
0255       }
0256     }
0257     summary << " filter stand-alone pass: " << std::endl;
0258     summary << std::right << std::setw(maxFnameSize) << "total read"
0259             << ": " << std::right << std::setw(10) << nSeen_ << std::endl;
0260     for (iterator filter = begin(); filter != end(); ++filter) {
0261       std::string fName = (*filter)->name();
0262       const Count& count = counts_[fName];
0263       if ((*filter).inverted())
0264         fName = '!' + fName;
0265       summary << std::right << std::setw(maxFnameSize) << fName << ": " << std::right << std::setw(10) << count.nPass_
0266               << " passed events. " << std::right << std::setw(10) << std::setprecision(5)
0267               << (count.nPass_ / (float)count.nSeen_) * 100. << " [%]" << std::endl;
0268     }
0269     summary << " filter cumulative pass:" << std::endl;
0270     summary << std::right << std::setw(maxFnameSize) << "total read"
0271             << ": " << std::right << std::setw(10) << nSeen_ << std::endl;
0272     unsigned int lastCount = nSeen_;
0273     for (iterator filter = begin(); filter != end(); ++filter) {
0274       std::string fName = (*filter)->name();
0275       const Count& count = counts_[fName];
0276       if ((*filter).inverted())
0277         fName = '!' + fName;
0278       summary << std::right << std::setw(maxFnameSize) << fName << ": " << std::right << std::setw(10)
0279               << count.nCumulative_ << " passed events. " << std::right << std::setw(10) << std::setprecision(5)
0280               << (count.nCumulative_ / (float)count.nSeen_) * 100. << " [%]";
0281       if (lastCount != 0)
0282         summary << " (to previous count) " << std::right << std::setw(10) << std::setprecision(5)
0283                 << (count.nCumulative_ / (float)lastCount) * 100. << " [%]";
0284       summary << std::endl;
0285 
0286       lastCount = count.nCumulative_;
0287     }
0288     summary << "-------------------------------------\n";
0289     edm::LogVerbatim(category) << summary.str();
0290     std::cout << summary.str();
0291   };
0292 
0293   bool ntuplize() { return ntuplize_; }
0294   bool makeContentPlots() { return makeContentPlots_; }
0295   bool makeFinalPlots() { return makeFinalPlots_; }
0296   bool makeCumulativePlots() { return makeCumulativePlots_; }
0297   bool makeAllButOnePlots() { return makeAllButOnePlots_; }
0298   bool makeSummaryTable() { return makeSummaryTable_; }
0299 
0300 private:
0301   std::string name_;
0302   std::vector<SFilter> filters_;  // this is the local list of filters belonging to the selection
0303 
0304   //some options
0305   bool ntuplize_;
0306   bool makeContentPlots_;
0307   bool makeFinalPlots_;
0308   bool makeCumulativePlots_;
0309   bool makeAllButOnePlots_;
0310 
0311   unsigned int nSeen_;
0312   unsigned int nMonitor_;
0313 
0314   struct Count {
0315     unsigned int nPass_;
0316     unsigned int nSeen_;
0317     unsigned int nCumulative_;
0318   };
0319   std::map<std::string, Count> counts_;
0320   bool makeSummaryTable_;
0321   bool makeDetailledPrintout_;
0322   std::string detailledPrintoutCategory_;
0323 };
0324 
0325 class FilterSelections {
0326 public:
0327   typedef std::vector<FilterSelection>::iterator iterator;
0328 
0329   FilterSelections(const edm::ParameterSet& iConfig, edm::ConsumesCollector&& iC)
0330       : filtersPSet_(iConfig.getParameter<edm::ParameterSet>("filters")),
0331         selectionPSet_(iConfig.getParameter<edm::ParameterSet>("selections")) {
0332     //FIXME. what about nested filters
0333     // not so needed since we are explicitely spelling all modules
0334     //make all configured filters
0335     std::vector<std::string> filterNames;
0336     unsigned int nF = filtersPSet_.getParameterSetNames(filterNames);
0337     for (unsigned int iF = 0; iF != nF; iF++) {
0338       edm::ParameterSet pset = filtersPSet_.getParameter<edm::ParameterSet>(filterNames[iF]);
0339       filters_.insert(std::make_pair(filterNames[iF],
0340                                      new Filter(filterNames[iF], pset, iC)));  // this is the global pool of filters
0341     }
0342 
0343     //parse all configured selections
0344     std::vector<std::string> selectionNames;
0345     std::map<std::string, std::vector<std::string> > selectionFilters;
0346     unsigned int nS = selectionPSet_.getParameterSetNames(selectionNames);
0347     for (unsigned int iS = 0; iS != nS; iS++) {
0348       edm::ParameterSet pset = selectionPSet_.getParameter<edm::ParameterSet>(selectionNames[iS]);
0349       // JR-2014 : the filters are not expanded here
0350       selections_.push_back(FilterSelection(selectionNames[iS], pset));
0351       //      selections_.insert(std::make_pair(selectionNames[iS],Selection(selectionNames[iS],pset)));
0352       //keep track of list of filters for this selection for further dependency resolution
0353       selectionFilters[selectionNames[iS]] = pset.getParameter<std::vector<std::string> >("filterOrder");
0354     }
0355 
0356     //watch out of recursive dependency
0357     //    unsigned int nestedDepth=0; //FIXME not taken care of
0358 
0359     //resolving dependencies
0360     for (std::map<std::string, std::vector<std::string> >::iterator sIt = selectionFilters.begin();
0361          sIt != selectionFilters.end();
0362          ++sIt) {
0363       //parse the vector of filterNames
0364       for (std::vector<std::string>::iterator fOrS = sIt->second.begin(); fOrS != sIt->second.end(); ++fOrS) {
0365         if (filters_.find(*fOrS) == filters_.end()) {
0366           //not a know filter names uncountered : either Selection of _OR_.
0367           if (fOrS->find("_OR_") != std::string::npos) {
0368             filters_.insert(std::make_pair((*fOrS), new FilterOR((*fOrS), filters_)));
0369           }  //_OR_ filter
0370           else {
0371             // look for a selection name
0372             std::map<std::string, std::vector<std::string> >::iterator s = selectionFilters.find(*fOrS);
0373             if (s == selectionFilters.end()) {
0374               //error.
0375               if ((*fOrS)[0] != '!') {
0376                 edm::LogError("SelectionHelper") << "unresolved filter/selection name: " << *fOrS;
0377               }
0378             }  //not a Selection name.
0379             else {
0380               // JR-2014 : don't do anything here, and move on : in fact no, replace it to have the details in the histograming tool
0381               //remove the occurence
0382               std::vector<std::string>::iterator newLoc = sIt->second.erase(fOrS);
0383               //insert the list of filters corresponding to this selection in there
0384               sIt->second.insert(newLoc, s->second.begin(), s->second.end());
0385               //decrement selection iterator to come back to it
0386               sIt--;
0387               break;
0388             }  //a Selection name
0389           }
0390         }  //the name is not a simple filter name : either Selection of _OR_.
0391 
0392       }  //loop over the strings in "filterOrder"
0393     }    //loop over all defined Selection
0394 
0395     //finally, configure the Selections
0396     //loop the selections instanciated
0397     //    for (std::map<std::string, FilterSelection>::iterator sIt=selections_.begin();sIt!=selections_.end();++sIt)
0398     //      const std::string & sName=sIt->first;
0399     //FilterSelection & selection =sIt->second;
0400     for (std::vector<FilterSelection>::iterator sIt = selections_.begin(); sIt != selections_.end(); ++sIt) {
0401       const std::string& sName = sIt->name();
0402       FilterSelection& selection = *sIt;
0403 
0404       //parse the vector of filterNames
0405       std::vector<std::string>& listOfFilters = selectionFilters[sName];
0406       for (std::vector<std::string>::iterator fIt = listOfFilters.begin(); fIt != listOfFilters.end(); ++fIt) {
0407         std::string fOsName = *fIt;
0408         bool inverted = false;
0409         if (fOsName[0] == '!') {
0410           inverted = true;
0411           fOsName = fOsName.substr(1);
0412         }
0413         std::map<std::string, Filter*>::iterator filterInstance = filters_.find(fOsName);
0414         if (filterInstance == filters_.end()) {
0415           // JR-2014 include the selection here, directly !
0416           bool replaceBySelection = false;
0417           //find an existing selection that match that name
0418           for (std::vector<FilterSelection>::iterator sit = selections_.begin(); sit != selections_.end(); ++sit) {
0419             if (fOsName == sit->name_) {
0420               selection.filters_.push_back(SFilter(&(*sit), inverted));
0421               replaceBySelection = true;
0422             }
0423           }
0424           if (!replaceBySelection) {
0425             //error
0426             edm::LogError("Selections") << "cannot resolve: " << fOsName;
0427           }
0428         } else {
0429           //actually increment the filter
0430           selection.filters_.push_back(SFilter(filterInstance->second, inverted));
0431         }
0432       }
0433     }
0434 
0435     for (iterator sIt = begin(); sIt != end(); ++sIt)
0436       sIt->printDetailledPrintoutHeader();
0437   }
0438 
0439   iterator begin() { return selections_.begin(); }
0440   iterator end() { return selections_.end(); }
0441 
0442   //print each selection
0443   void print() {
0444     for (std::vector<FilterSelection>::iterator sIt = selections_.begin(); sIt != selections_.end(); ++sIt)
0445       sIt->print();
0446   }
0447 
0448 private:
0449   edm::ParameterSet filtersPSet_;
0450   std::map<std::string, Filter*> filters_;  // the global collection of available filters to pick from
0451 
0452   edm::ParameterSet selectionPSet_;
0453   std::vector<FilterSelection> selections_;
0454 };
0455 
0456 #endif