CMS 3D CMS Logo

GenWeightsTableProducer.cc
Go to the documentation of this file.
15 #include "boost/algorithm/string.hpp"
16 
17 #include <array>
18 #include <memory>
19 
20 #include <vector>
21 #include <unordered_map>
22 #include <iostream>
23 #include <regex>
24 
25 namespace {
27  struct Counter {
28  Counter() : num(0), sumw(0), sumw2(0), sumPDF(), sumScale(), sumRwgt(), sumNamed(), sumPS() {}
29 
30  // the counters
31  long long num;
32  long double sumw;
33  long double sumw2;
34  std::vector<long double> sumPDF, sumScale, sumRwgt, sumNamed, sumPS;
35 
36  void clear() {
37  num = 0;
38  sumw = 0;
39  sumw2 = 0;
40  sumPDF.clear();
41  sumScale.clear();
42  sumRwgt.clear();
43  sumNamed.clear(), sumPS.clear();
44  }
45 
46  // inc the counters
47  void incGenOnly(double w) {
48  num++;
49  sumw += w;
50  sumw2 += (w * w);
51  }
52 
53  void incPSOnly(double w0, const std::vector<double>& wPS) {
54  if (!wPS.empty()) {
55  if (sumPS.empty())
56  sumPS.resize(wPS.size(), 0);
57  for (unsigned int i = 0, n = wPS.size(); i < n; ++i)
58  sumPS[i] += (w0 * wPS[i]);
59  }
60  }
61 
62  void incLHE(double w0,
63  const std::vector<double>& wScale,
64  const std::vector<double>& wPDF,
65  const std::vector<double>& wRwgt,
66  const std::vector<double>& wNamed,
67  const std::vector<double>& wPS) {
68  // add up weights
69  incGenOnly(w0);
70  // then add up variations
71  if (!wScale.empty()) {
72  if (sumScale.empty())
73  sumScale.resize(wScale.size(), 0);
74  for (unsigned int i = 0, n = wScale.size(); i < n; ++i)
75  sumScale[i] += (w0 * wScale[i]);
76  }
77  if (!wPDF.empty()) {
78  if (sumPDF.empty())
79  sumPDF.resize(wPDF.size(), 0);
80  for (unsigned int i = 0, n = wPDF.size(); i < n; ++i)
81  sumPDF[i] += (w0 * wPDF[i]);
82  }
83  if (!wRwgt.empty()) {
84  if (sumRwgt.empty())
85  sumRwgt.resize(wRwgt.size(), 0);
86  for (unsigned int i = 0, n = wRwgt.size(); i < n; ++i)
87  sumRwgt[i] += (w0 * wRwgt[i]);
88  }
89  if (!wNamed.empty()) {
90  if (sumNamed.empty())
91  sumNamed.resize(wNamed.size(), 0);
92  for (unsigned int i = 0, n = wNamed.size(); i < n; ++i)
93  sumNamed[i] += (w0 * wNamed[i]);
94  }
95  incPSOnly(w0, wPS);
96  }
97 
98  void merge(const Counter& other) {
99  num += other.num;
100  sumw += other.sumw;
101  sumw2 += other.sumw2;
102  if (sumScale.empty() && !other.sumScale.empty())
103  sumScale.resize(other.sumScale.size(), 0);
104  if (sumPDF.empty() && !other.sumPDF.empty())
105  sumPDF.resize(other.sumPDF.size(), 0);
106  if (sumRwgt.empty() && !other.sumRwgt.empty())
107  sumRwgt.resize(other.sumRwgt.size(), 0);
108  if (sumNamed.empty() && !other.sumNamed.empty())
109  sumNamed.resize(other.sumNamed.size(), 0);
110  if (sumPS.empty() && !other.sumPS.empty())
111  sumPS.resize(other.sumPS.size(), 0);
112  if (!other.sumScale.empty())
113  for (unsigned int i = 0, n = sumScale.size(); i < n; ++i)
114  sumScale[i] += other.sumScale[i];
115  if (!other.sumPDF.empty())
116  for (unsigned int i = 0, n = sumPDF.size(); i < n; ++i)
117  sumPDF[i] += other.sumPDF[i];
118  if (!other.sumRwgt.empty())
119  for (unsigned int i = 0, n = sumRwgt.size(); i < n; ++i)
120  sumRwgt[i] += other.sumRwgt[i];
121  if (!other.sumNamed.empty())
122  for (unsigned int i = 0, n = sumNamed.size(); i < n; ++i)
123  sumNamed[i] += other.sumNamed[i];
124  if (!other.sumPS.empty())
125  for (unsigned int i = 0, n = sumPS.size(); i < n; ++i)
126  sumPS[i] += other.sumPS[i];
127  }
128  };
129 
130  struct CounterMap {
131  std::map<std::string, Counter> countermap;
132  Counter* active_el = nullptr;
133  std::string active_label = "";
134  void merge(const CounterMap& other) {
135  for (const auto& y : other.countermap)
136  countermap[y.first].merge(y.second);
137  active_el = nullptr;
138  }
139  void clear() {
140  for (auto x : countermap)
141  x.second.clear();
142  active_el = nullptr;
143  active_label = "";
144  }
145  void setLabel(std::string label) {
146  active_el = &(countermap[label]);
147  active_label = label;
148  }
149  void checkLabelSet() {
150  if (!active_el)
151  throw cms::Exception("LogicError", "Called CounterMap::get() before setting the active label\n");
152  }
153  Counter* get() {
154  checkLabelSet();
155  return active_el;
156  }
157  std::string& getLabel() {
158  checkLabelSet();
159  return active_label;
160  }
161  };
162 
164  struct DynamicWeightChoice {
165  // choice of LHE weights
166  // ---- scale ----
167  std::vector<std::string> scaleWeightIDs;
168  std::string scaleWeightsDoc;
169  // ---- pdf ----
170  std::vector<std::string> pdfWeightIDs;
171  std::string pdfWeightsDoc;
172  // ---- rwgt ----
173  std::vector<std::string> rwgtIDs;
174  std::string rwgtWeightDoc;
175  };
176 
177  constexpr std::array<unsigned int, 4> defPSWeightIDs = {{6, 7, 8, 9}};
178  constexpr std::array<unsigned int, 4> defPSWeightIDs_alt = {{27, 5, 26, 4}};
179 
180  struct DynamicWeightChoiceGenInfo {
181  // choice of LHE weights
182  // ---- scale ----
183  std::vector<unsigned int> scaleWeightIDs;
184  std::string scaleWeightsDoc;
185  // ---- pdf ----
186  std::vector<unsigned int> pdfWeightIDs;
187  std::string pdfWeightsDoc;
188  // ---- ps ----
189  bool matchPS_alt = false;
190  std::vector<unsigned int> psWeightIDs;
191  unsigned int psBaselineID = 1;
192  std::string psWeightsDoc;
193 
194  void setMissingWeight(int idx) { psWeightIDs[idx] = (matchPS_alt) ? defPSWeightIDs_alt[idx] : defPSWeightIDs[idx]; }
195 
196  bool empty() const { return scaleWeightIDs.empty() && pdfWeightIDs.empty() && psWeightIDs.empty(); }
197  };
198 
199  struct LumiCacheInfoHolder {
200  CounterMap countermap;
201  void clear() { countermap.clear(); }
202  };
203 
204  float stof_fortrancomp(const std::string& str) {
205  std::string::size_type match = str.find('d');
206  if (match != std::string::npos) {
207  std::string pre = str.substr(0, match);
208  std::string post = str.substr(match + 1);
209  return std::stof(pre) * std::pow(10.0f, std::stof(post));
210  } else {
211  return std::stof(str);
212  }
213  }
215  struct ScaleVarWeight {
216  std::string wid, label;
217  std::pair<float, float> scales;
218  ScaleVarWeight(const std::string& id, const std::string& text, const std::string& muR, const std::string& muF)
219  : wid(id), label(text), scales(stof_fortrancomp(muR), stof_fortrancomp(muF)) {}
220  bool operator<(const ScaleVarWeight& other) {
221  return (scales == other.scales ? wid < other.wid : scales < other.scales);
222  }
223  };
224  struct PDFSetWeights {
225  std::vector<std::string> wids;
226  std::pair<unsigned int, unsigned int> lhaIDs;
227  PDFSetWeights(const std::string& wid, unsigned int lhaID) : wids(1, wid), lhaIDs(lhaID, lhaID) {}
228  bool operator<(const PDFSetWeights& other) const { return lhaIDs < other.lhaIDs; }
229  void add(const std::string& wid, unsigned int lhaID) {
230  wids.push_back(wid);
231  lhaIDs.second = lhaID;
232  }
233  bool maybe_add(const std::string& wid, unsigned int lhaID) {
234  if (lhaID == lhaIDs.second + 1) {
235  lhaIDs.second++;
236  wids.push_back(wid);
237  return true;
238  } else {
239  return false;
240  }
241  }
242  };
243 } // namespace
244 
245 class GenWeightsTableProducer : public edm::global::EDProducer<edm::StreamCache<LumiCacheInfoHolder>,
246  edm::RunCache<DynamicWeightChoice>,
247  edm::LuminosityBlockCache<DynamicWeightChoiceGenInfo>,
248  edm::RunSummaryCache<CounterMap>,
249  edm::EndRunProducer> {
250 public:
252  : genTag_(consumes<GenEventInfoProduct>(params.getParameter<edm::InputTag>("genEvent"))),
253  lheLabel_(params.getParameter<std::vector<edm::InputTag>>("lheInfo")),
255  [this](const edm::InputTag& tag) { return mayConsume<LHEEventProduct>(tag); })),
257  lheLabel_, [this](const edm::InputTag& tag) { return mayConsume<LHERunInfoProduct, edm::InRun>(tag); })),
259  mayConsume<GenLumiInfoHeader, edm::InLumi>(params.getParameter<edm::InputTag>("genLumiInfoHeader"))),
260  namedWeightIDs_(params.getParameter<std::vector<std::string>>("namedWeightIDs")),
261  namedWeightLabels_(params.getParameter<std::vector<std::string>>("namedWeightLabels")),
262  lheWeightPrecision_(params.getParameter<int32_t>("lheWeightPrecision")),
263  maxPdfWeights_(params.getParameter<uint32_t>("maxPdfWeights")),
264  keepAllPSWeights_(params.getParameter<bool>("keepAllPSWeights")),
265  debug_(params.getUntrackedParameter<bool>("debug", false)),
266  debugRun_(debug_.load()),
267  hasIssuedWarning_(false),
268  psWeightWarning_(false) {
269  produces<nanoaod::FlatTable>();
270  produces<std::string>("genModel");
271  produces<nanoaod::FlatTable>("LHEScale");
272  produces<nanoaod::FlatTable>("LHEPdf");
273  produces<nanoaod::FlatTable>("LHEReweighting");
274  produces<nanoaod::FlatTable>("LHENamed");
275  produces<nanoaod::FlatTable>("PS");
276  produces<nanoaod::MergeableCounterTable, edm::Transition::EndRun>();
277  if (namedWeightIDs_.size() != namedWeightLabels_.size()) {
278  throw cms::Exception("Configuration", "Size mismatch between namedWeightIDs & namedWeightLabels");
279  }
280  for (const edm::ParameterSet& pdfps : params.getParameter<std::vector<edm::ParameterSet>>("preferredPDFs")) {
281  const std::string& name = pdfps.getParameter<std::string>("name");
282  uint32_t lhaid = pdfps.getParameter<uint32_t>("lhaid");
283  preferredPDFLHAIDs_.push_back(lhaid);
285  lhaNameToID_[name + ".LHgrid"] = lhaid;
286  }
287  }
288 
290 
291  void produce(edm::StreamID id, edm::Event& iEvent, const edm::EventSetup& iSetup) const override {
292  // get my counter for weights
293  Counter* counter = streamCache(id)->countermap.get();
294 
295  // generator information (always available)
297  iEvent.getByToken(genTag_, genInfo);
298  double weight = genInfo->weight();
299 
300  // table for gen info, always available
301  auto out = std::make_unique<nanoaod::FlatTable>(1, "genWeight", true);
302  out->setDoc("generator weight");
303  out->addColumnValue<float>("", weight, "generator weight");
304  iEvent.put(std::move(out));
305 
306  std::string model_label = streamCache(id)->countermap.getLabel();
307  auto outM = std::make_unique<std::string>((!model_label.empty()) ? std::string("GenModel_") + model_label : "");
308  iEvent.put(std::move(outM), "genModel");
309  bool getLHEweightsFromGenInfo = !model_label.empty();
310 
311  // tables for LHE weights, may not be filled
312  std::unique_ptr<nanoaod::FlatTable> lheScaleTab, lhePdfTab, lheRwgtTab, lheNamedTab;
313  std::unique_ptr<nanoaod::FlatTable> genPSTab;
314 
316  for (const auto& lheTag : lheTag_) {
317  iEvent.getByToken(lheTag, lheInfo);
318  if (lheInfo.isValid()) {
319  break;
320  }
321  }
322 
323  const auto genWeightChoice = luminosityBlockCache(iEvent.getLuminosityBlock().index());
324  if (lheInfo.isValid()) {
325  if (getLHEweightsFromGenInfo && !hasIssuedWarning_.exchange(true))
326  edm::LogWarning("LHETablesProducer")
327  << "Found both a LHEEventProduct and a GenLumiInfoHeader: will only save weights from LHEEventProduct.\n";
328  // get the dynamic choice of weights
329  const DynamicWeightChoice* weightChoice = runCache(iEvent.getRun().index());
330  // go fill tables
332  weightChoice,
333  genWeightChoice,
334  weight,
335  *lheInfo,
336  *genInfo,
337  lheScaleTab,
338  lhePdfTab,
339  lheRwgtTab,
340  lheNamedTab,
341  genPSTab);
342  } else if (getLHEweightsFromGenInfo) {
344  counter, genWeightChoice, weight, *genInfo, lheScaleTab, lhePdfTab, lheNamedTab, genPSTab);
345  lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
346  //lheNamedTab.reset(new nanoaod::FlatTable(1, "LHENamedWeights", true));
347  //genPSTab.reset(new nanoaod::FlatTable(1, "PSWeight", true));
348  } else {
349  // Still try to add the PS weights
350  fillOnlyPSWeightTable(counter, genWeightChoice, weight, *genInfo, genPSTab);
351  // make dummy values
352  lheScaleTab = std::make_unique<nanoaod::FlatTable>(1, "LHEScaleWeights", true);
353  lhePdfTab = std::make_unique<nanoaod::FlatTable>(1, "LHEPdfWeights", true);
354  lheRwgtTab = std::make_unique<nanoaod::FlatTable>(1, "LHEReweightingWeights", true);
355  lheNamedTab = std::make_unique<nanoaod::FlatTable>(1, "LHENamedWeights", true);
356  if (!hasIssuedWarning_.exchange(true)) {
357  edm::LogWarning("LHETablesProducer") << "No LHEEventProduct, so there will be no LHE Tables\n";
358  }
359  }
360 
361  iEvent.put(std::move(lheScaleTab), "LHEScale");
362  iEvent.put(std::move(lhePdfTab), "LHEPdf");
363  iEvent.put(std::move(lheRwgtTab), "LHEReweighting");
364  iEvent.put(std::move(lheNamedTab), "LHENamed");
365  iEvent.put(std::move(genPSTab), "PS");
366  }
367 
369  const DynamicWeightChoice* weightChoice,
370  const DynamicWeightChoiceGenInfo* genWeightChoice,
371  double genWeight,
372  const LHEEventProduct& lheProd,
373  const GenEventInfoProduct& genProd,
374  std::unique_ptr<nanoaod::FlatTable>& outScale,
375  std::unique_ptr<nanoaod::FlatTable>& outPdf,
376  std::unique_ptr<nanoaod::FlatTable>& outRwgt,
377  std::unique_ptr<nanoaod::FlatTable>& outNamed,
378  std::unique_ptr<nanoaod::FlatTable>& outPS) const {
379  bool lheDebug = debug_.exchange(
380  false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind)
381 
382  const std::vector<std::string>& scaleWeightIDs = weightChoice->scaleWeightIDs;
383  const std::vector<std::string>& pdfWeightIDs = weightChoice->pdfWeightIDs;
384  const std::vector<std::string>& rwgtWeightIDs = weightChoice->rwgtIDs;
385 
386  double w0 = lheProd.originalXWGTUP();
387 
388  std::vector<double> wScale(scaleWeightIDs.size(), 1), wPDF(pdfWeightIDs.size(), 1), wRwgt(rwgtWeightIDs.size(), 1),
389  wNamed(namedWeightIDs_.size(), 1);
390  for (auto& weight : lheProd.weights()) {
391  if (lheDebug)
392  printf("Weight %+9.5f rel %+9.5f for id %s\n", weight.wgt, weight.wgt / w0, weight.id.c_str());
393  // now we do it slowly, can be optimized
394  auto mScale = std::find(scaleWeightIDs.begin(), scaleWeightIDs.end(), weight.id);
395  if (mScale != scaleWeightIDs.end())
396  wScale[mScale - scaleWeightIDs.begin()] = weight.wgt / w0;
397 
398  auto mPDF = std::find(pdfWeightIDs.begin(), pdfWeightIDs.end(), weight.id);
399  if (mPDF != pdfWeightIDs.end())
400  wPDF[mPDF - pdfWeightIDs.begin()] = weight.wgt / w0;
401 
402  auto mRwgt = std::find(rwgtWeightIDs.begin(), rwgtWeightIDs.end(), weight.id);
403  if (mRwgt != rwgtWeightIDs.end())
404  wRwgt[mRwgt - rwgtWeightIDs.begin()] = weight.wgt / w0;
405 
406  auto mNamed = std::find(namedWeightIDs_.begin(), namedWeightIDs_.end(), weight.id);
407  if (mNamed != namedWeightIDs_.end())
408  wNamed[mNamed - namedWeightIDs_.begin()] = weight.wgt / w0;
409  }
410 
411  std::vector<double> wPS;
412  std::string psWeightDocStr;
413  setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
414 
415  outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
416  outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
417 
418  outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
419  outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
420 
421  outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
422  outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
423 
424  outRwgt = std::make_unique<nanoaod::FlatTable>(wRwgt.size(), "LHEReweightingWeight", false);
425  outRwgt->addColumn<float>("", wRwgt, weightChoice->rwgtWeightDoc, lheWeightPrecision_);
426 
427  outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
428  outNamed->addColumnValue<float>("originalXWGTUP", lheProd.originalXWGTUP(), "Nominal event weight in the LHE file");
429  for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) {
430  outNamed->addColumnValue<float>(namedWeightLabels_[i],
431  wNamed[i],
432  "LHE weight for id " + namedWeightIDs_[i] + ", relative to nominal",
434  }
435 
436  counter->incLHE(genWeight, wScale, wPDF, wRwgt, wNamed, wPS);
437  }
438 
440  const DynamicWeightChoiceGenInfo* weightChoice,
441  double genWeight,
442  const GenEventInfoProduct& genProd,
443  std::unique_ptr<nanoaod::FlatTable>& outScale,
444  std::unique_ptr<nanoaod::FlatTable>& outPdf,
445  std::unique_ptr<nanoaod::FlatTable>& outNamed,
446  std::unique_ptr<nanoaod::FlatTable>& outPS) const {
447  const std::vector<unsigned int>& scaleWeightIDs = weightChoice->scaleWeightIDs;
448  const std::vector<unsigned int>& pdfWeightIDs = weightChoice->pdfWeightIDs;
449 
450  auto weights = genProd.weights();
451  double w0 = (weights.size() > 1) ? weights.at(1) : 1.;
452  double originalXWGTUP = (weights.size() > 1) ? weights.at(1) : 1.;
453 
454  std::vector<double> wScale, wPDF, wPS;
455  for (auto id : scaleWeightIDs)
456  wScale.push_back(weights.at(id) / w0);
457  for (auto id : pdfWeightIDs) {
458  wPDF.push_back(weights.at(id) / w0);
459  }
460 
461  std::string psWeightsDocStr;
462  setPSWeightInfo(genProd.weights(), weightChoice, wPS, psWeightsDocStr);
463 
464  outScale = std::make_unique<nanoaod::FlatTable>(wScale.size(), "LHEScaleWeight", false);
465  outScale->addColumn<float>("", wScale, weightChoice->scaleWeightsDoc, lheWeightPrecision_);
466 
467  outPdf = std::make_unique<nanoaod::FlatTable>(wPDF.size(), "LHEPdfWeight", false);
468  outPdf->addColumn<float>("", wPDF, weightChoice->pdfWeightsDoc, lheWeightPrecision_);
469 
470  outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
471  outPS->addColumn<float>("", wPS, psWeightsDocStr, lheWeightPrecision_);
472 
473  outNamed = std::make_unique<nanoaod::FlatTable>(1, "LHEWeight", true);
474  outNamed->addColumnValue<float>("originalXWGTUP", originalXWGTUP, "Nominal event weight in the LHE file");
475  /*for (unsigned int i = 0, n = wNamed.size(); i < n; ++i) {
476  outNamed->addColumnValue<float>(namedWeightLabels_[i], wNamed[i], "LHE weight for id "+namedWeightIDs_[i]+", relative to nominal", lheWeightPrecision_);
477  }*/
478 
479  counter->incLHE(genWeight, wScale, wPDF, std::vector<double>(), std::vector<double>(), wPS);
480  }
481 
483  const DynamicWeightChoiceGenInfo* genWeightChoice,
484  double genWeight,
485  const GenEventInfoProduct& genProd,
486  std::unique_ptr<nanoaod::FlatTable>& outPS) const {
487  std::vector<double> wPS;
488  std::string psWeightDocStr;
489  setPSWeightInfo(genProd.weights(), genWeightChoice, wPS, psWeightDocStr);
490  outPS = std::make_unique<nanoaod::FlatTable>(wPS.size(), "PSWeight", false);
491  outPS->addColumn<float>("", wPS, psWeightDocStr, lheWeightPrecision_);
492 
493  counter->incGenOnly(genWeight);
494  counter->incPSOnly(genWeight, wPS);
495  }
496 
497  void setPSWeightInfo(const std::vector<double>& genWeights,
498  const DynamicWeightChoiceGenInfo* genWeightChoice,
499  std::vector<double>& wPS,
500  std::string& psWeightDocStr) const {
501  wPS.clear();
502  // isRegularPSSet = keeping all weights and the weights are a usual size, ie
503  // all weights are PS weights (don't use header incase missing names)
504  bool isRegularPSSet = keepAllPSWeights_ && (genWeights.size() == 14 || genWeights.size() == 46);
505  if (!genWeightChoice->psWeightIDs.empty() && !isRegularPSSet) {
506  psWeightDocStr = genWeightChoice->psWeightsDoc;
507  double psNom = genWeights.at(genWeightChoice->psBaselineID);
508  for (auto wgtidx : genWeightChoice->psWeightIDs) {
509  wPS.push_back(genWeights.at(wgtidx) / psNom);
510  }
511  } else {
512  int vectorSize =
513  keepAllPSWeights_ ? (genWeights.size() - 2) : ((genWeights.size() == 14 || genWeights.size() == 46) ? 4 : 1);
514 
515  if (vectorSize > 1) {
516  double nominal = genWeights.at(1); // Called 'Baseline' in GenLumiInfoHeader
517  if (keepAllPSWeights_) {
518  for (int i = 0; i < vectorSize; i++) {
519  wPS.push_back(genWeights.at(i + 2) / nominal);
520  }
521  psWeightDocStr = "All PS weights (w_var / w_nominal)";
522  } else {
523  if (!psWeightWarning_.exchange(true))
524  edm::LogWarning("LHETablesProducer")
525  << "GenLumiInfoHeader not found: Central PartonShower weights will fill with the 6-10th entries \n"
526  << " This may incorrect for some mcs (madgraph 2.6.1 with its `isr:murfact=0.5` have a differnt "
527  "order )";
528  for (std::size_t i = 6; i < 10; i++) {
529  wPS.push_back(genWeights.at(i) / nominal);
530  }
531  psWeightDocStr =
532  "PS weights (w_var / w_nominal); [0] is ISR=2 FSR=1; [1] is ISR=1 FSR=2"
533  "[2] is ISR=0.5 FSR=1; [3] is ISR=1 FSR=0.5;";
534  }
535  } else {
536  wPS.push_back(1.0);
537  psWeightDocStr = "dummy PS weight (1.0) ";
538  }
539  }
540  }
541 
542  // create an empty counter
543  std::shared_ptr<DynamicWeightChoice> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&) const override {
545 
546  bool lheDebug = debugRun_.exchange(
547  false); // make sure only the first thread dumps out this (even if may still be mixed up with other output, but nevermind)
548  auto weightChoice = std::make_shared<DynamicWeightChoice>();
549 
550  // getByToken throws since we're not in the endRun (see https://github.com/cms-sw/cmssw/pull/18499)
551  //if (iRun.getByToken(lheRunTag_, lheInfo)) {
552  for (const auto& lheLabel : lheLabel_) {
553  iRun.getByLabel(lheLabel, lheInfo);
554  if (lheInfo.isValid()) {
555  break;
556  }
557  }
558  if (lheInfo.isValid()) {
559  std::vector<ScaleVarWeight> scaleVariationIDs;
560  std::vector<PDFSetWeights> pdfSetWeightIDs;
561  std::vector<std::string> lheReweighingIDs;
562  bool isFirstGroup = true;
563 
564  std::regex weightgroupmg26x("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s+combine=\"(.*)\"\\s*>");
565  std::regex weightgroup("<weightgroup\\s+combine=\"(.*)\"\\s+(?:name|type)=\"(.*)\"\\s*>");
566  std::regex weightgroupRwgt("<weightgroup\\s+(?:name|type)=\"(.*)\"\\s*>");
567  std::regex endweightgroup("</weightgroup>");
568  std::regex scalewmg26x(
569  "<weight\\s+(?:.*\\s+)?id=\"(\\d+)\"\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:[mM][uU][rR]|renscfact)=\"("
570  "\\S+)\"\\s+(?:[mM][uU][Ff]|facscfact)=\"(\\S+)\")(\\s+.*)?</weight>");
571  std::regex scalewmg26xNew(
572  "<weight\\s*((?:[mM][uU][fF]|facscfact)=\"(\\S+)\"\\s+(?:[mM][uU][Rr]|renscfact)=\"(\\S+)\").+id=\"(\\d+)\"(."
573  "*)?</weight>");
574 
575  //<weight MUF="1.0" MUR="2.0" PDF="306000" id="1006"> MUR=2.0 </weight>
576  std::regex scalew(
577  "<weight\\s+(?:.*\\s+)?id=\"(\\d+|\\d+-NNLOPS)\">\\s*(?:lhapdf=\\d+|dyn=\\s*-?\\d+)?\\s*((?:mu[rR]|renscfact)"
578  "=(\\S+)\\s+(?:mu[Ff]|facscfact)=(\\S+)(\\s+.*)?)</weight>");
579  std::regex pdfw(
580  "<weight\\s+id=\"(\\d+)\">\\s*(?:PDF set|lhapdf|PDF|pdfset)\\s*=\\s*(\\d+)\\s*(?:\\s.*)?</weight>");
581  std::regex pdfwOld("<weight\\s+(?:.*\\s+)?id=\"(\\d+)\">\\s*Member \\s*(\\d+)\\s*(?:.*)</weight>");
582  std::regex pdfwmg26x(
583  "<weight\\s+id=\"(\\d+)\"\\s*MUR=\"(?:\\S+)\"\\s*MUF=\"(?:\\S+)\"\\s*(?:PDF "
584  "set|lhapdf|PDF|pdfset)\\s*=\\s*\"(\\d+)\"\\s*>\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
585  "weight>");
586  //<weightgroup combine="symmhessian+as" name="NNPDF31_nnlo_as_0118_mc_hessian_pdfas">
587 
588  //<weight MUF="1.0" MUR="1.0" PDF="325300" id="1048"> PDF=325300 MemberID=0 </weight>
589  std::regex pdfwmg26xNew(
590  "<weight\\s+MUF=\"(?:\\S+)\"\\s*MUR=\"(?:\\S+)\"\\s*PDF=\"(?:\\S+)\"\\s*id=\"(\\S+)\"\\s*>"
591  "\\s*(?:PDF=(\\d+)\\s*MemberID=(\\d+))?\\s*(?:\\s.*)?</"
592  "weight>");
593 
594  std::regex rwgt("<weight\\s+id=\"(.+)\">(.+)?(</weight>)?");
595  std::smatch groups;
596  for (auto iter = lheInfo->headers_begin(), end = lheInfo->headers_end(); iter != end; ++iter) {
597  if (iter->tag() != "initrwgt") {
598  if (lheDebug)
599  std::cout << "Skipping LHE header with tag" << iter->tag() << std::endl;
600  continue;
601  }
602  if (lheDebug)
603  std::cout << "Found LHE header with tag" << iter->tag() << std::endl;
604  std::vector<std::string> lines = iter->lines();
605  bool missed_weightgroup =
606  false; //Needed because in some of the samples ( produced with MG26X ) a small part of the header info is ordered incorrectly
607  bool ismg26x = false;
608  bool ismg26xNew = false;
609  for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines;
610  ++iLine) { //First start looping through the lines to see which weightgroup pattern is matched
611  boost::replace_all(lines[iLine], "&lt;", "<");
612  boost::replace_all(lines[iLine], "&gt;", ">");
613  if (std::regex_search(lines[iLine], groups, weightgroupmg26x)) {
614  ismg26x = true;
615  } else if (std::regex_search(lines[iLine], groups, scalewmg26xNew) ||
616  std::regex_search(lines[iLine], groups, pdfwmg26xNew)) {
617  ismg26xNew = true;
618  }
619  }
620  for (unsigned int iLine = 0, nLines = lines.size(); iLine < nLines; ++iLine) {
621  if (lheDebug)
622  std::cout << lines[iLine];
623  if (std::regex_search(lines[iLine], groups, ismg26x ? weightgroupmg26x : weightgroup)) {
624  std::string groupname = groups.str(2);
625  if (ismg26x)
626  groupname = groups.str(1);
627  if (lheDebug)
628  std::cout << ">>> Looks like the beginning of a weight group for '" << groupname << "'" << std::endl;
629  if (groupname.find("scale_variation") == 0 || groupname == "Central scale variation" || isFirstGroup) {
630  if (lheDebug && groupname.find("scale_variation") != 0 && groupname != "Central scale variation")
631  std::cout << ">>> First weight is not scale variation, but assuming is the Central Weight" << std::endl;
632  else if (lheDebug)
633  std::cout << ">>> Looks like scale variation for theory uncertainties" << std::endl;
634  isFirstGroup = false;
635  for (++iLine; iLine < nLines; ++iLine) {
636  if (lheDebug) {
637  std::cout << " " << lines[iLine];
638  }
639  if (std::regex_search(
640  lines[iLine], groups, ismg26x ? scalewmg26x : (ismg26xNew ? scalewmg26xNew : scalew))) {
641  if (lheDebug)
642  std::cout << " >>> Scale weight " << groups[1].str() << " for " << groups[3].str() << " , "
643  << groups[4].str() << " , " << groups[5].str() << std::endl;
644  if (ismg26xNew) {
645  scaleVariationIDs.emplace_back(groups.str(4), groups.str(1), groups.str(3), groups.str(2));
646  } else {
647  scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
648  }
649  } else if (std::regex_search(lines[iLine], endweightgroup)) {
650  if (lheDebug)
651  std::cout << ">>> Looks like the end of a weight group" << std::endl;
652  if (!missed_weightgroup) {
653  break;
654  } else
655  missed_weightgroup = false;
656  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
657  if (lheDebug)
658  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
659  "of the group."
660  << std::endl;
661  if (ismg26x || ismg26xNew)
662  missed_weightgroup = true;
663  --iLine; // rewind by one, and go back to the outer loop
664  break;
665  }
666  }
667  } else if (groupname == "PDF_variation" || groupname.find("PDF_variation ") == 0) {
668  if (lheDebug)
669  std::cout << ">>> Looks like a new-style block of PDF weights for one or more pdfs" << std::endl;
670  for (++iLine; iLine < nLines; ++iLine) {
671  if (lheDebug)
672  std::cout << " " << lines[iLine];
673  if (std::regex_search(lines[iLine], groups, pdfw)) {
674  unsigned int lhaID = std::stoi(groups.str(2));
675  if (lheDebug)
676  std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
677  << std::endl;
678  if (pdfSetWeightIDs.empty() || !pdfSetWeightIDs.back().maybe_add(groups.str(1), lhaID)) {
679  pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
680  }
681  } else if (std::regex_search(lines[iLine], endweightgroup)) {
682  if (lheDebug)
683  std::cout << ">>> Looks like the end of a weight group" << std::endl;
684  if (!missed_weightgroup) {
685  break;
686  } else
687  missed_weightgroup = false;
688  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
689  if (lheDebug)
690  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
691  "of the group."
692  << std::endl;
693  if (ismg26x || ismg26xNew)
694  missed_weightgroup = true;
695  --iLine; // rewind by one, and go back to the outer loop
696  break;
697  }
698  }
699  } else if (groupname == "PDF_variation1" || groupname == "PDF_variation2") {
700  if (lheDebug)
701  std::cout << ">>> Looks like a new-style block of PDF weights for multiple pdfs" << std::endl;
702  unsigned int lastid = 0;
703  for (++iLine; iLine < nLines; ++iLine) {
704  if (lheDebug)
705  std::cout << " " << lines[iLine];
706  if (std::regex_search(lines[iLine], groups, pdfw)) {
707  unsigned int id = std::stoi(groups.str(1));
708  unsigned int lhaID = std::stoi(groups.str(2));
709  if (lheDebug)
710  std::cout << " >>> PDF weight " << groups.str(1) << " for " << groups.str(2) << " = " << lhaID
711  << std::endl;
712  if (id != (lastid + 1) || pdfSetWeightIDs.empty()) {
713  pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
714  } else {
715  pdfSetWeightIDs.back().add(groups.str(1), lhaID);
716  }
717  lastid = id;
718  } else if (std::regex_search(lines[iLine], endweightgroup)) {
719  if (lheDebug)
720  std::cout << ">>> Looks like the end of a weight group" << std::endl;
721  if (!missed_weightgroup) {
722  break;
723  } else
724  missed_weightgroup = false;
725  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
726  if (lheDebug)
727  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
728  "of the group."
729  << std::endl;
730  if (ismg26x || ismg26xNew)
731  missed_weightgroup = true;
732  --iLine; // rewind by one, and go back to the outer loop
733  break;
734  }
735  }
736  } else if (lhaNameToID_.find(groupname) != lhaNameToID_.end()) {
737  if (lheDebug)
738  std::cout << ">>> Looks like an old-style PDF weight for an individual pdf" << std::endl;
739  unsigned int firstLhaID = lhaNameToID_.find(groupname)->second;
740  bool first = true;
741  for (++iLine; iLine < nLines; ++iLine) {
742  if (lheDebug)
743  std::cout << " " << lines[iLine];
744  if (std::regex_search(
745  lines[iLine], groups, ismg26x ? pdfwmg26x : (ismg26xNew ? pdfwmg26xNew : pdfwOld))) {
746  unsigned int member = 0;
747  if (!ismg26x && !ismg26xNew) {
748  member = std::stoi(groups.str(2));
749  } else if (ismg26xNew) {
750  if (!groups.str(3).empty()) {
751  member = std::stoi(groups.str(3));
752  }
753  } else {
754  if (!groups.str(4).empty()) {
755  member = std::stoi(groups.str(4));
756  }
757  }
758  unsigned int lhaID = member + firstLhaID;
759  if (lheDebug)
760  std::cout << " >>> PDF weight " << groups.str(1) << " for " << member << " = " << lhaID
761  << std::endl;
762  //if (member == 0) continue; // let's keep also the central value for now
763  if (first) {
764  pdfSetWeightIDs.emplace_back(groups.str(1), lhaID);
765  first = false;
766  } else {
767  pdfSetWeightIDs.back().add(groups.str(1), lhaID);
768  }
769  } else if (std::regex_search(lines[iLine], endweightgroup)) {
770  if (lheDebug)
771  std::cout << ">>> Looks like the end of a weight group" << std::endl;
772  if (!missed_weightgroup) {
773  break;
774  } else
775  missed_weightgroup = false;
776  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
777  if (lheDebug)
778  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
779  "of the group."
780  << std::endl;
781  if (ismg26x || ismg26xNew)
782  missed_weightgroup = true;
783  --iLine; // rewind by one, and go back to the outer loop
784  break;
785  }
786  }
787  } else if (groupname == "mass_variation" || groupname == "sthw2_variation" ||
788  groupname == "width_variation") {
789  if (lheDebug)
790  std::cout << ">>> Looks like an EW parameter weight" << std::endl;
791  for (++iLine; iLine < nLines; ++iLine) {
792  if (lheDebug)
793  std::cout << " " << lines[iLine];
794  if (std::regex_search(lines[iLine], groups, rwgt)) {
795  std::string rwgtID = groups.str(1);
796  if (lheDebug)
797  std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
798  if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
799  // we're only interested in the beggining of the block
800  lheReweighingIDs.emplace_back(rwgtID);
801  }
802  } else if (std::regex_search(lines[iLine], endweightgroup)) {
803  if (lheDebug)
804  std::cout << ">>> Looks like the end of a weight group" << std::endl;
805  }
806  }
807  } else {
808  for (++iLine; iLine < nLines; ++iLine) {
809  if (lheDebug)
810  std::cout << " " << lines[iLine];
811  if (std::regex_search(lines[iLine], groups, endweightgroup)) {
812  if (lheDebug)
813  std::cout << ">>> Looks like the end of a weight group" << std::endl;
814  if (!missed_weightgroup) {
815  break;
816  } else
817  missed_weightgroup = false;
818  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
819  if (lheDebug)
820  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
821  "of the group."
822  << std::endl;
823  if (ismg26x || ismg26xNew)
824  missed_weightgroup = true;
825  --iLine; // rewind by one, and go back to the outer loop
826  break;
827  }
828  }
829  }
830  } else if (std::regex_search(lines[iLine], groups, weightgroupRwgt)) {
831  std::string groupname = groups.str(1);
832  if (groupname.find("mg_reweighting") != std::string::npos) {
833  if (lheDebug)
834  std::cout << ">>> Looks like a LHE weights for reweighting" << std::endl;
835  for (++iLine; iLine < nLines; ++iLine) {
836  if (lheDebug)
837  std::cout << " " << lines[iLine];
838  if (std::regex_search(lines[iLine], groups, rwgt)) {
839  std::string rwgtID = groups.str(1);
840  if (lheDebug)
841  std::cout << " >>> LHE reweighting weight: " << rwgtID << std::endl;
842  if (std::find(lheReweighingIDs.begin(), lheReweighingIDs.end(), rwgtID) == lheReweighingIDs.end()) {
843  // we're only interested in the beggining of the block
844  lheReweighingIDs.emplace_back(rwgtID);
845  }
846  } else if (std::regex_search(lines[iLine], endweightgroup)) {
847  if (lheDebug)
848  std::cout << ">>> Looks like the end of a weight group" << std::endl;
849  if (!missed_weightgroup) {
850  break;
851  } else
852  missed_weightgroup = false;
853  } else if (std::regex_search(lines[iLine], ismg26x ? weightgroupmg26x : weightgroup)) {
854  if (lheDebug)
855  std::cout << ">>> Looks like the beginning of a new weight group, I will assume I missed the end "
856  "of the group."
857  << std::endl;
858  if (ismg26x)
859  missed_weightgroup = true;
860  --iLine; // rewind by one, and go back to the outer loop
861  break;
862  }
863  }
864  }
865  }
866  }
867  //std::cout << "============= END [ " << iter->tag() << " ] ============ \n\n" << std::endl;
868 
869  // ----- SCALE VARIATIONS -----
870  std::sort(scaleVariationIDs.begin(), scaleVariationIDs.end());
871  if (lheDebug)
872  std::cout << "Found " << scaleVariationIDs.size() << " scale variations: " << std::endl;
873  std::stringstream scaleDoc;
874  scaleDoc << "LHE scale variation weights (w_var / w_nominal); ";
875  for (unsigned int isw = 0, nsw = scaleVariationIDs.size(); isw < nsw; ++isw) {
876  const auto& sw = scaleVariationIDs[isw];
877  if (isw)
878  scaleDoc << "; ";
879  scaleDoc << "[" << isw << "] is " << sw.label;
880  weightChoice->scaleWeightIDs.push_back(sw.wid);
881  if (lheDebug)
882  printf(" id %s: scales ren = % .2f fact = % .2f text = %s\n",
883  sw.wid.c_str(),
884  sw.scales.first,
885  sw.scales.second,
886  sw.label.c_str());
887  }
888  if (!scaleVariationIDs.empty())
889  weightChoice->scaleWeightsDoc = scaleDoc.str();
890 
891  // ------ PDF VARIATIONS (take the preferred one) -----
892  if (lheDebug) {
893  std::cout << "Found " << pdfSetWeightIDs.size() << " PDF set errors: " << std::endl;
894  for (const auto& pw : pdfSetWeightIDs)
895  printf("lhaIDs %6d - %6d (%3lu weights: %s, ... )\n",
896  pw.lhaIDs.first,
897  pw.lhaIDs.second,
898  pw.wids.size(),
899  pw.wids.front().c_str());
900  }
901 
902  // ------ LHE REWEIGHTING -------
903  if (lheDebug) {
904  std::cout << "Found " << lheReweighingIDs.size() << " reweighting weights" << std::endl;
905  }
906  std::copy(lheReweighingIDs.begin(), lheReweighingIDs.end(), std::back_inserter(weightChoice->rwgtIDs));
907 
908  std::stringstream pdfDoc;
909  pdfDoc << "LHE pdf variation weights (w_var / w_nominal) for LHA IDs ";
910  bool found = false;
911  for (const auto& pw : pdfSetWeightIDs) {
912  for (uint32_t lhaid : preferredPDFLHAIDs_) {
913  if (pw.lhaIDs.first != lhaid && pw.lhaIDs.first != (lhaid + 1))
914  continue; // sometimes the first weight is not saved if that PDF is the nominal one for the sample
915  if (pw.wids.size() == 1)
916  continue; // only consider error sets
917  pdfDoc << pw.lhaIDs.first << " - " << pw.lhaIDs.second;
918  weightChoice->pdfWeightIDs = pw.wids;
919  if (maxPdfWeights_ < pw.wids.size()) {
920  weightChoice->pdfWeightIDs.resize(maxPdfWeights_); // drop some replicas
921  pdfDoc << ", truncated to the first " << maxPdfWeights_ << " replicas";
922  }
923  weightChoice->pdfWeightsDoc = pdfDoc.str();
924  found = true;
925  break;
926  }
927  if (found)
928  break;
929  }
930  }
931  }
932  return weightChoice;
933  }
934 
935  // create an empty counter
936  std::unique_ptr<LumiCacheInfoHolder> beginStream(edm::StreamID) const override {
937  return std::make_unique<LumiCacheInfoHolder>();
938  }
939  // inizialize to zero at begin run
940  void streamBeginRun(edm::StreamID id, edm::Run const&, edm::EventSetup const&) const override {
941  streamCache(id)->clear();
942  }
943 
944  std::shared_ptr<DynamicWeightChoiceGenInfo> globalBeginLuminosityBlock(edm::LuminosityBlock const& lumiBlock,
945  edm::EventSetup const&) const override {
946  auto dynamicWeightChoiceGenInfo = std::make_shared<DynamicWeightChoiceGenInfo>();
947 
948  edm::Handle<GenLumiInfoHeader> genLumiInfoHead;
949  lumiBlock.getByToken(genLumiInfoHeadTag_, genLumiInfoHead);
950  if (!genLumiInfoHead.isValid())
951  edm::LogWarning("LHETablesProducer")
952  << "No GenLumiInfoHeader product found, will not fill generator model string.\n";
953 
954  if (genLumiInfoHead.isValid()) {
955  auto weightChoice = dynamicWeightChoiceGenInfo.get();
956 
957  std::vector<ScaleVarWeight> scaleVariationIDs;
958  std::vector<PDFSetWeights> pdfSetWeightIDs;
959  weightChoice->psWeightIDs.clear();
960 
961  std::regex scalew("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+)\\,\\s+mur=(\\S+)\\smuf=(\\S+)");
962  std::regex pdfw("LHE,\\s+id\\s+=\\s+(\\d+),\\s+(.+),\\s+Member\\s+(\\d+)\\s+of\\ssets\\s+(\\w+\\b)");
963  std::regex mainPSw("sr(Def|:murfac=)(Hi|Lo|_dn|_up|0.5|2.0)");
964  std::smatch groups;
965  auto weightNames = genLumiInfoHead->weightNames();
966  std::unordered_map<std::string, uint32_t> knownPDFSetsFromGenInfo_;
967  unsigned int weightIter = 0;
968  for (const auto& line : weightNames) {
969  if (std::regex_search(line, groups, scalew)) { // scale variation
970  auto id = groups.str(1);
971  auto group = groups.str(2);
972  auto mur = groups.str(3);
973  auto muf = groups.str(4);
974  if (group.find("Central scale variation") != std::string::npos)
975  scaleVariationIDs.emplace_back(groups.str(1), groups.str(2), groups.str(3), groups.str(4));
976  } else if (std::regex_search(line, groups, pdfw)) { // PDF variation
977  auto id = groups.str(1);
978  auto group = groups.str(2);
979  auto memberid = groups.str(3);
980  auto pdfset = groups.str(4);
981  if (group.find(pdfset) != std::string::npos) {
982  if (knownPDFSetsFromGenInfo_.find(pdfset) == knownPDFSetsFromGenInfo_.end()) {
983  knownPDFSetsFromGenInfo_[pdfset] = std::atoi(id.c_str());
984  pdfSetWeightIDs.emplace_back(id, std::atoi(id.c_str()));
985  } else
986  pdfSetWeightIDs.back().add(id, std::atoi(id.c_str()));
987  }
988  } else if (line == "Baseline") {
989  weightChoice->psBaselineID = weightIter;
990  } else if (line.find("isr") != std::string::npos || line.find("fsr") != std::string::npos) {
991  weightChoice->matchPS_alt = line.find("sr:") != std::string::npos; // (f/i)sr: for new weights
992  if (keepAllPSWeights_) {
993  weightChoice->psWeightIDs.push_back(weightIter); // PS variations
994  } else if (std::regex_search(line, groups, mainPSw)) {
995  if (weightChoice->psWeightIDs.empty())
996  weightChoice->psWeightIDs = std::vector<unsigned int>(4, -1);
997  int psIdx = (line.find("fsr") != std::string::npos) ? 1 : 0;
998  psIdx += (groups.str(2) == "Hi" || groups.str(2) == "_up" || groups.str(2) == "2.0") ? 0 : 2;
999  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; // only consider error sets
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_); // drop some replicas
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 
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 
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  // create an empty counter
1082  std::shared_ptr<CounterMap> globalBeginRunSummary(edm::Run const&, edm::EventSetup const&) const override {
1083  return std::make_shared<CounterMap>();
1084  }
1085  // add this stream to the summary
1087  edm::Run const&,
1088  edm::EventSetup const&,
1089  CounterMap* runCounterMap) const override {
1090  runCounterMap->merge(streamCache(id)->countermap);
1091  }
1092  // nothing to do per se
1093  void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, CounterMap* runCounterMap) const override {}
1094  // write the total to the run
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()) { // it could be empty if there's no LHE info in the sample
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  // nothing to do here
1151  void globalEndRun(edm::Run const&, edm::EventSetup const&) const override {}
1152 
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 
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:
1180  const std::vector<edm::InputTag> lheLabel_;
1181  const std::vector<edm::EDGetTokenT<LHEEventProduct>> lheTag_;
1182  const std::vector<edm::EDGetTokenT<LHERunInfoProduct>> lheRunTag_;
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_;
1190  unsigned int maxPdfWeights_;
1192 
1193  mutable std::atomic<bool> debug_, debugRun_, hasIssuedWarning_, psWeightWarning_;
1194 };
1195 
const std::vector< edm::EDGetTokenT< LHERunInfoProduct > > lheRunTag_
std::shared_ptr< CounterMap > globalBeginRunSummary(edm::Run const &, edm::EventSetup const &) const override
double originalXWGTUP() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
bool operator<(IOVSyncValue const &iLHS, IOVSyncValue const &iRHS)
Definition: IOVSyncValue.h:34
int merge(int argc, char *argv[])
Definition: DiMuonVmerge.cc:28
T w() const
const edm::EDGetTokenT< GenEventInfoProduct > genTag_
void setPSWeightInfo(const std::vector< double > &genWeights, const DynamicWeightChoiceGenInfo *genWeightChoice, std::vector< double > &wPS, std::string &psWeightDocStr) const
void fillOnlyPSWeightTable(Counter *counter, const DynamicWeightChoiceGenInfo *genWeightChoice, double genWeight, const GenEventInfoProduct &genProd, std::unique_ptr< nanoaod::FlatTable > &outPS) const
Definition: weight.py:1
std::atomic< bool > hasIssuedWarning_
auto vector_transform(std::vector< InputType > const &input, Function predicate) -> std::vector< typename std::remove_cv< typename std::remove_reference< decltype(predicate(input.front()))>::type >::type >
Definition: transform.h:11
std::unordered_map< std::string, uint32_t > lhaNameToID_
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
uint16_t size_type
const std::string & configDescription() const
const std::vector< edm::InputTag > lheLabel_
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
void fillLHEWeightTables(Counter *counter, const DynamicWeightChoice *weightChoice, const DynamicWeightChoiceGenInfo *genWeightChoice, double genWeight, const LHEEventProduct &lheProd, const GenEventInfoProduct &genProd, std::unique_ptr< nanoaod::FlatTable > &outScale, std::unique_ptr< nanoaod::FlatTable > &outPdf, std::unique_ptr< nanoaod::FlatTable > &outRwgt, std::unique_ptr< nanoaod::FlatTable > &outNamed, std::unique_ptr< nanoaod::FlatTable > &outPS) const
char const * label
std::function< unsigned int(align::ID)> Counter
int iEvent
Definition: GenABIO.cc:224
std::unique_ptr< LumiCacheInfoHolder > beginStream(edm::StreamID) const override
void globalEndRunProduce(edm::Run &iRun, edm::EventSetup const &, CounterMap const *runCounterMap) const override
void produce(edm::StreamID id, edm::Event &iEvent, const edm::EventSetup &iSetup) const override
bool getByLabel(std::string const &label, Handle< PROD > &result) const
Definition: Run.h:280
double f[11][100]
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
std::atomic< bool > psWeightWarning_
ParameterDescriptionBase * add(U const &iLabel, T const &value)
void fillLHEPdfWeightTablesFromGenInfo(Counter *counter, const DynamicWeightChoiceGenInfo *weightChoice, double genWeight, const GenEventInfoProduct &genProd, std::unique_ptr< nanoaod::FlatTable > &outScale, std::unique_ptr< nanoaod::FlatTable > &outPdf, std::unique_ptr< nanoaod::FlatTable > &outNamed, std::unique_ptr< nanoaod::FlatTable > &outPS) const
void streamBeginLuminosityBlock(edm::StreamID id, edm::LuminosityBlock const &lumiBlock, edm::EventSetup const &) const override
void globalEndRun(edm::Run const &, edm::EventSetup const &) const override
void streamEndRunSummary(edm::StreamID id, edm::Run const &, edm::EventSetup const &, CounterMap *runCounterMap) const override
bool getByToken(EDGetToken token, Handle< PROD > &result) const
std::vector< std::string > namedWeightLabels_
GenWeightsTableProducer(edm::ParameterSet const &params)
std::shared_ptr< DynamicWeightChoice > globalBeginRun(edm::Run const &iRun, edm::EventSetup const &) const override
void put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Run.h:106
void add(std::string const &label, ParameterSetDescription const &psetDescription)
bool isValid() const
Definition: HandleBase.h:70
void globalEndRunSummary(edm::Run const &, edm::EventSetup const &, CounterMap *runCounterMap) const override
const std::vector< edm::EDGetTokenT< LHEEventProduct > > lheTag_
std::vector< uint32_t > preferredPDFLHAIDs_
void add(std::map< std::string, TH1 *> &h, TH1 *hist)
void globalEndLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) const override
HLT enums.
std::vector< double > & weights()
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
std::vector< std::string > namedWeightIDs_
void clear(EGIsoObj &c)
Definition: egamma.h:82
Log< level::Warning, false > LogWarning
void streamBeginRun(edm::StreamID id, edm::Run const &, edm::EventSetup const &) const override
#define str(s)
if(threadIdxLocalY==0 &&threadIdxLocalX==0)
const edm::EDGetTokenT< GenLumiInfoHeader > genLumiInfoHeadTag_
std::shared_ptr< DynamicWeightChoiceGenInfo > globalBeginLuminosityBlock(edm::LuminosityBlock const &lumiBlock, edm::EventSetup const &) const override
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
def move(src, dest)
Definition: eostools.py:511
const std::vector< WGT > & weights() const
Definition: Run.h:45