Skip to content

Commit

Permalink
Merge pull request #28407 from schneiml/dqm-new-globaledanalyzer
Browse files Browse the repository at this point in the history
DQM: new DQMGlobalEDAnalyzer
cmsbuild authored Jan 8, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 3804db5 + 1dd3a3d commit a8d5c49
Showing 14 changed files with 81 additions and 259 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FWCore.ParameterSet.Config as cms

SiStripGainsPCLWorker = cms.EDAnalyzer(
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
SiStripGainsPCLWorker = DQMEDAnalyzer(
"SiStripGainsPCLWorker",
minTrackMomentum = cms.untracked.double(2),
maxNrStrips = cms.untracked.uint32(8),
3 changes: 2 additions & 1 deletion DQM/HLTEvF/python/trigObjTnPSource_cfi.py
Original file line number Diff line number Diff line change
@@ -45,7 +45,8 @@
filler = cms.PSet(var = cms.string("eta"),localCuts = cms.VPSet())
)

trigObjTnPSource = cms.EDAnalyzer('TrigObjTnPSource',
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
trigObjTnPSource = DQMEDAnalyzer('TrigObjTnPSource',
triggerEvent = cms.InputTag('hltTriggerSummaryAOD','','HLT'),
triggerResults = cms.InputTag('TriggerResults','','HLT'),
histColls = cms.VPSet(cms.PSet(
3 changes: 2 additions & 1 deletion DQMServices/Components/python/DQMLumiMonitor_cfi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FWCore.ParameterSet.Config as cms

dqmLumiMonitor = cms.EDAnalyzer("DQMLumiMonitor",
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
dqmLumiMonitor = DQMEDAnalyzer("DQMLumiMonitor",
ModuleName = cms.string('Info'),
FolderName = cms.string('Lumi'),
PixelClusterInputTag = cms.InputTag('siPixelClusters'),
93 changes: 57 additions & 36 deletions DQMServices/Core/interface/DQMGlobalEDAnalyzer.h
Original file line number Diff line number Diff line change
@@ -2,57 +2,78 @@
#define DQMServices_Core_DQMGlobalEDAnalyzer_h

#include "DQMServices/Core/interface/DQMStore.h"
#include "DataFormats/Histograms/interface/DQMToken.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/Run.h"
#include "FWCore/Framework/interface/global/EDAnalyzer.h"
#include "FWCore/Framework/interface/global/EDProducer.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ServiceRegistry/interface/Service.h"

template <typename H, typename... Args>
class DQMGlobalEDAnalyzer : public edm::global::EDAnalyzer<edm::RunCache<H>, Args...> {
class DQMGlobalEDAnalyzer
: public edm::global::EDProducer<edm::RunCache<H>,
// DQMGlobalEDAnalyzer are fundamentally unable to produce histograms for any
// other scope than MonitorElement::Scope::RUN.
edm::EndRunProducer,
edm::Accumulator,
Args...> {
public:
typedef dqm::reco::MonitorElement MonitorElement;
typedef dqm::reco::DQMStore DQMStore;
typedef dqm::reco::MonitorElement MonitorElement;

private:
std::shared_ptr<H> globalBeginRun(edm::Run const&, edm::EventSetup const&) const final;
// framework calls in the order of invocation
DQMGlobalEDAnalyzer() {
// for whatever reason we need the explicit `template` keyword here.
runToken_ = this->template produces<DQMToken, edm::Transition::EndRun>("DQMGenerationRecoRun");
dqmstore_ = edm::Service<DQMStore>().operator->();
}

void globalEndRun(edm::Run const&, edm::EventSetup const&) const final;
std::shared_ptr<H> globalBeginRun(edm::Run const& run, edm::EventSetup const& setup) const final {
auto h = std::make_shared<H>();

virtual void dqmBeginRun(edm::Run const&, edm::EventSetup const&, H&) const {}
dqmBeginRun(run, setup, *h);

// this will run while holding the DQMStore lock
virtual void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&, H&) const = 0;
// in case of concurrent runs, this will create clones of the already
// booked MEs.
dqmstore_->bookTransaction(
[&, this](DQMStore::IBooker& b) {
// this runs while holding the DQMStore lock
b.cd();
bookHistograms(b, run, setup, *h);
},
run.run(),
/* moduleID */ 0,
/* canSaveByLumi */ false);
// Populate run numbers, in case booking only books prototypes.
// We will not call enterLumi per-lumi, since this is strictly run-based.
return h;
}

void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const final;
void accumulate(edm::StreamID id, edm::Event const& event, edm::EventSetup const& setup) const final {
auto const& h = *this->runCache(event.getRun().index());
dqmAnalyze(event, setup, h);
}

virtual void dqmAnalyze(edm::Event const&, edm::EventSetup const&, H const&) const = 0;
};
void globalEndRunProduce(edm::Run& run, edm::EventSetup const& setup) const final {
auto const& h = *this->runCache(run.index());
dqmEndRun(run, setup, h);
run.emplace(runToken_);
}

template <typename H, typename... Args>
std::shared_ptr<H> DQMGlobalEDAnalyzer<H, Args...>::globalBeginRun(edm::Run const& run,
edm::EventSetup const& setup) const {
auto h = std::make_shared<H>();
dqmBeginRun(run, setup, *h);
edm::Service<DQMStore>()->bookConcurrentTransaction(
[&, this](DQMStore::IBooker& b) {
// this runs while holding the DQMStore lock
b.cd();
bookHistograms(b, run, setup, *h);
},
run.run());
return h;
}
// Subsystems could safely override this, but any changes to MEs would not be
// noticeable since the product was made already.
void globalEndRun(edm::Run const&, edm::EventSetup const&) const final{};

template <typename H, typename... Args>
void DQMGlobalEDAnalyzer<H, Args...>::globalEndRun(edm::Run const&, edm::EventSetup const&) const {}
// methods to be implemented by the user, in order of invocation
virtual void dqmBeginRun(edm::Run const&, edm::EventSetup const&, H&) const {}
virtual void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&, H&) const = 0;
// TODO: rename this analyze() for consistency.
virtual void dqmAnalyze(edm::Event const&, edm::EventSetup const&, H const&) const = 0;
virtual void dqmEndRun(edm::Run const&, edm::EventSetup const&, H const&) const {}

template <typename H, typename... Args>
void DQMGlobalEDAnalyzer<H, Args...>::analyze(edm::StreamID,
edm::Event const& event,
edm::EventSetup const& setup) const {
//auto& h = const_cast<H&>(* this->runCache(event.getRun().index()));
auto const& h = *this->runCache(event.getRun().index());
dqmAnalyze(event, setup, h);
}
private:
DQMStore* dqmstore_;
edm::EDPutTokenT<DQMToken> runToken_;
};

#endif // DQMServices_Core_DQMGlobalEDAnalyzer_h
50 changes: 0 additions & 50 deletions DQMServices/Core/interface/DQMStore.h
Original file line number Diff line number Diff line change
@@ -71,29 +71,6 @@ namespace dqm::dqmstoreimpl {
// change the ME subtype here
typedef dqm::legacy::MonitorElement MonitorElement;

/** Implements RegEx patterns which occur often in a high-performant
mattern. For all other expressions, the full RegEx engine is used.
Note: this class can only be used for lat::Regexp::Wildcard-like
patterns. */
class fastmatch {
enum MatchingHeuristicEnum { UseFull, OneStarStart, OneStarEnd, TwoStar };

public:
fastmatch(std::string fastString);

bool match(std::string const& s) const;

private:
// checks if two strings are equal, starting at the back of the strings
bool compare_strings_reverse(std::string const& pattern, std::string const& input) const;
// checks if two strings are equal, starting at the front of the strings
bool compare_strings(std::string const& pattern, std::string const& input) const;

std::unique_ptr<lat::Regexp> regexp_{nullptr};
std::string fastString_;
MatchingHeuristicEnum matching_;
};

class DQMStore {
public:
// legacy exposes the biggest API and implicitly converts to reco and
@@ -299,33 +276,6 @@ namespace dqm::dqmstoreimpl {
}
}

// Similar function used to book "global" histograms via the
// dqm::reco::MonitorElement* interface.
template <typename iFunc>
void bookConcurrentTransaction(iFunc f, uint32_t run) {
std::lock_guard<std::mutex> guard(book_mutex_);
/* Set the run_ member only if enableMultiThread is enabled */
if (enableMultiThread_) {
run_ = run;
moduleId_ = 0;
canSaveByLumi_ = false;
}
IBooker booker(this);
f(booker);

/* Reset the run_ member only if enableMultiThread is enabled */
if (enableMultiThread_) {
run_ = 0;
moduleId_ = 0;
canSaveByLumi_ = false;
}
}

// Signature needed in the harvesting where the booking is done in
// the endJob. No handles to the run there. Two arguments ensure the
// capability of booking and getting. The method relies on the
// initialization of run, stream and module ID to 0. The mutex is
// not needed.
template <typename iFunc>
void meBookerGetter(iFunc f) {
IBooker booker{this};
108 changes: 0 additions & 108 deletions DQMServices/Core/src/DQMStore.cc
Original file line number Diff line number Diff line change
@@ -108,114 +108,6 @@ namespace dqm::dqmstoreimpl {
path += name;
}

/////////////////////////////////////////////////////////////
fastmatch::fastmatch(std::string fastString) : fastString_{move(fastString)}, matching_{UseFull} {
try {
regexp_ = std::make_unique<lat::Regexp>(fastString_, 0, lat::Regexp::Wildcard);
regexp_->study();
} catch (lat::Error& e) {
raiseDQMError("DQMStore",
"Invalid wildcard pattern '%s' in quality"
" test specification",
fastString_.c_str());
}

// count stars ( "*" )
size_t starCount = 0;
int pos = -1;
while (true) {
pos = fastString_.find('*', pos + 1);
if ((size_t)pos == std::string::npos)
break;
++starCount;
}

// investigate for heuristics
if ((fastString_.find('"') != std::string::npos) || (fastString_.find(']') != std::string::npos) ||
(fastString_.find('?') != std::string::npos) || (fastString_.find('\\') != std::string::npos) ||
(starCount > 2)) {
// no fast version can be used
return;
}

// match for pattern "*MyString" and "MyString*"
if (starCount == 1) {
if (boost::algorithm::starts_with(fastString_, "*")) {
matching_ = OneStarStart;
fastString_.erase(0, 1);
return;
}

if (boost::algorithm::ends_with(fastString_, "*")) {
matching_ = OneStarEnd;
fastString_.erase(fastString_.length() - 1, 1);
return;
}
}

// match for pattern "*MyString*"
if (starCount == 2) {
if (boost::algorithm::starts_with(fastString_, "*") && boost::algorithm::ends_with(fastString_, "*")) {
matching_ = TwoStar;
fastString_.erase(0, 1);
fastString_.erase(fastString_.size() - 1, 1);
return;
}
}
}

bool fastmatch::compare_strings_reverse(std::string const& pattern, std::string const& input) const {
if (input.size() < pattern.size())
return false;

// compare the two strings character by character for equalness:
// this does not create uneeded copies of std::string. The
// boost::algorithm implementation does
auto rit_pattern = pattern.crbegin();
auto rit_input = input.crbegin();

for (; rit_pattern < pattern.rend(); ++rit_pattern, ++rit_input) {
if (*rit_pattern != *rit_input)
// found a difference, fail
return false;
}
return true;
}

bool fastmatch::compare_strings(std::string const& pattern, std::string const& input) const {
if (input.size() < pattern.size())
return false;

// compare the two strings character by character for equalness:
// this does not create uneeded copies of std::string. The
// boost::algorithm implementation does.
auto rit_pattern = pattern.cbegin();
auto rit_input = input.cbegin();

for (; rit_pattern < pattern.end(); ++rit_pattern, ++rit_input) {
if (*rit_pattern != *rit_input)
// found a difference, fail
return false;
}
return true;
}

bool fastmatch::match(std::string const& s) const {
switch (matching_) {
case OneStarStart:
return compare_strings_reverse(fastString_, s);

case OneStarEnd:
return compare_strings(fastString_, s);

case TwoStar:
return (s.find(fastString_) != std::string::npos);

default:
return regexp_->match(s);
}
}

//IBooker methods
MonitorElement* DQMStore::IBooker::bookInt(TString const& name) { return owner_->bookInt(name); }

2 changes: 0 additions & 2 deletions DQMServices/Core/test/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -7,5 +7,3 @@
<library file="DQMTestMultiThread.cc" name="DQMTestMultiThread">
<flags EDM_PLUGIN="1"/>
</library>
<bin file="DQMFastMatchTest.cc">
</bin>
47 changes: 0 additions & 47 deletions DQMServices/Core/test/DQMFastMatchTest.cc

This file was deleted.

4 changes: 2 additions & 2 deletions HLTrigger/Timer/plugins/FastTimerService.cc
Original file line number Diff line number Diff line change
@@ -872,8 +872,8 @@ void FastTimerService::preGlobalBeginRun(edm::GlobalContext const& gc) {
};

// book MonitorElements for this stream
edm::Service<dqm::legacy::DQMStore>()->bookConcurrentTransaction(bookTransactionCallback,
gc.luminosityBlockID().run());
edm::Service<dqm::legacy::DQMStore>()->bookTransaction(
bookTransactionCallback, gc.luminosityBlockID().run(), /* moduleID */ 0, /* canSaveByLumi*/ false);
}
}
}
3 changes: 2 additions & 1 deletion HLTrigger/Timer/plugins/ThroughputService.cc
Original file line number Diff line number Diff line change
@@ -66,7 +66,8 @@ void ThroughputService::preGlobalBeginRun(edm::GlobalContext const& gc) {
};

// book MonitorElement's for this run
edm::Service<DQMStore>()->bookConcurrentTransaction(bookTransactionCallback, gc.luminosityBlockID().run());
edm::Service<DQMStore>()->bookTransaction(
bookTransactionCallback, gc.luminosityBlockID().run(), /* moduleID */ 0, /* canSaveByLumi */ false);
} else {
std::cerr << "No DQMStore service, aborting." << std::endl;
abort();
9 changes: 5 additions & 4 deletions Validation/DTRecHits/python/DTRecHitQualityAll_cfi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FWCore.ParameterSet.Config as cms

rechivalidation = cms.EDAnalyzer("DTRecHitQuality",
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
rechivalidation = DQMEDAnalyzer("DTRecHitQuality",
doStep2 = cms.untracked.bool(False),
# Switches for analysis at various steps
doStep1 = cms.untracked.bool(True),
@@ -16,15 +17,15 @@

)

seg2dvalidation = cms.EDAnalyzer("DTSegment2DQuality",
seg2dvalidation = DQMEDAnalyzer("DTSegment2DQuality",
sigmaResPos = cms.double(0.013),
simHitLabel = cms.untracked.InputTag('g4SimHits',"MuonDTHits"),
segment2DLabel = cms.untracked.InputTag('dt2DSegments'),
debug = cms.untracked.bool(False),
sigmaResAngle = cms.double(0.008)
)

seg2dsuperphivalidation = cms.EDAnalyzer("DTSegment2DSLPhiQuality",
seg2dsuperphivalidation = DQMEDAnalyzer("DTSegment2DSLPhiQuality",
sigmaResPos = cms.double(0.013),
simHitLabel = cms.untracked.InputTag('g4SimHits',"MuonDTHits"),
sigmaResAngle = cms.double(0.008),
@@ -34,7 +35,7 @@
local = cms.untracked.bool(False)
)

seg4dvalidation = cms.EDAnalyzer("DTSegment4DQuality",
seg4dvalidation = DQMEDAnalyzer("DTSegment4DQuality",
#resolution on angle
sigmaResAlpha = cms.double(0.001),
sigmaResBeta = cms.double(0.007),
9 changes: 5 additions & 4 deletions Validation/DTRecHits/python/DTRecHitQuality_cfi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FWCore.ParameterSet.Config as cms

rechivalidation = cms.EDAnalyzer("DTRecHitQuality",
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
rechivalidation = DQMEDAnalyzer("DTRecHitQuality",
doStep2 = cms.untracked.bool(False),
# Switches for analysis at various steps
doStep1 = cms.untracked.bool(False),
@@ -15,15 +16,15 @@
local = cms.untracked.bool(False)
)

seg2dvalidation = cms.EDAnalyzer("DTSegment2DQuality",
seg2dvalidation = DQMEDAnalyzer("DTSegment2DQuality",
sigmaResPos = cms.double(0.013),
simHitLabel = cms.untracked.InputTag('g4SimHits',"MuonDTHits"),
segment2DLabel = cms.untracked.InputTag('dt2DSegments'),
debug = cms.untracked.bool(False),
sigmaResAngle = cms.double(0.008)
)

seg2dsuperphivalidation = cms.EDAnalyzer("DTSegment2DSLPhiQuality",
seg2dsuperphivalidation = DQMEDAnalyzer("DTSegment2DSLPhiQuality",
sigmaResPos = cms.double(0.013),
simHitLabel = cms.untracked.InputTag('g4SimHits',"MuonDTHits"),
sigmaResAngle = cms.double(0.008),
@@ -33,7 +34,7 @@
local = cms.untracked.bool(False)
)

seg4dvalidation = cms.EDAnalyzer("DTSegment4DQuality",
seg4dvalidation = DQMEDAnalyzer("DTSegment4DQuality",
#resolution on angle
sigmaResAlpha = cms.double(0.001),
sigmaResBeta = cms.double(0.007),
3 changes: 2 additions & 1 deletion Validation/HGCalValidation/python/HGCalValidator_cfi.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@
from Validation.HGCalValidation.CaloParticleSelectionForEfficiency_cfi import *
from Validation.HGCalValidation.HGVHistoProducerAlgoBlock_cfi import *

hgcalValidator = cms.EDAnalyzer(
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
hgcalValidator = DQMEDAnalyzer(
"HGCalValidator",

### general settings ###
3 changes: 2 additions & 1 deletion Validation/RecoTrack/python/MultiTrackValidator_cfi.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,8 @@
from SimTracker.TrackAssociation.CosmicParametersDefinerForTP_cfi import *
from Validation.RecoTrack.MTVHistoProducerAlgoForTrackerBlock_cfi import *

multiTrackValidator = cms.EDAnalyzer(
from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
multiTrackValidator = DQMEDAnalyzer(
"MultiTrackValidator",

### general settings ###

0 comments on commit a8d5c49

Please sign in to comment.