PDEFoam.cxx

Go to the documentation of this file.
00001 
00002 /**********************************************************************************
00003  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
00004  * Package: TMVA                                                                  *
00005  * Classes: PDEFoam                                                               *
00006  * Web    : http://tmva.sourceforge.net                                           *
00007  *                                                                                *
00008  * Description:                                                                   *
00009  *      Implementations                                                           *
00010  *                                                                                *
00011  * Authors (alphabetical):                                                        *
00012  *      Tancredi Carli   - CERN, Switzerland                                      *
00013  *      Dominik Dannheim - CERN, Switzerland                                      *
00014  *      S. Jadach        - Institute of Nuclear Physics, Cracow, Poland           *
00015  *      Alexander Voigt  - CERN, Switzerland                                      *
00016  *      Peter Speckmayer - CERN, Switzerland                                      *
00017  *                                                                                *
00018  * Copyright (c) 2008:                                                            *
00019  *      CERN, Switzerland                                                         *
00020  *      MPI-K Heidelberg, Germany                                                 *
00021  *                                                                                *
00022  * Redistribution and use in source and binary forms, with or without             *
00023  * modification, are permitted according to the terms listed in LICENSE           *
00024  * (http://tmva.sourceforge.net/LICENSE)                                          *
00025  **********************************************************************************/
00026 
00027 //_____________________________________________________________________
00028 //
00029 // Implementation of PDEFoam
00030 //
00031 // The PDEFoam method is an
00032 // extension of the PDERS method, which uses self-adapting binning to
00033 // divide the multi-dimensional phase space in a finite number of
00034 // hyper-rectangles (boxes).
00035 //
00036 // For a given number of boxes, the binning algorithm adjusts the size
00037 // and position of the boxes inside the multidimensional phase space,
00038 // minimizing the variance of the signal and background densities inside
00039 // the boxes. The binned density information is stored in binary trees,
00040 // allowing for a very fast and memory-efficient classification of
00041 // events.
00042 //
00043 // The implementation of the PDEFoam is based on the monte-carlo
00044 // integration package PDEFoam included in the analysis package ROOT.
00045 //_____________________________________________________________________
00046 
00047 
00048 #include <iostream>
00049 #include <iomanip>
00050 #include <fstream>
00051 #include <sstream>
00052 #include <cassert>
00053 #include <climits>
00054 
00055 #include "TMVA/Event.h"
00056 #include "TMVA/Tools.h"
00057 #include "TMVA/PDEFoam.h"
00058 #include "TMVA/MsgLogger.h"
00059 #include "TMVA/Types.h"
00060 
00061 #ifndef ROOT_TStyle
00062 #include "TStyle.h"
00063 #endif
00064 #ifndef ROOT_TObject
00065 #include "TObject.h"
00066 #endif
00067 #ifndef ROOT_TH1D
00068 #include "TH1D.h"
00069 #endif
00070 #ifndef ROOT_TMath
00071 #include "TMath.h"
00072 #endif
00073 #ifndef ROOT_TVectorT
00074 #include "TVectorT.h"
00075 #endif
00076 #ifndef ROOT_TRandom3
00077 #include "TRandom3.h"
00078 #endif
00079 #ifndef ROOT_TColor
00080 #include "TColor.h"
00081 #endif
00082 
00083 ClassImp(TMVA::PDEFoam)
00084 
00085 static const Float_t gHigh= FLT_MAX;
00086 static const Float_t gVlow=-FLT_MAX;
00087 
00088 using namespace std;
00089 
00090 //_____________________________________________________________________
00091 TMVA::PDEFoam::PDEFoam() :
00092    fName("PDEFoam"),
00093    fDim(0),
00094    fNCells(0),
00095    fNBin(5),
00096    fNSampl(2000),
00097    fEvPerBin(0),
00098    fMaskDiv(0),
00099    fInhiDiv(0),
00100    fNoAct(1),
00101    fLastCe(-1),
00102    fCells(0),
00103    fHistEdg(0),
00104    fRvec(0),
00105    fPseRan(new TRandom3(4356)),
00106    fAlpha(0),
00107    fFoamType(kDiscr),
00108    fXmin(0),
00109    fXmax(0),
00110    fNElements(0),
00111    fNmin(100),
00112    fMaxDepth(0),
00113    fVolFrac(30.0),
00114    fFillFoamWithOrigWeights(kFALSE),
00115    fDTSeparation(kFoam),
00116    fPeekMax(kTRUE),
00117    fDistr(new PDEFoamDistr()),
00118    fTimer(new Timer(0, "PDEFoam", kTRUE)),
00119    fVariableNames(new TObjArray()),
00120    fLogger(new MsgLogger("PDEFoam"))
00121 {
00122    // Default constructor for streamer, user should not use it.
00123 }
00124 
00125 //_____________________________________________________________________
00126 TMVA::PDEFoam::PDEFoam(const TString& Name) :
00127    fName(Name),
00128    fDim(0),
00129    fNCells(1000),
00130    fNBin(5),
00131    fNSampl(2000),
00132    fEvPerBin(0),
00133    fMaskDiv(0),
00134    fInhiDiv(0),
00135    fNoAct(1),
00136    fLastCe(-1),
00137    fCells(0),
00138    fHistEdg(0),
00139    fRvec(0),
00140    fPseRan(new TRandom3(4356)),
00141    fAlpha(0),
00142    fFoamType(kDiscr),
00143    fXmin(0),
00144    fXmax(0),
00145    fNElements(0),
00146    fNmin(100),
00147    fMaxDepth(0),
00148    fVolFrac(30.0),
00149    fFillFoamWithOrigWeights(kFALSE),
00150    fDTSeparation(kFoam),
00151    fPeekMax(kTRUE),
00152    fDistr(new PDEFoamDistr()),
00153    fTimer(new Timer(1, "PDEFoam", kTRUE)),
00154    fVariableNames(new TObjArray()),
00155    fLogger(new MsgLogger("PDEFoam"))
00156 {
00157    // User constructor, to be employed by the user
00158    if(strlen(Name) > 128)
00159       Log() << kFATAL << "Name too long " << Name.Data() << Endl;
00160 }
00161 
00162 //_____________________________________________________________________
00163 TMVA::PDEFoam::~PDEFoam()
00164 {
00165    // Default destructor
00166 
00167    delete fVariableNames;
00168    delete fTimer;
00169    if (fDistr)  delete fDistr;
00170    if (fPseRan) delete fPseRan;
00171    if (fXmin) delete [] fXmin;  fXmin=0;
00172    if (fXmax) delete [] fXmax;  fXmax=0;
00173 
00174    if(fCells!= 0) {
00175       for(Int_t i=0; i<fNCells; i++) delete fCells[i]; // PDEFoamCell*[]
00176       delete [] fCells;
00177    }
00178    delete [] fRvec;    //double[]
00179    delete [] fAlpha;   //double[]
00180    delete [] fMaskDiv; //int[]
00181    delete [] fInhiDiv; //int[]
00182 
00183    delete fLogger;
00184 }
00185 
00186 //_____________________________________________________________________
00187 TMVA::PDEFoam::PDEFoam(const PDEFoam &From) :
00188    TObject(From)
00189    , fDim(0)
00190    , fNCells(0)
00191    , fNBin(0)
00192    , fNSampl(0)
00193    , fEvPerBin(0)
00194    , fMaskDiv(0)
00195    , fInhiDiv(0)
00196    , fNoAct(0)
00197    , fLastCe(0)
00198    , fCells(0)
00199    , fHistEdg(0)
00200    , fRvec(0)
00201    , fPseRan(0)
00202    , fAlpha(0)
00203    , fFoamType(kSeparate)
00204    , fXmin(0)
00205    , fXmax(0)
00206    , fNElements(0)
00207    , fNmin(0)
00208    , fMaxDepth(0)
00209    , fVolFrac(30.0)
00210    , fFillFoamWithOrigWeights(kFALSE)
00211    , fDTSeparation(kFoam)
00212    , fPeekMax(kTRUE)
00213    , fDistr(0)
00214    , fTimer(0)
00215    , fVariableNames(0)
00216    , fLogger(new MsgLogger("PDEFoam"))
00217 {
00218    // Copy Constructor  NOT IMPLEMENTED (NEVER USED)
00219    Log() << kFATAL << "COPY CONSTRUCTOR NOT IMPLEMENTED" << Endl;
00220 }
00221 
00222 //_____________________________________________________________________
00223 void TMVA::PDEFoam::SetDim(Int_t kDim)
00224 {
00225    // Sets dimension of cubical space
00226    if (kDim < 1)
00227       Log() << kFATAL << "<SetDim>: Dimension is zero or negative!" << Endl;
00228 
00229    fDim = kDim;
00230    if (fXmin) delete [] fXmin;
00231    if (fXmax) delete [] fXmax;
00232    fXmin = new Double_t[GetTotDim()];
00233    fXmax = new Double_t[GetTotDim()];
00234 }
00235 
00236 //_____________________________________________________________________
00237 void TMVA::PDEFoam::SetXmin(Int_t idim, Double_t wmin)
00238 {
00239    // set lower foam bound in dimension idim
00240    if (idim<0 || idim>=GetTotDim())
00241       Log() << kFATAL << "<SetXmin>: Dimension out of bounds!" << Endl;
00242 
00243    fXmin[idim]=wmin;
00244 }
00245 
00246 //_____________________________________________________________________
00247 void TMVA::PDEFoam::SetXmax(Int_t idim, Double_t wmax)
00248 {
00249    // set upper foam bound in dimension idim
00250    if (idim<0 || idim>=GetTotDim())
00251       Log() << kFATAL << "<SetXmax>: Dimension out of bounds!" << Endl;
00252 
00253    fXmax[idim]=wmax;
00254 }
00255 
00256 //_____________________________________________________________________
00257 void TMVA::PDEFoam::Create()
00258 {
00259    // Basic initialization of FOAM invoked by the user.
00260    // IMPORTANT: Random number generator and the distribution object has to be
00261    // provided using SetPseRan and SetRho prior to invoking this initializator!
00262    //
00263    // After the foam is grown, space for 2 variables is reserved in
00264    // every cell.  They are used for filling the foam cells.
00265 
00266    Bool_t addStatus = TH1::AddDirectoryStatus();
00267    TH1::AddDirectory(kFALSE);
00268 
00269    if(fPseRan==0) Log() << kFATAL << "Random number generator not set" << Endl;
00270    if(fDistr==0)  Log() << kFATAL << "Distribution function not set" << Endl;
00271    if(fDim==0)    Log() << kFATAL << "Zero dimension not allowed" << Endl;
00272 
00273    /////////////////////////////////////////////////////////////////////////
00274    //                   ALLOCATE SMALL LISTS                              //
00275    //  it is done globally, not for each cell, to save on allocation time //
00276    /////////////////////////////////////////////////////////////////////////
00277    fRvec = new Double_t[fDim];   // Vector of random numbers
00278    if(fRvec==0)  Log() << kFATAL << "Cannot initialize buffer fRvec" << Endl;
00279 
00280    if(fDim>0){
00281       fAlpha = new Double_t[fDim];    // sum<1 for internal parametrization of the simplex
00282       if(fAlpha==0)  Log() << kFATAL << "Cannot initialize buffer fAlpha" << Endl;
00283    }
00284 
00285    //====== List of directions inhibited for division
00286    if(fInhiDiv == 0){
00287       fInhiDiv = new Int_t[fDim];
00288       for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
00289    }
00290    //====== Dynamic mask used in Explore for edge determination
00291    if(fMaskDiv == 0){
00292       fMaskDiv = new Int_t[fDim];
00293       for(Int_t i=0; i<fDim; i++) fMaskDiv[i]=1;
00294    }
00295    //====== Initialize list of histograms
00296    fHistEdg = new TObjArray(fDim);           // Initialize list of histograms
00297    for(Int_t i=0; i<fDim; i++){
00298       TString hname, htitle;
00299       hname   = fName+TString("_HistEdge_");
00300       hname  += i;
00301       htitle  = TString("Edge Histogram No. ");
00302       htitle += i;
00303       (*fHistEdg)[i] = new TH1D(hname.Data(),htitle.Data(),fNBin,0.0, 1.0); // Initialize histogram for each edge
00304       ((TH1D*)(*fHistEdg)[i])->Sumw2();
00305    }
00306 
00307    // ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //
00308    //                     BUILD-UP of the FOAM                            //
00309    // ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //
00310 
00311    // Define and explore root cell(s)
00312    InitCells();
00313    Grow();
00314 
00315    TH1::AddDirectory(addStatus);
00316 
00317    // prepare PDEFoam for the filling with events
00318    SetNElements(2);     // init space for 2 variables on every cell
00319    ResetCellElements(); // reset the cell elements of all active cells
00320 } // Create
00321 
00322 //_____________________________________________________________________
00323 void TMVA::PDEFoam::InitCells()
00324 {
00325    // Internal subprogram used by Create.
00326    // It initializes "root part" of the FOAM of the tree of cells.
00327 
00328    fLastCe =-1;                             // Index of the last cell
00329    if(fCells!= 0) {
00330       for(Int_t i=0; i<fNCells; i++) delete fCells[i];
00331       delete [] fCells;
00332    }
00333    //
00334    fCells = new PDEFoamCell*[fNCells];
00335    for(Int_t i=0; i<fNCells; i++){
00336       fCells[i]= new PDEFoamCell(fDim); // Allocate BIG list of cells
00337       fCells[i]->SetSerial(i);
00338    }
00339    if(fCells==0) Log() << kFATAL << "Cannot initialize CELLS" << Endl;
00340 
00341    // create cell elemets
00342    if (GetNmin() > 0) {
00343       SetNElements(1); // to save the number of events in the cell
00344       ResetCellElements(true);
00345    }
00346 
00347    /////////////////////////////////////////////////////////////////////////////
00348    //              Single Root Hypercube                                      //
00349    /////////////////////////////////////////////////////////////////////////////
00350    CellFill(1,   0);  //  0-th cell ACTIVE
00351 
00352    // Exploration of the root cell(s)
00353    for(Long_t iCell=0; iCell<=fLastCe; iCell++){
00354       if (fDTSeparation != kFoam)
00355          DTExplore( fCells[iCell] );  // Exploration of root cell(s)
00356       else
00357          Explore( fCells[iCell] );    // Exploration of root cell(s)
00358    }
00359 }//InitCells
00360 
00361 //_____________________________________________________________________
00362 Int_t TMVA::PDEFoam::CellFill(Int_t Status, PDEFoamCell *parent)
00363 {
00364    // Internal subprogram used by Create.
00365    // It initializes content of the newly allocated active cell.
00366 
00367    PDEFoamCell *cell;
00368    if (fLastCe==fNCells){
00369       Log() << kFATAL << "Too many cells" << Endl;
00370    }
00371    fLastCe++;   // 0-th cell is the first
00372 
00373    cell = fCells[fLastCe];
00374 
00375    cell->Fill(Status, parent, 0, 0);
00376 
00377    cell->SetBest( -1);         // pointer for planning division of the cell
00378    cell->SetXdiv(0.5);         // factor for division
00379    Double_t xInt2,xDri2;
00380    if(parent!=0){
00381       xInt2  = 0.5*parent->GetIntg();
00382       xDri2  = 0.5*parent->GetDriv();
00383       cell->SetIntg(xInt2);
00384       cell->SetDriv(xDri2);
00385    }else{
00386       cell->SetIntg(0.0);
00387       cell->SetDriv(0.0);
00388    }
00389    return fLastCe;
00390 }
00391 
00392 //_____________________________________________________________________
00393 void TMVA::PDEFoam::Explore(PDEFoamCell *cell)
00394 {
00395    // Internal subprogram used by Create.
00396    // It explores newly defined cell with help of special short MC sampling.
00397    // As a result, estimates of kTRUE and drive volume is defined/determined
00398    // Average and dispersion of the weight distribution will is found along
00399    // each edge and the best edge (minimum dispersion, best maximum weight)
00400    // is memorized for future use.
00401    // The optimal division point for eventual future cell division is
00402    // determined/recorded. Recorded are also minimum and maximum weight etc.
00403    // The volume estimate in all (inactive) parent cells is updated.
00404    // Note that links to parents and initial volume = 1/2 parent has to be
00405    // already defined prior to calling this routine.
00406    //
00407    // If fNmin > 0 then the total number of (training) events found in
00408    // the cell during the exploration is stored in the cell.  This
00409    // information is used withing PeekMax() to avoid splitting cells
00410    // which contain less than fNmin events.
00411 
00412    Double_t wt, dx, xBest, yBest;
00413    Double_t intOld, driOld;
00414 
00415    Long_t iev;
00416    Double_t nevMC;
00417    Int_t i, j, k;
00418    Int_t nProj, kBest;
00419    Double_t ceSum[5], xproj;
00420 
00421    Double_t event_density = 0;
00422    Double_t totevents     = 0;
00423    Double_t toteventsOld  = 0;
00424 
00425    PDEFoamVect  cellSize(fDim);
00426    PDEFoamVect  cellPosi(fDim);
00427 
00428    cell->GetHcub(cellPosi,cellSize);
00429 
00430    PDEFoamCell  *parent;
00431 
00432    Double_t *xRand = new Double_t[fDim];
00433 
00434    Double_t *volPart=0;
00435 
00436    cell->CalcVolume();
00437    dx = cell->GetVolume();
00438    intOld = cell->GetIntg(); //memorize old values,
00439    driOld = cell->GetDriv(); //will be needed for correcting parent cells
00440    if (GetNmin() > 0)
00441       toteventsOld = GetBuildUpCellEvents(cell);
00442 
00443    /////////////////////////////////////////////////////
00444    //    Special Short MC sampling to probe cell      //
00445    /////////////////////////////////////////////////////
00446    ceSum[0]=0;
00447    ceSum[1]=0;
00448    ceSum[2]=0;
00449    ceSum[3]=gHigh;  //wtmin
00450    ceSum[4]=gVlow;  //wtmax
00451 
00452    for (i=0;i<fDim;i++) ((TH1D *)(*fHistEdg)[i])->Reset(); // Reset histograms
00453 
00454    Double_t nevEff=0.;
00455    // ||||||||||||||||||||||||||BEGIN MC LOOP|||||||||||||||||||||||||||||
00456    for (iev=0;iev<fNSampl;iev++){
00457       MakeAlpha();               // generate uniformly vector inside hypercube
00458 
00459       if (fDim>0) for (j=0; j<fDim; j++) xRand[j]= cellPosi[j] +fAlpha[j]*(cellSize[j]);
00460 
00461       wt         = dx*Eval(xRand, event_density);
00462       totevents += dx*event_density;
00463       
00464       nProj = 0;
00465       if (fDim>0) {
00466          for (k=0; k<fDim; k++) {
00467             xproj =fAlpha[k];
00468             ((TH1D *)(*fHistEdg)[nProj])->Fill(xproj,wt);
00469             nProj++;
00470          }
00471       }
00472 
00473       ceSum[0] += wt;    // sum of weights
00474       ceSum[1] += wt*wt; // sum of weights squared
00475       ceSum[2]++;        // sum of 1
00476       if (ceSum[3]>wt) ceSum[3]=wt;  // minimum weight;
00477       if (ceSum[4]<wt) ceSum[4]=wt;  // maximum weight
00478       // test MC loop exit condition
00479       nevEff = ceSum[0]*ceSum[0]/ceSum[1];
00480       if ( nevEff >= fNBin*fEvPerBin) break;
00481    }   // ||||||||||||||||||||||||||END MC LOOP|||||||||||||||||||||||||||||
00482    totevents /= fNSampl;
00483 
00484    // make shure that, if root cell is explored, more than zero
00485    // events were found.
00486    if (cell==fCells[0] && ceSum[0]<=0.0){
00487       if (ceSum[0]==0.0)
00488          Log() << kFATAL << "No events were found during exploration of "
00489                << "root cell.  Please check PDEFoam parameters nSampl "
00490                << "and VolFrac." << Endl;
00491       else
00492          Log() << kWARNING << "Negative number of events found during "
00493                << "exploration of root cell" << Endl;
00494    }
00495 
00496    //------------------------------------------------------------------
00497    //---  predefine logics of searching for the best division edge ---
00498    for (k=0; k<fDim;k++){
00499       fMaskDiv[k] =1;                       // default is all
00500       if ( fInhiDiv[k]==1) fMaskDiv[k] =0; // inhibit some...
00501    }
00502    kBest=-1;
00503 
00504    //------------------------------------------------------------------
00505    nevMC            = ceSum[2];
00506    Double_t intTrue = ceSum[0]/(nevMC+0.000001);
00507    Double_t intDriv=0.;
00508 
00509    if (kBest == -1) Varedu(ceSum,kBest,xBest,yBest); // determine the best edge,
00510    intDriv =sqrt(ceSum[1]/nevMC) -intTrue; // Foam build-up, sqrt(<w**2>) -<w>
00511 
00512    //=================================================================================
00513    cell->SetBest(kBest);
00514    cell->SetXdiv(xBest);
00515    cell->SetIntg(intTrue);
00516    cell->SetDriv(intDriv);
00517    if (GetNmin() > 0)
00518       SetCellElement(cell, 0, totevents);
00519 
00520    // correct/update integrals in all parent cells to the top of the tree
00521    Double_t  parIntg, parDriv;
00522    for (parent = cell->GetPare(); parent!=0; parent = parent->GetPare()){
00523       parIntg = parent->GetIntg();
00524       parDriv = parent->GetDriv();
00525       parent->SetIntg( parIntg   +intTrue -intOld );
00526       parent->SetDriv( parDriv   +intDriv -driOld );
00527       if (GetNmin() > 0)
00528          SetCellElement( parent, 0, GetBuildUpCellEvents(parent) + totevents - toteventsOld);
00529    }
00530    delete [] volPart;
00531    delete [] xRand;
00532 }
00533 
00534 //_____________________________________________________________________
00535 void TMVA::PDEFoam::DTExplore(PDEFoamCell *cell)
00536 {
00537    // Internal subprogram used by Create.  It explores newly defined
00538    // cell with according to the decision tree logic.  The separation
00539    // set by the 'fDTSeparation' option is used (see also
00540    // GetSeparation()).
00541    //
00542    // The optimal division point for eventual future cell division is
00543    // determined/recorded.  Note that links to parents and initial
00544    // volume = 1/2 parent has to be already defined prior to calling
00545    // this routine.
00546    //
00547    // Note, that according to the decision tree logic, a cell is only
00548    // split, if the number of (unweighted) events in each dautghter
00549    // cell is greater than fNmin.
00550 
00551    if (!cell)
00552       Log() << kFATAL << "<DTExplore> Null pointer given!" << Endl;
00553 
00554    // create edge histograms
00555    std::vector<TH1F*> hsig, hbkg, hsig_unw, hbkg_unw;
00556    for (Int_t idim=0; idim<fDim; idim++) {
00557       hsig.push_back( new TH1F(Form("hsig_%i",idim), 
00558                                Form("signal[%i]",idim), fNBin, 0, 1 ));
00559       hbkg.push_back( new TH1F(Form("hbkg_%i",idim), 
00560                                Form("background[%i]",idim), fNBin, 0, 1 ));
00561       hsig_unw.push_back( new TH1F(Form("hsig_unw_%i",idim), 
00562                                    Form("signal_unw[%i]",idim), fNBin, 0, 1 ));
00563       hbkg_unw.push_back( new TH1F(Form("hbkg_unw_%i",idim), 
00564                                    Form("background_unw[%i]",idim), fNBin, 0, 1 ));
00565    }
00566 
00567    // Fill histograms
00568    fDistr->FillHist(cell, hsig, hbkg, hsig_unw, hbkg_unw);
00569 
00570    // ------ determine the best division edge
00571    Float_t xBest = 0.5;   // best division point
00572    Int_t   kBest = -1;    // best split dimension
00573    Float_t maxGain = -1.0; // maximum gain
00574    Float_t nTotS = hsig.at(0)->Integral(0, hsig.at(0)->GetNbinsX()+1);
00575    Float_t nTotB = hbkg.at(0)->Integral(0, hbkg.at(0)->GetNbinsX()+1);
00576    Float_t nTotS_unw = hsig_unw.at(0)->Integral(0, hsig_unw.at(0)->GetNbinsX()+1);
00577    Float_t nTotB_unw = hbkg_unw.at(0)->Integral(0, hbkg_unw.at(0)->GetNbinsX()+1);
00578    Float_t parentGain = (nTotS+nTotB) * GetSeparation(nTotS,nTotB);
00579 
00580    for (Int_t idim=0; idim<fDim; idim++) {
00581       Float_t nSelS=hsig.at(idim)->GetBinContent(0);
00582       Float_t nSelB=hbkg.at(idim)->GetBinContent(0);
00583       Float_t nSelS_unw=hsig_unw.at(idim)->GetBinContent(0);
00584       Float_t nSelB_unw=hbkg_unw.at(idim)->GetBinContent(0);
00585       for(Int_t jLo=1; jLo<fNBin; jLo++) {
00586          nSelS += hsig.at(idim)->GetBinContent(jLo);
00587          nSelB += hbkg.at(idim)->GetBinContent(jLo);
00588          nSelS_unw += hsig_unw.at(idim)->GetBinContent(jLo);
00589          nSelB_unw += hbkg_unw.at(idim)->GetBinContent(jLo);
00590 
00591          // proceed if total number of events in left and right cell
00592          // is greater than fNmin
00593          if ( !( (nSelS_unw + nSelB_unw) >= GetNmin() && 
00594                  (nTotS_unw-nSelS_unw + nTotB_unw-nSelB_unw) >= GetNmin() ) )
00595             continue;
00596 
00597          Float_t xLo = 1.0*jLo/fNBin;
00598 
00599          // calculate gain
00600          Float_t leftGain   = ((nTotS - nSelS) + (nTotB - nSelB))
00601             * GetSeparation(nTotS-nSelS,nTotB-nSelB);
00602          Float_t rightGain  = (nSelS+nSelB) * GetSeparation(nSelS,nSelB);
00603          Float_t gain = parentGain - leftGain - rightGain;
00604 
00605          if (gain >= maxGain) {
00606             maxGain = gain;
00607             xBest   = xLo;
00608             kBest   = idim;
00609          }
00610       } // jLo
00611    } // idim
00612 
00613    if (kBest >= fDim || kBest < 0)
00614       Log() << kWARNING << "No best division edge found!" << Endl;
00615    
00616    // set cell properties
00617    cell->SetBest(kBest);
00618    cell->SetXdiv(xBest);
00619    if (nTotB+nTotS > 0)
00620       cell->SetIntg( nTotS/(nTotB+nTotS) );
00621    else 
00622       cell->SetIntg( 0.0 );
00623    cell->SetDriv(maxGain);
00624    cell->CalcVolume();
00625 
00626    // set cell element 0 (total number of events in cell) during
00627    // build-up
00628    if (GetNmin() > 0)
00629       SetCellElement( cell, 0, nTotS + nTotB);
00630 
00631    // clean up
00632    for (UInt_t ih=0; ih<hsig.size(); ih++)  delete hsig.at(ih);
00633    for (UInt_t ih=0; ih<hbkg.size(); ih++)  delete hbkg.at(ih);
00634    for (UInt_t ih=0; ih<hsig_unw.size(); ih++)  delete hsig_unw.at(ih);
00635    for (UInt_t ih=0; ih<hbkg_unw.size(); ih++)  delete hbkg_unw.at(ih);
00636 }
00637 
00638 //_____________________________________________________________________
00639 Float_t TMVA::PDEFoam::GetSeparation(Float_t s, Float_t b)
00640 {
00641    // Calculate the separation depending on 'fDTSeparation' for the
00642    // given number of signal and background events 's', 'b'.  Note,
00643    // that if (s+b) < 0 or s < 0 or b < 0 than the return value is 0.
00644 
00645    if (s+b <= 0 || s < 0 || b < 0 )
00646       return 0;
00647 
00648    Float_t p = s/(s+b);
00649    
00650    switch(fDTSeparation) {
00651    case kFoam:                   // p
00652       return p;
00653    case kGiniIndex:              // p * (1-p)
00654       return p*(1-p);
00655    case kMisClassificationError: // 1 - max(p,1-p)
00656       return 1 - TMath::Max(p, 1-p);
00657    case kCrossEntropy: // -p*log(p) - (1-p)*log(1-p)
00658       return (p<=0 || p >=1 ? 0 : -p*TMath::Log(p) - (1-p)*TMath::Log(1-p));
00659    default:
00660       Log() << kFATAL << "Unknown separation type" << Endl;
00661       break;
00662    }
00663 
00664    return 0;
00665 }
00666 
00667 //_____________________________________________________________________
00668 void TMVA::PDEFoam::Varedu(Double_t ceSum[5], Int_t &kBest, Double_t &xBest, Double_t &yBest)
00669 {
00670    // Internal subrogram used by Create.
00671    // In determines the best edge candidate and the position of the cell division plane
00672    // in case of the variance reduction for future cell division,
00673    // using results of the MC exploration run stored in fHistEdg
00674 
00675    Double_t nent   = ceSum[2];
00676    Double_t swAll  = ceSum[0];
00677    Double_t sswAll = ceSum[1];
00678    Double_t ssw    = sqrt(sswAll)/sqrt(nent);
00679    //
00680    Double_t swIn,swOut,sswIn,sswOut,xLo,xUp;
00681    kBest =-1;
00682    xBest =0.5;
00683    yBest =1.0;
00684    Double_t maxGain=0.0;
00685    // Now go over all projections kProj
00686    for(Int_t kProj=0; kProj<fDim; kProj++) {
00687       if( fMaskDiv[kProj]) {
00688          // initialize search over bins
00689          Double_t sigmIn =0.0; Double_t sigmOut =0.0;
00690          Double_t sswtBest = gHigh;
00691          Double_t gain =0.0;
00692          Double_t xMin=0.0; Double_t xMax=0.0;
00693          // Double loop over all pairs jLo<jUp
00694          for(Int_t jLo=1; jLo<=fNBin; jLo++) {
00695             Double_t aswIn=0;  Double_t asswIn=0;
00696             for(Int_t jUp=jLo; jUp<=fNBin;jUp++) {
00697                aswIn  +=     ((TH1D *)(*fHistEdg)[kProj])->GetBinContent(jUp);
00698                asswIn += Sqr(((TH1D *)(*fHistEdg)[kProj])->GetBinError(  jUp));
00699                xLo=(jLo-1.0)/fNBin;
00700                xUp=(jUp*1.0)/fNBin;
00701                swIn  =        aswIn/nent;
00702                swOut = (swAll-aswIn)/nent;
00703                sswIn = sqrt(asswIn)       /sqrt(nent*(xUp-xLo))     *(xUp-xLo);
00704                sswOut= sqrt(sswAll-asswIn)/sqrt(nent*(1.0-xUp+xLo)) *(1.0-xUp+xLo);
00705                if( (sswIn+sswOut) < sswtBest) {
00706                   sswtBest = sswIn+sswOut;
00707                   gain     = ssw-sswtBest;
00708                   sigmIn   = sswIn -swIn;  // Debug
00709                   sigmOut  = sswOut-swOut; // Debug
00710                   xMin    = xLo;
00711                   xMax    = xUp;
00712                }
00713             }//jUp
00714          }//jLo
00715          Int_t iLo = (Int_t) (fNBin*xMin);
00716          Int_t iUp = (Int_t) (fNBin*xMax);
00717 
00718          if(gain>=maxGain) {
00719             maxGain=gain;
00720             kBest=kProj; // <--- !!!!! The best edge
00721             xBest=xMin;
00722             yBest=xMax;
00723             if(iLo == 0)     xBest=yBest; // The best division point
00724             if(iUp == fNBin) yBest=xBest; // this is not really used
00725          }
00726       }
00727    } //kProj
00728 
00729    if( (kBest >= fDim) || (kBest<0) )
00730       Log() << kFATAL << "Something wrong with kBest" << Endl;
00731 }          //PDEFoam::Varedu
00732 
00733 //_____________________________________________________________________
00734 void TMVA::PDEFoam::MakeAlpha()
00735 {
00736    // Internal subrogram used by Create.
00737    // Provides random vector Alpha  0< Alpha(i) < 1
00738 
00739    // simply generate and load kDim uniform random numbers
00740    fPseRan->RndmArray(fDim,fRvec);   // kDim random numbers needed
00741    for(Int_t k=0; k<fDim; k++) fAlpha[k] = fRvec[k];
00742 } //MakeAlpha
00743 
00744 //_____________________________________________________________________
00745 Long_t TMVA::PDEFoam::PeekMax()
00746 {
00747    // Internal subprogram used by Create.  It finds cell with maximal
00748    // driver integral for the purpose of the division.  This function
00749    // is overridden by the PDEFoam Class to apply cuts on the number
00750    // of events in the cell (fNmin) and the cell tree depth
00751    // (GetMaxDepth() > 0) during cell buildup.
00752 
00753    Long_t iCell = -1;
00754 
00755    Long_t  i;
00756    Double_t  drivMax, driv;
00757    Bool_t bCutNmin = kTRUE;
00758    Bool_t bCutMaxDepth = kTRUE;
00759    //   drivMax = gVlow;
00760    drivMax = 0;  // only split cells if gain>0 (this also avoids splitting at cell boundary)
00761    for(i=0; i<=fLastCe; i++) {//without root
00762       if( fCells[i]->GetStat() == 1 ) {
00763          // if driver integral < numeric limit, skip cell
00764          if (fCells[i]->GetDriv() < std::numeric_limits<float>::epsilon())
00765             continue;
00766 
00767          driv =  TMath::Abs( fCells[i]->GetDriv());
00768 
00769          // apply cut on depth
00770          if (GetMaxDepth() > 0)
00771             bCutMaxDepth = fCells[i]->GetDepth() < GetMaxDepth();
00772 
00773          // apply Nmin-cut
00774          if (GetNmin() > 0)
00775             bCutNmin = GetBuildUpCellEvents(fCells[i]) > GetNmin();
00776 
00777          // choose cell
00778          if(driv > drivMax && bCutNmin && bCutMaxDepth) {
00779             drivMax = driv;
00780             iCell = i;
00781          }
00782       }
00783    }
00784 
00785    if (iCell == -1){
00786       if (!bCutNmin)
00787          Log() << kVERBOSE << "Warning: No cell with more than " 
00788                << GetNmin() << " events found!" << Endl;
00789       else if (!bCutMaxDepth)
00790          Log() << kVERBOSE << "Warning: Maximum depth reached: " 
00791                << GetMaxDepth() << Endl;
00792       else
00793          Log() << kWARNING << "Warning: PDEFoam::PeekMax: no more candidate cells (drivMax>0) found for further splitting." << Endl;
00794    }
00795 
00796    return(iCell);
00797 }
00798 
00799 //_____________________________________________________________________
00800 Long_t TMVA::PDEFoam::PeekLast()
00801 {
00802    // Internal subprogram used by Create.  It finds the last created
00803    // active cell for the purpose of the division.  Analogous to
00804    // PeekMax() it is cut on the number of events in the cell (fNmin)
00805    // and the cell tree depth (GetMaxDepth() > 0).
00806 
00807    Long_t iCell = -1;
00808 
00809    Bool_t bCutNmin = kTRUE;
00810    Bool_t bCutMaxDepth = kTRUE;
00811 
00812    for(Long_t i=fLastCe; i>=0; i--) {
00813       if( fCells[i]->GetStat() == 1 ) {
00814          // if driver integral < numeric limit, skip cell
00815          if (fCells[i]->GetDriv() < std::numeric_limits<float>::epsilon())
00816             continue;
00817 
00818          // apply cut on depth
00819          if (GetMaxDepth() > 0)
00820             bCutMaxDepth = fCells[i]->GetDepth() < GetMaxDepth();
00821 
00822          // apply Nmin-cut
00823          if (GetNmin() > 0)
00824             bCutNmin = GetBuildUpCellEvents(fCells[i]) > GetNmin();
00825 
00826          // choose cell
00827          if(bCutNmin && bCutMaxDepth) {
00828             iCell = i;
00829             break;
00830          }
00831       }
00832    }
00833 
00834    if (iCell == -1){
00835       if (!bCutNmin)
00836          Log() << kVERBOSE << "Warning: No cell with more than " 
00837                << GetNmin() << " events found!" << Endl;
00838       else if (!bCutMaxDepth)
00839          Log() << kVERBOSE << "Warning: Maximum depth reached: " 
00840                << GetMaxDepth() << Endl;
00841       else
00842          Log() << kWARNING << "Warning: PDEFoam::PeekLast: no more candidate cells found for further splitting." << Endl;
00843    }
00844 
00845    return(iCell);
00846 }
00847 
00848 //_____________________________________________________________________
00849 Int_t TMVA::PDEFoam::Divide(PDEFoamCell *cell)
00850 {
00851    // Internal subrogram used by Create.
00852    // It divides cell iCell into two daughter cells.
00853    // The iCell is retained and tagged as inactive, daughter cells are appended
00854    // at the end of the buffer.
00855    // New vertex is added to list of vertices.
00856    // List of active cells is updated, iCell removed, two daughters added
00857    // and their properties set with help of MC sampling (PDEFoam_Explore)
00858    // Returns Code RC=-1 of buffer limit is reached,  fLastCe=fnBuf.
00859 
00860    Double_t xdiv;
00861    Int_t   kBest;
00862 
00863    if(fLastCe+1 >= fNCells) Log() << kFATAL << "Buffer limit is reached, fLastCe=fnBuf" << Endl;
00864 
00865    cell->SetStat(0); // reset cell as inactive
00866    fNoAct++;
00867 
00868    xdiv  = cell->GetXdiv();
00869    kBest = cell->GetBest();
00870    if( kBest<0 || kBest>=fDim ) Log() << kFATAL << "Wrong kBest" << Endl;
00871 
00872    //////////////////////////////////////////////////////////////////
00873    //           define two daughter cells (active)                 //
00874    //////////////////////////////////////////////////////////////////
00875 
00876    Int_t d1 = CellFill(1,   cell);
00877    Int_t d2 = CellFill(1,   cell);
00878    cell->SetDau0((fCells[d1]));
00879    cell->SetDau1((fCells[d2]));
00880    if (fDTSeparation != kFoam) {
00881       DTExplore( (fCells[d1]) );
00882       DTExplore( (fCells[d2]) );
00883    } else {
00884       Explore( (fCells[d1]) );
00885       Explore( (fCells[d2]) );
00886    }
00887    return 1;
00888 } // PDEFoam_Divide
00889 
00890 //_____________________________________________________________________
00891 Double_t TMVA::PDEFoam::Eval(Double_t *xRand, Double_t &event_density)
00892 {
00893    // Internal subprogram.
00894    // Evaluates (training) distribution.
00895    return fDistr->Density(xRand, event_density);
00896 }
00897 
00898 //_____________________________________________________________________
00899 void TMVA::PDEFoam::Grow()
00900 {
00901    // Internal subrogram used by Create.
00902    // It grow new cells by the binary division process.
00903    // This function is overridden by the PDEFoam class to stop the foam buildup process
00904    // if one of the cut conditions stop the cell split.
00905 
00906    fTimer->Init(fNCells);
00907 
00908    Long_t iCell;
00909    PDEFoamCell* newCell;
00910 
00911    while ( (fLastCe+2) < fNCells ) {  // this condition also checked inside Divide
00912       if (fPeekMax)
00913          iCell = PeekMax(); // peek up cell with maximum driver integral
00914       else
00915          iCell = PeekLast(); // peek up last cell created
00916 
00917       if ( (iCell<0) || (iCell>fLastCe) ) {
00918          Log() << kVERBOSE << "Break: "<< fLastCe+1 << " cells created" << Endl;
00919          // remove remaining empty cells
00920          for (Long_t jCell=fLastCe+1; jCell<fNCells; jCell++)
00921             delete fCells[jCell];
00922          fNCells = fLastCe+1;
00923          break;
00924       }
00925       newCell = fCells[iCell];
00926 
00927       OutputGrow();
00928 
00929       if ( Divide( newCell )==0) break;  // and divide it into two
00930    }
00931    OutputGrow( kTRUE );
00932    CheckAll(1);   // set arg=1 for more info
00933 
00934    Log() << kVERBOSE << GetNActiveCells() << " active cells created" << Endl;
00935 }// Grow
00936 
00937 //_____________________________________________________________________
00938 void  TMVA::PDEFoam::SetInhiDiv(Int_t iDim, Int_t InhiDiv)
00939 {
00940    // This can be called before Create, after setting kDim
00941    // It defines which variables are excluded in the process of the cell division.
00942    // For example 'FoamX->SetInhiDiv(1, 1);' inhibits division of y-variable.
00943 
00944    if(fDim==0) Log() << kFATAL << "SetInhiDiv: fDim=0" << Endl;
00945    if(fInhiDiv == 0) {
00946       fInhiDiv = new Int_t[ fDim ];
00947       for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
00948    }
00949    //
00950    if( ( 0<=iDim) && (iDim<fDim)) {
00951       fInhiDiv[iDim] = InhiDiv;
00952    } else
00953       Log() << kFATAL << "Wrong iDim" << Endl;
00954 }//SetInhiDiv
00955 
00956 //_____________________________________________________________________
00957 void TMVA::PDEFoam::CheckAll(Int_t level)
00958 {
00959    //  User utility, miscellaneous and debug.
00960    //  Checks all pointers in the tree of cells. This is useful autodiagnostic.
00961    //  level=0, no printout, failures causes STOP
00962    //  level=1, printout, failures lead to WARNINGS only
00963 
00964    Int_t errors, warnings;
00965    PDEFoamCell *cell;
00966    Long_t iCell;
00967 
00968    errors = 0; warnings = 0;
00969    if (level==1) Log() << kVERBOSE <<  "Performing consistency checks for created foam" << Endl;
00970    for(iCell=1; iCell<=fLastCe; iCell++) {
00971       cell = fCells[iCell];
00972       //  checking general rules
00973       if( ((cell->GetDau0()==0) && (cell->GetDau1()!=0) ) ||
00974           ((cell->GetDau1()==0) && (cell->GetDau0()!=0) ) ) {
00975          errors++;
00976          if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has only one daughter " << iCell << Endl;
00977       }
00978       if( (cell->GetDau0()==0) && (cell->GetDau1()==0) && (cell->GetStat()==0) ) {
00979          errors++;
00980          if (level==1) Log() << kFATAL << "ERROR: Cell's no %d  has no daughter and is inactive " << iCell << Endl;
00981       }
00982       if( (cell->GetDau0()!=0) && (cell->GetDau1()!=0) && (cell->GetStat()==1) ) {
00983          errors++;
00984          if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has two daughters and is active " << iCell << Endl;
00985       }
00986 
00987       // checking parents
00988       if( (cell->GetPare())!=fCells[0] ) { // not child of the root
00989          if ( (cell != cell->GetPare()->GetDau0()) && (cell != cell->GetPare()->GetDau1()) ) {
00990             errors++;
00991             if (level==1) Log() << kFATAL << "ERROR: Cell's no %d parent not pointing to this cell " << iCell << Endl;
00992          }
00993       }
00994 
00995       // checking daughters
00996       if(cell->GetDau0()!=0) {
00997          if(cell != (cell->GetDau0())->GetPare()) {
00998             errors++;
00999             if (level==1)  Log() << kFATAL << "ERROR: Cell's no %d daughter 0 not pointing to this cell " << iCell << Endl;
01000          }
01001       }
01002       if(cell->GetDau1()!=0) {
01003          if(cell != (cell->GetDau1())->GetPare()) {
01004             errors++;
01005             if (level==1) Log() << kFATAL << "ERROR: Cell's no %d daughter 1 not pointing to this cell " << iCell << Endl;
01006          }
01007       }
01008       if(cell->GetVolume()<1E-50) {
01009          errors++;
01010          if(level==1) Log() << kFATAL << "ERROR: Cell no. " << iCell << " has Volume of <1E-50" << Endl;
01011       }
01012    }// loop after cells;
01013 
01014    // Check for cells with Volume=0
01015    for(iCell=0; iCell<=fLastCe; iCell++) {
01016       cell = fCells[iCell];
01017       if( (cell->GetStat()==1) && (cell->GetVolume()<1E-11) ) {
01018          errors++;
01019          if(level==1) Log() << kFATAL << "ERROR: Cell no. " << iCell << " is active but Volume is 0 " <<  Endl;
01020       }
01021    }
01022    // summary
01023    if(level==1){
01024       Log() << kVERBOSE << "Check has found " << errors << " errors and " << warnings << " warnings." << Endl;
01025    }
01026    if(errors>0){
01027       Info("CheckAll","Check - found total %d  errors \n",errors);
01028    }
01029 } // Check
01030 
01031 //_____________________________________________________________________
01032 void TMVA::PDEFoam::PrintCell(Long_t iCell)
01033 {
01034    // Prints geometry of 'iCell'
01035 
01036    if (iCell < 0 || iCell > fLastCe) {
01037       Log() << kWARNING << "<PrintCell(iCell=" << iCell
01038             << ")>: cell number " << iCell << " out of bounds!" 
01039             << Endl;
01040       return;
01041    }
01042 
01043    PDEFoamVect cellPosi(fDim), cellSize(fDim);
01044    fCells[iCell]->GetHcub(cellPosi,cellSize);
01045    Int_t    kBest = fCells[iCell]->GetBest();
01046    Double_t xBest = fCells[iCell]->GetXdiv();
01047 
01048    Log() << "Cell[" << iCell << "]={ ";
01049    Log() << "  " << fCells[iCell] << "  " << Endl;  // extra DEBUG
01050    Log() << " Xdiv[abs. coord.]="
01051          << VarTransformInvers(kBest,cellPosi[kBest] + xBest*cellSize[kBest])
01052          << Endl;
01053    Log() << " Abs. coord. = (";
01054    for (Int_t idim=0; idim<fDim; idim++) {
01055       Log() << "dim[" << idim << "]={"
01056             << VarTransformInvers(idim,cellPosi[idim]) << ","
01057             << VarTransformInvers(idim,cellPosi[idim] + cellSize[idim])
01058             << "}";
01059       if (idim < fDim-1)
01060          Log() << ", ";
01061    }
01062    Log() << ")" << Endl;
01063    fCells[iCell]->Print("1");
01064    Log()<<"}"<<Endl;
01065 }
01066 
01067 //_____________________________________________________________________
01068 void TMVA::PDEFoam::PrintCells(void)
01069 {
01070    // Prints geometry of ALL cells of the FOAM
01071 
01072    for(Long_t iCell=0; iCell<=fLastCe; iCell++)
01073       PrintCell(iCell);
01074 }
01075 
01076 //_____________________________________________________________________
01077 void TMVA::PDEFoam::RemoveEmptyCell( Int_t iCell )
01078 {
01079    // This function removes a cell iCell, which has a volume equal to zero.
01080    // It works the following way:
01081    // 1) find grandparent to iCell
01082    // 2) set daughter of the grandparent cell to the sister of iCell
01083    //
01084    // Result:
01085    // iCell and its parent are alone standing ==> will be removed
01086 
01087    // get cell volume
01088    Double_t volume = fCells[iCell]->GetVolume();
01089 
01090    if (!fCells[iCell]->GetStat() || volume>0){
01091       Log() << kDEBUG << "<RemoveEmptyCell>: cell " << iCell
01092             << "is not active or has volume>0 ==> doesn't need to be removed" << Endl;
01093       return;
01094    }
01095 
01096    // get parent and grandparent Cells
01097    PDEFoamCell *pCell  = fCells[iCell]->GetPare();
01098    PDEFoamCell *ppCell = fCells[iCell]->GetPare()->GetPare();
01099 
01100    // get neighbour (sister) to iCell
01101    PDEFoamCell *sCell;
01102    if (pCell->GetDau0() == fCells[iCell])
01103       sCell = pCell->GetDau1();
01104    else
01105       sCell = pCell->GetDau0();
01106 
01107    // cross check
01108    if (pCell->GetIntg() != sCell->GetIntg())
01109       Log() << kWARNING << "<RemoveEmptyCell> Error: cell integrals are not equal!"
01110             << " Intg(parent cell)=" << pCell->GetIntg()
01111             << " Intg(sister cell)=" << sCell->GetIntg()
01112             << Endl;
01113 
01114    // set daughter of grandparent to sister of iCell
01115    if (ppCell->GetDau0() == pCell)
01116       ppCell->SetDau0(sCell);
01117    else
01118       ppCell->SetDau1(sCell);
01119 
01120    // set parent of sister to grandparent of of iCell
01121    sCell->SetPare(ppCell);
01122 
01123    // now iCell and its parent are alone ==> set them inactive
01124    fCells[iCell]->SetStat(0);
01125    pCell->SetStat(0);
01126 }
01127 
01128 //_____________________________________________________________________
01129 void TMVA::PDEFoam::CheckCells( Bool_t remove_empty_cells )
01130 {
01131    // debug function: checks all cells with respect to critical
01132    // values, f.e. cell volume, ...
01133 
01134    for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01135       if (!fCells[iCell]->GetStat())
01136          continue;
01137 
01138       Double_t volume = fCells[iCell]->GetVolume();
01139       if (volume<1e-10){
01140          if (volume<=0){
01141             Log() << kWARNING << "Critical: cell volume negative or zero! volume="
01142                   << volume << " cell number: " << iCell << Endl;
01143             // fCells[iCell]->Print("1"); // debug output
01144             if (remove_empty_cells){
01145                Log() << kWARNING << "Remove cell " << iCell << Endl;
01146                RemoveEmptyCell(iCell);
01147             }
01148          }
01149          else {
01150             Log() << kWARNING << "Cell volume close to zero! volume="
01151                   << volume << " cell number: " << iCell << Endl;
01152          }
01153       }
01154    }
01155 }
01156 
01157 //_____________________________________________________________________
01158 void TMVA::PDEFoam::PrintCellElements()
01159 {
01160    // This debug function prints the cell elements of all active
01161    // cells.
01162 
01163    for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01164       if (!fCells[iCell]->GetStat()) continue;
01165 
01166       Log() << "cell[" << iCell << "] elements: [";
01167       for (UInt_t i=0; i<GetNElements(); i++){
01168          if (i>0) Log() << " ; ";
01169          Log() << GetCellElement(fCells[iCell], i);
01170       }
01171       Log() << "]" << Endl;
01172    }
01173 }
01174 
01175 //_____________________________________________________________________
01176 void TMVA::PDEFoam::ResetCellElements(Bool_t allcells)
01177 {
01178    // creates a TVectorD object with fNElements in every cell
01179    // and initializes them by zero.
01180    // The TVectorD object is used to store classification or
01181    // regression data in every foam cell.
01182    //
01183    // Parameter:
01184    //   allcells == true  : create TVectorD on every cell
01185    //   allcells == false : create TVectorD on active cells with
01186    //                       cell index <= fLastCe (default)
01187 
01188    if (!fCells || GetNElements()==0) return;
01189 
01190    // delete all old cell elements
01191    Log() << kVERBOSE << "Delete old cell elements" << Endl;
01192    for(Long_t iCell=0; iCell<fNCells; iCell++) {
01193       if (fCells[iCell]->GetElement() != 0){
01194          delete dynamic_cast<TVectorD*>(fCells[iCell]->GetElement());
01195          fCells[iCell]->SetElement(0);
01196       }
01197    }
01198 
01199    if (allcells){
01200       Log() << kVERBOSE << "Reset new cell elements to "
01201             << GetNElements() << " value(s) per cell" << Endl;
01202    } else {
01203       Log() << kVERBOSE << "Reset active cell elements to "
01204             << GetNElements() << " value(s) per cell" << Endl;
01205    }
01206 
01207    // create new cell elements
01208    for(Long_t iCell=0; iCell<(allcells ? fNCells : fLastCe+1); iCell++) {
01209       // skip inactive cells if allcells == false
01210       if (!allcells && !(fCells[iCell]->GetStat()))
01211          continue;
01212 
01213       TVectorD *elem = new TVectorD(GetNElements());
01214       for (UInt_t i=0; i<GetNElements(); i++)
01215          (*elem)(i) = 0.;
01216 
01217       fCells[iCell]->SetElement(elem);
01218    }
01219 }
01220 
01221 //_____________________________________________________________________
01222 void TMVA::PDEFoam::CalcCellTarget()
01223 {
01224    // Calculate average cell target in every cell and save them to the cell.
01225    // This function is called when the Mono target regression option is set.
01226 
01227    // loop over cells
01228    for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01229       if (!(fCells[iCell]->GetStat()))
01230          continue;
01231 
01232       Double_t N_ev  = GetCellElement(fCells[iCell], 0); // get number of events
01233       Double_t tar   = GetCellElement(fCells[iCell], 1); // get sum of targets
01234 
01235       if (N_ev > 1e-20){
01236          SetCellElement(fCells[iCell], 0, tar/N_ev);  // set average target
01237          SetCellElement(fCells[iCell], 1, tar/TMath::Sqrt(N_ev)); // set error on average target
01238       }
01239       else {
01240          SetCellElement(fCells[iCell], 0, 0.0 ); // set mean target
01241          SetCellElement(fCells[iCell], 1, -1  ); // set mean target error
01242       }
01243    }
01244 }
01245 
01246 //_____________________________________________________________________
01247 void TMVA::PDEFoam::CalcCellDiscr()
01248 {
01249    // Calc discriminator and its error for every cell and save it to the cell.
01250    // This function is called when the fSigBgSeparated==False option is set.
01251 
01252    // loop over cells
01253    for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01254       if (!(fCells[iCell]->GetStat()))
01255          continue;
01256 
01257       Double_t N_sig = GetCellElement(fCells[iCell], 0); // get number of signal events
01258       Double_t N_bg  = GetCellElement(fCells[iCell], 1); // get number of bg events
01259 
01260       if (N_sig<0.) {
01261          Log() << kWARNING << "Negative number of signal events in cell " << iCell
01262                << ": " << N_sig << ". Set to 0." << Endl;
01263          N_sig=0.;
01264       }
01265       if (N_bg<0.) {
01266          Log() << kWARNING << "Negative number of background events in cell " << iCell
01267                << ": " << N_bg << ". Set to 0." << Endl;
01268          N_bg=0.;
01269       }
01270 
01271 
01272       if (N_sig+N_bg > 1e-10){
01273          SetCellElement(fCells[iCell], 0, N_sig/(N_sig+N_bg));  // set discriminator
01274          SetCellElement(fCells[iCell], 1, TMath::Sqrt( Sqr ( N_sig/Sqr(N_sig+N_bg))*N_sig +
01275                                                        Sqr ( N_bg /Sqr(N_sig+N_bg))*N_bg ) ); // set discriminator error
01276 
01277       }
01278       else {
01279          SetCellElement(fCells[iCell], 0, 0.5); // set discriminator
01280          SetCellElement(fCells[iCell], 1, 1. ); // set discriminator error
01281       }
01282    }
01283 }
01284 
01285 //_____________________________________________________________________
01286 Double_t TMVA::PDEFoam::GetCellDiscr( std::vector<Float_t> &xvec, EKernel kernel )
01287 {
01288    // Get discriminator saved in cell (previously calculated in CalcCellDiscr())
01289    // which encloses the coordinates given in xvec.
01290    // This function is used, when the fSigBgSeparated==False option is set
01291    // (unified foams).
01292 
01293    // transform xvec
01294    std::vector<Float_t> txvec(VarTransform(xvec));
01295 
01296    // find cell
01297    PDEFoamCell *cell= FindCell(txvec);
01298 
01299    if (!cell) return -999.;
01300 
01301    switch (kernel) {
01302    case kNone:
01303       return GetCellValue(cell, kDiscriminator);
01304 
01305    case kGaus: {
01306       Double_t result = 0.;
01307       Double_t norm = 0.;
01308 
01309       for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01310          if (!(fCells[iCell]->GetStat())) continue;
01311 
01312          // calc cell density
01313          Double_t cell_discr = GetCellValue(fCells[iCell], kDiscriminator);
01314          Double_t gau        = WeightGaus(fCells[iCell], txvec);
01315 
01316          result += gau * cell_discr;
01317          norm   += gau;
01318       }
01319 
01320       return result / norm;
01321    }
01322 
01323    case kLinN:
01324       return WeightLinNeighbors(txvec, kDiscriminator);
01325 
01326    default:
01327       Log() << kFATAL << "GetCellDiscr: ERROR: wrong kernel!" << Endl;
01328       return 0;
01329    }
01330 
01331    return 0;
01332 }
01333 
01334 //_____________________________________________________________________
01335 void TMVA::PDEFoam::FillFoamCells(const Event* ev, Bool_t NoNegWeights)
01336 {
01337    // This function fills an event into the foam.
01338    //
01339    // In case of Mono-Target regression this function prepares the
01340    // calculation of the average target value in every cell.  Note,
01341    // that only target 0 is saved in the cell!
01342    //
01343    // In case of a unified foam this function prepares the calculation of
01344    // the cell discriminator in every cell.
01345    //
01346    // If 'NoNegWeights' is true, an event with negative weight will
01347    // not be filled into the foam.  (Default value: false)
01348 
01349    std::vector<Float_t> values  = ev->GetValues();
01350    std::vector<Float_t> targets = ev->GetTargets();
01351    Float_t weight               = fFillFoamWithOrigWeights ? ev->GetOriginalWeight() : ev->GetWeight();
01352    EFoamType ft                 = GetFoamType();
01353 
01354    if((NoNegWeights && weight<=0) || weight==0)
01355       return;
01356 
01357    if (ft == kMultiTarget)
01358       values.insert(values.end(), targets.begin(), targets.end());
01359 
01360    // find corresponding foam cell
01361    std::vector<Float_t> tvalues = VarTransform(values);
01362    PDEFoamCell *cell = FindCell(tvalues);
01363    if (!cell) {
01364       Log() << kFATAL << "<PDEFoam::FillFoamCells>: No cell found!" << Endl;
01365       return;
01366    }
01367 
01368    // Add events to cell
01369    switch (ft) {
01370    case kSeparate:
01371    case kMultiTarget:
01372       // 0. Element: Number of events
01373       // 1. Element: RMS
01374       SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
01375       SetCellElement(cell, 1, GetCellElement(cell, 1) + weight*weight);
01376       break;
01377 
01378    case kDiscr:
01379       // 0. Element: Number of signal events
01380       // 1. Element: Number of background events times normalization
01381       if (ev->GetClass() == 0)
01382          SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
01383       else
01384          SetCellElement(cell, 1, GetCellElement(cell, 1) + weight);
01385       break;
01386 
01387    case kMonoTarget:
01388       // 0. Element: Number of events
01389       // 1. Element: Target 0
01390       SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
01391       SetCellElement(cell, 1, GetCellElement(cell, 1) + weight*targets.at(0));
01392       break;
01393 
01394    default:
01395       Log() << kFATAL << "<FillFoamCells>: unmatched foam type!" << Endl;
01396       break;
01397    }
01398 }
01399 
01400 //_____________________________________________________________________
01401 Double_t TMVA::PDEFoam::GetCellRegValue0( std::vector<Float_t> &xvec, EKernel kernel )
01402 {
01403    // Get regression value 0 from cell that contains the event vector xvec.
01404    // This function is used when the MultiTargetRegression==False option is set.
01405 
01406    std::vector<Float_t> txvec(VarTransform(xvec));
01407    PDEFoamCell *cell = FindCell(txvec);
01408 
01409    if (!cell) {
01410       Log() << kFATAL << "<GetCellRegValue0> ERROR: No cell found!" << Endl;
01411       return -999.;
01412    }
01413 
01414    switch (kernel) {
01415    case kNone:
01416       if (GetCellValue(cell, kTarget0Error) != -1)
01417          // cell is not empty
01418          return GetCellValue(cell, kTarget0);
01419       else
01420          // cell is empty -> calc average target of neighbor cells
01421          return GetAverageNeighborsValue(txvec, kTarget0);
01422       break;
01423 
01424    case kGaus: {
01425       // return gaus weighted cell density
01426       
01427       Double_t result = 0.;
01428       Double_t norm = 0.;
01429 
01430       for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01431          if (!(fCells[iCell]->GetStat())) continue;
01432 
01433          // calc cell density
01434          Double_t cell_val = 0;
01435          if (GetCellValue(fCells[iCell], kTarget0Error) != -1)
01436             // cell is not empty
01437             cell_val = GetCellValue(fCells[iCell], kTarget0);
01438          else
01439             // cell is empty -> calc average target of neighbor cells
01440             cell_val = GetAverageNeighborsValue(txvec, kTarget0);
01441          Double_t gau = WeightGaus(fCells[iCell], txvec);
01442 
01443          result += gau * cell_val;
01444          norm   += gau;
01445       }
01446       return result / norm;
01447    }
01448       break;
01449    case kLinN:
01450       if (GetCellValue(cell, kTarget0Error) != -1)
01451          // cell is not empty -> weight with non-empty neighbors
01452          return WeightLinNeighbors(txvec, kTarget0, -1, -1, kTRUE);
01453       else
01454          // cell is empty -> calc average target of non-empty neighbor
01455          // cells
01456          return GetAverageNeighborsValue(txvec, kTarget0);
01457       break;
01458 
01459    default:
01460       Log() << kFATAL << "<GetCellRegValue0>: unknown kernel!" << Endl;
01461       return 0.;
01462    }
01463 
01464    return 0.;
01465 }
01466 
01467 //_____________________________________________________________________
01468 Double_t TMVA::PDEFoam::GetAverageNeighborsValue( std::vector<Float_t> &txvec,
01469                                                   ECellValue cv )
01470 {
01471    // This function returns the average value 'cv' of only nearest
01472    // neighbor cells.  It is used in cases, where empty cells shall
01473    // not be evaluated.
01474    //
01475    // Parameters:
01476    // - txvec - event vector, transformed into foam coordinates [0, 1]
01477    // - cv - cell value, see definition of ECellValue
01478 
01479    const Double_t xoffset = 1.e-6;
01480    Double_t norm   = 0; // normalisation
01481    Double_t result = 0; // return value
01482 
01483    PDEFoamCell *cell = FindCell(txvec); // find cooresponding cell
01484    PDEFoamVect cellSize(GetTotDim());
01485    PDEFoamVect cellPosi(GetTotDim());
01486    cell->GetHcub(cellPosi, cellSize); // get cell coordinates
01487 
01488    // loop over all dimensions and find neighbor cells
01489    for (Int_t dim=0; dim<GetTotDim(); dim++) {
01490       std::vector<Float_t> ntxvec(txvec);
01491       PDEFoamCell* left_cell  = 0; // left cell
01492       PDEFoamCell* right_cell = 0; // right cell
01493 
01494       // get left cell
01495       ntxvec[dim] = cellPosi[dim]-xoffset;
01496       left_cell = FindCell(ntxvec);
01497       if (!CellValueIsUndefined(left_cell)){
01498          // if left cell is not empty, take its value
01499          result += GetCellValue(left_cell, cv);
01500          norm++;
01501       }
01502       // get right cell
01503       ntxvec[dim] = cellPosi[dim]+cellSize[dim]+xoffset;
01504       right_cell = FindCell(ntxvec);
01505       if (!CellValueIsUndefined(right_cell)){
01506          // if right cell is not empty, take its value
01507          result += GetCellValue(right_cell, cv);
01508          norm++;
01509       }
01510    }
01511    if (norm>0)  result /= norm; // calc average target
01512    else         result = 0;     // return null if all neighbors are empty
01513 
01514    return result;
01515 }
01516 
01517 //_____________________________________________________________________
01518 Bool_t TMVA::PDEFoam::CellValueIsUndefined( PDEFoamCell* cell )
01519 {
01520    // Returns true, if the value of the given cell is undefined.
01521 
01522    EFoamType ft = GetFoamType();
01523    switch(ft){
01524    case kSeparate:
01525       return kFALSE;
01526    case kDiscr:
01527       return kFALSE;
01528    case kMonoTarget:
01529       return GetCellValue(cell, kTarget0Error) == -1;
01530    case kMultiTarget:
01531       return kFALSE;
01532    default:
01533       return kFALSE;
01534    }
01535    return kFALSE;
01536 }
01537 
01538 //_____________________________________________________________________
01539 std::vector<Float_t> TMVA::PDEFoam::GetCellTargets( std::vector<Float_t> &tvals, ETargetSelection ts )
01540 {
01541    // This function is used when the MultiTargetRegression==True
01542    // option is set.  It calculates the mean target or most probable
01543    // target values if 'tvals' variables are given ('tvals' does not
01544    // contain targets)
01545    //
01546    // Parameters:
01547    // - tvals - transformed event variables (element of [0,1]) (no targets!)
01548    // - ts - method of target selection (kMean, kMpv)
01549    //
01550    // Result:
01551    // vetor of mean targets or most probable targets over all cells
01552    // which first coordinates enclose 'tvals'
01553 
01554    std::vector<Float_t> target(GetTotDim()-tvals.size(), 0); // returned vector
01555    std::vector<Float_t> norm(target); // normalisation
01556    Double_t max_dens = 0.;            // maximum cell density
01557 
01558    // find cells, which fit tvals (no targets)
01559    std::vector<PDEFoamCell*> cells = FindCells(tvals);
01560    if (cells.size()<1) return target;
01561 
01562    // loop over all cells found
01563    std::vector<PDEFoamCell*>::iterator cell_it(cells.begin());
01564    for (cell_it=cells.begin(); cell_it!=cells.end(); cell_it++){
01565 
01566       // get density of cell
01567       Double_t cell_density = GetCellValue(*cell_it, kDensity);
01568 
01569       // get cell position and size
01570       PDEFoamVect  cellPosi(GetTotDim()), cellSize(GetTotDim());
01571       (*cell_it)->GetHcub(cellPosi, cellSize);
01572 
01573       // loop over all target dimensions, in order to calculate target
01574       // value
01575       if (ts==kMean){
01576          // sum cell density times cell center
01577          for (UInt_t itar=0; itar<target.size(); itar++){
01578             UInt_t idim = itar+tvals.size();
01579             target.at(itar) += cell_density *
01580                VarTransformInvers(idim, cellPosi[idim]+0.5*cellSize[idim]);
01581             norm.at(itar) += cell_density;
01582          } // loop over targets
01583       } else {
01584          // get cell center with maximum event density
01585          if (cell_density > max_dens){
01586             max_dens = cell_density; // save new max density
01587             // fill target values
01588             for (UInt_t itar=0; itar<target.size(); itar++){
01589                UInt_t idim = itar+tvals.size();
01590                target.at(itar) =
01591                   VarTransformInvers(idim, cellPosi[idim]+0.5*cellSize[idim]);
01592             } // loop over targets
01593          }
01594       }
01595    } // loop over cells
01596 
01597    // normalise mean cell density
01598    if (ts==kMean){
01599       for (UInt_t itar=0; itar<target.size(); itar++){
01600          if (norm.at(itar)>1.0e-15)
01601             target.at(itar) /= norm.at(itar);
01602          else
01603             // normalisation factor is too small -> return approximate
01604             // target value
01605             target.at(itar) = (fXmax[itar+tvals.size()]-fXmin[itar+tvals.size()])/2.;
01606       }
01607    }
01608 
01609    return target;
01610 }
01611 
01612 //_____________________________________________________________________
01613 std::vector<Float_t> TMVA::PDEFoam::GetProjectedRegValue( std::vector<Float_t> &vals, EKernel kernel, ETargetSelection ts )
01614 {
01615    // This function is used when the MultiTargetRegression==True option is set.
01616    // Returns regression value i, given the event variables 'vals'.
01617    // Note: number of foam dimensions = number of variables + number of targets
01618    //
01619    // Parameters:
01620    // - vals - event variables (no targets)
01621    // - kernel - used kernel (None or Gaus)
01622    // - ts - method of target selection (Mean or Mpv)
01623 
01624    // checkt whether vals are within foam borders.
01625    // if not -> push it into foam
01626    const Float_t xsmall = 1.e-7;
01627    for (UInt_t l=0; l<vals.size(); l++) {
01628       if (vals.at(l) <= fXmin[l]){
01629          vals.at(l) = fXmin[l] + xsmall;
01630       }
01631       else if (vals.at(l) >= fXmax[l]){
01632          vals.at(l) = fXmax[l] - xsmall;
01633       }
01634    }
01635 
01636    // transform variables (vals)
01637    std::vector<Float_t> txvec(VarTransform(vals));
01638 
01639    // choose kernel
01640    switch (kernel) {
01641    case kNone:
01642       return GetCellTargets(txvec, ts);
01643 
01644    case kGaus: {
01645 
01646       std::vector<Float_t> target(GetTotDim()-txvec.size(), 0); // returned vector
01647       std::vector<Float_t> norm(target); // normalisation
01648 
01649       // loop over all active cells to calc gaus weighted target values
01650       for (Long_t ice=0; ice<=fLastCe; ice++) {
01651          if (!(fCells[ice]->GetStat())) continue;
01652 
01653          // weight with gaus only in non-target dimensions!
01654          Double_t gau = WeightGaus(fCells[ice], txvec, vals.size());
01655 
01656          PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
01657          fCells[ice]->GetHcub(cellPosi, cellSize);
01658 
01659          // fill new vector with coordinates of new cell
01660          std::vector<Float_t> new_vec;
01661          for (UInt_t k=0; k<txvec.size(); k++)
01662             new_vec.push_back(cellPosi[k] + 0.5*cellSize[k]);
01663 
01664          std::vector<Float_t> val = GetCellTargets(new_vec, ts);
01665          for (UInt_t itar=0; itar<target.size(); itar++){
01666             target.at(itar) += gau * val.at(itar);
01667             norm.at(itar)   += gau;
01668          }
01669       }
01670 
01671       // normalisation
01672       for (UInt_t itar=0; itar<target.size(); itar++){
01673          if (norm.at(itar)<1.0e-20){
01674             Log() << kWARNING << "Warning: norm too small!" << Endl;
01675             target.at(itar) = 0.;
01676          } else
01677             target.at(itar) /= norm.at(itar);
01678       }
01679       return target;
01680    }
01681       break;
01682 
01683    default:
01684       Log() << kFATAL << "<GetProjectedRegValue>: unsupported kernel!" << Endl;
01685       return std::vector<Float_t>(GetTotDim()-txvec.size(), 0);
01686    }
01687 
01688    return std::vector<Float_t>(GetTotDim()-txvec.size(), 0);
01689 }
01690 
01691 //_____________________________________________________________________
01692 Double_t TMVA::PDEFoam::GetCellDensity( std::vector<Float_t> &xvec, EKernel kernel )
01693 {
01694    // Returns density (=number of entries / volume) of cell that
01695    // encloses the untransformed event vector 'xvec'.  This function
01696    // is called by GetMvaValue() in case of two separated foams
01697    // (signal and background).  'kernel' can be either kNone or kGaus.
01698 
01699    std::vector<Float_t> txvec(VarTransform(xvec));
01700    PDEFoamCell *cell          = FindCell(txvec);
01701 
01702    if (!cell) {
01703       Log() << kFATAL << "<GetCellDensity(event)> ERROR: No cell found!" << Endl;
01704       return -999.;
01705    }
01706 
01707    switch (kernel) {
01708    case kNone:
01709       // return cell entries over cell volume
01710       return GetCellValue(cell, kDensity);
01711 
01712    case kGaus: {
01713       // return gaus weighted cell density
01714 
01715       Double_t result = 0;
01716       Double_t norm = 0.;
01717 
01718       for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
01719          if (!(fCells[iCell]->GetStat())) continue;
01720 
01721          // calc cell density
01722          Double_t cell_dens = GetCellValue(fCells[iCell], kDensity);
01723          Double_t gau       = WeightGaus(fCells[iCell], txvec);
01724 
01725          result += gau * cell_dens;
01726          norm   += gau;
01727       }
01728 
01729       return result / norm;
01730    }
01731       break;
01732 
01733    case kLinN:
01734       return WeightLinNeighbors(txvec, kDensity);
01735 
01736    default: 
01737       Log() << kFATAL << "<GetCellDensity(event)> unknown kernel!" << Endl;
01738       return 0.;
01739    }
01740 
01741    return 0;
01742 }
01743 
01744 //_____________________________________________________________________
01745 Double_t TMVA::PDEFoam::GetCellValue( PDEFoamCell* cell, ECellValue cv )
01746 {
01747    // This function returns a value, which was saved in the foam cell,
01748    // depending on the foam type.  The value to return is specified
01749    // with the 'cv' parameter.
01750 
01751    switch(cv){
01752       
01753    case kTarget0:
01754       if (GetFoamType() == kMonoTarget) return GetCellElement(cell, 0);
01755       break;
01756 
01757    case kTarget0Error:
01758       if (GetFoamType() == kMonoTarget) return GetCellElement(cell, 1);
01759       break;
01760 
01761    case kDiscriminator:
01762       if (GetFoamType() == kDiscr) return GetCellElement(cell, 0);
01763       break;
01764 
01765    case kDiscriminatorError:
01766       if (GetFoamType() == kDiscr) return GetCellElement(cell, 1);
01767       break;
01768 
01769    case kMeanValue:
01770       return cell->GetIntg();
01771       break;
01772 
01773    case kRms:
01774       return cell->GetDriv();
01775       break;
01776 
01777    case kRmsOvMean:
01778       if (cell->GetIntg() != 0) return cell->GetDriv()/cell->GetIntg();
01779       break;
01780 
01781    case kNev:
01782       if (GetFoamType() == kSeparate || GetFoamType() == kMultiTarget) 
01783          return GetCellElement(cell, 0);
01784       break;
01785 
01786    case kDensity: {
01787       
01788       Double_t volume  = cell->GetVolume();
01789       if ( volume > 1.0e-10 ){
01790          return GetCellValue(cell, kNev)/volume;
01791       } else {
01792          if (volume<=0){
01793             cell->Print("1"); // debug output
01794             Log() << kWARNING << "<GetCellDensity(cell)>: ERROR: cell volume"
01795                   << " negative or zero!"
01796                   << " ==> return cell density 0!"
01797                   << " cell volume=" << volume
01798                   << " cell entries=" << GetCellValue(cell, kNev) << Endl;
01799             return 0;
01800          } else
01801             Log() << kWARNING << "<GetCellDensity(cell)>: WARNING: cell volume"
01802                   << " close to zero!"
01803                   << " cell volume: " << volume << Endl;
01804       }
01805    } // kDensity
01806       
01807    default:
01808       return 0;
01809    }
01810 
01811    return 0;
01812 }
01813 
01814 //_____________________________________________________________________
01815 Double_t TMVA::PDEFoam::GetCellValue(std::vector<Float_t> &xvec, ECellValue cv)
01816 {
01817    // This function finds the cell, which corresponds to the given
01818    // untransformed event vector 'xvec' and return its value, which is
01819    // given by the parameter 'cv'.
01820    
01821    std::vector<Float_t> txvec(VarTransform(xvec));
01822    return GetCellValue(FindCell(txvec), cv);
01823 }
01824 
01825 //_____________________________________________________________________
01826 Double_t TMVA::PDEFoam::GetBuildUpCellEvents( PDEFoamCell* cell )
01827 {
01828    // Returns the number of events, saved in the 'cell' during foam build-up.
01829    // Only used during foam build-up!
01830    return GetCellElement(cell, 0);
01831 }
01832 
01833 //_____________________________________________________________________
01834 Double_t TMVA::PDEFoam::WeightLinNeighbors( std::vector<Float_t> &txvec, ECellValue cv, Int_t dim1, Int_t dim2, Bool_t TreatEmptyCells )
01835 {
01836    // Returns the cell value, corresponding to 'txvec' (foam
01837    // coordinates [0,1]), weighted by the neighbor cells via a linear
01838    // function.
01839    //
01840    // Parameters:
01841    //  - txvec - event vector, transformed into foam coordinates [0,1]
01842    //
01843    //  - cv - cell value to be weighted
01844    //
01845    //  - dim1, dim2 - dimensions for two-dimensional projection.
01846    //    Default values: dim1 = dim2 = -1
01847    //    If dim1 and dim2 are set to values >=0 and <fDim, than
01848    //    the function GetProjectionCellValue() is used to get cell
01849    //    value.  This is used for projection to two dimensions within
01850    //    Project2().
01851    //
01852    //  - TreatEmptyCells - if this option is set false (default),
01853    //    it is not checked, wether the cell or its neighbors are empty
01854    //    or not.  If this option is set true, than only non-empty
01855    //    neighbor cells are taken into account for weighting.  If the
01856    //    cell, which contains txvec is empty, than its value is
01857    //    replaced by the average value of the non-empty neighbor cells
01858 
01859    Double_t result = 0.;
01860    UInt_t norm     = 0;
01861    const Double_t xoffset = 1.e-6;
01862 
01863    if (txvec.size() != UInt_t(GetTotDim()))
01864       Log() << kFATAL << "Wrong dimension of event variable!" << Endl;
01865 
01866    // find cell, which contains txvec
01867    PDEFoamCell *cell= FindCell(txvec);
01868    PDEFoamVect cellSize(GetTotDim());
01869    PDEFoamVect cellPosi(GetTotDim());
01870    cell->GetHcub(cellPosi, cellSize);
01871    // calc value of cell, which contains txvec
01872    Double_t cellval = 0;
01873    if (!(TreatEmptyCells && CellValueIsUndefined(cell)))
01874       // cell is not empty -> get cell value
01875       cellval = GetCellValue(cell, cv);
01876    else
01877       // cell is empty -> get average value of non-empty neighbor
01878       // cells
01879       cellval = GetAverageNeighborsValue(txvec, cv);
01880 
01881    // loop over all dimensions to find neighbor cells
01882    for (Int_t dim=0; dim<GetTotDim(); dim++) {
01883       std::vector<Float_t> ntxvec(txvec);
01884       Double_t mindist;
01885       PDEFoamCell *mindistcell = 0; // cell with minimal distance to txvec
01886       // calc minimal distance to neighbor cell
01887       mindist = (txvec[dim]-cellPosi[dim])/cellSize[dim];
01888       if (mindist<0.5) { // left neighbour
01889          ntxvec[dim] = cellPosi[dim]-xoffset;
01890          mindistcell = FindCell(ntxvec); // left neighbor cell
01891       } else { // right neighbour
01892          mindist=1-mindist;
01893          ntxvec[dim] = cellPosi[dim]+cellSize[dim]+xoffset;
01894          mindistcell = FindCell(ntxvec); // right neighbor cell
01895       }
01896       Double_t mindistcellval = 0; // value of cell, which contains ntxvec
01897       if (dim1>=0 && dim1<GetTotDim() &&
01898           dim2>=0 && dim2<GetTotDim() &&
01899           dim1!=dim2){
01900          cellval        = GetProjectionCellValue(cell, dim1, dim2, cv);
01901          mindistcellval = GetProjectionCellValue(mindistcell, dim1, dim2, cv);
01902       } else {
01903          mindistcellval = GetCellValue(mindistcell, cv);
01904       }
01905       // if treatment of empty neighbor cells is deactivated, do
01906       // normal weighting
01907       if (!(TreatEmptyCells && CellValueIsUndefined(mindistcell))){
01908          result += cellval        * (0.5 + mindist);
01909          result += mindistcellval * (0.5 - mindist);
01910          norm++;
01911       }
01912    }
01913    if (norm==0) return cellval;     // all nearest neighbors were empty
01914    else         return result/norm; // normalisation
01915 }
01916 
01917 //_____________________________________________________________________
01918 Float_t TMVA::PDEFoam::WeightGaus( PDEFoamCell* cell, std::vector<Float_t> &txvec,
01919                                    UInt_t dim )
01920 {
01921    // Returns the gauss weight between the 'cell' and a given coordinate 'txvec'.
01922    //
01923    // Parameters:
01924    // - cell - the cell
01925    //
01926    // - txvec - the transformed event variables (in [0,1]) (coordinates <0 are
01927    //   set to 0, >1 are set to 1)
01928    //
01929    // - dim - number of dimensions for the calculation of the euclidean distance.
01930    //   If dim=0, all dimensions of the foam are taken.  Else only the first 'dim'
01931    //   coordinates of 'txvec' are used for the calculation of the euclidean distance.
01932    //
01933    // Returns:
01934    // exp(-(d/sigma)^2/2), where
01935    //  - d - is the euclidean distance between 'txvec' and the point of the 'cell'
01936    //    which is most close to 'txvec' (in order to avoid artefacts because of the
01937    //    form of the cells).
01938    //  - sigma = 1/VolFrac
01939 
01940    // get cell coordinates
01941    PDEFoamVect cellSize(GetTotDim());
01942    PDEFoamVect cellPosi(GetTotDim());
01943    cell->GetHcub(cellPosi, cellSize);
01944 
01945    // calc normalized distance
01946    UInt_t dims;            // number of dimensions for gaus weighting
01947    if (dim == 0)
01948       dims = GetTotDim();  // use all dimensions of cell txvec for weighting
01949    else if (dim <= UInt_t(GetTotDim()))
01950       dims = dim;          // use only 'dim' dimensions of cell txvec for weighting
01951    else {
01952       Log() << kFATAL << "ERROR: too many given dimensions for Gaus weight!" << Endl;
01953       return 0.;
01954    }
01955 
01956    // calc position of nearest edge of cell
01957    std::vector<Float_t> cell_center;
01958    for (UInt_t i=0; i<dims; i++){
01959       if (txvec[i]<0.) txvec[i]=0.;
01960       if (txvec[i]>1.) txvec[i]=1.;
01961       //cell_center.push_back(cellPosi[i] + (0.5*cellSize[i]));
01962       if (cellPosi[i] > txvec.at(i))
01963          cell_center.push_back(cellPosi[i]);
01964       else if (cellPosi[i]+cellSize[i] < txvec.at(i))
01965          cell_center.push_back(cellPosi[i]+cellSize[i]);
01966       else
01967          cell_center.push_back(txvec.at(i));
01968    }
01969 
01970    Float_t distance = 0.; // distance for weighting
01971    for (UInt_t i=0; i<dims; i++)
01972       distance += Sqr(txvec.at(i)-cell_center.at(i));
01973    distance = TMath::Sqrt(distance);
01974 
01975    Float_t width = 1./GetVolumeFraction();
01976    if (width < 1.0e-10)
01977       Log() << kWARNING << "Warning: wrong volume fraction: " << GetVolumeFraction() << Endl;
01978 
01979    // weight with Gaus with sigma = 1/VolFrac
01980    return TMath::Gaus(distance, 0, width, kFALSE);
01981 }
01982 
01983 //_____________________________________________________________________
01984 TMVA::PDEFoamCell* TMVA::PDEFoam::FindCell( std::vector<Float_t> &xvec )
01985 {
01986    // Find cell that contains 'xvec' (in foam coordinates [0,1]).
01987    //
01988    // Loop to find cell that contains 'xvec' starting at root cell,
01989    // and traversing binary tree to find the cell quickly.  Note, that
01990    // if 'xvec' lies outside the foam, the cell which is nearest to
01991    // 'xvec' is returned.  (The returned pointer should never be
01992    // NULL.)
01993 
01994    PDEFoamVect  cellPosi0(GetTotDim()), cellSize0(GetTotDim());
01995    PDEFoamCell *cell, *cell0;
01996 
01997    cell=fCells[0]; // start with root cell
01998    Int_t idim=0;
01999    while (cell->GetStat()!=1) { //go down binary tree until cell is found
02000       idim=cell->GetBest();  // dimension that changed
02001       cell0=cell->GetDau0();
02002       cell0->GetHcub(cellPosi0,cellSize0);
02003 
02004       if (xvec.at(idim)<=cellPosi0[idim]+cellSize0[idim])
02005          cell=cell0;
02006       else
02007          cell=(cell->GetDau1());
02008    }
02009    return cell;
02010 }
02011 
02012 //_____________________________________________________________________
02013 void TMVA::PDEFoam::FindCellsRecursive(std::vector<Float_t> &txvec, PDEFoamCell* cell, std::vector<PDEFoamCell*> &cells)
02014 {
02015    // This is a helper function for FindCells().  It saves in 'cells'
02016    // all cells, which contain txvec.  It works analogous to
02017    // FindCell().
02018    //
02019    // Parameters:
02020    //
02021    // - txvec - vector of variables (no targets!) (transformed into
02022    //   foam)
02023    //
02024    // - cell - cell to start searching with (usually root cell
02025    //   fCells[0])
02026    //
02027    // - cells - list of cells found
02028 
02029    PDEFoamVect  cellPosi0(GetTotDim()), cellSize0(GetTotDim());
02030    PDEFoamCell *cell0;
02031    Int_t idim=0;
02032 
02033    while (cell->GetStat()!=1) { //go down binary tree until cell is found
02034       idim=cell->GetBest();  // dimension that changed
02035 
02036       if (idim < Int_t(txvec.size())){
02037          // case 1: cell is splitten in dimension of a variable
02038          cell0=cell->GetDau0();
02039          cell0->GetHcub(cellPosi0,cellSize0);
02040          // check, whether left daughter cell contains txvec
02041          if (txvec.at(idim)<=cellPosi0[idim]+cellSize0[idim])
02042             cell=cell0;
02043          else
02044             cell=cell->GetDau1();
02045       } else {
02046          // case 2: cell is splitten in target dimension
02047          FindCellsRecursive(txvec, cell->GetDau0(), cells);
02048          FindCellsRecursive(txvec, cell->GetDau1(), cells);
02049          return;
02050       }
02051    }
02052    cells.push_back(cell);
02053 }
02054 
02055 //_____________________________________________________________________
02056 std::vector<TMVA::PDEFoamCell*> TMVA::PDEFoam::FindCells(std::vector<Float_t> &txvec)
02057 {
02058    // Find all cells, that contain txvec.  This function can be used,
02059    // when the dimension of the foam is greater than the dimension of
02060    // txvec.  E.G this is the case for multi-target regression
02061    //
02062    // Parameters:
02063    //
02064    // - txvec - vector of variables (no targets!) (transformed into
02065    //   foam)
02066    //
02067    // Return value:
02068    //
02069    // - vector of cells, that fit txvec
02070 
02071    std::vector<PDEFoamCell*> cells(0);
02072 
02073    // loop over all target dimensions
02074    FindCellsRecursive(txvec, fCells[0], cells);
02075 
02076    return cells;
02077 }
02078 
02079 //_____________________________________________________________________
02080 TH1D* TMVA::PDEFoam::Draw1Dim( const char *opt, Int_t nbin )
02081 {
02082    // Draws 1-dimensional foam (= histogram)
02083    //
02084    // Parameters:
02085    //
02086    // - opt - cell_value, rms, rms_ov_mean
02087    //   if cell_value is set, the following values will be filled into
02088    //   the result histogram:
02089    //    - number of events - in case of classification with 2 separate
02090    //                         foams or multi-target regression
02091    //    - discriminator    - in case of classification with one
02092    //                         unified foam
02093    //    - target           - in case of mono-target regression
02094    //
02095    // - nbin - number of bins of result histogram
02096    //
02097    // Warning: This function is not well tested!
02098 
02099    // avoid plotting of wrong dimensions
02100    if ( GetTotDim()!=1 ) return 0;
02101 
02102    // select value to plot
02103    ECellValue cell_value = kNev;
02104    EFoamType  foam_type  = GetFoamType();
02105    if (strcmp(opt,"cell_value")==0){
02106       switch (foam_type) {
02107       case kSeparate:
02108       case kMultiTarget:
02109          cell_value = kNev;
02110          break;
02111       case kDiscr:
02112          cell_value = kDiscriminator;
02113          break;
02114       case kMonoTarget:
02115          cell_value = kTarget0;
02116          break;
02117       default:
02118          Log() << kFATAL << "<Draw1Dim>: unknown foam type" << Endl;
02119          return 0;
02120       }
02121    } else if (strcmp(opt,"rms")==0){
02122       cell_value = kRms;
02123    } else if (strcmp(opt,"rms_ov_mean")==0){
02124       cell_value = kRmsOvMean;
02125    } else {
02126       Log() << kFATAL << "<Draw1Dim>: unknown option:" << opt << Endl;
02127       return 0;
02128    }
02129 
02130 
02131    TString hname(Form("h%s",opt));
02132 
02133    TH1D* h1=(TH1D*)gDirectory->Get(hname);
02134    if (h1) delete h1;
02135    h1= new TH1D(hname, Form("1-dimensional Foam: %s", opt), nbin, fXmin[0], fXmax[0]);
02136 
02137    if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
02138 
02139    std::vector<Float_t> xvec(GetTotDim(), 0.);
02140 
02141    // loop over all bins
02142    for (Int_t ibinx=1; ibinx<=nbin; ibinx++) { //loop over  x-bins
02143       xvec.at(0) = h1->GetBinCenter(ibinx);
02144 
02145       // transform xvec
02146       std::vector<Float_t> txvec(VarTransform(xvec));
02147 
02148       // loop over all active cells
02149       for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
02150          if (!(fCells[iCell]->GetStat())) continue; // cell not active -> continue
02151 
02152          // get cell position and dimesions
02153          PDEFoamVect  cellPosi(GetTotDim()), cellSize(GetTotDim());
02154          fCells[iCell]->GetHcub(cellPosi,cellSize);
02155 
02156          // compare them with txvec
02157          const Double_t xsmall = 1.e-10;
02158          if (!( (txvec.at(0)>cellPosi[0]-xsmall) &&
02159                 (txvec.at(0)<=cellPosi[0]+cellSize[0]+xsmall) ) )
02160             continue;
02161 
02162          Double_t vol = fCells[iCell]->GetVolume();
02163          if (vol<1e-10) {
02164             Log() << kWARNING << "Project: ERROR: Volume too small!" << Endl;
02165             continue;
02166          }
02167 
02168          // filling value to histogram
02169          h1->SetBinContent(ibinx, 
02170                            GetCellValue(fCells[iCell], cell_value) + h1->GetBinContent(ibinx));
02171       }
02172    }
02173    return h1;
02174 }
02175 
02176 //_____________________________________________________________________
02177 TH2D* TMVA::PDEFoam::Project2( Int_t idim1, Int_t idim2, const char *opt, const char *ker, UInt_t nbin )
02178 {
02179    // Project foam variable idim1 and variable idim2 to histogram.
02180    //
02181    // Parameters:
02182    //
02183    // - idim1, idim2 - dimensions to project to
02184    //
02185    // - opt - cell_value, rms, rms_ov_mean
02186    //   if cell_value is set, the following values will be filled into
02187    //   the result histogram:
02188    //    - number of events - in case of classification with 2 separate
02189    //                         foams or multi-target regression
02190    //    - discriminator    - in case of classification with one
02191    //                         unified foam
02192    //    - target           - in case of mono-target regression
02193    //
02194    // - ker - kGaus, kNone (warning: Gaus may be very slow!)
02195    //
02196    // - nbin - number of bins in x and y direction of result histogram.
02197    //
02198    // Returns:
02199    // a 2-dimensional histogram
02200 
02201    // avoid plotting of wrong dimensions
02202    if ((idim1>=GetTotDim()) || (idim1<0) ||
02203        (idim2>=GetTotDim()) || (idim2<0) ||
02204        (idim1==idim2) )
02205       return 0;
02206 
02207    // select value to plot
02208    ECellValue cell_value = kNev;
02209    EFoamType  foam_type  = GetFoamType();
02210    if (strcmp(opt,"cell_value")==0){
02211       switch (foam_type) {
02212       case kSeparate:
02213       case kMultiTarget:
02214          cell_value = kNev;
02215          break;
02216       case kDiscr:
02217          cell_value = kDiscriminator;
02218          break;
02219       case kMonoTarget:
02220          cell_value = kTarget0;
02221          break;
02222       default:
02223          Log() << kFATAL << "<Draw1Dim>: unknown foam type" << Endl;
02224          return 0;
02225       }
02226    } else if (strcmp(opt,"rms")==0){
02227       cell_value = kRms;
02228    } else if (strcmp(opt,"rms_ov_mean")==0){
02229       cell_value = kRmsOvMean;
02230    } else {
02231       Log() << kFATAL << "unknown option given" << Endl;
02232       return 0;
02233    }
02234 
02235    // select kernel to use
02236    EKernel kernel = kNone;
02237    if (!strcmp(ker, "kNone"))
02238       kernel = kNone;
02239    else if (!strcmp(ker, "kGaus"))
02240       kernel = kGaus;
02241    else if (!strcmp(ker, "kLinN"))
02242       kernel = kLinN;
02243    else
02244       Log() << kWARNING << "Warning: wrong kernel! using kNone instead" << Endl;
02245 
02246    // root can not handle too many bins in one histogram --> catch this
02247    // Furthermore, to have more than 1000 bins in the histogram doesn't make
02248    // sense.
02249    if (nbin>1000){
02250       Log() << kWARNING << "Warning: number of bins too big: " << nbin
02251             << " Using 1000 bins for each dimension instead." << Endl;
02252       nbin = 1000;
02253    } else if (nbin<1) {
02254       Log() << kWARNING << "Wrong bin number: " << nbin 
02255             << "; set nbin=50" << Endl;
02256       nbin = 50;
02257    }
02258 
02259    // create result histogram
02260    TString hname(Form("h%s_%d_vs_%d",opt,idim1,idim2));
02261 
02262    // if histogram with this name already exists, delete it
02263    TH2D* h1=(TH2D*)gDirectory->Get(hname.Data());
02264    if (h1) delete h1;
02265    h1= new TH2D(hname.Data(), Form("%s var%d vs var%d",opt,idim1,idim2), nbin, fXmin[idim1], fXmax[idim1], nbin, fXmin[idim2], fXmax[idim2]);
02266 
02267    if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
02268 
02269    // ============== start projection algorithm ================
02270    // loop over all active cells
02271    for (Long_t iCell=0; iCell<=fLastCe; iCell++) { // loop over all active cells
02272       if (!(fCells[iCell]->GetStat())) continue;   // cell not active -> continue
02273 
02274       // get cell position and dimesions
02275       PDEFoamVect  cellPosi(GetTotDim()), cellSize(GetTotDim());
02276       fCells[iCell]->GetHcub(cellPosi,cellSize);
02277 
02278       // get cell value (depending on the option)
02279       // this value will later be filled into the histogram
02280       Double_t var = GetProjectionCellValue(fCells[iCell], idim1, idim2, cell_value);
02281 
02282       // coordinates of upper left corner of cell
02283       Double_t x1 = VarTransformInvers( idim1, cellPosi[idim1] );
02284       Double_t y1 = VarTransformInvers( idim2, cellPosi[idim2] );
02285 
02286       // coordinates of lower right corner of cell
02287       Double_t x2 = VarTransformInvers( idim1, cellPosi[idim1]+cellSize[idim1] );
02288       Double_t y2 = VarTransformInvers( idim2, cellPosi[idim2]+cellSize[idim2] );
02289 
02290       // most left and most right bins, which correspond to cell
02291       // borders
02292       Int_t xbin_start = TMath::Max(1, h1->GetXaxis()->FindBin(x1));
02293       Int_t xbin_stop  = h1->GetXaxis()->FindBin(x2);
02294 
02295       // upper and lower bins, which correspond to cell borders
02296       Int_t ybin_start = TMath::Max(1, h1->GetYaxis()->FindBin(y1));
02297       Int_t ybin_stop  = h1->GetYaxis()->FindBin(y2);
02298 
02299       // loop over all bins, which the cell occupies
02300       for (Int_t ibinx=xbin_start; ibinx<xbin_stop; ibinx++) {    //loop over x-bins
02301          for (Int_t ibiny=ybin_start; ibiny<ybin_stop; ibiny++) { //loop over y-bins
02302 
02303             ////////////////////// weight with kernel ///////////////////////
02304             if (kernel == kGaus){
02305                Double_t result = 0.;
02306                Double_t norm   = 0.;
02307 
02308                // calc current position (depending on ibinx, ibiny)
02309                Double_t x_curr =
02310                   VarTransform( idim1, ((x2-x1)*ibinx - x2*xbin_start + x1*xbin_stop)/(xbin_stop-xbin_start) );
02311                Double_t y_curr =
02312                   VarTransform( idim2, ((y2-y1)*ibiny - y2*ybin_start + y1*ybin_stop)/(ybin_stop-ybin_start) );
02313 
02314                // loop over all active cells
02315                for (Long_t ice=0; ice<=fLastCe; ice++) {
02316                   if (!(fCells[ice]->GetStat())) continue;
02317 
02318                   // get cell value (depending on option)
02319                   Double_t cell_var = GetProjectionCellValue(fCells[ice], idim1, idim2, cell_value);
02320 
02321                   // fill ndim coordinate of current cell
02322                   std::vector<Float_t> coor;
02323                   for (Int_t i=0; i<GetTotDim(); i++) {
02324                      if (i == idim1)
02325                         coor.push_back(x_curr);
02326                      else if (i == idim2)
02327                         coor.push_back(y_curr);
02328                      else
02329                         coor.push_back(cellPosi[i] + 0.5*cellSize[i]); // approximation
02330                   }
02331 
02332                   // calc weighted value
02333                   Double_t weight_ = WeightGaus(fCells[ice], coor);
02334 
02335                   result += weight_ * cell_var;
02336                   norm   += weight_;
02337                }
02338                var = result/norm;
02339             }
02340             else if (kernel == kLinN){
02341                // calc current position (depending on ibinx, ibiny)
02342                Double_t x_curr =
02343                   VarTransform( idim1, ((x2-x1)*ibinx - x2*xbin_start + x1*xbin_stop)/(xbin_stop-xbin_start) );
02344                Double_t y_curr =
02345                   VarTransform( idim2, ((y2-y1)*ibiny - y2*ybin_start + y1*ybin_stop)/(ybin_stop-ybin_start) );
02346 
02347                // fill ndim coordinate of current cell
02348                std::vector<Float_t> coor;
02349                for (Int_t i=0; i<GetTotDim(); i++) {
02350                   if (i == idim1)
02351                      coor.push_back(x_curr);
02352                   else if (i == idim2)
02353                      coor.push_back(y_curr);
02354                   else
02355                      coor.push_back(cellPosi[i] + 0.5*cellSize[i]); // approximation
02356                }
02357 
02358                var = WeightLinNeighbors(coor, cell_value, idim1, idim2);
02359             }
02360             ////////////////////// END weight with kernel ///////////////////////
02361 
02362             // filling value to histogram
02363             h1->SetBinContent(ibinx, ibiny, var + h1->GetBinContent(ibinx, ibiny));
02364          } // y-loop
02365       } // x-loop
02366    } // cell loop
02367 
02368    return h1;
02369 }
02370 
02371 //_____________________________________________________________________
02372 Double_t TMVA::PDEFoam::GetProjectionCellValue( PDEFoamCell* cell,
02373                                                 Int_t idim1,
02374                                                 Int_t idim2,
02375                                                 ECellValue cv )
02376 {
02377    // Helper function for projection function Project2().  It returns
02378    // the cell value of 'cell' corresponding to the given option 'cv'.
02379    // The two dimensions are needed for weighting the return value,
02380    // because Project2() projects the foam to two dimensions.
02381 
02382    // get cell position and dimesions
02383    PDEFoamVect  cellPosi(GetTotDim()), cellSize(GetTotDim());
02384    cell->GetHcub(cellPosi,cellSize);
02385    const Double_t foam_area = (fXmax[idim1]-fXmin[idim1])*(fXmax[idim2]-fXmin[idim2]);
02386 
02387    // calculate cell value (depending on the given option 'cv')
02388    switch (cv) {
02389    case kNev: {
02390       // calculate projected area of cell
02391       Double_t area = cellSize[idim1] * cellSize[idim2];
02392       if (area<1e-20){
02393          Log() << kWARNING << "<Project2>: Warning, cell volume too small --> skiping cell!" << Endl;
02394          return 0;
02395       }
02396 
02397       // calc cell entries per projected cell area
02398       return GetCellValue(cell, kNev)/(area*foam_area);
02399    }
02400       // =========================================================
02401    case kRms:
02402       return GetCellValue(cell, kRms);
02403       // =========================================================
02404    case kRmsOvMean:
02405       return GetCellValue(cell, kRmsOvMean);
02406       // =========================================================
02407    case kDiscriminator: {
02408       // calculate cell volume in other dimensions (not including idim1 and idim2)
02409       Double_t area_cell = 1.;
02410       for (Int_t d1=0; d1<GetTotDim(); d1++){
02411          if ((d1!=idim1) && (d1!=idim2))
02412             area_cell *= cellSize[d1];
02413       }
02414       if (area_cell<1e-20){
02415          Log() << kWARNING << "<Project2>: Warning, cell volume too small --> skiping cell!" << Endl;
02416          return 0;
02417       }
02418 
02419       // calc discriminator * (cell area times foam area)
02420       // foam is normalized -> length of foam = 1.0
02421       return GetCellValue(cell, kDiscriminator)*area_cell;
02422    }
02423       // =========================================================
02424    case kDiscriminatorError:
02425       return GetCellValue(cell, kDiscriminator);
02426       // =========================================================
02427    case kTarget0:
02428       // plot mean over all underlying cells?
02429       return GetCellValue(cell, kTarget0);
02430    default:
02431       Log() << kFATAL << "<Project2>: unknown option" << Endl;
02432       return 0;
02433    }
02434 }
02435 
02436 //_____________________________________________________________________
02437 Double_t TMVA::PDEFoam::GetCellElement( PDEFoamCell *cell, UInt_t i )
02438 {
02439    // Returns cell element i of cell 'cell'.
02440 
02441    if (i >= GetNElements()) Log() << kFATAL << "ERROR: Index out of range" << Endl;
02442 
02443    // dynamic_cast doesn't seem to work here ?!
02444    TVectorD *vec = (TVectorD*)cell->GetElement();
02445 
02446    if (!vec) Log() << kFATAL << "<GetCellElement> ERROR: cell element is not a TVectorD*" << Endl;
02447 
02448    return (*vec)(i);
02449 }
02450 
02451 //_____________________________________________________________________
02452 void TMVA::PDEFoam::SetCellElement( PDEFoamCell *cell, UInt_t i, Double_t value )
02453 {
02454    // Set cell element i of cell to value.
02455 
02456    if (i >= GetNElements()) {
02457       Log() << kFATAL << "ERROR: Index out of range" << Endl;
02458       return;
02459    }
02460 
02461    // dynamic_cast doesn't seem to work here ?!
02462    TVectorD *vec = (TVectorD*)cell->GetElement();
02463 
02464    if (!vec) Log() << kFATAL << "<SetCellElement> ERROR: cell element is not a TVectorD*" << Endl;
02465 
02466    (*vec)(i) = value;
02467 }
02468 
02469 //_____________________________________________________________________
02470 void TMVA::PDEFoam::OutputGrow( Bool_t finished )
02471 {
02472    // Overridden function of PDEFoam to avoid native foam output.
02473    // Draw TMVA-process bar instead.
02474 
02475    if (finished) {
02476       Log() << kINFO << "Elapsed time: " + fTimer->GetElapsedTime()
02477             << "                                 " << Endl;
02478       return;
02479    }
02480 
02481    Int_t modulo = 1;
02482 
02483    if (fNCells        >= 100) modulo = Int_t(fNCells/100);
02484    if (fLastCe%modulo == 0)   fTimer->DrawProgressBar( fLastCe );
02485 }
02486 
02487 //_____________________________________________________________________
02488 void TMVA::PDEFoam::RootPlot2dim( const TString& filename, TString opt,
02489                                   Bool_t CreateCanvas, Bool_t colors, Bool_t log_colors )
02490 {
02491    // Debugging tool which plots the cells of a 2-dimensional PDEFoam
02492    // as rectangles in C++ format readable for ROOT.
02493    //
02494    // Parameters:
02495    // - filename - filename of ouput root macro
02496    //
02497    // - opt - cell_value, rms, rms_ov_mean
02498    //   If cell_value is set, the following values will be filled into
02499    //   the result histogram:
02500    //    - number of events - in case of classification with 2 separate
02501    //                         foams or multi-target regression
02502    //    - discriminator    - in case of classification with one
02503    //                         unified foam
02504    //    - target           - in case of mono-target regression
02505    //   If none of {cell_value, rms, rms_ov_mean} is given, the cells
02506    //   will not be filled.  
02507    //   If 'opt' contains the string 'cellnumber', the index of
02508    //   each cell is draw in addition.
02509    //
02510    // - CreateCanvas - whether to create a new canvas or not
02511    //
02512    // - colors - whether to fill cells with colors or shades of grey
02513    //
02514    // - log_colors - whether to fill cells with colors (logarithmic scale)
02515    //
02516    // Example:
02517    //
02518    //   The following commands load a mono-target regression foam from
02519    //   file 'foam.root' and create a ROOT macro 'output.C', which
02520    //   draws all PDEFoam cells with little boxes.  The latter are
02521    //   filled with colors according to the target value stored in the
02522    //   cell.  Also the cell number is drawn.
02523    //
02524    //   TFile file("foam.root");
02525    //   TMVA::PDEFoam *foam = (TMVA::PDEFoam*) gDirectory->Get("MonoTargetRegressionFoam");
02526    //   foam->RootPlot2dim("output.C","cell_value,cellnumber");
02527    //   gROOT->Macro("output.C");
02528 
02529    if (GetTotDim() != 2)
02530       Log() << kFATAL << "RootPlot2dim() can only be used with "
02531             << "two-dimensional foams!" << Endl;
02532 
02533    // select value to plot
02534    ECellValue cell_value = kNev;
02535    EFoamType  foam_type  = GetFoamType();
02536    Bool_t plotcellnumber = kFALSE;
02537    Bool_t fillcells      = kTRUE;
02538    if (opt.Contains("cell_value")){
02539       switch (foam_type) {
02540       case kSeparate:
02541       case kMultiTarget:
02542          cell_value = kNev;
02543          break;
02544       case kDiscr:
02545          cell_value = kDiscriminator;
02546          break;
02547       case kMonoTarget:
02548          cell_value = kTarget0;
02549          break;
02550       default:
02551          Log() << kFATAL << "<Draw1Dim>: unknown foam type" << Endl;
02552          return;
02553       }
02554    } else if (opt.Contains("rms_ov_mean")){
02555       cell_value = kRmsOvMean;
02556    } else if (opt.Contains("rms")){
02557       cell_value = kRms;
02558    } else {
02559       fillcells = kFALSE;
02560    }
02561    if (opt.Contains("cellnumber"))
02562       plotcellnumber = kTRUE;
02563 
02564    // open file (root macro)
02565    std::ofstream outfile(filename, std::ios::out);
02566 
02567    outfile<<"{" << std::endl;
02568 
02569    // declare boxes and set the fill styles
02570    if (!colors) { // define grayscale colors from light to dark,
02571       // starting from color index 1000
02572       outfile << "TColor *graycolors[100];" << std::endl;
02573       outfile << "for (Int_t i=0.; i<100; i++)" << std::endl;
02574       outfile << "  graycolors[i]=new TColor(1000+i, 1-(Float_t)i/100.,1-(Float_t)i/100.,1-(Float_t)i/100.);"<< std::endl;
02575    }
02576    if (CreateCanvas)
02577       outfile << "cMap = new TCanvas(\"" << fName << "\",\"Cell Map for "
02578               << fName << "\",600,600);" << std::endl;
02579 
02580    outfile<<"TBox*a=new TBox();"<<std::endl;
02581    outfile<<"a->SetFillStyle(0);"<<std::endl;  // big frame
02582    outfile<<"a->SetLineWidth(4);"<<std::endl;
02583    outfile<<"TBox *b1=new TBox();"<<std::endl;  // single cell
02584    outfile<<"TText*t=new TText();"<<endl;  // text for numbering
02585    if (fillcells) {
02586       outfile << (colors ? "gStyle->SetPalette(1, 0);" : "gStyle->SetPalette(0);") 
02587               << std::endl;
02588       outfile <<"b1->SetFillStyle(1001);"<<std::endl;
02589       outfile<<"TBox *b2=new TBox();"<<std::endl;  // single cell
02590       outfile <<"b2->SetFillStyle(0);"<<std::endl;
02591    }
02592    else {
02593       outfile <<"b1->SetFillStyle(0);"<<std::endl;
02594    }
02595 
02596    if (fillcells)
02597       (colors ? gStyle->SetPalette(1, 0) : gStyle->SetPalette(0) );
02598 
02599    Double_t zmin = 1E8;  // minimal value (for color calculation)
02600    Double_t zmax = -1E8; // maximal value (for color calculation)
02601 
02602    // if cells shall be filled, calculate minimal and maximal plot
02603    // value --> store in zmin and zmax
02604    if (fillcells) {            
02605       for (Long_t iCell=1; iCell<=fLastCe; iCell++) {
02606          if ( fCells[iCell]->GetStat() == 1) {
02607             Double_t value = GetCellValue(fCells[iCell], cell_value);
02608             if (value<zmin)
02609                zmin=value;
02610             if (value>zmax)
02611                zmax=value;
02612          }
02613       }
02614       outfile << "// observed minimum and maximum of distribution: " << std::endl;
02615       outfile << "// Double_t zmin = "<< zmin << ";" << std::endl;
02616       outfile << "// Double_t zmax = "<< zmax << ";" << std::endl;
02617    }
02618 
02619    if (log_colors) {
02620       if (zmin<1)
02621          zmin=1;
02622       zmin=TMath::Log(zmin);
02623       zmax=TMath::Log(zmax);
02624       outfile << "// logarthmic color scale used " << std::endl;
02625    } 
02626    else outfile << "// linear color scale used " << std::endl;
02627 
02628    outfile << "// used minimum and maximum of distribution (taking into account log scale if applicable): " << std::endl;
02629    outfile << "Double_t zmin = "<< zmin << ";" << std::endl;
02630    outfile << "Double_t zmax = "<< zmax << ";" << std::endl;
02631 
02632    Double_t x1,y1,x2,y2,x,y; // box and text coordintates
02633    Double_t offs  = 0.01;
02634    Double_t lpag  = 1-2*offs;
02635    Int_t ncolors  = colors ? gStyle->GetNumberOfColors() : 100;
02636    Double_t scale = (ncolors-1)/(zmax - zmin);
02637    PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
02638 
02639    // loop over cells and draw a box for every cell (and maybe the
02640    // cell number as well)
02641    outfile << "// =========== Rectangular cells  ==========="<< std::endl;
02642    for (Long_t iCell=1; iCell<=fLastCe; iCell++) {
02643       if ( fCells[iCell]->GetStat() == 1) {
02644          fCells[iCell]->GetHcub(cellPosi,cellSize);
02645          x1 = offs+lpag*(cellPosi[0]);             
02646          y1 = offs+lpag*(cellPosi[1]);
02647          x2 = offs+lpag*(cellPosi[0]+cellSize[0]); 
02648          y2 = offs+lpag*(cellPosi[1]+cellSize[1]);
02649          
02650          if (fillcells) {
02651             // get cell value
02652             Double_t value = GetCellValue(fCells[iCell], cell_value);
02653 
02654             if (log_colors) {
02655                if (value<1.) value=1;
02656                value = TMath::Log(value);
02657             }
02658 
02659             // calculate fill color
02660             Int_t color;
02661             if (colors)
02662                color = gStyle->GetColorPalette(Int_t((value-zmin)*scale));
02663             else
02664                color = 1000+(Int_t((value-zmin)*scale));
02665 
02666             // set fill color of box b1
02667             outfile << "b1->SetFillColor(" << color << ");" << std::endl;
02668          }
02669 
02670          //     cell rectangle
02671          outfile<<"b1->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
02672          if (fillcells)
02673             outfile<<"b2->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
02674 
02675          //     cell number
02676          if (plotcellnumber) {
02677             outfile<<"t->SetTextColor(4);"<<endl;
02678             if(fLastCe<51)
02679                outfile<<"t->SetTextSize(0.025);"<<endl;  // text for numbering
02680             else if(fLastCe<251)
02681                outfile<<"t->SetTextSize(0.015);"<<endl;
02682             else
02683                outfile<<"t->SetTextSize(0.008);"<<endl;
02684             x = offs+lpag*(cellPosi[0]+0.5*cellSize[0]); 
02685             y = offs+lpag*(cellPosi[1]+0.5*cellSize[1]);
02686             outfile<<"t->DrawText("<<x<<","<<y<<","<<"\""<<iCell<<"\""<<");"<<endl;
02687          }
02688       }
02689    }
02690    outfile<<"// ============== End Rectangles ==========="<< std::endl;
02691 
02692    outfile << "}" << std::endl;
02693    outfile.flush();
02694    outfile.close();
02695 }
02696 
02697 //_____________________________________________________________________
02698 void TMVA::PDEFoam::FillBinarySearchTree( const Event* ev, Bool_t NoNegWeights )
02699 {
02700    // Insert event to internal foam density PDEFoamDistr.
02701    GetDistr()->FillBinarySearchTree(ev, GetFoamType(), NoNegWeights);
02702 }
02703 
02704 //_____________________________________________________________________
02705 void TMVA::PDEFoam::DeleteBinarySearchTree()
02706 { 
02707    // Delete the fDistr object, which contains the binary search tree
02708    if(fDistr) delete fDistr; 
02709    fDistr = NULL;
02710 }
02711 
02712 //_____________________________________________________________________
02713 void TMVA::PDEFoam::Init()
02714 {
02715    // Initialize binary search tree, stored in object of type
02716    // PDEFoamDistr
02717    GetDistr()->SetPDEFoam(this);
02718    GetDistr()->Initialize();
02719 }
02720 
02721 //_____________________________________________________________________
02722 void TMVA::PDEFoam::SetFoamType( EFoamType ft )
02723 {
02724    // Set the foam type.  This determinates the method of the
02725    // calculation of the density during the foam build-up.
02726    switch (ft) {
02727    case kDiscr:
02728       GetDistr()->SetDensityCalc(kDISCRIMINATOR);
02729       break;
02730    case kMonoTarget:
02731       GetDistr()->SetDensityCalc(kTARGET);
02732       break;
02733    default:
02734       GetDistr()->SetDensityCalc(kEVENT_DENSITY);
02735       break;
02736    }
02737 
02738    fFoamType = ft; // set foam type class variable
02739 }
02740 
02741 //_____________________________________________________________________
02742 ostream& TMVA::operator<< ( ostream& os, const TMVA::PDEFoam& pdefoam )
02743 {
02744    // Write PDEFoam variables to stream 'os'.
02745    pdefoam.PrintStream(os);
02746    return os; // Return the output stream.
02747 }
02748 
02749 //_____________________________________________________________________
02750 istream& TMVA::operator>> ( istream& istr, TMVA::PDEFoam& pdefoam )
02751 {
02752    // Read PDEFoam variables from stream 'istr'.
02753    pdefoam.ReadStream(istr);
02754    return istr;
02755 }
02756 
02757 //_____________________________________________________________________
02758 void TMVA::PDEFoam::ReadStream( istream & istr )
02759 {
02760    // Read PDEFoam variables from stream 'istr'.
02761 
02762    // inherited class variables: fLastCe, fNCells, fDim[GetTotDim()]
02763    istr >> fLastCe;
02764    istr >> fNCells;
02765    // coverity[tainted_data_argument]
02766    istr >> fDim;
02767    if (fDim < 1 || fDim >= INT_MAX) {
02768       Log() << kERROR << "Foam dimension " << GetTotDim() << "our of range!" << Endl;
02769       return;
02770    }
02771 
02772    Double_t vfr = -1.;
02773    istr >> vfr;
02774    SetVolumeFraction(vfr);
02775 
02776    Log() << kVERBOSE << "Foam dimension: " << GetTotDim() << Endl;
02777 
02778    // read Class Variables: fXmin, fXmax
02779    if (fXmin) delete [] fXmin;
02780    if (fXmax) delete [] fXmax;
02781    fXmin = new Double_t[GetTotDim()];
02782    fXmax = new Double_t[GetTotDim()];
02783    for (Int_t i=0; i<GetTotDim(); i++)
02784       istr >> fXmin[i];
02785    for (Int_t i=0; i<GetTotDim(); i++)
02786       istr >> fXmax[i];
02787 }
02788 
02789 //_____________________________________________________________________
02790 void TMVA::PDEFoam::PrintStream( ostream & ostr ) const
02791 {
02792    // Write PDEFoam variables to stream 'os'.
02793 
02794    // inherited class variables: fLastCe, fNCells, fDim[GetTotDim()]
02795    ostr << fLastCe << std::endl;
02796    ostr << fNCells << std::endl;
02797    ostr << fDim    << std::endl;
02798    ostr << GetVolumeFraction() << std::endl;
02799 
02800    // write class variables: fXmin, fXmax
02801    for (Int_t i=0; i<GetTotDim(); i++)
02802       ostr << fXmin[i] << std::endl;
02803    for (Int_t i=0; i<GetTotDim(); i++)
02804       ostr << fXmax[i] << std::endl;
02805 }
02806 
02807 //_____________________________________________________________________
02808 void TMVA::PDEFoam::AddXMLTo( void* parent )
02809 {
02810    // write foam variables to xml
02811 
02812    void *variables = gTools().AddChild( parent, "Variables" );
02813    gTools().AddAttr( variables, "LastCe",           fLastCe );
02814    gTools().AddAttr( variables, "nCells",           fNCells );
02815    gTools().AddAttr( variables, "Dim",              fDim );
02816    gTools().AddAttr( variables, "VolumeFraction",   GetVolumeFraction() );
02817 
02818    void *xmin_wrap;
02819    for (Int_t i=0; i<GetTotDim(); i++){
02820       xmin_wrap = gTools().AddChild( variables, "Xmin" );
02821       gTools().AddAttr( xmin_wrap, "Index", i );
02822       gTools().AddAttr( xmin_wrap, "Value", fXmin[i] );
02823    }
02824 
02825    void *xmax_wrap;
02826    for (Int_t i=0; i<GetTotDim(); i++){
02827       xmax_wrap = gTools().AddChild( variables, "Xmax" );
02828       gTools().AddAttr( xmax_wrap, "Index", i );
02829       gTools().AddAttr( xmax_wrap, "Value", fXmax[i] );
02830    }
02831 }
02832 
02833 //_____________________________________________________________________
02834 void TMVA::PDEFoam::ReadXML( void* parent )
02835 {
02836    void *variables = gTools().GetChild( parent );
02837    gTools().ReadAttr( variables, "LastCe",         fLastCe );
02838    gTools().ReadAttr( variables, "nCells",         fNCells );
02839    gTools().ReadAttr( variables, "Dim",            fDim );
02840    if (fDim < 1 || fDim >= INT_MAX) {
02841       Log() << kERROR << "Foam dimension " << GetTotDim() << "our of range!" << Endl;
02842       return;
02843    }
02844    Float_t volfr;
02845    gTools().ReadAttr( variables, "VolumeFraction", volfr );
02846    SetVolumeFraction( volfr );
02847 
02848    if (fXmin) delete [] fXmin;
02849    if (fXmax) delete [] fXmax;
02850    fXmin = new Double_t[GetTotDim()];
02851    fXmax = new Double_t[GetTotDim()];
02852 
02853    void *xmin_wrap = gTools().GetChild( variables );
02854    for (Int_t counter=0; counter<fDim; counter++) {
02855       Int_t i=0;
02856       gTools().ReadAttr( xmin_wrap , "Index", i );
02857       if (i >= GetTotDim() || i<0)
02858          Log() << kFATAL << "dimension index out of range:" << i << Endl;
02859       gTools().ReadAttr( xmin_wrap , "Value", fXmin[i] );
02860       xmin_wrap = gTools().GetNextChild( xmin_wrap );
02861    }
02862 
02863    void *xmax_wrap = xmin_wrap; //gTools().xmlengine().GetChild( variables );
02864    for (Int_t counter=0; counter<fDim; counter++) {
02865       Int_t i=0;
02866       gTools().ReadAttr( xmax_wrap , "Index", i );
02867       if (i >= GetTotDim() || i<0)
02868          Log() << kFATAL << "dimension index out of range:" << i << Endl;
02869       gTools().ReadAttr( xmax_wrap , "Value", fXmax[i] );
02870       xmax_wrap = gTools().GetNextChild( xmax_wrap );
02871    }
02872 }

Generated on Tue Jul 5 15:25:13 2011 for ROOT_528-00b_version by  doxygen 1.5.1