Revision e60bc961b69056a4925f129d0a2042471f999042 authored by Rene Brun on 19 September 2006, 14:37:13 UTC, committed by Rene Brun on 19 September 2006, 14:37:13 UTC
some changes in the class TGeoPNEntry (needed for alignment purposes):

1. Constructor of TGeoPNEntry performs a check upon definition of a symbolic link to a physical node. The check is done redundantly also upon creation of a physical node starting from a symbolic link to prevent mis-usage of these objects in-between geometries.
2. Allows storage of an additional user-defined TGeoHMatrix. The matrix should be created by the user but
once TGeoPNEntry::SetMatrix() is called becomes owned by TGeoManager.


git-svn-id: http://root.cern.ch/svn/root/trunk@16298 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent cc15e88
Raw File
Tools.cxx
/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TMVA::Tools                                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Xavier Prudent  <prudent@lapp.in2p3.fr>  - LAPP, France                   *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-KP Heidelberg, Germany     *
 *      Kai Voss        <Kai.Voss@cern.ch>       - U. of Victoria, Canada         *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland,                                                        *
 *      U. of Victoria, Canada,                                                   *
 *      MPI-KP 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.txt)                                      *
 *                                                                                *
 * File and Version Information:                                                  *
 * $Id: Tools.cxx,v 1.5 2006/05/23 09:53:11 stelzer Exp $
 **********************************************************************************/
#include <algorithm>

#include "TMVA/Tools.h"
#include "Riostream.h"
#include "TObjString.h"
#include "TTree.h"
#include "TLeaf.h"
#include "TH1.h"
#include "TSpline.h"
#include "TVector.h"
#include "TMatrixD.h"
#include "TVectorD.h"

namespace TMVA {
   const char* Tools_NAME_ = "TMVA_Tools"; // name to locate output
}

Double_t TMVA::Tools::NormVariable( Double_t x, Double_t xmin, Double_t xmax )
{
   // normalise to output range: [-1, 1]
   return 2*(x - xmin)/(xmax - xmin) - 1.0;
}

void TMVA::Tools::ComputeStat( TTree* theTree, TString theVarName,
                               Double_t& meanS, Double_t& meanB,
                               Double_t& rmsS,  Double_t& rmsB,
                               Double_t& xmin,  Double_t& xmax,
                               Bool_t    norm )
{
   // compute basic statistics quantities for variable in input tree

   // sanity check
   if (0 == theTree) {
      cout << "---" << TMVA::Tools_NAME_ << ": Error in TMVA::Tools::ComputeStat:"
           << " tree is zero pointer ==> exit(1)" << endl;
      exit(1);
   }

   // does variable exist in tree?
   if (0 == theTree->FindBranch( theVarName )) {
      cout << "---" << TMVA::Tools_NAME_ << ": Error in TMVA::Tools::ComputeStat: variable: "
           << theVarName << " is not member of tree ==> exit(1)" << endl;
      exit(1);
   }

   Long64_t entries = theTree->GetEntries();

   // first fill signal and background in arrays before analysis
   Double_t* varVecS  = new Double_t[entries];
   Double_t* varVecB  = new Double_t[entries];
   xmin               = +1e20;
   xmax               = -1e20;
   Long64_t nEventsS  = -1;
   Long64_t nEventsB  = -1;
   Double_t xmin_ = 0, xmax_ = 0;

   if (norm) {
      xmin_ = theTree->GetMinimum( theVarName );
      xmax_ = theTree->GetMaximum( theVarName );
   }

   for (Int_t ievt=0; ievt<entries; ievt++) {

      Double_t theVar = TMVA::Tools::GetValue( theTree, ievt, theVarName );
      if (norm) theVar = __N__( theVar, xmin_, xmax_ );

      if ((Int_t)TMVA::Tools::GetValue( theTree, ievt, "type" ) == 1) // this is signal
         varVecS[++nEventsS] = theVar;
      else  // this is background
         varVecB[++nEventsB] = theVar;

      if (theVar > xmax) xmax = theVar;
      if (theVar < xmin) xmin = theVar;
   }
   ++nEventsS;
   ++nEventsB;

   // basic statistics
   meanS = TMath::Mean( nEventsS, varVecS );
   meanB = TMath::Mean( nEventsB, varVecB );
   rmsS  = TMath::RMS ( nEventsS, varVecS );
   rmsB  = TMath::RMS ( nEventsB, varVecB );

   delete [] varVecS;
   delete [] varVecB;
}

