Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:09:18

0001 //
0002 // $Id: LogErrorEventFilter.cc,v 1.4 2013/04/09 10:06:10 davidlt Exp $
0003 //
0004 
0005 /**
0006   \class    gLogErrorEventFilter PATMuonKinematics.h "PhysicsTools/PatAlgos/interface/PATMuonKinematics.h"
0007   \brief    Use StandAlone track to define the 4-momentum of a PAT Muon (normally the global one is used)
0008             
0009   \author   Giovanni Petrucciani
0010 */
0011 
0012 #include "FWCore/Framework/interface/global/EDFilter.h"
0013 #include "FWCore/Framework/interface/Event.h"
0014 #include "FWCore/Framework/interface/Run.h"
0015 #include "FWCore/Framework/interface/LuminosityBlock.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/Utilities/interface/InputTag.h"
0018 
0019 #include "DataFormats/Common/interface/ErrorSummaryEntry.h"
0020 
0021 #include <map>
0022 #include <set>
0023 #include <string>
0024 #include <iomanip>
0025 #include <iostream>
0026 #include <iterator>
0027 
0028 namespace leef {
0029   using Error = edm::ErrorSummaryEntry;
0030   struct ErrorSort {
0031     bool operator()(const Error &e1, const Error &e2) const {
0032       if (e1.severity.getLevel() != e2.severity.getLevel())
0033         return e1.severity.getLevel() > e2.severity.getLevel();
0034       if (e1.module != e2.module)
0035         return e1.module < e2.module;
0036       if (e1.category != e2.category)
0037         return e1.category < e2.category;
0038       return false;
0039     }
0040   };
0041   using ErrorSet = std::set<edm::ErrorSummaryEntry, ErrorSort>;
0042 
0043   struct RunErrors {
0044     RunErrors() : npass_{0}, nfail_{0}, collectionGuard_{false} {}
0045     //Errors should be sufficiently infrequent so that the use of a
0046     // spin lock on a thread-unsafe container should not pose a
0047     // performance problem
0048     CMS_THREAD_GUARD(collectionGuard_) mutable ErrorSet errorCollection_;
0049     mutable std::atomic<size_t> npass_;
0050     mutable std::atomic<size_t> nfail_;
0051 
0052     mutable std::atomic<bool> collectionGuard_;
0053   };
0054 
0055   struct LumiErrors {
0056     LumiErrors() : npass_{0}, nfail_{0}, collectionGuard_{false} {}
0057 
0058     CMS_THREAD_GUARD(collectionGuard_) mutable ErrorSet errorCollection_;
0059     mutable std::atomic<size_t> npass_;
0060     mutable std::atomic<size_t> nfail_;
0061 
0062     mutable std::atomic<bool> collectionGuard_;
0063   };
0064 }  // namespace leef
0065 
0066 namespace {
0067   //Use std::unique_ptr to guarantee that the use of an atomic
0068   // as a spin lock will get reset to false
0069   struct release {
0070     void operator()(std::atomic<bool> *b) const noexcept { b->store(false); }
0071   };
0072   std::unique_ptr<std::atomic<bool>, release> make_guard(std::atomic<bool> &b) noexcept {
0073     bool expected = false;
0074     while (not b.compare_exchange_strong(expected, true))
0075       ;
0076 
0077     return std::unique_ptr<std::atomic<bool>, release>(&b, release());
0078   }
0079 
0080 }  // namespace
0081 
0082 using namespace leef;
0083 
0084 class LogErrorEventFilter : public edm::global::EDFilter<edm::RunCache<leef::RunErrors>,
0085                                                          edm::LuminosityBlockCache<LumiErrors>,
0086                                                          edm::EndLuminosityBlockProducer> {
0087 public:
0088   explicit LogErrorEventFilter(const edm::ParameterSet &iConfig);
0089   ~LogErrorEventFilter() override {}
0090 
0091   bool filter(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &iSetup) const override;
0092   std::shared_ptr<LumiErrors> globalBeginLuminosityBlock(const edm::LuminosityBlock &lumi,
0093                                                          const edm::EventSetup &iSetup) const override;
0094   void globalEndLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &iSetup) const override;
0095   void globalEndLuminosityBlockProduce(edm::LuminosityBlock &lumi, const edm::EventSetup &iSetup) const override;
0096   std::shared_ptr<RunErrors> globalBeginRun(const edm::Run &run, const edm::EventSetup &iSetup) const override;
0097   void globalEndRun(const edm::Run &run, const edm::EventSetup &iSetup) const override;
0098   void endJob() override;
0099 
0100 private:
0101   typedef edm::ErrorSummaryEntry Error;
0102   typedef std::vector<edm::ErrorSummaryEntry> ErrorList;
0103 
0104   edm::InputTag src_;
0105   edm::EDGetTokenT<ErrorList> srcT_;
0106   bool readSummaryMode_;
0107   std::set<std::string> modulesToWatch_;
0108   std::set<std::string> modulesToIgnore_;
0109   std::set<std::string> categoriesToWatch_;
0110   std::set<std::string> categoriesToIgnore_;
0111   CMS_THREAD_GUARD(statsGuard_)
0112   mutable std::map<std::pair<uint32_t, uint32_t>, std::pair<size_t, size_t> > statsPerLumi_;
0113   CMS_THREAD_GUARD(statsGuard_) mutable std::map<uint32_t, std::pair<size_t, size_t> > statsPerRun_;
0114   CMS_THREAD_GUARD(statsGuard_) mutable ErrorSet errorCollectionAll_;
0115   double thresholdPerLumi_, thresholdPerRun_;
0116   size_t maxSavedEventsPerLumi_;
0117   bool verbose_, veryVerbose_;
0118   bool taggedMode_, forcedValue_;
0119   mutable std::atomic<bool> statsGuard_;
0120 
0121   template <typename Collection>
0122   static void increment(ErrorSet &scoreboard, Collection &list);
0123   template <typename Collection>
0124   static void print(const Collection &errors);
0125 
0126   static std::unique_ptr<ErrorList> serialize(const ErrorSet &set) {
0127     return std::make_unique<ErrorList>(set.begin(), set.end());
0128   }
0129 };
0130 
0131 LogErrorEventFilter::LogErrorEventFilter(const edm::ParameterSet &iConfig)
0132     : src_(iConfig.getParameter<edm::InputTag>("src")),
0133       srcT_(consumes<ErrorList>(iConfig.getParameter<edm::InputTag>("src"))),
0134       readSummaryMode_(iConfig.existsAs<bool>("readSummaryMode") ? iConfig.getParameter<bool>("readSummaryMode")
0135                                                                  : false),
0136       thresholdPerLumi_(iConfig.getParameter<double>("maxErrorFractionInLumi")),
0137       thresholdPerRun_(iConfig.getParameter<double>("maxErrorFractionInRun")),
0138       maxSavedEventsPerLumi_(iConfig.getParameter<uint32_t>("maxSavedEventsPerLumiAndError")),
0139       verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
0140       veryVerbose_(iConfig.getUntrackedParameter<bool>("veryVerbose", false)),
0141       taggedMode_(iConfig.getUntrackedParameter<bool>("taggedMode", false)),
0142       forcedValue_(iConfig.getUntrackedParameter<bool>("forcedValue", true)) {
0143   produces<ErrorList, edm::Transition::EndLuminosityBlock>();
0144   produces<int, edm::Transition::EndLuminosityBlock>("pass");
0145   produces<int, edm::Transition::EndLuminosityBlock>("fail");
0146   //produces<ErrorList, edm::InRun>();
0147   produces<bool>();
0148 
0149   if (iConfig.existsAs<std::vector<std::string> >("modulesToWatch")) {
0150     std::vector<std::string> modules = iConfig.getParameter<std::vector<std::string> >("modulesToWatch");
0151     if (!(modules.size() == 1 && modules[0] == "*")) {
0152       modulesToWatch_.insert(modules.begin(), modules.end());
0153     }
0154   }
0155   if (iConfig.existsAs<std::vector<std::string> >("modulesToIgnore")) {
0156     std::vector<std::string> modules = iConfig.getParameter<std::vector<std::string> >("modulesToIgnore");
0157     if (!(modules.size() == 1 && modules[0] == "*")) {
0158       modulesToIgnore_.insert(modules.begin(), modules.end());
0159     }
0160   }
0161   if (iConfig.existsAs<std::vector<std::string> >("categoriesToWatch")) {
0162     std::vector<std::string> categories = iConfig.getParameter<std::vector<std::string> >("categoriesToWatch");
0163     if (!(categories.size() == 1 && categories[0] == "*")) {
0164       categoriesToWatch_.insert(categories.begin(), categories.end());
0165     }
0166   }
0167   if (iConfig.existsAs<std::vector<std::string> >("categoriesToIgnore")) {
0168     std::vector<std::string> categories = iConfig.getParameter<std::vector<std::string> >("categoriesToIgnore");
0169     if (!(categories.size() == 1 && categories[0] == "*")) {
0170       categoriesToIgnore_.insert(categories.begin(), categories.end());
0171     }
0172   }
0173   //std::ostream_iterator<std::string> dump(std::cout, ", ");
0174   //std::cout << "\nWatch modules:     " ; std::copy(modulesToWatch_.begin(),     modulesToWatch_.end(),     dump);
0175   //std::cout << "\nIgnore modules:    " ; std::copy(modulesToIgnore_.begin(),    modulesToIgnore_.end(),    dump);
0176   //std::cout << "\nIgnore categories: " ; std::copy(categoriesToIgnore_.begin(), categoriesToIgnore_.end(), dump);
0177   //std::cout << "\nWatch categories:  " ; std::copy(categoriesToWatch_.begin(),  categoriesToWatch_.end(),  dump);
0178   //std::cout << std::endl;
0179 }
0180 
0181 std::shared_ptr<LumiErrors> LogErrorEventFilter::globalBeginLuminosityBlock(const edm::LuminosityBlock &lumi,
0182                                                                             const edm::EventSetup &iSetup) const {
0183   auto ret = std::make_shared<LumiErrors>();
0184   if (readSummaryMode_) {
0185     edm::Handle<ErrorList> handle;
0186     edm::Handle<int> hpass, hfail;
0187     lumi.getByLabel(src_, handle);
0188     lumi.getByLabel(edm::InputTag(src_.label(), "pass", src_.process()), hpass);
0189     lumi.getByLabel(edm::InputTag(src_.label(), "fail", src_.process()), hfail);
0190     increment(ret->errorCollection_, *handle);
0191     ret->npass_ = *hpass;
0192     ret->nfail_ = *hfail;
0193 
0194     auto runC = runCache(lumi.getRun().index());
0195     runC->npass_ += *hpass;
0196     runC->nfail_ += *hfail;
0197   }
0198   return ret;
0199 }
0200 void LogErrorEventFilter::globalEndLuminosityBlock(edm::LuminosityBlock const &lumi,
0201                                                    const edm::EventSetup &iSetup) const {
0202   auto lumiC = luminosityBlockCache(lumi.index());
0203   auto nfail = lumiC->nfail_.load();
0204   auto npass = lumiC->npass_.load();
0205   {
0206     auto guard = make_guard(statsGuard_);
0207     statsPerLumi_[std::pair<uint32_t, uint32_t>(lumi.run(), lumi.luminosityBlock())] =
0208         std::pair<size_t, size_t>(npass, nfail);
0209   }
0210   {
0211     //synchronize lumiC->errorCollection_
0212     auto guard = make_guard(lumiC->collectionGuard_);
0213 
0214     {
0215       if (nfail < thresholdPerLumi_ * (npass + nfail)) {
0216         //synchronize runC->errorCollection_
0217         auto runC = runCache(lumi.getRun().index());
0218         auto guard = make_guard(runC->collectionGuard_);
0219         increment(runC->errorCollection_, lumiC->errorCollection_);
0220       }
0221     }
0222     if (verbose_) {
0223       if (!lumiC->errorCollection_.empty()) {
0224         std::cout << "\n === REPORT FOR RUN " << lumi.run() << " LUMI " << lumi.luminosityBlock()
0225                   << " === " << std::endl;
0226         print(lumiC->errorCollection_);
0227       }
0228     }
0229   }
0230 }
0231 
0232 void LogErrorEventFilter::globalEndLuminosityBlockProduce(edm::LuminosityBlock &lumi,
0233                                                           const edm::EventSetup &iSetup) const {
0234   auto lumiC = luminosityBlockCache(lumi.index());
0235   {
0236     //synchronize errorCollection_
0237     auto guard = make_guard(lumiC->collectionGuard_);
0238     lumi.put(serialize(lumiC->errorCollection_));
0239   }
0240   lumi.put(std::make_unique<int>(lumiC->npass_.load()), "pass");
0241   lumi.put(std::make_unique<int>(lumiC->nfail_.load()), "fail");
0242 }
0243 
0244 std::shared_ptr<RunErrors> LogErrorEventFilter::globalBeginRun(const edm::Run &run,
0245                                                                const edm::EventSetup &iSetup) const {
0246   return std::make_shared<RunErrors>();
0247 }
0248 
0249 void LogErrorEventFilter::globalEndRun(const edm::Run &run, const edm::EventSetup &iSetup) const {
0250   auto runC = runCache(run.index());
0251   auto npass = runC->npass_.load();
0252   auto nfail = runC->nfail_.load();
0253   {
0254     auto guard = make_guard(statsGuard_);
0255     statsPerRun_[run.run()] = std::pair<size_t, size_t>(npass, nfail);
0256   }
0257   {
0258     //synchronize errorCollection_
0259     auto guard = make_guard(runC->collectionGuard_);
0260     if (nfail < thresholdPerRun_ * (npass + nfail)) {
0261       auto guard = make_guard(statsGuard_);
0262       increment(errorCollectionAll_, runC->errorCollection_);
0263     }
0264     if (verbose_) {
0265       if (!runC->errorCollection_.empty()) {
0266         std::cout << "\n === REPORT FOR RUN " << run.run() << " === " << std::endl;
0267         print(runC->errorCollection_);
0268       }
0269     }
0270   }
0271 }
0272 
0273 void LogErrorEventFilter::endJob() {
0274   if (verbose_) {
0275     std::cout << "\n === REPORT FOR JOB === " << std::endl;
0276     //synchronizes statsPerRun_ and errorCollectionAll_
0277     auto guard = make_guard(statsGuard_);
0278     print(errorCollectionAll_);
0279 
0280     typedef std::pair<size_t, size_t> counter;
0281 
0282     std::cout << "\n === SCOREBOARD PER RUN === " << std::endl;
0283     typedef std::pair<uint32_t, counter> hitRun;
0284     for (auto const &hit : statsPerRun_) {
0285       double fract = hit.second.second / double(hit.second.first + hit.second.second);
0286       printf("run %6d: fail %7zu, pass %7zu, fraction %7.3f%%%s\n",
0287              hit.first,
0288              hit.second.second,
0289              hit.second.first,
0290              fract * 100.,
0291              (fract >= thresholdPerRun_ ? " (run excluded from summary list)" : ""));
0292     }
0293 
0294     std::cout << "\n === SCOREBOARD PER LUMI === " << std::endl;
0295     typedef std::pair<std::pair<uint32_t, uint32_t>, counter> hitLumi;
0296     for (auto const &hit : statsPerLumi_) {
0297       double fract = hit.second.second / double(hit.second.first + hit.second.second);
0298       printf("run %6d, lumi %4d: fail %zu, pass %zu, fraction %7.3f%%%s\n",
0299              hit.first.first,
0300              hit.first.second,
0301              hit.second.second,
0302              hit.second.first,
0303              fract * 100.,
0304              (fract >= thresholdPerLumi_ ? " (lumi excluded from run list)" : ""));
0305     }
0306   }
0307 }
0308 
0309 bool LogErrorEventFilter::filter(edm::StreamID, edm::Event &iEvent, const edm::EventSetup &iSetup) const {
0310   if (readSummaryMode_)
0311     return true;
0312 
0313   bool fail = false, save = false;
0314 
0315   edm::Handle<ErrorList> errors;
0316   iEvent.getByToken(srcT_, errors);
0317 
0318   auto runC = runCache(iEvent.getRun().index());
0319   auto lumiC = luminosityBlockCache(iEvent.getLuminosityBlock().index());
0320 
0321   if (errors->empty()) {
0322     ++(runC->npass_);
0323     ++(lumiC->npass_);
0324     iEvent.put(std::make_unique<bool>(false));
0325 
0326     if (taggedMode_)
0327       return forcedValue_;
0328     return false;
0329   }
0330 
0331   for (auto const &err : *errors) {
0332     if (!modulesToWatch_.empty() && (modulesToWatch_.count(err.module) == 0))
0333       continue;
0334     if (!categoriesToWatch_.empty() && (categoriesToWatch_.count(err.category) == 0))
0335       continue;
0336     if (!modulesToIgnore_.empty() && (modulesToIgnore_.count(err.module) != 0))
0337       continue;
0338     if (!categoriesToIgnore_.empty() && (categoriesToIgnore_.count(err.category) != 0))
0339       continue;
0340 
0341     fail = true;
0342 
0343     //synchronize errorCollection_
0344     auto guard = make_guard(lumiC->collectionGuard_);
0345 
0346     std::pair<ErrorSet::iterator, bool> result = lumiC->errorCollection_.insert(err);
0347     if (!result.second) {  // already there
0348       // need the const_cast as set elements are const
0349       const_cast<unsigned int &>(result.first->count) += err.count;
0350       if (result.first->count < maxSavedEventsPerLumi_)
0351         save = true;
0352     } else {
0353       save = true;
0354     }
0355   }
0356   if (save && veryVerbose_) {
0357     std::cout << "\n === REPORT FOR EVENT " << iEvent.id().event() << " RUN " << iEvent.run() << " LUMI "
0358               << iEvent.luminosityBlock() << " === " << std::endl;
0359     print(*errors);
0360   }
0361 
0362   if (fail) {
0363     ++(lumiC->nfail_);
0364     ++(runC->nfail_);
0365   } else {
0366     ++(runC->npass_);
0367     ++(lumiC->npass_);
0368   }
0369   iEvent.put(std::make_unique<bool>(fail));  // fail is the unbiased boolean
0370 
0371   if (taggedMode_)
0372     return forcedValue_;
0373   return save;
0374 }
0375 
0376 template <typename Collection>
0377 void LogErrorEventFilter::increment(ErrorSet &scoreboard, Collection &list) {
0378   for (auto const &err : list) {
0379     std::pair<ErrorSet::iterator, bool> result = scoreboard.insert(err);
0380     // need the const_cast as set elements are const
0381     if (!result.second)
0382       const_cast<unsigned int &>(result.first->count) += err.count;
0383   }
0384 }
0385 
0386 template <typename Collection>
0387 void LogErrorEventFilter::print(const Collection &errors) {
0388   using namespace std;
0389   cout << setw(40) << left << "Category"
0390        << " " << setw(60) << left << "Module"
0391        << " " << setw(10) << left << "Level"
0392        << " " << setw(9) << right << "Count"
0393        << "\n";
0394   cout << setw(40) << left << "----------------------------------------"
0395        << " " << setw(60) << left << "------------------------------------------------------------"
0396        << " " << setw(10) << left << "----------"
0397        << " " << setw(9) << right << "---------"
0398        << "\n";
0399   for (auto const &err : errors) {
0400     cout << setw(40) << left << err.category << " " << setw(60) << left << err.module << " " << setw(10) << left
0401          << err.severity.getName() << " " << setw(9) << right << err.count << "\n";
0402   }
0403   cout << flush;
0404 }
0405 
0406 #include "FWCore/Framework/interface/MakerMacros.h"
0407 DEFINE_FWK_MODULE(LogErrorEventFilter);