Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 * *
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 * (see tmva/doc/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 ),
71 fConfigDescription ( "No description" ),
72 fReferenceFile ( "None" ),
73 fLogger ( new MsgLogger(this) )
74{
75 fListOfOptions.SetOwner();
76
77 // check if verbosity "V" set in option
78 if (gTools().CheckForVerboseOption( theOption )) Log().SetMinType( kVERBOSE );
79}
80
81////////////////////////////////////////////////////////////////////////////////
82/// default destructor
83
88
89////////////////////////////////////////////////////////////////////////////////
90/// splits the option string at ':' and fills the list 'loo' with the primitive strings
91
92void 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
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
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;
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
333void 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
349void 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
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
unsigned int UInt_t
Definition RtypesCore.h:46
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
Int_t i
R__EXTERN TSystem * gSystem
Definition TSystem.h:566
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Iterator of linked list.
Definition TList.h:193
void Reset() override
Reset list iterator.
Definition TList.cxx:1157
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:83
TString fOptionsReferenceFileDir
Definition Config.h:126
IONames & GetIONames()
Definition Config.h:98
void ReadOptionsFromXML(void *node)
Bool_t LooseOptionCheckingEnabled() const
TString fReferenceFile
reference file for options writing
OptionBase * fLastDeclaredOption
! last declared option
void ResetSetFlag()
resets the IsSet flag for all declare options to be called before options are read from stream
const char * GetConfigName() const
const char * GetConfigDescription() const
virtual ~Configurable()
default destructor
void WriteOptionsReferenceToFile()
write complete options to output stream
void WriteOptionsToStream(std::ostream &o, const TString &prefix) const
write options to output stream (e.g. in writing the MVA weight files
Configurable(const TString &theOption="")
constructor
TString fConfigDescription
description of this configurable
TList fListOfOptions
option list
virtual void ParseOptions()
options parser
MsgLogger & Log() const
MsgLogger * fLogger
! message logger
TString fOptions
options string
void PrintOptions() const
prints out the options set in the options string and the defaults
void CheckForUnusedOptions() const
checks for unused options in option string
void SplitOptions(const TString &theOpt, TList &loo) const
splits the option string at ':' and fills the list 'loo' with the primitive strings
Bool_t fLooseOptionCheckingEnabled
checker for option string
void ReadOptionsFromStream(std::istream &istr)
read option back from the weight file
void AddOptionsXMLTo(void *parent) const
write options to XML file
ostringstream derivative to redirect and format output
Definition MsgLogger.h:57
Class for TMVA-option handling.
Definition Option.h:52
virtual const char * TheName() const
Definition Option.h:62
virtual Bool_t SetValue(const TString &vs, Int_t i=-1)
set value for option
Definition Option.cxx:59
virtual Bool_t IsPreDefinedVal(const TString &) const =0
virtual Bool_t IsArrayOpt() const =0
Bool_t IsSet() const
Definition Option.h:65
virtual Bool_t HasPreDefinedVal() const =0
virtual const char * GetName() const
Returns name of object.
Definition Option.h:61
virtual Int_t GetArraySize() const =0
virtual TString GetValue(Int_t i=-1) const =0
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:1199
void ReadAttr(void *node, const char *, T &value)
read attribute from xml
Definition Tools.h:329
void * GetChild(void *parent, const char *childname=nullptr)
get child node
Definition Tools.cxx:1150
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
add attribute to xml
Definition Tools.h:347
void * AddChild(void *parent, const char *childname, const char *content=nullptr, bool isRootNode=false)
add child node
Definition Tools.cxx:1124
void * GetNextChild(void *prevchild, const char *childname=nullptr)
XML helpers.
Definition Tools.cxx:1162
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
TNamed()
Definition TNamed.h:36
Collectable string class.
Definition TObjString.h:28
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:538
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kLeading
Definition TString.h:276
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Remove(Ssiz_t pos)
Definition TString.h:685
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Config & gConfig()
Tools & gTools()
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148