ROOT logo
// @(#)root/tmva $Id: MethodCompositeBase.cxx 29195 2009-06-24 10:39:49Z brun $   
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Kai Voss,Or Cohen 

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : MethodCompositeBase                                                   *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Virtual base class for all MVA method                                     *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Joerg Stelzer   <Joerg.Stelzer@cern.ch>  - CERN, Switzerland              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *      Kai Voss        <Kai.Voss@cern.ch>       - U. of Victoria, Canada         *
 *      Or Cohen        <orcohenor@gmail.com>    - Weizmann Inst., Israel         *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         * 
 *      U. of Victoria, Canada                                                    * 
 *      MPI-K Heidelberg, Germany                                                 * 
 *      LAPP, Annecy, France                                                      *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//
// This class is virtual class meant to combine more than one classifier//
// together. The training of the classifiers is done by classes that are//
// derived from this one, while the saving and loading of weights file  //
// and the evaluation is done here.                                     //
//_______________________________________________________________________

#include <algorithm>
#include <iomanip>
#include <vector>

#include "Riostream.h"
#include "TRandom3.h"
#include "TMath.h"
#include "TObjString.h"

#include "TMVA/MethodCompositeBase.h"
#include "TMVA/MethodBoost.h"
#include "TMVA/MethodBase.h"
#include "TMVA/Tools.h"
#include "TMVA/Types.h"
#include "TMVA/Factory.h"
#include "TMVA/ClassifierFactory.h"

using std::vector;

ClassImp(TMVA::MethodCompositeBase)

//_______________________________________________________________________
TMVA::MethodCompositeBase::MethodCompositeBase( const TString& jobName, 
                                                Types::EMVA methodType,
                                                const TString& methodTitle,
                                                DataSetInfo& theData,
                                                const TString& theOption,
                                                TDirectory* theTargetDir )
   : TMVA::MethodBase( jobName, methodType, methodTitle, theData, theOption, theTargetDir )
{}

//_______________________________________________________________________
TMVA::MethodCompositeBase::MethodCompositeBase( Types::EMVA methodType,
                                                DataSetInfo& dsi,
                                                const TString& weightFile, 
                                                TDirectory* theTargetDir )
   : TMVA::MethodBase( methodType, dsi, weightFile, theTargetDir )
{}

//_______________________________________________________________________
TMVA::IMethod* TMVA::MethodCompositeBase::GetMethod( const TString &methodTitle ) const
{
   // returns pointer to MVA that corresponds to given method title
   vector<IMethod*>::const_iterator itrMethod    = fMethods.begin();
   vector<IMethod*>::const_iterator itrMethodEnd = fMethods.end();

   for (; itrMethod != itrMethodEnd; itrMethod++) {
      MethodBase* mva = dynamic_cast<MethodBase*>(*itrMethod);    
      if ( (mva->GetMethodName())==methodTitle ) return mva;
   }
   return 0;
}

//_______________________________________________________________________
TMVA::IMethod* TMVA::MethodCompositeBase::GetMethod( const Int_t index ) const
{
   // returns pointer to MVA that corresponds to given method index
   vector<IMethod*>::const_iterator itrMethod = fMethods.begin()+index;
   if (itrMethod<fMethods.end()) return *itrMethod;
   else                          return 0;
}

//_______________________________________________________________________
void TMVA::MethodCompositeBase::WriteWeightsToStream( ostream& o ) const
{
   o << "NClassifier= " << fMethods.size() <<endl;
   for (UInt_t i=0; i< fMethods.size(); i++) 
   {
      MethodBase* method = dynamic_cast<MethodBase*>(fMethods[i]);
      o << "Classifier : " << method->GetMethodTypeName() << "::" << method->GetMethodName()
        << "; Index= " << i << " ; Weight= " << fMethodWeight[i] << endl;
      if (GetMethodType() != Types::kBoost || i==0) 
      {
         // for the booster - writing the values only for the first method
         o << "Job Name= " << method->GetJobName()  << endl;
         o << "Title= " << method->GetMethodName()  << endl;
         o << "Option= " << method->GetOptions()  << endl;
      }
      method->WriteWeightsToStream(o);
   }
}

