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
56
57#ifdef _WIN32
58/*Disable warning C4355: 'this' : used in base member initializer list*/
59#pragma warning ( disable : 4355 )
60#endif
61
62////////////////////////////////////////////////////////////////////////////////
63/// constructor
64
66: TNamed("Configurable","Configurable"),
67 fOptions ( theOption ),
70 fConfigDescription ( "No description" ),
71 fReferenceFile ( "None" ),
72 fLogger ( new MsgLogger(this) )
73{
74 fListOfOptions.SetOwner();
75
76 // check if verbosity "V" set in option
77 if (gTools().CheckForVerboseOption( theOption )) Log().SetMinType( kVERBOSE );
78}
79
80////////////////////////////////////////////////////////////////////////////////
81/// default destructor
82
87
88////////////////////////////////////////////////////////////////////////////////
89/// splits the option string at ':' and fills the list 'loo' with the primitive strings
90
91void TMVA::Configurable::SplitOptions(const TString& theOpt, TList& loo) const
92{
93 TString splitOpt(theOpt);
94 loo.SetOwner();
95 while (splitOpt.Length()>0) {
96 if (!splitOpt.Contains(':')) {
97 loo.Add(new TObjString(splitOpt));
98 splitOpt = "";
99 }
100 else {
101 TString toSave = splitOpt(0,splitOpt.First(':'));
102 loo.Add(new TObjString(toSave.Data()));
103 splitOpt = splitOpt(splitOpt.First(':')+1,splitOpt.Length());
104 }
105 }
106}
107
108////////////////////////////////////////////////////////////////////////////////
109/// resets the IsSet flag for all declare options
110/// to be called before options are read from stream
111
113{
114 TListIter decOptIt(&fListOfOptions); // declared options
115 while (OptionBase* decOpt = (OptionBase*) decOptIt()) { // loop over declared options
116 decOpt->fIsSet = kFALSE;
117 }
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// options parser
122
124{
125 Log() << kVERBOSE << "Parsing option string: " << Endl;
126 TString optionsWithoutTilde(fOptions);
127 optionsWithoutTilde.ReplaceAll(TString("~"),TString(""));
128 Log() << kVERBOSE << "... \"" << optionsWithoutTilde << "\"" << Endl;
129
130 TList loo; // the List Of Options in the parsed string
131
132 fOptions = fOptions.Strip(TString::kLeading, ':');
133
134 // separate the options by the ':' marker
136 fOptions = "";
137
138 // loop over the declared options and check for their availability
139 std::map<TString, std::vector<std::pair<Int_t, TString> > > arrayTypeOptions;
140
141 TListIter decOptIt(&fListOfOptions); // declared options
142 TListIter setOptIt(&loo); // parsed options
143 while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options
144
145 TString s = os->GetString();
146
147 // the tilde in the beginning is an indication that the option
148 // has been accepted during previous parsing
149 //
150 // while parsing this option string eventual appearances of the
151 // tilde will be preserved, for correctly parsed options a new
152 // one will be added (in the end it will be checked if all
153 // options were parsed
154 Bool_t preserveTilde = s.BeginsWith('~');
155 s = s.Strip(TString::kLeading, '~');
156
157 Bool_t paramParsed = kFALSE;
158 if (s.Contains('=')) { // desired way of setting an option: "...:optname=optvalue:..."
159 TString optname = s(0,s.First('=')); optname.ToLower();
160 TString optval = s(s.First('=')+1,s.Length());
161 Int_t idx = -1;
162
163 // First check if the optname exists in the list of the
164 // objects. This does not depend on the existence of a [] in
165 // the optname. Sometimes the [] is part of the optname and
166 // does not describe an array
167 OptionBase* decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
168 if (decOpt==0 && optname.Contains('[')) {
169 // now we see if there is an [] and if the optname exists
170 // after removing the [idx]
171 TString st = optname(optname.First('[')+1,100);
172 st.Remove(st.First(']'));
173 std::stringstream str(st.Data());
174 str >> idx; // save the array index
175 optname.Remove(optname.First('[')); // and remove [idx] from the option name
176 decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
177 }
178
180 if (decOpt!=0) {
181 if (decOpt->IsSet())
182 Log() << kWARNING << "Value for option " << decOpt->GetName()
183 << " was previously set to " << decOpt->GetValue() << Endl;
184
185 if (!decOpt->HasPreDefinedVal() || (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(optval)) ) {
186 if (decOpt->IsArrayOpt()) { // arrays
187 // if no index was found then we assume the value is to be set for the entire array
188 if (idx==-1) {
189 decOpt->SetValue(optval);
190 }
191 else {
192 // since we don't know what else is coming we just put everthing into a map
193 if (!decOpt->SetValue(optval, idx))
194 Log() << kFATAL << "Index " << idx << " too large for option " << decOpt->TheName()
195 << ", allowed range is [0," << decOpt->GetArraySize()-1 << "]" << Endl;
196 }
197 }
198 else { // no arrays
199 if (idx!=-1)
200 Log() << kFATAL << "Option " << decOpt->TheName()
201 << " is not an array, but you specified an index" << Endl;
202 decOpt->SetValue(optval);
203 }
204 paramParsed = kTRUE;
205 }
206 else Log() << kFATAL << "Option " << decOpt->TheName()
207 << " does not have predefined value: \"" << optval << "\"" << Endl;
208 }
209 }
210
211 // boolean variables can be specified by just their name (!name),
212 // which will set the to true (false): ...:V:...:!S:..
213 Bool_t preserveNotSign = kFALSE;
214 if (!paramParsed) {
215 Bool_t hasNotSign = kFALSE;
216 if (s.BeginsWith("!")) { s.Remove(0,1); preserveNotSign = hasNotSign = kTRUE; }
217 TString optname(s); optname.ToLower();
218 OptionBase* decOpt = 0;
219 Bool_t optionExists = kFALSE;
221 while ((decOpt = (OptionBase*)optIt()) !=0) {
222 TString predOptName(decOpt->GetName());
223 predOptName.ToLower();
224 if (predOptName == optname) optionExists = kTRUE;
225 if (dynamic_cast<Option<bool>*>(decOpt)==0) continue; // not a boolean option
226 if (predOptName == optname) break;
227 }
228
229
230 if (decOpt != 0) {
231 decOpt->SetValue( hasNotSign ? "0" : "1" );
232 paramParsed = kTRUE;
233 }
234 else {
235 if (optionExists && hasNotSign) {
236 Log() << kFATAL << "Negating a non-boolean variable " << optname
237 << ", please check the options for method: " << GetName() << Endl;
238 }
239 }
240 }
241
242
243 if (!paramParsed && LooseOptionCheckingEnabled()) {
244 // loose options specification, loops through the possible string
245 // values any parameter can have not applicable for boolean or floats
246 decOptIt.Reset();
247 while (OptionBase* decOpt = (OptionBase*) decOptIt()) {
248 if (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(s) ) {
249 paramParsed = decOpt->SetValue(s);
250 break;
251 }
252 }
253 }
254
255 if (fOptions!="") fOptions += ":";
256 if (paramParsed || preserveTilde) fOptions += '~';
257 if (preserveNotSign) fOptions += '!';
258 fOptions += s;
259 }
260
261 // print options summary
262 PrintOptions();
263 if (gConfig().WriteOptionsReference()) WriteOptionsReferenceToFile();
264}
265
266////////////////////////////////////////////////////////////////////////////////
267/// checks for unused options in option string
268
270{
271 TString theOpt(fOptions);
272 theOpt = theOpt.Strip(TString::kLeading, ':');
273
274 // separate the options by the ':' marker
275 TList loo; // the List of Options in the parsed string
276 SplitOptions(theOpt, loo);
277
278 TListIter setOptIt(&loo); // options in a list
279 TString unusedOptions("");
280 while (TObjString * os = (TObjString*) setOptIt()) { // loop over parsed options
281
282 TString s = os->GetString();
283 if (!s.BeginsWith('~')) {
284 if (unusedOptions != "") unusedOptions += ':';
285 unusedOptions += s;
286 }
287 }
288 if (unusedOptions != "") {
289 Log() << kFATAL
290 << "The following options were specified, but could not be interpreted: \'"
291 << unusedOptions << "\', please check!" << Endl;
292 }
293}
294
295////////////////////////////////////////////////////////////////////////////////
296/// prints out the options set in the options string and the defaults
297
299{
300 Log() << kVERBOSE << "The following options are set:" << Endl;
301
302 TListIter optIt( &fListOfOptions );
303 Log() << kVERBOSE << "- By User:" << Endl;
304 Bool_t found = kFALSE;
305 while (OptionBase* opt = (OptionBase *) optIt()) {
306 if (opt->IsSet()) {
307 Log() << kVERBOSE << " ";
308 std::ostringstream oss;
309 opt->Print(oss);
310 Log() << oss.str();
311 Log() << Endl; found = kTRUE; }
312 }
313 if (!found) Log() << kVERBOSE << " <none>" << Endl;
314
315 optIt.Reset();
316 Log() << kVERBOSE << "- Default:" << Endl;
317 found = kFALSE;
318 while (OptionBase* opt = (OptionBase *) optIt()) {
319 if (!opt->IsSet()) {
320 Log() << kVERBOSE << " ";
321 std::ostringstream oss;
322 opt->Print(oss);
323 Log() << oss.str();
324 Log() << Endl; found = kTRUE; }
325 }
326 if (!found) Log() << kVERBOSE << " <none>" << Endl;
327}
328
329////////////////////////////////////////////////////////////////////////////////
330/// write options to output stream (e.g. in writing the MVA weight files
331
332void TMVA::Configurable::WriteOptionsToStream( std::ostream& o, const TString& prefix ) const
333{
334 TListIter optIt( &fListOfOptions );
335 o << prefix << "# Set by User:" << std::endl;
336 while (OptionBase * opt = (OptionBase *) optIt())
337 if (opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
338 optIt.Reset();
339 o << prefix << "# Default:" << std::endl;
340 while (OptionBase * opt = (OptionBase *) optIt())
341 if (!opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
342 o << prefix << "##" << std::endl;
343}
344
345////////////////////////////////////////////////////////////////////////////////
346/// write options to XML file
347
348void TMVA::Configurable::AddOptionsXMLTo( void* parent ) const
349{
350 if (!parent) return;
351 void* opts = gTools().AddChild(parent, "Options");
352 TListIter optIt( &fListOfOptions );
353 while (OptionBase * opt = (OptionBase *) optIt()) {
354 void* optnode = 0;
355 if (opt->IsArrayOpt()) {
356 std::stringstream s("");
357 s.precision( 16 );
358 for(Int_t i=0; i<opt->GetArraySize(); i++) {
359 if(i>0) s << " ";
360 s << std::scientific << opt->GetValue(i);
361 }
362 optnode = gTools().AddChild(opts,"Option",s.str().c_str());
363 }
364 else {
365 optnode = gTools().AddChild(opts,"Option", opt->GetValue());
366 }
367 gTools().AddAttr(optnode, "name", opt->TheName());
368 if (opt->IsArrayOpt()) {
369 gTools().AddAttr(optnode, "size", opt->GetArraySize());
370 }
371 gTools().AddAttr(optnode, "modified", (opt->IsSet()?"Yes":"No") );
372 }
373}
374
375////////////////////////////////////////////////////////////////////////////////
376
378{
379 void* opt = gTools().GetChild(node);
380 TString optName, optValue;
381 fOptions="";
382 while (opt != 0) {
383 if (fOptions.Length()!=0) fOptions += ":";
384 gTools().ReadAttr(opt, "name", optName);
385 optValue = TString( gTools().GetContent(opt) );
386 std::stringstream s("");
387 s.precision( 16 );
388 if (gTools().HasAttr(opt, "size")) {
389 UInt_t size;
390 gTools().ReadAttr(opt, "size", size);
391 std::vector<TString> values = gTools().SplitString(optValue, ' ');
392 for(UInt_t i=0; i<size; i++) {
393 if(i!=0) s << ":";
394 s << std::scientific << optName << "[" << i << "]=" << values[i];
395 }
396 }
397 else {
398 s << std::scientific << optName << "=" << optValue;
399 }
400 fOptions += s.str().c_str();
401 opt = gTools().GetNextChild(opt);
402 }
403}
404
405////////////////////////////////////////////////////////////////////////////////
406/// write complete options to output stream
407
409{
411 gSystem->MakeDirectory( dir );
412 fReferenceFile = dir + "/" + GetConfigName() + "_optionsRef.txt";
413 std::ofstream o( fReferenceFile );
414 if (!o.good()) { // file could not be opened --> Error
415 Log() << kFATAL << "<WriteOptionsToInfoFile> Unable to open output file: " << fReferenceFile << Endl;
416 }
417
418 TListIter optIt( &fListOfOptions );
419 o << "# List of options:" << std::endl;
420 o << "# Configurable: " << GetConfigName() << std::endl;
421 o << "# Description: " << GetConfigDescription() << std::endl;
422 while (OptionBase * opt = (OptionBase *) optIt()) {
423 opt->Print( o, 1 );
424 o << std::endl << "# ------------------------------------------------" << std::endl;
425 }
426
427 o.close();
428 Log() << kVERBOSE << "Wrote options reference file: \"" << fReferenceFile << "\"" << Endl;
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// read option back from the weight file
433
435{
436 // first set the IsSet flag of all declared options to false
437 // that is only necessary in our factory, when we test right
438 // after the training
439 ResetSetFlag();
440 fOptions = "";
441 char buf[512];
442 istr.getline(buf,512);
443 TString stropt, strval;
444 while (istr.good() && !istr.eof() && !(buf[0]=='#' && buf[1]=='#')) { // if line starts with ## return
445 char *p = buf;
446 while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace
447 if (*p=='#' || *p=='\0') {
448 istr.getline(buf,512); // reading the next line
449 continue; // if comment or empty line, read the next line
450 }
451 std::stringstream sstr(buf);
452 sstr >> stropt >> strval;
453 stropt.ReplaceAll(':','=');
454 strval.ReplaceAll("\"","");
455 if (fOptions.Length()!=0) fOptions += ":";
456 fOptions += stropt;
457 fOptions += strval;
458 istr.getline(buf,512); // reading the next line
459 }
460}
461
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int).
Definition RtypesCore.h:60
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
externTSystem * gSystem
Definition TSystem.h:582
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:196
void Reset() override
Reset list iterator.
Definition TList.cxx:1291
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
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
const char * GetName() const override
Returns name of object.
Definition Option.h:61
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 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:1174
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:1125
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:1099
void * GetNextChild(void *prevchild, const char *childname=nullptr)
XML helpers.
Definition Tools.cxx:1137
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
TNamed()
Definition TNamed.h:38
Collectable string class.
Definition TObjString.h:28
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1170
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:545
const char * Data() const
Definition TString.h:384
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:713
@ kLeading
Definition TString.h:284
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:632
TString & Remove(Ssiz_t pos)
Definition TString.h:694
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Config & gConfig()
Tools & gTools()
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148