File indexing completed on 2025-02-05 03:15:09
0001 #include "FWCore/Framework/interface/global/EDProducer.h"
0002 #include "FWCore/Framework/interface/Event.h"
0003 #include "FWCore/Framework/interface/Run.h"
0004 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0005 #include "DataFormats/NanoAOD/interface/FlatTable.h"
0006 #include "DataFormats/NanoAOD/interface/MergeableCounterTable.h"
0007 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0008 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0009 #include "FWCore/Utilities/interface/transform.h"
0010 #include "SimDataFormats/GeneratorProducts/interface/GenEventInfoProduct.h"
0011 #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h"
0012 #include "SimDataFormats/GeneratorProducts/interface/LHERunInfoProduct.h"
0013 #include "SimDataFormats/GeneratorProducts/interface/GenLumiInfoHeader.h"
0014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0015 #include "boost/algorithm/string.hpp"
0016
0017 #include <array>
0018 #include <memory>
0019
0020 #include <vector>
0021 #include <unordered_map>
0022 #include <iostream>
0023 #include <regex>
0024
0025 namespace {
0026
0027 struct Counter {
0028 Counter() : num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {}
0029
0030
0031 long long num;
0032 long double sumw;
0033 long double sumw2;
0034 std::vector<long double> sumPDF, sumScale, sumRwgt, sumNamed, sumPS;
0035
0036 void clear() {
0037 num = 0;
0038 sumw = 0;
0039 sumw2 = 0;
0040 sumPDF.clear();
0041 sumScale.clear();
0042 sumRwgt.clear();
0043 sumNamed.clear(), sumPS.clear();
0044 }
0045
0046
0047 void incGenOnly(double w) {
0048 num++;
0049 sumw += w;
0050 sumw2 += (w * w);
0051 }
0052
0053 void incPSOnly(double w0, const std::vector<double>& wPS) {
0054 if (!wPS.empty()) {
0055 if (sumPS.empty())
0056 sumPS.resize(wPS.size(), 0);
0057 for (unsigned int i = 0, n = wPS.size(); i < n; ++i)
0058 sumPS[i] += (w0 * wPS[i]);
0059 }
0060 }
0061
0062 void incLHE(double w0,
0063 const std::vector<double>& wScale,
0064 const std::vector<double>& wPDF,
0065 const std::vector<double>& wRwgt,
0066 const std::vector<double>& wNamed,
0067 const std::vector<double>& wPS) {
0068
0069 incGenOnly(w0);
0070
0071 if (!wScale.empty()) {
0072 if (sumScale.empty())
0073 sumScale.resize(wScale.size(), 0);
0074 for (unsigned int i = 0, n = wScale.size(); i < n; ++i)
0075 sumScale[i] += (w0 * wScale[i]);
0076 }
0077 if (!wPDF.empty()) {
0078 if (sumPDF.empty())
0079 sumPDF.resize(wPDF.size(), 0);
0080 for (unsigned int i = 0, n = wPDF.size(); i < n; ++i)
0081 sumPDF[i] += (w0 * wPDF[i]);
0082 }
0083 if (!wRwgt.empty()) {
0084 if (sumRwgt.empty())
0085 sumRwgt.resize(wRwgt.size(), 0);
0086 for (unsigned int i = 0, n = wRwgt.size(); i < n; ++i)
0087 sumRwgt[i] += (w0 * wRwgt[i]);
0088 }
0089 if (!wNamed.empty()) {
0090 if (sumNamed.empty())
0091 sumNamed.resize(wNamed.size(), 0);
0092 for (unsigned int i = 0, n = wNamed.size(); i < n; ++i)
0093 sumNamed[i] += (w0 * wNamed[i]);
0094 }
0095 incPSOnly(w0, wPS);
0096 }
0097
0098 void merge(const Counter& other) {
0099 num += other.num;
0100 sumw += other.sumw;
0101 sumw2 += other.sumw2;
0102 if (sumScale.empty() && !other.sumScale.empty())
0103 sumScale.resize(other.sumScale.size(), 0);
0104 if (sumPDF.empty() && !other.sumPDF.empty())
0105 sumPDF.resize(other.sumPDF.size(), 0);
0106 if (sumRwgt.empty() && !other.sumRwgt.empty())
0107 sumRwgt.resize(other.sumRwgt.size(), 0);
0108 if (sumNamed.empty() && !other.sumNamed.empty())
0109 sumNamed.resize(other.sumNamed.size(), 0);
0110 if (sumPS.empty() && !other.sumPS.empty())
0111 sumPS.resize(other.sumPS.size(), 0);
0112 if (!other.sumScale.empty())
0113 for (unsigned int i = 0, n = sumScale.size(); i < n; ++i)
0114 sumScale[i] += other.sumScale[i];
0115 if (!other.sumPDF.empty())
0116 for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i)
0117 sumPDF[i] += other.sumPDF[i];
0118 if (!other.sumRwgt.empty())
0119 for (unsigned int i = 0, n = sumRwgt.size(); i < n; ++i)
0120 sumRwgt[i] += other.sumRwgt[i];
0121 if (!other.sumNamed.empty())
0122 for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i)
0123 sumNamed[i] += other.sumNamed[i];
0124 if (!other.sumPS.empty())
0125 for (unsigned int i = 0, n = sumPS.size(); i < n; ++i)
0126 sumPS[i] += other.sumPS[i];
0127 }
0128 };
0129
0130 struct CounterMap {
0131 std::map<std::string, Counter> countermap;
0132 Counter* active_el = nullptr;
0133 std::string active_label = "";
0134 void merge(const CounterMap& other) {
0135 for (const auto& y : other.countermap)
0136 countermap[y.first].merge(y.second);
0137 active_el = nullptr;
0138 }
0139 void clear() {
0140 for (auto x : countermap)
0141 x.second.clear();
0142 active_el = nullptr;
0143 active_label = "";
0144 }
0145 void setLabel(std::string label) {
0146 active_el = &(countermap[label]);
0147 active_label = label;
0148 }
0149 void checkLabelSet() {
0150 if (!active_el)
0151 throw cms::Exception("LogicError", "Called CounterMap::get() before setting the active label\n");
0152 }
0153 Counter* get() {
0154 checkLabelSet();
0155 return active_el;
0156 }
0157 std::string& getLabel() {
0158 checkLabelSet();
0159 return active_label;
0160 }
0161 };
0162
0163
0164 struct DynamicWeightChoice {
0165
0166
0167 std::vector<std::string> scaleWeightIDs;
0168 std::string scaleWeightsDoc;
0169
0170 std::vector<std::string> pdfWeightIDs;
0171 std::string pdfWeightsDoc;
0172
0173 std::vector<std::string> rwgtIDs;
0174 std::string rwgtWeightDoc;
0175 };
0176
0177 constexpr std::array<unsigned int, 4> defPSWeightIDs = {{6, 7, 8, 9}};
0178 constexpr std::array<unsigned int, 4> defPSWeightIDs_alt = {{27, 5, 26, 4}};
0179
0180 struct DynamicWeightChoiceGenInfo {
0181
0182
0183 std::vector<unsigned int> scaleWeightIDs;
0184 std::string scaleWeightsDoc;
0185
0186 std::vector<unsigned int> pdfWeightIDs;
0187 std::string pdfWeightsDoc;
0188
0189 bool matchPS_alt = false;
0190 std::vector<unsigned int> psWeightIDs;
0191 unsigned int psBaselineID = 1;
0192 std::string psWeightsDoc;
0193
0194 void setMissingWeight(int idx) { psWeightIDs[idx] = (matchPS_alt) ? defPSWeightIDs_alt[idx] : defPSWeightIDs[idx]; }
0195
0196 bool empty() const { return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); }
0197 };
0198
0199 struct LumiCacheInfoHolder {
0200 CounterMap countermap;
0201 void clear() { countermap.clear(); }
0202 };
0203
0204 float stof_fortrancomp(const std::string& str) {
0205 std::string::size_type match = str.find('d');
0206 if (match != std::string::npos) {
0207 std::string pre = str.substr(0, match);
0208 std::string post = str.substr(match + 1);
0209 return std::stof(pre) * std::pow(10.0f, std::stof(post));
0210 } else {
0211 return std::stof(str);
0212 }
0213 }
0214
0215 struct ScaleVarWeight {
0216 std::string wid, label;
0217 std::pair<float, float> scales;
0218 ScaleVarWeight(const std::string& id, const std::string& text, const std::string& muR, const std::string& muF)
0219 : wid(id), label(text), scales(stof_fortrancomp(muR), stof_fortrancomp(muF)) {}
0220 bool operator<(const ScaleVarWeight& other) {
0221 return (scales == other.scales ? wid < other.wid : scales < other.scales);
0222 }
0223 };
0224 struct PDFSetWeights {
0225 std::vector<std::string> wids;
0226 std::pair<unsigned int, unsigned int> lhaIDs;
0227 PDFSetWeights(const std::string& wid, unsigned int lhaID) : wids(1, wid), lhaIDs(lhaID, lhaID) {}
0228 bool operator<(const PDFSetWeights& other) const { return lhaIDs < other.lhaIDs; }
0229 void add(const std::string& wid, unsigned int lhaID) {
0230 wids.push_back(wid);
0231 lhaIDs.second = lhaID;
0232 }
0233 bool maybe_add(const std::string& wid, unsigned int lhaID) {
0234 if (lhaID == lhaIDs.second + 1) {
0235 lhaIDs.second++;
0236 wids.push_back(wid);
0237 return true;
0238 } else {
0239 return false;
0240 }
0241 }
0242 };
0243 }
0244
0245 class GenWeightsTableProducer : public edm::global::EDProducer<edm::StreamCache<LumiCacheInfoHolder>,
0246 edm::RunCache<DynamicWeightChoice>,
0247 edm::LuminosityBlockCache<DynamicWeightChoiceGenInfo>,
0248 edm::RunSummaryCache<CounterMap>,
0249 edm::EndRunProducer> {
0250 public:
0251 GenWeightsTableProducer(edm::ParameterSet const& params)
0252 : genTag_(consumes<GenEventInfoProduct>(params.getParameter<edm::InputTag>("genEvent"))),
0253 lheLabel_(params.getParameter<std::vector<edm::InputTag>>("lheInfo")),
0254 lheTag_(edm::vector_transform(lheLabel_,
0255 [this](const edm::InputTag& tag) { return mayConsume<LHEEventProduct>(tag); })),
0256 lheRunTag_(edm::vector_transform(
0257 lheLabel_, [this](const edm::InputTag& tag) { return mayConsume<LHERunInfoProduct, edm::InRun>(tag); })),
0258 genLumiInfoHeadTag_(
0259 mayConsume<GenLumiInfoHeader, edm::InLumi>(params.getParameter<edm::InputTag>("genLumiInfoHeader"))),
0260 namedWeightIDs_(params.getParameter<std::vector<std::string>>("namedWeightIDs")),
0261 namedWeightLabels_(params.getParameter<std::vector<std::string>>("namedWeightLabels")),
0262 lheWeightPrecision_(params.getParameter<int32_t>("lheWeightPrecision")),
0263 maxPdfWeights_(params.getParameter<uint32_t>("maxPdfWeights")),
0264 keepAllPSWeights_(params.getParameter<bool>("keepAllPSWeights")),
0265 allowedNumScaleWeights_(params.getParameter<std::vector<uint32_t>>("allowedNumScaleWeights")),
0266 debug_(params.getUntrackedParameter<bool>("debug", false)),
0267 debugRun_(debug_.load()),
0268 hasIssuedWarning_(false),
0269 psWeightWarning_(false) {
0270 produces<nanoaod::FlatTable>();
0271 produces<std::string>("genModel");
0272 produces<nanoaod::FlatTable>("LHEScale");
0273 produces<nanoaod::FlatTable>("LHEPdf");
0274 produces<nanoaod::FlatTable>("LHEReweighting");
0275 produces<nanoaod::FlatTable>("LHENamed");
0276 produces<nanoaod::FlatTable>("PS");
0277 produces<nanoaod::MergeableCounterTable, edm::Transition::EndRun>();
0278 if (namedWeightIDs_.size() != namedWeightLabels_.size()) {
0279 throw cms::Exception("Configuration", "Size mismatch between namedWeightIDs & namedWeightLabels");
0280 }
0281 for (const edm::ParameterSet& pdfps : params.getParameter<std::vector<edm::ParameterSet>>("preferredPDFs")) {
0282 const std::string& name = pdfps.getParameter<std::string>("name");
0283 uint32_t lhaid = pdfps.getParameter<uint32_t>("lhaid");
0284 preferredPDFLHAIDs_.push_back(lhaid);
0285 lhaNameToID_[name] = lhaid;
0286 lhaNameToID_[name + ".LHgrid"] = lhaid;
0287 }
0288 }
0289
0290 ~GenWeightsTableProducer() override {}
0291
0292 void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override {
0293
0294 Counter* counter = streamCache(id)->countermap.get();
0295
0296
0297 edm::Handle<GenEventInfoProduct> genInfo;
0298 iEvent.getByToken(genTag_, genInfo);
0299 double weight = genInfo->weight();
0300
0301
0302 auto out = std::make_unique<nanoaod::FlatTable>(1, "genWeight", true);
0303 out->setDoc("generator weight");
0304 out->addColumnValue<float>("", weight, "generator weight");
0305 iEvent.put(std::move(out));
0306
0307 std::string model_label = streamCache(id)->countermap.getLabel();
0308 auto outM = std::make_unique<std::string>((!model_label.empty()) ? std::string("GenModel_") + model_label : "");
0309 iEvent.put(std::move(outM), "genModel");
0310 bool getLHEweightsFromGenInfo = !model_label.empty();
0311
0312
0313 std::unique_ptr<nanoaod::FlatTable> lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab;
0314 std::unique_ptr<nanoaod::FlatTable> genPSTab;
0315
0316 edm::Handle<LHEEventProduct> lheInfo;
0317 for (const auto& lheTag : lheTag_) {
0318 iEvent.getByToken(lheTag, lheInfo);
0319 if (lheInfo.isValid()) {
0320 break;
0321 }
0322 }
0323
0324 const auto genWeightChoice = luminosityBlockCache(iEvent.getLuminosityBlock().index());
0325 if (lheInfo.isValid()) {
0326 if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true))
0327 edm::LogWarning("LHETablesProducer")
0328 << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n";
0329
0330 const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index());
0331
0332 fillLHEWeightTables(counter,
0333 weightChoice,
0334 genWeightChoice,
0335 weight,
0336 *lheInfo,
0337 *genInfo,
0338 lheScaleTab,
0339 lhePdfTab,
0340 lheRwgtTab,
0341 lheNamedTab,
0342 genPSTab);
0343 } else if (getLHEweightsFromGenInfo) {
0344 fillLHEPdfWeightTablesFromGenInfo(
0345 counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab);
0346 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
0347
0348
0349 } else {
0350
0351 fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab);
0352
0353 lheScaleTab = std::make_unique<nanoaod::FlatTable>(1, "LHEScaleWeights", true);
0354 lhePdfTab = std::make_unique<nanoaod::FlatTable>(1, "LHEPdfWeights", true);
0355 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
0356 lheNamedTab = std::make_unique<nanoaod::FlatTable>(1, "LHENamedWeights", true);
0357 if (!hasIssuedWarning_.exchange(true)) {
0358 edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n";
0359 }
0360 }
0361
0362 iEvent.put(std::move(lheScaleTab), "LHEScale");
0363 iEvent.put(std::move(lhePdfTab), "LHEPdf");
0364 iEvent.put(std::move(lheRwgtTab), "LHEReweighting");
0365 iEvent.put(std::move(lheNamedTab), "LHENamed");
0366 iEvent.put(std::move(genPSTab), "PS");
0367 }
0368
0369 void fillLHEWeightTables(Counter* counter,
0370 const DynamicWeightChoice* weightChoice,
0371 const DynamicWeightChoiceGenInfo* genWeightChoice,
0372 double genWeight,
0373 const LHEEventProduct& lheProd,
0374 const GenEventInfoProduct& genProd,
0375 std::unique_ptr<nanoaod::FlatTable>& outScale,
0376 std::unique_ptr<nanoaod::FlatTable>& outPdf,
0377 std::unique_ptr<nanoaod::FlatTable>& outRwgt,
0378 std::unique_ptr<nanoaod::FlatTable>& outNamed,
0379 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0380 bool lheDebug = debug_.exchange(
0381 false);
0382
0383 const std::vector<std::string>& scaleWeightIDs = weightChoice->scaleWeightIDs;
0384 const std::vector<std::string>& pdfWeightIDs = weightChoice->pdfWeightIDs;
0385 const std::vector<std::string>& rwgtWeightIDs = weightChoice->rwgtIDs;
0386
0387 double w0 = lheProd.originalXWGTUP();
0388
0389 std::vector<double> wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1),
0390 wNamed(namedWeightIDs_.size(), 1);
0391 for (auto& weight : lheProd.weights()) {
0392 if (lheDebug)
0393 printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str());
0394
0395 auto mScale = std::find(scaleWeightIDs.begin(), scaleWeightIDs.end(), weight.id);
0396 if (mScale != scaleWeightIDs.end())
0397 wScale[mScale - scaleWeightIDs.begin()] = weight.wgt / w0;
0398
0399 auto mPDF = std::find(pdfWeightIDs.begin(), pdfWeightIDs.end(), weight.id);
0400 if (mPDF != pdfWeightIDs.end())
0401 wPDF[mPDF - pdfWeightIDs.begin()] = weight.wgt / w0;
0402
0403 auto mRwgt = std::find(rwgtWeightIDs.begin(), rwgtWeightIDs.end(), weight.id);
0404 if (mRwgt != rwgtWeightIDs.end())
0405 wRwgt[mRwgt - rwgtWeightIDs.begin()] = weight.wgt / w0;
0406
0407 auto mNamed = std::find(namedWeightIDs_.begin(), namedWeightIDs_.end(), weight.id);
0408 if (mNamed != namedWeightIDs_.end())
0409 wNamed[mNamed - namedWeightIDs_.begin()] = weight.wgt / w0;
0410 }
0411
0412 std::vector<double> wPS;
0413 std::string psWeightDocStr;
0414 setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
0415
0416 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0417 outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
0418
0419 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
0420 outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
0421
0422 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
0423 outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
0424
0425 outRwgt = std::make_unique<nanoaod::FlatTable>(wRwgt.size(), "LHEReweightingWeight", false);
0426 outRwgt->addColumn<float>("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_);
0427
0428 outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
0429 outNamed->addColumnValue<float>("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file");
0430 for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) {
0431 outNamed->addColumnValue<float>(namedWeightLabels_[i],
0432 wNamed[i],
0433 "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal",
0434 lheWeightPrecision_);
0435 }
0436
0437 counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS);
0438 }
0439
0440 void fillLHEPdfWeightTablesFromGenInfo(Counter* counter,
0441 const DynamicWeightChoiceGenInfo* weightChoice,
0442 double genWeight,
0443 const GenEventInfoProduct& genProd,
0444 std::unique_ptr<nanoaod::FlatTable>& outScale,
0445 std::unique_ptr<nanoaod::FlatTable>& outPdf,
0446 std::unique_ptr<nanoaod::FlatTable>& outNamed,
0447 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0448 const std::vector<unsigned int>& scaleWeightIDs = weightChoice->scaleWeightIDs;
0449 const std::vector<unsigned int>& pdfWeightIDs = weightChoice->pdfWeightIDs;
0450
0451 auto weights = genProd.weights();
0452 double w0 = (weights.size() > 1) ? weights.at(1) : 1.;
0453 double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.;
0454
0455 std::vector<double> wScale, wPDF, wPS;
0456 for (auto id : scaleWeightIDs)
0457 wScale.push_back(weights.at(id) / w0);
0458 for (auto id : pdfWeightIDs) {
0459 wPDF.push_back(weights.at(id) / w0);
0460 }
0461
0462 std::string psWeightsDocStr;
0463 setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr);
0464
0465 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
0466 outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
0467
0468 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
0469 outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
0470
0471 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0472 outPS->addColumn<float>("", wPS, psWeightsDocStr, lheWeightPrecision_);
0473
0474 outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
0475 outNamed->addColumnValue<float>("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file");
0476
0477
0478
0479
0480 counter->incLHE(genWeight, wScale, wPDF, std::vector<double>(), std::vector<double>(), wPS);
0481 }
0482
0483 void fillOnlyPSWeightTable(Counter* counter,
0484 const DynamicWeightChoiceGenInfo* genWeightChoice,
0485 double genWeight,
0486 const GenEventInfoProduct& genProd,
0487 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0488 std::vector<double> wPS;
0489 std::string psWeightDocStr;
0490 setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
0491 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0492 outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
0493
0494 counter->incGenOnly(genWeight);
0495 counter->incPSOnly(genWeight, wPS);
0496 }
0497
0498 void setPSWeightInfo(const std::vector<double>& genWeights,
0499 const DynamicWeightChoiceGenInfo* genWeightChoice,
0500 std::vector<double>& wPS,
0501 std::string& psWeightDocStr) const {
0502 wPS.clear();
0503
0504
0505 bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46);
0506 if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) {
0507 psWeightDocStr = genWeightChoice->psWeightsDoc;
0508 double psNom = genWeights.at(genWeightChoice->psBaselineID);
0509 for (auto wgtidx : genWeightChoice->psWeightIDs) {
0510 wPS.push_back(genWeights.at(wgtidx) / psNom);
0511 }
0512 } else {
0513 int vectorSize =
0514 keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1);
0515
0516 if (vectorSize > 1) {
0517 double nominal = genWeights.at(1);
0518 if (keepAllPSWeights_) {
0519 for (int i = 0; i < vectorSize; i++) {
0520 wPS.push_back(genWeights.at(i + 2) / nominal);
0521 }
0522 psWeightDocStr = ((int)genWeightChoice->psWeightIDs.size() == vectorSize)
0523 ? genWeightChoice->psWeightsDoc
0524 : "All PS weights (w_var / w_nominal)";
0525 } else {
0526 if (!psWeightWarning_.exchange(true))
0527 edm::LogWarning("LHETablesProducer")
0528 << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n"
0529 << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt "
0530 "order )";
0531 for (std::size_t i = 6; i < 10; i++) {
0532 wPS.push_back(genWeights.at(i) / nominal);
0533 }
0534 psWeightDocStr =
0535 "PS weights (w_var / w_nominal); default (maybe incorrect) order is: "
0536 "[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;";
0537 }
0538 } else {
0539 wPS.push_back(1.0);
0540 psWeightDocStr = "dummy PS weight (1.0) ";
0541 }
0542 }
0543 }
0544
0545
0546 std::shared_ptr<DynamicWeightChoice> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override {
0547 edm::Handle<LHERunInfoProduct> lheInfo;
0548
0549 bool lheDebug = debugRun_.exchange(
0550 false);
0551 auto weightChoice = std::make_shared<DynamicWeightChoice>();
0552
0553
0554
0555 for (const auto& lheLabel : lheLabel_) {
0556 iRun.getByLabel(lheLabel, lheInfo);
0557 if (lheInfo.isValid()) {
0558 break;
0559 }
0560 }
0561 if (lheInfo.isValid()) {
0562 std::vector<ScaleVarWeight> scaleVariationIDs;
0563 std::vector<PDFSetWeights> pdfSetWeightIDs;
0564 std::vector<std::string> lheReweighingIDs;
0565 bool preScaleVariationGroup = true;
0566
0567 std::regex weightgroupmg26x("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s+combine=\"(.*)\"\\s*>");
0568 std::regex weightgroup("<weightgroup\\s+combine=\"(.*)\"\\s+(?:name|type)=\"(.*)\"\\s*>");
0569 std::regex weightgroupRwgt("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s*>");
0570 std::regex endweightgroup("</weightgroup>");
0571 std::regex scalewmg26x(
0572 "<weight\\s+(?:.*\\s+)?id=\"(\\d+)\"\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:[mM][uU][rR]|renscfact)=\"("
0573 "\\S+)\"\\s+(?:[mM][uU][Ff]|facscfact)=\"(\\S+)\")(\\s+.*)?</weight>");
0574 std::regex scalewmg26xNew(
0575 "<weight\\s*((?:[mM][uU][fF]|facscfact)=\"(\\S+)\"\\s+(?:[mM][uU][Rr]|renscfact)=\"(\\S+)\").+id=\"(\\d+)\"(."
0576 "*)?</weight>");
0577
0578
0579 std::regex scalew(
0580 "<weight\\s+(?:.*\\s+)?id=\"(\\d+|\\d+-NNLOPS)\">\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)"
0581 "=(\\S+)\\s+(?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)</weight>");
0582 std::regex pdfw(
0583 "<weight\\s+id=\"(\\d+)\">\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?</weight>");
0584 std::regex pdfwOld("<weight\\s+(?:.*\\s+)?id=\"(\\d+)\">\\s*Member \\s*(\\d+)\\s*(?:.*)</weight>");
0585 std::regex pdfwmg26x(
0586 "<weight\\s+id=\"(\\d+)\"\\s*MUR=\"(?:\\S+)\"\\s*MUF=\"(?:\\S+)\"\\s*(?:PDF "
0587 "set|lhapdf|PDF|pdfset)\\s*=\\s*\"(\\d+)\"\\s*>\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
0588 "weight>");
0589
0590
0591
0592 std::regex pdfwmg26xNew(
0593 "<weight\\s+MUF=\"(?:\\S+)\"\\s*MUR=\"(?:\\S+)\"\\s*PDF=\"(?:\\S+)\"\\s*id=\"(\\S+)\"\\s*>"
0594 "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
0595 "weight>");
0596
0597 std::regex mgVerRegex(R"(VERSION\s+(\d+)\.(\d+)\.(\d+))");
0598 bool isMGVer2x = false;
0599
0600 std::regex rwgt("<weight\\s+id=\"(.+)\">(.+)?(</weight>)?");
0601 std::smatch groups;
0602 for (auto iter = lheInfo->headers_begin(), end = lheInfo->headers_end(); iter != end; ++iter) {
0603 if (iter->tag() == "MG5ProcCard") {
0604 for (const auto& line : iter->lines()) {
0605 if (std::regex_search(line, groups, mgVerRegex)) {
0606 isMGVer2x = (groups[1].str() == "2");
0607 break;
0608 }
0609 }
0610 }
0611 if (iter->tag() != "initrwgt") {
0612 if (lheDebug)
0613 std::cout << "Skipping LHE header with tag" << iter->tag() << std::endl;
0614 continue;
0615 }
0616 if (lheDebug)
0617 std::cout << "Found LHE header with tag" << iter->tag() << std::endl;
0618 std::vector<std::string> lines = iter->lines();
0619 bool missed_weightgroup =
0620 false;
0621 bool ismg26x = false;
0622 bool ismg26xNew = false;
0623 for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines;
0624 ++iLine) {
0625 boost::replace_all(lines[iLine], "<", "<");
0626 boost::replace_all(lines[iLine], ">", ">");
0627 if (std::regex_search(lines[iLine], groups, weightgroupmg26x)) {
0628 ismg26x = true;
0629 } else if (std::regex_search(lines[iLine], groups, scalewmg26xNew) ||
0630 std::regex_search(lines[iLine], groups, pdfwmg26xNew)) {
0631 ismg26xNew = true;
0632 }
0633 }
0634 for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; ++iLine) {
0635 if (lheDebug)
0636 std::cout << lines[iLine];
0637 auto foundWeightGroup = std::regex_search(lines[iLine], groups, ismg26x ? weightgroupmg26x : weightgroup);
0638 if (foundWeightGroup || preScaleVariationGroup) {
0639 std::string groupname;
0640 if (foundWeightGroup) {
0641 groupname = ismg26x ? groups.str(1) : groups.str(2);
0642 } else {
0643
0644 --iLine;
0645 }
0646 if (lheDebug)
0647 std::cout << ">>> Looks like the beginning of a weight group for '" << groupname << "'" << std::endl;
0648 if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation" ||
0649 preScaleVariationGroup) {
0650 if (lheDebug && groupname.find("scale_variation") != 0 && groupname != "Central scale variation")
0651 std::cout << ">>> First weight is not scale variation, but assuming is the Central Weight" << std::endl;
0652 else if (lheDebug)
0653 std::cout << ">>> Looks like scale variation for theory uncertainties" << std::endl;
0654 if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation") {
0655 preScaleVariationGroup = false;
0656 }
0657 for (++iLine; iLine < nLines; ++iLine) {
0658 if (lheDebug) {
0659 std::cout << " " << lines[iLine];
0660 }
0661 if (std::regex_search(
0662 lines[iLine], groups, ismg26x ? scalewmg26x : (ismg26xNew ? scalewmg26xNew : scalew))) {
0663 if (lheDebug)
0664 std::cout << " >>> Scale weight " << groups[1].str() << " for " << groups[3].str() << " , "
0665 << groups[4].str() << " , " << groups[5].str() << std::endl;
0666 if (ismg26xNew) {
0667 scaleVariationIDs.emplace_back(groups.str(4), groups.str(1), groups.str(3), groups.str(2));
0668 } else {
0669 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
0670 }
0671 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0672 if (lheDebug)
0673 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0674 if (!missed_weightgroup) {
0675 break;
0676 } else
0677 missed_weightgroup = false;
0678 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0679 if (lheDebug)
0680 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0681 "of the group."
0682 << std::endl;
0683 if (ismg26x || ismg26xNew)
0684 missed_weightgroup = true;
0685 --iLine;
0686 break;
0687 }
0688 }
0689 } else if (groupname == "PDF_variation" || groupname.find("PDF_variation ") == 0) {
0690 if (lheDebug)
0691 std::cout << ">>> Looks like a new-style block of PDF weights for one or more pdfs" << std::endl;
0692 for (++iLine; iLine < nLines; ++iLine) {
0693 if (lheDebug)
0694 std::cout << " " << lines[iLine];
0695 if (std::regex_search(lines[iLine], groups, pdfw)) {
0696 unsigned int lhaID = std::stoi(groups.str(2));
0697 if (lheDebug)
0698 std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
0699 << std::endl;
0700 if (pdfSetWeightIDs.empty() || !pdfSetWeightIDs.back().maybe_add(groups.str(1), lhaID)) {
0701 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0702 }
0703 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0704 if (lheDebug)
0705 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0706 if (!missed_weightgroup) {
0707 break;
0708 } else
0709 missed_weightgroup = false;
0710 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0711 if (lheDebug)
0712 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0713 "of the group."
0714 << std::endl;
0715 if (ismg26x || ismg26xNew)
0716 missed_weightgroup = true;
0717 --iLine;
0718 break;
0719 }
0720 }
0721 } else if (groupname == "PDF_variation1" || groupname == "PDF_variation2") {
0722 if (lheDebug)
0723 std::cout << ">>> Looks like a new-style block of PDF weights for multiple pdfs" << std::endl;
0724 unsigned int lastid = 0;
0725 for (++iLine; iLine < nLines; ++iLine) {
0726 if (lheDebug)
0727 std::cout << " " << lines[iLine];
0728 if (std::regex_search(lines[iLine], groups, pdfw)) {
0729 unsigned int id = std::stoi(groups.str(1));
0730 unsigned int lhaID = std::stoi(groups.str(2));
0731 if (lheDebug)
0732 std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
0733 << std::endl;
0734 if (id != (lastid + 1) || pdfSetWeightIDs.empty()) {
0735 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0736 } else {
0737 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
0738 }
0739 lastid = id;
0740 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0741 if (lheDebug)
0742 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0743 if (!missed_weightgroup) {
0744 break;
0745 } else
0746 missed_weightgroup = false;
0747 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0748 if (lheDebug)
0749 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0750 "of the group."
0751 << std::endl;
0752 if (ismg26x || ismg26xNew)
0753 missed_weightgroup = true;
0754 --iLine;
0755 break;
0756 }
0757 }
0758 } else if (lhaNameToID_.find(groupname) != lhaNameToID_.end()) {
0759 if (lheDebug)
0760 std::cout << ">>> Looks like an old-style PDF weight for an individual pdf" << std::endl;
0761 unsigned int firstLhaID = lhaNameToID_.find(groupname)->second;
0762 bool first = true;
0763 for (++iLine; iLine < nLines; ++iLine) {
0764 if (lheDebug)
0765 std::cout << " " << lines[iLine];
0766 if (std::regex_search(
0767 lines[iLine], groups, ismg26x ? pdfwmg26x : (ismg26xNew ? pdfwmg26xNew : pdfwOld))) {
0768 unsigned int member = 0;
0769 if (!ismg26x && !ismg26xNew) {
0770 member = std::stoi(groups.str(2));
0771 } else if (ismg26xNew) {
0772 if (!groups.str(3).empty()) {
0773 member = std::stoi(groups.str(3));
0774 }
0775 } else {
0776 if (!groups.str(4).empty()) {
0777 member = std::stoi(groups.str(4));
0778 }
0779 }
0780 unsigned int lhaID = member + firstLhaID;
0781 if (lheDebug)
0782 std::cout << " >>> PDF weight " << groups.str(1) << " for " << member << " = " << lhaID
0783 << std::endl;
0784
0785 if (first) {
0786 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0787 first = false;
0788 } else {
0789 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
0790 }
0791 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0792 if (lheDebug)
0793 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0794 if (!missed_weightgroup) {
0795 break;
0796 } else
0797 missed_weightgroup = false;
0798 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0799 if (lheDebug)
0800 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0801 "of the group."
0802 << std::endl;
0803 if (ismg26x || ismg26xNew)
0804 missed_weightgroup = true;
0805 --iLine;
0806 break;
0807 }
0808 }
0809 } else if (groupname == "mass_variation" || groupname == "sthw2_variation" ||
0810 groupname == "width_variation") {
0811 if (lheDebug)
0812 std::cout << ">>> Looks like an EW parameter weight" << std::endl;
0813 for (++iLine; iLine < nLines; ++iLine) {
0814 if (lheDebug)
0815 std::cout << " " << lines[iLine];
0816 if (std::regex_search(lines[iLine], groups, rwgt)) {
0817 std::string rwgtID = groups.str(1);
0818 if (lheDebug)
0819 std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
0820 if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
0821
0822 lheReweighingIDs.emplace_back(rwgtID);
0823 }
0824 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0825 if (lheDebug)
0826 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0827 }
0828 }
0829 } else {
0830 for (++iLine; iLine < nLines; ++iLine) {
0831 if (lheDebug)
0832 std::cout << " " << lines[iLine];
0833 if (std::regex_search(lines[iLine], groups, endweightgroup)) {
0834 if (lheDebug)
0835 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0836 if (!missed_weightgroup) {
0837 break;
0838 } else
0839 missed_weightgroup = false;
0840 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0841 if (lheDebug)
0842 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0843 "of the group."
0844 << std::endl;
0845 if (ismg26x || ismg26xNew)
0846 missed_weightgroup = true;
0847 --iLine;
0848 break;
0849 }
0850 }
0851 }
0852 } else if (std::regex_search(lines[iLine], groups, weightgroupRwgt)) {
0853 std::string groupname = groups.str(1);
0854 if (groupname.find("mg_reweighting") != std::string::npos) {
0855 if (lheDebug)
0856 std::cout << ">>> Looks like a LHE weights for reweighting" << std::endl;
0857 for (++iLine; iLine < nLines; ++iLine) {
0858 if (lheDebug)
0859 std::cout << " " << lines[iLine];
0860 if (std::regex_search(lines[iLine], groups, rwgt)) {
0861 std::string rwgtID = groups.str(1);
0862 if (lheDebug)
0863 std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
0864 if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
0865
0866 lheReweighingIDs.emplace_back(rwgtID);
0867 }
0868 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0869 if (lheDebug)
0870 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0871 if (!missed_weightgroup) {
0872 break;
0873 } else
0874 missed_weightgroup = false;
0875 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0876 if (lheDebug)
0877 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0878 "of the group."
0879 << std::endl;
0880 if (ismg26x)
0881 missed_weightgroup = true;
0882 --iLine;
0883 break;
0884 }
0885 }
0886 }
0887 }
0888 }
0889
0890
0891
0892 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
0893 if (lheDebug)
0894 std::cout << "Found " << scaleVariationIDs.size() << " scale variations: " << std::endl;
0895 std::stringstream scaleDoc;
0896 scaleDoc << "LHE scale variation weights (w_var / w_nominal); ";
0897 for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
0898 const auto& sw = scaleVariationIDs[isw];
0899 if (isw)
0900 scaleDoc << "; ";
0901 scaleDoc << "[" << isw << "] is " << sw.label;
0902 weightChoice->scaleWeightIDs.push_back(sw.wid);
0903 if (lheDebug)
0904 printf(" id %s: scales ren = % .2f fact = % .2f text = %s\n",
0905 sw.wid.c_str(),
0906 sw.scales.first,
0907 sw.scales.second,
0908 sw.label.c_str());
0909 }
0910 if (!scaleVariationIDs.empty())
0911 weightChoice->scaleWeightsDoc = scaleDoc.str();
0912
0913
0914 if (lheDebug) {
0915 std::cout << "Found " << pdfSetWeightIDs.size() << " PDF set errors: " << std::endl;
0916 for (const auto& pw : pdfSetWeightIDs)
0917 printf("lhaIDs %6d - %6d (%3lu weights: %s, ... )\n",
0918 pw.lhaIDs.first,
0919 pw.lhaIDs.second,
0920 pw.wids.size(),
0921 pw.wids.front().c_str());
0922 }
0923
0924
0925 if (lheDebug) {
0926 std::cout << "Found " << lheReweighingIDs.size() << " reweighting weights" << std::endl;
0927 }
0928 std::copy(lheReweighingIDs.begin(), lheReweighingIDs.end(), std::back_inserter(weightChoice->rwgtIDs));
0929
0930 std::stringstream pdfDoc;
0931 pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA IDs ";
0932 bool found = false;
0933 for (const auto& pw : pdfSetWeightIDs) {
0934 for (uint32_t lhaid : preferredPDFLHAIDs_) {
0935 if (pw.lhaIDs.first != lhaid && pw.lhaIDs.first != (lhaid + 1))
0936 continue;
0937 if (pw.wids.size() == 1)
0938 continue;
0939 pdfDoc << pw.lhaIDs.first << " - " << pw.lhaIDs.second;
0940 weightChoice->pdfWeightIDs = pw.wids;
0941 if (maxPdfWeights_ < pw.wids.size()) {
0942 weightChoice->pdfWeightIDs.resize(maxPdfWeights_);
0943 pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas";
0944 }
0945 weightChoice->pdfWeightsDoc = pdfDoc.str();
0946 found = true;
0947 break;
0948 }
0949 if (found)
0950 break;
0951 }
0952 }
0953
0954 if (isMGVer2x && !allowedNumScaleWeights_.empty()) {
0955 auto it = std::find(allowedNumScaleWeights_.begin(), allowedNumScaleWeights_.end(), scaleVariationIDs.size());
0956 if (it == allowedNumScaleWeights_.end()) {
0957 throw cms::Exception("LogicError")
0958 << "Number of scale variations found (" << scaleVariationIDs.size() << ") is invalid.";
0959 }
0960 }
0961 }
0962
0963 return weightChoice;
0964 }
0965
0966
0967 std::unique_ptr<LumiCacheInfoHolder> beginStream(edm::StreamID) const override {
0968 return std::make_unique<LumiCacheInfoHolder>();
0969 }
0970
0971 void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override {
0972 streamCache(id)->clear();
0973 }
0974
0975 std::shared_ptr<DynamicWeightChoiceGenInfo> globalBeginLuminosityBlock(edm::LuminosityBlock const& lumiBlock,
0976 edm::EventSetup const&) const override {
0977 auto dynamicWeightChoiceGenInfo = std::make_shared<DynamicWeightChoiceGenInfo>();
0978
0979 edm::Handle<GenLumiInfoHeader> genLumiInfoHead;
0980 lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead);
0981 if (!genLumiInfoHead.isValid())
0982 edm::LogWarning("LHETablesProducer")
0983 << "No GenLumiInfoHeader product found, will not fill generator model string.\n";
0984
0985 if (genLumiInfoHead.isValid()) {
0986 auto weightChoice = dynamicWeightChoiceGenInfo.get();
0987
0988 std::vector<ScaleVarWeight> scaleVariationIDs;
0989 std::vector<PDFSetWeights> pdfSetWeightIDs;
0990 weightChoice->psWeightIDs.clear();
0991
0992 std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)");
0993 std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)");
0994 std::regex mainPSw("sr(Def|:murfac=|\\.murfac=)(Hi|Lo|_dn|_up|0\\.5|2\\.0)");
0995 std::smatch groups;
0996 auto weightNames = genLumiInfoHead->weightNames();
0997 std::unordered_map<std::string, uint32_t> knownPDFSetsFromGenInfo_;
0998 unsigned int weightIter = 0;
0999 for (const auto& line : weightNames) {
1000 if (std::regex_search(line, groups, scalew)) {
1001 auto id = groups.str(1);
1002 auto group = groups.str(2);
1003 auto mur = groups.str(3);
1004 auto muf = groups.str(4);
1005 if (group.find("Central scale variation") != std::string::npos)
1006 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
1007 } else if (std::regex_search(line, groups, pdfw)) {
1008 auto id = groups.str(1);
1009 auto group = groups.str(2);
1010 auto memberid = groups.str(3);
1011 auto pdfset = groups.str(4);
1012 if (group.find(pdfset) != std::string::npos) {
1013 if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) {
1014 knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str());
1015 pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str()));
1016 } else
1017 pdfSetWeightIDs.back().add(id, std::atoi(id.c_str()));
1018 }
1019 } else if (line == "Baseline") {
1020 weightChoice->psBaselineID = weightIter;
1021 } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) {
1022 weightChoice->matchPS_alt = line.find("sr:") != std::string::npos ||
1023 line.find("sr.") != std::string::npos;
1024 if (keepAllPSWeights_) {
1025 weightChoice->psWeightIDs.push_back(weightIter);
1026 } else if (std::regex_search(line, groups, mainPSw)) {
1027 if (weightChoice->psWeightIDs.empty())
1028 weightChoice->psWeightIDs = std::vector<unsigned int>(4, -1);
1029 int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0;
1030 psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2;
1031 weightChoice->psWeightIDs[psIdx] = weightIter;
1032 }
1033 }
1034 weightIter++;
1035 }
1036 if (keepAllPSWeights_) {
1037 weightChoice->psWeightsDoc = "All PS weights (w_var / w_nominal) ";
1038 } else if (weightChoice->psWeightIDs.size() == 4) {
1039 weightChoice->psWeightsDoc = "PS weights (w_var / w_nominal) ";
1040 for (int i = 0; i < 4; i++) {
1041 if (static_cast<int>(weightChoice->psWeightIDs[i]) == -1)
1042 weightChoice->setMissingWeight(i);
1043 }
1044 } else {
1045 weightChoice->psWeightsDoc = "dummy PS weight (1.0) ";
1046 }
1047 for (unsigned i = 0; i < weightChoice->psWeightIDs.size(); ++i) {
1048 weightChoice->psWeightsDoc +=
1049 "[" + std::to_string(i) + "] " + weightNames.at(weightChoice->psWeightIDs.at(i)) + "; ";
1050 }
1051
1052 weightChoice->scaleWeightIDs.clear();
1053 weightChoice->pdfWeightIDs.clear();
1054
1055 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
1056 std::stringstream scaleDoc;
1057 scaleDoc << "LHE scale variation weights (w_var / w_nominal); ";
1058 for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
1059 const auto& sw = scaleVariationIDs[isw];
1060 if (isw)
1061 scaleDoc << "; ";
1062 scaleDoc << "[" << isw << "] is " << sw.label;
1063 weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str()));
1064 }
1065 if (!scaleVariationIDs.empty())
1066 weightChoice->scaleWeightsDoc = scaleDoc.str();
1067 std::stringstream pdfDoc;
1068 pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA names ";
1069 bool found = false;
1070 for (const auto& pw : pdfSetWeightIDs) {
1071 if (pw.wids.size() == 1)
1072 continue;
1073 for (const auto& wantedpdf : lhaNameToID_) {
1074 auto pdfname = wantedpdf.first;
1075 if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end())
1076 continue;
1077 uint32_t lhaid = knownPDFSetsFromGenInfo_.at(pdfname);
1078 if (pw.lhaIDs.first != lhaid)
1079 continue;
1080 pdfDoc << pdfname;
1081 for (const auto& x : pw.wids)
1082 weightChoice->pdfWeightIDs.push_back(std::atoi(x.c_str()));
1083 if (maxPdfWeights_ < pw.wids.size()) {
1084 weightChoice->pdfWeightIDs.resize(maxPdfWeights_);
1085 pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas";
1086 }
1087 weightChoice->pdfWeightsDoc = pdfDoc.str();
1088 found = true;
1089 break;
1090 }
1091 if (found)
1092 break;
1093 }
1094 }
1095 return dynamicWeightChoiceGenInfo;
1096 }
1097
1098 void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {}
1099
1100 void streamBeginLuminosityBlock(edm::StreamID id,
1101 edm::LuminosityBlock const& lumiBlock,
1102 edm::EventSetup const&) const override {
1103 auto counterMap = &(streamCache(id)->countermap);
1104 edm::Handle<GenLumiInfoHeader> genLumiInfoHead;
1105 lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead);
1106
1107 std::string label;
1108 if (genLumiInfoHead.isValid()) {
1109 label = genLumiInfoHead->configDescription();
1110 boost::replace_all(label, "-", "_");
1111 boost::replace_all(label, "/", "_");
1112 }
1113 counterMap->setLabel(label);
1114 }
1115
1116 std::shared_ptr<CounterMap> globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override {
1117 return std::make_shared<CounterMap>();
1118 }
1119
1120 void streamEndRunSummary(edm::StreamID id,
1121 edm::Run const&,
1122 edm::EventSetup const&,
1123 CounterMap* runCounterMap) const override {
1124 runCounterMap->merge(streamCache(id)->countermap);
1125 }
1126
1127 void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {}
1128
1129 void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const override {
1130 auto out = std::make_unique<nanoaod::MergeableCounterTable>();
1131
1132 for (const auto& x : runCounterMap->countermap) {
1133 auto runCounter = &(x.second);
1134 std::string label = (!x.first.empty()) ? (std::string("_") + x.first) : "";
1135 std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : "";
1136
1137 out->addInt("genEventCount" + label, "event count" + doclabel, runCounter->num);
1138 out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter->sumw);
1139 out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter->sumw2);
1140
1141 double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1;
1142 auto sumScales = runCounter->sumScale;
1143 for (auto& val : sumScales)
1144 val *= norm;
1145 out->addVFloatWithNorm("LHEScaleSumw" + label,
1146 "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel,
1147 sumScales,
1148 runCounter->sumw);
1149 auto sumPDFs = runCounter->sumPDF;
1150 for (auto& val : sumPDFs)
1151 val *= norm;
1152 out->addVFloatWithNorm("LHEPdfSumw" + label,
1153 "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel,
1154 sumPDFs,
1155 runCounter->sumw);
1156 auto sumPS = runCounter->sumPS;
1157 for (auto& val : sumPS)
1158 val *= norm;
1159 out->addVFloatWithNorm("PSSumw" + label,
1160 "Sum of genEventWeight * PSWeight[i], divided by genEventSumw" + doclabel,
1161 sumPS,
1162 runCounter->sumw);
1163 if (!runCounter->sumRwgt.empty()) {
1164 auto sumRwgts = runCounter->sumRwgt;
1165 for (auto& val : sumRwgts)
1166 val *= norm;
1167 out->addVFloatWithNorm("LHEReweightingSumw" + label,
1168 "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel,
1169 sumRwgts,
1170 runCounter->sumw);
1171 }
1172 if (!runCounter->sumNamed.empty()) {
1173 for (unsigned int i = 0, n = namedWeightLabels_.size(); i < n; ++i) {
1174 out->addFloatWithNorm(
1175 "LHESumw_" + namedWeightLabels_[i] + label,
1176 "Sum of genEventWeight * LHEWeight_" + namedWeightLabels_[i] + ", divided by genEventSumw" + doclabel,
1177 runCounter->sumNamed[i] * norm,
1178 runCounter->sumw);
1179 }
1180 }
1181 }
1182 iRun.put(std::move(out));
1183 }
1184
1185 void globalEndRun(edm::Run const&, edm::EventSetup const&) const override {}
1186
1187 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
1188 edm::ParameterSetDescription desc;
1189 desc.add<edm::InputTag>("genEvent", edm::InputTag("generator"))
1190 ->setComment("tag for the GenEventInfoProduct, to get the main weight");
1191 desc.add<edm::InputTag>("genLumiInfoHeader", edm::InputTag("generator"))
1192 ->setComment("tag for the GenLumiInfoProduct, to get the model string");
1193 desc.add<std::vector<edm::InputTag>>("lheInfo", std::vector<edm::InputTag>{{"externalLHEProducer"}, {"source"}})
1194 ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)");
1195
1196 edm::ParameterSetDescription prefpdf;
1197 prefpdf.add<std::string>("name");
1198 prefpdf.add<uint32_t>("lhaid");
1199 desc.addVPSet("preferredPDFs", prefpdf, std::vector<edm::ParameterSet>())
1200 ->setComment(
1201 "LHA PDF Ids of the preferred PDF sets, in order of preference (the first matching one will be used)");
1202 desc.add<std::vector<std::string>>("namedWeightIDs")->setComment("set of LHA weight IDs for named LHE weights");
1203 desc.add<std::vector<std::string>>("namedWeightLabels")
1204 ->setComment("output names for the namedWeightIDs (in the same order)");
1205 desc.add<int32_t>("lheWeightPrecision")->setComment("Number of bits in the mantissa for LHE weights");
1206 desc.add<uint32_t>("maxPdfWeights")->setComment("Maximum number of PDF weights to save (to crop NN replicas)");
1207 desc.add<bool>("keepAllPSWeights")->setComment("Store all PS weights found");
1208 desc.add<std::vector<uint32_t>>("allowedNumScaleWeights")
1209 ->setComment(
1210 "Allowed numbers of scale weights parsed from the header. Empty list means any number is allowed.");
1211 desc.addOptionalUntracked<bool>("debug")->setComment("dump out all LHE information for one event");
1212 descriptions.add("genWeightsTable", desc);
1213 }
1214
1215 protected:
1216 const edm::EDGetTokenT<GenEventInfoProduct> genTag_;
1217 const std::vector<edm::InputTag> lheLabel_;
1218 const std::vector<edm::EDGetTokenT<LHEEventProduct>> lheTag_;
1219 const std::vector<edm::EDGetTokenT<LHERunInfoProduct>> lheRunTag_;
1220 const edm::EDGetTokenT<GenLumiInfoHeader> genLumiInfoHeadTag_;
1221
1222 std::vector<uint32_t> preferredPDFLHAIDs_;
1223 std::unordered_map<std::string, uint32_t> lhaNameToID_;
1224 std::vector<std::string> namedWeightIDs_;
1225 std::vector<std::string> namedWeightLabels_;
1226 int lheWeightPrecision_;
1227 unsigned int maxPdfWeights_;
1228 bool keepAllPSWeights_;
1229 std::vector<uint32_t> allowedNumScaleWeights_;
1230
1231 mutable std::atomic<bool> debug_, debugRun_, hasIssuedWarning_, psWeightWarning_;
1232 };
1233
1234 #include "FWCore/Framework/interface/MakerMacros.h"
1235 DEFINE_FWK_MODULE(GenWeightsTableProducer);