void TMVA::Tools::ComputeStat( const std::vector<TMVA::Event*> eventCollection, Int_t ivar,
                               Double_t& meanS, Double_t& meanB,
                               Double_t& rmsS,  Double_t& rmsB,
                               Double_t& xmin,  Double_t& xmax,
                               Bool_t    norm )
{
   // compute basic statistics quantities for variable (ivar) in event vector

   // does variable exist?
   if (ivar > eventCollection[0]->GetEventSize()){
      cout << "---" << TMVA::Tools_NAME_ << ": Error in TMVA::Tools::ComputeStat: variable: "
           << ivar << " is too big ==> exit(1)" << endl;
      exit(1);
   }

   Int_t entries = eventCollection.size();
   // first fill signal and background in arrays before analysis
   Double_t* varVecS  = new Double_t[entries];
   Double_t* varVecB  = new Double_t[entries];
   xmin               = +1e20;
   xmax               = -1e20;
   Long64_t nEventsS  = -1;
   Long64_t nEventsB  = -1;
   Double_t xmin_ = 0, xmax_ = 0;

   std::vector<Double_t> content;
   if (norm) {
      for (int ie=0; ie<entries; ie++)content.push_back(eventCollection[ie]->GetData(ivar));
      xmax_ = *(std::max_element(content.begin(), content.end()));
      xmin_ = *(std::min_element(content.begin(), content.end()));
   }

   for (Int_t ievt=0; ievt<entries; ievt++) {
      if (norm) content[ievt] = __N__( content[ievt], xmin_, xmax_ );

      if (eventCollection[ievt]->GetType() == 1) // this is signal
         varVecS[++nEventsS] = eventCollection[ievt]->GetData(ivar);
      else  // this is background
         varVecB[++nEventsB] = eventCollection[ievt]->GetData(ivar);

      if (eventCollection[ievt]->GetData(ivar) > xmax) xmax = eventCollection[ievt]->GetData(ivar);
      if (eventCollection[ievt]->GetData(ivar) < xmin) xmin = eventCollection[ievt]->GetData(ivar);
   }
   ++nEventsS;
   ++nEventsB;

   // basic statistics
   meanS = TMath::Mean( nEventsS, varVecS );
   meanB = TMath::Mean( nEventsB, varVecB );
   rmsS  = TMath::RMS ( nEventsS, varVecS );
   rmsB  = TMath::RMS ( nEventsB, varVecB );

   delete [] varVecS;
   delete [] varVecB;
}

void TMVA::Tools::GetCovarianceMatrix( TTree* theTree, TMatrixDBase *theMatrix,
                                       vector<TString>* theVars, Int_t theType, Bool_t norm )
{
   // computes variance-covariance matrix for variables "theVars" in tree;
   // "theType" defines the required event "type" 
   // ("type" variable must be present in tree)

   Long64_t      entries = theTree->GetEntries();
   const Int_t   nvar    = theVars->size();
   Int_t         ievt, ivar, jvar;
   TVectorD      vec(nvar);
   TMatrixD      mat2(nvar, nvar);
   TVectorD      xmin(nvar), xmax(nvar);

   // init matrices
   for (ivar=0; ivar<nvar; ivar++) {
      vec(ivar) = 0;
      if (norm) {
         xmin(ivar) = theTree->GetMinimum( (*theVars)[ivar] );
         xmax(ivar) = theTree->GetMaximum( (*theVars)[ivar] );
      }
      for (jvar=0; jvar<nvar; jvar++) {
         mat2(ivar, jvar) = 0;
      }
   }

   // event loop
   Int_t ic = 0;
   for (ievt=0; ievt<entries; ievt++) {

      if (Int_t(TMVA::Tools::GetValue( theTree, ievt, "type" )) == theType) {

         ic++; // count used events
         for (ivar=0; ivar<nvar; ivar++) {
            Double_t xi = TMVA::Tools::GetValue( theTree, ievt, (*theVars)[ivar] );
            if (norm) xi = __N__( xi, xmin(ivar), xmax(ivar) );
            vec(ivar) += xi;
            mat2(ivar, ivar) += (xi*xi);

            for (jvar=ivar+1; jvar<nvar; jvar++) {
               Double_t xj = TMVA::Tools::GetValue( theTree, ievt, (*theVars)[jvar] );
               if (norm) xj = __N__( xj, xmin(jvar), xmax(jvar) );
               mat2(ivar, jvar) += (xi*xj);
               mat2(jvar, ivar) = mat2(ivar, jvar); // symmetric matrix
            }
         }
      }
   }

   // variance-covariance
   Double_t n = (Double_t)ic;
   for (ivar=0; ivar<nvar; ivar++)
      for (jvar=0; jvar<nvar; jvar++)
         (*theMatrix)(ivar, jvar) = mat2(ivar, jvar)/n - vec(ivar)*vec(jvar)/pow(n,2);
}

