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
global
module 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
ConcurrentMonitorElement
s rather thanMonitorElement
s to expose a concurrecy-safe interface to theDQMStore
; these objects are also "global": theDQMStore
holds a single copy of the histograms, and there is not merge step at the end fo each lumisection or run; theConcurrentMonitorElement
takes 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.