//_______________________________________________________________________
void TMVA::MethodCompositeBase::AddWeightsXMLTo( void* parent ) const 
{
   void* wght = gTools().xmlengine().NewChild(parent, 0, "Weights");
   gTools().AddAttr( wght, "NMethods",   fMethods.size()   );
   for (UInt_t i=0; i< fMethods.size(); i++) 
   {
      void* methxml = gTools().xmlengine().NewChild( wght, 0, "Method" );
      MethodBase* method = dynamic_cast<MethodBase*>(fMethods[i]);
      gTools().AddAttr(methxml,"Index",          i ); 
      gTools().AddAttr(methxml,"Weight",         fMethodWeight[i]); 
      gTools().AddAttr(methxml,"MethodSigCut",   method->GetSignalReferenceCut());
      gTools().AddAttr(methxml,"MethodTypeName", method->GetMethodTypeName());
      gTools().AddAttr(methxml,"MethodName",     method->GetMethodName()   ); 
      gTools().AddAttr(methxml,"JobName",        method->GetJobName());
      gTools().AddAttr(methxml,"Options",        method->GetOptions()); 
      method->AddWeightsXMLTo(methxml);
   }
}

//_______________________________________________________________________
TMVA::MethodCompositeBase::~MethodCompositeBase( void )
{
   // delete methods
   vector<IMethod*>::iterator itrMethod = fMethods.begin();
   for (; itrMethod != fMethods.end(); itrMethod++) {
      Log() << kVERBOSE << "Delete method: " << (*itrMethod)->GetName() << Endl;    
      delete (*itrMethod);
   }
   fMethods.clear();
}

//_______________________________________________________________________
void TMVA::MethodCompositeBase::ReadWeightsFromXML( void* wghtnode ) 
{
   // XML streamer
   UInt_t nMethods;
   TString methodName, methodTypeName, jobName, optionString;

   for (UInt_t i=0;i<fMethods.size();i++) delete fMethods[i];
   fMethods.clear();
   fMethodWeight.clear();
   gTools().ReadAttr( wghtnode, "NMethods",  nMethods );
   void* ch = gTools().xmlengine().GetChild(wghtnode);
   for (UInt_t i=0; i< nMethods; i++) {
      Double_t methodWeight, methodSigCut;
      gTools().ReadAttr( ch, "Weight",   methodWeight   );
      gTools().ReadAttr( ch, "MethodSigCut", methodSigCut);
      fMethodWeight.push_back(methodWeight);
      gTools().ReadAttr( ch, "MethodTypeName",  methodTypeName );
      gTools().ReadAttr( ch, "MethodName",  methodName );
      gTools().ReadAttr( ch, "JobName",  jobName );
      gTools().ReadAttr( ch, "Options",  optionString );

      if (i==0){
         // the cast on MethodBoost is ugly, but a similar line is also in ReadWeightsFromFile --> needs to be fixed later
         ((TMVA::MethodBoost*)this)->BookMethod( Types::Instance().GetMethodType( methodTypeName), methodName,  optionString );
      }
      fMethods.push_back(ClassifierFactory::Instance().Create(
         std::string(methodTypeName),jobName, methodName,DataInfo(),optionString));

      fMethodWeight.push_back(methodWeight);
      MethodBase* meth = dynamic_cast<MethodBase*>(fMethods.back());

      void* methXML = gTools().xmlengine().GetChild(ch);
      meth->SetupMethod();
      meth->ReadWeightsFromXML(methXML);
      meth->SetMsgType(kWARNING);
      meth->ParseOptions();
      meth->ProcessSetup();
      meth->CheckSetup();
      meth->SetSignalReferenceCut(methodSigCut);

      ch = gTools().xmlengine().GetNext(ch);
   }
   //Log() << kINFO << "Reading methods from XML done " << Endl;
}

