diff --git a/GeneratorInterface/RivetInterface/interface/RivetAnalyzer.h b/GeneratorInterface/RivetInterface/interface/RivetAnalyzer.h index 03cb4e9652253..e69f7adc97a8e 100644 --- a/GeneratorInterface/RivetInterface/interface/RivetAnalyzer.h +++ b/GeneratorInterface/RivetInterface/interface/RivetAnalyzer.h @@ -47,24 +47,28 @@ class RivetAnalyzer void normalizeTree(); edm::EDGetTokenT _hepmcCollection; - bool _useExternalWeight; bool _useLHEweights; - int _LHEweightNumber; - bool _useGENweights; - int _GENweightNumber; + double _weightCap; + double _NLOSmearing; + bool _skipMultiWeights; + std::string _selectMultiWeights; + std::string _deselectMultiWeights; + std::string _setNominalWeightName; edm::EDGetTokenT _LHECollection; edm::EDGetTokenT _genEventInfoCollection; edm::EDGetTokenT _genLumiInfoToken; edm::EDGetTokenT _lheRunInfoToken; - Rivet::AnalysisHandler _analysisHandler; + std::unique_ptr _analysisHandler; bool _isFirstEvent; std::string _outFileName; + std::vector _analysisNames; bool _doFinalize; bool _produceDQM; const edm::InputTag _lheLabel; double _xsection; std::vector _weightNames; std::vector _lheWeightNames; + std::vector _cleanedWeightNames; DQMStore *dbe; std::vector _mes; diff --git a/GeneratorInterface/RivetInterface/plugins/RivetAnalyzer.cc b/GeneratorInterface/RivetInterface/plugins/RivetAnalyzer.cc index a5d971df2018b..615a1a8561781 100644 --- a/GeneratorInterface/RivetInterface/plugins/RivetAnalyzer.cc +++ b/GeneratorInterface/RivetInterface/plugins/RivetAnalyzer.cc @@ -17,9 +17,9 @@ using namespace Rivet; using namespace edm; RivetAnalyzer::RivetAnalyzer(const edm::ParameterSet& pset) - : _analysisHandler(), - _isFirstEvent(true), + : _isFirstEvent(true), _outFileName(pset.getParameter("OutputFile")), + _analysisNames(pset.getParameter >("AnalysisNames")), //decide whether to finalize the plots or not. //deciding not to finalize them can be useful for further harvesting of many jobs _doFinalize(pset.getParameter("DoFinalize")), @@ -28,9 +28,6 @@ RivetAnalyzer::RivetAnalyzer(const edm::ParameterSet& pset) _xsection(-1.) { usesResource("Rivet"); - //retrive the analysis name from parameter set - std::vector analysisNames = pset.getParameter >("AnalysisNames"); - _hepmcCollection = consumes(pset.getParameter("HepMCCollection")); _genLumiInfoToken = consumes(pset.getParameter("genLumiInfo")); @@ -40,8 +37,12 @@ RivetAnalyzer::RivetAnalyzer(const edm::ParameterSet& pset) _LHECollection = consumes(_lheLabel); } - //get the analyses - _analysisHandler.addAnalyses(analysisNames); + _weightCap = pset.getParameter("weightCap"); + _NLOSmearing = pset.getParameter("NLOSmearing"); + _skipMultiWeights = pset.getParameter("skipMultiWeights"); + _selectMultiWeights = pset.getParameter("selectMultiWeights"); + _deselectMultiWeights = pset.getParameter("deselectMultiWeights"); + _setNominalWeightName = pset.getParameter("setNominalWeightName"); //set user cross section if needed _xsection = pset.getParameter("CrossSection"); @@ -115,6 +116,17 @@ void RivetAnalyzer::beginLuminosityBlock(const edm::LuminosityBlock& iLumi, cons void RivetAnalyzer::endLuminosityBlock(const edm::LuminosityBlock& iLumi, const edm::EventSetup& iSetup) { return; } void RivetAnalyzer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { + //finalize weight names on the first event + if (_isFirstEvent) { + if (_useLHEweights) { + _weightNames.insert(_weightNames.end(), _lheWeightNames.begin(), _lheWeightNames.end()); + } + // clean weight names to be accepted by Rivet plotting + for (const std::string& wn : _weightNames) { + _cleanedWeightNames.push_back(std::regex_replace(wn, std::regex("[^A-Za-z\\d\\._=]"), "_")); + } + } + //get the hepmc product from the event edm::Handle evt; iEvent.getByToken(_hepmcCollection, evt); @@ -123,63 +135,65 @@ void RivetAnalyzer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSe const HepMC::GenEvent* myGenEvent = evt->GetEvent(); std::unique_ptr tmpGenEvtPtr; //if you want to use an external weight or set the cross section we have to clone the GenEvent and change the weight - if (_useLHEweights || _xsection > 0) { - tmpGenEvtPtr = std::make_unique(*(evt->GetEvent())); + tmpGenEvtPtr = std::make_unique(*(evt->GetEvent())); - if (_xsection > 0) { - HepMC::GenCrossSection xsec; - xsec.set_cross_section(_xsection); - tmpGenEvtPtr->set_cross_section(xsec); - } - - if (_useLHEweights) { - std::vector mergedWeights; - for (unsigned int i = 0; i < tmpGenEvtPtr->weights().size(); i++) { - mergedWeights.push_back(tmpGenEvtPtr->weights()[i]); - } + if (_xsection > 0) { + HepMC::GenCrossSection xsec; + xsec.set_cross_section(_xsection); + tmpGenEvtPtr->set_cross_section(xsec); + } - edm::Handle lheEventHandle; - iEvent.getByToken(_LHECollection, lheEventHandle); - for (unsigned int i = 0; i < _lheWeightNames.size(); i++) { - mergedWeights.push_back(tmpGenEvtPtr->weights()[0] * lheEventHandle->weights().at(i).wgt / - lheEventHandle->originalXWGTUP()); - } + std::vector mergedWeights; + for (unsigned int i = 0; i < tmpGenEvtPtr->weights().size(); i++) { + mergedWeights.push_back(tmpGenEvtPtr->weights()[i]); + } - tmpGenEvtPtr->weights() = mergedWeights; + if (_useLHEweights) { + edm::Handle lheEventHandle; + iEvent.getByToken(_LHECollection, lheEventHandle); + for (unsigned int i = 0; i < _lheWeightNames.size(); i++) { + mergedWeights.push_back(tmpGenEvtPtr->weights()[0] * lheEventHandle->weights().at(i).wgt / + lheEventHandle->originalXWGTUP()); } - myGenEvent = tmpGenEvtPtr.get(); } + tmpGenEvtPtr->weights().clear(); + for (unsigned int i = 0; i < _cleanedWeightNames.size(); i++) { + tmpGenEvtPtr->weights()[_cleanedWeightNames[i]] = mergedWeights[i]; + } + myGenEvent = tmpGenEvtPtr.get(); + //apply the beams initialization on the first event if (_isFirstEvent) { - if (_useLHEweights) { - _weightNames.insert(_weightNames.end(), _lheWeightNames.begin(), _lheWeightNames.end()); - } - // clean weight names to be accepted by Rivet plotting - std::vector cleanedWeightNames; - for (const std::string& wn : _weightNames) { - cleanedWeightNames.push_back(std::regex_replace(wn, std::regex("[^A-Za-z\\d\\._=]"), "_")); - } - _analysisHandler.init(*myGenEvent, cleanedWeightNames); - const HepMC::GenCrossSection* xs = myGenEvent->cross_section(); - _analysisHandler.setCrossSection(make_pair(xs->cross_section(), xs->cross_section_error())); + _analysisHandler = std::make_unique(); + _analysisHandler->addAnalyses(_analysisNames); + + /// Set analysis handler weight options + _analysisHandler->skipMultiWeights(_skipMultiWeights); + _analysisHandler->selectMultiWeights(_selectMultiWeights); + _analysisHandler->deselectMultiWeights(_deselectMultiWeights); + _analysisHandler->setNominalWeightName(_setNominalWeightName); + _analysisHandler->setWeightCap(_weightCap); + _analysisHandler->setNLOSmearing(_NLOSmearing); + + _analysisHandler->init(*myGenEvent); _isFirstEvent = false; } //run the analysis - _analysisHandler.analyze(*myGenEvent); + _analysisHandler->analyze(*myGenEvent); } void RivetAnalyzer::endRun(const edm::Run& iRun, const edm::EventSetup& iSetup) { if (_doFinalize) - _analysisHandler.finalize(); + _analysisHandler->finalize(); else { //if we don't finalize we just want to do the transformation from histograms to DPS - ////normalizeTree(_analysisHandler.tree()); + ////normalizeTree(_analysisHandler->tree()); //normalizeTree(); } - _analysisHandler.writeData(_outFileName); + _analysisHandler->writeData(_outFileName); return; } @@ -194,7 +208,7 @@ void RivetAnalyzer::endJob() {} void RivetAnalyzer::normalizeTree() { using namespace YODA; - std::vector analyses = _analysisHandler.analysisNames(); + std::vector analyses = _analysisHandler->analysisNames(); //tree.ls(".", true); const string tmpdir = "/RivetNormalizeTmp"; @@ -205,12 +219,12 @@ void RivetAnalyzer::normalizeTree() { //global variables that are always present //sumOfWeights TH1F nevent("nEvt", "n analyzed Events", 1, 0., 1.); - nevent.SetBinContent(1, _analysisHandler.sumW()); + nevent.SetBinContent(1, _analysisHandler->sumW()); _mes.push_back(dbe->book1D("nEvt", &nevent)); } //cross section //TH1F xsection("xSection", "Cross Section", 1, 0., 1.); - //xsection.SetBinContent(1,_analysisHandler.crossSection()); + //xsection.SetBinContent(1,_analysisHandler->crossSection()); //_mes.push_back(dbe->book1D("xSection",&xsection)); //now loop over the histograms @@ -236,7 +250,7 @@ void RivetAnalyzer::normalizeTree() { if (histo) { IHistogram1D* tmphisto = dynamic_cast(tree.find(tmppath)); if (tmphisto) { - _analysisHandler.datapointsetFactory().create(path, *tmphisto); + _analysisHandler->datapointsetFactory().create(path, *tmphisto); } //now convert to root and then ME //need aida2flat (from Rivet 1.X) & flat2root here @@ -250,7 +264,7 @@ void RivetAnalyzer::normalizeTree() { else if (prof) { IProfile1D* tmpprof = dynamic_cast(tree.find(tmppath)); if (tmpprof) { - _analysisHandler.datapointsetFactory().create(path, *tmpprof); + _analysisHandler->datapointsetFactory().create(path, *tmpprof); } //now convert to root and then ME //need aida2flat (from Rivet 1.X) & flat2root here diff --git a/GeneratorInterface/RivetInterface/python/rivetAnalyzer_cfi.py b/GeneratorInterface/RivetInterface/python/rivetAnalyzer_cfi.py index 22750da6cc409..19c9185decc27 100644 --- a/GeneratorInterface/RivetInterface/python/rivetAnalyzer_cfi.py +++ b/GeneratorInterface/RivetInterface/python/rivetAnalyzer_cfi.py @@ -8,6 +8,12 @@ # Info: useLHEWeights will create BIG yoda files with Rivet 3. # Default plotting fails with too many histos, use -m/M options useLHEweights = cms.bool(False), + weightCap = cms.double(0.), + NLOSmearing = cms.double(0.), + skipMultiWeights = cms.bool(False), + selectMultiWeights = cms.string(''), + deselectMultiWeights = cms.string(''), + setNominalWeightName = cms.string(''), LHECollection = cms.InputTag('externalLHEProducer'), CrossSection = cms.double(-1), DoFinalize = cms.bool(True), diff --git a/GeneratorInterface/RivetInterface/test/BuildFile.xml b/GeneratorInterface/RivetInterface/test/BuildFile.xml index ca06300ccbe72..c044a6dbd8d59 100644 --- a/GeneratorInterface/RivetInterface/test/BuildFile.xml +++ b/GeneratorInterface/RivetInterface/test/BuildFile.xml @@ -1,2 +1,11 @@ + + + + + + + + + diff --git a/GeneratorInterface/RivetInterface/test/rivet_cfg.py b/GeneratorInterface/RivetInterface/test/rivet_cfg.py index a84a71d85de8a..975d9022f81a1 100644 --- a/GeneratorInterface/RivetInterface/test/rivet_cfg.py +++ b/GeneratorInterface/RivetInterface/test/rivet_cfg.py @@ -83,7 +83,7 @@ ) process.load("GeneratorInterface.RivetInterface.rivetAnalyzer_cfi") -process.rivetAnalyzer.AnalysisNames = cms.vstring('MC_GENERIC', 'CMS_2014_I1305624') +process.rivetAnalyzer.AnalysisNames = cms.vstring('MC_GENERIC', 'CMS_2014_I1305624', 'MC_XS') # Path and EndPath definitions process.generation_step = cms.Path(process.pgen*process.rivetAnalyzer) diff --git a/GeneratorInterface/RivetInterface/test/runRivetAnalyzerMiniAOD_cfg.py b/GeneratorInterface/RivetInterface/test/runRivetAnalyzerMiniAOD_cfg.py index 79b9822e53270..8f73f344130d6 100644 --- a/GeneratorInterface/RivetInterface/test/runRivetAnalyzerMiniAOD_cfg.py +++ b/GeneratorInterface/RivetInterface/test/runRivetAnalyzerMiniAOD_cfg.py @@ -1,6 +1,6 @@ import FWCore.ParameterSet.Config as cms -process = cms.Process('GEN') +process = cms.Process('Rivet') process.load("FWCore.MessageLogger.MessageLogger_cfi") process.MessageLogger.cerr.FwkReport.reportEvery = cms.untracked.int32(100) diff --git a/GeneratorInterface/RivetInterface/test/test-rivet-nan.sh b/GeneratorInterface/RivetInterface/test/test-rivet-nan.sh new file mode 100755 index 0000000000000..0a6f725df2661 --- /dev/null +++ b/GeneratorInterface/RivetInterface/test/test-rivet-nan.sh @@ -0,0 +1,3 @@ +#!/bin/sh -e + +! grep "nan" out.yoda diff --git a/GeneratorInterface/RivetInterface/test/test-yoda-merge.sh b/GeneratorInterface/RivetInterface/test/test-yoda-merge.sh new file mode 100755 index 0000000000000..51d58b4db3795 --- /dev/null +++ b/GeneratorInterface/RivetInterface/test/test-yoda-merge.sh @@ -0,0 +1,3 @@ +#!/bin/sh -e + +yodamerge -o merged.yoda out.yoda out.yoda diff --git a/GeneratorInterface/RivetInterface/test/test-yoda-root.sh b/GeneratorInterface/RivetInterface/test/test-yoda-root.sh new file mode 100755 index 0000000000000..1257724a9b01a --- /dev/null +++ b/GeneratorInterface/RivetInterface/test/test-yoda-root.sh @@ -0,0 +1,3 @@ +#!/bin/sh -e + +yoda2root out.yoda