Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-28 02:53:02

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