//_______________________________________________________________________
void  TMVA::MethodCompositeBase::ReadWeightsFromStream( istream& istr )
{
   // text streamer
   TString var, dummy;
   TString methodName, methodTitle=GetMethodName(),
    jobName=GetJobName(),optionString=GetOptions();
   UInt_t methodNum; Double_t methodWeight;
   // and read the Weights (BDT coefficients)  
   istr >> dummy >> methodNum;
   Log() << kINFO << "Read " << methodNum << " Classifiers" << Endl;
   for (UInt_t i=0;i<fMethods.size();i++) delete fMethods[i];
   fMethods.clear();
   fMethodWeight.clear();
   for (UInt_t i=0; i<methodNum; i++) {
      istr >> dummy >> methodName >>  dummy >> fMethodIndex >> dummy >> methodWeight;
      if ((UInt_t)fMethodIndex != i) {
         Log() << kFATAL << "Error while reading weight file; mismatch MethodIndex=" 
               << fMethodIndex << " i=" << i 
               << " MethodName " << methodName
               << " dummy " << dummy
               << " MethodWeight= " << methodWeight 
               << Endl;
      }
      if (GetMethodType() != Types::kBoost || i==0) {
         istr >> dummy >> jobName;
         istr >> dummy >> methodTitle;
         istr >> dummy >> optionString;
         if (GetMethodType() == Types::kBoost)
            ((TMVA::MethodBoost*)this)->BookMethod( Types::Instance().GetMethodType( methodName), methodTitle,  optionString );
      }
      else methodTitle=Form("%s (%04i)",GetMethodName().Data(),fMethodIndex);
      fMethods.push_back(ClassifierFactory::Instance().Create( std::string(methodName), jobName, 
                                                               methodTitle,DataInfo(), optionString) );
      fMethodWeight.push_back( methodWeight );
      dynamic_cast<MethodBase*>(fMethods.back())->ReadWeightsFromStream(istr);
   }
}

