AlgConfigPool.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2019, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5  or see $GENIE/LICENSE
6 
7  Author: Costas Andreopoulos <costas.andreopoulos \at stfc.ac.uk>
8  University of Liverpool & STFC Rutherford Appleton Lab
9 
10  For the class documentation see the corresponding header file.
11 
12  Important revisions after version 2.0.0 :
13  @ Oct 11, 2007 - CA
14  The GlobalParameterList method no longer returns a 'const Registry *'
15  but a 'Registry *'.
16  @ Jun 20, 2008 - CA
17  Fix a memory leak in code reading the XML files / added xmlFree(doc)
18  @ Dec 06, 2008 - CA
19  Tweak dtor so as not to clutter the output if GENIE exits in err so as to
20  spot the fatal mesg immediately.
21  @ Aug 25, 2009 - RH
22  Use the GetXMLFilePath() to search the potential XML config file locations
23  and return the first actual file that can be found. Adapt code to use the
24  utils::xml namespace.
25 */
26 //____________________________________________________________________________
27 
28 #include <iomanip>
29 #include <iostream>
30 #include <sstream>
31 #include <cstdlib>
32 
33 #include "libxml/xmlmemory.h"
34 #include "libxml/parser.h"
35 
36 #include <TSystem.h>
37 #include <TFile.h>
38 #include <TTree.h>
39 #include <TH1F.h>
40 #include <TH2F.h>
41 
46 
48 
49 using std::setw;
50 using std::setfill;
51 using std::endl;
52 using std::ostringstream;
53 
54 using namespace genie;
55 
56 //____________________________________________________________________________
57 namespace genie {
58  ostream & operator<<(ostream & stream, const AlgConfigPool & config_pool)
59  {
60  config_pool.Print(stream);
61  return stream;
62  }
63 }
64 //____________________________________________________________________________
66 //____________________________________________________________________________
68 {
69  if( ! this->LoadAlgConfig() )
70  LOG("AlgConfigPool", pERROR) << "Could not load XML config file";
71  fInstance = 0;
72 }
73 //____________________________________________________________________________
75 {
76 // Clean up and report the most important physics params used in this instance.
77 // Don't clutter output if exiting in err.
78 
79  if(!gAbortingInErr) {
80 /*
81  cout << "AlgConfigPool singleton dtor: "
82  << "Deleting all owned algorithm configurations" << endl;
83 */
84  }
85  map<string, Registry *>::iterator citer;
86  for(citer = fRegistryPool.begin(); citer != fRegistryPool.end(); ++citer) {
87  string key = citer->first;
88  Registry * config = citer->second;
89  if(config) {
90  delete config;
91  config = 0;
92  }
93  }
94  fRegistryPool.clear();
95  fConfigFiles.clear();
96  fConfigKeyList.clear();
97  fInstance = 0;
98 }
99 //____________________________________________________________________________
101 {
102  if(fInstance == 0) {
103  static AlgConfigPool::Cleaner cleaner;
105  fInstance = new AlgConfigPool;
106  }
107  return fInstance;
108 }
109 //____________________________________________________________________________
111 {
112 // Loads all algorithm XML configurations and creates a map with all loaded
113 // configuration registries
114 
115  SLOG("AlgConfigPool", pINFO)
116  << "AlgConfigPool late initialization: Loading all XML config. files";
117 
118  //-- read the global parameter lists
119  if(!this->LoadGlobalParamLists()) return false;
120 
121  //-- read the MASTER_CONFIG XML file
122  if(!this->LoadMasterConfig()) return false;
123 
124  //-- read Tune Generator List for the tune, if available
125  if( ! LoadTuneGeneratorList() ) {
126 
127  SLOG( "AlgConfigPool", pWARN ) << "Tune generator List not available" ;
128  }
129 
130  //-- loop over all XML config files and read all named configuration
131  // sets for each algorithm
132  map<string, string>::const_iterator conf_file_iter;
133 
134  for(conf_file_iter = fConfigFiles.begin();
135  conf_file_iter != fConfigFiles.end(); ++conf_file_iter) {
136 
137  string alg_name = conf_file_iter->first;
138  string file_name = conf_file_iter->second;
139 
140  SLOG("AlgConfigPool", pINFO)
141  << setfill('.') << setw(40) << alg_name << " -> " << file_name;
142 
143  string full_path = utils::xml::GetXMLFilePath(file_name);
144  SLOG("AlgConfigPool", pNOTICE)
145  << "*** GENIE XML config file " << full_path;
146  bool ok = this->LoadSingleAlgConfig(alg_name, full_path);
147  if(!ok) {
148  SLOG("AlgConfigPool", pERROR)
149  << "Error in loading config sets for algorithm = " << alg_name;
150  }
151  }
152  return true;
153 };
154 //____________________________________________________________________________
156 {
157 // Loads the master config XML file: the file that specifies which XML config
158 // file to load for each algorithm
159 
160  //-- get the master config XML file using GXMLPATH + default locations
161  fMasterConfig = utils::xml::GetXMLFilePath("master_config.xml");
162 
163  bool is_accessible = ! (gSystem->AccessPathName( fMasterConfig.c_str() ));
164  if (!is_accessible) {
165  SLOG("AlgConfigPool", pERROR)
166  << "The XML doc doesn't exist! (filename : " << fMasterConfig << ")";
167  return false;
168  }
169 
170  xmlDocPtr xml_doc = xmlParseFile(fMasterConfig.c_str());
171  if(xml_doc==NULL) {
172  SLOG("AlgConfigPool", pERROR)
173  << "The XML doc can't be parsed! (filename : " << fMasterConfig << ")";
174  return false;
175  }
176 
177  xmlNodePtr xml_root = xmlDocGetRootElement(xml_doc);
178  if(xml_root==NULL) {
179  SLOG("AlgConfigPool", pERROR)
180  << "The XML doc is empty! (filename : " << fMasterConfig << ")";
181  xmlFreeDoc(xml_doc);
182  return false;
183  }
184 
185  if( xmlStrcmp(xml_root->name, (const xmlChar *) "genie_config") ) {
186  SLOG("AlgConfigPool", pERROR)
187  << "The XML doc has invalid root element! "
188  << "(filename : " << fMasterConfig << ")";
189  xmlFreeDoc(xml_doc);
190  return false;
191  }
192 
193  // loop over all xml tree nodes (<alg_config>) that are children of the
194  // root node and read the config file name for each registered algorithm
195  xmlNodePtr xml_ac = xml_root->xmlChildrenNode;
196  while (xml_ac != NULL) {
197  if( (!xmlStrcmp(xml_ac->name, (const xmlChar *) "config")) ) {
198 
199  string alg_name = utils::str::TrimSpaces(
200  utils::xml::GetAttribute(xml_ac, "alg"));
202  xmlNodeListGetString(xml_doc, xml_ac->xmlChildrenNode, 1));
203 
204  pair<string, string> alg_conf(alg_name, config_file);
205  fConfigFiles.insert(alg_conf);
206  }
207  xml_ac = xml_ac->next;
208  }
209  xmlFreeNode(xml_ac);
210  xmlFreeDoc(xml_doc);
211  return true;
212 }
213 //____________________________________________________________________________
215 {
216 // Load the global parameter list (a list of physics constants at a given MC
217 // job, that is allowed to be modified to fine tune the generator output)
218 //
219  SLOG("AlgConfigPool", pINFO) << "Loading global parameter lists";
220 
221  // -- get the user config XML file using GXMLPATH + default locations
222  string glob_params = utils::xml::GetXMLFilePath("ModelConfiguration.xml");
223 
224  // fixed key prefix
225  string key_prefix = "GlobalParameterList";
226 
227  // load and report status
228  return this->LoadRegistries(key_prefix, glob_params, "global_param_list");
229 }
230 //____________________________________________________________________________
231 bool AlgConfigPool::LoadCommonLists( const string & file_id )
232 {
233 // Load the common parameter list
234 //
235  SLOG("AlgConfigPool", pINFO) << "Loading Common " << file_id << " lists";
236 
237  // -- get the user config XML file using GXMLPATH + default locations
238  std::string xml_name = "Common" + file_id + ".xml" ;
239  string full_path = utils::xml::GetXMLFilePath( xml_name );
240 
241  // fixed key prefix
242  string key_prefix = "Common" + file_id + "List";
243 
244  // load and report status
245  if ( ! this->LoadRegistries(key_prefix, full_path, "common_"+file_id+"_list") ) {
246 
247  SLOG("AlgConfigPool", pERROR) << "Failed to load Common " << file_id ;
248  return false ;
249  }
250 
251  return true ;
252 }
253 //____________________________________________________________________________
255 {
256 // Load the common parameter list
257 //
258  SLOG("AlgConfigPool", pINFO) << "Loading Tune Gerator List";
259 
260  // -- get the user config XML file using GXMLPATH + default locations
261  string generator_list_file = utils::xml::GetXMLFilePath("TuneGeneratorList.xml");
262 
263  // fixed key prefix
264  string key_prefix = "TuneGeneratorList";
265 
266  // load and report status
267  return this->LoadRegistries(key_prefix, generator_list_file, "tune_generator_list");
268 }
269 //____________________________________________________________________________
270 
271 bool AlgConfigPool::LoadSingleAlgConfig(string alg_name, string file_name)
272 {
273 // Loads all configuration sets for the input algorithm that can be found in
274 // the input XML file
275 
276  // use the algorithm name as the key prefix
277  string key_prefix = alg_name;
278 
279  // load and report status
280  return this->LoadRegistries(key_prefix, file_name, "alg_conf");
281 }
282 //____________________________________________________________________________
284  string key_prefix, string file_name, string root)
285 {
286 // Loads all the configuration registries from the input XML file
287 
288  SLOG("AlgConfigPool", pDEBUG) << "[-] Loading registries:";
289 
290  bool is_accessible = ! (gSystem->AccessPathName(file_name.c_str()));
291  if (!is_accessible) {
292  SLOG("AlgConfigPool", pERROR)
293  << "The XML doc doesn't exist! (filename : " << file_name << ")";
294  return false;
295  }
296 
297  xmlDocPtr xml_doc = xmlParseFile( file_name.c_str() );
298  if(xml_doc==NULL) {
299  SLOG("AlgConfigPool", pERROR)
300  << "The XML document can't be parsed! (filename : " << file_name << ")";
301  return false;
302  }
303 
304  xmlNodePtr xml_cur = xmlDocGetRootElement( xml_doc );
305  if(xml_cur==NULL) {
306  SLOG("AlgConfigPool", pERROR)
307  << "The XML document is empty! (filename : " << file_name << ")";
308  xmlFreeDoc(xml_doc);
309  return false;
310  }
311  if( xmlStrcmp(xml_cur->name, (const xmlChar *) root.c_str()) ) {
312  SLOG("AlgConfigPool", pERROR)
313  << "The XML document has invalid root element! "
314  << "(filename : " << file_name << ")";
315  xmlFreeNode(xml_cur);
316  xmlFreeDoc(xml_doc);
317  return false;
318  }
319 
320  // loop over all xml tree nodes that are children of the root node
321  xml_cur = xml_cur->xmlChildrenNode;
322  while (xml_cur != NULL) {
323  // enter everytime you find an 'param_set' tag
324  if( (!xmlStrcmp(xml_cur->name, (const xmlChar *) "param_set")) ) {
325 
326  string param_set = utils::str::TrimSpaces(
327  utils::xml::GetAttribute(xml_cur, "name"));
328 
329  // build the registry key
330  ostringstream key;
331  key << key_prefix << "/" << param_set;
332 
333  // store the key in the key list
334  fConfigKeyList.push_back(key.str());
335 
336  // create a new Registry and fill it with the configuration params
337  Registry * config = new Registry(param_set,false);
338 
339  xmlNodePtr xml_param = xml_cur->xmlChildrenNode;
340  while (xml_param != NULL) {
341  if( (!xmlStrcmp(xml_param->name, (const xmlChar *) "param")) ) {
342 
343  string param_type =
345  utils::xml::GetAttribute(xml_param, "type"));
346  string param_name =
348  utils::xml::GetAttribute(xml_param, "name"));
349  string param_value =
351  xmlNodeListGetString(
352  xml_doc, xml_param->xmlChildrenNode, 1));
353  this->AddConfigParameter(
354  config, param_type, param_name, param_value);
355  }
356  xml_param = xml_param->next;
357  }
358  //xmlFree(xml_param);
359  xmlFreeNode(xml_param);
360  config->SetName(param_set);
361  config->Lock();
362 
363  pair<string, Registry *> single_reg(key.str(), config);
364  fRegistryPool.insert(single_reg);
365 
366  SLOG("AlgConfigPool", pDEBUG) << " |---o " << key.str();
367  }
368  xml_cur = xml_cur->next;
369  }
370  //xmlFree(xml_cur);
371  xmlFreeNode(xml_cur);
372  //xmlFree(xml_doc);
373  xmlFreeDoc(xml_doc);
374 
375  return true;
376 }
377 //____________________________________________________________________________
379  Registry * r, string ptype, string pname, string pvalue)
380 {
381 // Adds a configuration parameter with type = ptype, key = pname and value =
382 // pvalue at the input configuration registry r
383 
384  SLOG("AlgConfigPool", pDEBUG)
385  << "Adding Parameter [" << ptype << "]: Key = "
386  << pname << " -> Value = " << pvalue;
387 
388  bool isRootObjParam = (strcmp(ptype.c_str(), "h1f") == 0) ||
389  (strcmp(ptype.c_str(), "Th2f") == 0) ||
390  (strcmp(ptype.c_str(), "tree") == 0);
391  bool isBasicParam = (strcmp(ptype.c_str(), "int") == 0) ||
392  (strcmp(ptype.c_str(), "bool") == 0) ||
393  (strcmp(ptype.c_str(), "double") == 0) ||
394  (strcmp(ptype.c_str(), "string") == 0) ||
395  (strcmp(ptype.c_str(), "alg") == 0);
396 
397  if (isBasicParam) this->AddBasicParameter (r, ptype, pname, pvalue);
398  else if(isRootObjParam) this->AddRootObjParameter(r, ptype, pname, pvalue);
399  else {
400  SLOG("AlgConfigPool", pERROR)
401  << "Parameter [" << ptype << "]: Key = " << pname
402  << " -> Value = " << pvalue << " could not be added";
403  }
404 }
405 //____________________________________________________________________________
407  Registry * r, string ptype, string pname, string pvalue)
408 {
409  RgKey key = pname;
410 
411  if (ptype=="double") {
412  RgDbl item = (double) atof(pvalue.c_str());
413  r->Set(key, item);
414  }
415  else if (ptype=="int") {
416  RgInt item = (int) atoi(pvalue.c_str());
417  r->Set(key, item);
418  }
419  else if (ptype=="bool") {
420  if (pvalue=="true" ) r->Set(key, true );
421  else if (pvalue=="TRUE" ) r->Set(key, true );
422  else if (pvalue=="1" ) r->Set(key, true );
423  else if (pvalue=="false") r->Set(key, false);
424  else if (pvalue=="FALSE") r->Set(key, false);
425  else if (pvalue=="0" ) r->Set(key, false);
426  else {
427  LOG("AlgConfigPool", pERROR)
428  << "Could not set bool param: " << key;
429  }
430  }
431  else if (ptype=="string") {
432  RgStr item = pvalue;
433  r->Set(key, item);
434  }
435  else if (ptype=="alg") {
436  string name, config;
437  vector<string> algv = utils::str::Split(pvalue, "/");
438  if (algv.size()==2) {
439  name = algv[0];
440  config = algv[1];
441  }
442  else if (algv.size()==1) {
443  name = algv[0];
444  config = "Default";
445  } else {
446  LOG("AlgConfigPool", pFATAL)
447  << "Unrecognized algorithm id: " << pvalue;
448  exit(1);
449  }
450  RgAlg item(name,config);
451  r->Set(key, item);
452  }
453  else {
454  LOG("AlgConfigPool", pERROR)
455  << "Config. parameter: " << key
456  << "has unrecognized type: " << ptype;
457  }
458 }
459 //____________________________________________________________________________
461  Registry * r, string ptype, string pname, string pvalue)
462 {
463  // the ROOT object is given in the XML config file as
464  // <param> object_name@root_file_name </param>
465  vector<string> rootobjv = utils::str::Split(pvalue, "@");
466 
467  if(rootobjv.size() != 2) {
468  SLOG("AlgConfigPool", pWARN)
469  << "ROOT objects are added in XML config files as: "
470  << "object-name@file-name. Wrong syntax in: [" << pvalue << "]";
471  SLOG("AlgConfigPool", pERROR)
472  << "Parameter [" << ptype << "]: Key = " << pname
473  << " -> Value = " << pvalue << " could not be added";
474  }
475 
476  string rootobj = rootobjv[0];
477  string rootfile = rootobjv[1];
478 
479  TFile f(rootfile.c_str(), "read");
480 
481  if (ptype=="h1f") {
482  TH1F * h = (TH1F*) f.Get(rootobj.c_str());
483  if(h) {
484  TH1F * ch = new TH1F(*h); // clone
485  ch->SetDirectory(0);
486  r->Set(pname,ch);
487  } else {
488  SLOG("AlgConfigPool", pERROR)
489  << "No TH1F named = " << rootobj << " in ROOT file = " << rootfile;
490  }
491  } else if (ptype=="h2f") {
492  TH2F * h2 = (TH2F*) f.Get(rootobj.c_str());
493  if(h2) {
494  TH2F * ch2 = new TH2F(*h2); // clone
495  ch2->SetDirectory(0);
496  r->Set(pname,ch2);
497  } else {
498  SLOG("AlgConfigPool", pERROR)
499  << "No TH2F named = " << rootobj << " in ROOT file = " << rootfile;
500  }
501  } else if (ptype=="tree") {
502  TTree * t = (TTree*) f.Get(rootobj.c_str());
503  if(t) {
504  //TTree * ct = new TTree(*t); // clone
505  TTree * ct = t->CopyTree("1");
506  r->Set(pname,ct);
507  } else {
508  SLOG("AlgConfigPool", pERROR)
509  << "No TTree named = " << rootobj << " in ROOT file = " << rootfile;
510  }
511  }
512  else {}
513 }
514 //____________________________________________________________________________
516 {
517  string key = algorithm->Id().Key();
518  return this->FindRegistry(key);
519 }
520 //____________________________________________________________________________
522 {
523  string key = algid.Key();
524  return this->FindRegistry(key);
525 }
526 //____________________________________________________________________________
527 Registry* AlgConfigPool::FindRegistry(string alg_name, string param_set) const
528 {
529  AlgId id(alg_name,param_set);
530  string key = id.Key();
531  return this->FindRegistry(key);
532 }
533 //____________________________________________________________________________
535 {
536  LOG("AlgConfigPool", pDEBUG) << "Searching for registry with key " << key;
537 
538  if( fRegistryPool.count(key) == 1 ) {
539  map<string, Registry *>::const_iterator config_entry =
540  fRegistryPool.find(key);
541  return config_entry->second;
542  } else {
543  LOG("AlgConfigPool", pDEBUG) << "No config registry for key " << key;
544  return 0;
545  }
546  return 0;
547 }
548 //____________________________________________________________________________
550 {
551  string glob_param_set = (gSystem->Getenv("GUSERPHYSOPT")) ?
552  string(gSystem->Getenv("GUSERPHYSOPT")) : "Default";
553  ostringstream key;
554  key << "GlobalParameterList/" << glob_param_set;
555 
556  return this->FindRegistry(key.str());
557 }
558 //____________________________________________________________________________
559 Registry * AlgConfigPool::CommonList( const string & file_id, const string & set_name ) const
560 {
561 
562  ostringstream key;
563  key << "Common" << file_id << "List/" << set_name;
564 
565  if ( ! this->FindRegistry(key.str()) ) {
566  const_cast<AlgConfigPool*>( this ) -> LoadCommonLists( file_id ) ;
567  }
568 
569  return this->FindRegistry(key.str()) ;
570 }
571 //____________________________________________________________________________
573 {
574 
575  ostringstream key;
576  key << "TuneGeneratorList/Default";
577 
578  return this->FindRegistry(key.str());
579 }
580 //____________________________________________________________________________
581 const vector<string> & AlgConfigPool::ConfigKeyList(void) const
582 {
583  return fConfigKeyList;
584 }
585 //____________________________________________________________________________
586 void AlgConfigPool::Print(ostream & stream) const
587 {
588  string frame(100,'~');
589 
590  typedef map<string, Registry *>::const_iterator sregIter;
591  typedef map<string, Registry *>::size_type sregSize;
592 
593  sregSize size = fRegistryPool.size();
594 
595  stream << frame
596  << endl << "Algorithm Configuration Pool ("
597  << size << " configuration sets found)"
598  << endl << frame << endl;
599 
600  sregIter iter = fRegistryPool.begin();
601  for( ; iter != fRegistryPool.end(); iter++) {
602  const Registry & reg = *(iter->second);
603  stream << iter->first;
604  stream << reg;
605  stream << frame << endl;
606  }
607 }
608 //____________________________________________________________________________
609 
::xsd::cxx::tree::id< char, ncname > id
Definition: Database.h:165
vector< string > fConfigKeyList
list of all available configuration keys
Definition: AlgConfigPool.h:84
const XML_Char * name
Definition: expat.h:151
THE MAIN GENIE PROJECT NAMESPACE
Definition: GeneratorBase.h:8
#define pERROR
Definition: Messenger.h:60
bool LoadGlobalParamLists(void)
void Print(ostream &stream) const
string TrimSpaces(xmlChar *xmls)
A singleton class holding all configuration registries built while parsing all loaded XML configurati...
Definition: AlgConfigPool.h:41
#define pFATAL
Definition: Messenger.h:57
int RgInt
Algorithm abstract base class.
Definition: Algorithm.h:54
Definition: config.py:1
void AddConfigParameter(Registry *r, string pt, string pn, string pv)
bool LoadSingleAlgConfig(string alg_name, string file_name)
Registry * CommonList(const string &file_id, const string &set_name) const
void AddRootObjParameter(Registry *r, string pt, string pn, string pv)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Definition: typedefs.hpp:11
static AlgConfigPool * fInstance
Definition: AlgConfigPool.h:80
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:97
Registry * TuneGeneratorList(void) const
root
Link up the nodes tree #####.
string GetXMLFilePath(string basename)
void AddBasicParameter(Registry *r, string pt, string pn, string pv)
bool LoadTuneGeneratorList(void)
string RgStr
#define pINFO
Definition: Messenger.h:63
void Lock(void)
locks the registry
Definition: Registry.cxx:163
void SetName(string name)
set the registry name
Definition: Registry.cxx:603
string pname
Definition: eplot.py:33
const vector< string > & ConfigKeyList(void) const
Registry * GlobalParameterList(void) const
#define pWARN
Definition: Messenger.h:61
TH1F * h2
Definition: plot.C:45
string TrimSpaces(string input)
Definition: StringUtils.cxx:24
Algorithm ID (algorithm name + configuration set name)
Definition: AlgId.h:35
bool LoadRegistries(string key_base, string file_name, string root)
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
virtual const AlgId & Id(void) const
Get algorithm ID.
Definition: Algorithm.h:98
map< string, string > fConfigFiles
algorithm -> XML config file
Definition: AlgConfigPool.h:83
vector< string > Split(string input, string delim)
Definition: StringUtils.cxx:42
string RgKey
ostream & operator<<(ostream &stream, const AlgConfigPool &config_pool)
A registry. Provides the container for algorithm configuration parameters.
Definition: Registry.h:66
map< string, Registry * > fRegistryPool
algorithm/param_set -> Registry
Definition: AlgConfigPool.h:82
exit(0)
TRandom3 r(0)
Registry * FindRegistry(string key) const
#define pNOTICE
Definition: Messenger.h:62
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
Definition: Messenger.h:85
string GetAttribute(xmlNodePtr xml_cur, string attr_name)
double RgDbl
bool gAbortingInErr
Definition: Messenger.cxx:56
void Set(RgIMapPair entry)
Definition: Registry.cxx:282
bool LoadCommonLists(const string &file_id)
string Key(void) const
Definition: AlgId.h:47
static AlgConfigPool * Instance()
#define pDEBUG
Definition: Messenger.h:64
string fMasterConfig
lists config files for all algorithms
Definition: AlgConfigPool.h:85