void TMVA::Tools::GetCorrelationMatrix( TTree* theTree, TMatrixDBase *theMatrix,
                                        vector<TString>* theVars, Int_t theType )
{
   // computes correlation matrix for variables "theVars" in tree;
   // "theType" defines the required event "type" 
   // ("type" variable must be present in tree)

   // first compute variance-covariance
   TMVA::Tools::GetCovarianceMatrix( theTree, theMatrix, theVars, theType, kTRUE );

   // now the correlation
   const Int_t nvar = theVars->size();

   for (Int_t ivar=0; ivar<nvar; ivar++) {
      for (Int_t jvar=0; jvar<nvar; jvar++) {
         if (ivar != jvar) {
            Double_t d = (*theMatrix)(ivar, ivar)*(*theMatrix)(jvar, jvar);
            if (d > 0) (*theMatrix)(ivar, jvar) /= sqrt(d);
            else {
               cout << "---" << TMVA::Tools_NAME_ << ": Warning: zero variances for variables "
                    << "(" << (*theVars)[ivar] << ", " << (*theVars)[jvar] << endl;
               (*theMatrix)(ivar, jvar) = 0;
            }
         }
      }
   }

   for (Int_t ivar=0; ivar<nvar; ivar++) (*theMatrix)(ivar, ivar) = 1.0;
}

void TMVA::Tools::GetSQRootMatrix( TMatrixDSym* symMat, TMatrixD* sqrtMat )
{
   // square-root of symmetric matrix
   // of course the resulting sqrtMat is also symmetric, but it's easier to
   // treat it as a general matrix
   Int_t n = symMat->GetNrows();

   // sanity check
   if (NULL != sqrtMat)
      if (sqrtMat->GetNrows() != n || sqrtMat->GetNcols() != n) {
         cout << "--- " << TMVA::Tools_NAME_ << ": mismatch in matrices ==> abort: "
              << n << " " << sqrtMat->GetNrows() << " " << sqrtMat->GetNcols() << endl;
      }

   // compute eigenvectors
   TMatrixDSymEigen* eigen = new TMatrixDSymEigen( *symMat );

   // D = ST C S
   TMatrixD* si = new TMatrixD( eigen->GetEigenVectors() );
   TMatrixD* s  = new TMatrixD( *si ); // copy
   si->Transpose( *si ); // invert (= transpose)

   // diagonal matrices
   TMatrixD* d = new TMatrixD( n, n);
   d->Mult( (*si), (*symMat) ); (*d) *= (*s);

   // sanity check: matrix must be diagonal and positive definit
   Int_t i, j;
   Double_t epsilon = 1.0e-13;
   for (i=0; i<n; i++) {
      for (j=0; j<n; j++) {
         if ((i != j && TMath::Abs((*d)(i,j)) > epsilon) ||
             (i == j && (*d)(i,i) < 0)) {
            cout << "--- " << TMVA::Tools_NAME_
                 << ": Error in matrix diagonalization; printing S and B ==> abort" << endl;
            d->Print();
            exit(1);
         }
      }
   }

   // make exactly diagonal
   for (i=0; i<n; i++) for (j=0; j<n; j++) if (j != i) (*d)(i,j) = 0;

   // compute the square-root C' of covariance matrix: C = C'*C'
   for (i=0; i<n; i++) (*d)(i,i) = sqrt((*d)(i,i));
   if (NULL == sqrtMat) sqrtMat = new TMatrixD( n, n );
   sqrtMat->Mult( (*s), (*d) );
   (*sqrtMat) *= (*si);

   // invert square-root matrices
   sqrtMat->Invert();

   delete eigen;
   delete s;
   delete si;
   delete d;
}

