using option '-treename HLTesdTree' for EsdCollector, adding default parameter for...
[u/mrichter/AliRoot.git] / PYTHIA8 / pythia8130 / src / Settings.cxx
CommitLineData
5ad4eb21 1// Settings.cc is a part of the PYTHIA event generator.
2// Copyright (C) 2008 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
13namespace Pythia8 {
14
15//**************************************************************************
16
17// Settings class.
18// This class contains flags, modes, parms and words used in generation.
19
20//*********
21
22// Definitions of static variables.
23map<string, Flag> Settings::flags;
24map<string, Mode> Settings::modes;
25map<string, Parm> Settings::parms;
26map<string, Word> Settings::words;
27bool Settings::isInit = false;
28
29// Static copy of Info - not optimal solution??
30Info* Settings::infoPtr = 0;
31
32//*********
33
34// Read in database from specific file.
35
36bool Settings::init(string startFile, bool append, ostream& os) {
37
38 // Don't initialize if it has already been done and not in append mode.
39 if (isInit && !append) return true;
40 int nError = 0;
41
42 // List of files to be checked. Start with input file.
43 vector<string> files;
44 files.push_back(startFile);
45
46 // If nontrivial startfile path, then use that for other files as well.
47 string pathName = "";
48 if (startFile.rfind("/") != string::npos)
49 pathName = startFile.substr(0, startFile.rfind("/") + 1);
50
51 // Loop over files. Open them for read.
52 for (int i = 0; i < int(files.size()); ++i) {
53 const char* cstring = files[i].c_str();
54 ifstream is(cstring);
55
56 // Check that instream is OK.
57 if (!is) {
58 os << "\n PYTHIA Error: settings file " << files[i]
59 << " not found" << endl;
60 return false;
61 }
62
63 // Read in one line at a time.
64 string line;
65 while ( getline(is, line) ) {
66
67 // Get first word of a line, to interpret it as tag.
68 istringstream getfirst(line);
69 string tag;
70 getfirst >> tag;
71
72 // Skip ahead if not interesting. Only look for new files in startfile.
73 if (tag != "<flag" && tag != "<flagfix" && tag != "<mode"
74 && tag != "<modeopen" && tag != "<modepick" && tag != "<modefix"
75 && tag != "<parm" && tag != "<parmfix" && tag != "<word"
76 && tag != "<wordfix" && tag != "<aidx") continue;
77
78 // Read and append continuation line(s) if line does not contain >.
79 while (line.find(">") == string::npos) {
80 string addLine;
81 getline(is, addLine);
82 line += " " + addLine;
83 }
84
85 // Remove extra blanks before an = sign.
86 while (line.find(" =") != string::npos) line.erase( line.find(" ="), 1);
87
88 // Add file also to be read.
89 if (tag == "<aidx") {
90 string name = attributeValue( line, "href");
91 if (name == "") {
92 os << " PYTHIA Error: failed to find name attribute in line "
93 << line << endl;
94 ++nError;
95 continue;
96 }
97 files.push_back(pathName + name + ".xml");
98 continue;
99 }
100
101 // Find name attribute.
102 string name = attributeValue( line, "name=");
103 if (name == "") {
104 os << " PYTHIA Error: failed to find name attribute in line "
105 << line << endl;
106 ++nError;
107 continue;
108 }
109
110 // Check that default value attribute present, and whether max and min.
111 if (line.find("default=") == string::npos) {
112 os << " PYTHIA Error: failed to find default value token in line "
113 << line << endl;
114 ++nError;
115 continue;
116 }
117 bool hasMin = (line.find("min=") != string::npos);
118 bool hasMax = (line.find("max=") != string::npos);
119
120 // Check for occurence of a bool and add to flag map.
121 if (tag == "<flag" || tag == "<flagfix") {
122 bool value = boolAttributeValue( line, "default=");
123 addFlag( name, value);
124
125 // Check for occurence of an int and add to mode map.
126 } else if (tag == "<mode" || tag == "<modeopen"
127 || tag == "<modepick" || tag == "<modefix") {
128 int value = intAttributeValue( line, "default=");
129 int minVal = intAttributeValue( line, "min=");
130 int maxVal = intAttributeValue( line, "max=");
131 addMode( name, value, hasMin, hasMax, minVal, maxVal);
132
133 // Check for occurence of a double and add to parm map.
134 } else if (tag == "<parm" || tag == "<parmfix") {
135 double value = doubleAttributeValue( line, "default=");
136 double minVal = doubleAttributeValue( line, "min=");
137 double maxVal = doubleAttributeValue( line, "max=");
138 addParm( name, value, hasMin, hasMax, minVal, maxVal);
139
140 // Check for occurence of a string and add to word map.
141 } else if (tag == "<word" || tag == "<wordfix") {
142 string value = attributeValue( line, "default=");
143 addWord( name, value);
144 }
145
146 // End of loop over lines in input file and loop over files.
147 };
148 };
149
150 // Done.
151 if (nError > 0) return false;
152 isInit = true;
153 return true;
154
155}
156
157//*********
158
159// Overwrite existing database by reading from specific file.
160
161bool Settings::reInit(string startFile) {
162
163 // Reset maps to empty.
164 flags.clear();
165 modes.clear();
166 parms.clear();
167 words.clear();
168
169 // Then let normal init do the rest.
170 isInit = false;
171 return init(startFile);
172
173}
174
175//*********
176
177// Read in updates from a character string, like a line of a file.
178// Is used by readString (and readFile) in Pythia.
179
180bool Settings::readString(string line, bool warn, ostream& os) {
181
182 // If empty line then done.
183 if (line.find_first_not_of(" ") == string::npos) return true;
184
185 // If first character is not a letter, then taken to be a comment line.
186 string lineNow = line;
187 int firstChar = lineNow.find_first_not_of(" ");
188 if (!isalpha(lineNow[firstChar])) return true;
189
190 // Replace an equal sign by a blank to make parsing simpler.
191 while (lineNow.find("=") != string::npos) {
192 int firstEqual = lineNow.find_first_of("=");
193 lineNow.replace(firstEqual, 1, " ");
194 }
195
196 // Get first word of a line.
197 istringstream splitLine(lineNow);
198 string name;
199 splitLine >> name;
200
201 // Replace two colons by one (:: -> :) to allow for such mistakes.
202 while (name.find("::") != string::npos) {
203 int firstColonColon = name.find_first_of("::");
204 name.replace(firstColonColon, 2, ":");
205 }
206
207 // Check whether this is in the database. Done if not.
208 int inDataBase = 0;
209 if (isFlag(name)) inDataBase = 1;
210 else if (isMode(name)) inDataBase = 2;
211 else if (isParm(name)) inDataBase = 3;
212 else if (isWord(name)) inDataBase = 4;
213 if (inDataBase == 0) {
214 if (warn) os << "\n PYTHIA Warning: input string not found in settings"
215 << " databases; skip:\n " << line << endl;
216 return false;
217 }
218
219 // Find value. Warn if none found.
220 string valueString;
221 splitLine >> valueString;
222 if (!splitLine) {
223 if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
224 << " not meaningful; skip:\n " << line << endl;
225 return false;
226 }
227
228 // Update flag map; allow many ways to say yes.
229 if (inDataBase == 1) {
230 bool value = boolString(valueString);
231 flag(name, value);
232
233 // Update mode map.
234 } else if (inDataBase == 2) {
235 istringstream modeData(valueString);
236 int value;
237 modeData >> value;
238 if (!modeData) {
239 if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
240 << " not meaningful; skip:\n " << line << endl;
241 return false;
242 }
243 mode(name, value);
244
245 // Update parm map.
246 } else if (inDataBase == 3) {
247 istringstream parmData(valueString);
248 double value;
249 parmData >> value;
250 if (!parmData) {
251 if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
252 << " not meaningful; skip:\n " << line << endl;
253 return false;
254 }
255 parm(name, value);
256
257 // Update word map.
258 } else {
259 word(name, valueString);
260 }
261
262 // Done.
263 return true;
264}
265
266//*********
267
268// Write updates or everything to user-defined file.
269
270bool Settings::writeFile(string toFile, bool writeAll) {
271
272 // Open file for writing.
273 const char* cstring = toFile.c_str();
274 ofstream os(cstring);
275 if (!os) {
276 infoPtr->errorMsg("Error in Settings::writeFile:"
277 " could not open file", toFile);
278 return false;
279 }
280 return writeFile( os, writeAll);
281
282}
283
284//*********
285
286// Write updates or everything to user-defined file.
287
288bool Settings::writeFile(ostream& os, bool writeAll) {
289
290 // Write simple header as comment.
291 if (writeAll) os << "! List of all current PYTHIA ";
292 else os << "! List of all modified PYTHIA ";
293 os << fixed << setprecision(3) << parm("Pythia:versionNumber")
294 << " settings.\n";
295
296 // Iterators for the flag, mode and parm tables.
297 map<string, Flag>::iterator flagEntry = flags.begin();
298 map<string, Mode>::iterator modeEntry = modes.begin();
299 map<string, Parm>::iterator parmEntry = parms.begin();
300 map<string, Word>::iterator wordEntry = words.begin();
301
302 // Loop while there is something left to do.
303 while (flagEntry != flags.end() || modeEntry != modes.end()
304 || parmEntry != parms.end() || wordEntry != words.end()) {
305
306 // Check if a flag is next in lexigraphical order; if so print it.
307 if ( flagEntry != flags.end()
308 && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first )
309 && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
310 && ( wordEntry == words.end() || flagEntry->first < wordEntry->first )
311 ) {
312 string state[2] = {"off", "on"};
313 bool valNow = flagEntry->second.valNow;
314 bool valDefault = flagEntry->second.valDefault;
315 if ( writeAll || valNow != valDefault )
316 os << flagEntry->second.name << " = " << state[valNow] << "\n";
317 ++flagEntry;
318
319 // Else check if mode is next, and if so print it.
320 } else if ( modeEntry != modes.end()
321 && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first )
322 && ( wordEntry == words.end() || modeEntry->first < wordEntry->first )
323 ) {
324 int valNow = modeEntry->second.valNow;
325 int valDefault = modeEntry->second.valDefault;
326 if ( writeAll || valNow != valDefault )
327 os << modeEntry->second.name << " = " << valNow << "\n";
328 ++modeEntry;
329
330 // Else check if parm is next, and if so print it;
331 // fixed or scientific depending on value.
332 } else if ( parmEntry != parms.end()
333 && ( wordEntry == words.end() || parmEntry->first < wordEntry->first )
334 ) {
335 double valNow = parmEntry->second.valNow;
336 double valDefault = parmEntry->second.valDefault;
337 if ( writeAll || valNow != valDefault ) {
338 os << parmEntry->second.name << " = ";
339 if ( valNow == 0. ) os << fixed << setprecision(1);
340 else if ( abs(valNow) < 0.001 ) os << scientific << setprecision(4);
341 else if ( abs(valNow) < 0.1 ) os << fixed << setprecision(7);
342 else if ( abs(valNow) < 1000. ) os << fixed << setprecision(5);
343 else if ( abs(valNow) < 1000000. ) os << fixed << setprecision(3);
344 else os << scientific << setprecision(4);
345 os << valNow << "\n";
346 }
347 ++parmEntry;
348
349 // Else print word.
350 } else {
351 string valNow = wordEntry->second.valNow;
352 string valDefault = wordEntry->second.valDefault;
353 if ( writeAll || valNow != valDefault )
354 os << wordEntry->second.name << " = " << valNow << "\n";
355 ++wordEntry;
356 }
357 } ;
358
359 // Done.
360 return true;
361}
362
363//*********
364
365// Print out table of database in lexigraphical order.
366
367void Settings::list(bool listAll, bool listString, string match,
368 ostream& os) {
369
370 // Table header; output for bool as off/on.
371 if (listAll)
372 os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (all) "
373 << " -------------------------------------------------------* \n";
374 else if (!listString)
375 os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (chang"
376 << "es only) ----------------------------------------------* \n" ;
377 else
378 os << "\n *------- PYTHIA Flag + Mode + Parm + Word Settings (with "
379 << "requested string) -------------------------------------* \n" ;
380 os << " | "
381 << " | \n"
382 << " | Name | "
383 << " Now | Default Min Max | \n"
384 << " | | "
385 << " | | \n";
386
387 // Convert input string to lowercase for match.
388 match = toLower(match);
389 if (match == "") match = " ";
390
391 // Iterators for the flag, mode and parm tables.
392 map<string, Flag>::iterator flagEntry = flags.begin();
393 map<string, Mode>::iterator modeEntry = modes.begin();
394 map<string, Parm>::iterator parmEntry = parms.begin();
395 map<string, Word>::iterator wordEntry = words.begin();
396
397 // Loop while there is something left to do.
398 while (flagEntry != flags.end() || modeEntry != modes.end()
399 || parmEntry != parms.end() || wordEntry != words.end()) {
400
401 // Check if a flag is next in lexigraphical order; if so print it.
402 if ( flagEntry != flags.end()
403 && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first )
404 && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
405 && ( wordEntry == words.end() || flagEntry->first < wordEntry->first )
406 ) {
407 string state[2] = {"off", "on"};
408 bool valNow = flagEntry->second.valNow;
409 bool valDefault = flagEntry->second.valDefault;
410 if ( listAll || (!listString && valNow != valDefault)
411 || (listString && flagEntry->first.find(match) != string::npos) )
412 os << " | " << setw(45) << left
413 << flagEntry->second.name << " | " << setw(24) << right
414 << state[valNow] << " | " << setw(12) << state[valDefault]
415 << " | \n";
416 ++flagEntry;
417
418 // Else check if mode is next, and if so print it.
419 } else if ( modeEntry != modes.end()
420 && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first )
421 && ( wordEntry == words.end() || modeEntry->first < wordEntry->first )
422 ) {
423 int valNow = modeEntry->second.valNow;
424 int valDefault = modeEntry->second.valDefault;
425 if ( listAll || (!listString && valNow != valDefault)
426 || (listString && modeEntry->first.find(match) != string::npos) ) {
427 os << " | " << setw(45) << left
428 << modeEntry->second.name << " | " << setw(24) << right
429 << valNow << " | " << setw(12) << valDefault;
430 if (modeEntry->second.hasMin)
431 os << setw(12) << modeEntry->second.valMin;
432 else os << " ";
433 if (modeEntry->second.hasMax)
434 os << setw(12) << modeEntry->second.valMax;
435 else os << " ";
436 os << " | \n";
437 }
438 ++modeEntry;
439
440 // Else check if parm is next, and if so print it;
441 // fixed or scientific depending on value.
442 } else if ( parmEntry != parms.end()
443 && ( wordEntry == words.end() || parmEntry->first < wordEntry->first )
444 ) {
445 double valNow = parmEntry->second.valNow;
446 double valDefault = parmEntry->second.valDefault;
447 if ( listAll || (!listString && valNow != valDefault )
448 || (listString && parmEntry->first.find(match) != string::npos) ) {
449 os << " | " << setw(45) << left
450 << parmEntry->second.name << right << " | ";
451 for (int i = 0; i < 4; ++i) {
452 if (i == 1) valNow = valDefault;
453 if (i == 2) valNow = parmEntry->second.valMin;
454 if (i == 3) valNow = parmEntry->second.valMax;
455 if ( (i == 2 && !parmEntry->second.hasMin)
456 || (i == 3 && !parmEntry->second.hasMax) )
457 os << " ";
458 else if ( valNow == 0. )
459 os << fixed << setprecision(1) << setw(12) << valNow;
460 else if ( abs(valNow) < 0.001 )
461 os << scientific << setprecision(4) << setw(12) << valNow;
462 else if ( abs(valNow) < 0.1 )
463 os << fixed << setprecision(7) << setw(12) << valNow;
464 else if ( abs(valNow) < 1000. )
465 os << fixed << setprecision(5) << setw(12) << valNow;
466 else if ( abs(valNow) < 1000000. )
467 os << fixed << setprecision(3) << setw(12) << valNow;
468 else
469 os << scientific << setprecision(4) << setw(12) << valNow;
470 if (i == 0) os << " | ";
471 }
472 os << " | \n";
473 }
474 ++parmEntry;
475
476 // Else print word.
477 } else {
478 string valNow = wordEntry->second.valNow;
479 string valDefault = wordEntry->second.valDefault;
480 int blankLeft = max(0, 60 - max(24, int(valNow.length()) )
481 - max(12, int(valDefault.length()) ) );
482 string blankPad( blankLeft, ' ');
483 if ( listAll || (!listString && valNow != valDefault)
484 || (listString && wordEntry->first.find(match) != string::npos) )
485 os << " | " << setw(45) << left
486 << wordEntry->second.name << " | " << setw(24) << right
487 << valNow << " | " << setw(12) << valDefault << blankPad
488 << " | \n";
489 ++wordEntry;
490 }
491 } ;
492
493 // End of loop over database contents.
494 os << " | "
495 << " | \n"
496 << " *------- End PYTHIA Flag + Mode + Parm + Word Settings ---"
497 << "------------------------------------------------------* " << endl;
498
499}
500
501//*********
502
503// Reset all values to their defaults.
504
505void Settings::resetAll() {
506
507 // Loop through the flags table, resetting all entries.
508 for (map<string, Flag>::iterator flagEntry = flags.begin();
509 flagEntry != flags.end(); ++flagEntry) {
510 string name = flagEntry->first;
511 resetFlag(name);
512 }
513
514 // Loop through the modes table, resetting all entries.
515 for (map<string, Mode>::iterator modeEntry = modes.begin();
516 modeEntry != modes.end(); ++modeEntry) {
517 string name = modeEntry->first;
518 resetMode(name);
519 }
520
521 // Loop through the parms table, resetting all entries.
522 for (map<string, Parm>::iterator parmEntry = parms.begin();
523 parmEntry != parms.end(); ++parmEntry) {
524 string name = parmEntry->first;
525 resetParm(name);
526 }
527
528 // Loop through the words table, resetting all entries.
529 for (map<string, Word>::iterator wordEntry = words.begin();
530 wordEntry != words.end(); ++wordEntry) {
531 string name = wordEntry->first;
532 resetWord(name);
533 }
534
535}
536
537//*********
538
539// Give back current value, with check that key exists.
540
541bool Settings::flag(string keyIn) {
542 if (isFlag(keyIn)) return flags[toLower(keyIn)].valNow;
543 infoPtr->errorMsg("Error in Settings::flag: unknown key", keyIn);
544 return false;
545}
546
547int Settings::mode(string keyIn) {
548 if (isMode(keyIn)) return modes[toLower(keyIn)].valNow;
549 infoPtr->errorMsg("Error in Settings::mode: unknown key", keyIn);
550 return 0;
551}
552
553double Settings::parm(string keyIn) {
554 if (isParm(keyIn)) return parms[toLower(keyIn)].valNow;
555 infoPtr->errorMsg("Error in Settings::parm: unknown key", keyIn);
556 return 0.;
557}
558
559string Settings::word(string keyIn) {
560 if (isWord(keyIn)) return words[toLower(keyIn)].valNow;
561 infoPtr->errorMsg("Error in Settings::word: unknown key", keyIn);
562 return " ";
563}
564
565//*********
566
567// Change current value, respecting limits.
568
569void Settings::flag(string keyIn, bool nowIn) {
570 if (isFlag(keyIn)) flags[toLower(keyIn)].valNow = nowIn;
571}
572
573void Settings:: mode(string keyIn, int nowIn) {
574 if (isMode(keyIn)) {
575 Mode& modeNow = modes[toLower(keyIn)];
576 if (modeNow.hasMin && nowIn < modeNow.valMin)
577 modeNow.valNow = modeNow.valMin;
578 else if (modeNow.hasMax && nowIn > modeNow.valMax)
579 modeNow.valNow = modeNow.valMax;
580 else modeNow.valNow = nowIn;
581 }
582}
583
584void Settings::parm(string keyIn, double nowIn) {
585 if (isParm(keyIn)) {
586 Parm& parmNow = parms[toLower(keyIn)];
587 if (parmNow.hasMin && nowIn < parmNow.valMin)
588 parmNow.valNow = parmNow.valMin;
589 else if (parmNow.hasMax && nowIn > parmNow.valMax)
590 parmNow.valNow = parmNow.valMax;
591 else parmNow.valNow = nowIn;
592 }
593}
594
595void Settings::word(string keyIn, string nowIn) {
596 if (isWord(keyIn)) words[toLower(keyIn)].valNow = nowIn;
597}
598
599//*********
600
601// Convert string to lowercase for case-insensitive comparisons.
602// Also remove initial and trailing blanks, if any.
603
604string Settings::toLower(const string& name) {
605
606 // Copy string without initial and trailing blanks.
607 if (name.find_first_not_of(" ") == string::npos) return "";
608 int firstChar = name.find_first_not_of(" ");
609 int lastChar = name.find_last_not_of(" ");
610 string temp = name.substr( firstChar, lastChar + 1 - firstChar);
611
612 // Convert to lowercase letter by letter.
613 for (int i = 0; i < int(temp.length()); ++i)
614 temp[i] = std::tolower(temp[i]);
615 return temp;
616
617}
618
619//*********
620
621// Allow several alternative inputs for true/false.
622
623bool Settings::boolString(string tag) {
624
625 string tagLow = toLower(tag);
626 return ( tagLow == "true" || tagLow == "1" || tagLow == "on"
627 || tagLow == "yes" || tagLow == "ok" );
628
629}
630
631//*********
632
633// Extract XML value string following XML attribute.
634
635string Settings::attributeValue(string line, string attribute) {
636
637 if (line.find(attribute) == string::npos) return "";
638 int iBegAttri = line.find(attribute);
639 int iBegQuote = line.find("\"", iBegAttri + 1);
640 int iEndQuote = line.find("\"", iBegQuote + 1);
641 return line.substr(iBegQuote + 1, iEndQuote - iBegQuote - 1);
642
643}
644
645//*********
646
647// Extract XML bool value following XML attribute.
648
649bool Settings::boolAttributeValue(string line, string attribute) {
650
651 string valString = attributeValue(line, attribute);
652 if (valString == "") return false;
653 return boolString(valString);
654
655}
656
657//*********
658
659// Extract XML int value following XML attribute.
660
661int Settings::intAttributeValue(string line, string attribute) {
662 string valString = attributeValue(line, attribute);
663 if (valString == "") return 0;
664 istringstream valStream(valString);
665 int intVal;
666 valStream >> intVal;
667 return intVal;
668
669}
670
671//*********
672
673// Extract XML double value following XML attribute.
674
675double Settings::doubleAttributeValue(string line, string attribute) {
676 string valString = attributeValue(line, attribute);
677 if (valString == "") return 0.;
678 istringstream valStream(valString);
679 double doubleVal;
680 valStream >> doubleVal;
681 return doubleVal;
682
683}
684
685//**************************************************************************
686
687} // end namespace Pythia8