StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Settings.cc
1 // Settings.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2012 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, 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 Settings class.
7 
8 #include "Settings.h"
9 
10 // Allow string and character manipulation.
11 #include <cctype>
12 
13 namespace Pythia8 {
14 
15 //==========================================================================
16 
17 // Settings class.
18 // This class contains flags, modes, parms and words used in generation.
19 
20 //--------------------------------------------------------------------------
21 
22 // Read in database from specific file.
23 
24 bool Settings::init(string startFile, bool append, ostream& os) {
25 
26  // Don't initialize if it has already been done and not in append mode.
27  if (isInit && !append) return true;
28  int nError = 0;
29 
30  // List of files to be checked. Start with input file.
31  vector<string> files;
32  files.push_back(startFile);
33 
34  // If nontrivial startfile path, then use that for other files as well.
35  string pathName = "";
36  if (startFile.rfind("/") != string::npos)
37  pathName = startFile.substr(0, startFile.rfind("/") + 1);
38 
39  // Loop over files. Open them for read.
40  for (int i = 0; i < int(files.size()); ++i) {
41  const char* cstring = files[i].c_str();
42  ifstream is(cstring);
43 
44  // Check that instream is OK.
45  if (!is.good()) {
46  os << "\n PYTHIA Error: settings file " << files[i]
47  << " not found" << endl;
48  return false;
49  }
50 
51  // Read in one line at a time.
52  string line;
53  while ( getline(is, line) ) {
54 
55  // Get first word of a line, to interpret it as tag.
56  istringstream getfirst(line);
57  string tag;
58  getfirst >> tag;
59 
60  // Skip ahead if not interesting. Only look for new files in startfile.
61  if (tag != "<flag" && tag != "<flagfix" && tag != "<mode"
62  && tag != "<modeopen" && tag != "<modepick" && tag != "<modefix"
63  && tag != "<parm" && tag != "<parmfix" && tag != "<word"
64  && tag != "<wordfix" && tag != "<aidx") continue;
65 
66  // Read and append continuation line(s) if line does not contain >.
67  while (line.find(">") == string::npos) {
68  string addLine;
69  getline(is, addLine);
70  line += " " + addLine;
71  }
72 
73  // Remove extra blanks before an = sign.
74  while (line.find(" =") != string::npos) line.erase( line.find(" ="), 1);
75 
76  // Add file also to be read.
77  if (tag == "<aidx") {
78  string name = attributeValue( line, "href");
79  if (name == "") {
80  os << " PYTHIA Error: failed to find name attribute in line "
81  << line << endl;
82  ++nError;
83  continue;
84  }
85  files.push_back(pathName + name + ".xml");
86  continue;
87  }
88 
89  // Find name attribute.
90  string name = attributeValue( line, "name=");
91  if (name == "") {
92  os << " PYTHIA Error: failed to find name attribute in line "
93  << line << endl;
94  ++nError;
95  continue;
96  }
97 
98  // Check that default value attribute present, and whether max and min.
99  if (line.find("default=") == string::npos) {
100  os << " PYTHIA Error: failed to find default value token in line "
101  << line << endl;
102  ++nError;
103  continue;
104  }
105  bool hasMin = (line.find("min=") != string::npos);
106  bool hasMax = (line.find("max=") != string::npos);
107 
108  // Check for occurence of a bool and add to flag map.
109  if (tag == "<flag" || tag == "<flagfix") {
110  bool value = boolAttributeValue( line, "default=");
111  addFlag( name, value);
112 
113  // Check for occurence of an int and add to mode map.
114  } else if (tag == "<mode" || tag == "<modeopen"
115  || tag == "<modepick" || tag == "<modefix") {
116  int value = intAttributeValue( line, "default=");
117  int minVal = intAttributeValue( line, "min=");
118  int maxVal = intAttributeValue( line, "max=");
119  addMode( name, value, hasMin, hasMax, minVal, maxVal);
120 
121  // Check for occurence of a double and add to parm map.
122  } else if (tag == "<parm" || tag == "<parmfix") {
123  double value = doubleAttributeValue( line, "default=");
124  double minVal = doubleAttributeValue( line, "min=");
125  double maxVal = doubleAttributeValue( line, "max=");
126  addParm( name, value, hasMin, hasMax, minVal, maxVal);
127 
128  // Check for occurence of a string and add to word map.
129  } else if (tag == "<word" || tag == "<wordfix") {
130  string value = attributeValue( line, "default=");
131  addWord( name, value);
132  }
133 
134  // End of loop over lines in input file and loop over files.
135  };
136  };
137 
138  // Set up default e+e- and pp tunes, if positive.
139  int eeTune = mode("Tune:ee");
140  if (eeTune > 0) initTuneEE( eeTune);
141  int ppTune = mode("Tune:pp");
142  if (ppTune > 0) initTunePP( ppTune);
143 
144  // Done.
145  if (nError > 0) return false;
146  isInit = true;
147  return true;
148 
149 }
150 
151 //--------------------------------------------------------------------------
152 
153 // Overwrite existing database by reading from specific file.
154 
155 bool Settings::reInit(string startFile, ostream& os) {
156 
157  // Reset maps to empty.
158  flags.clear();
159  modes.clear();
160  parms.clear();
161  words.clear();
162 
163  // Then let normal init do the rest.
164  isInit = false;
165  return init(startFile, false, os);
166 
167 }
168 
169 //--------------------------------------------------------------------------
170 
171 // Read in updates from a character string, like a line of a file.
172 // Is used by readString (and readFile) in Pythia.
173 
174 bool Settings::readString(string line, bool warn, ostream& os) {
175 
176  // If empty line then done.
177  if (line.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) return true;
178 
179  // If first character is not a letter, then taken to be a comment line.
180  string lineNow = line;
181  int firstChar = lineNow.find_first_not_of(" \n\t\v\b\r\f\a");
182  if (!isalpha(lineNow[firstChar])) return true;
183 
184  // Replace an equal sign by a blank to make parsing simpler.
185  while (lineNow.find("=") != string::npos) {
186  int firstEqual = lineNow.find_first_of("=");
187  lineNow.replace(firstEqual, 1, " ");
188  }
189 
190  // Get first word of a line.
191  istringstream splitLine(lineNow);
192  string name;
193  splitLine >> name;
194 
195  // Replace two colons by one (:: -> :) to allow for such mistakes.
196  while (name.find("::") != string::npos) {
197  int firstColonColon = name.find_first_of("::");
198  name.replace(firstColonColon, 2, ":");
199  }
200 
201  // Check whether this is in the database.
202  int inDataBase = 0;
203  if (isFlag(name)) inDataBase = 1;
204  else if (isMode(name)) inDataBase = 2;
205  else if (isParm(name)) inDataBase = 3;
206  else if (isWord(name)) inDataBase = 4;
207 
208  // For backwards compatibility: multiple -> multiparton, MI -> MPI.
209  if (inDataBase == 0) {
210  bool retry = false;
211  string nameLower = toLower(name);
212  if (nameLower.find("multiple") != string::npos) {
213  int firstMI = nameLower.find_first_of("multiple");
214  name.replace(firstMI, 8, "Multiparton");
215  retry = true;
216  }
217  if (!retry && nameLower.find("mi") != string::npos) {
218  int firstMI = nameLower.find_first_of("mi");
219  name.replace(firstMI, 2, "MPI");
220  retry = true;
221  }
222  if (retry) {
223  if (isFlag(name)) inDataBase = 1;
224  else if (isMode(name)) inDataBase = 2;
225  else if (isParm(name)) inDataBase = 3;
226  else if (isWord(name)) inDataBase = 4;
227  }
228  }
229 
230  // Warn and done if not in database.
231  if (inDataBase == 0) {
232  if (warn) os << "\n PYTHIA Warning: input string not found in settings"
233  << " databases; skip:\n " << line << endl;
234  return false;
235  }
236 
237  // Find value. Warn if none found.
238  string valueString;
239  splitLine >> valueString;
240  if (!splitLine) {
241  if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
242  << " not meaningful; skip:\n " << line << endl;
243  return false;
244  }
245 
246  // Update flag map; allow many ways to say yes.
247  if (inDataBase == 1) {
248  bool value = boolString(valueString);
249  flag(name, value);
250 
251  // Update mode map.
252  } else if (inDataBase == 2) {
253  istringstream modeData(valueString);
254  int value;
255  modeData >> value;
256  if (!modeData) {
257  if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
258  << " not meaningful; skip:\n " << line << endl;
259  return false;
260  }
261  mode(name, value);
262 
263  // Update parm map.
264  } else if (inDataBase == 3) {
265  istringstream parmData(valueString);
266  double value;
267  parmData >> value;
268  if (!parmData) {
269  if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
270  << " not meaningful; skip:\n " << line << endl;
271  return false;
272  }
273  parm(name, value);
274 
275  // Update word map.
276  } else {
277  word(name, valueString);
278  }
279 
280  // Done.
281  return true;
282 }
283 
284 //--------------------------------------------------------------------------
285 
286 // Write updates or everything to user-defined file.
287 
288 bool Settings::writeFile(string toFile, bool writeAll) {
289 
290  // Open file for writing.
291  const char* cstring = toFile.c_str();
292  ofstream os(cstring);
293  if (!os) {
294  infoPtr->errorMsg("Error in Settings::writeFile:"
295  " could not open file", toFile);
296  return false;
297  }
298 
299  // Hand over real work to next method.
300  return writeFile( os, writeAll);
301 
302 }
303 
304 //--------------------------------------------------------------------------
305 
306 // Write updates or everything to user-defined stream (or file).
307 
308 bool Settings::writeFile(ostream& os, bool writeAll) {
309 
310  // Write simple header as comment.
311  if (writeAll) os << "! List of all current PYTHIA ";
312  else os << "! List of all modified PYTHIA ";
313  os << fixed << setprecision(3) << parm("Pythia:versionNumber")
314  << " settings.\n";
315 
316  // Iterators for the flag, mode and parm tables.
317  map<string, Flag>::iterator flagEntry = flags.begin();
318  map<string, Mode>::iterator modeEntry = modes.begin();
319  map<string, Parm>::iterator parmEntry = parms.begin();
320  map<string, Word>::iterator wordEntry = words.begin();
321 
322  // Loop while there is something left to do.
323  while (flagEntry != flags.end() || modeEntry != modes.end()
324  || parmEntry != parms.end() || wordEntry != words.end()) {
325 
326  // Check if a flag is next in lexigraphical order; if so print it.
327  if ( flagEntry != flags.end()
328  && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first )
329  && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
330  && ( wordEntry == words.end() || flagEntry->first < wordEntry->first )
331  ) {
332  string state[2] = {"off", "on"};
333  bool valNow = flagEntry->second.valNow;
334  bool valDefault = flagEntry->second.valDefault;
335  if ( writeAll || valNow != valDefault )
336  os << flagEntry->second.name << " = " << state[valNow] << "\n";
337  ++flagEntry;
338 
339  // Else check if mode is next, and if so print it.
340  } else if ( modeEntry != modes.end()
341  && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first )
342  && ( wordEntry == words.end() || modeEntry->first < wordEntry->first )
343  ) {
344  int valNow = modeEntry->second.valNow;
345  int valDefault = modeEntry->second.valDefault;
346  if ( writeAll || valNow != valDefault )
347  os << modeEntry->second.name << " = " << valNow << "\n";
348  ++modeEntry;
349 
350  // Else check if parm is next, and if so print it;
351  // fixed or scientific depending on value.
352  } else if ( parmEntry != parms.end()
353  && ( wordEntry == words.end() || parmEntry->first < wordEntry->first )
354  ) {
355  double valNow = parmEntry->second.valNow;
356  double valDefault = parmEntry->second.valDefault;
357  if ( writeAll || valNow != valDefault ) {
358  os << parmEntry->second.name << " = ";
359  if ( valNow == 0. ) os << fixed << setprecision(1);
360  else if ( abs(valNow) < 0.001 ) os << scientific << setprecision(4);
361  else if ( abs(valNow) < 0.1 ) os << fixed << setprecision(7);
362  else if ( abs(valNow) < 1000. ) os << fixed << setprecision(5);
363  else if ( abs(valNow) < 1000000. ) os << fixed << setprecision(3);
364  else os << scientific << setprecision(4);
365  os << valNow << "\n";
366  }
367  ++parmEntry;
368 
369  // Else print word.
370  } else {
371  string valNow = wordEntry->second.valNow;
372  string valDefault = wordEntry->second.valDefault;
373  if ( writeAll || valNow != valDefault )
374  os << wordEntry->second.name << " = " << valNow << "\n";
375  ++wordEntry;
376  }
377  } ;
378 
379  // Done.
380  return true;
381 }
382 
383 //--------------------------------------------------------------------------
384 
385 // Print out table of database in lexigraphical order.
386 
387 void Settings::list(bool doListAll, bool doListString, string match,
388  ostream& os) {
389 
390  // Table header; output for bool as off/on.
391  if (doListAll)
392  os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (all) "
393  << " -------------------------------------------------------* \n";
394  else if (!doListString)
395  os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (chang"
396  << "es only) ----------------------------------------------* \n" ;
397  else
398  os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (with "
399  << "requested string) -------------------------------------* \n" ;
400  os << " | "
401  << " | \n"
402  << " | Name | "
403  << " Now | Default Min Max | \n"
404  << " | | "
405  << " | | \n";
406 
407  // Convert input string to lowercase for match.
408  match = toLower(match);
409  if (match == "") match = " ";
410 
411  // Iterators for the flag, mode and parm tables.
412  map<string, Flag>::iterator flagEntry = flags.begin();
413  map<string, Mode>::iterator modeEntry = modes.begin();
414  map<string, Parm>::iterator parmEntry = parms.begin();
415  map<string, Word>::iterator wordEntry = words.begin();
416 
417  // Loop while there is something left to do.
418  while (flagEntry != flags.end() || modeEntry != modes.end()
419  || parmEntry != parms.end() || wordEntry != words.end()) {
420 
421  // Check if a flag is next in lexigraphical order; if so print it.
422  if ( flagEntry != flags.end()
423  && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first )
424  && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
425  && ( wordEntry == words.end() || flagEntry->first < wordEntry->first )
426  ) {
427  string state[2] = {"off", "on"};
428  bool valNow = flagEntry->second.valNow;
429  bool valDefault = flagEntry->second.valDefault;
430  if ( doListAll || (!doListString && valNow != valDefault)
431  || (doListString && flagEntry->first.find(match) != string::npos) )
432  os << " | " << setw(45) << left
433  << flagEntry->second.name << " | " << setw(24) << right
434  << state[valNow] << " | " << setw(12) << state[valDefault]
435  << " | \n";
436  ++flagEntry;
437 
438  // Else check if mode is next, and if so print it.
439  } else if ( modeEntry != modes.end()
440  && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first )
441  && ( wordEntry == words.end() || modeEntry->first < wordEntry->first )
442  ) {
443  int valNow = modeEntry->second.valNow;
444  int valDefault = modeEntry->second.valDefault;
445  if ( doListAll || (!doListString && valNow != valDefault)
446  || (doListString && modeEntry->first.find(match) != string::npos) ) {
447  os << " | " << setw(45) << left
448  << modeEntry->second.name << " | " << setw(24) << right
449  << valNow << " | " << setw(12) << valDefault;
450  if (modeEntry->second.hasMin)
451  os << setw(12) << modeEntry->second.valMin;
452  else os << " ";
453  if (modeEntry->second.hasMax)
454  os << setw(12) << modeEntry->second.valMax;
455  else os << " ";
456  os << " | \n";
457  }
458  ++modeEntry;
459 
460  // Else check if parm is next, and if so print it;
461  // fixed or scientific depending on value.
462  } else if ( parmEntry != parms.end()
463  && ( wordEntry == words.end() || parmEntry->first < wordEntry->first )
464  ) {
465  double valNow = parmEntry->second.valNow;
466  double valDefault = parmEntry->second.valDefault;
467  if ( doListAll || (!doListString && valNow != valDefault )
468  || (doListString && parmEntry->first.find(match) != string::npos) ) {
469  os << " | " << setw(45) << left
470  << parmEntry->second.name << right << " | ";
471  for (int i = 0; i < 4; ++i) {
472  if (i == 1) valNow = valDefault;
473  if (i == 2) valNow = parmEntry->second.valMin;
474  if (i == 3) valNow = parmEntry->second.valMax;
475  if ( (i == 2 && !parmEntry->second.hasMin)
476  || (i == 3 && !parmEntry->second.hasMax) )
477  os << " ";
478  else if ( valNow == 0. )
479  os << fixed << setprecision(1) << setw(12) << valNow;
480  else if ( abs(valNow) < 0.001 )
481  os << scientific << setprecision(4) << setw(12) << valNow;
482  else if ( abs(valNow) < 0.1 )
483  os << fixed << setprecision(7) << setw(12) << valNow;
484  else if ( abs(valNow) < 1000. )
485  os << fixed << setprecision(5) << setw(12) << valNow;
486  else if ( abs(valNow) < 1000000. )
487  os << fixed << setprecision(3) << setw(12) << valNow;
488  else
489  os << scientific << setprecision(4) << setw(12) << valNow;
490  if (i == 0) os << " | ";
491  }
492  os << " | \n";
493  }
494  ++parmEntry;
495 
496  // Else print word.
497  } else {
498  string valNow = wordEntry->second.valNow;
499  string valDefault = wordEntry->second.valDefault;
500  int blankLeft = max(0, 60 - max(24, int(valNow.length()) )
501  - max(12, int(valDefault.length()) ) );
502  string blankPad( blankLeft, ' ');
503  if ( doListAll || (!doListString && valNow != valDefault)
504  || (doListString && wordEntry->first.find(match) != string::npos) )
505  os << " | " << setw(45) << left
506  << wordEntry->second.name << " | " << setw(24) << right
507  << valNow << " | " << setw(12) << valDefault << blankPad
508  << " | \n";
509  ++wordEntry;
510  }
511  } ;
512 
513  // End of loop over database contents.
514  os << " | "
515  << " | \n"
516  << " *------- End PYTHIA Flag + Mode + Parm + Word Settings ---"
517  << "------------------------------------------------------* " << endl;
518 
519 }
520 
521 //--------------------------------------------------------------------------
522 
523 // Reset all values to their defaults.
524 
525 void Settings::resetAll() {
526 
527  // Loop through the flags table, resetting all entries.
528  for (map<string, Flag>::iterator flagEntry = flags.begin();
529  flagEntry != flags.end(); ++flagEntry) {
530  string name = flagEntry->first;
531  resetFlag(name);
532  }
533 
534  // Loop through the modes table, resetting all entries.
535  for (map<string, Mode>::iterator modeEntry = modes.begin();
536  modeEntry != modes.end(); ++modeEntry) {
537  string name = modeEntry->first;
538  resetMode(name);
539  }
540 
541  // Loop through the parms table, resetting all entries.
542  for (map<string, Parm>::iterator parmEntry = parms.begin();
543  parmEntry != parms.end(); ++parmEntry) {
544  string name = parmEntry->first;
545  resetParm(name);
546  }
547 
548  // Loop through the words table, resetting all entries.
549  for (map<string, Word>::iterator wordEntry = words.begin();
550  wordEntry != words.end(); ++wordEntry) {
551  string name = wordEntry->first;
552  resetWord(name);
553  }
554 
555 }
556 
557 //--------------------------------------------------------------------------
558 
559 // Give back current value, with check that key exists.
560 
561 bool Settings::flag(string keyIn) {
562  if (isFlag(keyIn)) return flags[toLower(keyIn)].valNow;
563  infoPtr->errorMsg("Error in Settings::flag: unknown key", keyIn);
564  return false;
565 }
566 
567 int Settings::mode(string keyIn) {
568  if (isMode(keyIn)) return modes[toLower(keyIn)].valNow;
569  infoPtr->errorMsg("Error in Settings::mode: unknown key", keyIn);
570  return 0;
571 }
572 
573 double Settings::parm(string keyIn) {
574  if (isParm(keyIn)) return parms[toLower(keyIn)].valNow;
575  infoPtr->errorMsg("Error in Settings::parm: unknown key", keyIn);
576  return 0.;
577 }
578 
579 string Settings::word(string keyIn) {
580  if (isWord(keyIn)) return words[toLower(keyIn)].valNow;
581  infoPtr->errorMsg("Error in Settings::word: unknown key", keyIn);
582  return " ";
583 }
584 
585 //--------------------------------------------------------------------------
586 
587 // Get a map of entries whose names contain the string "match".
588 
589 map<string, Flag> Settings::getFlagMap(string match) {
590  // Make the match string lower case. Start with an empty map.
591  match = toLower(match);
592  map<string, Flag> flagMap;
593  // Loop over the flag map (using iterator).
594  for (map<string,Flag>::iterator flagEntry = flags.begin();
595  flagEntry != flags.end(); ++flagEntry)
596  if (flagEntry->first.find(match) != string::npos)
597  flagMap[flagEntry->first] = flagEntry->second;
598  return flagMap;
599 }
600 
601 map<string, Mode> Settings::getModeMap(string match) {
602  // Make the match string lower case. Start with an empty map.
603  match = toLower(match);
604  map<string, Mode> modeMap;
605  // Loop over the mode map (using iterator).
606  for (map<string,Mode>::iterator modeEntry = modes.begin();
607  modeEntry != modes.end(); ++modeEntry)
608  if (modeEntry->first.find(match) != string::npos)
609  modeMap[modeEntry->first] = modeEntry->second;
610  return modeMap;
611 }
612 
613 map<string, Parm> Settings::getParmMap(string match) {
614  // Make the match string lower case. Start with an empty map.
615  match = toLower(match);
616  map<string, Parm> parmMap;
617  // Loop over the parm map (using iterator).
618  for (map<string,Parm>::iterator parmEntry = parms.begin();
619  parmEntry != parms.end(); ++parmEntry)
620  if (parmEntry->first.find(match) != string::npos)
621  parmMap[parmEntry->first] = parmEntry->second;
622  return parmMap;
623 }
624 
625 map<string, Word> Settings::getWordMap(string match) {
626  // Make the match string lower case. Start with an empty map.
627  match = toLower(match);
628  map<string, Word> wordMap;
629  // Loop over the word map (using iterator).
630  for (map<string,Word>::iterator wordEntry = words.begin();
631  wordEntry != words.end(); ++wordEntry)
632  if (wordEntry->first.find(match) != string::npos)
633  wordMap[wordEntry->first] = wordEntry->second;
634  return wordMap;
635 }
636 
637 //--------------------------------------------------------------------------
638 
639 // Change current value, respecting limits.
640 
641 void Settings::flag(string keyIn, bool nowIn) {
642  if (isFlag(keyIn)) flags[toLower(keyIn)].valNow = nowIn;
643 }
644 
645 void Settings:: mode(string keyIn, int nowIn) {
646  if (isMode(keyIn)) {
647  string keyLower = toLower(keyIn);
648  Mode& modeNow = modes[keyLower];
649  if (modeNow.hasMin && nowIn < modeNow.valMin)
650  modeNow.valNow = modeNow.valMin;
651  else if (modeNow.hasMax && nowIn > modeNow.valMax)
652  modeNow.valNow = modeNow.valMax;
653  else modeNow.valNow = nowIn;
654  // Tune:ee and Tune:pp each trigger a whole set of changes.
655  if (keyLower == "tune:ee") initTuneEE( modeNow.valNow);
656  if (keyLower == "tune:pp") initTunePP( modeNow.valNow);
657  }
658 }
659 
660 void Settings::parm(string keyIn, double nowIn) {
661  if (isParm(keyIn)) {
662  Parm& parmNow = parms[toLower(keyIn)];
663  if (parmNow.hasMin && nowIn < parmNow.valMin)
664  parmNow.valNow = parmNow.valMin;
665  else if (parmNow.hasMax && nowIn > parmNow.valMax)
666  parmNow.valNow = parmNow.valMax;
667  else parmNow.valNow = nowIn;
668  }
669 }
670 
671 void Settings::word(string keyIn, string nowIn) {
672  if (isWord(keyIn)) words[toLower(keyIn)].valNow = nowIn;
673 }
674 
675 //--------------------------------------------------------------------------
676 
677 // Change current value, disregarding limits.
678 
679 void Settings::forceMode(string keyIn, int nowIn) {
680  if (isMode(keyIn)) {
681  string keyLower = toLower(keyIn);
682  Mode& modeNow = modes[keyLower];
683  modeNow.valNow = nowIn;
684  // Tune:ee and Tune:pp each trigger a whole set of changes.
685  if (keyLower == "tune:ee") initTuneEE( modeNow.valNow);
686  if (keyLower == "tune:pp") initTunePP( modeNow.valNow);
687  }
688 }
689 
690 void Settings::forceParm(string keyIn, double nowIn) {
691  if (isParm(keyIn)) parms[toLower(keyIn)].valNow = nowIn;
692 }
693 
694 //--------------------------------------------------------------------------
695 
696 // Restore current value to default.
697 
698 void Settings::resetFlag(string keyIn) {
699  if (isFlag(keyIn)) flags[toLower(keyIn)].valNow
700  = flags[toLower(keyIn)].valDefault ;
701 }
702 
703 void Settings::resetMode(string keyIn) {
704  string keyLower = toLower(keyIn);
705  if (isMode(keyIn)) modes[keyLower].valNow
706  = modes[toLower(keyIn)].valDefault ;
707 
708  // For Tune:ee must also restore variables involved in tune.
709  if (keyLower == "tune:ee") {
710  resetParm("StringFlav:probStoUD");
711  resetParm("StringFlav:probQQtoQ");
712  resetParm("StringFlav:probSQtoQQ");
713  resetParm("StringFlav:probQQ1toQQ0");
714  resetParm("StringFlav:mesonUDvector");
715  resetParm("StringFlav:mesonSvector");
716  resetParm("StringFlav:mesonCvector");
717  resetParm("StringFlav:mesonBvector");
718  resetParm("StringFlav:etaSup");
719  resetParm("StringFlav:etaPrimeSup");
720  resetParm("StringFlav:popcornSpair");
721  resetParm("StringFlav:popcornSmeson");
722  resetParm("StringZ:aLund");
723  resetParm("StringZ:bLund");
724  resetParm("StringZ:rFactB");
725  resetParm("StringPT:sigma");
726  resetParm("TimeShower:alphaSvalue");
727  resetParm("TimeShower:pTmin");
728  resetParm("TimeShower:pTminChgQ");
729  }
730 
731  // For Tune:pp must also restore variables involved in tune.
732  if (keyLower == "tune:pp") {
733  resetMode("PDF:pSet");
734  resetParm("SigmaProcess:alphaSvalue");
735  resetFlag("SigmaDiffractive:dampen");
736  resetFlag("TimeShower:dampenBeamRecoil");
737  resetFlag("TimeShower:phiPolAsym");
738  resetParm("SpaceShower:alphaSvalue");
739  resetFlag("SpaceShower:samePTasMPI");
740  resetParm("SpaceShower:pT0Ref");
741  resetParm("SpaceShower:ecmRef");
742  resetParm("SpaceShower:ecmPow");
743  resetFlag("SpaceShower:rapidityOrder");
744  resetFlag("SpaceShower:phiPolAsym");
745  resetFlag("SpaceShower:phiIntAsym");
746  resetParm("MultipartonInteractions:alphaSvalue");
747  resetParm("MultipartonInteractions:pT0Ref");
748  resetParm("MultipartonInteractions:ecmRef");
749  resetParm("MultipartonInteractions:ecmPow");
750  resetMode("MultipartonInteractions:bProfile");
751  resetParm("BeamRemnants:primordialKTsoft");
752  resetParm("BeamRemnants:primordialKThard");
753  resetParm("BeamRemnants:halfScaleForKT");
754  resetParm("BeamRemnants:halfMassForKT");
755  resetParm("BeamRemnants:reconnectRange");
756  }
757 
758 }
759 
760 void Settings::resetParm(string keyIn) {
761  if (isParm(keyIn)) parms[toLower(keyIn)].valNow
762  = parms[toLower(keyIn)].valDefault ;
763 }
764 
765 void Settings::resetWord(string keyIn) {
766  if (isWord(keyIn)) words[toLower(keyIn)].valNow
767  = words[toLower(keyIn)].valDefault ;
768 }
769 
770 //--------------------------------------------------------------------------
771 
772 // Set the values related to a tune of e+e- data,
773 // i.e. mainly for final-state radiation and hadronization.
774 
775 void Settings::initTuneEE( int eeTune) {
776 
777  // Restore all e+e- settings to their original values.
778  // Is first step for setting up a specific tune.
779  if (eeTune != 0) {
780  resetParm("StringFlav:probStoUD");
781  resetParm("StringFlav:probQQtoQ");
782  resetParm("StringFlav:probSQtoQQ");
783  resetParm("StringFlav:probQQ1toQQ0");
784  resetParm("StringFlav:mesonUDvector");
785  resetParm("StringFlav:mesonSvector");
786  resetParm("StringFlav:mesonCvector");
787  resetParm("StringFlav:mesonBvector");
788  resetParm("StringFlav:etaSup");
789  resetParm("StringFlav:etaPrimeSup");
790  resetParm("StringFlav:popcornSpair");
791  resetParm("StringFlav:popcornSmeson");
792  resetParm("StringZ:aLund");
793  resetParm("StringZ:bLund");
794  resetParm("StringZ:rFactB");
795  resetParm("StringPT:sigma");
796  resetParm("TimeShower:alphaSvalue");
797  resetParm("TimeShower:pTmin");
798  resetParm("TimeShower:pTminChgQ");
799  }
800 
801  // Old flavour and FSR defaults carried over from very old JETSET tune,
802  // only with alphaS roughly tuned for "new" pT-ordered shower.
803  if (eeTune == 1) {
804  parm("StringFlav:probStoUD", 0.30 );
805  parm("StringFlav:probQQtoQ", 0.10 );
806  parm("StringFlav:probSQtoQQ", 0.40 );
807  parm("StringFlav:probQQ1toQQ0", 0.05 );
808  parm("StringFlav:mesonUDvector", 1.00 );
809  parm("StringFlav:mesonSvector", 1.50 );
810  parm("StringFlav:mesonCvector", 2.50 );
811  parm("StringFlav:mesonBvector", 3.00 );
812  parm("StringFlav:etaSup", 1.00 );
813  parm("StringFlav:etaPrimeSup", 0.40 );
814  parm("StringFlav:popcornSpair", 0.50 );
815  parm("StringFlav:popcornSmeson", 0.50 );
816  parm("StringZ:aLund", 0.30 );
817  parm("StringZ:bLund", 0.58 );
818  parm("StringZ:rFactB", 1.00 );
819  parm("StringPT:sigma", 0.36 );
820  parm("TimeShower:alphaSvalue", 0.137 );
821  parm("TimeShower:pTmin", 0.5 );
822  parm("TimeShower:pTminChgQ", 0.5 );
823  }
824 
825  // Marc Montull's tune to particle composition at LEP1 (August 2007).
826  else if (eeTune == 2) {
827  parm("StringFlav:probStoUD", 0.22 );
828  parm("StringFlav:probQQtoQ", 0.08 );
829  parm("StringFlav:probSQtoQQ", 0.75 );
830  parm("StringFlav:probQQ1toQQ0", 0.025 );
831  parm("StringFlav:mesonUDvector", 0.5 );
832  parm("StringFlav:mesonSvector", 0.6 );
833  parm("StringFlav:mesonCvector", 1.5 );
834  parm("StringFlav:mesonBvector", 2.5 );
835  parm("StringFlav:etaSup", 0.60 );
836  parm("StringFlav:etaPrimeSup", 0.15 );
837  parm("StringFlav:popcornSpair", 1.0 );
838  parm("StringFlav:popcornSmeson", 1.0 );
839  parm("StringZ:aLund", 0.76 );
840  parm("StringZ:bLund", 0.58 ); // kept fixed
841  parm("StringZ:rFactB", 1.00 ); // kept fixed
842  parm("StringPT:sigma", 0.36 ); // kept fixed
843  parm("TimeShower:alphaSvalue", 0.137 ); // kept fixed
844  parm("TimeShower:pTmin", 0.5 ); // kept fixed
845  parm("TimeShower:pTminChgQ", 0.5 ); // kept fixed
846  }
847 
848  // Full e+e- tune of flavours and FSR to LEP1 data within the
849  // Rivet + Professor framework, by Hendrik Hoeth (June 2009).
850  else if (eeTune == 3) {
851  parm("StringFlav:probStoUD", 0.19 );
852  parm("StringFlav:probQQtoQ", 0.09 );
853  parm("StringFlav:probSQtoQQ", 1.00 );
854  parm("StringFlav:probQQ1toQQ0", 0.027 );
855  parm("StringFlav:mesonUDvector", 0.62 );
856  parm("StringFlav:mesonSvector", 0.725 );
857  parm("StringFlav:mesonCvector", 1.06 );
858  parm("StringFlav:mesonBvector", 3.0 );
859  parm("StringFlav:etaSup", 0.63 );
860  parm("StringFlav:etaPrimeSup", 0.12 );
861  parm("StringFlav:popcornSpair", 0.5 ); // kept fixed
862  parm("StringFlav:popcornSmeson", 0.5 ); // kept fixed
863  parm("StringZ:aLund", 0.3 ); // kept fixed
864  parm("StringZ:bLund", 0.8 );
865  parm("StringZ:rFactB", 0.67 );
866  parm("StringPT:sigma", 0.304 );
867  parm("TimeShower:alphaSvalue", 0.1383);
868  parm("TimeShower:pTmin", 0.4 ); // kept fixed (near limit)
869  parm("TimeShower:pTminChgQ", 0.4 ); // kept same as pTmin
870  }
871 
872 }
873 
874 //--------------------------------------------------------------------------
875 
876 // Set the values related to a tune of pp/ppbar data,
877 // i.e. mainly for initial-state radiation and multiparton interactions.
878 
879 void Settings::initTunePP( int ppTune) {
880 
881  // Restore all pp/ppbar settings to their original values.
882  // Is first step for setting up a specific tune.
883  if (ppTune != 0) {
884  resetMode("PDF:pSet");
885  resetParm("SigmaProcess:alphaSvalue");
886  resetFlag("SigmaDiffractive:dampen");
887  resetParm("SigmaDiffractive:maxXB");
888  resetParm("SigmaDiffractive:maxAX");
889  resetParm("SigmaDiffractive:maxXX");
890  resetFlag("TimeShower:dampenBeamRecoil");
891  resetFlag("TimeShower:phiPolAsym");
892  resetParm("SpaceShower:alphaSvalue");
893  resetFlag("SpaceShower:samePTasMPI");
894  resetParm("SpaceShower:pT0Ref");
895  resetParm("SpaceShower:ecmRef");
896  resetParm("SpaceShower:ecmPow");
897  resetFlag("SpaceShower:rapidityOrder");
898  resetFlag("SpaceShower:phiPolAsym");
899  resetFlag("SpaceShower:phiIntAsym");
900  resetParm("MultipartonInteractions:alphaSvalue");
901  resetParm("MultipartonInteractions:pT0Ref");
902  resetParm("MultipartonInteractions:ecmRef");
903  resetParm("MultipartonInteractions:ecmPow");
904  resetMode("MultipartonInteractions:bProfile");
905  resetParm("MultipartonInteractions:expPow");
906  resetParm("MultipartonInteractions:a1");
907  resetParm("BeamRemnants:primordialKTsoft");
908  resetParm("BeamRemnants:primordialKThard");
909  resetParm("BeamRemnants:halfScaleForKT");
910  resetParm("BeamRemnants:halfMassForKT");
911  resetParm("BeamRemnants:reconnectRange");
912  }
913 
914  // Old ISR and MPI defaults from early and primitive comparisons with data.
915  if (ppTune == 1) {
916  mode("PDF:pSet", 2 );
917  parm("SigmaProcess:alphaSvalue", 0.1265);
918  flag("SigmaDiffractive:dampen", false );
919  flag("TimeShower:dampenBeamRecoil", false );
920  flag("TimeShower:phiPolAsym", false );
921  parm("SpaceShower:alphaSvalue", 0.127 );
922  flag("SpaceShower:samePTasMPI", true );
923  parm("SpaceShower:pT0Ref", 2.2 );
924  parm("SpaceShower:ecmRef", 1800.0);
925  parm("SpaceShower:ecmPow", 0.16 );
926  flag("SpaceShower:rapidityOrder", false );
927  flag("SpaceShower:phiPolAsym", false );
928  flag("SpaceShower:phiIntAsym", false );
929  parm("MultipartonInteractions:alphaSvalue", 0.127 );
930  parm("MultipartonInteractions:pT0Ref", 2.15 );
931  parm("MultipartonInteractions:ecmRef", 1800. );
932  parm("MultipartonInteractions:ecmPow", 0.16 );
933  mode("MultipartonInteractions:bProfile", 2 );
934  parm("BeamRemnants:primordialKTsoft", 0.4 );
935  parm("BeamRemnants:primordialKThard", 2.1 );
936  parm("BeamRemnants:halfScaleForKT", 7.0 );
937  parm("BeamRemnants:halfMassForKT", 2.0 );
938  parm("BeamRemnants:reconnectRange", 2.5 );
939  }
940 
941  // "Tune 1" simple first tune by Peter Skands to ISR and MPI, July 2009.
942  else if (ppTune == 2) {
943  mode("PDF:pSet", 2 );
944  parm("SigmaProcess:alphaSvalue", 0.1265);
945  flag("SigmaDiffractive:dampen", false );
946  flag("TimeShower:dampenBeamRecoil", false );
947  flag("TimeShower:phiPolAsym", false );
948  parm("SpaceShower:alphaSvalue", 0.137 );
949  flag("SpaceShower:samePTasMPI", false );
950  parm("SpaceShower:pT0Ref", 2.0 );
951  parm("SpaceShower:ecmRef", 1800.0);
952  parm("SpaceShower:ecmPow", 0.0 );
953  flag("SpaceShower:rapidityOrder", false );
954  flag("SpaceShower:phiPolAsym", false );
955  flag("SpaceShower:phiIntAsym", false );
956  parm("MultipartonInteractions:alphaSvalue", 0.127 );
957  parm("MultipartonInteractions:pT0Ref", 2.25 );
958  parm("MultipartonInteractions:ecmRef", 1800. );
959  parm("MultipartonInteractions:ecmPow", 0.24 );
960  mode("MultipartonInteractions:bProfile", 1 );
961  parm("BeamRemnants:primordialKTsoft", 0.5 );
962  parm("BeamRemnants:primordialKThard", 2.0 );
963  parm("BeamRemnants:halfScaleForKT", 1.0 );
964  parm("BeamRemnants:halfMassForKT", 1.0 );
965  parm("BeamRemnants:reconnectRange", 10.0 );
966  }
967 
968  // Tune 2C, July 2010.
969  else if (ppTune == 3) {
970  mode("PDF:pSet", 8 );
971  parm("SigmaProcess:alphaSvalue", 0.135 );
972  flag("SigmaDiffractive:dampen", false );
973  flag("TimeShower:dampenBeamRecoil", true );
974  flag("TimeShower:phiPolAsym", true );
975  parm("SpaceShower:alphaSvalue", 0.137 );
976  flag("SpaceShower:samePTasMPI", false );
977  parm("SpaceShower:pT0Ref", 2.0 );
978  parm("SpaceShower:ecmRef", 1800.0);
979  parm("SpaceShower:ecmPow", 0.0 );
980  flag("SpaceShower:rapidityOrder", true );
981  flag("SpaceShower:phiPolAsym", true );
982  flag("SpaceShower:phiIntAsym", true );
983  parm("MultipartonInteractions:alphaSvalue", 0.135 );
984  parm("MultipartonInteractions:pT0Ref", 2.32 );
985  parm("MultipartonInteractions:ecmRef", 1800. );
986  parm("MultipartonInteractions:ecmPow", 0.21 );
987  mode("MultipartonInteractions:bProfile", 3 );
988  parm("MultipartonInteractions:expPow", 1.6 );
989  parm("BeamRemnants:primordialKTsoft", 0.5 );
990  parm("BeamRemnants:primordialKThard", 2.0 );
991  parm("BeamRemnants:halfScaleForKT", 1.0 );
992  parm("BeamRemnants:halfMassForKT", 1.0 );
993  parm("BeamRemnants:reconnectRange", 3.0 );
994  }
995 
996  // Tune 2M, July 2010.
997  else if (ppTune == 4) {
998  mode("PDF:pSet", 4 );
999  parm("SigmaProcess:alphaSvalue", 0.1265);
1000  flag("SigmaDiffractive:dampen", false );
1001  flag("TimeShower:dampenBeamRecoil", true );
1002  flag("TimeShower:phiPolAsym", true );
1003  parm("SpaceShower:alphaSvalue", 0.130 );
1004  flag("SpaceShower:samePTasMPI", false );
1005  parm("SpaceShower:pT0Ref", 2.0 );
1006  parm("SpaceShower:ecmRef", 1800.0);
1007  parm("SpaceShower:ecmPow", 0.0 );
1008  flag("SpaceShower:rapidityOrder", true );
1009  flag("SpaceShower:phiPolAsym", true );
1010  flag("SpaceShower:phiIntAsym", true );
1011  parm("MultipartonInteractions:alphaSvalue", 0.127 );
1012  parm("MultipartonInteractions:pT0Ref", 2.455 );
1013  parm("MultipartonInteractions:ecmRef", 1800. );
1014  parm("MultipartonInteractions:ecmPow", 0.26 );
1015  mode("MultipartonInteractions:bProfile", 3 );
1016  parm("MultipartonInteractions:expPow", 1.15 );
1017  parm("BeamRemnants:primordialKTsoft", 0.5 );
1018  parm("BeamRemnants:primordialKThard", 2.0 );
1019  parm("BeamRemnants:halfScaleForKT", 1.0 );
1020  parm("BeamRemnants:halfMassForKT", 1.0 );
1021  parm("BeamRemnants:reconnectRange", 3.0 );
1022  }
1023 
1024  // Tune 4C, October 2010.
1025  else if (ppTune == 5) {
1026  mode("PDF:pSet", 8 );
1027  parm("SigmaProcess:alphaSvalue", 0.135 );
1028  flag("SigmaDiffractive:dampen", true );
1029  parm("SigmaDiffractive:maxXB", 65.0 );
1030  parm("SigmaDiffractive:maxAX", 65.0 );
1031  parm("SigmaDiffractive:maxXX", 65.0 );
1032  flag("TimeShower:dampenBeamRecoil", true );
1033  flag("TimeShower:phiPolAsym", true );
1034  parm("SpaceShower:alphaSvalue", 0.137 );
1035  flag("SpaceShower:samePTasMPI", false );
1036  parm("SpaceShower:pT0Ref", 2.0 );
1037  parm("SpaceShower:ecmRef", 1800.0);
1038  parm("SpaceShower:ecmPow", 0.0 );
1039  flag("SpaceShower:rapidityOrder", true );
1040  flag("SpaceShower:phiPolAsym", true );
1041  flag("SpaceShower:phiIntAsym", true );
1042  parm("MultipartonInteractions:alphaSvalue", 0.135 );
1043  parm("MultipartonInteractions:pT0Ref", 2.085 );
1044  parm("MultipartonInteractions:ecmRef", 1800. );
1045  parm("MultipartonInteractions:ecmPow", 0.19 );
1046  mode("MultipartonInteractions:bProfile", 3 );
1047  parm("MultipartonInteractions:expPow", 2.0 );
1048  parm("BeamRemnants:primordialKTsoft", 0.5 );
1049  parm("BeamRemnants:primordialKThard", 2.0 );
1050  parm("BeamRemnants:halfScaleForKT", 1.0 );
1051  parm("BeamRemnants:halfMassForKT", 1.0 );
1052  parm("BeamRemnants:reconnectRange", 1.5 );
1053  }
1054 
1055  // Tune 4Cx, January 2011.
1056  else if (ppTune == 6) {
1057  mode("PDF:pSet", 8 );
1058  parm("SigmaProcess:alphaSvalue", 0.135 );
1059  flag("SigmaDiffractive:dampen", true );
1060  parm("SigmaDiffractive:maxXB", 65.0 );
1061  parm("SigmaDiffractive:maxAX", 65.0 );
1062  parm("SigmaDiffractive:maxXX", 65.0 );
1063  flag("TimeShower:dampenBeamRecoil", true );
1064  flag("TimeShower:phiPolAsym", true );
1065  parm("SpaceShower:alphaSvalue", 0.137 );
1066  flag("SpaceShower:samePTasMPI", false );
1067  parm("SpaceShower:pT0Ref", 2.0 );
1068  parm("SpaceShower:ecmRef", 1800.0);
1069  parm("SpaceShower:ecmPow", 0.0 );
1070  flag("SpaceShower:rapidityOrder", true );
1071  flag("SpaceShower:phiPolAsym", true );
1072  flag("SpaceShower:phiIntAsym", true );
1073  parm("MultipartonInteractions:alphaSvalue", 0.135 );
1074  parm("MultipartonInteractions:pT0Ref", 2.15 );
1075  parm("MultipartonInteractions:ecmRef", 1800. );
1076  parm("MultipartonInteractions:ecmPow", 0.19 );
1077  mode("MultipartonInteractions:bProfile", 4 );
1078  parm("MultipartonInteractions:a1", 0.15 );
1079  parm("BeamRemnants:primordialKTsoft", 0.5 );
1080  parm("BeamRemnants:primordialKThard", 2.0 );
1081  parm("BeamRemnants:halfScaleForKT", 1.0 );
1082  parm("BeamRemnants:halfMassForKT", 1.0 );
1083  parm("BeamRemnants:reconnectRange", 1.5 );
1084  }
1085 
1086  // Tune A2, November 2011 (ATLAS; Deepak Kar).
1087  else if (ppTune == 7) {
1088  mode("PDF:pSet", 8 );
1089  parm("SigmaProcess:alphaSvalue", 0.135 );
1090  flag("SigmaDiffractive:dampen", true );
1091  parm("SigmaDiffractive:maxXB", 65.0 );
1092  parm("SigmaDiffractive:maxAX", 65.0 );
1093  parm("SigmaDiffractive:maxXX", 65.0 );
1094  flag("TimeShower:dampenBeamRecoil", true );
1095  flag("TimeShower:phiPolAsym", true );
1096  parm("SpaceShower:alphaSvalue", 0.137 );
1097  flag("SpaceShower:samePTasMPI", false );
1098  parm("SpaceShower:pT0Ref", 2.0 );
1099  parm("SpaceShower:ecmRef", 1800.0);
1100  parm("SpaceShower:ecmPow", 0.0 );
1101  flag("SpaceShower:rapidityOrder", false );
1102  flag("SpaceShower:phiPolAsym", true );
1103  flag("SpaceShower:phiIntAsym", true );
1104  parm("MultipartonInteractions:alphaSvalue", 0.135 );
1105  parm("MultipartonInteractions:pT0Ref", 2.18 );
1106  parm("MultipartonInteractions:ecmRef", 1800. );
1107  parm("MultipartonInteractions:ecmPow", 0.22 );
1108  mode("MultipartonInteractions:bProfile", 4 );
1109  parm("MultipartonInteractions:a1", 0.06 );
1110  parm("BeamRemnants:primordialKTsoft", 0.5 );
1111  parm("BeamRemnants:primordialKThard", 2.0 );
1112  parm("BeamRemnants:halfScaleForKT", 1.0 );
1113  parm("BeamRemnants:halfMassForKT", 1.0 );
1114  parm("BeamRemnants:reconnectRange", 1.55 );
1115  }
1116 
1117 }
1118 
1119 //--------------------------------------------------------------------------
1120 
1121 // Convert string to lowercase for case-insensitive comparisons.
1122 // Also remove initial and trailing blanks, if any.
1123 
1124 string Settings::toLower(const string& name) {
1125 
1126  // Copy string without initial and trailing blanks.
1127  if (name.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) return "";
1128  int firstChar = name.find_first_not_of(" \n\t\v\b\r\f\a");
1129  int lastChar = name.find_last_not_of(" \n\t\v\b\r\f\a");
1130  string temp = name.substr( firstChar, lastChar + 1 - firstChar);
1131 
1132  // Convert to lowercase letter by letter.
1133  for (int i = 0; i < int(temp.length()); ++i)
1134  temp[i] = std::tolower(temp[i]);
1135  return temp;
1136 
1137 }
1138 
1139 //--------------------------------------------------------------------------
1140 
1141 // Allow several alternative inputs for true/false.
1142 
1143 bool Settings::boolString(string tag) {
1144 
1145  string tagLow = toLower(tag);
1146  return ( tagLow == "true" || tagLow == "1" || tagLow == "on"
1147  || tagLow == "yes" || tagLow == "ok" );
1148 
1149 }
1150 
1151 //--------------------------------------------------------------------------
1152 
1153 // Extract XML value string following XML attribute.
1154 
1155 string Settings::attributeValue(string line, string attribute) {
1156 
1157  if (line.find(attribute) == string::npos) return "";
1158  int iBegAttri = line.find(attribute);
1159  int iBegQuote = line.find("\"", iBegAttri + 1);
1160  int iEndQuote = line.find("\"", iBegQuote + 1);
1161  return line.substr(iBegQuote + 1, iEndQuote - iBegQuote - 1);
1162 
1163 }
1164 
1165 //--------------------------------------------------------------------------
1166 
1167 // Extract XML bool value following XML attribute.
1168 
1169 bool Settings::boolAttributeValue(string line, string attribute) {
1170 
1171  string valString = attributeValue(line, attribute);
1172  if (valString == "") return false;
1173  return boolString(valString);
1174 
1175 }
1176 
1177 //--------------------------------------------------------------------------
1178 
1179 // Extract XML int value following XML attribute.
1180 
1181 int Settings::intAttributeValue(string line, string attribute) {
1182  string valString = attributeValue(line, attribute);
1183  if (valString == "") return 0;
1184  istringstream valStream(valString);
1185  int intVal;
1186  valStream >> intVal;
1187  return intVal;
1188 
1189 }
1190 
1191 //--------------------------------------------------------------------------
1192 
1193 // Extract XML double value following XML attribute.
1194 
1195 double Settings::doubleAttributeValue(string line, string attribute) {
1196  string valString = attributeValue(line, attribute);
1197  if (valString == "") return 0.;
1198  istringstream valStream(valString);
1199  double doubleVal;
1200  valStream >> doubleVal;
1201  return doubleVal;
1202 
1203 }
1204 
1205 //==========================================================================
1206 
1207 } // end namespace Pythia8