// @(#)root/tmva $Id$ // Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Eckhard von Toerne /********************************************************************************** * Project: TMVA - a Root-integrated toolkit for multivariate data analysis * * Package: TMVA * * Class : VariableDecorrTransform * * Web : http://tmva.sourceforge.net * * * * Description: * * Implementation (see header for description) * * * * Authors (alphabetical): * * Andreas Hoecker - CERN, Switzerland * * Peter Speckmayer - CERN, Switzerland * * Joerg Stelzer - CERN, Switzerland * * Helge Voss - MPI-K Heidelberg, Germany * * * * Copyright (c) 2005-2011: * * CERN, Switzerland * * MPI-K Heidelberg, Germany * * U. of Bonn, Germany * * * * 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) * **********************************************************************************/ #include #include #include #include "TVectorF.h" #include "TVectorD.h" #include "TMatrixD.h" #include "TMatrixDBase.h" #ifndef ROOT_TMVA_MsgLogger #include "TMVA/MsgLogger.h" #endif #ifndef ROOT_TMVA_VariableDecorrTransform #include "TMVA/VariableDecorrTransform.h" #endif #ifndef ROOT_TMVA_Tools #include "TMVA/Tools.h" #endif #ifndef ROOT_TMVA_DataSet #include "TMVA/DataSet.h" #endif ClassImp(TMVA::VariableDecorrTransform) //_______________________________________________________________________ TMVA::VariableDecorrTransform::VariableDecorrTransform( DataSetInfo& dsi ) : VariableTransformBase( dsi, Types::kDecorrelated, "Deco" ) { // constructor } //_______________________________________________________________________ TMVA::VariableDecorrTransform::~VariableDecorrTransform() { // destructor for (std::vector::iterator it = fDecorrMatrices.begin(); it != fDecorrMatrices.end(); it++) { if ((*it) != 0) delete (*it); } } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::Initialize() { // initialisation } //_______________________________________________________________________ Bool_t TMVA::VariableDecorrTransform::PrepareTransformation (const std::vector& events) { // calculate the decorrelation matrix and the normalization Initialize(); if (!IsEnabled() || IsCreated()) return kTRUE; Log() << kINFO << "Preparing the Decorrelation transformation..." << Endl; Int_t inputSize = fGet.size(); SetNVariables(inputSize); if (inputSize > 200) { Log() << kINFO << "----------------------------------------------------------------------------" << Endl; Log() << kINFO << ": More than 200 variables, will not calculate decorrelation matrix " << "!" << Endl; Log() << kINFO << "----------------------------------------------------------------------------" << Endl; return kFALSE; } CalcSQRMats( events, GetNClasses() ); SetCreated( kTRUE ); return kTRUE; } //_______________________________________________________________________ std::vector* TMVA::VariableDecorrTransform::GetTransformationStrings( Int_t cls ) const { // creates string with variable transformations applied Int_t whichMatrix = cls; // if cls (the class chosen by the user) not existing, assume that user wants to // have the matrix for all classes together. if (cls < 0 || cls > GetNClasses()) whichMatrix = GetNClasses(); TMatrixD* m = fDecorrMatrices.at(whichMatrix); if (m == 0) { if (whichMatrix == GetNClasses() ) Log() << kFATAL << "Transformation matrix all classes is not defined" << Endl; else Log() << kFATAL << "Transformation matrix for class " << whichMatrix << " is not defined" << Endl; } const Int_t nvar = fGet.size(); std::vector* strVec = new std::vector; // fill vector for (Int_t ivar=0; ivar 0) ? " + " : " - "; Char_t type = fGet.at(jvar).first; Int_t idx = fGet.at(jvar).second; switch( type ) { case 'v': str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Variables()[idx].GetLabel().Data() ); break; case 't': str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Targets()[idx].GetLabel().Data() ); break; case 's': str += Form( "%10.5g*[%s]", TMath::Abs((*m)(ivar,jvar)), Spectators()[idx].GetLabel().Data() ); break; default: Log() << kFATAL << "VariableDecorrTransform::GetTransformationStrings : unknown type '" << type << "'." << Endl; } } strVec->push_back( str ); } return strVec; } //_______________________________________________________________________ const TMVA::Event* TMVA::VariableDecorrTransform::Transform( const TMVA::Event* const ev, Int_t cls ) const { // apply the decorrelation transformation if (!IsCreated()) Log() << kFATAL << "Transformation matrix not yet created" << Endl; Int_t whichMatrix = cls; // if cls (the class chosen by the user) not existing, assume that he wants to have the matrix for all classes together. // EVT this is a workaround to address the reader problem with transforma and EvaluateMVA(std::vector ,...) if (cls < 0 || cls >= (int) fDecorrMatrices.size()) whichMatrix = fDecorrMatrices.size()-1; //EVT workaround end //if (cls < 0 || cls > GetNClasses()) { // whichMatrix = GetNClasses(); // if (GetNClasses() == 1 ) whichMatrix = (fDecorrMatrices.size()==1?0:2); //} TMatrixD* m = fDecorrMatrices.at(whichMatrix); if (m == 0) { if (whichMatrix == GetNClasses() ) Log() << kFATAL << "Transformation matrix all classes is not defined" << Endl; else Log() << kFATAL << "Transformation matrix for class " << whichMatrix << " is not defined" << Endl; } if (fTransformedEvent==0 || fTransformedEvent->GetNVariables()!=ev->GetNVariables()) { if (fTransformedEvent!=0) { delete fTransformedEvent; fTransformedEvent = 0; } fTransformedEvent = new Event(); } // transformation to decorrelate the variables const Int_t nvar = fGet.size(); std::vector input; std::vector mask; // entries with kTRUE must not be transformed Bool_t hasMaskedEntries = GetInput( ev, input, mask ); if( hasMaskedEntries ){ // targets might be masked (for events where the targets have not been computed yet) UInt_t numMasked = std::count(mask.begin(), mask.end(), (Char_t)kTRUE); UInt_t numOK = std::count(mask.begin(), mask.end(), (Char_t)kFALSE); if( numMasked>0 && numOK>0 ){ Log() << kFATAL << "You mixed variables and targets in the decorrelation transformation. This is not possible." << Endl; } SetOutput( fTransformedEvent, input, mask, ev ); return fTransformedEvent; } TVectorD vec( nvar ); for (Int_t ivar=0; ivar& events, Int_t maxCls ) { // compute square-root matrices for signal and background // delete old matrices if any for (std::vector::iterator it = fDecorrMatrices.begin(); it != fDecorrMatrices.end(); it++) if (0 != (*it) ) { delete (*it); *it=0; } // if more than one classes, then produce one matrix for all events as well (beside the matrices for each class) const UInt_t matNum = (maxCls<=1)?maxCls:maxCls+1; fDecorrMatrices.resize( matNum, (TMatrixD*) 0 ); std::vector* covMat = gTools().CalcCovarianceMatrices( events, maxCls, this ); for (UInt_t cls=0; clsat(cls) ); if ( sqrMat==0 ) Log() << kFATAL << " Zero pointer returned for SQR matrix" << Endl; fDecorrMatrices[cls] = sqrMat; delete (*covMat)[cls]; } delete covMat; } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::WriteTransformationToStream( std::ostream& o ) const { // write the decorrelation matrix to the stream Int_t cls = 0; Int_t dp = o.precision(); for (std::vector::const_iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) { o << "# correlation matrix " << std::endl; TMatrixD* mat = (*itm); o << cls << " " << mat->GetNrows() << " x " << mat->GetNcols() << std::endl; for (Int_t row = 0; rowGetNrows(); row++) { for (Int_t col = 0; colGetNcols(); col++) { o << std::setprecision(12) << std::setw(20) << (*mat)[row][col] << " "; } o << std::endl; } cls++; } o << "##" << std::endl; o << std::setprecision(dp); } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::AttachXMLTo(void* parent) { // node attachment to parent void* trf = gTools().AddChild(parent, "Transform"); gTools().AddAttr(trf,"Name", "Decorrelation"); VariableTransformBase::AttachXMLTo( trf ); for (std::vector::const_iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) { TMatrixD* mat = (*itm); /*void* decmat = gTools().xmlengine().NewChild(trf, 0, "Matrix"); gTools().xmlengine().NewAttr(decmat,0,"Rows", gTools().StringFromInt(mat->GetNrows()) ); gTools().xmlengine().NewAttr(decmat,0,"Columns", gTools().StringFromInt(mat->GetNcols()) ); std::stringstream s; for (Int_t row = 0; rowGetNrows(); row++) { for (Int_t col = 0; colGetNcols(); col++) { s << (*mat)[row][col] << " "; } } gTools().xmlengine().AddRawLine( decmat, s.str().c_str() );*/ gTools().WriteTMatrixDToXML(trf,"Matrix",mat); } } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::ReadFromXML( void* trfnode ) { // Read the transformation matrices from the xml node // first delete the old matrices for( std::vector::iterator it = fDecorrMatrices.begin(); it != fDecorrMatrices.end(); it++ ) if( (*it) != 0 ) delete (*it); fDecorrMatrices.clear(); Bool_t newFormat = kFALSE; void* inpnode = NULL; inpnode = gTools().GetChild(trfnode, "Selection"); // new xml format if( inpnode!=NULL ) newFormat = kTRUE; // new xml format void* ch = NULL; if( newFormat ){ // ------------- new format -------------------- // read input VariableTransformBase::ReadFromXML( inpnode ); ch = gTools().GetNextChild(inpnode); }else ch = gTools().GetChild(trfnode); // Read the transformation matrices from the xml node while(ch!=0) { Int_t nrows, ncols; gTools().ReadAttr(ch, "Rows", nrows); gTools().ReadAttr(ch, "Columns", ncols); TMatrixD* mat = new TMatrixD(nrows,ncols); const char* content = gTools().GetContent(ch); std::stringstream s(content); for (Int_t row = 0; row> (*mat)[row][col]; } } fDecorrMatrices.push_back(mat); ch = gTools().GetNextChild(ch); } SetCreated(); } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::ReadTransformationFromStream( std::istream& istr, const TString& classname ) { // Read the decorellation matrix from an input stream char buf[512]; istr.getline(buf,512); TString strvar, dummy; Int_t nrows(0), ncols(0); UInt_t classIdx=0; while (!(buf[0]=='#'&& buf[1]=='#')) { // if line starts with ## return char* p = buf; while (*p==' ' || *p=='\t') p++; // 'remove' leading whitespace if (*p=='#' || *p=='\0') { istr.getline(buf,512); continue; // if comment or empty line, read the next line } std::stringstream sstr(buf); sstr >> strvar; if (strvar=="signal" || strvar=="background") { UInt_t cls=0; if(strvar=="background") cls=1; if(strvar==classname) classIdx = cls; // coverity[tainted_data_argument] sstr >> nrows >> dummy >> ncols; if (fDecorrMatrices.size() <= cls ) fDecorrMatrices.resize(cls+1); if (fDecorrMatrices.at(cls) != 0) delete fDecorrMatrices.at(cls); TMatrixD* mat = fDecorrMatrices.at(cls) = new TMatrixD(nrows,ncols); // now read all matrix parameters for (Int_t row = 0; rowGetNrows(); row++) { for (Int_t col = 0; colGetNcols(); col++) { istr >> (*mat)[row][col]; } } } // done reading a matrix istr.getline(buf,512); // reading the next line } fDecorrMatrices.push_back( new TMatrixD(*fDecorrMatrices[classIdx]) ); SetCreated(); } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::PrintTransformation( std::ostream& ) { // prints the transformation matrix Int_t cls = 0; for (std::vector::iterator itm = fDecorrMatrices.begin(); itm != fDecorrMatrices.end(); itm++) { Log() << kINFO << "Transformation matrix "<< cls <<":" << Endl; (*itm)->Print(); } } //_______________________________________________________________________ void TMVA::VariableDecorrTransform::MakeFunction( std::ostream& fout, const TString& fcncName, Int_t part, UInt_t trCounter, Int_t ) { // creates C++ code fragment of the decorrelation transform for inclusion in standalone C++ class Int_t dp = fout.precision(); UInt_t numC = fDecorrMatrices.size(); // creates a decorrelation function if (part==1) { TMatrixD* mat = fDecorrMatrices.at(0); // ToDo check if all Decorr matrices have identical dimensions fout << std::endl; fout << " double fDecTF_"<GetNrows()<<"]["<GetNcols()<<"];" << std::endl; } if (part==2) { fout << std::endl; fout << "//_______________________________________________________________________" << std::endl; fout << "inline void " << fcncName << "::InitTransform_"<GetNrows(); i++) { for (int j=0; jGetNcols(); j++) { fout << " fDecTF_"<& iv, int cls) const" << std::endl; fout << "{" << std::endl; fout << " // Decorrelation transformation" << std::endl; fout << " if (cls < 0 || cls > "< 1 ) cls = "< tv;" << std::endl; fout << " for (int i=0; i<"<GetNrows()<<";i++) {" << std::endl; fout << " double v = 0;" << std::endl; fout << " for (int j=0; j<"<GetNcols()<<"; j++)" << std::endl; fout << " v += iv[indicesGet.at(j)] * fDecTF_"<GetNrows()<<";i++) iv[indicesPut.at(i)] = tv[i];" << std::endl; fout << "}" << std::endl; } fout << std::setprecision(dp); }