File indexing completed on 2024-04-06 12:23:41
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 debug_(params.getUntrackedParameter<bool>("debug", false)),
0266 debugRun_(debug_.load()),
0267 hasIssuedWarning_(false),
0268 psWeightWarning_(false) {
0269 produces<nanoaod::FlatTable>();
0270 produces<std::string>("genModel");
0271 produces<nanoaod::FlatTable>("LHEScale");
0272 produces<nanoaod::FlatTable>("LHEPdf");
0273 produces<nanoaod::FlatTable>("LHEReweighting");
0274 produces<nanoaod::FlatTable>("LHENamed");
0275 produces<nanoaod::FlatTable>("PS");
0276 produces<nanoaod::MergeableCounterTable, edm::Transition::EndRun>();
0277 if (namedWeightIDs_.size() != namedWeightLabels_.size()) {
0278 throw cms::Exception("Configuration", "Size mismatch between namedWeightIDs & namedWeightLabels");
0279 }
0280 for (const edm::ParameterSet& pdfps : params.getParameter<std::vector<edm::ParameterSet>>("preferredPDFs")) {
0281 const std::string& name = pdfps.getParameter<std::string>("name");
0282 uint32_t lhaid = pdfps.getParameter<uint32_t>("lhaid");
0283 preferredPDFLHAIDs_.push_back(lhaid);
0284 lhaNameToID_[name] = lhaid;
0285 lhaNameToID_[name + ".LHgrid"] = lhaid;
0286 }
0287 }
0288
0289 ~GenWeightsTableProducer() override {}
0290
0291 void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override {
0292
0293 Counter* counter = streamCache(id)->countermap.get();
0294
0295
0296 edm::Handle<GenEventInfoProduct> genInfo;
0297 iEvent.getByToken(genTag_, genInfo);
0298 double weight = genInfo->weight();
0299
0300
0301 auto out = std::make_unique<nanoaod::FlatTable>(1, "genWeight", true);
0302 out->setDoc("generator weight");
0303 out->addColumnValue<float>("", weight, "generator weight");
0304 iEvent.put(std::move(out));
0305
0306 std::string model_label = streamCache(id)->countermap.getLabel();
0307 auto outM = std::make_unique<std::string>((!model_label.empty()) ? std::string("GenModel_") + model_label : "");
0308 iEvent.put(std::move(outM), "genModel");
0309 bool getLHEweightsFromGenInfo = !model_label.empty();
0310
0311
0312 std::unique_ptr<nanoaod::FlatTable> lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab;
0313 std::unique_ptr<nanoaod::FlatTable> genPSTab;
0314
0315 edm::Handle<LHEEventProduct> lheInfo;
0316 for (const auto& lheTag : lheTag_) {
0317 iEvent.getByToken(lheTag, lheInfo);
0318 if (lheInfo.isValid()) {
0319 break;
0320 }
0321 }
0322
0323 const auto genWeightChoice = luminosityBlockCache(iEvent.getLuminosityBlock().index());
0324 if (lheInfo.isValid()) {
0325 if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true))
0326 edm::LogWarning("LHETablesProducer")
0327 << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n";
0328
0329 const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index());
0330
0331 fillLHEWeightTables(counter,
0332 weightChoice,
0333 genWeightChoice,
0334 weight,
0335 *lheInfo,
0336 *genInfo,
0337 lheScaleTab,
0338 lhePdfTab,
0339 lheRwgtTab,
0340 lheNamedTab,
0341 genPSTab);
0342 } else if (getLHEweightsFromGenInfo) {
0343 fillLHEPdfWeightTablesFromGenInfo(
0344 counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab);
0345 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
0346
0347
0348 } else {
0349
0350 fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab);
0351
0352 lheScaleTab = std::make_unique<nanoaod::FlatTable>(1, "LHEScaleWeights", true);
0353 lhePdfTab = std::make_unique<nanoaod::FlatTable>(1, "LHEPdfWeights", true);
0354 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
0355 lheNamedTab = std::make_unique<nanoaod::FlatTable>(1, "LHENamedWeights", true);
0356 if (!hasIssuedWarning_.exchange(true)) {
0357 edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n";
0358 }
0359 }
0360
0361 iEvent.put(std::move(lheScaleTab), "LHEScale");
0362 iEvent.put(std::move(lhePdfTab), "LHEPdf");
0363 iEvent.put(std::move(lheRwgtTab), "LHEReweighting");
0364 iEvent.put(std::move(lheNamedTab), "LHENamed");
0365 iEvent.put(std::move(genPSTab), "PS");
0366 }
0367
0368 void fillLHEWeightTables(Counter* counter,
0369 const DynamicWeightChoice* weightChoice,
0370 const DynamicWeightChoiceGenInfo* genWeightChoice,
0371 double genWeight,
0372 const LHEEventProduct& lheProd,
0373 const GenEventInfoProduct& genProd,
0374 std::unique_ptr<nanoaod::FlatTable>& outScale,
0375 std::unique_ptr<nanoaod::FlatTable>& outPdf,
0376 std::unique_ptr<nanoaod::FlatTable>& outRwgt,
0377 std::unique_ptr<nanoaod::FlatTable>& outNamed,
0378 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0379 bool lheDebug = debug_.exchange(
0380 false);
0381
0382 const std::vector<std::string>& scaleWeightIDs = weightChoice->scaleWeightIDs;
0383 const std::vector<std::string>& pdfWeightIDs = weightChoice->pdfWeightIDs;
0384 const std::vector<std::string>& rwgtWeightIDs = weightChoice->rwgtIDs;
0385
0386 double w0 = lheProd.originalXWGTUP();
0387
0388 std::vector<double> wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1),
0389 wNamed(namedWeightIDs_.size(), 1);
0390 for (auto& weight : lheProd.weights()) {
0391 if (lheDebug)
0392 printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str());
0393
0394 auto mScale = std::find(scaleWeightIDs.begin(), scaleWeightIDs.end(), weight.id);
0395 if (mScale != scaleWeightIDs.end())
0396 wScale[mScale - scaleWeightIDs.begin()] = weight.wgt / w0;
0397
0398 auto mPDF = std::find(pdfWeightIDs.begin(), pdfWeightIDs.end(), weight.id);
0399 if (mPDF != pdfWeightIDs.end())
0400 wPDF[mPDF - pdfWeightIDs.begin()] = weight.wgt / w0;
0401
0402 auto mRwgt = std::find(rwgtWeightIDs.begin(), rwgtWeightIDs.end(), weight.id);
0403 if (mRwgt != rwgtWeightIDs.end())
0404 wRwgt[mRwgt - rwgtWeightIDs.begin()] = weight.wgt / w0;
0405
0406 auto mNamed = std::find(namedWeightIDs_.begin(), namedWeightIDs_.end(), weight.id);
0407 if (mNamed != namedWeightIDs_.end())
0408 wNamed[mNamed - namedWeightIDs_.begin()] = weight.wgt / w0;
0409 }
0410
0411 std::vector<double> wPS;
0412 std::string psWeightDocStr;
0413 setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
0414
0415 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0416 outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
0417
0418 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
0419 outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
0420
0421 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
0422 outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
0423
0424 outRwgt = std::make_unique<nanoaod::FlatTable>(wRwgt.size(), "LHEReweightingWeight", false);
0425 outRwgt->addColumn<float>("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_);
0426
0427 outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
0428 outNamed->addColumnValue<float>("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file");
0429 for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) {
0430 outNamed->addColumnValue<float>(namedWeightLabels_[i],
0431 wNamed[i],
0432 "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal",
0433 lheWeightPrecision_);
0434 }
0435
0436 counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS);
0437 }
0438
0439 void fillLHEPdfWeightTablesFromGenInfo(Counter* counter,
0440 const DynamicWeightChoiceGenInfo* weightChoice,
0441 double genWeight,
0442 const GenEventInfoProduct& genProd,
0443 std::unique_ptr<nanoaod::FlatTable>& outScale,
0444 std::unique_ptr<nanoaod::FlatTable>& outPdf,
0445 std::unique_ptr<nanoaod::FlatTable>& outNamed,
0446 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0447 const std::vector<unsigned int>& scaleWeightIDs = weightChoice->scaleWeightIDs;
0448 const std::vector<unsigned int>& pdfWeightIDs = weightChoice->pdfWeightIDs;
0449
0450 auto weights = genProd.weights();
0451 double w0 = (weights.size() > 1) ? weights.at(1) : 1.;
0452 double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.;
0453
0454 std::vector<double> wScale, wPDF, wPS;
0455 for (auto id : scaleWeightIDs)
0456 wScale.push_back(weights.at(id) / w0);
0457 for (auto id : pdfWeightIDs) {
0458 wPDF.push_back(weights.at(id) / w0);
0459 }
0460
0461 std::string psWeightsDocStr;
0462 setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr);
0463
0464 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
0465 outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
0466
0467 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
0468 outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
0469
0470 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0471 outPS->addColumn<float>("", wPS, psWeightsDocStr, lheWeightPrecision_);
0472
0473 outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
0474 outNamed->addColumnValue<float>("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file");
0475
0476
0477
0478
0479 counter->incLHE(genWeight, wScale, wPDF, std::vector<double>(), std::vector<double>(), wPS);
0480 }
0481
0482 void fillOnlyPSWeightTable(Counter* counter,
0483 const DynamicWeightChoiceGenInfo* genWeightChoice,
0484 double genWeight,
0485 const GenEventInfoProduct& genProd,
0486 std::unique_ptr<nanoaod::FlatTable>& outPS) const {
0487 std::vector<double> wPS;
0488 std::string psWeightDocStr;
0489 setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
0490 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
0491 outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
0492
0493 counter->incGenOnly(genWeight);
0494 counter->incPSOnly(genWeight, wPS);
0495 }
0496
0497 void setPSWeightInfo(const std::vector<double>& genWeights,
0498 const DynamicWeightChoiceGenInfo* genWeightChoice,
0499 std::vector<double>& wPS,
0500 std::string& psWeightDocStr) const {
0501 wPS.clear();
0502
0503
0504 bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46);
0505 if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) {
0506 psWeightDocStr = genWeightChoice->psWeightsDoc;
0507 double psNom = genWeights.at(genWeightChoice->psBaselineID);
0508 for (auto wgtidx : genWeightChoice->psWeightIDs) {
0509 wPS.push_back(genWeights.at(wgtidx) / psNom);
0510 }
0511 } else {
0512 int vectorSize =
0513 keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1);
0514
0515 if (vectorSize > 1) {
0516 double nominal = genWeights.at(1);
0517 if (keepAllPSWeights_) {
0518 for (int i = 0; i < vectorSize; i++) {
0519 wPS.push_back(genWeights.at(i + 2) / nominal);
0520 }
0521 psWeightDocStr = "All PS weights (w_var / w_nominal)";
0522 } else {
0523 if (!psWeightWarning_.exchange(true))
0524 edm::LogWarning("LHETablesProducer")
0525 << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n"
0526 << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt "
0527 "order )";
0528 for (std::size_t i = 6; i < 10; i++) {
0529 wPS.push_back(genWeights.at(i) / nominal);
0530 }
0531 psWeightDocStr =
0532 "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2"
0533 "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;";
0534 }
0535 } else {
0536 wPS.push_back(1.0);
0537 psWeightDocStr = "dummy PS weight (1.0) ";
0538 }
0539 }
0540 }
0541
0542
0543 std::shared_ptr<DynamicWeightChoice> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override {
0544 edm::Handle<LHERunInfoProduct> lheInfo;
0545
0546 bool lheDebug = debugRun_.exchange(
0547 false);
0548 auto weightChoice = std::make_shared<DynamicWeightChoice>();
0549
0550
0551
0552 for (const auto& lheLabel : lheLabel_) {
0553 iRun.getByLabel(lheLabel, lheInfo);
0554 if (lheInfo.isValid()) {
0555 break;
0556 }
0557 }
0558 if (lheInfo.isValid()) {
0559 std::vector<ScaleVarWeight> scaleVariationIDs;
0560 std::vector<PDFSetWeights> pdfSetWeightIDs;
0561 std::vector<std::string> lheReweighingIDs;
0562 bool isFirstGroup = true;
0563
0564 std::regex weightgroupmg26x("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s+combine=\"(.*)\"\\s*>");
0565 std::regex weightgroup("<weightgroup\\s+combine=\"(.*)\"\\s+(?:name|type)=\"(.*)\"\\s*>");
0566 std::regex weightgroupRwgt("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s*>");
0567 std::regex endweightgroup("</weightgroup>");
0568 std::regex scalewmg26x(
0569 "<weight\\s+(?:.*\\s+)?id=\"(\\d+)\"\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:[mM][uU][rR]|renscfact)=\"("
0570 "\\S+)\"\\s+(?:[mM][uU][Ff]|facscfact)=\"(\\S+)\")(\\s+.*)?</weight>");
0571 std::regex scalewmg26xNew(
0572 "<weight\\s*((?:[mM][uU][fF]|facscfact)=\"(\\S+)\"\\s+(?:[mM][uU][Rr]|renscfact)=\"(\\S+)\").+id=\"(\\d+)\"(."
0573 "*)?</weight>");
0574
0575
0576 std::regex scalew(
0577 "<weight\\s+(?:.*\\s+)?id=\"(\\d+|\\d+-NNLOPS)\">\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)"
0578 "=(\\S+)\\s+(?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)</weight>");
0579 std::regex pdfw(
0580 "<weight\\s+id=\"(\\d+)\">\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?</weight>");
0581 std::regex pdfwOld("<weight\\s+(?:.*\\s+)?id=\"(\\d+)\">\\s*Member \\s*(\\d+)\\s*(?:.*)</weight>");
0582 std::regex pdfwmg26x(
0583 "<weight\\s+id=\"(\\d+)\"\\s*MUR=\"(?:\\S+)\"\\s*MUF=\"(?:\\S+)\"\\s*(?:PDF "
0584 "set|lhapdf|PDF|pdfset)\\s*=\\s*\"(\\d+)\"\\s*>\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
0585 "weight>");
0586
0587
0588
0589 std::regex pdfwmg26xNew(
0590 "<weight\\s+MUF=\"(?:\\S+)\"\\s*MUR=\"(?:\\S+)\"\\s*PDF=\"(?:\\S+)\"\\s*id=\"(\\S+)\"\\s*>"
0591 "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
0592 "weight>");
0593
0594 std::regex rwgt("<weight\\s+id=\"(.+)\">(.+)?(</weight>)?");
0595 std::smatch groups;
0596 for (auto iter = lheInfo->headers_begin(), end = lheInfo->headers_end(); iter != end; ++iter) {
0597 if (iter->tag() != "initrwgt") {
0598 if (lheDebug)
0599 std::cout << "Skipping LHE header with tag" << iter->tag() << std::endl;
0600 continue;
0601 }
0602 if (lheDebug)
0603 std::cout << "Found LHE header with tag" << iter->tag() << std::endl;
0604 std::vector<std::string> lines = iter->lines();
0605 bool missed_weightgroup =
0606 false;
0607 bool ismg26x = false;
0608 bool ismg26xNew = false;
0609 for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines;
0610 ++iLine) {
0611 boost::replace_all(lines[iLine], "<", "<");
0612 boost::replace_all(lines[iLine], ">", ">");
0613 if (std::regex_search(lines[iLine], groups, weightgroupmg26x)) {
0614 ismg26x = true;
0615 } else if (std::regex_search(lines[iLine], groups, scalewmg26xNew) ||
0616 std::regex_search(lines[iLine], groups, pdfwmg26xNew)) {
0617 ismg26xNew = true;
0618 }
0619 }
0620 for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; ++iLine) {
0621 if (lheDebug)
0622 std::cout << lines[iLine];
0623 if (std::regex_search(lines[iLine], groups, ismg26x ? weightgroupmg26x : weightgroup)) {
0624 std::string groupname = groups.str(2);
0625 if (ismg26x)
0626 groupname = groups.str(1);
0627 if (lheDebug)
0628 std::cout << ">>> Looks like the beginning of a weight group for '" << groupname << "'" << std::endl;
0629 if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation" || isFirstGroup) {
0630 if (lheDebug && groupname.find("scale_variation") != 0 && groupname != "Central scale variation")
0631 std::cout << ">>> First weight is not scale variation, but assuming is the Central Weight" << std::endl;
0632 else if (lheDebug)
0633 std::cout << ">>> Looks like scale variation for theory uncertainties" << std::endl;
0634 isFirstGroup = false;
0635 for (++iLine; iLine < nLines; ++iLine) {
0636 if (lheDebug) {
0637 std::cout << " " << lines[iLine];
0638 }
0639 if (std::regex_search(
0640 lines[iLine], groups, ismg26x ? scalewmg26x : (ismg26xNew ? scalewmg26xNew : scalew))) {
0641 if (lheDebug)
0642 std::cout << " >>> Scale weight " << groups[1].str() << " for " << groups[3].str() << " , "
0643 << groups[4].str() << " , " << groups[5].str() << std::endl;
0644 if (ismg26xNew) {
0645 scaleVariationIDs.emplace_back(groups.str(4), groups.str(1), groups.str(3), groups.str(2));
0646 } else {
0647 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
0648 }
0649 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0650 if (lheDebug)
0651 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0652 if (!missed_weightgroup) {
0653 break;
0654 } else
0655 missed_weightgroup = false;
0656 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0657 if (lheDebug)
0658 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0659 "of the group."
0660 << std::endl;
0661 if (ismg26x || ismg26xNew)
0662 missed_weightgroup = true;
0663 --iLine;
0664 break;
0665 }
0666 }
0667 } else if (groupname == "PDF_variation" || groupname.find("PDF_variation ") == 0) {
0668 if (lheDebug)
0669 std::cout << ">>> Looks like a new-style block of PDF weights for one or more pdfs" << std::endl;
0670 for (++iLine; iLine < nLines; ++iLine) {
0671 if (lheDebug)
0672 std::cout << " " << lines[iLine];
0673 if (std::regex_search(lines[iLine], groups, pdfw)) {
0674 unsigned int lhaID = std::stoi(groups.str(2));
0675 if (lheDebug)
0676 std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
0677 << std::endl;
0678 if (pdfSetWeightIDs.empty() || !pdfSetWeightIDs.back().maybe_add(groups.str(1), lhaID)) {
0679 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0680 }
0681 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0682 if (lheDebug)
0683 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0684 if (!missed_weightgroup) {
0685 break;
0686 } else
0687 missed_weightgroup = false;
0688 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0689 if (lheDebug)
0690 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0691 "of the group."
0692 << std::endl;
0693 if (ismg26x || ismg26xNew)
0694 missed_weightgroup = true;
0695 --iLine;
0696 break;
0697 }
0698 }
0699 } else if (groupname == "PDF_variation1" || groupname == "PDF_variation2") {
0700 if (lheDebug)
0701 std::cout << ">>> Looks like a new-style block of PDF weights for multiple pdfs" << std::endl;
0702 unsigned int lastid = 0;
0703 for (++iLine; iLine < nLines; ++iLine) {
0704 if (lheDebug)
0705 std::cout << " " << lines[iLine];
0706 if (std::regex_search(lines[iLine], groups, pdfw)) {
0707 unsigned int id = std::stoi(groups.str(1));
0708 unsigned int lhaID = std::stoi(groups.str(2));
0709 if (lheDebug)
0710 std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
0711 << std::endl;
0712 if (id != (lastid + 1) || pdfSetWeightIDs.empty()) {
0713 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0714 } else {
0715 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
0716 }
0717 lastid = id;
0718 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0719 if (lheDebug)
0720 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0721 if (!missed_weightgroup) {
0722 break;
0723 } else
0724 missed_weightgroup = false;
0725 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0726 if (lheDebug)
0727 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0728 "of the group."
0729 << std::endl;
0730 if (ismg26x || ismg26xNew)
0731 missed_weightgroup = true;
0732 --iLine;
0733 break;
0734 }
0735 }
0736 } else if (lhaNameToID_.find(groupname) != lhaNameToID_.end()) {
0737 if (lheDebug)
0738 std::cout << ">>> Looks like an old-style PDF weight for an individual pdf" << std::endl;
0739 unsigned int firstLhaID = lhaNameToID_.find(groupname)->second;
0740 bool first = true;
0741 for (++iLine; iLine < nLines; ++iLine) {
0742 if (lheDebug)
0743 std::cout << " " << lines[iLine];
0744 if (std::regex_search(
0745 lines[iLine], groups, ismg26x ? pdfwmg26x : (ismg26xNew ? pdfwmg26xNew : pdfwOld))) {
0746 unsigned int member = 0;
0747 if (!ismg26x && !ismg26xNew) {
0748 member = std::stoi(groups.str(2));
0749 } else if (ismg26xNew) {
0750 if (!groups.str(3).empty()) {
0751 member = std::stoi(groups.str(3));
0752 }
0753 } else {
0754 if (!groups.str(4).empty()) {
0755 member = std::stoi(groups.str(4));
0756 }
0757 }
0758 unsigned int lhaID = member + firstLhaID;
0759 if (lheDebug)
0760 std::cout << " >>> PDF weight " << groups.str(1) << " for " << member << " = " << lhaID
0761 << std::endl;
0762
0763 if (first) {
0764 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
0765 first = false;
0766 } else {
0767 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
0768 }
0769 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0770 if (lheDebug)
0771 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0772 if (!missed_weightgroup) {
0773 break;
0774 } else
0775 missed_weightgroup = false;
0776 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0777 if (lheDebug)
0778 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0779 "of the group."
0780 << std::endl;
0781 if (ismg26x || ismg26xNew)
0782 missed_weightgroup = true;
0783 --iLine;
0784 break;
0785 }
0786 }
0787 } else if (groupname == "mass_variation" || groupname == "sthw2_variation" ||
0788 groupname == "width_variation") {
0789 if (lheDebug)
0790 std::cout << ">>> Looks like an EW parameter weight" << std::endl;
0791 for (++iLine; iLine < nLines; ++iLine) {
0792 if (lheDebug)
0793 std::cout << " " << lines[iLine];
0794 if (std::regex_search(lines[iLine], groups, rwgt)) {
0795 std::string rwgtID = groups.str(1);
0796 if (lheDebug)
0797 std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
0798 if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
0799
0800 lheReweighingIDs.emplace_back(rwgtID);
0801 }
0802 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0803 if (lheDebug)
0804 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0805 }
0806 }
0807 } else {
0808 for (++iLine; iLine < nLines; ++iLine) {
0809 if (lheDebug)
0810 std::cout << " " << lines[iLine];
0811 if (std::regex_search(lines[iLine], groups, endweightgroup)) {
0812 if (lheDebug)
0813 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0814 if (!missed_weightgroup) {
0815 break;
0816 } else
0817 missed_weightgroup = false;
0818 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0819 if (lheDebug)
0820 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0821 "of the group."
0822 << std::endl;
0823 if (ismg26x || ismg26xNew)
0824 missed_weightgroup = true;
0825 --iLine;
0826 break;
0827 }
0828 }
0829 }
0830 } else if (std::regex_search(lines[iLine], groups, weightgroupRwgt)) {
0831 std::string groupname = groups.str(1);
0832 if (groupname.find("mg_reweighting") != std::string::npos) {
0833 if (lheDebug)
0834 std::cout << ">>> Looks like a LHE weights for reweighting" << std::endl;
0835 for (++iLine; iLine < nLines; ++iLine) {
0836 if (lheDebug)
0837 std::cout << " " << lines[iLine];
0838 if (std::regex_search(lines[iLine], groups, rwgt)) {
0839 std::string rwgtID = groups.str(1);
0840 if (lheDebug)
0841 std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
0842 if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
0843
0844 lheReweighingIDs.emplace_back(rwgtID);
0845 }
0846 } else if (std::regex_search(lines[iLine], endweightgroup)) {
0847 if (lheDebug)
0848 std::cout << ">>> Looks like the end of a weight group" << std::endl;
0849 if (!missed_weightgroup) {
0850 break;
0851 } else
0852 missed_weightgroup = false;
0853 } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
0854 if (lheDebug)
0855 std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
0856 "of the group."
0857 << std::endl;
0858 if (ismg26x)
0859 missed_weightgroup = true;
0860 --iLine;
0861 break;
0862 }
0863 }
0864 }
0865 }
0866 }
0867
0868
0869
0870 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
0871 if (lheDebug)
0872 std::cout << "Found " << scaleVariationIDs.size() << " scale variations: " << std::endl;
0873 std::stringstream scaleDoc;
0874 scaleDoc << "LHE scale variation weights (w_var / w_nominal); ";
0875 for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
0876 const auto& sw = scaleVariationIDs[isw];
0877 if (isw)
0878 scaleDoc << "; ";
0879 scaleDoc << "[" << isw << "] is " << sw.label;
0880 weightChoice->scaleWeightIDs.push_back(sw.wid);
0881 if (lheDebug)
0882 printf(" id %s: scales ren = % .2f fact = % .2f text = %s\n",
0883 sw.wid.c_str(),
0884 sw.scales.first,
0885 sw.scales.second,
0886 sw.label.c_str());
0887 }
0888 if (!scaleVariationIDs.empty())
0889 weightChoice->scaleWeightsDoc = scaleDoc.str();
0890
0891
0892 if (lheDebug) {
0893 std::cout << "Found " << pdfSetWeightIDs.size() << " PDF set errors: " << std::endl;
0894 for (const auto& pw : pdfSetWeightIDs)
0895 printf("lhaIDs %6d - %6d (%3lu weights: %s, ... )\n",
0896 pw.lhaIDs.first,
0897 pw.lhaIDs.second,
0898 pw.wids.size(),
0899 pw.wids.front().c_str());
0900 }
0901
0902
0903 if (lheDebug) {
0904 std::cout << "Found " << lheReweighingIDs.size() << " reweighting weights" << std::endl;
0905 }
0906 std::copy(lheReweighingIDs.begin(), lheReweighingIDs.end(), std::back_inserter(weightChoice->rwgtIDs));
0907
0908 std::stringstream pdfDoc;
0909 pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA IDs ";
0910 bool found = false;
0911 for (const auto& pw : pdfSetWeightIDs) {
0912 for (uint32_t lhaid : preferredPDFLHAIDs_) {
0913 if (pw.lhaIDs.first != lhaid && pw.lhaIDs.first != (lhaid + 1))
0914 continue;
0915 if (pw.wids.size() == 1)
0916 continue;
0917 pdfDoc << pw.lhaIDs.first << " - " << pw.lhaIDs.second;
0918 weightChoice->pdfWeightIDs = pw.wids;
0919 if (maxPdfWeights_ < pw.wids.size()) {
0920 weightChoice->pdfWeightIDs.resize(maxPdfWeights_);
0921 pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas";
0922 }
0923 weightChoice->pdfWeightsDoc = pdfDoc.str();
0924 found = true;
0925 break;
0926 }
0927 if (found)
0928 break;
0929 }
0930 }
0931 }
0932 return weightChoice;
0933 }
0934
0935
0936 std::unique_ptr<LumiCacheInfoHolder> beginStream(edm::StreamID) const override {
0937 return std::make_unique<LumiCacheInfoHolder>();
0938 }
0939
0940 void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override {
0941 streamCache(id)->clear();
0942 }
0943
0944 std::shared_ptr<DynamicWeightChoiceGenInfo> globalBeginLuminosityBlock(edm::LuminosityBlock const& lumiBlock,
0945 edm::EventSetup const&) const override {
0946 auto dynamicWeightChoiceGenInfo = std::make_shared<DynamicWeightChoiceGenInfo>();
0947
0948 edm::Handle<GenLumiInfoHeader> genLumiInfoHead;
0949 lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead);
0950 if (!genLumiInfoHead.isValid())
0951 edm::LogWarning("LHETablesProducer")
0952 << "No GenLumiInfoHeader product found, will not fill generator model string.\n";
0953
0954 if (genLumiInfoHead.isValid()) {
0955 auto weightChoice = dynamicWeightChoiceGenInfo.get();
0956
0957 std::vector<ScaleVarWeight> scaleVariationIDs;
0958 std::vector<PDFSetWeights> pdfSetWeightIDs;
0959 weightChoice->psWeightIDs.clear();
0960
0961 std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)");
0962 std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)");
0963 std::regex mainPSw("sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)");
0964 std::smatch groups;
0965 auto weightNames = genLumiInfoHead->weightNames();
0966 std::unordered_map<std::string, uint32_t> knownPDFSetsFromGenInfo_;
0967 unsigned int weightIter = 0;
0968 for (const auto& line : weightNames) {
0969 if (std::regex_search(line, groups, scalew)) {
0970 auto id = groups.str(1);
0971 auto group = groups.str(2);
0972 auto mur = groups.str(3);
0973 auto muf = groups.str(4);
0974 if (group.find("Central scale variation") != std::string::npos)
0975 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
0976 } else if (std::regex_search(line, groups, pdfw)) {
0977 auto id = groups.str(1);
0978 auto group = groups.str(2);
0979 auto memberid = groups.str(3);
0980 auto pdfset = groups.str(4);
0981 if (group.find(pdfset) != std::string::npos) {
0982 if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) {
0983 knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str());
0984 pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str()));
0985 } else
0986 pdfSetWeightIDs.back().add(id, std::atoi(id.c_str()));
0987 }
0988 } else if (line == "Baseline") {
0989 weightChoice->psBaselineID = weightIter;
0990 } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) {
0991 weightChoice->matchPS_alt = line.find("sr:") != std::string::npos;
0992 if (keepAllPSWeights_) {
0993 weightChoice->psWeightIDs.push_back(weightIter);
0994 } else if (std::regex_search(line, groups, mainPSw)) {
0995 if (weightChoice->psWeightIDs.empty())
0996 weightChoice->psWeightIDs = std::vector<unsigned int>(4, -1);
0997 int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0;
0998 psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2;
0999 weightChoice->psWeightIDs[psIdx] = weightIter;
1000 }
1001 }
1002 weightIter++;
1003 }
1004 if (keepAllPSWeights_) {
1005 weightChoice->psWeightsDoc = "All PS weights (w_var / w_nominal)";
1006 } else if (weightChoice->psWeightIDs.size() == 4) {
1007 weightChoice->psWeightsDoc =
1008 "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2"
1009 "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;";
1010 for (int i = 0; i < 4; i++) {
1011 if (static_cast<int>(weightChoice->psWeightIDs[i]) == -1)
1012 weightChoice->setMissingWeight(i);
1013 }
1014 } else {
1015 weightChoice->psWeightsDoc = "dummy PS weight (1.0) ";
1016 }
1017
1018 weightChoice->scaleWeightIDs.clear();
1019 weightChoice->pdfWeightIDs.clear();
1020
1021 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
1022 std::stringstream scaleDoc;
1023 scaleDoc << "LHE scale variation weights (w_var / w_nominal); ";
1024 for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
1025 const auto& sw = scaleVariationIDs[isw];
1026 if (isw)
1027 scaleDoc << "; ";
1028 scaleDoc << "[" << isw << "] is " << sw.label;
1029 weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str()));
1030 }
1031 if (!scaleVariationIDs.empty())
1032 weightChoice->scaleWeightsDoc = scaleDoc.str();
1033 std::stringstream pdfDoc;
1034 pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA names ";
1035 bool found = false;
1036 for (const auto& pw : pdfSetWeightIDs) {
1037 if (pw.wids.size() == 1)
1038 continue;
1039 for (const auto& wantedpdf : lhaNameToID_) {
1040 auto pdfname = wantedpdf.first;
1041 if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end())
1042 continue;
1043 uint32_t lhaid = knownPDFSetsFromGenInfo_.at(pdfname);
1044 if (pw.lhaIDs.first != lhaid)
1045 continue;
1046 pdfDoc << pdfname;
1047 for (const auto& x : pw.wids)
1048 weightChoice->pdfWeightIDs.push_back(std::atoi(x.c_str()));
1049 if (maxPdfWeights_ < pw.wids.size()) {
1050 weightChoice->pdfWeightIDs.resize(maxPdfWeights_);
1051 pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas";
1052 }
1053 weightChoice->pdfWeightsDoc = pdfDoc.str();
1054 found = true;
1055 break;
1056 }
1057 if (found)
1058 break;
1059 }
1060 }
1061 return dynamicWeightChoiceGenInfo;
1062 }
1063
1064 void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {}
1065
1066 void streamBeginLuminosityBlock(edm::StreamID id,
1067 edm::LuminosityBlock const& lumiBlock,
1068 edm::EventSetup const&) const override {
1069 auto counterMap = &(streamCache(id)->countermap);
1070 edm::Handle<GenLumiInfoHeader> genLumiInfoHead;
1071 lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead);
1072
1073 std::string label;
1074 if (genLumiInfoHead.isValid()) {
1075 label = genLumiInfoHead->configDescription();
1076 boost::replace_all(label, "-", "_");
1077 boost::replace_all(label, "/", "_");
1078 }
1079 counterMap->setLabel(label);
1080 }
1081
1082 std::shared_ptr<CounterMap> globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override {
1083 return std::make_shared<CounterMap>();
1084 }
1085
1086 void streamEndRunSummary(edm::StreamID id,
1087 edm::Run const&,
1088 edm::EventSetup const&,
1089 CounterMap* runCounterMap) const override {
1090 runCounterMap->merge(streamCache(id)->countermap);
1091 }
1092
1093 void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {}
1094
1095 void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, CounterMap const* runCounterMap) const override {
1096 auto out = std::make_unique<nanoaod::MergeableCounterTable>();
1097
1098 for (const auto& x : runCounterMap->countermap) {
1099 auto runCounter = &(x.second);
1100 std::string label = (!x.first.empty()) ? (std::string("_") + x.first) : "";
1101 std::string doclabel = (!x.first.empty()) ? (std::string(", for model label ") + x.first) : "";
1102
1103 out->addInt("genEventCount" + label, "event count" + doclabel, runCounter->num);
1104 out->addFloat("genEventSumw" + label, "sum of gen weights" + doclabel, runCounter->sumw);
1105 out->addFloat("genEventSumw2" + label, "sum of gen (weight^2)" + doclabel, runCounter->sumw2);
1106
1107 double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1;
1108 auto sumScales = runCounter->sumScale;
1109 for (auto& val : sumScales)
1110 val *= norm;
1111 out->addVFloatWithNorm("LHEScaleSumw" + label,
1112 "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel,
1113 sumScales,
1114 runCounter->sumw);
1115 auto sumPDFs = runCounter->sumPDF;
1116 for (auto& val : sumPDFs)
1117 val *= norm;
1118 out->addVFloatWithNorm("LHEPdfSumw" + label,
1119 "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel,
1120 sumPDFs,
1121 runCounter->sumw);
1122 auto sumPS = runCounter->sumPS;
1123 for (auto& val : sumPS)
1124 val *= norm;
1125 out->addVFloatWithNorm("PSSumw" + label,
1126 "Sum of genEventWeight * PSWeight[i], divided by genEventSumw" + doclabel,
1127 sumPS,
1128 runCounter->sumw);
1129 if (!runCounter->sumRwgt.empty()) {
1130 auto sumRwgts = runCounter->sumRwgt;
1131 for (auto& val : sumRwgts)
1132 val *= norm;
1133 out->addVFloatWithNorm("LHEReweightingSumw" + label,
1134 "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel,
1135 sumRwgts,
1136 runCounter->sumw);
1137 }
1138 if (!runCounter->sumNamed.empty()) {
1139 for (unsigned int i = 0, n = namedWeightLabels_.size(); i < n; ++i) {
1140 out->addFloatWithNorm(
1141 "LHESumw_" + namedWeightLabels_[i] + label,
1142 "Sum of genEventWeight * LHEWeight_" + namedWeightLabels_[i] + ", divided by genEventSumw" + doclabel,
1143 runCounter->sumNamed[i] * norm,
1144 runCounter->sumw);
1145 }
1146 }
1147 }
1148 iRun.put(std::move(out));
1149 }
1150
1151 void globalEndRun(edm::Run const&, edm::EventSetup const&) const override {}
1152
1153 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
1154 edm::ParameterSetDescription desc;
1155 desc.add<edm::InputTag>("genEvent", edm::InputTag("generator"))
1156 ->setComment("tag for the GenEventInfoProduct, to get the main weight");
1157 desc.add<edm::InputTag>("genLumiInfoHeader", edm::InputTag("generator"))
1158 ->setComment("tag for the GenLumiInfoProduct, to get the model string");
1159 desc.add<std::vector<edm::InputTag>>("lheInfo", std::vector<edm::InputTag>{{"externalLHEProducer"}, {"source"}})
1160 ->setComment("tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)");
1161
1162 edm::ParameterSetDescription prefpdf;
1163 prefpdf.add<std::string>("name");
1164 prefpdf.add<uint32_t>("lhaid");
1165 desc.addVPSet("preferredPDFs", prefpdf, std::vector<edm::ParameterSet>())
1166 ->setComment(
1167 "LHA PDF Ids of the preferred PDF sets, in order of preference (the first matching one will be used)");
1168 desc.add<std::vector<std::string>>("namedWeightIDs")->setComment("set of LHA weight IDs for named LHE weights");
1169 desc.add<std::vector<std::string>>("namedWeightLabels")
1170 ->setComment("output names for the namedWeightIDs (in the same order)");
1171 desc.add<int32_t>("lheWeightPrecision")->setComment("Number of bits in the mantissa for LHE weights");
1172 desc.add<uint32_t>("maxPdfWeights")->setComment("Maximum number of PDF weights to save (to crop NN replicas)");
1173 desc.add<bool>("keepAllPSWeights")->setComment("Store all PS weights found");
1174 desc.addOptionalUntracked<bool>("debug")->setComment("dump out all LHE information for one event");
1175 descriptions.add("genWeightsTable", desc);
1176 }
1177
1178 protected:
1179 const edm::EDGetTokenT<GenEventInfoProduct> genTag_;
1180 const std::vector<edm::InputTag> lheLabel_;
1181 const std::vector<edm::EDGetTokenT<LHEEventProduct>> lheTag_;
1182 const std::vector<edm::EDGetTokenT<LHERunInfoProduct>> lheRunTag_;
1183 const edm::EDGetTokenT<GenLumiInfoHeader> genLumiInfoHeadTag_;
1184
1185 std::vector<uint32_t> preferredPDFLHAIDs_;
1186 std::unordered_map<std::string, uint32_t> lhaNameToID_;
1187 std::vector<std::string> namedWeightIDs_;
1188 std::vector<std::string> namedWeightLabels_;
1189 int lheWeightPrecision_;
1190 unsigned int maxPdfWeights_;
1191 bool keepAllPSWeights_;
1192
1193 mutable std::atomic<bool> debug_, debugRun_, hasIssuedWarning_, psWeightWarning_;
1194 };
1195
1196 #include "FWCore/Framework/interface/MakerMacros.h"
1197 DEFINE_FWK_MODULE(GenWeightsTableProducer);