Logo ROOT  
Reference Guide
Configurable.cxx
Go to the documentation of this file.
1 // @(#)root/tmva $Id$
2 // Author: Andreas Hoecker, Joerg Stelzer, Helge Voss
3 
4 /**********************************************************************************
5  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6  * Package: TMVA *
7  * Class : Configurable *
8  * Web : http://tmva.sourceforge.net *
9  * *
10  * Description: *
11  * Implementation (see header for description) *
12  * *
13  * Authors (alphabetical): *
14  * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
15  * Joerg Stelzer <Joerg.Stelzer@cern.ch> - CERN, Switzerland *
16  * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
17  * *
18  * Copyright (c) 2005: *
19  * CERN, Switzerland *
20  * MPI-K Heidelberg, Germany *
21  * *
22  * Redistribution and use in source and binary forms, with or without *
23  * modification, are permitted according to the terms listed in LICENSE *
24  * (http://tmva.sourceforge.net/LICENSE) *
25  * *
26  **********************************************************************************/
27 
28 /*! \class TMVA::
29 \ingroup TMVA
30 
31  Base Class for all classes that need option parsing
32 
33 */
34 
35 #include <string>
36 #include <iostream>
37 #include <fstream>
38 #include <cstdlib>
39 #include <vector>
40 
41 #include "TSystem.h"
42 #include "TString.h"
43 #include "TObjString.h"
44 #include "TQObject.h"
45 #include "TSpline.h"
46 #include "TMatrix.h"
47 
48 #include "TMVA/Configurable.h"
49 #include "TMVA/Config.h"
50 #include "TMVA/Tools.h"
51 #include "TMVA/Types.h"
52 
53 // don't change this flag without a good reason ! The FitterBase code won't work anymore !!!
54 // #define TMVA_Configurable_SanctionUnknownOption kTRUE
55 
57 
58 #ifdef _WIN32
59 /*Disable warning C4355: 'this' : used in base member initializer list*/
60 #pragma warning ( disable : 4355 )
61 #endif
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// constructor
65 
67 : TNamed("Configurable","Configurable"),
68  fOptions ( theOption ),
69  fLooseOptionCheckingEnabled ( kTRUE ),
70  fLastDeclaredOption ( 0 ),
71  fConfigDescription ( "No description" ),
72  fReferenceFile ( "None" ),
73  fLogger ( new MsgLogger(this) )
74 {
76 
77  // check if verbosity "V" set in option
78  if (gTools().CheckForVerboseOption( theOption )) Log().SetMinType( kVERBOSE );
79 }
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 /// default destructor
83 
85 {
86  delete fLogger;
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// splits the option string at ':' and fills the list 'loo' with the primitive strings
91 
92 void TMVA::Configurable::SplitOptions(const TString& theOpt, TList& loo) const
93 {
94  TString splitOpt(theOpt);
95  loo.SetOwner();
96  while (splitOpt.Length()>0) {
97  if (!splitOpt.Contains(':')) {
98  loo.Add(new TObjString(splitOpt));
99  splitOpt = "";
100  }
101  else {
102  TString toSave = splitOpt(0,splitOpt.First(':'));
103  loo.Add(new TObjString(toSave.Data()));
104  splitOpt = splitOpt(splitOpt.First(':')+1,splitOpt.Length());
105  }
106  }
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// resets the IsSet flag for all declare options
111 /// to be called before options are read from stream
112 
114 {
115  TListIter decOptIt(&fListOfOptions); // declared options
116  while (OptionBase* decOpt = (OptionBase*) decOptIt()) { // loop over declared options
117  decOpt->fIsSet = kFALSE;
118  }
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// options parser
123 
125 {
126  Log() << kVERBOSE << "Parsing option string: " << Endl;
127  TString optionsWithoutTilde(fOptions);
128  optionsWithoutTilde.ReplaceAll(TString("~"),TString(""));
129  Log() << kVERBOSE << "... \"" << optionsWithoutTilde << "\"" << Endl;
130 
131  TList loo; // the List Of Options in the parsed string
132 
133  fOptions = fOptions.Strip(TString::kLeading, ':');
134 
135  // separate the options by the ':' marker
136  SplitOptions(fOptions, loo);
137  fOptions = "";
138 
139  // loop over the declared options and check for their availability
140  std::map<TString, std::vector<std::pair<Int_t, TString> > > arrayTypeOptions;
141 
142  TListIter decOptIt(&fListOfOptions); // declared options
143  TListIter setOptIt(&loo); // parsed options
144  while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options
145 
146  TString s = os->GetString();
147 
148  // the tilde in the beginning is an indication that the option
149  // has been accepted during previous parsing
150  //
151  // while parsing this option string eventual appearances of the
152  // tilde will be preserved, for correctly parsed options a new
153  // one will be added (in the end it will be checked if all
154  // options were parsed
155  Bool_t preserveTilde = s.BeginsWith('~');
156  s = s.Strip(TString::kLeading, '~');
157 
158  Bool_t paramParsed = kFALSE;
159  if (s.Contains('=')) { // desired way of setting an option: "...:optname=optvalue:..."
160  TString optname = s(0,s.First('=')); optname.ToLower();
161  TString optval = s(s.First('=')+1,s.Length());
162  Int_t idx = -1;
163 
164  // First check if the optname exists in the list of the
165  // objects. This does not depend on the existence of a [] in
166  // the optname. Sometimes the [] is part of the optname and
167  // does not describe an array
168  OptionBase* decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
169  if (decOpt==0 && optname.Contains('[')) {
170  // now we see if there is an [] and if the optname exists
171  // after removing the [idx]
172  TString st = optname(optname.First('[')+1,100);
173  st.Remove(st.First(']'));
174  std::stringstream str(st.Data());
175  str >> idx; // save the array index
176  optname.Remove(optname.First('[')); // and remove [idx] from the option name
177  decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
178  }
179 
180  TListIter optIt(&fListOfOptions);
181  if (decOpt!=0) {
182  if (decOpt->IsSet())
183  Log() << kWARNING << "Value for option " << decOpt->GetName()
184  << " was previously set to " << decOpt->GetValue() << Endl;
185 
186  if (!decOpt->HasPreDefinedVal() || (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(optval)) ) {
187  if (decOpt->IsArrayOpt()) { // arrays
188  // if no index was found then we assume the value is to be set for the entire array
189  if (idx==-1) {
190  decOpt->SetValue(optval);
191  }
192  else {
193  // since we don't know what else is coming we just put everthing into a map
194  if (!decOpt->SetValue(optval, idx))
195  Log() << kFATAL << "Index " << idx << " too large for option " << decOpt->TheName()
196  << ", allowed range is [0," << decOpt->GetArraySize()-1 << "]" << Endl;
197  }
198  }
199  else { // no arrays
200  if (idx!=-1)
201  Log() << kFATAL << "Option " << decOpt->TheName()
202  << " is not an array, but you specified an index" << Endl;
203  decOpt->SetValue(optval);
204  }
205  paramParsed = kTRUE;
206  }
207  else Log() << kFATAL << "Option " << decOpt->TheName()
208  << " does not have predefined value: \"" << optval << "\"" << Endl;
209  }
210  }
211 
212  // boolean variables can be specified by just their name (!name),
213  // which will set the to true (false): ...:V:...:!S:..
214  Bool_t preserveNotSign = kFALSE;
215  if (!paramParsed) {
216  Bool_t hasNotSign = kFALSE;
217  if (s.BeginsWith("!")) { s.Remove(0,1); preserveNotSign = hasNotSign = kTRUE; }
218  TString optname(s); optname.ToLower();
219  OptionBase* decOpt = 0;
220  Bool_t optionExists = kFALSE;
221  TListIter optIt(&fListOfOptions);
222  while ((decOpt = (OptionBase*)optIt()) !=0) {
223  TString predOptName(decOpt->GetName());
224  predOptName.ToLower();
225  if (predOptName == optname) optionExists = kTRUE;
226  if (dynamic_cast<Option<bool>*>(decOpt)==0) continue; // not a boolean option
227  if (predOptName == optname) break;
228  }
229 
230 
231  if (decOpt != 0) {
232  decOpt->SetValue( hasNotSign ? "0" : "1" );
233  paramParsed = kTRUE;
234  }
235  else {
236  if (optionExists && hasNotSign) {
237  Log() << kFATAL << "Negating a non-boolean variable " << optname
238  << ", please check the options for method: " << GetName() << Endl;
239  }
240  }
241  }
242 
243 
244  if (!paramParsed && LooseOptionCheckingEnabled()) {
245  // loose options specification, loops through the possible string
246  // values any parameter can have not applicable for boolean or floats
247  decOptIt.Reset();
248  while (OptionBase* decOpt = (OptionBase*) decOptIt()) {
249  if (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(s) ) {
250  paramParsed = decOpt->SetValue(s);
251  break;
252  }
253  }
254  }
255 
256  if (fOptions!="") fOptions += ":";
257  if (paramParsed || preserveTilde) fOptions += '~';
258  if (preserveNotSign) fOptions += '!';
259  fOptions += s;
260  }
261 
262  // print options summary
263  PrintOptions();
264  if (gConfig().WriteOptionsReference()) WriteOptionsReferenceToFile();
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// checks for unused options in option string
269 
271 {
272  TString theOpt(fOptions);
273  theOpt = theOpt.Strip(TString::kLeading, ':');
274 
275  // separate the options by the ':' marker
276  TList loo; // the List of Options in the parsed string
277  SplitOptions(theOpt, loo);
278 
279  TListIter setOptIt(&loo); // options in a list
280  TString unusedOptions("");
281  while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options
282 
283  TString s = os->GetString();
284  if (!s.BeginsWith('~')) {
285  if (unusedOptions != "") unusedOptions += ':';
286  unusedOptions += s;
287  }
288  }
289  if (unusedOptions != "") {
290  Log() << kFATAL
291  << "The following options were specified, but could not be interpreted: \'"
292  << unusedOptions << "\', please check!" << Endl;
293  }
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 /// prints out the options set in the options string and the defaults
298 
300 {
301  Log() << kVERBOSE << "The following options are set:" << Endl;
302 
303  TListIter optIt( &fListOfOptions );
304  Log() << kVERBOSE << "- By User:" << Endl;
305  Bool_t found = kFALSE;
306  while (OptionBase* opt = (OptionBase *) optIt()) {
307  if (opt->IsSet()) {
308  Log() << kVERBOSE << " ";
309  std::ostringstream oss;
310  opt->Print(oss);
311  Log() << oss.str();
312  Log() << Endl; found = kTRUE; }
313  }
314  if (!found) Log() << kVERBOSE << " <none>" << Endl;
315 
316  optIt.Reset();
317  Log() << kVERBOSE << "- Default:" << Endl;
318  found = kFALSE;
319  while (OptionBase* opt = (OptionBase *) optIt()) {
320  if (!opt->IsSet()) {
321  Log() << kVERBOSE << " ";
322  std::ostringstream oss;
323  opt->Print(oss);
324  Log() << oss.str();
325  Log() << Endl; found = kTRUE; }
326  }
327  if (!found) Log() << kVERBOSE << " <none>" << Endl;
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// write options to output stream (e.g. in writing the MVA weight files
332 
333 void TMVA::Configurable::WriteOptionsToStream( std::ostream& o, const TString& prefix ) const
334 {
335  TListIter optIt( &fListOfOptions );
336  o << prefix << "# Set by User:" << std::endl;
337  while (OptionBase * opt = (OptionBase *) optIt())
338  if (opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
339  optIt.Reset();
340  o << prefix << "# Default:" << std::endl;
341  while (OptionBase * opt = (OptionBase *) optIt())
342  if (!opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
343  o << prefix << "##" << std::endl;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// write options to XML file
348 
349 void TMVA::Configurable::AddOptionsXMLTo( void* parent ) const
350 {
351  if (!parent) return;
352  void* opts = gTools().AddChild(parent, "Options");
353  TListIter optIt( &fListOfOptions );
354  while (OptionBase * opt = (OptionBase *) optIt()) {
355  void* optnode = 0;
356  if (opt->IsArrayOpt()) {
357  std::stringstream s("");
358  s.precision( 16 );
359  for(Int_t i=0; i<opt->GetArraySize(); i++) {
360  if(i>0) s << " ";
361  s << std::scientific << opt->GetValue(i);
362  }
363  optnode = gTools().AddChild(opts,"Option",s.str().c_str());
364  }
365  else {
366  optnode = gTools().AddChild(opts,"Option", opt->GetValue());
367  }
368  gTools().AddAttr(optnode, "name", opt->TheName());
369  if (opt->IsArrayOpt()) {
370  gTools().AddAttr(optnode, "size", opt->GetArraySize());
371  }
372  gTools().AddAttr(optnode, "modified", (opt->IsSet()?"Yes":"No") );
373  }
374 }
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 
379 {
380  void* opt = gTools().GetChild(node);
381  TString optName, optValue;
382  fOptions="";
383  while (opt != 0) {
384  if (fOptions.Length()!=0) fOptions += ":";
385  gTools().ReadAttr(opt, "name", optName);
386  optValue = TString( gTools().GetContent(opt) );
387  std::stringstream s("");
388  s.precision( 16 );
389  if (gTools().HasAttr(opt, "size")) {
390  UInt_t size;
391  gTools().ReadAttr(opt, "size", size);
392  std::vector<TString> values = gTools().SplitString(optValue, ' ');
393  for(UInt_t i=0; i<size; i++) {
394  if(i!=0) s << ":";
395  s << std::scientific << optName << "[" << i << "]=" << values[i];
396  }
397  }
398  else {
399  s << std::scientific << optName << "=" << optValue;
400  }
401  fOptions += s.str().c_str();
402  opt = gTools().GetNextChild(opt);
403  }
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// write complete options to output stream
408 
410 {
412  gSystem->MakeDirectory( dir );
413  fReferenceFile = dir + "/" + GetConfigName() + "_optionsRef.txt";
414  std::ofstream o( fReferenceFile );
415  if (!o.good()) { // file could not be opened --> Error
416  Log() << kFATAL << "<WriteOptionsToInfoFile> Unable to open output file: " << fReferenceFile << Endl;
417  }
418 
419  TListIter optIt( &fListOfOptions );
420  o << "# List of options:" << std::endl;
421  o << "# Configurable: " << GetConfigName() << std::endl;
422  o << "# Description: " << GetConfigDescription() << std::endl;
423  while (OptionBase * opt = (OptionBase *) optIt()) {
424  opt->Print( o, 1 );
425  o << std::endl << "# ------------------------------------------------" << std::endl;
426  }
427 
428  o.close();
429  Log() << kVERBOSE << "Wrote options reference file: \"" << fReferenceFile << "\"" << Endl;
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// read option back from the weight file
434 
436 {
437  // first set the IsSet flag of all declared options to false
438  // that is only necessary in our factory, when we test right
439  // after the training
440  ResetSetFlag();
441  fOptions = "";
442  char buf[512];
443  istr.getline(buf,512);
444  TString stropt, strval;
445  while (istr.good() && !istr.eof() && !(buf[0]=='#' && buf[1]=='#')) { // if line starts with ## return
446  char *p = buf;
447  while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace
448  if (*p=='#' || *p=='\0') {
449  istr.getline(buf,512); // reading the next line
450  continue; // if comment or empty line, read the next line
451  }
452  std::stringstream sstr(buf);
453  sstr >> stropt >> strval;
454  stropt.ReplaceAll(':','=');
455  strval.ReplaceAll("\"","");
456  if (fOptions.Length()!=0) fOptions += ":";
457  fOptions += stropt;
458  fOptions += strval;
459  istr.getline(buf,512); // reading the next line
460  }
461 }
462 
TMVA::OptionBase::GetArraySize
virtual Int_t GetArraySize() const =0
TMVA::Configurable::PrintOptions
void PrintOptions() const
prints out the options set in the options string and the defaults
Definition: Configurable.cxx:299
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TMVA::Configurable::Log
MsgLogger & Log() const
Definition: Configurable.h:122
TMVA::Tools::GetChild
void * GetChild(void *parent, const char *childname=0)
get child node
Definition: Tools.cxx:1162
TMVA::Configurable::ReadOptionsFromStream
void ReadOptionsFromStream(std::istream &istr)
read option back from the weight file
Definition: Configurable.cxx:435
TMVA::Configurable
Definition: Configurable.h:45
TMVA::Configurable::WriteOptionsReferenceToFile
void WriteOptionsReferenceToFile()
write complete options to output stream
Definition: Configurable.cxx:409
TString::Strip
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
TMVA::Tools::SplitString
std::vector< TString > SplitString(const TString &theOpt, const char separator) const
splits the option string at 'separator' and fills the list 'splitV' with the primitive strings
Definition: Tools.cxx:1211
TString::Data
const char * Data() const
Definition: TString.h:369
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
TObjString.h
TMVA::OptionBase::GetName
virtual const char * GetName() const
Returns name of object.
Definition: Option.h:61
TMath::Log
Double_t Log(Double_t x)
Definition: TMath.h:760
TMVA::OptionBase::TheName
virtual const char * TheName() const
Definition: Option.h:62
TMVA::Configurable::WriteOptionsToStream
void WriteOptionsToStream(std::ostream &o, const TString &prefix) const
write options to output stream (e.g. in writing the MVA weight files
Definition: Configurable.cxx:333
TMVA::OptionBase::HasPreDefinedVal
virtual Bool_t HasPreDefinedVal() const =0
TMVA::OptionBase::IsSet
Bool_t IsSet() const
Definition: Option.h:65
TCollection::SetOwner
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Definition: TCollection.cxx:746
TMVA::Tools::AddChild
void * AddChild(void *parent, const char *childname, const char *content=0, bool isRootNode=false)
add child node
Definition: Tools.cxx:1136
TMVA::Configurable::AddOptionsXMLTo
void AddOptionsXMLTo(void *parent) const
write options to XML file
Definition: Configurable.cxx:349
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:162
TString::Contains
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
TSystem::MakeDirectory
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:826
TMVA::Configurable::SplitOptions
void SplitOptions(const TString &theOpt, TList &loo) const
splits the option string at ':' and fills the list 'loo' with the primitive strings
Definition: Configurable.cxx:92
TString
Basic string class.
Definition: TString.h:136
TMVA::OptionBase::IsPreDefinedVal
virtual Bool_t IsPreDefinedVal(const TString &) const =0
TString.h
bool
TMatrix.h
TString::ReplaceAll
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
TListIter
Iterator of linked list.
Definition: TList.h:200
TObjString
Collectable string class.
Definition: TObjString.h:28
TMVA::Tools::AddAttr
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
add attribute to xml
Definition: Tools.h:353
TQObject.h
TMVA::Config::IONames::fOptionsReferenceFileDir
TString fOptionsReferenceFileDir
Definition: Config.h:128
TSpline.h
TMVA::Configurable::ReadOptionsFromXML
void ReadOptionsFromXML(void *node)
Definition: Configurable.cxx:378
TSystem.h
TMVA::Configurable::CheckForUnusedOptions
void CheckForUnusedOptions() const
checks for unused options in option string
Definition: Configurable.cxx:270
TMVA::Option
Definition: Option.h:97
TString::Remove
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
TNamed
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TMVA::gConfig
Config & gConfig()
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TString::TString
TString()
TString default ctor.
Definition: TString.cxx:87
TMVA::Tools::ReadAttr
void ReadAttr(void *node, const char *, T &value)
read attribute from xml
Definition: Tools.h:335
TString::First
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:499
TObject::FindObject
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:323
TMVA::MsgLogger::SetMinType
void SetMinType(EMsgType minType)
Definition: MsgLogger.h:72
TMVA::Configurable::ResetSetFlag
void ResetSetFlag()
resets the IsSet flag for all declare options to be called before options are read from stream
Definition: Configurable.cxx:113
TListIter::Reset
void Reset()
Reset list iterator.
Definition: TList.cxx:1161
Types.h
Configurable.h
TMVA::Endl
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:158
Config.h
unsigned int
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TMVA::MsgLogger
ostringstream derivative to redirect and format output
Definition: MsgLogger.h:59
TMVA::Tools::GetNextChild
void * GetNextChild(void *prevchild, const char *childname=0)
XML helpers.
Definition: Tools.cxx:1174
TMVA::Config::GetIONames
IONames & GetIONames()
Definition: Config.h:100
TMVA::OptionBase::IsArrayOpt
virtual Bool_t IsArrayOpt() const =0
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TMVA::OptionBase::GetValue
virtual TString GetValue(Int_t i=-1) const =0
TMVA::OptionBase::SetValue
virtual Bool_t SetValue(const TString &vs, Int_t i=-1)
set value for option
Definition: Option.cxx:59
TMVA::Configurable::Configurable
Configurable(const TString &theOption="")
constructor
Definition: Configurable.cxx:66
TString::kLeading
@ kLeading
Definition: TString.h:267
Tools.h
TString::ToLower
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
TMVA::gTools
Tools & gTools()
TMVA::Configurable::~Configurable
virtual ~Configurable()
default destructor
Definition: Configurable.cxx:84
TMVA::OptionBase
Class for TMVA-option handling.
Definition: Option.h:52
TMVA::Configurable::ParseOptions
virtual void ParseOptions()
options parser
Definition: Configurable.cxx:124
TMVA::Configurable::fListOfOptions
TList fListOfOptions
last declared option
Definition: Configurable.h:114
TList
A doubly linked list.
Definition: TList.h:44
int