Given the diversity and possible complexity of some legacy DQM modules, this guide will likely not address all the required changes. Please consider it more as a set of suggestions than as a strict list of steps to be follwed; for any more information please refer to the migration guide to the DQMAnalyzer module, or ask the DQM Core team.
A DQMGlobalEDAnalyzer module is a specialisation of an edm::global::EDanalyzer module:
- it is a
globalmodule rather than a legacy module: there is only one copy of it, no matter how many threads or streams the job is configured to use, but it can "see" multiple events being processed at the same time; the advantage is that multiple events can be analised concurrently; on the other hand the module's internal state (the data members) are not allowed to change during theanalyze()(ordqmAnalyze()) method, unless in a concurrency-safe way. See FWMultithreadedFrameworkGlobalModuleInterface for the details. - it uses
ConcurrentMonitorElements rather thanMonitorElements to expose a concurrecy-safe interface to theDQMStore; these objects are also "global": theDQMStoreholds a single copy of the histograms, and there is not merge step at the end fo each lumisection or run; theConcurrentMonitorElementtakes care of preventing multiple events from filling the same histogram at the same time. See Concurrent Monitor Elements for an overview. - it provides a special method,
dqmBeginRun(...), to cache or setup run-based conditions or confugurations.
If your module already inherits from DQMEDAnalyzer, see How to migrate a DQMEDanalyzer to a DQMGlobalEDAnalyzer.
From
#include "FWCore/Framework/interface/EDAnalyzer.h"
#include "DQMServices/Core/interface/MonitorElement.h"to
#include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h"
#include "DQMServices/Core/interface/ConcurrentMonitorElement.h"If you had something like
private:
MonitorElement * m_histo;
std::vector<MonitorElement *> m_more_histos;or
private:
TH2F * m_histo;
std::vector<TH1D *> m_more_histos;they need to be moved to a separate struct or class outside the EDAnalyzer itself:
namespace {
struct Histograms {
ConcurrentMonitorElement histo;
std::vector<ConcurrentMonitorElement> more_histos;
};
}You can no longer used the underlying ROOT objects directly. See the footnote if you need to access the TH1 interface in a way that is not supported by the ConcurrentmonitorElement interface.
From
class MyDQMModule : public edm::EDAnalyzer {
private:
void beginJob() override;
void beginRun(edm::Run const&, edm::EventSetup const&) override;
void analyze(edm::Event const&, edm::EventSetup const&) override;to
class MyDQMModule : public DQMGlobalEDAnalyzer<Histograms> {
private:
void dqmBeginRun(edm::Run const&, edm::EventSetup const&, Histograms &) const override;
void bookHistograms(DQMStore::ConcurrentBooker &, edm::Run const&, edm::EventSetup const&, Histograms &) const override;
void dqmAnalyze(edm::Event const&, edm::EventSetup const&, Histograms const&) const override;and similarly in the individual methods definition, from
void MyDQMModule::beginJob() {
...
}
void MyDQMModule::beginRun(edm::Run const& run, edm::EventSetup const& setup) {
...
}
void MyDQMModule::analyze(edm::Event const& event, edm::EventSetup const& setup) {
...
}to
void MyDQMModule::dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const {
...
}
void MyDQMModule::bookHistograms(DQMStore::ConcurrentBooker & booker, edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const {
...
}
void MyDQMModule::dqmAnalyze(edm::Event const& event, edm::EventSetup const& setup, Histograms const& histograms) const {
...
}The content of the beginJob() and beginRun(...) methods should be migrated to the bookHistograms(...) and dqmBeginRun(...) methods:
- histograms can be booked only inside the
bookHistograms(...)method, which is called at the beginning of each run; - other operations done in the
beginJob()andbeginRun(...)methods should likely be moved to thedqmBeginRun(...)method.
Note thatdqmBeginRun(...)is called beforebookHistograms(...), so non-DQM-related operations and initialisation code should probably be put there.
ThebeginJob()method should probably be removed.
Instead of accessing the DQMStore object directly, the DQMGlobalEDAnalyzer base class will automatically provide an instance of the ConcurrentBooker object.
Any direct reference to the DQMStore should be removed from the class.
All histograms must be booked in the bookHistograms method, using the interface of the ConcurrentBooker class:
void MyDQMModule::bookHistograms(DQMStore::ConcurrentBooker & booker, edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const {
...
histograms.histo = booker.book2D("histo", "My histogram", ...);
...
}Histograms should be filled in the dqmAnalyze(...) method, via the histograms parameter:
histo_->Fill(...);should likely become
histograms.histo.fill(...);bookHistograms(...) is called once at the beginning of each run, while holding the DQMStore lock - meaning that different modules cannot call their bookHistograms(...) methods at the same time.
For time-consuming per-run initialisation code (e.g. to create a local cache of run-based configurations, or to setup the histograms structure) it is better to use the dqmBeginRun(...) method:
void dqmBeginRun(edm::Run const& run, edm::EventSetup const& setup, H & histograms) const override
{
...
}If you need to customise the ConcurrentmonitorElement in a way which is not supported by the current interface, please send a request to extend the interface or implement a more general solution.