From cd2a110efdb81bea06a7f61dd6997bca5919994e Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sat, 15 Jan 2022 23:06:23 +0100 Subject: [PATCH 01/16] First implementation of WeightGroupInfo/product classes --- .../interface/LHEWeightInfoProduct.h | 37 ++++++++ .../interface/LHEWeightProduct.h | 43 ++++++++++ .../interface/PdfWeightGroupInfo.h | 44 ++++++++++ .../interface/ScaleWeightGroupInfo.h | 64 ++++++++++++++ .../interface/WeightGroupInfo.h | 77 +++++++++++++++++ .../src/LHEWeightInfoProduct.cc | 40 +++++++++ .../src/PdfWeightGroupInfo.cc | 15 ++++ .../src/ScaleWeightGroupInfo.cc | 52 +++++++++++ .../src/ScaleWeightGroupInfo.h | 16 ++++ .../GeneratorProducts/src/WeightGroupInfo.cc | 86 +++++++++++++++++++ .../GeneratorProducts/src/classes.h | 16 ++-- .../GeneratorProducts/src/classes_def.xml | 11 +++ 12 files changed, 495 insertions(+), 6 deletions(-) create mode 100644 SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h create mode 100644 SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h create mode 100644 SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc create mode 100644 SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc create mode 100644 SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc create mode 100644 SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc diff --git a/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h new file mode 100644 index 0000000000000..f0fa291ab3423 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h @@ -0,0 +1,37 @@ +#ifndef SimDataFormats_GeneratorProducts_LHEWeightInfoProduct_h +#define SimDataFormats_GeneratorProducts_LHEWeightInfoProduct_h + +#include +#include +#include +#include + +//#include + +#include "DataFormats/Common/interface/OwnVector.h" +#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +class LHEWeightInfoProduct { + public: + LHEWeightInfoProduct() {} + LHEWeightInfoProduct(edm::OwnVector& weightGroups); + LHEWeightInfoProduct(const LHEWeightInfoProduct& other); + LHEWeightInfoProduct(LHEWeightInfoProduct&& other); + ~LHEWeightInfoProduct() {} + LHEWeightInfoProduct& operator=(const LHEWeightInfoProduct &other); + LHEWeightInfoProduct& operator=(LHEWeightInfoProduct &&other); + + const edm::OwnVector& allWeightGroupsInfo() const; + const gen::WeightGroupInfo& containingWeightGroupInfo(int index) const; + const gen::WeightGroupInfo& orderedWeightGroupInfo(int index) const; + void addWeightGroupInfo(gen::WeightGroupInfo& info); + + private: + edm::OwnVector weightGroupsInfo_; + + +}; + +#endif // GeneratorWeightInfo_LHEInterface_LHEWeightInfoProduct_h + diff --git a/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h new file mode 100644 index 0000000000000..5c5fa132b4ee7 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h @@ -0,0 +1,43 @@ +#ifndef SimDataFormats_GeneratorProducts_LHEWeightProduct_h +#define SimDataFormats_GeneratorProducts_LHEWeightProduct_h + +#include +#include +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" + +typedef std::vector> WeightsContainer; + +class LHEWeightProduct { + public: + LHEWeightProduct() { weightsVector_ = {}; } + LHEWeightProduct& operator=(LHEWeightProduct&& other) { + weightsVector_ = std::move(other.weightsVector_); + return *this; + } + ~LHEWeightProduct() {} + + void setNumWeightSets(int num) { weightsVector_.resize(num); } + void addWeightSet() { weightsVector_.push_back({}); } + void addWeight(double weight, int setEntry, int weightNum) { + if (weightsVector_.size() == 0 && setEntry == 0) + addWeightSet(); + if (static_cast(weightsVector_.size()) <= setEntry) + throw std::domain_error("Out of range weight"); + auto& weights = weightsVector_.at(setEntry); + if (static_cast(weights.size()) <= weightNum) { + weights.resize(weightNum+1); + } + weights[weightNum] = weight; + } + const WeightsContainer& weights() const { return weightsVector_; } + + private: + WeightsContainer weightsVector_; +}; + +#endif // GeneratorEvent_LHEInterface_LHEWeightProduct_h + diff --git a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h new file mode 100644 index 0000000000000..5f1e5559f46e2 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h @@ -0,0 +1,44 @@ +#ifndef SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h + +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + enum PdfUncertaintyType { + kHessianUnc, + kMonteCarloUnc, + kUnknownUnc, + }; + + class PdfWeightGroupInfo : public WeightGroupInfo { + private: + PdfUncertaintyType uncertaintyType_; + bool hasAlphasVars_; + int alphasUpIndex_; + int alphasDownIndex_; + public: + PdfWeightGroupInfo() : WeightGroupInfo() { weightType_ = kPdfWeights; } + PdfWeightGroupInfo(std::string header, std::string name) : + WeightGroupInfo(header, name) { weightType_ = kPdfWeights; } + PdfWeightGroupInfo(std::string header) : + WeightGroupInfo(header) { weightType_ = kPdfWeights; } + PdfWeightGroupInfo(const PdfWeightGroupInfo &other) { + copy(other); + } + virtual ~PdfWeightGroupInfo() override {} + void copy(const PdfWeightGroupInfo &other); + PdfWeightGroupInfo* clone() const; + + void setUncertaintyType(PdfUncertaintyType uncertaintyType) { uncertaintyType_ = uncertaintyType; } + void setHasAlphasVariations(bool hasAlphasVars) { hasAlphasVars_ = hasAlphasVars; } + void setAlphasUpIndex(int alphasUpIndex) { alphasUpIndex_ = alphasUpIndex; } + void setAlphasDownIndex(int alphasDownIndex) { alphasDownIndex_ = alphasDownIndex; } + PdfUncertaintyType uncertaintyType() const { return uncertaintyType_; } + bool hasAlphasVariations() const { return hasAlphasVars_; } + int alphasUpIndex() const { return alphasUpIndex_; } + int alphasDownIndex() const { return alphasDownIndex_; } + }; +} + +#endif // SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h + diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h new file mode 100644 index 0000000000000..4a4c7971f0ab8 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -0,0 +1,64 @@ +#ifndef SimDataFormats_GeneratorProducts_ScaleWeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_ScaleWeightGroupInfo_h + +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + class ScaleWeightGroupInfo : public WeightGroupInfo { + private: + bool isFuncationFormVar_; + size_t icentral; + size_t imuR1muF2; + size_t imuR1muF05; + size_t imuR2muF05; + size_t imuR2muF1; + size_t imuR2muF2; + size_t imuR05muF05; + size_t imuR05muF1; + size_t imuR05muF2; + public: + ScaleWeightGroupInfo() : ScaleWeightGroupInfo("") {} + ScaleWeightGroupInfo(std::string header, std::string name) : + WeightGroupInfo(header, name) { + weightType_ = kScaleWeights; + isFuncationFormVar_ = false; + icentral = 0; + imuR1muF2 = 0; + imuR1muF05 = 0; + imuR2muF05 = 0; + imuR2muF1 = 0; + imuR2muF2 = 0; + imuR2muF05 = 0; + imuR05muF05 = 0; + imuR05muF1 = 0; + imuR05muF2 = 0; + } + ScaleWeightGroupInfo(std::string header) : + ScaleWeightGroupInfo(header, header) { } + ScaleWeightGroupInfo(const ScaleWeightGroupInfo &other) { + copy(other); + } + virtual ~ScaleWeightGroupInfo() override {} + void copy(const ScaleWeightGroupInfo &other); + ScaleWeightGroupInfo* clone() const; + + void setMuRMuFIndex(WeightMetaInfo info, float muR, float muF); + void addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF); + + // Is a variation of the functional form of the dynamic scale + bool isFunctionalFormVariation(); + void setIsFunctionalFormVariation(bool functionalVar) {isFuncationFormVar_ = functionalVar; } + size_t centralIndex() {return icentral; } + size_t muR1muF2Index() { return imuR1muF2; } + size_t muR1muF05Index() { return imuR1muF05; } + size_t muR2muF05Index() { return imuR2muF05; } + size_t muR2muF1Index() { return imuR2muF1; } + size_t muR2muF2Index() { return imuR2muF2; } + size_t muR05muF05Index() { return imuR05muF05; } + size_t muR05muF1Index() { return imuR05muF1; } + size_t muR05muF2Index() { return imuR05muF2; } + }; +} + +#endif + diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h new file mode 100644 index 0000000000000..a815ec762f7f8 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -0,0 +1,77 @@ +#ifndef SimDataFormats_GeneratorProducts_WeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_WeightGroupInfo_h + +/** \class PdfInfo + * + */ +#include +#include +#include + +namespace gen { + struct WeightMetaInfo { + size_t globalIndex; + size_t localIndex; + std::string id; + std::string label; + }; + + enum WeightType { + kPdfWeights, + kScaleWeights, + kMatrixElementWeights, + kUnknownWeights, + kShowerWeights, + }; + + class WeightGroupInfo { + public: + WeightGroupInfo() : WeightGroupInfo("") {} + WeightGroupInfo(std::string header, std::string name): + headerEntry_(header), name_(name), firstId_(-1), lastId_(-1) {} + WeightGroupInfo(std::string header): + headerEntry_(header), name_(header), firstId_(-1), lastId_(-1) {} + WeightGroupInfo(const WeightGroupInfo &other) { + copy(other); + } + WeightGroupInfo& operator=(const WeightGroupInfo &other) { + copy(other); + return *this; + } + virtual ~WeightGroupInfo() {}; + void copy(const WeightGroupInfo &other); + WeightGroupInfo* clone() const; + WeightMetaInfo weightMetaInfo(int weightEntry); + WeightMetaInfo weightMetaInfo(std::string wgtId); + int weightVectorEntry(const std::string& wgtId); + int containsWeight(const std::string& wgtId, int weightEntry); + int weightVectorEntry(const std::string& wgtId, int weightEntry); + void addContainedId(int weightEntry, std::string id, std::string label); + std::vector containedIds() const; + bool indexInRange(int index) const; + + void setName(std::string name) { name_ = name; } + void setHeaderEntry(std::string header) { headerEntry_ = header; } + void setWeightType(WeightType type) { weightType_ = type; } + void setFirstId(int firstId) { firstId_ = firstId; } + void setLastId(int lastId) { lastId_ = lastId; } + + std::string name() const { return name_; } + std::string headerEntry() const { return headerEntry_; } + WeightType weightType() const { return weightType_; } + std::vector idsContained() const { return idsContained_; } + int firstId() const { return firstId_; } + int lastId() const { return lastId_; } + + protected: + std::string headerEntry_; + std::string name_; + WeightType weightType_; + std::vector idsContained_; + int firstId_; + int lastId_; + }; +} + +#endif // SimDataFormats_GeneratorProducts_WeightGroupInfo_h + diff --git a/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc new file mode 100644 index 0000000000000..78c7d858f65f6 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc @@ -0,0 +1,40 @@ +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h" + +LHEWeightInfoProduct::LHEWeightInfoProduct(edm::OwnVector& weightGroups) { + weightGroupsInfo_ = weightGroups; +} + +LHEWeightInfoProduct& LHEWeightInfoProduct::operator=(const LHEWeightInfoProduct &other) { + weightGroupsInfo_ = other.weightGroupsInfo_; + return * this; +} + +LHEWeightInfoProduct& LHEWeightInfoProduct::operator=(LHEWeightInfoProduct &&other) { + weightGroupsInfo_ = std::move(other.weightGroupsInfo_); + return *this; +} + +const edm::OwnVector& LHEWeightInfoProduct::allWeightGroupsInfo() const { + return weightGroupsInfo_; +} + +const gen::WeightGroupInfo& LHEWeightInfoProduct::containingWeightGroupInfo(int index) const { + for (const auto& weightGroup : weightGroupsInfo_) { + if (weightGroup.indexInRange(index)) + return weightGroup; + } + throw std::domain_error("Failed to find containing weight group"); +} + +const gen::WeightGroupInfo& LHEWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { + if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) + throw std::range_error("Weight index out of range!"); + return weightGroupsInfo_[weightGroupIndex]; +} + +void LHEWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo& info) { + weightGroupsInfo_.push_back(info); +} diff --git a/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc new file mode 100644 index 0000000000000..4e0175bf9629c --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc @@ -0,0 +1,15 @@ +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" + +namespace gen { + void PdfWeightGroupInfo::copy(const PdfWeightGroupInfo &other) { + uncertaintyType_ = other.uncertaintyType(); + hasAlphasVars_ = other.hasAlphasVariations(); + alphasUpIndex_ = other.alphasDownIndex(); + alphasDownIndex_ = other.alphasDownIndex(); + WeightGroupInfo::copy(other); + } + + PdfWeightGroupInfo* PdfWeightGroupInfo::clone() const { + return new PdfWeightGroupInfo(*this); + } +} diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc new file mode 100644 index 0000000000000..cb237225cb76f --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -0,0 +1,52 @@ +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include + +namespace gen { + void ScaleWeightGroupInfo::copy(const ScaleWeightGroupInfo &other) { + icentral = centralIndex(); + imuR1muF2 = muR1muF2Index(); + imuR1muF05 = muR1muF05Index(); + imuR2muF05 = muR2muF05Index(); + imuR2muF1 = muR2muF1Index(); + imuR2muF2 = muR2muF2Index(); + imuR2muF05 = muR2muF05Index(); + imuR05muF1 = muR05muF1Index(); + imuR05muF2 = muR05muF2Index(); + WeightGroupInfo::copy(other); + } + + ScaleWeightGroupInfo* ScaleWeightGroupInfo::clone() const { + return new ScaleWeightGroupInfo(*this); + } + + void ScaleWeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF) { + WeightGroupInfo::addContainedId(weightEntry, id, label); + auto metaInfo = weightMetaInfo(weightEntry); + setMuRMuFIndex(metaInfo, muR, muF); + } + + void ScaleWeightGroupInfo::setMuRMuFIndex(WeightMetaInfo info, float muR, float muF) { + if (muR == 0.5 && muF == 0.5) + imuR05muF05 = info.localIndex; + else if (muR == 0.5 && muF == 1.0) + imuR05muF1 = info.localIndex; + else if (muR == 0.5 && muF == 2.0) + imuR05muF2 = info.localIndex; + else if (muR == 1.0 && muF == 0.5) + imuR1muF05 = info.localIndex; + else if (muR == 1.0 && muF == 1.0) + icentral = info.localIndex; + else if (muR == 1.0 && muF == 2.0) + imuR1muF2 = info.localIndex; + else if (muR == 2.0 && muF == 0.5) + imuR2muF05 = info.localIndex; + else if (muR == 2.0 && muF == 1.0) + imuR2muF1 = info.localIndex; + else if (muR == 2.0 && muF == 2.0) + imuR2muF2 = info.localIndex; + else + throw std::invalid_argument("Invalid muF and muR variation is not a factor of two from central value"); + } +} + + diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h new file mode 100644 index 0000000000000..d84b109a9b18b --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h @@ -0,0 +1,16 @@ +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" + +namespace gen { + void PdfWeightGroupInfo::copy(const PdfWeightGroupInfo &other) { + uncertaintyType_ = other.uncertaintyType(); + hasAlphasVars_ = other.hasAlphasVariations(); + alphasUpIndex_ = other.alphasDownIndex(); + alphasDownIndex_ = other.alphasDownIndex(); + WeightGroupInfo::copy(other); + } + + PdfWeightGroupInfo* PdfWeightGroupInfo::clone() const { + return new PdfWeightGroupInfo(*this); + } +} + diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc new file mode 100644 index 0000000000000..a9cbccfdea6f9 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -0,0 +1,86 @@ +#include +#include +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + void WeightGroupInfo::copy(const WeightGroupInfo &other) { + headerEntry_ = other.headerEntry(); + name_ = other.name(); + weightType_ = other.weightType(); + idsContained_ = other.idsContained(); + firstId_ = other.firstId(); + lastId_ = other.lastId(); + } + + WeightGroupInfo* WeightGroupInfo::clone() const { + return new WeightGroupInfo(*this); + } + + WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) { + return idsContained_.at(weightEntry); + } + + WeightMetaInfo WeightGroupInfo::weightMetaInfo(std::string wgtId) { + int weightEntry = weightVectorEntry(wgtId); + return idsContained_.at(weightEntry); + } + + int WeightGroupInfo::weightVectorEntry(const std::string& wgtId) { + return weightVectorEntry(wgtId, 0); + } + + int WeightGroupInfo::containsWeight(const std::string& wgtId, int weightEntry) { + return weightVectorEntry(wgtId, weightEntry) != -1; + } + + int WeightGroupInfo::weightVectorEntry(const std::string& wgtId, int weightEntry) { + int entry = -1; + if (!indexInRange(weightEntry)) { + size_t orderedEntry = weightEntry - firstId_; + if (orderedEntry < idsContained_.size()) + if (idsContained_.at(orderedEntry).id == wgtId) + return orderedEntry; + } + auto it = std::find_if(idsContained_.begin(), idsContained_.end(), + [wgtId] (const WeightMetaInfo& w) { return w.id == wgtId; }); + if (it != idsContained_.end()) + return std::distance(idsContained_.begin(), it); + return entry; + } + + void WeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label="") { + if (firstId_ == -1 || weightEntry < firstId_) { + firstId_ = weightEntry; + // Reset to reflect that indices will be shifted + for (auto& id : idsContained_) + id.localIndex = id.globalIndex - firstId_; + } + if (weightEntry > lastId_) + lastId_ = weightEntry; + + WeightMetaInfo info; + info.globalIndex = weightEntry; + info.localIndex = weightEntry - firstId_; + info.id = id; + info.label = label; + + if (idsContained_.size() < info.localIndex) { + idsContained_.resize(info.localIndex); + idsContained_.insert(idsContained_.begin()+info.localIndex, info); + } + else if (idsContained_.size() == info.localIndex) { + idsContained_.push_back(info); + } + else { + idsContained_.resize(info.localIndex+1); + idsContained_[info.localIndex] = info; + } + } + + std::vector WeightGroupInfo::containedIds() const { return idsContained_; } + + + bool WeightGroupInfo::indexInRange(int index) const { + return (index <= lastId_ && index >= firstId_); + } +} diff --git a/SimDataFormats/GeneratorProducts/src/classes.h b/SimDataFormats/GeneratorProducts/src/classes.h index f4ef658588213..3b31e9b4d7c20 100644 --- a/SimDataFormats/GeneratorProducts/src/classes.h +++ b/SimDataFormats/GeneratorProducts/src/classes.h @@ -8,6 +8,9 @@ #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHEXMLStringProduct.h" #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h" @@ -27,13 +30,14 @@ namespace hepmc_rootio { void add_to_particles_in(HepMC::GenVertex*, HepMC::GenParticle*); void clear_particles_in(HepMC::GenVertex*); - inline void weightcontainer_set_default_names(unsigned int n, - std::map& names) { - std::ostringstream name; - for (HepMC::WeightContainer::size_type count = 0; count < n; ++count) { + inline void weightcontainer_set_default_names(unsigned int n, std::map& names) { + std::ostringstream name; + for ( HepMC::WeightContainer::size_type count = 0; count + + @@ -228,8 +230,17 @@ + + + + + + + + + From 222d8c338ebb0e8b1aede4364d60c5b51baf0d09 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Thu, 15 Aug 2019 19:28:49 -0400 Subject: [PATCH 02/16] Working on parsing integration with scale/pdf weights overhaul of code: now works with tinyxml2 instead of regex --- GeneratorInterface/LHEInterface/BuildFile.xml | 1 + .../interface/LHEWeightGroupReaderHelper.h | 301 ++++++++++++++++++ .../interface/ScaleWeightGroupInfo.h | 58 ++-- .../src/ScaleWeightGroupInfo.cc | 36 +-- .../src/ScaleWeightGroupInfo.h | 16 - .../GeneratorProducts/src/classes_def.xml | 7 + 6 files changed, 356 insertions(+), 63 deletions(-) create mode 100644 GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h delete mode 100644 SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h diff --git a/GeneratorInterface/LHEInterface/BuildFile.xml b/GeneratorInterface/LHEInterface/BuildFile.xml index 6fcd808f731bd..c3bdd135e435e 100644 --- a/GeneratorInterface/LHEInterface/BuildFile.xml +++ b/GeneratorInterface/LHEInterface/BuildFile.xml @@ -12,6 +12,7 @@ + diff --git a/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h b/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h new file mode 100644 index 0000000000000..38315664782aa --- /dev/null +++ b/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h @@ -0,0 +1,301 @@ +#ifndef GeneratorInterface_LHEInterface_LHEWeightGroupReaderHelper_h +#define GeneratorInterface_LHEInterface_LHEWeightGroupReaderHelper_h + +#include +#include +#include +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" + +#include +using namespace tinyxml2; + + +class LHEWeightGroupReaderHelper { +public: + LHEWeightGroupReaderHelper(); + + //// possibly add more versions of this functions for different inputs + void parseLHEFile(std::string filename); + void parseWeightGroupsFromHeader(std::vector lheHeader); + + + edm::OwnVector getWeightGroups() {return weightGroups_;} +private: + void loadAttributeNames(std::string baseName, std::vector altNames ={}); + std::string toLowerCase(const char*); + std::string toLowerCase(const std::string); + std::map getAttributeMap(std::string); + std::string sanitizeText(std::string); + bool isAWeight(std::string); + + // Variables + edm::OwnVector weightGroups_; + std::regex weightGroupStart_; + std::regex weightGroupEnd_; + std::regex weightContent_; + + std::map nameConvMap; +}; + + +std::string +LHEWeightGroupReaderHelper::toLowerCase(const char* name) { + std::string returnStr; + for (size_t i = 0; i < strlen(name); ++i) + returnStr.push_back(tolower(name[i])); + return returnStr; +} + +std::string +LHEWeightGroupReaderHelper::toLowerCase(const std::string name) { + std::string returnStr = name; + transform(name.begin(), name.end(), returnStr.begin(), ::tolower); + return returnStr; + + +} + +void LHEWeightGroupReaderHelper::loadAttributeNames(std::string baseName, std::vector altNames) { + for(auto altname : altNames) { + nameConvMap[altname] = baseName; + } + nameConvMap[baseName] = baseName; +} + +std::string +LHEWeightGroupReaderHelper::sanitizeText(std::string line) { + std::map replaceMap = {{"<", "<"}, {">", ">"}}; + + for(auto pair: replaceMap) { + std::string badText = pair.first; + std::string goodText = pair.second; + while(line.find(badText) != std::string::npos) { + size_t spot = line.find(badText); + line.replace(spot, badText.size(), goodText); + } + } + return line; +} + + +LHEWeightGroupReaderHelper::LHEWeightGroupReaderHelper() { + weightGroupStart_ = std::regex(".*.*\n*"); + weightGroupEnd_ = std::regex(".*.*\n*"); + + std::cout << "Init" << "\n"; + + /// Might change later, order matters and code doesn't pick choices + + // Used for translating different naming convention to a common one + loadAttributeNames("muf", {"facscfact"}); + loadAttributeNames("mur", {"renscfact"}); + loadAttributeNames("id"); + loadAttributeNames("pdf", {"pdf set", "lhapdf", "pdfset"}); + loadAttributeNames("dyn_scale"); + + loadAttributeNames("combine"); + loadAttributeNames("name", {"type"}); + +} + +std::map +LHEWeightGroupReaderHelper::getAttributeMap(std::string line) { + XMLDocument xmlParser; + int error = xmlParser.Parse(line.c_str()); + if (error) { + std::cout << "we have a problem!" << "\n"; + return std::map(); + //do something.... + } + + std::map attMap; + XMLElement* element = xmlParser.FirstChildElement(); + + for( const XMLAttribute* a = element->FirstAttribute(); a; a=a->Next()) { + attMap[nameConvMap[toLowerCase(a->Name())]] = a->Value(); + } + // get stuff from content of tag if it has anything. + // always assume format is AAAAA=( )BBBB ( ) => optional space + if (element->GetText() == nullptr) { + return attMap; + } + // This adds "content: " to the beginning of the content. not sure if its a big deal or? + std::string content = element->GetText(); + attMap["content"] = content; + + std::regex reg("(?:(\\S+)=\\s*(\\S+))"); + std::smatch m; + while(std::regex_search(content, m, reg)) { + std::string key = nameConvMap[toLowerCase(m.str(1))]; + if (attMap[key] != std::string()) { + if (m[2] != attMap[key]) { + std::cout << m.str(2) << " vs " << attMap[key]; + // might do something if content and attribute don't match? + // but need to be careful since some are purposefully different + // eg dyn_scale is described in content but just given a number + } + } + else { + attMap[key] = m.str(2); + } + content = m.suffix().str(); + } + return attMap; + +} + +bool +LHEWeightGroupReaderHelper::isAWeight(std::string line) { + XMLDocument xmlParser; + int error = xmlParser.Parse(line.c_str()); + if (error) { + return false; + //do something.... + } + XMLElement* element = xmlParser.FirstChildElement(); + return element; +} + +// void +// LHEWeightGroupReaderHelper::parseLHEFile(std::string filename) { +// std::ifstream file; +// file.open(filename); + +// std::string line; +// std::smatch matches; +// // TODO: Not sure the weight indexing is right here, this seems to more or less +// // count the lines which isn't quite the goal. TOCHECK! +// int index = 0; +// while(getline(file, line)) { +// if(std::regex_match(line, weightGroupStart_)) { +// std::string name = getMap_testAll(line, {weightGroupInfo})["name"]; + +// //TODO: Fine for now, but in general there should also be a check on the PDF weights, +// // e.g., it could be an unknown weight + +// if(std::regex_match(name, scaleWeightMatch_)) { +// weightGroups_.push_back(new gen::ScaleWeightGroupInfo(line)); +// std::cout << "scale weight" << "\n"; +// } + + +// else +// weightGroups_.push_back(new gen::PdfWeightGroupInfo(line)); + +// /// file weights +// while(getline(file, line) && !std::regex_match(line, weightGroupEnd_)) { +// auto tagsMap = getMap_testAll(line, regexOptions); + +// std::regex_search(line, matches, weightContent_); +// // TODO: Add proper check that it worked +// std::string content = matches[1].str(); + +// auto& group = weightGroups_.back(); +// if (group.weightType() == gen::kScaleWeights) { +// float muR = std::stof(tagsMap["mur"]); +// float muF = std::stof(tagsMap["muf"]); +// auto& scaleGroup = static_cast(group); +// scaleGroup.addContainedId(index, tagsMap["id"], line, muR, muF); +// } +// else +// group.addContainedId(index, tagsMap["id"], line); + +// index++; +// } +// } +// } +// } + +void +LHEWeightGroupReaderHelper::parseWeightGroupsFromHeader(std::vector lheHeader) { + // TODO: Not sure the weight indexing is right here, this seems to more or less + // count the lines which isn't quite the goal. TOCHECK! + int index = 0; + bool foundGroup = false; + + for (std::string headerLine : lheHeader) { + std::cout << "Header line is:" << headerLine; + headerLine = sanitizeText(headerLine); + std::cout << "Header line is:" << weightGroups_.size() << " "<< headerLine; + //TODO: Fine for now, but in general there should also be a check on the PDF weights, + // e.g., it could be an unknown weight + + if (std::regex_match(headerLine, weightGroupStart_)) { + //std::cout << "Adding new group for headerLine" << std::endl; + foundGroup = true; + std::string fullTag = headerLine + ""; + auto groupMap = getAttributeMap(fullTag); + std::string name = groupMap["name"]; + + if(name.find("Central scale variation") != std::string::npos || + name.find("scale_variation") != std::string::npos) { + weightGroups_.push_back(new gen::ScaleWeightGroupInfo(headerLine)); + std::cout << "scale weight" << "\n"; + } + else + weightGroups_.push_back(new gen::PdfWeightGroupInfo(headerLine)); + } + /// file weights + else if (foundGroup && isAWeight(headerLine)) { + //std::cout << "Adding new weight for headerLine" << std::endl; + auto tagsMap = getAttributeMap(headerLine); + for(auto pair: tagsMap) { + std::cout << pair.first << ": " << pair.second << " | "; + } + std::cout << "\n"; + + std::string content = tagsMap["content"]; + if (tagsMap["id"] == std::string()) { + std::cout << "error" << "\n"; + // should do something + } + + auto& group = weightGroups_.back(); + if (group.weightType() == gen::kScaleWeights) { + if (tagsMap["mur"] == std::string() || tagsMap["muf"] == std::string()) { + std::cout << "error" << "\n"; + // something should happen here + continue; + } + float muR = std::stof(tagsMap["mur"]); + float muF = std::stof(tagsMap["muf"]); + std::cout << tagsMap["id"] << " " << muR << " " << muF << " " << content << "\n"; + auto& scaleGroup = static_cast(group); + scaleGroup.addContainedId(index, tagsMap["id"], headerLine, muR, muF); + } + else + group.addContainedId(index, tagsMap["id"], headerLine); + index++; + } + // commented out since code doesn't work with this in.... + // else if(isAWeight(headerLine)) { + // // found header. Don't know what to do with it so just shove it into a new weightgroup for now + // // do minimum work for it + // weightGroups_.push_back(new gen::PdfWeightGroupInfo(headerLine)); + // auto& group = weightGroups_.back(); + // auto tagsMap = getAttributeMap(headerLine); + // group.addContainedId(index, tagsMap["id"], headerLine); + // foundGroup = true; + // index++; + // } + + else if(std::regex_match(headerLine, weightGroupEnd_)) { + foundGroup = false; + } + else { + std::cout << "problem!!!" << "\n"; + } + } +} + + + +#endif + + diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index 4a4c7971f0ab8..179b183c07fd9 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -7,31 +7,31 @@ namespace gen { class ScaleWeightGroupInfo : public WeightGroupInfo { private: bool isFuncationFormVar_; - size_t icentral; - size_t imuR1muF2; - size_t imuR1muF05; - size_t imuR2muF05; - size_t imuR2muF1; - size_t imuR2muF2; - size_t imuR05muF05; - size_t imuR05muF1; - size_t imuR05muF2; + size_t icentral_; + size_t imuR1muF2_; + size_t imuR1muF05_; + size_t imuR2muF05_; + size_t imuR2muF1_; + size_t imuR2muF2_; + size_t imuR05muF05_; + size_t imuR05muF1_; + size_t imuR05muF2_; public: ScaleWeightGroupInfo() : ScaleWeightGroupInfo("") {} ScaleWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { weightType_ = kScaleWeights; isFuncationFormVar_ = false; - icentral = 0; - imuR1muF2 = 0; - imuR1muF05 = 0; - imuR2muF05 = 0; - imuR2muF1 = 0; - imuR2muF2 = 0; - imuR2muF05 = 0; - imuR05muF05 = 0; - imuR05muF1 = 0; - imuR05muF2 = 0; + icentral_ = 0; + imuR1muF2_ = 0; + imuR1muF05_ = 0; + imuR2muF05_ = 0; + imuR2muF1_ = 0; + imuR2muF2_ = 0; + imuR2muF05_ = 0; + imuR05muF05_ = 0; + imuR05muF1_ = 0; + imuR05muF2_ = 0; } ScaleWeightGroupInfo(std::string header) : ScaleWeightGroupInfo(header, header) { } @@ -48,16 +48,16 @@ namespace gen { // Is a variation of the functional form of the dynamic scale bool isFunctionalFormVariation(); void setIsFunctionalFormVariation(bool functionalVar) {isFuncationFormVar_ = functionalVar; } - size_t centralIndex() {return icentral; } - size_t muR1muF2Index() { return imuR1muF2; } - size_t muR1muF05Index() { return imuR1muF05; } - size_t muR2muF05Index() { return imuR2muF05; } - size_t muR2muF1Index() { return imuR2muF1; } - size_t muR2muF2Index() { return imuR2muF2; } - size_t muR05muF05Index() { return imuR05muF05; } - size_t muR05muF1Index() { return imuR05muF1; } - size_t muR05muF2Index() { return imuR05muF2; } - }; + size_t centralIndex() {return icentral_; } + size_t muR1muF2Index() { return imuR1muF2_; } + size_t muR1muF05Index() { return imuR1muF05_; } + size_t muR2muF05Index() { return imuR2muF05_; } + size_t muR2muF1Index() { return imuR2muF1_; } + size_t muR2muF2Index() { return imuR2muF2_; } + size_t muR05muF05Index() { return imuR05muF05_; } + size_t muR05muF1Index() { return imuR05muF1_; } + size_t muR05muF2Index() { return imuR05muF2_; } + }_; } #endif diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc index cb237225cb76f..5d2e392d89164 100644 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -3,15 +3,15 @@ namespace gen { void ScaleWeightGroupInfo::copy(const ScaleWeightGroupInfo &other) { - icentral = centralIndex(); - imuR1muF2 = muR1muF2Index(); - imuR1muF05 = muR1muF05Index(); - imuR2muF05 = muR2muF05Index(); - imuR2muF1 = muR2muF1Index(); - imuR2muF2 = muR2muF2Index(); - imuR2muF05 = muR2muF05Index(); - imuR05muF1 = muR05muF1Index(); - imuR05muF2 = muR05muF2Index(); + icentral_ = centralIndex(); + imuR1muF2_ = muR1muF2Index(); + imuR1muF05_ = muR1muF05Index(); + imuR2muF05_ = muR2muF05Index(); + imuR2muF1_ = muR2muF1Index(); + imuR2muF2_ = muR2muF2Index(); + imuR2muF05_ = muR2muF05Index(); + imuR05muF1_ = muR05muF1Index(); + imuR05muF2_ = muR05muF2Index(); WeightGroupInfo::copy(other); } @@ -27,23 +27,23 @@ namespace gen { void ScaleWeightGroupInfo::setMuRMuFIndex(WeightMetaInfo info, float muR, float muF) { if (muR == 0.5 && muF == 0.5) - imuR05muF05 = info.localIndex; + imuR05muF05_ = info.localIndex; else if (muR == 0.5 && muF == 1.0) - imuR05muF1 = info.localIndex; + imuR05muF1_ = info.localIndex; else if (muR == 0.5 && muF == 2.0) - imuR05muF2 = info.localIndex; + imuR05muF2_ = info.localIndex; else if (muR == 1.0 && muF == 0.5) - imuR1muF05 = info.localIndex; + imuR1muF05_ = info.localIndex; else if (muR == 1.0 && muF == 1.0) - icentral = info.localIndex; + icentral_ = info.localIndex; else if (muR == 1.0 && muF == 2.0) - imuR1muF2 = info.localIndex; + imuR1muF2_ = info.localIndex; else if (muR == 2.0 && muF == 0.5) - imuR2muF05 = info.localIndex; + imuR2muF05_ = info.localIndex; else if (muR == 2.0 && muF == 1.0) - imuR2muF1 = info.localIndex; + imuR2muF1_ = info.localIndex; else if (muR == 2.0 && muF == 2.0) - imuR2muF2 = info.localIndex; + imuR2muF2_ = info.localIndex; else throw std::invalid_argument("Invalid muF and muR variation is not a factor of two from central value"); } diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h deleted file mode 100644 index d84b109a9b18b..0000000000000 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" - -namespace gen { - void PdfWeightGroupInfo::copy(const PdfWeightGroupInfo &other) { - uncertaintyType_ = other.uncertaintyType(); - hasAlphasVars_ = other.hasAlphasVariations(); - alphasUpIndex_ = other.alphasDownIndex(); - alphasDownIndex_ = other.alphasDownIndex(); - WeightGroupInfo::copy(other); - } - - PdfWeightGroupInfo* PdfWeightGroupInfo::clone() const { - return new PdfWeightGroupInfo(*this); - } -} - diff --git a/SimDataFormats/GeneratorProducts/src/classes_def.xml b/SimDataFormats/GeneratorProducts/src/classes_def.xml index 604d4cd31250e..34a91335187d4 100644 --- a/SimDataFormats/GeneratorProducts/src/classes_def.xml +++ b/SimDataFormats/GeneratorProducts/src/classes_def.xml @@ -232,12 +232,19 @@ + + + + + + + From 4cb142f8eb079f38d8ae92f6207ba8763c5e62dd Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sat, 15 Jan 2022 23:33:12 +0100 Subject: [PATCH 03/16] New WeightGroups, improved parsing with helper class Dylan's improvements of weight parsing changed LHEsource so it compiles, running tests now added scientific notation for numbers so values are correct added a few more test statements. Need to think of future needs Add testing suite (will remove/squash commits right before merge) Change pdfSetsInfo to be read in from LHAPDF path Still lingering question of how to decide pdf type This can be resolved in the new function "setupPdfSetsInfo" Add check if orphan weight is pdf and fix xml tag swap (needs review) Allow reading '>' as '>' and fix bug with first weight w/o group As for the first weight error: if the first weight doesn't have a weight group, the code would not add it to the list of weights because of currentGroupName and the first weight both having a trivial "" as their name. Thats the reason for the currentGroupName being set to "None" for initialization Fix space issue in regex and moved unchaning variables outside for Add pdfgroup splitting. To do this, needed LHAPDF requirements clang format Fix parsing issue with pdfweights in certain files those files being "DrellYan_LO_MGMLMv233_2016_weightInfo.txt" and "DrellYan_NLO_MGFXFXv242_2017_weightInfo.txt", Remove PdfSetInfo in favor of LHAPDF library Refactor pdfweight so pdfweights are always split May put flags needed for the splitting. Only impliemented in LHEWeightHelper Simplify ScaleWeight structure in anticipation of dyn weight changes Add dynWeights to scaleWeightInfo. Can improve code (basic refactor) Add orphaned pdf weight into scale weight missing central index not my finest work. Definitely could have improvements, but technically works Add Pdf info to pdfWeights (size, type) & check of size consistency More testing scripts, better error handling Fix orphaned central scale problem. was resizing to 1 (not great) Simplify logic of adding to make less opaque Move weight building logic to WeightHelper so GEN can use it Add basic GenLevel parsing. Works on ZGTo2NuG test file Add PartonShower parsing for GenWeights Change PartonShower filename to match h file More error handling, parsing improvements Add option for raising expection if XML is not valid Fix parsing of PartonShower name in GenWeights Add basic MEParam weight functionality Allow for general adding of params to vector Also fixed formating with clang Simplifications for PS and ME weight groups --- DataFormats/NanoAOD/src/classes_def.xml | 3 + GeneratorInterface/Core/BuildFile.xml | 1 + .../Core/interface/GenWeightHelper.h | 26 + .../Core/interface/LHEWeightHelper.h | 34 + .../Core/interface/WeightHelper.h | 82 +++ GeneratorInterface/Core/plugins/BuildFile.xml | 1 + .../Core/plugins/GenWeightProductProducer.cc | 90 +++ .../Core/plugins/LHEWeightProductProducer.cc | 132 ++++ .../Core/src/GenWeightHelper.cc | 55 ++ .../Core/src/LHEWeightHelper.cc | 150 ++++ GeneratorInterface/Core/src/WeightHelper.cc | 348 ++++++++++ .../Core/test/dumpWeightInfo.py | 44 ++ .../LHEInterface/plugins/BuildFile.xml | 3 + .../plugins/GenWeightsTableProducer.cc | 655 +++++------------- .../NanoAOD/plugins/NanoAODOutputModule.cc | 365 +++++----- .../NanoAOD/plugins/TableOutputBranches.cc | 28 +- .../NanoAOD/plugins/TableOutputBranches.h | 16 +- PhysicsTools/NanoAOD/python/nano_cff.py | 365 ++++------ PhysicsTools/NanoAOD/python/nanogen_cff.py | 219 +++--- PhysicsTools/NanoAOD/test/testNanoWeights.py | 34 + .../GeneratorProducts/BuildFile.xml | 1 + .../interface/GenWeightInfoProduct.h | 48 ++ .../interface/GenWeightProduct.h | 52 ++ .../interface/MEParamWeightGroupInfo.h | 33 + .../interface/PartonShowerWeightGroupInfo.h | 39 ++ .../interface/PdfWeightGroupInfo.h | 92 ++- .../interface/ScaleWeightGroupInfo.h | 120 ++-- .../interface/UnknownWeightGroupInfo.h | 24 + .../interface/WeightGroupInfo.h | 143 ++-- .../src/GenWeightInfoProduct.cc | 93 +++ .../src/MEParamWeightGroupInfo.cc | 27 + .../src/PartonShowerWeightGroupInfo.cc | 22 + .../src/PdfWeightGroupInfo.cc | 38 +- .../src/ScaleWeightGroupInfo.cc | 137 ++-- .../src/UnknownWeightGroupInfo.cc | 5 + .../GeneratorProducts/src/WeightGroupInfo.cc | 158 +++-- .../GeneratorProducts/src/classes.h | 22 +- .../GeneratorProducts/src/classes_def.xml | 26 +- 38 files changed, 2382 insertions(+), 1349 deletions(-) create mode 100644 GeneratorInterface/Core/interface/GenWeightHelper.h create mode 100644 GeneratorInterface/Core/interface/LHEWeightHelper.h create mode 100644 GeneratorInterface/Core/interface/WeightHelper.h create mode 100644 GeneratorInterface/Core/plugins/GenWeightProductProducer.cc create mode 100644 GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc create mode 100644 GeneratorInterface/Core/src/GenWeightHelper.cc create mode 100644 GeneratorInterface/Core/src/LHEWeightHelper.cc create mode 100644 GeneratorInterface/Core/src/WeightHelper.cc create mode 100644 GeneratorInterface/Core/test/dumpWeightInfo.py create mode 100644 PhysicsTools/NanoAOD/test/testNanoWeights.py create mode 100644 SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h create mode 100644 SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h create mode 100644 SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h create mode 100644 SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc create mode 100644 SimDataFormats/GeneratorProducts/src/MEParamWeightGroupInfo.cc create mode 100644 SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc create mode 100644 SimDataFormats/GeneratorProducts/src/UnknownWeightGroupInfo.cc diff --git a/DataFormats/NanoAOD/src/classes_def.xml b/DataFormats/NanoAOD/src/classes_def.xml index 58f08dfc7e9f8..e8645de0f822c 100644 --- a/DataFormats/NanoAOD/src/classes_def.xml +++ b/DataFormats/NanoAOD/src/classes_def.xml @@ -10,6 +10,9 @@ + + + diff --git a/GeneratorInterface/Core/BuildFile.xml b/GeneratorInterface/Core/BuildFile.xml index 2d3cd1bb76d7f..eb5953775844c 100644 --- a/GeneratorInterface/Core/BuildFile.xml +++ b/GeneratorInterface/Core/BuildFile.xml @@ -10,6 +10,7 @@ + diff --git a/GeneratorInterface/Core/interface/GenWeightHelper.h b/GeneratorInterface/Core/interface/GenWeightHelper.h new file mode 100644 index 0000000000000..1a1724b36792e --- /dev/null +++ b/GeneratorInterface/Core/interface/GenWeightHelper.h @@ -0,0 +1,26 @@ +#ifndef GeneratorInterface_Core_GenWeightHelper_h +#define GeneratorInterface_Core_GenWeightHelper_h + +#include +#include +#include +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoProduct.h" +#include "GeneratorInterface/Core/interface/WeightHelper.h" + +#include + +namespace gen { + class GenWeightHelper : public WeightHelper { + public: + GenWeightHelper(); + void parseWeightGroupsFromNames(std::vector weightNames); + }; +} // namespace gen + +#endif diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h new file mode 100644 index 0000000000000..f29aaf5f2f7df --- /dev/null +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -0,0 +1,34 @@ +#ifndef GeneratorInterface_Core_LHEWeightHelper_h +#define GeneratorInterface_Core_LHEWeightHelper_h + +#include +#include +#include +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" +#include "GeneratorInterface/Core/interface/WeightHelper.h" + +#include + +namespace gen { + class LHEWeightHelper : public WeightHelper { + public: + LHEWeightHelper() : WeightHelper(){}; + void setHeaderLines(std::vector headerLines); + void parseWeights(); + bool isConsistent(); + void swapHeaders(); + void setFailIfInvalidXML(bool value) { failIfInvalidXML_ = value; } + private: + std::vector headerLines_; + bool failIfInvalidXML_ = false; + }; +} // namespace gen + +#endif diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h new file mode 100644 index 0000000000000..aea58eb6d587f --- /dev/null +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -0,0 +1,82 @@ +#ifndef GeneratorInterface_LHEInterface_WeightHelper_h +#define GeneratorInterface_LHEInterface_WeightHelper_h + +#include "DataFormats/Common/interface/OwnVector.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h" +#include "LHAPDF/LHAPDF.h" +#include +#include +#include + +namespace gen { + struct ParsedWeight { + std::string id; + int index; + std::string groupname; + std::string content; + std::unordered_map attributes; + int wgtGroup_idx; + }; + + class WeightHelper { + public: + WeightHelper(); + edm::OwnVector weightGroups() { return weightGroups_; } + std::unique_ptr weightProduct(std::vector, float w0); + std::unique_ptr weightProduct(std::vector, float w0); + void setModel(std::string model) { model_ = model; } + int addWeightToProduct( + std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex); + int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); + + protected: + // TODO: Make this only print from one thread a la + // https://github.com/kdlong/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 + bool debug_ = true; + std::string model_; + std::vector parsedWeights_; + std::map currWeightAttributeMap_; + std::map currGroupAttributeMap_; + edm::OwnVector weightGroups_; + bool isScaleWeightGroup(const ParsedWeight& weight); + bool isMEParamWeightGroup(const ParsedWeight& weight); + bool isPdfWeightGroup(const ParsedWeight& weight); + bool isPartonShowerWeightGroup(const ParsedWeight& weight); + bool isOrphanPdfWeightGroup(ParsedWeight& weight); + void updateScaleInfo(const ParsedWeight& weight, int index); + void updateMEParamInfo(const ParsedWeight& weight, int index); + void updatePdfInfo(const ParsedWeight& weight, int index); + void cleanupOrphanCentralWeight(); + + int lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup); + std::string searchAttributes(const std::string& label, const ParsedWeight& weight) const; + std::string searchAttributesByTag(const std::string& label, const ParsedWeight& weight) const; + std::string searchAttributesByRegex(const std::string& label, const ParsedWeight& weight) const; + + // Possible names for the same thing + const std::unordered_map> attributeNames_ = { + {"muf", {"muF", "MUF", "muf", "facscfact"}}, + {"mur", {"muR", "MUR", "mur", "renscfact"}}, + {"pdf", {"PDF", "PDF set", "lhapdf", "pdf", "pdf set", "pdfset"}}, + {"dyn", {"DYN_SCALE"}}, + {"dyn_name", {"dyn_scale_choice"}}, + {"up", {"_up", "Hi"}}, + {"down", {"_dn", "Lo"}}, + {"me_variation", {"mass", "sthw2", "width"}}, + }; + void printWeights(); + std::unique_ptr buildGroup(ParsedWeight& weight); + void buildGroups(); + std::string searchString(const std::string& label, const std::string& name); + }; +} // namespace gen + +#endif diff --git a/GeneratorInterface/Core/plugins/BuildFile.xml b/GeneratorInterface/Core/plugins/BuildFile.xml index 40c9678cb4bc6..73ee3894b576d 100644 --- a/GeneratorInterface/Core/plugins/BuildFile.xml +++ b/GeneratorInterface/Core/plugins/BuildFile.xml @@ -5,6 +5,7 @@ + diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc new file mode 100644 index 0000000000000..a69756f2b2aea --- /dev/null +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDProducer.h" +#include "FWCore/Framework/interface/LuminosityBlock.h" + +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/FileInPath.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" + +#include "GeneratorInterface/Core/interface/GenWeightHelper.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include + +class GenWeightProductProducer : public edm::one::EDProducer { +public: + explicit GenWeightProductProducer(const edm::ParameterSet& iConfig); + ~GenWeightProductProducer() override; + +private: + std::vector weightNames_; + gen::GenWeightHelper weightHelper_; + edm::EDGetTokenT genLumiInfoToken_; + edm::EDGetTokenT genEventToken_; + const edm::EDGetTokenT genLumiInfoHeadTag_; + + void produce(edm::Event&, const edm::EventSetup&) override; + void beginLuminosityBlockProduce(edm::LuminosityBlock& lb, edm::EventSetup const& c) override; +}; + +// +// constructors and destructor +// +GenWeightProductProducer::GenWeightProductProducer(const edm::ParameterSet& iConfig) + : genLumiInfoToken_(consumes(iConfig.getParameter("genInfo"))), + genEventToken_(consumes(iConfig.getParameter("genInfo"))), + genLumiInfoHeadTag_( + mayConsume(iConfig.getParameter("genLumiInfoHeader"))) { + produces(); + produces(); +} + +GenWeightProductProducer::~GenWeightProductProducer() {} + +// ------------ method called to produce the data ------------ +void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + edm::Handle genEventInfo; + iEvent.getByToken(genEventToken_, genEventInfo); + + float centralWeight = genEventInfo->weights().size() > 0 ? genEventInfo->weights().at(0) : 1.; + auto weightProduct = weightHelper_.weightProduct(genEventInfo->weights(), centralWeight); + iEvent.put(std::move(weightProduct)); +} + +void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) { + edm::Handle genLumiInfoHead; + iLumi.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); + if (genLumiInfoHead.isValid()) { + std::string label = genLumiInfoHead->configDescription(); + boost::replace_all(label, "-", "_"); + weightHelper_.setModel(label); + } + + edm::Handle genLumiInfoHandle; + iLumi.getByToken(genLumiInfoToken_, genLumiInfoHandle); + + weightNames_ = genLumiInfoHandle->weightNames(); + weightHelper_.parseWeightGroupsFromNames(weightNames_); + + auto weightInfoProduct = std::make_unique(); + for (auto& weightGroup : weightHelper_.weightGroups()) { + weightInfoProduct->addWeightGroupInfo(weightGroup.clone()); + } + iLumi.put(std::move(weightInfoProduct)); +} + +DEFINE_FWK_MODULE(GenWeightProductProducer); diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc new file mode 100644 index 0000000000000..f06d68d5e81f4 --- /dev/null +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDProducer.h" +#include "FWCore/Framework/interface/LuminosityBlock.h" + +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/FileInPath.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" + +#include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h" +#include "GeneratorInterface/LHEInterface/interface/LHEEvent.h" +#include "GeneratorInterface/Core/interface/LHEWeightHelper.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/transform.h" + +class LHEWeightProductProducer : public edm::one::EDProducer { +public: + explicit LHEWeightProductProducer(const edm::ParameterSet& iConfig); + ~LHEWeightProductProducer() override; + +private: + gen::LHEWeightHelper weightHelper_; + std::vector lheLabels_; + std::vector> lheEventTokens_; + std::vector> lheRunInfoTokens_; + std::vector> lheWeightInfoTokens_; + bool foundWeightProduct_ = false; + bool hasLhe_ = false; + + void produce(edm::Event&, const edm::EventSetup&) override; + void beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) override; + void beginRun(edm::Run const& run, edm::EventSetup const& es) override; + void endRun(edm::Run const& run, edm::EventSetup const& es) override; +}; + +// TODO: Accept a vector of strings (source, externalLHEProducer) exit if neither are found +LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iConfig) + : lheLabels_(iConfig.getParameter>("lheSourceLabels")), + lheEventTokens_(edm::vector_transform(lheLabels_, + [this](const std::string& tag) { return mayConsume(tag); })), + lheRunInfoTokens_(edm::vector_transform(lheLabels_, + [this](const std::string& tag) { return mayConsume(tag); })), + lheWeightInfoTokens_(edm::vector_transform(lheLabels_, + [this](const std::string& tag) { return mayConsume(tag); })) { + produces(); + produces(); + weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); +} + +LHEWeightProductProducer::~LHEWeightProductProducer() {} + +// ------------ method called to produce the data ------------ +void LHEWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + if (foundWeightProduct_ || !hasLhe_) + return; + + edm::Handle lheEventInfo; + for (auto& token : lheEventTokens_) { + iEvent.getByToken(token, lheEventInfo); + if (lheEventInfo.isValid()) { + break; + } + } + + auto weightProduct = weightHelper_.weightProduct(lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); + iEvent.put(std::move(weightProduct)); +} + +void LHEWeightProductProducer::beginRun(edm::Run const& run, edm::EventSetup const& es) { + edm::Handle lheRunInfoHandle; + for (auto& label : lheLabels_) { + run.getByLabel(label, lheRunInfoHandle); + if (lheRunInfoHandle.isValid()) { + hasLhe_ = true; + break; + } + } + if (!hasLhe_) + return; + + + typedef std::vector::const_iterator header_cit; + LHERunInfoProduct::Header headerWeightInfo; + for (header_cit iter = lheRunInfoHandle->headers_begin(); iter != lheRunInfoHandle->headers_end(); iter++) { + if (iter->tag() == "initrwgt") { + headerWeightInfo = *iter; + break; + } + } + + weightHelper_.setHeaderLines(headerWeightInfo.lines()); +} + +void LHEWeightProductProducer::endRun(edm::Run const& run, edm::EventSetup const& es) {} + +void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) { + edm::Handle lheWeightInfoHandle; + + for (auto& token : lheWeightInfoTokens_) { + lumi.getByToken(token, lheWeightInfoHandle); + if (lheWeightInfoHandle.isValid()) { + foundWeightProduct_ = true; + return; + } + } + + if (!hasLhe_) + return; + + weightHelper_.parseWeights(); + + auto weightInfoProduct = std::make_unique(); + for (auto& weightGroup : weightHelper_.weightGroups()) { + weightInfoProduct->addWeightGroupInfo(weightGroup.clone()); + } + lumi.put(std::move(weightInfoProduct)); +} + +DEFINE_FWK_MODULE(LHEWeightProductProducer); diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc new file mode 100644 index 0000000000000..ccc7f0b99b1a3 --- /dev/null +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -0,0 +1,55 @@ +#include "GeneratorInterface/Core/interface/GenWeightHelper.h" +#include + +using namespace tinyxml2; + +namespace gen { + GenWeightHelper::GenWeightHelper() {} + + void GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames) { + parsedWeights_.clear(); + int index = 0; + int groupIndex = -1; + int showerGroupIndex = -1; + std::string curGroup = ""; + // If size is 1, it's just the central weight + if (weightNames.size() <= 1) + return; + + for (std::string weightName : weightNames) { + if (weightName.find("LHE") != std::string::npos) { + // Parse as usual, this is the SUSY workflow + std::vector info; + boost::split(info, weightName, boost::is_any_of(",")); + std::unordered_map attributes; + std::string text = info.back(); + info.pop_back(); + for (auto i : info) { + std::vector subInfo; + boost::split(subInfo, i, boost::is_any_of("=")); + if (subInfo.size() == 2) { + attributes[boost::algorithm::trim_copy(subInfo[0])] = boost::algorithm::trim_copy(subInfo[1]); + } + } + if (attributes["group"] != curGroup) { + curGroup = attributes["group"]; + groupIndex++; + } + // Gen Weights can't have an ID, because they are just a std::vector in the event + attributes["id"] = ""; + parsedWeights_.push_back({attributes["id"], index, curGroup, text, attributes, groupIndex}); + } else { + parsedWeights_.push_back( + {"", index, weightName, weightName, std::unordered_map(), groupIndex}); + if (isPartonShowerWeightGroup(parsedWeights_.back())) { + if (showerGroupIndex < 0) + showerGroupIndex = ++groupIndex; + parsedWeights_.back().wgtGroup_idx = showerGroupIndex; // all parton showers are grouped together + } + } + index++; + } + buildGroups(); + printWeights(); + } +} // namespace gen diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc new file mode 100644 index 0000000000000..e9a7515d123e3 --- /dev/null +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -0,0 +1,150 @@ +#include "GeneratorInterface/Core/interface/LHEWeightHelper.h" +#include +#include +#include +#include + +using namespace tinyxml2; + +namespace gen { + void LHEWeightHelper::setHeaderLines(std::vector headerLines) { + headerLines_ = headerLines; + } + + void LHEWeightHelper::parseWeights() { + parsedWeights_.clear(); + + if (!isConsistent() && failIfInvalidXML_) { + throw std::runtime_error( + "XML in LHE is not consistent: Most likely, tags were swapped.\n" + "To turn on fault fixing, use 'setFailIfInvalidXML(false)'\n" + "WARNING: the tag swapping may lead to weights associated with the incorrect group"); + } else if (!isConsistent()) { + swapHeaders(); + } + + tinyxml2::XMLDocument xmlDoc; + std::string fullHeader = boost::algorithm::join(headerLines_, ""); + if (debug_) + std::cout << "Full header is \n" << fullHeader << std::endl; + + int xmlError = xmlDoc.Parse(fullHeader.c_str()); + // in case of > instead of < + if (xmlError != 0) { + boost::replace_all(fullHeader, "<", "<"); + boost::replace_all(fullHeader, ">", ">"); + xmlError = xmlDoc.Parse(fullHeader.c_str()); + } + // error persists (how to handle error?) + if (xmlError != 0) { + std::cerr << "WARNING: Error in parsing XML of LHE weight header!" << std::endl; + xmlDoc.PrintError(); + if (failIfInvalidXML_) + throw std::runtime_error("XML is unreadable because of above error."); + else + return; + } + + std::vector nameAlts_ = {"name", "type"}; + + int weightIndex = 0; + int groupIndex = 0; + for (auto* e = xmlDoc.RootElement(); e != nullptr; e = e->NextSiblingElement()) { + if (debug_) + std::cout << "XML element is " << e->Name() << std::endl; + std::string groupName = ""; + if (strcmp(e->Name(), "weight") == 0) { + if (debug_) + std::cout << "Found weight unmatched to group\n"; + // we are here if there is a weight that does not belong to any group + // TODO: Recylce code better between here when a weight is found in a group + std::string text = ""; + if (e->GetText()) { + text = e->GetText(); + } + std::unordered_map attributes; + for (auto* att = e->FirstAttribute(); att != nullptr; att = att->Next()) + attributes[att->Name()] = att->Value(); + parsedWeights_.push_back({e->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); + } else if (strcmp(e->Name(), "weightgroup") == 0) { + if (debug_) + std::cout << "Found a weight group.\n"; + // to deal wiht files with "id" instead of "name" + for (auto nameAtt : nameAlts_) { + if (e->Attribute(nameAtt.c_str())) { + groupName = e->Attribute(nameAtt.c_str()); + break; + } + } + if (groupName.empty()) { + // TODO: Need a better failure mode + throw std::runtime_error("couldn't find groupname"); + } + // May remove this, very specific error + if (groupName.find(".") != std::string::npos) + groupName.erase(groupName.find("."), groupName.size()); + + for (auto* inner = e->FirstChildElement("weight"); inner != nullptr; + inner = inner->NextSiblingElement("weight")) { + // we are here if there is a weight in a weightgroup + if (debug_) + std::cout << "Found a weight inside the group. Content is " << inner->GetText() << " group index is " << groupIndex << std::endl; + std::string text = ""; + if (inner->GetText()) + text = inner->GetText(); + std::unordered_map attributes; + for (auto* att = inner->FirstAttribute(); att != nullptr; att = att->Next()) + attributes[att->Name()] = att->Value(); + parsedWeights_.push_back({inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); + } + } else + std::cout << "Found an invalid entry\n"; + groupIndex++; + } + buildGroups(); + } + + bool LHEWeightHelper::isConsistent() { + int curLevel = 0; + + for (auto line : headerLines_) { + if (line.find("") != std::string::npos) { + curLevel--; + if (curLevel != 0) { + return false; + } + } + } + return curLevel == 0; + } + + void LHEWeightHelper::swapHeaders() { + int curLevel = 0; + int open = -1; + int close = -1; + for (size_t idx = 0; idx < headerLines_.size(); idx++) { + std::string line = headerLines_[idx]; + if (line.find("") != std::string::npos) { + curLevel--; + if (curLevel != 0) { + close = idx; + } + } + if (open > -1 && close > -1) { + std::swap(headerLines_[open], headerLines_[close]); + open = -1; + close = -1; + } + } + } +} // namespace gen diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc new file mode 100644 index 0000000000000..0b670f015964a --- /dev/null +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -0,0 +1,348 @@ +#include "GeneratorInterface/Core/interface/WeightHelper.h" +#include + +namespace gen { + WeightHelper::WeightHelper() { model_ = ""; } + + bool WeightHelper::isScaleWeightGroup(const ParsedWeight& weight) { + return (weight.groupname.find("scale_variation") != std::string::npos || + weight.groupname.find("Central scale variation") != std::string::npos); + } + + bool WeightHelper::isPdfWeightGroup(const ParsedWeight& weight) { + const std::string& name = weight.groupname; + + if (name.find("PDF_variation") != std::string::npos) + return true; + return LHAPDF::lookupLHAPDFID(name) != -1; + } + + bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) { + const std::string& name = boost::to_lower_copy(weight.groupname); + // But "Nominal" and "Baseline" weights in the PS group + return name.find("isr") != std::string::npos || name.find("fsr") != std::string::npos || + name.find("nominal") != std::string::npos || name.find("baseline") != std::string::npos; + } + + bool WeightHelper::isOrphanPdfWeightGroup(ParsedWeight& weight) { + std::string lhaidText = searchAttributes("pdf", weight); + try { + auto pairLHA = LHAPDF::lookupPDF(stoi(lhaidText)); + // require pdf set to exist and it to be the first entry (ie 0) + // possibly change this requirement + if (!pairLHA.first.empty() && pairLHA.second == 0) { + weight.groupname = std::string(pairLHA.first); + return true; + } + } catch (...) { + return false; + } + return false; + } + + bool WeightHelper::isMEParamWeightGroup(const ParsedWeight& weight) { + return (weight.groupname.find("mg_reweighting") != std::string::npos || + weight.groupname.find("variation") != std::string::npos); + // variation used for blanket of all variations, might need to change + } + + std::string WeightHelper::searchAttributes(const std::string& label, const ParsedWeight& weight) const { + std::string attribute = searchAttributesByTag(label, weight); + return attribute.empty() ? searchAttributesByRegex(label, weight) : attribute; + attribute = searchAttributesByRegex(label, weight); + } + + std::string WeightHelper::searchAttributesByTag(const std::string& label, const ParsedWeight& weight) const { + auto& attributes = weight.attributes; + for (const auto& lab : attributeNames_.at(label)) { + if (attributes.find(lab) != attributes.end()) { + return boost::algorithm::trim_copy_if(attributes.at(lab), boost::is_any_of("\"")); + } + } + return ""; + } + + std::string WeightHelper::searchString(const std::string& label, const std::string& name) { + for (const auto& lab : attributeNames_.at(label)) { + if (name.find(lab) != std::string::npos) + return name.substr(0, name.find(lab)); + } + return ""; + } + + std::string WeightHelper::searchAttributesByRegex(const std::string& label, const ParsedWeight& weight) const { + auto& content = weight.content; + std::smatch match; + for (const auto& lab : attributeNames_.at(label)) { + std::regex floatExpr(lab + "\\s*=\\s*([0-9.]+(?:[eE][+-]?[0-9]+)?)"); + std::regex strExpr(lab + "\\s*=\\s*([^=]+)"); + if (std::regex_search(content, match, floatExpr)) { + return boost::algorithm::trim_copy(match.str(1)); + } else if (std::regex_search(content, match, strExpr)) { + return boost::algorithm::trim_copy(match.str(1)); + } + } + return ""; + } + + void WeightHelper::updateScaleInfo(const ParsedWeight& weight, int index) { + auto& group = weightGroups_[index]; + auto& scaleGroup = dynamic_cast(group); + std::string muRText = searchAttributes("mur", weight); + std::string muFText = searchAttributes("muf", weight); + + if (muRText.empty() || muFText.empty()) { + scaleGroup.setIsWellFormed(false); + return; + } + + try { + float muR = std::stof(muRText); + float muF = std::stof(muFText); + std::string dynNumText = searchAttributes("dyn", weight); + if (dynNumText.empty()) { + scaleGroup.setMuRMuFIndex(weight.index, weight.id, muR, muF); + } else { + std::string dynType = searchAttributes("dyn_name", weight); + int dynNum = std::stoi(dynNumText); + scaleGroup.setMuRMuFIndex(weight.index, weight.id, muR, muF, dynNum, dynType); + } + } catch (std::invalid_argument& e) { + scaleGroup.setIsWellFormed(false); + } + if (scaleGroup.lhaid() == -1) { + std::string lhaidText = searchAttributes("pdf", weight); + try { + scaleGroup.setLhaid(std::stoi(lhaidText)); + } catch (std::invalid_argument& e) { + scaleGroup.setLhaid(-2); + } + } + } + + int WeightHelper::lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup) { + std::string lhaidText = searchAttributes("pdf", weight); + if (!lhaidText.empty()) { + try { + return std::stoi(lhaidText); + } catch (std::invalid_argument& e) { + pdfGroup.setIsWellFormed(false); + } + } else if (pdfGroup.lhaIds().size() > 0) { + return pdfGroup.lhaIds().back() + 1; + } else { + return LHAPDF::lookupLHAPDFID(weight.groupname); + } + return -1; + } + + void WeightHelper::updatePdfInfo(const ParsedWeight& weight, int index) { + auto& pdfGroup = dynamic_cast(weightGroups_[index]); + int lhaid = lhapdfId(weight, pdfGroup); + if (pdfGroup.parentLhapdfId() < 0) { + int parentId = lhaid - LHAPDF::lookupPDF(lhaid).second; + pdfGroup.setParentLhapdfInfo(parentId); + pdfGroup.setUncertaintyType(gen::kUnknownUnc); + + std::string description = ""; + if (pdfGroup.uncertaintyType() == gen::kHessianUnc) + description += "Hessian "; + else if (pdfGroup.uncertaintyType() == gen::kMonteCarloUnc) + description += "Monte Carlo "; + description += "Uncertainty sets for LHAPDF set " + LHAPDF::lookupPDF(parentId).first; + description += " with LHAID = " + std::to_string(parentId); + description += "; "; + + pdfGroup.appendDescription(description); + } + // after setup parent info, add lhaid + pdfGroup.addLhaid(lhaid); + } + + // TODO: Could probably recycle this code better + std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { + auto weightProduct = std::make_unique(w0); + weightProduct->setNumWeightSets(weightGroups_.size()); + int weightGroupIndex = 0; + // This happens if there are no PS weights, so the weights vector contains only the central GEN weight. + // Just add an empty product + if (weights.size() > 1) { + for (unsigned int i = 0; i < weights.size(); i++) { + std::string id = std::to_string(i); + addWeightToProduct(weightProduct, weights.at(i), id, i, weightGroupIndex); + } + } + return std::move(weightProduct); + } + + void WeightHelper::cleanupOrphanCentralWeight() { + std::vector removeList; + for (auto it = weightGroups_.begin(); it < weightGroups_.end(); it++) { + if (it->weightType() != WeightType::kScaleWeights) + continue; + auto& baseWeight = dynamic_cast(*it); + if (baseWeight.containsCentralWeight()) + continue; + for (auto subIt = weightGroups_.begin(); subIt < it; subIt++) { + if (subIt->weightType() != WeightType::kPdfWeights) + continue; + auto& subWeight = dynamic_cast(*subIt); + if (subWeight.nIdsContained() == 1 && subWeight.parentLhapdfId() == baseWeight.lhaid()) { + removeList.push_back(subIt - weightGroups_.begin()); + auto info = subWeight.idsContained().at(0); + baseWeight.addContainedId(info.globalIndex, info.id, info.label, 1, 1); + } + } + } + std::sort(removeList.begin(), removeList.end(), std::greater()); + for (auto idx : removeList) { + weightGroups_.erase(weightGroups_.begin() + idx); + } + } + + std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { + auto weightProduct = std::make_unique(w0); + weightProduct->setNumWeightSets(weightGroups_.size()); + int weightGroupIndex = 0; + int i = 0; + for (const auto& weight : weights) { + weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i++, weightGroupIndex); + } + return std::move(weightProduct); + } + + int WeightHelper::addWeightToProduct( + std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex) { + groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); + auto group = weightGroups_[groupIndex]; + int entry = group.weightVectorEntry(name, weightNum); + if (debug_) + std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; + product->addWeight(weight, groupIndex, entry); + return groupIndex; + } + + int WeightHelper::findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex) { + // Start search at previous index, under expectation of ordered weights + previousGroupIndex = previousGroupIndex >= 0 ? previousGroupIndex : 0; + for (int index = previousGroupIndex; index < std::min(index + 1, static_cast(weightGroups_.size())); index++) { + const gen::WeightGroupInfo& weightGroup = weightGroups_[index]; + if (weightGroup.indexInRange(weightIndex) && weightGroup.containsWeight(wgtId, weightIndex)) { + return static_cast(index); + } + } + + // Fall back to unordered search + int counter = 0; + for (auto weightGroup : weightGroups_) { + if (weightGroup.containsWeight(wgtId, weightIndex)) + return counter; + counter++; + } + // Needs to be properly handled + throw std::range_error("Unmatched Generator weight! ID was " + wgtId + " index was " + std::to_string(weightIndex) + + "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); + } + + void WeightHelper::printWeights() { + // checks + for (auto& wgt : weightGroups_) { + if (!wgt.isWellFormed()) + std::cout << "\033[1;31m"; + std::cout << std::boolalpha << wgt.name() << " (" << wgt.firstId() << "-" << wgt.lastId() + << "): " << wgt.isWellFormed() << std::endl; + if (wgt.weightType() == gen::WeightType::kScaleWeights) { + auto& wgtScale = dynamic_cast(wgt); + std::cout << wgtScale.centralIndex() << " "; + std::cout << wgtScale.muR1muF2Index() << " "; + std::cout << wgtScale.muR1muF05Index() << " "; + std::cout << wgtScale.muR2muF1Index() << " "; + std::cout << wgtScale.muR2muF2Index() << " "; + std::cout << wgtScale.muR2muF05Index() << " "; + std::cout << wgtScale.muR05muF1Index() << " "; + std::cout << wgtScale.muR05muF2Index() << " "; + std::cout << wgtScale.muR05muF05Index() << " \n"; + for (auto name : wgtScale.getDynNames()) { + std::cout << name << ": "; + std::cout << wgtScale.getScaleIndex(1.0, 1.0, name) << " "; + std::cout << wgtScale.getScaleIndex(1.0, 2.0, name) << " "; + std::cout << wgtScale.getScaleIndex(1.0, 0.5, name) << " "; + std::cout << wgtScale.getScaleIndex(2.0, 1.0, name) << " "; + std::cout << wgtScale.getScaleIndex(2.0, 2.0, name) << " "; + std::cout << wgtScale.getScaleIndex(2.0, 0.5, name) << " "; + std::cout << wgtScale.getScaleIndex(0.5, 1.0, name) << " "; + std::cout << wgtScale.getScaleIndex(0.5, 2.0, name) << " "; + std::cout << wgtScale.getScaleIndex(0.5, 0.5, name) << "\n"; + } + + } else if (wgt.weightType() == gen::WeightType::kPdfWeights) { + std::cout << wgt.description() << "\n"; + } else if (wgt.weightType() == gen::WeightType::kPartonShowerWeights) { + auto& wgtPS = dynamic_cast(wgt); + for (auto group : wgtPS.getWeightNames()) { + std::cout << group << ": up " << wgtPS.upIndex(group); + std::cout << " - down " << wgtPS.downIndex(group) << std::endl; + } + } + if (!wgt.isWellFormed()) + std::cout << "\033[0m"; + } + } + + std::unique_ptr WeightHelper::buildGroup(ParsedWeight& weight) { + if (debug_) { + std::cout << "Building group for weight group " << weight.groupname + << " weight content is " << weight.content << std::endl; + } + if (isScaleWeightGroup(weight)) + return std::make_unique(weight.groupname); + else if (isPdfWeightGroup(weight)) + return std::make_unique(weight.groupname); + else if (isMEParamWeightGroup(weight)) + return std::make_unique(weight.groupname); + else if (isPartonShowerWeightGroup(weight)) + return std::make_unique("shower"); + else if (isOrphanPdfWeightGroup(weight)) + return std::make_unique(weight.groupname); + + return std::make_unique(weight.groupname); + } + + void WeightHelper::buildGroups() { + weightGroups_.clear(); + int currentGroupIdx = 0; + int groupOffset = 0; + for (auto& weight : parsedWeights_) { + weight.wgtGroup_idx += groupOffset; + currentGroupIdx = weight.wgtGroup_idx; + if (debug_) + std::cout << "Building group for weight " << weight.content << " group " + << weight.groupname << " group index " << weight.wgtGroup_idx << std::endl; + + int numGroups = static_cast(weightGroups_.size()); + if (weight.wgtGroup_idx == numGroups) { + weightGroups_.push_back(*buildGroup(weight)); + } else if (weight.wgtGroup_idx >= numGroups) + throw std::range_error("Invalid group index " + currentGroupIdx); + + // split PDF groups + if (weightGroups_[currentGroupIdx].weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = dynamic_cast(weightGroups_[currentGroupIdx]); + int lhaid = lhapdfId(weight, pdfGroup); + if (lhaid > 0 && !pdfGroup.isIdInParentSet(lhaid) && pdfGroup.parentLhapdfId() > 0) { + weightGroups_.push_back(*buildGroup(weight)); + groupOffset++; + } + } + WeightGroupInfo& group = weightGroups_[currentGroupIdx]; + group.addContainedId(weight.index, weight.id, weight.content); + if (group.weightType() == gen::WeightType::kScaleWeights) + updateScaleInfo(weight, currentGroupIdx); + else if (group.weightType() == gen::WeightType::kPdfWeights) { + updatePdfInfo(weight, currentGroupIdx); + } + } + cleanupOrphanCentralWeight(); + } + +} // namespace gen diff --git a/GeneratorInterface/Core/test/dumpWeightInfo.py b/GeneratorInterface/Core/test/dumpWeightInfo.py new file mode 100644 index 0000000000000..b7231c6945a33 --- /dev/null +++ b/GeneratorInterface/Core/test/dumpWeightInfo.py @@ -0,0 +1,44 @@ +from __future__ import print_function +from DataFormats.FWLite import Events,Handle,Runs,Lumis +import ROOT +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("infile", type=str, help="Input EDM file") +parser.add_argument("--source", type=str, help="product ID of weight product", default="externalLHEProducer") +args = parser.parse_args() + +lumis = Lumis(args.infile) +lumi = lumis.__iter__().next() +weightInfoHandle = Handle("GenWeightInfoProduct") +print("Trying to get weightInfo from lumi") +lumi.getByLabel(args.source, weightInfoHandle) +weightInfoProd = weightInfoHandle.product() + +events = Events(args.infile) +event = events.__iter__().next() +weightHandle = Handle("GenWeightProduct") +print("Trying to get weightProduct from event") +event.getByLabel(args.source, weightHandle) +weightInfo = weightHandle.product() +print("Number of weight groups in weightInfo is", len(weightInfo.weights())) +for j, weights in enumerate(weightInfo.weights()): + print("-"*10, "Looking at entry", j, "length is", len(weights),"-"*10) + matching = weightInfoProd.orderedWeightGroupInfo(j) + print("Group is", matching, "name is", matching.name(), "well formed?", matching.isWellFormed()) + print("Group description", matching.description()) + print(type(matching.weightType()), matching.weightType()) + if matching.weightType() == 's': + for var in [(x, y) for x in ["05", "1", "2"] for y in ["05", "1", "2"]]: + name = "muR%smuF%sIndex" % (var[0], var[1]) if not (var[0] == "1" and var[1] == "1") else "centralIndex" + print(name, getattr(matching, name)()) + elif matching.weightType() == 'P': + print("uncertaintyType", "Hessian" if matching.uncertaintyType() == ROOT.gen.kHessianUnc else "MC") + print("Has alphas? ", matching.hasAlphasVariations()) + print("Weights length?", len(weights), "Contained ids lenths?", len(matching.containedIds())) + print("-"*80) + for i,weight in enumerate(weights): + print(i, weight) + info = matching.weightMetaInfo(i) + print(" ID, localIndex, globalIndex, label, set:", info.id, info.localIndex, info.globalIndex, info.label, matching.name()) + print("-"*80) diff --git a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml index 167989f991b0d..c758089b243a9 100644 --- a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml +++ b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml @@ -16,6 +16,7 @@ +<<<<<<< HEAD @@ -23,3 +24,5 @@ +======= +>>>>>>> bad6d6546e0... New WeightGroups, improved parsing with helper class diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index b4bd5cf399317..6b678099e98b8 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -14,47 +14,48 @@ #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "boost/algorithm/string.hpp" -#include - #include #include #include #include namespace { - /// ---- Cache object for running sums of weights ---- - struct Counter { - Counter() : num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {} - // the counters - long long num; - long double sumw; - long double sumw2; - std::vector sumPDF, sumScale, sumRwgt, sumNamed, sumPS; + void mergeSumVectors(std::vector& v1, std::vector const& v2) { + if (v1.empty() && !v2.empty()) + v1.resize(v2.size(), 0); + if (!v2.empty()) + for (unsigned int i = 0, n = v1.size(); i < n; ++i) + v1[i] += v2[i]; + } + /// ---- Cache object for running sums of weights ---- + class Counter { + public: void clear() { - num = 0; - sumw = 0; - sumw2 = 0; - sumPDF.clear(); - sumScale.clear(); - sumRwgt.clear(); - sumNamed.clear(), sumPS.clear(); + num_ = 0; + sumw_ = 0; + sumw2_ = 0; + sumPDF_.clear(); + sumScale_.clear(); + sumRwgt_.clear(); + sumNamed_.clear(); + sumPS_.clear(); } // inc the counters void incGenOnly(double w) { - num++; - sumw += w; - sumw2 += (w * w); + num_++; + sumw_ += w; + sumw2_ += (w * w); } void incPSOnly(double w0, const std::vector& wPS) { if (!wPS.empty()) { - if (sumPS.empty()) - sumPS.resize(wPS.size(), 0); + if (sumPS_.empty()) + sumPS_.resize(wPS.size(), 0); for (unsigned int i = 0, n = wPS.size(); i < n; ++i) - sumPS[i] += (w0 * wPS[i]); + sumPS_[i] += (w0 * wPS[i]); } } @@ -68,62 +69,55 @@ namespace { incGenOnly(w0); // then add up variations if (!wScale.empty()) { - if (sumScale.empty()) - sumScale.resize(wScale.size(), 0); + if (sumScale_.empty()) + sumScale_.resize(wScale.size(), 0); for (unsigned int i = 0, n = wScale.size(); i < n; ++i) - sumScale[i] += (w0 * wScale[i]); + sumScale_[i] += (w0 * wScale[i]); } if (!wPDF.empty()) { - if (sumPDF.empty()) - sumPDF.resize(wPDF.size(), 0); + if (sumPDF_.empty()) + sumPDF_.resize(wPDF.size(), 0); for (unsigned int i = 0, n = wPDF.size(); i < n; ++i) - sumPDF[i] += (w0 * wPDF[i]); + sumPDF_[i] += (w0 * wPDF[i]); } if (!wRwgt.empty()) { - if (sumRwgt.empty()) - sumRwgt.resize(wRwgt.size(), 0); + if (sumRwgt_.empty()) + sumRwgt_.resize(wRwgt.size(), 0); for (unsigned int i = 0, n = wRwgt.size(); i < n; ++i) - sumRwgt[i] += (w0 * wRwgt[i]); + sumRwgt_[i] += (w0 * wRwgt[i]); } if (!wNamed.empty()) { - if (sumNamed.empty()) - sumNamed.resize(wNamed.size(), 0); + if (sumNamed_.empty()) + sumNamed_.resize(wNamed.size(), 0); for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) - sumNamed[i] += (w0 * wNamed[i]); + sumNamed_[i] += (w0 * wNamed[i]); } incPSOnly(w0, wPS); } void merge(const Counter& other) { - num += other.num; - sumw += other.sumw; - sumw2 += other.sumw2; - if (sumScale.empty() && !other.sumScale.empty()) - sumScale.resize(other.sumScale.size(), 0); - if (sumPDF.empty() && !other.sumPDF.empty()) - sumPDF.resize(other.sumPDF.size(), 0); - if (sumRwgt.empty() && !other.sumRwgt.empty()) - sumRwgt.resize(other.sumRwgt.size(), 0); - if (sumNamed.empty() && !other.sumNamed.empty()) - sumNamed.resize(other.sumNamed.size(), 0); - if (sumPS.empty() && !other.sumPS.empty()) - sumPS.resize(other.sumPS.size(), 0); - if (!other.sumScale.empty()) - for (unsigned int i = 0, n = sumScale.size(); i < n; ++i) - sumScale[i] += other.sumScale[i]; - if (!other.sumPDF.empty()) - for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i) - sumPDF[i] += other.sumPDF[i]; - if (!other.sumRwgt.empty()) - for (unsigned int i = 0, n = sumRwgt.size(); i < n; ++i) - sumRwgt[i] += other.sumRwgt[i]; - if (!other.sumNamed.empty()) - for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i) - sumNamed[i] += other.sumNamed[i]; - if (!other.sumPS.empty()) - for (unsigned int i = 0, n = sumPS.size(); i < n; ++i) - sumPS[i] += other.sumPS[i]; + num_ += other.num_; + sumw_ += other.sumw_; + sumw2_ += other.sumw2_; + + mergeSumVectors(sumScale_, other.sumScale_); + mergeSumVectors(sumPDF_, other.sumPDF_); + mergeSumVectors(sumRwgt_, other.sumRwgt_); + mergeSumVectors(sumNamed_, other.sumNamed_); + mergeSumVectors(sumPS_, other.sumPS_); } + + //private: + // the counters + long long num_ = 0; + long double sumw_ = 0; + long double sumw2_ = 0; + + std::vector sumPDF_; + std::vector sumScale_; + std::vector sumRwgt_; + std::vector sumNamed_; + std::vector sumPS_; }; struct CounterMap { @@ -138,8 +132,6 @@ namespace { void clear() { for (auto x : countermap) x.second.clear(); - active_el = nullptr; - active_label = ""; } void setLabel(std::string label) { active_el = &(countermap[label]); @@ -173,38 +165,8 @@ namespace { std::string rwgtWeightDoc; }; - struct DynamicWeightChoiceGenInfo { - // choice of LHE weights - // ---- scale ---- - std::vector scaleWeightIDs; - std::string scaleWeightsDoc; - // ---- pdf ---- - std::vector pdfWeightIDs; - std::string pdfWeightsDoc; - // ---- ps ---- - std::vector defPSWeightIDs = {6, 7, 8, 9}; - std::vector defPSWeightIDs_alt = {27, 5, 26, 4}; - bool matchPS_alt = false; - std::vector psWeightIDs; - unsigned int psBaselineID = 1; - std::string psWeightsDoc; - - void setMissingWeight(int idx) { psWeightIDs[idx] = (matchPS_alt) ? defPSWeightIDs_alt[idx] : defPSWeightIDs[idx]; } - - bool empty() const { return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); } - }; - - struct LumiCacheInfoHolder { - CounterMap countermap; - DynamicWeightChoiceGenInfo weightChoice; - void clear() { - countermap.clear(); - weightChoice = DynamicWeightChoiceGenInfo(); - } - }; - float stof_fortrancomp(const std::string& str) { - std::string::size_type match = str.find('d'); + std::string::size_type match = str.find("d"); if (match != std::string::npos) { std::string pre = str.substr(0, match); std::string post = str.substr(match + 1); @@ -244,7 +206,7 @@ namespace { }; } // namespace -class GenWeightsTableProducer : public edm::global::EDProducer, +class GenWeightsTableProducer : public edm::global::EDProducer, edm::RunCache, edm::RunSummaryCache, edm::EndRunProducer> { @@ -262,17 +224,11 @@ class GenWeightsTableProducer : public edm::global::EDProducer>("namedWeightLabels")), lheWeightPrecision_(params.getParameter("lheWeightPrecision")), maxPdfWeights_(params.getParameter("maxPdfWeights")), - keepAllPSWeights_(params.getParameter("keepAllPSWeights")), debug_(params.getUntrackedParameter("debug", false)), debugRun_(debug_.load()), - hasIssuedWarning_(false), - psWeightWarning_(false) { + hasIssuedWarning_(false) { produces(); produces("genModel"); - produces("LHEScale"); - produces("LHEPdf"); - produces("LHEReweighting"); - produces("LHENamed"); produces("PS"); produces(); if (namedWeightIDs_.size() != namedWeightLabels_.size()) { @@ -291,26 +247,22 @@ class GenWeightsTableProducer : public edm::global::EDProducercountermap.get(); + Counter& counter = *streamCache(id)->get(); // generator information (always available) - edm::Handle genInfo; - iEvent.getByToken(genTag_, genInfo); - double weight = genInfo->weight(); + auto const& genInfo = iEvent.get(genTag_); // table for gen info, always available auto out = std::make_unique(1, "genWeight", true); out->setDoc("generator weight"); - out->addColumnValue("", weight, "generator weight"); + out->addColumnValue("", genInfo.weight(), "generator weight", nanoaod::FlatTable::FloatColumn); iEvent.put(std::move(out)); - std::string model_label = streamCache(id)->countermap.getLabel(); + std::string model_label = streamCache(id)->getLabel(); auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); iEvent.put(std::move(outM), "genModel"); - bool getLHEweightsFromGenInfo = !model_label.empty(); // tables for LHE weights, may not be filled - std::unique_ptr lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab; std::unique_ptr genPSTab; edm::Handle lheInfo; @@ -320,74 +272,43 @@ class GenWeightsTableProducer : public edm::global::EDProducerweightChoice); if (lheInfo.isValid()) { - if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true)) - edm::LogWarning("LHETablesProducer") - << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n"; // get the dynamic choice of weights - const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index()); + const DynamicWeightChoice& weightChoice = *runCache(iEvent.getRun().index()); // go fill tables - fillLHEWeightTables(counter, - weightChoice, - genWeightChoice, - weight, - *lheInfo, - *genInfo, - lheScaleTab, - lhePdfTab, - lheRwgtTab, - lheNamedTab, - genPSTab); - } else if (getLHEweightsFromGenInfo) { - fillLHEPdfWeightTablesFromGenInfo( - counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab); - lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); - //lheNamedTab.reset(new nanoaod::FlatTable(1, "LHENamedWeights", true)); - //genPSTab.reset(new nanoaod::FlatTable(1, "PSWeight", true)); + fillLHEWeightTables(counter, weightChoice, genInfo.weight(), *lheInfo, genInfo, genPSTab); } else { // Still try to add the PS weights - fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab); + fillOnlyPSWeightTable(counter, genInfo.weight(), genInfo, genPSTab); // make dummy values - lheScaleTab = std::make_unique(1, "LHEScaleWeights", true); - lhePdfTab = std::make_unique(1, "LHEPdfWeights", true); - lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); - lheNamedTab = std::make_unique(1, "LHENamedWeights", true); if (!hasIssuedWarning_.exchange(true)) { edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n"; } } - iEvent.put(std::move(lheScaleTab), "LHEScale"); - iEvent.put(std::move(lhePdfTab), "LHEPdf"); - iEvent.put(std::move(lheRwgtTab), "LHEReweighting"); - iEvent.put(std::move(lheNamedTab), "LHENamed"); iEvent.put(std::move(genPSTab), "PS"); } - void fillLHEWeightTables(Counter* counter, - const DynamicWeightChoice* weightChoice, - const DynamicWeightChoiceGenInfo* genWeightChoice, + void fillLHEWeightTables(Counter& counter, + const DynamicWeightChoice& weightChoice, double genWeight, const LHEEventProduct& lheProd, const GenEventInfoProduct& genProd, - std::unique_ptr& outScale, - std::unique_ptr& outPdf, - std::unique_ptr& outRwgt, - std::unique_ptr& outNamed, std::unique_ptr& outPS) const { - bool lheDebug = debug_.exchange( - false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) + // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) + bool lheDebug = debug_.exchange(false); - const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; - const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; - const std::vector& rwgtWeightIDs = weightChoice->rwgtIDs; + const std::vector& scaleWeightIDs = weightChoice.scaleWeightIDs; + const std::vector& pdfWeightIDs = weightChoice.pdfWeightIDs; + const std::vector& rwgtWeightIDs = weightChoice.rwgtIDs; double w0 = lheProd.originalXWGTUP(); - std::vector wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1), - wNamed(namedWeightIDs_.size(), 1); + std::vector wScale(scaleWeightIDs.size(), 1); + std::vector wPDF(pdfWeightIDs.size(), 1); + std::vector wRwgt(rwgtWeightIDs.size(), 1); + std::vector wNamed(namedWeightIDs_.size(), 1); + for (auto& weight : lheProd.weights()) { if (lheDebug) printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str()); @@ -409,143 +330,57 @@ class GenWeightsTableProducer : public edm::global::EDProducer wPS; - std::string psWeightDocStr; - setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); - - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); - - outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); - outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); - - outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); - outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); - - outRwgt = std::make_unique(wRwgt.size(), "LHEReweightingWeight", false); - outRwgt->addColumn("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_); - - outNamed = std::make_unique(1, "LHEWeight", true); - outNamed->addColumnValue("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file"); - for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { - outNamed->addColumnValue(namedWeightLabels_[i], - wNamed[i], - "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal", - lheWeightPrecision_); - } - - counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS); - } - - void fillLHEPdfWeightTablesFromGenInfo(Counter* counter, - const DynamicWeightChoiceGenInfo* weightChoice, - double genWeight, - const GenEventInfoProduct& genProd, - std::unique_ptr& outScale, - std::unique_ptr& outPdf, - std::unique_ptr& outNamed, - std::unique_ptr& outPS) const { - const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; - const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; - - auto weights = genProd.weights(); - double w0 = (weights.size() > 1) ? weights.at(1) : 1.; - double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.; - - std::vector wScale, wPDF, wPS; - for (auto id : scaleWeightIDs) - wScale.push_back(weights.at(id) / w0); - for (auto id : pdfWeightIDs) { - wPDF.push_back(weights.at(id) / w0); + int vectorSize = (genProd.weights().size() == 14 || genProd.weights().size() == 46) ? 4 : 1; + std::vector wPS(vectorSize, 1); + if (vectorSize > 1) { + for (unsigned int i = 6; i < 10; i++) { + wPS[i - 6] = (genProd.weights()[i]) / w0; + } } - - std::string psWeightsDocStr; - setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr); - - outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); - outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); - - outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); - outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightsDocStr, lheWeightPrecision_); - - outNamed = std::make_unique(1, "LHEWeight", true); - outNamed->addColumnValue("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file"); - /*for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { - outNamed->addColumnValue(namedWeightLabels_[i], wNamed[i], "LHE weight for id "+namedWeightIDs_[i]+", relative to nominal", lheWeightPrecision_); - }*/ - - counter->incLHE(genWeight, wScale, wPDF, std::vector(), std::vector(), wPS); + outPS->addColumn("", + wPS, + vectorSize > 1 ? "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 " + "FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2 " + : "dummy PS weight (1.0) ", + nanoaod::FlatTable::FloatColumn, + lheWeightPrecision_); + + counter.incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS); } - void fillOnlyPSWeightTable(Counter* counter, - const DynamicWeightChoiceGenInfo* genWeightChoice, + void fillOnlyPSWeightTable(Counter& counter, double genWeight, const GenEventInfoProduct& genProd, std::unique_ptr& outPS) const { - std::vector wPS; - std::string psWeightDocStr; - setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); - - counter->incGenOnly(genWeight); - counter->incPSOnly(genWeight, wPS); - } + int vectorSize = (genProd.weights().size() == 14 || genProd.weights().size() == 46) ? 4 : 1; - void setPSWeightInfo(const std::vector& genWeights, - const DynamicWeightChoiceGenInfo* genWeightChoice, - std::vector& wPS, - std::string& psWeightDocStr) const { - wPS.clear(); - // isRegularPSSet = keeping all weights and the weights are a usual size, ie - // all weights are PS weights (don't use header incase missing names) - bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46); - if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) { - psWeightDocStr = genWeightChoice->psWeightsDoc; - double psNom = genWeights.at(genWeightChoice->psBaselineID); - for (auto wgtidx : genWeightChoice->psWeightIDs) { - wPS.push_back(genWeights.at(wgtidx) / psNom); - } - } else { - int vectorSize = - keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1); - - if (vectorSize > 1) { - double nominal = genWeights.at(1); // Called 'Baseline' in GenLumiInfoHeader - if (keepAllPSWeights_) { - for (int i = 0; i < vectorSize; i++) { - wPS.push_back(genWeights.at(i + 2) / nominal); - } - psWeightDocStr = "All PS weights (w_var / w_nominal)"; - } else { - if (!psWeightWarning_.exchange(true)) - edm::LogWarning("LHETablesProducer") - << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n" - << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt " - "order )"; - for (std::size_t i = 6; i < 10; i++) { - wPS.push_back(genWeights.at(i) / nominal); - } - psWeightDocStr = - "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" - "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; - } - } else { - wPS.push_back(1.0); - psWeightDocStr = "dummy PS weight (1.0) "; + std::vector wPS(vectorSize, 1); + if (vectorSize > 1) { + for (unsigned int i = 6; i < 10; i++) { + wPS[i - 6] = (genProd.weights()[i]) / genWeight; } } + + outPS = std::make_unique(wPS.size(), "PSWeight", false); + outPS->addColumn("", + wPS, + vectorSize > 1 ? "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 " + "FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2 " + : "dummy PS weight (1.0) ", + nanoaod::FlatTable::FloatColumn, + lheWeightPrecision_); + + counter.incGenOnly(genWeight); + counter.incPSOnly(genWeight, wPS); } // create an empty counter std::shared_ptr globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override { edm::Handle lheInfo; - bool lheDebug = debugRun_.exchange( - false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) + // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) + bool lheDebug = debugRun_.exchange(false); auto weightChoice = std::make_shared(); // getByToken throws since we're not in the endRun (see https://github.com/cms-sw/cmssw/pull/18499) @@ -560,7 +395,6 @@ class GenWeightsTableProducer : public edm::global::EDProducer scaleVariationIDs; std::vector pdfSetWeightIDs; std::vector lheReweighingIDs; - bool isFirstGroup = true; std::regex weightgroupmg26x(""); std::regex weightgroup(""); @@ -569,14 +403,9 @@ class GenWeightsTableProducer : public edm::global::EDProducer"); - std::regex scalewmg26xNew( - ""); - - // MUR=2.0 std::regex scalew( - "\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)" - "=(\\S+)\\s+(?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)"); + "\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)=(\\S+)\\s+(" + "?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)"); std::regex pdfw( "\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?"); std::regex pdfwOld("\\s*Member \\s*(\\d+)\\s*(?:.*)"); @@ -584,14 +413,6 @@ class GenWeightsTableProducer : public edm::global::EDProducer\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?"); - // - - // PDF=325300 MemberID=0 - std::regex pdfwmg26xNew( - "" - "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?"); - std::regex rwgt("(.+)?()?"); std::smatch groups; for (auto iter = lheInfo->headers_begin(), end = lheInfo->headers_end(); iter != end; ++iter) { @@ -606,16 +427,12 @@ class GenWeightsTableProducer : public edm::global::EDProducer"); if (std::regex_search(lines[iLine], groups, weightgroupmg26x)) { ismg26x = true; - } else if (std::regex_search(lines[iLine], groups, scalewmg26xNew) || - std::regex_search(lines[iLine], groups, pdfwmg26xNew)) { - ismg26xNew = true; } } for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; ++iLine) { @@ -627,26 +444,17 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a weight group for '" << groupname << "'" << std::endl; - if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation" || isFirstGroup) { - if (lheDebug && groupname.find("scale_variation") != 0 && groupname != "Central scale variation") - std::cout << ">>> First weight is not scale variation, but assuming is the Central Weight" << std::endl; - else if (lheDebug) + if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation") { + if (lheDebug) std::cout << ">>> Looks like scale variation for theory uncertainties" << std::endl; - isFirstGroup = false; for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) { + if (lheDebug) std::cout << " " << lines[iLine]; - } - if (std::regex_search( - lines[iLine], groups, ismg26x ? scalewmg26x : (ismg26xNew ? scalewmg26xNew : scalew))) { + if (std::regex_search(lines[iLine], groups, ismg26x ? scalewmg26x : scalew)) { if (lheDebug) std::cout << " >>> Scale weight " << groups[1].str() << " for " << groups[3].str() << " , " << groups[4].str() << " , " << groups[5].str() << std::endl; - if (ismg26xNew) { - scaleVariationIDs.emplace_back(groups.str(4), groups.str(1), groups.str(3), groups.str(2)); - } else { - scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); - } + scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); } else if (std::regex_search(lines[iLine], endweightgroup)) { if (lheDebug) std::cout << ">>> Looks like the end of a weight group" << std::endl; @@ -659,7 +467,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a new weight group, I will assume I missed the end " "of the group." << std::endl; - if (ismg26x || ismg26xNew) + if (ismg26x) missed_weightgroup = true; --iLine; // rewind by one, and go back to the outer loop break; @@ -691,7 +499,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a new weight group, I will assume I missed the end " "of the group." << std::endl; - if (ismg26x || ismg26xNew) + if (ismg26x) missed_weightgroup = true; --iLine; // rewind by one, and go back to the outer loop break; @@ -728,7 +536,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a new weight group, I will assume I missed the end " "of the group." << std::endl; - if (ismg26x || ismg26xNew) + if (ismg26x) missed_weightgroup = true; --iLine; // rewind by one, and go back to the outer loop break; @@ -742,15 +550,10 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a new weight group, I will assume I missed the end " "of the group." << std::endl; - if (ismg26x || ismg26xNew) + if (ismg26x) missed_weightgroup = true; --iLine; // rewind by one, and go back to the outer loop break; } } - } else if (groupname == "mass_variation" || groupname == "sthw2_variation" || - groupname == "width_variation") { - if (lheDebug) - std::cout << ">>> Looks like an EW parameter weight" << std::endl; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, rwgt)) { - std::string rwgtID = groups.str(1); - if (lheDebug) - std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl; - if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) { - // we're only interested in the beggining of the block - lheReweighingIDs.emplace_back(rwgtID); - } - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - } - } } else { for (++iLine; iLine < nLines; ++iLine) { if (lheDebug) @@ -821,7 +604,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like the beginning of a new weight group, I will assume I missed the end " "of the group." << std::endl; - if (ismg26x || ismg26xNew) + if (ismg26x) missed_weightgroup = true; --iLine; // rewind by one, and go back to the outer loop break; @@ -909,8 +692,8 @@ class GenWeightsTableProducer : public edm::global::EDProducer beginStream(edm::StreamID) const override { - return std::make_unique(); - } + std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } // inizialize to zero at begin run void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override { streamCache(id)->clear(); @@ -944,128 +725,13 @@ class GenWeightsTableProducer : public edm::global::EDProducercountermap); + auto counterMap = streamCache(id); edm::Handle genLumiInfoHead; lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); if (!genLumiInfoHead.isValid()) edm::LogWarning("LHETablesProducer") << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; - - std::string label; - if (genLumiInfoHead.isValid()) { - label = genLumiInfoHead->configDescription(); - boost::replace_all(label, "-", "_"); - boost::replace_all(label, "/", "_"); - } - counterMap->setLabel(label); - - if (genLumiInfoHead.isValid()) { - auto weightChoice = &(streamCache(id)->weightChoice); - - std::vector scaleVariationIDs; - std::vector pdfSetWeightIDs; - weightChoice->psWeightIDs.clear(); - - std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)"); - std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)"); - std::regex mainPSw("sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)"); - std::smatch groups; - auto weightNames = genLumiInfoHead->weightNames(); - std::unordered_map knownPDFSetsFromGenInfo_; - unsigned int weightIter = 0; - for (const auto& line : weightNames) { - if (std::regex_search(line, groups, scalew)) { // scale variation - auto id = groups.str(1); - auto group = groups.str(2); - auto mur = groups.str(3); - auto muf = groups.str(4); - if (group.find("Central scale variation") != std::string::npos) - scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); - } else if (std::regex_search(line, groups, pdfw)) { // PDF variation - auto id = groups.str(1); - auto group = groups.str(2); - auto memberid = groups.str(3); - auto pdfset = groups.str(4); - if (group.find(pdfset) != std::string::npos) { - if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) { - knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str()); - pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str())); - } else - pdfSetWeightIDs.back().add(id, std::atoi(id.c_str())); - } - } else if (line == "Baseline") { - weightChoice->psBaselineID = weightIter; - } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) { - weightChoice->matchPS_alt = line.find("sr:") != std::string::npos; // (f/i)sr: for new weights - if (keepAllPSWeights_) { - weightChoice->psWeightIDs.push_back(weightIter); // PS variations - } else if (std::regex_search(line, groups, mainPSw)) { - if (weightChoice->psWeightIDs.empty()) - weightChoice->psWeightIDs = std::vector(4, -1); - int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0; - psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2; - weightChoice->psWeightIDs[psIdx] = weightIter; - } - } - weightIter++; - } - if (keepAllPSWeights_) { - weightChoice->psWeightsDoc = "All PS weights (w_var / w_nominal)"; - } else if (weightChoice->psWeightIDs.size() == 4) { - weightChoice->psWeightsDoc = - "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" - "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; - for (int i = 0; i < 4; i++) { - if (static_cast(weightChoice->psWeightIDs[i]) == -1) - weightChoice->setMissingWeight(i); - } - } else { - weightChoice->psWeightsDoc = "dummy PS weight (1.0) "; - } - - weightChoice->scaleWeightIDs.clear(); - weightChoice->pdfWeightIDs.clear(); - - std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end()); - std::stringstream scaleDoc; - scaleDoc << "LHE scale variation weights (w_var / w_nominal); "; - for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) { - const auto& sw = scaleVariationIDs[isw]; - if (isw) - scaleDoc << "; "; - scaleDoc << "[" << isw << "] is " << sw.label; - weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str())); - } - if (!scaleVariationIDs.empty()) - weightChoice->scaleWeightsDoc = scaleDoc.str(); - std::stringstream pdfDoc; - pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA names "; - bool found = false; - for (const auto& pw : pdfSetWeightIDs) { - if (pw.wids.size() == 1) - continue; // only consider error sets - for (const auto& wantedpdf : lhaNameToID_) { - auto pdfname = wantedpdf.first; - if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end()) - continue; - uint32_t lhaid = knownPDFSetsFromGenInfo_.at(pdfname); - if (pw.lhaIDs.first != lhaid) - continue; - pdfDoc << pdfname; - for (const auto& x : pw.wids) - weightChoice->pdfWeightIDs.push_back(std::atoi(x.c_str())); - if (maxPdfWeights_ < pw.wids.size()) { - weightChoice->pdfWeightIDs.resize(maxPdfWeights_); // drop some replicas - pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas"; - } - weightChoice->pdfWeightsDoc = pdfDoc.str(); - found = true; - break; - } - if (found) - break; - } - } + counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); } // create an empty counter std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { @@ -1076,7 +742,7 @@ class GenWeightsTableProducer : public edm::global::EDProducermerge(streamCache(id)->countermap); + runCounterMap->merge(*streamCache(id)); } // nothing to do per se void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} @@ -1084,46 +750,41 @@ class GenWeightsTableProducer : public edm::global::EDProducer(); - for (const auto& x : runCounterMap->countermap) { - auto runCounter = &(x.second); - std::string label = (!x.first.empty()) ? (std::string("_") + x.first) : ""; + for (auto x : runCounterMap->countermap) { + auto& runCounter = x.second; + std::string label = std::string("_") + x.first; std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; - out->addInt("genEventCount" + label, "event count" + doclabel, runCounter->num); - out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter->sumw); - out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter->sumw2); + out->addInt("genEventCount" + label, "event count" + doclabel, runCounter.num_); + out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter.sumw_); + out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); - double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1; - auto sumScales = runCounter->sumScale; + double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; + auto sumScales = runCounter.sumScale_; for (auto& val : sumScales) val *= norm; - out->addVFloatWithNorm("LHEScaleSumw" + label, - "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel, - sumScales, - runCounter->sumw); - auto sumPDFs = runCounter->sumPDF; + out->addVFloat("LHEScaleSumw" + label, + "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel, + sumScales); + auto sumPDFs = runCounter.sumPDF_; for (auto& val : sumPDFs) val *= norm; - out->addVFloatWithNorm("LHEPdfSumw" + label, - "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel, - sumPDFs, - runCounter->sumw); - if (!runCounter->sumRwgt.empty()) { - auto sumRwgts = runCounter->sumRwgt; + out->addVFloat( + "LHEPdfSumw" + label, "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel, sumPDFs); + if (!runCounter.sumRwgt_.empty()) { + auto sumRwgts = runCounter.sumRwgt_; for (auto& val : sumRwgts) val *= norm; - out->addVFloatWithNorm("LHEReweightingSumw" + label, - "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel, - sumRwgts, - runCounter->sumw); + out->addVFloat("LHEReweightingSumw" + label, + "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel, + sumRwgts); } - if (!runCounter->sumNamed.empty()) { // it could be empty if there's no LHE info in the sample + if (!runCounter.sumNamed_.empty()) { // it could be empty if there's no LHE info in the sample for (unsigned int i = 0, n = namedWeightLabels_.size(); i < n; ++i) { - out->addFloatWithNorm( + out->addFloat( "LHESumw_" + namedWeightLabels_[i] + label, "Sum of genEventWeight * LHEWeight_" + namedWeightLabels_[i] + ", divided by genEventSumw" + doclabel, - runCounter->sumNamed[i] * norm, - runCounter->sumw); + runCounter.sumNamed_[i] * norm); } } } @@ -1152,7 +813,6 @@ class GenWeightsTableProducer : public edm::global::EDProducersetComment("output names for the namedWeightIDs (in the same order)"); desc.add("lheWeightPrecision")->setComment("Number of bits in the mantissa for LHE weights"); desc.add("maxPdfWeights")->setComment("Maximum number of PDF weights to save (to crop NN replicas)"); - desc.add("keepAllPSWeights")->setComment("Store all PS weights found"); desc.addOptionalUntracked("debug")->setComment("dump out all LHE information for one event"); descriptions.add("genWeightsTable", desc); } @@ -1170,9 +830,8 @@ class GenWeightsTableProducer : public edm::global::EDProducer namedWeightLabels_; int lheWeightPrecision_; unsigned int maxPdfWeights_; - bool keepAllPSWeights_; - mutable std::atomic debug_, debugRun_, hasIssuedWarning_, psWeightWarning_; + mutable std::atomic debug_, debugRun_, hasIssuedWarning_; }; #include "FWCore/Framework/interface/MakerMacros.h" diff --git a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc index 1b53a0fc0d1b5..b942db79bcd1f 100644 --- a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc +++ b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc @@ -2,7 +2,7 @@ // // Package: PhysicsTools/NanoAODOutput // Class : NanoAODOutputModule -// +// // Implementation: // [Notes on implementation] // @@ -11,17 +11,15 @@ // // system include files -#include -#include - -#include "Compression.h" +#include #include "TFile.h" -#include "TObjString.h" -#include "TROOT.h" #include "TTree.h" -#include +#include "TROOT.h" +#include "TObjString.h" +#include "Compression.h" // user include files +#include "FWCore/Framework/interface/OutputModule.h" #include "FWCore/Framework/interface/one/OutputModule.h" #include "FWCore/Framework/interface/RunForOutput.h" #include "FWCore/Framework/interface/LuminosityBlockForOutput.h" @@ -39,19 +37,15 @@ #include "DataFormats/NanoAOD/interface/FlatTable.h" #include "DataFormats/NanoAOD/interface/UniqueString.h" #include "PhysicsTools/NanoAOD/plugins/TableOutputBranches.h" -#include "PhysicsTools/NanoAOD/plugins/LumiOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/TriggerOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/EventStringOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/SummaryTableOutputBranches.h" #include -#include "tbb/task_arena.h" - class NanoAODOutputModule : public edm::one::OutputModule<> { public: NanoAODOutputModule(edm::ParameterSet const& pset); - ~NanoAODOutputModule() override; static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); @@ -69,7 +63,7 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { int m_eventsSinceFlush{0}; std::string m_compressionAlgorithm; bool m_writeProvenance; - bool m_fakeName; //crab workaround, remove after crab is fixed + bool m_fakeName; //crab workaround, remove after crab is fixed int m_autoFlush; edm::ProcessHistoryRegistry m_processHistoryRegistry; edm::JobReport::Token m_jrToken; @@ -79,62 +73,59 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { static constexpr int m_firstFlush{1000}; class CommonEventBranches { - public: - void branch(TTree& tree) { - tree.Branch("run", &m_run, "run/i"); - tree.Branch("luminosityBlock", &m_luminosityBlock, "luminosityBlock/i"); - tree.Branch("event", &m_event, "event/l"); - } - void fill(const edm::EventID& id) { - m_run = id.run(); - m_luminosityBlock = id.luminosityBlock(); - m_event = id.event(); - } - - private: - UInt_t m_run; - UInt_t m_luminosityBlock; - ULong64_t m_event; + public: + void branch(TTree &tree) { + tree.Branch("run", & m_run, "run/i"); + tree.Branch("luminosityBlock", & m_luminosityBlock, "luminosityBlock/i"); + tree.Branch("event", & m_event, "event/l"); + } + void fill(const edm::EventID & id) { + m_run = id.run(); m_luminosityBlock = id.luminosityBlock(); m_event = id.event(); + } + private: + UInt_t m_run; UInt_t m_luminosityBlock; ULong64_t m_event; } m_commonBranches; class CommonLumiBranches { - public: - void branch(TTree& tree) { - tree.Branch("run", &m_run, "run/i"); - tree.Branch("luminosityBlock", &m_luminosityBlock, "luminosityBlock/i"); - } - void fill(const edm::LuminosityBlockID& id) { - m_run = id.run(); - m_luminosityBlock = id.value(); - } - - private: - UInt_t m_run; - UInt_t m_luminosityBlock; + public: + void branch(TTree &tree) { + tree.Branch("run", & m_run, "run/i"); + tree.Branch("luminosityBlock", & m_luminosityBlock, "luminosityBlock/i"); + } + void fill(const edm::LuminosityBlockID & id) { + m_run = id.run(); + m_luminosityBlock = id.value(); + } + private: + UInt_t m_run; UInt_t m_luminosityBlock; } m_commonLumiBranches; class CommonRunBranches { - public: - void branch(TTree& tree) { tree.Branch("run", &m_run, "run/i"); } - void fill(const edm::RunID& id) { m_run = id.run(); } - - private: - UInt_t m_run; + public: + void branch(TTree &tree) { + tree.Branch("run", & m_run, "run/i"); + } + void fill(const edm::RunID & id) { + m_run = id.run(); + } + private: + UInt_t m_run; } m_commonRunBranches; + std::vector m_tables; + std::vector m_tableTokens; + std::vector m_tableVectorTokens; std::vector m_triggers; - bool m_triggers_areSorted = false; std::vector m_evstrings; std::vector m_runTables; - std::vector m_lumiTables; - std::vector m_lumiTables2; - std::vector m_runFlatTables; - std::vector> m_nanoMetadata; + std::vector> m_nanoMetadata; + }; + // // constants, enums and typedefs // @@ -146,21 +137,22 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { // // constructors and destructor // -NanoAODOutputModule::NanoAODOutputModule(edm::ParameterSet const& pset) - : edm::one::OutputModuleBase::OutputModuleBase(pset), - edm::one::OutputModule<>(pset), - m_fileName(pset.getUntrackedParameter("fileName")), - m_logicalFileName(pset.getUntrackedParameter("logicalFileName")), - m_compressionLevel(pset.getUntrackedParameter("compressionLevel")), - m_compressionAlgorithm(pset.getUntrackedParameter("compressionAlgorithm")), - m_writeProvenance(pset.getUntrackedParameter("saveProvenance", true)), - m_fakeName(pset.getUntrackedParameter("fakeNameForCrab", false)), - m_autoFlush(pset.getUntrackedParameter("autoFlush", -10000000)), - m_processHistoryRegistry() {} - -NanoAODOutputModule::~NanoAODOutputModule() {} - -void NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { +NanoAODOutputModule::NanoAODOutputModule(edm::ParameterSet const& pset): + edm::one::OutputModuleBase::OutputModuleBase(pset), + edm::one::OutputModule<>(pset), + m_fileName(pset.getUntrackedParameter("fileName")), + m_logicalFileName(pset.getUntrackedParameter("logicalFileName")), + m_compressionLevel(pset.getUntrackedParameter("compressionLevel")), + m_compressionAlgorithm(pset.getUntrackedParameter("compressionAlgorithm")), + m_writeProvenance(pset.getUntrackedParameter("saveProvenance", true)), + m_fakeName(pset.getUntrackedParameter("fakeNameForCrab", false)), + m_autoFlush(pset.getUntrackedParameter("autoFlush", -10000000)), + m_processHistoryRegistry() +{ +} + +void +NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { //Get data from 'e' and write it to the file edm::Service jr; jr->eventWrittenToFile(m_jrToken, iEvent.id().run(), iEvent.id().event()); @@ -176,7 +168,7 @@ void NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { float percentClusterDone = m_firstFlush / static_cast(m_autoFlush); maxMemory = static_cast(m_tree->GetTotBytes()) / percentClusterDone; } else if (m_tree->GetZipBytes() == 0) { - maxMemory = 100 * 1024 * 1024; // Degenerate case of no information in the tree; arbitrary value + maxMemory = 100*1024*1024; // Degenerate case of no information in the tree; arbitrary value } else { // Estimate the memory we'll be using by scaling the current compression ratio. float cxnRatio = m_tree->GetTotBytes() / static_cast(m_tree->GetZipBytes()); @@ -200,121 +192,118 @@ void NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { m_commonBranches.fill(iEvent.id()); // fill all tables, starting from main tables and then doing extension tables - for (unsigned int extensions = 0; extensions <= 1; ++extensions) { - for (auto& t : m_tables) - t.fill(iEvent, *m_tree, extensions); + std::vector tables; + for (auto& tableToken : m_tableTokens) { + edm::Handle handle; + iEvent.getByToken(tableToken, handle); + tables.push_back(&(*handle)); } - if (!m_triggers_areSorted) { // sort triggers/flags in inverse processHistory order, to save without any special label the most recent ones - std::vector pnames; - for (auto& p : iEvent.processHistory()) - pnames.push_back(p.processName()); - std::sort(m_triggers.begin(), m_triggers.end(), [pnames](TriggerOutputBranches& a, TriggerOutputBranches& b) { - return ((std::find(pnames.begin(), pnames.end(), a.processName()) - pnames.begin()) > - (std::find(pnames.begin(), pnames.end(), b.processName()) - pnames.begin())); - }); - m_triggers_areSorted = true; + for (auto& tableToken : m_tableVectorTokens) { + edm::Handle> handle; + iEvent.getByToken(tableToken, handle); + for (auto const& table : *handle) { + tables.push_back(&table); + } + } + + if (m_tables.empty()) { + m_tables.resize(tables.size()); + } + for (unsigned int extensions = 0; extensions <= 1; ++extensions) { + size_t iTable = 0; + for (auto& table : tables) { + m_tables[iTable].fill(*table, *m_tree, extensions); + ++iTable; + } } // fill triggers - for (auto& t : m_triggers) - t.fill(iEvent, *m_tree); + for (auto & t : m_triggers) t.fill(iEvent,*m_tree); // fill event branches - for (auto& t : m_evstrings) - t.fill(iEvent, *m_tree); - tbb::this_task_arena::isolate([&] { m_tree->Fill(); }); + for (auto & t : m_evstrings) t.fill(iEvent,*m_tree); + m_tree->Fill(); m_processHistoryRegistry.registerProcessHistory(iEvent.processHistory()); } -void NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& iLumi) { +void +NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& iLumi) { edm::Service jr; jr->reportLumiSection(m_jrToken, iLumi.id().run(), iLumi.id().value()); m_commonLumiBranches.fill(iLumi.id()); - - for (auto& t : m_lumiTables) - t.fill(iLumi, *m_lumiTree); - - for (unsigned int extensions = 0; extensions <= 1; ++extensions) { - for (auto& t : m_lumiTables2) - t.fill(iLumi, *m_lumiTree, extensions); - } - - tbb::this_task_arena::isolate([&] { m_lumiTree->Fill(); }); + m_lumiTree->Fill(); m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory()); } -void NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { +void +NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { edm::Service jr; jr->reportRunNumber(m_jrToken, iRun.id().run()); m_commonRunBranches.fill(iRun.id()); - for (auto& t : m_runTables) - t.fill(iRun, *m_runTree); - - for (unsigned int extensions = 0; extensions <= 1; ++extensions) { - for (auto& t : m_runFlatTables) - t.fill(iRun, *m_runTree, extensions); - } + for (auto & t : m_runTables) t.fill(iRun,*m_runTree); edm::Handle hstring; - for (const auto& p : m_nanoMetadata) { + for (const auto & p : m_nanoMetadata) { iRun.getByToken(p.second, hstring); - TObjString* tos = dynamic_cast(m_file->Get(p.first.c_str())); + TObjString *tos = dynamic_cast(m_file->Get(p.first.c_str())); if (tos) { - if (hstring->str() != tos->GetString()) - throw cms::Exception("LogicError", "Inconsistent nanoMetadata " + p.first + " (" + hstring->str() + ")"); + if (hstring->str() != tos->GetString()) throw cms::Exception("LogicError", "Inconsistent nanoMetadata " + p.first + " (" + hstring->str() +")"); } else { - auto ostr = std::make_unique(hstring->str().c_str()); - m_file->WriteTObject(ostr.release(), p.first.c_str()); + auto ostr = std::make_unique(hstring->str().c_str()); + m_file->WriteTObject(ostr.release(), p.first.c_str()); } } - tbb::this_task_arena::isolate([&] { m_runTree->Fill(); }); + m_runTree->Fill(); m_processHistoryRegistry.registerProcessHistory(iRun.processHistory()); } -bool NanoAODOutputModule::isFileOpen() const { return nullptr != m_file.get(); } +bool +NanoAODOutputModule::isFileOpen() const { + return nullptr != m_file.get(); +} -void NanoAODOutputModule::openFile(edm::FileBlock const&) { - m_file = std::make_unique(m_fileName.c_str(), "RECREATE", "", m_compressionLevel); +void +NanoAODOutputModule::openFile(edm::FileBlock const&) { + m_file = std::make_unique(m_fileName.c_str(),"RECREATE","",m_compressionLevel); edm::Service jr; cms::Digest branchHash; m_jrToken = jr->outputFileOpened(m_fileName, m_logicalFileName, std::string(), - m_fakeName ? "PoolOutputModule" : "NanoAODOutputModule", + m_fakeName?"PoolOutputModule":"NanoAODOutputModule", description().moduleLabel(), edm::createGlobalIdentifier(), std::string(), branchHash.digest().toString(), - std::vector()); + std::vector() + ); if (m_compressionAlgorithm == std::string("ZLIB")) { - m_file->SetCompressionAlgorithm(ROOT::kZLIB); - } else if (m_compressionAlgorithm == std::string("LZMA")) { - m_file->SetCompressionAlgorithm(ROOT::kLZMA); - } else { - throw cms::Exception("Configuration") - << "NanoAODOutputModule configured with unknown compression algorithm '" << m_compressionAlgorithm << "'\n" - << "Allowed compression algorithms are ZLIB and LZMA\n"; - } + m_file->SetCompressionAlgorithm(ROOT::kZLIB); + } else if (m_compressionAlgorithm == std::string("LZMA")) { + m_file->SetCompressionAlgorithm(ROOT::kLZMA); + } else { + throw cms::Exception("Configuration") << "NanoAODOutputModule configured with unknown compression algorithm '" << m_compressionAlgorithm << "'\n" + << "Allowed compression algorithms are ZLIB and LZMA\n"; + } /* Setup file structure here */ m_tables.clear(); + m_tableTokens.clear(); m_triggers.clear(); - m_triggers_areSorted = false; m_evstrings.clear(); m_runTables.clear(); - m_lumiTables.clear(); - m_lumiTables2.clear(); - m_runFlatTables.clear(); const auto& keeps = keptProducts(); for (const auto& keep : keeps[edm::InEvent]) { - if (keep.first->className() == "nanoaod::FlatTable") - m_tables.emplace_back(keep.first, keep.second); - else if (keep.first->className() == "edm::TriggerResults") { + if (keep.first->className() == "nanoaod::FlatTable") { + m_tableTokens.emplace_back(keep.second); + } else if (keep.first->className() == "std::vector") { + m_tableVectorTokens.emplace_back(keep.second); + } else if (keep.first->className() == "edm::TriggerResults") { m_triggers.emplace_back(keep.first, keep.second); } else if (keep.first->className() == "std::basic_string >" && keep.first->productInstanceName() == "genModel") { // friendlyClassName == "String" @@ -323,113 +312,97 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className()); } - for (const auto& keep : keeps[edm::InLumi]) { - if (keep.first->className() == "nanoaod::MergeableCounterTable") - m_lumiTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); - else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") - m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); - else if (keep.first->className() == "nanoaod::FlatTable") - m_lumiTables2.push_back(LumiOutputBranches(keep.first, keep.second)); - else - throw cms::Exception( - "Configuration", - "NanoAODOutputModule cannot handle class " + keep.first->className() + " in LuminosityBlock branch"); + for (const auto & keep : keeps[edm::InRun]) { + if(keep.first->className() == "nanoaod::MergeableCounterTable" ) + m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); + else if(keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") + m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); + else throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className() + " in Run branch"); } - for (const auto& keep : keeps[edm::InRun]) { - if (keep.first->className() == "nanoaod::MergeableCounterTable") - m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); - else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") - m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); - else if (keep.first->className() == "nanoaod::FlatTable") - m_runFlatTables.emplace_back(keep.first, keep.second); - else - throw cms::Exception("Configuration", - "NanoAODOutputModule cannot handle class " + keep.first->className() + " in Run branch"); - } // create the trees - m_tree = std::make_unique("Events", "Events"); + m_tree.reset(new TTree("Events","Events")); m_tree->SetAutoSave(0); m_tree->SetAutoFlush(0); m_commonBranches.branch(*m_tree); - m_lumiTree = std::make_unique("LuminosityBlocks", "LuminosityBlocks"); + m_lumiTree.reset(new TTree("LuminosityBlocks","LuminosityBlocks")); m_lumiTree->SetAutoSave(0); m_commonLumiBranches.branch(*m_lumiTree); - m_runTree = std::make_unique("Runs", "Runs"); + m_runTree.reset(new TTree("Runs","Runs")); m_runTree->SetAutoSave(0); m_commonRunBranches.branch(*m_runTree); - + if (m_writeProvenance) { - m_metaDataTree = std::make_unique(edm::poolNames::metaDataTreeName().c_str(), "Job metadata"); - m_metaDataTree->SetAutoSave(0); - m_parameterSetsTree = std::make_unique(edm::poolNames::parameterSetsTreeName().c_str(), "Parameter sets"); - m_parameterSetsTree->SetAutoSave(0); + m_metaDataTree.reset(new TTree(edm::poolNames::metaDataTreeName().c_str(),"Job metadata")); + m_metaDataTree->SetAutoSave(0); + m_parameterSetsTree.reset(new TTree(edm::poolNames::parameterSetsTreeName().c_str(),"Parameter sets")); + m_parameterSetsTree->SetAutoSave(0); } } -void NanoAODOutputModule::reallyCloseFile() { +void +NanoAODOutputModule::reallyCloseFile() { if (m_writeProvenance) { - int basketSize = 16384; // fixme configurable? - edm::fillParameterSetBranch(m_parameterSetsTree.get(), basketSize); - edm::fillProcessHistoryBranch(m_metaDataTree.get(), basketSize, m_processHistoryRegistry); - if (m_metaDataTree->GetNbranches() != 0) { - m_metaDataTree->SetEntries(-1); - } - if (m_parameterSetsTree->GetNbranches() != 0) { - m_parameterSetsTree->SetEntries(-1); - } + int basketSize = 16384; // fixme configurable? + edm::fillParameterSetBranch(m_parameterSetsTree.get(), basketSize); + edm::fillProcessHistoryBranch(m_metaDataTree.get(), basketSize, m_processHistoryRegistry); + if (m_metaDataTree->GetNbranches() != 0) { + m_metaDataTree->SetEntries(-1); + } + if (m_parameterSetsTree->GetNbranches() != 0) { + m_parameterSetsTree->SetEntries(-1); + } } m_file->Write(); m_file->Close(); m_file.reset(); - m_tree.release(); // apparently root has ownership - m_lumiTree.release(); // - m_runTree.release(); // - m_metaDataTree.release(); // - m_parameterSetsTree.release(); // + m_tree.release(); // apparently root has ownership + m_lumiTree.release(); // + m_runTree.release(); // + m_metaDataTree.release(); // + m_parameterSetsTree.release(); // edm::Service jr; jr->outputFileClosed(m_jrToken); } -void NanoAODOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { +void +NanoAODOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; desc.addUntracked("fileName"); - desc.addUntracked("logicalFileName", ""); + desc.addUntracked("logicalFileName",""); - desc.addUntracked("compressionLevel", 9)->setComment("ROOT compression level of output file."); + desc.addUntracked("compressionLevel", 9) + ->setComment("ROOT compression level of output file."); desc.addUntracked("compressionAlgorithm", "ZLIB") - ->setComment("Algorithm used to compress data in the ROOT output file, allowed values are ZLIB and LZMA"); + ->setComment("Algorithm used to compress data in the ROOT output file, allowed values are ZLIB and LZMA"); desc.addUntracked("saveProvenance", true) - ->setComment("Save process provenance information, e.g. for edmProvDump"); + ->setComment("Save process provenance information, e.g. for edmProvDump"); desc.addUntracked("fakeNameForCrab", false) - ->setComment( - "Change the OutputModule name in the fwk job report to fake PoolOutputModule. This is needed to run on cran " - "(and publish) till crab is fixed"); - desc.addUntracked("autoFlush", -10000000)->setComment("Autoflush parameter for ROOT file"); + ->setComment("Change the OutputModule name in the fwk job report to fake PoolOutputModule. This is needed to run on cran (and publish) till crab is fixed"); + desc.addUntracked("autoFlush", -10000000) + ->setComment("Autoflush parameter for ROOT file"); //replace with whatever you want to get from the EDM by default - const std::vector keep = {"drop *", - "keep nanoaodFlatTable_*Table_*_*", - "keep edmTriggerResults_*_*_*", - "keep String_*_genModel_*", - "keep nanoaodMergeableCounterTable_*Table_*_*", - "keep nanoaodUniqueString_nanoMetadata_*_*"}; - edm::one::OutputModule<>::fillDescription(desc, keep); - + const std::vector keep = {"drop *", "keep nanoaodFlatTable_*Table_*_*", "keep edmTriggerResults_*_*_*", "keep String_*_genModel_*", "keep nanoaodMergeableCounterTable_*Table_*_*", "keep nanoaodUniqueString_nanoMetadata_*_*"}; + edm::OutputModule::fillDescription(desc, keep); + //Used by Workflow management for their own meta data edm::ParameterSetDescription dataSet; dataSet.setAllowAnything(); desc.addUntracked("dataset", dataSet) - ->setComment("PSet is only used by Data Operations and not by this module."); - + ->setComment("PSet is only used by Data Operations and not by this module."); + edm::ParameterSetDescription branchSet; branchSet.setAllowAnything(); desc.add("branches", branchSet); + + descriptions.addDefault(desc); + } DEFINE_FWK_MODULE(NanoAODOutputModule); diff --git a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc index 9e0c46d2f99c9..4f411b12dfe55 100644 --- a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc +++ b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc @@ -13,26 +13,18 @@ void TableOutputBranches::defineBranchesFromFirstEvent(const nanoaod::FlatTable for (size_t i = 0; i < tab.nColumns(); i++) { const std::string &var = tab.columnName(i); switch (tab.columnType(i)) { - case nanoaod::FlatTable::ColumnType::Float: + case (nanoaod::FlatTable::FloatColumn): m_floatBranches.emplace_back(var, tab.columnDoc(i), "F"); break; - case nanoaod::FlatTable::ColumnType::Int: + case (nanoaod::FlatTable::IntColumn): m_intBranches.emplace_back(var, tab.columnDoc(i), "I"); break; - case nanoaod::FlatTable::ColumnType::UInt8: + case (nanoaod::FlatTable::UInt8Column): m_uint8Branches.emplace_back(var, tab.columnDoc(i), "b"); break; - case nanoaod::FlatTable::ColumnType::Bool: + case (nanoaod::FlatTable::BoolColumn): m_uint8Branches.emplace_back(var, tab.columnDoc(i), "O"); break; - case nanoaod::FlatTable::ColumnType::UInt32: - m_uint32Branches.emplace_back(var, tab.columnDoc(i), "i"); - break; - case nanoaod::FlatTable::ColumnType::Double: - m_doubleBranches.emplace_back(var, tab.columnDoc(i), "D"); - break; - default: - throw cms::Exception("LogicError", "Unsupported type"); } } } @@ -55,8 +47,7 @@ void TableOutputBranches::branch(TTree &tree) { } } std::string varsize = m_singleton ? "" : "[n" + m_baseName + "]"; - for (std::vector *branches : - {&m_floatBranches, &m_intBranches, &m_uint8Branches, &m_uint32Branches, &m_doubleBranches}) { + for (std::vector *branches : {&m_floatBranches, &m_intBranches, &m_uint8Branches}) { for (auto &pair : *branches) { std::string branchName = makeBranchName(m_baseName, pair.name); pair.branch = @@ -66,15 +57,12 @@ void TableOutputBranches::branch(TTree &tree) { } } -void TableOutputBranches::fill(const edm::OccurrenceForOutput &iWhatever, TTree &tree, bool extensions) { +void TableOutputBranches::fill(const nanoaod::FlatTable &tab, TTree &tree, bool extensions) { if (m_extension != DontKnowYetIfMainOrExtension) { if (extensions != m_extension) return; // do nothing, wait to be called with the proper flag } - edm::Handle handle; - iWhatever.getByToken(m_token, handle); - const nanoaod::FlatTable &tab = *handle; m_counter = tab.size(); m_singleton = tab.singleton(); if (!m_branchesBooked) { @@ -98,8 +86,4 @@ void TableOutputBranches::fill(const edm::OccurrenceForOutput &iWhatever, TTree fillColumn(pair, tab); for (auto &pair : m_uint8Branches) fillColumn(pair, tab); - for (auto &pair : m_uint32Branches) - fillColumn(pair, tab); - for (auto &pair : m_doubleBranches) - fillColumn(pair, tab); } diff --git a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h index 148f0dc9b67f2..c8e4366e48539 100644 --- a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h +++ b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h @@ -4,31 +4,23 @@ #include #include #include -#include "FWCore/Framework/interface/OccurrenceForOutput.h" #include "DataFormats/NanoAOD/interface/FlatTable.h" #include "DataFormats/Provenance/interface/BranchDescription.h" #include "FWCore/Utilities/interface/EDGetToken.h" class TableOutputBranches { public: - TableOutputBranches(const edm::BranchDescription *desc, const edm::EDGetToken &token) - : m_token(token), m_extension(DontKnowYetIfMainOrExtension), m_branchesBooked(false) { - if (desc->className() != "nanoaod::FlatTable") - throw cms::Exception("Configuration", "NanoAODOutputModule can only write out nanoaod::FlatTable objects"); - } - void defineBranchesFromFirstEvent(const nanoaod::FlatTable &tab); void branch(TTree &tree); /// Fill the current table, if extensions == table.extension(). /// This parameter is used so that the fill is called first for non-extensions and then for extensions - void fill(const edm::OccurrenceForOutput &iWhatever, TTree &tree, bool extensions); + void fill(const nanoaod::FlatTable &tab, TTree &tree, bool extensions); private: - edm::EDGetToken m_token; std::string m_baseName; bool m_singleton; - enum { IsMain = 0, IsExtension = 1, DontKnowYetIfMainOrExtension = 2 } m_extension; + enum { IsMain = 0, IsExtension = 1, DontKnowYetIfMainOrExtension = 2 } m_extension = DontKnowYetIfMainOrExtension; std::string m_doc; UInt_t m_counter; struct NamedBranchPtr { @@ -44,9 +36,7 @@ class TableOutputBranches { std::vector m_floatBranches; std::vector m_intBranches; std::vector m_uint8Branches; - std::vector m_uint32Branches; - std::vector m_doubleBranches; - bool m_branchesBooked; + bool m_branchesBooked = false; template void fillColumn(NamedBranchPtr &pair, const nanoaod::FlatTable &tab) { diff --git a/PhysicsTools/NanoAOD/python/nano_cff.py b/PhysicsTools/NanoAOD/python/nano_cff.py index 23de15d98e814..8a13b7dda4d11 100644 --- a/PhysicsTools/NanoAOD/python/nano_cff.py +++ b/PhysicsTools/NanoAOD/python/nano_cff.py @@ -1,29 +1,29 @@ from __future__ import print_function import FWCore.ParameterSet.Config as cms from PhysicsTools.NanoAOD.common_cff import * -from PhysicsTools.NanoAOD.nano_eras_cff import * from PhysicsTools.NanoAOD.jets_cff import * from PhysicsTools.NanoAOD.muons_cff import * from PhysicsTools.NanoAOD.taus_cff import * -from PhysicsTools.NanoAOD.boostedTaus_cff import * from PhysicsTools.NanoAOD.electrons_cff import * -from PhysicsTools.NanoAOD.lowPtElectrons_cff import * from PhysicsTools.NanoAOD.photons_cff import * from PhysicsTools.NanoAOD.globals_cff import * from PhysicsTools.NanoAOD.extraflags_cff import * from PhysicsTools.NanoAOD.ttbarCategorization_cff import * from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * -from PhysicsTools.NanoAOD.genWeightsTable_cfi import * -from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.vertices_cff import * from PhysicsTools.NanoAOD.met_cff import * from PhysicsTools.NanoAOD.triggerObjects_cff import * from PhysicsTools.NanoAOD.isotracks_cff import * -from PhysicsTools.NanoAOD.protons_cff import * -from PhysicsTools.NanoAOD.btagWeightTable_cff import * from PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff import * +from PhysicsTools.NanoAOD.genWeightsTable_cfi import * +from Configuration.Eras.Modifier_run2_miniAOD_80XLegacy_cff import run2_miniAOD_80XLegacy +from Configuration.Eras.Modifier_run2_nanoAOD_94X2016_cff import run2_nanoAOD_94X2016 +from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv1_cff import run2_nanoAOD_94XMiniAODv1 +from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv2_cff import run2_nanoAOD_94XMiniAODv2 +from Configuration.Eras.Modifier_run2_nanoAOD_102Xv1_cff import run2_nanoAOD_102Xv1 +from Configuration.Eras.Modifier_run2_nanoAOD_106Xv1_cff import run2_nanoAOD_106Xv1 nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( @@ -56,70 +56,104 @@ tauName=cms.string("Tau"),photonName=cms.string("Photon") ) - -lhcInfoTable = cms.EDProducer("LHCInfoProducer", - precision = cms.int32(10), +btagSFdir="PhysicsTools/NanoAOD/data/btagSF/" + +btagWeightTable = cms.EDProducer("BTagSFProducer", + src = cms.InputTag("linkedObjects","jets"), + cut = cms.string("pt > 25. && abs(eta) < 2.5"), + discNames = cms.vstring( + "pfCombinedInclusiveSecondaryVertexV2BJetTags", + "pfDeepCSVJetTags:probb+pfDeepCSVJetTags:probbb", #if multiple MiniAOD branches need to be summed up (e.g., DeepCSV b+bb), separate them using '+' delimiter + "pfCombinedMVAV2BJetTags" + ), + discShortNames = cms.vstring( + "CSVV2", + "DeepCSVB", + "CMVA" + ), + weightFiles = cms.vstring( #default settings are for 2017 94X. toModify function is called later for other eras. + btagSFdir+"CSVv2_94XSF_V2_B_F.csv", + btagSFdir+"DeepCSV_94XSF_V2_B_F.csv", + "unavailable" #if SFs for an algorithm in an era is unavailable, the corresponding branch will not be stored + ), + operatingPoints = cms.vstring("3","3","3"), #loose = 0, medium = 1, tight = 2, reshaping = 3 + measurementTypesB = cms.vstring("iterativefit","iterativefit","iterativefit"), #e.g. "comb", "incl", "ttbar", "iterativefit" + measurementTypesC = cms.vstring("iterativefit","iterativefit","iterativefit"), + measurementTypesUDSG = cms.vstring("iterativefit","iterativefit","iterativefit"), + sysTypes = cms.vstring("central","central","central") ) -nanoTableTaskCommon = cms.Task( - cms.Task(nanoMetadata), jetTask, extraFlagsProducersTask, muonTask, tauTask, boostedTauTask, - electronTask , lowPtElectronTask, photonTask, - vertexTask, isoTrackTask, jetLepTask, # must be after all the leptons - cms.Task(linkedObjects), - jetTablesTask, muonTablesTask, tauTablesTask, boostedTauTablesTask, - electronTablesTask, lowPtElectronTablesTask, photonTablesTask, - globalTablesTask, vertexTablesTask, metTablesTask, simpleCleanerTable, extraFlagsTableTask, - isoTrackTablesTask - ) +for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: # to be updated when SF for Summer16MiniAODv3 MC will be available + modifier.toModify(btagWeightTable, + cut = cms.string("pt > 25. && abs(eta) < 2.4"), #80X corresponds to 2016, |eta| < 2.4 + weightFiles = cms.vstring( #80X corresponds to 2016 SFs + btagSFdir+"CSVv2_Moriond17_B_H.csv", + "unavailable", + btagSFdir+"cMVAv2_Moriond17_B_H.csv" + ) + ) -nanoSequenceCommon = cms.Sequence(nanoTableTaskCommon) -nanoSequenceOnlyFullSim = cms.Sequence(triggerObjectTablesTask) -nanoSequenceOnlyData = cms.Sequence(cms.Sequence(protonTablesTask) + lhcInfoTable) +genWeightsTable = cms.EDProducer("GenWeightsTableProducer", + genEvent = cms.InputTag("generator"), + genLumiInfoHeader = cms.InputTag("generator"), + lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), + preferredPDFs = cms.VPSet( # see https://lhapdf.hepforge.org/pdfsets.html + cms.PSet( name = cms.string("PDF4LHC15_nnlo_30_pdfas"), lhaid = cms.uint32(91400) ), + cms.PSet( name = cms.string("NNPDF31_nnlo_hessian_pdfas"), lhaid = cms.uint32(306000) ), + cms.PSet( name = cms.string("NNPDF30_nlo_as_0118"), lhaid = cms.uint32(260000) ), # for some 92X samples. Note that the nominal weight, 260000, is not included in the LHE ... + cms.PSet( name = cms.string("NNPDF30_lo_as_0130"), lhaid = cms.uint32(262000) ), # some MLM 80X samples have only this (e.g. /store/mc/RunIISummer16MiniAODv2/DYJetsToLL_M-50_TuneCUETP8M1_13TeV-madgraphMLM-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6_ext1-v2/120000/02A210D6-F5C3-E611-B570-008CFA197BD4.root ) + cms.PSet( name = cms.string("NNPDF30_nlo_nf_4_pdfas"), lhaid = cms.uint32(292000) ), # some FXFX 80X samples have only this (e.g. WWTo1L1Nu2Q, WWTo4Q) + cms.PSet( name = cms.string("NNPDF30_nlo_nf_5_pdfas"), lhaid = cms.uint32(292200) ), # some FXFX 80X samples have only this (e.g. DYJetsToLL_Pt, WJetsToLNu_Pt, DYJetsToNuNu_Pt) + ), + namedWeightIDs = cms.vstring(), + namedWeightLabels = cms.vstring(), + lheWeightPrecision = cms.int32(14), + maxPdfWeights = cms.uint32(150), + debug = cms.untracked.bool(False), +) +lheInfoTable = cms.EDProducer("LHETablesProducer", + lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), + precision = cms.int32(14), + storeLHEParticles = cms.bool(True), + storeAllLHEInfo = cms.bool(False), +) -nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyData + nanoSequenceOnlyFullSim) +l1bits=cms.EDProducer("L1TriggerResultsConverter", src=cms.InputTag("gtStage2Digis"), legacyL1=cms.bool(False), + storeUnprefireableBit=cms.bool(True), src_ext=cms.InputTag("gtStage2Digis")) +(run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1).toModify(l1bits, storeUnprefireableBit=False) -nanoTableTaskFS = cms.Task(genParticleTask, particleLevelTask, jetMCTask, muonMCTask, electronMCTask, lowPtElectronMCTask, photonMCTask, - tauMCTask, boostedTauMCTask, - metMCTable, ttbarCatMCProducersTask, globalTablesMCTask, cms.Task(btagWeightTable), ttbarCategoryTableTask, - genWeightsTableTask, genVertexTablesTask, genParticleTablesTask, particleLevelTablesTask) +nanoSequenceCommon = cms.Sequence( + nanoMetadata + jetSequence + muonSequence + tauSequence + electronSequence+photonSequence+vertexSequence+ + isoTrackSequence + # must be after all the leptons + linkedObjects + + jetTables + muonTables + tauTables + electronTables + photonTables + globalTables +vertexTables+ metTables+simpleCleanerTable + isoTrackTables + ) +nanoSequenceOnlyFullSim = cms.Sequence(triggerObjectTables + l1bits) -nanoSequenceFS = cms.Sequence(nanoSequenceCommon + cms.Sequence(nanoTableTaskFS)) +nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyFullSim) + +nanoSequenceFS = cms.Sequence(genParticleSequence + particleLevelSequence + nanoSequenceCommon + jetMC + muonMC + electronMC + photonMC + tauMC + metMC + ttbarCatMCProducers + globalTablesMC + btagWeightTable + genWeightsTable + genParticleTables + particleLevelTables + lheInfoTable + ttbarCategoryTable ) -# GenVertex only stored in newer MiniAOD nanoSequenceMC = nanoSequenceFS.copy() nanoSequenceMC.insert(nanoSequenceFS.index(nanoSequenceCommon)+1,nanoSequenceOnlyFullSim) +# modify extraFlagsTable to store ecalBadCalibFilter decision which is re-run with updated bad crystal list for 2017 and 2018 samples +for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1: + modifier.toModify(extraFlagsTable, variables= cms.PSet()) + modifier.toModify(extraFlagsTable, variables = dict(Flag_ecalBadCalibFilterV2 = ExtVar(cms.InputTag("ecalBadCalibFilterNanoTagger"), bool, doc = "Bad ECAL calib flag (updated xtal list)"))) + # modifier which adds new tauIDs (currently only deepTauId2017v2p1 is being added) import RecoTauTag.RecoTau.tools.runTauIdMVA as tauIdConfig def nanoAOD_addTauIds(process): updatedTauName = "slimmedTausUpdated" - tauIdEmbedder = tauIdConfig.TauIDEmbedder(process, debug = False, updatedTauName = updatedTauName, + tauIdEmbedder = tauIdConfig.TauIDEmbedder(process, cms, debug = False, updatedTauName = updatedTauName, toKeep = [ "deepTau2017v2p1" ]) tauIdEmbedder.runTauID() - _tauTask = patTauMVAIDsTask.copy() - _tauTask.add(process.rerunMvaIsolationTask) - _tauTask.add(finalTaus) - process.tauTask = _tauTask.copy() + process.patTauMVAIDsSeq.insert(process.patTauMVAIDsSeq.index(getattr(process, updatedTauName)), + process.rerunMvaIsolationSequence) return process -def nanoAOD_addBoostedTauIds(process): - updatedBoostedTauName = "slimmedTausBoostedNewID" - boostedTauIdEmbedder = tauIdConfig.TauIDEmbedder(process, debug=False, - originalTauName = "slimmedTausBoosted", - updatedTauName = updatedBoostedTauName, - postfix="Boosted", - toKeep = [ "2017v2", "dR0p32017v2", "newDM2017v2","againstEle2018",]) - boostedTauIdEmbedder.runTauID() - _boostedTauTask = process.rerunMvaIsolationTaskBoosted.copy() - _boostedTauTask.add(getattr(process, updatedBoostedTauName)) - _boostedTauTask.add(process.finalBoostedTaus) - - process.boostedTauTask = _boostedTauTask.copy() - - return process - - from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection def nanoAOD_addDeepInfo(process,addDeepBTag,addDeepFlavour): _btagDiscriminators=[] @@ -143,98 +177,56 @@ def nanoAOD_addDeepInfo(process,addDeepBTag,addDeepFlavour): process.updatedJets.jetSource="selectedUpdatedPatJetsWithDeepInfo" return process - from PhysicsTools.PatUtils.tools.runMETCorrectionsAndUncertainties import runMetCorAndUncFromMiniAOD +#from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD def nanoAOD_recalibrateMETs(process,isData): - # add DeepMETs - nanoAOD_DeepMET_switch = cms.PSet( - ResponseTune_Graph = cms.untracked.string('RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2018.pb') - ) - for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: - modifier.toModify(nanoAOD_DeepMET_switch, ResponseTune_Graph=cms.untracked.string("RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2016.pb")) - - print("add DeepMET Producers") - process.load('RecoMET.METPUSubtraction.deepMETProducer_cfi') - process.deepMETsResolutionTune = process.deepMETProducer.clone() - process.deepMETsResponseTune = process.deepMETProducer.clone() - process.deepMETsResponseTune.graph_path = nanoAOD_DeepMET_switch.ResponseTune_Graph.value() - runMetCorAndUncFromMiniAOD(process,isData=isData) - process.nanoSequenceCommon.insert(2,cms.Sequence(process.fullPatMetSequence)) - - - from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD - makePuppiesFromMiniAOD(process,True) - process.puppiNoLep.useExistingWeights = True - process.puppi.useExistingWeights = True - run2_nanoAOD_106Xv1.toModify(process.puppiNoLep, useExistingWeights = False) - run2_nanoAOD_106Xv1.toModify(process.puppi, useExistingWeights = False) - print("will make Puppies on top of MINIAOD") - + process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.fullPatMetSequence)) + process.basicJetsForMetForT1METNano = process.basicJetsForMet.clone( + src = process.updatedJetsWithUserData.src, + skipEM = False, + type1JetPtThreshold = 0.0, + calcMuonSubtrRawPtAsValueMap = cms.bool(True), + ) + process.jetSequence.insert(process.jetSequence.index(process.updatedJetsWithUserData),cms.Sequence(process.basicJetsForMetForT1METNano)) + process.updatedJetsWithUserData.userFloats.muonSubtrRawPt = cms.InputTag("basicJetsForMetForT1METNano:MuonSubtrRawPt") + process.corrT1METJetTable.src = process.finalJets.src + process.corrT1METJetTable.cut = "pt<15 && abs(eta)<9.9" + for table in process.jetTable, process.corrT1METJetTable: + table.variables.muonSubtrFactor = Var("1-userFloat('muonSubtrRawPt')/(pt()*jecFactor('Uncorrected'))",float,doc="1-(muon-subtracted raw pt)/(raw pt)",precision=6) + process.metTables += process.corrT1METJetTable # makePuppiesFromMiniAOD(process,True) # call this before in the global customizer otherwise it would reset photon IDs in VID - nanoAOD_PuppiV15_switch = cms.PSet( - recoMetFromPFCs = cms.untracked.bool(False), - reclusterJets = cms.untracked.bool(False), - ) - run2_nanoAOD_106Xv1.toModify(nanoAOD_PuppiV15_switch,recoMetFromPFCs=True,reclusterJets=True) - if nanoAOD_PuppiV15_switch.reclusterJets: - from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets - from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask, addToProcessAndTask - task = getPatAlgosToolsTask(process) - addToProcessAndTask('ak4PuppiJets', ak4PFJets.clone (src = 'puppi', doAreaFastjet = True, jetPtMin = 10.), process, task) - from PhysicsTools.PatAlgos.tools.jetTools import addJetCollection - addJetCollection(process, - labelName = 'Puppi', - jetSource = cms.InputTag('ak4PuppiJets'), - algo = 'AK', rParam=0.4, - genJetCollection=cms.InputTag('slimmedGenJets'), - jetCorrections = ('AK4PFPuppi', ['L1FastJet', 'L2Relative', 'L3Absolute','L2L3Residual'], 'None'), - pfCandidates = cms.InputTag('packedPFCandidates'), - pvSource = cms.InputTag('offlineSlimmedPrimaryVertices'), - svSource = cms.InputTag('slimmedSecondaryVertices'), - muSource =cms.InputTag( 'slimmedMuons'), - elSource = cms.InputTag('slimmedElectrons'), - genParticles= cms.InputTag('prunedGenParticles'), - getJetMCFlavour= False - ) - - process.patJetsPuppi.addGenPartonMatch = cms.bool(False) - process.patJetsPuppi.addGenJetMatch = cms.bool(False) - - print("nanoAOD_PuppiV15_switch.reclusterJets is true") - - runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi", recoMetFromPFCs=bool(nanoAOD_PuppiV15_switch.recoMetFromPFCs), reclusterJets=bool(nanoAOD_PuppiV15_switch.reclusterJets)) - process.nanoSequenceCommon.insert(2,cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) - +# runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi") +# process.puppiNoLep.useExistingWeights = False +# process.puppi.useExistingWeights = False +# process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(jetSequence),cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) return process from PhysicsTools.SelectorUtils.tools.vid_id_tools import * def nanoAOD_activateVID(process): - - switchOnVIDElectronIdProducer(process,DataFormat.MiniAOD,electronTask) + switchOnVIDElectronIdProducer(process,DataFormat.MiniAOD) for modname in electron_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDElectronSelection) - - electronTask_ = process.egmGsfElectronIDTask.copy() - electronTask_.add(electronTask.copy()) - process.electronTask = electronTask_.copy() - for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: + process.electronSequence.insert(process.electronSequence.index(process.bitmapVIDForEle),process.egmGsfElectronIDSequence) + for modifier in run2_miniAOD_80XLegacy, : modifier.toModify(process.electronMVAValueMapProducer, src = "slimmedElectronsUpdated") modifier.toModify(process.egmGsfElectronIDs, physicsObjectSrc = "slimmedElectronsUpdated") + for modifier in run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016 ,run2_nanoAOD_102Xv1: + modifier.toModify(process.electronMVAValueMapProducer, src = "slimmedElectronsTo106X") + modifier.toModify(process.egmGsfElectronIDs, physicsObjectSrc = "slimmedElectronsTo106X") + + - switchOnVIDPhotonIdProducer(process,DataFormat.MiniAOD,photonTask) # do not call this to avoid resetting photon IDs in VID, if called before inside makePuppiesFromMiniAOD + switchOnVIDPhotonIdProducer(process,DataFormat.MiniAOD) # do not call this to avoid resetting photon IDs in VID, if called before inside makePuppiesFromMiniAOD for modname in photon_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDPhotonSelection) - - photonTask_ = process.egmPhotonIDTask.copy() - photonTask_.add(photonTask.copy()) - process.photonTask = photonTask_.copy() - for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1: + process.photonSequence.insert(process.photonSequence.index(bitmapVIDForPho),process.egmPhotonIDSequence) + for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016 ,run2_nanoAOD_102Xv1: modifier.toModify(process.photonMVAValueMapProducer, src = "slimmedPhotonsTo106X") modifier.toModify(process.egmPhotonIDs, physicsObjectSrc = "slimmedPhotonsTo106X") return process -def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubleX, addDeepDoubleXV2, addParticleNet, addParticleNetMass, jecPayload): +def nanoAOD_addDeepInfoAK8(process,addDeepBTag,addDeepBoostedJet, addDeepDoubleX, jecPayload): _btagDiscriminators=[] if addDeepBTag: print("Updating process to run DeepCSV btag to AK8 jets") @@ -243,26 +235,12 @@ def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubl print("Updating process to run DeepBoostedJet on datasets before 103X") from RecoBTag.ONNXRuntime.pfDeepBoostedJet_cff import _pfDeepBoostedJetTagsAll as pfDeepBoostedJetTagsAll _btagDiscriminators += pfDeepBoostedJetTagsAll - if addParticleNet: - print("Updating process to run ParticleNet before it's included in MiniAOD") - from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetJetTagsAll as pfParticleNetJetTagsAll - _btagDiscriminators += pfParticleNetJetTagsAll - if addParticleNetMass: - from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetMassRegressionOutputs - _btagDiscriminators += _pfParticleNetMassRegressionOutputs - if addDeepDoubleX: + if addDeepDoubleX: print("Updating process to run DeepDoubleX on datasets before 104X") _btagDiscriminators += ['pfDeepDoubleBvLJetTags:probHbb', \ 'pfDeepDoubleCvLJetTags:probHcc', \ 'pfDeepDoubleCvBJetTags:probHcc', \ 'pfMassIndependentDeepDoubleBvLJetTags:probHbb', 'pfMassIndependentDeepDoubleCvLJetTags:probHcc', 'pfMassIndependentDeepDoubleCvBJetTags:probHcc'] - if addDeepDoubleXV2: - print("Updating process to run DeepDoubleXv2 on datasets before 11X") - _btagDiscriminators += [ - 'pfMassIndependentDeepDoubleBvLV2JetTags:probHbb', - 'pfMassIndependentDeepDoubleCvLV2JetTags:probHcc', - 'pfMassIndependentDeepDoubleCvBV2JetTags:probHcc' - ] if len(_btagDiscriminators)==0: return process print("Will recalculate the following discriminators on AK8 jets: "+", ".join(_btagDiscriminators)) updateJetCollection( @@ -286,38 +264,10 @@ def nanoAOD_runMETfixEE2017(process,isData): fixEE2017 = True, fixEE2017Params = {'userawPt': True, 'ptThreshold':50.0, 'minEtaThreshold':2.65, 'maxEtaThreshold': 3.139}, postfix = "FixEE2017") - process.nanoSequenceCommon.insert(2,process.fullPatMetSequenceFixEE2017) - - -def nanoAOD_jetForT1met(process): - process.basicJetsForMetForT1METNano = cms.EDProducer("PATJetCleanerForType1MET", - src = process.updatedJetsWithUserData.src, - jetCorrEtaMax = cms.double(9.9), - jetCorrLabel = cms.InputTag("L3Absolute"), - jetCorrLabelRes = cms.InputTag("L2L3Residual"), - offsetCorrLabel = cms.InputTag("L1FastJet"), - skipEM = cms.bool(False), - skipEMfractionThreshold = cms.double(0.9), - skipMuonSelection = cms.string('isGlobalMuon | isStandAloneMuon'), - skipMuons = cms.bool(True), - type1JetPtThreshold = cms.double(0.0), - calcMuonSubtrRawPtAsValueMap = cms.bool(True) - ) - - process.jetTask.add(process.basicJetsForMetForT1METNano) - process.updatedJetsWithUserData.userFloats.muonSubtrRawPt = cms.InputTag("basicJetsForMetForT1METNano:MuonSubtrRawPt") - process.corrT1METJetTable.src = process.finalJets.src - process.corrT1METJetTable.cut = "pt<15 && abs(eta)<9.9" - process.metTablesTask.add(process.corrT1METJetTable) - - for table in process.jetTable, process.corrT1METJetTable: - table.variables.muonSubtrFactor = Var("1-userFloat('muonSubtrRawPt')/(pt()*jecFactor('Uncorrected'))",float,doc="1-(muon-subtracted raw pt)/(raw pt)",precision=6) - - return process + process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(jetSequence),process.fullPatMetSequenceFixEE2017) def nanoAOD_customizeCommon(process): - - process = nanoAOD_jetForT1met(process) +# makePuppiesFromMiniAOD(process,True) # call this here as it calls switchOnVIDPhotonIdProducer process = nanoAOD_activateVID(process) nanoAOD_addDeepInfo_switch = cms.PSet( nanoAOD_addDeepBTag_switch = cms.untracked.bool(False), @@ -331,76 +281,53 @@ def nanoAOD_customizeCommon(process): addDeepFlavour=nanoAOD_addDeepInfo_switch.nanoAOD_addDeepFlavourTag_switch) nanoAOD_addDeepInfoAK8_switch = cms.PSet( nanoAOD_addDeepBTag_switch = cms.untracked.bool(False), - nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(False), - nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(False), - nanoAOD_addDeepDoubleXV2_switch = cms.untracked.bool(False), - nanoAOD_addParticleNet_switch = cms.untracked.bool(False), - nanoAOD_addParticleNetMass_switch = cms.untracked.bool(False), + nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(True), # will deactivate this in future miniAOD releases + nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(True), jecPayload = cms.untracked.string('AK8PFPuppi') ) # deepAK8 should not run on 80X, that contains ak8PFJetsCHS jets run2_miniAOD_80XLegacy.toModify(nanoAOD_addDeepInfoAK8_switch, - nanoAOD_addDeepBTag_switch = True, - jecPayload = 'AK8PFchs') - # for 94X and 102X samples: needs to run DeepAK8, DeepDoubleX and ParticleNet - (run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1).toModify( - nanoAOD_addDeepInfoAK8_switch, - nanoAOD_addDeepBoostedJet_switch = True, - nanoAOD_addDeepDoubleX_switch = True, - nanoAOD_addDeepDoubleXV2_switch = True, - nanoAOD_addParticleNet_switch = True, - nanoAOD_addParticleNetMass_switch = True, - ) - # for 106Xv1: only needs to run ParticleNet and DDXV2; DeepAK8, DeepDoubleX are already in MiniAOD - run2_nanoAOD_106Xv1.toModify( - nanoAOD_addDeepInfoAK8_switch, - nanoAOD_addDeepDoubleXV2_switch = True, - nanoAOD_addParticleNet_switch = True, - nanoAOD_addParticleNetMass_switch = True, - ) - - run2_nanoAOD_106Xv2.toModify( - nanoAOD_addDeepInfoAK8_switch, - nanoAOD_addParticleNetMass_switch = True, - ) - + nanoAOD_addDeepBTag_switch = cms.untracked.bool(True), + nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(False), + nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(False), + jecPayload = cms.untracked.string('AK8PFchs')) process = nanoAOD_addDeepInfoAK8(process, addDeepBTag=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBTag_switch, addDeepBoostedJet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBoostedJet_switch, addDeepDoubleX=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleX_switch, - addDeepDoubleXV2=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleXV2_switch, - addParticleNet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addParticleNet_switch, - addParticleNetMass=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addParticleNetMass_switch, jecPayload=nanoAOD_addDeepInfoAK8_switch.jecPayload) (run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1 | run2_nanoAOD_106Xv1).toModify(process, lambda p : nanoAOD_addTauIds(p)) - (~(run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1 | run2_nanoAOD_106Xv1)).toModify(process, lambda p : nanoAOD_addBoostedTauIds(p)) return process def nanoAOD_customizeData(process): process = nanoAOD_customizeCommon(process) - - for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94X2016,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: - modifier.toModify(process, lambda p: nanoAOD_recalibrateMETs(p,isData=True)) + process = nanoAOD_recalibrateMETs(process,isData=True) for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2: modifier.toModify(process, lambda p: nanoAOD_runMETfixEE2017(p,isData=True)) return process def nanoAOD_customizeMC(process): process = nanoAOD_customizeCommon(process) - for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94X2016,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: - modifier.toModify(process, lambda p: nanoAOD_recalibrateMETs(p,isData=False)) + process = nanoAOD_recalibrateMETs(process,isData=False) for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2: modifier.toModify(process, lambda p: nanoAOD_runMETfixEE2017(p,isData=False)) return process -###increasing the precision of selected GenParticles. -def nanoWmassGenCustomize(process): - pdgSelection="?(abs(pdgId) == 11|| abs(pdgId)==13 || abs(pdgId)==15 ||abs(pdgId)== 12 || abs(pdgId)== 14 || abs(pdgId)== 16|| abs(pdgId)== 24|| pdgId== 23)" - # Keep precision same as default RECO for selected particles - ptPrecision="{}?{}:{}".format(pdgSelection, CandVars.pt.precision.value(),genParticleTable.variables.pt.precision.value()) - process.genParticleTable.variables.pt.precision=cms.string(ptPrecision) - phiPrecision="{} ? {} : {}".format(pdgSelection, CandVars.phi.precision.value(), genParticleTable.variables.phi.precision.value()) - process.genParticleTable.variables.phi.precision=cms.string(phiPrecision) - etaPrecision="{} ? {} : {}".format(pdgSelection, CandVars.eta.precision.value(), genParticleTable.variables.eta.precision.value()) - process.genParticleTable.variables.eta.precision=cms.string(etaPrecision) - return process +### Era dependent customization +_80x_sequence = nanoSequenceCommon.copy() +#remove stuff +_80x_sequence.remove(isoTrackTables) +_80x_sequence.remove(isoTrackSequence) +#add stuff +_80x_sequence.insert(_80x_sequence.index(jetSequence), extraFlagsProducers) +_80x_sequence.insert(_80x_sequence.index(simpleCleanerTable)+1, extraFlagsTable) + +run2_miniAOD_80XLegacy.toReplaceWith( nanoSequenceCommon, _80x_sequence) + +_102x_sequence = nanoSequenceCommon.copy() +#add stuff +_102x_sequence.insert(_102x_sequence.index(jetSequence),extraFlagsProducers102x) +_102x_sequence.insert(_102x_sequence.index(simpleCleanerTable)+1,extraFlagsTable) + +for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1: + modifier.toReplaceWith(nanoSequenceCommon, _102x_sequence) diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index 3551f0442184a..6e81ab1ce2023 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -1,12 +1,37 @@ from PhysicsTools.NanoAOD.taus_cff import * from PhysicsTools.NanoAOD.jets_cff import * -from PhysicsTools.NanoAOD.globals_cff import genTable,genFilterTable -from PhysicsTools.NanoAOD.met_cff import metMCTable +from PhysicsTools.NanoAOD.globals_cff import * from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * +from PhysicsTools.NanoAOD.lheInfoTable_cfi import * from PhysicsTools.NanoAOD.genWeightsTable_cfi import * -from PhysicsTools.NanoAOD.genVertex_cff import * -from PhysicsTools.NanoAOD.common_cff import Var,CandVars + +genWeights = cms.EDProducer("GenWeightProductProducer", + genInfo = cms.InputTag("generator"), + genLumiInfoHeader = cms.InputTag("generator")) + +lheWeights = cms.EDProducer("LHEWeightProductProducer", + lheSourceLabels = cms.vstring(["externalLHEProducer", "source"]), + failIfInvalidXML = cms.untracked.bool(True) + #lheWeightSourceLabels = cms.vstring(["externalLHEProducer", "source"]) +) + +lheWeightsTable = cms.EDProducer( + "LHEWeightsTableProducer", + lheWeights = cms.VInputTag(["externalLHEProducer", "source", "lheWeights"]), + lheWeightPrecision = cms.int32(14), + genWeights = cms.InputTag("genWeights"), + # Warning: you can use a full string, but only the first character is read. + # Note also that the capitalization is important! For example, 'parton shower' + # must be lower case and 'PDF' must be capital + weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), + # Max number of groups to store for each type above, -1 ==> store all found + maxGroupsPerType = cms.vint32([-1, -1, -1, -1, 1]), + # If empty or not specified, no critieria is applied to filter on LHAPDF IDs + #pdfIds = cms.untracked.vint32([91400, 306000, 260000]), + #unknownOnlyIfEmpty = cms.untracked.vstring(['scale', 'PDF']), + #unknownOnlyIfAllEmpty = cms.untracked.bool(False), +) nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( @@ -14,145 +39,113 @@ ) ) +metGenTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("genMetTrue"), + name = cms.string("GenMET"), + doc = cms.string("Gen MET"), + singleton = cms.bool(True), + extension = cms.bool(False), + variables = cms.PSet( + pt = Var("pt", float, doc="pt", precision=10), + phi = Var("phi", float, doc="phi", precision=10), + ), +) + nanogenSequence = cms.Sequence( + genWeights+ + lheWeights+ nanoMetadata+ - cms.Sequence(particleLevelTask)+ + particleLevel+ genJetTable+ - patJetPartonsNano+ + patJetPartons+ genJetFlavourAssociation+ genJetFlavourTable+ genJetAK8Table+ genJetAK8FlavourAssociation+ genJetAK8FlavourTable+ - cms.Sequence(genTauTask)+ + tauGenJets+ + tauGenJetsSelectorAllHadrons+ + genVisTaus+ + genVisTauTable+ genTable+ - genFilterTable+ - cms.Sequence(genParticleTablesTask)+ - cms.Sequence(genVertexTablesTask)+ + genWeightsTable+ + lheWeightsTable+ + genParticleTables+ tautagger+ rivetProducerHTXS+ - cms.Sequence(particleLevelTablesTask)+ - metMCTable+ - genWeightsTable + particleLevelTables+ + metGenTable+ + lheInfoTable ) -def nanoGenCommonCustomize(process): - process.rivetMetTable.extension = False - process.lheInfoTable.storeLHEParticles = True - process.lheInfoTable.precision = 14 - process.genWeightsTable.keepAllPSWeights = True - process.genJetFlavourAssociation.jets = process.genJetTable.src - process.genJetFlavourTable.src = process.genJetTable.src - process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src - process.genJetAK8FlavourTable.src = process.genJetAK8Table.src - process.particleLevel.particleMaxEta = 999. - process.particleLevel.lepMinPt = 0. - process.particleLevel.lepMaxEta = 999. - process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" - # Same as default RECO - setGenPtPrecision(process, CandVars.pt.precision) - setGenEtaPrecision(process, CandVars.eta.precision) - setGenPhiPrecision(process, CandVars.phi.precision) - setGenMassPrecision(process, CandVars.mass.precision) +nanogenMiniSequence = cms.Sequence( + genWeights+ + lheWeights+ + nanoMetadata+ + mergedGenParticles+ + genParticles2HepMC+ + particleLevel+ + genJetTable+ + patJetPartons+ + genJetFlavourAssociation+ + genJetFlavourTable+ + genJetAK8Table+ + genJetAK8FlavourAssociation+ + genJetAK8FlavourTable+ + tauGenJets+ + tauGenJetsSelectorAllHadrons+ + genVisTaus+ + genVisTauTable+ + genTable+ + genWeightsTable+ + lheWeightsTable+ + genParticleTables+ + tautagger+ + genParticles2HepMCHiggsVtx+ + rivetProducerHTXS+ + particleLevelTables+ + metGenTable+ + lheInfoTable +) def customizeNanoGENFromMini(process): - process.nanogenSequence.insert(0, process.genParticles2HepMCHiggsVtx) - process.nanogenSequence.insert(0, process.genParticles2HepMC) - process.nanogenSequence.insert(0, process.mergedGenParticles) - - process.metMCTable.src = "slimmedMETs" - process.metMCTable.variables.pt = Var("genMET.pt", float, doc="pt") - process.metMCTable.variables.phi = Var("genMET.phi", float, doc="phi") - process.metMCTable.variables.phi.precision = CandVars.phi.precision - - process.rivetProducerHTXS.HepMCCollection = "genParticles2HepMCHiggsVtx:unsmeared" + # Why is this false by default?! + process.lheInfoTable.storeLHEParticles = True process.genParticleTable.src = "prunedGenParticles" - process.patJetPartonsNano.particles = "prunedGenParticles" + process.patJetPartons.particles = "prunedGenParticles" process.particleLevel.src = "genParticles2HepMC:unsmeared" + process.rivetProducerHTXS.HepMCCollection = "genParticles2HepMCHiggsVtx:unsmeared" process.genJetTable.src = "slimmedGenJets" + process.genJetFlavourAssociation.jets = process.genJetTable.src + process.genJetFlavourTable.src = process.genJetTable.src + process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" process.genJetAK8Table.src = "slimmedGenJetsAK8" - process.tauGenJetsForNano.GenParticles = "prunedGenParticles" + process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src + process.genJetAK8FlavourTable.src = process.genJetAK8Table.src + process.tauGenJets.GenParticles = "prunedGenParticles" process.genVisTaus.srcGenParticles = "prunedGenParticles" - nanoGenCommonCustomize(process) - return process def customizeNanoGEN(process): - process.metMCTable.src = "genMetTrue" - process.metMCTable.variables = cms.PSet(PTVars) - - process.rivetProducerHTXS.HepMCCollection = "generatorSmeared" + process.lheInfoTable.storeLHEParticles = True process.genParticleTable.src = "genParticles" - process.patJetPartonsNano.particles = "genParticles" + process.patJetPartons.particles = "genParticles" process.particleLevel.src = "generatorSmeared" + process.particleLevel.particleMaxEta = 999. + process.particleLevel.lepMinPt = 0. + process.particleLevel.lepMaxEta = 999. + process.rivetProducerHTXS.HepMCCollection = "generatorSmeared" process.genJetTable.src = "ak4GenJets" + process.genJetFlavourAssociation.jets = process.genJetTable.src + process.genJetFlavourTable.src = process.genJetTable.src + process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" process.genJetAK8Table.src = "ak8GenJets" - process.tauGenJetsForNano.GenParticles = "genParticles" + process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src + process.genJetAK8FlavourTable.src = process.genJetAK8Table.src + process.tauGenJets.GenParticles = "genParticles" process.genVisTaus.srcGenParticles = "genParticles" - # In case customizeNanoGENFromMini has already been called - process.nanogenSequence.remove(process.genParticles2HepMCHiggsVtx) - process.nanogenSequence.remove(process.genParticles2HepMC) - process.nanogenSequence.remove(process.mergedGenParticles) - nanoGenCommonCustomize(process) - return process - -# Prune gen particles with tight conditions applied in usual NanoAOD -def pruneGenParticlesNano(process): - process.finalGenParticles.src = process.genParticleTable.src.getModuleLabel() - process.genParticleTable.src = "finalGenParticles" - process.nanogenSequence.insert(0, process.finalGenParticles) - return process - -# Prune gen particles with conditions applied in usual MiniAOD -def pruneGenParticlesMini(process): - if process.nanogenSequence.contains(process.mergedGenParticles): - raise ValueError("Applying the MiniAOD genParticle pruner to MiniAOD is redunant. " \ - "Use a different customization.") - from PhysicsTools.PatAlgos.slimming.prunedGenParticles_cfi import prunedGenParticles - process.prunedGenParticles = prunedGenParticles.clone() - process.prunedGenParticles.src = "genParticles" - process.genParticleTable.src = "prunedGenParticles" - - process.nanogenSequence.insert(0, process.prunedGenParticles) - return process - -def setGenFullPrecision(process): - process = setGenPtPrecision(process, 23) - process = setGenEtaPrecision(process, 23) - process = setGenPhiPrecision(process, 23) - process = setGenMassPrecision(process, 23) - return process - -def setGenPtPrecision(process, precision): - process.genParticleTable.variables.pt.precision = precision - process.genJetTable.variables.pt.precision = precision - process.metMCTable.variables.pt.precision = precision - return process - -def setGenEtaPrecision(process, precision): - process.genParticleTable.variables.eta.precision = precision - process.genJetTable.variables.eta.precision = precision - return process - -def setGenPhiPrecision(process, precision): - process.genParticleTable.variables.phi.precision = precision - process.genJetTable.variables.phi.precision = precision - process.metMCTable.variables.phi.precision = precision - return process - -def setGenMassPrecision(process, precision): - process.genParticleTable.variables.mass.precision = precision - process.genJetTable.variables.mass.precision = precision - return process - -def setLHEFullPrecision(process): - process.lheInfoTable.precision = 23 - return process - -def setGenWeightsFullPrecision(process): - process.genWeightsTable.lheWeightPrecision = 23 return process diff --git a/PhysicsTools/NanoAOD/test/testNanoWeights.py b/PhysicsTools/NanoAOD/test/testNanoWeights.py new file mode 100644 index 0000000000000..54d17f85ac41c --- /dev/null +++ b/PhysicsTools/NanoAOD/test/testNanoWeights.py @@ -0,0 +1,34 @@ +import ROOT +import argparse + +def variableAndNumber(varName, tree): + countVar = "n"+varName + if not hasattr(tree, varName): + print("No variable %s found in file" % varName) + else: + count = getattr(tree, countVar) + var = getattr(tree, varName) + print("Found %i entries of %s in file" % (count, varName)) + branch = tree.GetBranch(varName) + print(" --> Desciption:%s" % branch.GetTitle()) + +parser = argparse.ArgumentParser() +parser.add_argument('inputFile', type=str, help='NanoAOD file to process') +args = parser.parse_args() + +rtfile = ROOT.TFile(args.inputFile) +tree = rtfile.Get("Events") +tree.GetEntry(0) +types = ["ScaleWeight", "PdfWeight", "MEParamWeight", "UnknownWeight", ] +variables = ["LHE"+t for t in types] +variables.append("GenPartonShowerWeight") +variables.extend(["Gen"+t for t in types]) + +for varName in variables: + variableAndNumber(varName, tree) + i = 1 + altName = varName + "AltSet%i" % i + while hasattr(tree, altName): + variableAndNumber(altName, tree) + i = i+1 + altName = varName + "AltSet%i" % i diff --git a/SimDataFormats/GeneratorProducts/BuildFile.xml b/SimDataFormats/GeneratorProducts/BuildFile.xml index b35ce8e95f1ff..2e9a7977ec404 100644 --- a/SimDataFormats/GeneratorProducts/BuildFile.xml +++ b/SimDataFormats/GeneratorProducts/BuildFile.xml @@ -4,6 +4,7 @@ + diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h new file mode 100644 index 0000000000000..550a886df1757 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -0,0 +1,48 @@ +#ifndef SimDataFormats_GeneratorProducts_GenWeightInfoProduct_h +#define SimDataFormats_GeneratorProducts_GenWeightInfoProduct_h + +#include +#include +#include +#include +#include + +//#include + +#include "DataFormats/Common/interface/OwnVector.h" +#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + struct WeightGroupData { + size_t index; + const gen::WeightGroupInfo* group; + }; +} // namespace gen + +class GenWeightInfoProduct { +public: + GenWeightInfoProduct() {} + GenWeightInfoProduct(edm::OwnVector& weightGroups); + GenWeightInfoProduct(const GenWeightInfoProduct& other); + GenWeightInfoProduct(GenWeightInfoProduct&& other); + ~GenWeightInfoProduct() {} + GenWeightInfoProduct& operator=(const GenWeightInfoProduct& other); + GenWeightInfoProduct& operator=(GenWeightInfoProduct&& other); + + const edm::OwnVector& allWeightGroupsInfo() const; + const gen::WeightGroupInfo* containingWeightGroupInfo(int index) const; + const gen::WeightGroupInfo* orderedWeightGroupInfo(int index) const; + std::vector weightGroupsByType(gen::WeightType type) const; + std::vector weightGroupIndicesByType(gen::WeightType type) const; + std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; + std::optional pdfGroupWithIndexByLHAID(int lhaid) const; + std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; + void addWeightGroupInfo(gen::WeightGroupInfo* info); + const int numberOfGroups() const { return weightGroupsInfo_.size(); } + +private: + edm::OwnVector weightGroupsInfo_; +}; + +#endif // GeneratorWeightInfo_LHEInterface_GenWeightInfoProduct_h diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h new file mode 100644 index 0000000000000..872ae29b65d9f --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -0,0 +1,52 @@ +#ifndef SimDataFormats_GeneratorProducts_GenWeightProduct_h +#define SimDataFormats_GeneratorProducts_GenWeightProduct_h + +#include +#include +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" + +typedef std::vector> WeightsContainer; + +class GenWeightProduct { +public: + GenWeightProduct() { + weightsVector_ = {}; + centralWeight_ = 1.; + } + GenWeightProduct(double w0) { + weightsVector_ = {}; + centralWeight_ = w0; + } + GenWeightProduct& operator=(GenWeightProduct&& other) { + weightsVector_ = std::move(other.weightsVector_); + centralWeight_ = other.centralWeight_; + return *this; + } + ~GenWeightProduct() {} + + void setNumWeightSets(int num) { weightsVector_.resize(num); } + void addWeightSet() { weightsVector_.push_back({}); } + void addWeight(double weight, int setEntry, int weightNum) { + if (weightsVector_.size() == 0 && setEntry == 0) + addWeightSet(); + if (static_cast(weightsVector_.size()) <= setEntry) + throw std::domain_error("Out of range weight"); + auto& weights = weightsVector_.at(setEntry); + if (static_cast(weights.size()) <= weightNum) { + weights.resize(weightNum + 1); + } + weights[weightNum] = weight / centralWeight_; + } + const WeightsContainer& weights() const { return weightsVector_; } + double centralWeight() const { return centralWeight_; } + +private: + WeightsContainer weightsVector_; + double centralWeight_; +}; + +#endif // GeneratorEvent_LHEInterface_GenWeightProduct_h diff --git a/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h new file mode 100644 index 0000000000000..2ea53a8d32adb --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h @@ -0,0 +1,33 @@ +#ifndef SimDataFormats_GeneratorProducts_MEParamWeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_MEParamWeightGroupInfo_h + +#include +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + class MEParamWeightGroupInfo : public WeightGroupInfo { + public: + MEParamWeightGroupInfo() : WeightGroupInfo() { weightType_ = WeightType::kMEParamWeights; } + MEParamWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { + weightType_ = WeightType::kMEParamWeights; + } + MEParamWeightGroupInfo(std::string header) : MEParamWeightGroupInfo(header, header) {} + virtual ~MEParamWeightGroupInfo() override {} + void copy(const MEParamWeightGroupInfo& other); + virtual MEParamWeightGroupInfo* clone() const override; + int getCentralIndex() { return centralIdx; } + int getVariationIndex(int sig) { return massValue.at(numSigma + sig).second; } + double getVariationValue(int sig) { return massValue.at(numSigma + sig).first; } + void updateWeight(int globalIndex, std::string id, double weight); + void updateWeight(int globalIndex, std::string id, std::vector& content); + + private: + std::unordered_map> splitContent; + std::vector> massValue; + double central; + int centralIdx; + int numSigma; + }; +} // namespace gen + +#endif // SimDataFormats_GeneratorProducts_MEParamWeightGroupInfo_h diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h new file mode 100644 index 0000000000000..59f67ce2e3a91 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -0,0 +1,39 @@ +#ifndef SimDataFormats_GeneratorProducts_PartonShowerWeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_PartonShowerWeightGroupInfo_h + +#include + +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + class PartonShowerWeightGroupInfo : public WeightGroupInfo { + public: + PartonShowerWeightGroupInfo() : PartonShowerWeightGroupInfo("") {} + PartonShowerWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { + weightType_ = WeightType::kPartonShowerWeights; + } + PartonShowerWeightGroupInfo(std::string header) : PartonShowerWeightGroupInfo(header, header) {} + PartonShowerWeightGroupInfo(const PartonShowerWeightGroupInfo &other) { copy(other); } + virtual ~PartonShowerWeightGroupInfo() override {} + void copy(const PartonShowerWeightGroupInfo &other); + virtual PartonShowerWeightGroupInfo *clone() const override; + + // TODO: replace these general functions with specific ones + int upIndex(std::string weightName) { + int index = weightIndexFromLabel(weightName+"Hi"); + return index >= 0 ? index : weightIndexFromLabel(weightName+"_up"); + } + int downIndex(std::string weightName) { + int index = weightIndexFromLabel(weightName+"Low"); + return index >= 0 ? index : weightIndexFromLabel(weightName+"_dn"); + } + std::vector getWeightNames() const { return weightNames; } + + private: + std::unordered_map> weightNameToUpDown; + std::vector weightNames; + // Is a variation of the functional form of the dynamic scale + }; +} // namespace gen + +#endif diff --git a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h index 5f1e5559f46e2..f04fb71ffa728 100644 --- a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h @@ -2,43 +2,61 @@ #define SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "LHAPDF/LHAPDF.h" +#include +#include +#include namespace gen { - enum PdfUncertaintyType { - kHessianUnc, - kMonteCarloUnc, - kUnknownUnc, - }; - - class PdfWeightGroupInfo : public WeightGroupInfo { - private: - PdfUncertaintyType uncertaintyType_; - bool hasAlphasVars_; - int alphasUpIndex_; - int alphasDownIndex_; - public: - PdfWeightGroupInfo() : WeightGroupInfo() { weightType_ = kPdfWeights; } - PdfWeightGroupInfo(std::string header, std::string name) : - WeightGroupInfo(header, name) { weightType_ = kPdfWeights; } - PdfWeightGroupInfo(std::string header) : - WeightGroupInfo(header) { weightType_ = kPdfWeights; } - PdfWeightGroupInfo(const PdfWeightGroupInfo &other) { - copy(other); - } - virtual ~PdfWeightGroupInfo() override {} - void copy(const PdfWeightGroupInfo &other); - PdfWeightGroupInfo* clone() const; - - void setUncertaintyType(PdfUncertaintyType uncertaintyType) { uncertaintyType_ = uncertaintyType; } - void setHasAlphasVariations(bool hasAlphasVars) { hasAlphasVars_ = hasAlphasVars; } - void setAlphasUpIndex(int alphasUpIndex) { alphasUpIndex_ = alphasUpIndex; } - void setAlphasDownIndex(int alphasDownIndex) { alphasDownIndex_ = alphasDownIndex; } - PdfUncertaintyType uncertaintyType() const { return uncertaintyType_; } - bool hasAlphasVariations() const { return hasAlphasVars_; } - int alphasUpIndex() const { return alphasUpIndex_; } - int alphasDownIndex() const { return alphasDownIndex_; } - }; -} - -#endif // SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h + enum PdfUncertaintyType { + kHessianUnc, + kMonteCarloUnc, + kVariationSet, + kUnknownUnc, + }; + class PdfWeightGroupInfo : public WeightGroupInfo { + private: + PdfUncertaintyType uncertaintyType_; + bool hasAlphasVars_; + int alphasUpIndex_; + int alphasDownIndex_; + int parentLhapdfId_ = -1; + size_t parentLhapdfSize_ = -1; + std::string parentLhapdfError_; + std::vector lhaids_; + int parentLhapdfId(int lhaid) const { return lhaid - LHAPDF::lookupPDF(lhaid).second; } + + public: + PdfWeightGroupInfo() : WeightGroupInfo() { weightType_ = WeightType::kPdfWeights; } + PdfWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { + weightType_ = WeightType::kPdfWeights; + } + PdfWeightGroupInfo(std::string header) : WeightGroupInfo(header) { weightType_ = WeightType::kPdfWeights; } + PdfWeightGroupInfo(const PdfWeightGroupInfo& other) { copy(other); } + virtual ~PdfWeightGroupInfo() override {} + void copy(const PdfWeightGroupInfo& other); + virtual PdfWeightGroupInfo* clone() const override; + + void setUncertaintyType(PdfUncertaintyType uncertaintyType) { uncertaintyType_ = uncertaintyType; } + void setHasAlphasVariations(bool hasAlphasVars) { hasAlphasVars_ = hasAlphasVars; } + void setAlphasUpIndex(int alphasUpIndex) { alphasUpIndex_ = alphasUpIndex; } + void setAlphasDownIndex(int alphasDownIndex) { alphasDownIndex_ = alphasDownIndex; } + PdfUncertaintyType uncertaintyType() const { return uncertaintyType_; } + bool hasAlphasVariations() const { return hasAlphasVars_; } + void addLhaid(int lhaid); + std::vector& lhaIds() { return lhaids_; } + + bool isIdInParentSet(int lhaid) const { return parentLhapdfId_ == parentLhapdfId(lhaid); } + int parentLhapdfId() const { return parentLhapdfId_; } + void setParentLhapdfInfo(int lhaid); + + // need to remove + bool containsLhapdfId(int lhaid) const { return isIdInParentSet(lhaid); } + + int alphasUpIndex() const { return alphasUpIndex_; } + int alphasDownIndex() const { return alphasDownIndex_; } + }; +} // namespace gen + +#endif // SimDataFormats_GeneratorProducts_PdfWeightGroupInfo_h diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index 179b183c07fd9..e5130b9d62c36 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -2,63 +2,75 @@ #define SimDataFormats_GeneratorProducts_ScaleWeightGroupInfo_h #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include +#include namespace gen { - class ScaleWeightGroupInfo : public WeightGroupInfo { - private: - bool isFuncationFormVar_; - size_t icentral_; - size_t imuR1muF2_; - size_t imuR1muF05_; - size_t imuR2muF05_; - size_t imuR2muF1_; - size_t imuR2muF2_; - size_t imuR05muF05_; - size_t imuR05muF1_; - size_t imuR05muF2_; - public: - ScaleWeightGroupInfo() : ScaleWeightGroupInfo("") {} - ScaleWeightGroupInfo(std::string header, std::string name) : - WeightGroupInfo(header, name) { - weightType_ = kScaleWeights; - isFuncationFormVar_ = false; - icentral_ = 0; - imuR1muF2_ = 0; - imuR1muF05_ = 0; - imuR2muF05_ = 0; - imuR2muF1_ = 0; - imuR2muF2_ = 0; - imuR2muF05_ = 0; - imuR05muF05_ = 0; - imuR05muF1_ = 0; - imuR05muF2_ = 0; - } - ScaleWeightGroupInfo(std::string header) : - ScaleWeightGroupInfo(header, header) { } - ScaleWeightGroupInfo(const ScaleWeightGroupInfo &other) { - copy(other); - } - virtual ~ScaleWeightGroupInfo() override {} - void copy(const ScaleWeightGroupInfo &other); - ScaleWeightGroupInfo* clone() const; + class ScaleWeightGroupInfo : public WeightGroupInfo { + private: + bool isFunctionalFormVar_; + std::vector muIndices_; + bool containsCentral_ = false; + int lhaid_ = -1; + // Dyn_scale + std::vector dynNames_; + std::vector> dynVec_; - void setMuRMuFIndex(WeightMetaInfo info, float muR, float muF); - void addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF); + void setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF); + void setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF, size_t dynNum, std::string dynName); + inline int getIndex(int muR, int muF) const { return 3 * muR + muF; } + inline bool isValidValue(float mu) const { return mu == 0.5 || mu == 1.0 || mu == 2.0; } - // Is a variation of the functional form of the dynamic scale - bool isFunctionalFormVariation(); - void setIsFunctionalFormVariation(bool functionalVar) {isFuncationFormVar_ = functionalVar; } - size_t centralIndex() {return icentral_; } - size_t muR1muF2Index() { return imuR1muF2_; } - size_t muR1muF05Index() { return imuR1muF05_; } - size_t muR2muF05Index() { return imuR2muF05_; } - size_t muR2muF1Index() { return imuR2muF1_; } - size_t muR2muF2Index() { return imuR2muF2_; } - size_t muR05muF05Index() { return imuR05muF05_; } - size_t muR05muF1Index() { return imuR05muF1_; } - size_t muR05muF2Index() { return imuR05muF2_; } - }_; -} + public: + ScaleWeightGroupInfo() : ScaleWeightGroupInfo("") {} + ScaleWeightGroupInfo(std::string header, std::string name) + : WeightGroupInfo(header, name), muIndices_(9, -1), dynVec_(9) { + weightType_ = WeightType::kScaleWeights; + isFunctionalFormVar_ = false; + } + ScaleWeightGroupInfo(std::string header) : ScaleWeightGroupInfo(header, header) {} + ScaleWeightGroupInfo(const ScaleWeightGroupInfo& other) { copy(other); } + virtual ~ScaleWeightGroupInfo() override {} + void copy(const ScaleWeightGroupInfo& other); + virtual ScaleWeightGroupInfo* clone() const override; + bool containsCentralWeight() const { return containsCentral_; } -#endif + void setMuRMuFIndex( + int globalIndex, std::string id, float muR, float muF, size_t dynNum = -1, std::string dynName = ""); + void addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF); + int lhaid() { return lhaid_; } + void setLhaid(int lhaid) { lhaid_ = lhaid; } + // Is a variation of the functional form of the dynamic scale + bool isFunctionalFormVariation(); + void setIsFunctionalFormVariation(bool functionalVar) { isFunctionalFormVar_ = functionalVar; } + size_t centralIndex() const { return muIndices_.at(4); } + size_t muR1muF2Index() const { return muIndices_.at(5); } + size_t muR1muF05Index() const { return muIndices_.at(3); } + size_t muR2muF05Index() const { return muIndices_.at(6); } + size_t muR2muF1Index() const { return muIndices_.at(7); } + size_t muR2muF2Index() const { return muIndices_.at(8); } + size_t muR05muF05Index() const { return muIndices_.at(0); } + size_t muR05muF1Index() const { return muIndices_.at(1); } + size_t muR05muF2Index() const { return muIndices_.at(2); } + // dynweight version + size_t centralIndex(std::string& dynName) const { return getScaleIndex(4, dynName); } + size_t muR1muF2Index(std::string& dynName) const { return getScaleIndex(5, dynName); } + size_t muR1muF05Index(std::string& dynName) const { return getScaleIndex(3, dynName); } + size_t muR2muF05Index(std::string& dynName) const { return getScaleIndex(6, dynName); } + size_t muR2muF1Index(std::string& dynName) const { return getScaleIndex(7, dynName); } + size_t muR2muF2Index(std::string& dynName) const { return getScaleIndex(8, dynName); } + size_t muR05muF05Index(std::string& dynName) const { return getScaleIndex(0, dynName); } + size_t muR05muF1Index(std::string& dynName) const { return getScaleIndex(1, dynName); } + size_t muR05muF2Index(std::string& dynName) const { return getScaleIndex(2, dynName); } + + size_t getScaleIndex(float muR, float muF, size_t dynNum) const; + size_t getScaleIndex(float muR, float muF, std::string& dynName) const; + size_t getScaleIndex(int index, std::string& dynName) const; + size_t getScaleIndex(float muR, float muF) const; + size_t getScaleIndex(int index, size_t dynNum) const { return dynVec_.at(index).at(dynNum); } + std::vector getDynNames() const; + }; +} // namespace gen + +#endif diff --git a/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h new file mode 100644 index 0000000000000..d314b9ad40d8a --- /dev/null +++ b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h @@ -0,0 +1,24 @@ +#ifndef SimDataFormats_GeneratorProducts_UnknownWeightGroupInfo_h +#define SimDataFormats_GeneratorProducts_UnknownWeightGroupInfo_h + +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" + +namespace gen { + class UnknownWeightGroupInfo : public WeightGroupInfo { + public: + UnknownWeightGroupInfo() : WeightGroupInfo() { weightType_ = WeightType::kUnknownWeights; } + UnknownWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { + weightType_ = WeightType::kUnknownWeights; + isWellFormed_ = false; + } + UnknownWeightGroupInfo(std::string header) : WeightGroupInfo(header) { + weightType_ = WeightType::kUnknownWeights; + isWellFormed_ = false; + } + virtual ~UnknownWeightGroupInfo() override {} + void copy(const UnknownWeightGroupInfo& other); + virtual UnknownWeightGroupInfo* clone() const override; + }; +} // namespace gen + +#endif // SimDataFormats_GeneratorProducts_UnknownWeightGroupInfo_h diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index a815ec762f7f8..9db98139ec9e6 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -7,71 +7,96 @@ #include #include #include +#include +#include namespace gen { - struct WeightMetaInfo { - size_t globalIndex; - size_t localIndex; - std::string id; - std::string label; - }; + struct WeightMetaInfo { + size_t globalIndex; + size_t localIndex; + std::string id; + std::string label; - enum WeightType { - kPdfWeights, - kScaleWeights, - kMatrixElementWeights, - kUnknownWeights, - kShowerWeights, - }; + bool operator==(const WeightMetaInfo& other) { + return (other.globalIndex == globalIndex && other.localIndex == localIndex && other.id == id && + other.label == label); + } + }; - class WeightGroupInfo { - public: - WeightGroupInfo() : WeightGroupInfo("") {} - WeightGroupInfo(std::string header, std::string name): - headerEntry_(header), name_(name), firstId_(-1), lastId_(-1) {} - WeightGroupInfo(std::string header): - headerEntry_(header), name_(header), firstId_(-1), lastId_(-1) {} - WeightGroupInfo(const WeightGroupInfo &other) { - copy(other); - } - WeightGroupInfo& operator=(const WeightGroupInfo &other) { - copy(other); - return *this; - } - virtual ~WeightGroupInfo() {}; - void copy(const WeightGroupInfo &other); - WeightGroupInfo* clone() const; - WeightMetaInfo weightMetaInfo(int weightEntry); - WeightMetaInfo weightMetaInfo(std::string wgtId); - int weightVectorEntry(const std::string& wgtId); - int containsWeight(const std::string& wgtId, int weightEntry); - int weightVectorEntry(const std::string& wgtId, int weightEntry); - void addContainedId(int weightEntry, std::string id, std::string label); - std::vector containedIds() const; - bool indexInRange(int index) const; + enum class WeightType : char { + kPdfWeights = 'P', + kScaleWeights = 's', + kMEParamWeights = 'm', + kPartonShowerWeights = 'p', + kUnknownWeights = 'u', + }; - void setName(std::string name) { name_ = name; } - void setHeaderEntry(std::string header) { headerEntry_ = header; } - void setWeightType(WeightType type) { weightType_ = type; } - void setFirstId(int firstId) { firstId_ = firstId; } - void setLastId(int lastId) { lastId_ = lastId; } + const std::array allWeightTypes = {{ + WeightType::kPdfWeights, + WeightType::kScaleWeights, + WeightType::kMEParamWeights, + WeightType::kPartonShowerWeights, + WeightType::kUnknownWeights, + }}; - std::string name() const { return name_; } - std::string headerEntry() const { return headerEntry_; } - WeightType weightType() const { return weightType_; } - std::vector idsContained() const { return idsContained_; } - int firstId() const { return firstId_; } - int lastId() const { return lastId_; } + class WeightGroupInfo { + public: + WeightGroupInfo() : WeightGroupInfo("") {} + WeightGroupInfo(std::string header, std::string name) + : isWellFormed_(true), headerEntry_(header), name_(name), firstId_(-1), lastId_(-1) {} + WeightGroupInfo(std::string header) + : isWellFormed_(true), headerEntry_(header), name_(header), firstId_(-1), lastId_(-1) {} + WeightGroupInfo(const WeightGroupInfo& other) { copy(other); } + WeightGroupInfo& operator=(const WeightGroupInfo& other) { + copy(other); + return *this; + } + virtual ~WeightGroupInfo(){}; + void copy(const WeightGroupInfo& other); + virtual WeightGroupInfo* clone() const; + WeightMetaInfo weightMetaInfo(int weightEntry) const; + WeightMetaInfo weightMetaInfoByGlobalIndex(std::string wgtId, int weightEntry) const; + int weightVectorEntry(std::string& wgtId) const; + bool containsWeight(std::string& wgtId, int weightEntry) const; + int weightVectorEntry(std::string& wgtId, int weightEntry) const; + void addContainedId(int weightEntry, std::string id, std::string label); + std::vector containedIds() const; + bool indexInRange(int index) const; - protected: - std::string headerEntry_; - std::string name_; - WeightType weightType_; - std::vector idsContained_; - int firstId_; - int lastId_; - }; -} + void setName(std::string name) { name_ = name; } + void setDescription(std::string description) { description_ = description; } + void appendDescription(std::string description) { description_ += description; } + void setHeaderEntry(std::string header) { headerEntry_ = header; } + void setWeightType(WeightType type) { weightType_ = type; } + void setFirstId(int firstId) { firstId_ = firstId; } + void setLastId(int lastId) { lastId_ = lastId; } + // Call before doing lots of searches by label + void cacheWeightIndicesByLabel(); -#endif // SimDataFormats_GeneratorProducts_WeightGroupInfo_h + std::string name() const { return name_; } + std::string description() const { return description_; } + std::string headerEntry() const { return headerEntry_; } + WeightType weightType() const { return weightType_; } + std::vector idsContained() const { return idsContained_; } + size_t nIdsContained() const { return idsContained_.size(); } + int firstId() const { return firstId_; } + int lastId() const { return lastId_; } + // Store whether the group was fully parsed succesfully + void setIsWellFormed(bool wellFormed) { isWellFormed_ = wellFormed; } + bool isWellFormed() const { return isWellFormed_; } + int weightIndexFromLabel(std::string weightLabel) const; + protected: + bool isWellFormed_; + std::string headerEntry_; + std::string name_; + std::string description_; + WeightType weightType_; + std::vector idsContained_; + int firstId_; + int lastId_; + std::unordered_map weightLabelsToIndices_; + }; +} // namespace gen + +#endif // SimDataFormats_GeneratorProducts_WeightGroupInfo_h diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc new file mode 100644 index 0000000000000..7b53436c4c7ff --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -0,0 +1,93 @@ +#include +#include + +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" + +GenWeightInfoProduct::GenWeightInfoProduct(edm::OwnVector& weightGroups) { + weightGroupsInfo_ = weightGroups; +} + +GenWeightInfoProduct& GenWeightInfoProduct::operator=(const GenWeightInfoProduct& other) { + weightGroupsInfo_ = other.weightGroupsInfo_; + return *this; +} + +GenWeightInfoProduct& GenWeightInfoProduct::operator=(GenWeightInfoProduct&& other) { + weightGroupsInfo_ = std::move(other.weightGroupsInfo_); + return *this; +} + +const edm::OwnVector& GenWeightInfoProduct::allWeightGroupsInfo() const { + return weightGroupsInfo_; +} + +const gen::WeightGroupInfo* GenWeightInfoProduct::containingWeightGroupInfo(int index) const { + for (const auto& weightGroup : weightGroupsInfo_) { + if (weightGroup.indexInRange(index)) + return &weightGroup; + } + throw std::domain_error("Failed to find containing weight group"); +} + +const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { + if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) + throw std::range_error("Weight index out of range!"); + return &weightGroupsInfo_[weightGroupIndex]; +} + +std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type) const { + std::vector matchingGroups; + for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + if (weightGroupsInfo_[i].weightType() == type) + matchingGroups.push_back({i, weightGroupsInfo_[i].clone()}); + } + return matchingGroups; +} + +std::vector GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { + std::vector matchingGroups; + for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + if (weightGroupsInfo_[i].weightType() == type) + matchingGroups.push_back(weightGroupsInfo_[i].clone()); + } + return matchingGroups; +} + +std::optional GenWeightInfoProduct::pdfGroupWithIndexByLHAID(int lhaid) const { + auto pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); + + auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { + auto pdfGroup = dynamic_cast(data.group); + return pdfGroup->containsLhapdfId(lhaid); + }); + return matchingPdfSet != pdfGroups.end() ? std::optional(*matchingPdfSet) : std::nullopt; +} + +std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLHAIDs( + const std::vector& lhaids) const { + auto pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); + std::vector groups; + + for (auto lhaid : lhaids) { + auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { + auto pdfGroup = dynamic_cast(data.group); + return pdfGroup->containsLhapdfId(lhaid); + }); + if (matchingPdfSet != pdfGroups.end()) + pdfGroups.push_back(*matchingPdfSet); + } + + return pdfGroups; +} + +std::vector GenWeightInfoProduct::weightGroupIndicesByType(gen::WeightType type) const { + std::vector matchingGroupIndices; + for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + if (weightGroupsInfo_[i].weightType() == type) + matchingGroupIndices.push_back(i); + } + return matchingGroupIndices; +} + +void GenWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo* info) { weightGroupsInfo_.push_back(info); } diff --git a/SimDataFormats/GeneratorProducts/src/MEParamWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/MEParamWeightGroupInfo.cc new file mode 100644 index 0000000000000..f3053ef5a1624 --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/MEParamWeightGroupInfo.cc @@ -0,0 +1,27 @@ +#include "SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h" +#include + +namespace gen { + void MEParamWeightGroupInfo::copy(const MEParamWeightGroupInfo& other) { WeightGroupInfo::copy(other); } + + MEParamWeightGroupInfo* MEParamWeightGroupInfo::clone() const { return new MEParamWeightGroupInfo(*this); } + + void MEParamWeightGroupInfo::updateWeight(int globalIndex, std::string id, double weight) { + size_t localIndex = weightMetaInfoByGlobalIndex(id, globalIndex).localIndex; + auto lower = + std::lower_bound(massValue.begin(), massValue.end(), std::make_pair(weight, std::numeric_limits::min())); + massValue.insert(lower, std::make_pair(weight, localIndex)); + isWellFormed_ = massValue.size() % 2 == 1; + if (isWellFormed_) { + numSigma = massValue.size() / 2; + central = massValue.at(centralIdx).first; + centralIdx = massValue.at(centralIdx).second; + } + } + + void MEParamWeightGroupInfo::updateWeight(int globalIndex, std::string id, std::vector& content) { + size_t localIndex = weightMetaInfoByGlobalIndex(id, globalIndex).localIndex; + splitContent[localIndex] = content; + } + +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc new file mode 100644 index 0000000000000..46bd94298a06c --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc @@ -0,0 +1,22 @@ +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" + +namespace gen { + void PartonShowerWeightGroupInfo::copy(const PartonShowerWeightGroupInfo& other) { WeightGroupInfo::copy(other); } + + PartonShowerWeightGroupInfo* PartonShowerWeightGroupInfo::clone() const { + return new PartonShowerWeightGroupInfo(*this); + } + + void PartonShowerWeightGroupInfo::updateWeight(int globalIndex, std::string id, std::string subName, bool isUp) { + size_t localIndex = weightMetaInfoByGlobalIndex(id, globalIndex).localIndex; + if (weightNameToUpDown.find(subName) == weightNameToUpDown.end()) { + weightNames.push_back(subName); + weightNameToUpDown[subName] = std::pair(); + } + if (isUp) + weightNameToUpDown[subName].first = localIndex; + else + weightNameToUpDown[subName].second = localIndex; + } + +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc index 4e0175bf9629c..818ad16a78ef2 100644 --- a/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/PdfWeightGroupInfo.cc @@ -1,15 +1,29 @@ #include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" namespace gen { - void PdfWeightGroupInfo::copy(const PdfWeightGroupInfo &other) { - uncertaintyType_ = other.uncertaintyType(); - hasAlphasVars_ = other.hasAlphasVariations(); - alphasUpIndex_ = other.alphasDownIndex(); - alphasDownIndex_ = other.alphasDownIndex(); - WeightGroupInfo::copy(other); - } - - PdfWeightGroupInfo* PdfWeightGroupInfo::clone() const { - return new PdfWeightGroupInfo(*this); - } -} + void PdfWeightGroupInfo::copy(const PdfWeightGroupInfo& other) { + uncertaintyType_ = other.uncertaintyType(); + hasAlphasVars_ = other.hasAlphasVariations(); + alphasUpIndex_ = other.alphasDownIndex(); + alphasDownIndex_ = other.alphasDownIndex(); + parentLhapdfId_ = other.parentLhapdfId(); + WeightGroupInfo::copy(other); + } + + PdfWeightGroupInfo* PdfWeightGroupInfo::clone() const { return new PdfWeightGroupInfo(*this); } + void PdfWeightGroupInfo::addLhaid(int lhaid) { + lhaids_.push_back(lhaid); + if (lhaids_.size() == parentLhapdfSize_) + setIsWellFormed(true); + else + setIsWellFormed(false); + } + + void PdfWeightGroupInfo::setParentLhapdfInfo(int lhaid) { + parentLhapdfId_ = lhaid; + LHAPDF::PDFSet pdfSet(LHAPDF::lookupPDF(lhaid).first); + parentLhapdfSize_ = pdfSet.size(); + parentLhapdfError_ = pdfSet.errorType(); + } + +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc index 5d2e392d89164..72dc7b6f48133 100644 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -1,52 +1,111 @@ #include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" #include +#include namespace gen { - void ScaleWeightGroupInfo::copy(const ScaleWeightGroupInfo &other) { - icentral_ = centralIndex(); - imuR1muF2_ = muR1muF2Index(); - imuR1muF05_ = muR1muF05Index(); - imuR2muF05_ = muR2muF05Index(); - imuR2muF1_ = muR2muF1Index(); - imuR2muF2_ = muR2muF2Index(); - imuR2muF05_ = muR2muF05Index(); - imuR05muF1_ = muR05muF1Index(); - imuR05muF2_ = muR05muF2Index(); - WeightGroupInfo::copy(other); + void ScaleWeightGroupInfo::copy(const ScaleWeightGroupInfo& other) { + muIndices_ = other.muIndices_; + dynVec_ = other.dynVec_; + dynNames_ = other.dynNames_; + WeightGroupInfo::copy(other); + } + + ScaleWeightGroupInfo* ScaleWeightGroupInfo::clone() const { return new ScaleWeightGroupInfo(*this); } + + void ScaleWeightGroupInfo::addContainedId(int globalIndex, std::string id, std::string label, float muR, float muF) { + int idxDiff = firstId_ - globalIndex; + if (idxDiff > 0) { + for (auto& entry : muIndices_) { + entry += idxDiff; + } + for (auto& subVec : dynVec_) { + for (auto& entry : subVec) { + entry += idxDiff; + } + } } + WeightGroupInfo::addContainedId(globalIndex, id, label); + setMuRMuFIndex(globalIndex, id, muR, muF); + } - ScaleWeightGroupInfo* ScaleWeightGroupInfo::clone() const { - return new ScaleWeightGroupInfo(*this); + void ScaleWeightGroupInfo::setMuRMuFIndex( + int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName) { + auto metaInfo = weightMetaInfoByGlobalIndex(id, globalIndex); + if ((int)dynNum == -1) + setMuRMuFIndex(metaInfo, muR, muF); + else + setMuRMuFIndex(metaInfo, muR, muF, dynNum, dynName); + } + + void ScaleWeightGroupInfo::setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF) { + int index = getIndex(muR, muF); + if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { + isWellFormed_ = false; + return; } + if (index == 4) + containsCentral_ = true; + muIndices_[index] = info.localIndex; + } - void ScaleWeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF) { - WeightGroupInfo::addContainedId(weightEntry, id, label); - auto metaInfo = weightMetaInfo(weightEntry); - setMuRMuFIndex(metaInfo, muR, muF); + void ScaleWeightGroupInfo::setMuRMuFIndex( + WeightMetaInfo& info, float muR, float muF, size_t dynNum, std::string dynName) { + int index = getIndex(muR, muF); + if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { + isWellFormed_ = false; + return; + } + // resize if too small + if (dynVec_.at(index).size() < dynNum + 1) { + for (auto& dynIt : dynVec_) + dynIt.resize(dynNum + 1); + dynNames_.resize(dynNum + 1); } - void ScaleWeightGroupInfo::setMuRMuFIndex(WeightMetaInfo info, float muR, float muF) { - if (muR == 0.5 && muF == 0.5) - imuR05muF05_ = info.localIndex; - else if (muR == 0.5 && muF == 1.0) - imuR05muF1_ = info.localIndex; - else if (muR == 0.5 && muF == 2.0) - imuR05muF2_ = info.localIndex; - else if (muR == 1.0 && muF == 0.5) - imuR1muF05_ = info.localIndex; - else if (muR == 1.0 && muF == 1.0) - icentral_ = info.localIndex; - else if (muR == 1.0 && muF == 2.0) - imuR1muF2_ = info.localIndex; - else if (muR == 2.0 && muF == 0.5) - imuR2muF05_ = info.localIndex; - else if (muR == 2.0 && muF == 1.0) - imuR2muF1_ = info.localIndex; - else if (muR == 2.0 && muF == 2.0) - imuR2muF2_ = info.localIndex; - else - throw std::invalid_argument("Invalid muF and muR variation is not a factor of two from central value"); + if (dynNames_.at(dynNum).empty()) + dynNames_[dynNum] = dynName; + dynVec_[index][dynNum] = info.localIndex; + } + + size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF, std::string& dynName) const { + auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); + if (it == dynNames_.end()) + return -1; + else + return getScaleIndex(muR, muF, it - dynNames_.begin()); + } + size_t ScaleWeightGroupInfo::getScaleIndex(int index, std::string& dynName) const { + auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); + if (it == dynNames_.end()) + return -1; + else + return getScaleIndex(index, it - dynNames_.begin()); + } + + size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF, size_t dynNum) const { + int index = getIndex(muR, muF); + if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF)) || dynNum + 1 > dynNames_.size()) { + // Bad access! + return -1; } -} + return getScaleIndex(index, dynNum); + } + size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF) const { + int index = getIndex(muR, muF); + if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { + // Bad access! + return -1; + } + return muIndices_.at(index); + } + std::vector ScaleWeightGroupInfo::getDynNames() const { + std::vector returnVec; + for (auto item : dynNames_) { + if (!item.empty()) + returnVec.push_back(item); + } + return returnVec; + } +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/UnknownWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/UnknownWeightGroupInfo.cc new file mode 100644 index 0000000000000..8c33d59eff35b --- /dev/null +++ b/SimDataFormats/GeneratorProducts/src/UnknownWeightGroupInfo.cc @@ -0,0 +1,5 @@ +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" + +namespace gen { + UnknownWeightGroupInfo* UnknownWeightGroupInfo::clone() const { return new UnknownWeightGroupInfo(*this); } +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index a9cbccfdea6f9..04aa722601d9e 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -1,86 +1,106 @@ #include #include #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "FWCore/Utilities/interface/Exception.h" + +#include namespace gen { - void WeightGroupInfo::copy(const WeightGroupInfo &other) { - headerEntry_ = other.headerEntry(); - name_ = other.name(); - weightType_ = other.weightType(); - idsContained_ = other.idsContained(); - firstId_ = other.firstId(); - lastId_ = other.lastId(); - } + void WeightGroupInfo::copy(const WeightGroupInfo& other) { + isWellFormed_ = other.isWellFormed_; + headerEntry_ = other.headerEntry_; + name_ = other.name_; + description_ = other.description_; + weightType_ = other.weightType_; + idsContained_ = other.idsContained_; + firstId_ = other.firstId_; + lastId_ = other.lastId_; + } - WeightGroupInfo* WeightGroupInfo::clone() const { - return new WeightGroupInfo(*this); - } + WeightGroupInfo* WeightGroupInfo::clone() const { + throw cms::Exception("LogicError", "WeightGroupInfo is abstract, so it's clone() method can't be implemented.\n"); + } - WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) { - return idsContained_.at(weightEntry); - } + WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) const { return idsContained_.at(weightEntry); } - WeightMetaInfo WeightGroupInfo::weightMetaInfo(std::string wgtId) { - int weightEntry = weightVectorEntry(wgtId); - return idsContained_.at(weightEntry); - } + WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string wgtId, int weightEntry) const { + if (wgtId.empty()) + wgtId = std::to_string(weightEntry); + int entry = weightVectorEntry(wgtId, weightEntry); + if (entry < 0 || entry >= static_cast(idsContained_.size())) + throw std::range_error("Weight entry " + std::to_string(weightEntry) + " is not a member of group " + name_ + + ". \n firstID = " + std::to_string(firstId_) + " lastId = " + std::to_string(lastId_)); + return idsContained_.at(entry); + } - int WeightGroupInfo::weightVectorEntry(const std::string& wgtId) { - return weightVectorEntry(wgtId, 0); - } + int WeightGroupInfo::weightVectorEntry(std::string& wgtId) const { return weightVectorEntry(wgtId, 0); } - int WeightGroupInfo::containsWeight(const std::string& wgtId, int weightEntry) { - return weightVectorEntry(wgtId, weightEntry) != -1; - } + bool WeightGroupInfo::containsWeight(std::string& wgtId, int weightEntry) const { + return weightVectorEntry(wgtId, weightEntry) != -1; + } - int WeightGroupInfo::weightVectorEntry(const std::string& wgtId, int weightEntry) { - int entry = -1; - if (!indexInRange(weightEntry)) { - size_t orderedEntry = weightEntry - firstId_; - if (orderedEntry < idsContained_.size()) - if (idsContained_.at(orderedEntry).id == wgtId) - return orderedEntry; - } - auto it = std::find_if(idsContained_.begin(), idsContained_.end(), - [wgtId] (const WeightMetaInfo& w) { return w.id == wgtId; }); - if (it != idsContained_.end()) - return std::distance(idsContained_.begin(), it); - return entry; + int WeightGroupInfo::weightVectorEntry(std::string& wgtId, int weightEntry) const { + if (wgtId.empty()) + wgtId = std::to_string(weightEntry); + // First try ordered search + size_t orderedEntry = weightEntry - firstId_; + if (indexInRange(weightEntry) && orderedEntry < idsContained_.size()) { + if (wgtId.empty() || idsContained_.at(orderedEntry).id == wgtId) { + return orderedEntry; + } } + // Fall back to search on ID + else if (!wgtId.empty()) { + auto it = std::find_if( + idsContained_.begin(), idsContained_.end(), [wgtId](const WeightMetaInfo& w) { return w.id == wgtId; }); + if (it != idsContained_.end()) + return std::distance(idsContained_.begin(), it); + } + return -1; + } + + void WeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label = "") { + if (id.empty()) + id = std::to_string(weightEntry); - void WeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label="") { - if (firstId_ == -1 || weightEntry < firstId_) { - firstId_ = weightEntry; - // Reset to reflect that indices will be shifted - for (auto& id : idsContained_) - id.localIndex = id.globalIndex - firstId_; - } - if (weightEntry > lastId_) - lastId_ = weightEntry; - - WeightMetaInfo info; - info.globalIndex = weightEntry; - info.localIndex = weightEntry - firstId_; - info.id = id; - info.label = label; - - if (idsContained_.size() < info.localIndex) { - idsContained_.resize(info.localIndex); - idsContained_.insert(idsContained_.begin()+info.localIndex, info); - } - else if (idsContained_.size() == info.localIndex) { - idsContained_.push_back(info); - } - else { - idsContained_.resize(info.localIndex+1); - idsContained_[info.localIndex] = info; - } + if (firstId_ == -1 || weightEntry < firstId_) { + firstId_ = weightEntry; + for (auto& entry : idsContained_) // Reset if indices need to be shifted + entry.localIndex++; } + if (weightEntry > lastId_) + lastId_ = weightEntry; - std::vector WeightGroupInfo::containedIds() const { return idsContained_; } + size_t localIndex = std::min(weightEntry - firstId_, static_cast(idsContained_.size())); + WeightMetaInfo info = {static_cast(weightEntry), localIndex, id, label}; + // logic to insert for all cases e.g. inserting in the middle of the vector + if (localIndex == idsContained_.size()) + idsContained_.emplace_back(info); + else + idsContained_.insert(idsContained_.begin() + localIndex, info); + } + std::vector WeightGroupInfo::containedIds() const { return idsContained_; } - bool WeightGroupInfo::indexInRange(int index) const { - return (index <= lastId_ && index >= firstId_); - } -} + bool WeightGroupInfo::indexInRange(int index) const { return (index <= lastId_ && index >= firstId_); } + + void WeightGroupInfo::cacheWeightIndicesByLabel() { + for (const auto& weight : idsContained_) + weightLabelsToIndices_[weight.label] = weight.localIndex; + } + + int WeightGroupInfo::weightIndexFromLabel(std::string weightLabel) const { + if (!weightLabelsToIndices_.empty()) { + if (weightLabelsToIndices_.find(weightLabel) != weightLabelsToIndices_.end()) + return static_cast(weightLabelsToIndices_.at(weightLabel)); + return -1; + } + + auto it = std::find_if(idsContained_.begin(), idsContained_.end(), + [weightLabel](const auto& w) { return weightLabel == w.label; }); + if (it == idsContained_.end()) + return -1; + return std::distance(idsContained_.begin(), it); + } + +} // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/classes.h b/SimDataFormats/GeneratorProducts/src/classes.h index 3b31e9b4d7c20..4562fa5097487 100644 --- a/SimDataFormats/GeneratorProducts/src/classes.h +++ b/SimDataFormats/GeneratorProducts/src/classes.h @@ -9,8 +9,13 @@ #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHEXMLStringProduct.h" #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h" @@ -30,14 +35,13 @@ namespace hepmc_rootio { void add_to_particles_in(HepMC::GenVertex*, HepMC::GenParticle*); void clear_particles_in(HepMC::GenVertex*); - inline void weightcontainer_set_default_names(unsigned int n, std::map& names) { - std::ostringstream name; - for ( HepMC::WeightContainer::size_type count = 0; count& names) { + std::ostringstream name; + for (HepMC::WeightContainer::size_type count = 0; count < n; ++count) { name.str(std::string()); name << count; names[name.str()] = count; - } + } } -} - +} // namespace hepmc_rootio diff --git a/SimDataFormats/GeneratorProducts/src/classes_def.xml b/SimDataFormats/GeneratorProducts/src/classes_def.xml index 34a91335187d4..1cfcc6144a4e4 100644 --- a/SimDataFormats/GeneratorProducts/src/classes_def.xml +++ b/SimDataFormats/GeneratorProducts/src/classes_def.xml @@ -200,8 +200,8 @@ - - + + @@ -231,24 +231,32 @@ + + + - - - - - + + + + + - - + + + + + + + From 91a79015db21aacad524d976ba8af92df78dd89e Mon Sep 17 00:00:00 2001 From: Suvankar Roy Chowdhury Date: Fri, 21 Aug 2020 19:26:39 +0200 Subject: [PATCH 04/16] updates to allow saving weight sums from all weight categories adding option to save preferred PS weights Support unassociated LHE weights, simplify PS weights Refactor ScaleWeightGroup to simplify codebase Remove/change lines in WeightHelper to clean Fix naming problems in ScaleWeight Refactor LHWeightHelper (moved to helper functions) Fix errors in ScaleWeight and add print statements for debug --- .../Core/interface/LHEWeightHelper.h | 3 + .../Core/interface/WeightHelper.h | 10 +- .../Core/plugins/GenWeightProductProducer.cc | 5 +- .../Core/plugins/LHEWeightProductProducer.cc | 4 +- .../Core/src/GenWeightHelper.cc | 3 +- .../Core/src/LHEWeightHelper.cc | 103 +++-- GeneratorInterface/Core/src/WeightHelper.cc | 137 +++--- .../NanoAOD/interface/GenWeightCounters.h | 119 +++++ .../plugins/LHEWeightsTableProducer.cc | 413 ++++++++++++++++++ PhysicsTools/NanoAOD/python/nanogen_cff.py | 5 +- .../interface/GenWeightInfoProduct.h | 15 +- .../interface/PartonShowerWeightGroupInfo.h | 22 +- .../interface/ScaleWeightGroupInfo.h | 77 ++-- .../interface/WeightGroupInfo.h | 5 +- .../src/GenWeightInfoProduct.cc | 33 +- .../src/ScaleWeightGroupInfo.cc | 72 ++- .../GeneratorProducts/src/WeightGroupInfo.cc | 8 + 17 files changed, 818 insertions(+), 216 deletions(-) create mode 100644 PhysicsTools/NanoAOD/interface/GenWeightCounters.h create mode 100644 PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index f29aaf5f2f7df..b2f636250f230 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -28,6 +28,9 @@ namespace gen { private: std::vector headerLines_; bool failIfInvalidXML_ = false; + std::string parseGroupName(tinyxml2::XMLElement* el); + void addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex); + bool parseLHE(tinyxml2::XMLDocument& xmlDoc); }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index aea58eb6d587f..cfc14ceffc7db 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -33,14 +33,20 @@ namespace gen { std::unique_ptr weightProduct(std::vector, float w0); std::unique_ptr weightProduct(std::vector, float w0); void setModel(std::string model) { model_ = model; } + void addUnassociatedGroup() { + weightGroups_.push_back(std::make_unique("unassociated")); + weightGroups_.back().setDescription("Weights missing or with invalid header meta data"); + } int addWeightToProduct( std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex); int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); protected: - // TODO: Make this only print from one thread a la + // TODO: Make this only print from one thread a la // https://github.com/kdlong/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 - bool debug_ = true; + bool debug_ = true; //true; + const unsigned int FIRST_PSWEIGHT_ENTRY = 2; + const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; std::string model_; std::vector parsedWeights_; std::map currWeightAttributeMap_; diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index a69756f2b2aea..f066ef0492c83 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -81,8 +81,11 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& weightHelper_.parseWeightGroupsFromNames(weightNames_); auto weightInfoProduct = std::make_unique(); + if (weightHelper_.weightGroups().size() == 0) + weightHelper_.addUnassociatedGroup(); + for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(weightGroup.clone()); + weightInfoProduct->addWeightGroupInfo(std::make_unique(*weightGroup.clone())); } iLumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index f06d68d5e81f4..5937693c518b8 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -121,10 +121,12 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& return; weightHelper_.parseWeights(); + if (weightHelper_.weightGroups().size() == 0) + weightHelper_.addUnassociatedGroup(); auto weightInfoProduct = std::make_unique(); for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(weightGroup.clone()); + weightInfoProduct->addWeightGroupInfo(std::make_unique(*weightGroup.clone())); } lumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index ccc7f0b99b1a3..1fc086f688e56 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -42,8 +42,9 @@ namespace gen { parsedWeights_.push_back( {"", index, weightName, weightName, std::unordered_map(), groupIndex}); if (isPartonShowerWeightGroup(parsedWeights_.back())) { - if (showerGroupIndex < 0) + if (showerGroupIndex < 0) { showerGroupIndex = ++groupIndex; + } parsedWeights_.back().wgtGroup_idx = showerGroupIndex; // all parton showers are grouped together } } diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index e9a7515d123e3..013072992d45e 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -7,11 +7,9 @@ using namespace tinyxml2; namespace gen { - void LHEWeightHelper::setHeaderLines(std::vector headerLines) { - headerLines_ = headerLines; - } + void LHEWeightHelper::setHeaderLines(std::vector headerLines) { headerLines_ = headerLines; } - void LHEWeightHelper::parseWeights() { + bool LHEWeightHelper::parseLHE(tinyxml2::XMLDocument& xmlDoc) { parsedWeights_.clear(); if (!isConsistent() && failIfInvalidXML_) { @@ -23,7 +21,6 @@ namespace gen { swapHeaders(); } - tinyxml2::XMLDocument xmlDoc; std::string fullHeader = boost::algorithm::join(headerLines_, ""); if (debug_) std::cout << "Full header is \n" << fullHeader << std::endl; @@ -42,66 +39,76 @@ namespace gen { if (failIfInvalidXML_) throw std::runtime_error("XML is unreadable because of above error."); else - return; + return false; } - std::vector nameAlts_ = {"name", "type"}; + return true; + } + + void LHEWeightHelper::addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex) { + if (debug_) + std::cout << " >> Found a weight inside the group. " << std::endl; + std::string text = ""; + if (inner->GetText()) + text = inner->GetText(); + + std::unordered_map attributes; + for (auto* att = inner->FirstAttribute(); att != nullptr; att = att->Next()) + attributes[att->Name()] = att->Value(); + if (debug_) + std::cout << " " << weightIndex << ": \"" << text << "\"" << std::endl; + parsedWeights_.push_back({inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); + } + + void LHEWeightHelper::parseWeights() { + tinyxml2::XMLDocument xmlDoc; + if (!parseLHE(xmlDoc)) { + return; + } int weightIndex = 0; int groupIndex = 0; for (auto* e = xmlDoc.RootElement(); e != nullptr; e = e->NextSiblingElement()) { - if (debug_) + if (debug_) std::cout << "XML element is " << e->Name() << std::endl; std::string groupName = ""; if (strcmp(e->Name(), "weight") == 0) { - if (debug_) + if (debug_) std::cout << "Found weight unmatched to group\n"; - // we are here if there is a weight that does not belong to any group - // TODO: Recylce code better between here when a weight is found in a group - std::string text = ""; - if (e->GetText()) { - text = e->GetText(); - } - std::unordered_map attributes; - for (auto* att = e->FirstAttribute(); att != nullptr; att = att->Next()) - attributes[att->Name()] = att->Value(); - parsedWeights_.push_back({e->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); + // need to fix + addGroup(e, groupName, groupIndex, weightIndex); } else if (strcmp(e->Name(), "weightgroup") == 0) { + groupName = parseGroupName(e); if (debug_) - std::cout << "Found a weight group.\n"; - // to deal wiht files with "id" instead of "name" - for (auto nameAtt : nameAlts_) { - if (e->Attribute(nameAtt.c_str())) { - groupName = e->Attribute(nameAtt.c_str()); - break; - } - } - if (groupName.empty()) { - // TODO: Need a better failure mode - throw std::runtime_error("couldn't find groupname"); - } - // May remove this, very specific error - if (groupName.find(".") != std::string::npos) - groupName.erase(groupName.find("."), groupName.size()); + std::cout << ">>>> Found a weight group: " << groupName << std::endl; + + for (auto inner = e->FirstChildElement("weight"); inner != nullptr; inner = inner->NextSiblingElement("weight")) + addGroup(inner, groupName, groupIndex, weightIndex); - for (auto* inner = e->FirstChildElement("weight"); inner != nullptr; - inner = inner->NextSiblingElement("weight")) { - // we are here if there is a weight in a weightgroup - if (debug_) - std::cout << "Found a weight inside the group. Content is " << inner->GetText() << " group index is " << groupIndex << std::endl; - std::string text = ""; - if (inner->GetText()) - text = inner->GetText(); - std::unordered_map attributes; - for (auto* att = inner->FirstAttribute(); att != nullptr; att = att->Next()) - attributes[att->Name()] = att->Value(); - parsedWeights_.push_back({inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); - } } else - std::cout << "Found an invalid entry\n"; + std::cout << "Found an invalid entry\n"; groupIndex++; } buildGroups(); + if (debug_) + printWeights(); + } + + std::string LHEWeightHelper::parseGroupName(tinyxml2::XMLElement* el) { + std::vector nameAlts_ = {"name", "type"}; + for (auto nameAtt : nameAlts_) { + if (el->Attribute(nameAtt.c_str())) { + std::string groupName = el->Attribute(nameAtt.c_str()); + if (groupName.find(".") != std::string::npos) + groupName.erase(groupName.find("."), groupName.size()); + return groupName; + } + } + bool hardFail = true; + if (hardFail) { + throw std::runtime_error("couldn't find groupname"); + } + return ""; } bool LHEWeightHelper::isConsistent() { diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 0b670f015964a..bfcc373e7bccd 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -11,7 +11,6 @@ namespace gen { bool WeightHelper::isPdfWeightGroup(const ParsedWeight& weight) { const std::string& name = weight.groupname; - if (name.find("PDF_variation") != std::string::npos) return true; return LHAPDF::lookupLHAPDFID(name) != -1; @@ -19,25 +18,24 @@ namespace gen { bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) { const std::string& name = boost::to_lower_copy(weight.groupname); - // But "Nominal" and "Baseline" weights in the PS group return name.find("isr") != std::string::npos || name.find("fsr") != std::string::npos || name.find("nominal") != std::string::npos || name.find("baseline") != std::string::npos; } bool WeightHelper::isOrphanPdfWeightGroup(ParsedWeight& weight) { - std::string lhaidText = searchAttributes("pdf", weight); + std::pair pairLHA; try { - auto pairLHA = LHAPDF::lookupPDF(stoi(lhaidText)); - // require pdf set to exist and it to be the first entry (ie 0) - // possibly change this requirement - if (!pairLHA.first.empty() && pairLHA.second == 0) { - weight.groupname = std::string(pairLHA.first); - return true; - } + pairLHA = LHAPDF::lookupPDF(stoi(searchAttributes("pdf", weight))); } catch (...) { return false; } - return false; + + if (!pairLHA.first.empty() && pairLHA.second == 0) { + weight.groupname = std::string(pairLHA.first); + return true; + } else { + return false; + } } bool WeightHelper::isMEParamWeightGroup(const ParsedWeight& weight) { @@ -49,7 +47,6 @@ namespace gen { std::string WeightHelper::searchAttributes(const std::string& label, const ParsedWeight& weight) const { std::string attribute = searchAttributesByTag(label, weight); return attribute.empty() ? searchAttributesByRegex(label, weight) : attribute; - attribute = searchAttributesByRegex(label, weight); } std::string WeightHelper::searchAttributesByTag(const std::string& label, const ParsedWeight& weight) const { @@ -62,14 +59,6 @@ namespace gen { return ""; } - std::string WeightHelper::searchString(const std::string& label, const std::string& name) { - for (const auto& lab : attributeNames_.at(label)) { - if (name.find(lab) != std::string::npos) - return name.substr(0, name.find(lab)); - } - return ""; - } - std::string WeightHelper::searchAttributesByRegex(const std::string& label, const ParsedWeight& weight) const { auto& content = weight.content; std::smatch match; @@ -86,36 +75,44 @@ namespace gen { } void WeightHelper::updateScaleInfo(const ParsedWeight& weight, int index) { - auto& group = weightGroups_[index]; - auto& scaleGroup = dynamic_cast(group); + auto& scaleGroup = dynamic_cast(weightGroups_[index]); + std::string muRText = searchAttributes("mur", weight); std::string muFText = searchAttributes("muf", weight); - - if (muRText.empty() || muFText.empty()) { + std::string dynNumText = searchAttributes("dyn", weight); + float muR, muF; + try { + muR = std::stof(muRText); + muF = std::stof(muFText); + } catch (...) { + if (debug_) + std::cout << "Tried to convert (" << muR << ", " << muF << ") to a int" << std::endl; scaleGroup.setIsWellFormed(false); return; + /// do something } - try { - float muR = std::stof(muRText); - float muF = std::stof(muFText); - std::string dynNumText = searchAttributes("dyn", weight); - if (dynNumText.empty()) { - scaleGroup.setMuRMuFIndex(weight.index, weight.id, muR, muF); - } else { - std::string dynType = searchAttributes("dyn_name", weight); + if (dynNumText.empty()) { + scaleGroup.setMuRMuFIndex(weight.index, weight.id, muR, muF); + } else { + std::string dynType = searchAttributes("dyn_name", weight); + try { int dynNum = std::stoi(dynNumText); - scaleGroup.setMuRMuFIndex(weight.index, weight.id, muR, muF, dynNum, dynType); + scaleGroup.setDyn(weight.index, weight.id, muR, muF, dynNum, dynType); + } catch (...) { + std::cout << "Tried to convert (" << dynNumText << ") a int" << std::endl; + scaleGroup.setIsWellFormed(false); + /// do something here } - } catch (std::invalid_argument& e) { - scaleGroup.setIsWellFormed(false); } + if (scaleGroup.lhaid() == -1) { std::string lhaidText = searchAttributes("pdf", weight); try { scaleGroup.setLhaid(std::stoi(lhaidText)); - } catch (std::invalid_argument& e) { + } catch (...) { scaleGroup.setLhaid(-2); + // do something here } } } @@ -213,11 +210,32 @@ namespace gen { int WeightHelper::addWeightToProduct( std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex) { - groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); - auto group = weightGroups_[groupIndex]; - int entry = group.weightVectorEntry(name, weightNum); + bool isUnassociated = false; + try { + groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); + } catch (const std::range_error& e) { + std::cerr << "WARNING: " << e.what() << std::endl; + isUnassociated = true; + + bool foundUnassocGroup = false; + while (!foundUnassocGroup && groupIndex < static_cast(weightGroups_.size())) { + auto& g = weightGroups_[groupIndex]; + if (g.weightType() == gen::WeightType::kUnknownWeights && g.name() == "unassociated") + foundUnassocGroup = true; + else + groupIndex++; + } + if (!foundUnassocGroup) { + addUnassociatedGroup(); + } + } + auto& group = weightGroups_[groupIndex]; + if (isUnassociated) { + group.addContainedId(weightNum, name, name); + } + int entry = !isUnassociated ? group.weightVectorEntry(name, weightNum) : group.nIdsContained(); if (debug_) - std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; + std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; product->addWeight(weight, groupIndex, entry); return groupIndex; } @@ -262,26 +280,31 @@ namespace gen { std::cout << wgtScale.muR05muF1Index() << " "; std::cout << wgtScale.muR05muF2Index() << " "; std::cout << wgtScale.muR05muF05Index() << " \n"; - for (auto name : wgtScale.getDynNames()) { + for (auto name : wgtScale.dynNames()) { std::cout << name << ": "; - std::cout << wgtScale.getScaleIndex(1.0, 1.0, name) << " "; - std::cout << wgtScale.getScaleIndex(1.0, 2.0, name) << " "; - std::cout << wgtScale.getScaleIndex(1.0, 0.5, name) << " "; - std::cout << wgtScale.getScaleIndex(2.0, 1.0, name) << " "; - std::cout << wgtScale.getScaleIndex(2.0, 2.0, name) << " "; - std::cout << wgtScale.getScaleIndex(2.0, 0.5, name) << " "; - std::cout << wgtScale.getScaleIndex(0.5, 1.0, name) << " "; - std::cout << wgtScale.getScaleIndex(0.5, 2.0, name) << " "; - std::cout << wgtScale.getScaleIndex(0.5, 0.5, name) << "\n"; + std::cout << wgtScale.scaleIndex(1.0, 1.0, name) << " "; + std::cout << wgtScale.scaleIndex(1.0, 2.0, name) << " "; + std::cout << wgtScale.scaleIndex(1.0, 0.5, name) << " "; + std::cout << wgtScale.scaleIndex(2.0, 1.0, name) << " "; + std::cout << wgtScale.scaleIndex(2.0, 2.0, name) << " "; + std::cout << wgtScale.scaleIndex(2.0, 0.5, name) << " "; + std::cout << wgtScale.scaleIndex(0.5, 1.0, name) << " "; + std::cout << wgtScale.scaleIndex(0.5, 2.0, name) << " "; + std::cout << wgtScale.scaleIndex(0.5, 0.5, name) << "\n"; } } else if (wgt.weightType() == gen::WeightType::kPdfWeights) { std::cout << wgt.description() << "\n"; } else if (wgt.weightType() == gen::WeightType::kPartonShowerWeights) { auto& wgtPS = dynamic_cast(wgt); - for (auto group : wgtPS.getWeightNames()) { - std::cout << group << ": up " << wgtPS.upIndex(group); - std::cout << " - down " << wgtPS.downIndex(group) << std::endl; + if (wgtPS.containedIds().size() == DEFAULT_PSWEIGHT_LENGTH) + wgtPS.setIsWellFormed(true); + + wgtPS.cacheWeightIndicesByLabel(); + std::vector labels = wgtPS.weightLabels(); + if (labels.size() > FIRST_PSWEIGHT_ENTRY && labels.at(FIRST_PSWEIGHT_ENTRY).find(":") != std::string::npos && + labels.at(FIRST_PSWEIGHT_ENTRY).find("=") != std::string::npos) { + wgtPS.setNameIsPythiaSyntax(true); } } if (!wgt.isWellFormed()) @@ -291,8 +314,8 @@ namespace gen { std::unique_ptr WeightHelper::buildGroup(ParsedWeight& weight) { if (debug_) { - std::cout << "Building group for weight group " << weight.groupname - << " weight content is " << weight.content << std::endl; + std::cout << "Building group for weight group " << weight.groupname << " weight content is " << weight.content + << std::endl; } if (isScaleWeightGroup(weight)) return std::make_unique(weight.groupname); @@ -316,8 +339,8 @@ namespace gen { weight.wgtGroup_idx += groupOffset; currentGroupIdx = weight.wgtGroup_idx; if (debug_) - std::cout << "Building group for weight " << weight.content << " group " - << weight.groupname << " group index " << weight.wgtGroup_idx << std::endl; + std::cout << "Building group for weight " << weight.content << " group " << weight.groupname << " group index " + << weight.wgtGroup_idx << std::endl; int numGroups = static_cast(weightGroups_.size()); if (weight.wgtGroup_idx == numGroups) { diff --git a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h new file mode 100644 index 0000000000000..15ac334b2e863 --- /dev/null +++ b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h @@ -0,0 +1,119 @@ +#ifndef GENWEIGHTSCOUNTERS_h +#define GENWEIGHTSCOUNTERS_h +#include +#include +#include +namespace genCounter { + + void mergeSumVectors(std::vector& v1, std::vector const& v2) { + if (v1.empty() && !v2.empty()) + v1.resize(v2.size(), 0); + if (!v2.empty()) + for (unsigned int i = 0, n = v1.size(); i < n; ++i) + v1[i] += v2[i]; + } + + /// ---- Cache object for running sums of weights ---- + class Counter { + public: + void clear() { + num_ = 0; + sumw_ = 0; + sumw2_ = 0; + weightSumMap_.clear(); + } + + // inc only the gen counters + void incGenOnly(double w) { + num_++; + sumw_ += w; + sumw2_ += (w * w); + } + + void incLHE(double w0, const std::vector& weightV, const std::string& wName) { + //if new type of weight, create a map element + if(weightSumMap_.find(wName) == weightSumMap_.end()) { + std::vector temp; + weightSumMap_.insert({wName, temp}); + } + if (!weightV.empty()) { + if (weightSumMap_[wName].empty()) + weightSumMap_[wName].resize(weightV.size(), 0); + for (unsigned int i = 0, n = weightV.size(); i < n; ++i) + weightSumMap_[wName][i] += (w0 * weightV[i]); + } + // incGenOnly(w0); + //incPSOnly(w0, wPS); + } + + void mergeSumMap(const Counter& other) { + num_ += other.num_; + sumw_ += other.sumw_; + sumw2_ += other.sumw2_; + //if weightMap_ for "this" is empty, create map elements with empty + //vectors before merging + if(weightSumMap_.empty() && !other.weightSumMap_.empty()) { + for(auto& wmap : other.weightSumMap_) { + std::vector temp; + weightSumMap_.insert({wmap.first, temp}); + } + } + for(auto& wmap : weightSumMap_) { + mergeSumVectors(wmap.second, other.weightSumMap_.at(wmap.first)); + } + /* + std::cout << "From merge function\n"; + for(auto& wmap : weightSumMap_) { + std::cout << "Wname:" << wmap.first + << "\t WVec Size:" << wmap.second.size() + << "\t First entry:" << wmap.second.at(0) + << std::endl;; + } + std::cout << "End : From merge function\n"; + */ + } + + //private: + // the counters + long long num_ = 0; + long double sumw_ = 0; + long double sumw2_ = 0; + std::map> weightSumMap_; + }; + + struct CounterMap { + std::map countermap; + Counter* active_el = nullptr; + std::string active_label = ""; + + void mergeSumMap(const CounterMap& other) { + for (const auto& y : other.countermap) + countermap[y.first].mergeSumMap(y.second); + active_el = nullptr; + } + + void clear() { + for (auto x : countermap) + x.second.clear(); + } + + void setLabel(std::string label) { + active_el = &(countermap[label]); + active_label = label; + } + void checkLabelSet() { + if (!active_el) + throw cms::Exception("LogicError", "Called CounterMap::get() before setting the active label\n"); + } + Counter* get() { + checkLabelSet(); + return active_el; + } + std::string& getLabel() { + checkLabelSet(); + return active_label; + } + }; + +} +#endif diff --git a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc new file mode 100644 index 0000000000000..c8f0aa06684ff --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc @@ -0,0 +1,413 @@ +#include "FWCore/Framework/interface/global/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/NanoAOD/interface/FlatTable.h" +#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include "FWCore/Utilities/interface/transform.h" +#include "PhysicsTools/NanoAOD/interface/GenWeightCounters.h" +#include +#include +#include + +namespace { + typedef std::vector WeightGroupDataContainer; + typedef std::array, 2> WeightGroupsToStore; +} // namespace +using CounterMap = genCounter::CounterMap; +using Counter = genCounter::Counter; + +class LHEWeightsTableProducer : +public edm::global::EDProducer, + edm::StreamCache, + edm::RunSummaryCache, + edm::EndRunProducer> { +public: + LHEWeightsTableProducer(edm::ParameterSet const& params); + + void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; + //func changed//sroychow + void addWeightGroupToTable(std::unique_ptr>& lheWeightTables, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, Counter& counter, + double genWeight) const; + + WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, + gen::WeightType weightType, + int& maxStore) const; + + std::vector orderedScaleWeights(const std::vector& scaleWeights, + const gen::ScaleWeightGroupInfo* scaleGroup) const; + + std::vector getPreferredPSweights(const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo* pswV) const; + + //Lumiblock + std::shared_ptr globalBeginLuminosityBlock(edm::LuminosityBlock const& iLumi, + edm::EventSetup const&) const override { + // Set equal to the max number of groups + // subtrack 1 for each weight group you find + bool foundLheWeights = false; + edm::Handle lheWeightInfoHandle; + for (auto& token : lheWeightInfoTokens_) { + iLumi.getByToken(token, lheWeightInfoHandle); + if (lheWeightInfoHandle.isValid()) { + foundLheWeights = true; + break; + } + } + edm::Handle genWeightInfoHandle; + iLumi.getByToken(genWeightInfoToken_, genWeightInfoHandle); + + std::unordered_map storePerType; + for (size_t i = 0; i < weightgroups_.size(); i++) + storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); + + WeightGroupsToStore weightsToStore; + for (auto weightType : gen::allWeightTypes) { + if (foundLheWeights) { + auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); + weightsToStore.at(inLHE).insert(weightsToStore.at(inLHE).end(), lheWeights.begin(), lheWeights.end()); + } + auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); + weightsToStore.at(inGen).insert(weightsToStore.at(inGen).end(), genWeights.begin(), genWeights.end()); + } + return std::make_shared(weightsToStore); + } + + // nothing to do here + virtual void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} + // create an empty counter + std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } + // inizialize to zero at begin run + void streamBeginRun(edm::StreamID id, + edm::Run const&, edm::EventSetup const&) const override { streamCache(id)->clear(); } + + void streamBeginLuminosityBlock(edm::StreamID id, + edm::LuminosityBlock const& lumiBlock, + edm::EventSetup const& eventSetup) const override { + auto counterMap = streamCache(id); + edm::Handle genLumiInfoHead; + lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); + if (!genLumiInfoHead.isValid()) + edm::LogWarning("LHETablesProducer") + << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; + counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); + //std::cout << "StreamBeginLuminosityBlock:" << id.value() << "\nPrinting counter map keys" << std::endl; + //for(auto& cm : counterMap->countermap) + // std::cout << cm.first << std::endl; + std::string label = genLumiInfoHead.isValid() ? counterMap->getLabel() : "NULL"; + //std::cout << "StreamBeginLuminosityBlock:" << id.value() << "\nCounterMapLabel:" << label << std::endl; + + } + // create an empty counter + std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { + return std::make_shared(); + } + // add this stream to the summary + void streamEndRunSummary(edm::StreamID id, edm::Run const&, + edm::EventSetup const&, CounterMap* runCounterMap) const override; + // nothing to do per se + void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} + // write the total to the run + void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const& es, CounterMap const* runCounterMap) const override; + // nothing to do here + //void globalEndRun(edm::Run const& iRun, edm::EventSetup const& es, CounterMap* runCounterMap) const override {} + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +protected: + //const std::vector> lheTokens_; + const std::vector> lheWeightTokens_; + const std::vector> lheWeightInfoTokens_; + const edm::EDGetTokenT genWeightToken_; + const edm::EDGetTokenT genWeightInfoToken_; + const edm::EDGetTokenT genEventInfoToken_; + const edm::EDGetTokenT genLumiInfoHeadTag_; + const std::vector weightgroups_; + const std::vector maxGroupsPerType_; + const std::vector pdfIds_; + const std::unordered_map weightTypeNames_ = { + {gen::WeightType::kScaleWeights, "Scale"}, + {gen::WeightType::kPdfWeights, "Pdf"}, + {gen::WeightType::kMEParamWeights, "MEParam"}, + {gen::WeightType::kPartonShowerWeights, "PartonShower"}, + {gen::WeightType::kUnknownWeights, "Unknown"}, + }; + //std::unordered_map weightGroupIndices_; + int lheWeightPrecision_; + bool storeAllPSweights_; + + enum { inLHE, inGen }; +}; +//put back if needed; till now not used +LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params) + : lheWeightTokens_( + edm::vector_transform(params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + lheWeightInfoTokens_(edm::vector_transform( + params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightToken_(consumes(params.getParameter("genWeights"))), + genWeightInfoToken_(consumes(params.getParameter("genWeights"))), + genEventInfoToken_(consumes(params.getParameter("genEvent"))), + genLumiInfoHeadTag_(mayConsume(params.getParameter("genLumiInfoHeader"))), + weightgroups_(edm::vector_transform(params.getParameter>("weightgroups"), + [](auto& c) { return gen::WeightType(c.at(0)); })), + maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), + pdfIds_(params.getUntrackedParameter>("pdfIds", {})), + lheWeightPrecision_(params.getParameter("lheWeightPrecision")), + storeAllPSweights_(params.getParameter("storeAllPSweights")) +{ + if (weightgroups_.size() != maxGroupsPerType_.size()) + throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); + produces>(); + produces(); + produces(); + produces(); +} + +void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { + //access counter for weight sums + Counter& counter = *streamCache(id)->get(); + + edm::Handle lheWeightHandle; + bool foundLheWeights = false; + for (auto& token : lheWeightTokens_) { + iEvent.getByToken(token, lheWeightHandle); + if (lheWeightHandle.isValid()) { + foundLheWeights = true; + break; + } + } + //Taken from genweight producer //Added sroychow + // generator information (always available) + auto const& genInfo = iEvent.get(genEventInfoToken_); + const double genWeight = genInfo.weight(); + // table for gen info, always available + auto outGeninfo = std::make_unique(1, "genWeightNEW", true); + outGeninfo->setDoc("generator weight"); + outGeninfo->addColumnValue("", genInfo.weight(), "generator weight", nanoaod::FlatTable::FloatColumn); + iEvent.put(std::move(outGeninfo)); + //this will take care of sum of genWeights + counter.incGenOnly(genWeight); + + WeightsContainer lheWeights; + if (foundLheWeights) { + const GenWeightProduct* lheWeightProduct = lheWeightHandle.product(); + lheWeights = lheWeightProduct->weights(); + } + + edm::Handle genWeightHandle; + iEvent.getByToken(genWeightToken_, genWeightHandle); + const GenWeightProduct* genWeightProduct = genWeightHandle.product(); + WeightsContainer genWeights = genWeightProduct->weights(); + + auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); + + auto lheWeightTables = std::make_unique>(); + if (foundLheWeights) { + addWeightGroupToTable(lheWeightTables, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + } + + addWeightGroupToTable(lheWeightTables, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); + + iEvent.put(std::move(lheWeightTables)); + /* + std::string& model_label = streamCache(id)->getLabel(); + auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); + iEvent.put(std::move(outM), "genModel"); + */ + //std::cout << "From Event:\n"; + //for(auto& cm : counter.weightSumMap_) + // std::cout << "WeightName:" << cm.first + // << "\t size:" << cm.second.size() + // << "\t First value:" << cm.second.at(0) + // << std::endl; +} + +void LHEWeightsTableProducer::addWeightGroupToTable(std::unique_ptr>& lheWeightTables, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, Counter& counter, + double genWeight) const { + std::unordered_map typeCount = {}; + for (auto& type : gen::allWeightTypes) + typeCount[type] = 0; + + for (const auto& groupInfo : weightInfos) { + std::string entryName = typeName; + gen::WeightType weightType = groupInfo.group->weightType(); + std::string name = weightTypeNames_.at(weightType); + std::string label = groupInfo.group->name(); + auto& weights = allWeights.at(groupInfo.index); + label.append("; "); + if (false && weightType == gen::WeightType::kScaleWeights && groupInfo.group->isWellFormed() && + groupInfo.group->nIdsContained() < 10) { + weights = orderedScaleWeights(weights, dynamic_cast(groupInfo.group)); + label.append( + "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" + " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" + " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); + } else if (!storeAllPSweights_ && weightType == gen::WeightType::kPartonShowerWeights && groupInfo.group->isWellFormed()) { + const gen::PartonShowerWeightGroupInfo* psgInfo = dynamic_cast(groupInfo.group); + //std::cout << "PSWeights size :" << weights.size() + // << "\tWtnames size:" << psgInfo->getWeightNames().size() + // << std::endl; + //std::cout << "WeightMetaInfo size:" << psgInfo->idsContained().size() << std::endl; + //for(unsigned int i = 0 ; i < psgInfo->idsContained().size(); i++) + // std::cout << "Index :" << i << "\t" << psgInfo->idsContained().at(i).label << std::endl; + std::cout << "PS weights \n Index: 1\t" << psgInfo->idsContained().at(0).label + << "\t value:" << weights.at(0) << std::endl; + std::cout << "PS weights \n Index: 1\t" << psgInfo->idsContained().at(1).label + << "\t value:" << weights.at(1) << std::endl; + for (unsigned int i = 6; i < 10; i++) + std::cout << "Index :" << i + << "\t weight name:" << psgInfo->idsContained().at(i).label + << "\t value:" << weights.at(i) + << std::endl; + weights = getPreferredPSweights(weights, dynamic_cast(groupInfo.group)); + label.append("PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2"); + } else + label.append(groupInfo.group->description()); + + entryName.append(name); + entryName.append("Weight"); + if (typeCount[weightType] > 0) { + entryName.append("AltSet"); + entryName.append(std::to_string(typeCount[weightType])); + } + counter.incLHE(genWeight, weights, entryName); + lheWeightTables->emplace_back(weights.size(), entryName, false); + lheWeightTables->back().addColumn("", weights, label, nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + typeCount[weightType]++; + + //std::cout << "Weight type read: " << name << std::endl; + } +} + +WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, + gen::WeightType weightType, + int& maxStore) const { + WeightGroupDataContainer group; + if (weightType == gen::WeightType::kPdfWeights && pdfIds_.size() > 0) { + group = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + } else + group = weightsHandle->weightGroupsAndIndicesByType(weightType); + + if (maxStore < 0 || static_cast(group.size()) <= maxStore) { + // Modify size in case one type of weight is present in multiple products + maxStore -= group.size(); + return group; + } + return std::vector(group.begin(), group.begin() + maxStore); +} + +std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, + const gen::ScaleWeightGroupInfo* scaleGroup) const { + std::vector weights; + weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR1muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->centralIndex())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR1muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF2Index())); + + return weights; +} + +std::vector LHEWeightsTableProducer::getPreferredPSweights(const std::vector& psWeights, + const gen::PartonShowerWeightGroupInfo* pswV) const { + std::vector psTosave; + + double baseline = psWeights.at(pswV->weightIndexFromLabel("Baseline"));//at 1 + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefHi"))/baseline ); // at 6 + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefHi"))/baseline ); // at 7 + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefLo"))/baseline ); // at 8 + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefLo"))/baseline ); // at 9 + return psTosave; +} + +void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, + edm::Run const&, + edm::EventSetup const&, + CounterMap* runCounterMap) const { + std::cout << "<<<<>>>>>\n"; + std::cout << "Map label:" << (*streamCache(id)).active_label << std::endl; + Counter& counter = *streamCache(id)->get(); + for(auto& cm : counter.weightSumMap_) + std::cout << "WeightName:" << cm.first + << "\t size:" << cm.second.size() + << "\t First value:" << cm.second.at(0) + << std::endl; + std::cout << "<<<<>>>>>\n"; + //this takes care for mergeing all the weight sums + runCounterMap->mergeSumMap(*streamCache(id)); +} + +void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const { + auto out = std::make_unique(); + + for (auto x : runCounterMap->countermap) { + auto& runCounter = x.second; + std::string label = std::string("_") + x.first; + std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; + + out->addInt("genEventCountNEW" + label, "event count" + doclabel, runCounter.num_); + out->addFloat("genEventSumwNEW" + label, "sum of gen weights" + doclabel, runCounter.sumw_); + out->addFloat("genEventSumw2NEW" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); + + double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; + //Sum from map + std::cout << "SUM map size:" << runCounter.weightSumMap_.size() << std::endl; + for(auto& sumw : runCounter.weightSumMap_) { + std::cout << "Adding wsum for:" + << sumw.first << "\t Size:" + << sumw.second.size() + << "\t First value:" << sumw.second.at(0) + << std::endl; + + //Normalize with genEventSumw + for(auto& val : sumw.second) val *= norm; + out->addVFloat(sumw.first + "Sumw" + label, + "Sum of genEventWeight *" + sumw.first + "[i]/genEventSumw" + doclabel, + sumw.second) ; + } + } + iRun.put(std::move(out)); +} +void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add>("lheWeights"); + desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) + ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); + //desc.add>("genWeights"); + desc.add("genWeights"); + desc.add("genEvent", edm::InputTag("generator"))->setComment("tag for the GenEventInfoProduct, to get the main weight"); + desc.add("genLumiInfoHeader", edm::InputTag("generator"))->setComment("tag for the GenLumiInfoProduct, to get the model string"); + desc.add>("weightgroups"); + desc.add>("maxGroupsPerType"); + desc.addOptionalUntracked>("pdfIds"); + desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); + desc.add("storeAllPSweights", -1)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); + descriptions.addDefault(desc); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(LHEWeightsTableProducer); diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index 6e81ab1ce2023..6e5a45c467f43 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -5,6 +5,7 @@ from PhysicsTools.NanoAOD.particlelevel_cff import * from PhysicsTools.NanoAOD.lheInfoTable_cfi import * from PhysicsTools.NanoAOD.genWeightsTable_cfi import * +from PhysicsTools.NanoAOD.lheWeightsTable_cfi import * genWeights = cms.EDProducer("GenWeightProductProducer", genInfo = cms.InputTag("generator"), @@ -15,7 +16,7 @@ failIfInvalidXML = cms.untracked.bool(True) #lheWeightSourceLabels = cms.vstring(["externalLHEProducer", "source"]) ) - +''' lheWeightsTable = cms.EDProducer( "LHEWeightsTableProducer", lheWeights = cms.VInputTag(["externalLHEProducer", "source", "lheWeights"]), @@ -32,7 +33,7 @@ #unknownOnlyIfEmpty = cms.untracked.vstring(['scale', 'PDF']), #unknownOnlyIfAllEmpty = cms.untracked.bool(False), ) - +''' nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( tag = cms.string("untagged"), diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index 550a886df1757..e0db5a539f86b 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -16,7 +16,12 @@ namespace gen { struct WeightGroupData { size_t index; - const gen::WeightGroupInfo* group; + std::unique_ptr group; + }; + + struct SharedWeightGroupData { + size_t index; + std::shared_ptr group; }; } // namespace gen @@ -31,14 +36,14 @@ class GenWeightInfoProduct { GenWeightInfoProduct& operator=(GenWeightInfoProduct&& other); const edm::OwnVector& allWeightGroupsInfo() const; - const gen::WeightGroupInfo* containingWeightGroupInfo(int index) const; - const gen::WeightGroupInfo* orderedWeightGroupInfo(int index) const; - std::vector weightGroupsByType(gen::WeightType type) const; + const std::unique_ptr containingWeightGroupInfo(int index) const; + const std::unique_ptr orderedWeightGroupInfo(int index) const; + std::vector> weightGroupsByType(gen::WeightType type) const; std::vector weightGroupIndicesByType(gen::WeightType type) const; std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; - void addWeightGroupInfo(gen::WeightGroupInfo* info); + void addWeightGroupInfo(std::unique_ptr info); const int numberOfGroups() const { return weightGroupsInfo_.size(); } private: diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index 59f67ce2e3a91..561a8dc805ddb 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -6,6 +6,9 @@ #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" namespace gen { + enum class PSVarType { muR, cNS, con, def, red}; + enum class PSSplittingType { combined, g2gg, x2xg, g2qq }; + class PartonShowerWeightGroupInfo : public WeightGroupInfo { public: PartonShowerWeightGroupInfo() : PartonShowerWeightGroupInfo("") {} @@ -17,22 +20,13 @@ namespace gen { virtual ~PartonShowerWeightGroupInfo() override {} void copy(const PartonShowerWeightGroupInfo &other); virtual PartonShowerWeightGroupInfo *clone() const override; - - // TODO: replace these general functions with specific ones - int upIndex(std::string weightName) { - int index = weightIndexFromLabel(weightName+"Hi"); - return index >= 0 ? index : weightIndexFromLabel(weightName+"_up"); - } - int downIndex(std::string weightName) { - int index = weightIndexFromLabel(weightName+"Low"); - return index >= 0 ? index : weightIndexFromLabel(weightName+"_dn"); - } - std::vector getWeightNames() const { return weightNames; } + void setNameIsPythiaSyntax(bool isPythiaSyntax) { nameIsPythiaSyntax_ = isPythiaSyntax; } + bool nameIsPythiaSyntax(bool isPythiaSyntax) const { return nameIsPythiaSyntax_; } + int variationIndex(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; + int variationIndex(bool isISR, bool isUp, PSVarType variationType) const; private: - std::unordered_map> weightNameToUpDown; - std::vector weightNames; - // Is a variation of the functional form of the dynamic scale + bool nameIsPythiaSyntax_ = false; }; } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index e5130b9d62c36..c57119487f115 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -12,21 +12,34 @@ namespace gen { std::vector muIndices_; bool containsCentral_ = false; int lhaid_ = -1; + bool hasAllWeights = false; // Dyn_scale std::vector dynNames_; std::vector> dynVec_; - void setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF); - void setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF, size_t dynNum, std::string dynName); - inline int getIndex(int muR, int muF) const { return 3 * muR + muF; } + inline int indexFromMus(int muR, int muF) const { return 3 * muR + muF; } inline bool isValidValue(float mu) const { return mu == 0.5 || mu == 1.0 || mu == 2.0; } + enum scaleIndices { + muR0p5_muF0p5_idx = 0, + muR0p5_muF1_idx = 1, + muR0p5_muF2_idx = 2, + muR1_muF0p5_idx = 3, + Central_idx = 4, + muR1_muF2_idx = 5, + muR2_muF0p5_idx = 6, + muR2_muF1_idx = 7, + muR2_muF2_idx = 8 + }; + public: + static const unsigned int MIN_SCALE_VARIATIONS = 9; ScaleWeightGroupInfo() : ScaleWeightGroupInfo("") {} ScaleWeightGroupInfo(std::string header, std::string name) - : WeightGroupInfo(header, name), muIndices_(9, -1), dynVec_(9) { + : WeightGroupInfo(header, name), muIndices_(MIN_SCALE_VARIATIONS, -1), dynVec_(MIN_SCALE_VARIATIONS) { weightType_ = WeightType::kScaleWeights; isFunctionalFormVar_ = false; + isWellFormed_ = true; } ScaleWeightGroupInfo(std::string header) : ScaleWeightGroupInfo(header, header) {} ScaleWeightGroupInfo(const ScaleWeightGroupInfo& other) { copy(other); } @@ -34,42 +47,44 @@ namespace gen { void copy(const ScaleWeightGroupInfo& other); virtual ScaleWeightGroupInfo* clone() const override; bool containsCentralWeight() const { return containsCentral_; } + void addContainedId(int globalIndex, std::string id, std::string label, float muR, float muF); + bool isWellFormed() { return isWellFormed_ && hasAllWeights; } - void setMuRMuFIndex( - int globalIndex, std::string id, float muR, float muF, size_t dynNum = -1, std::string dynName = ""); - void addContainedId(int weightEntry, std::string id, std::string label, float muR, float muF); + void setMuRMuFIndex(int globalIndex, std::string id, float muR, float muF); + void setDyn(int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName); int lhaid() { return lhaid_; } void setLhaid(int lhaid) { lhaid_ = lhaid; } // Is a variation of the functional form of the dynamic scale bool isFunctionalFormVariation(); void setIsFunctionalFormVariation(bool functionalVar) { isFunctionalFormVar_ = functionalVar; } - size_t centralIndex() const { return muIndices_.at(4); } - size_t muR1muF2Index() const { return muIndices_.at(5); } - size_t muR1muF05Index() const { return muIndices_.at(3); } - size_t muR2muF05Index() const { return muIndices_.at(6); } - size_t muR2muF1Index() const { return muIndices_.at(7); } - size_t muR2muF2Index() const { return muIndices_.at(8); } - size_t muR05muF05Index() const { return muIndices_.at(0); } - size_t muR05muF1Index() const { return muIndices_.at(1); } - size_t muR05muF2Index() const { return muIndices_.at(2); } + int centralIndex() const { return muIndices_.at(Central_idx); } + int muR1muF2Index() const { return muIndices_.at(muR1_muF2_idx); } + int muR1muF05Index() const { return muIndices_.at(muR1_muF0p5_idx); } + int muR2muF05Index() const { return muIndices_.at(muR2_muF0p5_idx); } + int muR2muF1Index() const { return muIndices_.at(muR2_muF1_idx); } + int muR2muF2Index() const { return muIndices_.at(muR2_muF2_idx); } + int muR05muF05Index() const { return muIndices_.at(muR0p5_muF0p5_idx); } + int muR05muF1Index() const { return muIndices_.at(muR0p5_muF1_idx); } + int muR05muF2Index() const { return muIndices_.at(muR0p5_muF2_idx); } + // dynweight version - size_t centralIndex(std::string& dynName) const { return getScaleIndex(4, dynName); } - size_t muR1muF2Index(std::string& dynName) const { return getScaleIndex(5, dynName); } - size_t muR1muF05Index(std::string& dynName) const { return getScaleIndex(3, dynName); } - size_t muR2muF05Index(std::string& dynName) const { return getScaleIndex(6, dynName); } - size_t muR2muF1Index(std::string& dynName) const { return getScaleIndex(7, dynName); } - size_t muR2muF2Index(std::string& dynName) const { return getScaleIndex(8, dynName); } - size_t muR05muF05Index(std::string& dynName) const { return getScaleIndex(0, dynName); } - size_t muR05muF1Index(std::string& dynName) const { return getScaleIndex(1, dynName); } - size_t muR05muF2Index(std::string& dynName) const { return getScaleIndex(2, dynName); } + size_t centralIndex(std::string& dynName) const { return scaleIndex(Central_idx, dynName); } + size_t muR1muF2Index(std::string& dynName) const { return scaleIndex(muR1_muF2_idx, dynName); } + size_t muR1muF05Index(std::string& dynName) const { return scaleIndex(muR1_muF0p5_idx, dynName); } + size_t muR2muF05Index(std::string& dynName) const { return scaleIndex(muR2_muF0p5_idx, dynName); } + size_t muR2muF1Index(std::string& dynName) const { return scaleIndex(muR2_muF1_idx, dynName); } + size_t muR2muF2Index(std::string& dynName) const { return scaleIndex(muR2_muF2_idx, dynName); } + size_t muR05muF05Index(std::string& dynName) const { return scaleIndex(muR0p5_muF0p5_idx, dynName); } + size_t muR05muF1Index(std::string& dynName) const { return scaleIndex(muR0p5_muF1_idx, dynName); } + size_t muR05muF2Index(std::string& dynName) const { return scaleIndex(muR0p5_muF2_idx, dynName); } - size_t getScaleIndex(float muR, float muF, size_t dynNum) const; - size_t getScaleIndex(float muR, float muF, std::string& dynName) const; - size_t getScaleIndex(int index, std::string& dynName) const; - size_t getScaleIndex(float muR, float muF) const; + size_t scaleIndex(float muR, float muF, size_t dynNum) const; + size_t scaleIndex(float muR, float muF, std::string& dynName) const; + size_t scaleIndex(int index, std::string& dynName) const; + size_t scaleIndex(float muR, float muF) const; - size_t getScaleIndex(int index, size_t dynNum) const { return dynVec_.at(index).at(dynNum); } - std::vector getDynNames() const; + size_t scaleIndex(int index, size_t dynNum) const { return dynVec_.at(index).at(dynNum); } + std::vector dynNames() const; }; } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index 9db98139ec9e6..d53aa6e90c509 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -43,9 +43,9 @@ namespace gen { public: WeightGroupInfo() : WeightGroupInfo("") {} WeightGroupInfo(std::string header, std::string name) - : isWellFormed_(true), headerEntry_(header), name_(name), firstId_(-1), lastId_(-1) {} + : isWellFormed_(false), headerEntry_(header), name_(name), firstId_(-1), lastId_(-1) {} WeightGroupInfo(std::string header) - : isWellFormed_(true), headerEntry_(header), name_(header), firstId_(-1), lastId_(-1) {} + : isWellFormed_(false), headerEntry_(header), name_(header), firstId_(-1), lastId_(-1) {} WeightGroupInfo(const WeightGroupInfo& other) { copy(other); } WeightGroupInfo& operator=(const WeightGroupInfo& other) { copy(other); @@ -85,6 +85,7 @@ namespace gen { void setIsWellFormed(bool wellFormed) { isWellFormed_ = wellFormed; } bool isWellFormed() const { return isWellFormed_; } int weightIndexFromLabel(std::string weightLabel) const; + std::vector weightLabels() const; protected: bool isWellFormed_; diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 7b53436c4c7ff..23b63469354f2 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -22,46 +22,48 @@ const edm::OwnVector& GenWeightInfoProduct::allWeightGroup return weightGroupsInfo_; } -const gen::WeightGroupInfo* GenWeightInfoProduct::containingWeightGroupInfo(int index) const { +const std::unique_ptr GenWeightInfoProduct::containingWeightGroupInfo(int index) const { for (const auto& weightGroup : weightGroupsInfo_) { if (weightGroup.indexInRange(index)) - return &weightGroup; + return std::make_unique(weightGroup); } throw std::domain_error("Failed to find containing weight group"); } -const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { +const std::unique_ptr GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) throw std::range_error("Weight index out of range!"); - return &weightGroupsInfo_[weightGroupIndex]; + return std::make_unique(weightGroupsInfo_[weightGroupIndex]); } std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type) const { std::vector matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back({i, weightGroupsInfo_[i].clone()}); + matchingGroups.push_back({i, std::make_unique(weightGroupsInfo_[i])}); } return matchingGroups; } -std::vector GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { - std::vector matchingGroups; +std::vector> GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { + std::vector> matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back(weightGroupsInfo_[i].clone()); + matchingGroups.push_back(std::make_unique(weightGroupsInfo_[i])); } return matchingGroups; } std::optional GenWeightInfoProduct::pdfGroupWithIndexByLHAID(int lhaid) const { - auto pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); + std::vector pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = dynamic_cast(data.group); + auto pdfGroup = std::make_unique(*static_cast(data.group.release())); return pdfGroup->containsLhapdfId(lhaid); }); - return matchingPdfSet != pdfGroups.end() ? std::optional(*matchingPdfSet) : std::nullopt; + + return matchingPdfSet == pdfGroups.end() ? std::nullopt : + std::optional({matchingPdfSet->index, std::move(matchingPdfSet->group)}); } std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLHAIDs( @@ -71,11 +73,12 @@ std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLH for (auto lhaid : lhaids) { auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = dynamic_cast(data.group); + auto pdfGroup = std::make_unique(*static_cast(data.group.release())); return pdfGroup->containsLhapdfId(lhaid); }); - if (matchingPdfSet != pdfGroups.end()) - pdfGroups.push_back(*matchingPdfSet); + if (matchingPdfSet != pdfGroups.end()) { + pdfGroups.push_back({matchingPdfSet->index, std::move(matchingPdfSet->group)}); + } } return pdfGroups; @@ -90,4 +93,4 @@ std::vector GenWeightInfoProduct::weightGroupIndicesByType(gen::WeightType return matchingGroupIndices; } -void GenWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo* info) { weightGroupsInfo_.push_back(info); } +void GenWeightInfoProduct::addWeightGroupInfo(std::unique_ptr info) { weightGroupsInfo_.push_back(std::move(info)); } diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc index 72dc7b6f48133..99826e88d14b9 100644 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -26,35 +26,35 @@ namespace gen { } WeightGroupInfo::addContainedId(globalIndex, id, label); setMuRMuFIndex(globalIndex, id, muR, muF); + std::cout << hasAllWeights << " " << isWellFormed_ << std::endl; + for (int muidx : muIndices_) { + std::cout << muidx << " "; + } + std::cout << std::endl; } - void ScaleWeightGroupInfo::setMuRMuFIndex( - int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName) { - auto metaInfo = weightMetaInfoByGlobalIndex(id, globalIndex); - if ((int)dynNum == -1) - setMuRMuFIndex(metaInfo, muR, muF); - else - setMuRMuFIndex(metaInfo, muR, muF, dynNum, dynName); - } - - void ScaleWeightGroupInfo::setMuRMuFIndex(WeightMetaInfo& info, float muR, float muF) { - int index = getIndex(muR, muF); - if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { + void ScaleWeightGroupInfo::setMuRMuFIndex(int globalIndex, std::string id, float muR, float muF) { + auto info = weightMetaInfoByGlobalIndex(id, globalIndex); + int index = indexFromMus(muR, muF); + if (!(isValidValue(muR) && isValidValue(muF))) { isWellFormed_ = false; return; } - if (index == 4) + if (index == Central_idx) containsCentral_ = true; muIndices_[index] = info.localIndex; - } - void ScaleWeightGroupInfo::setMuRMuFIndex( - WeightMetaInfo& info, float muR, float muF, size_t dynNum, std::string dynName) { - int index = getIndex(muR, muF); - if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { - isWellFormed_ = false; - return; + for (int muidx : muIndices_) { + if (muidx == -1) + return; } + hasAllWeights = true; + } + + void ScaleWeightGroupInfo::setDyn( + int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName) { + auto info = weightMetaInfoByGlobalIndex(id, globalIndex); + int index = indexFromMus(muR, muF); // resize if too small if (dynVec_.at(index).size() < dynNum + 1) { for (auto& dynIt : dynVec_) @@ -67,39 +67,37 @@ namespace gen { dynVec_[index][dynNum] = info.localIndex; } - size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF, std::string& dynName) const { + size_t ScaleWeightGroupInfo::scaleIndex(float muR, float muF, std::string& dynName) const { auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); if (it == dynNames_.end()) return -1; else - return getScaleIndex(muR, muF, it - dynNames_.begin()); + return scaleIndex(muR, muF, it - dynNames_.begin()); } - size_t ScaleWeightGroupInfo::getScaleIndex(int index, std::string& dynName) const { + + size_t ScaleWeightGroupInfo::scaleIndex(int index, std::string& dynName) const { auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); if (it == dynNames_.end()) return -1; else - return getScaleIndex(index, it - dynNames_.begin()); + return scaleIndex(index, it - dynNames_.begin()); } - size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF, size_t dynNum) const { - int index = getIndex(muR, muF); - if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF)) || dynNum + 1 > dynNames_.size()) { - // Bad access! + size_t ScaleWeightGroupInfo::scaleIndex(float muR, float muF, size_t dynNum) const { + ; + if (!(isValidValue(muR) && isValidValue(muF)) || dynNum + 1 > dynNames_.size()) return -1; - } - return getScaleIndex(index, dynNum); + else + return scaleIndex(indexFromMus(muR, muF), dynNum); } - size_t ScaleWeightGroupInfo::getScaleIndex(float muR, float muF) const { - int index = getIndex(muR, muF); - if (index < 0 || index > 8 || !(isValidValue(muR) && isValidValue(muF))) { - // Bad access! + size_t ScaleWeightGroupInfo::scaleIndex(float muR, float muF) const { + if (!(isValidValue(muR) && isValidValue(muF))) return -1; - } - return muIndices_.at(index); + else + return muIndices_.at(indexFromMus(muR, muF)); } - std::vector ScaleWeightGroupInfo::getDynNames() const { + std::vector ScaleWeightGroupInfo::dynNames() const { std::vector returnVec; for (auto item : dynNames_) { if (!item.empty()) diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index 04aa722601d9e..8e199219435ac 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -89,6 +89,14 @@ namespace gen { weightLabelsToIndices_[weight.label] = weight.localIndex; } + std::vector WeightGroupInfo::weightLabels() const { + std::vector labels; + labels.reserve(idsContained_.size()); + for (const auto& weight : idsContained_) + labels.push_back(weight.label); + return labels; + } + int WeightGroupInfo::weightIndexFromLabel(std::string weightLabel) const { if (!weightLabelsToIndices_.empty()) { if (weightLabelsToIndices_.find(weightLabel) != weightLabelsToIndices_.end()) From 8f101c5499cd0d49c7a1418ce1907b707d8d8bc7 Mon Sep 17 00:00:00 2001 From: Dylan Teague Date: Wed, 14 Oct 2020 20:05:09 +0200 Subject: [PATCH 05/16] Add more error handling Fix off-by-one error in pdf weight splitting Templatize product adder in WeightHelper Expand emission functionality to PSWeight needs to add more to make sure works correctly clang-format the partonshowerWeightGroupInfo.cc file as well Fix central weight and error from mg26xNew Fix PSWeights in LumiHeader to work w diff pythia format --- .../Core/interface/WeightHelper.h | 32 +- .../Core/src/LHEWeightHelper.cc | 16 +- GeneratorInterface/Core/src/WeightHelper.cc | 70 +-- .../plugins/GenWeightsTableProducer.cc | 591 +++++++++++++----- .../interface/PartonShowerWeightGroupInfo.h | 2 +- .../src/PartonShowerWeightGroupInfo.cc | 70 ++- 6 files changed, 576 insertions(+), 205 deletions(-) diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index cfc14ceffc7db..e8955e541a957 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -30,8 +30,10 @@ namespace gen { public: WeightHelper(); edm::OwnVector weightGroups() { return weightGroups_; } - std::unique_ptr weightProduct(std::vector, float w0); - std::unique_ptr weightProduct(std::vector, float w0); + + template + std::unique_ptr weightProduct(std::vector weights, float w0); + void setModel(std::string model) { model_ = model; } void addUnassociatedGroup() { weightGroups_.push_back(std::make_unique("unassociated")); @@ -57,10 +59,11 @@ namespace gen { bool isPdfWeightGroup(const ParsedWeight& weight); bool isPartonShowerWeightGroup(const ParsedWeight& weight); bool isOrphanPdfWeightGroup(ParsedWeight& weight); - void updateScaleInfo(const ParsedWeight& weight, int index); + void updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight); void updateMEParamInfo(const ParsedWeight& weight, int index); - void updatePdfInfo(const ParsedWeight& weight, int index); + void updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight); void cleanupOrphanCentralWeight(); + bool splitPdfWeight(ParsedWeight& weight); int lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup); std::string searchAttributes(const std::string& label, const ParsedWeight& weight) const; @@ -83,6 +86,27 @@ namespace gen { void buildGroups(); std::string searchString(const std::string& label, const std::string& name); }; + + // Templated function (needed here because of plugins) + template + std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { + auto weightProduct = std::make_unique(w0); + weightProduct->setNumWeightSets(weightGroups_.size()); + int weightGroupIndex = 0; + int i = 0; + // This happens if there are no PS weights, so the weights vector contains only the central GEN weight. + // Just add an empty product (need for all cases or...?) + if (weights.size() > 1) { + for (const auto& weight : weights) { + if constexpr (std::is_same::value) + weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i, weightGroupIndex); + else if (std::is_same::value) + weightGroupIndex = addWeightToProduct(weightProduct, weight, std::to_string(i), i, weightGroupIndex); + i++; + } + } + return std::move(weightProduct); + } } // namespace gen #endif diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 013072992d45e..5403b3bfd4c60 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -24,22 +24,23 @@ namespace gen { std::string fullHeader = boost::algorithm::join(headerLines_, ""); if (debug_) std::cout << "Full header is \n" << fullHeader << std::endl; - int xmlError = xmlDoc.Parse(fullHeader.c_str()); + // in case of > instead of < - if (xmlError != 0) { + if (xmlError != 0 && failIfInvalidXML_) { + xmlDoc.PrintError(); + throw std::runtime_error("XML is unreadable because of above error."); + } else if (xmlError != 0 && !failIfInvalidXML_) { boost::replace_all(fullHeader, "<", "<"); boost::replace_all(fullHeader, ">", ">"); xmlError = xmlDoc.Parse(fullHeader.c_str()); } + // error persists (how to handle error?) if (xmlError != 0) { std::cerr << "WARNING: Error in parsing XML of LHE weight header!" << std::endl; xmlDoc.PrintError(); - if (failIfInvalidXML_) - throw std::runtime_error("XML is unreadable because of above error."); - else - return false; + return false; } return true; @@ -75,16 +76,13 @@ namespace gen { if (strcmp(e->Name(), "weight") == 0) { if (debug_) std::cout << "Found weight unmatched to group\n"; - // need to fix addGroup(e, groupName, groupIndex, weightIndex); } else if (strcmp(e->Name(), "weightgroup") == 0) { groupName = parseGroupName(e); if (debug_) std::cout << ">>>> Found a weight group: " << groupName << std::endl; - for (auto inner = e->FirstChildElement("weight"); inner != nullptr; inner = inner->NextSiblingElement("weight")) addGroup(inner, groupName, groupIndex, weightIndex); - } else std::cout << "Found an invalid entry\n"; groupIndex++; diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index bfcc373e7bccd..68a643bf3d9b1 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -17,9 +17,13 @@ namespace gen { } bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) { - const std::string& name = boost::to_lower_copy(weight.groupname); - return name.find("isr") != std::string::npos || name.find("fsr") != std::string::npos || - name.find("nominal") != std::string::npos || name.find("baseline") != std::string::npos; + const std::string& groupname = boost::to_lower_copy(weight.groupname); + std::vector psNames = {"isr", "fsr", "nominal", "baseline", "emission"}; + for (auto name : psNames) { + if (groupname.find(name) != std::string::npos) + return true; + } + return false; } bool WeightHelper::isOrphanPdfWeightGroup(ParsedWeight& weight) { @@ -74,9 +78,7 @@ namespace gen { return ""; } - void WeightHelper::updateScaleInfo(const ParsedWeight& weight, int index) { - auto& scaleGroup = dynamic_cast(weightGroups_[index]); - + void WeightHelper::updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight) { std::string muRText = searchAttributes("mur", weight); std::string muFText = searchAttributes("muf", weight); std::string dynNumText = searchAttributes("dyn", weight); @@ -133,8 +135,7 @@ namespace gen { return -1; } - void WeightHelper::updatePdfInfo(const ParsedWeight& weight, int index) { - auto& pdfGroup = dynamic_cast(weightGroups_[index]); + void WeightHelper::updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight) { int lhaid = lhapdfId(weight, pdfGroup); if (pdfGroup.parentLhapdfId() < 0) { int parentId = lhaid - LHAPDF::lookupPDF(lhaid).second; @@ -156,20 +157,17 @@ namespace gen { pdfGroup.addLhaid(lhaid); } - // TODO: Could probably recycle this code better - std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { - auto weightProduct = std::make_unique(w0); - weightProduct->setNumWeightSets(weightGroups_.size()); - int weightGroupIndex = 0; - // This happens if there are no PS weights, so the weights vector contains only the central GEN weight. - // Just add an empty product - if (weights.size() > 1) { - for (unsigned int i = 0; i < weights.size(); i++) { - std::string id = std::to_string(i); - addWeightToProduct(weightProduct, weights.at(i), id, i, weightGroupIndex); + bool WeightHelper::splitPdfWeight(ParsedWeight& weight) { + if (weightGroups_[weight.wgtGroup_idx].weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = dynamic_cast(weightGroups_[weight.wgtGroup_idx]); + int lhaid = lhapdfId(weight, pdfGroup); + if (lhaid > 0 && !pdfGroup.isIdInParentSet(lhaid) && pdfGroup.parentLhapdfId() > 0) { + weightGroups_.push_back(*buildGroup(weight)); + weight.wgtGroup_idx++; + return true; } } - return std::move(weightProduct); + return false; } void WeightHelper::cleanupOrphanCentralWeight() { @@ -197,17 +195,6 @@ namespace gen { } } - std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { - auto weightProduct = std::make_unique(w0); - weightProduct->setNumWeightSets(weightGroups_.size()); - int weightGroupIndex = 0; - int i = 0; - for (const auto& weight : weights) { - weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i++, weightGroupIndex); - } - return std::move(weightProduct); - } - int WeightHelper::addWeightToProduct( std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex) { bool isUnassociated = false; @@ -333,11 +320,9 @@ namespace gen { void WeightHelper::buildGroups() { weightGroups_.clear(); - int currentGroupIdx = 0; int groupOffset = 0; for (auto& weight : parsedWeights_) { weight.wgtGroup_idx += groupOffset; - currentGroupIdx = weight.wgtGroup_idx; if (debug_) std::cout << "Building group for weight " << weight.content << " group " << weight.groupname << " group index " << weight.wgtGroup_idx << std::endl; @@ -346,23 +331,18 @@ namespace gen { if (weight.wgtGroup_idx == numGroups) { weightGroups_.push_back(*buildGroup(weight)); } else if (weight.wgtGroup_idx >= numGroups) - throw std::range_error("Invalid group index " + currentGroupIdx); + throw std::range_error("Invalid group index " + weight.wgtGroup_idx); // split PDF groups - if (weightGroups_[currentGroupIdx].weightType() == gen::WeightType::kPdfWeights) { - auto& pdfGroup = dynamic_cast(weightGroups_[currentGroupIdx]); - int lhaid = lhapdfId(weight, pdfGroup); - if (lhaid > 0 && !pdfGroup.isIdInParentSet(lhaid) && pdfGroup.parentLhapdfId() > 0) { - weightGroups_.push_back(*buildGroup(weight)); - groupOffset++; - } - } - WeightGroupInfo& group = weightGroups_[currentGroupIdx]; + if (splitPdfWeight(weight)) + groupOffset++; + + WeightGroupInfo& group = weightGroups_[weight.wgtGroup_idx]; group.addContainedId(weight.index, weight.id, weight.content); if (group.weightType() == gen::WeightType::kScaleWeights) - updateScaleInfo(weight, currentGroupIdx); + updateScaleInfo(dynamic_cast(group), weight); else if (group.weightType() == gen::WeightType::kPdfWeights) { - updatePdfInfo(weight, currentGroupIdx); + updatePdfInfo(dynamic_cast(group), weight); } } cleanupOrphanCentralWeight(); diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 6b678099e98b8..5cc5569643bdd 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -14,48 +14,47 @@ #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "boost/algorithm/string.hpp" +#include + #include #include #include #include namespace { + /// ---- Cache object for running sums of weights ---- + struct Counter { + Counter() : num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {} - void mergeSumVectors(std::vector& v1, std::vector const& v2) { - if (v1.empty() && !v2.empty()) - v1.resize(v2.size(), 0); - if (!v2.empty()) - for (unsigned int i = 0, n = v1.size(); i < n; ++i) - v1[i] += v2[i]; - } + // the counters + long long num; + long double sumw; + long double sumw2; + std::vector sumPDF, sumScale, sumRwgt, sumNamed, sumPS; - /// ---- Cache object for running sums of weights ---- - class Counter { - public: void clear() { - num_ = 0; - sumw_ = 0; - sumw2_ = 0; - sumPDF_.clear(); - sumScale_.clear(); - sumRwgt_.clear(); - sumNamed_.clear(); - sumPS_.clear(); + num = 0; + sumw = 0; + sumw2 = 0; + sumPDF.clear(); + sumScale.clear(); + sumRwgt.clear(); + sumNamed.clear(), sumPS.clear(); } // inc the counters void incGenOnly(double w) { - num_++; - sumw_ += w; - sumw2_ += (w * w); + num++; + sumw += w; + sumw2 += (w * w); } void incPSOnly(double w0, const std::vector& wPS) { if (!wPS.empty()) { - if (sumPS_.empty()) - sumPS_.resize(wPS.size(), 0); + if (sumPS.empty()) + sumPS.resize(wPS.size(), 0); for (unsigned int i = 0, n = wPS.size(); i < n; ++i) - sumPS_[i] += (w0 * wPS[i]); + sumPS[i] += (w0 * wPS[i]); } } @@ -69,55 +68,62 @@ namespace { incGenOnly(w0); // then add up variations if (!wScale.empty()) { - if (sumScale_.empty()) - sumScale_.resize(wScale.size(), 0); + if (sumScale.empty()) + sumScale.resize(wScale.size(), 0); for (unsigned int i = 0, n = wScale.size(); i < n; ++i) - sumScale_[i] += (w0 * wScale[i]); + sumScale[i] += (w0 * wScale[i]); } if (!wPDF.empty()) { - if (sumPDF_.empty()) - sumPDF_.resize(wPDF.size(), 0); + if (sumPDF.empty()) + sumPDF.resize(wPDF.size(), 0); for (unsigned int i = 0, n = wPDF.size(); i < n; ++i) - sumPDF_[i] += (w0 * wPDF[i]); + sumPDF[i] += (w0 * wPDF[i]); } if (!wRwgt.empty()) { - if (sumRwgt_.empty()) - sumRwgt_.resize(wRwgt.size(), 0); + if (sumRwgt.empty()) + sumRwgt.resize(wRwgt.size(), 0); for (unsigned int i = 0, n = wRwgt.size(); i < n; ++i) - sumRwgt_[i] += (w0 * wRwgt[i]); + sumRwgt[i] += (w0 * wRwgt[i]); } if (!wNamed.empty()) { - if (sumNamed_.empty()) - sumNamed_.resize(wNamed.size(), 0); + if (sumNamed.empty()) + sumNamed.resize(wNamed.size(), 0); for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) - sumNamed_[i] += (w0 * wNamed[i]); + sumNamed[i] += (w0 * wNamed[i]); } incPSOnly(w0, wPS); } void merge(const Counter& other) { - num_ += other.num_; - sumw_ += other.sumw_; - sumw2_ += other.sumw2_; - - mergeSumVectors(sumScale_, other.sumScale_); - mergeSumVectors(sumPDF_, other.sumPDF_); - mergeSumVectors(sumRwgt_, other.sumRwgt_); - mergeSumVectors(sumNamed_, other.sumNamed_); - mergeSumVectors(sumPS_, other.sumPS_); + num += other.num; + sumw += other.sumw; + sumw2 += other.sumw2; + if (sumScale.empty() && !other.sumScale.empty()) + sumScale.resize(other.sumScale.size(), 0); + if (sumPDF.empty() && !other.sumPDF.empty()) + sumPDF.resize(other.sumPDF.size(), 0); + if (sumRwgt.empty() && !other.sumRwgt.empty()) + sumRwgt.resize(other.sumRwgt.size(), 0); + if (sumNamed.empty() && !other.sumNamed.empty()) + sumNamed.resize(other.sumNamed.size(), 0); + if (sumPS.empty() && !other.sumPS.empty()) + sumPS.resize(other.sumPS.size(), 0); + if (!other.sumScale.empty()) + for (unsigned int i = 0, n = sumScale.size(); i < n; ++i) + sumScale[i] += other.sumScale[i]; + if (!other.sumPDF.empty()) + for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i) + sumPDF[i] += other.sumPDF[i]; + if (!other.sumRwgt.empty()) + for (unsigned int i = 0, n = sumRwgt.size(); i < n; ++i) + sumRwgt[i] += other.sumRwgt[i]; + if (!other.sumNamed.empty()) + for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i) + sumNamed[i] += other.sumNamed[i]; + if (!other.sumPS.empty()) + for (unsigned int i = 0, n = sumPS.size(); i < n; ++i) + sumPS[i] += other.sumPS[i]; } - - //private: - // the counters - long long num_ = 0; - long double sumw_ = 0; - long double sumw2_ = 0; - - std::vector sumPDF_; - std::vector sumScale_; - std::vector sumRwgt_; - std::vector sumNamed_; - std::vector sumPS_; }; struct CounterMap { @@ -132,6 +138,8 @@ namespace { void clear() { for (auto x : countermap) x.second.clear(); + active_el = nullptr; + active_label = ""; } void setLabel(std::string label) { active_el = &(countermap[label]); @@ -165,8 +173,38 @@ namespace { std::string rwgtWeightDoc; }; + struct DynamicWeightChoiceGenInfo { + // choice of LHE weights + // ---- scale ---- + std::vector scaleWeightIDs; + std::string scaleWeightsDoc; + // ---- pdf ---- + std::vector pdfWeightIDs; + std::string pdfWeightsDoc; + // ---- ps ---- + std::vector defPSWeightIDs = {6, 7, 8, 9}; + std::vector defPSWeightIDs_alt = {27, 5, 26, 4}; + bool matchPS_alt = false; + std::vector psWeightIDs; + unsigned int psBaselineID = 1; + std::string psWeightsDoc; + + void setMissingWeight(int idx) { psWeightIDs[idx] = (matchPS_alt) ? defPSWeightIDs_alt[idx] : defPSWeightIDs[idx]; } + + bool empty() const { return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); } + }; + + struct LumiCacheInfoHolder { + CounterMap countermap; + DynamicWeightChoiceGenInfo weightChoice; + void clear() { + countermap.clear(); + weightChoice = DynamicWeightChoiceGenInfo(); + } + }; + float stof_fortrancomp(const std::string& str) { - std::string::size_type match = str.find("d"); + std::string::size_type match = str.find('d'); if (match != std::string::npos) { std::string pre = str.substr(0, match); std::string post = str.substr(match + 1); @@ -206,7 +244,7 @@ namespace { }; } // namespace -class GenWeightsTableProducer : public edm::global::EDProducer, +class GenWeightsTableProducer : public edm::global::EDProducer, edm::RunCache, edm::RunSummaryCache, edm::EndRunProducer> { @@ -224,11 +262,17 @@ class GenWeightsTableProducer : public edm::global::EDProducer>("namedWeightLabels")), lheWeightPrecision_(params.getParameter("lheWeightPrecision")), maxPdfWeights_(params.getParameter("maxPdfWeights")), + keepAllPSWeights_(params.getParameter("keepAllPSWeights")), debug_(params.getUntrackedParameter("debug", false)), debugRun_(debug_.load()), - hasIssuedWarning_(false) { + hasIssuedWarning_(false), + psWeightWarning_(false) { produces(); produces("genModel"); + produces("LHEScale"); + produces("LHEPdf"); + produces("LHEReweighting"); + produces("LHENamed"); produces("PS"); produces(); if (namedWeightIDs_.size() != namedWeightLabels_.size()) { @@ -247,22 +291,26 @@ class GenWeightsTableProducer : public edm::global::EDProducerget(); + Counter* counter = streamCache(id)->countermap.get(); // generator information (always available) - auto const& genInfo = iEvent.get(genTag_); + edm::Handle genInfo; + iEvent.getByToken(genTag_, genInfo); + double weight = genInfo->weight(); // table for gen info, always available auto out = std::make_unique(1, "genWeight", true); out->setDoc("generator weight"); - out->addColumnValue("", genInfo.weight(), "generator weight", nanoaod::FlatTable::FloatColumn); + out->addColumnValue("", weight, "generator weight"); iEvent.put(std::move(out)); - std::string model_label = streamCache(id)->getLabel(); + std::string model_label = streamCache(id)->countermap.getLabel(); auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); iEvent.put(std::move(outM), "genModel"); + bool getLHEweightsFromGenInfo = !model_label.empty(); // tables for LHE weights, may not be filled + std::unique_ptr lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab; std::unique_ptr genPSTab; edm::Handle lheInfo; @@ -272,43 +320,74 @@ class GenWeightsTableProducer : public edm::global::EDProducerweightChoice); if (lheInfo.isValid()) { + if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true)) + edm::LogWarning("LHETablesProducer") + << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n"; // get the dynamic choice of weights - const DynamicWeightChoice& weightChoice = *runCache(iEvent.getRun().index()); + const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index()); // go fill tables - fillLHEWeightTables(counter, weightChoice, genInfo.weight(), *lheInfo, genInfo, genPSTab); + fillLHEWeightTables(counter, + weightChoice, + genWeightChoice, + weight, + *lheInfo, + *genInfo, + lheScaleTab, + lhePdfTab, + lheRwgtTab, + lheNamedTab, + genPSTab); + } else if (getLHEweightsFromGenInfo) { + fillLHEPdfWeightTablesFromGenInfo( + counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab); + lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); + //lheNamedTab.reset(new nanoaod::FlatTable(1, "LHENamedWeights", true)); + //genPSTab.reset(new nanoaod::FlatTable(1, "PSWeight", true)); } else { // Still try to add the PS weights - fillOnlyPSWeightTable(counter, genInfo.weight(), genInfo, genPSTab); + fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab); // make dummy values + lheScaleTab = std::make_unique(1, "LHEScaleWeights", true); + lhePdfTab = std::make_unique(1, "LHEPdfWeights", true); + lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); + lheNamedTab = std::make_unique(1, "LHENamedWeights", true); if (!hasIssuedWarning_.exchange(true)) { edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n"; } } + iEvent.put(std::move(lheScaleTab), "LHEScale"); + iEvent.put(std::move(lhePdfTab), "LHEPdf"); + iEvent.put(std::move(lheRwgtTab), "LHEReweighting"); + iEvent.put(std::move(lheNamedTab), "LHENamed"); iEvent.put(std::move(genPSTab), "PS"); } - void fillLHEWeightTables(Counter& counter, - const DynamicWeightChoice& weightChoice, + void fillLHEWeightTables(Counter* counter, + const DynamicWeightChoice* weightChoice, + const DynamicWeightChoiceGenInfo* genWeightChoice, double genWeight, const LHEEventProduct& lheProd, const GenEventInfoProduct& genProd, + std::unique_ptr& outScale, + std::unique_ptr& outPdf, + std::unique_ptr& outRwgt, + std::unique_ptr& outNamed, std::unique_ptr& outPS) const { - // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) - bool lheDebug = debug_.exchange(false); + bool lheDebug = debug_.exchange( + false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) - const std::vector& scaleWeightIDs = weightChoice.scaleWeightIDs; - const std::vector& pdfWeightIDs = weightChoice.pdfWeightIDs; - const std::vector& rwgtWeightIDs = weightChoice.rwgtIDs; + const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; + const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; + const std::vector& rwgtWeightIDs = weightChoice->rwgtIDs; double w0 = lheProd.originalXWGTUP(); - std::vector wScale(scaleWeightIDs.size(), 1); - std::vector wPDF(pdfWeightIDs.size(), 1); - std::vector wRwgt(rwgtWeightIDs.size(), 1); - std::vector wNamed(namedWeightIDs_.size(), 1); - + std::vector wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1), + wNamed(namedWeightIDs_.size(), 1); for (auto& weight : lheProd.weights()) { if (lheDebug) printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str()); @@ -330,57 +409,143 @@ class GenWeightsTableProducer : public edm::global::EDProducer wPS(vectorSize, 1); - if (vectorSize > 1) { - for (unsigned int i = 6; i < 10; i++) { - wPS[i - 6] = (genProd.weights()[i]) / w0; - } + std::vector wPS; + std::string psWeightDocStr; + setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); + + outPS = std::make_unique(wPS.size(), "PSWeight", false); + outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); + + outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); + outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); + + outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); + outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); + + outRwgt = std::make_unique(wRwgt.size(), "LHEReweightingWeight", false); + outRwgt->addColumn("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_); + + outNamed = std::make_unique(1, "LHEWeight", true); + outNamed->addColumnValue("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file"); + for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { + outNamed->addColumnValue(namedWeightLabels_[i], + wNamed[i], + "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal", + lheWeightPrecision_); + } + + counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS); + } + + void fillLHEPdfWeightTablesFromGenInfo(Counter* counter, + const DynamicWeightChoiceGenInfo* weightChoice, + double genWeight, + const GenEventInfoProduct& genProd, + std::unique_ptr& outScale, + std::unique_ptr& outPdf, + std::unique_ptr& outNamed, + std::unique_ptr& outPS) const { + const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; + const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; + + auto weights = genProd.weights(); + double w0 = (weights.size() > 1) ? weights.at(1) : 1.; + double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.; + + std::vector wScale, wPDF, wPS; + for (auto id : scaleWeightIDs) + wScale.push_back(weights.at(id) / w0); + for (auto id : pdfWeightIDs) { + wPDF.push_back(weights.at(id) / w0); } + + std::string psWeightsDocStr; + setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr); + + outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); + outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); + + outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); + outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); + outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", - wPS, - vectorSize > 1 ? "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 " - "FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2 " - : "dummy PS weight (1.0) ", - nanoaod::FlatTable::FloatColumn, - lheWeightPrecision_); - - counter.incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS); + outPS->addColumn("", wPS, psWeightsDocStr, lheWeightPrecision_); + + outNamed = std::make_unique(1, "LHEWeight", true); + outNamed->addColumnValue("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file"); + /*for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { + outNamed->addColumnValue(namedWeightLabels_[i], wNamed[i], "LHE weight for id "+namedWeightIDs_[i]+", relative to nominal", lheWeightPrecision_); + }*/ + + counter->incLHE(genWeight, wScale, wPDF, std::vector(), std::vector(), wPS); } - void fillOnlyPSWeightTable(Counter& counter, + void fillOnlyPSWeightTable(Counter* counter, + const DynamicWeightChoiceGenInfo* genWeightChoice, double genWeight, const GenEventInfoProduct& genProd, std::unique_ptr& outPS) const { - int vectorSize = (genProd.weights().size() == 14 || genProd.weights().size() == 46) ? 4 : 1; + std::vector wPS; + std::string psWeightDocStr; + setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); + outPS = std::make_unique(wPS.size(), "PSWeight", false); + outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); + + counter->incGenOnly(genWeight); + counter->incPSOnly(genWeight, wPS); + } - std::vector wPS(vectorSize, 1); - if (vectorSize > 1) { - for (unsigned int i = 6; i < 10; i++) { - wPS[i - 6] = (genProd.weights()[i]) / genWeight; + void setPSWeightInfo(const std::vector& genWeights, + const DynamicWeightChoiceGenInfo* genWeightChoice, + std::vector& wPS, + std::string& psWeightDocStr) const { + wPS.clear(); + // isRegularPSSet = keeping all weights and the weights are a usual size, ie + // all weights are PS weights (don't use header incase missing names) + bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46); + if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) { + psWeightDocStr = genWeightChoice->psWeightsDoc; + double psNom = genWeights.at(genWeightChoice->psBaselineID); + for (auto wgtidx : genWeightChoice->psWeightIDs) { + wPS.push_back(genWeights.at(wgtidx) / psNom); } - } + } else { + int vectorSize = + keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1); - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", - wPS, - vectorSize > 1 ? "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 " - "FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2 " - : "dummy PS weight (1.0) ", - nanoaod::FlatTable::FloatColumn, - lheWeightPrecision_); - - counter.incGenOnly(genWeight); - counter.incPSOnly(genWeight, wPS); + if (vectorSize > 1) { + double nominal = genWeights.at(1); // Called 'Baseline' in GenLumiInfoHeader + if (keepAllPSWeights_) { + for (int i = 0; i < vectorSize; i++) { + wPS.push_back(genWeights.at(i + 2) / nominal); + } + psWeightDocStr = "All PS weights (w_var / w_nominal)"; + } else { + if (!psWeightWarning_.exchange(true)) + edm::LogWarning("LHETablesProducer") + << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n" + << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt " + "order )"; + for (std::size_t i = 6; i < 10; i++) { + wPS.push_back(genWeights.at(i) / nominal); + } + psWeightDocStr = + "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" + "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; + } + } else { + wPS.push_back(1.0); + psWeightDocStr = "dummy PS weight (1.0) "; + } + } } // create an empty counter std::shared_ptr globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override { edm::Handle lheInfo; - // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) - bool lheDebug = debugRun_.exchange(false); + bool lheDebug = debugRun_.exchange( + false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) auto weightChoice = std::make_shared(); // getByToken throws since we're not in the endRun (see https://github.com/cms-sw/cmssw/pull/18499) @@ -588,6 +753,26 @@ class GenWeightsTableProducer : public edm::global::EDProducer>> Looks like an EW parameter weight" << std::endl; + for (++iLine; iLine < nLines; ++iLine) { + if (lheDebug) + std::cout << " " << lines[iLine]; + if (std::regex_search(lines[iLine], groups, rwgt)) { + std::string rwgtID = groups.str(1); + if (lheDebug) + std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl; + if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) { + // we're only interested in the beggining of the block + lheReweighingIDs.emplace_back(rwgtID); + } + } else if (std::regex_search(lines[iLine], endweightgroup)) { + if (lheDebug) + std::cout << ">>> Looks like the end of a weight group" << std::endl; + } + } } else { for (++iLine; iLine < nLines; ++iLine) { if (lheDebug) @@ -717,7 +902,9 @@ class GenWeightsTableProducer : public edm::global::EDProducer beginStream(edm::StreamID) const override { return std::make_unique(); } + std::unique_ptr beginStream(edm::StreamID) const override { + return std::make_unique(); + } // inizialize to zero at begin run void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override { streamCache(id)->clear(); @@ -725,13 +912,128 @@ class GenWeightsTableProducer : public edm::global::EDProducercountermap); edm::Handle genLumiInfoHead; lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); if (!genLumiInfoHead.isValid()) edm::LogWarning("LHETablesProducer") << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; - counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); + + std::string label; + if (genLumiInfoHead.isValid()) { + label = genLumiInfoHead->configDescription(); + boost::replace_all(label, "-", "_"); + boost::replace_all(label, "/", "_"); + } + counterMap->setLabel(label); + + if (genLumiInfoHead.isValid()) { + auto weightChoice = &(streamCache(id)->weightChoice); + + std::vector scaleVariationIDs; + std::vector pdfSetWeightIDs; + weightChoice->psWeightIDs.clear(); + + std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)"); + std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)"); + std::regex mainPSw("sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)"); + std::smatch groups; + auto weightNames = genLumiInfoHead->weightNames(); + std::unordered_map knownPDFSetsFromGenInfo_; + unsigned int weightIter = 0; + for (const auto& line : weightNames) { + if (std::regex_search(line, groups, scalew)) { // scale variation + auto id = groups.str(1); + auto group = groups.str(2); + auto mur = groups.str(3); + auto muf = groups.str(4); + if (group.find("Central scale variation") != std::string::npos) + scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); + } else if (std::regex_search(line, groups, pdfw)) { // PDF variation + auto id = groups.str(1); + auto group = groups.str(2); + auto memberid = groups.str(3); + auto pdfset = groups.str(4); + if (group.find(pdfset) != std::string::npos) { + if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) { + knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str()); + pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str())); + } else + pdfSetWeightIDs.back().add(id, std::atoi(id.c_str())); + } + } else if (line == "Baseline") { + weightChoice->psBaselineID = weightIter; + } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) { + weightChoice->matchPS_alt = line.find("sr:") != std::string::npos; // (f/i)sr: for new weights + if (keepAllPSWeights_) { + weightChoice->psWeightIDs.push_back(weightIter); // PS variations + } else if (std::regex_search(line, groups, mainPSw)) { + if (weightChoice->psWeightIDs.size() == 0) + weightChoice->psWeightIDs = std::vector(4, -1); + int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0; + psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2; + weightChoice->psWeightIDs[psIdx] = weightIter; + } + } + weightIter++; + } + if (keepAllPSWeights_) { + weightChoice->psWeightsDoc = "All PS weights (w_var / w_nominal)"; + } else if (weightChoice->psWeightIDs.size() == 4) { + weightChoice->psWeightsDoc = + "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" + "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; + for (int i = 0; i < 4; i++) { + if (static_cast(weightChoice->psWeightIDs[i]) == -1) + weightChoice->setMissingWeight(i); + } + } else { + weightChoice->psWeightsDoc = "dummy PS weight (1.0) "; + } + + weightChoice->scaleWeightIDs.clear(); + weightChoice->pdfWeightIDs.clear(); + + std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end()); + std::stringstream scaleDoc; + scaleDoc << "LHE scale variation weights (w_var / w_nominal); "; + for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) { + const auto& sw = scaleVariationIDs[isw]; + if (isw) + scaleDoc << "; "; + scaleDoc << "[" << isw << "] is " << sw.label; + weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str())); + } + if (!scaleVariationIDs.empty()) + weightChoice->scaleWeightsDoc = scaleDoc.str(); + std::stringstream pdfDoc; + pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA names "; + bool found = false; + for (const auto& pw : pdfSetWeightIDs) { + if (pw.wids.size() == 1) + continue; // only consider error sets + for (const auto& wantedpdf : lhaNameToID_) { + auto pdfname = wantedpdf.first; + if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end()) + continue; + uint32_t lhaid = knownPDFSetsFromGenInfo_.at(pdfname); + if (pw.lhaIDs.first != lhaid) + continue; + pdfDoc << pdfname; + for (const auto& x : pw.wids) + weightChoice->pdfWeightIDs.push_back(std::atoi(x.c_str())); + if (maxPdfWeights_ < pw.wids.size()) { + weightChoice->pdfWeightIDs.resize(maxPdfWeights_); // drop some replicas + pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas"; + } + weightChoice->pdfWeightsDoc = pdfDoc.str(); + found = true; + break; + } + if (found) + break; + } + } } // create an empty counter std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { @@ -742,7 +1044,7 @@ class GenWeightsTableProducer : public edm::global::EDProducermerge(*streamCache(id)); + runCounterMap->merge(streamCache(id)->countermap); } // nothing to do per se void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} @@ -750,41 +1052,46 @@ class GenWeightsTableProducer : public edm::global::EDProducer(); - for (auto x : runCounterMap->countermap) { - auto& runCounter = x.second; - std::string label = std::string("_") + x.first; + for (const auto& x : runCounterMap->countermap) { + auto runCounter = &(x.second); + std::string label = (!x.first.empty()) ? (std::string("_") + x.first) : ""; std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; - out->addInt("genEventCount" + label, "event count" + doclabel, runCounter.num_); - out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter.sumw_); - out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); + out->addInt("genEventCount" + label, "event count" + doclabel, runCounter->num); + out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter->sumw); + out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter->sumw2); - double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; - auto sumScales = runCounter.sumScale_; + double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1; + auto sumScales = runCounter->sumScale; for (auto& val : sumScales) val *= norm; - out->addVFloat("LHEScaleSumw" + label, - "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel, - sumScales); - auto sumPDFs = runCounter.sumPDF_; + out->addVFloatWithNorm("LHEScaleSumw" + label, + "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel, + sumScales, + runCounter->sumw); + auto sumPDFs = runCounter->sumPDF; for (auto& val : sumPDFs) val *= norm; - out->addVFloat( - "LHEPdfSumw" + label, "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel, sumPDFs); - if (!runCounter.sumRwgt_.empty()) { - auto sumRwgts = runCounter.sumRwgt_; + out->addVFloatWithNorm("LHEPdfSumw" + label, + "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel, + sumPDFs, + runCounter->sumw); + if (!runCounter->sumRwgt.empty()) { + auto sumRwgts = runCounter->sumRwgt; for (auto& val : sumRwgts) val *= norm; - out->addVFloat("LHEReweightingSumw" + label, - "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel, - sumRwgts); + out->addVFloatWithNorm("LHEReweightingSumw" + label, + "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel, + sumRwgts, + runCounter->sumw); } - if (!runCounter.sumNamed_.empty()) { // it could be empty if there's no LHE info in the sample + if (!runCounter->sumNamed.empty()) { // it could be empty if there's no LHE info in the sample for (unsigned int i = 0, n = namedWeightLabels_.size(); i < n; ++i) { - out->addFloat( + out->addFloatWithNorm( "LHESumw_" + namedWeightLabels_[i] + label, "Sum of genEventWeight * LHEWeight_" + namedWeightLabels_[i] + ", divided by genEventSumw" + doclabel, - runCounter.sumNamed_[i] * norm); + runCounter->sumNamed[i] * norm, + runCounter->sumw); } } } @@ -813,6 +1120,7 @@ class GenWeightsTableProducer : public edm::global::EDProducersetComment("output names for the namedWeightIDs (in the same order)"); desc.add("lheWeightPrecision")->setComment("Number of bits in the mantissa for LHE weights"); desc.add("maxPdfWeights")->setComment("Maximum number of PDF weights to save (to crop NN replicas)"); + desc.add("keepAllPSWeights")->setComment("Store all PS weights found"); desc.addOptionalUntracked("debug")->setComment("dump out all LHE information for one event"); descriptions.add("genWeightsTable", desc); } @@ -830,8 +1138,9 @@ class GenWeightsTableProducer : public edm::global::EDProducer namedWeightLabels_; int lheWeightPrecision_; unsigned int maxPdfWeights_; + bool keepAllPSWeights_; - mutable std::atomic debug_, debugRun_, hasIssuedWarning_; + mutable std::atomic debug_, debugRun_, hasIssuedWarning_, psWeightWarning_; }; #include "FWCore/Framework/interface/MakerMacros.h" diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index 561a8dc805ddb..9c64d5ce849e2 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -6,7 +6,7 @@ #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" namespace gen { - enum class PSVarType { muR, cNS, con, def, red}; + enum class PSVarType { muR, cNS, con, def, red, alphaS}; enum class PSSplittingType { combined, g2gg, x2xg, g2qq }; class PartonShowerWeightGroupInfo : public WeightGroupInfo { diff --git a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc index 46bd94298a06c..f2ebb9c1150c8 100644 --- a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc @@ -2,16 +2,73 @@ namespace gen { void PartonShowerWeightGroupInfo::copy(const PartonShowerWeightGroupInfo& other) { WeightGroupInfo::copy(other); } + void PartonShowerWeightGroupInfo::copy(const PartonShowerWeightGroupInfo& other) { + WeightGroupInfo::copy(other); + nameIsPythiaSyntax_ = other.nameIsPythiaSyntax_; + } PartonShowerWeightGroupInfo* PartonShowerWeightGroupInfo::clone() const { return new PartonShowerWeightGroupInfo(*this); } - void PartonShowerWeightGroupInfo::updateWeight(int globalIndex, std::string id, std::string subName, bool isUp) { - size_t localIndex = weightMetaInfoByGlobalIndex(id, globalIndex).localIndex; - if (weightNameToUpDown.find(subName) == weightNameToUpDown.end()) { - weightNames.push_back(subName); - weightNameToUpDown[subName] = std::pair(); + int PartonShowerWeightGroupInfo::variationIndex(bool isISR, bool isUp, PSVarType variationType) const { + return variationIndex(isISR, isUp, variationType, PSSplittingType::combined); + } + + int PartonShowerWeightGroupInfo::variationIndex(bool isISR, + bool isUp, + PSVarType variationType, + PSSplittingType splittingType) const { + std::string label = isISR ? "isr" : "fsr"; + + if ((variationType == PSVarType::con || variationType == PSVarType::def || variationType == PSVarType::red) && + splittingType != PSSplittingType::combined) + throw std::invalid_argument("VariationType must be muR or CNS if subprocess is specified"); + + std::string variation; + switch (variationType) { + case PSVarType::con: + variation = !nameIsPythiaSyntax_ ? "Con" : (isUp ? "murfac=4.0" : "murfac=0.25"); + break; + case PSVarType::def: + variation = !nameIsPythiaSyntax_ ? "Def" : (isUp ? "murfac=2.0" : "murfac=0.5"); + break; + case PSVarType::red: + variation = !nameIsPythiaSyntax_ ? "Red" : (isUp ? "murfac=1.414" : "murfac=0.707"); + case PSVarType::muR: + variation = !nameIsPythiaSyntax_ ? "muR" : (isUp ? "murfac=2.0" : "murfac=0.5"); + break; + case PSVarType::cNS: + variation = !nameIsPythiaSyntax_ ? "cNS" : (isUp ? "cns=2.0" : "murfac=-2.0"); + break; + case PSVarType::alphaS: + variation = (isUp ? "alpsfact=2.0" : "alpsfact=0.5"); + return weightIndexFromLabel(variation); + } + + std::string splitting; + switch (splittingType) { + case PSSplittingType::g2gg: + splitting = !nameIsPythiaSyntax_ ? "G2GG" : "g2gg"; + break; + case PSSplittingType::g2qq: + splitting = !nameIsPythiaSyntax_ ? "G2QQ" : "g2qq"; + break; + case PSSplittingType::x2xg: + splitting = !nameIsPythiaSyntax_ ? "X2XG" : "x2xg"; + break; + default: + break; + } + + if (nameIsPythiaSyntax_) { + std::string app = splittingType != PSSplittingType::combined ? splitting + ":" + variation : variation; + label += ":" + app; + } else { + if (splittingType != PSSplittingType::combined) { + label += variation + "_" + splitting + "_" + variation + (isUp ? "_up" : "_dn"); + } else + label += variation + (isUp ? "Hi" : "Lo"); } if (isUp) weightNameToUpDown[subName].first = localIndex; @@ -19,4 +76,7 @@ namespace gen { weightNameToUpDown[subName].second = localIndex; } + return weightIndexFromLabel(label); + } + } // namespace gen From 09380ddfbca15ccba1e97712e40429ef9b5eb9a7 Mon Sep 17 00:00:00 2001 From: Suvankar Roy Chowdhury Date: Tue, 3 Nov 2020 10:41:47 +0100 Subject: [PATCH 06/16] adding altset index table --- .../plugins/LHEWeightsTableProducer.cc | 187 +++++++++--------- 1 file changed, 96 insertions(+), 91 deletions(-) diff --git a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc index c8f0aa06684ff..45dfd0df6b147 100644 --- a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc @@ -40,12 +40,13 @@ public edm::global::EDProducer, void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; //func changed//sroychow - void addWeightGroupToTable(std::unique_ptr>& lheWeightTables, + void addWeightGroupToTable(std::map>& lheWeightTables, + std::map>& weightVecsizes, + std::map& weightlabels, const char* typeName, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights, Counter& counter, double genWeight) const; - WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, gen::WeightType weightType, int& maxStore) const; @@ -106,11 +107,7 @@ public edm::global::EDProducer, edm::LogWarning("LHETablesProducer") << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); - //std::cout << "StreamBeginLuminosityBlock:" << id.value() << "\nPrinting counter map keys" << std::endl; - //for(auto& cm : counterMap->countermap) - // std::cout << cm.first << std::endl; std::string label = genLumiInfoHead.isValid() ? counterMap->getLabel() : "NULL"; - //std::cout << "StreamBeginLuminosityBlock:" << id.value() << "\nCounterMapLabel:" << label << std::endl; } // create an empty counter @@ -130,7 +127,6 @@ public edm::global::EDProducer, static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); protected: - //const std::vector> lheTokens_; const std::vector> lheWeightTokens_; const std::vector> lheWeightInfoTokens_; const edm::EDGetTokenT genWeightToken_; @@ -141,10 +137,10 @@ public edm::global::EDProducer, const std::vector maxGroupsPerType_; const std::vector pdfIds_; const std::unordered_map weightTypeNames_ = { - {gen::WeightType::kScaleWeights, "Scale"}, - {gen::WeightType::kPdfWeights, "Pdf"}, + {gen::WeightType::kScaleWeights, "LHEScale"}, + {gen::WeightType::kPdfWeights, "LHEPdf"}, {gen::WeightType::kMEParamWeights, "MEParam"}, - {gen::WeightType::kPartonShowerWeights, "PartonShower"}, + {gen::WeightType::kPartonShowerWeights, "GENPartonShower"}, {gen::WeightType::kUnknownWeights, "Unknown"}, }; //std::unordered_map weightGroupIndices_; @@ -174,16 +170,18 @@ LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params { if (weightgroups_.size() != maxGroupsPerType_.size()) throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); - produces>(); - produces(); + for(auto& wg : weightTypeNames_) { + produces(wg.second); + produces(wg.second + "sizes"); + } + produces("GENWeight"); produces(); - produces(); + produces("genModel"); } void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { //access counter for weight sums Counter& counter = *streamCache(id)->get(); - edm::Handle lheWeightHandle; bool foundLheWeights = false; for (auto& token : lheWeightTokens_) { @@ -201,10 +199,14 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons auto outGeninfo = std::make_unique(1, "genWeightNEW", true); outGeninfo->setDoc("generator weight"); outGeninfo->addColumnValue("", genInfo.weight(), "generator weight", nanoaod::FlatTable::FloatColumn); - iEvent.put(std::move(outGeninfo)); + iEvent.put(std::move(outGeninfo), "GENWeight"); //this will take care of sum of genWeights counter.incGenOnly(genWeight); + std::string& model_label = streamCache(id)->getLabel(); + auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); + iEvent.put(std::move(outM), "genModel"); + WeightsContainer lheWeights; if (foundLheWeights) { const GenWeightProduct* lheWeightProduct = lheWeightHandle.product(); @@ -218,28 +220,45 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); - auto lheWeightTables = std::make_unique>(); + //create a container with dummy weight vector + std::map> lheWeightTables; + std::map> weightVecsizes; + std::map weightlabels; + for(auto& wg : weightTypeNames_) { + lheWeightTables.insert(std::make_pair(wg.first, std::vector())); + weightVecsizes.insert(std::make_pair(wg.first, std::vector())); + weightlabels.insert(std::make_pair(wg.first, "")); + } if (foundLheWeights) { - addWeightGroupToTable(lheWeightTables, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + addWeightGroupToTable(lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); } - addWeightGroupToTable(lheWeightTables, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); + addWeightGroupToTable(lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); - iEvent.put(std::move(lheWeightTables)); - /* - std::string& model_label = streamCache(id)->getLabel(); - auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); - iEvent.put(std::move(outM), "genModel"); - */ - //std::cout << "From Event:\n"; - //for(auto& cm : counter.weightSumMap_) - // std::cout << "WeightName:" << cm.first - // << "\t size:" << cm.second.size() - // << "\t First value:" << cm.second.at(0) - // << std::endl; + for(auto& wg : weightTypeNames_) { + std::string wname = wg.second; + auto& weightVec = lheWeightTables[wg.first]; + counter.incLHE(genWeight, weightVec, wname); + //std::cout << "Writing out weight of type:" << wname << std::endl; + auto outTable = std::make_unique(weightVec.size(), wname + "Weight", false); + outTable->addColumn("", weightVec, weightlabels[wg.first], + nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + + //now add the vector containing the sizes of alt sets + auto outTableSizes = std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); + outTableSizes->addColumn("", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, + nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + iEvent.put(std::move(outTable), wname); + iEvent.put(std::move(outTableSizes), wname + "sizes"); + } } -void LHEWeightsTableProducer::addWeightGroupToTable(std::unique_ptr>& lheWeightTables, +/* + +*/ +void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, + std::map>& weightVecsizes, + std::map& weightlabels, const char* typeName, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights, Counter& counter, @@ -249,53 +268,40 @@ void LHEWeightsTableProducer::addWeightGroupToTable(std::unique_ptrweightType(); std::string name = weightTypeNames_.at(weightType); - std::string label = groupInfo.group->name(); + std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->name(); auto& weights = allWeights.at(groupInfo.index); - label.append("; "); - if (false && weightType == gen::WeightType::kScaleWeights && groupInfo.group->isWellFormed() && - groupInfo.group->nIdsContained() < 10) { - weights = orderedScaleWeights(weights, dynamic_cast(groupInfo.group)); - label.append( - "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" - " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" - " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); + //std::cout << "Name:" << name + // << "\tWsize=" << weights.size() + // << "\tPrevious size=" << lheWeightTables[weightType].size() + // << std::endl; + label.append("["); + label.append(std::to_string(lheWeightTables[weightType].size()));//to append the start index of this set + label.append("]; "); + lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); + weightVecsizes[weightType].emplace_back(weights.size()); + if (weightType == gen::WeightType::kScaleWeights && groupInfo.group->isWellFormed()) { + if(groupInfo.group->nIdsContained() == 9) { + weights = orderedScaleWeights(weights, dynamic_cast(groupInfo.group)); + label.append( + "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" + " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" + " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); + } else { + label.append( "Scale weight size is "); + label.append( std::to_string(groupInfo.group->nIdsContained())); + //label.append( ". Very fishy!!!"); + } } else if (!storeAllPSweights_ && weightType == gen::WeightType::kPartonShowerWeights && groupInfo.group->isWellFormed()) { - const gen::PartonShowerWeightGroupInfo* psgInfo = dynamic_cast(groupInfo.group); - //std::cout << "PSWeights size :" << weights.size() - // << "\tWtnames size:" << psgInfo->getWeightNames().size() - // << std::endl; - //std::cout << "WeightMetaInfo size:" << psgInfo->idsContained().size() << std::endl; - //for(unsigned int i = 0 ; i < psgInfo->idsContained().size(); i++) - // std::cout << "Index :" << i << "\t" << psgInfo->idsContained().at(i).label << std::endl; - std::cout << "PS weights \n Index: 1\t" << psgInfo->idsContained().at(0).label - << "\t value:" << weights.at(0) << std::endl; - std::cout << "PS weights \n Index: 1\t" << psgInfo->idsContained().at(1).label - << "\t value:" << weights.at(1) << std::endl; - for (unsigned int i = 6; i < 10; i++) - std::cout << "Index :" << i - << "\t weight name:" << psgInfo->idsContained().at(i).label - << "\t value:" << weights.at(i) - << std::endl; - weights = getPreferredPSweights(weights, dynamic_cast(groupInfo.group)); + weights = getPreferredPSweights(weights, dynamic_cast(groupInfo.group)); label.append("PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2"); - } else - label.append(groupInfo.group->description()); - - entryName.append(name); - entryName.append("Weight"); - if (typeCount[weightType] > 0) { - entryName.append("AltSet"); - entryName.append(std::to_string(typeCount[weightType])); } - counter.incLHE(genWeight, weights, entryName); - lheWeightTables->emplace_back(weights.size(), entryName, false); - lheWeightTables->back().addColumn("", weights, label, nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + if(weightlabels[weightType] == "") + weightlabels[weightType].append("[idx in AltSetSizes array] Name [start idx in weight array];\n"); + weightlabels[weightType].append(label); typeCount[weightType]++; - - //std::cout << "Weight type read: " << name << std::endl; } } @@ -337,10 +343,23 @@ std::vector LHEWeightsTableProducer::getPreferredPSweights(const std::ve std::vector psTosave; double baseline = psWeights.at(pswV->weightIndexFromLabel("Baseline"));//at 1 - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefHi"))/baseline ); // at 6 - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefHi"))/baseline ); // at 7 - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefLo"))/baseline ); // at 8 - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefLo"))/baseline ); // at 9 + + if(psWeights.at(pswV->weightIndexFromLabel("isrDefHi")) >= 0) + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefHi"))/baseline ); // at 6 + else psTosave.emplace_back(1.); + + if(psWeights.at(pswV->weightIndexFromLabel("isrDefLo")) >= 0) + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefLo"))/baseline ); // at 6 + else psTosave.emplace_back(1.); + + if(psWeights.at(pswV->weightIndexFromLabel("fsrDefHi")) >= 0) + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefHi"))/baseline ); // at 6 + else psTosave.emplace_back(1.); + + if(psWeights.at(pswV->weightIndexFromLabel("fsrDefLo")) >= 0) + psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefLo"))/baseline ); // at 6 + else psTosave.emplace_back(1.); + return psTosave; } @@ -348,15 +367,7 @@ void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const { - std::cout << "<<<<>>>>>\n"; - std::cout << "Map label:" << (*streamCache(id)).active_label << std::endl; - Counter& counter = *streamCache(id)->get(); - for(auto& cm : counter.weightSumMap_) - std::cout << "WeightName:" << cm.first - << "\t size:" << cm.second.size() - << "\t First value:" << cm.second.at(0) - << std::endl; - std::cout << "<<<<>>>>>\n"; + //Counter& counter = *streamCache(id)->get(); //this takes care for mergeing all the weight sums runCounterMap->mergeSumMap(*streamCache(id)); } @@ -375,13 +386,7 @@ void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, edm::EventSetu double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; //Sum from map - std::cout << "SUM map size:" << runCounter.weightSumMap_.size() << std::endl; for(auto& sumw : runCounter.weightSumMap_) { - std::cout << "Adding wsum for:" - << sumw.first << "\t Size:" - << sumw.second.size() - << "\t First value:" << sumw.second.at(0) - << std::endl; //Normalize with genEventSumw for(auto& val : sumw.second) val *= norm; @@ -405,7 +410,7 @@ void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d desc.add>("maxGroupsPerType"); desc.addOptionalUntracked>("pdfIds"); desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); - desc.add("storeAllPSweights", -1)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); + desc.add("storeAllPSweights", 0)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); descriptions.addDefault(desc); } From 14b1034580343c2567bd7db13233cd266eb3cd06 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 01:43:33 +0100 Subject: [PATCH 07/16] Use cms::Exception, configure debugging, code formatting Further cleanup, nano improvements change way PS weights handled Allow for finding missing weights Fix error with gap fixing code Change around logic to have bool to decide if use guess for PS Amend wellformed logic for scaleweight Cleanup code Nano back to GenWeightsTableProducer file --- .../Core/interface/LHEWeightHelper.h | 1 + .../Core/interface/WeightHelper.h | 9 +- .../Core/plugins/GenWeightProductProducer.cc | 12 +- .../Core/plugins/LHEWeightProductProducer.cc | 43 +- .../Core/src/GenWeightHelper.cc | 2 +- .../Core/src/LHEWeightHelper.cc | 23 +- GeneratorInterface/Core/src/WeightHelper.cc | 47 +- .../LHEInterface/plugins/BuildFile.xml | 6 +- .../NanoAOD/interface/GenWeightCounters.h | 59 +- .../plugins/GenWeightsTableProducer.cc | 1453 +++++------------ .../plugins/LHEWeightsTableProducer.cc | 371 +++-- .../NanoAOD/plugins/NanoAODOutputModule.cc | 285 ++-- .../NanoAOD/plugins/TableOutputBranches.cc | 10 +- PhysicsTools/NanoAOD/python/nano_cff.py | 178 +- PhysicsTools/NanoAOD/python/nanogen_cff.py | 201 +-- PhysicsTools/NanoAOD/test/testNanoWeights.py | 15 +- .../GeneratorProducts/BuildFile.xml | 2 +- .../interface/GenWeightInfoProduct.h | 10 +- .../interface/GenWeightProduct.h | 4 +- .../interface/MEParamWeightGroupInfo.h | 4 +- .../interface/PartonShowerWeightGroupInfo.h | 46 +- .../interface/PdfWeightGroupInfo.h | 4 +- .../interface/ScaleWeightGroupInfo.h | 12 +- .../interface/UnknownWeightGroupInfo.h | 4 +- .../interface/WeightGroupInfo.h | 2 +- .../src/GenWeightInfoProduct.cc | 39 +- .../src/PartonShowerWeightGroupInfo.cc | 137 +- .../src/ScaleWeightGroupInfo.cc | 11 +- .../GeneratorProducts/src/WeightGroupInfo.cc | 46 +- 29 files changed, 1256 insertions(+), 1780 deletions(-) diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index b2f636250f230..80bd3cf14af19 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -25,6 +25,7 @@ namespace gen { bool isConsistent(); void swapHeaders(); void setFailIfInvalidXML(bool value) { failIfInvalidXML_ = value; } + private: std::vector headerLines_; bool failIfInvalidXML_ = false; diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index e8955e541a957..ed857f07bd8dc 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -35,18 +35,22 @@ namespace gen { std::unique_ptr weightProduct(std::vector weights, float w0); void setModel(std::string model) { model_ = model; } + void setGuessPSWeightIdx(bool guessPSWeightIdx) { + PartonShowerWeightGroupInfo::setGuessPSWeightIdx(guessPSWeightIdx); + } void addUnassociatedGroup() { weightGroups_.push_back(std::make_unique("unassociated")); - weightGroups_.back().setDescription("Weights missing or with invalid header meta data"); + weightGroups_.back().setDescription("Weights with missing or invalid header meta data"); } int addWeightToProduct( std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex); int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); + void setDebug(bool value) { debug_ = value; } protected: // TODO: Make this only print from one thread a la // https://github.com/kdlong/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 - bool debug_ = true; //true; + bool debug_ = false; const unsigned int FIRST_PSWEIGHT_ENTRY = 2; const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; std::string model_; @@ -62,6 +66,7 @@ namespace gen { void updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight); void updateMEParamInfo(const ParsedWeight& weight, int index); void updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight); + void updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight); void cleanupOrphanCentralWeight(); bool splitPdfWeight(ParsedWeight& weight); diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index f066ef0492c83..198917def4506 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -49,8 +49,10 @@ GenWeightProductProducer::GenWeightProductProducer(const edm::ParameterSet& iCon genEventToken_(consumes(iConfig.getParameter("genInfo"))), genLumiInfoHeadTag_( mayConsume(iConfig.getParameter("genLumiInfoHeader"))) { + weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); produces(); produces(); + weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); } GenWeightProductProducer::~GenWeightProductProducer() {} @@ -60,7 +62,7 @@ void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup edm::Handle genEventInfo; iEvent.getByToken(genEventToken_, genEventInfo); - float centralWeight = genEventInfo->weights().size() > 0 ? genEventInfo->weights().at(0) : 1.; + float centralWeight = !genEventInfo->weights().empty() ? genEventInfo->weights().at(0) : 1.; auto weightProduct = weightHelper_.weightProduct(genEventInfo->weights(), centralWeight); iEvent.put(std::move(weightProduct)); } @@ -81,11 +83,11 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& weightHelper_.parseWeightGroupsFromNames(weightNames_); auto weightInfoProduct = std::make_unique(); - if (weightHelper_.weightGroups().size() == 0) - weightHelper_.addUnassociatedGroup(); - + if (weightHelper_.weightGroups().empty()) + weightHelper_.addUnassociatedGroup(); + for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::make_unique(*weightGroup.clone())); + weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup.clone())); } iLumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index 5937693c518b8..daa7b26bb874d 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -49,15 +49,17 @@ class LHEWeightProductProducer : public edm::one::EDProducer>("lheSourceLabels")), - lheEventTokens_(edm::vector_transform(lheLabels_, - [this](const std::string& tag) { return mayConsume(tag); })), - lheRunInfoTokens_(edm::vector_transform(lheLabels_, - [this](const std::string& tag) { return mayConsume(tag); })), - lheWeightInfoTokens_(edm::vector_transform(lheLabels_, - [this](const std::string& tag) { return mayConsume(tag); })) { + lheEventTokens_(edm::vector_transform( + lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), + lheRunInfoTokens_(edm::vector_transform( + lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), + lheWeightInfoTokens_(edm::vector_transform( + lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })) { produces(); produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); + weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); + weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); } LHEWeightProductProducer::~LHEWeightProductProducer() {} @@ -71,7 +73,7 @@ void LHEWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup for (auto& token : lheEventTokens_) { iEvent.getByToken(token, lheEventInfo); if (lheEventInfo.isValid()) { - break; + break; } } @@ -84,13 +86,12 @@ void LHEWeightProductProducer::beginRun(edm::Run const& run, edm::EventSetup con for (auto& label : lheLabels_) { run.getByLabel(label, lheRunInfoHandle); if (lheRunInfoHandle.isValid()) { - hasLhe_ = true; - break; + hasLhe_ = true; + break; } } if (!hasLhe_) - return; - + return; typedef std::vector::const_iterator header_cit; LHERunInfoProduct::Header headerWeightInfo; @@ -118,15 +119,25 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& } if (!hasLhe_) - return; + return; + + try { + weightHelper_.parseWeights(); + } catch (cms::Exception& e) { + std::string error = e.what(); + error += + "\n NOTE: if you want to attempt to process this sample anyway, set failIfInvalidXML = False " + "in the configuration file\n. If you set this flag and the error persists, the issue " + " is fatal and must be solved at the LHE/gridpack level."; + throw cms::Exception("LHEWeightProductProducer") << error; + } - weightHelper_.parseWeights(); - if (weightHelper_.weightGroups().size() == 0) - weightHelper_.addUnassociatedGroup(); + if (weightHelper_.weightGroups().empty()) + weightHelper_.addUnassociatedGroup(); auto weightInfoProduct = std::make_unique(); for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::make_unique(*weightGroup.clone())); + weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup.clone())); } lumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index 1fc086f688e56..b06475941efd6 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -43,7 +43,7 @@ namespace gen { {"", index, weightName, weightName, std::unordered_map(), groupIndex}); if (isPartonShowerWeightGroup(parsedWeights_.back())) { if (showerGroupIndex < 0) { - showerGroupIndex = ++groupIndex; + showerGroupIndex = ++groupIndex; } parsedWeights_.back().wgtGroup_idx = showerGroupIndex; // all parton showers are grouped together } diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 5403b3bfd4c60..4be51105c9cec 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -13,10 +13,8 @@ namespace gen { parsedWeights_.clear(); if (!isConsistent() && failIfInvalidXML_) { - throw std::runtime_error( - "XML in LHE is not consistent: Most likely, tags were swapped.\n" - "To turn on fault fixing, use 'setFailIfInvalidXML(false)'\n" - "WARNING: the tag swapping may lead to weights associated with the incorrect group"); + throw cms::Exception("LHEWeightHelper") + << "XML in LHE is not consistent: Most likely, XML tags are out of order."; } else if (!isConsistent()) { swapHeaders(); } @@ -29,7 +27,8 @@ namespace gen { // in case of > instead of < if (xmlError != 0 && failIfInvalidXML_) { xmlDoc.PrintError(); - throw std::runtime_error("XML is unreadable because of above error."); + throw cms::Exception("LHEWeightHelper") + << "The LHE header is not valid XML! Weight information was not properly parsed."; } else if (xmlError != 0 && !failIfInvalidXML_) { boost::replace_all(fullHeader, "<", "<"); boost::replace_all(fullHeader, ">", ">"); @@ -38,9 +37,9 @@ namespace gen { // error persists (how to handle error?) if (xmlError != 0) { - std::cerr << "WARNING: Error in parsing XML of LHE weight header!" << std::endl; - xmlDoc.PrintError(); - return false; + std::string error = "Fatal error when parsing the LHE header. The header is not valid XML! Parsing error was "; + error += xmlDoc.ErrorStr(); + throw cms::Exception("LHEWeightHelper") << error; } return true; @@ -94,11 +93,11 @@ namespace gen { std::string LHEWeightHelper::parseGroupName(tinyxml2::XMLElement* el) { std::vector nameAlts_ = {"name", "type"}; - for (auto nameAtt : nameAlts_) { + for (const auto& nameAtt : nameAlts_) { if (el->Attribute(nameAtt.c_str())) { std::string groupName = el->Attribute(nameAtt.c_str()); - if (groupName.find(".") != std::string::npos) - groupName.erase(groupName.find("."), groupName.size()); + if (groupName.find('.') != std::string::npos) + groupName.erase(groupName.find('.'), groupName.size()); return groupName; } } @@ -112,7 +111,7 @@ namespace gen { bool LHEWeightHelper::isConsistent() { int curLevel = 0; - for (auto line : headerLines_) { + for (const auto& line : headerLines_) { if (line.find(" namespace gen { @@ -19,7 +20,7 @@ namespace gen { bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) { const std::string& groupname = boost::to_lower_copy(weight.groupname); std::vector psNames = {"isr", "fsr", "nominal", "baseline", "emission"}; - for (auto name : psNames) { + for (const auto& name : psNames) { if (groupname.find(name) != std::string::npos) return true; } @@ -86,10 +87,10 @@ namespace gen { try { muR = std::stof(muRText); muF = std::stof(muFText); - } catch (...) { + } catch (std::invalid_argument& e) { if (debug_) std::cout << "Tried to convert (" << muR << ", " << muF << ") to a int" << std::endl; - scaleGroup.setIsWellFormed(false); + scaleGroup.setWeightIsCorrupt(); return; /// do something } @@ -101,9 +102,9 @@ namespace gen { try { int dynNum = std::stoi(dynNumText); scaleGroup.setDyn(weight.index, weight.id, muR, muF, dynNum, dynType); - } catch (...) { + } catch (std::invalid_argument& e) { std::cout << "Tried to convert (" << dynNumText << ") a int" << std::endl; - scaleGroup.setIsWellFormed(false); + scaleGroup.setWeightIsCorrupt(); /// do something here } } @@ -112,8 +113,8 @@ namespace gen { std::string lhaidText = searchAttributes("pdf", weight); try { scaleGroup.setLhaid(std::stoi(lhaidText)); - } catch (...) { - scaleGroup.setLhaid(-2); + } catch (std::invalid_argument& e) { + scaleGroup.setLhaid(-1); // do something here } } @@ -127,7 +128,7 @@ namespace gen { } catch (std::invalid_argument& e) { pdfGroup.setIsWellFormed(false); } - } else if (pdfGroup.lhaIds().size() > 0) { + } else if (!pdfGroup.lhaIds().empty()) { return pdfGroup.lhaIds().back() + 1; } else { return LHAPDF::lookupLHAPDFID(weight.groupname); @@ -157,6 +158,13 @@ namespace gen { pdfGroup.addLhaid(lhaid); } + void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) { + if (psGroup.containedIds().size() == DEFAULT_PSWEIGHT_LENGTH) + psGroup.setIsWellFormed(true); + if (weight.content.find(':') != std::string::npos && weight.content.find('=') != std::string::npos) + psGroup.setNameIsPythiaSyntax(true); + } + bool WeightHelper::splitPdfWeight(ParsedWeight& weight) { if (weightGroups_[weight.wgtGroup_idx].weightType() == gen::WeightType::kPdfWeights) { auto& pdfGroup = dynamic_cast(weightGroups_[weight.wgtGroup_idx]); @@ -222,7 +230,7 @@ namespace gen { } int entry = !isUnassociated ? group.weightVectorEntry(name, weightNum) : group.nIdsContained(); if (debug_) - std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; + std::cout << "Adding weight " << entry << " to group " << groupIndex; product->addWeight(weight, groupIndex, entry); return groupIndex; } @@ -239,7 +247,7 @@ namespace gen { // Fall back to unordered search int counter = 0; - for (auto weightGroup : weightGroups_) { + for (const auto& weightGroup : weightGroups_) { if (weightGroup.containsWeight(wgtId, weightIndex)) return counter; counter++; @@ -252,8 +260,6 @@ namespace gen { void WeightHelper::printWeights() { // checks for (auto& wgt : weightGroups_) { - if (!wgt.isWellFormed()) - std::cout << "\033[1;31m"; std::cout << std::boolalpha << wgt.name() << " (" << wgt.firstId() << "-" << wgt.lastId() << "): " << wgt.isWellFormed() << std::endl; if (wgt.weightType() == gen::WeightType::kScaleWeights) { @@ -284,18 +290,10 @@ namespace gen { std::cout << wgt.description() << "\n"; } else if (wgt.weightType() == gen::WeightType::kPartonShowerWeights) { auto& wgtPS = dynamic_cast(wgt); - if (wgtPS.containedIds().size() == DEFAULT_PSWEIGHT_LENGTH) - wgtPS.setIsWellFormed(true); - - wgtPS.cacheWeightIndicesByLabel(); std::vector labels = wgtPS.weightLabels(); - if (labels.size() > FIRST_PSWEIGHT_ENTRY && labels.at(FIRST_PSWEIGHT_ENTRY).find(":") != std::string::npos && - labels.at(FIRST_PSWEIGHT_ENTRY).find("=") != std::string::npos) { - wgtPS.setNameIsPythiaSyntax(true); - } + wgtPS.cacheWeightIndicesByLabel(); + wgtPS.printVariables(); } - if (!wgt.isWellFormed()) - std::cout << "\033[0m"; } } @@ -341,9 +339,10 @@ namespace gen { group.addContainedId(weight.index, weight.id, weight.content); if (group.weightType() == gen::WeightType::kScaleWeights) updateScaleInfo(dynamic_cast(group), weight); - else if (group.weightType() == gen::WeightType::kPdfWeights) { + else if (group.weightType() == gen::WeightType::kPdfWeights) updatePdfInfo(dynamic_cast(group), weight); - } + else if (group.weightType() == gen::WeightType::kPartonShowerWeights) + updatePartonShowerInfo(dynamic_cast(group), weight); } cleanupOrphanCentralWeight(); } diff --git a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml index c758089b243a9..f43689ef148df 100644 --- a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml +++ b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml @@ -6,7 +6,9 @@ + + @@ -14,9 +16,7 @@ - -<<<<<<< HEAD @@ -24,5 +24,3 @@ -======= ->>>>>>> bad6d6546e0... New WeightGroups, improved parsing with helper class diff --git a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h index 15ac334b2e863..1e815e2d5f414 100644 --- a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h +++ b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h @@ -1,8 +1,8 @@ #ifndef GENWEIGHTSCOUNTERS_h #define GENWEIGHTSCOUNTERS_h -#include -#include -#include +#include +#include +#include namespace genCounter { void mergeSumVectors(std::vector& v1, std::vector const& v2) { @@ -32,12 +32,12 @@ namespace genCounter { void incLHE(double w0, const std::vector& weightV, const std::string& wName) { //if new type of weight, create a map element - if(weightSumMap_.find(wName) == weightSumMap_.end()) { - std::vector temp; - weightSumMap_.insert({wName, temp}); + if (weightSumMap_.find(wName) == weightSumMap_.end()) { + std::vector temp; + weightSumMap_.insert({wName, temp}); } if (!weightV.empty()) { - if (weightSumMap_[wName].empty()) + if (weightSumMap_[wName].empty()) weightSumMap_[wName].resize(weightV.size(), 0); for (unsigned int i = 0, n = weightV.size(); i < n; ++i) weightSumMap_[wName][i] += (w0 * weightV[i]); @@ -46,32 +46,24 @@ namespace genCounter { //incPSOnly(w0, wPS); } - void mergeSumMap(const Counter& other) { - num_ += other.num_; - sumw_ += other.sumw_; - sumw2_ += other.sumw2_; - //if weightMap_ for "this" is empty, create map elements with empty - //vectors before merging - if(weightSumMap_.empty() && !other.weightSumMap_.empty()) { - for(auto& wmap : other.weightSumMap_) { - std::vector temp; - weightSumMap_.insert({wmap.first, temp}); + void mergeSumMap(const Counter& other) { + num_ += other.num_; + sumw_ += other.sumw_; + sumw2_ += other.sumw2_; + //if weightMap_ for "this" is empty, create map elements with empty + //vectors before merging + if(weightSumMap_.empty() && !other.weightSumMap_.empty()) { + for(auto& wmap : other.weightSumMap_) { + std::vector temp; + weightSumMap_.insert({wmap.first, temp}); + } + } + + for(auto& wmap : weightSumMap_) { + if (other.weightSumMap_.find(wmap.first) != other.weightSumMap_.end()) + mergeSumVectors(wmap.second, other.weightSumMap_.at(wmap.first)); } } - for(auto& wmap : weightSumMap_) { - mergeSumVectors(wmap.second, other.weightSumMap_.at(wmap.first)); - } - /* - std::cout << "From merge function\n"; - for(auto& wmap : weightSumMap_) { - std::cout << "Wname:" << wmap.first - << "\t WVec Size:" << wmap.second.size() - << "\t First entry:" << wmap.second.at(0) - << std::endl;; - } - std::cout << "End : From merge function\n"; - */ - } //private: // the counters @@ -87,8 +79,9 @@ namespace genCounter { std::string active_label = ""; void mergeSumMap(const CounterMap& other) { - for (const auto& y : other.countermap) + for (const auto& y : other.countermap) { countermap[y.first].mergeSumMap(y.second); + } active_el = nullptr; } @@ -115,5 +108,5 @@ namespace genCounter { } }; -} +} // namespace genCounter #endif diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 5cc5569643bdd..e069c4fb12c6b 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -6,1034 +6,112 @@ #include "DataFormats/NanoAOD/interface/MergeableCounterTable.h" #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" -#include "FWCore/Utilities/interface/transform.h" -#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" -#include "boost/algorithm/string.hpp" - -#include - -#include -#include +#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include "FWCore/Utilities/interface/transform.h" +#include "PhysicsTools/NanoAOD/interface/GenWeightCounters.h" +#include #include -#include +#include namespace { - /// ---- Cache object for running sums of weights ---- - struct Counter { - Counter() : num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {} - - // the counters - long long num; - long double sumw; - long double sumw2; - std::vector sumPDF, sumScale, sumRwgt, sumNamed, sumPS; - - void clear() { - num = 0; - sumw = 0; - sumw2 = 0; - sumPDF.clear(); - sumScale.clear(); - sumRwgt.clear(); - sumNamed.clear(), sumPS.clear(); - } - - // inc the counters - void incGenOnly(double w) { - num++; - sumw += w; - sumw2 += (w * w); - } - - void incPSOnly(double w0, const std::vector& wPS) { - if (!wPS.empty()) { - if (sumPS.empty()) - sumPS.resize(wPS.size(), 0); - for (unsigned int i = 0, n = wPS.size(); i < n; ++i) - sumPS[i] += (w0 * wPS[i]); - } - } - - void incLHE(double w0, - const std::vector& wScale, - const std::vector& wPDF, - const std::vector& wRwgt, - const std::vector& wNamed, - const std::vector& wPS) { - // add up weights - incGenOnly(w0); - // then add up variations - if (!wScale.empty()) { - if (sumScale.empty()) - sumScale.resize(wScale.size(), 0); - for (unsigned int i = 0, n = wScale.size(); i < n; ++i) - sumScale[i] += (w0 * wScale[i]); - } - if (!wPDF.empty()) { - if (sumPDF.empty()) - sumPDF.resize(wPDF.size(), 0); - for (unsigned int i = 0, n = wPDF.size(); i < n; ++i) - sumPDF[i] += (w0 * wPDF[i]); - } - if (!wRwgt.empty()) { - if (sumRwgt.empty()) - sumRwgt.resize(wRwgt.size(), 0); - for (unsigned int i = 0, n = wRwgt.size(); i < n; ++i) - sumRwgt[i] += (w0 * wRwgt[i]); - } - if (!wNamed.empty()) { - if (sumNamed.empty()) - sumNamed.resize(wNamed.size(), 0); - for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) - sumNamed[i] += (w0 * wNamed[i]); - } - incPSOnly(w0, wPS); - } - - void merge(const Counter& other) { - num += other.num; - sumw += other.sumw; - sumw2 += other.sumw2; - if (sumScale.empty() && !other.sumScale.empty()) - sumScale.resize(other.sumScale.size(), 0); - if (sumPDF.empty() && !other.sumPDF.empty()) - sumPDF.resize(other.sumPDF.size(), 0); - if (sumRwgt.empty() && !other.sumRwgt.empty()) - sumRwgt.resize(other.sumRwgt.size(), 0); - if (sumNamed.empty() && !other.sumNamed.empty()) - sumNamed.resize(other.sumNamed.size(), 0); - if (sumPS.empty() && !other.sumPS.empty()) - sumPS.resize(other.sumPS.size(), 0); - if (!other.sumScale.empty()) - for (unsigned int i = 0, n = sumScale.size(); i < n; ++i) - sumScale[i] += other.sumScale[i]; - if (!other.sumPDF.empty()) - for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i) - sumPDF[i] += other.sumPDF[i]; - if (!other.sumRwgt.empty()) - for (unsigned int i = 0, n = sumRwgt.size(); i < n; ++i) - sumRwgt[i] += other.sumRwgt[i]; - if (!other.sumNamed.empty()) - for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i) - sumNamed[i] += other.sumNamed[i]; - if (!other.sumPS.empty()) - for (unsigned int i = 0, n = sumPS.size(); i < n; ++i) - sumPS[i] += other.sumPS[i]; - } - }; - - struct CounterMap { - std::map countermap; - Counter* active_el = nullptr; - std::string active_label = ""; - void merge(const CounterMap& other) { - for (const auto& y : other.countermap) - countermap[y.first].merge(y.second); - active_el = nullptr; - } - void clear() { - for (auto x : countermap) - x.second.clear(); - active_el = nullptr; - active_label = ""; - } - void setLabel(std::string label) { - active_el = &(countermap[label]); - active_label = label; - } - void checkLabelSet() { - if (!active_el) - throw cms::Exception("LogicError", "Called CounterMap::get() before setting the active label\n"); - } - Counter* get() { - checkLabelSet(); - return active_el; - } - std::string& getLabel() { - checkLabelSet(); - return active_label; - } - }; - - /// ---- RunCache object for dynamic choice of LHE IDs ---- - struct DynamicWeightChoice { - // choice of LHE weights - // ---- scale ---- - std::vector scaleWeightIDs; - std::string scaleWeightsDoc; - // ---- pdf ---- - std::vector pdfWeightIDs; - std::string pdfWeightsDoc; - // ---- rwgt ---- - std::vector rwgtIDs; - std::string rwgtWeightDoc; - }; - - struct DynamicWeightChoiceGenInfo { - // choice of LHE weights - // ---- scale ---- - std::vector scaleWeightIDs; - std::string scaleWeightsDoc; - // ---- pdf ---- - std::vector pdfWeightIDs; - std::string pdfWeightsDoc; - // ---- ps ---- - std::vector defPSWeightIDs = {6, 7, 8, 9}; - std::vector defPSWeightIDs_alt = {27, 5, 26, 4}; - bool matchPS_alt = false; - std::vector psWeightIDs; - unsigned int psBaselineID = 1; - std::string psWeightsDoc; - - void setMissingWeight(int idx) { psWeightIDs[idx] = (matchPS_alt) ? defPSWeightIDs_alt[idx] : defPSWeightIDs[idx]; } - - bool empty() const { return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); } - }; - - struct LumiCacheInfoHolder { - CounterMap countermap; - DynamicWeightChoiceGenInfo weightChoice; - void clear() { - countermap.clear(); - weightChoice = DynamicWeightChoiceGenInfo(); - } - }; - - float stof_fortrancomp(const std::string& str) { - std::string::size_type match = str.find('d'); - if (match != std::string::npos) { - std::string pre = str.substr(0, match); - std::string post = str.substr(match + 1); - return std::stof(pre) * std::pow(10.0f, std::stof(post)); - } else { - return std::stof(str); - } - } - /// -------------- temporary objects -------------- - struct ScaleVarWeight { - std::string wid, label; - std::pair scales; - ScaleVarWeight(const std::string& id, const std::string& text, const std::string& muR, const std::string& muF) - : wid(id), label(text), scales(stof_fortrancomp(muR), stof_fortrancomp(muF)) {} - bool operator<(const ScaleVarWeight& other) { - return (scales == other.scales ? wid < other.wid : scales < other.scales); - } - }; - struct PDFSetWeights { - std::vector wids; - std::pair lhaIDs; - PDFSetWeights(const std::string& wid, unsigned int lhaID) : wids(1, wid), lhaIDs(lhaID, lhaID) {} - bool operator<(const PDFSetWeights& other) const { return lhaIDs < other.lhaIDs; } - void add(const std::string& wid, unsigned int lhaID) { - wids.push_back(wid); - lhaIDs.second = lhaID; - } - bool maybe_add(const std::string& wid, unsigned int lhaID) { - if (lhaID == lhaIDs.second + 1) { - lhaIDs.second++; - wids.push_back(wid); - return true; - } else { - return false; - } - } - }; + typedef std::vector WeightGroupDataContainer; + typedef std::array, 2> WeightGroupsToStore; } // namespace +using CounterMap = genCounter::CounterMap; +using Counter = genCounter::Counter; -class GenWeightsTableProducer : public edm::global::EDProducer, - edm::RunCache, +class LHEWeightsTableProducer : public edm::global::EDProducer, + edm::StreamCache, edm::RunSummaryCache, edm::EndRunProducer> { public: - GenWeightsTableProducer(edm::ParameterSet const& params) - : genTag_(consumes(params.getParameter("genEvent"))), - lheLabel_(params.getParameter>("lheInfo")), - lheTag_(edm::vector_transform(lheLabel_, - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - lheRunTag_(edm::vector_transform( - lheLabel_, [this](const edm::InputTag& tag) { return mayConsume(tag); })), - genLumiInfoHeadTag_( - mayConsume(params.getParameter("genLumiInfoHeader"))), - namedWeightIDs_(params.getParameter>("namedWeightIDs")), - namedWeightLabels_(params.getParameter>("namedWeightLabels")), - lheWeightPrecision_(params.getParameter("lheWeightPrecision")), - maxPdfWeights_(params.getParameter("maxPdfWeights")), - keepAllPSWeights_(params.getParameter("keepAllPSWeights")), - debug_(params.getUntrackedParameter("debug", false)), - debugRun_(debug_.load()), - hasIssuedWarning_(false), - psWeightWarning_(false) { - produces(); - produces("genModel"); - produces("LHEScale"); - produces("LHEPdf"); - produces("LHEReweighting"); - produces("LHENamed"); - produces("PS"); - produces(); - if (namedWeightIDs_.size() != namedWeightLabels_.size()) { - throw cms::Exception("Configuration", "Size mismatch between namedWeightIDs & namedWeightLabels"); - } - for (const edm::ParameterSet& pdfps : params.getParameter>("preferredPDFs")) { - const std::string& name = pdfps.getParameter("name"); - uint32_t lhaid = pdfps.getParameter("lhaid"); - preferredPDFLHAIDs_.push_back(lhaid); - lhaNameToID_[name] = lhaid; - lhaNameToID_[name + ".LHgrid"] = lhaid; - } - } - - ~GenWeightsTableProducer() override {} - - void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override { - // get my counter for weights - Counter* counter = streamCache(id)->countermap.get(); - - // generator information (always available) - edm::Handle genInfo; - iEvent.getByToken(genTag_, genInfo); - double weight = genInfo->weight(); - - // table for gen info, always available - auto out = std::make_unique(1, "genWeight", true); - out->setDoc("generator weight"); - out->addColumnValue("", weight, "generator weight"); - iEvent.put(std::move(out)); - - std::string model_label = streamCache(id)->countermap.getLabel(); - auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); - iEvent.put(std::move(outM), "genModel"); - bool getLHEweightsFromGenInfo = !model_label.empty(); - - // tables for LHE weights, may not be filled - std::unique_ptr lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab; - std::unique_ptr genPSTab; - - edm::Handle lheInfo; - for (const auto& lheTag : lheTag_) { - iEvent.getByToken(lheTag, lheInfo); - if (lheInfo.isValid()) { - break; - } - } - - const auto genWeightChoice = &(streamCache(id)->weightChoice); - if (lheInfo.isValid()) { - if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true)) - edm::LogWarning("LHETablesProducer") - << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n"; - // get the dynamic choice of weights - const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index()); - // go fill tables - fillLHEWeightTables(counter, - weightChoice, - genWeightChoice, - weight, - *lheInfo, - *genInfo, - lheScaleTab, - lhePdfTab, - lheRwgtTab, - lheNamedTab, - genPSTab); - } else if (getLHEweightsFromGenInfo) { - fillLHEPdfWeightTablesFromGenInfo( - counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab); - lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); - //lheNamedTab.reset(new nanoaod::FlatTable(1, "LHENamedWeights", true)); - //genPSTab.reset(new nanoaod::FlatTable(1, "PSWeight", true)); - } else { - // Still try to add the PS weights - fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab); - // make dummy values - lheScaleTab = std::make_unique(1, "LHEScaleWeights", true); - lhePdfTab = std::make_unique(1, "LHEPdfWeights", true); - lheRwgtTab = std::make_unique(1, "LHEReweightingWeights", true); - lheNamedTab = std::make_unique(1, "LHENamedWeights", true); - if (!hasIssuedWarning_.exchange(true)) { - edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n"; - } - } - - iEvent.put(std::move(lheScaleTab), "LHEScale"); - iEvent.put(std::move(lhePdfTab), "LHEPdf"); - iEvent.put(std::move(lheRwgtTab), "LHEReweighting"); - iEvent.put(std::move(lheNamedTab), "LHENamed"); - iEvent.put(std::move(genPSTab), "PS"); - } - - void fillLHEWeightTables(Counter* counter, - const DynamicWeightChoice* weightChoice, - const DynamicWeightChoiceGenInfo* genWeightChoice, - double genWeight, - const LHEEventProduct& lheProd, - const GenEventInfoProduct& genProd, - std::unique_ptr& outScale, - std::unique_ptr& outPdf, - std::unique_ptr& outRwgt, - std::unique_ptr& outNamed, - std::unique_ptr& outPS) const { - bool lheDebug = debug_.exchange( - false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) - - const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; - const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; - const std::vector& rwgtWeightIDs = weightChoice->rwgtIDs; - - double w0 = lheProd.originalXWGTUP(); - - std::vector wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1), - wNamed(namedWeightIDs_.size(), 1); - for (auto& weight : lheProd.weights()) { - if (lheDebug) - printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str()); - // now we do it slowly, can be optimized - auto mScale = std::find(scaleWeightIDs.begin(), scaleWeightIDs.end(), weight.id); - if (mScale != scaleWeightIDs.end()) - wScale[mScale - scaleWeightIDs.begin()] = weight.wgt / w0; - - auto mPDF = std::find(pdfWeightIDs.begin(), pdfWeightIDs.end(), weight.id); - if (mPDF != pdfWeightIDs.end()) - wPDF[mPDF - pdfWeightIDs.begin()] = weight.wgt / w0; - - auto mRwgt = std::find(rwgtWeightIDs.begin(), rwgtWeightIDs.end(), weight.id); - if (mRwgt != rwgtWeightIDs.end()) - wRwgt[mRwgt - rwgtWeightIDs.begin()] = weight.wgt / w0; - - auto mNamed = std::find(namedWeightIDs_.begin(), namedWeightIDs_.end(), weight.id); - if (mNamed != namedWeightIDs_.end()) - wNamed[mNamed - namedWeightIDs_.begin()] = weight.wgt / w0; - } - - std::vector wPS; - std::string psWeightDocStr; - setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); - - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); - - outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); - outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); - - outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); - outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); - - outRwgt = std::make_unique(wRwgt.size(), "LHEReweightingWeight", false); - outRwgt->addColumn("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_); - - outNamed = std::make_unique(1, "LHEWeight", true); - outNamed->addColumnValue("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file"); - for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { - outNamed->addColumnValue(namedWeightLabels_[i], - wNamed[i], - "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal", - lheWeightPrecision_); - } - - counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS); - } - - void fillLHEPdfWeightTablesFromGenInfo(Counter* counter, - const DynamicWeightChoiceGenInfo* weightChoice, - double genWeight, - const GenEventInfoProduct& genProd, - std::unique_ptr& outScale, - std::unique_ptr& outPdf, - std::unique_ptr& outNamed, - std::unique_ptr& outPS) const { - const std::vector& scaleWeightIDs = weightChoice->scaleWeightIDs; - const std::vector& pdfWeightIDs = weightChoice->pdfWeightIDs; - - auto weights = genProd.weights(); - double w0 = (weights.size() > 1) ? weights.at(1) : 1.; - double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.; - - std::vector wScale, wPDF, wPS; - for (auto id : scaleWeightIDs) - wScale.push_back(weights.at(id) / w0); - for (auto id : pdfWeightIDs) { - wPDF.push_back(weights.at(id) / w0); - } - - std::string psWeightsDocStr; - setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr); - - outScale = std::make_unique(wScale.size(), "LHEScaleWeight", false); - outScale->addColumn("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_); - - outPdf = std::make_unique(wPDF.size(), "LHEPdfWeight", false); - outPdf->addColumn("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_); - - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightsDocStr, lheWeightPrecision_); - - outNamed = std::make_unique(1, "LHEWeight", true); - outNamed->addColumnValue("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file"); - /*for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) { - outNamed->addColumnValue(namedWeightLabels_[i], wNamed[i], "LHE weight for id "+namedWeightIDs_[i]+", relative to nominal", lheWeightPrecision_); - }*/ - - counter->incLHE(genWeight, wScale, wPDF, std::vector(), std::vector(), wPS); - } - - void fillOnlyPSWeightTable(Counter* counter, - const DynamicWeightChoiceGenInfo* genWeightChoice, - double genWeight, - const GenEventInfoProduct& genProd, - std::unique_ptr& outPS) const { - std::vector wPS; - std::string psWeightDocStr; - setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr); - outPS = std::make_unique(wPS.size(), "PSWeight", false); - outPS->addColumn("", wPS, psWeightDocStr, lheWeightPrecision_); - - counter->incGenOnly(genWeight); - counter->incPSOnly(genWeight, wPS); - } - - void setPSWeightInfo(const std::vector& genWeights, - const DynamicWeightChoiceGenInfo* genWeightChoice, - std::vector& wPS, - std::string& psWeightDocStr) const { - wPS.clear(); - // isRegularPSSet = keeping all weights and the weights are a usual size, ie - // all weights are PS weights (don't use header incase missing names) - bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46); - if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) { - psWeightDocStr = genWeightChoice->psWeightsDoc; - double psNom = genWeights.at(genWeightChoice->psBaselineID); - for (auto wgtidx : genWeightChoice->psWeightIDs) { - wPS.push_back(genWeights.at(wgtidx) / psNom); - } - } else { - int vectorSize = - keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1); - - if (vectorSize > 1) { - double nominal = genWeights.at(1); // Called 'Baseline' in GenLumiInfoHeader - if (keepAllPSWeights_) { - for (int i = 0; i < vectorSize; i++) { - wPS.push_back(genWeights.at(i + 2) / nominal); - } - psWeightDocStr = "All PS weights (w_var / w_nominal)"; - } else { - if (!psWeightWarning_.exchange(true)) - edm::LogWarning("LHETablesProducer") - << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n" - << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt " - "order )"; - for (std::size_t i = 6; i < 10; i++) { - wPS.push_back(genWeights.at(i) / nominal); - } - psWeightDocStr = - "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" - "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; - } - } else { - wPS.push_back(1.0); - psWeightDocStr = "dummy PS weight (1.0) "; - } - } - } - - // create an empty counter - std::shared_ptr globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override { - edm::Handle lheInfo; - - bool lheDebug = debugRun_.exchange( - false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind) - auto weightChoice = std::make_shared(); - - // getByToken throws since we're not in the endRun (see https://github.com/cms-sw/cmssw/pull/18499) - //if (iRun.getByToken(lheRunTag_, lheInfo)) { - for (const auto& lheLabel : lheLabel_) { - iRun.getByLabel(lheLabel, lheInfo); - if (lheInfo.isValid()) { + LHEWeightsTableProducer(edm::ParameterSet const& params); + + void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; + //func changed//sroychow + void addWeightGroupToTable(std::map>& lheWeightTables, + std::map>& weightVecsizes, + std::map& weightlabels, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + Counter& counter, + double genWeight) const; + WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, + gen::WeightType weightType, + int& maxStore) const; + + std::vector orderedScaleWeights(const std::vector& scaleWeights, + const gen::ScaleWeightGroupInfo& scaleGroup) const; + + std::vector preferredPSweights(const std::vector& psWeights, + const gen::PartonShowerWeightGroupInfo& pswV) const; + + //Lumiblock + std::shared_ptr globalBeginLuminosityBlock(edm::LuminosityBlock const& iLumi, + edm::EventSetup const&) const override { + // Set equal to the max number of groups + // subtrack 1 for each weight group you find + bool foundLheWeights = false; + edm::Handle lheWeightInfoHandle; + for (auto& token : lheWeightInfoTokens_) { + iLumi.getByToken(token, lheWeightInfoHandle); + if (lheWeightInfoHandle.isValid()) { + foundLheWeights = true; break; } } - if (lheInfo.isValid()) { - std::vector scaleVariationIDs; - std::vector pdfSetWeightIDs; - std::vector lheReweighingIDs; - - std::regex weightgroupmg26x(""); - std::regex weightgroup(""); - std::regex weightgroupRwgt(""); - std::regex endweightgroup(""); - std::regex scalewmg26x( - ""); - std::regex scalew( - "\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)=(\\S+)\\s+(" - "?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)"); - std::regex pdfw( - "\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?"); - std::regex pdfwOld("\\s*Member \\s*(\\d+)\\s*(?:.*)"); - std::regex pdfwmg26x( - "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?"); - std::regex rwgt("(.+)?()?"); - std::smatch groups; - for (auto iter = lheInfo->headers_begin(), end = lheInfo->headers_end(); iter != end; ++iter) { - if (iter->tag() != "initrwgt") { - if (lheDebug) - std::cout << "Skipping LHE header with tag" << iter->tag() << std::endl; - continue; - } - if (lheDebug) - std::cout << "Found LHE header with tag" << iter->tag() << std::endl; - std::vector lines = iter->lines(); - bool missed_weightgroup = - false; //Needed because in some of the samples ( produced with MG26X ) a small part of the header info is ordered incorrectly - bool ismg26x = false; - for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; - ++iLine) { //First start looping through the lines to see which weightgroup pattern is matched - boost::replace_all(lines[iLine], "<", "<"); - boost::replace_all(lines[iLine], ">", ">"); - if (std::regex_search(lines[iLine], groups, weightgroupmg26x)) { - ismg26x = true; - } - } - for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << lines[iLine]; - if (std::regex_search(lines[iLine], groups, ismg26x ? weightgroupmg26x : weightgroup)) { - std::string groupname = groups.str(2); - if (ismg26x) - groupname = groups.str(1); - if (lheDebug) - std::cout << ">>> Looks like the beginning of a weight group for '" << groupname << "'" << std::endl; - if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation") { - if (lheDebug) - std::cout << ">>> Looks like scale variation for theory uncertainties" << std::endl; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, ismg26x ? scalewmg26x : scalew)) { - if (lheDebug) - std::cout << " >>> Scale weight " << groups[1].str() << " for " << groups[3].str() << " , " - << groups[4].str() << " , " << groups[5].str() << std::endl; - scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } else if (groupname == "PDF_variation" || groupname.find("PDF_variation ") == 0) { - if (lheDebug) - std::cout << ">>> Looks like a new-style block of PDF weights for one or more pdfs" << std::endl; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, pdfw)) { - unsigned int lhaID = std::stoi(groups.str(2)); - if (lheDebug) - std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID - << std::endl; - if (pdfSetWeightIDs.empty() || !pdfSetWeightIDs.back().maybe_add(groups.str(1), lhaID)) { - pdfSetWeightIDs.emplace_back(groups.str(1), lhaID); - } - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } else if (groupname == "PDF_variation1" || groupname == "PDF_variation2") { - if (lheDebug) - std::cout << ">>> Looks like a new-style block of PDF weights for multiple pdfs" << std::endl; - unsigned int lastid = 0; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, pdfw)) { - unsigned int id = std::stoi(groups.str(1)); - unsigned int lhaID = std::stoi(groups.str(2)); - if (lheDebug) - std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID - << std::endl; - if (id != (lastid + 1) || pdfSetWeightIDs.empty()) { - pdfSetWeightIDs.emplace_back(groups.str(1), lhaID); - } else { - pdfSetWeightIDs.back().add(groups.str(1), lhaID); - } - lastid = id; - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } else if (lhaNameToID_.find(groupname) != lhaNameToID_.end()) { - if (lheDebug) - std::cout << ">>> Looks like an old-style PDF weight for an individual pdf" << std::endl; - unsigned int firstLhaID = lhaNameToID_.find(groupname)->second; - bool first = true; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, ismg26x ? pdfwmg26x : pdfwOld)) { - unsigned int member = 0; - if (ismg26x == 0) { - member = std::stoi(groups.str(2)); - } else { - if (!groups.str(4).empty()) { - member = std::stoi(groups.str(4)); - } - } - unsigned int lhaID = member + firstLhaID; - if (lheDebug) - std::cout << " >>> PDF weight " << groups.str(1) << " for " << member << " = " << lhaID - << std::endl; - //if (member == 0) continue; // let's keep also the central value for now - if (first) { - pdfSetWeightIDs.emplace_back(groups.str(1), lhaID); - first = false; - } else { - pdfSetWeightIDs.back().add(groups.str(1), lhaID); - } - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } else if (groupname == "mass_variation" || groupname == "sthw2_variation" || - groupname == "width_variation") { - if (lheDebug) - std::cout << ">>> Looks like an EW parameter weight" << std::endl; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, rwgt)) { - std::string rwgtID = groups.str(1); - if (lheDebug) - std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl; - if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) { - // we're only interested in the beggining of the block - lheReweighingIDs.emplace_back(rwgtID); - } - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - } - } - } else { - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } - } else if (std::regex_search(lines[iLine], groups, weightgroupRwgt)) { - std::string groupname = groups.str(1); - if (groupname == "mg_reweighting") { - if (lheDebug) - std::cout << ">>> Looks like a LHE weights for reweighting" << std::endl; - for (++iLine; iLine < nLines; ++iLine) { - if (lheDebug) - std::cout << " " << lines[iLine]; - if (std::regex_search(lines[iLine], groups, rwgt)) { - std::string rwgtID = groups.str(1); - if (lheDebug) - std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl; - if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) { - // we're only interested in the beggining of the block - lheReweighingIDs.emplace_back(rwgtID); - } - } else if (std::regex_search(lines[iLine], endweightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the end of a weight group" << std::endl; - if (!missed_weightgroup) { - break; - } else - missed_weightgroup = false; - } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) { - if (lheDebug) - std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end " - "of the group." - << std::endl; - if (ismg26x) - missed_weightgroup = true; - --iLine; // rewind by one, and go back to the outer loop - break; - } - } - } - } - } - //std::cout << "============= END [ " << iter->tag() << " ] ============ \n\n" << std::endl; - - // ----- SCALE VARIATIONS ----- - std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end()); - if (lheDebug) - std::cout << "Found " << scaleVariationIDs.size() << " scale variations: " << std::endl; - std::stringstream scaleDoc; - scaleDoc << "LHE scale variation weights (w_var / w_nominal); "; - for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) { - const auto& sw = scaleVariationIDs[isw]; - if (isw) - scaleDoc << "; "; - scaleDoc << "[" << isw << "] is " << sw.label; - weightChoice->scaleWeightIDs.push_back(sw.wid); - if (lheDebug) - printf(" id %s: scales ren = % .2f fact = % .2f text = %s\n", - sw.wid.c_str(), - sw.scales.first, - sw.scales.second, - sw.label.c_str()); - } - if (!scaleVariationIDs.empty()) - weightChoice->scaleWeightsDoc = scaleDoc.str(); - - // ------ PDF VARIATIONS (take the preferred one) ----- - if (lheDebug) { - std::cout << "Found " << pdfSetWeightIDs.size() << " PDF set errors: " << std::endl; - for (const auto& pw : pdfSetWeightIDs) - printf("lhaIDs %6d - %6d (%3lu weights: %s, ... )\n", - pw.lhaIDs.first, - pw.lhaIDs.second, - pw.wids.size(), - pw.wids.front().c_str()); - } - - // ------ LHE REWEIGHTING ------- - if (lheDebug) { - std::cout << "Found " << lheReweighingIDs.size() << " reweighting weights" << std::endl; - } - std::copy(lheReweighingIDs.begin(), lheReweighingIDs.end(), std::back_inserter(weightChoice->rwgtIDs)); - - std::stringstream pdfDoc; - pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA IDs "; - bool found = false; - for (uint32_t lhaid : preferredPDFLHAIDs_) { - for (const auto& pw : pdfSetWeightIDs) { - if (pw.lhaIDs.first != lhaid && pw.lhaIDs.first != (lhaid + 1)) - continue; // sometimes the first weight is not saved if that PDF is the nominal one for the sample - if (pw.wids.size() == 1) - continue; // only consider error sets - pdfDoc << pw.lhaIDs.first << " - " << pw.lhaIDs.second; - weightChoice->pdfWeightIDs = pw.wids; - if (maxPdfWeights_ < pw.wids.size()) { - weightChoice->pdfWeightIDs.resize(maxPdfWeights_); // drop some replicas - pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas"; - } - weightChoice->pdfWeightsDoc = pdfDoc.str(); - found = true; - break; - } - if (found) - break; - } + edm::Handle genWeightInfoHandle; + iLumi.getByToken(genWeightInfoToken_, genWeightInfoHandle); + + std::unordered_map storePerType; + for (size_t i = 0; i < weightgroups_.size(); i++) + storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); + + WeightGroupsToStore weightsToStore; + for (auto weightType : gen::allWeightTypes) { + if (foundLheWeights) { + auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); + for (auto& w : lheWeights) + weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); } + auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); + for (auto& w : genWeights) + weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); } - return weightChoice; + return std::make_shared(weightsToStore); } + // nothing to do here + void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} // create an empty counter - std::unique_ptr beginStream(edm::StreamID) const override { - return std::make_unique(); - } + std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } // inizialize to zero at begin run void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override { streamCache(id)->clear(); } + void streamBeginLuminosityBlock(edm::StreamID id, edm::LuminosityBlock const& lumiBlock, edm::EventSetup const& eventSetup) const override { - auto counterMap = &(streamCache(id)->countermap); + auto counterMap = streamCache(id); edm::Handle genLumiInfoHead; lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); if (!genLumiInfoHead.isValid()) edm::LogWarning("LHETablesProducer") << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; - - std::string label; - if (genLumiInfoHead.isValid()) { - label = genLumiInfoHead->configDescription(); - boost::replace_all(label, "-", "_"); - boost::replace_all(label, "/", "_"); - } - counterMap->setLabel(label); - - if (genLumiInfoHead.isValid()) { - auto weightChoice = &(streamCache(id)->weightChoice); - - std::vector scaleVariationIDs; - std::vector pdfSetWeightIDs; - weightChoice->psWeightIDs.clear(); - - std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)"); - std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)"); - std::regex mainPSw("sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)"); - std::smatch groups; - auto weightNames = genLumiInfoHead->weightNames(); - std::unordered_map knownPDFSetsFromGenInfo_; - unsigned int weightIter = 0; - for (const auto& line : weightNames) { - if (std::regex_search(line, groups, scalew)) { // scale variation - auto id = groups.str(1); - auto group = groups.str(2); - auto mur = groups.str(3); - auto muf = groups.str(4); - if (group.find("Central scale variation") != std::string::npos) - scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4)); - } else if (std::regex_search(line, groups, pdfw)) { // PDF variation - auto id = groups.str(1); - auto group = groups.str(2); - auto memberid = groups.str(3); - auto pdfset = groups.str(4); - if (group.find(pdfset) != std::string::npos) { - if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) { - knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str()); - pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str())); - } else - pdfSetWeightIDs.back().add(id, std::atoi(id.c_str())); - } - } else if (line == "Baseline") { - weightChoice->psBaselineID = weightIter; - } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) { - weightChoice->matchPS_alt = line.find("sr:") != std::string::npos; // (f/i)sr: for new weights - if (keepAllPSWeights_) { - weightChoice->psWeightIDs.push_back(weightIter); // PS variations - } else if (std::regex_search(line, groups, mainPSw)) { - if (weightChoice->psWeightIDs.size() == 0) - weightChoice->psWeightIDs = std::vector(4, -1); - int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0; - psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2; - weightChoice->psWeightIDs[psIdx] = weightIter; - } - } - weightIter++; - } - if (keepAllPSWeights_) { - weightChoice->psWeightsDoc = "All PS weights (w_var / w_nominal)"; - } else if (weightChoice->psWeightIDs.size() == 4) { - weightChoice->psWeightsDoc = - "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2" - "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;"; - for (int i = 0; i < 4; i++) { - if (static_cast(weightChoice->psWeightIDs[i]) == -1) - weightChoice->setMissingWeight(i); - } - } else { - weightChoice->psWeightsDoc = "dummy PS weight (1.0) "; - } - - weightChoice->scaleWeightIDs.clear(); - weightChoice->pdfWeightIDs.clear(); - - std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end()); - std::stringstream scaleDoc; - scaleDoc << "LHE scale variation weights (w_var / w_nominal); "; - for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) { - const auto& sw = scaleVariationIDs[isw]; - if (isw) - scaleDoc << "; "; - scaleDoc << "[" << isw << "] is " << sw.label; - weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str())); - } - if (!scaleVariationIDs.empty()) - weightChoice->scaleWeightsDoc = scaleDoc.str(); - std::stringstream pdfDoc; - pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA names "; - bool found = false; - for (const auto& pw : pdfSetWeightIDs) { - if (pw.wids.size() == 1) - continue; // only consider error sets - for (const auto& wantedpdf : lhaNameToID_) { - auto pdfname = wantedpdf.first; - if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end()) - continue; - uint32_t lhaid = knownPDFSetsFromGenInfo_.at(pdfname); - if (pw.lhaIDs.first != lhaid) - continue; - pdfDoc << pdfname; - for (const auto& x : pw.wids) - weightChoice->pdfWeightIDs.push_back(std::atoi(x.c_str())); - if (maxPdfWeights_ < pw.wids.size()) { - weightChoice->pdfWeightIDs.resize(maxPdfWeights_); // drop some replicas - pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas"; - } - weightChoice->pdfWeightsDoc = pdfDoc.str(); - found = true; - break; - } - if (found) - break; - } - } + counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); + std::string label = genLumiInfoHead.isValid() ? counterMap->getLabel() : "NULL"; } // create an empty counter std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { @@ -1043,105 +121,314 @@ class GenWeightsTableProducer : public edm::global::EDProducermerge(streamCache(id)->countermap); - } + CounterMap* runCounterMap) const override; // nothing to do per se void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} // write the total to the run - void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const override { - auto out = std::make_unique(); + void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const& es, CounterMap const* runCounterMap) const override; + // nothing to do here + //void globalEndRun(edm::Run const& iRun, edm::EventSetup const& es, CounterMap* runCounterMap) const override {} - for (const auto& x : runCounterMap->countermap) { - auto runCounter = &(x.second); - std::string label = (!x.first.empty()) ? (std::string("_") + x.first) : ""; - std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); - out->addInt("genEventCount" + label, "event count" + doclabel, runCounter->num); - out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter->sumw); - out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter->sumw2); +protected: + const std::vector> lheWeightTokens_; + const std::vector> lheWeightInfoTokens_; + const edm::EDGetTokenT genWeightToken_; + const edm::EDGetTokenT genWeightInfoToken_; + const edm::EDGetTokenT genEventInfoToken_; + const edm::EDGetTokenT genLumiInfoHeadTag_; + const std::vector weightgroups_; + const std::vector maxGroupsPerType_; + const std::vector pdfIds_; + const std::unordered_map weightTypeNames_ = { + {gen::WeightType::kScaleWeights, "LHEScaleWeight"}, + {gen::WeightType::kPdfWeights, "LHEPdfWeight"}, + {gen::WeightType::kMEParamWeights, "MEParamWeight"}, + {gen::WeightType::kPartonShowerWeights, "PSWeight"}, + {gen::WeightType::kUnknownWeights, "UnknownWeight"}, + }; + //std::unordered_map weightGroupIndices_; + int lheWeightPrecision_; + bool keepAllPSWeights_; - double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1; - auto sumScales = runCounter->sumScale; - for (auto& val : sumScales) - val *= norm; - out->addVFloatWithNorm("LHEScaleSumw" + label, - "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel, - sumScales, - runCounter->sumw); - auto sumPDFs = runCounter->sumPDF; - for (auto& val : sumPDFs) - val *= norm; - out->addVFloatWithNorm("LHEPdfSumw" + label, - "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel, - sumPDFs, - runCounter->sumw); - if (!runCounter->sumRwgt.empty()) { - auto sumRwgts = runCounter->sumRwgt; - for (auto& val : sumRwgts) - val *= norm; - out->addVFloatWithNorm("LHEReweightingSumw" + label, - "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel, - sumRwgts, - runCounter->sumw); - } - if (!runCounter->sumNamed.empty()) { // it could be empty if there's no LHE info in the sample - for (unsigned int i = 0, n = namedWeightLabels_.size(); i < n; ++i) { - out->addFloatWithNorm( - "LHESumw_" + namedWeightLabels_[i] + label, - "Sum of genEventWeight * LHEWeight_" + namedWeightLabels_[i] + ", divided by genEventSumw" + doclabel, - runCounter->sumNamed[i] * norm, - runCounter->sumw); - } - } + enum { inLHE, inGen }; +}; +//put back if needed; till now not used +LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params) + : lheWeightTokens_( + edm::vector_transform(params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + lheWeightInfoTokens_(edm::vector_transform( + params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightToken_(consumes(params.getParameter("genWeights"))), + genWeightInfoToken_( + consumes(params.getParameter("genWeights"))), + genEventInfoToken_(consumes(params.getParameter("genEvent"))), + genLumiInfoHeadTag_( + mayConsume(params.getParameter("genLumiInfoHeader"))), + weightgroups_(edm::vector_transform(params.getParameter>("weightgroups"), + [](auto& c) { return gen::WeightType(c.at(0)); })), + maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), + pdfIds_(params.getUntrackedParameter>("pdfIds", {})), + lheWeightPrecision_(params.getParameter("lheWeightPrecision")), + keepAllPSWeights_(params.getParameter("keepAllPSWeights")) { + if (weightgroups_.size() != maxGroupsPerType_.size()) + throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); + for (auto& wg : weightTypeNames_) { + produces(wg.second); + produces(wg.second + "sizes"); + } + produces("GENWeight"); + produces(); + produces("genModel"); +} + +void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { + //access counter for weight sums + Counter& counter = *streamCache(id)->get(); + edm::Handle lheWeightHandle; + bool foundLheWeights = false; + for (auto& token : lheWeightTokens_) { + iEvent.getByToken(token, lheWeightHandle); + if (lheWeightHandle.isValid()) { + foundLheWeights = true; + break; } - iRun.put(std::move(out)); } - // nothing to do here - void globalEndRun(edm::Run const&, edm::EventSetup const&) const override {} + //Taken from genweight producer //Added sroychow + // generator information (always available) + auto const& genInfo = iEvent.get(genEventInfoToken_); + const double genWeight = genInfo.weight(); + // table for gen info, always available + auto outGeninfo = std::make_unique(1, "genWeight", true); + outGeninfo->setDoc("generator weight"); + outGeninfo->addColumnValue("", genInfo.weight(), "generator weight"); + iEvent.put(std::move(outGeninfo), "GENWeight"); + //this will take care of sum of genWeights + counter.incGenOnly(genWeight); + + std::string& model_label = streamCache(id)->getLabel(); + auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); + iEvent.put(std::move(outM), "genModel"); + + WeightsContainer lheWeights; + if (foundLheWeights) { + const GenWeightProduct* lheWeightProduct = lheWeightHandle.product(); + lheWeights = lheWeightProduct->weights(); + } - static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { - edm::ParameterSetDescription desc; - desc.add("genEvent", edm::InputTag("generator")) - ->setComment("tag for the GenEventInfoProduct, to get the main weight"); - desc.add("genLumiInfoHeader", edm::InputTag("generator")) - ->setComment("tag for the GenLumiInfoProduct, to get the model string"); - desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) - ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); + edm::Handle genWeightHandle; + iEvent.getByToken(genWeightToken_, genWeightHandle); + const GenWeightProduct* genWeightProduct = genWeightHandle.product(); + WeightsContainer genWeights = genWeightProduct->weights(); + + auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); + + //create a container with dummy weight vector + std::map> lheWeightTables; + std::map> weightVecsizes; + std::map weightlabels; + for (auto& wg : weightTypeNames_) { + lheWeightTables.insert(std::make_pair(wg.first, std::vector())); + weightVecsizes.insert(std::make_pair(wg.first, std::vector())); + weightlabels.insert(std::make_pair(wg.first, "")); + } + if (foundLheWeights) { + addWeightGroupToTable( + lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + } - edm::ParameterSetDescription prefpdf; - prefpdf.add("name"); - prefpdf.add("lhaid"); - desc.addVPSet("preferredPDFs", prefpdf, std::vector()) - ->setComment( - "LHA PDF Ids of the preferred PDF sets, in order of preference (the first matching one will be used)"); - desc.add>("namedWeightIDs")->setComment("set of LHA weight IDs for named LHE weights"); - desc.add>("namedWeightLabels") - ->setComment("output names for the namedWeightIDs (in the same order)"); - desc.add("lheWeightPrecision")->setComment("Number of bits in the mantissa for LHE weights"); - desc.add("maxPdfWeights")->setComment("Maximum number of PDF weights to save (to crop NN replicas)"); - desc.add("keepAllPSWeights")->setComment("Store all PS weights found"); - desc.addOptionalUntracked("debug")->setComment("dump out all LHE information for one event"); - descriptions.add("genWeightsTable", desc); + addWeightGroupToTable( + lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); + + for (auto& wg : weightTypeNames_) { + std::string wname = wg.second; + auto& weightVec = lheWeightTables[wg.first]; + counter.incLHE(genWeight, weightVec, wname); + auto outTable = std::make_unique(weightVec.size(), wname, false); + outTable->addColumn("", weightVec, weightlabels[wg.first], lheWeightPrecision_); + + //now add the vector containing the sizes of alt sets + auto outTableSizes = + std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); + outTableSizes->addColumn( + "", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, lheWeightPrecision_); + iEvent.put(std::move(outTable), wname); + iEvent.put(std::move(outTableSizes), wname + "sizes"); } +} + +/* + +*/ +void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, + std::map>& weightVecsizes, + std::map& weightlabels, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + Counter& counter, + double genWeight) const { + std::unordered_map typeCount = {}; + for (auto& type : gen::allWeightTypes) + typeCount[type] = 0; + + for (const auto& groupInfo : weightInfos) { + //std::string entryName = typeName; + gen::WeightType weightType = groupInfo.group->weightType(); + std::string name = weightTypeNames_.at(weightType); + std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->description(); + label.append("["); + label.append(std::to_string(lheWeightTables[weightType].size())); //to append the start index of this set + label.append("]; "); + auto& weights = allWeights.at(groupInfo.index); + //std::cout << "Group name is " << groupInfo.group->name() << " is it wellFormed? " << groupInfo.group->isWellFormed() << std::endl; + if (weightType == gen::WeightType::kScaleWeights) { + if (groupInfo.group->isWellFormed()) { + const auto scaleGroup = *static_cast(groupInfo.group.get()); + std::cout << "They're well formed, will be ordered as expected\n"; + weights = orderedScaleWeights(weights, scaleGroup); + label.append( + "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" + " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" + " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); + } else { + std::cout << "NOT WELL FORMED!\n"; + size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); + weights = std::vector(weights.begin(), weights.begin() + nstore); + label.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + + " elements of weights vector, unordered"); + } + // TODO: Handle storeAllWeights and !isWellFormed + } else if (!keepAllPSWeights_ && weightType == gen::WeightType::kPartonShowerWeights && + groupInfo.group->isWellFormed()) { + const auto psGroup = *static_cast(groupInfo.group.get()); + weights = preferredPSweights(weights, psGroup); + label.append( + "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is " + "ISR=1 FSR=2"); + } + //else + // label.append(groupInfo.group->description()); + lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); + weightVecsizes[weightType].emplace_back(weights.size()); -protected: - const edm::EDGetTokenT genTag_; - const std::vector lheLabel_; - const std::vector> lheTag_; - const std::vector> lheRunTag_; - const edm::EDGetTokenT genLumiInfoHeadTag_; + if (weightlabels[weightType].empty()) + weightlabels[weightType].append("[idx in AltSetSizes array] Name [start idx in weight array];\n"); - std::vector preferredPDFLHAIDs_; - std::unordered_map lhaNameToID_; - std::vector namedWeightIDs_; - std::vector namedWeightLabels_; - int lheWeightPrecision_; - unsigned int maxPdfWeights_; - bool keepAllPSWeights_; + weightlabels[weightType].append(label); + typeCount[weightType]++; + } +} + +WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, + gen::WeightType weightType, + int& maxStore) const { + std::vector allgroups; + if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { + allgroups = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + } else + allgroups = weightsHandle->weightGroupsAndIndicesByType(weightType); + + int toStore = maxStore; + if (maxStore < 0 || static_cast(allgroups.size()) <= maxStore) { + // Modify size in case one type of weight is present in multiple products + maxStore -= allgroups.size(); + toStore = allgroups.size(); + } - mutable std::atomic debug_, debugRun_, hasIssuedWarning_, psWeightWarning_; -}; + WeightGroupDataContainer out; + for (int i = 0; i < toStore; i++) { + auto& group = allgroups.at(i); + gen::SharedWeightGroupData temp = {group.index, std::move(group.group)}; + out.push_back(temp); + } + return out; +} + +std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, + const gen::ScaleWeightGroupInfo& scaleGroup) const { + std::vector weights; + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.centralIndex())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); + + return weights; +} + +std::vector LHEWeightsTableProducer::preferredPSweights(const std::vector& psWeights, + const gen::PartonShowerWeightGroupInfo& pswV) const { + std::vector psTosave; + + double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, true, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, true, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, false, gen::PSVarType::def)) / baseline); + return psTosave; +} + +void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, + edm::Run const&, + edm::EventSetup const&, + CounterMap* runCounterMap) const { + //this takes care for mergeing all the weight sums + runCounterMap->mergeSumMap(*streamCache(id)); +} + +void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, + edm::EventSetup const&, + CounterMap const* runCounterMap) const { + auto out = std::make_unique(); + + for (auto x : runCounterMap->countermap) { + auto& runCounter = x.second; + std::string label = std::string("_") + x.first; + std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; + + out->addInt("genEventCount" + label, "event count" + doclabel, runCounter.num_); + out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter.sumw_); + out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); + + double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; + //Sum from map + for (auto& sumw : runCounter.weightSumMap_) { + //Normalize with genEventSumw + for (auto& val : sumw.second) + val *= norm; + out->addVFloat(sumw.first + "Sumw" + label, + "Sum of genEventWeight *" + sumw.first + "[i]/genEventSumw" + doclabel, + sumw.second); + } + } + iRun.put(std::move(out)); +} +void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add>("lheWeights"); + desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) + ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); + //desc.add>("genWeights"); + desc.add("genWeights"); + desc.add("genEvent", edm::InputTag("generator")) + ->setComment("tag for the GenEventInfoProduct, to get the main weight"); + desc.add("genLumiInfoHeader", edm::InputTag("generator")) + ->setComment("tag for the GenLumiInfoProduct, to get the model string"); + desc.add>("weightgroups"); + desc.add>("maxGroupsPerType"); + desc.addOptionalUntracked>("pdfIds"); + desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); + desc.add("keepAllPSWeights", false)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); + descriptions.addDefault(desc); +} #include "FWCore/Framework/interface/MakerMacros.h" -DEFINE_FWK_MODULE(GenWeightsTableProducer); +DEFINE_FWK_MODULE(LHEWeightsTableProducer); diff --git a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc index 45dfd0df6b147..2803d52f0ccb2 100644 --- a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc @@ -24,41 +24,42 @@ #include namespace { - typedef std::vector WeightGroupDataContainer; - typedef std::array, 2> WeightGroupsToStore; + typedef std::vector WeightGroupDataContainer; + typedef std::array, 2> WeightGroupsToStore; } // namespace using CounterMap = genCounter::CounterMap; using Counter = genCounter::Counter; -class LHEWeightsTableProducer : -public edm::global::EDProducer, - edm::StreamCache, - edm::RunSummaryCache, - edm::EndRunProducer> { +class LHEWeightsTableProducer : public edm::global::EDProducer, + edm::StreamCache, + edm::RunSummaryCache, + edm::EndRunProducer> { public: LHEWeightsTableProducer(edm::ParameterSet const& params); void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; //func changed//sroychow void addWeightGroupToTable(std::map>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - const char* typeName, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, Counter& counter, - double genWeight) const; + std::map>& weightVecsizes, + std::map& weightlabels, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + Counter& counter, + double genWeight) const; WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, gen::WeightType weightType, int& maxStore) const; std::vector orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo* scaleGroup) const; + const gen::ScaleWeightGroupInfo& scaleGroup) const; - std::vector getPreferredPSweights(const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo* pswV) const; + std::vector preferredPSweights(const std::vector& psWeights, + const gen::PartonShowerWeightGroupInfo& pswV) const; //Lumiblock std::shared_ptr globalBeginLuminosityBlock(edm::LuminosityBlock const& iLumi, - edm::EventSetup const&) const override { + edm::EventSetup const&) const override { // Set equal to the max number of groups // subtrack 1 for each weight group you find bool foundLheWeights = false; @@ -66,66 +67,70 @@ public edm::global::EDProducer, for (auto& token : lheWeightInfoTokens_) { iLumi.getByToken(token, lheWeightInfoHandle); if (lheWeightInfoHandle.isValid()) { - foundLheWeights = true; - break; + foundLheWeights = true; + break; } } edm::Handle genWeightInfoHandle; iLumi.getByToken(genWeightInfoToken_, genWeightInfoHandle); - + std::unordered_map storePerType; for (size_t i = 0; i < weightgroups_.size(); i++) storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); - + WeightGroupsToStore weightsToStore; for (auto weightType : gen::allWeightTypes) { - if (foundLheWeights) { - auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); - weightsToStore.at(inLHE).insert(weightsToStore.at(inLHE).end(), lheWeights.begin(), lheWeights.end()); + if (foundLheWeights) { + auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); + for (auto& w : lheWeights) + weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); } auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); - weightsToStore.at(inGen).insert(weightsToStore.at(inGen).end(), genWeights.begin(), genWeights.end()); + for (auto& w : genWeights) + weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); } return std::make_shared(weightsToStore); } - + // nothing to do here - virtual void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} + void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} // create an empty counter - std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } + std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } // inizialize to zero at begin run - void streamBeginRun(edm::StreamID id, - edm::Run const&, edm::EventSetup const&) const override { streamCache(id)->clear(); } - + void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override { + streamCache(id)->clear(); + } + void streamBeginLuminosityBlock(edm::StreamID id, - edm::LuminosityBlock const& lumiBlock, - edm::EventSetup const& eventSetup) const override { + edm::LuminosityBlock const& lumiBlock, + edm::EventSetup const& eventSetup) const override { auto counterMap = streamCache(id); edm::Handle genLumiInfoHead; lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); if (!genLumiInfoHead.isValid()) edm::LogWarning("LHETablesProducer") - << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; - counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); + << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; + counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); std::string label = genLumiInfoHead.isValid() ? counterMap->getLabel() : "NULL"; - } // create an empty counter std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { return std::make_shared(); } // add this stream to the summary - void streamEndRunSummary(edm::StreamID id, edm::Run const&, - edm::EventSetup const&, CounterMap* runCounterMap) const override; + void streamEndRunSummary(edm::StreamID id, + edm::Run const&, + edm::EventSetup const&, + CounterMap* runCounterMap) const override; // nothing to do per se void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} // write the total to the run void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const& es, CounterMap const* runCounterMap) const override; // nothing to do here //void globalEndRun(edm::Run const& iRun, edm::EventSetup const& es, CounterMap* runCounterMap) const override {} - + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); - + protected: const std::vector> lheWeightTokens_; const std::vector> lheWeightInfoTokens_; @@ -137,40 +142,41 @@ public edm::global::EDProducer, const std::vector maxGroupsPerType_; const std::vector pdfIds_; const std::unordered_map weightTypeNames_ = { - {gen::WeightType::kScaleWeights, "LHEScale"}, - {gen::WeightType::kPdfWeights, "LHEPdf"}, - {gen::WeightType::kMEParamWeights, "MEParam"}, - {gen::WeightType::kPartonShowerWeights, "GENPartonShower"}, - {gen::WeightType::kUnknownWeights, "Unknown"}, + {gen::WeightType::kScaleWeights, "LHEScaleWeight"}, + {gen::WeightType::kPdfWeights, "LHEPdfWeight"}, + {gen::WeightType::kMEParamWeights, "MEParamWeight"}, + {gen::WeightType::kPartonShowerWeights, "PSWeight"}, + {gen::WeightType::kUnknownWeights, "UnknownWeight"}, }; //std::unordered_map weightGroupIndices_; int lheWeightPrecision_; - bool storeAllPSweights_; + bool storeAllPSweights_; enum { inLHE, inGen }; }; //put back if needed; till now not used LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params) - : lheWeightTokens_( - edm::vector_transform(params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + : lheWeightTokens_( + edm::vector_transform(params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), lheWeightInfoTokens_(edm::vector_transform( - params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - genWeightToken_(consumes(params.getParameter("genWeights"))), - genWeightInfoToken_(consumes(params.getParameter("genWeights"))), - genEventInfoToken_(consumes(params.getParameter("genEvent"))), - genLumiInfoHeadTag_(mayConsume(params.getParameter("genLumiInfoHeader"))), - weightgroups_(edm::vector_transform(params.getParameter>("weightgroups"), - [](auto& c) { return gen::WeightType(c.at(0)); })), - maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), - pdfIds_(params.getUntrackedParameter>("pdfIds", {})), - lheWeightPrecision_(params.getParameter("lheWeightPrecision")), - storeAllPSweights_(params.getParameter("storeAllPSweights")) -{ + params.getParameter>("lheWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightToken_(consumes(params.getParameter("genWeights"))), + genWeightInfoToken_( + consumes(params.getParameter("genWeights"))), + genEventInfoToken_(consumes(params.getParameter("genEvent"))), + genLumiInfoHeadTag_( + mayConsume(params.getParameter("genLumiInfoHeader"))), + weightgroups_(edm::vector_transform(params.getParameter>("weightgroups"), + [](auto& c) { return gen::WeightType(c.at(0)); })), + maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), + pdfIds_(params.getUntrackedParameter>("pdfIds", {})), + lheWeightPrecision_(params.getParameter("lheWeightPrecision")), + storeAllPSweights_(params.getParameter("storeAllPSweights")) { if (weightgroups_.size() != maxGroupsPerType_.size()) throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); - for(auto& wg : weightTypeNames_) { + for (auto& wg : weightTypeNames_) { produces(wg.second); produces(wg.second + "sizes"); } @@ -186,23 +192,23 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons bool foundLheWeights = false; for (auto& token : lheWeightTokens_) { iEvent.getByToken(token, lheWeightHandle); - if (lheWeightHandle.isValid()) { - foundLheWeights = true; - break; - } + if (lheWeightHandle.isValid()) { + foundLheWeights = true; + break; + } } //Taken from genweight producer //Added sroychow // generator information (always available) auto const& genInfo = iEvent.get(genEventInfoToken_); - const double genWeight = genInfo.weight(); + const double genWeight = genInfo.weight(); // table for gen info, always available - auto outGeninfo = std::make_unique(1, "genWeightNEW", true); + auto outGeninfo = std::make_unique(1, "genWeight", true); outGeninfo->setDoc("generator weight"); - outGeninfo->addColumnValue("", genInfo.weight(), "generator weight", nanoaod::FlatTable::FloatColumn); + outGeninfo->addColumnValue("", genInfo.weight(), "generator weight"); iEvent.put(std::move(outGeninfo), "GENWeight"); //this will take care of sum of genWeights counter.incGenOnly(genWeight); - + std::string& model_label = streamCache(id)->getLabel(); auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); iEvent.put(std::move(outM), "genModel"); @@ -212,42 +218,43 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons const GenWeightProduct* lheWeightProduct = lheWeightHandle.product(); lheWeights = lheWeightProduct->weights(); } - + edm::Handle genWeightHandle; iEvent.getByToken(genWeightToken_, genWeightHandle); const GenWeightProduct* genWeightProduct = genWeightHandle.product(); WeightsContainer genWeights = genWeightProduct->weights(); - + auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); - + //create a container with dummy weight vector std::map> lheWeightTables; std::map> weightVecsizes; std::map weightlabels; - for(auto& wg : weightTypeNames_) { + for (auto& wg : weightTypeNames_) { lheWeightTables.insert(std::make_pair(wg.first, std::vector())); weightVecsizes.insert(std::make_pair(wg.first, std::vector())); weightlabels.insert(std::make_pair(wg.first, "")); } if (foundLheWeights) { - addWeightGroupToTable(lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + addWeightGroupToTable( + lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); } - addWeightGroupToTable(lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); - - for(auto& wg : weightTypeNames_) { + addWeightGroupToTable( + lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); + + for (auto& wg : weightTypeNames_) { std::string wname = wg.second; auto& weightVec = lheWeightTables[wg.first]; counter.incLHE(genWeight, weightVec, wname); - //std::cout << "Writing out weight of type:" << wname << std::endl; - auto outTable = std::make_unique(weightVec.size(), wname + "Weight", false); - outTable->addColumn("", weightVec, weightlabels[wg.first], - nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + auto outTable = std::make_unique(weightVec.size(), wname, false); + outTable->addColumn("", weightVec, weightlabels[wg.first], lheWeightPrecision_); //now add the vector containing the sizes of alt sets - auto outTableSizes = std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); - outTableSizes->addColumn("", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, - nanoaod::FlatTable::FloatColumn, lheWeightPrecision_); + auto outTableSizes = + std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); + outTableSizes->addColumn( + "", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, lheWeightPrecision_); iEvent.put(std::move(outTable), wname); iEvent.put(std::move(outTableSizes), wname + "sizes"); } @@ -256,143 +263,145 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons /* */ -void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - const char* typeName, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, Counter& counter, - double genWeight) const { +void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, + std::map>& weightVecsizes, + std::map& weightlabels, + const char* typeName, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + Counter& counter, + double genWeight) const { std::unordered_map typeCount = {}; for (auto& type : gen::allWeightTypes) - typeCount[type] = 0; - + typeCount[type] = 0; + for (const auto& groupInfo : weightInfos) { //std::string entryName = typeName; gen::WeightType weightType = groupInfo.group->weightType(); std::string name = weightTypeNames_.at(weightType); - std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->name(); - auto& weights = allWeights.at(groupInfo.index); - //std::cout << "Name:" << name - // << "\tWsize=" << weights.size() - // << "\tPrevious size=" << lheWeightTables[weightType].size() - // << std::endl; + std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->description(); label.append("["); - label.append(std::to_string(lheWeightTables[weightType].size()));//to append the start index of this set + label.append(std::to_string(lheWeightTables[weightType].size())); //to append the start index of this set label.append("]; "); - lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); - weightVecsizes[weightType].emplace_back(weights.size()); - if (weightType == gen::WeightType::kScaleWeights && groupInfo.group->isWellFormed()) { - if(groupInfo.group->nIdsContained() == 9) { - weights = orderedScaleWeights(weights, dynamic_cast(groupInfo.group)); - label.append( - "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" - " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" - " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); + auto& weights = allWeights.at(groupInfo.index); + if (weightType == gen::WeightType::kScaleWeights) { + if (groupInfo.group->isWellFormed()) { + const auto scaleGroup = *static_cast(groupInfo.group.get()); + weights = orderedScaleWeights(weights, scaleGroup); + label.append( + "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" + " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" + " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); } else { - label.append( "Scale weight size is "); - label.append( std::to_string(groupInfo.group->nIdsContained())); - //label.append( ". Very fishy!!!"); + size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); + weights = std::vector(weights.begin(), weights.begin() + nstore); + label.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + + " elements of weights vector, unordered"); } - } else if (!storeAllPSweights_ && weightType == gen::WeightType::kPartonShowerWeights && groupInfo.group->isWellFormed()) { - weights = getPreferredPSweights(weights, dynamic_cast(groupInfo.group)); - label.append("PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is ISR=1 FSR=2"); + } else if (!storeAllPSweights_ && weightType == gen::WeightType::kPartonShowerWeights) { // && groupInfo.group->isWellFormed() + const auto psGroup = *static_cast(groupInfo.group.get()); + weights = preferredPSweights(weights, psGroup); + label.append( + "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is " + "ISR=1 FSR=2"); } - if(weightlabels[weightType] == "") + //else + // label.append(groupInfo.group->description()); + lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); + weightVecsizes[weightType].emplace_back(weights.size()); + + if (weightlabels[weightType].empty()) weightlabels[weightType].append("[idx in AltSetSizes array] Name [start idx in weight array];\n"); + weightlabels[weightType].append(label); typeCount[weightType]++; } } WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, - gen::WeightType weightType, - int& maxStore) const { - WeightGroupDataContainer group; - if (weightType == gen::WeightType::kPdfWeights && pdfIds_.size() > 0) { - group = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + gen::WeightType weightType, + int& maxStore) const { + std::vector allgroups; + if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { + allgroups = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); } else - group = weightsHandle->weightGroupsAndIndicesByType(weightType); - - if (maxStore < 0 || static_cast(group.size()) <= maxStore) { + allgroups = weightsHandle->weightGroupsAndIndicesByType(weightType); + + int toStore = maxStore; + if (maxStore < 0 || static_cast(allgroups.size()) <= maxStore) { // Modify size in case one type of weight is present in multiple products - maxStore -= group.size(); - return group; + maxStore -= allgroups.size(); + toStore = allgroups.size(); + } + + WeightGroupDataContainer out; + for (int i = 0; i < toStore; i++) { + auto& group = allgroups.at(i); + gen::SharedWeightGroupData temp = {group.index, std::move(group.group)}; + out.push_back(temp); } - return std::vector(group.begin(), group.begin() + maxStore); + return out; } std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo* scaleGroup) const { + const gen::ScaleWeightGroupInfo& scaleGroup) const { std::vector weights; - weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR05muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR1muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->centralIndex())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR1muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup->muR2muF2Index())); - + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.centralIndex())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF2Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF05Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF1Index())); + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); + return weights; } -std::vector LHEWeightsTableProducer::getPreferredPSweights(const std::vector& psWeights, - const gen::PartonShowerWeightGroupInfo* pswV) const { +std::vector LHEWeightsTableProducer::preferredPSweights(const std::vector& psWeights, + const gen::PartonShowerWeightGroupInfo& pswV) const { std::vector psTosave; - - double baseline = psWeights.at(pswV->weightIndexFromLabel("Baseline"));//at 1 - - if(psWeights.at(pswV->weightIndexFromLabel("isrDefHi")) >= 0) - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefHi"))/baseline ); // at 6 - else psTosave.emplace_back(1.); - - if(psWeights.at(pswV->weightIndexFromLabel("isrDefLo")) >= 0) - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("isrDefLo"))/baseline ); // at 6 - else psTosave.emplace_back(1.); - - if(psWeights.at(pswV->weightIndexFromLabel("fsrDefHi")) >= 0) - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefHi"))/baseline ); // at 6 - else psTosave.emplace_back(1.); - - if(psWeights.at(pswV->weightIndexFromLabel("fsrDefLo")) >= 0) - psTosave.emplace_back( psWeights.at(pswV->weightIndexFromLabel("fsrDefLo"))/baseline ); // at 6 - else psTosave.emplace_back(1.); + double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, true, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, true, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, false, gen::PSVarType::def)) / baseline); return psTosave; } void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, - edm::Run const&, - edm::EventSetup const&, - CounterMap* runCounterMap) const { - //Counter& counter = *streamCache(id)->get(); + edm::Run const&, + edm::EventSetup const&, + CounterMap* runCounterMap) const { //this takes care for mergeing all the weight sums runCounterMap->mergeSumMap(*streamCache(id)); } -void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const { +void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, + edm::EventSetup const&, + CounterMap const* runCounterMap) const { auto out = std::make_unique(); - + for (auto x : runCounterMap->countermap) { auto& runCounter = x.second; std::string label = std::string("_") + x.first; std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; - - out->addInt("genEventCountNEW" + label, "event count" + doclabel, runCounter.num_); - out->addFloat("genEventSumwNEW" + label, "sum of gen weights" + doclabel, runCounter.sumw_); - out->addFloat("genEventSumw2NEW" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); - + + out->addInt("genEventCount" + label, "event count" + doclabel, runCounter.num_); + out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter.sumw_); + out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); + double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; //Sum from map - for(auto& sumw : runCounter.weightSumMap_) { - + for (auto& sumw : runCounter.weightSumMap_) { //Normalize with genEventSumw - for(auto& val : sumw.second) val *= norm; - out->addVFloat(sumw.first + "Sumw" + label, - "Sum of genEventWeight *" + sumw.first + "[i]/genEventSumw" + doclabel, - sumw.second) ; + for (auto& val : sumw.second) + val *= norm; + out->addVFloat(sumw.first + "Sumw" + label, + "Sum of genEventWeight *" + sumw.first + "[i]/genEventSumw" + doclabel, + sumw.second); } } iRun.put(std::move(out)); @@ -401,16 +410,18 @@ void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d edm::ParameterSetDescription desc; desc.add>("lheWeights"); desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) - ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); + ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); //desc.add>("genWeights"); desc.add("genWeights"); - desc.add("genEvent", edm::InputTag("generator"))->setComment("tag for the GenEventInfoProduct, to get the main weight"); - desc.add("genLumiInfoHeader", edm::InputTag("generator"))->setComment("tag for the GenLumiInfoProduct, to get the model string"); + desc.add("genEvent", edm::InputTag("generator")) + ->setComment("tag for the GenEventInfoProduct, to get the main weight"); + desc.add("genLumiInfoHeader", edm::InputTag("generator")) + ->setComment("tag for the GenLumiInfoProduct, to get the model string"); desc.add>("weightgroups"); desc.add>("maxGroupsPerType"); desc.addOptionalUntracked>("pdfIds"); desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); - desc.add("storeAllPSweights", 0)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); + desc.add("storeAllPSweights", false)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); descriptions.addDefault(desc); } diff --git a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc index b942db79bcd1f..4a6999ed42733 100644 --- a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc +++ b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc @@ -2,7 +2,7 @@ // // Package: PhysicsTools/NanoAODOutput // Class : NanoAODOutputModule -// +// // Implementation: // [Notes on implementation] // @@ -11,15 +11,17 @@ // // system include files -#include +#include +#include + +#include "Compression.h" #include "TFile.h" -#include "TTree.h" -#include "TROOT.h" #include "TObjString.h" -#include "Compression.h" +#include "TROOT.h" +#include "TTree.h" +#include // user include files -#include "FWCore/Framework/interface/OutputModule.h" #include "FWCore/Framework/interface/one/OutputModule.h" #include "FWCore/Framework/interface/RunForOutput.h" #include "FWCore/Framework/interface/LuminosityBlockForOutput.h" @@ -63,7 +65,7 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { int m_eventsSinceFlush{0}; std::string m_compressionAlgorithm; bool m_writeProvenance; - bool m_fakeName; //crab workaround, remove after crab is fixed + bool m_fakeName; //crab workaround, remove after crab is fixed int m_autoFlush; edm::ProcessHistoryRegistry m_processHistoryRegistry; edm::JobReport::Token m_jrToken; @@ -73,59 +75,61 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { static constexpr int m_firstFlush{1000}; class CommonEventBranches { - public: - void branch(TTree &tree) { - tree.Branch("run", & m_run, "run/i"); - tree.Branch("luminosityBlock", & m_luminosityBlock, "luminosityBlock/i"); - tree.Branch("event", & m_event, "event/l"); - } - void fill(const edm::EventID & id) { - m_run = id.run(); m_luminosityBlock = id.luminosityBlock(); m_event = id.event(); - } - private: - UInt_t m_run; UInt_t m_luminosityBlock; ULong64_t m_event; + public: + void branch(TTree& tree) { + tree.Branch("run", &m_run, "run/i"); + tree.Branch("luminosityBlock", &m_luminosityBlock, "luminosityBlock/i"); + tree.Branch("event", &m_event, "event/l"); + } + void fill(const edm::EventID& id) { + m_run = id.run(); + m_luminosityBlock = id.luminosityBlock(); + m_event = id.event(); + } + + private: + UInt_t m_run; + UInt_t m_luminosityBlock; + ULong64_t m_event; } m_commonBranches; class CommonLumiBranches { - public: - void branch(TTree &tree) { - tree.Branch("run", & m_run, "run/i"); - tree.Branch("luminosityBlock", & m_luminosityBlock, "luminosityBlock/i"); - } - void fill(const edm::LuminosityBlockID & id) { - m_run = id.run(); - m_luminosityBlock = id.value(); - } - private: - UInt_t m_run; UInt_t m_luminosityBlock; + public: + void branch(TTree& tree) { + tree.Branch("run", &m_run, "run/i"); + tree.Branch("luminosityBlock", &m_luminosityBlock, "luminosityBlock/i"); + } + void fill(const edm::LuminosityBlockID& id) { + m_run = id.run(); + m_luminosityBlock = id.value(); + } + + private: + UInt_t m_run; + UInt_t m_luminosityBlock; } m_commonLumiBranches; class CommonRunBranches { - public: - void branch(TTree &tree) { - tree.Branch("run", & m_run, "run/i"); - } - void fill(const edm::RunID & id) { - m_run = id.run(); - } - private: - UInt_t m_run; - } m_commonRunBranches; + public: + void branch(TTree& tree) { tree.Branch("run", &m_run, "run/i"); } + void fill(const edm::RunID& id) { m_run = id.run(); } + private: + UInt_t m_run; + } m_commonRunBranches; std::vector m_tables; std::vector m_tableTokens; std::vector m_tableVectorTokens; std::vector m_triggers; + bool m_triggers_areSorted = false; std::vector m_evstrings; std::vector m_runTables; - std::vector> m_nanoMetadata; - + std::vector> m_nanoMetadata; }; - // // constants, enums and typedefs // @@ -137,22 +141,19 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { // // constructors and destructor // -NanoAODOutputModule::NanoAODOutputModule(edm::ParameterSet const& pset): - edm::one::OutputModuleBase::OutputModuleBase(pset), - edm::one::OutputModule<>(pset), - m_fileName(pset.getUntrackedParameter("fileName")), - m_logicalFileName(pset.getUntrackedParameter("logicalFileName")), - m_compressionLevel(pset.getUntrackedParameter("compressionLevel")), - m_compressionAlgorithm(pset.getUntrackedParameter("compressionAlgorithm")), - m_writeProvenance(pset.getUntrackedParameter("saveProvenance", true)), - m_fakeName(pset.getUntrackedParameter("fakeNameForCrab", false)), - m_autoFlush(pset.getUntrackedParameter("autoFlush", -10000000)), - m_processHistoryRegistry() -{ -} - -void -NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { +NanoAODOutputModule::NanoAODOutputModule(edm::ParameterSet const& pset) + : edm::one::OutputModuleBase::OutputModuleBase(pset), + edm::one::OutputModule<>(pset), + m_fileName(pset.getUntrackedParameter("fileName")), + m_logicalFileName(pset.getUntrackedParameter("logicalFileName")), + m_compressionLevel(pset.getUntrackedParameter("compressionLevel")), + m_compressionAlgorithm(pset.getUntrackedParameter("compressionAlgorithm")), + m_writeProvenance(pset.getUntrackedParameter("saveProvenance", true)), + m_fakeName(pset.getUntrackedParameter("fakeNameForCrab", false)), + m_autoFlush(pset.getUntrackedParameter("autoFlush", -10000000)), + m_processHistoryRegistry() {} + +void NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { //Get data from 'e' and write it to the file edm::Service jr; jr->eventWrittenToFile(m_jrToken, iEvent.id().run(), iEvent.id().event()); @@ -168,7 +169,7 @@ NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { float percentClusterDone = m_firstFlush / static_cast(m_autoFlush); maxMemory = static_cast(m_tree->GetTotBytes()) / percentClusterDone; } else if (m_tree->GetZipBytes() == 0) { - maxMemory = 100*1024*1024; // Degenerate case of no information in the tree; arbitrary value + maxMemory = 100 * 1024 * 1024; // Degenerate case of no information in the tree; arbitrary value } else { // Estimate the memory we'll be using by scaling the current compression ratio. float cxnRatio = m_tree->GetTotBytes() / static_cast(m_tree->GetZipBytes()); @@ -216,17 +217,28 @@ NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { ++iTable; } } + if (!m_triggers_areSorted) { // sort triggers/flags in inverse processHistory order, to save without any special label the most recent ones + std::vector pnames; + for (auto& p : iEvent.processHistory()) + pnames.push_back(p.processName()); + std::sort(m_triggers.begin(), m_triggers.end(), [pnames](TriggerOutputBranches& a, TriggerOutputBranches& b) { + return ((std::find(pnames.begin(), pnames.end(), a.processName()) - pnames.begin()) > + (std::find(pnames.begin(), pnames.end(), b.processName()) - pnames.begin())); + }); + m_triggers_areSorted = true; + } // fill triggers - for (auto & t : m_triggers) t.fill(iEvent,*m_tree); + for (auto& t : m_triggers) + t.fill(iEvent, *m_tree); // fill event branches - for (auto & t : m_evstrings) t.fill(iEvent,*m_tree); + for (auto& t : m_evstrings) + t.fill(iEvent, *m_tree); m_tree->Fill(); m_processHistoryRegistry.registerProcessHistory(iEvent.processHistory()); } -void -NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& iLumi) { +void NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& iLumi) { edm::Service jr; jr->reportLumiSection(m_jrToken, iLumi.id().run(), iLumi.id().value()); @@ -236,24 +248,25 @@ NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput const& i m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory()); } -void -NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { +void NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { edm::Service jr; jr->reportRunNumber(m_jrToken, iRun.id().run()); m_commonRunBranches.fill(iRun.id()); - for (auto & t : m_runTables) t.fill(iRun,*m_runTree); + for (auto& t : m_runTables) + t.fill(iRun, *m_runTree); edm::Handle hstring; - for (const auto & p : m_nanoMetadata) { + for (const auto& p : m_nanoMetadata) { iRun.getByToken(p.second, hstring); - TObjString *tos = dynamic_cast(m_file->Get(p.first.c_str())); + TObjString* tos = dynamic_cast(m_file->Get(p.first.c_str())); if (tos) { - if (hstring->str() != tos->GetString()) throw cms::Exception("LogicError", "Inconsistent nanoMetadata " + p.first + " (" + hstring->str() +")"); + if (hstring->str() != tos->GetString()) + throw cms::Exception("LogicError", "Inconsistent nanoMetadata " + p.first + " (" + hstring->str() + ")"); } else { - auto ostr = std::make_unique(hstring->str().c_str()); - m_file->WriteTObject(ostr.release(), p.first.c_str()); + auto ostr = std::make_unique(hstring->str().c_str()); + m_file->WriteTObject(ostr.release(), p.first.c_str()); } } @@ -262,39 +275,36 @@ NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { m_processHistoryRegistry.registerProcessHistory(iRun.processHistory()); } -bool -NanoAODOutputModule::isFileOpen() const { - return nullptr != m_file.get(); -} +bool NanoAODOutputModule::isFileOpen() const { return nullptr != m_file.get(); } -void -NanoAODOutputModule::openFile(edm::FileBlock const&) { - m_file = std::make_unique(m_fileName.c_str(),"RECREATE","",m_compressionLevel); +void NanoAODOutputModule::openFile(edm::FileBlock const&) { + m_file = std::make_unique(m_fileName.c_str(), "RECREATE", "", m_compressionLevel); edm::Service jr; cms::Digest branchHash; m_jrToken = jr->outputFileOpened(m_fileName, m_logicalFileName, std::string(), - m_fakeName?"PoolOutputModule":"NanoAODOutputModule", + m_fakeName ? "PoolOutputModule" : "NanoAODOutputModule", description().moduleLabel(), edm::createGlobalIdentifier(), std::string(), branchHash.digest().toString(), - std::vector() - ); + std::vector()); if (m_compressionAlgorithm == std::string("ZLIB")) { - m_file->SetCompressionAlgorithm(ROOT::kZLIB); - } else if (m_compressionAlgorithm == std::string("LZMA")) { - m_file->SetCompressionAlgorithm(ROOT::kLZMA); - } else { - throw cms::Exception("Configuration") << "NanoAODOutputModule configured with unknown compression algorithm '" << m_compressionAlgorithm << "'\n" - << "Allowed compression algorithms are ZLIB and LZMA\n"; - } + m_file->SetCompressionAlgorithm(ROOT::kZLIB); + } else if (m_compressionAlgorithm == std::string("LZMA")) { + m_file->SetCompressionAlgorithm(ROOT::kLZMA); + } else { + throw cms::Exception("Configuration") + << "NanoAODOutputModule configured with unknown compression algorithm '" << m_compressionAlgorithm << "'\n" + << "Allowed compression algorithms are ZLIB and LZMA\n"; + } /* Setup file structure here */ m_tables.clear(); m_tableTokens.clear(); m_triggers.clear(); + m_triggers_areSorted = false; m_evstrings.clear(); m_runTables.clear(); const auto& keeps = keptProducts(); @@ -312,97 +322,98 @@ NanoAODOutputModule::openFile(edm::FileBlock const&) { throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className()); } - for (const auto & keep : keeps[edm::InRun]) { - if(keep.first->className() == "nanoaod::MergeableCounterTable" ) - m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); - else if(keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") - m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); - else throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className() + " in Run branch"); + for (const auto& keep : keeps[edm::InRun]) { + if (keep.first->className() == "nanoaod::MergeableCounterTable") + m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); + else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") + m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); + else + throw cms::Exception("Configuration", + "NanoAODOutputModule cannot handle class " + keep.first->className() + " in Run branch"); } - // create the trees - m_tree.reset(new TTree("Events","Events")); + m_tree = std::make_unique("Events", "Events"); m_tree->SetAutoSave(0); m_tree->SetAutoFlush(0); m_commonBranches.branch(*m_tree); - m_lumiTree.reset(new TTree("LuminosityBlocks","LuminosityBlocks")); + m_lumiTree = std::make_unique("LuminosityBlocks", "LuminosityBlocks"); m_lumiTree->SetAutoSave(0); m_commonLumiBranches.branch(*m_lumiTree); - m_runTree.reset(new TTree("Runs","Runs")); + m_runTree = std::make_unique("Runs", "Runs"); m_runTree->SetAutoSave(0); m_commonRunBranches.branch(*m_runTree); - + if (m_writeProvenance) { - m_metaDataTree.reset(new TTree(edm::poolNames::metaDataTreeName().c_str(),"Job metadata")); - m_metaDataTree->SetAutoSave(0); - m_parameterSetsTree.reset(new TTree(edm::poolNames::parameterSetsTreeName().c_str(),"Parameter sets")); - m_parameterSetsTree->SetAutoSave(0); + m_metaDataTree = std::make_unique(edm::poolNames::metaDataTreeName().c_str(), "Job metadata"); + m_metaDataTree->SetAutoSave(0); + m_parameterSetsTree = std::make_unique(edm::poolNames::parameterSetsTreeName().c_str(), "Parameter sets"); + m_parameterSetsTree->SetAutoSave(0); } } -void -NanoAODOutputModule::reallyCloseFile() { +void NanoAODOutputModule::reallyCloseFile() { if (m_writeProvenance) { - int basketSize = 16384; // fixme configurable? - edm::fillParameterSetBranch(m_parameterSetsTree.get(), basketSize); - edm::fillProcessHistoryBranch(m_metaDataTree.get(), basketSize, m_processHistoryRegistry); - if (m_metaDataTree->GetNbranches() != 0) { - m_metaDataTree->SetEntries(-1); - } - if (m_parameterSetsTree->GetNbranches() != 0) { - m_parameterSetsTree->SetEntries(-1); - } + int basketSize = 16384; // fixme configurable? + edm::fillParameterSetBranch(m_parameterSetsTree.get(), basketSize); + edm::fillProcessHistoryBranch(m_metaDataTree.get(), basketSize, m_processHistoryRegistry); + if (m_metaDataTree->GetNbranches() != 0) { + m_metaDataTree->SetEntries(-1); + } + if (m_parameterSetsTree->GetNbranches() != 0) { + m_parameterSetsTree->SetEntries(-1); + } } m_file->Write(); m_file->Close(); m_file.reset(); - m_tree.release(); // apparently root has ownership - m_lumiTree.release(); // - m_runTree.release(); // - m_metaDataTree.release(); // - m_parameterSetsTree.release(); // + m_tree.release(); // apparently root has ownership + m_lumiTree.release(); // + m_runTree.release(); // + m_metaDataTree.release(); // + m_parameterSetsTree.release(); // edm::Service jr; jr->outputFileClosed(m_jrToken); } -void -NanoAODOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { +void NanoAODOutputModule::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; desc.addUntracked("fileName"); - desc.addUntracked("logicalFileName",""); + desc.addUntracked("logicalFileName", ""); - desc.addUntracked("compressionLevel", 9) - ->setComment("ROOT compression level of output file."); + desc.addUntracked("compressionLevel", 9)->setComment("ROOT compression level of output file."); desc.addUntracked("compressionAlgorithm", "ZLIB") - ->setComment("Algorithm used to compress data in the ROOT output file, allowed values are ZLIB and LZMA"); + ->setComment("Algorithm used to compress data in the ROOT output file, allowed values are ZLIB and LZMA"); desc.addUntracked("saveProvenance", true) - ->setComment("Save process provenance information, e.g. for edmProvDump"); + ->setComment("Save process provenance information, e.g. for edmProvDump"); desc.addUntracked("fakeNameForCrab", false) - ->setComment("Change the OutputModule name in the fwk job report to fake PoolOutputModule. This is needed to run on cran (and publish) till crab is fixed"); - desc.addUntracked("autoFlush", -10000000) - ->setComment("Autoflush parameter for ROOT file"); + ->setComment( + "Change the OutputModule name in the fwk job report to fake PoolOutputModule. This is needed to run on cran " + "(and publish) till crab is fixed"); + desc.addUntracked("autoFlush", -10000000)->setComment("Autoflush parameter for ROOT file"); //replace with whatever you want to get from the EDM by default - const std::vector keep = {"drop *", "keep nanoaodFlatTable_*Table_*_*", "keep edmTriggerResults_*_*_*", "keep String_*_genModel_*", "keep nanoaodMergeableCounterTable_*Table_*_*", "keep nanoaodUniqueString_nanoMetadata_*_*"}; - edm::OutputModule::fillDescription(desc, keep); - + const std::vector keep = {"drop *", + "keep nanoaodFlatTable_*Table_*_*", + "keep edmTriggerResults_*_*_*", + "keep String_*_genModel_*", + "keep nanoaodMergeableCounterTable_*Table_*_*", + "keep nanoaodUniqueString_nanoMetadata_*_*"}; + edm::one::OutputModule<>::fillDescription(desc, keep); + //Used by Workflow management for their own meta data edm::ParameterSetDescription dataSet; dataSet.setAllowAnything(); desc.addUntracked("dataset", dataSet) - ->setComment("PSet is only used by Data Operations and not by this module."); - + ->setComment("PSet is only used by Data Operations and not by this module."); + edm::ParameterSetDescription branchSet; branchSet.setAllowAnything(); desc.add("branches", branchSet); - - descriptions.addDefault(desc); - } DEFINE_FWK_MODULE(NanoAODOutputModule); diff --git a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc index 4f411b12dfe55..abf25ffaf831b 100644 --- a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc +++ b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc @@ -13,18 +13,20 @@ void TableOutputBranches::defineBranchesFromFirstEvent(const nanoaod::FlatTable for (size_t i = 0; i < tab.nColumns(); i++) { const std::string &var = tab.columnName(i); switch (tab.columnType(i)) { - case (nanoaod::FlatTable::FloatColumn): + case nanoaod::FlatTable::ColumnType::Float: m_floatBranches.emplace_back(var, tab.columnDoc(i), "F"); break; - case (nanoaod::FlatTable::IntColumn): + case nanoaod::FlatTable::ColumnType::Int: m_intBranches.emplace_back(var, tab.columnDoc(i), "I"); break; - case (nanoaod::FlatTable::UInt8Column): + case nanoaod::FlatTable::ColumnType::UInt8: m_uint8Branches.emplace_back(var, tab.columnDoc(i), "b"); break; - case (nanoaod::FlatTable::BoolColumn): + case nanoaod::FlatTable::ColumnType::Bool: m_uint8Branches.emplace_back(var, tab.columnDoc(i), "O"); break; + default: + throw cms::Exception("LogicError", "Unsupported type"); } } } diff --git a/PhysicsTools/NanoAOD/python/nano_cff.py b/PhysicsTools/NanoAOD/python/nano_cff.py index 8a13b7dda4d11..b98faffe69fb2 100644 --- a/PhysicsTools/NanoAOD/python/nano_cff.py +++ b/PhysicsTools/NanoAOD/python/nano_cff.py @@ -11,19 +11,24 @@ from PhysicsTools.NanoAOD.ttbarCategorization_cff import * from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * +from PhysicsTools.NanoAOD.genVertex_cff import * +from PhysicsTools.NanoAOD.genWeights_cff import * from PhysicsTools.NanoAOD.vertices_cff import * from PhysicsTools.NanoAOD.met_cff import * from PhysicsTools.NanoAOD.triggerObjects_cff import * from PhysicsTools.NanoAOD.isotracks_cff import * from PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff import * -from PhysicsTools.NanoAOD.genWeightsTable_cfi import * from Configuration.Eras.Modifier_run2_miniAOD_80XLegacy_cff import run2_miniAOD_80XLegacy +from Configuration.Eras.Modifier_run2_nanoAOD_92X_cff import run2_nanoAOD_92X from Configuration.Eras.Modifier_run2_nanoAOD_94X2016_cff import run2_nanoAOD_94X2016 from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv1_cff import run2_nanoAOD_94XMiniAODv1 from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv2_cff import run2_nanoAOD_94XMiniAODv2 from Configuration.Eras.Modifier_run2_nanoAOD_102Xv1_cff import run2_nanoAOD_102Xv1 from Configuration.Eras.Modifier_run2_nanoAOD_106Xv1_cff import run2_nanoAOD_106Xv1 +from Configuration.Eras.Modifier_run2_egamma_2017_cff import run2_egamma_2017 +from Configuration.Eras.Modifier_run2_egamma_2018_cff import run2_egamma_2018 + nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( @@ -64,7 +69,7 @@ discNames = cms.vstring( "pfCombinedInclusiveSecondaryVertexV2BJetTags", "pfDeepCSVJetTags:probb+pfDeepCSVJetTags:probbb", #if multiple MiniAOD branches need to be summed up (e.g., DeepCSV b+bb), separate them using '+' delimiter - "pfCombinedMVAV2BJetTags" + "pfCombinedMVAV2BJetTags" ), discShortNames = cms.vstring( "CSVV2", @@ -73,7 +78,7 @@ ), weightFiles = cms.vstring( #default settings are for 2017 94X. toModify function is called later for other eras. btagSFdir+"CSVv2_94XSF_V2_B_F.csv", - btagSFdir+"DeepCSV_94XSF_V2_B_F.csv", + btagSFdir+"DeepCSV_94XSF_V2_B_F.csv", "unavailable" #if SFs for an algorithm in an era is unavailable, the corresponding branch will not be stored ), operatingPoints = cms.vstring("3","3","3"), #loose = 0, medium = 1, tight = 2, reshaping = 3 @@ -84,34 +89,16 @@ ) for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: # to be updated when SF for Summer16MiniAODv3 MC will be available - modifier.toModify(btagWeightTable, + modifier.toModify(btagWeightTable, cut = cms.string("pt > 25. && abs(eta) < 2.4"), #80X corresponds to 2016, |eta| < 2.4 weightFiles = cms.vstring( #80X corresponds to 2016 SFs - btagSFdir+"CSVv2_Moriond17_B_H.csv", - "unavailable", - btagSFdir+"cMVAv2_Moriond17_B_H.csv" + btagSFdir+"CSVv2_Moriond17_B_H.csv", + "unavailable", + btagSFdir+"cMVAv2_Moriond17_B_H.csv" ) ) -genWeightsTable = cms.EDProducer("GenWeightsTableProducer", - genEvent = cms.InputTag("generator"), - genLumiInfoHeader = cms.InputTag("generator"), - lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), - preferredPDFs = cms.VPSet( # see https://lhapdf.hepforge.org/pdfsets.html - cms.PSet( name = cms.string("PDF4LHC15_nnlo_30_pdfas"), lhaid = cms.uint32(91400) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_hessian_pdfas"), lhaid = cms.uint32(306000) ), - cms.PSet( name = cms.string("NNPDF30_nlo_as_0118"), lhaid = cms.uint32(260000) ), # for some 92X samples. Note that the nominal weight, 260000, is not included in the LHE ... - cms.PSet( name = cms.string("NNPDF30_lo_as_0130"), lhaid = cms.uint32(262000) ), # some MLM 80X samples have only this (e.g. /store/mc/RunIISummer16MiniAODv2/DYJetsToLL_M-50_TuneCUETP8M1_13TeV-madgraphMLM-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6_ext1-v2/120000/02A210D6-F5C3-E611-B570-008CFA197BD4.root ) - cms.PSet( name = cms.string("NNPDF30_nlo_nf_4_pdfas"), lhaid = cms.uint32(292000) ), # some FXFX 80X samples have only this (e.g. WWTo1L1Nu2Q, WWTo4Q) - cms.PSet( name = cms.string("NNPDF30_nlo_nf_5_pdfas"), lhaid = cms.uint32(292200) ), # some FXFX 80X samples have only this (e.g. DYJetsToLL_Pt, WJetsToLNu_Pt, DYJetsToNuNu_Pt) - ), - namedWeightIDs = cms.vstring(), - namedWeightLabels = cms.vstring(), - lheWeightPrecision = cms.int32(14), - maxPdfWeights = cms.uint32(150), - debug = cms.untracked.bool(False), -) lheInfoTable = cms.EDProducer("LHETablesProducer", lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), precision = cms.int32(14), @@ -125,7 +112,7 @@ nanoSequenceCommon = cms.Sequence( nanoMetadata + jetSequence + muonSequence + tauSequence + electronSequence+photonSequence+vertexSequence+ - isoTrackSequence + # must be after all the leptons + isoTrackSequence + jetLepSequence + # must be after all the leptons linkedObjects + jetTables + muonTables + tauTables + electronTables + photonTables + globalTables +vertexTables+ metTables+simpleCleanerTable + isoTrackTables ) @@ -133,8 +120,13 @@ nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyFullSim) -nanoSequenceFS = cms.Sequence(genParticleSequence + particleLevelSequence + nanoSequenceCommon + jetMC + muonMC + electronMC + photonMC + tauMC + metMC + ttbarCatMCProducers + globalTablesMC + btagWeightTable + genWeightsTable + genParticleTables + particleLevelTables + lheInfoTable + ttbarCategoryTable ) +nanoSequenceFS = cms.Sequence(genParticleSequence + genVertexTables + particleLevelSequence + nanoSequenceCommon + jetMC + muonMC + electronMC + photonMC + tauMC + metMC + ttbarCatMCProducers + globalTablesMC + btagWeightTable + genWeightsTable + genVertexTable + genParticleTables + particleLevelTables + lheInfoTable + ttbarCategoryTable ) +(run2_nanoAOD_92X | run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94X2016 | \ + run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | \ + run2_nanoAOD_102Xv1).toReplaceWith(nanoSequenceFS, nanoSequenceFS.copyAndExclude([genVertexTable, genVertexT0Table])) + +# GenVertex only stored in newer MiniAOD nanoSequenceMC = nanoSequenceFS.copy() nanoSequenceMC.insert(nanoSequenceFS.index(nanoSequenceCommon)+1,nanoSequenceOnlyFullSim) @@ -147,7 +139,7 @@ import RecoTauTag.RecoTau.tools.runTauIdMVA as tauIdConfig def nanoAOD_addTauIds(process): updatedTauName = "slimmedTausUpdated" - tauIdEmbedder = tauIdConfig.TauIDEmbedder(process, cms, debug = False, updatedTauName = updatedTauName, + tauIdEmbedder = tauIdConfig.TauIDEmbedder(process, debug = False, updatedTauName = updatedTauName, toKeep = [ "deepTau2017v2p1" ]) tauIdEmbedder.runTauID() process.patTauMVAIDsSeq.insert(process.patTauMVAIDsSeq.index(getattr(process, updatedTauName)), @@ -177,10 +169,41 @@ def nanoAOD_addDeepInfo(process,addDeepBTag,addDeepFlavour): process.updatedJets.jetSource="selectedUpdatedPatJetsWithDeepInfo" return process +def nanoAOD_addDeepMET(process, addDeepMETProducer, ResponseTune_Graph): + if addDeepMETProducer: + # produce DeepMET on the fly if it is not in MiniAOD + print("add DeepMET Producers") + process.load('RecoMET.METPUSubtraction.deepMETProducer_cfi') + process.deepMETsResolutionTune = process.deepMETProducer.clone() + process.deepMETsResponseTune = process.deepMETProducer.clone() + #process.deepMETsResponseTune.graph_path = 'RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2018.pb' + process.deepMETsResponseTune.graph_path = ResponseTune_Graph.value() + process.metTables += process.deepMetTables + return process + from PhysicsTools.PatUtils.tools.runMETCorrectionsAndUncertainties import runMetCorAndUncFromMiniAOD -#from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD +from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD def nanoAOD_recalibrateMETs(process,isData): - runMetCorAndUncFromMiniAOD(process,isData=isData) + # add DeepMETs + nanoAOD_DeepMET_switch = cms.PSet( + nanoAOD_addDeepMET_switch = cms.untracked.bool(True), # decide if DeeMET should be included in Nano + nanoAOD_produceDeepMET_switch = cms.untracked.bool(False), # decide if DeepMET should be computed on the fly + ResponseTune_Graph = cms.untracked.string('RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2018.pb') + ) + for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016, run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1, run2_nanoAOD_106Xv1: + # compute DeepMETs in these eras (before 111X) + modifier.toModify(nanoAOD_DeepMET_switch, nanoAOD_produceDeepMET_switch = cms.untracked.bool(True)) + for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: + modifier.toModify(nanoAOD_DeepMET_switch, ResponseTune_Graph=cms.untracked.string("RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2016.pb")) + if nanoAOD_DeepMET_switch.nanoAOD_addDeepMET_switch: + process = nanoAOD_addDeepMET(process, + addDeepMETProducer=nanoAOD_DeepMET_switch.nanoAOD_produceDeepMET_switch, + ResponseTune_Graph=nanoAOD_DeepMET_switch.ResponseTune_Graph) + + # if included in Nano, and not computed in the fly, then it should be extracted from minAOD + extractDeepMETs = nanoAOD_DeepMET_switch.nanoAOD_addDeepMET_switch and not nanoAOD_DeepMET_switch.nanoAOD_produceDeepMET_switch + + runMetCorAndUncFromMiniAOD(process,isData=isData, extractDeepMETs=extractDeepMETs) process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.fullPatMetSequence)) process.basicJetsForMetForT1METNano = process.basicJetsForMet.clone( src = process.updatedJetsWithUserData.src, @@ -196,10 +219,36 @@ def nanoAOD_recalibrateMETs(process,isData): table.variables.muonSubtrFactor = Var("1-userFloat('muonSubtrRawPt')/(pt()*jecFactor('Uncorrected'))",float,doc="1-(muon-subtracted raw pt)/(raw pt)",precision=6) process.metTables += process.corrT1METJetTable # makePuppiesFromMiniAOD(process,True) # call this before in the global customizer otherwise it would reset photon IDs in VID -# runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi") -# process.puppiNoLep.useExistingWeights = False -# process.puppi.useExistingWeights = False -# process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(jetSequence),cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) + nanoAOD_PuppiV15_switch = cms.PSet( + recoMetFromPFCs = cms.untracked.bool(False), + reclusterJets = cms.untracked.bool(False), + ) + run2_nanoAOD_106Xv1.toModify(nanoAOD_PuppiV15_switch,recoMetFromPFCs=True,reclusterJets=True) + runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi", recoMetFromPFCs=bool(nanoAOD_PuppiV15_switch.recoMetFromPFCs), reclusterJets=bool(nanoAOD_PuppiV15_switch.reclusterJets)) + if nanoAOD_PuppiV15_switch.reclusterJets: + from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets + from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask, addToProcessAndTask + task = getPatAlgosToolsTask(process) + addToProcessAndTask('ak4PuppiJets', ak4PFJets.clone (src = 'puppi', doAreaFastjet = True, jetPtMin = 10.), process, task) + from PhysicsTools.PatAlgos.tools.jetTools import addJetCollection + addJetCollection(process, + labelName = 'Puppi', + jetSource = cms.InputTag('ak4PuppiJets'), + algo = 'AK', rParam=0.4, + genJetCollection=cms.InputTag('slimmedGenJets'), + jetCorrections = ('AK4PFPuppi', ['L1FastJet', 'L2Relative', 'L3Absolute','L2L3Residual'], 'None'), + pfCandidates = cms.InputTag('packedPFCandidates'), + pvSource = cms.InputTag('offlineSlimmedPrimaryVertices'), + svSource = cms.InputTag('slimmedSecondaryVertices'), + muSource =cms.InputTag( 'slimmedMuons'), + elSource = cms.InputTag('slimmedElectrons'), + genParticles= cms.InputTag('prunedGenParticles'), + getJetMCFlavour=False + ) + + process.patJetsPuppi.addGenPartonMatch = cms.bool(False) + process.patJetsPuppi.addGenJetMatch = cms.bool(False) + process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) return process from PhysicsTools.SelectorUtils.tools.vid_id_tools import * @@ -208,25 +257,21 @@ def nanoAOD_activateVID(process): for modname in electron_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDElectronSelection) process.electronSequence.insert(process.electronSequence.index(process.bitmapVIDForEle),process.egmGsfElectronIDSequence) - for modifier in run2_miniAOD_80XLegacy, : + for modifier in run2_egamma_2017,run2_egamma_2018,run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: modifier.toModify(process.electronMVAValueMapProducer, src = "slimmedElectronsUpdated") modifier.toModify(process.egmGsfElectronIDs, physicsObjectSrc = "slimmedElectronsUpdated") - for modifier in run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016 ,run2_nanoAOD_102Xv1: - modifier.toModify(process.electronMVAValueMapProducer, src = "slimmedElectronsTo106X") - modifier.toModify(process.egmGsfElectronIDs, physicsObjectSrc = "slimmedElectronsTo106X") - - + switchOnVIDPhotonIdProducer(process,DataFormat.MiniAOD) # do not call this to avoid resetting photon IDs in VID, if called before inside makePuppiesFromMiniAOD for modname in photon_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDPhotonSelection) process.photonSequence.insert(process.photonSequence.index(bitmapVIDForPho),process.egmPhotonIDSequence) - for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016 ,run2_nanoAOD_102Xv1: + for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1: modifier.toModify(process.photonMVAValueMapProducer, src = "slimmedPhotonsTo106X") modifier.toModify(process.egmPhotonIDs, physicsObjectSrc = "slimmedPhotonsTo106X") return process -def nanoAOD_addDeepInfoAK8(process,addDeepBTag,addDeepBoostedJet, addDeepDoubleX, jecPayload): +def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubleX, addDeepDoubleXV2, addParticleNet, jecPayload): _btagDiscriminators=[] if addDeepBTag: print("Updating process to run DeepCSV btag to AK8 jets") @@ -235,12 +280,23 @@ def nanoAOD_addDeepInfoAK8(process,addDeepBTag,addDeepBoostedJet, addDeepDoubleX print("Updating process to run DeepBoostedJet on datasets before 103X") from RecoBTag.ONNXRuntime.pfDeepBoostedJet_cff import _pfDeepBoostedJetTagsAll as pfDeepBoostedJetTagsAll _btagDiscriminators += pfDeepBoostedJetTagsAll - if addDeepDoubleX: + if addParticleNet: + print("Updating process to run ParticleNet before it's included in MiniAOD") + from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetJetTagsAll as pfParticleNetJetTagsAll + _btagDiscriminators += pfParticleNetJetTagsAll + if addDeepDoubleX: print("Updating process to run DeepDoubleX on datasets before 104X") _btagDiscriminators += ['pfDeepDoubleBvLJetTags:probHbb', \ 'pfDeepDoubleCvLJetTags:probHcc', \ 'pfDeepDoubleCvBJetTags:probHcc', \ 'pfMassIndependentDeepDoubleBvLJetTags:probHbb', 'pfMassIndependentDeepDoubleCvLJetTags:probHcc', 'pfMassIndependentDeepDoubleCvBJetTags:probHcc'] + if addDeepDoubleXV2: + print("Updating process to run DeepDoubleXv2 on datasets before 11X") + _btagDiscriminators += [ + 'pfMassIndependentDeepDoubleBvLV2JetTags:probHbb', + 'pfMassIndependentDeepDoubleCvLV2JetTags:probHcc', + 'pfMassIndependentDeepDoubleCvBV2JetTags:probHcc' + ] if len(_btagDiscriminators)==0: return process print("Will recalculate the following discriminators on AK8 jets: "+", ".join(_btagDiscriminators)) updateJetCollection( @@ -267,7 +323,11 @@ def nanoAOD_runMETfixEE2017(process,isData): process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(jetSequence),process.fullPatMetSequenceFixEE2017) def nanoAOD_customizeCommon(process): -# makePuppiesFromMiniAOD(process,True) # call this here as it calls switchOnVIDPhotonIdProducer + makePuppiesFromMiniAOD(process,True) + process.puppiNoLep.useExistingWeights = True + process.puppi.useExistingWeights = True + run2_nanoAOD_106Xv1.toModify(process.puppiNoLep, useExistingWeights = False) + run2_nanoAOD_106Xv1.toModify(process.puppi, useExistingWeights = False) process = nanoAOD_activateVID(process) nanoAOD_addDeepInfo_switch = cms.PSet( nanoAOD_addDeepBTag_switch = cms.untracked.bool(False), @@ -281,20 +341,36 @@ def nanoAOD_customizeCommon(process): addDeepFlavour=nanoAOD_addDeepInfo_switch.nanoAOD_addDeepFlavourTag_switch) nanoAOD_addDeepInfoAK8_switch = cms.PSet( nanoAOD_addDeepBTag_switch = cms.untracked.bool(False), - nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(True), # will deactivate this in future miniAOD releases - nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(True), + nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(False), + nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(False), + nanoAOD_addDeepDoubleXV2_switch = cms.untracked.bool(False), + nanoAOD_addParticleNet_switch = cms.untracked.bool(False), jecPayload = cms.untracked.string('AK8PFPuppi') ) # deepAK8 should not run on 80X, that contains ak8PFJetsCHS jets run2_miniAOD_80XLegacy.toModify(nanoAOD_addDeepInfoAK8_switch, - nanoAOD_addDeepBTag_switch = cms.untracked.bool(True), - nanoAOD_addDeepBoostedJet_switch = cms.untracked.bool(False), - nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(False), - jecPayload = cms.untracked.string('AK8PFchs')) + nanoAOD_addDeepBTag_switch = True, + jecPayload = 'AK8PFchs') + # for 94X and 102X samples: needs to run DeepAK8, DeepDoubleX and ParticleNet + (run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1).toModify( + nanoAOD_addDeepInfoAK8_switch, + nanoAOD_addDeepBoostedJet_switch = True, + nanoAOD_addDeepDoubleX_switch = True, + nanoAOD_addDeepDoubleXV2_switch = True, + nanoAOD_addParticleNet_switch = True, + ) + # for 106Xv1: only needs to run ParticleNet and DDXV2; DeepAK8, DeepDoubleX are already in MiniAOD + run2_nanoAOD_106Xv1.toModify( + nanoAOD_addDeepInfoAK8_switch, + nanoAOD_addDeepDoubleXV2_switch = True, + nanoAOD_addParticleNet_switch = True, + ) process = nanoAOD_addDeepInfoAK8(process, addDeepBTag=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBTag_switch, addDeepBoostedJet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBoostedJet_switch, addDeepDoubleX=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleX_switch, + addDeepDoubleXV2=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleXV2_switch, + addParticleNet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addParticleNet_switch, jecPayload=nanoAOD_addDeepInfoAK8_switch.jecPayload) (run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1 | run2_nanoAOD_106Xv1).toModify(process, lambda p : nanoAOD_addTauIds(p)) return process @@ -315,7 +391,7 @@ def nanoAOD_customizeMC(process): ### Era dependent customization _80x_sequence = nanoSequenceCommon.copy() -#remove stuff +#remove stuff _80x_sequence.remove(isoTrackTables) _80x_sequence.remove(isoTrackSequence) #add stuff diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index 6e5a45c467f43..bcff05f2416c0 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -1,60 +1,20 @@ from PhysicsTools.NanoAOD.taus_cff import * from PhysicsTools.NanoAOD.jets_cff import * -from PhysicsTools.NanoAOD.globals_cff import * +from PhysicsTools.NanoAOD.globals_cff import genTable +from PhysicsTools.NanoAOD.met_cff import metMCTable from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * from PhysicsTools.NanoAOD.lheInfoTable_cfi import * -from PhysicsTools.NanoAOD.genWeightsTable_cfi import * -from PhysicsTools.NanoAOD.lheWeightsTable_cfi import * +from PhysicsTools.NanoAOD.genVertex_cff import * +from PhysicsTools.NanoAOD.common_cff import Var,CandVars -genWeights = cms.EDProducer("GenWeightProductProducer", - genInfo = cms.InputTag("generator"), - genLumiInfoHeader = cms.InputTag("generator")) - -lheWeights = cms.EDProducer("LHEWeightProductProducer", - lheSourceLabels = cms.vstring(["externalLHEProducer", "source"]), - failIfInvalidXML = cms.untracked.bool(True) - #lheWeightSourceLabels = cms.vstring(["externalLHEProducer", "source"]) -) -''' -lheWeightsTable = cms.EDProducer( - "LHEWeightsTableProducer", - lheWeights = cms.VInputTag(["externalLHEProducer", "source", "lheWeights"]), - lheWeightPrecision = cms.int32(14), - genWeights = cms.InputTag("genWeights"), - # Warning: you can use a full string, but only the first character is read. - # Note also that the capitalization is important! For example, 'parton shower' - # must be lower case and 'PDF' must be capital - weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), - # Max number of groups to store for each type above, -1 ==> store all found - maxGroupsPerType = cms.vint32([-1, -1, -1, -1, 1]), - # If empty or not specified, no critieria is applied to filter on LHAPDF IDs - #pdfIds = cms.untracked.vint32([91400, 306000, 260000]), - #unknownOnlyIfEmpty = cms.untracked.vstring(['scale', 'PDF']), - #unknownOnlyIfAllEmpty = cms.untracked.bool(False), -) -''' nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( tag = cms.string("untagged"), ) ) -metGenTable = cms.EDProducer("SimpleCandidateFlatTableProducer", - src = cms.InputTag("genMetTrue"), - name = cms.string("GenMET"), - doc = cms.string("Gen MET"), - singleton = cms.bool(True), - extension = cms.bool(False), - variables = cms.PSet( - pt = Var("pt", float, doc="pt", precision=10), - phi = Var("phi", float, doc="phi", precision=10), - ), -) - nanogenSequence = cms.Sequence( - genWeights+ - lheWeights+ nanoMetadata+ particleLevel+ genJetTable+ @@ -69,84 +29,137 @@ genVisTaus+ genVisTauTable+ genTable+ - genWeightsTable+ - lheWeightsTable+ genParticleTables+ + genVertexTables+ tautagger+ rivetProducerHTXS+ particleLevelTables+ - metGenTable+ + metMCTable+ + genWeightsTables+ lheInfoTable ) -nanogenMiniSequence = cms.Sequence( - genWeights+ - lheWeights+ - nanoMetadata+ - mergedGenParticles+ - genParticles2HepMC+ - particleLevel+ - genJetTable+ - patJetPartons+ - genJetFlavourAssociation+ - genJetFlavourTable+ - genJetAK8Table+ - genJetAK8FlavourAssociation+ - genJetAK8FlavourTable+ - tauGenJets+ - tauGenJetsSelectorAllHadrons+ - genVisTaus+ - genVisTauTable+ - genTable+ - genWeightsTable+ - lheWeightsTable+ - genParticleTables+ - tautagger+ - genParticles2HepMCHiggsVtx+ - rivetProducerHTXS+ - particleLevelTables+ - metGenTable+ - lheInfoTable -) +def nanoGenCommonCustomize(process): + process.rivetMetTable.extension = False + process.lheInfoTable.storeLHEParticles = True + process.lheInfoTable.storeAllLHEInfo = True + process.lheInfoTable.precision = 14 + process.genWeightsTable.keepAllPSWeights = True + process.genJetFlavourAssociation.jets = process.genJetTable.src + process.genJetFlavourTable.src = process.genJetTable.src + process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src + process.genJetAK8FlavourTable.src = process.genJetAK8Table.src + process.particleLevel.particleMaxEta = 999. + process.particleLevel.lepMinPt = 0. + process.particleLevel.lepMaxEta = 999. + process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" + # Same as default RECO + setGenPtPrecision(process, CandVars.pt.precision) + setGenEtaPrecision(process, CandVars.eta.precision) + setGenPhiPrecision(process, CandVars.phi.precision) def customizeNanoGENFromMini(process): - # Why is this false by default?! - process.lheInfoTable.storeLHEParticles = True + process.nanogenSequence.insert(0, process.genParticles2HepMCHiggsVtx) + process.nanogenSequence.insert(0, process.genParticles2HepMC) + process.nanogenSequence.insert(0, process.mergedGenParticles) + + from Configuration.Eras.Modifier_run2_miniAOD_80XLegacy_cff import run2_miniAOD_80XLegacy + from Configuration.Eras.Modifier_run2_nanoAOD_94X2016_cff import run2_nanoAOD_94X2016 + from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv1_cff import run2_nanoAOD_94XMiniAODv1 + from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv2_cff import run2_nanoAOD_94XMiniAODv2 + from Configuration.Eras.Modifier_run2_nanoAOD_102Xv1_cff import run2_nanoAOD_102Xv1 + from Configuration.Eras.Modifier_run2_nanoAOD_92X_cff import run2_nanoAOD_92X + + (run2_nanoAOD_92X | run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94X2016 | \ + run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | \ + run2_nanoAOD_102Xv1).toReplaceWith(nanogenSequence, nanogenSequence.copyAndExclude([genVertexTable, genVertexT0Table])) + + process.metMCTable.src = "slimmedMETs" + process.metMCTable.variables.pt = Var("genMET.pt", float, doc="pt") + process.metMCTable.variables.phi = Var("genMET.phi", float, doc="phi") + process.metMCTable.variables.phi.precision = CandVars.phi.precision + + process.rivetProducerHTXS.HepMCCollection = "genParticles2HepMCHiggsVtx:unsmeared" process.genParticleTable.src = "prunedGenParticles" process.patJetPartons.particles = "prunedGenParticles" process.particleLevel.src = "genParticles2HepMC:unsmeared" - process.rivetProducerHTXS.HepMCCollection = "genParticles2HepMCHiggsVtx:unsmeared" process.genJetTable.src = "slimmedGenJets" - process.genJetFlavourAssociation.jets = process.genJetTable.src - process.genJetFlavourTable.src = process.genJetTable.src - process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" process.genJetAK8Table.src = "slimmedGenJetsAK8" - process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src - process.genJetAK8FlavourTable.src = process.genJetAK8Table.src process.tauGenJets.GenParticles = "prunedGenParticles" process.genVisTaus.srcGenParticles = "prunedGenParticles" + nanoGenCommonCustomize(process) + return process def customizeNanoGEN(process): - process.lheInfoTable.storeLHEParticles = True + process.metMCTable.src = "genMetTrue" + process.metMCTable.variables = cms.PSet(PTVars) + + process.rivetProducerHTXS.HepMCCollection = "generatorSmeared" process.genParticleTable.src = "genParticles" process.patJetPartons.particles = "genParticles" process.particleLevel.src = "generatorSmeared" - process.particleLevel.particleMaxEta = 999. - process.particleLevel.lepMinPt = 0. - process.particleLevel.lepMaxEta = 999. - process.rivetProducerHTXS.HepMCCollection = "generatorSmeared" process.genJetTable.src = "ak4GenJets" - process.genJetFlavourAssociation.jets = process.genJetTable.src - process.genJetFlavourTable.src = process.genJetTable.src - process.genJetFlavourTable.jetFlavourInfos = "genJetFlavourAssociation" process.genJetAK8Table.src = "ak8GenJets" - process.genJetAK8FlavourAssociation.jets = process.genJetAK8Table.src - process.genJetAK8FlavourTable.src = process.genJetAK8Table.src process.tauGenJets.GenParticles = "genParticles" process.genVisTaus.srcGenParticles = "genParticles" + # In case customizeNanoGENFromMini has already been called + process.nanogenSequence.remove(process.genParticles2HepMCHiggsVtx) + process.nanogenSequence.remove(process.genParticles2HepMC) + process.nanogenSequence.remove(process.mergedGenParticles) + nanoGenCommonCustomize(process) + return process + +# Prune gen particles with tight conditions applied in usual NanoAOD +def pruneGenParticlesNano(process): + process.finalGenParticles = finalGenParticles.clone() + process.genParticleTable.src = "prunedGenParticles" + process.patJetPartons.particles = "prunedGenParticles" + process.nanogenSequence.insert(0, process.finalGenParticles) + return process + +# Prune gen particles with conditions applied in usual MiniAOD +def pruneGenParticlesMini(process): + if process.nanogenSequence.contains(process.mergedGenParticles): + raise ValueError("Applying the MiniAOD genParticle pruner to MiniAOD is redunant. " \ + "Use a different customization.") + from PhysicsTools.PatAlgos.slimming.prunedGenParticles_cfi import prunedGenParticles + process.prunedGenParticles = prunedGenParticles.clone() + process.genParticleTable.src = "prunedGenParticles" + process.patJetPartons.particles = "prunedGenParticles" + process.nanogenSequence.insert(0, process.prunedGenParticles) + return process + +def setGenFullPrecision(process): + setGenPtPrecision(process, 23) + setGenEtaPrecision(process, 23) + setGenPhiPrecision(process, 23) + +def setGenPtPrecision(process, precision): + process.genParticleTable.variables.pt.precision = precision + process.genJetTable.variables.pt.precision = precision + process.metMCTable.variables.pt.precision = precision + return process + +def setGenEtaPrecision(process, precision): + process.genParticleTable.variables.eta.precision = precision + process.genJetTable.variables.eta.precision = precision + return process + +def setGenPhiPrecision(process, precision): + process.genParticleTable.variables.phi.precision = precision + process.genJetTable.variables.phi.precision = precision + process.metMCTable.variables.phi.precision = precision + return process + +def setLHEFullPrecision(process): + process.lheInfoTable.precision = 23 + return process + +def setGenWeightsFullPrecision(process): + process.genWeightsTable.lheWeightPrecision = 23 return process diff --git a/PhysicsTools/NanoAOD/test/testNanoWeights.py b/PhysicsTools/NanoAOD/test/testNanoWeights.py index 54d17f85ac41c..2f288b8629c91 100644 --- a/PhysicsTools/NanoAOD/test/testNanoWeights.py +++ b/PhysicsTools/NanoAOD/test/testNanoWeights.py @@ -14,21 +14,16 @@ def variableAndNumber(varName, tree): parser = argparse.ArgumentParser() parser.add_argument('inputFile', type=str, help='NanoAOD file to process') +parser.add_argument('--scan', action='store_true', help='Scan the weight values') args = parser.parse_args() rtfile = ROOT.TFile(args.inputFile) tree = rtfile.Get("Events") tree.GetEntry(0) -types = ["ScaleWeight", "PdfWeight", "MEParamWeight", "UnknownWeight", ] -variables = ["LHE"+t for t in types] -variables.append("GenPartonShowerWeight") -variables.extend(["Gen"+t for t in types]) +variables = ["LHEScaleWeight", "LHEPdfWeight", "MEParamWeight", "UnknownWeight", "PSWeight", ] for varName in variables: variableAndNumber(varName, tree) - i = 1 - altName = varName + "AltSet%i" % i - while hasattr(tree, altName): - variableAndNumber(altName, tree) - i = i+1 - altName = varName + "AltSet%i" % i + +if args.scan: + tree.Scan(":".join(variables)) diff --git a/SimDataFormats/GeneratorProducts/BuildFile.xml b/SimDataFormats/GeneratorProducts/BuildFile.xml index 2e9a7977ec404..b35e098a0995a 100644 --- a/SimDataFormats/GeneratorProducts/BuildFile.xml +++ b/SimDataFormats/GeneratorProducts/BuildFile.xml @@ -3,8 +3,8 @@ - + diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index e0db5a539f86b..cdccd169797c9 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -16,12 +16,12 @@ namespace gen { struct WeightGroupData { size_t index; - std::unique_ptr group; + std::unique_ptr group; }; struct SharedWeightGroupData { size_t index; - std::shared_ptr group; + std::shared_ptr group; }; } // namespace gen @@ -36,9 +36,9 @@ class GenWeightInfoProduct { GenWeightInfoProduct& operator=(GenWeightInfoProduct&& other); const edm::OwnVector& allWeightGroupsInfo() const; - const std::unique_ptr containingWeightGroupInfo(int index) const; - const std::unique_ptr orderedWeightGroupInfo(int index) const; - std::vector> weightGroupsByType(gen::WeightType type) const; + std::unique_ptr containingWeightGroupInfo(int index) const; + std::unique_ptr orderedWeightGroupInfo(int index) const; + std::vector weightGroupsByType(gen::WeightType type) const; std::vector weightGroupIndicesByType(gen::WeightType type) const; std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h index 872ae29b65d9f..0110600384e6c 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -31,10 +31,10 @@ class GenWeightProduct { void setNumWeightSets(int num) { weightsVector_.resize(num); } void addWeightSet() { weightsVector_.push_back({}); } void addWeight(double weight, int setEntry, int weightNum) { - if (weightsVector_.size() == 0 && setEntry == 0) + if (weightsVector_.empty() && setEntry == 0) addWeightSet(); if (static_cast(weightsVector_.size()) <= setEntry) - throw std::domain_error("Out of range weight"); + throw cms::Exception("GenWeightProduct") << "Trying to add weight index outside the range of weights expected"; auto& weights = weightsVector_.at(setEntry); if (static_cast(weights.size()) <= weightNum) { weights.resize(weightNum + 1); diff --git a/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h index 2ea53a8d32adb..2b6714b240542 100644 --- a/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h @@ -12,9 +12,9 @@ namespace gen { weightType_ = WeightType::kMEParamWeights; } MEParamWeightGroupInfo(std::string header) : MEParamWeightGroupInfo(header, header) {} - virtual ~MEParamWeightGroupInfo() override {} + ~MEParamWeightGroupInfo() override {} void copy(const MEParamWeightGroupInfo& other); - virtual MEParamWeightGroupInfo* clone() const override; + MEParamWeightGroupInfo* clone() const override; int getCentralIndex() { return centralIdx; } int getVariationIndex(int sig) { return massValue.at(numSigma + sig).second; } double getVariationValue(int sig) { return massValue.at(numSigma + sig).first; } diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index 9c64d5ce849e2..feb8face8658b 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -1,32 +1,58 @@ #ifndef SimDataFormats_GeneratorProducts_PartonShowerWeightGroupInfo_h #define SimDataFormats_GeneratorProducts_PartonShowerWeightGroupInfo_h -#include - #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" namespace gen { - enum class PSVarType { muR, cNS, con, def, red, alphaS}; - enum class PSSplittingType { combined, g2gg, x2xg, g2qq }; + enum class PSVarType { muR, cNS, con, def, red, alphaS, LAST }; + enum class PSSplittingType { combined, g2gg, x2xg, g2qq, q2qg }; class PartonShowerWeightGroupInfo : public WeightGroupInfo { public: PartonShowerWeightGroupInfo() : PartonShowerWeightGroupInfo("") {} - PartonShowerWeightGroupInfo(std::string header, std::string name) : WeightGroupInfo(header, name) { - weightType_ = WeightType::kPartonShowerWeights; - } + PartonShowerWeightGroupInfo(std::string header, std::string name); PartonShowerWeightGroupInfo(std::string header) : PartonShowerWeightGroupInfo(header, header) {} PartonShowerWeightGroupInfo(const PartonShowerWeightGroupInfo &other) { copy(other); } - virtual ~PartonShowerWeightGroupInfo() override {} + ~PartonShowerWeightGroupInfo() override {} void copy(const PartonShowerWeightGroupInfo &other); - virtual PartonShowerWeightGroupInfo *clone() const override; + PartonShowerWeightGroupInfo *clone() const override; void setNameIsPythiaSyntax(bool isPythiaSyntax) { nameIsPythiaSyntax_ = isPythiaSyntax; } - bool nameIsPythiaSyntax(bool isPythiaSyntax) const { return nameIsPythiaSyntax_; } + bool nameIsPythiaSyntax() const { return nameIsPythiaSyntax_; } int variationIndex(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; + std::string variationName(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; int variationIndex(bool isISR, bool isUp, PSVarType variationType) const; + static void setGuessPSWeightIdx(bool guessPSWeightIdx) { guessPSWeightIdx_ = guessPSWeightIdx; } + int psWeightIdxGuess(const std::string &varName) const; + void printVariables() const; private: bool nameIsPythiaSyntax_ = false; + static inline bool guessPSWeightIdx_ = false; + + const std::vector expectedOrderPythiaSyntax_ = { + "fsr:murfac=0.707", "fsr:murfac=1.414", "fsr:murfac=0.5", "fsr:murfac=2.0", + "fsr:murfac=0.25", "fsr:murfac=4.0", "fsr:g2gg:murfac=0.5", "fsr:g2gg:murfac=2.0", + "fsr:g2qq:murfac=0.5", "fsr:g2qq:murfac=2.0", "fsr:q2qg:murfac=0.5", "fsr:q2qg:murfac=2.0", + "fsr:x2xg:murfac=0.5", "fsr:x2xg:murfac=2.0", "fsr:g2gg:cns=-2.0", "fsr:g2gg:cns=2.0", + "fsr:g2qq:cns=-2.0", "fsr:g2qq:cns=2.0", "fsr:q2qg:cns=-2.0", "fsr:q2qg:cns=2.0", + "fsr:x2xg:cns=-2.0", "fsr:x2xg:cns=2.0", "isr:murfac=0.707", "isr:murfac=1.414", + "isr:murfac=0.5", "isr:murfac=2.0", "isr:murfac=0.25", "isr:murfac=4.0", + "isr:g2gg:murfac=0.5", "isr:g2gg:murfac=2.0", "isr:g2qq:murfac=0.5", "isr:g2qq:murfac=2.0", + "isr:q2qg:murfac=0.5", "isr:q2qg:murfac=2.0", "isr:x2xg:murfac=0.5", "isr:x2xg:murfac=2.0", + "isr:g2gg:cns=-2.0", "isr:g2gg:cns=2.0", "isr:g2qq:cns=-2.0", "isr:g2qq:cns=2.0", + "isr:q2qg:cns=-2.0", "isr:q2qg:cns=2.0", "isr:x2xg:cns=-2.0", "isr:x2xg:cns=2.0", + }; + const std::vector expectedOrder_ = { + "isrRedHi", "fsrRedHi", "isrRedLo", "fsrRedLo", "isrDefHi", + "fsrDefHi", "isrDefLo", "fsrDefLo", "isrConHi", "fsrConHi", + "isrConLo", "fsrConLo", "fsr_G2GG_muR_dn", "fsr_G2GG_muR_up", "fsr_G2QQ_muR_dn", + "fsr_G2QQ_muR_up", "fsr_Q2QG_muR_dn", "fsr_Q2QG_muR_up", "fsr_X2XG_muR_dn", "fsr_X2XG_muR_up", + "fsr_G2GG_cNS_dn", "fsr_G2GG_cNS_up", "fsr_G2QQ_cNS_dn", "fsr_G2QQ_cNS_up", "fsr_Q2QG_cNS_dn", + "fsr_Q2QG_cNS_up", "fsr_X2XG_cNS_dn", "fsr_X2XG_cNS_up", "isr_G2GG_muR_dn", "isr_G2GG_muR_up", + "isr_G2QQ_muR_dn", "isr_G2QQ_muR_up", "isr_Q2QG_muR_dn", "isr_Q2QG_muR_up", "isr_X2XG_muR_dn", + "isr_X2XG_muR_up", "isr_G2GG_cNS_dn", "isr_G2GG_cNS_up", "isr_G2QQ_cNS_dn", "isr_G2QQ_cNS_up", + "isr_Q2QG_cNS_dn", "isr_Q2QG_cNS_up", "isr_X2XG_cNS_dn", "isr_X2XG_cNS_up", + }; }; } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h index f04fb71ffa728..5c8214fa9eb35 100644 --- a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h @@ -34,9 +34,9 @@ namespace gen { } PdfWeightGroupInfo(std::string header) : WeightGroupInfo(header) { weightType_ = WeightType::kPdfWeights; } PdfWeightGroupInfo(const PdfWeightGroupInfo& other) { copy(other); } - virtual ~PdfWeightGroupInfo() override {} + ~PdfWeightGroupInfo() override {} void copy(const PdfWeightGroupInfo& other); - virtual PdfWeightGroupInfo* clone() const override; + PdfWeightGroupInfo* clone() const override; void setUncertaintyType(PdfUncertaintyType uncertaintyType) { uncertaintyType_ = uncertaintyType; } void setHasAlphasVariations(bool hasAlphasVars) { hasAlphasVars_ = hasAlphasVars; } diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index c57119487f115..7bb460f57d210 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -12,7 +12,7 @@ namespace gen { std::vector muIndices_; bool containsCentral_ = false; int lhaid_ = -1; - bool hasAllWeights = false; + bool weightIsCorrupt_ = false; // Dyn_scale std::vector dynNames_; std::vector> dynVec_; @@ -39,16 +39,18 @@ namespace gen { : WeightGroupInfo(header, name), muIndices_(MIN_SCALE_VARIATIONS, -1), dynVec_(MIN_SCALE_VARIATIONS) { weightType_ = WeightType::kScaleWeights; isFunctionalFormVar_ = false; - isWellFormed_ = true; } ScaleWeightGroupInfo(std::string header) : ScaleWeightGroupInfo(header, header) {} ScaleWeightGroupInfo(const ScaleWeightGroupInfo& other) { copy(other); } - virtual ~ScaleWeightGroupInfo() override {} + ~ScaleWeightGroupInfo() override {} void copy(const ScaleWeightGroupInfo& other); - virtual ScaleWeightGroupInfo* clone() const override; + ScaleWeightGroupInfo* clone() const override; bool containsCentralWeight() const { return containsCentral_; } void addContainedId(int globalIndex, std::string id, std::string label, float muR, float muF); - bool isWellFormed() { return isWellFormed_ && hasAllWeights; } + void setWeightIsCorrupt() { + isWellFormed_ = false; + weightIsCorrupt_ = true; + } void setMuRMuFIndex(int globalIndex, std::string id, float muR, float muF); void setDyn(int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName); diff --git a/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h index d314b9ad40d8a..3513cc70841dc 100644 --- a/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h @@ -15,9 +15,9 @@ namespace gen { weightType_ = WeightType::kUnknownWeights; isWellFormed_ = false; } - virtual ~UnknownWeightGroupInfo() override {} + ~UnknownWeightGroupInfo() override {} void copy(const UnknownWeightGroupInfo& other); - virtual UnknownWeightGroupInfo* clone() const override; + UnknownWeightGroupInfo* clone() const override; }; } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index d53aa6e90c509..e9058546d584c 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -88,7 +88,7 @@ namespace gen { std::vector weightLabels() const; protected: - bool isWellFormed_; + bool isWellFormed_ = false; std::string headerEntry_; std::string name_; std::string description_; diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 23b63469354f2..f54ced13fc6d7 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -3,6 +3,7 @@ #include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" +#include "FWCore/Utilities/interface/Exception.h" GenWeightInfoProduct::GenWeightInfoProduct(edm::OwnVector& weightGroups) { weightGroupsInfo_ = weightGroups; @@ -22,34 +23,37 @@ const edm::OwnVector& GenWeightInfoProduct::allWeightGroup return weightGroupsInfo_; } -const std::unique_ptr GenWeightInfoProduct::containingWeightGroupInfo(int index) const { +std::unique_ptr GenWeightInfoProduct::containingWeightGroupInfo(int index) const { for (const auto& weightGroup : weightGroupsInfo_) { if (weightGroup.indexInRange(index)) - return std::make_unique(weightGroup); + return std::unique_ptr(weightGroup.clone()); } - throw std::domain_error("Failed to find containing weight group"); + throw cms::Exception("GenWeightInfoProduct") << "No weight group found containing the weight index requested"; } -const std::unique_ptr GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { +std::unique_ptr GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) - throw std::range_error("Weight index out of range!"); - return std::make_unique(weightGroupsInfo_[weightGroupIndex]); + throw cms::Exception("GenWeightInfoProduct") + << "Weight index requested is outside the range of weights in the product"; + return std::unique_ptr(weightGroupsInfo_[weightGroupIndex].clone()); } std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type) const { std::vector matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + const gen::WeightGroupInfo& group = weightGroupsInfo_[i]; if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back({i, std::make_unique(weightGroupsInfo_[i])}); + matchingGroups.push_back({i, std::unique_ptr(group.clone())}); } return matchingGroups; } -std::vector> GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { - std::vector> matchingGroups; +std::vector GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { + std::vector matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + const gen::WeightGroupInfo& group = weightGroupsInfo_[i]; if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back(std::make_unique(weightGroupsInfo_[i])); + matchingGroups.push_back({i, std::unique_ptr(group.clone())}); } return matchingGroups; } @@ -58,12 +62,14 @@ std::optional GenWeightInfoProduct::pdfGroupWithIndexByLHA std::vector pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = std::make_unique(*static_cast(data.group.release())); + auto pdfGroup = std::unique_ptr( + static_cast(data.group.release())); return pdfGroup->containsLhapdfId(lhaid); }); - return matchingPdfSet == pdfGroups.end() ? std::nullopt : - std::optional({matchingPdfSet->index, std::move(matchingPdfSet->group)}); + return matchingPdfSet == pdfGroups.end() + ? std::nullopt + : std::optional({matchingPdfSet->index, std::move(matchingPdfSet->group)}); } std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLHAIDs( @@ -73,7 +79,8 @@ std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLH for (auto lhaid : lhaids) { auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = std::make_unique(*static_cast(data.group.release())); + auto pdfGroup = std::unique_ptr( + static_cast(data.group.release())); return pdfGroup->containsLhapdfId(lhaid); }); if (matchingPdfSet != pdfGroups.end()) { @@ -93,4 +100,6 @@ std::vector GenWeightInfoProduct::weightGroupIndicesByType(gen::WeightType return matchingGroupIndices; } -void GenWeightInfoProduct::addWeightGroupInfo(std::unique_ptr info) { weightGroupsInfo_.push_back(std::move(info)); } +void GenWeightInfoProduct::addWeightGroupInfo(std::unique_ptr info) { + weightGroupsInfo_.push_back(std::move(info)); +} diff --git a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc index f2ebb9c1150c8..eba4d4571ce26 100644 --- a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc @@ -1,7 +1,13 @@ #include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" +#include +#include namespace gen { - void PartonShowerWeightGroupInfo::copy(const PartonShowerWeightGroupInfo& other) { WeightGroupInfo::copy(other); } + PartonShowerWeightGroupInfo::PartonShowerWeightGroupInfo(std::string header, std::string name) + : WeightGroupInfo(header, name) { + weightType_ = WeightType::kPartonShowerWeights; + } + void PartonShowerWeightGroupInfo::copy(const PartonShowerWeightGroupInfo& other) { WeightGroupInfo::copy(other); nameIsPythiaSyntax_ = other.nameIsPythiaSyntax_; @@ -19,64 +25,97 @@ namespace gen { bool isUp, PSVarType variationType, PSSplittingType splittingType) const { - std::string label = isISR ? "isr" : "fsr"; - - if ((variationType == PSVarType::con || variationType == PSVarType::def || variationType == PSVarType::red) && - splittingType != PSSplittingType::combined) - throw std::invalid_argument("VariationType must be muR or CNS if subprocess is specified"); + std::string varName = variationName(isISR, isUp, variationType, splittingType); + int wgtIdx = weightIndexFromLabel(varName); + // Guess PS idx if not in label list + if (wgtIdx == -1 && guessPSWeightIdx_) + wgtIdx = psWeightIdxGuess(varName); + return wgtIdx; + } - std::string variation; - switch (variationType) { - case PSVarType::con: - variation = !nameIsPythiaSyntax_ ? "Con" : (isUp ? "murfac=4.0" : "murfac=0.25"); - break; - case PSVarType::def: - variation = !nameIsPythiaSyntax_ ? "Def" : (isUp ? "murfac=2.0" : "murfac=0.5"); - break; - case PSVarType::red: - variation = !nameIsPythiaSyntax_ ? "Red" : (isUp ? "murfac=1.414" : "murfac=0.707"); - case PSVarType::muR: - variation = !nameIsPythiaSyntax_ ? "muR" : (isUp ? "murfac=2.0" : "murfac=0.5"); - break; - case PSVarType::cNS: - variation = !nameIsPythiaSyntax_ ? "cNS" : (isUp ? "cns=2.0" : "murfac=-2.0"); - break; - case PSVarType::alphaS: - variation = (isUp ? "alpsfact=2.0" : "alpsfact=0.5"); - return weightIndexFromLabel(variation); - } + std::string PartonShowerWeightGroupInfo::variationName(bool isISR, + bool isUp, + PSVarType variationType, + PSSplittingType splittingType) const { + std::string label = isISR ? "isr" : "fsr"; - std::string splitting; - switch (splittingType) { - case PSSplittingType::g2gg: - splitting = !nameIsPythiaSyntax_ ? "G2GG" : "g2gg"; - break; - case PSSplittingType::g2qq: - splitting = !nameIsPythiaSyntax_ ? "G2QQ" : "g2qq"; - break; - case PSSplittingType::x2xg: - splitting = !nameIsPythiaSyntax_ ? "X2XG" : "x2xg"; - break; - default: - break; - } + // if ((variationType == PSVarType::con || variationType == PSVarType::def || variationType == PSVarType::red) && + // splittingType != PSSplittingType::combined) + // throw std::invalid_argument("VariationType must be muR or CNS if subprocess is specified"); if (nameIsPythiaSyntax_) { - std::string app = splittingType != PSSplittingType::combined ? splitting + ":" + variation : variation; - label += ":" + app; + // Splitting + if (splittingType == PSSplittingType::g2gg) + label += ":g2gg"; + else if (splittingType == PSSplittingType::g2qq) + label += ":g2qq"; + else if (splittingType == PSSplittingType::x2xg) + label += ":x2xg"; + else if (splittingType == PSSplittingType::q2qg) + label += ":q2qg"; + // type + if (variationType == PSVarType::con) + label += isUp ? ":murfac=4.0" : ":murfac=0.25"; + else if (variationType == PSVarType::def || variationType == PSVarType::muR) + label += isUp ? ":murfac=2.0" : ":murfac=0.5"; + else if (variationType == PSVarType::red) + label += isUp ? ":murfac=1.414" : ":murfac=0.707"; + else if (variationType == PSVarType::cNS) + label += isUp ? ":cns=2.0" : ":cns=-2.0"; } else { + // Splitting + if (splittingType == PSSplittingType::g2gg) + label += "_G2GG_"; + else if (splittingType == PSSplittingType::g2qq) + label += "_G2QQ_"; + else if (splittingType == PSSplittingType::x2xg) + label += "_X2XG_"; + else if (splittingType == PSSplittingType::q2qg) + label += "_Q2QG_"; + // type + if (variationType == PSVarType::con) + label += "Con"; + else if (variationType == PSVarType::def) + label += "Def"; + else if (variationType == PSVarType::muR) + label += "muR"; + else if (variationType == PSVarType::red) + label += "Red"; + else if (variationType == PSVarType::cNS) + label += "cNS"; + // Up/Down if (splittingType != PSSplittingType::combined) { - label += variation + "_" + splitting + "_" + variation + (isUp ? "_up" : "_dn"); + label += isUp ? "_up" : "_dn"; } else - label += variation + (isUp ? "Hi" : "Lo"); + label += isUp ? "Hi" : "Lo"; } - if (isUp) - weightNameToUpDown[subName].first = localIndex; - else - weightNameToUpDown[subName].second = localIndex; + return label; } - return weightIndexFromLabel(label); + int PartonShowerWeightGroupInfo::psWeightIdxGuess(const std::string& varName) const { + int wgtIdx; + if (nameIsPythiaSyntax_) { + auto wgtIter = std::find(expectedOrderPythiaSyntax_.begin(), expectedOrderPythiaSyntax_.end(), varName); + wgtIdx = wgtIter - expectedOrderPythiaSyntax_.begin() + 2; + } else { + auto wgtIter = std::find(expectedOrder_.begin(), expectedOrder_.end(), varName); + wgtIdx = wgtIter - expectedOrder_.begin() + 2; + } + if (wgtIdx >= (int)containedIds().size()) + wgtIdx = -1; + return wgtIdx; + } + + void PartonShowerWeightGroupInfo::printVariables() const { + const auto& variations = (nameIsPythiaSyntax_) ? expectedOrderPythiaSyntax_ : expectedOrder_; + for (auto varName: variations) { + int wgtIdx = weightIndexFromLabel(varName); + // Guess PS idx if not in label list + if (wgtIdx == -1 && guessPSWeightIdx_) + wgtIdx = psWeightIdxGuess(varName); + if (wgtIdx != -1) + std::cout << varName << " : " << wgtIdx << std::endl; + } } } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc index 99826e88d14b9..955b4f5c8e260 100644 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -26,18 +26,13 @@ namespace gen { } WeightGroupInfo::addContainedId(globalIndex, id, label); setMuRMuFIndex(globalIndex, id, muR, muF); - std::cout << hasAllWeights << " " << isWellFormed_ << std::endl; - for (int muidx : muIndices_) { - std::cout << muidx << " "; - } - std::cout << std::endl; } void ScaleWeightGroupInfo::setMuRMuFIndex(int globalIndex, std::string id, float muR, float muF) { auto info = weightMetaInfoByGlobalIndex(id, globalIndex); int index = indexFromMus(muR, muF); if (!(isValidValue(muR) && isValidValue(muF))) { - isWellFormed_ = false; + setWeightIsCorrupt(); return; } if (index == Central_idx) @@ -48,7 +43,7 @@ namespace gen { if (muidx == -1) return; } - hasAllWeights = true; + isWellFormed_ = !weightIsCorrupt_; } void ScaleWeightGroupInfo::setDyn( @@ -99,7 +94,7 @@ namespace gen { std::vector ScaleWeightGroupInfo::dynNames() const { std::vector returnVec; - for (auto item : dynNames_) { + for (const auto& item : dynNames_) { if (!item.empty()) returnVec.push_back(item); } diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index 8e199219435ac..90ad7c284aca5 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -18,18 +18,20 @@ namespace gen { } WeightGroupInfo* WeightGroupInfo::clone() const { - throw cms::Exception("LogicError", "WeightGroupInfo is abstract, so it's clone() method can't be implemented.\n"); + throw cms::Exception("WeightGroupInfo") + << "WeightGroupInfo is abstract, so it's clone() method can't be implemented."; } WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) const { return idsContained_.at(weightEntry); } WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string wgtId, int weightEntry) const { - if (wgtId.empty()) - wgtId = std::to_string(weightEntry); + if (wgtId.empty()) + wgtId = std::to_string(weightEntry); int entry = weightVectorEntry(wgtId, weightEntry); if (entry < 0 || entry >= static_cast(idsContained_.size())) - throw std::range_error("Weight entry " + std::to_string(weightEntry) + " is not a member of group " + name_ + - ". \n firstID = " + std::to_string(firstId_) + " lastId = " + std::to_string(lastId_)); + throw cms::Exception("WeightGroupInfo") + << "Weight entry " << std::to_string(weightEntry) << " is not a member of group " << name_ + << ". \n firstID = " << std::to_string(firstId_) << " lastId = " << std::to_string(lastId_); return idsContained_.at(entry); } @@ -60,8 +62,8 @@ namespace gen { } void WeightGroupInfo::addContainedId(int weightEntry, std::string id, std::string label = "") { - if (id.empty()) - id = std::to_string(weightEntry); + if (id.empty()) + id = std::to_string(weightEntry); if (firstId_ == -1 || weightEntry < firstId_) { firstId_ = weightEntry; @@ -75,9 +77,9 @@ namespace gen { WeightMetaInfo info = {static_cast(weightEntry), localIndex, id, label}; // logic to insert for all cases e.g. inserting in the middle of the vector if (localIndex == idsContained_.size()) - idsContained_.emplace_back(info); + idsContained_.emplace_back(info); else - idsContained_.insert(idsContained_.begin() + localIndex, info); + idsContained_.insert(idsContained_.begin() + localIndex, info); } std::vector WeightGroupInfo::containedIds() const { return idsContained_; } @@ -85,8 +87,8 @@ namespace gen { bool WeightGroupInfo::indexInRange(int index) const { return (index <= lastId_ && index >= firstId_); } void WeightGroupInfo::cacheWeightIndicesByLabel() { - for (const auto& weight : idsContained_) - weightLabelsToIndices_[weight.label] = weight.localIndex; + for (const auto& weight : idsContained_) + weightLabelsToIndices_[weight.label] = weight.localIndex; } std::vector WeightGroupInfo::weightLabels() const { @@ -98,17 +100,17 @@ namespace gen { } int WeightGroupInfo::weightIndexFromLabel(std::string weightLabel) const { - if (!weightLabelsToIndices_.empty()) { - if (weightLabelsToIndices_.find(weightLabel) != weightLabelsToIndices_.end()) - return static_cast(weightLabelsToIndices_.at(weightLabel)); - return -1; - } - - auto it = std::find_if(idsContained_.begin(), idsContained_.end(), - [weightLabel](const auto& w) { return weightLabel == w.label; }); - if (it == idsContained_.end()) - return -1; - return std::distance(idsContained_.begin(), it); + if (!weightLabelsToIndices_.empty()) { + if (weightLabelsToIndices_.find(weightLabel) != weightLabelsToIndices_.end()) + return static_cast(weightLabelsToIndices_.at(weightLabel)); + return -1; + } + + auto it = std::find_if( + idsContained_.begin(), idsContained_.end(), [weightLabel](const auto& w) { return weightLabel == w.label; }); + if (it == idsContained_.end()) + return -1; + return std::distance(idsContained_.begin(), it); } } // namespace gen From 4fc34fd2c2acfa96ccccddff13aaf691093e5187 Mon Sep 17 00:00:00 2001 From: Sanghyun Ko Date: Fri, 20 Nov 2020 13:43:28 +0100 Subject: [PATCH 08/16] attempt to delete extra kets after the last fix runtime error failIfInvalidXML_ cleanup failIfInvalidXML_ cleanup (2) scram b code-format --- .../Core/interface/LHEWeightHelper.h | 7 ++ .../Core/src/LHEWeightHelper.cc | 76 +++++++++++++------ PhysicsTools/NanoAOD/python/nanogen_cff.py | 1 + 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index 80bd3cf14af19..0418823095f2e 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -20,6 +20,9 @@ namespace gen { class LHEWeightHelper : public WeightHelper { public: LHEWeightHelper() : WeightHelper(){}; + + enum ErrorType { SWAPHEADER, HTMLSTYLE, TRAILINGSTR, UNKNOWN }; + void setHeaderLines(std::vector headerLines); void parseWeights(); bool isConsistent(); @@ -28,10 +31,14 @@ namespace gen { private: std::vector headerLines_; + std::string weightgroupKet_ = ""; bool failIfInvalidXML_ = false; std::string parseGroupName(tinyxml2::XMLElement* el); void addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex); bool parseLHE(tinyxml2::XMLDocument& xmlDoc); + tinyxml2::XMLError tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); + tinyxml2::XMLError tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); + ErrorType findErrorType(std::string& fullHeader); }; } // namespace gen diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 4be51105c9cec..290b8fd77f268 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -12,34 +12,36 @@ namespace gen { bool LHEWeightHelper::parseLHE(tinyxml2::XMLDocument& xmlDoc) { parsedWeights_.clear(); - if (!isConsistent() && failIfInvalidXML_) { - throw cms::Exception("LHEWeightHelper") - << "XML in LHE is not consistent: Most likely, XML tags are out of order."; - } else if (!isConsistent()) { - swapHeaders(); - } - std::string fullHeader = boost::algorithm::join(headerLines_, ""); if (debug_) std::cout << "Full header is \n" << fullHeader << std::endl; int xmlError = xmlDoc.Parse(fullHeader.c_str()); - // in case of > instead of < - if (xmlError != 0 && failIfInvalidXML_) { - xmlDoc.PrintError(); - throw cms::Exception("LHEWeightHelper") - << "The LHE header is not valid XML! Weight information was not properly parsed."; - } else if (xmlError != 0 && !failIfInvalidXML_) { - boost::replace_all(fullHeader, "<", "<"); - boost::replace_all(fullHeader, ">", ">"); - xmlError = xmlDoc.Parse(fullHeader.c_str()); - } + while (!isConsistent() || xmlError != 0) { + if (failIfInvalidXML_) { + xmlDoc.PrintError(); + throw cms::Exception("LHEWeightHelper") + << "The LHE header is not valid XML! Weight information was not properly parsed."; + } - // error persists (how to handle error?) - if (xmlError != 0) { - std::string error = "Fatal error when parsing the LHE header. The header is not valid XML! Parsing error was "; - error += xmlDoc.ErrorStr(); - throw cms::Exception("LHEWeightHelper") << error; + switch (findErrorType(fullHeader)) { + case ErrorType::SWAPHEADER: + swapHeaders(); + fullHeader = boost::algorithm::join(headerLines_, ""); + xmlError = xmlDoc.Parse(fullHeader.c_str()); + break; + case ErrorType::HTMLSTYLE: + xmlError = tryReplaceHtmlStyle(xmlDoc, fullHeader); + break; + case ErrorType::TRAILINGSTR: + xmlError = tryRemoveTrailings(xmlDoc, fullHeader); + break; + case ErrorType::UNKNOWN: + std::string error = + "Fatal error when parsing the LHE header. The header is not valid XML! Parsing error was "; + error += xmlDoc.ErrorStr(); + throw cms::Exception("LHEWeightHelper") << error; + } } return true; @@ -151,4 +153,34 @@ namespace gen { } } } + + tinyxml2::XMLError LHEWeightHelper::tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) { + // in case of > instead of < + boost::replace_all(fullHeader, "<", "<"); + boost::replace_all(fullHeader, ">", ">"); + + return xmlDoc.Parse(fullHeader.c_str()); + } + + tinyxml2::XMLError LHEWeightHelper::tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) { + // delete extra strings after the last (occasionally contain '<' or '>') + std::size_t theLastKet = fullHeader.rfind(weightgroupKet_) + weightgroupKet_.length(); + fullHeader = fullHeader.substr(0, theLastKet); + + return xmlDoc.Parse(fullHeader.c_str()); + } + + LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(std::string& fullHeader) { + if (!isConsistent()) + return LHEWeightHelper::ErrorType::SWAPHEADER; + if (fullHeader.find("<") != std::string::npos || fullHeader.find(">") != std::string::npos) + return LHEWeightHelper::ErrorType::HTMLSTYLE; + + std::string trailingCand = + fullHeader.substr(fullHeader.rfind(weightgroupKet_) + std::string(weightgroupKet_).length()); + if (trailingCand.find('<') != std::string::npos || trailingCand.find('>') != std::string::npos) + return LHEWeightHelper::ErrorType::TRAILINGSTR; + + return LHEWeightHelper::ErrorType::UNKNOWN; + } } // namespace gen diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index bcff05f2416c0..53978e512e11d 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -7,6 +7,7 @@ from PhysicsTools.NanoAOD.lheInfoTable_cfi import * from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.common_cff import Var,CandVars +from PhysicsTools.NanoAOD.genWeights_cff import * nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( From 10b01150963dad6dcc87f9ace255f7c75e4cf28c Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 01:54:47 +0100 Subject: [PATCH 09/16] Step forward to newer cmssw version Fix problem of confounding issues in xmlParsing code fails to parse correctly when swapped weigthgroup tags and escaped </> characters in header. Also clean up the xmlError parsing and add some debug statements associated with tose errors falling back to vector of flattables Add "fillEmptyIfWeightFails" option and fix an err Error is related to the product size not being updated when an unknown weight is found Add more error states to LHEWEightHelper to handle empty xml --- DataFormats/NanoAOD/src/classes_def.xml | 4 +- .../Core/interface/LHEWeightHelper.h | 5 +- .../Core/interface/WeightHelper.h | 25 +++- .../Core/plugins/GenWeightProductProducer.cc | 2 +- .../Core/plugins/LHEWeightProductProducer.cc | 3 +- .../Core/src/GenWeightHelper.cc | 3 +- .../Core/src/LHEWeightHelper.cc | 114 ++++++++++-------- GeneratorInterface/Core/src/WeightHelper.cc | 66 +++++++--- .../LHEInterface/plugins/BuildFile.xml | 1 - .../plugins/GenWeightsTableProducer.cc | 45 ++++--- .../NanoAOD/plugins/NanoAODOutputModule.cc | 17 +++ PhysicsTools/NanoAOD/python/nano_cff.py | 23 ++-- PhysicsTools/NanoAOD/python/nanogen_cff.py | 17 +-- .../interface/GenWeightInfoProduct.h | 2 +- .../interface/GenWeightProduct.h | 1 + .../interface/PartonShowerWeightGroupInfo.h | 2 +- .../interface/PdfWeightGroupInfo.h | 2 +- .../interface/ScaleWeightGroupInfo.h | 2 +- .../interface/UnknownWeightGroupInfo.h | 1 - .../src/GenWeightInfoProduct.cc | 4 +- .../GeneratorProducts/src/WeightGroupInfo.cc | 6 +- .../GeneratorProducts/src/classes_def.xml | 5 +- 22 files changed, 220 insertions(+), 130 deletions(-) diff --git a/DataFormats/NanoAOD/src/classes_def.xml b/DataFormats/NanoAOD/src/classes_def.xml index e8645de0f822c..866c4cee9d66e 100644 --- a/DataFormats/NanoAOD/src/classes_def.xml +++ b/DataFormats/NanoAOD/src/classes_def.xml @@ -1,3 +1,4 @@ + @@ -10,8 +11,9 @@ - + + diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index 0418823095f2e..a60e74ec0cf98 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -21,7 +21,7 @@ namespace gen { public: LHEWeightHelper() : WeightHelper(){}; - enum ErrorType { SWAPHEADER, HTMLSTYLE, TRAILINGSTR, UNKNOWN }; + enum class ErrorType { Empty, SwapHeader, HTMLStyle, NoWeightGroup, TrailingStr, Unknown, NoError }; void setHeaderLines(std::vector headerLines); void parseWeights(); @@ -32,13 +32,14 @@ namespace gen { private: std::vector headerLines_; std::string weightgroupKet_ = ""; + std::string weightTag_ = ""; bool failIfInvalidXML_ = false; std::string parseGroupName(tinyxml2::XMLElement* el); void addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex); bool parseLHE(tinyxml2::XMLDocument& xmlDoc); tinyxml2::XMLError tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); tinyxml2::XMLError tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); - ErrorType findErrorType(std::string& fullHeader); + ErrorType findErrorType(int xmlError, std::string& fullHeader); }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index ed857f07bd8dc..5b1f217342ca7 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -34,6 +34,7 @@ namespace gen { template std::unique_ptr weightProduct(std::vector weights, float w0); + void setfillEmptyIfWeightFails(bool value) { fillEmptyIfWeightFails_ = value; } void setModel(std::string model) { model_ = model; } void setGuessPSWeightIdx(bool guessPSWeightIdx) { PartonShowerWeightGroupInfo::setGuessPSWeightIdx(guessPSWeightIdx); @@ -51,6 +52,7 @@ namespace gen { // TODO: Make this only print from one thread a la // https://github.com/kdlong/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 bool debug_ = false; + bool fillEmptyIfWeightFails_ = false; const unsigned int FIRST_PSWEIGHT_ENTRY = 2; const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; std::string model_; @@ -103,14 +105,27 @@ namespace gen { // Just add an empty product (need for all cases or...?) if (weights.size() > 1) { for (const auto& weight : weights) { - if constexpr (std::is_same::value) - weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i, weightGroupIndex); - else if (std::is_same::value) - weightGroupIndex = addWeightToProduct(weightProduct, weight, std::to_string(i), i, weightGroupIndex); + try { + if constexpr (std::is_same::value) { + weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i, weightGroupIndex); + } else if (std::is_same::value) + weightGroupIndex = addWeightToProduct(weightProduct, weight, std::to_string(i), i, weightGroupIndex); + + } catch (cms::Exception& e) { + if (fillEmptyIfWeightFails_) { + std::cerr << "WARNING: " << e.what() << std::endl; + std::cerr << "fillEmptyIfWeightFails_ is set to True, so variations will be empty!!" << std::endl; + weightProduct->setNumWeightSets(1); // Only central weight + return weightProduct; + } else { + throw cms::Exception("ERROR: " + std::string(e.what()) + + "\nfillEmptyIfWeightFails_ is set to False, so exiting code"); + } + } i++; } } - return std::move(weightProduct); + return weightProduct; } } // namespace gen diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index 198917def4506..33cfd00d49970 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -87,7 +87,7 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& weightHelper_.addUnassociatedGroup(); for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup.clone())); + weightInfoProduct->addWeightGroupInfo(weightGroup); } iLumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index daa7b26bb874d..0a628eadddde6 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -58,6 +58,7 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon produces(); produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); + weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); } @@ -137,7 +138,7 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& auto weightInfoProduct = std::make_unique(); for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup.clone())); + weightInfoProduct->addWeightGroupInfo(weightGroup); } lumi.put(std::move(weightInfoProduct)); } diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index b06475941efd6..9302005217e15 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -51,6 +51,7 @@ namespace gen { index++; } buildGroups(); - printWeights(); + if (debug_) + printWeights(); } } // namespace gen diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 290b8fd77f268..4f15ebfb2a18a 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -13,37 +13,45 @@ namespace gen { parsedWeights_.clear(); std::string fullHeader = boost::algorithm::join(headerLines_, ""); + if (debug_) std::cout << "Full header is \n" << fullHeader << std::endl; int xmlError = xmlDoc.Parse(fullHeader.c_str()); + ErrorType errorType; - while (!isConsistent() || xmlError != 0) { + while (errorType = findErrorType(xmlError, fullHeader), errorType != ErrorType::NoError) { if (failIfInvalidXML_) { xmlDoc.PrintError(); throw cms::Exception("LHEWeightHelper") << "The LHE header is not valid XML! Weight information was not properly parsed."; - } - - switch (findErrorType(fullHeader)) { - case ErrorType::SWAPHEADER: - swapHeaders(); - fullHeader = boost::algorithm::join(headerLines_, ""); - xmlError = xmlDoc.Parse(fullHeader.c_str()); - break; - case ErrorType::HTMLSTYLE: - xmlError = tryReplaceHtmlStyle(xmlDoc, fullHeader); - break; - case ErrorType::TRAILINGSTR: - xmlError = tryRemoveTrailings(xmlDoc, fullHeader); - break; - case ErrorType::UNKNOWN: - std::string error = - "Fatal error when parsing the LHE header. The header is not valid XML! Parsing error was "; - error += xmlDoc.ErrorStr(); - throw cms::Exception("LHEWeightHelper") << error; + } else if (errorType == ErrorType::HTMLStyle) { + if (debug_) + std::cout << " >>> This file uses > instead of >\n"; + xmlError = tryReplaceHtmlStyle(xmlDoc, fullHeader); + } else if (errorType == ErrorType::SwapHeader) { + if (debug_) + std::cout << " >>> Some headers in the file are swapped\n"; + swapHeaders(); + fullHeader = boost::algorithm::join(headerLines_, ""); + xmlError = xmlDoc.Parse(fullHeader.c_str()); + } else if (errorType == ErrorType::TrailingStr) { + if (debug_) + std::cout << " >>> There is non-XML text at the end of this file\n"; + xmlError = tryRemoveTrailings(xmlDoc, fullHeader); + } else if (errorType == ErrorType::Empty) { + if (debug_) + std::cout << " >>> There are no LHE xml header, ending parsing" << std::endl; + return false; + } else if (errorType == ErrorType::NoWeightGroup) { + if (debug_) + std::cout << " >>> There are no in the LHE xml header, ending parsing" << std::endl; + return false; + } else { + std::string error = "Fatal error when parsing the LHE header. The header is not valid XML! Parsing error was "; + error += xmlDoc.ErrorStr(); + throw cms::Exception("LHEWeightHelper") << error; } } - return true; } @@ -84,8 +92,7 @@ namespace gen { std::cout << ">>>> Found a weight group: " << groupName << std::endl; for (auto inner = e->FirstChildElement("weight"); inner != nullptr; inner = inner->NextSiblingElement("weight")) addGroup(inner, groupName, groupIndex, weightIndex); - } else - std::cout << "Found an invalid entry\n"; + } groupIndex++; } buildGroups(); @@ -103,8 +110,8 @@ namespace gen { return groupName; } } - bool hardFail = true; - if (hardFail) { + + if (!fillEmptyIfWeightFails_) { throw std::runtime_error("couldn't find groupname"); } return ""; @@ -114,16 +121,16 @@ namespace gen { int curLevel = 0; for (const auto& line : headerLines_) { - if (line.find("") != std::string::npos) { + if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { return false; } + } else if (line.find("weightgroup") != std::string::npos) { + curLevel++; + if (curLevel != 1) { + return false; + } } } return curLevel == 0; @@ -135,16 +142,16 @@ namespace gen { int close = -1; for (size_t idx = 0; idx < headerLines_.size(); idx++) { std::string line = headerLines_[idx]; - if (line.find("") != std::string::npos) { + if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { close = idx; } + } else if (line.find("weightgroup") != std::string::npos) { + curLevel++; + if (curLevel != 1) { + open = idx; + } } if (open > -1 && close > -1) { std::swap(headerLines_[open], headerLines_[close]); @@ -165,22 +172,29 @@ namespace gen { tinyxml2::XMLError LHEWeightHelper::tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) { // delete extra strings after the last (occasionally contain '<' or '>') std::size_t theLastKet = fullHeader.rfind(weightgroupKet_) + weightgroupKet_.length(); - fullHeader = fullHeader.substr(0, theLastKet); + std::size_t thelastWeight = fullHeader.rfind(weightTag_) + weightTag_.length(); + fullHeader = fullHeader.substr(0, std::max(theLastKet, thelastWeight)); return xmlDoc.Parse(fullHeader.c_str()); } - LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(std::string& fullHeader) { - if (!isConsistent()) - return LHEWeightHelper::ErrorType::SWAPHEADER; - if (fullHeader.find("<") != std::string::npos || fullHeader.find(">") != std::string::npos) - return LHEWeightHelper::ErrorType::HTMLSTYLE; - - std::string trailingCand = - fullHeader.substr(fullHeader.rfind(weightgroupKet_) + std::string(weightgroupKet_).length()); - if (trailingCand.find('<') != std::string::npos || trailingCand.find('>') != std::string::npos) - return LHEWeightHelper::ErrorType::TRAILINGSTR; - - return LHEWeightHelper::ErrorType::UNKNOWN; + LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, std::string& fullHeader) { + if (fullHeader.size() == 0) + return ErrorType::Empty; + else if (!isConsistent()) + return ErrorType::SwapHeader; + else if (fullHeader.find("<") != std::string::npos || fullHeader.find(">") != std::string::npos) + return ErrorType::HTMLStyle; + else if (xmlError != 0) { + if (fullHeader.rfind(weightgroupKet_) == std::string::npos) + return ErrorType::NoWeightGroup; + std::string trailingCand = + fullHeader.substr(fullHeader.rfind(weightgroupKet_) + std::string(weightgroupKet_).length()); + if (trailingCand.find('<') == std::string::npos || trailingCand.find('>') == std::string::npos) + return ErrorType::TrailingStr; + else + return ErrorType::Unknown; + } else + return ErrorType::NoError; } } // namespace gen diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 4441705dd93ab..852ed59c5a0cd 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -1,5 +1,6 @@ #include "GeneratorInterface/Core/interface/WeightHelper.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/Exception.h" #include namespace gen { @@ -103,7 +104,6 @@ namespace gen { int dynNum = std::stoi(dynNumText); scaleGroup.setDyn(weight.index, weight.id, muR, muF, dynNum, dynType); } catch (std::invalid_argument& e) { - std::cout << "Tried to convert (" << dynNumText << ") a int" << std::endl; scaleGroup.setWeightIsCorrupt(); /// do something here } @@ -122,6 +122,10 @@ namespace gen { int WeightHelper::lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup) { std::string lhaidText = searchAttributes("pdf", weight); + + if (debug_) + std::cout << "Looking for LHAPDF info in ID " << lhaidText << std::endl; + if (!lhaidText.empty()) { try { return std::stoi(lhaidText); @@ -131,6 +135,8 @@ namespace gen { } else if (!pdfGroup.lhaIds().empty()) { return pdfGroup.lhaIds().back() + 1; } else { + if (debug_) + std::cout << "Looking up LHAPDF ID from name" << weight.groupname << std::endl; return LHAPDF::lookupLHAPDFID(weight.groupname); } return -1; @@ -138,6 +144,8 @@ namespace gen { void WeightHelper::updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight) { int lhaid = lhapdfId(weight, pdfGroup); + if (debug_) + std::cout << "LHAID identified as " << lhaid << std::endl; if (pdfGroup.parentLhapdfId() < 0) { int parentId = lhaid - LHAPDF::lookupPDF(lhaid).second; pdfGroup.setParentLhapdfInfo(parentId); @@ -208,29 +216,37 @@ namespace gen { bool isUnassociated = false; try { groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); - } catch (const std::range_error& e) { + } catch (const cms::Exception& e) { std::cerr << "WARNING: " << e.what() << std::endl; isUnassociated = true; bool foundUnassocGroup = false; - while (!foundUnassocGroup && groupIndex < static_cast(weightGroups_.size())) { + for (; static_cast(groupIndex) < weightGroups_.size(); ++groupIndex) { auto& g = weightGroups_[groupIndex]; - if (g.weightType() == gen::WeightType::kUnknownWeights && g.name() == "unassociated") + if (g.weightType() == gen::WeightType::kUnknownWeights && g.name() == "unassociated") { foundUnassocGroup = true; - else - groupIndex++; + break; + } } if (!foundUnassocGroup) { addUnassociatedGroup(); + product->addWeightSet(); // Unaccounted for weights need a place } } + // This should be impossible, but in case the try/catch doesn't work, come here + if (groupIndex < 0 || groupIndex >= static_cast(weightGroups_.size())) + throw cms::Exception("Unmatched Generator weight! ID was " + name + " index was " + std::to_string(weightNum) + + "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); + auto& group = weightGroups_[groupIndex]; + if (isUnassociated) { group.addContainedId(weightNum, name, name); } - int entry = !isUnassociated ? group.weightVectorEntry(name, weightNum) : group.nIdsContained(); + + int entry = !isUnassociated ? group.weightVectorEntry(name, weightNum) : group.nIdsContained() - 1; if (debug_) - std::cout << "Adding weight " << entry << " to group " << groupIndex; + std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; product->addWeight(weight, groupIndex, entry); return groupIndex; } @@ -253,8 +269,9 @@ namespace gen { counter++; } // Needs to be properly handled - throw std::range_error("Unmatched Generator weight! ID was " + wgtId + " index was " + std::to_string(weightIndex) + - "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); + throw cms::Exception("Unmatched Generator weight! ID was " + wgtId + " index was " + std::to_string(weightIndex) + + "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); + return -1; } void WeightHelper::printWeights() { @@ -302,16 +319,31 @@ namespace gen { std::cout << "Building group for weight group " << weight.groupname << " weight content is " << weight.content << std::endl; } - if (isScaleWeightGroup(weight)) + if (isScaleWeightGroup(weight)) { + if (debug_) + std::cout << "Weight type is scale\n"; return std::make_unique(weight.groupname); - else if (isPdfWeightGroup(weight)) + } else if (isPdfWeightGroup(weight)) { + if (debug_) + std::cout << "Weight type is PDF\n"; return std::make_unique(weight.groupname); - else if (isMEParamWeightGroup(weight)) + } else if (isMEParamWeightGroup(weight)) { + if (debug_) + std::cout << "Weight type is MEParam\n"; return std::make_unique(weight.groupname); - else if (isPartonShowerWeightGroup(weight)) + } else if (isPartonShowerWeightGroup(weight)) { + if (debug_) + std::cout << "Weight type is parton shower\n"; return std::make_unique("shower"); - else if (isOrphanPdfWeightGroup(weight)) + } else if (isOrphanPdfWeightGroup(weight)) { + if (debug_) + std::cout << "Weight type is PDF\n"; return std::make_unique(weight.groupname); + } + if (debug_) + std::cout << "Weight type is unknown\n"; + + std::cout << "Group name is " << weight.groupname << std::endl; return std::make_unique(weight.groupname); } @@ -327,9 +359,11 @@ namespace gen { int numGroups = static_cast(weightGroups_.size()); if (weight.wgtGroup_idx == numGroups) { + std::cout << "Building a group"; weightGroups_.push_back(*buildGroup(weight)); + std::cout << "The name is now " << weightGroups_[weightGroups_.size() - 1].name() << std::endl; } else if (weight.wgtGroup_idx >= numGroups) - throw std::range_error("Invalid group index " + weight.wgtGroup_idx); + throw cms::Exception("Invalid group index " + std::to_string(weight.wgtGroup_idx)); // split PDF groups if (splitPdfWeight(weight)) diff --git a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml index f43689ef148df..2dae1e9cd252f 100644 --- a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml +++ b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml @@ -6,7 +6,6 @@ - diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index e069c4fb12c6b..4d206a7bbd5d6 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -30,18 +30,19 @@ namespace { using CounterMap = genCounter::CounterMap; using Counter = genCounter::Counter; -class LHEWeightsTableProducer : public edm::global::EDProducer, +class GenWeightsTableProducer : public edm::global::EDProducer, edm::StreamCache, edm::RunSummaryCache, edm::EndRunProducer> { public: - LHEWeightsTableProducer(edm::ParameterSet const& params); + GenWeightsTableProducer(edm::ParameterSet const& params); void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; //func changed//sroychow void addWeightGroupToTable(std::map>& lheWeightTables, std::map>& weightVecsizes, std::map& weightlabels, + std::unique_ptr>& lheWeightTablevec, const char* typeName, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights, @@ -155,7 +156,7 @@ class LHEWeightsTableProducer : public edm::global::EDProducer>("lheWeights"), [this](const edm::InputTag& tag) { return mayConsume(tag); })), @@ -183,9 +184,10 @@ LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params produces("GENWeight"); produces(); produces("genModel"); + produces>("LHEWeightTableVec"); } -void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { +void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { //access counter for weight sums Counter& counter = *streamCache(id)->get(); edm::Handle lheWeightHandle; @@ -235,13 +237,15 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons weightVecsizes.insert(std::make_pair(wg.first, std::vector())); weightlabels.insert(std::make_pair(wg.first, "")); } + + auto lheWeightTablevec = std::make_unique>(); if (foundLheWeights) { addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + lheWeightTables, weightVecsizes, weightlabels, lheWeightTablevec, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); } addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); + lheWeightTables, weightVecsizes, weightlabels, lheWeightTablevec, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); for (auto& wg : weightTypeNames_) { std::string wname = wg.second; @@ -258,14 +262,16 @@ void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons iEvent.put(std::move(outTable), wname); iEvent.put(std::move(outTableSizes), wname + "sizes"); } + iEvent.put(std::move(lheWeightTablevec),"LHEWeightTableVec"); } /* */ -void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, +void GenWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, std::map>& weightVecsizes, std::map& weightlabels, + std::unique_ptr>& lheWeightTablevec, const char* typeName, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights, @@ -276,7 +282,7 @@ void LHEWeightsTableProducer::addWeightGroupToTable(std::mapweightType(); std::string name = weightTypeNames_.at(weightType); std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->description(); @@ -297,7 +303,7 @@ void LHEWeightsTableProducer::addWeightGroupToTable(std::map(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); - weights = std::vector(weights.begin(), weights.begin() + nstore); + weights = std::vector(begin(weights), std::begin(weights)+nstore); label.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + " elements of weights vector, unordered"); } @@ -317,13 +323,20 @@ void LHEWeightsTableProducer::addWeightGroupToTable(std::map 0) { + entryName.append("AltSet"); + entryName.append(std::to_string(typeCount[weightType])); + } + lheWeightTablevec->emplace_back(weights.size(), entryName, false); + lheWeightTablevec->back().addColumn("", weights, label, lheWeightPrecision_); + weightlabels[weightType].append(label); typeCount[weightType]++; } } -WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, +WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, gen::WeightType weightType, int& maxStore) const { std::vector allgroups; @@ -348,7 +361,7 @@ WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle< return out; } -std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, +std::vector GenWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, const gen::ScaleWeightGroupInfo& scaleGroup) const { std::vector weights; weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); @@ -364,7 +377,7 @@ std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vect return weights; } -std::vector LHEWeightsTableProducer::preferredPSweights(const std::vector& psWeights, +std::vector GenWeightsTableProducer::preferredPSweights(const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo& pswV) const { std::vector psTosave; @@ -376,7 +389,7 @@ std::vector LHEWeightsTableProducer::preferredPSweights(const std::vecto return psTosave; } -void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, +void GenWeightsTableProducer::streamEndRunSummary(edm::StreamID id, edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const { @@ -384,7 +397,7 @@ void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, runCounterMap->mergeSumMap(*streamCache(id)); } -void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, +void GenWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const { auto out = std::make_unique(); @@ -411,7 +424,7 @@ void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, } iRun.put(std::move(out)); } -void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { +void GenWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; desc.add>("lheWeights"); desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) @@ -431,4 +444,4 @@ void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d } #include "FWCore/Framework/interface/MakerMacros.h" -DEFINE_FWK_MODULE(LHEWeightsTableProducer); +DEFINE_FWK_MODULE(GenWeightsTableProducer); diff --git a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc index 4a6999ed42733..4d83d34efec2f 100644 --- a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc +++ b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc @@ -126,6 +126,7 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { std::vector m_evstrings; std::vector m_runTables; + std::vector m_lumiTables; std::vector> m_nanoMetadata; }; @@ -243,6 +244,10 @@ void NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput con jr->reportLumiSection(m_jrToken, iLumi.id().run(), iLumi.id().value()); m_commonLumiBranches.fill(iLumi.id()); + + for (auto& t : m_lumiTables) + t.fill(iLumi, *m_lumiTree); + m_lumiTree->Fill(); m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory()); @@ -307,6 +312,7 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { m_triggers_areSorted = false; m_evstrings.clear(); m_runTables.clear(); + m_lumiTables.clear(); const auto& keeps = keptProducts(); for (const auto& keep : keeps[edm::InEvent]) { if (keep.first->className() == "nanoaod::FlatTable") { @@ -322,6 +328,17 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className()); } + for (const auto& keep : keeps[edm::InLumi]) { + if (keep.first->className() == "nanoaod::MergeableCounterTable") + m_lumiTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); + else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") + m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); + else + throw cms::Exception( + "Configuration", + "NanoAODOutputModule cannot handle class " + keep.first->className() + " in LuminosityBlock branch"); + } + for (const auto& keep : keeps[edm::InRun]) { if (keep.first->className() == "nanoaod::MergeableCounterTable") m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); diff --git a/PhysicsTools/NanoAOD/python/nano_cff.py b/PhysicsTools/NanoAOD/python/nano_cff.py index b98faffe69fb2..9b21c653c6c8c 100644 --- a/PhysicsTools/NanoAOD/python/nano_cff.py +++ b/PhysicsTools/NanoAOD/python/nano_cff.py @@ -1,6 +1,7 @@ from __future__ import print_function import FWCore.ParameterSet.Config as cms from PhysicsTools.NanoAOD.common_cff import * +from PhysicsTools.NanoAOD.nano_eras_cff import * from PhysicsTools.NanoAOD.jets_cff import * from PhysicsTools.NanoAOD.muons_cff import * from PhysicsTools.NanoAOD.taus_cff import * @@ -17,18 +18,9 @@ from PhysicsTools.NanoAOD.met_cff import * from PhysicsTools.NanoAOD.triggerObjects_cff import * from PhysicsTools.NanoAOD.isotracks_cff import * +from PhysicsTools.NanoAOD.protons_cff import * from PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff import * -from Configuration.Eras.Modifier_run2_miniAOD_80XLegacy_cff import run2_miniAOD_80XLegacy -from Configuration.Eras.Modifier_run2_nanoAOD_92X_cff import run2_nanoAOD_92X -from Configuration.Eras.Modifier_run2_nanoAOD_94X2016_cff import run2_nanoAOD_94X2016 -from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv1_cff import run2_nanoAOD_94XMiniAODv1 -from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv2_cff import run2_nanoAOD_94XMiniAODv2 -from Configuration.Eras.Modifier_run2_nanoAOD_102Xv1_cff import run2_nanoAOD_102Xv1 -from Configuration.Eras.Modifier_run2_nanoAOD_106Xv1_cff import run2_nanoAOD_106Xv1 -from Configuration.Eras.Modifier_run2_egamma_2017_cff import run2_egamma_2017 -from Configuration.Eras.Modifier_run2_egamma_2018_cff import run2_egamma_2018 - nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( @@ -98,6 +90,9 @@ ) ) +lhcInfoTable = cms.EDProducer("LHCInfoProducer", + precision = cms.int32(10), +) lheInfoTable = cms.EDProducer("LHETablesProducer", lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), @@ -117,8 +112,9 @@ jetTables + muonTables + tauTables + electronTables + photonTables + globalTables +vertexTables+ metTables+simpleCleanerTable + isoTrackTables ) nanoSequenceOnlyFullSim = cms.Sequence(triggerObjectTables + l1bits) +nanoSequenceOnlyData = cms.Sequence(protonTables + lhcInfoTable) -nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyFullSim) +nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyData + nanoSequenceOnlyFullSim) nanoSequenceFS = cms.Sequence(genParticleSequence + genVertexTables + particleLevelSequence + nanoSequenceCommon + jetMC + muonMC + electronMC + photonMC + tauMC + metMC + ttbarCatMCProducers + globalTablesMC + btagWeightTable + genWeightsTable + genVertexTable + genParticleTables + particleLevelTables + lheInfoTable + ttbarCategoryTable ) @@ -224,7 +220,6 @@ def nanoAOD_recalibrateMETs(process,isData): reclusterJets = cms.untracked.bool(False), ) run2_nanoAOD_106Xv1.toModify(nanoAOD_PuppiV15_switch,recoMetFromPFCs=True,reclusterJets=True) - runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi", recoMetFromPFCs=bool(nanoAOD_PuppiV15_switch.recoMetFromPFCs), reclusterJets=bool(nanoAOD_PuppiV15_switch.reclusterJets)) if nanoAOD_PuppiV15_switch.reclusterJets: from RecoJets.JetProducers.ak4PFJets_cfi import ak4PFJets from PhysicsTools.PatAlgos.tools.helpers import getPatAlgosToolsTask, addToProcessAndTask @@ -243,11 +238,13 @@ def nanoAOD_recalibrateMETs(process,isData): muSource =cms.InputTag( 'slimmedMuons'), elSource = cms.InputTag('slimmedElectrons'), genParticles= cms.InputTag('prunedGenParticles'), - getJetMCFlavour=False + getJetMCFlavour= False ) process.patJetsPuppi.addGenPartonMatch = cms.bool(False) process.patJetsPuppi.addGenJetMatch = cms.bool(False) + + runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi", recoMetFromPFCs=bool(nanoAOD_PuppiV15_switch.recoMetFromPFCs), reclusterJets=bool(nanoAOD_PuppiV15_switch.reclusterJets)) process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) return process diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index 53978e512e11d..05828273f38f6 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -5,8 +5,10 @@ from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * from PhysicsTools.NanoAOD.lheInfoTable_cfi import * +from PhysicsTools.NanoAOD.genWeights_cff import * from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.common_cff import Var,CandVars +from PhysicsTools.NanoAOD.nano_eras_cff import * from PhysicsTools.NanoAOD.genWeights_cff import * nanoMetadata = cms.EDProducer("UniqueStringProducer", @@ -64,13 +66,6 @@ def customizeNanoGENFromMini(process): process.nanogenSequence.insert(0, process.genParticles2HepMC) process.nanogenSequence.insert(0, process.mergedGenParticles) - from Configuration.Eras.Modifier_run2_miniAOD_80XLegacy_cff import run2_miniAOD_80XLegacy - from Configuration.Eras.Modifier_run2_nanoAOD_94X2016_cff import run2_nanoAOD_94X2016 - from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv1_cff import run2_nanoAOD_94XMiniAODv1 - from Configuration.Eras.Modifier_run2_nanoAOD_94XMiniAODv2_cff import run2_nanoAOD_94XMiniAODv2 - from Configuration.Eras.Modifier_run2_nanoAOD_102Xv1_cff import run2_nanoAOD_102Xv1 - from Configuration.Eras.Modifier_run2_nanoAOD_92X_cff import run2_nanoAOD_92X - (run2_nanoAOD_92X | run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94X2016 | \ run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | \ run2_nanoAOD_102Xv1).toReplaceWith(nanogenSequence, nanogenSequence.copyAndExclude([genVertexTable, genVertexT0Table])) @@ -117,9 +112,8 @@ def customizeNanoGEN(process): # Prune gen particles with tight conditions applied in usual NanoAOD def pruneGenParticlesNano(process): - process.finalGenParticles = finalGenParticles.clone() - process.genParticleTable.src = "prunedGenParticles" - process.patJetPartons.particles = "prunedGenParticles" + process.finalGenParticles.src = process.genParticleTable.src.getModuleLabel() + process.genParticleTable.src = "finalGenParticles" process.nanogenSequence.insert(0, process.finalGenParticles) return process @@ -130,8 +124,9 @@ def pruneGenParticlesMini(process): "Use a different customization.") from PhysicsTools.PatAlgos.slimming.prunedGenParticles_cfi import prunedGenParticles process.prunedGenParticles = prunedGenParticles.clone() + process.prunedGenParticles.src = "genParticles" process.genParticleTable.src = "prunedGenParticles" - process.patJetPartons.particles = "prunedGenParticles" + process.nanogenSequence.insert(0, process.prunedGenParticles) return process diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index cdccd169797c9..48a755404b268 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -43,7 +43,7 @@ class GenWeightInfoProduct { std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; - void addWeightGroupInfo(std::unique_ptr info); + void addWeightGroupInfo(gen::WeightGroupInfo& info); const int numberOfGroups() const { return weightGroupsInfo_.size(); } private: diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h index 0110600384e6c..601b37ca46bc9 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -8,6 +8,7 @@ #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" #include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" +#include "FWCore/Utilities/interface/Exception.h" typedef std::vector> WeightsContainer; diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index feb8face8658b..c5e1e3c89a73a 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -12,7 +12,7 @@ namespace gen { PartonShowerWeightGroupInfo() : PartonShowerWeightGroupInfo("") {} PartonShowerWeightGroupInfo(std::string header, std::string name); PartonShowerWeightGroupInfo(std::string header) : PartonShowerWeightGroupInfo(header, header) {} - PartonShowerWeightGroupInfo(const PartonShowerWeightGroupInfo &other) { copy(other); } + PartonShowerWeightGroupInfo(const PartonShowerWeightGroupInfo &other) : WeightGroupInfo(other) { copy(other); } ~PartonShowerWeightGroupInfo() override {} void copy(const PartonShowerWeightGroupInfo &other); PartonShowerWeightGroupInfo *clone() const override; diff --git a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h index 5c8214fa9eb35..a819d4060bb94 100644 --- a/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h @@ -33,7 +33,7 @@ namespace gen { weightType_ = WeightType::kPdfWeights; } PdfWeightGroupInfo(std::string header) : WeightGroupInfo(header) { weightType_ = WeightType::kPdfWeights; } - PdfWeightGroupInfo(const PdfWeightGroupInfo& other) { copy(other); } + PdfWeightGroupInfo(const PdfWeightGroupInfo& other) : WeightGroupInfo(other) { copy(other); } ~PdfWeightGroupInfo() override {} void copy(const PdfWeightGroupInfo& other); PdfWeightGroupInfo* clone() const override; diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index 7bb460f57d210..1e9e6d6387f7c 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -41,7 +41,7 @@ namespace gen { isFunctionalFormVar_ = false; } ScaleWeightGroupInfo(std::string header) : ScaleWeightGroupInfo(header, header) {} - ScaleWeightGroupInfo(const ScaleWeightGroupInfo& other) { copy(other); } + ScaleWeightGroupInfo(const ScaleWeightGroupInfo& other) : WeightGroupInfo(other) { copy(other); } ~ScaleWeightGroupInfo() override {} void copy(const ScaleWeightGroupInfo& other); ScaleWeightGroupInfo* clone() const override; diff --git a/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h index 3513cc70841dc..21a20b891e160 100644 --- a/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h @@ -16,7 +16,6 @@ namespace gen { isWellFormed_ = false; } ~UnknownWeightGroupInfo() override {} - void copy(const UnknownWeightGroupInfo& other); UnknownWeightGroupInfo* clone() const override; }; } // namespace gen diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index f54ced13fc6d7..3b29d35f05927 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -100,6 +100,6 @@ std::vector GenWeightInfoProduct::weightGroupIndicesByType(gen::WeightType return matchingGroupIndices; } -void GenWeightInfoProduct::addWeightGroupInfo(std::unique_ptr info) { - weightGroupsInfo_.push_back(std::move(info)); +void GenWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo& info) { + weightGroupsInfo_.push_back(info.clone()); } diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index 90ad7c284aca5..03dd1ed8c85f7 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -45,8 +45,8 @@ namespace gen { if (wgtId.empty()) wgtId = std::to_string(weightEntry); // First try ordered search - size_t orderedEntry = weightEntry - firstId_; - if (indexInRange(weightEntry) && orderedEntry < idsContained_.size()) { + int orderedEntry = weightEntry - firstId_; + if (indexInRange(weightEntry) && orderedEntry < static_cast(idsContained_.size())) { if (wgtId.empty() || idsContained_.at(orderedEntry).id == wgtId) { return orderedEntry; } @@ -65,7 +65,7 @@ namespace gen { if (id.empty()) id = std::to_string(weightEntry); - if (firstId_ == -1 || weightEntry < firstId_) { + if (firstId_ < 0 || weightEntry < firstId_) { firstId_ = weightEntry; for (auto& entry : idsContained_) // Reset if indices need to be shifted entry.localIndex++; diff --git a/SimDataFormats/GeneratorProducts/src/classes_def.xml b/SimDataFormats/GeneratorProducts/src/classes_def.xml index 1cfcc6144a4e4..24738e36f042b 100644 --- a/SimDataFormats/GeneratorProducts/src/classes_def.xml +++ b/SimDataFormats/GeneratorProducts/src/classes_def.xml @@ -200,12 +200,12 @@ - - + + @@ -274,5 +274,6 @@ + From 28d0302c6aa3c8348380186b3a42c17cd3c492b8 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 02:27:29 +0100 Subject: [PATCH 10/16] Allow gen products to run at GEN step or Nano --- .../StandardSequences/python/Generator_cff.py | 6 +- DataFormats/NanoAOD/src/classes_def.xml | 1 - .../GeneratorInterface_EventContent_cff.py | 6 + .../Core/interface/WeightHelper.h | 1 + GeneratorInterface/Core/plugins/BuildFile.xml | 2 +- .../Core/plugins/GenWeightProductProducer.cc | 82 +++-- .../Core/plugins/LHEWeightProductProducer.cc | 39 ++- GeneratorInterface/Core/src/WeightHelper.cc | 2 - .../Core/test/dumpWeightInfo.py | 6 +- .../test/createLHEFormatFromROOTFile.py | 107 +++++++ .../NanoAOD/interface/GenWeightCounters.h | 30 +- .../plugins/GenWeightsTableProducer.cc | 300 +++++++++--------- .../NanoAOD/plugins/LHETablesProducer.cc | 41 ++- .../NanoAOD/plugins/NanoAODOutputModule.cc | 28 +- .../NanoAOD/plugins/TableOutputBranches.cc | 13 +- .../NanoAOD/plugins/TableOutputBranches.h | 2 + .../python/NanoAODEDMEventContent_cff.py | 15 +- PhysicsTools/NanoAOD/python/genWeights_cff.py | 34 ++ PhysicsTools/NanoAOD/python/nano_cff.py | 283 ++++++++--------- PhysicsTools/NanoAOD/python/nanogen_cff.py | 70 ++-- .../python/slimming/MicroEventContent_cff.py | 3 +- .../interface/PartonShowerWeightGroupInfo.h | 12 + .../interface/WeightGroupInfo.h | 1 + .../src/PartonShowerWeightGroupInfo.cc | 2 +- .../GeneratorProducts/src/classes_def.xml | 1 + 25 files changed, 676 insertions(+), 411 deletions(-) create mode 100644 GeneratorInterface/LHEInterface/test/createLHEFormatFromROOTFile.py create mode 100644 PhysicsTools/NanoAOD/python/genWeights_cff.py diff --git a/Configuration/StandardSequences/python/Generator_cff.py b/Configuration/StandardSequences/python/Generator_cff.py index efebc7fed5b68..8606236c14dd2 100644 --- a/Configuration/StandardSequences/python/Generator_cff.py +++ b/Configuration/StandardSequences/python/Generator_cff.py @@ -5,6 +5,8 @@ # from PhysicsTools.HepMCCandAlgos.genParticles_cfi import * from GeneratorInterface.Core.generatorSmeared_cfi import * +from GeneratorInterface.Core.genWeights_cfi import genWeights +from GeneratorInterface.Core.lheWeights_cfi import lheWeights from RecoJets.Configuration.RecoGenJets_cff import * from RecoMET.Configuration.RecoGenMET_cff import * from RecoJets.Configuration.GenJetParticles_cff import * @@ -53,10 +55,12 @@ VertexSmearing = cms.Sequence(cms.SequencePlaceholder("VtxSmeared")) GenSmeared = cms.Sequence(generatorSmeared) GeneInfo = cms.Sequence(GeneInfoTask) +lheWeights.failIfInvalidXML = False +genWeightsSeq = cms.Sequence(genWeights*lheWeights) genJetMET = cms.Sequence(genJetMETTask) from SimPPS.Configuration.GenPPS_cff import * -pgen = cms.Sequence(cms.SequencePlaceholder("randomEngineStateProducer")+VertexSmearing+GenSmeared+GeneInfo+genJetMET, PPSTransportTask) +pgen = cms.Sequence(cms.SequencePlaceholder("randomEngineStateProducer")+VertexSmearing+GenSmeared+GeneInfo+genWeightsSeq+genJetMET, PPSTransportTask) # sequence for bare generator result only, without vertex smearing and analysis objects added diff --git a/DataFormats/NanoAOD/src/classes_def.xml b/DataFormats/NanoAOD/src/classes_def.xml index 866c4cee9d66e..5d57ee3cef58c 100644 --- a/DataFormats/NanoAOD/src/classes_def.xml +++ b/DataFormats/NanoAOD/src/classes_def.xml @@ -14,7 +14,6 @@ - diff --git a/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py b/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py index b293b0f6422a3..48078d55f7e2e 100644 --- a/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py +++ b/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py @@ -19,6 +19,8 @@ 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', 'keep edmHepMCProduct_generatorSmeared_*_*', + 'keep GenWeightProduct_*_*_*', + 'keep GenWeightInfoProduct_*_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) @@ -34,6 +36,8 @@ 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', 'keep edmHepMCProduct_generatorSmeared_*_*', + 'keep GenWeightProduct_*_*_*', + 'keep GenWeightInfoProduct_*_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) @@ -48,6 +52,8 @@ 'keep GenLumiInfoHeader_generator_*_*', 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', + 'keep GenWeightProduct_*_*_*', + 'keep GenWeightInfoProduct_*_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index 5b1f217342ca7..099997c008d9c 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -47,6 +47,7 @@ namespace gen { std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex); int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); void setDebug(bool value) { debug_ = value; } + bool fillEmptyIfWeightFails() { return fillEmptyIfWeightFails_; } protected: // TODO: Make this only print from one thread a la diff --git a/GeneratorInterface/Core/plugins/BuildFile.xml b/GeneratorInterface/Core/plugins/BuildFile.xml index 73ee3894b576d..a8c9a22737fc6 100644 --- a/GeneratorInterface/Core/plugins/BuildFile.xml +++ b/GeneratorInterface/Core/plugins/BuildFile.xml @@ -3,9 +3,9 @@ + - diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index 33cfd00d49970..fb2bbbcd2121d 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -23,22 +23,23 @@ #include "GeneratorInterface/Core/interface/GenWeightHelper.h" #include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Utilities/interface/transform.h" #include class GenWeightProductProducer : public edm::one::EDProducer { public: explicit GenWeightProductProducer(const edm::ParameterSet& iConfig); ~GenWeightProductProducer() override; - -private: - std::vector weightNames_; - gen::GenWeightHelper weightHelper_; - edm::EDGetTokenT genLumiInfoToken_; - edm::EDGetTokenT genEventToken_; - const edm::EDGetTokenT genLumiInfoHeadTag_; - void produce(edm::Event&, const edm::EventSetup&) override; void beginLuminosityBlockProduce(edm::LuminosityBlock& lb, edm::EventSetup const& c) override; + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); +private: + gen::GenWeightHelper weightHelper_; + const edm::EDGetTokenT genLumiInfoToken_; + const edm::EDGetTokenT genEventToken_; + std::vector> weightInfoTokens_; + const bool debug_; + bool foundWeightProduct_ = false; }; // @@ -47,18 +48,25 @@ class GenWeightProductProducer : public edm::one::EDProducer(iConfig.getParameter("genInfo"))), genEventToken_(consumes(iConfig.getParameter("genInfo"))), - genLumiInfoHeadTag_( - mayConsume(iConfig.getParameter("genLumiInfoHeader"))) { - weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); + weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), + [this](const std::string& tag) { return mayConsume(tag); })), + debug_(iConfig.getUntrackedParameter("debug", false)) { + weightHelper_.setDebug(debug_); produces(); produces(); weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); + weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); } GenWeightProductProducer::~GenWeightProductProducer() {} // ------------ method called to produce the data ------------ void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + // In case there is already a product in the file when this is scheduled + // (leave the list of weightproducts empty if you always want to produce a new product) + if (foundWeightProduct_) + return; + edm::Handle genEventInfo; iEvent.getByToken(genEventToken_, genEventInfo); @@ -68,28 +76,52 @@ void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup } void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) { - edm::Handle genLumiInfoHead; - iLumi.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); - if (genLumiInfoHead.isValid()) { - std::string label = genLumiInfoHead->configDescription(); - boost::replace_all(label, "-", "_"); - weightHelper_.setModel(label); + edm::Handle weightInfoHandle; + + for (auto& token : weightInfoTokens_) { + iLumi.getByToken(token, weightInfoHandle); + if (weightInfoHandle.isValid()) { + foundWeightProduct_ = true; + return; + } } edm::Handle genLumiInfoHandle; iLumi.getByToken(genLumiInfoToken_, genLumiInfoHandle); - weightNames_ = genLumiInfoHandle->weightNames(); - weightHelper_.parseWeightGroupsFromNames(weightNames_); - auto weightInfoProduct = std::make_unique(); - if (weightHelper_.weightGroups().empty()) - weightHelper_.addUnassociatedGroup(); - - for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(weightGroup); + if (genLumiInfoHandle.isValid()) { + std::string label = genLumiInfoHandle->configDescription(); + boost::replace_all(label, "-", "_"); + weightHelper_.setModel(label); + weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames()); + if (weightHelper_.weightGroups().empty()) + weightHelper_.addUnassociatedGroup(); + + for (auto& weightGroup : weightHelper_.weightGroups()) { + weightInfoProduct->addWeightGroupInfo(weightGroup); + } + } else if (weightHelper_.fillEmptyIfWeightFails() && debug_) { + std::cerr << "genLumiInfoHeader not found, but fillEmptyIfWeightFails is True. Will produce empty product!" << std::endl; + } else { + throw cms::Exception("GenWeightProductProducer") + << "genLumiInfoHeader not found, code is exiting." << std::endl + << "If this is expect and want to continue, set fillEmptyIfWeightFails to True"; } iLumi.put(std::move(weightInfoProduct)); } +void GenWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("genInfo", edm::InputTag{"generator"}) + ->setComment("tag(s) for the GenLumiInfoHeader and GenEventInfoProduct"); + desc.add>("weightProductLabels", std::vector{{""}}) + ->setComment("tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + desc.addUntracked("debug", false)->setComment("Output debug info"); + desc.addUntracked("guessPSWeightIdx", false)->setComment("If not possible to parse text, guess the parton shower weight indices"); + desc.addUntracked("fillEmptyIfWeightFails", false)->setComment("Produce an empty product if parsing of header fails"); + descriptions.add("genWeights", desc); +} + DEFINE_FWK_MODULE(GenWeightProductProducer); diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index 0a628eadddde6..782964e887335 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -30,20 +30,20 @@ class LHEWeightProductProducer : public edm::one::EDProducer lheLabels_; std::vector> lheEventTokens_; std::vector> lheRunInfoTokens_; - std::vector> lheWeightInfoTokens_; + std::vector> weightInfoTokens_; bool foundWeightProduct_ = false; bool hasLhe_ = false; - - void produce(edm::Event&, const edm::EventSetup&) override; - void beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) override; - void beginRun(edm::Run const& run, edm::EventSetup const& es) override; - void endRun(edm::Run const& run, edm::EventSetup const& es) override; }; // TODO: Accept a vector of strings (source, externalLHEProducer) exit if neither are found @@ -53,8 +53,8 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), lheRunInfoTokens_(edm::vector_transform( lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), - lheWeightInfoTokens_(edm::vector_transform( - lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })) { + weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })) { produces(); produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); @@ -109,11 +109,11 @@ void LHEWeightProductProducer::beginRun(edm::Run const& run, edm::EventSetup con void LHEWeightProductProducer::endRun(edm::Run const& run, edm::EventSetup const& es) {} void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) { - edm::Handle lheWeightInfoHandle; + edm::Handle weightInfoHandle; - for (auto& token : lheWeightInfoTokens_) { - lumi.getByToken(token, lheWeightInfoHandle); - if (lheWeightInfoHandle.isValid()) { + for (auto& token : weightInfoTokens_) { + lumi.getByToken(token, weightInfoHandle); + if (weightInfoHandle.isValid()) { foundWeightProduct_ = true; return; } @@ -143,4 +143,19 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& lumi.put(std::move(weightInfoProduct)); } +void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add>("lheSourceLabels", std::vector{{"externalLHEProducer"}, {"source"}}) + ->setComment("tag(s) to look for LHERunInfoProduct/LHEEventProduct" + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + desc.add>("weightProductLabels", std::vector{{""}}) + ->setComment("tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + desc.addUntracked("debug", false)->setComment("Output debug info"); + desc.addUntracked("failIfInvalidXML", true)->setComment("Throw exception if XML header is invalid (rather than trying to recover and parse anyway)"); + desc.addUntracked("fillEmptyIfWeightFails", false)->setComment("Produce an empty product if parsing of header fails"); + descriptions.add("lheWeights", desc); +} + + DEFINE_FWK_MODULE(LHEWeightProductProducer); diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 852ed59c5a0cd..8dca568848259 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -359,9 +359,7 @@ namespace gen { int numGroups = static_cast(weightGroups_.size()); if (weight.wgtGroup_idx == numGroups) { - std::cout << "Building a group"; weightGroups_.push_back(*buildGroup(weight)); - std::cout << "The name is now " << weightGroups_[weightGroups_.size() - 1].name() << std::endl; } else if (weight.wgtGroup_idx >= numGroups) throw cms::Exception("Invalid group index " + std::to_string(weight.wgtGroup_idx)); diff --git a/GeneratorInterface/Core/test/dumpWeightInfo.py b/GeneratorInterface/Core/test/dumpWeightInfo.py index b7231c6945a33..5aa70aff048c1 100644 --- a/GeneratorInterface/Core/test/dumpWeightInfo.py +++ b/GeneratorInterface/Core/test/dumpWeightInfo.py @@ -5,18 +5,18 @@ parser = argparse.ArgumentParser() parser.add_argument("infile", type=str, help="Input EDM file") -parser.add_argument("--source", type=str, help="product ID of weight product", default="externalLHEProducer") +parser.add_argument("--source", type=str, help="product ID of weight product", default="genWeights") args = parser.parse_args() lumis = Lumis(args.infile) -lumi = lumis.__iter__().next() +lumi = next(lumis.__iter__()) weightInfoHandle = Handle("GenWeightInfoProduct") print("Trying to get weightInfo from lumi") lumi.getByLabel(args.source, weightInfoHandle) weightInfoProd = weightInfoHandle.product() events = Events(args.infile) -event = events.__iter__().next() +event = next(events.__iter__()) weightHandle = Handle("GenWeightProduct") print("Trying to get weightProduct from event") event.getByLabel(args.source, weightHandle) diff --git a/GeneratorInterface/LHEInterface/test/createLHEFormatFromROOTFile.py b/GeneratorInterface/LHEInterface/test/createLHEFormatFromROOTFile.py new file mode 100644 index 0000000000000..33c60dbff7ca4 --- /dev/null +++ b/GeneratorInterface/LHEInterface/test/createLHEFormatFromROOTFile.py @@ -0,0 +1,107 @@ +import ROOT +import sys + + +""" +Usage +python createLHEFormatFromROOTFile.py inputfile outputfile pdgId_particle_to_undo_decay1 pdgId_particle_to_undo_decay2 pdgId_particle_to_undo_decay3 ... +""" + +args = sys.argv[:] + +class HEPPart(object): + def __init__(self,event, idx): + """ + Class to organize the description of a particle in the LHE event + event : whole event information (usually a entry in the input TTree) + idx : the index of the particle inside the LHE file + """ + for att in ["pt","eta","phi", "mass","lifetime","pdgId","status","spin","color1", "color2","mother1","mother2","incomingpz"]: + setattr(self, att, getattr(event, "LHEPart_"+att)[idx]) + self.setP4() + + def setP4(self): + self.p4 = ROOT.TLorentzVector() + if self.status != -1: + self.p4.SetPtEtaPhiM(self.pt, self.eta, self.phi, self.mass) + else: + self.p4.SetPxPyPzE(0.,0.,self.incomingpz, abs(self.incomingpz)) + def printPart(self): + """ Just to print it pretty """ + return " {pdg:d} {status:d} {mother1:d} {mother2:d} {color1:d} {color2:d} {px:e} {py:e} {pz:e} {energy:e} {mass:e} {time:e} {spin:e}\n".format(pdg=self.pdgId,status=self.status, mother1=self.mother1, mother2=self.mother2, color1=self.color1, color2=self.color2, px=self.p4.Px(), py=self.p4.Py(), pz=self.p4.Pz(), energy=self.p4.E(), mass=self.mass, time=self.lifetime, spin=self.spin) + + +class LHEPrinter(object): + def __init__(self,theFile,theTree,outputLHE,undoDecays=[], chunkers=-1, prDict={}): + """ + theFile : path to input root file with the whole LHEinformation + theTree : number of ttree inside the file, usually "Events" + outputLHE: name of output .lhe file + undoDecays: pdgId of particles whose decays we want to undo (i.e. W that are decayed with madspin, as the reweighting is called before madspin) + chunkers: process by chunks in case we want to later multithread the jobs. Argument is max size (in events) of the chunks + prDict : a dictionary indicating possible mismatchings between the ProcessID in the new gridpack and the old (matching the numbers at generate p p > x y z @0 in the run card) + """ + + self.prDict = prDict + self.outputLHE = outputLHE + self.fil = ROOT.TFile(theFile,"OPEN") + self.tree = self.fil.Get(theTree) + self.undoDecays = undoDecays + self.baseheader = "\n" + self.baseline1 = " {nparts} {prid} {weight} {scale} {aqed} {aqcd}\n" + self.baseender = "\n\n\n" + self.chunkers = chunkers + + def insideLoop(self): + """ Loop over all events and process the root file into a plain text LHE file""" + totalEvents = self.tree.GetEntries() + if self.chunkers == -1 or self.chunkers > totalEvents: + self.output = open(self.outputLHE,"w") + self.chunkers = totalEvents + 1 + else: + self.output = open(self.outputLHE+"chunk0","w") + chunk = 0 + + print "Processing %i events, please wait..."%totalEvents + iEv = 0 + pEv = 0 + chunk = 0 + for ev in self.tree: + iEv += 1 + pEv += 1 + if pEv >= self.chunkers: + pEv = 0 + chunk += 1 + self.output.close() + self.output = open(self.outputLHE+"chunk%i"%chunk,"w") + print "...Event %i/%i"%(iEv, totalEvents) + self.process(ev) + + def process(self, ev): + """First produce the global line like """ + self.output.write(self.baseheader.format(nplo = ord(str(ev.LHE_NpLO)) if ord(str(ev.LHE_NpLO)) != 255 else -1, npnlo = ord(str(ev.LHE_NpNLO)) if ord(str(ev.LHE_NpNLO)) != 255 else -1)) + + """Then we need to treat the whole thing to undo the madspin decays, update statuses and rewrite particle order""" + lhepart = [] + deletedIndexes = [] + for i in range(getattr(ev, "nLHEPart")): + testPart = HEPPart(ev,i) + testPart.mother1 = testPart.mother1 - sum([1*(testPart.mother1 > d) for d in deletedIndexes]) + testPart.mother2 = testPart.mother2 - sum([1*(testPart.mother2 > d) for d in deletedIndexes]) + if testPart.mother1 != 0: + if abs(lhepart[testPart.mother1-1].pdgId) in self.undoDecays: #If from something that decays after weighting just skip it and update particle indexes + deletedIndexes.append(i) + continue + if abs(testPart.pdgId) in self.undoDecays: + testPart.status = 1 + lhepart.append(testPart) + + """ Now we can compute properly the number of particles at LHE """ + self.output.write(self.baseline1.format(nparts=len(lhepart), prid=self.prDict[str(ord(str(ev.LHE_ProcessID)))], weight=ev.LHEWeight_originalXWGTUP, scale=ev.LHE_Scale,aqed=ev.LHE_AlphaQED,aqcd=ev.LHE_AlphaS)) + """ And save each particle information """ + for part in lhepart: + self.output.write(part.printPart()) + self.output.write(self.baseender) + +theP = LHEPrinter(args[1],"Events",args[2],undoDecays=[int(i) for i in args[4:]],chunkers=int(args[3]), prDict={str(i):i for i in range(1000)}) #PRDict by default set to not change anything as it is rare to use it +theP.insideLoop() diff --git a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h index 1e815e2d5f414..35446d7172e78 100644 --- a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h +++ b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h @@ -46,24 +46,24 @@ namespace genCounter { //incPSOnly(w0, wPS); } - void mergeSumMap(const Counter& other) { - num_ += other.num_; - sumw_ += other.sumw_; - sumw2_ += other.sumw2_; - //if weightMap_ for "this" is empty, create map elements with empty - //vectors before merging - if(weightSumMap_.empty() && !other.weightSumMap_.empty()) { - for(auto& wmap : other.weightSumMap_) { - std::vector temp; - weightSumMap_.insert({wmap.first, temp}); - } + void mergeSumMap(const Counter& other) { + num_ += other.num_; + sumw_ += other.sumw_; + sumw2_ += other.sumw2_; + //if weightMap_ for "this" is empty, create map elements with empty + //vectors before merging + if (weightSumMap_.empty() && !other.weightSumMap_.empty()) { + for (auto& wmap : other.weightSumMap_) { + std::vector temp; + weightSumMap_.insert({wmap.first, temp}); } + } - for(auto& wmap : weightSumMap_) { - if (other.weightSumMap_.find(wmap.first) != other.weightSumMap_.end()) - mergeSumVectors(wmap.second, other.weightSumMap_.at(wmap.first)); - } + for (auto& wmap : weightSumMap_) { + if (other.weightSumMap_.find(wmap.first) != other.weightSumMap_.end()) + mergeSumVectors(wmap.second, other.weightSumMap_.at(wmap.first)); } + } //private: // the counters diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 4d206a7bbd5d6..8d150751bab83 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -19,9 +19,7 @@ #include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" #include "FWCore/Utilities/interface/transform.h" #include "PhysicsTools/NanoAOD/interface/GenWeightCounters.h" -#include #include -#include namespace { typedef std::vector WeightGroupDataContainer; @@ -38,24 +36,23 @@ class GenWeightsTableProducer : public edm::global::EDProducer>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - std::unique_ptr>& lheWeightTablevec, - const char* typeName, + void addWeightGroupToTable( + std::unique_ptr>& weightTablevec, const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - Counter& counter, - double genWeight) const; - WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, + WeightsContainer& allWeights) const; + // Need to either pass the handle or a pointer to avoid a copy and conversion to the base class + WeightGroupDataContainer weightDataPerType(edm::Handle& weightsInfoHandle, gen::WeightType weightType, int& maxStore) const; - std::vector orderedScaleWeights(const std::vector& scaleWeights, + WeightGroupsToStore groupsToStore(bool foundLheWeights, + edm::Handle& genWeightInfoHandle, + edm::Handle& lheWeightInfoHandle) const; + + std::pair> orderedScaleWeights(const std::vector& scaleWeights, const gen::ScaleWeightGroupInfo& scaleGroup) const; - std::vector preferredPSweights(const std::vector& psWeights, + std::pair> preferredPSweights(const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo& pswV) const; //Lumiblock @@ -72,28 +69,18 @@ class GenWeightsTableProducer : public edm::global::EDProducer genWeightInfoHandle; - iLumi.getByToken(genWeightInfoToken_, genWeightInfoHandle); - - std::unordered_map storePerType; - for (size_t i = 0; i < weightgroups_.size(); i++) - storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); - WeightGroupsToStore weightsToStore; - for (auto weightType : gen::allWeightTypes) { - if (foundLheWeights) { - auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : lheWeights) - weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); + edm::Handle genWeightInfoHandle; + for (auto& token : genWeightInfoTokens_) { + iLumi.getByToken(token, genWeightInfoHandle); + if (genWeightInfoHandle.isValid()) { + break; } - auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : genWeights) - weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); } - return std::make_shared(weightsToStore); + auto tostore = groupsToStore(foundLheWeights, genWeightInfoHandle, lheWeightInfoHandle); + return std::make_shared(tostore); } - // nothing to do here void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} // create an empty counter std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } @@ -135,8 +122,8 @@ class GenWeightsTableProducer : public edm::global::EDProducer> lheWeightTokens_; const std::vector> lheWeightInfoTokens_; - const edm::EDGetTokenT genWeightToken_; - const edm::EDGetTokenT genWeightInfoToken_; + const std::vector> genWeightTokens_; + const std::vector> genWeightInfoTokens_; const edm::EDGetTokenT genEventInfoToken_; const edm::EDGetTokenT genLumiInfoHeadTag_; const std::vector weightgroups_; @@ -149,9 +136,11 @@ class GenWeightsTableProducer : public edm::global::EDProducer weightGroupIndices_; int lheWeightPrecision_; bool keepAllPSWeights_; + bool ignoreLheGroups_ = true; + bool ignoreGenGroups_ = false; + int nStoreUngroupedLhe_ = 105; enum { inLHE, inGen }; }; @@ -159,13 +148,16 @@ class GenWeightsTableProducer : public edm::global::EDProducer>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), lheWeightInfoTokens_(edm::vector_transform( params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - genWeightToken_(consumes(params.getParameter("genWeights"))), - genWeightInfoToken_( - consumes(params.getParameter("genWeights"))), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightTokens_( + edm::vector_transform(params.getParameter>("genWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightInfoTokens_( + edm::vector_transform(params.getParameter>("genWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), genEventInfoToken_(consumes(params.getParameter("genEvent"))), genLumiInfoHeadTag_( mayConsume(params.getParameter("genLumiInfoHeader"))), @@ -176,11 +168,7 @@ GenWeightsTableProducer::GenWeightsTableProducer(edm::ParameterSet const& params lheWeightPrecision_(params.getParameter("lheWeightPrecision")), keepAllPSWeights_(params.getParameter("keepAllPSWeights")) { if (weightgroups_.size() != maxGroupsPerType_.size()) - throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); - for (auto& wg : weightTypeNames_) { - produces(wg.second); - produces(wg.second + "sizes"); - } + throw std::invalid_argument("Inputs 'weightgroups' and 'maxGroupsPerType' must have equal size"); produces("GENWeight"); produces(); produces("genModel"); @@ -199,8 +187,7 @@ void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons break; } } - //Taken from genweight producer //Added sroychow - // generator information (always available) + auto const& genInfo = iEvent.get(genEventInfoToken_); const double genWeight = genInfo.weight(); // table for gen info, always available @@ -222,128 +209,107 @@ void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons } edm::Handle genWeightHandle; - iEvent.getByToken(genWeightToken_, genWeightHandle); + for (auto& token : genWeightTokens_) { + iEvent.getByToken(token, genWeightHandle); + if (genWeightHandle.isValid()) { + break; + } + } const GenWeightProduct* genWeightProduct = genWeightHandle.product(); WeightsContainer genWeights = genWeightProduct->weights(); auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); //create a container with dummy weight vector - std::map> lheWeightTables; - std::map> weightVecsizes; - std::map weightlabels; - for (auto& wg : weightTypeNames_) { - lheWeightTables.insert(std::make_pair(wg.first, std::vector())); - weightVecsizes.insert(std::make_pair(wg.first, std::vector())); - weightlabels.insert(std::make_pair(wg.first, "")); - } - - auto lheWeightTablevec = std::make_unique>(); + auto weightTablevec = std::make_unique>(); if (foundLheWeights) { - addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, lheWeightTablevec, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); + addWeightGroupToTable(weightTablevec, weightInfos.at(inLHE), lheWeights); } - addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, lheWeightTablevec, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); - - for (auto& wg : weightTypeNames_) { - std::string wname = wg.second; - auto& weightVec = lheWeightTables[wg.first]; - counter.incLHE(genWeight, weightVec, wname); - auto outTable = std::make_unique(weightVec.size(), wname, false); - outTable->addColumn("", weightVec, weightlabels[wg.first], lheWeightPrecision_); - - //now add the vector containing the sizes of alt sets - auto outTableSizes = - std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); - outTableSizes->addColumn( - "", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, lheWeightPrecision_); - iEvent.put(std::move(outTable), wname); - iEvent.put(std::move(outTableSizes), wname + "sizes"); - } - iEvent.put(std::move(lheWeightTablevec),"LHEWeightTableVec"); -} + addWeightGroupToTable(weightTablevec, weightInfos.at(inGen), genWeights); -/* + iEvent.put(std::move(weightTablevec),"LHEWeightTableVec"); +} -*/ -void GenWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - std::unique_ptr>& lheWeightTablevec, - const char* typeName, +void GenWeightsTableProducer::addWeightGroupToTable( + std::unique_ptr>& weightTablevec, const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - Counter& counter, - double genWeight) const { + WeightsContainer& allWeights) const { std::unordered_map typeCount = {}; for (auto& type : gen::allWeightTypes) typeCount[type] = 0; + // TODO: Handle keepAllWeights for (const auto& groupInfo : weightInfos) { - std::string entryName = typeName; gen::WeightType weightType = groupInfo.group->weightType(); - std::string name = weightTypeNames_.at(weightType); - std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->description(); - label.append("["); - label.append(std::to_string(lheWeightTables[weightType].size())); //to append the start index of this set - label.append("]; "); + std::string entryName = weightTypeNames_.at(weightType); + std::string label = groupInfo.group->description(); auto& weights = allWeights.at(groupInfo.index); - //std::cout << "Group name is " << groupInfo.group->name() << " is it wellFormed? " << groupInfo.group->isWellFormed() << std::endl; if (weightType == gen::WeightType::kScaleWeights) { - if (groupInfo.group->isWellFormed()) { - const auto scaleGroup = *static_cast(groupInfo.group.get()); - std::cout << "They're well formed, will be ordered as expected\n"; - weights = orderedScaleWeights(weights, scaleGroup); - label.append( - "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" - " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" - " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); - } else { - std::cout << "NOT WELL FORMED!\n"; - size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); - weights = std::vector(begin(weights), std::begin(weights)+nstore); - label.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + - " elements of weights vector, unordered"); - } - // TODO: Handle storeAllWeights and !isWellFormed - } else if (!keepAllPSWeights_ && weightType == gen::WeightType::kPartonShowerWeights && - groupInfo.group->isWellFormed()) { - const auto psGroup = *static_cast(groupInfo.group.get()); - weights = preferredPSweights(weights, psGroup); - label.append( - "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is " - "ISR=1 FSR=2"); + const auto& scaleGroup = *std::static_pointer_cast(groupInfo.group); + auto weightsAndLabel = orderedScaleWeights(weights, scaleGroup); + label.append(weightsAndLabel.first); + weights = weightsAndLabel.second; + } else if (weightType == gen::WeightType::kPartonShowerWeights) { + const auto& psGroup = *std::static_pointer_cast(groupInfo.group); + auto weightsAndLabel = preferredPSweights(weights, psGroup); + label.append(weightsAndLabel.first); + weights = weightsAndLabel.second; } - //else - // label.append(groupInfo.group->description()); - lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); - weightVecsizes[weightType].emplace_back(weights.size()); + else + label.append(groupInfo.group->description()); - if (weightlabels[weightType].empty()) - weightlabels[weightType].append("[idx in AltSetSizes array] Name [start idx in weight array];\n"); if(typeCount[weightType] > 0) { entryName.append("AltSet"); entryName.append(std::to_string(typeCount[weightType])); } - lheWeightTablevec->emplace_back(weights.size(), entryName, false); - lheWeightTablevec->back().addColumn("", weights, label, lheWeightPrecision_); - + weightTablevec->emplace_back(weights.size(), entryName, false); + weightTablevec->back().addColumn("", weights, label, lheWeightPrecision_); - weightlabels[weightType].append(label); typeCount[weightType]++; } } -WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, +WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, + edm::Handle& genWeightInfoHandle, + edm::Handle& lheWeightInfoHandle) const { + std::unordered_map storePerType; + for (size_t i = 0; i < weightgroups_.size(); i++) + storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); + + WeightGroupsToStore weightsToStore; + if (!(ignoreLheGroups_ && ignoreGenGroups_)) { + for (auto weightType : gen::allWeightTypes) { + if (foundLheWeights && !ignoreLheGroups_) { + auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); + for (auto& w : lheWeights) + weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); + } + if (!ignoreGenGroups_) { + auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); + for (auto& w : genWeights) + weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); + } + } + } + // For now treating 'ignoreGroups' as only relevant to LHE... + else if (ignoreLheGroups_) { + auto& allGroups = lheWeightInfoHandle->allWeightGroupsInfo(); + for (size_t i = 0; i < allGroups.size(); i++) { + weightsToStore.at(inLHE).push_back({i, std::make_shared(allGroups[i])}); + } + } + return weightsToStore; +} + +WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsInfoHandle, gen::WeightType weightType, int& maxStore) const { std::vector allgroups; if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { - allgroups = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); } else - allgroups = weightsHandle->weightGroupsAndIndicesByType(weightType); + allgroups = weightsInfoHandle->weightGroupsAndIndicesByType(weightType); int toStore = maxStore; if (maxStore < 0 || static_cast(allgroups.size()) <= maxStore) { @@ -361,32 +327,59 @@ WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle< return out; } -std::vector GenWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo& scaleGroup) const { +std::pair> +GenWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, + const gen::ScaleWeightGroupInfo& scaleGroup) const { std::vector weights; - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.centralIndex())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); - - return weights; + std::string labels = "LHE scale variation weights (w_var / w_nominal); "; + if (scaleGroup.isWellFormed()) { + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); + labels += "[0] is muR=0.5 muF=0.5; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF1Index())); + labels += "[1] is muR=0.5 muF=1; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF2Index())); + labels += "[2] is muR=0.5 muF=2; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF05Index())); + labels += "[3] is muR=1 muF=0.5; "; + weights.emplace_back(scaleWeights.at(scaleGroup.centralIndex())); + labels += "[4] is muR=1 muF=1; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF2Index())); + labels += "[5] is muR=1 muF=2; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF05Index())); + labels += "[6] is muR=2 muF=0.5; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF1Index())); + labels += "[7] is muR=2 muF=1; "; + weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); + labels += "[8] is muR=2 muF=2"; + } + else { + size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); + weights = std::vector(begin(weights), std::begin(weights)+nstore); + labels.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + + " elements of weights vector, unordered"); + } + + return std::make_pair(labels, weights); } -std::vector GenWeightsTableProducer::preferredPSweights(const std::vector& psWeights, +std::pair> GenWeightsTableProducer::preferredPSweights(const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo& pswV) const { std::vector psTosave; - double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, true, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, true, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, false, gen::PSVarType::def)) / baseline); - return psTosave; + std::string labels = "PS weights (w_var / w_nominal); "; + // TODO: Probably just drop them if they aren't well formed... + if (pswV.isWellFormed()) { + double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); + psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); + labels += "[0] is ISR=2 FSR=1; "; + psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, false, gen::PSVarType::def)) / baseline); + labels += "[1] is ISR=1 FSR=2; "; + psTosave.emplace_back(psWeights.at(pswV.isrCombinedDownIndex(gen::PSVarType::def)) / baseline); + labels += "[2] is ISR=0.5 FSR=1; "; + psTosave.emplace_back(psWeights.at(pswV.fsrCombinedDownIndex(gen::PSVarType::def)) / baseline); + labels += "[3] is ISR=1 FSR=0.5; "; + } + return std::make_pair(labels, psTosave); } void GenWeightsTableProducer::streamEndRunSummary(edm::StreamID id, @@ -429,8 +422,7 @@ void GenWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d desc.add>("lheWeights"); desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); - //desc.add>("genWeights"); - desc.add("genWeights"); + desc.add>("genWeights", std::vector{{"genWeights"}}); desc.add("genEvent", edm::InputTag("generator")) ->setComment("tag for the GenEventInfoProduct, to get the main weight"); desc.add("genLumiInfoHeader", edm::InputTag("generator")) diff --git a/PhysicsTools/NanoAOD/plugins/LHETablesProducer.cc b/PhysicsTools/NanoAOD/plugins/LHETablesProducer.cc index f99d453815838..9c9ac2117c46c 100644 --- a/PhysicsTools/NanoAOD/plugins/LHETablesProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/LHETablesProducer.cc @@ -17,7 +17,8 @@ class LHETablesProducer : public edm::global::EDProducer<> { : lheTag_(edm::vector_transform(params.getParameter>("lheInfo"), [this](const edm::InputTag& tag) { return mayConsume(tag); })), precision_(params.getParameter("precision")), - storeLHEParticles_(params.getParameter("storeLHEParticles")) { + storeLHEParticles_(params.getParameter("storeLHEParticles")), + storeAllLHEInfo_(params.getParameter("storeAllLHEInfo")) { produces("LHE"); if (storeLHEParticles_) produces("LHEPart"); @@ -54,7 +55,9 @@ class LHETablesProducer : public edm::global::EDProducer<> { unsigned int lheNj = 0, lheNb = 0, lheNc = 0, lheNuds = 0, lheNglu = 0; double lheVpt = 0; double alphaS = 0; - + double alphaQED = 0; + double scale = 0; + int idproc = 0; const auto& hepeup = lheProd.hepeup(); const auto& pup = hepeup.PUP; int lep = -1, lepBar = -1, nu = -1, nuBar = -1; @@ -63,18 +66,33 @@ class LHETablesProducer : public edm::global::EDProducer<> { std::vector vals_phi; std::vector vals_mass; std::vector vals_pz; + std::vector vals_time; std::vector vals_pid; std::vector vals_status; std::vector vals_spin; + std::vector vals_col1; + std::vector vals_col2; + std::vector vals_mother1; + std::vector vals_mother2; alphaS = hepeup.AQCDUP; + alphaQED = hepeup.AQEDUP; + scale = hepeup.SCALUP; + idproc = hepeup.IDPRUP; for (unsigned int i = 0, n = pup.size(); i < n; ++i) { int status = hepeup.ISTUP[i]; int idabs = std::abs(hepeup.IDUP[i]); - if (status == 1 || status == -1 || (status == 2 && (idabs >= 23 && idabs <= 25))) { + if (status == 1 || status == -1 || (status == 2 && (idabs >= 23 && idabs <= 25)) || storeAllLHEInfo_) { TLorentzVector p4(pup[i][0], pup[i][1], pup[i][2], pup[i][3]); // x,y,z,t vals_pid.push_back(hepeup.IDUP[i]); vals_spin.push_back(hepeup.SPINUP[i]); vals_status.push_back(status); + if (storeAllLHEInfo_) { + vals_col1.push_back(hepeup.ICOLUP[i].first); + vals_col2.push_back(hepeup.ICOLUP[i].second); + vals_mother1.push_back(hepeup.MOTHUP[i].first); + vals_mother2.push_back(hepeup.MOTHUP[i].second); + vals_time.push_back(hepeup.VTIMUP[i]); + } if (status == -1) { vals_pt.push_back(0); vals_eta.push_back(0); @@ -143,7 +161,11 @@ class LHETablesProducer : public edm::global::EDProducer<> { out.addColumnValue("NpNLO", lheProd.npNLO(), "number of partons at NLO"); out.addColumnValue("NpLO", lheProd.npLO(), "number of partons at LO"); out.addColumnValue("AlphaS", alphaS, "Per-event alphaS"); - + if (storeAllLHEInfo_) { + out.addColumnValue("AlphaQED", alphaQED, "Per-event alphaQED"); + out.addColumnValue("Scale", scale, "Per-event scale"); + out.addColumnValue("ProcessID", idproc, "Process id (as in the card ordering)"); + } auto outPart = std::make_unique(vals_pt.size(), "LHEPart", false); outPart->addColumn("pt", vals_pt, "Pt of LHE particles", this->precision_); outPart->addColumn("eta", vals_eta, "Pseodorapidity of LHE particles", this->precision_); @@ -153,7 +175,13 @@ class LHETablesProducer : public edm::global::EDProducer<> { outPart->addColumn("pdgId", vals_pid, "PDG ID of LHE particles"); outPart->addColumn("status", vals_status, "LHE particle status; -1:incoming, 1:outgoing"); outPart->addColumn("spin", vals_spin, "Spin of LHE particles"); - + if (storeAllLHEInfo_) { + outPart->addColumn("color1", vals_col1, "First color index of LHE particles"); + outPart->addColumn("color2", vals_col2, "Second color index of LHE particles"); + outPart->addColumn("mother1", vals_mother1, "First mother index of LHE particles"); + outPart->addColumn("mother2", vals_mother2, "Second mother index of LHE particles"); + outPart->addColumn("lifetime", vals_time, "Own lifetime of LHE particles", this->precision_); + } return outPart; } @@ -164,6 +192,8 @@ class LHETablesProducer : public edm::global::EDProducer<> { desc.add("precision", -1)->setComment("precision on the 4-momenta of the LHE particles"); desc.add("storeLHEParticles", false) ->setComment("Whether we want to store the 4-momenta of the status 1 particles at LHE level"); + desc.add("storeAllLHEInfo", false) + ->setComment("Whether to store the whole set of intermediate LHE particles, not only the status +/-1 ones"); descriptions.add("lheInfoTable", desc); } @@ -171,6 +201,7 @@ class LHETablesProducer : public edm::global::EDProducer<> { const std::vector> lheTag_; const unsigned int precision_; const bool storeLHEParticles_; + const bool storeAllLHEInfo_; }; #include "FWCore/Framework/interface/MakerMacros.h" diff --git a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc index 4d83d34efec2f..26ada163f6eee 100644 --- a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc +++ b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc @@ -45,6 +45,8 @@ #include +#include "tbb/task_arena.h" + class NanoAODOutputModule : public edm::one::OutputModule<> { public: NanoAODOutputModule(edm::ParameterSet const& pset); @@ -121,12 +123,14 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { std::vector m_tables; std::vector m_tableTokens; std::vector m_tableVectorTokens; + std::vector m_runFlatTableTokens; std::vector m_triggers; bool m_triggers_areSorted = false; std::vector m_evstrings; std::vector m_runTables; std::vector m_lumiTables; + std::vector m_runFlatTables; std::vector> m_nanoMetadata; }; @@ -234,7 +238,7 @@ void NanoAODOutputModule::write(edm::EventForOutput const& iEvent) { // fill event branches for (auto& t : m_evstrings) t.fill(iEvent, *m_tree); - m_tree->Fill(); + tbb::this_task_arena::isolate([&] { m_tree->Fill(); }); m_processHistoryRegistry.registerProcessHistory(iEvent.processHistory()); } @@ -248,7 +252,7 @@ void NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput con for (auto& t : m_lumiTables) t.fill(iLumi, *m_lumiTree); - m_lumiTree->Fill(); + tbb::this_task_arena::isolate([&] { m_lumiTree->Fill(); }); m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory()); } @@ -262,6 +266,15 @@ void NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { for (auto& t : m_runTables) t.fill(iRun, *m_runTree); + for (unsigned int extensions = 0; extensions <= 1; ++extensions) { + size_t iRunTable = 0; + for (auto& token : m_runFlatTableTokens) { + edm::Handle handle; + iRun.getByToken(token, handle); + m_runFlatTables[iRunTable].fill(*handle, *m_runTree, extensions); + } + } + edm::Handle hstring; for (const auto& p : m_nanoMetadata) { iRun.getByToken(p.second, hstring); @@ -275,7 +288,7 @@ void NanoAODOutputModule::writeRun(edm::RunForOutput const& iRun) { } } - m_runTree->Fill(); + tbb::this_task_arena::isolate([&] { m_runTree->Fill(); }); m_processHistoryRegistry.registerProcessHistory(iRun.processHistory()); } @@ -313,8 +326,11 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { m_evstrings.clear(); m_runTables.clear(); m_lumiTables.clear(); + m_runFlatTables.clear(); + m_runFlatTableTokens.clear(); const auto& keeps = keptProducts(); for (const auto& keep : keeps[edm::InEvent]) { + std::cout << keep.first->className() << std::endl; if (keep.first->className() == "nanoaod::FlatTable") { m_tableTokens.emplace_back(keep.second); } else if (keep.first->className() == "std::vector") { @@ -331,7 +347,7 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { for (const auto& keep : keeps[edm::InLumi]) { if (keep.first->className() == "nanoaod::MergeableCounterTable") m_lumiTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); - else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") + else if (keep.first->className() == "nanoaod::UniqueString") m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); else throw cms::Exception( @@ -342,8 +358,10 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { for (const auto& keep : keeps[edm::InRun]) { if (keep.first->className() == "nanoaod::MergeableCounterTable") m_runTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); - else if (keep.first->className() == "nanoaod::UniqueString" && keep.first->moduleLabel() == "nanoMetadata") + else if (keep.first->className() == "nanoaod::UniqueString") m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); + else if (keep.first->className() == "nanoaod::FlatTable") + m_runFlatTableTokens.emplace_back(keep.second); else throw cms::Exception("Configuration", "NanoAODOutputModule cannot handle class " + keep.first->className() + " in Run branch"); diff --git a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc index abf25ffaf831b..d79b1c96436c4 100644 --- a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc +++ b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.cc @@ -25,6 +25,12 @@ void TableOutputBranches::defineBranchesFromFirstEvent(const nanoaod::FlatTable case nanoaod::FlatTable::ColumnType::Bool: m_uint8Branches.emplace_back(var, tab.columnDoc(i), "O"); break; + case nanoaod::FlatTable::ColumnType::UInt32: + m_uint32Branches.emplace_back(var, tab.columnDoc(i), "i"); + break; + case nanoaod::FlatTable::ColumnType::Double: + m_doubleBranches.emplace_back(var, tab.columnDoc(i), "D"); + break; default: throw cms::Exception("LogicError", "Unsupported type"); } @@ -49,7 +55,8 @@ void TableOutputBranches::branch(TTree &tree) { } } std::string varsize = m_singleton ? "" : "[n" + m_baseName + "]"; - for (std::vector *branches : {&m_floatBranches, &m_intBranches, &m_uint8Branches}) { + for (std::vector *branches : + {&m_floatBranches, &m_intBranches, &m_uint8Branches, &m_uint32Branches, &m_doubleBranches}) { for (auto &pair : *branches) { std::string branchName = makeBranchName(m_baseName, pair.name); pair.branch = @@ -88,4 +95,8 @@ void TableOutputBranches::fill(const nanoaod::FlatTable &tab, TTree &tree, bool fillColumn(pair, tab); for (auto &pair : m_uint8Branches) fillColumn(pair, tab); + for (auto &pair : m_uint32Branches) + fillColumn(pair, tab); + for (auto &pair : m_doubleBranches) + fillColumn(pair, tab); } diff --git a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h index c8e4366e48539..431917613daa6 100644 --- a/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h +++ b/PhysicsTools/NanoAOD/plugins/TableOutputBranches.h @@ -36,6 +36,8 @@ class TableOutputBranches { std::vector m_floatBranches; std::vector m_intBranches; std::vector m_uint8Branches; + std::vector m_uint32Branches; + std::vector m_doubleBranches; bool m_branchesBooked = false; template diff --git a/PhysicsTools/NanoAOD/python/NanoAODEDMEventContent_cff.py b/PhysicsTools/NanoAOD/python/NanoAODEDMEventContent_cff.py index d2e1f939d795e..c30f0c8238d41 100644 --- a/PhysicsTools/NanoAOD/python/NanoAODEDMEventContent_cff.py +++ b/PhysicsTools/NanoAOD/python/NanoAODEDMEventContent_cff.py @@ -3,7 +3,9 @@ NanoAODEDMEventContent = cms.PSet( outputCommands = cms.untracked.vstring( 'drop *', + "keep *_genWeightsTable_*_*", # event data "keep nanoaodFlatTable_*Table_*_*", # event data + "keep nanoaodFlatTables_*Table_*_*", # event data "keep edmTriggerResults_*_*_*", # event data "keep String_*_genModel_*", # generator model data "keep nanoaodMergeableCounterTable_*Table_*_*", # accumulated per/run or per/lumi data @@ -19,12 +21,15 @@ compressionLevel = cms.untracked.int32(9), compressionAlgorithm = cms.untracked.string("LZMA"), ) - -NanoGenOutput = NanoAODEDMEventContent.outputCommands[:] -NanoGenOutput.remove("keep edmTriggerResults_*_*_*") - NANOAODGENEventContent = cms.PSet( + outputCommands = cms.untracked.vstring( + 'drop *', + "keep *_genWeightsTable_*_*", # event data + "keep nanoaodFlatTable_*Table_*_*", # event data + "keep String_*_genModel_*", # generator model data + "keep nanoaodMergeableCounterTable_*Table_*_*", # accumulated per/run or per/lumi data + "keep nanoaodUniqueString_nanoMetadata_*_*", # basic metadata + ), compressionLevel = cms.untracked.int32(9), compressionAlgorithm = cms.untracked.string("LZMA"), - outputCommands = cms.untracked.vstring(NanoGenOutput) ) diff --git a/PhysicsTools/NanoAOD/python/genWeights_cff.py b/PhysicsTools/NanoAOD/python/genWeights_cff.py new file mode 100644 index 0000000000000..56ecb54c93175 --- /dev/null +++ b/PhysicsTools/NanoAOD/python/genWeights_cff.py @@ -0,0 +1,34 @@ +import FWCore.ParameterSet.Config as cms +from GeneratorInterface.Core.genWeights_cfi import genWeights +from GeneratorInterface.Core.lheWeights_cfi import lheWeights + +genWeightsNano = genWeights.clone() +genWeightsNano.weightProductLabels = ["genWeights"] +genWeightsNano.debug = True + +lheWeightsNano = lheWeights.clone() +lheWeightsNano.weightProductLabels = ["lheWeights"] +lheWeightsNano.debug = True + +genWeightsTable = cms.EDProducer("GenWeightsTableProducer", + lheWeightPrecision = cms.int32(14), + lheWeights = cms.VInputTag(["lheWeights", "lheWeightsNano"]), + genWeights = cms.VInputTag(["genWeights", "genWeightsNano"]), + genLumiInfoHeader = cms.InputTag("generator"), + # Warning: you can use a full string, but only the first character is read. + # Note also that the capitalization is important! For example, 'parton shower' + # must be lower case and 'PDF' must be capital + weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), + # Max number of groups to store for each type above, -1 ==> store all found + maxGroupsPerType = cms.vint32([-1, -1, -1, -1, 1]), + # If empty or not specified, no criteria are applied to filter on LHAPDF IDs + #pdfIds = cms.untracked.vint32([91400, 306000, 260000]), + #unknownOnlyIfEmpty = cms.untracked.vstring(['scale', 'PDF']), + #unknownOnlyIfAllEmpty = cms.untracked.bool(False), + keepAllPSWeights = cms.bool(False), + #ignoreGroups = cms.bool(True), + #storeUngrouped = cms.int32(100), +) + +#genWeightsTableTask = cms.Task(lheWeights, genWeights, genWeightsTable) +genWeightsTableTask = cms.Task(lheWeights, genWeightsNano, genWeightsTable) diff --git a/PhysicsTools/NanoAOD/python/nano_cff.py b/PhysicsTools/NanoAOD/python/nano_cff.py index 9b21c653c6c8c..ee07710630340 100644 --- a/PhysicsTools/NanoAOD/python/nano_cff.py +++ b/PhysicsTools/NanoAOD/python/nano_cff.py @@ -5,23 +5,25 @@ from PhysicsTools.NanoAOD.jets_cff import * from PhysicsTools.NanoAOD.muons_cff import * from PhysicsTools.NanoAOD.taus_cff import * +from PhysicsTools.NanoAOD.boostedTaus_cff import * from PhysicsTools.NanoAOD.electrons_cff import * +from PhysicsTools.NanoAOD.lowPtElectrons_cff import * from PhysicsTools.NanoAOD.photons_cff import * from PhysicsTools.NanoAOD.globals_cff import * from PhysicsTools.NanoAOD.extraflags_cff import * from PhysicsTools.NanoAOD.ttbarCategorization_cff import * from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * -from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.genWeights_cff import * +from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.vertices_cff import * from PhysicsTools.NanoAOD.met_cff import * from PhysicsTools.NanoAOD.triggerObjects_cff import * from PhysicsTools.NanoAOD.isotracks_cff import * from PhysicsTools.NanoAOD.protons_cff import * +from PhysicsTools.NanoAOD.btagWeightTable_cff import * from PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff import * - nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( tag = cms.string("untagged"), @@ -53,84 +55,40 @@ tauName=cms.string("Tau"),photonName=cms.string("Photon") ) -btagSFdir="PhysicsTools/NanoAOD/data/btagSF/" - -btagWeightTable = cms.EDProducer("BTagSFProducer", - src = cms.InputTag("linkedObjects","jets"), - cut = cms.string("pt > 25. && abs(eta) < 2.5"), - discNames = cms.vstring( - "pfCombinedInclusiveSecondaryVertexV2BJetTags", - "pfDeepCSVJetTags:probb+pfDeepCSVJetTags:probbb", #if multiple MiniAOD branches need to be summed up (e.g., DeepCSV b+bb), separate them using '+' delimiter - "pfCombinedMVAV2BJetTags" - ), - discShortNames = cms.vstring( - "CSVV2", - "DeepCSVB", - "CMVA" - ), - weightFiles = cms.vstring( #default settings are for 2017 94X. toModify function is called later for other eras. - btagSFdir+"CSVv2_94XSF_V2_B_F.csv", - btagSFdir+"DeepCSV_94XSF_V2_B_F.csv", - "unavailable" #if SFs for an algorithm in an era is unavailable, the corresponding branch will not be stored - ), - operatingPoints = cms.vstring("3","3","3"), #loose = 0, medium = 1, tight = 2, reshaping = 3 - measurementTypesB = cms.vstring("iterativefit","iterativefit","iterativefit"), #e.g. "comb", "incl", "ttbar", "iterativefit" - measurementTypesC = cms.vstring("iterativefit","iterativefit","iterativefit"), - measurementTypesUDSG = cms.vstring("iterativefit","iterativefit","iterativefit"), - sysTypes = cms.vstring("central","central","central") -) - -for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: # to be updated when SF for Summer16MiniAODv3 MC will be available - modifier.toModify(btagWeightTable, - cut = cms.string("pt > 25. && abs(eta) < 2.4"), #80X corresponds to 2016, |eta| < 2.4 - weightFiles = cms.vstring( #80X corresponds to 2016 SFs - btagSFdir+"CSVv2_Moriond17_B_H.csv", - "unavailable", - btagSFdir+"cMVAv2_Moriond17_B_H.csv" - ) - ) lhcInfoTable = cms.EDProducer("LHCInfoProducer", precision = cms.int32(10), ) -lheInfoTable = cms.EDProducer("LHETablesProducer", - lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), - precision = cms.int32(14), - storeLHEParticles = cms.bool(True), - storeAllLHEInfo = cms.bool(False), -) +nanoTableTaskCommon = cms.Task( + cms.Task(nanoMetadata), jetTask, extraFlagsProducersTask, muonTask, tauTask, boostedTauTask, + electronTask , lowPtElectronTask, photonTask, + vertexTask, isoTrackTask, jetLepTask, # must be after all the leptons + cms.Task(linkedObjects), + jetTablesTask, muonTablesTask, tauTablesTask, boostedTauTablesTask, + electronTablesTask, lowPtElectronTablesTask, photonTablesTask, + globalTablesTask, vertexTablesTask, metTablesTask, simpleCleanerTable, extraFlagsTableTask, + isoTrackTablesTask + ) -l1bits=cms.EDProducer("L1TriggerResultsConverter", src=cms.InputTag("gtStage2Digis"), legacyL1=cms.bool(False), - storeUnprefireableBit=cms.bool(True), src_ext=cms.InputTag("gtStage2Digis")) -(run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1).toModify(l1bits, storeUnprefireableBit=False) +nanoSequenceCommon = cms.Sequence(nanoTableTaskCommon) -nanoSequenceCommon = cms.Sequence( - nanoMetadata + jetSequence + muonSequence + tauSequence + electronSequence+photonSequence+vertexSequence+ - isoTrackSequence + jetLepSequence + # must be after all the leptons - linkedObjects + - jetTables + muonTables + tauTables + electronTables + photonTables + globalTables +vertexTables+ metTables+simpleCleanerTable + isoTrackTables - ) -nanoSequenceOnlyFullSim = cms.Sequence(triggerObjectTables + l1bits) -nanoSequenceOnlyData = cms.Sequence(protonTables + lhcInfoTable) +nanoSequenceOnlyFullSim = cms.Sequence(triggerObjectTablesTask) +nanoSequenceOnlyData = cms.Sequence(cms.Sequence(protonTablesTask) + lhcInfoTable) nanoSequence = cms.Sequence(nanoSequenceCommon + nanoSequenceOnlyData + nanoSequenceOnlyFullSim) -nanoSequenceFS = cms.Sequence(genParticleSequence + genVertexTables + particleLevelSequence + nanoSequenceCommon + jetMC + muonMC + electronMC + photonMC + tauMC + metMC + ttbarCatMCProducers + globalTablesMC + btagWeightTable + genWeightsTable + genVertexTable + genParticleTables + particleLevelTables + lheInfoTable + ttbarCategoryTable ) +nanoTableTaskFS = cms.Task(genParticleTask, particleLevelTask, jetMCTask, muonMCTask, electronMCTask, lowPtElectronMCTask, photonMCTask, + tauMCTask, boostedTauMCTask, + metMCTable, ttbarCatMCProducersTask, globalTablesMCTask, cms.Task(btagWeightTable), ttbarCategoryTableTask, + genWeightsTableTask, genVertexTablesTask, genParticleTablesTask, particleLevelTablesTask) -(run2_nanoAOD_92X | run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94X2016 | \ - run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | \ - run2_nanoAOD_102Xv1).toReplaceWith(nanoSequenceFS, nanoSequenceFS.copyAndExclude([genVertexTable, genVertexT0Table])) +nanoSequenceFS = cms.Sequence(nanoSequenceCommon + cms.Sequence(nanoTableTaskFS)) # GenVertex only stored in newer MiniAOD nanoSequenceMC = nanoSequenceFS.copy() nanoSequenceMC.insert(nanoSequenceFS.index(nanoSequenceCommon)+1,nanoSequenceOnlyFullSim) -# modify extraFlagsTable to store ecalBadCalibFilter decision which is re-run with updated bad crystal list for 2017 and 2018 samples -for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1: - modifier.toModify(extraFlagsTable, variables= cms.PSet()) - modifier.toModify(extraFlagsTable, variables = dict(Flag_ecalBadCalibFilterV2 = ExtVar(cms.InputTag("ecalBadCalibFilterNanoTagger"), bool, doc = "Bad ECAL calib flag (updated xtal list)"))) - # modifier which adds new tauIDs (currently only deepTauId2017v2p1 is being added) import RecoTauTag.RecoTau.tools.runTauIdMVA as tauIdConfig def nanoAOD_addTauIds(process): @@ -138,9 +96,28 @@ def nanoAOD_addTauIds(process): tauIdEmbedder = tauIdConfig.TauIDEmbedder(process, debug = False, updatedTauName = updatedTauName, toKeep = [ "deepTau2017v2p1" ]) tauIdEmbedder.runTauID() - process.patTauMVAIDsSeq.insert(process.patTauMVAIDsSeq.index(getattr(process, updatedTauName)), - process.rerunMvaIsolationSequence) + _tauTask = patTauMVAIDsTask.copy() + _tauTask.add(process.rerunMvaIsolationTask) + _tauTask.add(finalTaus) + process.tauTask = _tauTask.copy() + return process + +def nanoAOD_addBoostedTauIds(process): + updatedBoostedTauName = "slimmedTausBoostedNewID" + boostedTauIdEmbedder = tauIdConfig.TauIDEmbedder(process, debug=False, + originalTauName = "slimmedTausBoosted", + updatedTauName = updatedBoostedTauName, + postfix="Boosted", + toKeep = [ "2017v2", "dR0p32017v2", "newDM2017v2","againstEle2018",]) + boostedTauIdEmbedder.runTauID() + _boostedTauTask = process.rerunMvaIsolationTaskBoosted.copy() + _boostedTauTask.add(getattr(process, updatedBoostedTauName)) + _boostedTauTask.add(process.finalBoostedTaus) + + process.boostedTauTask = _boostedTauTask.copy() + return process + from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection def nanoAOD_addDeepInfo(process,addDeepBTag,addDeepFlavour): @@ -165,55 +142,34 @@ def nanoAOD_addDeepInfo(process,addDeepBTag,addDeepFlavour): process.updatedJets.jetSource="selectedUpdatedPatJetsWithDeepInfo" return process -def nanoAOD_addDeepMET(process, addDeepMETProducer, ResponseTune_Graph): - if addDeepMETProducer: - # produce DeepMET on the fly if it is not in MiniAOD - print("add DeepMET Producers") - process.load('RecoMET.METPUSubtraction.deepMETProducer_cfi') - process.deepMETsResolutionTune = process.deepMETProducer.clone() - process.deepMETsResponseTune = process.deepMETProducer.clone() - #process.deepMETsResponseTune.graph_path = 'RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2018.pb' - process.deepMETsResponseTune.graph_path = ResponseTune_Graph.value() - process.metTables += process.deepMetTables - return process from PhysicsTools.PatUtils.tools.runMETCorrectionsAndUncertainties import runMetCorAndUncFromMiniAOD -from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD def nanoAOD_recalibrateMETs(process,isData): # add DeepMETs nanoAOD_DeepMET_switch = cms.PSet( - nanoAOD_addDeepMET_switch = cms.untracked.bool(True), # decide if DeeMET should be included in Nano - nanoAOD_produceDeepMET_switch = cms.untracked.bool(False), # decide if DeepMET should be computed on the fly ResponseTune_Graph = cms.untracked.string('RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2018.pb') ) - for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016, run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1, run2_nanoAOD_106Xv1: - # compute DeepMETs in these eras (before 111X) - modifier.toModify(nanoAOD_DeepMET_switch, nanoAOD_produceDeepMET_switch = cms.untracked.bool(True)) for modifier in run2_miniAOD_80XLegacy, run2_nanoAOD_94X2016: modifier.toModify(nanoAOD_DeepMET_switch, ResponseTune_Graph=cms.untracked.string("RecoMET/METPUSubtraction/data/deepmet/deepmet_resp_v1_2016.pb")) - if nanoAOD_DeepMET_switch.nanoAOD_addDeepMET_switch: - process = nanoAOD_addDeepMET(process, - addDeepMETProducer=nanoAOD_DeepMET_switch.nanoAOD_produceDeepMET_switch, - ResponseTune_Graph=nanoAOD_DeepMET_switch.ResponseTune_Graph) - - # if included in Nano, and not computed in the fly, then it should be extracted from minAOD - extractDeepMETs = nanoAOD_DeepMET_switch.nanoAOD_addDeepMET_switch and not nanoAOD_DeepMET_switch.nanoAOD_produceDeepMET_switch - - runMetCorAndUncFromMiniAOD(process,isData=isData, extractDeepMETs=extractDeepMETs) - process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.fullPatMetSequence)) - process.basicJetsForMetForT1METNano = process.basicJetsForMet.clone( - src = process.updatedJetsWithUserData.src, - skipEM = False, - type1JetPtThreshold = 0.0, - calcMuonSubtrRawPtAsValueMap = cms.bool(True), - ) - process.jetSequence.insert(process.jetSequence.index(process.updatedJetsWithUserData),cms.Sequence(process.basicJetsForMetForT1METNano)) - process.updatedJetsWithUserData.userFloats.muonSubtrRawPt = cms.InputTag("basicJetsForMetForT1METNano:MuonSubtrRawPt") - process.corrT1METJetTable.src = process.finalJets.src - process.corrT1METJetTable.cut = "pt<15 && abs(eta)<9.9" - for table in process.jetTable, process.corrT1METJetTable: - table.variables.muonSubtrFactor = Var("1-userFloat('muonSubtrRawPt')/(pt()*jecFactor('Uncorrected'))",float,doc="1-(muon-subtracted raw pt)/(raw pt)",precision=6) - process.metTables += process.corrT1METJetTable + + print("add DeepMET Producers") + process.load('RecoMET.METPUSubtraction.deepMETProducer_cfi') + process.deepMETsResolutionTune = process.deepMETProducer.clone() + process.deepMETsResponseTune = process.deepMETProducer.clone() + process.deepMETsResponseTune.graph_path = nanoAOD_DeepMET_switch.ResponseTune_Graph.value() + + runMetCorAndUncFromMiniAOD(process,isData=isData) + process.nanoSequenceCommon.insert(2,cms.Sequence(process.fullPatMetSequence)) + + + from PhysicsTools.PatAlgos.slimming.puppiForMET_cff import makePuppiesFromMiniAOD + makePuppiesFromMiniAOD(process,True) + process.puppiNoLep.useExistingWeights = True + process.puppi.useExistingWeights = True + run2_nanoAOD_106Xv1.toModify(process.puppiNoLep, useExistingWeights = False) + run2_nanoAOD_106Xv1.toModify(process.puppi, useExistingWeights = False) + print("will make Puppies on top of MINIAOD") + # makePuppiesFromMiniAOD(process,True) # call this before in the global customizer otherwise it would reset photon IDs in VID nanoAOD_PuppiV15_switch = cms.PSet( recoMetFromPFCs = cms.untracked.bool(False), @@ -243,32 +199,41 @@ def nanoAOD_recalibrateMETs(process,isData): process.patJetsPuppi.addGenPartonMatch = cms.bool(False) process.patJetsPuppi.addGenJetMatch = cms.bool(False) + + print("nanoAOD_PuppiV15_switch.reclusterJets is true") runMetCorAndUncFromMiniAOD(process,isData=isData,metType="Puppi",postfix="Puppi",jetFlavor="AK4PFPuppi", recoMetFromPFCs=bool(nanoAOD_PuppiV15_switch.recoMetFromPFCs), reclusterJets=bool(nanoAOD_PuppiV15_switch.reclusterJets)) - process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(process.jetSequence),cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) + process.nanoSequenceCommon.insert(2,cms.Sequence(process.puppiMETSequence+process.fullPatMetSequencePuppi)) + return process from PhysicsTools.SelectorUtils.tools.vid_id_tools import * def nanoAOD_activateVID(process): - switchOnVIDElectronIdProducer(process,DataFormat.MiniAOD) + + switchOnVIDElectronIdProducer(process,DataFormat.MiniAOD,electronTask) for modname in electron_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDElectronSelection) - process.electronSequence.insert(process.electronSequence.index(process.bitmapVIDForEle),process.egmGsfElectronIDSequence) - for modifier in run2_egamma_2017,run2_egamma_2018,run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: + + electronTask_ = process.egmGsfElectronIDTask.copy() + electronTask_.add(electronTask.copy()) + process.electronTask = electronTask_.copy() + for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: modifier.toModify(process.electronMVAValueMapProducer, src = "slimmedElectronsUpdated") modifier.toModify(process.egmGsfElectronIDs, physicsObjectSrc = "slimmedElectronsUpdated") - - switchOnVIDPhotonIdProducer(process,DataFormat.MiniAOD) # do not call this to avoid resetting photon IDs in VID, if called before inside makePuppiesFromMiniAOD + switchOnVIDPhotonIdProducer(process,DataFormat.MiniAOD,photonTask) # do not call this to avoid resetting photon IDs in VID, if called before inside makePuppiesFromMiniAOD for modname in photon_id_modules_WorkingPoints_nanoAOD.modules: setupAllVIDIdsInModule(process,modname,setupVIDPhotonSelection) - process.photonSequence.insert(process.photonSequence.index(bitmapVIDForPho),process.egmPhotonIDSequence) + + photonTask_ = process.egmPhotonIDTask.copy() + photonTask_.add(photonTask.copy()) + process.photonTask = photonTask_.copy() for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_94X2016,run2_nanoAOD_102Xv1: modifier.toModify(process.photonMVAValueMapProducer, src = "slimmedPhotonsTo106X") modifier.toModify(process.egmPhotonIDs, physicsObjectSrc = "slimmedPhotonsTo106X") return process -def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubleX, addDeepDoubleXV2, addParticleNet, jecPayload): +def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubleX, addDeepDoubleXV2, addParticleNet, addParticleNetMass, jecPayload): _btagDiscriminators=[] if addDeepBTag: print("Updating process to run DeepCSV btag to AK8 jets") @@ -281,6 +246,9 @@ def nanoAOD_addDeepInfoAK8(process, addDeepBTag, addDeepBoostedJet, addDeepDoubl print("Updating process to run ParticleNet before it's included in MiniAOD") from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetJetTagsAll as pfParticleNetJetTagsAll _btagDiscriminators += pfParticleNetJetTagsAll + if addParticleNetMass: + from RecoBTag.ONNXRuntime.pfParticleNet_cff import _pfParticleNetMassRegressionOutputs + _btagDiscriminators += _pfParticleNetMassRegressionOutputs if addDeepDoubleX: print("Updating process to run DeepDoubleX on datasets before 104X") _btagDiscriminators += ['pfDeepDoubleBvLJetTags:probHbb', \ @@ -317,14 +285,38 @@ def nanoAOD_runMETfixEE2017(process,isData): fixEE2017 = True, fixEE2017Params = {'userawPt': True, 'ptThreshold':50.0, 'minEtaThreshold':2.65, 'maxEtaThreshold': 3.139}, postfix = "FixEE2017") - process.nanoSequenceCommon.insert(process.nanoSequenceCommon.index(jetSequence),process.fullPatMetSequenceFixEE2017) + process.nanoSequenceCommon.insert(2,process.fullPatMetSequenceFixEE2017) + + +def nanoAOD_jetForT1met(process): + process.basicJetsForMetForT1METNano = cms.EDProducer("PATJetCleanerForType1MET", + src = process.updatedJetsWithUserData.src, + jetCorrEtaMax = cms.double(9.9), + jetCorrLabel = cms.InputTag("L3Absolute"), + jetCorrLabelRes = cms.InputTag("L2L3Residual"), + offsetCorrLabel = cms.InputTag("L1FastJet"), + skipEM = cms.bool(False), + skipEMfractionThreshold = cms.double(0.9), + skipMuonSelection = cms.string('isGlobalMuon | isStandAloneMuon'), + skipMuons = cms.bool(True), + type1JetPtThreshold = cms.double(0.0), + calcMuonSubtrRawPtAsValueMap = cms.bool(True) + ) + + process.jetTask.add(process.basicJetsForMetForT1METNano) + process.updatedJetsWithUserData.userFloats.muonSubtrRawPt = cms.InputTag("basicJetsForMetForT1METNano:MuonSubtrRawPt") + process.corrT1METJetTable.src = process.finalJets.src + process.corrT1METJetTable.cut = "pt<15 && abs(eta)<9.9" + process.metTablesTask.add(process.corrT1METJetTable) + + for table in process.jetTable, process.corrT1METJetTable: + table.variables.muonSubtrFactor = Var("1-userFloat('muonSubtrRawPt')/(pt()*jecFactor('Uncorrected'))",float,doc="1-(muon-subtracted raw pt)/(raw pt)",precision=6) + + return process def nanoAOD_customizeCommon(process): - makePuppiesFromMiniAOD(process,True) - process.puppiNoLep.useExistingWeights = True - process.puppi.useExistingWeights = True - run2_nanoAOD_106Xv1.toModify(process.puppiNoLep, useExistingWeights = False) - run2_nanoAOD_106Xv1.toModify(process.puppi, useExistingWeights = False) + + process = nanoAOD_jetForT1met(process) process = nanoAOD_activateVID(process) nanoAOD_addDeepInfo_switch = cms.PSet( nanoAOD_addDeepBTag_switch = cms.untracked.bool(False), @@ -342,6 +334,7 @@ def nanoAOD_customizeCommon(process): nanoAOD_addDeepDoubleX_switch = cms.untracked.bool(False), nanoAOD_addDeepDoubleXV2_switch = cms.untracked.bool(False), nanoAOD_addParticleNet_switch = cms.untracked.bool(False), + nanoAOD_addParticleNetMass_switch = cms.untracked.bool(False), jecPayload = cms.untracked.string('AK8PFPuppi') ) # deepAK8 should not run on 80X, that contains ak8PFJetsCHS jets @@ -355,52 +348,58 @@ def nanoAOD_customizeCommon(process): nanoAOD_addDeepDoubleX_switch = True, nanoAOD_addDeepDoubleXV2_switch = True, nanoAOD_addParticleNet_switch = True, - ) + nanoAOD_addParticleNetMass_switch = True, + ) # for 106Xv1: only needs to run ParticleNet and DDXV2; DeepAK8, DeepDoubleX are already in MiniAOD run2_nanoAOD_106Xv1.toModify( nanoAOD_addDeepInfoAK8_switch, nanoAOD_addDeepDoubleXV2_switch = True, nanoAOD_addParticleNet_switch = True, - ) + nanoAOD_addParticleNetMass_switch = True, + ) + + run2_nanoAOD_106Xv2.toModify( + nanoAOD_addDeepInfoAK8_switch, + nanoAOD_addParticleNetMass_switch = True, + ) + process = nanoAOD_addDeepInfoAK8(process, addDeepBTag=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBTag_switch, addDeepBoostedJet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepBoostedJet_switch, addDeepDoubleX=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleX_switch, addDeepDoubleXV2=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addDeepDoubleXV2_switch, addParticleNet=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addParticleNet_switch, + addParticleNetMass=nanoAOD_addDeepInfoAK8_switch.nanoAOD_addParticleNetMass_switch, jecPayload=nanoAOD_addDeepInfoAK8_switch.jecPayload) (run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1 | run2_nanoAOD_106Xv1).toModify(process, lambda p : nanoAOD_addTauIds(p)) + (~(run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94X2016 | run2_nanoAOD_94XMiniAODv2 | run2_nanoAOD_102Xv1 | run2_nanoAOD_106Xv1)).toModify(process, lambda p : nanoAOD_addBoostedTauIds(p)) return process def nanoAOD_customizeData(process): process = nanoAOD_customizeCommon(process) - process = nanoAOD_recalibrateMETs(process,isData=True) + + for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94X2016,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: + modifier.toModify(process, lambda p: nanoAOD_recalibrateMETs(p,isData=True)) for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2: modifier.toModify(process, lambda p: nanoAOD_runMETfixEE2017(p,isData=True)) return process def nanoAOD_customizeMC(process): process = nanoAOD_customizeCommon(process) - process = nanoAOD_recalibrateMETs(process,isData=False) + for modifier in run2_miniAOD_80XLegacy,run2_nanoAOD_94X2016,run2_nanoAOD_94XMiniAODv1,run2_nanoAOD_94XMiniAODv2,run2_nanoAOD_102Xv1,run2_nanoAOD_106Xv1: + modifier.toModify(process, lambda p: nanoAOD_recalibrateMETs(p,isData=False)) for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2: modifier.toModify(process, lambda p: nanoAOD_runMETfixEE2017(p,isData=False)) return process -### Era dependent customization -_80x_sequence = nanoSequenceCommon.copy() -#remove stuff -_80x_sequence.remove(isoTrackTables) -_80x_sequence.remove(isoTrackSequence) -#add stuff -_80x_sequence.insert(_80x_sequence.index(jetSequence), extraFlagsProducers) -_80x_sequence.insert(_80x_sequence.index(simpleCleanerTable)+1, extraFlagsTable) - -run2_miniAOD_80XLegacy.toReplaceWith( nanoSequenceCommon, _80x_sequence) - -_102x_sequence = nanoSequenceCommon.copy() -#add stuff -_102x_sequence.insert(_102x_sequence.index(jetSequence),extraFlagsProducers102x) -_102x_sequence.insert(_102x_sequence.index(simpleCleanerTable)+1,extraFlagsTable) - -for modifier in run2_nanoAOD_94XMiniAODv1, run2_nanoAOD_94XMiniAODv2, run2_nanoAOD_102Xv1: - modifier.toReplaceWith(nanoSequenceCommon, _102x_sequence) +###increasing the precision of selected GenParticles. +def nanoWmassGenCustomize(process): + pdgSelection="?(abs(pdgId) == 11|| abs(pdgId)==13 || abs(pdgId)==15 ||abs(pdgId)== 12 || abs(pdgId)== 14 || abs(pdgId)== 16|| abs(pdgId)== 24|| pdgId== 23)" + # Keep precision same as default RECO for selected particles + ptPrecision="{}?{}:{}".format(pdgSelection, CandVars.pt.precision.value(),genParticleTable.variables.pt.precision.value()) + process.genParticleTable.variables.pt.precision=cms.string(ptPrecision) + phiPrecision="{} ? {} : {}".format(pdgSelection, CandVars.phi.precision.value(), genParticleTable.variables.phi.precision.value()) + process.genParticleTable.variables.phi.precision=cms.string(phiPrecision) + etaPrecision="{} ? {} : {}".format(pdgSelection, CandVars.eta.precision.value(), genParticleTable.variables.eta.precision.value()) + process.genParticleTable.variables.eta.precision=cms.string(etaPrecision) + return process diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index 05828273f38f6..a580a067a2ef5 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -4,12 +4,9 @@ from PhysicsTools.NanoAOD.met_cff import metMCTable from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * -from PhysicsTools.NanoAOD.lheInfoTable_cfi import * from PhysicsTools.NanoAOD.genWeights_cff import * from PhysicsTools.NanoAOD.genVertex_cff import * from PhysicsTools.NanoAOD.common_cff import Var,CandVars -from PhysicsTools.NanoAOD.nano_eras_cff import * -from PhysicsTools.NanoAOD.genWeights_cff import * nanoMetadata = cms.EDProducer("UniqueStringProducer", strings = cms.PSet( @@ -18,34 +15,29 @@ ) nanogenSequence = cms.Sequence( - nanoMetadata+ - particleLevel+ - genJetTable+ - patJetPartons+ - genJetFlavourAssociation+ - genJetFlavourTable+ - genJetAK8Table+ - genJetAK8FlavourAssociation+ - genJetAK8FlavourTable+ - tauGenJets+ - tauGenJetsSelectorAllHadrons+ - genVisTaus+ - genVisTauTable+ - genTable+ - genParticleTables+ - genVertexTables+ - tautagger+ - rivetProducerHTXS+ - particleLevelTables+ - metMCTable+ - genWeightsTables+ - lheInfoTable + nanoMetadata + +cms.Sequence(particleLevelTask) + +genJetTable + +patJetPartonsNano + +genJetFlavourAssociation + +genJetFlavourTable + +genJetAK8Table + +genJetAK8FlavourAssociation + +genJetAK8FlavourTable + +cms.Sequence(genTauTask) + +genTable + +cms.Sequence(genParticleTablesTask) + +cms.Sequence(genVertexTablesTask) + +tautagger + +rivetProducerHTXS + +cms.Sequence(particleLevelTablesTask) + +metMCTable + +cms.Sequence(genWeightsTableTask) ) def nanoGenCommonCustomize(process): process.rivetMetTable.extension = False process.lheInfoTable.storeLHEParticles = True - process.lheInfoTable.storeAllLHEInfo = True process.lheInfoTable.precision = 14 process.genWeightsTable.keepAllPSWeights = True process.genJetFlavourAssociation.jets = process.genJetTable.src @@ -60,16 +52,13 @@ def nanoGenCommonCustomize(process): setGenPtPrecision(process, CandVars.pt.precision) setGenEtaPrecision(process, CandVars.eta.precision) setGenPhiPrecision(process, CandVars.phi.precision) + setGenMassPrecision(process, CandVars.mass.precision) def customizeNanoGENFromMini(process): process.nanogenSequence.insert(0, process.genParticles2HepMCHiggsVtx) process.nanogenSequence.insert(0, process.genParticles2HepMC) process.nanogenSequence.insert(0, process.mergedGenParticles) - (run2_nanoAOD_92X | run2_miniAOD_80XLegacy | run2_nanoAOD_94X2016 | run2_nanoAOD_94X2016 | \ - run2_nanoAOD_94XMiniAODv1 | run2_nanoAOD_94XMiniAODv2 | \ - run2_nanoAOD_102Xv1).toReplaceWith(nanogenSequence, nanogenSequence.copyAndExclude([genVertexTable, genVertexT0Table])) - process.metMCTable.src = "slimmedMETs" process.metMCTable.variables.pt = Var("genMET.pt", float, doc="pt") process.metMCTable.variables.phi = Var("genMET.phi", float, doc="phi") @@ -77,12 +66,12 @@ def customizeNanoGENFromMini(process): process.rivetProducerHTXS.HepMCCollection = "genParticles2HepMCHiggsVtx:unsmeared" process.genParticleTable.src = "prunedGenParticles" - process.patJetPartons.particles = "prunedGenParticles" + process.patJetPartonsNano.particles = "prunedGenParticles" process.particleLevel.src = "genParticles2HepMC:unsmeared" process.genJetTable.src = "slimmedGenJets" process.genJetAK8Table.src = "slimmedGenJetsAK8" - process.tauGenJets.GenParticles = "prunedGenParticles" + process.tauGenJetsForNano.GenParticles = "prunedGenParticles" process.genVisTaus.srcGenParticles = "prunedGenParticles" nanoGenCommonCustomize(process) @@ -95,12 +84,12 @@ def customizeNanoGEN(process): process.rivetProducerHTXS.HepMCCollection = "generatorSmeared" process.genParticleTable.src = "genParticles" - process.patJetPartons.particles = "genParticles" + process.patJetPartonsNano.particles = "genParticles" process.particleLevel.src = "generatorSmeared" process.genJetTable.src = "ak4GenJets" process.genJetAK8Table.src = "ak8GenJets" - process.tauGenJets.GenParticles = "genParticles" + process.tauGenJetsForNano.GenParticles = "genParticles" process.genVisTaus.srcGenParticles = "genParticles" # In case customizeNanoGENFromMini has already been called @@ -131,9 +120,11 @@ def pruneGenParticlesMini(process): return process def setGenFullPrecision(process): - setGenPtPrecision(process, 23) - setGenEtaPrecision(process, 23) - setGenPhiPrecision(process, 23) + process = setGenPtPrecision(process, 23) + process = setGenEtaPrecision(process, 23) + process = setGenPhiPrecision(process, 23) + process = setGenMassPrecision(process, 23) + return process def setGenPtPrecision(process, precision): process.genParticleTable.variables.pt.precision = precision @@ -152,6 +143,11 @@ def setGenPhiPrecision(process, precision): process.metMCTable.variables.phi.precision = precision return process +def setGenMassPrecision(process, precision): + process.genParticleTable.variables.mass.precision = precision + process.genJetTable.variables.mass.precision = precision + return process + def setLHEFullPrecision(process): process.lheInfoTable.precision = 23 return process diff --git a/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py b/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py index 5035ec39e78e4..9dd0db71d37d1 100644 --- a/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py +++ b/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py @@ -115,9 +115,10 @@ 'keep *_slimmedGenJetsAK8__*', 'keep *_slimmedGenJetsAK8SoftDropSubJets__*', 'keep *_genMetTrue_*_*', - # RUN 'keep LHERunInfoProduct_*_*_*', 'keep GenRunInfoProduct_*_*_*', + 'keep GenWeightProduct_*_*_*', + 'keep GenWeightInfoProduct_*_*_*', 'keep *_genParticles_xyz0_*', 'keep *_genParticles_t0_*', ) diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index c5e1e3c89a73a..b169299aadf04 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -21,6 +21,18 @@ namespace gen { int variationIndex(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; std::string variationName(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; int variationIndex(bool isISR, bool isUp, PSVarType variationType) const; + int isrCombinedUpIndex(PSVarType variationType) const { + return variationIndex(true, true, variationType); + } + int isrCombinedDownIndex(PSVarType variationType) const { + return variationIndex(true, false, variationType); + } + int fsrCombinedUpIndex(PSVarType variationType) const { + return variationIndex(false, true, variationType); + } + int fsrCombinedDownIndex(PSVarType variationType) const { + return variationIndex(false, false, variationType); + } static void setGuessPSWeightIdx(bool guessPSWeightIdx) { guessPSWeightIdx_ = guessPSWeightIdx; } int psWeightIdxGuess(const std::string &varName) const; void printVariables() const; diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index e9058546d584c..876eead42951f 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -31,6 +31,7 @@ namespace gen { kUnknownWeights = 'u', }; + //const std::array allWeightTypes = {{ const std::array allWeightTypes = {{ WeightType::kPdfWeights, WeightType::kScaleWeights, diff --git a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc index eba4d4571ce26..d54d00212e7b1 100644 --- a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc @@ -108,7 +108,7 @@ namespace gen { void PartonShowerWeightGroupInfo::printVariables() const { const auto& variations = (nameIsPythiaSyntax_) ? expectedOrderPythiaSyntax_ : expectedOrder_; - for (auto varName: variations) { + for (const auto& varName : variations) { int wgtIdx = weightIndexFromLabel(varName); // Guess PS idx if not in label list if (wgtIdx == -1 && guessPSWeightIdx_) diff --git a/SimDataFormats/GeneratorProducts/src/classes_def.xml b/SimDataFormats/GeneratorProducts/src/classes_def.xml index 24738e36f042b..bcd6bbda4730e 100644 --- a/SimDataFormats/GeneratorProducts/src/classes_def.xml +++ b/SimDataFormats/GeneratorProducts/src/classes_def.xml @@ -275,5 +275,6 @@ + From 85a4fe790f1b61065e427a9a7120f6f65bcbef2f Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Mon, 3 Jan 2022 02:09:21 +0100 Subject: [PATCH 11/16] Support ignoregroups in nano, fixes for unassociated weights --- .../StandardSequences/python/Generator_cff.py | 1 - .../Core/interface/WeightHelper.h | 11 +- .../Core/plugins/GenWeightProductProducer.cc | 4 +- GeneratorInterface/Core/src/WeightHelper.cc | 46 ++-- .../Core/test/dumpWeightInfo.py | 15 +- .../plugins/GenWeightsTableProducer.cc | 206 ++++++++++++++---- PhysicsTools/NanoAOD/python/genWeights_cff.py | 15 +- .../interface/GenWeightInfoProduct.h | 16 +- .../interface/GenWeightProduct.h | 2 +- .../interface/WeightGroupInfo.h | 6 +- .../src/GenWeightInfoProduct.cc | 13 +- .../src/PartonShowerWeightGroupInfo.cc | 2 +- .../GeneratorProducts/src/WeightGroupInfo.cc | 44 ++-- 13 files changed, 263 insertions(+), 118 deletions(-) diff --git a/Configuration/StandardSequences/python/Generator_cff.py b/Configuration/StandardSequences/python/Generator_cff.py index 8606236c14dd2..da9bbe1d99103 100644 --- a/Configuration/StandardSequences/python/Generator_cff.py +++ b/Configuration/StandardSequences/python/Generator_cff.py @@ -55,7 +55,6 @@ VertexSmearing = cms.Sequence(cms.SequencePlaceholder("VtxSmeared")) GenSmeared = cms.Sequence(generatorSmeared) GeneInfo = cms.Sequence(GeneInfoTask) -lheWeights.failIfInvalidXML = False genWeightsSeq = cms.Sequence(genWeights*lheWeights) genJetMET = cms.Sequence(genJetMETTask) diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index 099997c008d9c..05b4e4ef4140e 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -42,18 +42,21 @@ namespace gen { void addUnassociatedGroup() { weightGroups_.push_back(std::make_unique("unassociated")); weightGroups_.back().setDescription("Weights with missing or invalid header meta data"); + unassociatedIndex_ = weightGroups_.size()-1; } int addWeightToProduct( - std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex); + GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex); int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); void setDebug(bool value) { debug_ = value; } bool fillEmptyIfWeightFails() { return fillEmptyIfWeightFails_; } protected: // TODO: Make this only print from one thread a la - // https://github.com/kdlong/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 + // https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 bool debug_ = false; + bool allowUnassociatedWeights_ = true; bool fillEmptyIfWeightFails_ = false; + int unassociatedIndex_ = -1; const unsigned int FIRST_PSWEIGHT_ENTRY = 2; const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; std::string model_; @@ -108,9 +111,9 @@ namespace gen { for (const auto& weight : weights) { try { if constexpr (std::is_same::value) { - weightGroupIndex = addWeightToProduct(weightProduct, weight.wgt, weight.id, i, weightGroupIndex); + weightGroupIndex = addWeightToProduct(*weightProduct, weight.wgt, weight.id, i, weightGroupIndex); } else if (std::is_same::value) - weightGroupIndex = addWeightToProduct(weightProduct, weight, std::to_string(i), i, weightGroupIndex); + weightGroupIndex = addWeightToProduct(*weightProduct, weight, std::to_string(i), i, weightGroupIndex); } catch (cms::Exception& e) { if (fillEmptyIfWeightFails_) { diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index fb2bbbcd2121d..afef4a071604e 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -95,8 +95,8 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& boost::replace_all(label, "-", "_"); weightHelper_.setModel(label); weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames()); - if (weightHelper_.weightGroups().empty()) - weightHelper_.addUnassociatedGroup(); + // Always add an unassociated group, which generally will not be filled + weightHelper_.addUnassociatedGroup(); for (auto& weightGroup : weightHelper_.weightGroups()) { weightInfoProduct->addWeightGroupInfo(weightGroup); diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 8dca568848259..9eed436ba8669 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -167,7 +167,7 @@ namespace gen { } void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) { - if (psGroup.containedIds().size() == DEFAULT_PSWEIGHT_LENGTH) + if (psGroup.nIdsContained() == DEFAULT_PSWEIGHT_LENGTH) psGroup.setIsWellFormed(true); if (weight.content.find(':') != std::string::npos && weight.content.find('=') != std::string::npos) psGroup.setNameIsPythiaSyntax(true); @@ -212,42 +212,34 @@ namespace gen { } int WeightHelper::addWeightToProduct( - std::unique_ptr& product, double weight, std::string name, int weightNum, int groupIndex) { - bool isUnassociated = false; + GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex) { try { groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); } catch (const cms::Exception& e) { - std::cerr << "WARNING: " << e.what() << std::endl; - isUnassociated = true; - - bool foundUnassocGroup = false; - for (; static_cast(groupIndex) < weightGroups_.size(); ++groupIndex) { - auto& g = weightGroups_[groupIndex]; - if (g.weightType() == gen::WeightType::kUnknownWeights && g.name() == "unassociated") { - foundUnassocGroup = true; - break; - } - } - if (!foundUnassocGroup) { - addUnassociatedGroup(); - product->addWeightSet(); // Unaccounted for weights need a place + if (!allowUnassociatedWeights_ || unassociatedIndex_ == -1) + throw e; + if (debug_) { + std::cout << "WARNING: " << e.what() << std::endl; } + groupIndex = unassociatedIndex_; } // This should be impossible, but in case the try/catch doesn't work, come here if (groupIndex < 0 || groupIndex >= static_cast(weightGroups_.size())) - throw cms::Exception("Unmatched Generator weight! ID was " + name + " index was " + std::to_string(weightNum) + - "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); + throw cms::Exception("WeightHelper") << "Unmatched Generator weight! ID was " << name << " index was " << std::to_string(weightNum) << + "\nNot found in any of " << std::to_string(weightGroups_.size()) << " weightGroups."; auto& group = weightGroups_[groupIndex]; - - if (isUnassociated) { - group.addContainedId(weightNum, name, name); - } - - int entry = !isUnassociated ? group.weightVectorEntry(name, weightNum) : group.nIdsContained() - 1; + bool isUnassociated = groupIndex == unassociatedIndex_; + // NOTE: Adding the weight explicitly to the group is necessary for this code to work properly, + // but it WON'T be propagated to the group info in the GenWeightInfoProduct, which is + // already written to the lumi before the event processing. The Unknown group there will appear empty. + if (isUnassociated) + group.addContainedId(weightNum, name, name); + + int entry = group.weightVectorEntry(name, weightNum);//: group.nIdsContained() - 1; if (debug_) - std::cout << "Adding weight " << entry << " to group " << groupIndex << std::endl; - product->addWeight(weight, groupIndex, entry); + std::cout << "Adding weight num " << weightNum << " EntryNum " << entry << " to group " << groupIndex << std::endl; + product.addWeight(weight, groupIndex, entry); return groupIndex; } diff --git a/GeneratorInterface/Core/test/dumpWeightInfo.py b/GeneratorInterface/Core/test/dumpWeightInfo.py index 5aa70aff048c1..77cfd9ebcb882 100644 --- a/GeneratorInterface/Core/test/dumpWeightInfo.py +++ b/GeneratorInterface/Core/test/dumpWeightInfo.py @@ -11,23 +11,20 @@ lumis = Lumis(args.infile) lumi = next(lumis.__iter__()) weightInfoHandle = Handle("GenWeightInfoProduct") -print("Trying to get weightInfo from lumi") lumi.getByLabel(args.source, weightInfoHandle) weightInfoProd = weightInfoHandle.product() events = Events(args.infile) event = next(events.__iter__()) weightHandle = Handle("GenWeightProduct") -print("Trying to get weightProduct from event") event.getByLabel(args.source, weightHandle) weightInfo = weightHandle.product() print("Number of weight groups in weightInfo is", len(weightInfo.weights())) for j, weights in enumerate(weightInfo.weights()): print("-"*10, "Looking at entry", j, "length is", len(weights),"-"*10) matching = weightInfoProd.orderedWeightGroupInfo(j) - print("Group is", matching, "name is", matching.name(), "well formed?", matching.isWellFormed()) + print(f"name = {matching.name()}; type is {matching.weightType()}; Well formed? {str(matching.isWellFormed())}") print("Group description", matching.description()) - print(type(matching.weightType()), matching.weightType()) if matching.weightType() == 's': for var in [(x, y) for x in ["05", "1", "2"] for y in ["05", "1", "2"]]: name = "muR%smuF%sIndex" % (var[0], var[1]) if not (var[0] == "1" and var[1] == "1") else "centralIndex" @@ -35,10 +32,12 @@ elif matching.weightType() == 'P': print("uncertaintyType", "Hessian" if matching.uncertaintyType() == ROOT.gen.kHessianUnc else "MC") print("Has alphas? ", matching.hasAlphasVariations()) - print("Weights length?", len(weights), "Contained ids lenths?", len(matching.containedIds())) + print("Weights length?", len(weights), "Contained ids lenths?", matching.nIdsContained()) print("-"*80) for i,weight in enumerate(weights): - print(i, weight) - info = matching.weightMetaInfo(i) - print(" ID, localIndex, globalIndex, label, set:", info.id, info.localIndex, info.globalIndex, info.label, matching.name()) + try: + info = matching.weightMetaInfo(i) + print(" ID, localIndex, globalIndex, label, set:", info.id, info.localIndex, info.globalIndex, info.label, matching.name()) + except: + print(f"--> Entry {i} in group {matching.name()} does not have any associated metaInfo!") print("-"*80) diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 8d150751bab83..31d7382404ff3 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -20,6 +20,7 @@ #include "FWCore/Utilities/interface/transform.h" #include "PhysicsTools/NanoAOD/interface/GenWeightCounters.h" #include +#include namespace { typedef std::vector WeightGroupDataContainer; @@ -36,14 +37,19 @@ class GenWeightsTableProducer : public edm::global::EDProducer& weightTablevec, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + size_t maxStore, + std::string tablename) const; void addWeightGroupToTable( - std::unique_ptr>& weightTablevec, + std::vector& weightTablevec, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights) const; // Need to either pass the handle or a pointer to avoid a copy and conversion to the base class WeightGroupDataContainer weightDataPerType(edm::Handle& weightsInfoHandle, gen::WeightType weightType, - int& maxStore) const; + int maxStore) const; WeightGroupsToStore groupsToStore(bool foundLheWeights, edm::Handle& genWeightInfoHandle, @@ -137,10 +143,12 @@ class GenWeightsTableProducer : public edm::global::EDProducer unknownOnlyIfEmpty_; bool keepAllPSWeights_; - bool ignoreLheGroups_ = true; - bool ignoreGenGroups_ = false; - int nStoreUngroupedLhe_ = 105; + bool ignoreLheGroups_; + bool ignoreGenGroups_; + int nStoreUngroupedLhe_; + int nStoreUngroupedGen_; enum { inLHE, inGen }; }; @@ -166,7 +174,13 @@ GenWeightsTableProducer::GenWeightsTableProducer(edm::ParameterSet const& params maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), pdfIds_(params.getUntrackedParameter>("pdfIds", {})), lheWeightPrecision_(params.getParameter("lheWeightPrecision")), - keepAllPSWeights_(params.getParameter("keepAllPSWeights")) { + unknownOnlyIfEmpty_(edm::vector_transform(params.getParameter>("unknownOnlyIfEmpty"), + [](auto& c) { return gen::WeightType(c.at(0)); })), + keepAllPSWeights_(params.getParameter("keepAllPSWeights")), + ignoreLheGroups_(params.getUntrackedParameter("ignoreLheGroups", false)), + ignoreGenGroups_(params.getUntrackedParameter("ignoreGenGroups", false)), + nStoreUngroupedLhe_(params.getUntrackedParameter("nStoreUngroupedLhe", 10)), + nStoreUngroupedGen_(params.getUntrackedParameter("nStoreUngroupedGen", 10)) { if (weightgroups_.size() != maxGroupsPerType_.size()) throw std::invalid_argument("Inputs 'weightgroups' and 'maxGroupsPerType' must have equal size"); produces("GENWeight"); @@ -223,48 +237,131 @@ void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons //create a container with dummy weight vector auto weightTablevec = std::make_unique>(); if (foundLheWeights) { - addWeightGroupToTable(weightTablevec, weightInfos.at(inLHE), lheWeights); + if (ignoreLheGroups_) { + fillTableIgnoringGroups(*weightTablevec, weightInfos.at(inLHE), lheWeights, nStoreUngroupedLhe_, "LHEWeight"); + } + else + addWeightGroupToTable(*weightTablevec, weightInfos.at(inLHE), lheWeights); } - addWeightGroupToTable(weightTablevec, weightInfos.at(inGen), genWeights); + if (ignoreGenGroups_) + fillTableIgnoringGroups(*weightTablevec, weightInfos.at(inGen), genWeights, nStoreUngroupedGen_, "GenWeight"); + else + addWeightGroupToTable(*weightTablevec, weightInfos.at(inGen), genWeights); iEvent.put(std::move(weightTablevec),"LHEWeightTableVec"); } +// Sequentially add the weights, up to maxStore +// Note that the order of the weights in the WeightsVector matches the order of weightgroups. +// In very rare cases, this could be modified from the order in the LHE file. If this happens, +// write a warning message in the table info +void GenWeightsTableProducer::fillTableIgnoringGroups( + std::vector& weightTablevec, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + size_t maxStore, + std::string tablename) const { + + std::vector weights(maxStore); + size_t groupIdx = 0; + size_t offset = 0; + std::string tableInfo = "First "; + tableInfo.append(std::to_string(maxStore)); + tableInfo.append(" weights; "); + std::string warnings = ""; + bool foundUnassociated = false; + for (size_t i = 0; i < maxStore; i++) { + if (groupIdx >= allWeights.size()) + throw cms::Exception("GenWeightsTableProducer") + << "Requested " + std::to_string(maxStore) + " weights, which is more than there are in the file"; + size_t entry = i - offset; + auto& weightsForGroup = allWeights.at(groupIdx); + weights.at(i) = weightsForGroup.at(entry); + + if (weightInfos.size() <= groupIdx) + throw cms::Exception("GenWeightsTableProducer") << "Unable to match weight to one of " << weightInfos.size() << " WeightGroups"; + auto matchingGroup = weightInfos.at(groupIdx).group; + if (entry == 0) { + size_t maxRange = std::min(offset+weightsForGroup.size()-1, maxStore); + tableInfo.append("["); + tableInfo.append(std::to_string(offset)); + tableInfo.append("]-["); + tableInfo.append(std::to_string(maxRange)); + tableInfo.append("] "); + tableInfo.append(matchingGroup->name()); + tableInfo.append("; "); + } + + // Check if the order corresponds to the LHE file order + try { + auto matchingInfo = matchingGroup->weightMetaInfo(entry); + + if (matchingInfo.globalIndex != i) { + warnings.append("Index "); + warnings.append(std::to_string(i)); + warnings.append(" does not match order in the LHE file or gen product (where it is entry "); + warnings.append(std::to_string(matchingInfo.globalIndex)); + warnings.append(")"); + } + } catch (cms::Exception& e) { + if (!foundUnassociated) + warnings.append("Could not associate some weights to a group. Cannot verify" + " that the order is maintained wrt the LHE file or gen product"); + foundUnassociated = true; + } + if (entry == weightsForGroup.size()-1) { + groupIdx += 1; + offset += weightsForGroup.size(); + } + } + if (!warnings.empty()) + tableInfo.append("WARNING: " + warnings); + + weightTablevec.emplace_back(weights.size(), tablename, false); + weightTablevec.back().addColumn("", weights, tableInfo, lheWeightPrecision_); +} + void GenWeightsTableProducer::addWeightGroupToTable( - std::unique_ptr>& weightTablevec, + std::vector& weightTablevec, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights) const { std::unordered_map typeCount = {}; for (auto& type : gen::allWeightTypes) typeCount[type] = 0; - // TODO: Handle keepAllWeights for (const auto& groupInfo : weightInfos) { gen::WeightType weightType = groupInfo.group->weightType(); std::string entryName = weightTypeNames_.at(weightType); std::string label = groupInfo.group->description(); - auto& weights = allWeights.at(groupInfo.index); + auto weights = allWeights.at(groupInfo.index); if (weightType == gen::WeightType::kScaleWeights) { const auto& scaleGroup = *std::static_pointer_cast(groupInfo.group); auto weightsAndLabel = orderedScaleWeights(weights, scaleGroup); label.append(weightsAndLabel.first); weights = weightsAndLabel.second; } else if (weightType == gen::WeightType::kPartonShowerWeights) { - const auto& psGroup = *std::static_pointer_cast(groupInfo.group); - auto weightsAndLabel = preferredPSweights(weights, psGroup); - label.append(weightsAndLabel.first); - weights = weightsAndLabel.second; - } - else - label.append(groupInfo.group->description()); + const auto psGroup = std::static_pointer_cast(groupInfo.group); + if(!keepAllPSWeights_) { + auto weightsAndLabel = preferredPSweights(weights, *psGroup); + label.append(weightsAndLabel.first); + weights = weightsAndLabel.second; + } else if (psGroup->isWellFormed()) { + double baseline = weights[psGroup->weightIndexFromLabel("Baseline")]; + for (size_t i = 0; i < weights.size(); i++) + weights[i] = weights[i]/baseline; + label = "PS weights (w_var / w_nominal)"; + } else + label.append("WARNING: Did not properly parse weight information. Verify order manually."); + } else if (!groupInfo.group->isWellFormed()) + label.append("WARNING: Did not properly parse weight information. Verify order manually."); if(typeCount[weightType] > 0) { entryName.append("AltSet"); entryName.append(std::to_string(typeCount[weightType])); } - weightTablevec->emplace_back(weights.size(), entryName, false); - weightTablevec->back().addColumn("", weights, label, lheWeightPrecision_); + weightTablevec.emplace_back(weights.size(), entryName, false); + weightTablevec.back().addColumn("", weights, label, lheWeightPrecision_); typeCount[weightType]++; } @@ -278,33 +375,49 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); WeightGroupsToStore weightsToStore; - if (!(ignoreLheGroups_ && ignoreGenGroups_)) { - for (auto weightType : gen::allWeightTypes) { - if (foundLheWeights && !ignoreLheGroups_) { - auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : lheWeights) - weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); - } - if (!ignoreGenGroups_) { - auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : genWeights) - weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); - } - } - } - // For now treating 'ignoreGroups' as only relevant to LHE... - else if (ignoreLheGroups_) { - auto& allGroups = lheWeightInfoHandle->allWeightGroupsInfo(); - for (size_t i = 0; i < allGroups.size(); i++) { - weightsToStore.at(inLHE).push_back({i, std::make_shared(allGroups[i])}); - } - } + // The order LHE then GEN is useful for the unknownOnlyIfEmpy check + bool storeUnknown = unknownOnlyIfEmpty_.empty(); + auto groupsToSearch = unknownOnlyIfEmpty_; + for (auto genOrLhe : {inLHE, inGen}) { + bool isLHE = genOrLhe == inLHE; + if (isLHE && !foundLheWeights) + continue; + auto& hand = isLHE ? lheWeightInfoHandle : genWeightInfoHandle; + bool ignoreGroups = isLHE ? ignoreLheGroups_ : ignoreGenGroups_; + if (ignoreGroups) { + auto& groups = hand->allWeightGroupsInfo(); + for (size_t i = 0; i < groups.size(); i++) + weightsToStore.at(genOrLhe).push_back({i, std::make_shared(groups[i])}); + } else { + for (auto weightType : gen::allWeightTypes) { + if (weightType == gen::WeightType::kUnknownWeights && !storeUnknown) + continue; + auto allWeights = weightDataPerType(hand, weightType, storePerType[weightType]); + // Only store unknown if at least one specified groups is empty + if (!storeUnknown && !groupsToSearch.empty()) { + auto it = std::find(std::begin(groupsToSearch), std::end(groupsToSearch), weightType); + if (it != std::end(groupsToSearch)) { + if (allWeights.empty()) + storeUnknown = true; + // Remove from array to avoid repeating the check on GEN. NOTE, if parton + // shower weights are included as one of the ones to consider, this can + // cause unknown LHE weights to be stored, given the order of the loops + else + groupsToSearch.erase(it); + + } + } + for (auto& w : allWeights) + weightsToStore.at(genOrLhe).push_back({w.index, std::move(w.group)}); + } + } + } return weightsToStore; } WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsInfoHandle, gen::WeightType weightType, - int& maxStore) const { + int maxStore) const { std::vector allgroups; if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); @@ -367,7 +480,6 @@ std::pair> GenWeightsTableProducer::preferredPS std::vector psTosave; std::string labels = "PS weights (w_var / w_nominal); "; - // TODO: Probably just drop them if they aren't well formed... if (pswV.isWellFormed()) { double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); @@ -431,7 +543,13 @@ void GenWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d desc.add>("maxGroupsPerType"); desc.addOptionalUntracked>("pdfIds"); desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); - desc.add("keepAllPSWeights", false)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); + desc.add>("unknownOnlyIfEmpty") + ->setComment("Only store weights in an Unknown WeightGroup if one of the specified groups is empty"); + desc.add("keepAllPSWeights", false)->setComment("True: stores all PS weights (usually 45); False: saves preferred 4"); + desc.addUntracked("ignoreLheGroups", false)->setComment("Ignore LHE groups and store the first n weights, regardless of type"); + desc.addUntracked("ignoreGenGroups", false)->setComment("Ignore Gen groups and store the first n weights, regardless of type"); + desc.addUntracked("nStoreUngroupedLhe", 10)->setComment("Store the first n LHE weights (only relevant if ignoreLheGroups is true)"); + desc.addUntracked("nStoreUngroupedGen", 10)->setComment("Store the first n Gen weights (only relevant if ignoreGenGroups is true)"); descriptions.addDefault(desc); } diff --git a/PhysicsTools/NanoAOD/python/genWeights_cff.py b/PhysicsTools/NanoAOD/python/genWeights_cff.py index 56ecb54c93175..8fed1636ee3ca 100644 --- a/PhysicsTools/NanoAOD/python/genWeights_cff.py +++ b/PhysicsTools/NanoAOD/python/genWeights_cff.py @@ -20,15 +20,16 @@ # must be lower case and 'PDF' must be capital weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), # Max number of groups to store for each type above, -1 ==> store all found - maxGroupsPerType = cms.vint32([-1, -1, -1, -1, 1]), + maxGroupsPerType = cms.vint32([-1, -1, -1, -1, -1]), # If empty or not specified, no criteria are applied to filter on LHAPDF IDs - #pdfIds = cms.untracked.vint32([91400, 306000, 260000]), - #unknownOnlyIfEmpty = cms.untracked.vstring(['scale', 'PDF']), - #unknownOnlyIfAllEmpty = cms.untracked.bool(False), + # pdfIds = cms.untracked.vint32([91400, 306000, 260000]), + unknownOnlyIfEmpty = cms.vstring(['scale', 'PDF']), keepAllPSWeights = cms.bool(False), - #ignoreGroups = cms.bool(True), - #storeUngrouped = cms.int32(100), + # ignoreGenGroups = cms.untracked.bool(True), + # nStoreUngroupedGen = cms.untracked.int32(40), + # ignoreLheGroups = cms.untracked.bool(False), + # nStoreUngroupedLhe = cms.untracked.int32(100), ) #genWeightsTableTask = cms.Task(lheWeights, genWeights, genWeightsTable) -genWeightsTableTask = cms.Task(lheWeights, genWeightsNano, genWeightsTable) +genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano, genWeightsTable) diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index 48a755404b268..5c0c65ac1116c 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -6,8 +6,7 @@ #include #include #include - -//#include +#include #include "DataFormats/Common/interface/OwnVector.h" #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" @@ -36,6 +35,7 @@ class GenWeightInfoProduct { GenWeightInfoProduct& operator=(GenWeightInfoProduct&& other); const edm::OwnVector& allWeightGroupsInfo() const; + const std::vector allWeightGroupsInfoWithIndices() const; std::unique_ptr containingWeightGroupInfo(int index) const; std::unique_ptr orderedWeightGroupInfo(int index) const; std::vector weightGroupsByType(gen::WeightType type) const; @@ -45,6 +45,18 @@ class GenWeightInfoProduct { std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; void addWeightGroupInfo(gen::WeightGroupInfo& info); const int numberOfGroups() const { return weightGroupsInfo_.size(); } + // If there are unassociated weights, the number of filled groups will be less than the number + // of groups, because the unassociated group can't be filled. Likewise the number of weights + // in the GenWeightInfoProduct product will be less than the number of weights in the event + const int numberOfFilledGroups() const { + return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, + [](auto sum, auto& entry) { return sum + (entry.nIdsContained() > 0 ? 1 : 0); }); + } + const int numberOfWeights() const { + return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, + [](auto sum, auto& entry) { return sum + entry.nIdsContained(); }); + } + private: edm::OwnVector weightGroupsInfo_; diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h index 601b37ca46bc9..411f4716c768a 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -36,7 +36,7 @@ class GenWeightProduct { addWeightSet(); if (static_cast(weightsVector_.size()) <= setEntry) throw cms::Exception("GenWeightProduct") << "Trying to add weight index outside the range of weights expected"; - auto& weights = weightsVector_.at(setEntry); + auto& weights = weightsVector_[setEntry]; if (static_cast(weights.size()) <= weightNum) { weights.resize(weightNum + 1); } diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index 876eead42951f..5c1516375ab53 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -31,7 +31,6 @@ namespace gen { kUnknownWeights = 'u', }; - //const std::array allWeightTypes = {{ const std::array allWeightTypes = {{ WeightType::kPdfWeights, WeightType::kScaleWeights, @@ -56,12 +55,13 @@ namespace gen { void copy(const WeightGroupInfo& other); virtual WeightGroupInfo* clone() const; WeightMetaInfo weightMetaInfo(int weightEntry) const; - WeightMetaInfo weightMetaInfoByGlobalIndex(std::string wgtId, int weightEntry) const; + WeightMetaInfo weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const; + WeightMetaInfo weightMetaInfoByGlobalIndex(int weightEntry) const; int weightVectorEntry(std::string& wgtId) const; bool containsWeight(std::string& wgtId, int weightEntry) const; + bool containsWeight(int weightEntry) const; int weightVectorEntry(std::string& wgtId, int weightEntry) const; void addContainedId(int weightEntry, std::string id, std::string label); - std::vector containedIds() const; bool indexInRange(int index) const; void setName(std::string name) { name_ = name; } diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 3b29d35f05927..e6c81d4f8d110 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -23,9 +23,20 @@ const edm::OwnVector& GenWeightInfoProduct::allWeightGroup return weightGroupsInfo_; } +const std::vector GenWeightInfoProduct::allWeightGroupsInfoWithIndices() const { + std::vector groupInfo; + for (size_t i = 0; i < weightGroupsInfo_.size(); i++) + groupInfo.push_back({i, std::make_unique(weightGroupsInfo_[i])}); + return groupInfo; +} + std::unique_ptr GenWeightInfoProduct::containingWeightGroupInfo(int index) const { + // The weight values in the product are arranged to match the order of the groups in the GenWeightInfoProduct + int maxIdx = 0; for (const auto& weightGroup : weightGroupsInfo_) { - if (weightGroup.indexInRange(index)) + int minIdx = maxIdx; + maxIdx = maxIdx+weightGroup.nIdsContained(); + if (index >= minIdx && index < maxIdx) return std::unique_ptr(weightGroup.clone()); } throw cms::Exception("GenWeightInfoProduct") << "No weight group found containing the weight index requested"; diff --git a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc index d54d00212e7b1..711cfa3251996 100644 --- a/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/PartonShowerWeightGroupInfo.cc @@ -101,7 +101,7 @@ namespace gen { auto wgtIter = std::find(expectedOrder_.begin(), expectedOrder_.end(), varName); wgtIdx = wgtIter - expectedOrder_.begin() + 2; } - if (wgtIdx >= (int)containedIds().size()) + if (wgtIdx >= static_cast(nIdsContained())) wgtIdx = -1; return wgtIdx; } diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index 03dd1ed8c85f7..aec7b2cd14285 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -22,11 +22,20 @@ namespace gen { << "WeightGroupInfo is abstract, so it's clone() method can't be implemented."; } - WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) const { return idsContained_.at(weightEntry); } + WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) const { + if (weightEntry < 0 || weightEntry >= static_cast(idsContained_.size())) + throw cms::Exception("WeightGroupInfo") + << "Local index " << std::to_string(weightEntry) << " is not within the range of group " << name_ + << " which has " << idsContained_.size() << " entries\n"; + return idsContained_.at(weightEntry); + } - WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string wgtId, int weightEntry) const { - if (wgtId.empty()) - wgtId = std::to_string(weightEntry); + WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(int weightEntry) const { + std::string emptyLabel = ""; + return weightMetaInfoByGlobalIndex(emptyLabel, weightEntry); + } + + WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const { int entry = weightVectorEntry(wgtId, weightEntry); if (entry < 0 || entry >= static_cast(idsContained_.size())) throw cms::Exception("WeightGroupInfo") @@ -41,23 +50,26 @@ namespace gen { return weightVectorEntry(wgtId, weightEntry) != -1; } + bool WeightGroupInfo::containsWeight(int weightEntry) const { + std::string id = std::to_string(weightEntry); + return weightVectorEntry(id, weightEntry) != -1; + } + int WeightGroupInfo::weightVectorEntry(std::string& wgtId, int weightEntry) const { - if (wgtId.empty()) - wgtId = std::to_string(weightEntry); - // First try ordered search + // First try direct comparison assuming ordered indices int orderedEntry = weightEntry - firstId_; if (indexInRange(weightEntry) && orderedEntry < static_cast(idsContained_.size())) { - if (wgtId.empty() || idsContained_.at(orderedEntry).id == wgtId) { + if (!wgtId.empty() && idsContained_.at(orderedEntry).id == wgtId) { + return orderedEntry; + } else if (static_cast(idsContained_.at(orderedEntry).globalIndex) == weightEntry) { return orderedEntry; } } - // Fall back to search on ID - else if (!wgtId.empty()) { - auto it = std::find_if( - idsContained_.begin(), idsContained_.end(), [wgtId](const WeightMetaInfo& w) { return w.id == wgtId; }); - if (it != idsContained_.end()) - return std::distance(idsContained_.begin(), it); - } + // Fall back to global search on ID or global index + auto it = std::find_if(idsContained_.begin(), idsContained_.end(), [wgtId, weightEntry](const WeightMetaInfo& w) + { return wgtId.empty() ? static_cast(w.globalIndex) == weightEntry : w.id == wgtId; }); + if (it != idsContained_.end()) + return std::distance(idsContained_.begin(), it); return -1; } @@ -82,8 +94,6 @@ namespace gen { idsContained_.insert(idsContained_.begin() + localIndex, info); } - std::vector WeightGroupInfo::containedIds() const { return idsContained_; } - bool WeightGroupInfo::indexInRange(int index) const { return (index <= lastId_ && index >= firstId_); } void WeightGroupInfo::cacheWeightIndicesByLabel() { From 0d58e0faddfc971177561e6ab069a5450089735b Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Mon, 3 Jan 2022 17:56:56 +0100 Subject: [PATCH 12/16] Convert OwnVector to unique_ptr --- .../Core/interface/WeightHelper.h | 10 +- .../Core/plugins/GenWeightProductProducer.cc | 10 +- .../Core/plugins/LHEWeightProductProducer.cc | 9 +- GeneratorInterface/Core/src/WeightHelper.cc | 151 +++++++++--------- .../plugins/GenWeightsTableProducer.cc | 4 +- PhysicsTools/NanoAOD/python/genWeights_cff.py | 5 +- .../interface/GenWeightInfoProduct.h | 32 ++-- .../interface/ScaleWeightGroupInfo.h | 24 +-- .../src/GenWeightInfoProduct.cc | 62 ++++--- .../src/ScaleWeightGroupInfo.cc | 6 +- .../GeneratorProducts/src/classes.h | 1 + .../GeneratorProducts/src/classes_def.xml | 18 +-- 12 files changed, 170 insertions(+), 162 deletions(-) diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index 05b4e4ef4140e..c135b2728569d 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -1,7 +1,6 @@ #ifndef GeneratorInterface_LHEInterface_WeightHelper_h #define GeneratorInterface_LHEInterface_WeightHelper_h -#include "DataFormats/Common/interface/OwnVector.h" #include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" #include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" @@ -15,6 +14,7 @@ #include #include #include +#include namespace gen { struct ParsedWeight { @@ -29,7 +29,7 @@ namespace gen { class WeightHelper { public: WeightHelper(); - edm::OwnVector weightGroups() { return weightGroups_; } + std::vector>& weightGroups() { return weightGroups_; } template std::unique_ptr weightProduct(std::vector weights, float w0); @@ -41,7 +41,7 @@ namespace gen { } void addUnassociatedGroup() { weightGroups_.push_back(std::make_unique("unassociated")); - weightGroups_.back().setDescription("Weights with missing or invalid header meta data"); + weightGroups_.back()->setDescription("Weights with missing or invalid header meta data"); unassociatedIndex_ = weightGroups_.size()-1; } int addWeightToProduct( @@ -63,7 +63,7 @@ namespace gen { std::vector parsedWeights_; std::map currWeightAttributeMap_; std::map currGroupAttributeMap_; - edm::OwnVector weightGroups_; + std::vector> weightGroups_; bool isScaleWeightGroup(const ParsedWeight& weight); bool isMEParamWeightGroup(const ParsedWeight& weight); bool isPdfWeightGroup(const ParsedWeight& weight); @@ -73,7 +73,7 @@ namespace gen { void updateMEParamInfo(const ParsedWeight& weight, int index); void updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight); void updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight); - void cleanupOrphanCentralWeight(); + //void cleanupOrphanCentralWeight(); bool splitPdfWeight(ParsedWeight& weight); int lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup); diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index afef4a071604e..fe09858cc256d 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -40,6 +40,7 @@ class GenWeightProductProducer : public edm::one::EDProducer> weightInfoTokens_; const bool debug_; bool foundWeightProduct_ = false; + edm::EDPutTokenT groupToken_; }; // @@ -50,7 +51,8 @@ GenWeightProductProducer::GenWeightProductProducer(const edm::ParameterSet& iCon genEventToken_(consumes(iConfig.getParameter("genInfo"))), weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), [this](const std::string& tag) { return mayConsume(tag); })), - debug_(iConfig.getUntrackedParameter("debug", false)) { + debug_(iConfig.getUntrackedParameter("debug", false)), + groupToken_(produces()) { weightHelper_.setDebug(debug_); produces(); produces(); @@ -98,8 +100,10 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& // Always add an unassociated group, which generally will not be filled weightHelper_.addUnassociatedGroup(); + // Need to have separate copies of the groups in the helper class and in the product, + // because the helper can still modify the data for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(weightGroup); + weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup->clone())); } } else if (weightHelper_.fillEmptyIfWeightFails() && debug_) { std::cerr << "genLumiInfoHeader not found, but fillEmptyIfWeightFails is True. Will produce empty product!" << std::endl; @@ -108,7 +112,7 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& << "genLumiInfoHeader not found, code is exiting." << std::endl << "If this is expect and want to continue, set fillEmptyIfWeightFails to True"; } - iLumi.put(std::move(weightInfoProduct)); + iLumi.emplace(groupToken_, std::move(weightInfoProduct)); } void GenWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index 782964e887335..862c7081fda98 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -44,6 +44,7 @@ class LHEWeightProductProducer : public edm::one::EDProducer> weightInfoTokens_; bool foundWeightProduct_ = false; bool hasLhe_ = false; + edm::EDPutTokenT groupToken_; }; // TODO: Accept a vector of strings (source, externalLHEProducer) exit if neither are found @@ -54,9 +55,9 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon lheRunInfoTokens_(edm::vector_transform( lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })) { + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + groupToken_(produces()) { produces(); - produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); @@ -138,9 +139,9 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& auto weightInfoProduct = std::make_unique(); for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(weightGroup); + weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup->clone())); } - lumi.put(std::move(weightInfoProduct)); + lumi.emplace(groupToken_, std::move(weightInfoProduct)); } void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 9eed436ba8669..5ad462594467e 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -167,18 +167,20 @@ namespace gen { } void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) { - if (psGroup.nIdsContained() == DEFAULT_PSWEIGHT_LENGTH) + if (psGroup.nIdsContained() == DEFAULT_PSWEIGHT_LENGTH) { psGroup.setIsWellFormed(true); + psGroup.cacheWeightIndicesByLabel(); + } if (weight.content.find(':') != std::string::npos && weight.content.find('=') != std::string::npos) psGroup.setNameIsPythiaSyntax(true); } bool WeightHelper::splitPdfWeight(ParsedWeight& weight) { - if (weightGroups_[weight.wgtGroup_idx].weightType() == gen::WeightType::kPdfWeights) { - auto& pdfGroup = dynamic_cast(weightGroups_[weight.wgtGroup_idx]); + if (weightGroups_[weight.wgtGroup_idx]->weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = *static_cast(weightGroups_[weight.wgtGroup_idx].get()); int lhaid = lhapdfId(weight, pdfGroup); if (lhaid > 0 && !pdfGroup.isIdInParentSet(lhaid) && pdfGroup.parentLhapdfId() > 0) { - weightGroups_.push_back(*buildGroup(weight)); + weightGroups_.push_back(buildGroup(weight)); weight.wgtGroup_idx++; return true; } @@ -186,30 +188,34 @@ namespace gen { return false; } - void WeightHelper::cleanupOrphanCentralWeight() { - std::vector removeList; - for (auto it = weightGroups_.begin(); it < weightGroups_.end(); it++) { - if (it->weightType() != WeightType::kScaleWeights) - continue; - auto& baseWeight = dynamic_cast(*it); - if (baseWeight.containsCentralWeight()) - continue; - for (auto subIt = weightGroups_.begin(); subIt < it; subIt++) { - if (subIt->weightType() != WeightType::kPdfWeights) - continue; - auto& subWeight = dynamic_cast(*subIt); - if (subWeight.nIdsContained() == 1 && subWeight.parentLhapdfId() == baseWeight.lhaid()) { - removeList.push_back(subIt - weightGroups_.begin()); - auto info = subWeight.idsContained().at(0); - baseWeight.addContainedId(info.globalIndex, info.id, info.label, 1, 1); - } - } - } - std::sort(removeList.begin(), removeList.end(), std::greater()); - for (auto idx : removeList) { - weightGroups_.erase(weightGroups_.begin() + idx); - } - } + // Come back to improving this, it's gross + //void WeightHelper::cleanupOrphanCentralWeight() { + // std::vector removeList; + // for (auto& group : weightGroups_) { + // if (group->weightType() != WeightType::kScaleWeights) + // continue; + // auto& baseWeight = *static_cast(group.get()); + // if (baseWeight.containsCentralWeight()) + // continue; + // for (auto subIt = weightGroups_.begin(); subIt < it; subIt++) { + // if (subIt->weightType() != WeightType::kPdfWeights) + // continue; + // auto& subWeight = dynamic_cast(*subIt); + // if (subWeight.nIdsContained() == 1 && subWeight.parentLhapdfId() == baseWeight.lhaid()) { + // removeList.push_back(subIt - weightGroups_.begin()); + // auto info = subWeight.idsContained().at(0); + // baseWeight.addContainedId(info.globalIndex, info.id, info.label, 1, 1); + // } + // } + // } + // auto& orphanedWeight = std::find_if(std::begin(weightGroups_), std::end(weightGroups_), + // [](auto& entry) { return entry->containsCentralWeight(); }); + + // std::sort(removeList.begin(), removeList.end(), std::greater()); + // for (auto idx : removeList) { + // weightGroups_.erase(weightGroups_.begin() + idx); + // } + //} int WeightHelper::addWeightToProduct( GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex) { @@ -228,7 +234,7 @@ namespace gen { throw cms::Exception("WeightHelper") << "Unmatched Generator weight! ID was " << name << " index was " << std::to_string(weightNum) << "\nNot found in any of " << std::to_string(weightGroups_.size()) << " weightGroups."; - auto& group = weightGroups_[groupIndex]; + auto& group = *weightGroups_[groupIndex]; bool isUnassociated = groupIndex == unassociatedIndex_; // NOTE: Adding the weight explicitly to the group is necessary for this code to work properly, // but it WON'T be propagated to the group info in the GenWeightInfoProduct, which is @@ -236,7 +242,7 @@ namespace gen { if (isUnassociated) group.addContainedId(weightNum, name, name); - int entry = group.weightVectorEntry(name, weightNum);//: group.nIdsContained() - 1; + int entry = group.weightVectorEntry(name, weightNum); if (debug_) std::cout << "Adding weight num " << weightNum << " EntryNum " << entry << " to group " << groupIndex << std::endl; product.addWeight(weight, groupIndex, entry); @@ -247,7 +253,7 @@ namespace gen { // Start search at previous index, under expectation of ordered weights previousGroupIndex = previousGroupIndex >= 0 ? previousGroupIndex : 0; for (int index = previousGroupIndex; index < std::min(index + 1, static_cast(weightGroups_.size())); index++) { - const gen::WeightGroupInfo& weightGroup = weightGroups_[index]; + const auto& weightGroup = *weightGroups_[index]; if (weightGroup.indexInRange(weightIndex) && weightGroup.containsWeight(wgtId, weightIndex)) { return static_cast(index); } @@ -256,7 +262,7 @@ namespace gen { // Fall back to unordered search int counter = 0; for (const auto& weightGroup : weightGroups_) { - if (weightGroup.containsWeight(wgtId, weightIndex)) + if (weightGroup->containsWeight(wgtId, weightIndex)) return counter; counter++; } @@ -268,40 +274,39 @@ namespace gen { void WeightHelper::printWeights() { // checks - for (auto& wgt : weightGroups_) { - std::cout << std::boolalpha << wgt.name() << " (" << wgt.firstId() << "-" << wgt.lastId() - << "): " << wgt.isWellFormed() << std::endl; - if (wgt.weightType() == gen::WeightType::kScaleWeights) { - auto& wgtScale = dynamic_cast(wgt); - std::cout << wgtScale.centralIndex() << " "; - std::cout << wgtScale.muR1muF2Index() << " "; - std::cout << wgtScale.muR1muF05Index() << " "; - std::cout << wgtScale.muR2muF1Index() << " "; - std::cout << wgtScale.muR2muF2Index() << " "; - std::cout << wgtScale.muR2muF05Index() << " "; - std::cout << wgtScale.muR05muF1Index() << " "; - std::cout << wgtScale.muR05muF2Index() << " "; - std::cout << wgtScale.muR05muF05Index() << " \n"; - for (auto name : wgtScale.dynNames()) { + for (const auto& group : weightGroups_) { + std::cout << std::boolalpha << group->name() << " (" << group->firstId() << "-" << group->lastId() + << "): " << group->isWellFormed() << std::endl; + if (group->weightType() == gen::WeightType::kScaleWeights) { + const auto& groupScale = *static_cast(group.get()); + std::cout << groupScale.centralIndex() << " "; + std::cout << groupScale.muR1muF2Index() << " "; + std::cout << groupScale.muR1muF05Index() << " "; + std::cout << groupScale.muR2muF1Index() << " "; + std::cout << groupScale.muR2muF2Index() << " "; + std::cout << groupScale.muR2muF05Index() << " "; + std::cout << groupScale.muR05muF1Index() << " "; + std::cout << groupScale.muR05muF2Index() << " "; + std::cout << groupScale.muR05muF05Index() << " \n"; + for (auto& name : groupScale.dynNames()) { std::cout << name << ": "; - std::cout << wgtScale.scaleIndex(1.0, 1.0, name) << " "; - std::cout << wgtScale.scaleIndex(1.0, 2.0, name) << " "; - std::cout << wgtScale.scaleIndex(1.0, 0.5, name) << " "; - std::cout << wgtScale.scaleIndex(2.0, 1.0, name) << " "; - std::cout << wgtScale.scaleIndex(2.0, 2.0, name) << " "; - std::cout << wgtScale.scaleIndex(2.0, 0.5, name) << " "; - std::cout << wgtScale.scaleIndex(0.5, 1.0, name) << " "; - std::cout << wgtScale.scaleIndex(0.5, 2.0, name) << " "; - std::cout << wgtScale.scaleIndex(0.5, 0.5, name) << "\n"; + std::cout << groupScale.scaleIndex(1.0, 1.0, name) << " "; + std::cout << groupScale.scaleIndex(1.0, 2.0, name) << " "; + std::cout << groupScale.scaleIndex(1.0, 0.5, name) << " "; + std::cout << groupScale.scaleIndex(2.0, 1.0, name) << " "; + std::cout << groupScale.scaleIndex(2.0, 2.0, name) << " "; + std::cout << groupScale.scaleIndex(2.0, 0.5, name) << " "; + std::cout << groupScale.scaleIndex(0.5, 1.0, name) << " "; + std::cout << groupScale.scaleIndex(0.5, 2.0, name) << " "; + std::cout << groupScale.scaleIndex(0.5, 0.5, name) << "\n"; } - } else if (wgt.weightType() == gen::WeightType::kPdfWeights) { - std::cout << wgt.description() << "\n"; - } else if (wgt.weightType() == gen::WeightType::kPartonShowerWeights) { - auto& wgtPS = dynamic_cast(wgt); - std::vector labels = wgtPS.weightLabels(); - wgtPS.cacheWeightIndicesByLabel(); - wgtPS.printVariables(); + } else if (group->weightType() == gen::WeightType::kPdfWeights) { + std::cout << group->description() << "\n"; + } else if (group->weightType() == gen::WeightType::kPartonShowerWeights) { + const auto& groupPS = *static_cast(group.get()); + std::vector labels = groupPS.weightLabels(); + groupPS.printVariables(); } } } @@ -351,7 +356,7 @@ namespace gen { int numGroups = static_cast(weightGroups_.size()); if (weight.wgtGroup_idx == numGroups) { - weightGroups_.push_back(*buildGroup(weight)); + weightGroups_.push_back(buildGroup(weight)); } else if (weight.wgtGroup_idx >= numGroups) throw cms::Exception("Invalid group index " + std::to_string(weight.wgtGroup_idx)); @@ -359,16 +364,16 @@ namespace gen { if (splitPdfWeight(weight)) groupOffset++; - WeightGroupInfo& group = weightGroups_[weight.wgtGroup_idx]; - group.addContainedId(weight.index, weight.id, weight.content); - if (group.weightType() == gen::WeightType::kScaleWeights) - updateScaleInfo(dynamic_cast(group), weight); - else if (group.weightType() == gen::WeightType::kPdfWeights) - updatePdfInfo(dynamic_cast(group), weight); - else if (group.weightType() == gen::WeightType::kPartonShowerWeights) - updatePartonShowerInfo(dynamic_cast(group), weight); + auto& group = weightGroups_[weight.wgtGroup_idx]; + group->addContainedId(weight.index, weight.id, weight.content); + if (group->weightType() == gen::WeightType::kScaleWeights) + updateScaleInfo(*static_cast(group.get()), weight); + else if (group->weightType() == gen::WeightType::kPdfWeights) + updatePdfInfo(*static_cast(group.get()), weight); + else if (group->weightType() == gen::WeightType::kPartonShowerWeights) + updatePartonShowerInfo(*static_cast(group.get()), weight); } - cleanupOrphanCentralWeight(); + //cleanupOrphanCentralWeight(); } } // namespace gen diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 31d7382404ff3..261e998244f66 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -387,7 +387,7 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, if (ignoreGroups) { auto& groups = hand->allWeightGroupsInfo(); for (size_t i = 0; i < groups.size(); i++) - weightsToStore.at(genOrLhe).push_back({i, std::make_shared(groups[i])}); + weightsToStore.at(genOrLhe).push_back({i, std::shared_ptr(groups[i]->clone())}); } else { for (auto weightType : gen::allWeightTypes) { if (weightType == gen::WeightType::kUnknownWeights && !storeUnknown) @@ -434,7 +434,7 @@ WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle< WeightGroupDataContainer out; for (int i = 0; i < toStore; i++) { auto& group = allgroups.at(i); - gen::SharedWeightGroupData temp = {group.index, std::move(group.group)}; + gen::SharedWeightGroupData temp = {group.index, std::shared_ptr(group.group->clone())}; out.push_back(temp); } return out; diff --git a/PhysicsTools/NanoAOD/python/genWeights_cff.py b/PhysicsTools/NanoAOD/python/genWeights_cff.py index 8fed1636ee3ca..c4176d3211399 100644 --- a/PhysicsTools/NanoAOD/python/genWeights_cff.py +++ b/PhysicsTools/NanoAOD/python/genWeights_cff.py @@ -20,7 +20,7 @@ # must be lower case and 'PDF' must be capital weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), # Max number of groups to store for each type above, -1 ==> store all found - maxGroupsPerType = cms.vint32([-1, -1, -1, -1, -1]), + maxGroupsPerType = cms.vint32([1, 1, -1, 2, -1]), # If empty or not specified, no criteria are applied to filter on LHAPDF IDs # pdfIds = cms.untracked.vint32([91400, 306000, 260000]), unknownOnlyIfEmpty = cms.vstring(['scale', 'PDF']), @@ -32,4 +32,5 @@ ) #genWeightsTableTask = cms.Task(lheWeights, genWeights, genWeightsTable) -genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano, genWeightsTable) +#genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano, genWeightsTable) +genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano) diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index 5c0c65ac1116c..b5fdb34672ac6 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -7,15 +7,15 @@ #include #include #include +#include -#include "DataFormats/Common/interface/OwnVector.h" #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" namespace gen { struct WeightGroupData { size_t index; - std::unique_ptr group; + const gen::WeightGroupInfo* group; }; struct SharedWeightGroupData { @@ -27,39 +27,43 @@ namespace gen { class GenWeightInfoProduct { public: GenWeightInfoProduct() {} - GenWeightInfoProduct(edm::OwnVector& weightGroups); - GenWeightInfoProduct(const GenWeightInfoProduct& other); - GenWeightInfoProduct(GenWeightInfoProduct&& other); + GenWeightInfoProduct(std::vector>& weightGroups); + GenWeightInfoProduct(std::vector> weightGroups); + GenWeightInfoProduct(std::unique_ptr other) { + for (auto& ptr : other->weightGroupsInfo_) { + std::unique_ptr cloneptr(ptr->clone()); + weightGroupsInfo_.emplace_back(std::move(cloneptr)); + } + } ~GenWeightInfoProduct() {} - GenWeightInfoProduct& operator=(const GenWeightInfoProduct& other); - GenWeightInfoProduct& operator=(GenWeightInfoProduct&& other); - const edm::OwnVector& allWeightGroupsInfo() const; + const std::vector>& allWeightGroupsInfo() const; const std::vector allWeightGroupsInfoWithIndices() const; - std::unique_ptr containingWeightGroupInfo(int index) const; - std::unique_ptr orderedWeightGroupInfo(int index) const; + const gen::WeightGroupInfo* containingWeightGroupInfo(int index) const; + const gen::WeightGroupInfo* orderedWeightGroupInfo(int index) const; std::vector weightGroupsByType(gen::WeightType type) const; std::vector weightGroupIndicesByType(gen::WeightType type) const; std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; - void addWeightGroupInfo(gen::WeightGroupInfo& info); + void addWeightGroupInfo(gen::WeightGroupInfo info); + void addWeightGroupInfo(std::unique_ptr info); const int numberOfGroups() const { return weightGroupsInfo_.size(); } // If there are unassociated weights, the number of filled groups will be less than the number // of groups, because the unassociated group can't be filled. Likewise the number of weights // in the GenWeightInfoProduct product will be less than the number of weights in the event const int numberOfFilledGroups() const { return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, - [](auto sum, auto& entry) { return sum + (entry.nIdsContained() > 0 ? 1 : 0); }); + [](auto sum, auto& entry) { return sum + (entry->nIdsContained() > 0 ? 1 : 0); }); } const int numberOfWeights() const { return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, - [](auto sum, auto& entry) { return sum + entry.nIdsContained(); }); + [](auto sum, auto& entry) { return sum + entry->nIdsContained(); }); } private: - edm::OwnVector weightGroupsInfo_; + std::vector> weightGroupsInfo_; }; #endif // GeneratorWeightInfo_LHEInterface_GenWeightInfoProduct_h diff --git a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h index 1e9e6d6387f7c..9d2dedb3b1f9b 100644 --- a/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h @@ -53,7 +53,7 @@ namespace gen { } void setMuRMuFIndex(int globalIndex, std::string id, float muR, float muF); - void setDyn(int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName); + void setDyn(int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string_view dynName); int lhaid() { return lhaid_; } void setLhaid(int lhaid) { lhaid_ = lhaid; } // Is a variation of the functional form of the dynamic scale @@ -70,19 +70,19 @@ namespace gen { int muR05muF2Index() const { return muIndices_.at(muR0p5_muF2_idx); } // dynweight version - size_t centralIndex(std::string& dynName) const { return scaleIndex(Central_idx, dynName); } - size_t muR1muF2Index(std::string& dynName) const { return scaleIndex(muR1_muF2_idx, dynName); } - size_t muR1muF05Index(std::string& dynName) const { return scaleIndex(muR1_muF0p5_idx, dynName); } - size_t muR2muF05Index(std::string& dynName) const { return scaleIndex(muR2_muF0p5_idx, dynName); } - size_t muR2muF1Index(std::string& dynName) const { return scaleIndex(muR2_muF1_idx, dynName); } - size_t muR2muF2Index(std::string& dynName) const { return scaleIndex(muR2_muF2_idx, dynName); } - size_t muR05muF05Index(std::string& dynName) const { return scaleIndex(muR0p5_muF0p5_idx, dynName); } - size_t muR05muF1Index(std::string& dynName) const { return scaleIndex(muR0p5_muF1_idx, dynName); } - size_t muR05muF2Index(std::string& dynName) const { return scaleIndex(muR0p5_muF2_idx, dynName); } + size_t centralIndex(std::string_view dynName) const { return scaleIndex(Central_idx, dynName); } + size_t muR1muF2Index(std::string_view dynName) const { return scaleIndex(muR1_muF2_idx, dynName); } + size_t muR1muF05Index(std::string_view dynName) const { return scaleIndex(muR1_muF0p5_idx, dynName); } + size_t muR2muF05Index(std::string_view dynName) const { return scaleIndex(muR2_muF0p5_idx, dynName); } + size_t muR2muF1Index(std::string_view dynName) const { return scaleIndex(muR2_muF1_idx, dynName); } + size_t muR2muF2Index(std::string_view dynName) const { return scaleIndex(muR2_muF2_idx, dynName); } + size_t muR05muF05Index(std::string_view dynName) const { return scaleIndex(muR0p5_muF0p5_idx, dynName); } + size_t muR05muF1Index(std::string_view dynName) const { return scaleIndex(muR0p5_muF1_idx, dynName); } + size_t muR05muF2Index(std::string_view dynName) const { return scaleIndex(muR0p5_muF2_idx, dynName); } size_t scaleIndex(float muR, float muF, size_t dynNum) const; - size_t scaleIndex(float muR, float muF, std::string& dynName) const; - size_t scaleIndex(int index, std::string& dynName) const; + size_t scaleIndex(float muR, float muF, std::string_view dynName) const; + size_t scaleIndex(int index, std::string_view dynName) const; size_t scaleIndex(float muR, float muF) const; size_t scaleIndex(int index, size_t dynNum) const { return dynVec_.at(index).at(dynNum); } diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index e6c81d4f8d110..8a6e771643057 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -5,56 +5,50 @@ #include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" #include "FWCore/Utilities/interface/Exception.h" -GenWeightInfoProduct::GenWeightInfoProduct(edm::OwnVector& weightGroups) { - weightGroupsInfo_ = weightGroups; +GenWeightInfoProduct::GenWeightInfoProduct(std::vector>& weightGroups) { + weightGroupsInfo_ = std::move(weightGroups); } -GenWeightInfoProduct& GenWeightInfoProduct::operator=(const GenWeightInfoProduct& other) { - weightGroupsInfo_ = other.weightGroupsInfo_; - return *this; +GenWeightInfoProduct::GenWeightInfoProduct(std::vector> weightGroups) { + weightGroupsInfo_ = std::move(weightGroups); } -GenWeightInfoProduct& GenWeightInfoProduct::operator=(GenWeightInfoProduct&& other) { - weightGroupsInfo_ = std::move(other.weightGroupsInfo_); - return *this; -} - -const edm::OwnVector& GenWeightInfoProduct::allWeightGroupsInfo() const { +const std::vector>& GenWeightInfoProduct::allWeightGroupsInfo() const { return weightGroupsInfo_; } const std::vector GenWeightInfoProduct::allWeightGroupsInfoWithIndices() const { std::vector groupInfo; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) - groupInfo.push_back({i, std::make_unique(weightGroupsInfo_[i])}); + groupInfo.push_back({i, weightGroupsInfo_[i].get()}); return groupInfo; } -std::unique_ptr GenWeightInfoProduct::containingWeightGroupInfo(int index) const { +const gen::WeightGroupInfo* GenWeightInfoProduct::containingWeightGroupInfo(int index) const { // The weight values in the product are arranged to match the order of the groups in the GenWeightInfoProduct int maxIdx = 0; for (const auto& weightGroup : weightGroupsInfo_) { int minIdx = maxIdx; - maxIdx = maxIdx+weightGroup.nIdsContained(); + maxIdx = maxIdx+weightGroup->nIdsContained(); if (index >= minIdx && index < maxIdx) - return std::unique_ptr(weightGroup.clone()); + return weightGroup.get(); } throw cms::Exception("GenWeightInfoProduct") << "No weight group found containing the weight index requested"; } -std::unique_ptr GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { +const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) throw cms::Exception("GenWeightInfoProduct") << "Weight index requested is outside the range of weights in the product"; - return std::unique_ptr(weightGroupsInfo_[weightGroupIndex].clone()); + return weightGroupsInfo_[weightGroupIndex].get(); } std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type) const { std::vector matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { - const gen::WeightGroupInfo& group = weightGroupsInfo_[i]; - if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back({i, std::unique_ptr(group.clone())}); + const gen::WeightGroupInfo* group = weightGroupsInfo_[i].get(); + if (group->weightType() == type) + matchingGroups.push_back({i, group}); } return matchingGroups; } @@ -62,9 +56,9 @@ std::vector GenWeightInfoProduct::weightGroupsAndIndicesBy std::vector GenWeightInfoProduct::weightGroupsByType(gen::WeightType type) const { std::vector matchingGroups; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { - const gen::WeightGroupInfo& group = weightGroupsInfo_[i]; - if (weightGroupsInfo_[i].weightType() == type) - matchingGroups.push_back({i, std::unique_ptr(group.clone())}); + const gen::WeightGroupInfo* group = weightGroupsInfo_[i].get(); + if (group->weightType() == type) + matchingGroups.push_back({i, group}); } return matchingGroups; } @@ -72,15 +66,14 @@ std::vector GenWeightInfoProduct::weightGroupsByType(gen:: std::optional GenWeightInfoProduct::pdfGroupWithIndexByLHAID(int lhaid) const { std::vector pdfGroups = weightGroupsAndIndicesByType(gen::WeightType::kPdfWeights); - auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = std::unique_ptr( - static_cast(data.group.release())); + auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](auto& data) { + const auto* pdfGroup = static_cast(data.group); return pdfGroup->containsLhapdfId(lhaid); }); return matchingPdfSet == pdfGroups.end() ? std::nullopt - : std::optional({matchingPdfSet->index, std::move(matchingPdfSet->group)}); + : std::optional({matchingPdfSet->index, matchingPdfSet->group}); } std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLHAIDs( @@ -90,12 +83,11 @@ std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLH for (auto lhaid : lhaids) { auto matchingPdfSet = std::find_if(pdfGroups.begin(), pdfGroups.end(), [lhaid](gen::WeightGroupData& data) { - auto pdfGroup = std::unique_ptr( - static_cast(data.group.release())); + const auto* pdfGroup = static_cast(data.group); return pdfGroup->containsLhapdfId(lhaid); }); if (matchingPdfSet != pdfGroups.end()) { - pdfGroups.push_back({matchingPdfSet->index, std::move(matchingPdfSet->group)}); + pdfGroups.push_back({matchingPdfSet->index, matchingPdfSet->group}); } } @@ -105,12 +97,16 @@ std::vector GenWeightInfoProduct::pdfGroupsWithIndicesByLH std::vector GenWeightInfoProduct::weightGroupIndicesByType(gen::WeightType type) const { std::vector matchingGroupIndices; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { - if (weightGroupsInfo_[i].weightType() == type) + if (weightGroupsInfo_[i]->weightType() == type) matchingGroupIndices.push_back(i); } return matchingGroupIndices; } -void GenWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo& info) { - weightGroupsInfo_.push_back(info.clone()); +void GenWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo info) { + weightGroupsInfo_.push_back(std::make_unique(info)); +} + +void GenWeightInfoProduct::addWeightGroupInfo(std::unique_ptr info) { + weightGroupsInfo_.push_back(std::move(info)); } diff --git a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc index 955b4f5c8e260..bac8ccf99de7f 100644 --- a/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/ScaleWeightGroupInfo.cc @@ -47,7 +47,7 @@ namespace gen { } void ScaleWeightGroupInfo::setDyn( - int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string dynName) { + int globalIndex, std::string id, float muR, float muF, size_t dynNum, std::string_view dynName) { auto info = weightMetaInfoByGlobalIndex(id, globalIndex); int index = indexFromMus(muR, muF); // resize if too small @@ -62,7 +62,7 @@ namespace gen { dynVec_[index][dynNum] = info.localIndex; } - size_t ScaleWeightGroupInfo::scaleIndex(float muR, float muF, std::string& dynName) const { + size_t ScaleWeightGroupInfo::scaleIndex(float muR, float muF, std::string_view dynName) const { auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); if (it == dynNames_.end()) return -1; @@ -70,7 +70,7 @@ namespace gen { return scaleIndex(muR, muF, it - dynNames_.begin()); } - size_t ScaleWeightGroupInfo::scaleIndex(int index, std::string& dynName) const { + size_t ScaleWeightGroupInfo::scaleIndex(int index, std::string_view dynName) const { auto it = std::find(dynNames_.begin(), dynNames_.end(), dynName); if (it == dynNames_.end()) return -1; diff --git a/SimDataFormats/GeneratorProducts/src/classes.h b/SimDataFormats/GeneratorProducts/src/classes.h index 4562fa5097487..25312a49eb949 100644 --- a/SimDataFormats/GeneratorProducts/src/classes.h +++ b/SimDataFormats/GeneratorProducts/src/classes.h @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/SimDataFormats/GeneratorProducts/src/classes_def.xml b/SimDataFormats/GeneratorProducts/src/classes_def.xml index bcd6bbda4730e..4b99a2f1908fe 100644 --- a/SimDataFormats/GeneratorProducts/src/classes_def.xml +++ b/SimDataFormats/GeneratorProducts/src/classes_def.xml @@ -246,17 +246,13 @@ - - - - - - - - - - - + + + + + + + From eacce78267530e29c32830dbf3d3d260494d1b50 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 02:29:01 +0100 Subject: [PATCH 13/16] Simplify nano producer and weight parsing --- .../Core/interface/GenWeightHelper.h | 2 +- .../Core/interface/LHEWeightHelper.h | 20 ++- .../Core/interface/WeightHelper.h | 116 ++++++++------ .../Core/plugins/GenWeightProductProducer.cc | 27 ++-- .../Core/plugins/LHEWeightProductProducer.cc | 61 ++++---- .../Core/src/GenWeightHelper.cc | 19 +-- .../Core/src/LHEWeightHelper.cc | 63 ++++---- GeneratorInterface/Core/src/WeightHelper.cc | 147 ++++++++---------- .../plugins/GenWeightsTableProducer.cc | 61 +++----- PhysicsTools/NanoAOD/python/genWeights_cff.py | 6 +- .../interface/GenWeightInfoProduct.h | 38 +++-- .../interface/GenWeightProduct.h | 6 +- .../interface/WeightGroupInfo.h | 6 +- .../src/GenWeightInfoProduct.cc | 37 +++-- .../GeneratorProducts/src/WeightGroupInfo.cc | 8 +- 15 files changed, 302 insertions(+), 315 deletions(-) diff --git a/GeneratorInterface/Core/interface/GenWeightHelper.h b/GeneratorInterface/Core/interface/GenWeightHelper.h index 1a1724b36792e..0947efb3eda7b 100644 --- a/GeneratorInterface/Core/interface/GenWeightHelper.h +++ b/GeneratorInterface/Core/interface/GenWeightHelper.h @@ -19,7 +19,7 @@ namespace gen { class GenWeightHelper : public WeightHelper { public: GenWeightHelper(); - void parseWeightGroupsFromNames(std::vector weightNames); + std::vector> parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociatedGroup); }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index a60e74ec0cf98..5653187084498 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -23,23 +23,21 @@ namespace gen { enum class ErrorType { Empty, SwapHeader, HTMLStyle, NoWeightGroup, TrailingStr, Unknown, NoError }; - void setHeaderLines(std::vector headerLines); - void parseWeights(); - bool isConsistent(); - void swapHeaders(); + std::vector> parseWeights(std::vector headerLines, bool addUnassociated) const; + bool isConsistent(const std::vector& headerLines) const; + void swapHeaders(std::vector& headerLines) const; void setFailIfInvalidXML(bool value) { failIfInvalidXML_ = value; } private: - std::vector headerLines_; std::string weightgroupKet_ = ""; std::string weightTag_ = ""; bool failIfInvalidXML_ = false; - std::string parseGroupName(tinyxml2::XMLElement* el); - void addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex); - bool parseLHE(tinyxml2::XMLDocument& xmlDoc); - tinyxml2::XMLError tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); - tinyxml2::XMLError tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader); - ErrorType findErrorType(int xmlError, std::string& fullHeader); + std::string parseGroupName(tinyxml2::XMLElement* el) const; + ParsedWeight parseWeight(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex) const; + bool validateAndFixHeader(std::vector& headerLines, tinyxml2::XMLDocument& xmlDoc) const; + tinyxml2::XMLError tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const; + tinyxml2::XMLError tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const; + ErrorType findErrorType(int xmlError, const std::vector& headerLines) const; }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index c135b2728569d..17a52311bfe84 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -2,6 +2,7 @@ #define GeneratorInterface_LHEInterface_WeightHelper_h #include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" #include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" #include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" @@ -29,54 +30,47 @@ namespace gen { class WeightHelper { public: WeightHelper(); - std::vector>& weightGroups() { return weightGroups_; } template - std::unique_ptr weightProduct(std::vector weights, float w0); + std::unique_ptr weightProduct(const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0); void setfillEmptyIfWeightFails(bool value) { fillEmptyIfWeightFails_ = value; } void setModel(std::string model) { model_ = model; } void setGuessPSWeightIdx(bool guessPSWeightIdx) { PartonShowerWeightGroupInfo::setGuessPSWeightIdx(guessPSWeightIdx); } - void addUnassociatedGroup() { - weightGroups_.push_back(std::make_unique("unassociated")); - weightGroups_.back()->setDescription("Weights with missing or invalid header meta data"); - unassociatedIndex_ = weightGroups_.size()-1; + void addUnassociatedGroup(std::vector>& weightGroups) const { + gen::UnknownWeightGroupInfo unassoc("unassociated"); + unassoc.setDescription("Weights with missing or invalid header meta data"); + weightGroups.push_back(std::make_unique(unassoc)); } int addWeightToProduct( GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex); - int findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex); void setDebug(bool value) { debug_ = value; } bool fillEmptyIfWeightFails() { return fillEmptyIfWeightFails_; } protected: - // TODO: Make this only print from one thread a la - // https://github.com/cms-sw/cmssw/blob/master/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc#L1069 bool debug_ = false; - bool allowUnassociatedWeights_ = true; bool fillEmptyIfWeightFails_ = false; - int unassociatedIndex_ = -1; + std::unique_ptr unassociatedGroup_; const unsigned int FIRST_PSWEIGHT_ENTRY = 2; const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; std::string model_; - std::vector parsedWeights_; std::map currWeightAttributeMap_; std::map currGroupAttributeMap_; - std::vector> weightGroups_; - bool isScaleWeightGroup(const ParsedWeight& weight); - bool isMEParamWeightGroup(const ParsedWeight& weight); - bool isPdfWeightGroup(const ParsedWeight& weight); - bool isPartonShowerWeightGroup(const ParsedWeight& weight); - bool isOrphanPdfWeightGroup(ParsedWeight& weight); - void updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight); - void updateMEParamInfo(const ParsedWeight& weight, int index); - void updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight); - void updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight); - //void cleanupOrphanCentralWeight(); - bool splitPdfWeight(ParsedWeight& weight); + bool isScaleWeightGroup(const ParsedWeight& weight) const; + bool isMEParamWeightGroup(const ParsedWeight& weight) const; + bool isPdfWeightGroup(const ParsedWeight& weight) const; + bool isPartonShowerWeightGroup(const ParsedWeight& weight) const; + bool isOrphanPdfWeightGroup(ParsedWeight& weight) const; + void updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight) const; + void updateMEParamInfo(const ParsedWeight& weight, int index) const; + void updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight) const; + void updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) const; + void cleanupOrphanCentralWeight(WeightGroupInfoContainer& weightGroups) const; + bool splitPdfWeight(ParsedWeight& weight, WeightGroupInfoContainer& weightGroups) const; - int lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup); + int lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup) const; std::string searchAttributes(const std::string& label, const ParsedWeight& weight) const; std::string searchAttributesByTag(const std::string& label, const ParsedWeight& weight) const; std::string searchAttributesByRegex(const std::string& label, const ParsedWeight& weight) const; @@ -92,44 +86,66 @@ namespace gen { {"down", {"_dn", "Lo"}}, {"me_variation", {"mass", "sthw2", "width"}}, }; - void printWeights(); - std::unique_ptr buildGroup(ParsedWeight& weight); - void buildGroups(); - std::string searchString(const std::string& label, const std::string& name); + void printWeights(const WeightGroupInfoContainer& weightGroups) const; + std::unique_ptr buildGroup(ParsedWeight& weight) const; + WeightGroupInfoContainer buildGroups(std::vector& parsedWeights, bool addUnassociatedGroup) const; + std::string searchString(const std::string& label, const std::string& name) const; }; - // Templated function (needed here because of plugins) template - std::unique_ptr WeightHelper::weightProduct(std::vector weights, float w0) { + std::unique_ptr WeightHelper::weightProduct( + const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) { auto weightProduct = std::make_unique(w0); - weightProduct->setNumWeightSets(weightGroups_.size()); - int weightGroupIndex = 0; + weightProduct->setNumWeightSets(weightsInfo.numberOfGroups()); + gen::WeightGroupData groupData = {0, nullptr}; int i = 0; - // This happens if there are no PS weights, so the weights vector contains only the central GEN weight. - // Just add an empty product (need for all cases or...?) + // size=1 happens if there are no PS weights, so the weights vector contains only the central GEN weight. if (weights.size() > 1) { for (const auto& weight : weights) { + double wgtval; + std::string wgtid; + if constexpr (std::is_same::value) { + wgtid = weight.id; + wgtval = weight.wgt; + } else if (std::is_same::value) { + wgtid = std::to_string(i); + wgtval = weight; + } try { - if constexpr (std::is_same::value) { - weightGroupIndex = addWeightToProduct(*weightProduct, weight.wgt, weight.id, i, weightGroupIndex); - } else if (std::is_same::value) - weightGroupIndex = addWeightToProduct(*weightProduct, weight, std::to_string(i), i, weightGroupIndex); - - } catch (cms::Exception& e) { - if (fillEmptyIfWeightFails_) { - std::cerr << "WARNING: " << e.what() << std::endl; - std::cerr << "fillEmptyIfWeightFails_ is set to True, so variations will be empty!!" << std::endl; - weightProduct->setNumWeightSets(1); // Only central weight - return weightProduct; - } else { - throw cms::Exception("ERROR: " + std::string(e.what()) + - "\nfillEmptyIfWeightFails_ is set to False, so exiting code"); + groupData = weightsInfo.containingWeightGroupInfo(i, groupData.index); + } catch (const cms::Exception& e) { + int unassociatedIdx = weightsInfo.unassociatedIdx(); + if (unassociatedIdx == -1) + throw e; + if (debug_) { + std::cout << "WARNING: " << e.what() << std::endl; } + // Access the unassociated group separately so it can be modified + unassociatedGroup_->addContainedId(i, wgtid, wgtid); + groupData = {static_cast(unassociatedIdx), unassociatedGroup_.get()}; } + + // TODO: is this too slow? + int entry = groupData.group->weightVectorEntry(wgtid, i); + if (debug_) + std::cout << "Adding weight num " << i << " EntryNum " << entry << " to group " << groupData.index << std::endl; + weightProduct->addWeight(wgtval, groupData.index, entry); + // TODO: Need to understand if this is still needed + //catch (cms::Exception& e) { + // if (fillEmptyIfWeightFails_) { + // std::cerr << "WARNING: " << e.what() << std::endl; + // std::cerr << "fillEmptyIfWeightFails_ is set to True, so variations will be empty!!" << std::endl; + // weightProduct->setNumWeightSets(1); // Only central weight + // return weightProduct; + // } else { + // throw cms::Exception("ERROR: " + std::string(e.what()) + + // "\nfillEmptyIfWeightFails_ is set to False, so exiting code"); + // } + //} i++; } } - return weightProduct; + return weightProduct; } } // namespace gen diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index fe09858cc256d..566547aac397e 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -19,6 +19,7 @@ #include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" #include "GeneratorInterface/Core/interface/GenWeightHelper.h" @@ -40,7 +41,8 @@ class GenWeightProductProducer : public edm::one::EDProducer> weightInfoTokens_; const bool debug_; bool foundWeightProduct_ = false; - edm::EDPutTokenT groupToken_; + edm::EDPutTokenT groupPutToken_; + GenWeightInfoProduct weightsInfo_; }; // @@ -52,7 +54,7 @@ GenWeightProductProducer::GenWeightProductProducer(const edm::ParameterSet& iCon weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), [this](const std::string& tag) { return mayConsume(tag); })), debug_(iConfig.getUntrackedParameter("debug", false)), - groupToken_(produces()) { + groupPutToken_(produces()) { weightHelper_.setDebug(debug_); produces(); produces(); @@ -73,7 +75,7 @@ void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup iEvent.getByToken(genEventToken_, genEventInfo); float centralWeight = !genEventInfo->weights().empty() ? genEventInfo->weights().at(0) : 1.; - auto weightProduct = weightHelper_.weightProduct(genEventInfo->weights(), centralWeight); + auto weightProduct = weightHelper_.weightProduct(weightsInfo_, genEventInfo->weights(), centralWeight); iEvent.put(std::move(weightProduct)); } @@ -91,28 +93,25 @@ void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& edm::Handle genLumiInfoHandle; iLumi.getByToken(genLumiInfoToken_, genLumiInfoHandle); - auto weightInfoProduct = std::make_unique(); + //std::unique_ptr weightInfoProduct = std::make_unique(); + std::unique_ptr weightInfoProduct; if (genLumiInfoHandle.isValid()) { std::string label = genLumiInfoHandle->configDescription(); boost::replace_all(label, "-", "_"); weightHelper_.setModel(label); - weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames()); // Always add an unassociated group, which generally will not be filled - weightHelper_.addUnassociatedGroup(); - - // Need to have separate copies of the groups in the helper class and in the product, - // because the helper can still modify the data - for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup->clone())); - } + // TODO: control this with an argument? + auto weightGroups = weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames(), true); + weightInfoProduct = std::make_unique(weightGroups); + weightsInfo_ = *weightInfoProduct; } else if (weightHelper_.fillEmptyIfWeightFails() && debug_) { - std::cerr << "genLumiInfoHeader not found, but fillEmptyIfWeightFails is True. Will produce empty product!" << std::endl; + weightInfoProduct = std::make_unique(); } else { throw cms::Exception("GenWeightProductProducer") << "genLumiInfoHeader not found, code is exiting." << std::endl << "If this is expect and want to continue, set fillEmptyIfWeightFails to True"; } - iLumi.emplace(groupToken_, std::move(weightInfoProduct)); + iLumi.emplace(groupPutToken_, std::move(weightInfoProduct)); } void GenWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index 862c7081fda98..d60427b02b86f 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -18,6 +18,7 @@ #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" +#include "SimDataFormats/GeneratorProducts/interface/UnknownWeightGroupInfo.h" #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h" #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h" @@ -26,14 +27,15 @@ #include "FWCore/ServiceRegistry/interface/Service.h" #include "FWCore/Utilities/interface/transform.h" -class LHEWeightProductProducer : public edm::one::EDProducer { +class LHEWeightProductProducer : public edm::one::EDProducer> { public: explicit LHEWeightProductProducer(const edm::ParameterSet& iConfig); ~LHEWeightProductProducer() override; void produce(edm::Event&, const edm::EventSetup&) override; void beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) override; - void beginRun(edm::Run const& run, edm::EventSetup const& es) override; - void endRun(edm::Run const& run, edm::EventSetup const& es) override; + std::shared_ptr globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const; + void globalEndRun(edm::Run const& iRun, edm::EventSetup const&) {} static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); private: @@ -43,8 +45,9 @@ class LHEWeightProductProducer : public edm::one::EDProducer> lheRunInfoTokens_; std::vector> weightInfoTokens_; bool foundWeightProduct_ = false; - bool hasLhe_ = false; - edm::EDPutTokenT groupToken_; + bool hasLhe_ = true; + edm::EDPutTokenT groupPutToken_; + GenWeightInfoProduct weightsInfo_; }; // TODO: Accept a vector of strings (source, externalLHEProducer) exit if neither are found @@ -56,7 +59,7 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), [this](const edm::InputTag& tag) { return mayConsume(tag); })), - groupToken_(produces()) { + groupPutToken_(produces()) { produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); @@ -79,21 +82,20 @@ void LHEWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup } } - auto weightProduct = weightHelper_.weightProduct(lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); + auto weightProduct = weightHelper_.weightProduct(weightsInfo_, lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); iEvent.put(std::move(weightProduct)); } -void LHEWeightProductProducer::beginRun(edm::Run const& run, edm::EventSetup const& es) { +std::shared_ptr LHEWeightProductProducer::globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const { edm::Handle lheRunInfoHandle; for (auto& label : lheLabels_) { run.getByLabel(label, lheRunInfoHandle); if (lheRunInfoHandle.isValid()) { - hasLhe_ = true; break; } } - if (!hasLhe_) - return; + if (!lheRunInfoHandle.isValid()) + return {}; typedef std::vector::const_iterator header_cit; LHERunInfoProduct::Header headerWeightInfo; @@ -104,11 +106,21 @@ void LHEWeightProductProducer::beginRun(edm::Run const& run, edm::EventSetup con } } - weightHelper_.setHeaderLines(headerWeightInfo.lines()); + gen::WeightGroupInfoContainer groups; + try { + // TODO: Maybe make unassociated group optional + groups = weightHelper_.parseWeights(headerWeightInfo.lines(), true); + } catch (cms::Exception& e) { + std::string error = e.what(); + error += + "\n NOTE: if you want to attempt to process this sample anyway, set failIfInvalidXML = False " + "in the configuration file\n. If you set this flag and the error persists, the issue " + " is fatal and must be solved at the LHE/gridpack level."; + throw cms::Exception("LHEWeightProductProducer") << error; + } + return std::make_shared(std::move(groups)); } -void LHEWeightProductProducer::endRun(edm::Run const& run, edm::EventSetup const& es) {} - void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) { edm::Handle weightInfoHandle; @@ -123,25 +135,10 @@ void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& if (!hasLhe_) return; - try { - weightHelper_.parseWeights(); - } catch (cms::Exception& e) { - std::string error = e.what(); - error += - "\n NOTE: if you want to attempt to process this sample anyway, set failIfInvalidXML = False " - "in the configuration file\n. If you set this flag and the error persists, the issue " - " is fatal and must be solved at the LHE/gridpack level."; - throw cms::Exception("LHEWeightProductProducer") << error; - } + auto weightInfoProduct = std::make_unique(*runCache(lumi.getRun().index())); + weightsInfo_ = *weightInfoProduct; - if (weightHelper_.weightGroups().empty()) - weightHelper_.addUnassociatedGroup(); - - auto weightInfoProduct = std::make_unique(); - for (auto& weightGroup : weightHelper_.weightGroups()) { - weightInfoProduct->addWeightGroupInfo(std::unique_ptr(weightGroup->clone())); - } - lumi.emplace(groupToken_, std::move(weightInfoProduct)); + lumi.emplace(groupPutToken_, std::move(weightInfoProduct)); } void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index 9302005217e15..541e60d8be9f1 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -6,15 +6,15 @@ using namespace tinyxml2; namespace gen { GenWeightHelper::GenWeightHelper() {} - void GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames) { - parsedWeights_.clear(); + std::vector> GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociated) { + std::vector parsedWeights; int index = 0; int groupIndex = -1; int showerGroupIndex = -1; std::string curGroup = ""; // If size is 1, it's just the central weight if (weightNames.size() <= 1) - return; + return {}; for (std::string weightName : weightNames) { if (weightName.find("LHE") != std::string::npos) { @@ -37,21 +37,22 @@ namespace gen { } // Gen Weights can't have an ID, because they are just a std::vector in the event attributes["id"] = ""; - parsedWeights_.push_back({attributes["id"], index, curGroup, text, attributes, groupIndex}); + parsedWeights.push_back({attributes["id"], index, curGroup, text, attributes, groupIndex}); } else { - parsedWeights_.push_back( + parsedWeights.push_back( {"", index, weightName, weightName, std::unordered_map(), groupIndex}); - if (isPartonShowerWeightGroup(parsedWeights_.back())) { + if (isPartonShowerWeightGroup(parsedWeights.back())) { if (showerGroupIndex < 0) { showerGroupIndex = ++groupIndex; } - parsedWeights_.back().wgtGroup_idx = showerGroupIndex; // all parton showers are grouped together + parsedWeights.back().wgtGroup_idx = showerGroupIndex; // all parton showers are grouped together } } index++; } - buildGroups(); + auto groups = buildGroups(parsedWeights, addUnassociated); if (debug_) - printWeights(); + printWeights(groups); + return groups; } } // namespace gen diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 4f15ebfb2a18a..274c0c43f592b 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -7,19 +7,16 @@ using namespace tinyxml2; namespace gen { - void LHEWeightHelper::setHeaderLines(std::vector headerLines) { headerLines_ = headerLines; } - - bool LHEWeightHelper::parseLHE(tinyxml2::XMLDocument& xmlDoc) { - parsedWeights_.clear(); - - std::string fullHeader = boost::algorithm::join(headerLines_, ""); + bool LHEWeightHelper::validateAndFixHeader( + std::vector& headerLines, tinyxml2::XMLDocument& xmlDoc) const { + std::string fullHeader = boost::algorithm::join(headerLines, ""); if (debug_) std::cout << "Full header is \n" << fullHeader << std::endl; int xmlError = xmlDoc.Parse(fullHeader.c_str()); ErrorType errorType; - while (errorType = findErrorType(xmlError, fullHeader), errorType != ErrorType::NoError) { + while (errorType = findErrorType(xmlError, headerLines), errorType != ErrorType::NoError) { if (failIfInvalidXML_) { xmlDoc.PrintError(); throw cms::Exception("LHEWeightHelper") @@ -31,8 +28,8 @@ namespace gen { } else if (errorType == ErrorType::SwapHeader) { if (debug_) std::cout << " >>> Some headers in the file are swapped\n"; - swapHeaders(); - fullHeader = boost::algorithm::join(headerLines_, ""); + swapHeaders(headerLines); + fullHeader = boost::algorithm::join(headerLines, ""); xmlError = xmlDoc.Parse(fullHeader.c_str()); } else if (errorType == ErrorType::TrailingStr) { if (debug_) @@ -55,7 +52,7 @@ namespace gen { return true; } - void LHEWeightHelper::addGroup(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex) { + ParsedWeight LHEWeightHelper::parseWeight(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex) const { if (debug_) std::cout << " >> Found a weight inside the group. " << std::endl; std::string text = ""; @@ -67,15 +64,17 @@ namespace gen { attributes[att->Name()] = att->Value(); if (debug_) std::cout << " " << weightIndex << ": \"" << text << "\"" << std::endl; - parsedWeights_.push_back({inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}); + return {inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}; } - void LHEWeightHelper::parseWeights() { + std::vector> LHEWeightHelper::parseWeights( + std::vector headerLines, bool addUnassociatedGroup) const { tinyxml2::XMLDocument xmlDoc; - if (!parseLHE(xmlDoc)) { - return; + if (!validateAndFixHeader(headerLines, xmlDoc)) { + return {}; } + std::vector parsedWeights; int weightIndex = 0; int groupIndex = 0; for (auto* e = xmlDoc.RootElement(); e != nullptr; e = e->NextSiblingElement()) { @@ -85,24 +84,25 @@ namespace gen { if (strcmp(e->Name(), "weight") == 0) { if (debug_) std::cout << "Found weight unmatched to group\n"; - addGroup(e, groupName, groupIndex, weightIndex); + parsedWeights.push_back(parseWeight(e, groupName, groupIndex, weightIndex)); } else if (strcmp(e->Name(), "weightgroup") == 0) { groupName = parseGroupName(e); if (debug_) std::cout << ">>>> Found a weight group: " << groupName << std::endl; for (auto inner = e->FirstChildElement("weight"); inner != nullptr; inner = inner->NextSiblingElement("weight")) - addGroup(inner, groupName, groupIndex, weightIndex); + parsedWeights.push_back(parseWeight(inner, groupName, groupIndex, weightIndex)); } groupIndex++; } - buildGroups(); + auto groups = buildGroups(parsedWeights, addUnassociatedGroup); if (debug_) - printWeights(); + printWeights(groups); + return groups; } - std::string LHEWeightHelper::parseGroupName(tinyxml2::XMLElement* el) { - std::vector nameAlts_ = {"name", "type"}; - for (const auto& nameAtt : nameAlts_) { + std::string LHEWeightHelper::parseGroupName(tinyxml2::XMLElement* el) const { + std::vector nameAlts = {"name", "type"}; + for (const auto& nameAtt : nameAlts) { if (el->Attribute(nameAtt.c_str())) { std::string groupName = el->Attribute(nameAtt.c_str()); if (groupName.find('.') != std::string::npos) @@ -117,10 +117,10 @@ namespace gen { return ""; } - bool LHEWeightHelper::isConsistent() { + bool LHEWeightHelper::isConsistent(const std::vector& headerLines) const { int curLevel = 0; - for (const auto& line : headerLines_) { + for (const auto& line : headerLines) { if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { @@ -136,12 +136,12 @@ namespace gen { return curLevel == 0; } - void LHEWeightHelper::swapHeaders() { + void LHEWeightHelper::swapHeaders(std::vector& headerLines) const { int curLevel = 0; int open = -1; int close = -1; - for (size_t idx = 0; idx < headerLines_.size(); idx++) { - std::string line = headerLines_[idx]; + for (size_t idx = 0; idx < headerLines.size(); idx++) { + std::string line = headerLines[idx]; if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { @@ -154,14 +154,14 @@ namespace gen { } } if (open > -1 && close > -1) { - std::swap(headerLines_[open], headerLines_[close]); + std::swap(headerLines[open], headerLines[close]); open = -1; close = -1; } } } - tinyxml2::XMLError LHEWeightHelper::tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) { + tinyxml2::XMLError LHEWeightHelper::tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const { // in case of > instead of < boost::replace_all(fullHeader, "<", "<"); boost::replace_all(fullHeader, ">", ">"); @@ -169,7 +169,7 @@ namespace gen { return xmlDoc.Parse(fullHeader.c_str()); } - tinyxml2::XMLError LHEWeightHelper::tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) { + tinyxml2::XMLError LHEWeightHelper::tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const { // delete extra strings after the last (occasionally contain '<' or '>') std::size_t theLastKet = fullHeader.rfind(weightgroupKet_) + weightgroupKet_.length(); std::size_t thelastWeight = fullHeader.rfind(weightTag_) + weightTag_.length(); @@ -178,10 +178,11 @@ namespace gen { return xmlDoc.Parse(fullHeader.c_str()); } - LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, std::string& fullHeader) { + LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, const std::vector& headerLines) const { + std::string fullHeader = boost::algorithm::join(headerLines, ""); if (fullHeader.size() == 0) return ErrorType::Empty; - else if (!isConsistent()) + else if (!isConsistent(headerLines)) return ErrorType::SwapHeader; else if (fullHeader.find("<") != std::string::npos || fullHeader.find(">") != std::string::npos) return ErrorType::HTMLStyle; diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 5ad462594467e..d8cf2874efe44 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -4,21 +4,27 @@ #include namespace gen { - WeightHelper::WeightHelper() { model_ = ""; } + WeightHelper::WeightHelper() { + model_ = ""; + gen::UnknownWeightGroupInfo unassoc("unassociated"); + unassoc.setDescription("Weights with missing or invalid header meta data"); + // Keep track separately so it can be modified within the event + unassociatedGroup_ = std::make_unique(unassoc); + } - bool WeightHelper::isScaleWeightGroup(const ParsedWeight& weight) { + bool WeightHelper::isScaleWeightGroup(const ParsedWeight& weight) const { return (weight.groupname.find("scale_variation") != std::string::npos || weight.groupname.find("Central scale variation") != std::string::npos); } - bool WeightHelper::isPdfWeightGroup(const ParsedWeight& weight) { + bool WeightHelper::isPdfWeightGroup(const ParsedWeight& weight) const { const std::string& name = weight.groupname; if (name.find("PDF_variation") != std::string::npos) return true; return LHAPDF::lookupLHAPDFID(name) != -1; } - bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) { + bool WeightHelper::isPartonShowerWeightGroup(const ParsedWeight& weight) const { const std::string& groupname = boost::to_lower_copy(weight.groupname); std::vector psNames = {"isr", "fsr", "nominal", "baseline", "emission"}; for (const auto& name : psNames) { @@ -28,7 +34,7 @@ namespace gen { return false; } - bool WeightHelper::isOrphanPdfWeightGroup(ParsedWeight& weight) { + bool WeightHelper::isOrphanPdfWeightGroup(ParsedWeight& weight) const { std::pair pairLHA; try { pairLHA = LHAPDF::lookupPDF(stoi(searchAttributes("pdf", weight))); @@ -44,7 +50,7 @@ namespace gen { } } - bool WeightHelper::isMEParamWeightGroup(const ParsedWeight& weight) { + bool WeightHelper::isMEParamWeightGroup(const ParsedWeight& weight) const { return (weight.groupname.find("mg_reweighting") != std::string::npos || weight.groupname.find("variation") != std::string::npos); // variation used for blanket of all variations, might need to change @@ -80,7 +86,7 @@ namespace gen { return ""; } - void WeightHelper::updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight) { + void WeightHelper::updateScaleInfo(gen::ScaleWeightGroupInfo& scaleGroup, const ParsedWeight& weight) const { std::string muRText = searchAttributes("mur", weight); std::string muFText = searchAttributes("muf", weight); std::string dynNumText = searchAttributes("dyn", weight); @@ -120,7 +126,7 @@ namespace gen { } } - int WeightHelper::lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup) { + int WeightHelper::lhapdfId(const ParsedWeight& weight, gen::PdfWeightGroupInfo& pdfGroup) const { std::string lhaidText = searchAttributes("pdf", weight); if (debug_) @@ -142,7 +148,7 @@ namespace gen { return -1; } - void WeightHelper::updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight) { + void WeightHelper::updatePdfInfo(gen::PdfWeightGroupInfo& pdfGroup, const ParsedWeight& weight) const { int lhaid = lhapdfId(weight, pdfGroup); if (debug_) std::cout << "LHAID identified as " << lhaid << std::endl; @@ -166,7 +172,7 @@ namespace gen { pdfGroup.addLhaid(lhaid); } - void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) { + void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) const { if (psGroup.nIdsContained() == DEFAULT_PSWEIGHT_LENGTH) { psGroup.setIsWellFormed(true); psGroup.cacheWeightIndicesByLabel(); @@ -175,12 +181,12 @@ namespace gen { psGroup.setNameIsPythiaSyntax(true); } - bool WeightHelper::splitPdfWeight(ParsedWeight& weight) { - if (weightGroups_[weight.wgtGroup_idx]->weightType() == gen::WeightType::kPdfWeights) { - auto& pdfGroup = *static_cast(weightGroups_[weight.wgtGroup_idx].get()); + bool WeightHelper::splitPdfWeight(ParsedWeight& weight, WeightGroupInfoContainer& weightGroups) const { + if (weightGroups[weight.wgtGroup_idx]->weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = *static_cast(weightGroups[weight.wgtGroup_idx].get()); int lhaid = lhapdfId(weight, pdfGroup); if (lhaid > 0 && !pdfGroup.isIdInParentSet(lhaid) && pdfGroup.parentLhapdfId() > 0) { - weightGroups_.push_back(buildGroup(weight)); + weightGroups.push_back(buildGroup(weight)); weight.wgtGroup_idx++; return true; } @@ -189,7 +195,7 @@ namespace gen { } // Come back to improving this, it's gross - //void WeightHelper::cleanupOrphanCentralWeight() { + void WeightHelper::cleanupOrphanCentralWeight(WeightGroupInfoContainer& weightGroups) const { // std::vector removeList; // for (auto& group : weightGroups_) { // if (group->weightType() != WeightType::kScaleWeights) @@ -208,73 +214,38 @@ namespace gen { // } // } // } - // auto& orphanedWeight = std::find_if(std::begin(weightGroups_), std::end(weightGroups_), - // [](auto& entry) { return entry->containsCentralWeight(); }); - - // std::sort(removeList.begin(), removeList.end(), std::greater()); - // for (auto idx : removeList) { - // weightGroups_.erase(weightGroups_.begin() + idx); - // } - //} - - int WeightHelper::addWeightToProduct( - GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex) { - try { - groupIndex = findContainingWeightGroup(name, weightNum, groupIndex); - } catch (const cms::Exception& e) { - if (!allowUnassociatedWeights_ || unassociatedIndex_ == -1) - throw e; - if (debug_) { - std::cout << "WARNING: " << e.what() << std::endl; - } - groupIndex = unassociatedIndex_; - } - // This should be impossible, but in case the try/catch doesn't work, come here - if (groupIndex < 0 || groupIndex >= static_cast(weightGroups_.size())) - throw cms::Exception("WeightHelper") << "Unmatched Generator weight! ID was " << name << " index was " << std::to_string(weightNum) << - "\nNot found in any of " << std::to_string(weightGroups_.size()) << " weightGroups."; - - auto& group = *weightGroups_[groupIndex]; - bool isUnassociated = groupIndex == unassociatedIndex_; - // NOTE: Adding the weight explicitly to the group is necessary for this code to work properly, - // but it WON'T be propagated to the group info in the GenWeightInfoProduct, which is - // already written to the lumi before the event processing. The Unknown group there will appear empty. - if (isUnassociated) - group.addContainedId(weightNum, name, name); - - int entry = group.weightVectorEntry(name, weightNum); - if (debug_) - std::cout << "Adding weight num " << weightNum << " EntryNum " << entry << " to group " << groupIndex << std::endl; - product.addWeight(weight, groupIndex, entry); - return groupIndex; - } - - int WeightHelper::findContainingWeightGroup(std::string wgtId, int weightIndex, int previousGroupIndex) { - // Start search at previous index, under expectation of ordered weights - previousGroupIndex = previousGroupIndex >= 0 ? previousGroupIndex : 0; - for (int index = previousGroupIndex; index < std::min(index + 1, static_cast(weightGroups_.size())); index++) { - const auto& weightGroup = *weightGroups_[index]; - if (weightGroup.indexInRange(weightIndex) && weightGroup.containsWeight(wgtId, weightIndex)) { - return static_cast(index); - } + auto centralIt = std::find_if(std::begin(weightGroups), std::end(weightGroups), + [](auto& entry) { return entry->weightType() == gen::WeightType::kScaleWeights + && static_cast(entry.get())->containsCentralWeight(); }); + if (centralIt == std::end(weightGroups)) + return; + + auto& centralWeight = *static_cast(centralIt->get()); + + std::vector toRemove; + for (size_t i = 0; i < weightGroups.size(); i++) { + auto& group = weightGroups[i]; + if (group->weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = *static_cast(group.get()); + // These are weights that contain nothing but a single central weight, because + // some versions of madgraph write the central weight separately + if (pdfGroup.nIdsContained() == 1 && pdfGroup.parentLhapdfId() == centralWeight.lhaid()) { + toRemove.push_back(i); + const auto& weightInfo = pdfGroup.weightMetaInfo(0); + centralWeight.addContainedId(weightInfo.globalIndex, weightInfo.id, weightInfo.label, 1, 1); + } + } } - - // Fall back to unordered search - int counter = 0; - for (const auto& weightGroup : weightGroups_) { - if (weightGroup->containsWeight(wgtId, weightIndex)) - return counter; - counter++; + // Indices are guaranteed to be unique, delete from high to low to avoid changing indices + std::sort(std::begin(toRemove), std::end(toRemove), std::greater()); + for (auto i : toRemove) { + weightGroups.erase(std::begin(weightGroups)+i); } - // Needs to be properly handled - throw cms::Exception("Unmatched Generator weight! ID was " + wgtId + " index was " + std::to_string(weightIndex) + - "\nNot found in any of " + std::to_string(weightGroups_.size()) + " weightGroups."); - return -1; } - void WeightHelper::printWeights() { + void WeightHelper::printWeights(const WeightGroupInfoContainer& weightGroups) const { // checks - for (const auto& group : weightGroups_) { + for (const auto& group : weightGroups) { std::cout << std::boolalpha << group->name() << " (" << group->firstId() << "-" << group->lastId() << "): " << group->isWellFormed() << std::endl; if (group->weightType() == gen::WeightType::kScaleWeights) { @@ -311,7 +282,7 @@ namespace gen { } } - std::unique_ptr WeightHelper::buildGroup(ParsedWeight& weight) { + std::unique_ptr WeightHelper::buildGroup(ParsedWeight& weight) const { if (debug_) { std::cout << "Building group for weight group " << weight.groupname << " weight content is " << weight.content << std::endl; @@ -345,26 +316,27 @@ namespace gen { return std::make_unique(weight.groupname); } - void WeightHelper::buildGroups() { - weightGroups_.clear(); + WeightGroupInfoContainer WeightHelper::buildGroups( + std::vector& parsedWeights, bool addUnassociated) const { + WeightGroupInfoContainer weightGroups; int groupOffset = 0; - for (auto& weight : parsedWeights_) { + for (auto& weight : parsedWeights) { weight.wgtGroup_idx += groupOffset; if (debug_) std::cout << "Building group for weight " << weight.content << " group " << weight.groupname << " group index " << weight.wgtGroup_idx << std::endl; - int numGroups = static_cast(weightGroups_.size()); + int numGroups = static_cast(weightGroups.size()); if (weight.wgtGroup_idx == numGroups) { - weightGroups_.push_back(buildGroup(weight)); + weightGroups.push_back(buildGroup(weight)); } else if (weight.wgtGroup_idx >= numGroups) throw cms::Exception("Invalid group index " + std::to_string(weight.wgtGroup_idx)); // split PDF groups - if (splitPdfWeight(weight)) + if (splitPdfWeight(weight, weightGroups)) groupOffset++; - auto& group = weightGroups_[weight.wgtGroup_idx]; + auto& group = weightGroups[weight.wgtGroup_idx]; group->addContainedId(weight.index, weight.id, weight.content); if (group->weightType() == gen::WeightType::kScaleWeights) updateScaleInfo(*static_cast(group.get()), weight); @@ -373,7 +345,10 @@ namespace gen { else if (group->weightType() == gen::WeightType::kPartonShowerWeights) updatePartonShowerInfo(*static_cast(group.get()), weight); } - //cleanupOrphanCentralWeight(); + cleanupOrphanCentralWeight(weightGroups); + if (addUnassociated) + addUnassociatedGroup(weightGroups); + return weightGroups; } } // namespace gen diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 261e998244f66..118e3b6b96e9a 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -23,8 +23,8 @@ #include namespace { - typedef std::vector WeightGroupDataContainer; - typedef std::array, 2> WeightGroupsToStore; + typedef std::vector WeightGroupDataContainer; + typedef std::array WeightGroupsToStore; } // namespace using CounterMap = genCounter::CounterMap; using Counter = genCounter::Counter; @@ -49,7 +49,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer& weightsInfoHandle, gen::WeightType weightType, - int maxStore) const; + size_t maxStore) const; WeightGroupsToStore groupsToStore(bool foundLheWeights, edm::Handle& genWeightInfoHandle, @@ -336,18 +336,18 @@ void GenWeightsTableProducer::addWeightGroupToTable( std::string label = groupInfo.group->description(); auto weights = allWeights.at(groupInfo.index); if (weightType == gen::WeightType::kScaleWeights) { - const auto& scaleGroup = *std::static_pointer_cast(groupInfo.group); + const auto& scaleGroup = *static_cast(groupInfo.group); auto weightsAndLabel = orderedScaleWeights(weights, scaleGroup); label.append(weightsAndLabel.first); weights = weightsAndLabel.second; } else if (weightType == gen::WeightType::kPartonShowerWeights) { - const auto psGroup = std::static_pointer_cast(groupInfo.group); + const auto& psGroup = *static_cast(groupInfo.group); if(!keepAllPSWeights_) { - auto weightsAndLabel = preferredPSweights(weights, *psGroup); + auto weightsAndLabel = preferredPSweights(weights, psGroup); label.append(weightsAndLabel.first); weights = weightsAndLabel.second; - } else if (psGroup->isWellFormed()) { - double baseline = weights[psGroup->weightIndexFromLabel("Baseline")]; + } else if (psGroup.isWellFormed()) { + double baseline = weights[psGroup.weightIndexFromLabel("Baseline")]; for (size_t i = 0; i < weights.size(); i++) weights[i] = weights[i]/baseline; label = "PS weights (w_var / w_nominal)"; @@ -384,20 +384,20 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, continue; auto& hand = isLHE ? lheWeightInfoHandle : genWeightInfoHandle; bool ignoreGroups = isLHE ? ignoreLheGroups_ : ignoreGenGroups_; + auto& toStorePerType = weightsToStore[genOrLhe]; if (ignoreGroups) { - auto& groups = hand->allWeightGroupsInfo(); - for (size_t i = 0; i < groups.size(); i++) - weightsToStore.at(genOrLhe).push_back({i, std::shared_ptr(groups[i]->clone())}); + toStorePerType = hand->allWeightGroupsInfoWithIndices(); } else { - for (auto weightType : gen::allWeightTypes) { - if (weightType == gen::WeightType::kUnknownWeights && !storeUnknown) + for (auto& typeAndCount : storePerType) { + if (typeAndCount.first == gen::WeightType::kUnknownWeights && !storeUnknown) continue; - auto allWeights = weightDataPerType(hand, weightType, storePerType[weightType]); + // Since the count isn't updated, the counts are effectively independent between LHE and GEN + auto groupsPerType = weightDataPerType(hand, typeAndCount.first, typeAndCount.second); // Only store unknown if at least one specified groups is empty if (!storeUnknown && !groupsToSearch.empty()) { - auto it = std::find(std::begin(groupsToSearch), std::end(groupsToSearch), weightType); + auto it = std::find(std::begin(groupsToSearch), std::end(groupsToSearch), typeAndCount.first); if (it != std::end(groupsToSearch)) { - if (allWeights.empty()) + if (groupsPerType.empty()) storeUnknown = true; // Remove from array to avoid repeating the check on GEN. NOTE, if parton // shower weights are included as one of the ones to consider, this can @@ -407,8 +407,7 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, } } - for (auto& w : allWeights) - weightsToStore.at(genOrLhe).push_back({w.index, std::move(w.group)}); + toStorePerType.insert(std::end(toStorePerType), std::begin(groupsPerType), std::end(groupsPerType)); } } } @@ -417,27 +416,17 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsInfoHandle, gen::WeightType weightType, - int maxStore) const { - std::vector allgroups; + size_t maxStore) const { + WeightGroupDataContainer allgroups; if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { - allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + auto pdfIds = pdfIds_; + if (pdfIds.size() > maxStore) + pdfIds.resize(maxStore); + allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds); } else - allgroups = weightsInfoHandle->weightGroupsAndIndicesByType(weightType); + allgroups = weightsInfoHandle->weightGroupsAndIndicesByType(weightType, maxStore); - int toStore = maxStore; - if (maxStore < 0 || static_cast(allgroups.size()) <= maxStore) { - // Modify size in case one type of weight is present in multiple products - maxStore -= allgroups.size(); - toStore = allgroups.size(); - } - - WeightGroupDataContainer out; - for (int i = 0; i < toStore; i++) { - auto& group = allgroups.at(i); - gen::SharedWeightGroupData temp = {group.index, std::shared_ptr(group.group->clone())}; - out.push_back(temp); - } - return out; + return allgroups; } std::pair> diff --git a/PhysicsTools/NanoAOD/python/genWeights_cff.py b/PhysicsTools/NanoAOD/python/genWeights_cff.py index c4176d3211399..7f399e93dd977 100644 --- a/PhysicsTools/NanoAOD/python/genWeights_cff.py +++ b/PhysicsTools/NanoAOD/python/genWeights_cff.py @@ -4,11 +4,9 @@ genWeightsNano = genWeights.clone() genWeightsNano.weightProductLabels = ["genWeights"] -genWeightsNano.debug = True lheWeightsNano = lheWeights.clone() lheWeightsNano.weightProductLabels = ["lheWeights"] -lheWeightsNano.debug = True genWeightsTable = cms.EDProducer("GenWeightsTableProducer", lheWeightPrecision = cms.int32(14), @@ -31,6 +29,4 @@ # nStoreUngroupedLhe = cms.untracked.int32(100), ) -#genWeightsTableTask = cms.Task(lheWeights, genWeights, genWeightsTable) -#genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano, genWeightsTable) -genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano) +genWeightsTableTask = cms.Task(lheWeightsNano, genWeightsNano, genWeightsTable) diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index b5fdb34672ac6..0b30ef5b0e544 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -18,32 +18,39 @@ namespace gen { const gen::WeightGroupInfo* group; }; - struct SharedWeightGroupData { - size_t index; - std::shared_ptr group; - }; + typedef std::vector> WeightGroupInfoContainer; } // namespace gen class GenWeightInfoProduct { public: GenWeightInfoProduct() {} - GenWeightInfoProduct(std::vector>& weightGroups); - GenWeightInfoProduct(std::vector> weightGroups); + GenWeightInfoProduct(gen::WeightGroupInfoContainer& weightGroups); GenWeightInfoProduct(std::unique_ptr other) { - for (auto& ptr : other->weightGroupsInfo_) { - std::unique_ptr cloneptr(ptr->clone()); - weightGroupsInfo_.emplace_back(std::move(cloneptr)); - } + copy(*other); + } + GenWeightInfoProduct(const GenWeightInfoProduct& other) { + copy(other); + } + GenWeightInfoProduct& operator=(const GenWeightInfoProduct& other) { + copy(other); + return *this; + } + void copy(const GenWeightInfoProduct& other) { + for (auto& ptr : other.weightGroupsInfo_) { + std::unique_ptr cloneptr(ptr->clone()); + weightGroupsInfo_.emplace_back(std::move(cloneptr)); + } + unassociatedIdx_ = other.unassociatedIdx_; } ~GenWeightInfoProduct() {} - const std::vector>& allWeightGroupsInfo() const; + const gen::WeightGroupInfoContainer& allWeightGroupsInfo() const; const std::vector allWeightGroupsInfoWithIndices() const; - const gen::WeightGroupInfo* containingWeightGroupInfo(int index) const; + gen::WeightGroupData containingWeightGroupInfo(int index, size_t startSearch=0) const; const gen::WeightGroupInfo* orderedWeightGroupInfo(int index) const; std::vector weightGroupsByType(gen::WeightType type) const; std::vector weightGroupIndicesByType(gen::WeightType type) const; - std::vector weightGroupsAndIndicesByType(gen::WeightType type) const; + std::vector weightGroupsAndIndicesByType(gen::WeightType type, int maxStore=-1) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; void addWeightGroupInfo(gen::WeightGroupInfo info); @@ -60,10 +67,11 @@ class GenWeightInfoProduct { return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, [](auto sum, auto& entry) { return sum + entry->nIdsContained(); }); } - + const int unassociatedIdx() const { return unassociatedIdx_; } private: - std::vector> weightGroupsInfo_; + gen::WeightGroupInfoContainer weightGroupsInfo_; + int unassociatedIdx_ = -1; }; #endif // GeneratorWeightInfo_LHEInterface_GenWeightInfoProduct_h diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h index 411f4716c768a..4a1c54bdfae85 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -34,8 +34,10 @@ class GenWeightProduct { void addWeight(double weight, int setEntry, int weightNum) { if (weightsVector_.empty() && setEntry == 0) addWeightSet(); - if (static_cast(weightsVector_.size()) <= setEntry) - throw cms::Exception("GenWeightProduct") << "Trying to add weight index outside the range of weights expected"; + int maxSets = static_cast(weightsVector_.size()); + if (maxSets <= setEntry) + throw cms::Exception("GenWeightProduct") << "WeightGroup index " << setEntry + << " is exceeds the number of WeightGroups expected (max " << maxSets << " )"; auto& weights = weightsVector_[setEntry]; if (static_cast(weights.size()) <= weightNum) { weights.resize(weightNum + 1); diff --git a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h index 5c1516375ab53..d9387af03399a 100644 --- a/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h @@ -54,9 +54,9 @@ namespace gen { virtual ~WeightGroupInfo(){}; void copy(const WeightGroupInfo& other); virtual WeightGroupInfo* clone() const; - WeightMetaInfo weightMetaInfo(int weightEntry) const; - WeightMetaInfo weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const; - WeightMetaInfo weightMetaInfoByGlobalIndex(int weightEntry) const; + const WeightMetaInfo& weightMetaInfo(int weightEntry) const; + const WeightMetaInfo& weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const; + const WeightMetaInfo& weightMetaInfoByGlobalIndex(int weightEntry) const; int weightVectorEntry(std::string& wgtId) const; bool containsWeight(std::string& wgtId, int weightEntry) const; bool containsWeight(int weightEntry) const; diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 8a6e771643057..081260a5b46b1 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -6,11 +6,13 @@ #include "FWCore/Utilities/interface/Exception.h" GenWeightInfoProduct::GenWeightInfoProduct(std::vector>& weightGroups) { - weightGroupsInfo_ = std::move(weightGroups); -} - -GenWeightInfoProduct::GenWeightInfoProduct(std::vector> weightGroups) { - weightGroupsInfo_ = std::move(weightGroups); + // Could just do a std::move on the vector, but copying is safer if the user expects the vector to still be usable + for (auto& ptr : weightGroups) { + std::unique_ptr cloneptr(ptr->clone()); + weightGroupsInfo_.emplace_back(std::move(cloneptr)); + } + auto it = std::find_if(std::begin(weightGroups), std::end(weightGroups), [](auto& entry) { return entry->name() == "unassociated"; }); + unassociatedIdx_ = std::distance(std::begin(weightGroups), it); } const std::vector>& GenWeightInfoProduct::allWeightGroupsInfo() const { @@ -24,15 +26,17 @@ const std::vector GenWeightInfoProduct::allWeightGroupsInf return groupInfo; } -const gen::WeightGroupInfo* GenWeightInfoProduct::containingWeightGroupInfo(int index) const { - // The weight values in the product are arranged to match the order of the groups in the GenWeightInfoProduct - int maxIdx = 0; - for (const auto& weightGroup : weightGroupsInfo_) { - int minIdx = maxIdx; - maxIdx = maxIdx+weightGroup->nIdsContained(); - if (index >= minIdx && index < maxIdx) - return weightGroup.get(); - } +gen::WeightGroupData GenWeightInfoProduct::containingWeightGroupInfo(int index, size_t startSearch) const { + // When filling the weights, most likely to find the weight matches the previous group or the one after + if (startSearch < weightGroupsInfo_.size() && weightGroupsInfo_[startSearch]->containsWeight(index)) + return {startSearch, weightGroupsInfo_[startSearch].get()}; + else if (startSearch+1 < weightGroupsInfo_.size() && weightGroupsInfo_[startSearch+1]->containsWeight(index)) + return {startSearch+1, weightGroupsInfo_[startSearch+1].get()}; + + auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [index](auto& entry) { return entry->containsWeight(index); }); + if (it != std::end(weightGroupsInfo_)) + return {static_cast(std::distance(std::begin(weightGroupsInfo_), it)), it->get()}; + throw cms::Exception("GenWeightInfoProduct") << "No weight group found containing the weight index requested"; } @@ -43,9 +47,10 @@ const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int wei return weightGroupsInfo_[weightGroupIndex].get(); } -std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type) const { +std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type, int maxStore) const { std::vector matchingGroups; - for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { + size_t toStore = maxStore <= 0 ? weightGroupsInfo_.size() : std::min(maxStore, weightGroupsInfo_.size()); + for (size_t i = 0; i < toStore; i++) { const gen::WeightGroupInfo* group = weightGroupsInfo_[i].get(); if (group->weightType() == type) matchingGroups.push_back({i, group}); diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index aec7b2cd14285..0b172b821fd0f 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -19,10 +19,10 @@ namespace gen { WeightGroupInfo* WeightGroupInfo::clone() const { throw cms::Exception("WeightGroupInfo") - << "WeightGroupInfo is abstract, so it's clone() method can't be implemented."; + << "In group " << name_ << ": WeightGroupInfo is abstract, so it's clone() method can't be implemented."; } - WeightMetaInfo WeightGroupInfo::weightMetaInfo(int weightEntry) const { + const WeightMetaInfo& WeightGroupInfo::weightMetaInfo(int weightEntry) const { if (weightEntry < 0 || weightEntry >= static_cast(idsContained_.size())) throw cms::Exception("WeightGroupInfo") << "Local index " << std::to_string(weightEntry) << " is not within the range of group " << name_ @@ -30,12 +30,12 @@ namespace gen { return idsContained_.at(weightEntry); } - WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(int weightEntry) const { + const WeightMetaInfo& WeightGroupInfo::weightMetaInfoByGlobalIndex(int weightEntry) const { std::string emptyLabel = ""; return weightMetaInfoByGlobalIndex(emptyLabel, weightEntry); } - WeightMetaInfo WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const { + const WeightMetaInfo& WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const { int entry = weightVectorEntry(wgtId, weightEntry); if (entry < 0 || entry >= static_cast(idsContained_.size())) throw cms::Exception("WeightGroupInfo") From a29eea3fa6fbc84c5817383365bc33d4b97ee176 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 02:29:47 +0100 Subject: [PATCH 14/16] Make producers edm::Global --- .../Core/interface/GenWeightHelper.h | 2 +- .../Core/interface/LHEWeightHelper.h | 10 +- .../Core/interface/WeightHelper.h | 35 +++---- .../Core/plugins/GenWeightProductProducer.cc | 75 +++++++------- .../Core/plugins/LHEWeightProductProducer.cc | 98 ++++++++++--------- .../Core/src/GenWeightHelper.cc | 2 +- .../Core/src/LHEWeightHelper.cc | 34 ++++--- GeneratorInterface/Core/src/WeightHelper.cc | 8 +- .../plugins/GenWeightsTableProducer.cc | 11 +-- PhysicsTools/NanoAOD/python/genWeights_cff.py | 5 +- .../src/GenWeightInfoProduct.cc | 15 ++- 11 files changed, 151 insertions(+), 144 deletions(-) diff --git a/GeneratorInterface/Core/interface/GenWeightHelper.h b/GeneratorInterface/Core/interface/GenWeightHelper.h index 0947efb3eda7b..3fcf4169f7aba 100644 --- a/GeneratorInterface/Core/interface/GenWeightHelper.h +++ b/GeneratorInterface/Core/interface/GenWeightHelper.h @@ -19,7 +19,7 @@ namespace gen { class GenWeightHelper : public WeightHelper { public: GenWeightHelper(); - std::vector> parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociatedGroup); + std::vector> parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociatedGroup) const; }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index 5653187084498..5313137bfb027 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -22,11 +22,17 @@ namespace gen { LHEWeightHelper() : WeightHelper(){}; enum class ErrorType { Empty, SwapHeader, HTMLStyle, NoWeightGroup, TrailingStr, Unknown, NoError }; + const std::unordered_map errorTypeAsString_ = { + {ErrorType::Empty, "Empty header"}, {ErrorType::SwapHeader, "Header info out of order" }, + {ErrorType::HTMLStyle, "Header is invalid HTML"}, {ErrorType::TrailingStr, "Header has extraneous info"}, + {ErrorType::Unknown, "Unregonized error"}, {ErrorType::NoError, "No error here!"} + }; std::vector> parseWeights(std::vector headerLines, bool addUnassociated) const; - bool isConsistent(const std::vector& headerLines) const; + bool isConsistent(const std::string& fullHeader) const; void swapHeaders(std::vector& headerLines) const; void setFailIfInvalidXML(bool value) { failIfInvalidXML_ = value; } + bool failIfInvalidXML() const { return failIfInvalidXML_; } private: std::string weightgroupKet_ = ""; @@ -37,7 +43,7 @@ namespace gen { bool validateAndFixHeader(std::vector& headerLines, tinyxml2::XMLDocument& xmlDoc) const; tinyxml2::XMLError tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const; tinyxml2::XMLError tryRemoveTrailings(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const; - ErrorType findErrorType(int xmlError, const std::vector& headerLines) const; + ErrorType findErrorType(int xmlError, const std::string& headerLines) const; }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index 17a52311bfe84..116ed2f66d112 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -32,10 +32,8 @@ namespace gen { WeightHelper(); template - std::unique_ptr weightProduct(const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0); + std::unique_ptr weightProduct(const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) const; - void setfillEmptyIfWeightFails(bool value) { fillEmptyIfWeightFails_ = value; } - void setModel(std::string model) { model_ = model; } void setGuessPSWeightIdx(bool guessPSWeightIdx) { PartonShowerWeightGroupInfo::setGuessPSWeightIdx(guessPSWeightIdx); } @@ -47,15 +45,11 @@ namespace gen { int addWeightToProduct( GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex); void setDebug(bool value) { debug_ = value; } - bool fillEmptyIfWeightFails() { return fillEmptyIfWeightFails_; } protected: bool debug_ = false; - bool fillEmptyIfWeightFails_ = false; - std::unique_ptr unassociatedGroup_; const unsigned int FIRST_PSWEIGHT_ENTRY = 2; const unsigned int DEFAULT_PSWEIGHT_LENGTH = 46; - std::string model_; std::map currWeightAttributeMap_; std::map currGroupAttributeMap_; bool isScaleWeightGroup(const ParsedWeight& weight) const; @@ -94,13 +88,19 @@ namespace gen { template std::unique_ptr WeightHelper::weightProduct( - const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) { + const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) const { auto weightProduct = std::make_unique(w0); weightProduct->setNumWeightSets(weightsInfo.numberOfGroups()); gen::WeightGroupData groupData = {0, nullptr}; int i = 0; // size=1 happens if there are no PS weights, so the weights vector contains only the central GEN weight. if (weights.size() > 1) { + // This gets remade every event to avoid having state-dependence in the helper class + // could think about doing caching instead + int unassociatedIdx = weightsInfo.unassociatedIdx(); + std::unique_ptr unassociatedGroup; + if (unassociatedIdx != -1) + unassociatedGroup = std::make_unique("unassociated"); for (const auto& weight : weights) { double wgtval; std::string wgtid; @@ -114,34 +114,21 @@ namespace gen { try { groupData = weightsInfo.containingWeightGroupInfo(i, groupData.index); } catch (const cms::Exception& e) { - int unassociatedIdx = weightsInfo.unassociatedIdx(); if (unassociatedIdx == -1) throw e; if (debug_) { std::cout << "WARNING: " << e.what() << std::endl; } // Access the unassociated group separately so it can be modified - unassociatedGroup_->addContainedId(i, wgtid, wgtid); - groupData = {static_cast(unassociatedIdx), unassociatedGroup_.get()}; + unassociatedGroup->addContainedId(i, wgtid, wgtid); + groupData = {static_cast(unassociatedIdx), unassociatedGroup.get()}; } + int entry = groupData.group->weightVectorEntry(wgtid, i); // TODO: is this too slow? - int entry = groupData.group->weightVectorEntry(wgtid, i); if (debug_) std::cout << "Adding weight num " << i << " EntryNum " << entry << " to group " << groupData.index << std::endl; weightProduct->addWeight(wgtval, groupData.index, entry); - // TODO: Need to understand if this is still needed - //catch (cms::Exception& e) { - // if (fillEmptyIfWeightFails_) { - // std::cerr << "WARNING: " << e.what() << std::endl; - // std::cerr << "fillEmptyIfWeightFails_ is set to True, so variations will be empty!!" << std::endl; - // weightProduct->setNumWeightSets(1); // Only central weight - // return weightProduct; - // } else { - // throw cms::Exception("ERROR: " + std::string(e.what()) + - // "\nfillEmptyIfWeightFails_ is set to False, so exiting code"); - // } - //} i++; } } diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index 566547aac397e..a5cf5f85e6e16 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -5,7 +5,7 @@ // user include files #include "FWCore/Framework/interface/Frameworkfwd.h" -#include "FWCore/Framework/interface/one/EDProducer.h" +#include "FWCore/Framework/interface/global/EDProducer.h" #include "FWCore/Framework/interface/LuminosityBlock.h" #include "FWCore/Framework/interface/Run.h" @@ -27,12 +27,20 @@ #include "FWCore/Utilities/interface/transform.h" #include -class GenWeightProductProducer : public edm::one::EDProducer { +struct GenWeightInfoProdData { + bool makeNewProduct; + GenWeightInfoProduct product; +}; + +class GenWeightProductProducer : public edm::global::EDProducer> { public: explicit GenWeightProductProducer(const edm::ParameterSet& iConfig); ~GenWeightProductProducer() override; - void produce(edm::Event&, const edm::EventSetup&) override; - void beginLuminosityBlockProduce(edm::LuminosityBlock& lb, edm::EventSetup const& c) override; + void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; + void globalBeginLuminosityBlockProduce(edm::LuminosityBlock& lb, edm::EventSetup const& c) const override; + std::shared_ptr globalBeginLuminosityBlock(const edm::LuminosityBlock& lb, edm::EventSetup const& c) const override; + void globalEndLuminosityBlock(const edm::LuminosityBlock& lb, edm::EventSetup const& c) const override {} static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); private: gen::GenWeightHelper weightHelper_; @@ -40,77 +48,72 @@ class GenWeightProductProducer : public edm::one::EDProducer genEventToken_; std::vector> weightInfoTokens_; const bool debug_; - bool foundWeightProduct_ = false; edm::EDPutTokenT groupPutToken_; GenWeightInfoProduct weightsInfo_; + bool allowUnassociated_; }; -// -// constructors and destructor -// GenWeightProductProducer::GenWeightProductProducer(const edm::ParameterSet& iConfig) : genLumiInfoToken_(consumes(iConfig.getParameter("genInfo"))), genEventToken_(consumes(iConfig.getParameter("genInfo"))), weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), [this](const std::string& tag) { return mayConsume(tag); })), debug_(iConfig.getUntrackedParameter("debug", false)), - groupPutToken_(produces()) { + groupPutToken_(produces()), + allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { weightHelper_.setDebug(debug_); produces(); produces(); weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); - weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); } GenWeightProductProducer::~GenWeightProductProducer() {} -// ------------ method called to produce the data ------------ -void GenWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { +void GenWeightProductProducer::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const { // In case there is already a product in the file when this is scheduled // (leave the list of weightproducts empty if you always want to produce a new product) - if (foundWeightProduct_) + const auto& productInfo = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); + if (!productInfo.makeNewProduct) return; edm::Handle genEventInfo; iEvent.getByToken(genEventToken_, genEventInfo); float centralWeight = !genEventInfo->weights().empty() ? genEventInfo->weights().at(0) : 1.; - auto weightProduct = weightHelper_.weightProduct(weightsInfo_, genEventInfo->weights(), centralWeight); + auto weightProduct = weightHelper_.weightProduct(productInfo.product, genEventInfo->weights(), centralWeight); iEvent.put(std::move(weightProduct)); } -void GenWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) { - edm::Handle weightInfoHandle; +std::shared_ptr GenWeightProductProducer::globalBeginLuminosityBlock(const edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) const { + GenWeightInfoProdData productInfo; + edm::Handle weightInfoHandle; for (auto& token : weightInfoTokens_) { iLumi.getByToken(token, weightInfoHandle); if (weightInfoHandle.isValid()) { - foundWeightProduct_ = true; - return; + productInfo.makeNewProduct = false; + break; } } edm::Handle genLumiInfoHandle; iLumi.getByToken(genLumiInfoToken_, genLumiInfoHandle); - //std::unique_ptr weightInfoProduct = std::make_unique(); - std::unique_ptr weightInfoProduct; if (genLumiInfoHandle.isValid()) { - std::string label = genLumiInfoHandle->configDescription(); - boost::replace_all(label, "-", "_"); - weightHelper_.setModel(label); - // Always add an unassociated group, which generally will not be filled - // TODO: control this with an argument? - auto weightGroups = weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames(), true); - weightInfoProduct = std::make_unique(weightGroups); - weightsInfo_ = *weightInfoProduct; - } else if (weightHelper_.fillEmptyIfWeightFails() && debug_) { - weightInfoProduct = std::make_unique(); - } else { - throw cms::Exception("GenWeightProductProducer") - << "genLumiInfoHeader not found, code is exiting." << std::endl - << "If this is expect and want to continue, set fillEmptyIfWeightFails to True"; - } + auto weightGroups = weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames(), allowUnassociated_); + productInfo.product = GenWeightInfoProduct(weightGroups); + } + return std::make_shared(productInfo); +} + +void GenWeightProductProducer::globalBeginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) const { + edm::Handle weightInfoHandle; + + const auto& productInfo = *luminosityBlockCache(iLumi.index()); + if (!productInfo.makeNewProduct) + return; + + auto weightInfoProduct = std::make_unique(productInfo.product); iLumi.emplace(groupPutToken_, std::move(weightInfoProduct)); } @@ -123,7 +126,7 @@ void GenWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); desc.addUntracked("debug", false)->setComment("Output debug info"); desc.addUntracked("guessPSWeightIdx", false)->setComment("If not possible to parse text, guess the parton shower weight indices"); - desc.addUntracked("fillEmptyIfWeightFails", false)->setComment("Produce an empty product if parsing of header fails"); + desc.addUntracked("allowUnassociatedWeights", false)->setComment("Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); descriptions.add("genWeights", desc); } diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index d60427b02b86f..6c2a7de9d8da6 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -5,8 +5,7 @@ // user include files #include "FWCore/Framework/interface/Frameworkfwd.h" -#include "FWCore/Framework/interface/one/EDProducer.h" -#include "FWCore/Framework/interface/LuminosityBlock.h" +#include "FWCore/Framework/interface/global/EDProducer.h" #include "FWCore/Framework/interface/Run.h" #include "FWCore/Framework/interface/Event.h" @@ -26,31 +25,34 @@ #include "FWCore/ServiceRegistry/interface/Service.h" #include "FWCore/Utilities/interface/transform.h" +#include "FWCore/Utilities/interface/ReusableObjectHolder.h" -class LHEWeightProductProducer : public edm::one::EDProducer> { +struct GenWeightInfoProdData { + bool makeNewProduct; + GenWeightInfoProduct product; +}; + +class LHEWeightProductProducer : public edm::global::EDProducer, + edm::BeginRunProducer> { public: explicit LHEWeightProductProducer(const edm::ParameterSet& iConfig); ~LHEWeightProductProducer() override; - void produce(edm::Event&, const edm::EventSetup&) override; - void beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) override; - std::shared_ptr globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const; - void globalEndRun(edm::Run const& iRun, edm::EventSetup const&) {} + void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const; + void globalBeginRunProduce(edm::Run& run, edm::EventSetup const& es) const; + void globalEndRunProduce(edm::Run& run, edm::EventSetup const& es) const {}; + std::shared_ptr globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const; + void globalEndRun(edm::Run const& iRun, edm::EventSetup const&) const override {} static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); - private: gen::LHEWeightHelper weightHelper_; - std::vector lheLabels_; + const std::vector lheLabels_; std::vector> lheEventTokens_; std::vector> lheRunInfoTokens_; std::vector> weightInfoTokens_; - bool foundWeightProduct_ = false; - bool hasLhe_ = true; edm::EDPutTokenT groupPutToken_; - GenWeightInfoProduct weightsInfo_; + bool allowUnassociated_; }; -// TODO: Accept a vector of strings (source, externalLHEProducer) exit if neither are found LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iConfig) : lheLabels_(iConfig.getParameter>("lheSourceLabels")), lheEventTokens_(edm::vector_transform( @@ -58,20 +60,21 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon lheRunInfoTokens_(edm::vector_transform( lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - groupPutToken_(produces()) { + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + groupPutToken_(produces()), + allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); - weightHelper_.setfillEmptyIfWeightFails(iConfig.getUntrackedParameter("fillEmptyIfWeightFails", false)); weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); weightHelper_.setGuessPSWeightIdx(iConfig.getUntrackedParameter("guessPSWeightIdx", false)); } LHEWeightProductProducer::~LHEWeightProductProducer() {} -// ------------ method called to produce the data ------------ -void LHEWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { - if (foundWeightProduct_ || !hasLhe_) +void LHEWeightProductProducer::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const { + const auto& productInfo = *runCache(iEvent.getRun().index()); + + if (!productInfo.makeNewProduct) return; edm::Handle lheEventInfo; @@ -82,11 +85,25 @@ void LHEWeightProductProducer::produce(edm::Event& iEvent, const edm::EventSetup } } - auto weightProduct = weightHelper_.weightProduct(weightsInfo_, lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); + auto weightProduct = weightHelper_.weightProduct(productInfo.product, lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); iEvent.put(std::move(weightProduct)); } -std::shared_ptr LHEWeightProductProducer::globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const { +std::shared_ptr LHEWeightProductProducer::globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const { + bool hasWeightProduct = false; + edm::Handle weightInfoHandle; + for (auto& token : weightInfoTokens_) { + run.getByToken(token, weightInfoHandle); + if (weightInfoHandle.isValid()) { + hasWeightProduct = true; + break; + } + } + GenWeightInfoProdData productInfo; + productInfo.makeNewProduct = !hasWeightProduct; + if (hasWeightProduct) + return std::make_shared(productInfo); + edm::Handle lheRunInfoHandle; for (auto& label : lheLabels_) { run.getByLabel(label, lheRunInfoHandle); @@ -95,7 +112,7 @@ std::shared_ptr LHEWeightProductProducer::globalB } } if (!lheRunInfoHandle.isValid()) - return {}; + return std::make_shared(productInfo); typedef std::vector::const_iterator header_cit; LHERunInfoProduct::Header headerWeightInfo; @@ -108,37 +125,26 @@ std::shared_ptr LHEWeightProductProducer::globalB gen::WeightGroupInfoContainer groups; try { - // TODO: Maybe make unassociated group optional - groups = weightHelper_.parseWeights(headerWeightInfo.lines(), true); + groups = weightHelper_.parseWeights(headerWeightInfo.lines(), allowUnassociated_); } catch (cms::Exception& e) { std::string error = e.what(); error += "\n NOTE: if you want to attempt to process this sample anyway, set failIfInvalidXML = False " - "in the configuration file\n. If you set this flag and the error persists, the issue " + "in the configuration file (current value is "; + error += weightHelper_.failIfInvalidXML() ? "True" : "False"; + error += ")\n.If you set this flag and the error persists, the issue " " is fatal and must be solved at the LHE/gridpack level."; throw cms::Exception("LHEWeightProductProducer") << error; } - return std::make_shared(std::move(groups)); + // Need copy for the run cache + productInfo.product = GenWeightInfoProduct(groups); + return std::make_shared(productInfo); } -void LHEWeightProductProducer::beginLuminosityBlockProduce(edm::LuminosityBlock& lumi, edm::EventSetup const& es) { - edm::Handle weightInfoHandle; - - for (auto& token : weightInfoTokens_) { - lumi.getByToken(token, weightInfoHandle); - if (weightInfoHandle.isValid()) { - foundWeightProduct_ = true; - return; - } - } - - if (!hasLhe_) - return; - - auto weightInfoProduct = std::make_unique(*runCache(lumi.getRun().index())); - weightsInfo_ = *weightInfoProduct; - - lumi.emplace(groupPutToken_, std::move(weightInfoProduct)); +void LHEWeightProductProducer::globalBeginRunProduce(edm::Run& run, const edm::EventSetup& es) const { + const auto& productInfo = *runCache(run.index()); + auto prod = std::make_unique(productInfo.product); + run.emplace(groupPutToken_, std::move(prod)); } void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { @@ -151,7 +157,7 @@ void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); desc.addUntracked("debug", false)->setComment("Output debug info"); desc.addUntracked("failIfInvalidXML", true)->setComment("Throw exception if XML header is invalid (rather than trying to recover and parse anyway)"); - desc.addUntracked("fillEmptyIfWeightFails", false)->setComment("Produce an empty product if parsing of header fails"); + desc.addUntracked("allowUnassociatedWeights", false)->setComment("Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); descriptions.add("lheWeights", desc); } diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index 541e60d8be9f1..6922ef14bbdb8 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -6,7 +6,7 @@ using namespace tinyxml2; namespace gen { GenWeightHelper::GenWeightHelper() {} - std::vector> GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociated) { + std::vector> GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociated) const { std::vector parsedWeights; int index = 0; int groupIndex = -1; diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 274c0c43f592b..616c102933bb7 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -16,11 +16,13 @@ namespace gen { int xmlError = xmlDoc.Parse(fullHeader.c_str()); ErrorType errorType; - while (errorType = findErrorType(xmlError, headerLines), errorType != ErrorType::NoError) { + while (errorType = findErrorType(xmlError, fullHeader), errorType != ErrorType::NoError) { if (failIfInvalidXML_) { - xmlDoc.PrintError(); + std::cout << "XML error: "; + xmlDoc.PrintError(); throw cms::Exception("LHEWeightHelper") - << "The LHE header is not valid XML! Weight information was not properly parsed."; + << "The LHE header is not valid! Weight information was not properly parsed." + << " The error type is '" << errorTypeAsString_.at(errorType) << "'"; } else if (errorType == ErrorType::HTMLStyle) { if (debug_) std::cout << " >>> This file uses > instead of >\n"; @@ -28,8 +30,10 @@ namespace gen { } else if (errorType == ErrorType::SwapHeader) { if (debug_) std::cout << " >>> Some headers in the file are swapped\n"; - swapHeaders(headerLines); - fullHeader = boost::algorithm::join(headerLines, ""); + std::vector fixedHeaderLines; + boost::split(fixedHeaderLines, fullHeader, boost::is_any_of("\n")); + swapHeaders(fixedHeaderLines); + fullHeader = boost::algorithm::join(fixedHeaderLines, "\n"); xmlError = xmlDoc.Parse(fullHeader.c_str()); } else if (errorType == ErrorType::TrailingStr) { if (debug_) @@ -111,13 +115,13 @@ namespace gen { } } - if (!fillEmptyIfWeightFails_) { - throw std::runtime_error("couldn't find groupname"); - } + throw cms::Exception("LHEWeightHelper") << "Could not parse a name for weight group"; return ""; } - bool LHEWeightHelper::isConsistent(const std::vector& headerLines) const { + bool LHEWeightHelper::isConsistent(const std::string& fullHeader) const { + std::vector headerLines; + boost::split(headerLines, fullHeader, boost::is_any_of("\n")); int curLevel = 0; for (const auto& line : headerLines) { @@ -141,7 +145,8 @@ namespace gen { int open = -1; int close = -1; for (size_t idx = 0; idx < headerLines.size(); idx++) { - std::string line = headerLines[idx]; + std::string& line = headerLines[idx]; + std::cout << "Line is " << line << std::endl;; if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { @@ -178,11 +183,10 @@ namespace gen { return xmlDoc.Parse(fullHeader.c_str()); } - LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, const std::vector& headerLines) const { - std::string fullHeader = boost::algorithm::join(headerLines, ""); + LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, const std::string& fullHeader) const { if (fullHeader.size() == 0) return ErrorType::Empty; - else if (!isConsistent(headerLines)) + else if (!isConsistent(fullHeader)) return ErrorType::SwapHeader; else if (fullHeader.find("<") != std::string::npos || fullHeader.find(">") != std::string::npos) return ErrorType::HTMLStyle; @@ -195,7 +199,7 @@ namespace gen { return ErrorType::TrailingStr; else return ErrorType::Unknown; - } else - return ErrorType::NoError; + } + return ErrorType::NoError; } } // namespace gen diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index d8cf2874efe44..632db40c198b4 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -4,13 +4,7 @@ #include namespace gen { - WeightHelper::WeightHelper() { - model_ = ""; - gen::UnknownWeightGroupInfo unassoc("unassociated"); - unassoc.setDescription("Weights with missing or invalid header meta data"); - // Keep track separately so it can be modified within the event - unassociatedGroup_ = std::make_unique(unassoc); - } + WeightHelper::WeightHelper() {} bool WeightHelper::isScaleWeightGroup(const ParsedWeight& weight) const { return (weight.groupname.find("scale_variation") != std::string::npos || diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 118e3b6b96e9a..197d63b03ccab 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -69,7 +69,7 @@ class GenWeightsTableProducer : public edm::global::EDProducer lheWeightInfoHandle; for (auto& token : lheWeightInfoTokens_) { - iLumi.getByToken(token, lheWeightInfoHandle); + iLumi.getRun().getByToken(token, lheWeightInfoHandle); if (lheWeightInfoHandle.isValid()) { foundLheWeights = true; break; @@ -159,7 +159,7 @@ GenWeightsTableProducer::GenWeightsTableProducer(edm::ParameterSet const& params [this](const edm::InputTag& tag) { return mayConsume(tag); })), lheWeightInfoTokens_(edm::vector_transform( params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), genWeightTokens_( edm::vector_transform(params.getParameter>("genWeights"), [this](const edm::InputTag& tag) { return mayConsume(tag); })), @@ -419,10 +419,9 @@ WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle< size_t maxStore) const { WeightGroupDataContainer allgroups; if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { - auto pdfIds = pdfIds_; - if (pdfIds.size() > maxStore) - pdfIds.resize(maxStore); - allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds); + allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); + if (allgroups.size() > maxStore) + allgroups.resize(maxStore); } else allgroups = weightsInfoHandle->weightGroupsAndIndicesByType(weightType, maxStore); diff --git a/PhysicsTools/NanoAOD/python/genWeights_cff.py b/PhysicsTools/NanoAOD/python/genWeights_cff.py index 7f399e93dd977..2a5e1e2d09475 100644 --- a/PhysicsTools/NanoAOD/python/genWeights_cff.py +++ b/PhysicsTools/NanoAOD/python/genWeights_cff.py @@ -18,9 +18,10 @@ # must be lower case and 'PDF' must be capital weightgroups = cms.vstring(['scale', 'PDF', 'matrix element', 'unknown', 'parton shower']), # Max number of groups to store for each type above, -1 ==> store all found - maxGroupsPerType = cms.vint32([1, 1, -1, 2, -1]), + #maxGroupsPerType = cms.vint32([-1, -1, -1, -1, -1]), + maxGroupsPerType = cms.vint32([1, 1, -1, 1, 1]), # If empty or not specified, no criteria are applied to filter on LHAPDF IDs - # pdfIds = cms.untracked.vint32([91400, 306000, 260000]), + #pdfIds = cms.untracked.vint32([91400, 306000, 260000]), unknownOnlyIfEmpty = cms.vstring(['scale', 'PDF']), keepAllPSWeights = cms.bool(False), # ignoreGenGroups = cms.untracked.bool(True), diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 081260a5b46b1..4e217f6e5fb0b 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -11,8 +11,12 @@ GenWeightInfoProduct::GenWeightInfoProduct(std::vector cloneptr(ptr->clone()); weightGroupsInfo_.emplace_back(std::move(cloneptr)); } - auto it = std::find_if(std::begin(weightGroups), std::end(weightGroups), [](auto& entry) { return entry->name() == "unassociated"; }); - unassociatedIdx_ = std::distance(std::begin(weightGroups), it); + auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [](auto& entry) { return entry->name() == "unassociated"; }); + if (it != std::end(weightGroupsInfo_)) { + unassociatedIdx_ = std::distance(std::begin(weightGroupsInfo_), it); + } + else + unassociatedIdx_ = -1; } const std::vector>& GenWeightInfoProduct::allWeightGroupsInfo() const { @@ -50,10 +54,13 @@ const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int wei std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type, int maxStore) const { std::vector matchingGroups; size_t toStore = maxStore <= 0 ? weightGroupsInfo_.size() : std::min(maxStore, weightGroupsInfo_.size()); - for (size_t i = 0; i < toStore; i++) { + for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { const gen::WeightGroupInfo* group = weightGroupsInfo_[i].get(); - if (group->weightType() == type) + if (group->weightType() == type) { matchingGroups.push_back({i, group}); + if (matchingGroups.size() == toStore) + break; + } } return matchingGroups; } From 359187bd69bbd9766dcf34fe392ea026e9936017 Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 02:30:49 +0100 Subject: [PATCH 15/16] Code format, don't fail for missing LHEEventProduct --- .../GeneratorInterface_EventContent_cff.py | 18 +- .../Core/interface/GenWeightHelper.h | 3 +- .../Core/interface/LHEWeightHelper.h | 17 +- .../Core/interface/WeightHelper.h | 27 +- .../Core/plugins/GenWeightProductProducer.cc | 40 ++- .../Core/plugins/LHEWeightProductProducer.cc | 62 ++-- .../Core/src/GenWeightHelper.cc | 3 +- .../Core/src/LHEWeightHelper.cc | 29 +- GeneratorInterface/Core/src/WeightHelper.cc | 74 ++--- .../NanoAOD/interface/GenWeightCounters.h | 2 +- .../plugins/GenWeightsTableProducer.cc | 273 +++++++++--------- .../NanoAOD/plugins/NanoAODOutputModule.cc | 10 + .../NanoAOD/python/genWeightsTable_cfi.py | 30 -- PhysicsTools/NanoAOD/python/nanogen_cff.py | 3 +- .../python/slimming/MicroEventContent_cff.py | 6 +- .../interface/GenWeightInfoProduct.h | 32 +- .../interface/GenWeightProduct.h | 5 +- .../interface/MEParamWeightGroupInfo.h | 1 + .../interface/PartonShowerWeightGroupInfo.h | 16 +- .../src/GenWeightInfoProduct.cc | 34 ++- .../GeneratorProducts/src/WeightGroupInfo.cc | 13 +- 21 files changed, 361 insertions(+), 337 deletions(-) delete mode 100644 PhysicsTools/NanoAOD/python/genWeightsTable_cfi.py diff --git a/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py b/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py index 48078d55f7e2e..a16ec90ef154e 100644 --- a/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py +++ b/GeneratorInterface/Configuration/python/GeneratorInterface_EventContent_cff.py @@ -19,8 +19,10 @@ 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', 'keep edmHepMCProduct_generatorSmeared_*_*', - 'keep GenWeightProduct_*_*_*', - 'keep GenWeightInfoProduct_*_*_*', + 'keep GenWeightProduct_lheWeights_*_*', + 'keep GenWeightProduct_genWeights_*_*', + 'keep GenWeightInfoProduct_lheWeights_*_*', + 'keep GenWeightInfoProduct_genWeights_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) @@ -36,8 +38,10 @@ 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', 'keep edmHepMCProduct_generatorSmeared_*_*', - 'keep GenWeightProduct_*_*_*', - 'keep GenWeightInfoProduct_*_*_*', + 'keep GenWeightProduct_lheWeights_*_*', + 'keep GenWeightProduct_genWeights_*_*', + 'keep GenWeightInfoProduct_lheWeights_*_*', + 'keep GenWeightInfoProduct_genWeights_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) @@ -52,8 +56,10 @@ 'keep GenLumiInfoHeader_generator_*_*', 'keep GenLumiInfoProduct_generator_*_*', 'keep GenEventInfoProduct_generator_*_*', - 'keep GenWeightProduct_*_*_*', - 'keep GenWeightInfoProduct_*_*_*', + 'keep GenWeightProduct_genWeights_*_*', + 'keep GenWeightInfoProduct_lheWeights_*_*', + 'keep GenWeightInfoProduct_genWeights_*_*', + 'keep GenFilterInfo_*_*_*', 'keep GenFilterInfo_*_*_*', 'keep *_genParticles_*_*' ) diff --git a/GeneratorInterface/Core/interface/GenWeightHelper.h b/GeneratorInterface/Core/interface/GenWeightHelper.h index 3fcf4169f7aba..3aad4587c7b7b 100644 --- a/GeneratorInterface/Core/interface/GenWeightHelper.h +++ b/GeneratorInterface/Core/interface/GenWeightHelper.h @@ -19,7 +19,8 @@ namespace gen { class GenWeightHelper : public WeightHelper { public: GenWeightHelper(); - std::vector> parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociatedGroup) const; + std::vector> parseWeightGroupsFromNames(std::vector weightNames, + bool addUnassociatedGroup) const; }; } // namespace gen diff --git a/GeneratorInterface/Core/interface/LHEWeightHelper.h b/GeneratorInterface/Core/interface/LHEWeightHelper.h index 5313137bfb027..a2657c3d2cb06 100644 --- a/GeneratorInterface/Core/interface/LHEWeightHelper.h +++ b/GeneratorInterface/Core/interface/LHEWeightHelper.h @@ -22,13 +22,16 @@ namespace gen { LHEWeightHelper() : WeightHelper(){}; enum class ErrorType { Empty, SwapHeader, HTMLStyle, NoWeightGroup, TrailingStr, Unknown, NoError }; - const std::unordered_map errorTypeAsString_ = { - {ErrorType::Empty, "Empty header"}, {ErrorType::SwapHeader, "Header info out of order" }, - {ErrorType::HTMLStyle, "Header is invalid HTML"}, {ErrorType::TrailingStr, "Header has extraneous info"}, - {ErrorType::Unknown, "Unregonized error"}, {ErrorType::NoError, "No error here!"} - }; - - std::vector> parseWeights(std::vector headerLines, bool addUnassociated) const; + const std::unordered_map errorTypeAsString_ = { + {ErrorType::Empty, "Empty header"}, + {ErrorType::SwapHeader, "Header info out of order"}, + {ErrorType::HTMLStyle, "Header is invalid HTML"}, + {ErrorType::TrailingStr, "Header has extraneous info"}, + {ErrorType::Unknown, "Unregonized error"}, + {ErrorType::NoError, "No error here!"}}; + + std::vector> parseWeights(std::vector headerLines, + bool addUnassociated) const; bool isConsistent(const std::string& fullHeader) const; void swapHeaders(std::vector& headerLines) const; void setFailIfInvalidXML(bool value) { failIfInvalidXML_ = value; } diff --git a/GeneratorInterface/Core/interface/WeightHelper.h b/GeneratorInterface/Core/interface/WeightHelper.h index 116ed2f66d112..60825f2e787e3 100644 --- a/GeneratorInterface/Core/interface/WeightHelper.h +++ b/GeneratorInterface/Core/interface/WeightHelper.h @@ -32,7 +32,9 @@ namespace gen { WeightHelper(); template - std::unique_ptr weightProduct(const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) const; + std::unique_ptr weightProduct(const GenWeightInfoProduct& weightsInfo, + std::vector weights, + float w0) const; void setGuessPSWeightIdx(bool guessPSWeightIdx) { PartonShowerWeightGroupInfo::setGuessPSWeightIdx(guessPSWeightIdx); @@ -42,8 +44,7 @@ namespace gen { unassoc.setDescription("Weights with missing or invalid header meta data"); weightGroups.push_back(std::make_unique(unassoc)); } - int addWeightToProduct( - GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex); + int addWeightToProduct(GenWeightProduct& product, double weight, std::string name, int weightNum, int groupIndex); void setDebug(bool value) { debug_ = value; } protected: @@ -87,20 +88,21 @@ namespace gen { }; template - std::unique_ptr WeightHelper::weightProduct( - const GenWeightInfoProduct& weightsInfo, std::vector weights, float w0) const { + std::unique_ptr WeightHelper::weightProduct(const GenWeightInfoProduct& weightsInfo, + std::vector weights, + float w0) const { auto weightProduct = std::make_unique(w0); weightProduct->setNumWeightSets(weightsInfo.numberOfGroups()); gen::WeightGroupData groupData = {0, nullptr}; int i = 0; // size=1 happens if there are no PS weights, so the weights vector contains only the central GEN weight. if (weights.size() > 1) { - // This gets remade every event to avoid having state-dependence in the helper class - // could think about doing caching instead + // This gets remade every event to avoid having state-dependence in the helper class + // could think about doing caching instead int unassociatedIdx = weightsInfo.unassociatedIdx(); - std::unique_ptr unassociatedGroup; + std::unique_ptr unassociatedGroup; if (unassociatedIdx != -1) - unassociatedGroup = std::make_unique("unassociated"); + unassociatedGroup = std::make_unique("unassociated"); for (const auto& weight : weights) { double wgtval; std::string wgtid; @@ -115,7 +117,7 @@ namespace gen { groupData = weightsInfo.containingWeightGroupInfo(i, groupData.index); } catch (const cms::Exception& e) { if (unassociatedIdx == -1) - throw e; + throw e; if (debug_) { std::cout << "WARNING: " << e.what() << std::endl; } @@ -127,12 +129,13 @@ namespace gen { // TODO: is this too slow? if (debug_) - std::cout << "Adding weight num " << i << " EntryNum " << entry << " to group " << groupData.index << std::endl; + std::cout << "Adding weight num " << i << " EntryNum " << entry << " to group " << groupData.index + << std::endl; weightProduct->addWeight(wgtval, groupData.index, entry); i++; } } - return weightProduct; + return weightProduct; } } // namespace gen diff --git a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc index a5cf5f85e6e16..176ccc7e2f197 100644 --- a/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/GenWeightProductProducer.cc @@ -28,20 +28,22 @@ #include struct GenWeightInfoProdData { - bool makeNewProduct; - GenWeightInfoProduct product; + bool makeNewProduct; + GenWeightInfoProduct product; }; class GenWeightProductProducer : public edm::global::EDProducer> { + edm::LuminosityBlockCache> { public: explicit GenWeightProductProducer(const edm::ParameterSet& iConfig); ~GenWeightProductProducer() override; void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; void globalBeginLuminosityBlockProduce(edm::LuminosityBlock& lb, edm::EventSetup const& c) const override; - std::shared_ptr globalBeginLuminosityBlock(const edm::LuminosityBlock& lb, edm::EventSetup const& c) const override; + std::shared_ptr globalBeginLuminosityBlock(const edm::LuminosityBlock& lb, + edm::EventSetup const& c) const override; void globalEndLuminosityBlock(const edm::LuminosityBlock& lb, edm::EventSetup const& c) const override {} static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + private: gen::GenWeightHelper weightHelper_; const edm::EDGetTokenT genLumiInfoToken_; @@ -56,11 +58,12 @@ class GenWeightProductProducer : public edm::global::EDProducer(iConfig.getParameter("genInfo"))), genEventToken_(consumes(iConfig.getParameter("genInfo"))), - weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), + weightInfoTokens_(edm::vector_transform( + iConfig.getParameter>("weightProductLabels"), [this](const std::string& tag) { return mayConsume(tag); })), debug_(iConfig.getUntrackedParameter("debug", false)), groupPutToken_(produces()), - allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { + allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { weightHelper_.setDebug(debug_); produces(); produces(); @@ -84,7 +87,8 @@ void GenWeightProductProducer::produce(edm::StreamID, edm::Event& iEvent, const iEvent.put(std::move(weightProduct)); } -std::shared_ptr GenWeightProductProducer::globalBeginLuminosityBlock(const edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) const { +std::shared_ptr GenWeightProductProducer::globalBeginLuminosityBlock( + const edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) const { GenWeightInfoProdData productInfo; edm::Handle weightInfoHandle; @@ -92,7 +96,7 @@ std::shared_ptr GenWeightProductProducer::globalBeginLumi iLumi.getByToken(token, weightInfoHandle); if (weightInfoHandle.isValid()) { productInfo.makeNewProduct = false; - break; + break; } } @@ -102,16 +106,17 @@ std::shared_ptr GenWeightProductProducer::globalBeginLumi if (genLumiInfoHandle.isValid()) { auto weightGroups = weightHelper_.parseWeightGroupsFromNames(genLumiInfoHandle->weightNames(), allowUnassociated_); productInfo.product = GenWeightInfoProduct(weightGroups); - } + } return std::make_shared(productInfo); } -void GenWeightProductProducer::globalBeginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, edm::EventSetup const& iSetup) const { +void GenWeightProductProducer::globalBeginLuminosityBlockProduce(edm::LuminosityBlock& iLumi, + edm::EventSetup const& iSetup) const { edm::Handle weightInfoHandle; const auto& productInfo = *luminosityBlockCache(iLumi.index()); if (!productInfo.makeNewProduct) - return; + return; auto weightInfoProduct = std::make_unique(productInfo.product); iLumi.emplace(groupPutToken_, std::move(weightInfoProduct)); @@ -122,11 +127,16 @@ void GenWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& desc.add("genInfo", edm::InputTag{"generator"}) ->setComment("tag(s) for the GenLumiInfoHeader and GenEventInfoProduct"); desc.add>("weightProductLabels", std::vector{{""}}) - ->setComment("tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " - "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + ->setComment( + "tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new " + "products regardless."); desc.addUntracked("debug", false)->setComment("Output debug info"); - desc.addUntracked("guessPSWeightIdx", false)->setComment("If not possible to parse text, guess the parton shower weight indices"); - desc.addUntracked("allowUnassociatedWeights", false)->setComment("Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); + desc.addUntracked("guessPSWeightIdx", false) + ->setComment("If not possible to parse text, guess the parton shower weight indices"); + desc.addUntracked("allowUnassociatedWeights", false) + ->setComment( + "Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); descriptions.add("genWeights", desc); } diff --git a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc index 6c2a7de9d8da6..7593ae944102a 100644 --- a/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc +++ b/GeneratorInterface/Core/plugins/LHEWeightProductProducer.cc @@ -28,21 +28,22 @@ #include "FWCore/Utilities/interface/ReusableObjectHolder.h" struct GenWeightInfoProdData { - bool makeNewProduct; - GenWeightInfoProduct product; + bool makeNewProduct; + GenWeightInfoProduct product; }; -class LHEWeightProductProducer : public edm::global::EDProducer, - edm::BeginRunProducer> { +class LHEWeightProductProducer + : public edm::global::EDProducer, edm::BeginRunProducer> { public: explicit LHEWeightProductProducer(const edm::ParameterSet& iConfig); ~LHEWeightProductProducer() override; - void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const; - void globalBeginRunProduce(edm::Run& run, edm::EventSetup const& es) const; + void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; + void globalBeginRunProduce(edm::Run& run, edm::EventSetup const& es) const override; void globalEndRunProduce(edm::Run& run, edm::EventSetup const& es) const {}; - std::shared_ptr globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const; + std::shared_ptr globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const override; void globalEndRun(edm::Run const& iRun, edm::EventSetup const&) const override {} static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + private: gen::LHEWeightHelper weightHelper_; const std::vector lheLabels_; @@ -59,10 +60,11 @@ LHEWeightProductProducer::LHEWeightProductProducer(const edm::ParameterSet& iCon lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), lheRunInfoTokens_(edm::vector_transform( lheLabels_, [this](const std::string& tag) { return mayConsume(tag); })), - weightInfoTokens_(edm::vector_transform(iConfig.getParameter>("weightProductLabels"), + weightInfoTokens_(edm::vector_transform( + iConfig.getParameter>("weightProductLabels"), [this](const edm::InputTag& tag) { return mayConsume(tag); })), groupPutToken_(produces()), - allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { + allowUnassociated_(iConfig.getUntrackedParameter("allowUnassociatedWeights", false)) { produces(); weightHelper_.setFailIfInvalidXML(iConfig.getUntrackedParameter("failIfInvalidXML", false)); weightHelper_.setDebug(iConfig.getUntrackedParameter("debug", false)); @@ -85,25 +87,30 @@ void LHEWeightProductProducer::produce(edm::StreamID, edm::Event& iEvent, const } } - auto weightProduct = weightHelper_.weightProduct(productInfo.product, lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); + if (!lheEventInfo.isValid()) + return; + + auto weightProduct = + weightHelper_.weightProduct(productInfo.product, lheEventInfo->weights(), lheEventInfo->originalXWGTUP()); iEvent.put(std::move(weightProduct)); } -std::shared_ptr LHEWeightProductProducer::globalBeginRun(edm::Run const& run, edm::EventSetup const& es) const { +std::shared_ptr LHEWeightProductProducer::globalBeginRun(edm::Run const& run, + edm::EventSetup const& es) const { bool hasWeightProduct = false; edm::Handle weightInfoHandle; for (auto& token : weightInfoTokens_) { run.getByToken(token, weightInfoHandle); if (weightInfoHandle.isValid()) { hasWeightProduct = true; - break; + break; } } GenWeightInfoProdData productInfo; productInfo.makeNewProduct = !hasWeightProduct; if (hasWeightProduct) - return std::make_shared(productInfo); - + return std::make_shared(productInfo); + edm::Handle lheRunInfoHandle; for (auto& label : lheLabels_) { run.getByLabel(label, lheRunInfoHandle); @@ -112,7 +119,7 @@ std::shared_ptr LHEWeightProductProducer::globalBeginRun( } } if (!lheRunInfoHandle.isValid()) - return std::make_shared(productInfo); + return std::make_shared(productInfo); typedef std::vector::const_iterator header_cit; LHERunInfoProduct::Header headerWeightInfo; @@ -131,8 +138,9 @@ std::shared_ptr LHEWeightProductProducer::globalBeginRun( error += "\n NOTE: if you want to attempt to process this sample anyway, set failIfInvalidXML = False " "in the configuration file (current value is "; - error += weightHelper_.failIfInvalidXML() ? "True" : "False"; - error += ")\n.If you set this flag and the error persists, the issue " + error += weightHelper_.failIfInvalidXML() ? "True" : "False"; + error += + ")\n.If you set this flag and the error persists, the issue " " is fatal and must be solved at the LHE/gridpack level."; throw cms::Exception("LHEWeightProductProducer") << error; } @@ -150,16 +158,22 @@ void LHEWeightProductProducer::globalBeginRunProduce(edm::Run& run, const edm::E void LHEWeightProductProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; desc.add>("lheSourceLabels", std::vector{{"externalLHEProducer"}, {"source"}}) - ->setComment("tag(s) to look for LHERunInfoProduct/LHEEventProduct" - "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + ->setComment( + "tag(s) to look for LHERunInfoProduct/LHEEventProduct" + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new " + "products regardless."); desc.add>("weightProductLabels", std::vector{{""}}) - ->setComment("tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " - "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new products regardless."); + ->setComment( + "tag(s) to look for existing GenWeightProduct/GenWeightInfoProducts. " + "If they are found, a new one won't be created. Leave this argument empty if you want to recreate new " + "products regardless."); desc.addUntracked("debug", false)->setComment("Output debug info"); - desc.addUntracked("failIfInvalidXML", true)->setComment("Throw exception if XML header is invalid (rather than trying to recover and parse anyway)"); - desc.addUntracked("allowUnassociatedWeights", false)->setComment("Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); + desc.addUntracked("failIfInvalidXML", true) + ->setComment("Throw exception if XML header is invalid (rather than trying to recover and parse anyway)"); + desc.addUntracked("allowUnassociatedWeights", false) + ->setComment( + "Handle weights found in the event that aren't advertised in the weight header (otherwise throw exception)"); descriptions.add("lheWeights", desc); } - DEFINE_FWK_MODULE(LHEWeightProductProducer); diff --git a/GeneratorInterface/Core/src/GenWeightHelper.cc b/GeneratorInterface/Core/src/GenWeightHelper.cc index 6922ef14bbdb8..aac76ff5c9b46 100644 --- a/GeneratorInterface/Core/src/GenWeightHelper.cc +++ b/GeneratorInterface/Core/src/GenWeightHelper.cc @@ -6,7 +6,8 @@ using namespace tinyxml2; namespace gen { GenWeightHelper::GenWeightHelper() {} - std::vector> GenWeightHelper::parseWeightGroupsFromNames(std::vector weightNames, bool addUnassociated) const { + std::vector> GenWeightHelper::parseWeightGroupsFromNames( + std::vector weightNames, bool addUnassociated) const { std::vector parsedWeights; int index = 0; int groupIndex = -1; diff --git a/GeneratorInterface/Core/src/LHEWeightHelper.cc b/GeneratorInterface/Core/src/LHEWeightHelper.cc index 616c102933bb7..dba765e5a6b16 100644 --- a/GeneratorInterface/Core/src/LHEWeightHelper.cc +++ b/GeneratorInterface/Core/src/LHEWeightHelper.cc @@ -7,8 +7,8 @@ using namespace tinyxml2; namespace gen { - bool LHEWeightHelper::validateAndFixHeader( - std::vector& headerLines, tinyxml2::XMLDocument& xmlDoc) const { + bool LHEWeightHelper::validateAndFixHeader(std::vector& headerLines, + tinyxml2::XMLDocument& xmlDoc) const { std::string fullHeader = boost::algorithm::join(headerLines, ""); if (debug_) @@ -19,10 +19,10 @@ namespace gen { while (errorType = findErrorType(xmlError, fullHeader), errorType != ErrorType::NoError) { if (failIfInvalidXML_) { std::cout << "XML error: "; - xmlDoc.PrintError(); + xmlDoc.PrintError(); throw cms::Exception("LHEWeightHelper") << "The LHE header is not valid! Weight information was not properly parsed." - << " The error type is '" << errorTypeAsString_.at(errorType) << "'"; + << " The error type is '" << errorTypeAsString_.at(errorType) << "'"; } else if (errorType == ErrorType::HTMLStyle) { if (debug_) std::cout << " >>> This file uses > instead of >\n"; @@ -30,8 +30,8 @@ namespace gen { } else if (errorType == ErrorType::SwapHeader) { if (debug_) std::cout << " >>> Some headers in the file are swapped\n"; - std::vector fixedHeaderLines; - boost::split(fixedHeaderLines, fullHeader, boost::is_any_of("\n")); + std::vector fixedHeaderLines; + boost::split(fixedHeaderLines, fullHeader, boost::is_any_of("\n")); swapHeaders(fixedHeaderLines); fullHeader = boost::algorithm::join(fixedHeaderLines, "\n"); xmlError = xmlDoc.Parse(fullHeader.c_str()); @@ -56,7 +56,10 @@ namespace gen { return true; } - ParsedWeight LHEWeightHelper::parseWeight(tinyxml2::XMLElement* inner, std::string groupName, int groupIndex, int& weightIndex) const { + ParsedWeight LHEWeightHelper::parseWeight(tinyxml2::XMLElement* inner, + std::string groupName, + int groupIndex, + int& weightIndex) const { if (debug_) std::cout << " >> Found a weight inside the group. " << std::endl; std::string text = ""; @@ -71,8 +74,8 @@ namespace gen { return {inner->Attribute("id"), weightIndex++, groupName, text, attributes, groupIndex}; } - std::vector> LHEWeightHelper::parseWeights( - std::vector headerLines, bool addUnassociatedGroup) const { + std::vector> LHEWeightHelper::parseWeights(std::vector headerLines, + bool addUnassociatedGroup) const { tinyxml2::XMLDocument xmlDoc; if (!validateAndFixHeader(headerLines, xmlDoc)) { return {}; @@ -146,7 +149,8 @@ namespace gen { int close = -1; for (size_t idx = 0; idx < headerLines.size(); idx++) { std::string& line = headerLines[idx]; - std::cout << "Line is " << line << std::endl;; + std::cout << "Line is " << line << std::endl; + ; if (line.find("/weightgroup") != std::string::npos) { curLevel--; if (curLevel != 0) { @@ -166,7 +170,8 @@ namespace gen { } } - tinyxml2::XMLError LHEWeightHelper::tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, std::string& fullHeader) const { + tinyxml2::XMLError LHEWeightHelper::tryReplaceHtmlStyle(tinyxml2::XMLDocument& xmlDoc, + std::string& fullHeader) const { // in case of > instead of < boost::replace_all(fullHeader, "<", "<"); boost::replace_all(fullHeader, ">", ">"); @@ -184,7 +189,7 @@ namespace gen { } LHEWeightHelper::ErrorType LHEWeightHelper::findErrorType(int xmlError, const std::string& fullHeader) const { - if (fullHeader.size() == 0) + if (fullHeader.empty()) return ErrorType::Empty; else if (!isConsistent(fullHeader)) return ErrorType::SwapHeader; diff --git a/GeneratorInterface/Core/src/WeightHelper.cc b/GeneratorInterface/Core/src/WeightHelper.cc index 632db40c198b4..037586986602c 100644 --- a/GeneratorInterface/Core/src/WeightHelper.cc +++ b/GeneratorInterface/Core/src/WeightHelper.cc @@ -166,7 +166,8 @@ namespace gen { pdfGroup.addLhaid(lhaid); } - void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, const ParsedWeight& weight) const { + void WeightHelper::updatePartonShowerInfo(gen::PartonShowerWeightGroupInfo& psGroup, + const ParsedWeight& weight) const { if (psGroup.nIdsContained() == DEFAULT_PSWEIGHT_LENGTH) { psGroup.setIsWellFormed(true); psGroup.cacheWeightIndicesByLabel(); @@ -190,50 +191,51 @@ namespace gen { // Come back to improving this, it's gross void WeightHelper::cleanupOrphanCentralWeight(WeightGroupInfoContainer& weightGroups) const { - // std::vector removeList; - // for (auto& group : weightGroups_) { - // if (group->weightType() != WeightType::kScaleWeights) - // continue; - // auto& baseWeight = *static_cast(group.get()); - // if (baseWeight.containsCentralWeight()) - // continue; - // for (auto subIt = weightGroups_.begin(); subIt < it; subIt++) { - // if (subIt->weightType() != WeightType::kPdfWeights) - // continue; - // auto& subWeight = dynamic_cast(*subIt); - // if (subWeight.nIdsContained() == 1 && subWeight.parentLhapdfId() == baseWeight.lhaid()) { - // removeList.push_back(subIt - weightGroups_.begin()); - // auto info = subWeight.idsContained().at(0); - // baseWeight.addContainedId(info.globalIndex, info.id, info.label, 1, 1); - // } - // } - // } - auto centralIt = std::find_if(std::begin(weightGroups), std::end(weightGroups), - [](auto& entry) { return entry->weightType() == gen::WeightType::kScaleWeights - && static_cast(entry.get())->containsCentralWeight(); }); + // std::vector removeList; + // for (auto& group : weightGroups_) { + // if (group->weightType() != WeightType::kScaleWeights) + // continue; + // auto& baseWeight = *static_cast(group.get()); + // if (baseWeight.containsCentralWeight()) + // continue; + // for (auto subIt = weightGroups_.begin(); subIt < it; subIt++) { + // if (subIt->weightType() != WeightType::kPdfWeights) + // continue; + // auto& subWeight = dynamic_cast(*subIt); + // if (subWeight.nIdsContained() == 1 && subWeight.parentLhapdfId() == baseWeight.lhaid()) { + // removeList.push_back(subIt - weightGroups_.begin()); + // auto info = subWeight.idsContained().at(0); + // baseWeight.addContainedId(info.globalIndex, info.id, info.label, 1, 1); + // } + // } + // } + auto centralIt = std::find_if(std::begin(weightGroups), std::end(weightGroups), [](auto& entry) { + return entry->weightType() == gen::WeightType::kScaleWeights && + static_cast(entry.get())->containsCentralWeight(); + }); if (centralIt == std::end(weightGroups)) - return; + return; auto& centralWeight = *static_cast(centralIt->get()); std::vector toRemove; for (size_t i = 0; i < weightGroups.size(); i++) { - auto& group = weightGroups[i]; - if (group->weightType() == gen::WeightType::kPdfWeights) { - auto& pdfGroup = *static_cast(group.get()); - // These are weights that contain nothing but a single central weight, because - // some versions of madgraph write the central weight separately - if (pdfGroup.nIdsContained() == 1 && pdfGroup.parentLhapdfId() == centralWeight.lhaid()) { - toRemove.push_back(i); - const auto& weightInfo = pdfGroup.weightMetaInfo(0); - centralWeight.addContainedId(weightInfo.globalIndex, weightInfo.id, weightInfo.label, 1, 1); - } + auto& group = weightGroups[i]; + if (group->weightType() == gen::WeightType::kPdfWeights) { + auto& pdfGroup = *static_cast(group.get()); + // These are weights that contain nothing but a single central weight, because + // some versions of madgraph write the central weight separately + if (pdfGroup.nIdsContained() == 1 && pdfGroup.parentLhapdfId() == centralWeight.lhaid()) { + toRemove.push_back(i); + const auto& weightInfo = pdfGroup.weightMetaInfo(0); + centralWeight.addContainedId(weightInfo.globalIndex, weightInfo.id, weightInfo.label, 1, 1); } + } } // Indices are guaranteed to be unique, delete from high to low to avoid changing indices std::sort(std::begin(toRemove), std::end(toRemove), std::greater()); for (auto i : toRemove) { - weightGroups.erase(std::begin(weightGroups)+i); + weightGroups.erase(std::begin(weightGroups) + i); } } @@ -310,8 +312,8 @@ namespace gen { return std::make_unique(weight.groupname); } - WeightGroupInfoContainer WeightHelper::buildGroups( - std::vector& parsedWeights, bool addUnassociated) const { + WeightGroupInfoContainer WeightHelper::buildGroups(std::vector& parsedWeights, + bool addUnassociated) const { WeightGroupInfoContainer weightGroups; int groupOffset = 0; for (auto& weight : parsedWeights) { diff --git a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h index 35446d7172e78..26375ab9fc41a 100644 --- a/PhysicsTools/NanoAOD/interface/GenWeightCounters.h +++ b/PhysicsTools/NanoAOD/interface/GenWeightCounters.h @@ -5,7 +5,7 @@ #include namespace genCounter { - void mergeSumVectors(std::vector& v1, std::vector const& v2) { + inline void mergeSumVectors(std::vector& v1, std::vector const& v2) { if (v1.empty() && !v2.empty()) v1.resize(v2.size(), 0); if (!v2.empty()) diff --git a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc index 197d63b03ccab..ea13c0290b9ad 100644 --- a/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc +++ b/PhysicsTools/NanoAOD/plugins/GenWeightsTableProducer.cc @@ -38,12 +38,11 @@ class GenWeightsTableProducer : public edm::global::EDProducer& weightTablevec, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - size_t maxStore, - std::string tablename) const; - void addWeightGroupToTable( - std::vector& weightTablevec, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + size_t maxStore, + std::string tablename) const; + void addWeightGroupToTable(std::vector& weightTablevec, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights) const; // Need to either pass the handle or a pointer to avoid a copy and conversion to the base class @@ -51,15 +50,15 @@ class GenWeightsTableProducer : public edm::global::EDProducer& genWeightInfoHandle, edm::Handle& lheWeightInfoHandle) const; std::pair> orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo& scaleGroup) const; + const gen::ScaleWeightGroupInfo& scaleGroup) const; std::pair> preferredPSweights(const std::vector& psWeights, - const gen::PartonShowerWeightGroupInfo& pswV) const; + const gen::PartonShowerWeightGroupInfo& pswV) const; //Lumiblock std::shared_ptr globalBeginLuminosityBlock(edm::LuminosityBlock const& iLumi, @@ -156,16 +155,16 @@ class GenWeightsTableProducer : public edm::global::EDProducer>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), lheWeightInfoTokens_(edm::vector_transform( params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), genWeightTokens_( edm::vector_transform(params.getParameter>("genWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - genWeightInfoTokens_( - edm::vector_transform(params.getParameter>("genWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), + genWeightInfoTokens_(edm::vector_transform( + params.getParameter>("genWeights"), + [this](const edm::InputTag& tag) { return mayConsume(tag); })), genEventInfoToken_(consumes(params.getParameter("genEvent"))), genLumiInfoHeadTag_( mayConsume(params.getParameter("genLumiInfoHeader"))), @@ -175,7 +174,7 @@ GenWeightsTableProducer::GenWeightsTableProducer(edm::ParameterSet const& params pdfIds_(params.getUntrackedParameter>("pdfIds", {})), lheWeightPrecision_(params.getParameter("lheWeightPrecision")), unknownOnlyIfEmpty_(edm::vector_transform(params.getParameter>("unknownOnlyIfEmpty"), - [](auto& c) { return gen::WeightType(c.at(0)); })), + [](auto& c) { return gen::WeightType(c.at(0)); })), keepAllPSWeights_(params.getParameter("keepAllPSWeights")), ignoreLheGroups_(params.getUntrackedParameter("ignoreLheGroups", false)), ignoreGenGroups_(params.getUntrackedParameter("ignoreGenGroups", false)), @@ -238,10 +237,9 @@ void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons auto weightTablevec = std::make_unique>(); if (foundLheWeights) { if (ignoreLheGroups_) { - fillTableIgnoringGroups(*weightTablevec, weightInfos.at(inLHE), lheWeights, nStoreUngroupedLhe_, "LHEWeight"); - } - else - addWeightGroupToTable(*weightTablevec, weightInfos.at(inLHE), lheWeights); + fillTableIgnoringGroups(*weightTablevec, weightInfos.at(inLHE), lheWeights, nStoreUngroupedLhe_, "LHEWeight"); + } else + addWeightGroupToTable(*weightTablevec, weightInfos.at(inLHE), lheWeights); } if (ignoreGenGroups_) @@ -249,81 +247,80 @@ void GenWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, cons else addWeightGroupToTable(*weightTablevec, weightInfos.at(inGen), genWeights); - iEvent.put(std::move(weightTablevec),"LHEWeightTableVec"); + iEvent.put(std::move(weightTablevec), "LHEWeightTableVec"); } // Sequentially add the weights, up to maxStore // Note that the order of the weights in the WeightsVector matches the order of weightgroups. // In very rare cases, this could be modified from the order in the LHE file. If this happens, // write a warning message in the table info -void GenWeightsTableProducer::fillTableIgnoringGroups( - std::vector& weightTablevec, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - size_t maxStore, - std::string tablename) const { - - std::vector weights(maxStore); - size_t groupIdx = 0; - size_t offset = 0; - std::string tableInfo = "First "; - tableInfo.append(std::to_string(maxStore)); - tableInfo.append(" weights; "); - std::string warnings = ""; - bool foundUnassociated = false; - for (size_t i = 0; i < maxStore; i++) { - if (groupIdx >= allWeights.size()) - throw cms::Exception("GenWeightsTableProducer") - << "Requested " + std::to_string(maxStore) + " weights, which is more than there are in the file"; - size_t entry = i - offset; - auto& weightsForGroup = allWeights.at(groupIdx); - weights.at(i) = weightsForGroup.at(entry); - - if (weightInfos.size() <= groupIdx) - throw cms::Exception("GenWeightsTableProducer") << "Unable to match weight to one of " << weightInfos.size() << " WeightGroups"; - auto matchingGroup = weightInfos.at(groupIdx).group; - if (entry == 0) { - size_t maxRange = std::min(offset+weightsForGroup.size()-1, maxStore); - tableInfo.append("["); - tableInfo.append(std::to_string(offset)); - tableInfo.append("]-["); - tableInfo.append(std::to_string(maxRange)); - tableInfo.append("] "); - tableInfo.append(matchingGroup->name()); - tableInfo.append("; "); - } +void GenWeightsTableProducer::fillTableIgnoringGroups(std::vector& weightTablevec, + const WeightGroupDataContainer& weightInfos, + WeightsContainer& allWeights, + size_t maxStore, + std::string tablename) const { + std::vector weights(maxStore); + size_t groupIdx = 0; + size_t offset = 0; + std::string tableInfo = "First "; + tableInfo.append(std::to_string(maxStore)); + tableInfo.append(" weights; "); + std::string warnings = ""; + bool foundUnassociated = false; + for (size_t i = 0; i < maxStore; i++) { + if (groupIdx >= allWeights.size()) + throw cms::Exception("GenWeightsTableProducer") + << "Requested " + std::to_string(maxStore) + " weights, which is more than there are in the file"; + size_t entry = i - offset; + auto& weightsForGroup = allWeights.at(groupIdx); + weights.at(i) = weightsForGroup.at(entry); + + if (weightInfos.size() <= groupIdx) + throw cms::Exception("GenWeightsTableProducer") + << "Unable to match weight to one of " << weightInfos.size() << " WeightGroups"; + auto matchingGroup = weightInfos.at(groupIdx).group; + if (entry == 0) { + size_t maxRange = std::min(offset + weightsForGroup.size() - 1, maxStore); + tableInfo.append("["); + tableInfo.append(std::to_string(offset)); + tableInfo.append("]-["); + tableInfo.append(std::to_string(maxRange)); + tableInfo.append("] "); + tableInfo.append(matchingGroup->name()); + tableInfo.append("; "); + } - // Check if the order corresponds to the LHE file order - try { - auto matchingInfo = matchingGroup->weightMetaInfo(entry); - - if (matchingInfo.globalIndex != i) { - warnings.append("Index "); - warnings.append(std::to_string(i)); - warnings.append(" does not match order in the LHE file or gen product (where it is entry "); - warnings.append(std::to_string(matchingInfo.globalIndex)); - warnings.append(")"); - } - } catch (cms::Exception& e) { - if (!foundUnassociated) - warnings.append("Could not associate some weights to a group. Cannot verify" - " that the order is maintained wrt the LHE file or gen product"); - foundUnassociated = true; - } - if (entry == weightsForGroup.size()-1) { - groupIdx += 1; - offset += weightsForGroup.size(); - } + // Check if the order corresponds to the LHE file order + try { + auto matchingInfo = matchingGroup->weightMetaInfo(entry); + + if (matchingInfo.globalIndex != i) { + warnings.append("Index "); + warnings.append(std::to_string(i)); + warnings.append(" does not match order in the LHE file or gen product (where it is entry "); + warnings.append(std::to_string(matchingInfo.globalIndex)); + warnings.append(")"); + } + } catch (cms::Exception& e) { + if (!foundUnassociated) + warnings.append( + "Could not associate some weights to a group. Cannot verify" + " that the order is maintained wrt the LHE file or gen product"); + foundUnassociated = true; + } + if (entry == weightsForGroup.size() - 1) { + groupIdx += 1; + offset += weightsForGroup.size(); } - if (!warnings.empty()) - tableInfo.append("WARNING: " + warnings); + } + if (!warnings.empty()) + tableInfo.append("WARNING: " + warnings); - weightTablevec.emplace_back(weights.size(), tablename, false); - weightTablevec.back().addColumn("", weights, tableInfo, lheWeightPrecision_); + weightTablevec.emplace_back(weights.size(), tablename, false); + weightTablevec.back().addColumn("", weights, tableInfo, lheWeightPrecision_); } -void GenWeightsTableProducer::addWeightGroupToTable( - std::vector& weightTablevec, +void GenWeightsTableProducer::addWeightGroupToTable(std::vector& weightTablevec, const WeightGroupDataContainer& weightInfos, WeightsContainer& allWeights) const { std::unordered_map typeCount = {}; @@ -336,27 +333,27 @@ void GenWeightsTableProducer::addWeightGroupToTable( std::string label = groupInfo.group->description(); auto weights = allWeights.at(groupInfo.index); if (weightType == gen::WeightType::kScaleWeights) { - const auto& scaleGroup = *static_cast(groupInfo.group); - auto weightsAndLabel = orderedScaleWeights(weights, scaleGroup); - label.append(weightsAndLabel.first); - weights = weightsAndLabel.second; + const auto& scaleGroup = *static_cast(groupInfo.group); + auto weightsAndLabel = orderedScaleWeights(weights, scaleGroup); + label.append(weightsAndLabel.first); + weights = weightsAndLabel.second; } else if (weightType == gen::WeightType::kPartonShowerWeights) { const auto& psGroup = *static_cast(groupInfo.group); - if(!keepAllPSWeights_) { + if (!keepAllPSWeights_) { auto weightsAndLabel = preferredPSweights(weights, psGroup); label.append(weightsAndLabel.first); weights = weightsAndLabel.second; } else if (psGroup.isWellFormed()) { double baseline = weights[psGroup.weightIndexFromLabel("Baseline")]; for (size_t i = 0; i < weights.size(); i++) - weights[i] = weights[i]/baseline; + weights[i] = weights[i] / baseline; label = "PS weights (w_var / w_nominal)"; } else label.append("WARNING: Did not properly parse weight information. Verify order manually."); } else if (!groupInfo.group->isWellFormed()) label.append("WARNING: Did not properly parse weight information. Verify order manually."); - if(typeCount[weightType] > 0) { + if (typeCount[weightType] > 0) { entryName.append("AltSet"); entryName.append(std::to_string(typeCount[weightType])); } @@ -367,13 +364,14 @@ void GenWeightsTableProducer::addWeightGroupToTable( } } -WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, - edm::Handle& genWeightInfoHandle, +WeightGroupsToStore GenWeightsTableProducer::groupsToStore( + bool foundLheWeights, + edm::Handle& genWeightInfoHandle, edm::Handle& lheWeightInfoHandle) const { std::unordered_map storePerType; for (size_t i = 0; i < weightgroups_.size(); i++) - storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); - + storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); + WeightGroupsToStore weightsToStore; // The order LHE then GEN is useful for the unknownOnlyIfEmpy check bool storeUnknown = unknownOnlyIfEmpty_.empty(); @@ -381,56 +379,53 @@ WeightGroupsToStore GenWeightsTableProducer::groupsToStore(bool foundLheWeights, for (auto genOrLhe : {inLHE, inGen}) { bool isLHE = genOrLhe == inLHE; if (isLHE && !foundLheWeights) - continue; + continue; auto& hand = isLHE ? lheWeightInfoHandle : genWeightInfoHandle; bool ignoreGroups = isLHE ? ignoreLheGroups_ : ignoreGenGroups_; auto& toStorePerType = weightsToStore[genOrLhe]; if (ignoreGroups) { - toStorePerType = hand->allWeightGroupsInfoWithIndices(); + toStorePerType = hand->allWeightGroupsInfoWithIndices(); } else { - for (auto& typeAndCount : storePerType) { - if (typeAndCount.first == gen::WeightType::kUnknownWeights && !storeUnknown) - continue; - // Since the count isn't updated, the counts are effectively independent between LHE and GEN - auto groupsPerType = weightDataPerType(hand, typeAndCount.first, typeAndCount.second); - // Only store unknown if at least one specified groups is empty - if (!storeUnknown && !groupsToSearch.empty()) { - auto it = std::find(std::begin(groupsToSearch), std::end(groupsToSearch), typeAndCount.first); - if (it != std::end(groupsToSearch)) { - if (groupsPerType.empty()) - storeUnknown = true; - // Remove from array to avoid repeating the check on GEN. NOTE, if parton - // shower weights are included as one of the ones to consider, this can - // cause unknown LHE weights to be stored, given the order of the loops - else - groupsToSearch.erase(it); - - } - } - toStorePerType.insert(std::end(toStorePerType), std::begin(groupsPerType), std::end(groupsPerType)); + for (auto& typeAndCount : storePerType) { + if (typeAndCount.first == gen::WeightType::kUnknownWeights && !storeUnknown) + continue; + // Since the count isn't updated, the counts are effectively independent between LHE and GEN + auto groupsPerType = weightDataPerType(hand, typeAndCount.first, typeAndCount.second); + // Only store unknown if at least one specified groups is empty + if (!storeUnknown && !groupsToSearch.empty()) { + auto it = std::find(std::begin(groupsToSearch), std::end(groupsToSearch), typeAndCount.first); + if (it != std::end(groupsToSearch)) { + if (groupsPerType.empty()) + storeUnknown = true; + // Remove from array to avoid repeating the check on GEN. NOTE, if parton + // shower weights are included as one of the ones to consider, this can + // cause unknown LHE weights to be stored, given the order of the loops + else + groupsToSearch.erase(it); + } } + toStorePerType.insert(std::end(toStorePerType), std::begin(groupsPerType), std::end(groupsPerType)); + } } - } + } return weightsToStore; } -WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType(edm::Handle& weightsInfoHandle, - gen::WeightType weightType, - size_t maxStore) const { +WeightGroupDataContainer GenWeightsTableProducer::weightDataPerType( + edm::Handle& weightsInfoHandle, gen::WeightType weightType, size_t maxStore) const { WeightGroupDataContainer allgroups; if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { allgroups = weightsInfoHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); - if (allgroups.size() > maxStore) - allgroups.resize(maxStore); + if (allgroups.size() > maxStore) + allgroups.resize(maxStore); } else allgroups = weightsInfoHandle->weightGroupsAndIndicesByType(weightType, maxStore); return allgroups; } -std::pair> -GenWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo& scaleGroup) const { +std::pair> GenWeightsTableProducer::orderedScaleWeights( + const std::vector& scaleWeights, const gen::ScaleWeightGroupInfo& scaleGroup) const { std::vector weights; std::string labels = "LHE scale variation weights (w_var / w_nominal); "; if (scaleGroup.isWellFormed()) { @@ -452,19 +447,18 @@ GenWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWei labels += "[7] is muR=2 muF=1; "; weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); labels += "[8] is muR=2 muF=2"; - } - else { + } else { size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); - weights = std::vector(begin(weights), std::begin(weights)+nstore); + weights = std::vector(begin(weights), std::begin(weights) + nstore); labels.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + - " elements of weights vector, unordered"); + " elements of weights vector, unordered"); } return std::make_pair(labels, weights); } -std::pair> GenWeightsTableProducer::preferredPSweights(const std::vector& psWeights, - const gen::PartonShowerWeightGroupInfo& pswV) const { +std::pair> GenWeightsTableProducer::preferredPSweights( + const std::vector& psWeights, const gen::PartonShowerWeightGroupInfo& pswV) const { std::vector psTosave; std::string labels = "PS weights (w_var / w_nominal); "; @@ -533,11 +527,16 @@ void GenWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& d desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); desc.add>("unknownOnlyIfEmpty") ->setComment("Only store weights in an Unknown WeightGroup if one of the specified groups is empty"); - desc.add("keepAllPSWeights", false)->setComment("True: stores all PS weights (usually 45); False: saves preferred 4"); - desc.addUntracked("ignoreLheGroups", false)->setComment("Ignore LHE groups and store the first n weights, regardless of type"); - desc.addUntracked("ignoreGenGroups", false)->setComment("Ignore Gen groups and store the first n weights, regardless of type"); - desc.addUntracked("nStoreUngroupedLhe", 10)->setComment("Store the first n LHE weights (only relevant if ignoreLheGroups is true)"); - desc.addUntracked("nStoreUngroupedGen", 10)->setComment("Store the first n Gen weights (only relevant if ignoreGenGroups is true)"); + desc.add("keepAllPSWeights", false) + ->setComment("True: stores all PS weights (usually 45); False: saves preferred 4"); + desc.addUntracked("ignoreLheGroups", false) + ->setComment("Ignore LHE groups and store the first n weights, regardless of type"); + desc.addUntracked("ignoreGenGroups", false) + ->setComment("Ignore Gen groups and store the first n weights, regardless of type"); + desc.addUntracked("nStoreUngroupedLhe", 10) + ->setComment("Store the first n LHE weights (only relevant if ignoreLheGroups is true)"); + desc.addUntracked("nStoreUngroupedGen", 10) + ->setComment("Store the first n Gen weights (only relevant if ignoreGenGroups is true)"); descriptions.addDefault(desc); } diff --git a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc index 26ada163f6eee..af7af25d4406e 100644 --- a/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc +++ b/PhysicsTools/NanoAOD/plugins/NanoAODOutputModule.cc @@ -39,6 +39,7 @@ #include "DataFormats/NanoAOD/interface/FlatTable.h" #include "DataFormats/NanoAOD/interface/UniqueString.h" #include "PhysicsTools/NanoAOD/plugins/TableOutputBranches.h" +#include "PhysicsTools/NanoAOD/plugins/LumiOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/TriggerOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/EventStringOutputBranches.h" #include "PhysicsTools/NanoAOD/plugins/SummaryTableOutputBranches.h" @@ -130,6 +131,7 @@ class NanoAODOutputModule : public edm::one::OutputModule<> { std::vector m_runTables; std::vector m_lumiTables; + std::vector m_lumiTables2; std::vector m_runFlatTables; std::vector> m_nanoMetadata; @@ -252,6 +254,11 @@ void NanoAODOutputModule::writeLuminosityBlock(edm::LuminosityBlockForOutput con for (auto& t : m_lumiTables) t.fill(iLumi, *m_lumiTree); + for (unsigned int extensions = 0; extensions <= 1; ++extensions) { + for (auto& t : m_lumiTables2) + t.fill(iLumi, *m_lumiTree, extensions); + } + tbb::this_task_arena::isolate([&] { m_lumiTree->Fill(); }); m_processHistoryRegistry.registerProcessHistory(iLumi.processHistory()); @@ -326,6 +333,7 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { m_evstrings.clear(); m_runTables.clear(); m_lumiTables.clear(); + m_lumiTables2.clear(); m_runFlatTables.clear(); m_runFlatTableTokens.clear(); const auto& keeps = keptProducts(); @@ -349,6 +357,8 @@ void NanoAODOutputModule::openFile(edm::FileBlock const&) { m_lumiTables.push_back(SummaryTableOutputBranches(keep.first, keep.second)); else if (keep.first->className() == "nanoaod::UniqueString") m_nanoMetadata.emplace_back(keep.first->productInstanceName(), keep.second); + else if (keep.first->className() == "nanoaod::FlatTable") + m_lumiTables2.push_back(LumiOutputBranches(keep.first, keep.second)); else throw cms::Exception( "Configuration", diff --git a/PhysicsTools/NanoAOD/python/genWeightsTable_cfi.py b/PhysicsTools/NanoAOD/python/genWeightsTable_cfi.py deleted file mode 100644 index 158763fc7d51d..0000000000000 --- a/PhysicsTools/NanoAOD/python/genWeightsTable_cfi.py +++ /dev/null @@ -1,30 +0,0 @@ -import FWCore.ParameterSet.Config as cms - -genWeightsTable = cms.EDProducer("GenWeightsTableProducer", - genEvent = cms.InputTag("generator"), - genLumiInfoHeader = cms.InputTag("generator"), - lheInfo = cms.VInputTag(cms.InputTag("externalLHEProducer"), cms.InputTag("source")), - preferredPDFs = cms.VPSet( # see https://lhapdf.hepforge.org/pdfsets.html - cms.PSet( name = cms.string("NNPDF31_nnlo_hessian_pdfas"), lhaid = cms.uint32(306000) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_as_0118_hessian"), lhaid = cms.uint32(304400) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_as_0118_mc_hessian_pdfas"), lhaid = cms.uint32(325300) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_as_0118_mc"), lhaid = cms.uint32(316200) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_as_0118_nf_4_mc_hessian"), lhaid = cms.uint32(325500) ), - cms.PSet( name = cms.string("NNPDF31_nnlo_as_0118_nf_4"), lhaid = cms.uint32(320900) ), - cms.PSet( name = cms.string("NNPDF30_nlo_as_0118"), lhaid = cms.uint32(260000) ), # for some 92X samples. Note that the nominal weight, 260000, is not included in the LHE ... - cms.PSet( name = cms.string("NNPDF30_lo_as_0130"), lhaid = cms.uint32(262000) ), # some MLM 80X samples have only this (e.g. /store/mc/RunIISummer16MiniAODv2/DYJetsToLL_M-50_TuneCUETP8M1_13TeV-madgraphMLM-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6_ext1-v2/120000/02A210D6-F5C3-E611-B570-008CFA197BD4.root ) - cms.PSet( name = cms.string("NNPDF30_nlo_nf_4_pdfas"), lhaid = cms.uint32(292000) ), # some FXFX 80X samples have only this (e.g. WWTo1L1Nu2Q, WWTo4Q) - cms.PSet( name = cms.string("NNPDF30_nlo_nf_5_pdfas"), lhaid = cms.uint32(292200) ), # some FXFX 80X samples have only this (e.g. DYJetsToLL_Pt, WJetsToLNu_Pt, DYJetsToNuNu_Pt) - cms.PSet( name = cms.string("PDF4LHC15_nnlo_30_pdfas"), lhaid = cms.uint32(91400) ), - cms.PSet( name = cms.string("PDF4LHC15_nlo_30_pdfas"), lhaid = cms.uint32(90400) ), - cms.PSet( name = cms.string("PDF4LHC15_nlo_30"), lhaid = cms.uint32(90900) ), - ), - namedWeightIDs = cms.vstring(), - namedWeightLabels = cms.vstring(), - lheWeightPrecision = cms.int32(14), - maxPdfWeights = cms.uint32(150), - keepAllPSWeights = cms.bool(False), - debug = cms.untracked.bool(False), -) - -genWeightsTableTask = cms.Task(genWeightsTable) diff --git a/PhysicsTools/NanoAOD/python/nanogen_cff.py b/PhysicsTools/NanoAOD/python/nanogen_cff.py index a580a067a2ef5..bf20e2354abf4 100644 --- a/PhysicsTools/NanoAOD/python/nanogen_cff.py +++ b/PhysicsTools/NanoAOD/python/nanogen_cff.py @@ -1,6 +1,6 @@ from PhysicsTools.NanoAOD.taus_cff import * from PhysicsTools.NanoAOD.jets_cff import * -from PhysicsTools.NanoAOD.globals_cff import genTable +from PhysicsTools.NanoAOD.globals_cff import genTable,genFilterTable from PhysicsTools.NanoAOD.met_cff import metMCTable from PhysicsTools.NanoAOD.genparticles_cff import * from PhysicsTools.NanoAOD.particlelevel_cff import * @@ -26,6 +26,7 @@ +genJetAK8FlavourTable +cms.Sequence(genTauTask) +genTable + +genFilterTable +cms.Sequence(genParticleTablesTask) +cms.Sequence(genVertexTablesTask) +tautagger diff --git a/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py b/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py index 9dd0db71d37d1..cc883ec0ac141 100644 --- a/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py +++ b/PhysicsTools/PatAlgos/python/slimming/MicroEventContent_cff.py @@ -117,8 +117,10 @@ 'keep *_genMetTrue_*_*', 'keep LHERunInfoProduct_*_*_*', 'keep GenRunInfoProduct_*_*_*', - 'keep GenWeightProduct_*_*_*', - 'keep GenWeightInfoProduct_*_*_*', + 'keep GenWeightProduct_lheWeights_*_*', + 'keep GenWeightProduct_genWeights_*_*', + 'keep GenWeightInfoProduct_lheWeights_*_*', + 'keep GenWeightInfoProduct_genWeights_*_*', 'keep *_genParticles_xyz0_*', 'keep *_genParticles_t0_*', ) diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h index 0b30ef5b0e544..90753c828c4bc 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h @@ -25,15 +25,11 @@ class GenWeightInfoProduct { public: GenWeightInfoProduct() {} GenWeightInfoProduct(gen::WeightGroupInfoContainer& weightGroups); - GenWeightInfoProduct(std::unique_ptr other) { - copy(*other); - } - GenWeightInfoProduct(const GenWeightInfoProduct& other) { - copy(other); - } + GenWeightInfoProduct(std::unique_ptr other) { copy(*other); } + GenWeightInfoProduct(const GenWeightInfoProduct& other) { copy(other); } GenWeightInfoProduct& operator=(const GenWeightInfoProduct& other) { - copy(other); - return *this; + copy(other); + return *this; } void copy(const GenWeightInfoProduct& other) { for (auto& ptr : other.weightGroupsInfo_) { @@ -46,26 +42,28 @@ class GenWeightInfoProduct { const gen::WeightGroupInfoContainer& allWeightGroupsInfo() const; const std::vector allWeightGroupsInfoWithIndices() const; - gen::WeightGroupData containingWeightGroupInfo(int index, size_t startSearch=0) const; + gen::WeightGroupData containingWeightGroupInfo(int index, size_t startSearch = 0) const; const gen::WeightGroupInfo* orderedWeightGroupInfo(int index) const; std::vector weightGroupsByType(gen::WeightType type) const; std::vector weightGroupIndicesByType(gen::WeightType type) const; - std::vector weightGroupsAndIndicesByType(gen::WeightType type, int maxStore=-1) const; + std::vector weightGroupsAndIndicesByType(gen::WeightType type, int maxStore = -1) const; std::optional pdfGroupWithIndexByLHAID(int lhaid) const; std::vector pdfGroupsWithIndicesByLHAIDs(const std::vector& lhaids) const; void addWeightGroupInfo(gen::WeightGroupInfo info); void addWeightGroupInfo(std::unique_ptr info); const int numberOfGroups() const { return weightGroupsInfo_.size(); } - // If there are unassociated weights, the number of filled groups will be less than the number + // If there are unassociated weights, the number of filled groups will be less than the number // of groups, because the unassociated group can't be filled. Likewise the number of weights // in the GenWeightInfoProduct product will be less than the number of weights in the event - const int numberOfFilledGroups() const { - return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, - [](auto sum, auto& entry) { return sum + (entry->nIdsContained() > 0 ? 1 : 0); }); + const int numberOfFilledGroups() const { + return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, [](auto sum, auto& entry) { + return sum + (entry->nIdsContained() > 0 ? 1 : 0); + }); } - const int numberOfWeights() const { - return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, - [](auto sum, auto& entry) { return sum + entry->nIdsContained(); }); + const int numberOfWeights() const { + return std::accumulate(weightGroupsInfo_.begin(), weightGroupsInfo_.end(), 0, [](auto sum, auto& entry) { + return sum + entry->nIdsContained(); + }); } const int unassociatedIdx() const { return unassociatedIdx_; } diff --git a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h index 4a1c54bdfae85..3f1d00c81ab0f 100644 --- a/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h +++ b/SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h @@ -36,8 +36,9 @@ class GenWeightProduct { addWeightSet(); int maxSets = static_cast(weightsVector_.size()); if (maxSets <= setEntry) - throw cms::Exception("GenWeightProduct") << "WeightGroup index " << setEntry - << " is exceeds the number of WeightGroups expected (max " << maxSets << " )"; + throw cms::Exception("GenWeightProduct") + << "WeightGroup index " << setEntry << " is exceeds the number of WeightGroups expected (max " << maxSets + << " )"; auto& weights = weightsVector_[setEntry]; if (static_cast(weights.size()) <= weightNum) { weights.resize(weightNum + 1); diff --git a/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h index 2b6714b240542..5e0cbe72a8492 100644 --- a/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/MEParamWeightGroupInfo.h @@ -13,6 +13,7 @@ namespace gen { } MEParamWeightGroupInfo(std::string header) : MEParamWeightGroupInfo(header, header) {} ~MEParamWeightGroupInfo() override {} + MEParamWeightGroupInfo(const MEParamWeightGroupInfo& other) : WeightGroupInfo(other) { copy(other); } void copy(const MEParamWeightGroupInfo& other); MEParamWeightGroupInfo* clone() const override; int getCentralIndex() { return centralIdx; } diff --git a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h index b169299aadf04..fbfe0a0f1de8c 100644 --- a/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h +++ b/SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h @@ -21,18 +21,10 @@ namespace gen { int variationIndex(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; std::string variationName(bool isISR, bool isUp, PSVarType variationType, PSSplittingType splittingType) const; int variationIndex(bool isISR, bool isUp, PSVarType variationType) const; - int isrCombinedUpIndex(PSVarType variationType) const { - return variationIndex(true, true, variationType); - } - int isrCombinedDownIndex(PSVarType variationType) const { - return variationIndex(true, false, variationType); - } - int fsrCombinedUpIndex(PSVarType variationType) const { - return variationIndex(false, true, variationType); - } - int fsrCombinedDownIndex(PSVarType variationType) const { - return variationIndex(false, false, variationType); - } + int isrCombinedUpIndex(PSVarType variationType) const { return variationIndex(true, true, variationType); } + int isrCombinedDownIndex(PSVarType variationType) const { return variationIndex(true, false, variationType); } + int fsrCombinedUpIndex(PSVarType variationType) const { return variationIndex(false, true, variationType); } + int fsrCombinedDownIndex(PSVarType variationType) const { return variationIndex(false, false, variationType); } static void setGuessPSWeightIdx(bool guessPSWeightIdx) { guessPSWeightIdx_ = guessPSWeightIdx; } int psWeightIdxGuess(const std::string &varName) const; void printVariables() const; diff --git a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc index 4e217f6e5fb0b..f03b401b0979c 100644 --- a/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc +++ b/SimDataFormats/GeneratorProducts/src/GenWeightInfoProduct.cc @@ -6,17 +6,18 @@ #include "FWCore/Utilities/interface/Exception.h" GenWeightInfoProduct::GenWeightInfoProduct(std::vector>& weightGroups) { - // Could just do a std::move on the vector, but copying is safer if the user expects the vector to still be usable + // Could just do a std::move on the vector, but copying is safer if the user expects the vector to still be usable for (auto& ptr : weightGroups) { std::unique_ptr cloneptr(ptr->clone()); weightGroupsInfo_.emplace_back(std::move(cloneptr)); } - auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [](auto& entry) { return entry->name() == "unassociated"; }); + auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [](auto& entry) { + return entry->name() == "unassociated"; + }); if (it != std::end(weightGroupsInfo_)) { - unassociatedIdx_ = std::distance(std::begin(weightGroupsInfo_), it); - } - else - unassociatedIdx_ = -1; + unassociatedIdx_ = std::distance(std::begin(weightGroupsInfo_), it); + } else + unassociatedIdx_ = -1; } const std::vector>& GenWeightInfoProduct::allWeightGroupsInfo() const { @@ -26,7 +27,7 @@ const std::vector>& GenWeightInfoProduct:: const std::vector GenWeightInfoProduct::allWeightGroupsInfoWithIndices() const { std::vector groupInfo; for (size_t i = 0; i < weightGroupsInfo_.size(); i++) - groupInfo.push_back({i, weightGroupsInfo_[i].get()}); + groupInfo.push_back({i, weightGroupsInfo_[i].get()}); return groupInfo; } @@ -34,12 +35,14 @@ gen::WeightGroupData GenWeightInfoProduct::containingWeightGroupInfo(int index, // When filling the weights, most likely to find the weight matches the previous group or the one after if (startSearch < weightGroupsInfo_.size() && weightGroupsInfo_[startSearch]->containsWeight(index)) return {startSearch, weightGroupsInfo_[startSearch].get()}; - else if (startSearch+1 < weightGroupsInfo_.size() && weightGroupsInfo_[startSearch+1]->containsWeight(index)) - return {startSearch+1, weightGroupsInfo_[startSearch+1].get()}; + else if (startSearch + 1 < weightGroupsInfo_.size() && weightGroupsInfo_[startSearch + 1]->containsWeight(index)) + return {startSearch + 1, weightGroupsInfo_[startSearch + 1].get()}; - auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [index](auto& entry) { return entry->containsWeight(index); }); + auto it = std::find_if(std::begin(weightGroupsInfo_), std::end(weightGroupsInfo_), [index](auto& entry) { + return entry->containsWeight(index); + }); if (it != std::end(weightGroupsInfo_)) - return {static_cast(std::distance(std::begin(weightGroupsInfo_), it)), it->get()}; + return {static_cast(std::distance(std::begin(weightGroupsInfo_), it)), it->get()}; throw cms::Exception("GenWeightInfoProduct") << "No weight group found containing the weight index requested"; } @@ -51,16 +54,17 @@ const gen::WeightGroupInfo* GenWeightInfoProduct::orderedWeightGroupInfo(int wei return weightGroupsInfo_[weightGroupIndex].get(); } -std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type, int maxStore) const { +std::vector GenWeightInfoProduct::weightGroupsAndIndicesByType(gen::WeightType type, + int maxStore) const { std::vector matchingGroups; size_t toStore = maxStore <= 0 ? weightGroupsInfo_.size() : std::min(maxStore, weightGroupsInfo_.size()); for (size_t i = 0; i < weightGroupsInfo_.size(); i++) { const gen::WeightGroupInfo* group = weightGroupsInfo_[i].get(); if (group->weightType() == type) { matchingGroups.push_back({i, group}); - if (matchingGroups.size() == toStore) - break; - } + if (matchingGroups.size() == toStore) + break; + } } return matchingGroups; } diff --git a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc index 0b172b821fd0f..cc65bec64eb56 100644 --- a/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc +++ b/SimDataFormats/GeneratorProducts/src/WeightGroupInfo.cc @@ -22,17 +22,17 @@ namespace gen { << "In group " << name_ << ": WeightGroupInfo is abstract, so it's clone() method can't be implemented."; } - const WeightMetaInfo& WeightGroupInfo::weightMetaInfo(int weightEntry) const { + const WeightMetaInfo& WeightGroupInfo::weightMetaInfo(int weightEntry) const { if (weightEntry < 0 || weightEntry >= static_cast(idsContained_.size())) throw cms::Exception("WeightGroupInfo") << "Local index " << std::to_string(weightEntry) << " is not within the range of group " << name_ << " which has " << idsContained_.size() << " entries\n"; - return idsContained_.at(weightEntry); + return idsContained_.at(weightEntry); } const WeightMetaInfo& WeightGroupInfo::weightMetaInfoByGlobalIndex(int weightEntry) const { - std::string emptyLabel = ""; - return weightMetaInfoByGlobalIndex(emptyLabel, weightEntry); + std::string emptyLabel = ""; + return weightMetaInfoByGlobalIndex(emptyLabel, weightEntry); } const WeightMetaInfo& WeightGroupInfo::weightMetaInfoByGlobalIndex(std::string& wgtId, int weightEntry) const { @@ -66,8 +66,9 @@ namespace gen { } } // Fall back to global search on ID or global index - auto it = std::find_if(idsContained_.begin(), idsContained_.end(), [wgtId, weightEntry](const WeightMetaInfo& w) - { return wgtId.empty() ? static_cast(w.globalIndex) == weightEntry : w.id == wgtId; }); + auto it = std::find_if(idsContained_.begin(), idsContained_.end(), [wgtId, weightEntry](const WeightMetaInfo& w) { + return wgtId.empty() ? static_cast(w.globalIndex) == weightEntry : w.id == wgtId; + }); if (it != idsContained_.end()) return std::distance(idsContained_.begin(), it); return -1; From d3d2af5886173df953c117b86b3a2eb7ae4b3beb Mon Sep 17 00:00:00 2001 From: Kenneth Long Date: Sun, 16 Jan 2022 02:43:43 +0100 Subject: [PATCH 16/16] Remove redundant files (renamed or dropped) revert unneeded change --- .../interface/LHEWeightGroupReaderHelper.h | 301 ------------ .../LHEInterface/plugins/BuildFile.xml | 2 +- .../plugins/LHEWeightsTableProducer.cc | 429 ------------------ .../interface/LHEWeightInfoProduct.h | 37 -- .../interface/LHEWeightProduct.h | 43 -- .../src/LHEWeightInfoProduct.cc | 40 -- 6 files changed, 1 insertion(+), 851 deletions(-) delete mode 100644 GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h delete mode 100644 PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc delete mode 100644 SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h delete mode 100644 SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h delete mode 100644 SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc diff --git a/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h b/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h deleted file mode 100644 index 38315664782aa..0000000000000 --- a/GeneratorInterface/LHEInterface/interface/LHEWeightGroupReaderHelper.h +++ /dev/null @@ -1,301 +0,0 @@ -#ifndef GeneratorInterface_LHEInterface_LHEWeightGroupReaderHelper_h -#define GeneratorInterface_LHEInterface_LHEWeightGroupReaderHelper_h - -#include -#include -#include -#include -#include - -#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" - -#include -using namespace tinyxml2; - - -class LHEWeightGroupReaderHelper { -public: - LHEWeightGroupReaderHelper(); - - //// possibly add more versions of this functions for different inputs - void parseLHEFile(std::string filename); - void parseWeightGroupsFromHeader(std::vector lheHeader); - - - edm::OwnVector getWeightGroups() {return weightGroups_;} -private: - void loadAttributeNames(std::string baseName, std::vector altNames ={}); - std::string toLowerCase(const char*); - std::string toLowerCase(const std::string); - std::map getAttributeMap(std::string); - std::string sanitizeText(std::string); - bool isAWeight(std::string); - - // Variables - edm::OwnVector weightGroups_; - std::regex weightGroupStart_; - std::regex weightGroupEnd_; - std::regex weightContent_; - - std::map nameConvMap; -}; - - -std::string -LHEWeightGroupReaderHelper::toLowerCase(const char* name) { - std::string returnStr; - for (size_t i = 0; i < strlen(name); ++i) - returnStr.push_back(tolower(name[i])); - return returnStr; -} - -std::string -LHEWeightGroupReaderHelper::toLowerCase(const std::string name) { - std::string returnStr = name; - transform(name.begin(), name.end(), returnStr.begin(), ::tolower); - return returnStr; - - -} - -void LHEWeightGroupReaderHelper::loadAttributeNames(std::string baseName, std::vector altNames) { - for(auto altname : altNames) { - nameConvMap[altname] = baseName; - } - nameConvMap[baseName] = baseName; -} - -std::string -LHEWeightGroupReaderHelper::sanitizeText(std::string line) { - std::map replaceMap = {{"<", "<"}, {">", ">"}}; - - for(auto pair: replaceMap) { - std::string badText = pair.first; - std::string goodText = pair.second; - while(line.find(badText) != std::string::npos) { - size_t spot = line.find(badText); - line.replace(spot, badText.size(), goodText); - } - } - return line; -} - - -LHEWeightGroupReaderHelper::LHEWeightGroupReaderHelper() { - weightGroupStart_ = std::regex(".*.*\n*"); - weightGroupEnd_ = std::regex(".*.*\n*"); - - std::cout << "Init" << "\n"; - - /// Might change later, order matters and code doesn't pick choices - - // Used for translating different naming convention to a common one - loadAttributeNames("muf", {"facscfact"}); - loadAttributeNames("mur", {"renscfact"}); - loadAttributeNames("id"); - loadAttributeNames("pdf", {"pdf set", "lhapdf", "pdfset"}); - loadAttributeNames("dyn_scale"); - - loadAttributeNames("combine"); - loadAttributeNames("name", {"type"}); - -} - -std::map -LHEWeightGroupReaderHelper::getAttributeMap(std::string line) { - XMLDocument xmlParser; - int error = xmlParser.Parse(line.c_str()); - if (error) { - std::cout << "we have a problem!" << "\n"; - return std::map(); - //do something.... - } - - std::map attMap; - XMLElement* element = xmlParser.FirstChildElement(); - - for( const XMLAttribute* a = element->FirstAttribute(); a; a=a->Next()) { - attMap[nameConvMap[toLowerCase(a->Name())]] = a->Value(); - } - // get stuff from content of tag if it has anything. - // always assume format is AAAAA=( )BBBB ( ) => optional space - if (element->GetText() == nullptr) { - return attMap; - } - // This adds "content: " to the beginning of the content. not sure if its a big deal or? - std::string content = element->GetText(); - attMap["content"] = content; - - std::regex reg("(?:(\\S+)=\\s*(\\S+))"); - std::smatch m; - while(std::regex_search(content, m, reg)) { - std::string key = nameConvMap[toLowerCase(m.str(1))]; - if (attMap[key] != std::string()) { - if (m[2] != attMap[key]) { - std::cout << m.str(2) << " vs " << attMap[key]; - // might do something if content and attribute don't match? - // but need to be careful since some are purposefully different - // eg dyn_scale is described in content but just given a number - } - } - else { - attMap[key] = m.str(2); - } - content = m.suffix().str(); - } - return attMap; - -} - -bool -LHEWeightGroupReaderHelper::isAWeight(std::string line) { - XMLDocument xmlParser; - int error = xmlParser.Parse(line.c_str()); - if (error) { - return false; - //do something.... - } - XMLElement* element = xmlParser.FirstChildElement(); - return element; -} - -// void -// LHEWeightGroupReaderHelper::parseLHEFile(std::string filename) { -// std::ifstream file; -// file.open(filename); - -// std::string line; -// std::smatch matches; -// // TODO: Not sure the weight indexing is right here, this seems to more or less -// // count the lines which isn't quite the goal. TOCHECK! -// int index = 0; -// while(getline(file, line)) { -// if(std::regex_match(line, weightGroupStart_)) { -// std::string name = getMap_testAll(line, {weightGroupInfo})["name"]; - -// //TODO: Fine for now, but in general there should also be a check on the PDF weights, -// // e.g., it could be an unknown weight - -// if(std::regex_match(name, scaleWeightMatch_)) { -// weightGroups_.push_back(new gen::ScaleWeightGroupInfo(line)); -// std::cout << "scale weight" << "\n"; -// } - - -// else -// weightGroups_.push_back(new gen::PdfWeightGroupInfo(line)); - -// /// file weights -// while(getline(file, line) && !std::regex_match(line, weightGroupEnd_)) { -// auto tagsMap = getMap_testAll(line, regexOptions); - -// std::regex_search(line, matches, weightContent_); -// // TODO: Add proper check that it worked -// std::string content = matches[1].str(); - -// auto& group = weightGroups_.back(); -// if (group.weightType() == gen::kScaleWeights) { -// float muR = std::stof(tagsMap["mur"]); -// float muF = std::stof(tagsMap["muf"]); -// auto& scaleGroup = static_cast(group); -// scaleGroup.addContainedId(index, tagsMap["id"], line, muR, muF); -// } -// else -// group.addContainedId(index, tagsMap["id"], line); - -// index++; -// } -// } -// } -// } - -void -LHEWeightGroupReaderHelper::parseWeightGroupsFromHeader(std::vector lheHeader) { - // TODO: Not sure the weight indexing is right here, this seems to more or less - // count the lines which isn't quite the goal. TOCHECK! - int index = 0; - bool foundGroup = false; - - for (std::string headerLine : lheHeader) { - std::cout << "Header line is:" << headerLine; - headerLine = sanitizeText(headerLine); - std::cout << "Header line is:" << weightGroups_.size() << " "<< headerLine; - //TODO: Fine for now, but in general there should also be a check on the PDF weights, - // e.g., it could be an unknown weight - - if (std::regex_match(headerLine, weightGroupStart_)) { - //std::cout << "Adding new group for headerLine" << std::endl; - foundGroup = true; - std::string fullTag = headerLine + ""; - auto groupMap = getAttributeMap(fullTag); - std::string name = groupMap["name"]; - - if(name.find("Central scale variation") != std::string::npos || - name.find("scale_variation") != std::string::npos) { - weightGroups_.push_back(new gen::ScaleWeightGroupInfo(headerLine)); - std::cout << "scale weight" << "\n"; - } - else - weightGroups_.push_back(new gen::PdfWeightGroupInfo(headerLine)); - } - /// file weights - else if (foundGroup && isAWeight(headerLine)) { - //std::cout << "Adding new weight for headerLine" << std::endl; - auto tagsMap = getAttributeMap(headerLine); - for(auto pair: tagsMap) { - std::cout << pair.first << ": " << pair.second << " | "; - } - std::cout << "\n"; - - std::string content = tagsMap["content"]; - if (tagsMap["id"] == std::string()) { - std::cout << "error" << "\n"; - // should do something - } - - auto& group = weightGroups_.back(); - if (group.weightType() == gen::kScaleWeights) { - if (tagsMap["mur"] == std::string() || tagsMap["muf"] == std::string()) { - std::cout << "error" << "\n"; - // something should happen here - continue; - } - float muR = std::stof(tagsMap["mur"]); - float muF = std::stof(tagsMap["muf"]); - std::cout << tagsMap["id"] << " " << muR << " " << muF << " " << content << "\n"; - auto& scaleGroup = static_cast(group); - scaleGroup.addContainedId(index, tagsMap["id"], headerLine, muR, muF); - } - else - group.addContainedId(index, tagsMap["id"], headerLine); - index++; - } - // commented out since code doesn't work with this in.... - // else if(isAWeight(headerLine)) { - // // found header. Don't know what to do with it so just shove it into a new weightgroup for now - // // do minimum work for it - // weightGroups_.push_back(new gen::PdfWeightGroupInfo(headerLine)); - // auto& group = weightGroups_.back(); - // auto tagsMap = getAttributeMap(headerLine); - // group.addContainedId(index, tagsMap["id"], headerLine); - // foundGroup = true; - // index++; - // } - - else if(std::regex_match(headerLine, weightGroupEnd_)) { - foundGroup = false; - } - else { - std::cout << "problem!!!" << "\n"; - } - } -} - - - -#endif - - diff --git a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml index 2dae1e9cd252f..167989f991b0d 100644 --- a/GeneratorInterface/LHEInterface/plugins/BuildFile.xml +++ b/GeneratorInterface/LHEInterface/plugins/BuildFile.xml @@ -7,7 +7,6 @@ - @@ -15,6 +14,7 @@ + diff --git a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc b/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc deleted file mode 100644 index 2803d52f0ccb2..0000000000000 --- a/PhysicsTools/NanoAOD/plugins/LHEWeightsTableProducer.cc +++ /dev/null @@ -1,429 +0,0 @@ -#include "FWCore/Framework/interface/global/EDProducer.h" -#include "FWCore/Framework/interface/Event.h" -#include "FWCore/Framework/interface/Run.h" -#include "FWCore/ParameterSet/interface/ParameterSet.h" -#include "DataFormats/NanoAOD/interface/FlatTable.h" -#include "DataFormats/NanoAOD/interface/MergeableCounterTable.h" -#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" -#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" -#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h" -#include "FWCore/MessageLogger/interface/MessageLogger.h" -#include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/GenWeightInfoProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h" -#include "SimDataFormats/GeneratorProducts/interface/GenWeightProduct.h" -#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/ScaleWeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/PdfWeightGroupInfo.h" -#include "SimDataFormats/GeneratorProducts/interface/PartonShowerWeightGroupInfo.h" -#include "FWCore/Utilities/interface/transform.h" -#include "PhysicsTools/NanoAOD/interface/GenWeightCounters.h" -#include -#include -#include - -namespace { - typedef std::vector WeightGroupDataContainer; - typedef std::array, 2> WeightGroupsToStore; -} // namespace -using CounterMap = genCounter::CounterMap; -using Counter = genCounter::Counter; - -class LHEWeightsTableProducer : public edm::global::EDProducer, - edm::StreamCache, - edm::RunSummaryCache, - edm::EndRunProducer> { -public: - LHEWeightsTableProducer(edm::ParameterSet const& params); - - void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override; - //func changed//sroychow - void addWeightGroupToTable(std::map>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - const char* typeName, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - Counter& counter, - double genWeight) const; - WeightGroupDataContainer weightDataPerType(edm::Handle& weightsHandle, - gen::WeightType weightType, - int& maxStore) const; - - std::vector orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo& scaleGroup) const; - - std::vector preferredPSweights(const std::vector& psWeights, - const gen::PartonShowerWeightGroupInfo& pswV) const; - - //Lumiblock - std::shared_ptr globalBeginLuminosityBlock(edm::LuminosityBlock const& iLumi, - edm::EventSetup const&) const override { - // Set equal to the max number of groups - // subtrack 1 for each weight group you find - bool foundLheWeights = false; - edm::Handle lheWeightInfoHandle; - for (auto& token : lheWeightInfoTokens_) { - iLumi.getByToken(token, lheWeightInfoHandle); - if (lheWeightInfoHandle.isValid()) { - foundLheWeights = true; - break; - } - } - edm::Handle genWeightInfoHandle; - iLumi.getByToken(genWeightInfoToken_, genWeightInfoHandle); - - std::unordered_map storePerType; - for (size_t i = 0; i < weightgroups_.size(); i++) - storePerType[weightgroups_.at(i)] = maxGroupsPerType_.at(i); - - WeightGroupsToStore weightsToStore; - for (auto weightType : gen::allWeightTypes) { - if (foundLheWeights) { - auto lheWeights = weightDataPerType(lheWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : lheWeights) - weightsToStore.at(inLHE).push_back({w.index, std::move(w.group)}); - } - auto genWeights = weightDataPerType(genWeightInfoHandle, weightType, storePerType[weightType]); - for (auto& w : genWeights) - weightsToStore.at(inGen).push_back({w.index, std::move(w.group)}); - } - return std::make_shared(weightsToStore); - } - - // nothing to do here - void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {} - // create an empty counter - std::unique_ptr beginStream(edm::StreamID) const override { return std::make_unique(); } - // inizialize to zero at begin run - void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override { - streamCache(id)->clear(); - } - - void streamBeginLuminosityBlock(edm::StreamID id, - edm::LuminosityBlock const& lumiBlock, - edm::EventSetup const& eventSetup) const override { - auto counterMap = streamCache(id); - edm::Handle genLumiInfoHead; - lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead); - if (!genLumiInfoHead.isValid()) - edm::LogWarning("LHETablesProducer") - << "No GenLumiInfoHeader product found, will not fill generator model string.\n"; - counterMap->setLabel(genLumiInfoHead.isValid() ? genLumiInfoHead->configDescription() : ""); - std::string label = genLumiInfoHead.isValid() ? counterMap->getLabel() : "NULL"; - } - // create an empty counter - std::shared_ptr globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override { - return std::make_shared(); - } - // add this stream to the summary - void streamEndRunSummary(edm::StreamID id, - edm::Run const&, - edm::EventSetup const&, - CounterMap* runCounterMap) const override; - // nothing to do per se - void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {} - // write the total to the run - void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const& es, CounterMap const* runCounterMap) const override; - // nothing to do here - //void globalEndRun(edm::Run const& iRun, edm::EventSetup const& es, CounterMap* runCounterMap) const override {} - - static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); - -protected: - const std::vector> lheWeightTokens_; - const std::vector> lheWeightInfoTokens_; - const edm::EDGetTokenT genWeightToken_; - const edm::EDGetTokenT genWeightInfoToken_; - const edm::EDGetTokenT genEventInfoToken_; - const edm::EDGetTokenT genLumiInfoHeadTag_; - const std::vector weightgroups_; - const std::vector maxGroupsPerType_; - const std::vector pdfIds_; - const std::unordered_map weightTypeNames_ = { - {gen::WeightType::kScaleWeights, "LHEScaleWeight"}, - {gen::WeightType::kPdfWeights, "LHEPdfWeight"}, - {gen::WeightType::kMEParamWeights, "MEParamWeight"}, - {gen::WeightType::kPartonShowerWeights, "PSWeight"}, - {gen::WeightType::kUnknownWeights, "UnknownWeight"}, - }; - //std::unordered_map weightGroupIndices_; - int lheWeightPrecision_; - bool storeAllPSweights_; - - enum { inLHE, inGen }; -}; -//put back if needed; till now not used -LHEWeightsTableProducer::LHEWeightsTableProducer(edm::ParameterSet const& params) - : lheWeightTokens_( - edm::vector_transform(params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - lheWeightInfoTokens_(edm::vector_transform( - params.getParameter>("lheWeights"), - [this](const edm::InputTag& tag) { return mayConsume(tag); })), - genWeightToken_(consumes(params.getParameter("genWeights"))), - genWeightInfoToken_( - consumes(params.getParameter("genWeights"))), - genEventInfoToken_(consumes(params.getParameter("genEvent"))), - genLumiInfoHeadTag_( - mayConsume(params.getParameter("genLumiInfoHeader"))), - weightgroups_(edm::vector_transform(params.getParameter>("weightgroups"), - [](auto& c) { return gen::WeightType(c.at(0)); })), - maxGroupsPerType_(params.getParameter>("maxGroupsPerType")), - pdfIds_(params.getUntrackedParameter>("pdfIds", {})), - lheWeightPrecision_(params.getParameter("lheWeightPrecision")), - storeAllPSweights_(params.getParameter("storeAllPSweights")) { - if (weightgroups_.size() != maxGroupsPerType_.size()) - throw std::invalid_argument("Inputs 'weightgroups' and 'weightgroupNums' must have equal size"); - for (auto& wg : weightTypeNames_) { - produces(wg.second); - produces(wg.second + "sizes"); - } - produces("GENWeight"); - produces(); - produces("genModel"); -} - -void LHEWeightsTableProducer::produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const { - //access counter for weight sums - Counter& counter = *streamCache(id)->get(); - edm::Handle lheWeightHandle; - bool foundLheWeights = false; - for (auto& token : lheWeightTokens_) { - iEvent.getByToken(token, lheWeightHandle); - if (lheWeightHandle.isValid()) { - foundLheWeights = true; - break; - } - } - //Taken from genweight producer //Added sroychow - // generator information (always available) - auto const& genInfo = iEvent.get(genEventInfoToken_); - const double genWeight = genInfo.weight(); - // table for gen info, always available - auto outGeninfo = std::make_unique(1, "genWeight", true); - outGeninfo->setDoc("generator weight"); - outGeninfo->addColumnValue("", genInfo.weight(), "generator weight"); - iEvent.put(std::move(outGeninfo), "GENWeight"); - //this will take care of sum of genWeights - counter.incGenOnly(genWeight); - - std::string& model_label = streamCache(id)->getLabel(); - auto outM = std::make_unique((!model_label.empty()) ? std::string("GenModel_") + model_label : ""); - iEvent.put(std::move(outM), "genModel"); - - WeightsContainer lheWeights; - if (foundLheWeights) { - const GenWeightProduct* lheWeightProduct = lheWeightHandle.product(); - lheWeights = lheWeightProduct->weights(); - } - - edm::Handle genWeightHandle; - iEvent.getByToken(genWeightToken_, genWeightHandle); - const GenWeightProduct* genWeightProduct = genWeightHandle.product(); - WeightsContainer genWeights = genWeightProduct->weights(); - - auto const& weightInfos = *luminosityBlockCache(iEvent.getLuminosityBlock().index()); - - //create a container with dummy weight vector - std::map> lheWeightTables; - std::map> weightVecsizes; - std::map weightlabels; - for (auto& wg : weightTypeNames_) { - lheWeightTables.insert(std::make_pair(wg.first, std::vector())); - weightVecsizes.insert(std::make_pair(wg.first, std::vector())); - weightlabels.insert(std::make_pair(wg.first, "")); - } - if (foundLheWeights) { - addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, "LHE", weightInfos.at(inLHE), lheWeights, counter, genWeight); - } - - addWeightGroupToTable( - lheWeightTables, weightVecsizes, weightlabels, "Gen", weightInfos.at(inGen), genWeights, counter, genWeight); - - for (auto& wg : weightTypeNames_) { - std::string wname = wg.second; - auto& weightVec = lheWeightTables[wg.first]; - counter.incLHE(genWeight, weightVec, wname); - auto outTable = std::make_unique(weightVec.size(), wname, false); - outTable->addColumn("", weightVec, weightlabels[wg.first], lheWeightPrecision_); - - //now add the vector containing the sizes of alt sets - auto outTableSizes = - std::make_unique(weightVecsizes[wg.first].size(), wname + "_AltSetSizes", false); - outTableSizes->addColumn( - "", weightVecsizes[wg.first], "Sizes of weight arrays for weight type:" + wname, lheWeightPrecision_); - iEvent.put(std::move(outTable), wname); - iEvent.put(std::move(outTableSizes), wname + "sizes"); - } -} - -/* - -*/ -void LHEWeightsTableProducer::addWeightGroupToTable(std::map>& lheWeightTables, - std::map>& weightVecsizes, - std::map& weightlabels, - const char* typeName, - const WeightGroupDataContainer& weightInfos, - WeightsContainer& allWeights, - Counter& counter, - double genWeight) const { - std::unordered_map typeCount = {}; - for (auto& type : gen::allWeightTypes) - typeCount[type] = 0; - - for (const auto& groupInfo : weightInfos) { - //std::string entryName = typeName; - gen::WeightType weightType = groupInfo.group->weightType(); - std::string name = weightTypeNames_.at(weightType); - std::string label = "[" + std::to_string(typeCount[weightType]) + "] " + groupInfo.group->description(); - label.append("["); - label.append(std::to_string(lheWeightTables[weightType].size())); //to append the start index of this set - label.append("]; "); - auto& weights = allWeights.at(groupInfo.index); - if (weightType == gen::WeightType::kScaleWeights) { - if (groupInfo.group->isWellFormed()) { - const auto scaleGroup = *static_cast(groupInfo.group.get()); - weights = orderedScaleWeights(weights, scaleGroup); - label.append( - "[1] is mur=0.5 muf=1; [2] is mur=0.5 muf=2; [3] is mur=1 muf=0.5 ;" - " [4] is mur=1 muf=1; [5] is mur=1 muf=2; [6] is mur=2 muf=0.5;" - " [7] is mur=2 muf=1 ; [8] is mur=2 muf=2)"); - } else { - size_t nstore = std::min(gen::ScaleWeightGroupInfo::MIN_SCALE_VARIATIONS, weights.size()); - weights = std::vector(weights.begin(), weights.begin() + nstore); - label.append("WARNING: Unexpected format found. Contains first " + std::to_string(nstore) + - " elements of weights vector, unordered"); - } - } else if (!storeAllPSweights_ && weightType == gen::WeightType::kPartonShowerWeights) { // && groupInfo.group->isWellFormed() - const auto psGroup = *static_cast(groupInfo.group.get()); - weights = preferredPSweights(weights, psGroup); - label.append( - "PS weights (w_var / w_nominal); [0] is ISR=0.5 FSR=1; [1] is ISR=1 FSR=0.5; [2] is ISR=2 FSR=1; [3] is " - "ISR=1 FSR=2"); - } - //else - // label.append(groupInfo.group->description()); - lheWeightTables[weightType].insert(lheWeightTables[weightType].end(), weights.begin(), weights.end()); - weightVecsizes[weightType].emplace_back(weights.size()); - - if (weightlabels[weightType].empty()) - weightlabels[weightType].append("[idx in AltSetSizes array] Name [start idx in weight array];\n"); - - weightlabels[weightType].append(label); - typeCount[weightType]++; - } -} - -WeightGroupDataContainer LHEWeightsTableProducer::weightDataPerType(edm::Handle& weightsHandle, - gen::WeightType weightType, - int& maxStore) const { - std::vector allgroups; - if (weightType == gen::WeightType::kPdfWeights && !pdfIds_.empty()) { - allgroups = weightsHandle->pdfGroupsWithIndicesByLHAIDs(pdfIds_); - } else - allgroups = weightsHandle->weightGroupsAndIndicesByType(weightType); - - int toStore = maxStore; - if (maxStore < 0 || static_cast(allgroups.size()) <= maxStore) { - // Modify size in case one type of weight is present in multiple products - maxStore -= allgroups.size(); - toStore = allgroups.size(); - } - - WeightGroupDataContainer out; - for (int i = 0; i < toStore; i++) { - auto& group = allgroups.at(i); - gen::SharedWeightGroupData temp = {group.index, std::move(group.group)}; - out.push_back(temp); - } - return out; -} - -std::vector LHEWeightsTableProducer::orderedScaleWeights(const std::vector& scaleWeights, - const gen::ScaleWeightGroupInfo& scaleGroup) const { - std::vector weights; - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR05muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.centralIndex())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR1muF2Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF05Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF1Index())); - weights.emplace_back(scaleWeights.at(scaleGroup.muR2muF2Index())); - - return weights; -} - -std::vector LHEWeightsTableProducer::preferredPSweights(const std::vector& psWeights, - const gen::PartonShowerWeightGroupInfo& pswV) const { - std::vector psTosave; - - double baseline = psWeights.at(pswV.weightIndexFromLabel("Baseline")); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, true, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, true, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(true, false, gen::PSVarType::def)) / baseline); - psTosave.emplace_back(psWeights.at(pswV.variationIndex(false, false, gen::PSVarType::def)) / baseline); - return psTosave; -} - -void LHEWeightsTableProducer::streamEndRunSummary(edm::StreamID id, - edm::Run const&, - edm::EventSetup const&, - CounterMap* runCounterMap) const { - //this takes care for mergeing all the weight sums - runCounterMap->mergeSumMap(*streamCache(id)); -} - -void LHEWeightsTableProducer::globalEndRunProduce(edm::Run& iRun, - edm::EventSetup const&, - CounterMap const* runCounterMap) const { - auto out = std::make_unique(); - - for (auto x : runCounterMap->countermap) { - auto& runCounter = x.second; - std::string label = std::string("_") + x.first; - std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : ""; - - out->addInt("genEventCount" + label, "event count" + doclabel, runCounter.num_); - out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter.sumw_); - out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter.sumw2_); - - double norm = runCounter.sumw_ ? 1.0 / runCounter.sumw_ : 1; - //Sum from map - for (auto& sumw : runCounter.weightSumMap_) { - //Normalize with genEventSumw - for (auto& val : sumw.second) - val *= norm; - out->addVFloat(sumw.first + "Sumw" + label, - "Sum of genEventWeight *" + sumw.first + "[i]/genEventSumw" + doclabel, - sumw.second); - } - } - iRun.put(std::move(out)); -} -void LHEWeightsTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { - edm::ParameterSetDescription desc; - desc.add>("lheWeights"); - desc.add>("lheInfo", std::vector{{"externalLHEProducer"}, {"source"}}) - ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)"); - //desc.add>("genWeights"); - desc.add("genWeights"); - desc.add("genEvent", edm::InputTag("generator")) - ->setComment("tag for the GenEventInfoProduct, to get the main weight"); - desc.add("genLumiInfoHeader", edm::InputTag("generator")) - ->setComment("tag for the GenLumiInfoProduct, to get the model string"); - desc.add>("weightgroups"); - desc.add>("maxGroupsPerType"); - desc.addOptionalUntracked>("pdfIds"); - desc.add("lheWeightPrecision", -1)->setComment("Number of bits in the mantissa for LHE weights"); - desc.add("storeAllPSweights", false)->setComment("True:stores all 45 PS weights; False:saves preferred 4"); - descriptions.addDefault(desc); -} - -#include "FWCore/Framework/interface/MakerMacros.h" -DEFINE_FWK_MODULE(LHEWeightsTableProducer); diff --git a/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h b/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h deleted file mode 100644 index f0fa291ab3423..0000000000000 --- a/SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SimDataFormats_GeneratorProducts_LHEWeightInfoProduct_h -#define SimDataFormats_GeneratorProducts_LHEWeightInfoProduct_h - -#include -#include -#include -#include - -//#include - -#include "DataFormats/Common/interface/OwnVector.h" -#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" -#include "SimDataFormats/GeneratorProducts/interface/WeightGroupInfo.h" - -class LHEWeightInfoProduct { - public: - LHEWeightInfoProduct() {} - LHEWeightInfoProduct(edm::OwnVector& weightGroups); - LHEWeightInfoProduct(const LHEWeightInfoProduct& other); - LHEWeightInfoProduct(LHEWeightInfoProduct&& other); - ~LHEWeightInfoProduct() {} - LHEWeightInfoProduct& operator=(const LHEWeightInfoProduct &other); - LHEWeightInfoProduct& operator=(LHEWeightInfoProduct &&other); - - const edm::OwnVector& allWeightGroupsInfo() const; - const gen::WeightGroupInfo& containingWeightGroupInfo(int index) const; - const gen::WeightGroupInfo& orderedWeightGroupInfo(int index) const; - void addWeightGroupInfo(gen::WeightGroupInfo& info); - - private: - edm::OwnVector weightGroupsInfo_; - - -}; - -#endif // GeneratorWeightInfo_LHEInterface_LHEWeightInfoProduct_h - diff --git a/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h b/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h deleted file mode 100644 index 5c5fa132b4ee7..0000000000000 --- a/SimDataFormats/GeneratorProducts/interface/LHEWeightProduct.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SimDataFormats_GeneratorProducts_LHEWeightProduct_h -#define SimDataFormats_GeneratorProducts_LHEWeightProduct_h - -#include -#include -#include -#include - -#include "SimDataFormats/GeneratorProducts/interface/LesHouches.h" -#include "SimDataFormats/GeneratorProducts/interface/WeightsInfo.h" - -typedef std::vector> WeightsContainer; - -class LHEWeightProduct { - public: - LHEWeightProduct() { weightsVector_ = {}; } - LHEWeightProduct& operator=(LHEWeightProduct&& other) { - weightsVector_ = std::move(other.weightsVector_); - return *this; - } - ~LHEWeightProduct() {} - - void setNumWeightSets(int num) { weightsVector_.resize(num); } - void addWeightSet() { weightsVector_.push_back({}); } - void addWeight(double weight, int setEntry, int weightNum) { - if (weightsVector_.size() == 0 && setEntry == 0) - addWeightSet(); - if (static_cast(weightsVector_.size()) <= setEntry) - throw std::domain_error("Out of range weight"); - auto& weights = weightsVector_.at(setEntry); - if (static_cast(weights.size()) <= weightNum) { - weights.resize(weightNum+1); - } - weights[weightNum] = weight; - } - const WeightsContainer& weights() const { return weightsVector_; } - - private: - WeightsContainer weightsVector_; -}; - -#endif // GeneratorEvent_LHEInterface_LHEWeightProduct_h - diff --git a/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc b/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc deleted file mode 100644 index 78c7d858f65f6..0000000000000 --- a/SimDataFormats/GeneratorProducts/src/LHEWeightInfoProduct.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -#include "SimDataFormats/GeneratorProducts/interface/LHEWeightInfoProduct.h" - -LHEWeightInfoProduct::LHEWeightInfoProduct(edm::OwnVector& weightGroups) { - weightGroupsInfo_ = weightGroups; -} - -LHEWeightInfoProduct& LHEWeightInfoProduct::operator=(const LHEWeightInfoProduct &other) { - weightGroupsInfo_ = other.weightGroupsInfo_; - return * this; -} - -LHEWeightInfoProduct& LHEWeightInfoProduct::operator=(LHEWeightInfoProduct &&other) { - weightGroupsInfo_ = std::move(other.weightGroupsInfo_); - return *this; -} - -const edm::OwnVector& LHEWeightInfoProduct::allWeightGroupsInfo() const { - return weightGroupsInfo_; -} - -const gen::WeightGroupInfo& LHEWeightInfoProduct::containingWeightGroupInfo(int index) const { - for (const auto& weightGroup : weightGroupsInfo_) { - if (weightGroup.indexInRange(index)) - return weightGroup; - } - throw std::domain_error("Failed to find containing weight group"); -} - -const gen::WeightGroupInfo& LHEWeightInfoProduct::orderedWeightGroupInfo(int weightGroupIndex) const { - if (weightGroupIndex >= static_cast(weightGroupsInfo_.size())) - throw std::range_error("Weight index out of range!"); - return weightGroupsInfo_[weightGroupIndex]; -} - -void LHEWeightInfoProduct::addWeightGroupInfo(gen::WeightGroupInfo& info) { - weightGroupsInfo_.push_back(info); -}