TH1* TMVA::Tools::projNormTH1F( TTree* theTree, TString theVarName,
                                TString name, Int_t nbins,
                                Double_t xmin, Double_t xmax, TString cut )
{
   // projects variable from tree into normalised histogram
   TH1* hist = new TH1F( name, name, nbins, xmin, xmax );
   hist->Sumw2(); // enable quadratic errors
   theTree->Project( name, theVarName, cut );
   NormHist( hist );
   return hist;
}

Double_t TMVA::Tools::NormHist( TH1* theHist, Double_t norm )
{
   // normalises histogram
   if (NULL == theHist) {
      cout << "--- " << TMVA::Tools_NAME_ << "::NormHist: null TH1 pointer ==> abort" << endl;
      exit(1);
   }
   TAxis* tx  = theHist->GetXaxis();
   Double_t w = ((theHist->GetEntries() > 0 ? theHist->GetEntries() : 1)
                 * (tx->GetXmax() - tx->GetXmin())/tx->GetNbins());
   theHist->Scale( (w > 0) ? norm/w : norm );
   return w;
}

TList* TMVA::Tools::ParseFormatLine( TString formatString )
{
   // Parse the string and cut into labels separated by ":"
   TList*   labelList = new TList();
   TString* label     = new TString();
   Int_t    nLabels   = 0;

   const Int_t n = (Int_t)formatString.Length();
   TObjString** label_obj = new TObjString*[n];  // array of labels

   for (Int_t i=0; i<n; i++) {
      label->Append(formatString(i));
      if (formatString(i)==':') {
         label->Chop();
         label_obj[nLabels] = new TObjString(label->Data());
         labelList->Add(label_obj[nLabels]);
         label->Resize(0);
         nLabels++;
      }
      if (i == n-1) {
         label_obj[nLabels] = new TObjString(label->Data());
         labelList->Add(label_obj[nLabels]);
         label->Resize(0);
         nLabels++;
      }
   }
   delete label;
   delete [] label_obj;
   return labelList;
}

Double_t TMVA::Tools::GetValue( TTree *theTree, Int_t entry, TString varname )
{
   // returns tree value for variable "varname" and event "entry" 
   // branches are safely set to static variables
 
   // branch addresses
   static Float_t  f = 0;
   static Double_t d = 0;
   static Int_t    i = 0;

   // sanity check
   if (0 == theTree) {
      cout << "---" << TMVA::Tools_NAME_ << ": fatal error: zero tree pointer ==> exit(1) " << endl;
      exit(1);
   }

   // return value
   Double_t retval = -1;

   TBranch* branch = theTree->GetBranch( varname );
   if (0 != branch) {

      TLeaf *leaf = branch->GetLeaf(branch->GetName());

      if (((TString)leaf->GetTypeName()).Contains("Int_t")) {     
         branch->SetAddress(&i);
         branch->GetEntry(entry);
         retval = (Double_t)i;
      }
      else if (((TString)leaf->GetTypeName()).Contains("Float_t")) {
         branch->SetAddress(&f);
         branch->GetEntry(entry);
         retval = (Double_t)f;
      }
      else if (((TString)leaf->GetTypeName()).Contains("Double_t")) {
         branch->SetAddress(&d);
         branch->GetEntry(entry);
         retval = (Double_t)d;
      }

   } // end of found right branch
   else {
      cout << "---" << TMVA::Tools_NAME_ << ": branch " << varname
           << " does not exist in tree" << endl;
      cout << "---" << TMVA::Tools_NAME_ << ": candidates are:" << endl;
      TIter next_branch1( theTree->GetListOfBranches() );
      while (TBranch *branch = (TBranch*)next_branch1())
         cout << "---\t" << branch->GetName() << endl;
   }

   return retval;
}

