15 #include "boost/algorithm/string.hpp"
20 #include <unordered_map>
27 Counter() :
num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {}
33 std::vector<long double> sumPDF, sumScale, sumRwgt, sumNamed, sumPS;
42 sumNamed.clear(), sumPS.clear();
46 void incGenOnly(
double w) {
52 void incPSOnly(
double w0,
const std::vector<double>& wPS) {
55 sumPS.resize(wPS.size(), 0);
56 for (
unsigned int i = 0,
n = wPS.size();
i <
n; ++
i)
57 sumPS[
i] += (w0 * wPS[
i]);
61 void incLHE(
double w0,
62 const std::vector<double>& wScale,
63 const std::vector<double>& wPDF,
64 const std::vector<double>& wRwgt,
65 const std::vector<double>& wNamed,
66 const std::vector<double>& wPS) {
70 if (!wScale.empty()) {
72 sumScale.resize(wScale.size(), 0);
73 for (
unsigned int i = 0,
n = wScale.size();
i <
n; ++
i)
74 sumScale[
i] += (w0 * wScale[
i]);
78 sumPDF.resize(wPDF.size(), 0);
79 for (
unsigned int i = 0,
n = wPDF.size();
i <
n; ++
i)
80 sumPDF[
i] += (w0 * wPDF[
i]);
84 sumRwgt.resize(wRwgt.size(), 0);
85 for (
unsigned int i = 0,
n = wRwgt.size();
i <
n; ++
i)
86 sumRwgt[
i] += (w0 * wRwgt[
i]);
88 if (!wNamed.empty()) {
90 sumNamed.resize(wNamed.size(), 0);
91 for (
unsigned int i = 0,
n = wNamed.size();
i <
n; ++
i)
92 sumNamed[
i] += (w0 * wNamed[
i]);
100 sumw2 +=
other.sumw2;
101 if (sumScale.empty() && !
other.sumScale.empty())
102 sumScale.resize(
other.sumScale.size(), 0);
103 if (sumPDF.empty() && !
other.sumPDF.empty())
104 sumPDF.resize(
other.sumPDF.size(), 0);
105 if (sumRwgt.empty() && !
other.sumRwgt.empty())
106 sumRwgt.resize(
other.sumRwgt.size(), 0);
107 if (sumNamed.empty() && !
other.sumNamed.empty())
108 sumNamed.resize(
other.sumNamed.size(), 0);
109 if (sumPS.empty() && !
other.sumPS.empty())
110 sumPS.resize(
other.sumPS.size(), 0);
111 if (!
other.sumScale.empty())
112 for (
unsigned int i = 0,
n = sumScale.size();
i <
n; ++
i)
113 sumScale[
i] +=
other.sumScale[
i];
114 if (!
other.sumPDF.empty())
115 for (
unsigned int i = 0,
n = sumPDF.size();
i <
n; ++
i)
117 if (!
other.sumRwgt.empty())
118 for (
unsigned int i = 0,
n = sumRwgt.size();
i <
n; ++
i)
119 sumRwgt[
i] +=
other.sumRwgt[
i];
120 if (!
other.sumNamed.empty())
121 for (
unsigned int i = 0,
n = sumNamed.size();
i <
n; ++
i)
122 sumNamed[
i] +=
other.sumNamed[
i];
123 if (!
other.sumPS.empty())
124 for (
unsigned int i = 0,
n = sumPS.size();
i <
n; ++
i)
130 std::map<std::string, Counter> countermap;
134 for (
const auto&
y :
other.countermap)
135 countermap[
y.first].merge(
y.second);
139 for (
auto x : countermap)
145 active_el = &(countermap[
label]);
146 active_label =
label;
148 void checkLabelSet() {
150 throw cms::Exception(
"LogicError",
"Called CounterMap::get() before setting the active label\n");
163 struct DynamicWeightChoice {
166 std::vector<std::string> scaleWeightIDs;
169 std::vector<std::string> pdfWeightIDs;
172 std::vector<std::string> rwgtIDs;
176 struct DynamicWeightChoiceGenInfo {
179 std::vector<unsigned int> scaleWeightIDs;
182 std::vector<unsigned int> pdfWeightIDs;
185 std::vector<unsigned int> defPSWeightIDs = {6, 7, 8, 9};
186 std::vector<unsigned int> defPSWeightIDs_alt = {27, 5, 26, 4};
187 bool matchPS_alt =
false;
188 std::vector<unsigned int> psWeightIDs;
189 unsigned int psBaselineID = 1;
192 void setMissingWeight(
int idx) { psWeightIDs[
idx] = (matchPS_alt) ? defPSWeightIDs_alt[
idx] : defPSWeightIDs[
idx]; }
194 bool empty()
const {
return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); }
197 struct LumiCacheInfoHolder {
198 CounterMap countermap;
199 DynamicWeightChoiceGenInfo weightChoice;
202 weightChoice = DynamicWeightChoiceGenInfo();
208 if (
match != std::string::npos) {
211 return std::stof(pre) *
std::pow(10.0
f, std::stof(post));
213 return std::stof(
str);
217 struct ScaleVarWeight {
219 std::pair<float, float> scales;
221 : wid(
id),
label(
text), scales(stof_fortrancomp(muR), stof_fortrancomp(muF)) {}
223 return (scales ==
other.scales ? wid <
other.wid : scales <
other.scales);
226 struct PDFSetWeights {
227 std::vector<std::string> wids;
228 std::pair<unsigned int, unsigned int> lhaIDs;
229 PDFSetWeights(
const std::string& wid,
unsigned int lhaID) : wids(1, wid), lhaIDs(lhaID, lhaID) {}
233 lhaIDs.second = lhaID;
235 bool maybe_add(
const std::string& wid,
unsigned int lhaID) {
236 if (lhaID == lhaIDs.second + 1) {
248 edm::RunCache<DynamicWeightChoice>,
249 edm::RunSummaryCache<CounterMap>,
250 edm::EndRunProducer> {
260 mayConsume<GenLumiInfoHeader, edm::InLumi>(
params.getParameter<
edm::InputTag>(
"genLumiInfoHeader"))),
266 debug_(
params.getUntrackedParameter<
bool>(
"debug",
false)),
270 produces<nanoaod::FlatTable>();
271 produces<std::string>(
"genModel");
272 produces<nanoaod::FlatTable>(
"LHEScale");
273 produces<nanoaod::FlatTable>(
"LHEPdf");
274 produces<nanoaod::FlatTable>(
"LHEReweighting");
275 produces<nanoaod::FlatTable>(
"LHENamed");
276 produces<nanoaod::FlatTable>(
"PS");
277 produces<nanoaod::MergeableCounterTable, edm::Transition::EndRun>();
279 throw cms::Exception(
"Configuration",
"Size mismatch between namedWeightIDs & namedWeightLabels");
283 uint32_t
lhaid = pdfps.getParameter<uint32_t>(
"lhaid");
302 auto out = std::make_unique<nanoaod::FlatTable>(1,
"genWeight",
true);
303 out->setDoc(
"generator weight");
304 out->addColumnValue<
float>(
"",
weight,
"generator weight");
307 std::string model_label = streamCache(
id)->countermap.getLabel();
308 auto outM = std::make_unique<std::string>((!model_label.empty()) ?
std::string(
"GenModel_") + model_label :
"");
310 bool getLHEweightsFromGenInfo = !model_label.empty();
313 std::unique_ptr<nanoaod::FlatTable> lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab;
314 std::unique_ptr<nanoaod::FlatTable> genPSTab;
317 for (
const auto& lheTag :
lheTag_) {
324 const auto genWeightChoice = &(streamCache(
id)->weightChoice);
328 <<
"Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n";
330 const DynamicWeightChoice* weightChoice = runCache(
iEvent.getRun().index());
343 }
else if (getLHEweightsFromGenInfo) {
345 counter, genWeightChoice,
weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab);
346 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1,
"LHEReweightingWeights",
true);
353 lheScaleTab = std::make_unique<nanoaod::FlatTable>(1,
"LHEScaleWeights",
true);
354 lhePdfTab = std::make_unique<nanoaod::FlatTable>(1,
"LHEPdfWeights",
true);
355 lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1,
"LHEReweightingWeights",
true);
356 lheNamedTab = std::make_unique<nanoaod::FlatTable>(1,
"LHENamedWeights",
true);
358 edm::LogWarning(
"LHETablesProducer") <<
"No LHEEventProduct, so there will be no LHE Tables\n";
370 const DynamicWeightChoice* weightChoice,
371 const DynamicWeightChoiceGenInfo* genWeightChoice,
375 std::unique_ptr<nanoaod::FlatTable>& outScale,
376 std::unique_ptr<nanoaod::FlatTable>& outPdf,
377 std::unique_ptr<nanoaod::FlatTable>& outRwgt,
378 std::unique_ptr<nanoaod::FlatTable>& outNamed,
379 std::unique_ptr<nanoaod::FlatTable>& outPS)
const {
380 bool lheDebug =
debug_.exchange(
383 const std::vector<std::string>& scaleWeightIDs = weightChoice->scaleWeightIDs;
384 const std::vector<std::string>& pdfWeightIDs = weightChoice->pdfWeightIDs;
385 const std::vector<std::string>& rwgtWeightIDs = weightChoice->rwgtIDs;
389 std::vector<double> wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1),
393 printf(
"Weight %+9.5f rel %+9.5f for id %s\n",
weight.wgt,
weight.wgt / w0,
weight.id.c_str());
395 auto mScale =
std::find(scaleWeightIDs.begin(), scaleWeightIDs.end(),
weight.id);
396 if (mScale != scaleWeightIDs.end())
397 wScale[mScale - scaleWeightIDs.begin()] =
weight.wgt / w0;
399 auto mPDF =
std::find(pdfWeightIDs.begin(), pdfWeightIDs.end(),
weight.id);
400 if (mPDF != pdfWeightIDs.end())
401 wPDF[mPDF - pdfWeightIDs.begin()] =
weight.wgt / w0;
403 auto mRwgt =
std::find(rwgtWeightIDs.begin(), rwgtWeightIDs.end(),
weight.id);
404 if (mRwgt != rwgtWeightIDs.end())
405 wRwgt[mRwgt - rwgtWeightIDs.begin()] =
weight.wgt / w0;
412 std::vector<double> wPS;
416 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(),
"PSWeight",
false);
419 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(),
"LHEScaleWeight",
false);
420 outScale->addColumn<
float>(
"", wScale, weightChoice->scaleWeightsDoc,
lheWeightPrecision_);
422 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(),
"LHEPdfWeight",
false);
425 outRwgt = std::make_unique<nanoaod::FlatTable>(wRwgt.size(),
"LHEReweightingWeight",
false);
428 outNamed = std::make_unique<nanoaod::FlatTable>(1,
"LHEWeight",
true);
429 outNamed->addColumnValue<
float>(
"originalXWGTUP", lheProd.
originalXWGTUP(),
"Nominal event weight in the LHE file");
430 for (
unsigned int i = 0,
n = wNamed.size();
i <
n; ++
i) {
437 counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS);
441 const DynamicWeightChoiceGenInfo* weightChoice,
444 std::unique_ptr<nanoaod::FlatTable>& outScale,
445 std::unique_ptr<nanoaod::FlatTable>& outPdf,
446 std::unique_ptr<nanoaod::FlatTable>& outNamed,
447 std::unique_ptr<nanoaod::FlatTable>& outPS)
const {
448 const std::vector<unsigned int>& scaleWeightIDs = weightChoice->scaleWeightIDs;
449 const std::vector<unsigned int>& pdfWeightIDs = weightChoice->pdfWeightIDs;
453 double originalXWGTUP = (
weights.size() > 1) ?
weights.at(1) : 1.;
455 std::vector<double> wScale, wPDF, wPS;
456 for (
auto id : scaleWeightIDs)
457 wScale.push_back(
weights.at(
id) / w0);
458 for (
auto id : pdfWeightIDs) {
459 wPDF.push_back(
weights.at(
id) / w0);
465 outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(),
"LHEScaleWeight",
false);
466 outScale->addColumn<
float>(
"", wScale, weightChoice->scaleWeightsDoc,
lheWeightPrecision_);
468 outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(),
"LHEPdfWeight",
false);
471 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(),
"PSWeight",
false);
474 outNamed = std::make_unique<nanoaod::FlatTable>(1,
"LHEWeight",
true);
475 outNamed->addColumnValue<
float>(
"originalXWGTUP", originalXWGTUP,
"Nominal event weight in the LHE file");
480 counter->incLHE(genWeight, wScale, wPDF, std::vector<double>(), std::vector<double>(), wPS);
484 const DynamicWeightChoiceGenInfo* genWeightChoice,
487 std::unique_ptr<nanoaod::FlatTable>& outPS)
const {
488 std::vector<double> wPS;
491 outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(),
"PSWeight",
false);
494 counter->incGenOnly(genWeight);
495 counter->incPSOnly(genWeight, wPS);
499 const DynamicWeightChoiceGenInfo* genWeightChoice,
500 std::vector<double>& wPS,
505 bool isRegularPSSet =
keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46);
506 if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) {
507 psWeightDocStr = genWeightChoice->psWeightsDoc;
508 double psNom = genWeights.at(genWeightChoice->psBaselineID);
509 for (
auto wgtidx : genWeightChoice->psWeightIDs) {
510 wPS.push_back(genWeights.at(wgtidx) / psNom);
514 keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1);
516 if (vectorSize > 1) {
517 double nominal = genWeights.at(1);
519 for (
int i = 0;
i < vectorSize;
i++) {
520 wPS.push_back(genWeights.at(
i + 2) / nominal);
522 psWeightDocStr =
"All PS weights (w_var / w_nominal)";
526 <<
"GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n"
527 <<
" This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt "
529 for (std::size_t
i = 6;
i < 10;
i++) {
530 wPS.push_back(genWeights.at(
i) / nominal);
533 "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2"
534 "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;";
538 psWeightDocStr =
"dummy PS weight (1.0) ";
549 auto weightChoice = std::make_shared<DynamicWeightChoice>();
560 std::vector<ScaleVarWeight> scaleVariationIDs;
561 std::vector<PDFSetWeights> pdfSetWeightIDs;
562 std::vector<std::string> lheReweighingIDs;
563 bool isFirstGroup =
true;
565 std::regex weightgroupmg26x(
"<weightgroup\\s+(?:name|type)=\"(.*)\"\\s+combine=\"(.*)\"\\s*>");
566 std::regex weightgroup(
"<weightgroup\\s+combine=\"(.*)\"\\s+(?:name|type)=\"(.*)\"\\s*>");
567 std::regex weightgroupRwgt(
"<weightgroup\\s+(?:name|type)=\"(.*)\"\\s*>");
568 std::regex endweightgroup(
"</weightgroup>");
569 std::regex scalewmg26x(
570 "<weight\\s+(?:.*\\s+)?id=\"(\\d+)\"\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:[mM][uU][rR]|renscfact)=\"("
571 "\\S+)\"\\s+(?:[mM][uU][Ff]|facscfact)=\"(\\S+)\")(\\s+.*)?</weight>");
572 std::regex scalewmg26xNew(
573 "<weight\\s*((?:[mM][uU][fF]|facscfact)=\"(\\S+)\"\\s+(?:[mM][uU][Rr]|renscfact)=\"(\\S+)\").+id=\"(\\d+)\"(."
578 "<weight\\s+(?:.*\\s+)?id=\"(\\d+|\\d+-NNLOPS)\">\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)"
579 "=(\\S+)\\s+(?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)</weight>");
581 "<weight\\s+id=\"(\\d+)\">\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?</weight>");
582 std::regex pdfwOld(
"<weight\\s+(?:.*\\s+)?id=\"(\\d+)\">\\s*Member \\s*(\\d+)\\s*(?:.*)</weight>");
583 std::regex pdfwmg26x(
584 "<weight\\s+id=\"(\\d+)\"\\s*MUR=\"(?:\\S+)\"\\s*MUF=\"(?:\\S+)\"\\s*(?:PDF "
585 "set|lhapdf|PDF|pdfset)\\s*=\\s*\"(\\d+)\"\\s*>\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
590 std::regex pdfwmg26xNew(
591 "<weight\\s+MUF=\"(?:\\S+)\"\\s*MUR=\"(?:\\S+)\"\\s*PDF=\"(?:\\S+)\"\\s*id=\"(\\S+)\"\\s*>"
592 "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
595 std::regex rwgt(
"<weight\\s+id=\"(.+)\">(.+)?(</weight>)?");
598 if (iter->tag() !=
"initrwgt") {
600 std::cout <<
"Skipping LHE header with tag" << iter->tag() << std::endl;
604 std::cout <<
"Found LHE header with tag" << iter->tag() << std::endl;
605 std::vector<std::string>
lines = iter->lines();
606 bool missed_weightgroup =
608 bool ismg26x =
false;
609 bool ismg26xNew =
false;
612 boost::replace_all(
lines[iLine],
"<",
"<");
613 boost::replace_all(
lines[iLine],
">",
">");
614 if (std::regex_search(
lines[iLine], groups, weightgroupmg26x)) {
616 }
else if (std::regex_search(
lines[iLine], groups, scalewmg26xNew) ||
617 std::regex_search(
lines[iLine], groups, pdfwmg26xNew)) {
624 if (std::regex_search(
lines[iLine], groups, ismg26x ? weightgroupmg26x : weightgroup)) {
627 groupname = groups.str(1);
629 std::cout <<
">>> Looks like the beginning of a weight group for '" << groupname <<
"'" << std::endl;
630 if (groupname.find(
"scale_variation") == 0 || groupname ==
"Central scale variation" || isFirstGroup) {
631 if (lheDebug && groupname.find(
"scale_variation") != 0 && groupname !=
"Central scale variation")
632 std::cout <<
">>> First weight is not scale variation, but assuming is the Central Weight" << std::endl;
634 std::cout <<
">>> Looks like scale variation for theory uncertainties" << std::endl;
635 isFirstGroup =
false;
636 for (++iLine; iLine <
nLines; ++iLine) {
640 if (std::regex_search(
641 lines[iLine], groups, ismg26x ? scalewmg26x : (ismg26xNew ? scalewmg26xNew : scalew))) {
643 std::cout <<
" >>> Scale weight " << groups[1].str() <<
" for " << groups[3].str() <<
" , "
644 << groups[4].str() <<
" , " << groups[5].str() << std::endl;
646 scaleVariationIDs.emplace_back(groups.str(4), groups.str(1), groups.str(3), groups.str(2));
648 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
650 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
652 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
653 if (!missed_weightgroup) {
656 missed_weightgroup =
false;
657 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
659 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
662 if (ismg26x || ismg26xNew)
663 missed_weightgroup =
true;
668 }
else if (groupname ==
"PDF_variation" || groupname.find(
"PDF_variation ") == 0) {
670 std::cout <<
">>> Looks like a new-style block of PDF weights for one or more pdfs" << std::endl;
671 for (++iLine; iLine <
nLines; ++iLine) {
674 if (std::regex_search(
lines[iLine], groups, pdfw)) {
675 unsigned int lhaID = std::stoi(groups.str(2));
677 std::cout <<
" >>> PDF weight " << groups.str(1) <<
" for " << groups.str(2) <<
" = " << lhaID
679 if (pdfSetWeightIDs.empty() || !pdfSetWeightIDs.back().maybe_add(groups.str(1), lhaID)) {
680 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
682 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
684 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
685 if (!missed_weightgroup) {
688 missed_weightgroup =
false;
689 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
691 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
694 if (ismg26x || ismg26xNew)
695 missed_weightgroup =
true;
700 }
else if (groupname ==
"PDF_variation1" || groupname ==
"PDF_variation2") {
702 std::cout <<
">>> Looks like a new-style block of PDF weights for multiple pdfs" << std::endl;
703 unsigned int lastid = 0;
704 for (++iLine; iLine <
nLines; ++iLine) {
707 if (std::regex_search(
lines[iLine], groups, pdfw)) {
708 unsigned int id = std::stoi(groups.str(1));
709 unsigned int lhaID = std::stoi(groups.str(2));
711 std::cout <<
" >>> PDF weight " << groups.str(1) <<
" for " << groups.str(2) <<
" = " << lhaID
713 if (
id != (lastid + 1) || pdfSetWeightIDs.empty()) {
714 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
716 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
719 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
721 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
722 if (!missed_weightgroup) {
725 missed_weightgroup =
false;
726 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
728 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
731 if (ismg26x || ismg26xNew)
732 missed_weightgroup =
true;
739 std::cout <<
">>> Looks like an old-style PDF weight for an individual pdf" << std::endl;
740 unsigned int firstLhaID =
lhaNameToID_.find(groupname)->second;
742 for (++iLine; iLine <
nLines; ++iLine) {
745 if (std::regex_search(
746 lines[iLine], groups, ismg26x ? pdfwmg26x : (ismg26xNew ? pdfwmg26xNew : pdfwOld))) {
747 unsigned int member = 0;
748 if (!ismg26x && !ismg26xNew) {
749 member = std::stoi(groups.str(2));
750 }
else if (ismg26xNew) {
751 if (!groups.str(3).empty()) {
752 member = std::stoi(groups.str(3));
755 if (!groups.str(4).empty()) {
756 member = std::stoi(groups.str(4));
759 unsigned int lhaID = member + firstLhaID;
761 std::cout <<
" >>> PDF weight " << groups.str(1) <<
" for " << member <<
" = " << lhaID
765 pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
768 pdfSetWeightIDs.back().add(groups.str(1), lhaID);
770 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
772 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
773 if (!missed_weightgroup) {
776 missed_weightgroup =
false;
777 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
779 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
782 if (ismg26x || ismg26xNew)
783 missed_weightgroup =
true;
788 }
else if (groupname ==
"mass_variation" || groupname ==
"sthw2_variation" ||
789 groupname ==
"width_variation") {
791 std::cout <<
">>> Looks like an EW parameter weight" << std::endl;
792 for (++iLine; iLine <
nLines; ++iLine) {
795 if (std::regex_search(
lines[iLine], groups, rwgt)) {
798 std::cout <<
" >>> LHE reweighting weight: " << rwgtID << std::endl;
799 if (
std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
801 lheReweighingIDs.emplace_back(rwgtID);
803 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
805 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
809 for (++iLine; iLine <
nLines; ++iLine) {
812 if (std::regex_search(
lines[iLine], groups, endweightgroup)) {
814 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
815 if (!missed_weightgroup) {
818 missed_weightgroup =
false;
819 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
821 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
824 if (ismg26x || ismg26xNew)
825 missed_weightgroup =
true;
831 }
else if (std::regex_search(
lines[iLine], groups, weightgroupRwgt)) {
833 if (groupname ==
"mg_reweighting") {
835 std::cout <<
">>> Looks like a LHE weights for reweighting" << std::endl;
836 for (++iLine; iLine <
nLines; ++iLine) {
839 if (std::regex_search(
lines[iLine], groups, rwgt)) {
842 std::cout <<
" >>> LHE reweighting weight: " << rwgtID << std::endl;
843 if (
std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
845 lheReweighingIDs.emplace_back(rwgtID);
847 }
else if (std::regex_search(
lines[iLine], endweightgroup)) {
849 std::cout <<
">>> Looks like the end of a weight group" << std::endl;
850 if (!missed_weightgroup) {
853 missed_weightgroup =
false;
854 }
else if (std::regex_search(
lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
856 std::cout <<
">>> Looks like the beginning of a new weight group, I will assume I missed the end "
860 missed_weightgroup =
true;
871 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
873 std::cout <<
"Found " << scaleVariationIDs.size() <<
" scale variations: " << std::endl;
874 std::stringstream scaleDoc;
875 scaleDoc <<
"LHE scale variation weights (w_var / w_nominal); ";
876 for (
unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
877 const auto& sw = scaleVariationIDs[isw];
880 scaleDoc <<
"[" << isw <<
"] is " << sw.label;
881 weightChoice->scaleWeightIDs.push_back(sw.wid);
883 printf(
" id %s: scales ren = % .2f fact = % .2f text = %s\n",
889 if (!scaleVariationIDs.empty())
890 weightChoice->scaleWeightsDoc = scaleDoc.str();
894 std::cout <<
"Found " << pdfSetWeightIDs.size() <<
" PDF set errors: " << std::endl;
895 for (
const auto& pw : pdfSetWeightIDs)
896 printf(
"lhaIDs %6d - %6d (%3lu weights: %s, ... )\n",
900 pw.wids.front().c_str());
905 std::cout <<
"Found " << lheReweighingIDs.size() <<
" reweighting weights" << std::endl;
907 std::copy(lheReweighingIDs.begin(), lheReweighingIDs.end(), std::back_inserter(weightChoice->rwgtIDs));
909 std::stringstream pdfDoc;
910 pdfDoc <<
"LHE pdf variation weights (w_var / w_nominal) for LHA IDs ";
912 for (
const auto& pw : pdfSetWeightIDs) {
914 if (pw.lhaIDs.first !=
lhaid && pw.lhaIDs.first != (
lhaid + 1))
916 if (pw.wids.size() == 1)
918 pdfDoc << pw.lhaIDs.first <<
" - " << pw.lhaIDs.second;
919 weightChoice->pdfWeightIDs = pw.wids;
922 pdfDoc <<
", truncated to the first " <<
maxPdfWeights_ <<
" replicas";
924 weightChoice->pdfWeightsDoc = pdfDoc.str();
938 return std::make_unique<LumiCacheInfoHolder>();
942 streamCache(
id)->clear();
947 auto counterMap = &(streamCache(
id)->countermap);
950 if (!genLumiInfoHead.
isValid())
952 <<
"No GenLumiInfoHeader product found, will not fill generator model string.\n";
955 if (genLumiInfoHead.
isValid()) {
957 boost::replace_all(
label,
"-",
"_");
958 boost::replace_all(
label,
"/",
"_");
960 counterMap->setLabel(
label);
962 if (genLumiInfoHead.
isValid()) {
963 auto weightChoice = &(streamCache(
id)->weightChoice);
965 std::vector<ScaleVarWeight> scaleVariationIDs;
966 std::vector<PDFSetWeights> pdfSetWeightIDs;
967 weightChoice->psWeightIDs.clear();
969 std::regex scalew(
"LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)");
970 std::regex pdfw(
"LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)");
971 std::regex mainPSw(
"sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)");
974 std::unordered_map<std::string, uint32_t> knownPDFSetsFromGenInfo_;
975 unsigned int weightIter = 0;
976 for (
const auto&
line : weightNames) {
977 if (std::regex_search(
line, groups, scalew)) {
978 auto id = groups.str(1);
979 auto group = groups.str(2);
980 auto mur = groups.str(3);
981 auto muf = groups.str(4);
982 if (
group.find(
"Central scale variation") != std::string::npos)
983 scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
984 }
else if (std::regex_search(
line, groups, pdfw)) {
985 auto id = groups.str(1);
986 auto group = groups.str(2);
987 auto memberid = groups.str(3);
988 auto pdfset = groups.str(4);
989 if (
group.find(pdfset) != std::string::npos) {
990 if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) {
991 knownPDFSetsFromGenInfo_[pdfset] = std::atoi(
id.c_str());
992 pdfSetWeightIDs.emplace_back(
id, std::atoi(
id.c_str()));
994 pdfSetWeightIDs.back().add(
id, std::atoi(
id.c_str()));
996 }
else if (
line ==
"Baseline") {
997 weightChoice->psBaselineID = weightIter;
998 }
else if (
line.find(
"isr") != std::string::npos ||
line.find(
"fsr") != std::string::npos) {
999 weightChoice->matchPS_alt =
line.find(
"sr:") != std::string::npos;
1001 weightChoice->psWeightIDs.push_back(weightIter);
1002 }
else if (std::regex_search(
line, groups, mainPSw)) {
1003 if (weightChoice->psWeightIDs.empty())
1004 weightChoice->psWeightIDs = std::vector<unsigned int>(4, -1);
1005 int psIdx = (
line.find(
"fsr") != std::string::npos) ? 1 : 0;
1006 psIdx += (groups.str(2) ==
"Hi" || groups.str(2) ==
"_up" || groups.str(2) ==
"2.0") ? 0 : 2;
1007 weightChoice->psWeightIDs[psIdx] = weightIter;
1013 weightChoice->psWeightsDoc =
"All PS weights (w_var / w_nominal)";
1014 }
else if (weightChoice->psWeightIDs.size() == 4) {
1015 weightChoice->psWeightsDoc =
1016 "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2"
1017 "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;";
1018 for (
int i = 0;
i < 4;
i++) {
1019 if (static_cast<int>(weightChoice->psWeightIDs[
i]) == -1)
1020 weightChoice->setMissingWeight(
i);
1023 weightChoice->psWeightsDoc =
"dummy PS weight (1.0) ";
1026 weightChoice->scaleWeightIDs.clear();
1027 weightChoice->pdfWeightIDs.clear();
1029 std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
1030 std::stringstream scaleDoc;
1031 scaleDoc <<
"LHE scale variation weights (w_var / w_nominal); ";
1032 for (
unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
1033 const auto& sw = scaleVariationIDs[isw];
1036 scaleDoc <<
"[" << isw <<
"] is " << sw.label;
1037 weightChoice->scaleWeightIDs.push_back(std::atoi(sw.wid.c_str()));
1039 if (!scaleVariationIDs.empty())
1040 weightChoice->scaleWeightsDoc = scaleDoc.str();
1041 std::stringstream pdfDoc;
1042 pdfDoc <<
"LHE pdf variation weights (w_var / w_nominal) for LHA names ";
1044 for (
const auto& pw : pdfSetWeightIDs) {
1045 if (pw.wids.size() == 1)
1048 auto pdfname = wantedpdf.first;
1049 if (knownPDFSetsFromGenInfo_.find(pdfname) == knownPDFSetsFromGenInfo_.end())
1051 uint32_t
lhaid = knownPDFSetsFromGenInfo_.at(pdfname);
1052 if (pw.lhaIDs.first !=
lhaid)
1055 for (
const auto&
x : pw.wids)
1056 weightChoice->pdfWeightIDs.push_back(std::atoi(
x.c_str()));
1059 pdfDoc <<
", truncated to the first " <<
maxPdfWeights_ <<
" replicas";
1061 weightChoice->pdfWeightsDoc = pdfDoc.str();
1072 return std::make_shared<CounterMap>();
1078 CounterMap* runCounterMap)
const override {
1079 runCounterMap->merge(streamCache(
id)->countermap);
1085 auto out = std::make_unique<nanoaod::MergeableCounterTable>();
1087 for (
const auto&
x : runCounterMap->countermap) {
1088 auto runCounter = &(
x.second);
1092 out->addInt(
"genEventCount" +
label,
"event count" + doclabel, runCounter->num);
1093 out->addFloat(
"genEventSumw" +
label,
"sum of gen weights" + doclabel, runCounter->sumw);
1094 out->addFloat(
"genEventSumw2" +
label,
"sum of gen (weight^2)" + doclabel, runCounter->sumw2);
1096 double norm = runCounter->sumw ? 1.0 / runCounter->sumw : 1;
1097 auto sumScales = runCounter->sumScale;
1098 for (
auto&
val : sumScales)
1100 out->addVFloatWithNorm(
"LHEScaleSumw" +
label,
1101 "Sum of genEventWeight * LHEScaleWeight[i], divided by genEventSumw" + doclabel,
1104 auto sumPDFs = runCounter->sumPDF;
1105 for (
auto&
val : sumPDFs)
1107 out->addVFloatWithNorm(
"LHEPdfSumw" +
label,
1108 "Sum of genEventWeight * LHEPdfWeight[i], divided by genEventSumw" + doclabel,
1111 if (!runCounter->sumRwgt.empty()) {
1112 auto sumRwgts = runCounter->sumRwgt;
1113 for (
auto&
val : sumRwgts)
1115 out->addVFloatWithNorm(
"LHEReweightingSumw" +
label,
1116 "Sum of genEventWeight * LHEReweightingWeight[i], divided by genEventSumw" + doclabel,
1120 if (!runCounter->sumNamed.empty()) {
1122 out->addFloatWithNorm(
1124 "Sum of genEventWeight * LHEWeight_" +
namedWeightLabels_[
i] +
", divided by genEventSumw" + doclabel,
1125 runCounter->sumNamed[
i] * norm,
1138 ->setComment(
"tag for the GenEventInfoProduct, to get the main weight");
1140 ->setComment(
"tag for the GenLumiInfoProduct, to get the model string");
1141 desc.add<std::vector<edm::InputTag>>(
"lheInfo", std::vector<edm::InputTag>{{
"externalLHEProducer"}, {
"source"}})
1142 ->setComment(
"tag(s) for the LHE information (LHEEventProduct and LHERunInfoProduct)");
1146 prefpdf.
add<uint32_t>(
"lhaid");
1147 desc.addVPSet(
"preferredPDFs", prefpdf, std::vector<edm::ParameterSet>())
1149 "LHA PDF Ids of the preferred PDF sets, in order of preference (the first matching one will be used)");
1150 desc.add<std::vector<std::string>>(
"namedWeightIDs")->setComment(
"set of LHA weight IDs for named LHE weights");
1151 desc.add<std::vector<std::string>>(
"namedWeightLabels")
1152 ->setComment(
"output names for the namedWeightIDs (in the same order)");
1153 desc.add<int32_t>(
"lheWeightPrecision")->setComment(
"Number of bits in the mantissa for LHE weights");
1154 desc.add<uint32_t>(
"maxPdfWeights")->setComment(
"Maximum number of PDF weights to save (to crop NN replicas)");
1155 desc.add<
bool>(
"keepAllPSWeights")->setComment(
"Store all PS weights found");
1156 desc.addOptionalUntracked<
bool>(
"debug")->setComment(
"dump out all LHE information for one event");
1157 descriptions.
add(
"genWeightsTable",
desc);
1163 const std::vector<edm::EDGetTokenT<LHEEventProduct>>
lheTag_;
1164 const std::vector<edm::EDGetTokenT<LHERunInfoProduct>>
lheRunTag_;