//_______________________________________________________________________
Double_t TMVA::MethodCompositeBase::GetMvaValue( Double_t* err )
{
   // return composite MVA response
   Double_t mvaValue = 0;
   for (UInt_t i=0;i< fMethods.size(); i++) mvaValue+=fMethods[i]->GetMvaValue()*fMethodWeight[i];

   // cannot determine error
   if (err != 0) *err = -1;

   return mvaValue;
}
 MethodCompositeBase.cxx:1
 MethodCompositeBase.cxx:2
 MethodCompositeBase.cxx:3
 MethodCompositeBase.cxx:4
 MethodCompositeBase.cxx:5
 MethodCompositeBase.cxx:6
 MethodCompositeBase.cxx:7
 MethodCompositeBase.cxx:8
 MethodCompositeBase.cxx:9
 MethodCompositeBase.cxx:10
 MethodCompositeBase.cxx:11
 MethodCompositeBase.cxx:12
 MethodCompositeBase.cxx:13
 MethodCompositeBase.cxx:14
 MethodCompositeBase.cxx:15
 MethodCompositeBase.cxx:16
 MethodCompositeBase.cxx:17
 MethodCompositeBase.cxx:18
 MethodCompositeBase.cxx:19
 MethodCompositeBase.cxx:20
 MethodCompositeBase.cxx:21
 MethodCompositeBase.cxx:22
 MethodCompositeBase.cxx:23
 MethodCompositeBase.cxx:24
 MethodCompositeBase.cxx:25
 MethodCompositeBase.cxx:26
 MethodCompositeBase.cxx:27
 MethodCompositeBase.cxx:28
 MethodCompositeBase.cxx:29
 MethodCompositeBase.cxx:30
 MethodCompositeBase.cxx:31
 MethodCompositeBase.cxx:32
 MethodCompositeBase.cxx:33
 MethodCompositeBase.cxx:34
 MethodCompositeBase.cxx:35
 MethodCompositeBase.cxx:36
 MethodCompositeBase.cxx:37
 MethodCompositeBase.cxx:38
 MethodCompositeBase.cxx:39
 MethodCompositeBase.cxx:40
 MethodCompositeBase.cxx:41
 MethodCompositeBase.cxx:42
 MethodCompositeBase.cxx:43
 MethodCompositeBase.cxx:44
 MethodCompositeBase.cxx:45
 MethodCompositeBase.cxx:46
 MethodCompositeBase.cxx:47
 MethodCompositeBase.cxx:48
 MethodCompositeBase.cxx:49
 MethodCompositeBase.cxx:50
 MethodCompositeBase.cxx:51
 MethodCompositeBase.cxx:52
 MethodCompositeBase.cxx:53
 MethodCompositeBase.cxx:54
 MethodCompositeBase.cxx:55
 MethodCompositeBase.cxx:56
 MethodCompositeBase.cxx:57
 MethodCompositeBase.cxx:58
 MethodCompositeBase.cxx:59
 MethodCompositeBase.cxx:60
 MethodCompositeBase.cxx:61
 MethodCompositeBase.cxx:62
 MethodCompositeBase.cxx:63
 MethodCompositeBase.cxx:64
 MethodCompositeBase.cxx:65
 MethodCompositeBase.cxx:66
 MethodCompositeBase.cxx:67
 MethodCompositeBase.cxx:68
 MethodCompositeBase.cxx:69
 MethodCompositeBase.cxx:70
 MethodCompositeBase.cxx:71
 MethodCompositeBase.cxx:72
 MethodCompositeBase.cxx:73
 MethodCompositeBase.cxx:74
 MethodCompositeBase.cxx:75
 MethodCompositeBase.cxx:76
 MethodCompositeBase.cxx:77
 MethodCompositeBase.cxx:78
 MethodCompositeBase.cxx:79
 MethodCompositeBase.cxx:80
 MethodCompositeBase.cxx:81
 MethodCompositeBase.cxx:82
 MethodCompositeBase.cxx:83
 MethodCompositeBase.cxx:84
 MethodCompositeBase.cxx:85
 MethodCompositeBase.cxx:86
 MethodCompositeBase.cxx:87
 MethodCompositeBase.cxx:88
 MethodCompositeBase.cxx:89
 MethodCompositeBase.cxx:90
 MethodCompositeBase.cxx:91
 MethodCompositeBase.cxx:92
 MethodCompositeBase.cxx:93
 MethodCompositeBase.cxx:94
 MethodCompositeBase.cxx:95
 MethodCompositeBase.cxx:96
 MethodCompositeBase.cxx:97
 MethodCompositeBase.cxx:98
 MethodCompositeBase.cxx:99
 MethodCompositeBase.cxx:100
 MethodCompositeBase.cxx:101
 MethodCompositeBase.cxx:102
 MethodCompositeBase.cxx:103
 MethodCompositeBase.cxx:104
 MethodCompositeBase.cxx:105
 MethodCompositeBase.cxx:106
 MethodCompositeBase.cxx:107
 MethodCompositeBase.cxx:108
 MethodCompositeBase.cxx:109
 MethodCompositeBase.cxx:110
 MethodCompositeBase.cxx:111
 MethodCompositeBase.cxx:112
 MethodCompositeBase.cxx:113
 MethodCompositeBase.cxx:114
 MethodCompositeBase.cxx:115
 MethodCompositeBase.cxx:116
 MethodCompositeBase.cxx:117
 MethodCompositeBase.cxx:118
 MethodCompositeBase.cxx:119
 MethodCompositeBase.cxx:120
 MethodCompositeBase.cxx:121
 MethodCompositeBase.cxx:122
 MethodCompositeBase.cxx:123
 MethodCompositeBase.cxx:124
 MethodCompositeBase.cxx:125
 MethodCompositeBase.cxx:126
 MethodCompositeBase.cxx:127
 MethodCompositeBase.cxx:128
 MethodCompositeBase.cxx:129
 MethodCompositeBase.cxx:130
 MethodCompositeBase.cxx:131
 MethodCompositeBase.cxx:132
 MethodCompositeBase.cxx:133
 MethodCompositeBase.cxx:134
 MethodCompositeBase.cxx:135
 MethodCompositeBase.cxx:136
 MethodCompositeBase.cxx:137
 MethodCompositeBase.cxx:138
 MethodCompositeBase.cxx:139
 MethodCompositeBase.cxx:140
 MethodCompositeBase.cxx:141
 MethodCompositeBase.cxx:142
 MethodCompositeBase.cxx:143
 MethodCompositeBase.cxx:144
 MethodCompositeBase.cxx:145
 MethodCompositeBase.cxx:146
 MethodCompositeBase.cxx:147
 MethodCompositeBase.cxx:148
 MethodCompositeBase.cxx:149
 MethodCompositeBase.cxx:150
 MethodCompositeBase.cxx:151
 MethodCompositeBase.cxx:152
 MethodCompositeBase.cxx:153
 MethodCompositeBase.cxx:154
 MethodCompositeBase.cxx:155
 MethodCompositeBase.cxx:156
 MethodCompositeBase.cxx:157
 MethodCompositeBase.cxx:158
 MethodCompositeBase.cxx:159
 MethodCompositeBase.cxx:160
 MethodCompositeBase.cxx:161
 MethodCompositeBase.cxx:162
 MethodCompositeBase.cxx:163
 MethodCompositeBase.cxx:164
 MethodCompositeBase.cxx:165
 MethodCompositeBase.cxx:166
 MethodCompositeBase.cxx:167
 MethodCompositeBase.cxx:168
 MethodCompositeBase.cxx:169
 MethodCompositeBase.cxx:170
 MethodCompositeBase.cxx:171
 MethodCompositeBase.cxx:172
 MethodCompositeBase.cxx:173
 MethodCompositeBase.cxx:174
 MethodCompositeBase.cxx:175
 MethodCompositeBase.cxx:176
 MethodCompositeBase.cxx:177
 MethodCompositeBase.cxx:178
 MethodCompositeBase.cxx:179
 MethodCompositeBase.cxx:180
 MethodCompositeBase.cxx:181
 MethodCompositeBase.cxx:182
 MethodCompositeBase.cxx:183
 MethodCompositeBase.cxx:184
 MethodCompositeBase.cxx:185
 MethodCompositeBase.cxx:186
 MethodCompositeBase.cxx:187
 MethodCompositeBase.cxx:188
 MethodCompositeBase.cxx:189
 MethodCompositeBase.cxx:190
 MethodCompositeBase.cxx:191
 MethodCompositeBase.cxx:192
 MethodCompositeBase.cxx:193
 MethodCompositeBase.cxx:194
 MethodCompositeBase.cxx:195
 MethodCompositeBase.cxx:196
 MethodCompositeBase.cxx:197
 MethodCompositeBase.cxx:198
 MethodCompositeBase.cxx:199
 MethodCompositeBase.cxx:200
 MethodCompositeBase.cxx:201
 MethodCompositeBase.cxx:202
 MethodCompositeBase.cxx:203
 MethodCompositeBase.cxx:204
 MethodCompositeBase.cxx:205
 MethodCompositeBase.cxx:206
 MethodCompositeBase.cxx:207
 MethodCompositeBase.cxx:208
 MethodCompositeBase.cxx:209
 MethodCompositeBase.cxx:210
 MethodCompositeBase.cxx:211
 MethodCompositeBase.cxx:212
 MethodCompositeBase.cxx:213
 MethodCompositeBase.cxx:214
 MethodCompositeBase.cxx:215
 MethodCompositeBase.cxx:216
 MethodCompositeBase.cxx:217
 MethodCompositeBase.cxx:218
 MethodCompositeBase.cxx:219
 MethodCompositeBase.cxx:220
 MethodCompositeBase.cxx:221
 MethodCompositeBase.cxx:222
 MethodCompositeBase.cxx:223
 MethodCompositeBase.cxx:224
 MethodCompositeBase.cxx:225
 MethodCompositeBase.cxx:226
 MethodCompositeBase.cxx:227
 MethodCompositeBase.cxx:228
 MethodCompositeBase.cxx:229
 MethodCompositeBase.cxx:230
 MethodCompositeBase.cxx:231
 MethodCompositeBase.cxx:232
 MethodCompositeBase.cxx:233
 MethodCompositeBase.cxx:234
 MethodCompositeBase.cxx:235
 MethodCompositeBase.cxx:236
 MethodCompositeBase.cxx:237
 MethodCompositeBase.cxx:238
 MethodCompositeBase.cxx:239
 MethodCompositeBase.cxx:240
 MethodCompositeBase.cxx:241
 MethodCompositeBase.cxx:242
 MethodCompositeBase.cxx:243
 MethodCompositeBase.cxx:244
 MethodCompositeBase.cxx:245
 MethodCompositeBase.cxx:246
 MethodCompositeBase.cxx:247
 MethodCompositeBase.cxx:248
 MethodCompositeBase.cxx:249