# How to migrate a legacy DQM edm::EDAnalyzer to a DQMGlobalEDAnalyzer 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 the `analyze()` (or `dqmAnalyze()`) method, unless in a concurrency-safe way. See [FWMultithreadedFrameworkGlobalModuleInterface](https://twiki.cern.ch/twiki/bin/view/CMSPublic/FWMultithreadedFrameworkGlobalModuleInterface) for the details. - it uses `ConcurrentMonitorElement`s rather than `MonitorElement`s to expose a concurrecy-safe interface to the `DQMStore`; these objects are also "global": the `DQMStore` holds a single copy of the histograms, and there is not merge step at the end fo each lumisection or run; the `ConcurrentMonitorElement` takes care of preventing multiple events from filling the same histogram at the same time. See [Concurrent Monitor Elements](https://indico.cern.ch/event/689165/contributions/2829871/attachments/1577616/2491752/Concurrent_Monitor_Elements.pdf) 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](https://gist.github.com/fwyzard/9831080ea903e571c69b8b3f92632f9b). ## Update the headers From ```c++ #include "FWCore/Framework/interface/EDAnalyzer.h" #include "DQMServices/Core/interface/MonitorElement.h" ``` to ```c++ #include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h" #include "DQMServices/Core/interface/ConcurrentMonitorElement.h" ``` ## Move the histograms to a separate structure If you had something like ```c++ private: MonitorElement * m_histo; std::vector m_more_histos; ``` or ```c++ private: TH2F * m_histo; std::vector m_more_histos; ``` they need to be moved to a separate `struct` or `class` outside the EDAnalyzer itself: ```c++ namespace { struct Histograms { ConcurrentMonitorElement histo; std::vector 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. ## Update the class signature From ```c++ 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 ```c++ class MyDQMModule : public DQMGlobalEDAnalyzer { 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 ```c++ 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 ```c++ 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()` and `beginRun(...)` methods should likely be moved to the `dqmBeginRun(...)` method. Note that `dqmBeginRun(...)` is called before `bookHistograms(...)`, so non-DQM-related operations and initialisation code should probably be put there. The `beginJob()` method should probably be removed. ## Remove any explicit reference to the `DQMStore` 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. ## Update the logic for booking histograms All histograms must be booked in the `bookHistograms` method, using [the interface](https://github.com/cms-sw/cmssw/blob/master/DQMServices/Core/interface/DQMStore.h#L195) of the `ConcurrentBooker` class: ```c++ void MyDQMModule::bookHistograms(DQMStore::ConcurrentBooker & booker, edm::Run const& run, edm::EventSetup const& setup, Histograms & histograms) const { ... histograms.histo = booker.book2D("histo", "My histogram", ...); ... } ``` ## Update the logic for filling histograms Histograms should be filled in the `dqmAnalyze(...)` method, via the `histograms` parameter: ```c++ histo_->Fill(...); ``` should likely become ```c++ histograms.histo.fill(...); ``` ## `dqmBeginRun(...)` `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: ```c++ 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](mailto:"DQM%20Core%20Team"%20<cms-dqm-coreTeam@cern.ch>?cc="Andrea%20Bocci"%20<andrea.bocci@cern.ch>&subject=Extend%20the%20ConcurrentMonitorElement%20interface) to extend the interface or implement a more general solution.