ROOT  6.06/09
Reference Guide
VariableDecorrTransform.cxx
Go to the documentation of this file.
1 // @(#)root/tmva $Id$
2 // Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Eckhard von Toerne
3 
4 /**********************************************************************************
5  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6  * Package: TMVA *
7  * Class : VariableDecorrTransform *
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  * Peter Speckmayer <Peter.Speckmayer@cern.ch> - CERN, Switzerland *
16  * Joerg Stelzer <Joerg.Stelzer@cern.ch> - CERN, Switzerland *
17  * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
18  * *
19  * Copyright (c) 2005-2011: *
20  * CERN, Switzerland *
21  * MPI-K Heidelberg, Germany *
22  * U. of Bonn, Germany *
23  * *
24  * Redistribution and use in source and binary forms, with or without *
25  * modification, are permitted according to the terms listed in LICENSE *
26  * (http://tmva.sourceforge.net/LICENSE) *
27  **********************************************************************************/
28 
29 #include <iostream>
30 #include <iomanip>
31 #include <algorithm>
32 
33 #include "TVectorF.h"
34 #include "TVectorD.h"
35 #include "TMatrixD.h"
36 #include "TMatrixDBase.h"
37 
38 #ifndef ROOT_TMVA_MsgLogger
39 #include "TMVA/MsgLogger.h"
40 #endif
41 #ifndef ROOT_TMVA_VariableDecorrTransform
43 #endif
44 #ifndef ROOT_TMVA_Tools
45 #include "TMVA/Tools.h"
46 #endif
47 #ifndef ROOT_TMVA_DataSet
48 #include "TMVA/DataSet.h"
49 #endif
50 
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 /// constructor
55 
56 TMVA::VariableDecorrTransform::VariableDecorrTransform( DataSetInfo& dsi )
57  : VariableTransformBase( dsi, Types::kDecorrelated, "Deco" )
58 {
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// destructor
63 
65 {
66  for (std::vector<TMatrixD*>::iterator it = fDecorrMatrices.begin(); it != fDecorrMatrices.end(); it++) {
67  if ((*it) != 0) delete (*it);
68  }
69 }
70 
71 ////////////////////////////////////////////////////////////////////////////////
72 /// initialisation
73 
75 {
76 }
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// calculate the decorrelation matrix and the normalization
80 
82 {
83  Initialize();
84 
85  if (!IsEnabled() || IsCreated()) return kTRUE;
86 
87  Log() << kINFO << "Preparing the Decorrelation transformation..." << Endl;
88 
89  Int_t inputSize = fGet.size();
90  SetNVariables(inputSize);
91 
92  if (inputSize > 200) {
93  Log() << kINFO << "----------------------------------------------------------------------------"
94  << Endl;
95  Log() << kINFO
96  << ": More than 200 variables, will not calculate decorrelation matrix "
97  << "!" << Endl;
98  Log() << kINFO << "----------------------------------------------------------------------------"
99  << Endl;
100  return kFALSE;
101  }
102 
103  CalcSQRMats( events, GetNClasses() );
104 
105  SetCreated( kTRUE );
106 
107  return kTRUE;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// creates string with variable transformations applied
112 
114 {
115  Int_t whichMatrix = cls;
116  // if cls (the class chosen by the user) not existing, assume that user wants to
117  // have the matrix for all classes together.
118 
119  if (cls < 0 || cls > GetNClasses()) whichMatrix = GetNClasses();
120 
121  TMatrixD* m = fDecorrMatrices.at(whichMatrix);
122  if (m == 0) {
123  if (whichMatrix == GetNClasses() )
124  Log() << kFATAL << "Transformation matrix all classes is not defined"
125  << Endl;
126  else
127  Log() << kFATAL << "Transformation matrix for class " << whichMatrix << " is not defined"
128  << Endl;
129  }
130 
131  const Int_t nvar = fGet.size();
132  std::vector<TString>* strVec = new std::vector<TString>;
133 
134  // fill vector
135  for (Int_t ivar=0; ivar<nvar; ivar++) {
136  TString str( "" );
137  for (Int_t jvar=0; jvar<nvar; jvar++) {
138  str += ((*m)(ivar,jvar) > 0) ? " + " : " - ";
139 
140  Char_t type = fGet.at(jvar).first;
141  Int_t idx = fGet.at(jvar).second;
142 
143  switch( type ) {
144  case 'v':
145  str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Variables()[idx].GetLabel().Data() );
146  break;
147  case 't':
148  str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Targets()[idx].GetLabel().Data() );
149  break;
150  case 's':
151  str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Spectators()[idx].GetLabel().Data() );
152  break;
153  default:
154  Log() << kFATAL << "VariableDecorrTransform::GetTransformationStrings : unknown type '" << type << "'." << Endl;
155  }
156  }
157  strVec->push_back( str );
158  }
159 
160  return strVec;
161 }
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// apply the decorrelation transformation
165 
167 {
168  if (!IsCreated())
169  Log() << kFATAL << "Transformation matrix not yet created"
170  << Endl;
171 
172  Int_t whichMatrix = cls;
173  // if cls (the class chosen by the user) not existing, assume that he wants to have the matrix for all classes together.
174  // EVT this is a workaround to address the reader problem with transforma and EvaluateMVA(std::vector<float/double> ,...)
175  if (cls < 0 || cls >= (int) fDecorrMatrices.size()) whichMatrix = fDecorrMatrices.size()-1;
176  //EVT workaround end
177  //if (cls < 0 || cls > GetNClasses()) {
178  // whichMatrix = GetNClasses();
179  // if (GetNClasses() == 1 ) whichMatrix = (fDecorrMatrices.size()==1?0:2);
180  //}
181 
182  TMatrixD* m = fDecorrMatrices.at(whichMatrix);
183  if (m == 0) {
184  if (whichMatrix == GetNClasses() )
185  Log() << kFATAL << "Transformation matrix all classes is not defined"
186  << Endl;
187  else
188  Log() << kFATAL << "Transformation matrix for class " << whichMatrix << " is not defined"
189  << Endl;
190  }
191 
192  if (fTransformedEvent==0 || fTransformedEvent->GetNVariables()!=ev->GetNVariables()) {
193  if (fTransformedEvent!=0) { delete fTransformedEvent; fTransformedEvent = 0; }
194  fTransformedEvent = new Event();
195  }
196 
197  // transformation to decorrelate the variables
198  const Int_t nvar = fGet.size();
199 
200  std::vector<Float_t> input;
201  std::vector<Char_t> mask; // entries with kTRUE must not be transformed
202  Bool_t hasMaskedEntries = GetInput( ev, input, mask );
203 
204  if( hasMaskedEntries ){ // targets might be masked (for events where the targets have not been computed yet)
205  UInt_t numMasked = std::count(mask.begin(), mask.end(), (Char_t)kTRUE);
206  UInt_t numOK = std::count(mask.begin(), mask.end(), (Char_t)kFALSE);
207  if( numMasked>0 && numOK>0 ){
208  Log() << kFATAL << "You mixed variables and targets in the decorrelation transformation. This is not possible." << Endl;
209  }
210  SetOutput( fTransformedEvent, input, mask, ev );
211  return fTransformedEvent;
212  }
213 
214  TVectorD vec( nvar );
215  for (Int_t ivar=0; ivar<nvar; ivar++) vec(ivar) = input.at(ivar);
216 
217  // diagonalise variable vectors
218  vec *= *m;
219 
220  input.clear();
221  for (Int_t ivar=0; ivar<nvar; ivar++) input.push_back( vec(ivar) );
222 
223  SetOutput( fTransformedEvent, input, mask, ev );
224 
225  return fTransformedEvent;
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /// apply the inverse decorrelation transformation ...
230 /// TODO : ... build the inverse transformation
231 
233 {
234  Log() << kFATAL << "Inverse transformation for decorrelation transformation not yet implemented. Hence, this transformation cannot be applied together with regression if targets should be transformed. Please contact the authors if necessary." << Endl;
235 
236 
237  return fBackTransformedEvent;
238 }
239 
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// compute square-root matrices for signal and background
243 
244 void TMVA::VariableDecorrTransform::CalcSQRMats( const std::vector< Event*>& events, Int_t maxCls )
245 {
246  // delete old matrices if any
247  for (std::vector<TMatrixD*>::iterator it = fDecorrMatrices.begin();
248  it != fDecorrMatrices.end(); it++)
249  if (0 != (*it) ) { delete (*it); *it=0; }
250 
251 
252  // if more than one classes, then produce one matrix for all events as well (beside the matrices for each class)
253  const UInt_t matNum = (maxCls<=1)?maxCls:maxCls+1;
254  fDecorrMatrices.resize( matNum, (TMatrixD*) 0 );
255 
256  std::vector<TMatrixDSym*>* covMat = gTools().CalcCovarianceMatrices( events, maxCls, this );
257 
258 
259  for (UInt_t cls=0; cls<matNum; cls++) {
260  TMatrixD* sqrMat = gTools().GetSQRootMatrix( covMat->at(cls) );
261  if ( sqrMat==0 )
262  Log() << kFATAL << "<GetSQRMats> Zero pointer returned for SQR matrix" << Endl;
263  fDecorrMatrices[cls] = sqrMat;
264  delete (*covMat)[cls];
265  }
266  delete covMat;
267 }
268 
269 ////////////////////////////////////////////////////////////////////////////////
270 /// write the decorrelation matrix to the stream
271 
273 {
274  Int_t cls = 0;
275  Int_t dp = o.precision();
276  for (std::vector<TMatrixD*>::const_iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) {
277  o << "# correlation matrix " << std::endl;
278  TMatrixD* mat = (*itm);
279  o << cls << " " << mat->GetNrows() << " x " << mat->GetNcols() << std::endl;
280  for (Int_t row = 0; row<mat->GetNrows(); row++) {
281  for (Int_t col = 0; col<mat->GetNcols(); col++) {
282  o << std::setprecision(12) << std::setw(20) << (*mat)[row][col] << " ";
283  }
284  o << std::endl;
285  }
286  cls++;
287  }
288  o << "##" << std::endl;
289  o << std::setprecision(dp);
290 }
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// node attachment to parent
294 
296 {
297  void* trf = gTools().AddChild(parent, "Transform");
298  gTools().AddAttr(trf,"Name", "Decorrelation");
299 
301 
302  for (std::vector<TMatrixD*>::const_iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) {
303  TMatrixD* mat = (*itm);
304  /*void* decmat = gTools().xmlengine().NewChild(trf, 0, "Matrix");
305  gTools().xmlengine().NewAttr(decmat,0,"Rows", gTools().StringFromInt(mat->GetNrows()) );
306  gTools().xmlengine().NewAttr(decmat,0,"Columns", gTools().StringFromInt(mat->GetNcols()) );
307 
308  std::stringstream s;
309  for (Int_t row = 0; row<mat->GetNrows(); row++) {
310  for (Int_t col = 0; col<mat->GetNcols(); col++) {
311  s << (*mat)[row][col] << " ";
312  }
313  }
314  gTools().xmlengine().AddRawLine( decmat, s.str().c_str() );*/
315  gTools().WriteTMatrixDToXML(trf,"Matrix",mat);
316  }
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Read the transformation matrices from the xml node
321 
323 {
324  // first delete the old matrices
325  for( std::vector<TMatrixD*>::iterator it = fDecorrMatrices.begin(); it != fDecorrMatrices.end(); it++ )
326  if( (*it) != 0 ) delete (*it);
327  fDecorrMatrices.clear();
328 
329  Bool_t newFormat = kFALSE;
330 
331  void* inpnode = NULL;
332 
333  inpnode = gTools().GetChild(trfnode, "Selection"); // new xml format
334  if( inpnode!=NULL )
335  newFormat = kTRUE; // new xml format
336 
337  void* ch = NULL;
338  if( newFormat ){
339  // ------------- new format --------------------
340  // read input
342 
343  ch = gTools().GetNextChild(inpnode);
344  }else
345  ch = gTools().GetChild(trfnode);
346 
347  // Read the transformation matrices from the xml node
348  while(ch!=0) {
349  Int_t nrows, ncols;
350  gTools().ReadAttr(ch, "Rows", nrows);
351  gTools().ReadAttr(ch, "Columns", ncols);
352  TMatrixD* mat = new TMatrixD(nrows,ncols);
353  const char* content = gTools().GetContent(ch);
354  std::stringstream s(content);
355  for (Int_t row = 0; row<nrows; row++) {
356  for (Int_t col = 0; col<ncols; col++) {
357  s >> (*mat)[row][col];
358  }
359  }
360  fDecorrMatrices.push_back(mat);
361  ch = gTools().GetNextChild(ch);
362  }
363  SetCreated();
364 }
365 
366 
367 ////////////////////////////////////////////////////////////////////////////////
368 /// Read the decorellation matrix from an input stream
369 
370 void TMVA::VariableDecorrTransform::ReadTransformationFromStream( std::istream& istr, const TString& classname )
371 {
372  char buf[512];
373  istr.getline(buf,512);
374  TString strvar, dummy;
375  Int_t nrows(0), ncols(0);
376  UInt_t classIdx=0;
377  while (!(buf[0]=='#'&& buf[1]=='#')) { // if line starts with ## return
378  char* p = buf;
379  while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace
380  if (*p=='#' || *p=='\0') {
381  istr.getline(buf,512);
382  continue; // if comment or empty line, read the next line
383  }
384  std::stringstream sstr(buf);
385 
386  sstr >> strvar;
387  if (strvar=="signal" || strvar=="background") {
388  UInt_t cls=0;
389  if(strvar=="background") cls=1;
390  if(strvar==classname) classIdx = cls;
391  // coverity[tainted_data_argument]
392  sstr >> nrows >> dummy >> ncols;
393  if (fDecorrMatrices.size() <= cls ) fDecorrMatrices.resize(cls+1);
394  if (fDecorrMatrices.at(cls) != 0) delete fDecorrMatrices.at(cls);
395  TMatrixD* mat = fDecorrMatrices.at(cls) = new TMatrixD(nrows,ncols);
396  // now read all matrix parameters
397  for (Int_t row = 0; row<mat->GetNrows(); row++) {
398  for (Int_t col = 0; col<mat->GetNcols(); col++) {
399  istr >> (*mat)[row][col];
400  }
401  }
402  } // done reading a matrix
403  istr.getline(buf,512); // reading the next line
404  }
405 
406  fDecorrMatrices.push_back( new TMatrixD(*fDecorrMatrices[classIdx]) );
407 
408  SetCreated();
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 /// prints the transformation matrix
413 
415 {
416  Int_t cls = 0;
417  for (std::vector<TMatrixD*>::iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) {
418  Log() << kINFO << "Transformation matrix "<< cls <<":" << Endl;
419  (*itm)->Print();
420  }
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// creates C++ code fragment of the decorrelation transform for inclusion in standalone C++ class
425 
426 void TMVA::VariableDecorrTransform::MakeFunction( std::ostream& fout, const TString& fcncName, Int_t part, UInt_t trCounter, Int_t )
427 {
428  Int_t dp = fout.precision();
429 
430  UInt_t numC = fDecorrMatrices.size();
431  // creates a decorrelation function
432  if (part==1) {
433  TMatrixD* mat = fDecorrMatrices.at(0); // ToDo check if all Decorr matrices have identical dimensions
434  fout << std::endl;
435  fout << " double fDecTF_"<<trCounter<<"["<<numC<<"]["<<mat->GetNrows()<<"]["<<mat->GetNcols()<<"];" << std::endl;
436  }
437 
438  if (part==2) {
439  fout << std::endl;
440  fout << "//_______________________________________________________________________" << std::endl;
441  fout << "inline void " << fcncName << "::InitTransform_"<<trCounter<<"()" << std::endl;
442  fout << "{" << std::endl;
443  fout << " // Decorrelation transformation, initialisation" << std::endl;
444  for (UInt_t icls = 0; icls < numC; icls++){
445  TMatrixD* matx = fDecorrMatrices.at(icls);
446  for (int i=0; i<matx->GetNrows(); i++) {
447  for (int j=0; j<matx->GetNcols(); j++) {
448  fout << " fDecTF_"<<trCounter<<"["<<icls<<"]["<<i<<"]["<<j<<"] = " << std::setprecision(12) << (*matx)[i][j] << ";" << std::endl;
449  }
450  }
451  }
452  fout << "}" << std::endl;
453  fout << std::endl;
454  TMatrixD* matx = fDecorrMatrices.at(0); // ToDo check if all Decorr matrices have identicla dimensions
455  fout << "//_______________________________________________________________________" << std::endl;
456  fout << "inline void " << fcncName << "::Transform_"<<trCounter<<"( std::vector<double>& iv, int cls) const" << std::endl;
457  fout << "{" << std::endl;
458  fout << " // Decorrelation transformation" << std::endl;
459  fout << " if (cls < 0 || cls > "<<GetNClasses()<<") {"<< std::endl;
460  fout << " if ("<<GetNClasses()<<" > 1 ) cls = "<<GetNClasses()<<";"<< std::endl;
461  fout << " else cls = "<<(fDecorrMatrices.size()==1?0:2)<<";"<< std::endl;
462  fout << " }"<< std::endl;
463 
464  VariableTransformBase::MakeFunction(fout, fcncName, 0, trCounter, 0 );
465 
466  fout << " std::vector<double> tv;" << std::endl;
467  fout << " for (int i=0; i<"<<matx->GetNrows()<<";i++) {" << std::endl;
468  fout << " double v = 0;" << std::endl;
469  fout << " for (int j=0; j<"<<matx->GetNcols()<<"; j++)" << std::endl;
470  fout << " v += iv[indicesGet.at(j)] * fDecTF_"<<trCounter<<"[cls][i][j];" << std::endl;
471  fout << " tv.push_back(v);" << std::endl;
472  fout << " }" << std::endl;
473  fout << " for (int i=0; i<"<<matx->GetNrows()<<";i++) iv[indicesPut.at(i)] = tv[i];" << std::endl;
474  fout << "}" << std::endl;
475  }
476 
477  fout << std::setprecision(dp);
478 }
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:162
virtual void MakeFunction(std::ostream &fout, const TString &fncName, Int_t part, UInt_t trCounter, Int_t cls)=0
getinput and setoutput equivalent
std::vector< TMatrixDSym * > * CalcCovarianceMatrices(const std::vector< Event * > &events, Int_t maxCls, VariableTransformBase *transformBase=0)
compute covariance matrices
Definition: Tools.cxx:1521
Bool_t PrepareTransformation(const std::vector< Event * > &)
calculate the decorrelation matrix and the normalization
ClassImp(TMVA::VariableDecorrTransform) TMVA
constructor
virtual void AttachXMLTo(void *parent)=0
create XML description the transformation (write out info of selected variables)
virtual void PrintTransformation(std::ostream &o)
prints the transformation matrix
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual ~VariableDecorrTransform(void)
destructor
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
Definition: Tools.h:308
void * AddChild(void *parent, const char *childname, const char *content=0, bool isRootNode=false)
add child node
Definition: Tools.cxx:1134
virtual void MakeFunction(std::ostream &fout, const TString &fncName, Int_t part, UInt_t trCounter, Int_t cls)
creates C++ code fragment of the decorrelation transform for inclusion in standalone C++ class ...
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Tools & gTools()
Definition: Tools.cxx:79
void * GetChild(void *parent, const char *childname=0)
get child node
Definition: Tools.cxx:1158
virtual void ReadFromXML(void *trfnode)
Read the transformation matrices from the xml node.
std::vector< std::vector< double > > Data
virtual void ReadFromXML(void *trfnode)=0
Read the input variables from the XML node.
Int_t GetNrows() const
Definition: TMatrixTBase.h:134
UInt_t GetNVariables() const
accessor to the number of variables
Definition: Event.cxx:303
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:594
TMatrixT< Double_t > TMatrixD
Definition: TMatrixDfwd.h:24
void Initialize(Bool_t useTMVAStyle=kTRUE)
Definition: tmvaglob.cxx:176
void ReadTransformationFromStream(std::istream &, const TString &)
Read the decorellation matrix from an input stream.
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
char * Form(const char *fmt,...)
const char * GetContent(void *node)
XML helpers.
Definition: Tools.cxx:1182
void ReadAttr(void *node, const char *, T &value)
Definition: Tools.h:295
void CalcSQRMats(const std::vector< Event * > &, Int_t maxCls)
Decorrelation matrix [class0/class1/.../all classes].
void WriteTransformationToStream(std::ostream &) const
write the decorrelation matrix to the stream
std::vector< TString > * GetTransformationStrings(Int_t cls) const
creates string with variable transformations applied
virtual void AttachXMLTo(void *parent)
node attachment to parent
virtual const Event * InverseTransform(const Event *const, Int_t cls) const
apply the inverse decorrelation transformation ...
int type
Definition: TGX11.cxx:120
Int_t GetNcols() const
Definition: TMatrixTBase.h:137
static RooMathCoreReg dummy
void * GetNextChild(void *prevchild, const char *childname=0)
XML helpers.
Definition: Tools.cxx:1170
void WriteTMatrixDToXML(void *node, const char *name, TMatrixD *mat)
XML helpers.
Definition: Tools.cxx:1251
char Char_t
Definition: RtypesCore.h:29
Abstract ClassifierFactory template that handles arbitrary types.
virtual const Event * Transform(const Event *const, Int_t cls) const
apply the decorrelation transformation
#define NULL
Definition: Rtypes.h:82
TMatrixD * GetSQRootMatrix(TMatrixDSym *symMat)
square-root of symmetric matrix of course the resulting sqrtMat is also symmetric, but it's easier to treat it as a general matrix
Definition: Tools.cxx:284
const Bool_t kTRUE
Definition: Rtypes.h:91
std::vector< TMatrixD * > fDecorrMatrices
Definition: math.cpp:60