Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:53:21

0001 // C++ headers
0002 #include <string>
0003 #include <cstring>
0004 
0005 // boost headers
0006 #include <boost/regex.hpp>
0007 
0008 // Root headers
0009 #include <TH1F.h>
0010 
0011 // CMSSW headers
0012 #include "FWCore/Framework/interface/Frameworkfwd.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/ParameterSet/interface/ParameterSetDescription.h"
0018 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0019 #include "FWCore/ParameterSet/interface/Registry.h"
0020 #include "FWCore/ServiceRegistry/interface/Service.h"
0021 #include "DataFormats/Provenance/interface/ProcessHistory.h"
0022 #include "DQMServices/Core/interface/DQMStore.h"
0023 #include "DQMServices/Core/interface/DQMEDHarvester.h"
0024 
0025 class ThroughputServiceClient : public DQMEDHarvester {
0026 public:
0027   explicit ThroughputServiceClient(edm::ParameterSet const &);
0028   ~ThroughputServiceClient() override = default;
0029 
0030   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
0031 
0032 private:
0033   const std::string m_dqm_path;
0034   const bool m_dqm_merge;
0035   const bool m_fillEveryLumiSection;
0036 
0037   void dqmEndLuminosityBlock(DQMStore::IBooker &booker,
0038                              DQMStore::IGetter &getter,
0039                              edm::LuminosityBlock const &,
0040                              edm::EventSetup const &) override;
0041   void dqmEndJob(DQMStore::IBooker &booker, DQMStore::IGetter &getter) override;
0042 
0043 private:
0044   void fillSummaryPlots(DQMStore::IBooker &booker, DQMStore::IGetter &getter);
0045 };
0046 
0047 ThroughputServiceClient::ThroughputServiceClient(edm::ParameterSet const &config)
0048     : m_dqm_path(config.getUntrackedParameter<std::string>("dqmPath")),
0049       m_dqm_merge(config.getUntrackedParameter<bool>("createSummary")),
0050       m_fillEveryLumiSection(config.getParameter<bool>("fillEveryLumiSection")) {}
0051 
0052 void ThroughputServiceClient::dqmEndJob(DQMStore::IBooker &booker, DQMStore::IGetter &getter) {
0053   fillSummaryPlots(booker, getter);
0054 }
0055 
0056 void ThroughputServiceClient::dqmEndLuminosityBlock(DQMStore::IBooker &booker,
0057                                                     DQMStore::IGetter &getter,
0058                                                     edm::LuminosityBlock const &,
0059                                                     edm::EventSetup const &) {
0060   if (m_fillEveryLumiSection) {
0061     fillSummaryPlots(booker, getter);
0062   }
0063 }
0064 
0065 void ThroughputServiceClient::fillSummaryPlots(DQMStore::IBooker &booker, DQMStore::IGetter &getter) {
0066   // find whether the plots are in the main folder, or in per-number-of-processess subfolders
0067   std::vector<std::string> folders;
0068   if (getter.get(m_dqm_path + "/throughput_sourced")) {
0069     // the plots are in the main folder
0070     folders.push_back(m_dqm_path);
0071   } else {
0072     static const boost::regex running_n_processes(".*/Running .*");
0073     booker.setCurrentFolder(m_dqm_path);
0074     std::vector<std::string> subdirs = getter.getSubdirs();
0075     for (auto const &subdir : subdirs) {
0076       if (boost::regex_match(subdir, running_n_processes)) {
0077         if (getter.get(subdir + "/throughput_sourced")) {
0078           // the plots are in a per-number-of-processes subfolder
0079           folders.push_back(subdir);
0080         }
0081       }
0082     }
0083   }
0084   // create a summary folder if there are more than one
0085   if (m_dqm_merge and folders.size() > 1) {
0086     std::string summary_folder = m_dqm_path + "/Summary";
0087     booker.setCurrentFolder(summary_folder);
0088     // clone the first set of histograms
0089     auto folder = folders.begin();
0090     TH1F *sourced =
0091         booker.book1D("throughput_sourced", getter.get(*folder + "/throughput_sourced")->getTH1F())->getTH1F();
0092     TH1F *retired =
0093         booker.book1D("throughput_retired", getter.get(*folder + "/throughput_retired")->getTH1F())->getTH1F();
0094     // add the other sets of histograms
0095     for (++folder; folder != folders.end(); ++folder) {
0096       sourced->Add(getter.get(*folder + "/throughput_sourced")->getTH1F());
0097       retired->Add(getter.get(*folder + "/throughput_retired")->getTH1F());
0098     }
0099     // move the summary folder to the list
0100     folders.push_back(std::move(summary_folder));
0101   }
0102   for (auto const &folder : folders) {
0103     TH1F *sourced = getter.get(folder + "/throughput_sourced")->getTH1F();
0104     TH1F *retired = getter.get(folder + "/throughput_retired")->getTH1F();
0105     booker.setCurrentFolder(folder);
0106     unsigned int nbins = sourced->GetXaxis()->GetNbins();
0107     double range = sourced->GetXaxis()->GetXmax();
0108 
0109     // (re)book and fill .../concurrent
0110     TH1F *concurrent = booker.book1D("concurrent", "Concurrent events being processed", nbins, 0., range)->getTH1F();
0111     double sum = 0;
0112     // from bin=0 (underflow) to bin=nbins+1 (overflow)
0113     for (unsigned int i = 0; i <= nbins + 1; ++i) {
0114       sum += sourced->GetBinContent(i) - retired->GetBinContent(i);
0115       concurrent->Fill(concurrent->GetXaxis()->GetBinCenter(i), sum);
0116     }
0117 
0118     TH1F *average = nullptr;
0119     double avg_min = std::min(sourced->GetMinimum(0.), retired->GetMinimum(0.));
0120     double avg_max = std::max(sourced->GetMaximum(), retired->GetMaximum());
0121     double width = avg_max - avg_min;
0122     avg_min = std::floor(avg_min - width * 0.2);
0123     if (avg_min < 0.)
0124       avg_min = 0.;
0125     avg_max = std::ceil(avg_max + width * 0.2);
0126     width = avg_max - avg_min;
0127 
0128     // define the range for .../average_sourced
0129     auto first = sourced->FindFirstBinAbove(0.);
0130     auto last = sourced->FindLastBinAbove(0.);
0131     booker.setCurrentFolder(folder);
0132     // (re)book and fill .../average_sourced
0133     average = booker.book1D("average_sourced", "Throughput (sourced events)", (int)width, avg_min, avg_max)->getTH1F();
0134     if (first >= 0)
0135       for (auto i = first; i <= last; ++i)
0136         average->Fill(sourced->GetBinContent(i));
0137 
0138     // define the range for .../average_retired
0139     first = retired->FindFirstBinAbove(0.);
0140     last = retired->FindLastBinAbove(0.);
0141     booker.setCurrentFolder(folder);
0142     // (re)book and fill .../average_retired
0143     average = booker.book1D("average_retired", "Throughput (retired events)", (int)width, avg_min, avg_max)->getTH1F();
0144     if (first >= 0)
0145       for (auto i = first; i <= last; ++i)
0146         average->Fill(retired->GetBinContent(i));
0147   }
0148 }
0149 
0150 void ThroughputServiceClient::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0151   edm::ParameterSetDescription desc;
0152   desc.addUntracked<std::string>("dqmPath", "HLT/Throughput");
0153   desc.addUntracked<bool>("createSummary", true);
0154   desc.add<bool>("fillEveryLumiSection", true);
0155   descriptions.add("throughputServiceClient", desc);
0156 }
0157 
0158 // declare this class as a framework plugin
0159 #include "FWCore/Framework/interface/MakerMacros.h"
0160 DEFINE_FWK_MODULE(ThroughputServiceClient);