- Update to pythia8140
[u/mrichter/AliRoot.git] / PYTHIA8 / pythia8140 / src / Settings.cxx
1 // Settings.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2010 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   // Done.
139   if (nError > 0) return false;
140   isInit = true;
141   return true;
142
143 }
144
145 //--------------------------------------------------------------------------
146
147 // Overwrite existing database by reading from specific file.
148
149 bool Settings::reInit(string startFile, ostream& os) {
150
151   // Reset maps to empty.
152   flags.clear();
153   modes.clear();
154   parms.clear();
155   words.clear();
156
157   // Then let normal init do the rest.
158   isInit = false;
159   return init(startFile, false, os);
160
161
162
163 //--------------------------------------------------------------------------
164
165 // Read in updates from a character string, like a line of a file. 
166 // Is used by readString (and readFile) in Pythia.
167
168 bool Settings::readString(string line, bool warn, ostream& os) {
169
170   // If empty line then done.
171   if (line.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) return true;
172
173   // If first character is not a letter, then taken to be a comment line.
174   string lineNow = line;
175   int firstChar = lineNow.find_first_not_of(" \n\t\v\b\r\f\a");
176   if (!isalpha(lineNow[firstChar])) return true; 
177
178   // Replace an equal sign by a blank to make parsing simpler.
179   while (lineNow.find("=") != string::npos) {
180     int firstEqual = lineNow.find_first_of("=");
181     lineNow.replace(firstEqual, 1, " ");   
182   }
183
184   // Get first word of a line.
185   istringstream splitLine(lineNow);
186   string name;
187   splitLine >> name;
188
189   // Replace two colons by one (:: -> :) to allow for such mistakes.
190   while (name.find("::") != string::npos) {
191     int firstColonColon = name.find_first_of("::");
192     name.replace(firstColonColon, 2, ":");   
193   }
194      
195   // Check whether this is in the database. Done if not.
196   int inDataBase = 0;
197   if      (isFlag(name)) inDataBase = 1;   
198   else if (isMode(name)) inDataBase = 2;   
199   else if (isParm(name)) inDataBase = 3; 
200   else if (isWord(name)) inDataBase = 4; 
201   if (inDataBase == 0) {
202     if (warn) os << "\n PYTHIA Warning: input string not found in settings"
203       << " databases; skip:\n   " << line << endl;
204     return false;  
205   }  
206
207   // Find value. Warn if none found.
208   string valueString;
209   splitLine >> valueString;
210   if (!splitLine) {
211     if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
212       << " not meaningful; skip:\n   " << line << endl;
213     return false;  
214   }  
215
216   // Update flag map; allow many ways to say yes.
217   if (inDataBase == 1) {
218     bool value = boolString(valueString);
219     flag(name, value);
220
221   // Update mode map.
222   } else if (inDataBase == 2) {
223     istringstream modeData(valueString);
224     int value;
225     modeData >> value;
226     if (!modeData) {
227       if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
228         << " not meaningful; skip:\n   " << line << endl;
229       return false;  
230     }  
231     mode(name, value);
232         
233   // Update parm map.
234   } else if (inDataBase == 3) {
235     istringstream parmData(valueString);
236     double value;
237     parmData >> value;
238     if (!parmData) {
239       if (warn) os << "\n PYTHIA Warning: variable recognized, but its value"
240         << " not meaningful; skip:\n   " << line << endl;
241       return false;  
242     }  
243     parm(name, value);
244         
245   // Update word map.
246   } else {
247     word(name, valueString);
248   }
249
250   // Done.
251   return true;
252 }
253
254 //--------------------------------------------------------------------------
255  
256 // Write updates or everything to user-defined file.
257
258 bool Settings::writeFile(string toFile, bool writeAll) {
259
260   // Open file for writing.
261   const char* cstring = toFile.c_str();
262   ofstream os(cstring);  
263   if (!os) {
264     infoPtr->errorMsg("Error in Settings::writeFile:"
265       " could not open file", toFile);
266     return false;
267   }
268
269   // Hand over real work to next method.
270   return writeFile( os, writeAll);
271
272 }
273
274 //--------------------------------------------------------------------------
275  
276 // Write updates or everything to user-defined stream (or file).
277
278 bool Settings::writeFile(ostream& os, bool writeAll) {
279
280   // Write simple header as comment.
281   if (writeAll) os << "! List of all current PYTHIA ";
282   else          os << "! List of all modified PYTHIA ";
283   os << fixed << setprecision(3) << parm("Pythia:versionNumber")
284      << " settings.\n";
285
286   // Iterators for the flag, mode and parm tables.
287   map<string, Flag>::iterator flagEntry = flags.begin();
288   map<string, Mode>::iterator modeEntry = modes.begin();
289   map<string, Parm>::iterator parmEntry = parms.begin();
290   map<string, Word>::iterator wordEntry = words.begin();
291
292   // Loop while there is something left to do.
293   while (flagEntry != flags.end() || modeEntry != modes.end() 
294     || parmEntry != parms.end() || wordEntry != words.end()) {
295
296     // Check if a flag is next in lexigraphical order; if so print it.
297     if ( flagEntry != flags.end() 
298       && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first ) 
299       && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
300       && ( wordEntry == words.end() || flagEntry->first < wordEntry->first ) 
301       ) {
302       string state[2] = {"off", "on"};
303       bool valNow = flagEntry->second.valNow;
304       bool valDefault = flagEntry->second.valDefault;
305       if ( writeAll || valNow != valDefault )
306         os << flagEntry->second.name << " = " << state[valNow] << "\n";
307       ++flagEntry;
308      
309     // Else check if mode is next, and if so print it.
310     } else if ( modeEntry != modes.end() 
311       && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first ) 
312       && ( wordEntry == words.end() || modeEntry->first < wordEntry->first ) 
313       ) {
314       int valNow = modeEntry->second.valNow;
315       int valDefault = modeEntry->second.valDefault;
316       if ( writeAll || valNow != valDefault ) 
317         os << modeEntry->second.name << " = " << valNow << "\n"; 
318       ++modeEntry;
319       
320     // Else check if parm is next, and if so print it; 
321     // fixed or scientific depending on value.
322     } else if ( parmEntry != parms.end()
323       && ( wordEntry == words.end() || parmEntry->first < wordEntry->first ) 
324       ) {
325       double valNow = parmEntry->second.valNow;
326       double valDefault = parmEntry->second.valDefault;      
327       if ( writeAll || valNow != valDefault ) {
328         os  << parmEntry->second.name << " = ";
329         if ( valNow == 0. ) os << fixed << setprecision(1); 
330         else if ( abs(valNow) < 0.001 ) os << scientific << setprecision(4); 
331         else if ( abs(valNow) < 0.1 ) os << fixed << setprecision(7); 
332         else if ( abs(valNow) < 1000. ) os << fixed << setprecision(5); 
333         else if ( abs(valNow) < 1000000. ) os << fixed << setprecision(3); 
334         else os << scientific << setprecision(4); 
335         os << valNow << "\n";
336       }
337       ++parmEntry;
338
339     // Else print word. 
340     } else {
341       string valNow = wordEntry->second.valNow;
342       string valDefault = wordEntry->second.valDefault; 
343       if ( writeAll || valNow != valDefault ) 
344         os << wordEntry->second.name << " = " << valNow << "\n";
345       ++wordEntry;
346     }
347   } ;
348
349   // Done.
350   return true;
351 }
352
353 //--------------------------------------------------------------------------
354  
355 // Print out table of database in lexigraphical order.
356
357 void Settings::list(bool doListAll,  bool doListString, string match,
358   ostream& os) {
359
360   // Table header; output for bool as off/on.
361   if (doListAll) 
362     os << "\n *-------  PYTHIA Flag + Mode + Parm + Word Settings (all) "
363        << " -------------------------------------------------------* \n";
364   else if (!doListString) 
365     os << "\n *-------  PYTHIA Flag + Mode + Parm + Word Settings (chang" 
366        << "es only)  ----------------------------------------------* \n" ;
367   else
368     os << "\n *-------  PYTHIA Flag + Mode + Parm + Word Settings (with " 
369        << "requested string)  -------------------------------------* \n" ;
370   os << " |                                                           "
371      << "                                                      | \n"
372      << " | Name                                          |           "
373      << "           Now |      Default         Min         Max | \n"
374      << " |                                               |           "
375      << "               |                                      | \n";
376  
377   // Convert input string to lowercase for match.
378   match = toLower(match);
379   if (match == "") match = "             ";
380
381   // Iterators for the flag, mode and parm tables.
382   map<string, Flag>::iterator flagEntry = flags.begin();
383   map<string, Mode>::iterator modeEntry = modes.begin();
384   map<string, Parm>::iterator parmEntry = parms.begin();
385   map<string, Word>::iterator wordEntry = words.begin();
386
387   // Loop while there is something left to do.
388   while (flagEntry != flags.end() || modeEntry != modes.end() 
389     || parmEntry != parms.end() || wordEntry != words.end()) {
390
391     // Check if a flag is next in lexigraphical order; if so print it.
392     if ( flagEntry != flags.end() 
393       && ( modeEntry == modes.end() || flagEntry->first < modeEntry->first ) 
394       && ( parmEntry == parms.end() || flagEntry->first < parmEntry->first )
395       && ( wordEntry == words.end() || flagEntry->first < wordEntry->first ) 
396       ) {
397       string state[2] = {"off", "on"};
398       bool valNow = flagEntry->second.valNow;
399       bool valDefault = flagEntry->second.valDefault;
400       if ( doListAll || (!doListString && valNow != valDefault)
401         || (doListString && flagEntry->first.find(match) != string::npos) )
402         os << " | " << setw(45) << left 
403            << flagEntry->second.name << " | " << setw(24) << right
404            << state[valNow] << " | " << setw(12) << state[valDefault] 
405            << "                         | \n";
406       ++flagEntry;
407      
408     // Else check if mode is next, and if so print it.
409     } else if ( modeEntry != modes.end() 
410       && ( parmEntry == parms.end() || modeEntry->first < parmEntry->first ) 
411       && ( wordEntry == words.end() || modeEntry->first < wordEntry->first ) 
412       ) {
413       int valNow = modeEntry->second.valNow;
414       int valDefault = modeEntry->second.valDefault;
415       if ( doListAll || (!doListString && valNow != valDefault)
416         || (doListString && modeEntry->first.find(match) != string::npos) ) {
417         os << " | " << setw(45) << left 
418            << modeEntry->second.name << " | " << setw(24) << right 
419            << valNow << " | " << setw(12) << valDefault; 
420         if (modeEntry->second.hasMin) 
421           os << setw(12) << modeEntry->second.valMin; 
422         else os << "            ";
423         if (modeEntry->second.hasMax) 
424           os << setw(12) << modeEntry->second.valMax; 
425         else os << "            ";
426         os << " | \n";
427       }
428       ++modeEntry;
429       
430     // Else check if parm is next, and if so print it; 
431     // fixed or scientific depending on value.
432     } else if ( parmEntry != parms.end()
433       && ( wordEntry == words.end() || parmEntry->first < wordEntry->first ) 
434       ) {
435       double valNow = parmEntry->second.valNow;
436       double valDefault = parmEntry->second.valDefault;      
437       if ( doListAll || (!doListString && valNow != valDefault ) 
438         || (doListString && parmEntry->first.find(match) != string::npos) ) {
439         os << " | " << setw(45) << left 
440            << parmEntry->second.name << right << " |             ";
441         for (int i = 0; i < 4; ++i) { 
442           if (i == 1) valNow = valDefault;  
443           if (i == 2) valNow = parmEntry->second.valMin;  
444           if (i == 3) valNow = parmEntry->second.valMax;  
445           if ( (i == 2 && !parmEntry->second.hasMin)
446             || (i == 3 && !parmEntry->second.hasMax) )
447             os << "            ";
448           else if ( valNow == 0. ) 
449             os << fixed << setprecision(1) << setw(12) << valNow; 
450           else if ( abs(valNow) < 0.001 ) 
451             os << scientific << setprecision(4) << setw(12) << valNow;  
452           else if ( abs(valNow) < 0.1 )
453             os << fixed << setprecision(7) << setw(12) << valNow; 
454           else if ( abs(valNow) < 1000. )
455             os << fixed << setprecision(5) << setw(12) << valNow; 
456           else if ( abs(valNow) < 1000000. )
457             os << fixed << setprecision(3) << setw(12) << valNow; 
458           else 
459             os << scientific << setprecision(4) << setw(12) << valNow; 
460           if (i == 0) os << " | ";
461         }  
462         os << " | \n";
463       }
464       ++parmEntry;
465
466     // Else print word. 
467     } else {
468       string valNow = wordEntry->second.valNow;
469       string valDefault = wordEntry->second.valDefault; 
470       int blankLeft = max(0, 60 - max(24, int(valNow.length()) ) 
471         - max(12, int(valDefault.length()) ) );  
472       string blankPad( blankLeft, ' '); 
473       if ( doListAll || (!doListString && valNow != valDefault)
474         || (doListString && wordEntry->first.find(match) != string::npos) )
475         os << " | " << setw(45) << left 
476            << wordEntry->second.name << " | " << setw(24) << right
477            << valNow << " | " << setw(12) << valDefault << blankPad 
478            << " | \n";
479       ++wordEntry;
480     }
481   } ;
482
483   // End of loop over database contents.
484   os << " |                                                           "
485      << "                                                      | \n"
486      << " *-------  End PYTHIA Flag + Mode + Parm + Word Settings  ---"
487      << "------------------------------------------------------* " << endl;
488
489 }
490
491 //--------------------------------------------------------------------------
492  
493 // Reset all values to their defaults.
494
495 void Settings::resetAll() {
496
497   // Loop through the flags table, resetting all entries.
498   for (map<string, Flag>::iterator flagEntry = flags.begin();
499     flagEntry != flags.end(); ++flagEntry) {
500     string name = flagEntry->first;
501     resetFlag(name);
502   }
503
504   // Loop through the modes table, resetting all entries.
505   for (map<string, Mode>::iterator modeEntry = modes.begin();
506     modeEntry != modes.end(); ++modeEntry) {
507     string name = modeEntry->first;
508     resetMode(name);
509   }
510
511   // Loop through the parms table, resetting all entries.
512   for (map<string, Parm>::iterator parmEntry = parms.begin(); 
513     parmEntry != parms.end(); ++parmEntry) {
514     string name = parmEntry->first;
515     resetParm(name);
516   }
517
518   // Loop through the words table, resetting all entries.
519   for (map<string, Word>::iterator wordEntry = words.begin();
520     wordEntry != words.end(); ++wordEntry) {
521     string name = wordEntry->first;
522     resetWord(name);
523   }
524
525 }
526
527 //--------------------------------------------------------------------------
528  
529 // Give back current value, with check that key exists.
530
531 bool Settings::flag(string keyIn) {
532   if (isFlag(keyIn)) return flags[toLower(keyIn)].valNow; 
533   infoPtr->errorMsg("Error in Settings::flag: unknown key", keyIn);
534   return false; 
535 }
536
537 int Settings::mode(string keyIn) {
538   if (isMode(keyIn)) return modes[toLower(keyIn)].valNow; 
539   infoPtr->errorMsg("Error in Settings::mode: unknown key", keyIn);
540   return 0; 
541 }
542
543 double Settings::parm(string keyIn) {
544   if (isParm(keyIn)) return parms[toLower(keyIn)].valNow; 
545   infoPtr->errorMsg("Error in Settings::parm: unknown key", keyIn);
546   return 0.; 
547 }
548
549 string Settings::word(string keyIn) {
550   if (isWord(keyIn)) return words[toLower(keyIn)].valNow; 
551   infoPtr->errorMsg("Error in Settings::word: unknown key", keyIn);
552   return " "; 
553 }
554
555 //--------------------------------------------------------------------------
556  
557 // Change current value, respecting limits.
558
559 void Settings::flag(string keyIn, bool nowIn) { 
560     if (isFlag(keyIn)) flags[toLower(keyIn)].valNow = nowIn; 
561 }
562
563 void Settings:: mode(string keyIn, int nowIn) { 
564   if (isMode(keyIn)) { 
565     Mode& modeNow = modes[toLower(keyIn)];
566     if (modeNow.hasMin && nowIn < modeNow.valMin) 
567       modeNow.valNow = modeNow.valMin; 
568     else if (modeNow.hasMax && nowIn > modeNow.valMax) 
569       modeNow.valNow = modeNow.valMax;
570     else modeNow.valNow = nowIn; 
571   } 
572
573
574 void Settings::parm(string keyIn, double nowIn) { 
575   if (isParm(keyIn)) {
576     Parm& parmNow = parms[toLower(keyIn)];
577     if (parmNow.hasMin && nowIn < parmNow.valMin) 
578       parmNow.valNow = parmNow.valMin; 
579     else if (parmNow.hasMax && nowIn > parmNow.valMax) 
580       parmNow.valNow = parmNow.valMax;
581     else parmNow.valNow = nowIn; 
582   } 
583 }  
584
585 void Settings::word(string keyIn, string nowIn) { 
586     if (isWord(keyIn)) words[toLower(keyIn)].valNow = nowIn; 
587 }
588
589 //--------------------------------------------------------------------------
590
591 // Convert string to lowercase for case-insensitive comparisons.
592 // Also remove initial and trailing blanks, if any.
593
594 string Settings::toLower(const string& name) { 
595
596   // Copy string without initial and trailing blanks.
597   if (name.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) return "";
598   int firstChar = name.find_first_not_of(" \n\t\v\b\r\f\a");
599   int lastChar  = name.find_last_not_of(" \n\t\v\b\r\f\a");
600   string temp   = name.substr( firstChar, lastChar + 1 - firstChar);
601
602   // Convert to lowercase letter by letter.
603   for (int i = 0; i < int(temp.length()); ++i) 
604     temp[i] = std::tolower(temp[i]); 
605   return temp; 
606
607 }
608
609 //--------------------------------------------------------------------------
610
611 // Allow several alternative inputs for true/false.
612
613 bool Settings::boolString(string tag) {
614
615   string tagLow = toLower(tag);
616   return ( tagLow == "true" || tagLow == "1" || tagLow == "on" 
617   || tagLow == "yes" || tagLow == "ok" ); 
618
619 }  
620
621 //--------------------------------------------------------------------------
622
623 // Extract XML value string following XML attribute.
624
625 string Settings::attributeValue(string line, string attribute) {
626
627   if (line.find(attribute) == string::npos) return "";
628   int iBegAttri = line.find(attribute); 
629   int iBegQuote = line.find("\"", iBegAttri + 1);
630   int iEndQuote = line.find("\"", iBegQuote + 1);
631   return line.substr(iBegQuote + 1, iEndQuote - iBegQuote - 1);
632
633 }
634
635 //--------------------------------------------------------------------------
636
637 // Extract XML bool value following XML attribute.
638
639 bool Settings::boolAttributeValue(string line, string attribute) {
640
641   string valString = attributeValue(line, attribute);
642   if (valString == "") return false;
643   return boolString(valString);   
644
645 }
646
647 //--------------------------------------------------------------------------
648
649 // Extract XML int value following XML attribute.
650
651 int Settings::intAttributeValue(string line, string attribute) {
652   string valString = attributeValue(line, attribute);
653   if (valString == "") return 0; 
654   istringstream valStream(valString);
655   int intVal; 
656   valStream >> intVal; 
657   return intVal;     
658
659 }
660
661 //--------------------------------------------------------------------------
662
663 // Extract XML double value following XML attribute.
664
665 double Settings::doubleAttributeValue(string line, string attribute) {
666   string valString = attributeValue(line, attribute);
667   if (valString == "") return 0.; 
668   istringstream valStream(valString);
669   double doubleVal; 
670   valStream >> doubleVal; 
671   return doubleVal;     
672
673 }
674
675 //==========================================================================
676
677 } // end namespace Pythia8