Bool_t TMVA::Tools::CheckSplines( TH1* theHist, TSpline* theSpline )
{
   // check quality of splining by comparing splines and histograms in each bin
   const Double_t sanityCrit = 0.01; // relative deviation

   Bool_t retval = kTRUE;
   for (Int_t ibin=1; ibin<=theHist->GetNbinsX(); ibin++) {
      Double_t x  = theHist->GetBinCenter( ibin );
      Double_t yh = theHist->GetBinContent( ibin ); // the histogram output
      Double_t ys = theSpline->Eval( x );           // the spline output

      if (ys + yh > 0) {
         Double_t dev = 0.5*(ys - yh)/(ys + yh);
         if (TMath::Abs(dev) > sanityCrit) {
            cout << "---" << TMVA::Tools_NAME_ << ": Warning: Spline failed sanity criterion; "
                 << " relative deviation from histogram: " << dev
                 << " in (bin, value): (" << ibin << ", " << x << ")" << endl;
            retval = kFALSE;
         }
      }
   }

   return retval;
}

vector<Double_t> TMVA::Tools::MVADiff(vector<Double_t> & a, vector<Double_t> & b)
{
   // computes difference between two vectors
   if (a.size() != b.size()) {
      throw;
   }
   vector<Double_t> result(a.size());
   for (UInt_t i=0; i<a.size();i++) result[i]=a[i]-b[i];
   return result;
}

void TMVA::Tools::Scale( vector<Double_t> &v, Double_t f )
{
   // scales double vector
   for (UInt_t i=0; i<v.size();i++) v[i]*=f;
}

void TMVA::Tools::Scale( vector<Float_t> &v, Float_t f )
{
   // scales float vector
   for (UInt_t i=0; i<v.size();i++) v[i]*=f;
}

void TMVA::Tools::UsefulSortAscending(vector< vector<Double_t> > &v)
{
   // sort 2D vector
   UInt_t nArrays=v.size();
   Double_t temp;
   if (nArrays > 0) {
      UInt_t sizeofarray=v[0].size();
      for (UInt_t i=0; i<sizeofarray; i++) {
         for (UInt_t j=sizeofarray-1; j>i; j--) {
            if (v[0][j-1] > v[0][j]) {
               for (UInt_t k=0; k< nArrays; k++) {
                  temp = v[k][j-1];v[k][j-1] = v[k][j]; v[k][j] = temp;
               }
            }
         }
      }
   }
}

void TMVA::Tools::UsefulSortDescending(vector< vector<Double_t> > &v, vector<TString>* vs)
{
   // sort 2D vector AND (in parallel) TString vector
   UInt_t nArrays=v.size();
   Double_t temp;
   if (nArrays > 0) {
      UInt_t sizeofarray=v[0].size();
      for (UInt_t i=0; i<sizeofarray; i++) {
         for (UInt_t j=sizeofarray-1; j>i; j--) {
            if (v[0][j-1] < v[0][j]) {
               for (UInt_t k=0; k< nArrays; k++) {
                  temp = v[k][j-1]; v[k][j-1] = v[k][j]; v[k][j] = temp;
               }
               if (NULL != vs) {
                  TString temps = (*vs)[j-1]; (*vs)[j-1] = (*vs)[j]; (*vs)[j] = temps;
               }
            }
         }
      }
   }
}

void TMVA::Tools::UsefulSortDescending(vector<Double_t> &v)
{
   // sort vector
   vector< vector<Double_t> > vtemp;
   vtemp.push_back(v);
   UsefulSortDescending(vtemp);
   v = vtemp[0];
}

void TMVA::Tools::UsefulSortAscending(vector<Double_t>  &v)
{
   // sort vector
   vector<vector<Double_t> > vtemp;
   vtemp.push_back(v);
   UsefulSortAscending(vtemp);
   v=vtemp[0];
}

int TMVA::Tools::GetIndexMaxElement(vector<Double_t>  &v)
{
   // find index of maximum entry in vector
   if (v.size()==0) return -1;

   Int_t pos=0; Double_t mx=v[0];
   for (UInt_t i=0; i<v.size(); i++){
      if (v[i] > mx){
         mx=v[i];
         pos=i;
      }
   }
   return pos;
}

int TMVA::Tools::GetIndexMinElement(vector<Double_t>  &v)
{
   // find index of minimum entry in vector
   if (v.size()==0) return -1;

   Int_t pos=0; Double_t mn=v[0];
   for (UInt_t i=0; i<v.size(); i++){
      if (v[i] < mn){
         mn=v[i];
         pos=i;
      }
   }
   return pos;
}

back to top