StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Weights.cc
1 // Weights.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2020 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Function definitions (not found in the header) for the Weight classes.
7 
8 #include "Pythia8/Info.h"
9 #include "Pythia8/Settings.h"
10 #include "Pythia8/Weights.h"
11 #include <limits>
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // WeightsBase class.
18 
19 //--------------------------------------------------------------------------
20 
21 // Function to return processed weights to weight container, e.g. if
22 // weights should be combined before proceeding.
23 void WeightsBase::collectWeightValues(vector<double>& outputWeights,
24  double norm) {
25  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
26  double value = getWeightsValue(iwt)*norm;
27  outputWeights.push_back(value);
28  }
29  return;
30 }
31 
32 //--------------------------------------------------------------------------
33 
34 // Similar function to return processed weight names.
35 void WeightsBase::collectWeightNames(vector<string>& outputNames) {
36  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
37  string name = getWeightsName(iwt);
38  outputNames.push_back(name);
39  }
40  return;
41 }
42 
43 //==========================================================================
44 
45 // WeightsSimpleShower class.
46 
47 //--------------------------------------------------------------------------
48 
49 // Reset all internal values
50 void WeightsSimpleShower::clear() {
51  for (size_t i=0; i < weightValues.size(); ++i) weightValues[i] = 1.;
52 }
53 
54 //--------------------------------------------------------------------------
55 
56 // Initialize shower weights
57 void WeightsSimpleShower::init( bool doMerging ) {
58 
59  // Empty weight vector, relevant to avoid double init of ISR variations
60  weightValues.resize(0);
61  weightNames.resize(0);
62  mergingVarNames.resize(0);
63  // Remember the nominal weight, since this might be needed for splitting
64  // enhancement hanlding.
65  bookWeight("Baseline");
66 
67  // Force shower variations if needed by merging but not requested by user
68  if (!infoPtr->settingsPtr->flag("UncertaintyBands:doVariations") &&
69  infoPtr->weightContainerPtr->weightsMerging.getMuRVarFactors().size()
70  && doMerging ) {
71  infoPtr->settingsPtr->flag("UncertaintyBands:doVariations", true);
72  // In this case, also empty requested variations, to not do default ones
73  infoPtr->settingsPtr->wvec("UncertaintyBands:List",vector<string>(0));
74  }
75 
76  // Assemble shower variation strings needed for merging
77  if (doMerging)
78  for (double fac: infoPtr->weightContainerPtr->weightsMerging.
79  getMuRVarFactors()) {
80  string stringfsr = "fsr:murfac=" + std::to_string(fac);
81  string stringisr = "isr:murfac=" + std::to_string(fac);
82  mergingVarNames.push_back({stringfsr,stringisr});
83  }
84 
85 }
86 
87 //--------------------------------------------------------------------------
88 
89 // Store the current event information.
90 void WeightsSimpleShower::bookVectors(vector<double> weights,
91  vector<string> names) {
92 
93  replaceWhitespace(names);
94 
95  for (size_t i=0; i < weights.size(); ++i) bookWeight(names[i], weights[i]);
96 
97 }
98 
99 //--------------------------------------------------------------------------
100 
101 // Replace whitespace with underscore in wieght names, so that the names
102 // transferred to HepMC do not contain whitespace.
103 void WeightsSimpleShower::replaceWhitespace( vector<string>& namesIn) {
104  vector<string> ret;
105  for (size_t i=0; i < namesIn.size(); ++i) {
106  string name=namesIn[i];
107  replace(name.begin(), name.end(), ' ', '_');
108  ret.push_back(name);
109  namesIn[i] = name;
110  }
111 }
112 
113 //--------------------------------------------------------------------------
114 
115 // Functions to set values of weights.
116 void WeightsSimpleShower::reweightValueByIndex(int iPos, double val) {
117  weightValues[iPos] *= val;
118 }
119 
120 //--------------------------------------------------------------------------
121 
122 void WeightsSimpleShower::reweightValueByName(string name, double val) {
123  // Use existing functions: Find index of name, then set by index.
124  int iPos = findIndexOfName(name);
125  reweightValueByIndex(iPos, val);
126 }
127 
128 //--------------------------------------------------------------------------
129 
130 // Uncertainty variations initialization
131 void WeightsSimpleShower::initAutomatedVariationGroups(bool isISR) {
132  vector<string> variationListIn = infoPtr->settingsPtr->
133  wvec("UncertaintyBands:List");
134  size_t vNames = weightNames.size();
135  externalVariations.clear();
136  externalVarNames.clear();
137  externalGroupNames.clear();
138  externalMap.clear();
139  initialNameSave.clear();
140  externalVariations.push_back("Baseline");
141  initialNameSave.push_back("Baseline");
142  for(vector<string>::const_iterator v=variationListIn.begin();
143  v != variationListIn.end(); ++v) {
144  string line = *v;
145  // Remove initial blank spaces
146  while (line.find(" ") == 0) line.erase( 0, 1);
147  size_t pos=0;
148  // Search for pdf:family keyword for SpaceShower
149  if( isISR && ((pos = line.find("isr:pdf:family")) != string::npos) ) {
150  size_t posEnd = line.find(" ",pos);
151  if( posEnd == string::npos ) posEnd = line.size();
152  for(size_t i=0; i < vNames; ++i) {
153  string local = weightNames[i];
154  if( local.find("isr:pdf:member") != string::npos ) {
155  size_t iEqual = local.find("=")+1;
156  string nMember = local.substr(iEqual,local.size());
157  nMember.append(" ");
158  string tmpLine = line;
159  tmpLine.replace(pos,posEnd-pos,local);
160  size_t iBlank = line.find_first_of(" ");
161  tmpLine.replace(iBlank,1,nMember);
162  externalVariations.push_back(tmpLine);
163  initialNameSave.push_back(line.substr(0,line.find_first_of(" ")));
164  }
165  }
166  } else {
167  externalVariations.push_back(line);
168  initialNameSave.push_back(line.substr(0,line.find_first_of(" ")));
169  }
170  }
171  externalVariationsSize = externalVariations.size();
172  size_t nNames = externalVariationsSize;
173  externalVarNames.resize(nNames);
174  externalVarNames[0].push_back("Baseline");
175  externalGroupNames.resize(nNames);
176  externalGroupNames[0]="Baseline";
177  for(size_t iWeight = 0; iWeight < nNames; ++iWeight) {
178  string uVarString = toLower(externalVariations[iWeight]);
179  size_t firstBlank = uVarString.find_first_of(" ");
180  size_t endLine = uVarString.size();
181  if( firstBlank > endLine) continue;
182  externalGroupNames[iWeight] = uVarString.substr(0,firstBlank);
183  uVarString = uVarString.substr(firstBlank+1,endLine);
184  size_t pos = 0;
185  while ((pos = uVarString.find(" ")) != string::npos) {
186  string token = uVarString.substr(0, pos);
187  externalVarNames[iWeight].push_back(token);
188  uVarString.erase(0, pos + 1);
189  }
190  if (uVarString == "" || uVarString == " ") continue;
191  externalVarNames[iWeight].push_back(uVarString);
192  }
193  externalMap.resize(nNames);
194  for(size_t iWeight = 0; iWeight < vNames; ++iWeight) {
195  for(size_t iV = 0; iV < nNames; ++iV) {
196  for(size_t iW = 0; iW < externalVarNames[iV].size(); ++iW) {
197  if( externalVarNames[iV][iW] == weightNames[iWeight] ) {
198  externalMap[iV].push_back(iWeight);
199  } else if ( isISR && externalVarNames[iV][iW].find("isr:pdf:family")
200  != string::npos && weightNames[iWeight].find("isr:pdf:member")
201  != string::npos ) {
202  externalMap[iV].push_back(iWeight);
203  }
204  }
205  }
206  }
207 }
208 
209 //--------------------------------------------------------------------------
210 
211 // Return weight group name
212 string WeightsSimpleShower::getGroupName(int iGN) const {
213  string tmpString("Null");
214  if( iGN < 0 || iGN >= externalVariationsSize )
215  return tmpString;
216  return externalGroupNames[iGN];
217 }
218 
219 //--------------------------------------------------------------------------
220 
221 // Return weight group value
222 double WeightsSimpleShower::getGroupWeight(int iGW) const {
223  double tempWeight(1.0);
224  if( iGW < 0 || iGW >= externalVariationsSize )
225  return tempWeight;
226  for( vector<int>::const_iterator cit = externalMap[iGW].
227  begin(); cit < externalMap[iGW].end(); ++cit )
228  tempWeight *= getWeightsValue(*cit);
229  return tempWeight;
230 }
231 
232 //--------------------------------------------------------------------------
233 
234 // Return list of atomic weight variations to be performed by shower
235 vector<string> WeightsSimpleShower::getUniqueShowerVars() {
236  // Get uncertainty variations from Settings (as list of strings to parse).
237  vector<string> uVars = infoPtr->settingsPtr->wvec("UncertaintyBands:List");
238  size_t varSize = uVars.size();
239  vector<string> uniqueVars;
240 
241  // Parse each string in uVars to look for recognized keywords.
242  for (size_t iWeight = 0; iWeight < varSize; ++iWeight) {
243  // Convert to lowercase (to be case-insensitive). Also remove
244  // extra spaces, so everything is mapped to "key=value"
245  string uVarString = toLower(uVars[iWeight]);
246  while (uVarString.find(" ") == 0) uVarString.erase( 0, 1);
247  int iEnd = uVarString.find(" ", 0);
248  uVarString.erase(0,iEnd+1);
249  while (uVarString.find("=") != string::npos) {
250  iEnd = uVarString.find_first_of(" ", 0);
251  if( iEnd<0 ) iEnd = uVarString.length();
252  string insertString = uVarString.substr(0,iEnd);
253  if( uniqueVars.size() == 0 ) {
254  uniqueVars.push_back(insertString);
255  } else if ( find(uniqueVars.begin(), uniqueVars.end(), insertString)
256  == uniqueVars.end() ) {
257  uniqueVars.push_back(insertString);
258  }
259  uVarString.erase(0,iEnd+1);
260  }
261  }
262 
263  // Also attach weights needed for merging
264  for (vector<string> mergingVariation: mergingVarNames) {
265  for (string varString: mergingVariation) {
266  uniqueVars.push_back(varString);
267  }
268  }
269 
270  return uniqueVars;
271 }
272 
273 //--------------------------------------------------------------------------
274 
275 // Get vector of muR weight combinations (isr & fsr) needed by merging
276 vector<double> WeightsSimpleShower::getMuRWeightVector() {
277  int nVarCombs = mergingVarNames.size();
278  vector<double> ret( nVarCombs, 1. );
279  for (int iVarComb = 0; iVarComb < nVarCombs; ++iVarComb) {
280  int nVars = mergingVarNames[iVarComb].size();
281  for (int iVar = 0; iVar < nVars; ++iVar) {
282  int index = findIndexOfName(mergingVarNames[iVarComb][iVar]);
283  if (index != -1) ret[iVarComb] *= getWeightsValue(index);
284  }
285  // Normalize... even though variations should be relative
286  ret[iVarComb] /= getWeightsValue(0);
287  }
288  return ret;
289 }
290 
291 //--------------------------------------------------------------------------
292 
293 // Collect shower weight names
294 void WeightsSimpleShower::collectWeightNames(vector<string>& outputNames) {
295  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
296  string name = getWeightsName(iwt);
297  outputNames.push_back("AUX_"+name);
298  }
299  for (int iwtGrp = 1; iwtGrp < nVariationGroups(); ++iwtGrp) {
300  string name = getGroupName(iwtGrp);
301  outputNames.push_back("AUX_"+name);
302  }
303  return;
304 }
305 
306 //--------------------------------------------------------------------------
307 
308 // Collect shower weight values
309 void WeightsSimpleShower::collectWeightValues(vector<double>& outputWeights,
310  double norm) {
311  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
312  double value = getWeightsValue(iwt)*norm;
313  outputWeights.push_back(value);
314  }
315  for (int iwtGrp = 1; iwtGrp < nVariationGroups(); ++iwtGrp) {
316  double value = getGroupWeight(iwtGrp)*norm;
317  outputWeights.push_back(value);
318  }
319  return;
320 }
321 
322 //==========================================================================
323 
324 // WeightsLHEF class.
325 
326 // Reset all internal values;
327 void WeightsLHEF::clear() {
328  weightValues.resize(0);
329  weightNames.resize(0);
330 }
331 
332 //--------------------------------------------------------------------------
333 
334 // Store the current event information.
335 void WeightsLHEF::bookVectors(vector<double> weights_detailed_vecIn,
336  vector<string> weights_detailed_name_vecIn){
337  weightValues = weights_detailed_vecIn;
338  // Normalize values relative to eventWeightLHEF
339  double norm = 1./infoPtr->eventWeightLHEF;
340  for (double& value: weightValues)
341  value *= norm;
342  weightNames = weightnames_lhef2hepmc(weights_detailed_name_vecIn);
343 }
344 
345 //--------------------------------------------------------------------------
346 
347 // Function to return processed weights to weight container.
348 void WeightsLHEF::collectWeightValues(vector<double>& ret, double norm) {
349 
350  // Attach the LHEF weights, starting with well-defined MUF and MUR
351  // variations, and then followed by any other LHEF weight.
352  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
353  double value = getWeightsValue(iwt);
354  string name = getWeightsName(iwt);
355  if (name.find("MUR") == string::npos || name.find("MUF") == string::npos)
356  continue;
357  ret.push_back(value*norm);
358  }
359  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
360  double value = getWeightsValue(iwt);
361  string name = getWeightsName(iwt);
362  if (name.find("MUR") != string::npos || name.find("MUF") != string::npos)
363  continue;
364  ret.push_back(value*norm);
365  }
366 
367  // Done.
368  return;
369 }
370 
371 //--------------------------------------------------------------------------
372 
373 // Function to return processed weight names to weight container.
374 void WeightsLHEF::collectWeightNames(vector<string>& ret) {
375 
376  // Attach the LHEF weights, starting with well-defined MUF and MUR
377  // variations, and then followed by any other LHEF weight.
378  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
379  string name = getWeightsName(iwt);
380  if (name.find("MUR") == string::npos || name.find("MUF") == string::npos)
381  continue;
382  ret.push_back("AUX_"+name);
383  }
384  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
385  string name = getWeightsName(iwt);
386  if (name.find("MUR") != string::npos || name.find("MUF") != string::npos)
387  continue;
388  ret.push_back("AUX_"+name);
389  }
390 
391  // Done.
392  return;
393 }
394 
395 //--------------------------------------------------------------------------
396 
397 // Convert weight names in MadGraph5 convention to the convention outlined
398 // in https://arxiv.org/pdf/1405.1067.pdf, page 162ff.
399 vector<string> WeightsLHEF::weightnames_lhef2hepmc(
400  vector<string> weights_detailed_name_vecIn) {
401  vector<string> ret;
402  for (size_t i=0; i < weights_detailed_name_vecIn.size(); ++i) {
403  string name=weights_detailed_name_vecIn[i];
404  if (name=="1001") name="MUR1.0_MUF1.0";
405  if (name=="1002") name="MUR1.0_MUF2.0";
406  if (name=="1003") name="MUR1.0_MUF0.5";
407  if (name=="1004") name="MUR2.0_MUF1.0";
408  if (name=="1005") name="MUR2.0_MUF2.0";
409  if (name=="1006") name="MUR2.0_MUF0.5";
410  if (name=="1007") name="MUR0.5_MUF1.0";
411  if (name=="1008") name="MUR0.5_MUF2.0";
412  if (name=="1009") name="MUR0.5_MUF0.5";
413  ret.push_back(name);
414  }
415  return ret;
416 }
417 
418 //--------------------------------------------------------------------------
419 
420 // Identify muR (and muF) variations in LHEF weights. This mapping is needed
421 // to later combine with the respective shower and merging weights
422 void WeightsLHEF::identifyVariationsFromLHAinit( map<string,LHAweight>
423  *init_weightsIn ) {
424  muRvars.clear();
425  int index = 0;
426  for (map<string,LHAweight>::const_iterator it =
427  init_weightsIn->begin(); it != init_weightsIn->end(); ++it) {
428  string cont = it->second.contents;
429  double muR = 0, muF = 0;
430  // Go through all tags of one weight
431  while (true) {
432  // Erase leading blanks, skip irrelevant tags
433  while (cont.substr(0,4) != "muR=" && cont.substr(0,4) != "muF=") {
434  if (cont.find_first_of(" ") != string::npos) {
435  cont = cont.substr(cont.find_first_of(" ") + 1);
436  } else break;
437  }
438  // Parse muF and muR
439  if (cont.substr(0,4) == "muR=") {
440  muR = stof(cont.substr(4,cont.find_first_of(" ")));
441  cont = cont.substr(cont.find_first_of(" ") + 1);
442  }
443  if (cont.substr(0,4) == "muF=") {
444  muF = stof(cont.substr(4,cont.find_first_of(" ")));
445  cont = cont.substr(cont.find_first_of(" ") + 1);
446  }
447  // Stop if both muF and muR set
448  if (muR && muF) break;
449  // Also stop if end of contents reached
450  if (cont.find_first_of(" ") == string::npos) break;
451  }
452  // For now, only save muR values for corresponding muF=1.
453  if (muF == 1.) muRvars[index] = muR;
454  ++index;
455  }
456 }
457 
458 //==========================================================================
459 
460 // WeightsMerging class.
461 
462 //--------------------------------------------------------------------------
463 
464 // Reset all internal values;
465 void WeightsMerging::clear() {
466  for (size_t i=0; i < weightValues.size(); ++i) {
467  weightValues[i] = 1.;
468  weightValuesFirst[i] = 0.;
469  }
470  for (size_t i=0; i < weightValuesP.size(); ++i) {
471  weightValuesP[i] = 1.;
472  weightValuesFirstP[i] = 0.;
473  weightValuesPC[i] = 1.;
474  weightValuesFirstPC[i] = 0.;
475  }
476 }
477 
478 //--------------------------------------------------------------------------
479 
480 // Initialize merging weights
481 void WeightsMerging::init() {
482 
483  // Reset weight vectors
484  weightValues.resize(0);
485  weightNames.resize(0);
486  weightValuesFirst.resize(0);
487  weightValuesP.resize(0);
488  weightValuesPC.resize(0);
489  weightValuesFirstP.resize(0);
490  weightValuesFirstPC.resize(0);
491 
492  // Initialization of all required variation weights done in MergingHooks.cc
493  bookWeight("MUR1.0_MUF1.0", 1., 0.);
494 
495  isNLO = (infoPtr->settingsPtr->flag("Merging:doUNLOPSLoop") ||
496  infoPtr->settingsPtr->flag("Merging:doUNLOPSSubtNLO") ||
497  infoPtr->settingsPtr->flag("Merging:doNL3LOOP") );
498 }
499 
500 //--------------------------------------------------------------------------
501 
502 // Function to create a new, synchronized, pair of weight name and value.
503 void WeightsMerging::bookWeight(string name, double value, double valueFirst) {
504  weightNames.push_back(name);
505  weightValues.push_back(value);
506  weightValuesFirst.push_back(valueFirst);
507 }
508 
509 //--------------------------------------------------------------------------
510 
511 // Store the current event information.
512 void WeightsMerging::bookVectors(vector<double> weights, vector<string> names){
513 
514  // Reset weight vectors
515  weightValues.resize(0);
516  weightNames.resize(0);
517  weightValuesFirst.resize(0);
518  weightValuesP.resize(0);
519  weightValuesPC.resize(0);
520  weightValuesFirstP.resize(0);
521  weightValuesFirstPC.resize(0);
522 
523  for (size_t i=0; i < weights.size(); ++i) bookWeight(names[i],
524  weights[i], 0.);
525 
526 }
527 
528 //--------------------------------------------------------------------------
529 
530 // Store the current event information, including first order weights for
531 // NLO merging.
532 void WeightsMerging::bookVectors(vector<double> weights,
533  vector<double> weightsFirst, vector<string> names) {
534 
535  // Reset weight vectors
536  weightValues.resize(0);
537  weightNames.resize(0);
538  weightValuesFirst.resize(0);
539  weightValuesP.resize(0);
540  weightValuesPC.resize(0);
541  weightValuesFirstP.resize(0);
542  weightValuesFirstPC.resize(0);
543 
544  for (size_t i=0; i < weights.size(); ++i) bookWeight(names[i],
545  weights[i], weightsFirst[i]);
546 
547 }
548 
549 //--------------------------------------------------------------------------
550 
551 // Functions to set values of weights. Does not apply to first order weights or
552 // scheme variation weights.
553 void WeightsMerging::reweightValueByIndex(int iPos, double val) {
554  weightValues[iPos] *= val;
555 }
556 
557 //--------------------------------------------------------------------------
558 
559 // Reweigth merging weights by name. Does not apply to first order weights or
560 // scheme variation weights.
561 void WeightsMerging::reweightValueByName(string name, double val) {
562  // Use existing functions: Find index of name, then set by index.
563  int iPos = findIndexOfName(name);
564  reweightValueByIndex(iPos, val);
565 }
566 
567 //--------------------------------------------------------------------------
568 
569 // Functions to set values of first order weights. Does not apply to scheme
570 // variation weights.
571 void WeightsMerging::setValueFirstByIndex(int iPos, double val) {
572  weightValuesFirst[iPos] = val;
573 }
574 
575 //--------------------------------------------------------------------------
576 
577 // Set values of first order weights by name. Does not apply to scheme
578 // variation weights.
579 void WeightsMerging::setValueFirstByName(string name, double val) {
580  // Use existing functions: Find index of name, then set by index.
581  int iPos = findIndexOfName(name);
582  setValueFirstByIndex(iPos, val);
583 }
584 
585 //--------------------------------------------------------------------------
586 
587 // Set values as whole vector.
588 void WeightsMerging::setValueVector(vector<double> valueVector) {
589  weightValues = valueVector;
590 }
591 
592 //--------------------------------------------------------------------------
593 
594 // Set first order weight values as vector
595 void WeightsMerging::setValueFirstVector(vector<double> valueFirstVector) {
596  weightValuesFirst = valueFirstVector;
597 }
598 
599 //--------------------------------------------------------------------------
600 
601 // Function telling merging which muR variations to perform, read from
602 // Merging:muRfactors setting.
603 vector<double> WeightsMerging::getMuRVarFactors() {
604  vector<double> ret = infoPtr->settingsPtr->pvec("Merging:muRfactors");
605  return ret;
606 }
607 
608 //--------------------------------------------------------------------------
609 
610 // Function to return processed weights to weight container.
611 void WeightsMerging::collectWeightValues(vector<double>& ret, double norm) {
612  vector<double> showerWeights = infoPtr->weightContainerPtr->weightsPS.
613  getMuRWeightVector();
614  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
615  double value = getWeightsValue(iwt)*norm;
616  if (getWeightsValue(0) != 0 ) value /= getWeightsValue(0);
617  // Combine with corresponding LHE variation
618  if (isNLO) {
619  // Check if corresponding muR variation is available
620  if (muRVarLHEFindex.find(iwt) == muRVarLHEFindex.end()) {
621  string errormsg = "Error in WeightsMerging::collectWeightValues: "
622  "Requested muR variation ";
623  errormsg += std::to_string(getMuRVarFactors()[iwt-1]) +
624  " not found in LHE file.";
625  infoPtr->errorMsg(errormsg);
626  } else
627  value *= infoPtr->weightContainerPtr->weightsLHEF.
628  getWeightsValue(muRVarLHEFindex[iwt]);
629  }
630  // Combine with corresponding shower weight
631  value *= showerWeights[iwt-1];
632  ret.push_back(value);
633  }
634 
635  // Include scheme variation weights if present
636  if (weightValuesP.size()) {
637  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
638  // Normalize with UNLOPS-1 central merging weight, since that is
639  // collected into the nominal weight.
640  double valueP = getWeightsValueP(iwt)*norm;
641  double valuePC = getWeightsValuePC(iwt)*norm;
642  if (getWeightsValue(0) != 0 ) {
643  valueP /= getWeightsValue(0);
644  valuePC /= getWeightsValue(0);
645  }
646 
647  // Combine with corresponding LHE variation
648  if (isNLO) {
649  // Check if corresponding muR variation is available
650  if (muRVarLHEFindex.find(iwt) != muRVarLHEFindex.end()) {
651  double fact = infoPtr->weightContainerPtr->weightsLHEF.
652  getWeightsValue(muRVarLHEFindex[iwt]);
653  valueP *= fact;
654  valuePC *= fact;
655  }
656  }
657  // Combine with corresponding shower weight
658  if (iwt != 0) {
659  valueP *= showerWeights[iwt-1];
660  valuePC *= showerWeights[iwt-1];
661  }
662  ret.push_back(valueP);
663  ret.push_back(valuePC);
664  }
665  }
666 
667  // Done.
668  return;
669 }
670 
671 //--------------------------------------------------------------------------
672 
673 // Similar function to return processed weight names.
674 void WeightsMerging::collectWeightNames(vector<string>& outputNames) {
675  for (int iwt=1; iwt < getWeightsSize(); ++iwt) {
676  string name = getWeightsName(iwt);
677  outputNames.push_back(name);
678  }
679 
680  // Include scheme variation names if present
681  if (weightValuesP.size()) {
682  for (int iwt=0; iwt < getWeightsSize(); ++iwt) {
683  string nameP = getWeightsName(iwt)+"_SCHEMEP";
684  string namePC = getWeightsName(iwt)+"_SCHEMEPC";
685  outputNames.push_back(nameP);
686  outputNames.push_back(namePC);
687  }
688  }
689 
690  return;
691 }
692 
693 //--------------------------------------------------------------------------
694 
695 // Set up mapping between LHEF variations and
696 void WeightsMerging::setLHEFvariationMapping() {
697  if (!isNLO) return;
698  map<int,double> muRvarsLHEF = infoPtr->weightContainerPtr->weightsLHEF.
699  muRvars;
700  vector<double> muRvarsMerging = getMuRVarFactors();
701  for (unsigned int iMerVar = 0; iMerVar < muRvarsMerging.size(); ++iMerVar) {
702  for (pair<int,double> muRvarLHEF: muRvarsLHEF) {
703  if (abs(muRvarLHEF.second - muRvarsMerging[iMerVar]) < 1e-10) {
704  muRVarLHEFindex[iMerVar+1] = muRvarLHEF.first;
705  continue;
706  }
707  }
708  }
709 }
710 
711 //==========================================================================
712 
713 // The WeightContainer class.
714 
715 //--------------------------------------------------------------------------
716 
717 // Set nominala weight
718 void WeightContainer::setWeightNominal(double weightNow) {
719  weightNominal = weightNow;
720 }
721 
722 //--------------------------------------------------------------------------
723 
724 // Assemble nominal weight, including nominal parton shower and merging weight.
725 // PS and Merging weight variations are stored relative to this return value.
726 double WeightContainer::collectWeightNominal() {
727  return weightNominal * weightsPS.getWeightsValue(0)
728  * weightsMerging.getWeightsValue(0);
729 }
730 
731 
732 //--------------------------------------------------------------------------
733 
734 // Functions to retrieve the stored information.
735 int WeightContainer::numberOfWeights() {
736  // Get total number of merging weights
737  int nMergingWeights = weightsMerging.getWeightsSize() - 1;
738  if (weightsMerging.weightValuesP.size())
739  nMergingWeights += 2*weightsMerging.weightValuesP.size();
740  // Get total number of shower weights
741  int nShowerWeights = weightsPS.getWeightsSize()
742  + weightsPS.nVariationGroups()
743  - 2;
744  // One nominal weight + variations. -1 for all since 0th component goes
745  // into nominal weight.
746  if (doSuppressAUXweights) return 1 + nMergingWeights;
747  else return (1 + weightsLHEF.getWeightsSize()
748  + nShowerWeights + nMergingWeights);
749 }
750 
751 double WeightContainer::weightValueByIndex(int key) {
752  vector<double> values = weightValueVector();
753  return values[key];
754 }
755 
756 string WeightContainer::weightNameByIndex(int key) {
757  vector<string> names = weightNameVector();
758  return names[key];
759 }
760 
761 //--------------------------------------------------------------------------
762 
763 // Function to return the vector of weight values, combining all weights from
764 // all subcategories.
765 vector<double> WeightContainer::weightValueVector() {
766  vector<double> ret;
767 
768  // The very first entry in the vector should always be the nominal weight.
769  double collWgtNom = collectWeightNominal();
770  ret.push_back(collWgtNom);
771 
772  // Let all weights attach the relative weight values to the return vector.
773  // Second argument allows for normalization.
774  if (!doSuppressAUXweights) weightsLHEF.collectWeightValues(ret,collWgtNom);
775  if (!doSuppressAUXweights) weightsPS.collectWeightValues(ret,collWgtNom);
776  weightsMerging.collectWeightValues(ret,collWgtNom);
777 
778  // Done
779  return ret;
780 
781 }
782 
783 //--------------------------------------------------------------------------
784 
785 // Function to return the vector of weight names, combining all names from
786 // all subcategories, cf. weightValueVector function.
787 vector<string> WeightContainer::weightNameVector() {
788  vector<string> ret;
789 
790  // The very first entry in the vector should always be the nominal weight.
791  ret.push_back("Weight");
792 
793  // Let all weights attach the weight names to the return vector.
794  if (!doSuppressAUXweights) weightsLHEF.collectWeightNames(ret);
795  if (!doSuppressAUXweights) weightsPS.collectWeightNames(ret);
796  weightsMerging.collectWeightNames(ret);
797 
798  // Done
799  return ret;
800 
801 }
802 
803 //--------------------------------------------------------------------------
804 
805 // Reset all members to default status.
806 void WeightContainer::clear() {
807  weightNominal = 1.;
808  weightsLHEF.clear();
809  weightsPS.clear();
810  weightsMerging.clear();
811 }
812 
813 //--------------------------------------------------------------------------
814 
815 // Reset total cross section estimate
816 void WeightContainer::clearTotal() {
817  if (sigmaTotal.size()) {
818  sigmaTotal = vector<double>(sigmaTotal.size(),0.);
819  errorTotal = vector<double>(errorTotal.size(),0.);
820  }
821 }
822 
823 //--------------------------------------------------------------------------
824 
825 // Function to set Pointers in weight classes
826 void WeightContainer::initPtrs(Info* infoPtrIn) {
827  infoPtr = infoPtrIn;
828  weightsLHEF.setPtrs(infoPtrIn);
829  weightsPS.setPtrs(infoPtrIn);
830  weightsMerging.setPtrs(infoPtrIn);
831 }
832 
833 //--------------------------------------------------------------------------
834 
835 // Function to initialize weight classes
836 void WeightContainer::init( bool doMerging ) {
837  weightsPS.init(doMerging);
838  weightsMerging.init();
839  doSuppressAUXweights = infoPtr->settingsPtr->
840  flag("Weights:suppressAUX");
841  if (xsecIsInit) {
842  sigmaSample = vector<double>(sigmaSample.size(),0.);
843  errorSample = vector<double>(errorSample.size(),0.);
844  }
845 }
846 
847 //--------------------------------------------------------------------------
848 
849 // Initialize accumulation of cross section
850 void WeightContainer::initXsecVec() {
851  if (!xsecIsInit) {
852  sigmaTotal = vector<double>(weightNameVector().size(),0.);
853  sigmaSample = vector<double>(weightNameVector().size(),0.);
854  errorTotal = vector<double>(weightNameVector().size(),0.);
855  errorSample = vector<double>(weightNameVector().size(),0.);
856  xsecIsInit = true;
857  }
858 }
859 
860 //--------------------------------------------------------------------------
861 
862 // Return cross section for current sample
863 vector<double> WeightContainer::getSampleXsec() {
864  vector<double> ret;
865  for (double sigma: sigmaSample)
866  ret.push_back(sigma);
867  return ret;
868 }
869 
870 //--------------------------------------------------------------------------
871 
872 // Return cross section error for current sample
873 vector<double> WeightContainer::getSampleXsecErr() {
874  vector<double> ret;
875  for (double error: errorSample)
876  ret.push_back(sqrt(error));
877  return ret;
878 }
879 
880 //--------------------------------------------------------------------------
881 
882 // Return cross section estimate for total run
883 vector<double> WeightContainer::getTotalXsec() {
884  vector<double> ret;
885  for (double sigma: sigmaTotal)
886  ret.push_back(sigma);
887  return ret;
888 }
889 
890 //--------------------------------------------------------------------------
891 
892 // Return cross section error estimate for total run
893 vector<double> WeightContainer::getTotalXsecErr() {
894  vector<double> ret;
895  for (double error: errorTotal)
896  ret.push_back(sqrt(error));
897  return ret;
898 }
899 //--------------------------------------------------------------------------
900 
901 // Accumulate cross section for all weights. Provide cross section estimate
902 // for whole sample if lhaStrategy != 4 or -4.
903 void WeightContainer::accumulateXsec(double norm) {
904  if (!xsecIsInit) initXsecVec();
905  vector<double> weights = weightValueVector();
906  for (unsigned int iWgt = 0; iWgt < weights.size(); ++iWgt) {
907  sigmaTotal[iWgt] += weights[iWgt]*norm;
908  sigmaSample[iWgt] += weights[iWgt]*norm;
909  errorTotal[iWgt] += pow2(weights[iWgt]*norm);
910  errorSample[iWgt] += pow2(weights[iWgt]*norm);
911  }
912 }
913 
914 //==========================================================================
915 
916 } // end namespace Pythia8