00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <string>
00035 #include <iostream>
00036 #include <fstream>
00037 #include <cstdlib>
00038 #include <vector>
00039
00040 #include "TROOT.h"
00041 #include "TSystem.h"
00042 #include "TString.h"
00043 #include "TObjString.h"
00044 #include "TQObject.h"
00045 #include "TSpline.h"
00046 #include "TMatrix.h"
00047 #include "TMath.h"
00048 #include "TFile.h"
00049 #include "TKey.h"
00050
00051 #include "TMVA/Configurable.h"
00052 #include "TMVA/Config.h"
00053 #include "TMVA/Tools.h"
00054
00055
00056
00057
00058 ClassImp(TMVA::Configurable)
00059
00060 #ifdef _WIN32
00061
00062 #pragma warning ( disable : 4355 )
00063 #endif
00064
00065
00066 TMVA::Configurable::Configurable( const TString& theOption)
00067 : fOptions ( theOption ),
00068 fLooseOptionCheckingEnabled ( kTRUE ),
00069 fLastDeclaredOption ( 0 ),
00070 fConfigName ( "Configurable" ),
00071 fConfigDescription ( "No description" ),
00072 fReferenceFile ( "None" ),
00073 fLogger ( new MsgLogger(this) )
00074 {
00075
00076 fListOfOptions.SetOwner();
00077
00078
00079 if (gTools().CheckForVerboseOption( theOption )) Log().SetMinType( kVERBOSE );
00080 }
00081
00082
00083 TMVA::Configurable::~Configurable()
00084 {
00085
00086 delete fLogger;
00087 }
00088
00089
00090 void TMVA::Configurable::SplitOptions(const TString& theOpt, TList& loo) const
00091 {
00092
00093 TString splitOpt(theOpt);
00094 loo.SetOwner();
00095 while (splitOpt.Length()>0) {
00096 if (!splitOpt.Contains(':')) {
00097 loo.Add(new TObjString(splitOpt));
00098 splitOpt = "";
00099 }
00100 else {
00101 TString toSave = splitOpt(0,splitOpt.First(':'));
00102 loo.Add(new TObjString(toSave.Data()));
00103 splitOpt = splitOpt(splitOpt.First(':')+1,splitOpt.Length());
00104 }
00105 }
00106 }
00107
00108
00109 void TMVA::Configurable::ResetSetFlag()
00110 {
00111
00112
00113
00114 TListIter decOptIt(&fListOfOptions);
00115 while (OptionBase* decOpt = (OptionBase*) decOptIt()) {
00116 decOpt->fIsSet = kFALSE;
00117 }
00118 }
00119
00120
00121 void TMVA::Configurable::ParseOptions()
00122 {
00123
00124 Log() << kVERBOSE << "Parsing option string: " << Endl;
00125 TString optionsWithoutTilde(fOptions);
00126 optionsWithoutTilde.ReplaceAll(TString("~"),TString(""));
00127 Log() << kVERBOSE << "... \"" << optionsWithoutTilde << "\"" << Endl;
00128
00129 TList loo;
00130
00131 fOptions = fOptions.Strip(TString::kLeading, ':');
00132
00133
00134 SplitOptions(fOptions, loo);
00135 fOptions = "";
00136
00137
00138 std::map<TString, std::vector<std::pair<Int_t, TString> > > arrayTypeOptions;
00139
00140 TListIter decOptIt(&fListOfOptions);
00141 TListIter setOptIt(&loo);
00142 while (TObjString * os = (TObjString*) setOptIt()) {
00143
00144 TString s = os->GetString();
00145
00146
00147
00148
00149
00150
00151
00152
00153 Bool_t preserveTilde = s.BeginsWith('~');
00154 s = s.Strip(TString::kLeading, '~');
00155
00156 Bool_t paramParsed = kFALSE;
00157 if (s.Contains('=')) {
00158 TString optname = s(0,s.First('=')); optname.ToLower();
00159 TString optval = s(s.First('=')+1,s.Length());
00160 Int_t idx = -1;
00161
00162
00163
00164
00165
00166 OptionBase* decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
00167 if (decOpt==0 && optname.Contains('[')) {
00168
00169
00170 TString st = optname(optname.First('[')+1,100);
00171 st.Remove(st.First(']'));
00172 std::stringstream str(st.Data());
00173 str >> idx;
00174 optname.Remove(optname.First('['));
00175 decOpt = (OptionBase *)fListOfOptions.FindObject(optname);
00176 }
00177
00178 TListIter optIt(&fListOfOptions);
00179 if (decOpt!=0) {
00180 if (decOpt->IsSet())
00181 Log() << kWARNING << "Value for option " << decOpt->GetName()
00182 << " was previously set to " << decOpt->GetValue() << Endl;
00183
00184 if (!decOpt->HasPreDefinedVal() || (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(optval)) ) {
00185 if (decOpt->IsArrayOpt()) {
00186
00187 if (idx==-1) {
00188 decOpt->SetValue(optval);
00189 }
00190 else {
00191
00192 if (!decOpt->SetValue(optval, idx))
00193 Log() << kFATAL << "Index " << idx << " too large for option " << decOpt->TheName()
00194 << ", allowed range is [0," << decOpt->GetArraySize()-1 << "]" << Endl;
00195 }
00196 }
00197 else {
00198 if (idx!=-1)
00199 Log() << kFATAL << "Option " << decOpt->TheName()
00200 << " is not an array, but you specified an index" << Endl;
00201 decOpt->SetValue(optval);
00202 }
00203 paramParsed = kTRUE;
00204 }
00205 else Log() << kFATAL << "Option " << decOpt->TheName()
00206 << " does not have predefined value: \"" << optval << "\"" << Endl;
00207 }
00208 }
00209
00210
00211
00212 Bool_t preserveNotSign = kFALSE;
00213 if (!paramParsed) {
00214 Bool_t hasNotSign = kFALSE;
00215 if (s.BeginsWith("!")) { s.Remove(0,1); preserveNotSign = hasNotSign = kTRUE; }
00216 TString optname(s); optname.ToLower();
00217 OptionBase* decOpt = 0;
00218 Bool_t optionExists = kFALSE;
00219 TListIter optIt(&fListOfOptions);
00220 while ((decOpt = (OptionBase*)optIt()) !=0) {
00221 TString predOptName(decOpt->GetName());
00222 predOptName.ToLower();
00223 if (predOptName == optname) optionExists = kTRUE;
00224 if (dynamic_cast<Option<bool>*>(decOpt)==0) continue;
00225 if (predOptName == optname) break;
00226 }
00227
00228
00229 if (decOpt != 0) {
00230 decOpt->SetValue( hasNotSign ? "0" : "1" );
00231 paramParsed = kTRUE;
00232 }
00233 else {
00234 if (optionExists && hasNotSign) {
00235 Log() << kFATAL << "Negating a non-boolean variable " << optname
00236 << ", please check the opions for method: " << GetName() << Endl;
00237 }
00238 }
00239 }
00240
00241
00242 if (!paramParsed && LooseOptionCheckingEnabled()) {
00243
00244
00245 decOptIt.Reset();
00246 while (OptionBase* decOpt = (OptionBase*) decOptIt()) {
00247 if (decOpt->HasPreDefinedVal() && decOpt->IsPreDefinedVal(s) ) {
00248 paramParsed = decOpt->SetValue(s);
00249 break;
00250 }
00251 }
00252 }
00253
00254 if (fOptions!="") fOptions += ":";
00255 if (paramParsed || preserveTilde) fOptions += '~';
00256 if (preserveNotSign) fOptions += '!';
00257 fOptions += s;
00258 }
00259
00260
00261 PrintOptions();
00262 if (gConfig().WriteOptionsReference()) WriteOptionsReferenceToFile();
00263 }
00264
00265
00266 void TMVA::Configurable::CheckForUnusedOptions() const
00267 {
00268
00269 TString theOpt(fOptions);
00270 theOpt = theOpt.Strip(TString::kLeading, ':');
00271
00272
00273 TList loo;
00274 SplitOptions(theOpt, loo);
00275
00276 TListIter setOptIt(&loo);
00277 TString unusedOptions("");
00278 while (TObjString * os = (TObjString*) setOptIt()) {
00279
00280 TString s = os->GetString();
00281 if (!s.BeginsWith('~')) {
00282 if (unusedOptions != "") unusedOptions += ':';
00283 unusedOptions += s;
00284 }
00285 }
00286 if (unusedOptions != "") {
00287 Log() << kFATAL
00288 << "The following options were specified, but could not be interpreted: \'"
00289 << unusedOptions << "\', please check!" << Endl;
00290 }
00291 }
00292
00293
00294 void TMVA::Configurable::PrintOptions() const
00295 {
00296
00297
00298 Log() << kVERBOSE << "The following options are set:" << Endl;
00299
00300 TListIter optIt( &fListOfOptions );
00301 Log() << kVERBOSE << "- By User:" << Endl;
00302 Bool_t found = kFALSE;
00303 while (OptionBase* opt = (OptionBase *) optIt()) {
00304 if (opt->IsSet()) { Log() << kVERBOSE << " "; opt->Print(Log()); Log() << Endl; found = kTRUE; }
00305 }
00306 if (!found) Log() << kVERBOSE << " <none>" << Endl;
00307
00308 optIt.Reset();
00309 Log() << kVERBOSE << "- Default:" << Endl;
00310 found = kFALSE;
00311 while (OptionBase* opt = (OptionBase *) optIt()) {
00312 if (!opt->IsSet()) { Log() << kVERBOSE << " "; opt->Print(Log()); Log() << Endl; found = kTRUE; }
00313 }
00314 if (!found) Log() << kVERBOSE << " <none>" << Endl;
00315 }
00316
00317
00318 void TMVA::Configurable::WriteOptionsToStream( ostream& o, const TString& prefix ) const
00319 {
00320
00321
00322 TListIter optIt( &fListOfOptions );
00323 o << prefix << "# Set by User:" << std::endl;
00324 while (OptionBase * opt = (OptionBase *) optIt())
00325 if (opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
00326 optIt.Reset();
00327 o << prefix << "# Default:" << std::endl;
00328 while (OptionBase * opt = (OptionBase *) optIt())
00329 if (!opt->IsSet()) { o << prefix; opt->Print(o); o << std::endl; }
00330 o << prefix << "##" << std::endl;
00331 }
00332
00333
00334 void TMVA::Configurable::AddOptionsXMLTo( void* parent ) const
00335 {
00336
00337 if (!parent) return;
00338 void* opts = gTools().AddChild(parent, "Options");
00339 TListIter optIt( &fListOfOptions );
00340 while (OptionBase * opt = (OptionBase *) optIt()) {
00341 void* optnode = 0;
00342 if (opt->IsArrayOpt()) {
00343 std::stringstream s("");
00344 s.precision( 16 );
00345 for(Int_t i=0; i<opt->GetArraySize(); i++) {
00346 if(i>0) s << " ";
00347 s << std::scientific << opt->GetValue(i);
00348 }
00349 optnode = gTools().AddChild(opts,"Option",s.str().c_str());
00350 }
00351 else {
00352 optnode = gTools().AddChild(opts,"Option", opt->GetValue());
00353 }
00354 gTools().AddAttr(optnode, "name", opt->TheName());
00355 if (opt->IsArrayOpt()) {
00356 gTools().AddAttr(optnode, "size", opt->GetArraySize());
00357 }
00358 gTools().AddAttr(optnode, "modified", (opt->IsSet()?"Yes":"No") );
00359 }
00360 }
00361
00362
00363 void TMVA::Configurable::ReadOptionsFromXML( void* node )
00364 {
00365 void* opt = gTools().GetChild(node);
00366 TString optName, optValue;
00367 fOptions="";
00368 while (opt != 0) {
00369 if (fOptions.Length()!=0) fOptions += ":";
00370 gTools().ReadAttr(opt, "name", optName);
00371 optValue = TString( gTools().GetContent(opt) );
00372 std::stringstream s("");
00373 s.precision( 16 );
00374 if (gTools().HasAttr(opt, "size")) {
00375 UInt_t size;
00376 gTools().ReadAttr(opt, "size", size);
00377 std::vector<TString> values = gTools().SplitString(optValue, ' ');
00378 for(UInt_t i=0; i<size; i++) {
00379 if(i!=0) s << ":";
00380 s << std::scientific << optName << "[" << i << "]=" << values[i];
00381 }
00382 }
00383 else {
00384 s << std::scientific << optName << "=" << optValue;
00385 }
00386 fOptions += s.str().c_str();
00387 opt = gTools().GetNextChild(opt);
00388 }
00389 }
00390
00391
00392 void TMVA::Configurable::WriteOptionsReferenceToFile()
00393 {
00394
00395
00396 TString dir = gConfig().GetIONames().fOptionsReferenceFileDir;
00397 gSystem->MakeDirectory( dir );
00398 fReferenceFile = dir + "/" + GetConfigName() + "_optionsRef.txt";
00399 std::ofstream o( fReferenceFile );
00400 if (!o.good()) {
00401 Log() << kFATAL << "<WriteOptionsToInfoFile> Unable to open output file: " << fReferenceFile << Endl;
00402 }
00403
00404 TListIter optIt( &fListOfOptions );
00405 o << "# List of options:" << std::endl;
00406 o << "# Configurable: " << GetConfigName() << std::endl;
00407 o << "# Description: " << GetConfigDescription() << std::endl;
00408 while (OptionBase * opt = (OptionBase *) optIt()) {
00409 opt->Print( o, 1 );
00410 o << std::endl << "# ------------------------------------------------" << std::endl;
00411 }
00412
00413 o.close();
00414 Log() << kVERBOSE << "Wrote options reference file: \"" << fReferenceFile << "\"" << Endl;
00415 }
00416
00417
00418 void TMVA::Configurable::ReadOptionsFromStream(istream& istr)
00419 {
00420
00421
00422
00423
00424
00425 ResetSetFlag();
00426 fOptions = "";
00427 char buf[512];
00428 istr.getline(buf,512);
00429 TString stropt, strval;
00430 while (istr.good() && !istr.eof() && !(buf[0]=='#' && buf[1]=='#')) {
00431 char *p = buf;
00432 while (*p==' ' || *p=='\t') p++;
00433 if (*p=='#' || *p=='\0') {
00434 istr.getline(buf,512);
00435 continue;
00436 }
00437 std::stringstream sstr(buf);
00438 sstr >> stropt >> strval;
00439 stropt.ReplaceAll(':','=');
00440 strval.ReplaceAll("\"","");
00441 if (fOptions.Length()!=0) fOptions += ":";
00442 fOptions += stropt;
00443 fOptions += strval;
00444 istr.getline(buf,512);
00445 }
00446 }