Skip to content

Instantly share code, notes, and snippets.

@fwyzard
Last active January 18, 2018 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fwyzard/23ea1b58cf736524d0eb7e240d9afd1e to your computer and use it in GitHub Desktop.
Save fwyzard/23ea1b58cf736524d0eb7e240d9afd1e to your computer and use it in GitHub Desktop.
How to migrate a legacy DQM edm::EDAnalyzer to a DQMGlobalEDAnalyzer

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 for the details.
  • it uses ConcurrentMonitorElements rather than MonitorElements 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 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.

Update the headers

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"

Move the histograms to a separate structure

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.

Update the class signature

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() 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 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", ...);
  ...
}

Update the logic for filling histograms

Histograms should be filled in the dqmAnalyze(...) method, via the histograms parameter:

  histo_->Fill(...);

should likely become

  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:

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment