#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cassert>
#include "TMVA/Event.h"
#include "TMVA/Tools.h"
#include "TMVA/PDEFoam.h"
#include "TMVA/MsgLogger.h"
#include "TMVA/Types.h"
#ifndef ROOT_TStyle
#include "TStyle.h"
#endif
#ifndef ROOT_TObject
#include "TObject.h"
#endif
#ifndef ROOT_TH1D
#include "TH1D.h"
#endif
#ifndef ROOT_TMath
#include "TMath.h"
#endif
#ifndef ROOT_TVectorT
#include "TVectorT.h"
#endif
#ifndef ROOT_TRandom3
#include "TRandom3.h"
#endif
#ifndef ROOT_TColor
#include "TColor.h"
#endif
ClassImp(TMVA::PDEFoam)
static const Float_t gHigh= FLT_MAX;
static const Float_t gVlow=-FLT_MAX;
using namespace std;
TMVA::PDEFoam::PDEFoam() :
fLogger(new MsgLogger("PDEFoam"))
{
fDim = 0;
fNoAct = 1;
fNCells = 0;
fMaskDiv = 0;
fInhiDiv = 0;
fCells = 0;
fAlpha = 0;
fHistEdg = 0;
fRvec = 0;
fPseRan = new TRandom3(4356);
fFoamType = kSeparate;
fXmin = 0;
fXmax = 0;
fNElements = 0;
fCutNmin = kTRUE;
fNmin = 100;
fCutRMSmin = kFALSE;
fRMSmin = 1.0;
SetPDEFoamVolumeFraction(-1.);
fSignalClass = -1;
fBackgroundClass = -1;
fDistr = new PDEFoamDistr();
fDistr->SetSignalClass( fSignalClass );
fDistr->SetBackgroundClass( fBackgroundClass );
fTimer = new Timer(fNCells, "PDEFoam", kTRUE);
fVariableNames = new TObjArray();
}
TMVA::PDEFoam::PDEFoam(const TString& Name) :
fLogger(new MsgLogger("PDEFoam"))
{
if(strlen(Name) >129) {
Log() << kFATAL << "Name too long " << Name.Data() << Endl;
}
fName = Name;
fMaskDiv = 0;
fInhiDiv = 0;
fCells = 0;
fAlpha = 0;
fHistEdg = 0;
fDim = 0;
fNCells = 1000;
fNSampl = 200;
fNBin = 8;
fEvPerBin =25;
fLastCe =-1;
fNoAct = 1;
fPseRan = new TRandom3(4356);
fFoamType = kSeparate;
fXmin = 0;
fXmax = 0;
fCutNmin = kFALSE;
fCutRMSmin = kFALSE;
SetPDEFoamVolumeFraction(-1.);
fSignalClass = -1;
fBackgroundClass = -1;
fDistr = new PDEFoamDistr();
fDistr->SetSignalClass( fSignalClass );
fDistr->SetBackgroundClass( fBackgroundClass );
fTimer = new Timer(fNCells, "PDEFoam", kTRUE);
fVariableNames = new TObjArray();
Log().SetSource( "PDEFoam" );
}
TMVA::PDEFoam::~PDEFoam()
{
delete fVariableNames;
delete fTimer;
delete fDistr;
delete fPseRan;
if (fXmin) delete [] fXmin; fXmin=0;
if (fXmax) delete [] fXmax; fXmax=0;
if(fCells!= 0) {
for(Int_t i=0; i<fNCells; i++) delete fCells[i];
delete [] fCells;
}
delete [] fRvec;
delete [] fAlpha;
delete [] fMaskDiv;
delete [] fInhiDiv;
delete fLogger;
}
TMVA::PDEFoam::PDEFoam(const PDEFoam &From):
TObject(From),
fLogger( new MsgLogger("PDEFoam"))
{
Log() << kFATAL << "COPY CONSTRUCTOR NOT IMPLEMENTED" << Endl;
}
void TMVA::PDEFoam::SetkDim(Int_t kDim)
{
if (kDim < 1)
Log() << kFATAL << "<SetkDim>: Dimension is zero or negative!" << Endl;
fDim = kDim;
if (fXmin) delete [] fXmin;
if (fXmax) delete [] fXmax;
fXmin = new Double_t[GetTotDim()];
fXmax = new Double_t[GetTotDim()];
}
void TMVA::PDEFoam::SetXmin(Int_t idim, Double_t wmin)
{
if (idim<0 || idim>=GetTotDim())
Log() << kFATAL << "<SetXmin>: Dimension out of bounds!" << Endl;
fXmin[idim]=wmin;
fDistr->SetXmin(idim, wmin);
}
void TMVA::PDEFoam::SetXmax(Int_t idim, Double_t wmax)
{
if (idim<0 || idim>=GetTotDim())
Log() << kFATAL << "<SetXmax>: Dimension out of bounds!" << Endl;
fXmax[idim]=wmax;
fDistr->SetXmax(idim, wmax);
}
void TMVA::PDEFoam::Create(Bool_t CreateCellElements)
{
Bool_t addStatus = TH1::AddDirectoryStatus();
TH1::AddDirectory(kFALSE);
if(fPseRan==0) Log() << kFATAL << "Random number generator not set" << Endl;
if(fDistr==0) Log() << kFATAL << "Distribution function not set" << Endl;
if(fDim==0) Log() << kFATAL << "Zero dimension not allowed" << Endl;
fRvec = new Double_t[fDim];
if(fRvec==0) Log() << kFATAL << "Cannot initialize buffer fRvec" << Endl;
if(fDim>0){
fAlpha = new Double_t[fDim];
if(fAlpha==0) Log() << kFATAL << "Cannot initialize buffer fAlpha" << Endl;
}
if(fInhiDiv == 0){
fInhiDiv = new Int_t[fDim];
for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
}
if(fMaskDiv == 0){
fMaskDiv = new Int_t[fDim];
for(Int_t i=0; i<fDim; i++) fMaskDiv[i]=1;
}
fHistEdg = new TObjArray(fDim);
for(Int_t i=0; i<fDim; i++){
TString hname, htitle;
hname = fName+TString("_HistEdge_");
hname += i;
htitle = TString("Edge Histogram No. ");
htitle += i;
(*fHistEdg)[i] = new TH1D(hname.Data(),htitle.Data(),fNBin,0.0, 1.0);
((TH1D*)(*fHistEdg)[i])->Sumw2();
}
InitCells(CreateCellElements);
Grow();
TH1::AddDirectory(addStatus);
}
void TMVA::PDEFoam::InitCells(Bool_t CreateCellElements)
{
fLastCe =-1;
if(fCells!= 0) {
for(Int_t i=0; i<fNCells; i++) delete fCells[i];
delete [] fCells;
}
fCells = new PDEFoamCell*[fNCells];
for(Int_t i=0; i<fNCells; i++){
fCells[i]= new PDEFoamCell(fDim);
fCells[i]->SetSerial(i);
}
if(fCells==0) Log() << kFATAL << "Cannot initialize CELLS" << Endl;
if (CreateCellElements)
ResetCellElements(true);
CellFill(1, 0);
for(Long_t iCell=0; iCell<=fLastCe; iCell++){
Explore( fCells[iCell] );
}
}
Int_t TMVA::PDEFoam::CellFill(Int_t Status, PDEFoamCell *parent)
{
PDEFoamCell *cell;
if (fLastCe==fNCells){
Log() << kFATAL << "Too many cells" << Endl;
}
fLastCe++;
cell = fCells[fLastCe];
cell->Fill(Status, parent, 0, 0);
cell->SetBest( -1);
cell->SetXdiv(0.5);
Double_t xInt2,xDri2;
if(parent!=0){
xInt2 = 0.5*parent->GetIntg();
xDri2 = 0.5*parent->GetDriv();
cell->SetIntg(xInt2);
cell->SetDriv(xDri2);
}else{
cell->SetIntg(0.0);
cell->SetDriv(0.0);
}
return fLastCe;
}
void TMVA::PDEFoam::Explore(PDEFoamCell *cell)
{
Double_t wt, dx, xBest, yBest;
Double_t intOld, driOld;
Long_t iev;
Double_t nevMC;
Int_t i, j, k;
Int_t nProj, kBest;
Double_t ceSum[5], xproj;
Double_t event_density = 0;
Double_t totevents = 0;
Double_t toteventsOld = 0;
PDEFoamVect cellSize(fDim);
PDEFoamVect cellPosi(fDim);
cell->GetHcub(cellPosi,cellSize);
PDEFoamCell *parent;
Double_t *xRand = new Double_t[fDim];
Double_t *volPart=0;
cell->CalcVolume();
dx = cell->GetVolume();
intOld = cell->GetIntg();
driOld = cell->GetDriv();
if (CutNmin())
toteventsOld = GetBuildUpCellEvents(cell);
ceSum[0]=0;
ceSum[1]=0;
ceSum[2]=0;
ceSum[3]=gHigh;
ceSum[4]=gVlow;
for (i=0;i<fDim;i++) ((TH1D *)(*fHistEdg)[i])->Reset();
Double_t nevEff=0.;
for (iev=0;iev<fNSampl;iev++){
MakeAlpha();
if (fDim>0){
for (j=0; j<fDim; j++)
xRand[j]= cellPosi[j] +fAlpha[j]*(cellSize[j]);
}
wt = dx*Eval(xRand, event_density);
totevents += dx*event_density;
nProj = 0;
if (fDim>0) {
for (k=0; k<fDim; k++) {
xproj =fAlpha[k];
((TH1D *)(*fHistEdg)[nProj])->Fill(xproj,wt);
nProj++;
}
}
ceSum[0] += wt;
ceSum[1] += wt*wt;
ceSum[2]++;
if (ceSum[3]>wt) ceSum[3]=wt;
if (ceSum[4]<wt) ceSum[4]=wt;
nevEff = ceSum[0]*ceSum[0]/ceSum[1];
if ( nevEff >= fNBin*fEvPerBin) break;
}
totevents /= fNSampl;
if (cell==fCells[0] && ceSum[0]<=0.0){
if (ceSum[0]==0.0)
Log() << kFATAL << "No events were found during exploration of "
<< "root cell. Please check PDEFoam parameters nSampl "
<< "and VolFrac." << Endl;
else
Log() << kWARNING << "Negative number of events found during "
<< "exploration of root cell" << Endl;
}
for (k=0; k<fDim;k++){
fMaskDiv[k] =1;
if ( fInhiDiv[k]==1) fMaskDiv[k] =0;
}
kBest=-1;
nevMC = ceSum[2];
Double_t intTrue = ceSum[0]/(nevMC+0.000001);
Double_t intDriv=0.;
if (kBest == -1) Varedu(ceSum,kBest,xBest,yBest);
if (CutRMSmin())
intDriv =sqrt( ceSum[1]/nevMC -intTrue*intTrue );
else
intDriv =sqrt(ceSum[1]/nevMC) -intTrue;
cell->SetBest(kBest);
cell->SetXdiv(xBest);
cell->SetIntg(intTrue);
cell->SetDriv(intDriv);
if (CutNmin())
SetCellElement(cell, 0, totevents);
Double_t parIntg, parDriv;
for (parent = cell->GetPare(); parent!=0; parent = parent->GetPare()){
parIntg = parent->GetIntg();
parDriv = parent->GetDriv();
parent->SetIntg( parIntg +intTrue -intOld );
parent->SetDriv( parDriv +intDriv -driOld );
if (CutNmin())
SetCellElement( parent, 0, GetBuildUpCellEvents(parent) + totevents - toteventsOld);
}
delete [] volPart;
delete [] xRand;
}
void TMVA::PDEFoam::Varedu(Double_t ceSum[5], Int_t &kBest, Double_t &xBest, Double_t &yBest)
{
Double_t nent = ceSum[2];
Double_t swAll = ceSum[0];
Double_t sswAll = ceSum[1];
Double_t ssw = sqrt(sswAll)/sqrt(nent);
Double_t swIn,swOut,sswIn,sswOut,xLo,xUp;
kBest =-1;
xBest =0.5;
yBest =1.0;
Double_t maxGain=0.0;
for(Int_t kProj=0; kProj<fDim; kProj++) {
if( fMaskDiv[kProj]) {
Double_t sigmIn =0.0; Double_t sigmOut =0.0;
Double_t sswtBest = gHigh;
Double_t gain =0.0;
Double_t xMin=0.0; Double_t xMax=0.0;
for(Int_t jLo=1; jLo<=fNBin; jLo++) {
Double_t aswIn=0; Double_t asswIn=0;
for(Int_t jUp=jLo; jUp<=fNBin;jUp++) {
aswIn += ((TH1D *)(*fHistEdg)[kProj])->GetBinContent(jUp);
asswIn += Sqr(((TH1D *)(*fHistEdg)[kProj])->GetBinError( jUp));
xLo=(jLo-1.0)/fNBin;
xUp=(jUp*1.0)/fNBin;
swIn = aswIn/nent;
swOut = (swAll-aswIn)/nent;
sswIn = sqrt(asswIn) /sqrt(nent*(xUp-xLo)) *(xUp-xLo);
sswOut= sqrt(sswAll-asswIn)/sqrt(nent*(1.0-xUp+xLo)) *(1.0-xUp+xLo);
if( (sswIn+sswOut) < sswtBest) {
sswtBest = sswIn+sswOut;
gain = ssw-sswtBest;
sigmIn = sswIn -swIn;
sigmOut = sswOut-swOut;
xMin = xLo;
xMax = xUp;
}
}
}
Int_t iLo = (Int_t) (fNBin*xMin);
Int_t iUp = (Int_t) (fNBin*xMax);
if(gain>=maxGain) {
maxGain=gain;
kBest=kProj;
xBest=xMin;
yBest=xMax;
if(iLo == 0) xBest=yBest;
if(iUp == fNBin) yBest=xBest;
}
}
}
if( (kBest >= fDim) || (kBest<0) )
Log() << kFATAL << "Something wrong with kBest" << Endl;
}
void TMVA::PDEFoam::MakeAlpha()
{
fPseRan->RndmArray(fDim,fRvec);
for(Int_t k=0; k<fDim; k++) fAlpha[k] = fRvec[k];
}
Long_t TMVA::PDEFoam::PeekMax()
{
Long_t iCell = -1;
Long_t i;
Double_t drivMax, driv;
Bool_t bCutNmin = kTRUE;
Bool_t bCutRMS = kTRUE;
drivMax = 0;
for(i=0; i<=fLastCe; i++) {
if( fCells[i]->GetStat() == 1 ) {
driv = TMath::Abs( fCells[i]->GetDriv());
if (CutRMSmin()){
bCutRMS = driv > GetRMSmin() ;
Log() << kINFO << "rms[cell "<<i<<"]=" << driv << Endl;
}
if (CutNmin())
bCutNmin = GetBuildUpCellEvents(fCells[i]) > GetNmin();
if(driv > drivMax && bCutNmin && bCutRMS) {
drivMax = driv;
iCell = i;
}
}
}
if (iCell == -1){
if (!bCutNmin)
Log() << kVERBOSE << "Warning: No cell with more than " << GetNmin() << " events found!" << Endl;
else if (!bCutRMS)
Log() << kVERBOSE << "Warning: No cell with RMS/mean > " << GetRMSmin() << " found!" << Endl;
else
Log() << kWARNING << "Warning: PDEFoam::PeekMax: no more candidate cells (drivMax>0) found for further splitting." << Endl;
}
return(iCell);
}
Int_t TMVA::PDEFoam::Divide(PDEFoamCell *cell)
{
Double_t xdiv;
Int_t kBest;
if(fLastCe+1 >= fNCells) Log() << kFATAL << "Buffer limit is reached, fLastCe=fnBuf" << Endl;
cell->SetStat(0);
fNoAct++;
xdiv = cell->GetXdiv();
kBest = cell->GetBest();
if( kBest<0 || kBest>=fDim ) Log() << kFATAL << "Wrong kBest" << Endl;
Int_t d1 = CellFill(1, cell);
Int_t d2 = CellFill(1, cell);
cell->SetDau0((fCells[d1]));
cell->SetDau1((fCells[d2]));
Explore( (fCells[d1]) );
Explore( (fCells[d2]) );
return 1;
}
Double_t TMVA::PDEFoam::Eval(Double_t *xRand, Double_t &event_density)
{
return fDistr->Density(xRand, event_density);
}
void TMVA::PDEFoam::Grow()
{
fTimer->Init(fNCells);
Long_t iCell;
PDEFoamCell* newCell;
while ( (fLastCe+2) < fNCells ) {
iCell = PeekMax();
if ( (iCell<0) || (iCell>fLastCe) ) {
Log() << kVERBOSE << "Break: "<< fLastCe+1 << " cells created" << Endl;
for (Long_t jCell=fLastCe+1; jCell<fNCells; jCell++)
delete fCells[jCell];
fNCells = fLastCe+1;
break;
}
newCell = fCells[iCell];
OutputGrow();
if ( Divide( newCell )==0) break;
}
OutputGrow( kTRUE );
CheckAll(1);
Log() << kINFO << GetNActiveCells() << " active cells created" << Endl;
}
void TMVA::PDEFoam::SetInhiDiv(Int_t iDim, Int_t InhiDiv)
{
if(fDim==0) Log() << kFATAL << "SetInhiDiv: fDim=0" << Endl;
if(fInhiDiv == 0) {
fInhiDiv = new Int_t[ fDim ];
for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
}
if( ( 0<=iDim) && (iDim<fDim)) {
fInhiDiv[iDim] = InhiDiv;
} else
Log() << kFATAL << "Wrong iDim" << Endl;
}
void TMVA::PDEFoam::CheckAll(Int_t level)
{
Int_t errors, warnings;
PDEFoamCell *cell;
Long_t iCell;
errors = 0; warnings = 0;
if (level==1) Log() << "Performing consistency checks for created foam" << Endl;
for(iCell=1; iCell<=fLastCe; iCell++) {
cell = fCells[iCell];
if( ((cell->GetDau0()==0) && (cell->GetDau1()!=0) ) ||
((cell->GetDau1()==0) && (cell->GetDau0()!=0) ) ) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has only one daughter " << iCell << Endl;
}
if( (cell->GetDau0()==0) && (cell->GetDau1()==0) && (cell->GetStat()==0) ) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has no daughter and is inactive " << iCell << Endl;
}
if( (cell->GetDau0()!=0) && (cell->GetDau1()!=0) && (cell->GetStat()==1) ) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has two daughters and is active " << iCell << Endl;
}
if( (cell->GetPare())!=fCells[0] ) {
if ( (cell != cell->GetPare()->GetDau0()) && (cell != cell->GetPare()->GetDau1()) ) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d parent not pointing to this cell " << iCell << Endl;
}
}
if(cell->GetDau0()!=0) {
if(cell != (cell->GetDau0())->GetPare()) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d daughter 0 not pointing to this cell " << iCell << Endl;
}
}
if(cell->GetDau1()!=0) {
if(cell != (cell->GetDau1())->GetPare()) {
errors++;
if (level==1) Log() << kFATAL << "ERROR: Cell's no %d daughter 1 not pointing to this cell " << iCell << Endl;
}
}
if(cell->GetVolume()<1E-50) {
errors++;
if(level==1) Log() << kFATAL << "ERROR: Cell no. %d has Volume of <1E-50" << iCell << Endl;
}
}
for(iCell=0; iCell<=fLastCe; iCell++) {
cell = fCells[iCell];
if( (cell->GetStat()==1) && (cell->GetVolume()<1E-11) ) {
errors++;
if(level==1) Log() << kFATAL << "ERROR: Cell no. " << iCell << " is active but Volume is 0 " << Endl;
}
}
if(level==1){
Log() << kINFO << "Check has found " << errors << " errors and " << warnings << " warnings." << Endl;
}
if(errors>0){
Info("CheckAll","Check - found total %d errors \n",errors);
}
}
void TMVA::PDEFoam::PrintCells(void)
{
Long_t iCell;
for(iCell=0; iCell<=fLastCe; iCell++) {
Log()<<"Cell["<<iCell<<"]={ ";
Log()<<" "<< fCells[iCell]<<" ";
Log()<<Endl;
fCells[iCell]->Print("1");
Log()<<"}"<<Endl;
}
}
void TMVA::PDEFoam::RemoveEmptyCell( Int_t iCell )
{
Double_t volume = fCells[iCell]->GetVolume();
if (!fCells[iCell]->GetStat() || volume>0){
Log() << "<RemoveEmptyCell>: cell " << iCell
<< "is not active or has volume>0 ==> doesn't need to be removed" << Endl;
return;
}
PDEFoamCell *pCell = fCells[iCell]->GetPare();
PDEFoamCell *ppCell = fCells[iCell]->GetPare()->GetPare();
PDEFoamCell *sCell;
if (pCell->GetDau0() == fCells[iCell])
sCell = pCell->GetDau1();
else
sCell = pCell->GetDau0();
if (pCell->GetIntg() != sCell->GetIntg())
Log() << kWARNING << "<RemoveEmptyCell> Error: cell integrals are not equal!"
<< " Intg(parent cell)=" << pCell->GetIntg()
<< " Intg(sister cell)=" << sCell->GetIntg()
<< Endl;
if (ppCell->GetDau0() == pCell)
ppCell->SetDau0(sCell);
else
ppCell->SetDau1(sCell);
sCell->SetPare(ppCell);
fCells[iCell]->SetStat(0);
pCell->SetStat(0);
}
void TMVA::PDEFoam::CheckCells( Bool_t remove_empty_cells )
{
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!fCells[iCell]->GetStat())
continue;
Double_t volume = fCells[iCell]->GetVolume();
if (volume<1e-10){
if (volume<=0){
Log() << kWARNING << "Critical: cell volume negative or zero! volume="
<< volume << " cell number: " << iCell << Endl;
if (remove_empty_cells){
Log() << kWARNING << "Remove cell " << iCell << Endl;
RemoveEmptyCell(iCell);
}
}
else {
Log() << kWARNING << "Cell volume close to zero! volume="
<< volume << " cell number: " << iCell << Endl;
}
}
}
}
void TMVA::PDEFoam::PrintCellElements()
{
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!fCells[iCell]->GetStat()) continue;
Log() << "cell[" << iCell << "] elements: [";
for (UInt_t i=0; i<GetNElements(); i++){
if (i>0) Log() << " ; ";
Log() << GetCellElement(fCells[iCell], i);
}
Log() << "]" << Endl;
}
}
void TMVA::PDEFoam::ResetCellElements(Bool_t allcells)
{
if (!fCells || GetNElements()==0) return;
Log() << kVERBOSE << "Delete old cell elements" << Endl;
for(Long_t iCell=0; iCell<fNCells; iCell++) {
if (fCells[iCell]->GetElement() != 0){
delete dynamic_cast<TVectorD*>(fCells[iCell]->GetElement());
fCells[iCell]->SetElement(0);
}
}
if (allcells){
Log() << kVERBOSE << "Reset new cell elements to "
<< GetNElements() << " value(s) per cell" << Endl;
for(Long_t iCell=0; iCell<fNCells; iCell++) {
TVectorD *elem = new TVectorD(GetNElements());
for (UInt_t i=0; i<GetNElements(); i++)
(*elem)(i) = 0.;
fCells[iCell]->SetElement(elem);
}
} else {
Log() << kVERBOSE << "Reset active cell elements to "
<< GetNElements() << " value(s) per cell" << Endl;
for(Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat()))
continue;
TVectorD *elem = new TVectorD(GetNElements());
for (UInt_t i=0; i<GetNElements(); i++)
(*elem)(i) = 0.;
fCells[iCell]->SetElement(elem);
}
}
}
void TMVA::PDEFoam::CalcCellTarget()
{
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat()))
continue;
Double_t N_ev = GetCellElement(fCells[iCell], 0);
Double_t tar = GetCellElement(fCells[iCell], 1);
if (N_ev > 1e-20){
SetCellElement(fCells[iCell], 0, tar/N_ev);
SetCellElement(fCells[iCell], 1, tar/TMath::Sqrt(N_ev));
}
else {
SetCellElement(fCells[iCell], 0, 0.0 );
SetCellElement(fCells[iCell], 1, -1 );
}
}
}
void TMVA::PDEFoam::CalcCellDiscr()
{
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat()))
continue;
Double_t N_sig = GetCellElement(fCells[iCell], 0);
Double_t N_bg = GetCellElement(fCells[iCell], 1);
if (N_sig<0.) {
Log() << kWARNING << "Negative number of signal events in cell " << iCell
<< ": " << N_sig << ". Set to 0." << Endl;
N_sig=0.;
}
if (N_bg<0.) {
Log() << kWARNING << "Negative number of background events in cell " << iCell
<< ": " << N_bg << ". Set to 0." << Endl;
N_bg=0.;
}
if (N_sig+N_bg > 1e-10){
SetCellElement(fCells[iCell], 0, N_sig/(N_sig+N_bg));
SetCellElement(fCells[iCell], 1, TMath::Sqrt( TMath::Power ( N_sig/TMath::Power(N_sig+N_bg,2),2)*N_sig +
TMath::Power ( N_bg /TMath::Power(N_sig+N_bg,2),2)*N_bg ) );
}
else {
SetCellElement(fCells[iCell], 0, 0.5);
SetCellElement(fCells[iCell], 1, 1. );
}
}
}
Double_t TMVA::PDEFoam::GetCellDiscr( std::vector<Float_t> xvec, EKernel kernel )
{
Double_t result = 0.;
std::vector<Float_t> txvec = VarTransform(xvec);
PDEFoamCell *cell= FindCell(txvec);
if (!cell) return -999.;
if (kernel == kNone) result = GetCellValue(cell, kDiscriminator);
else if (kernel == kGaus) {
Double_t norm = 0.;
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
Double_t cell_discr = GetCellValue(fCells[iCell], kDiscriminator);
Double_t gau = WeightGaus(fCells[iCell], txvec);
result += gau * cell_discr;
norm += gau;
}
result /= norm;
}
else if (kernel == kLinN) {
result = WeightLinNeighbors(txvec, kDiscriminator);
}
else {
Log() << kFATAL << "GetCellDiscr: ERROR: wrong kernel!" << Endl;
result = -999.0;
}
return result;
}
void TMVA::PDEFoam::FillFoamCells(const Event* ev, Bool_t NoNegWeights)
{
std::vector<Float_t> values = ev->GetValues();
std::vector<Float_t> targets = ev->GetTargets();
Float_t weight = ev->GetOriginalWeight();
EFoamType ft = GetFoamType();
if((NoNegWeights && weight<=0) || weight==0)
return;
if (ft == kMultiTarget)
values.insert(values.end(), targets.begin(), targets.end());
PDEFoamCell *cell = FindCell(VarTransform(values));
if (!cell) {
Log() << kFATAL << "<PDEFoam::FillFoamCells>: No cell found!" << Endl;
return;
}
if (ft == kSeparate || ft == kMultiTarget){
SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
SetCellElement(cell, 1, GetCellElement(cell, 1) + weight*weight);
} else if (ft == kDiscr){
if (ev->IsSignal())
SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
else
SetCellElement(cell, 1, GetCellElement(cell, 1) + weight);
} else if (ft == kMonoTarget){
SetCellElement(cell, 0, GetCellElement(cell, 0) + weight);
SetCellElement(cell, 1, GetCellElement(cell, 1) + weight*targets.at(0));
}
}
Double_t TMVA::PDEFoam::GetCellRegValue0( std::vector<Float_t> xvec, EKernel kernel )
{
Double_t result = 0.;
std::vector<Float_t> txvec = VarTransform(xvec);
PDEFoamCell *cell = FindCell(txvec);
if (!cell) {
Log() << kFATAL << "<GetCellRegValue0> ERROR: No cell found!" << Endl;
return -999.;
}
if (kernel == kNone){
if (GetCellValue(cell, kTarget0Error)!=-1)
result = GetCellValue(cell, kTarget0);
else
result = GetAverageNeighborsValue(txvec, kTarget0);
}
else if (kernel == kGaus){
Double_t norm = 0.;
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
Double_t cell_val = 0;
if (GetCellValue(fCells[iCell], kTarget0Error) != -1)
cell_val = GetCellValue(fCells[iCell], kTarget0);
else
cell_val = GetAverageNeighborsValue(txvec, kTarget0);
Double_t gau = WeightGaus(fCells[iCell], txvec);
result += gau * cell_val;
norm += gau;
}
result /= norm;
}
else if (kernel == kLinN) {
if (GetCellValue(cell, kTarget0Error) != -1)
result = WeightLinNeighbors(txvec, kTarget0, -1, -1, kTRUE);
else
result = GetAverageNeighborsValue(txvec, kTarget0);
}
else {
Log() << kFATAL << "ERROR: unknown kernel!" << Endl;
return -999.;
}
return result;
}
Double_t TMVA::PDEFoam::GetAverageNeighborsValue( std::vector<Float_t> txvec,
ECellValue cv )
{
const Double_t xoffset = 1.e-6;
Double_t norm = 0;
Double_t result = 0;
PDEFoamCell *cell = FindCell(txvec);
PDEFoamVect cellSize(GetTotDim());
PDEFoamVect cellPosi(GetTotDim());
cell->GetHcub(cellPosi, cellSize);
for (Int_t dim=0; dim<GetTotDim(); dim++) {
std::vector<Float_t> ntxvec = txvec;
PDEFoamCell* left_cell = 0;
PDEFoamCell* right_cell = 0;
ntxvec[dim] = cellPosi[dim]-xoffset;
left_cell = FindCell(ntxvec);
if (!CellValueIsUndefined(left_cell)){
result += GetCellValue(left_cell, cv);
norm++;
}
ntxvec[dim] = cellPosi[dim]+cellSize[dim]+xoffset;
right_cell = FindCell(ntxvec);
if (!CellValueIsUndefined(right_cell)){
result += GetCellValue(right_cell, cv);
norm++;
}
}
if (norm>0) result /= norm;
else result = 0;
return result;
}
Bool_t TMVA::PDEFoam::CellValueIsUndefined( PDEFoamCell* cell )
{
EFoamType ft = GetFoamType();
switch(ft){
case kSeparate:
return kFALSE;
break;
case kDiscr:
return kFALSE;
break;
case kMonoTarget:
return GetCellValue(cell, kTarget0Error) == -1;
break;
case kMultiTarget:
return kFALSE;
break;
default:
return kFALSE;
}
}
std::vector<Float_t> TMVA::PDEFoam::GetCellTargets( std::vector<Float_t> tvals, ETargetSelection ts )
{
std::vector<Float_t> target(GetTotDim()-tvals.size(), 0);
std::vector<Float_t> norm(target);
Double_t max_dens = 0.;
std::vector<PDEFoamCell*> cells = FindCells(tvals);
if (cells.size()<1) return target;
std::vector<PDEFoamCell*>::iterator cell_it(cells.begin());
for (cell_it=cells.begin(); cell_it!=cells.end(); cell_it++){
Double_t cell_density = GetCellValue(*cell_it, kDensity);
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
(*cell_it)->GetHcub(cellPosi, cellSize);
if (ts==kMean){
for (UInt_t itar=0; itar<target.size(); itar++){
UInt_t idim = itar+tvals.size();
target.at(itar) += cell_density *
VarTransformInvers(idim, cellPosi[idim]+0.5*cellSize[idim]);
norm.at(itar) += cell_density;
}
} else {
if (cell_density > max_dens){
max_dens = cell_density;
for (UInt_t itar=0; itar<target.size(); itar++){
UInt_t idim = itar+tvals.size();
target.at(itar) =
VarTransformInvers(idim, cellPosi[idim]+0.5*cellSize[idim]);
}
}
}
}
if (ts==kMean){
for (UInt_t itar=0; itar<target.size(); itar++){
if (norm.at(itar)>1.0e-15)
target.at(itar) /= norm.at(itar);
else
target.at(itar) = (fXmax[itar+tvals.size()]-fXmin[itar+tvals.size()])/2.;
}
}
return target;
}
std::vector<Float_t> TMVA::PDEFoam::GetProjectedRegValue( std::vector<Float_t> vals, EKernel kernel, ETargetSelection ts )
{
const Float_t xsmall = 1.e-7;
for (UInt_t l=0; l<vals.size(); l++) {
if (vals.at(l) <= fXmin[l]){
vals.at(l) = fXmin[l] + xsmall;
}
else if (vals.at(l) >= fXmax[l]){
vals.at(l) = fXmax[l] - xsmall;
}
}
std::vector<Float_t> txvec = VarTransform(vals);
std::vector<Float_t> target(GetTotDim()-txvec.size(), 0);
if (kernel == kNone)
return GetCellTargets(txvec, ts);
else if (kernel == kGaus){
std::vector<Float_t> norm(target);
for (Long_t ice=0; ice<=fLastCe; ice++) {
if (!(fCells[ice]->GetStat())) continue;
Double_t gau = WeightGaus(fCells[ice], txvec, vals.size());
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
fCells[ice]->GetHcub(cellPosi, cellSize);
std::vector<Float_t> new_vec;
for (UInt_t k=0; k<txvec.size(); k++)
new_vec.push_back(cellPosi[k] + 0.5*cellSize[k]);
std::vector<Float_t> val = GetCellTargets(new_vec, ts);
for (UInt_t itar=0; itar<target.size(); itar++){
target.at(itar) += gau * val.at(itar);
norm.at(itar) += gau;
}
}
for (UInt_t itar=0; itar<target.size(); itar++){
if (norm.at(itar)<1.0e-20){
Log() << kWARNING << "Warning: norm too small!" << Endl;
target.at(itar) = 0.;
} else
target.at(itar) /= norm.at(itar);
}
}
else {
Log() << kFATAL << "<GetProjectedRegValue> ERROR: unsupported kernel!" << Endl;
return std::vector<Float_t>(GetTotDim()-txvec.size(), 0);
}
return target;
}
Double_t TMVA::PDEFoam::GetCellDensity( std::vector<Float_t> xvec, EKernel kernel )
{
Double_t result = 0;
std::vector<Float_t> txvec = VarTransform(xvec);
PDEFoamCell *cell = FindCell(txvec);
if (!cell) {
Log() << kFATAL << "<GetCellDensity(event)> ERROR: No cell found!" << Endl;
return -999.;
}
if (kernel == kNone){
return GetCellValue(cell, kDensity);
}
else if (kernel == kGaus){
Double_t norm = 0.;
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
Double_t cell_dens = GetCellValue(fCells[iCell], kDensity);
Double_t gau = WeightGaus(fCells[iCell], txvec);
result += gau * cell_dens;
norm += gau;
}
result /= norm;
}
else if (kernel == kLinN){
result = WeightLinNeighbors(txvec, kDensity);
}
else {
Log() << kFATAL << "<GetCellDensity(event)> ERROR: unknown kernel!" << Endl;
return -999.;
}
return result;
}
Double_t TMVA::PDEFoam::GetCellValue( PDEFoamCell* cell, ECellValue cv )
{
switch(cv){
case kTarget0:
if (GetFoamType() == kMonoTarget) return GetCellElement(cell, 0);
break;
case kTarget0Error:
if (GetFoamType() == kMonoTarget) return GetCellElement(cell, 1);
break;
case kDiscriminator:
if (GetFoamType() == kDiscr) return GetCellElement(cell, 0);
break;
case kDiscriminatorError:
if (GetFoamType() == kDiscr) return GetCellElement(cell, 1);
break;
case kMeanValue:
return cell->GetIntg();
break;
case kRms:
return cell->GetDriv();
break;
case kRmsOvMean:
if (cell->GetIntg() != 0) return cell->GetDriv()/cell->GetIntg();
break;
case kNev:
if (GetFoamType() == kSeparate || GetFoamType() == kMultiTarget)
return GetCellElement(cell, 0);
break;
case kDensity: {
Double_t volume = cell->GetVolume();
if ( volume > 1.0e-10 ){
return GetCellValue(cell, kNev)/volume;
} else {
if (volume<=0){
cell->Print("1");
Log() << kWARNING << "<GetCellDensity(cell)>: ERROR: cell volume"
<< " negative or zero!"
<< " ==> return cell density 0!"
<< " cell volume=" << volume
<< " cell entries=" << GetCellValue(cell, kNev) << Endl;
return 0;
} else
Log() << kWARNING << "<GetCellDensity(cell)>: WARNING: cell volume"
<< " close to zero!"
<< " cell volume: " << volume << Endl;
}
}
default:
return 0;
}
return 0;
}
Double_t TMVA::PDEFoam::GetCellValue(std::vector<Float_t> xvec, ECellValue cv)
{
return GetCellValue(FindCell(VarTransform(xvec)), cv);
}
Double_t TMVA::PDEFoam::GetBuildUpCellEvents( PDEFoamCell* cell )
{
return GetCellElement(cell, 0);
}
Double_t TMVA::PDEFoam::WeightLinNeighbors( std::vector<Float_t> txvec, ECellValue cv, Int_t dim1, Int_t dim2, Bool_t TreatEmptyCells )
{
Double_t result = 0.;
UInt_t norm = 0;
const Double_t xoffset = 1.e-6;
if (txvec.size() != UInt_t(GetTotDim()))
Log() << kFATAL << "Wrong dimension of event variable!" << Endl;
PDEFoamCell *cell= FindCell(txvec);
PDEFoamVect cellSize(GetTotDim());
PDEFoamVect cellPosi(GetTotDim());
cell->GetHcub(cellPosi, cellSize);
Double_t cellval = 0;
if (!(TreatEmptyCells && CellValueIsUndefined(cell)))
cellval = GetCellValue(cell, cv);
else
cellval = GetAverageNeighborsValue(txvec, cv);
for (Int_t dim=0; dim<GetTotDim(); dim++) {
std::vector<Float_t> ntxvec = txvec;
Double_t mindist;
PDEFoamCell *mindistcell = 0;
mindist = (txvec[dim]-cellPosi[dim])/cellSize[dim];
if (mindist<0.5) {
ntxvec[dim] = cellPosi[dim]-xoffset;
mindistcell = FindCell(ntxvec);
} else {
mindist=1-mindist;
ntxvec[dim] = cellPosi[dim]+cellSize[dim]+xoffset;
mindistcell = FindCell(ntxvec);
}
Double_t mindistcellval = 0;
if (dim1>=0 && dim1<GetTotDim() &&
dim2>=0 && dim2<GetTotDim() &&
dim1!=dim2){
cellval = GetProjectionCellValue(cell, dim1, dim2, cv);
mindistcellval = GetProjectionCellValue(mindistcell, dim1, dim2, cv);
} else {
mindistcellval = GetCellValue(mindistcell, cv);
}
if (!(TreatEmptyCells && CellValueIsUndefined(mindistcell))){
result += cellval * (0.5 + mindist);
result += mindistcellval * (0.5 - mindist);
norm++;
}
}
if (norm==0) return cellval;
else return result/norm;
}
Float_t TMVA::PDEFoam::WeightGaus( PDEFoamCell* cell, std::vector<Float_t> txvec,
UInt_t dim )
{
PDEFoamVect cellSize(GetTotDim());
PDEFoamVect cellPosi(GetTotDim());
cell->GetHcub(cellPosi, cellSize);
UInt_t dims;
if (dim == 0)
dims = GetTotDim();
else if (dim <= UInt_t(GetTotDim()))
dims = dim;
else {
Log() << kFATAL << "ERROR: too many given dimensions for Gaus weight!" << Endl;
return 0.;
}
std::vector<Float_t> cell_center;
for (UInt_t i=0; i<dims; i++){
if (txvec[i]<0.) txvec[i]=0.;
if (txvec[i]>1.) txvec[i]=1.;
if (cellPosi[i] > txvec.at(i))
cell_center.push_back(cellPosi[i]);
else if (cellPosi[i]+cellSize[i] < txvec.at(i))
cell_center.push_back(cellPosi[i]+cellSize[i]);
else
cell_center.push_back(txvec.at(i));
}
Float_t distance = 0.;
for (UInt_t i=0; i<dims; i++)
distance += TMath::Power(txvec.at(i)-cell_center.at(i), 2);
distance = TMath::Sqrt(distance);
Float_t width = 1./GetPDEFoamVolumeFraction();
if (width < 1.0e-10)
Log() << kWARNING << "Warning: wrong volume fraction: " << GetPDEFoamVolumeFraction() << Endl;
return TMath::Gaus(distance, 0, width, kFALSE);
}
TMVA::PDEFoamCell* TMVA::PDEFoam::FindCell( std::vector<Float_t> xvec )
{
PDEFoamVect cellPosi0(GetTotDim()), cellSize0(GetTotDim());
PDEFoamCell *cell, *cell0;
cell=fCells[0];
Int_t idim=0;
while (cell->GetStat()!=1) {
idim=cell->GetBest();
cell0=cell->GetDau0();
cell0->GetHcub(cellPosi0,cellSize0);
if (xvec.at(idim)<=cellPosi0[idim]+cellSize0[idim])
cell=cell0;
else
cell=(cell->GetDau1());
}
return cell;
}
void TMVA::PDEFoam::FindCellsRecursive(std::vector<Float_t> txvec, PDEFoamCell* cell, std::vector<PDEFoamCell*> &cells)
{
PDEFoamVect cellPosi0(GetTotDim()), cellSize0(GetTotDim());
PDEFoamCell *cell0;
Int_t idim=0;
while (cell->GetStat()!=1) {
idim=cell->GetBest();
if (idim < Int_t(txvec.size())){
cell0=cell->GetDau0();
cell0->GetHcub(cellPosi0,cellSize0);
if (txvec.at(idim)<=cellPosi0[idim]+cellSize0[idim])
cell=cell0;
else
cell=cell->GetDau1();
} else {
FindCellsRecursive(txvec, cell->GetDau0(), cells);
FindCellsRecursive(txvec, cell->GetDau1(), cells);
return;
}
}
cells.push_back(cell);
}
std::vector<TMVA::PDEFoamCell*> TMVA::PDEFoam::FindCells(std::vector<Float_t> txvec)
{
std::vector<PDEFoamCell*> cells(0);
FindCellsRecursive(txvec, fCells[0], cells);
return cells;
}
TH1D* TMVA::PDEFoam::Draw1Dim( const char *opt, Int_t nbin )
{
if ( GetTotDim()!=1 ) return 0;
ECellValue cell_value = kNev;
EFoamType foam_type = GetFoamType();
if (strcmp(opt,"cell_value")==0){
if (foam_type == kSeparate || foam_type == kMultiTarget){
cell_value = kNev;
} else if (foam_type == kDiscr){
cell_value = kDiscriminator;
} else if (foam_type == kMonoTarget){
cell_value = kTarget0;
} else {
Log() << kFATAL << "unknown foam type" << Endl;
return 0;
}
} else if (strcmp(opt,"rms")==0){
cell_value = kRms;
} else if (strcmp(opt,"rms_ov_mean")==0){
cell_value = kRmsOvMean;
} else {
Log() << kFATAL << "<Draw1Dim>: unknown option:" << opt << Endl;
return 0;
}
char hname[100]; char htit[100];
sprintf(htit,"1-dimensional Foam: %s", opt);
sprintf(hname,"h%s",opt);
TH1D* h1=(TH1D*)gDirectory->Get(hname);
if (h1) delete h1;
h1= new TH1D(hname, htit, nbin, fXmin[0], fXmax[0]);
if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
std::vector<Float_t> xvec(GetTotDim(), 0.);
for (Int_t ibinx=1; ibinx<=nbin; ibinx++) {
xvec.at(0) = h1->GetBinCenter(ibinx);
std::vector<Float_t> txvec = VarTransform(xvec);
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
fCells[iCell]->GetHcub(cellPosi,cellSize);
const Double_t xsmall = 1.e-10;
if (!( (txvec.at(0)>cellPosi[0]-xsmall) &&
(txvec.at(0)<=cellPosi[0]+cellSize[0]+xsmall) ) )
continue;
Double_t vol = fCells[iCell]->GetVolume();
if (vol<1e-10) {
Log() << kWARNING << "Project: ERROR: Volume too small!" << Endl;
continue;
}
h1->SetBinContent(ibinx,
GetCellValue(fCells[iCell], cell_value) + h1->GetBinContent(ibinx));
}
}
return h1;
}
TH2D* TMVA::PDEFoam::Project2( Int_t idim1, Int_t idim2, const char *opt, const char *ker, UInt_t maxbins )
{
if ((idim1>=GetTotDim()) || (idim1<0) ||
(idim2>=GetTotDim()) || (idim2<0) ||
(idim1==idim2) )
return 0;
ECellValue cell_value = kNev;
EFoamType foam_type = GetFoamType();
if (strcmp(opt,"cell_value")==0){
if (foam_type == kSeparate || foam_type == kMultiTarget){
cell_value = kNev;
} else if (foam_type == kDiscr){
cell_value = kDiscriminator;
} else if (foam_type == kMonoTarget){
cell_value = kTarget0;
} else {
Log() << kFATAL << "unknown foam type" << Endl;
return 0;
}
} else if (strcmp(opt,"rms")==0){
cell_value = kRms;
} else if (strcmp(opt,"rms_ov_mean")==0){
cell_value = kRmsOvMean;
} else {
Log() << kFATAL << "unknown option given" << Endl;
return 0;
}
EKernel kernel = kNone;
if (!strcmp(ker, "kNone"))
kernel = kNone;
else if (!strcmp(ker, "kGaus"))
kernel = kGaus;
else if (!strcmp(ker, "kLinN"))
kernel = kLinN;
else
Log() << kWARNING << "Warning: wrong kernel! using kNone instead" << Endl;
Double_t bin_width = 1.;
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
fCells[iCell]->GetHcub(cellPosi,cellSize);
for (Int_t d1=0; d1<GetTotDim(); d1++)
if (cellSize[d1]<bin_width && cellSize[d1]>0)
bin_width = cellSize[d1];
}
UInt_t nbin = UInt_t(1./bin_width);
if (maxbins>0 && nbin>maxbins)
nbin = maxbins;
if (nbin>1000){
Log() << kWARNING << "Warning: number of bins too big: " << nbin
<< " Using 1000 bins for each dimension instead." << Endl;
nbin = 1000;
}
char hname[100], htit[100];
sprintf(htit,"%s var%d vs var%d",opt,idim1,idim2);
sprintf(hname,"h%s_%d_vs_%d",opt,idim1,idim2);
TH2D* h1=(TH2D*)gDirectory->Get(hname);
if (h1) delete h1;
h1= new TH2D(hname, htit, nbin, fXmin[idim1], fXmax[idim1], nbin, fXmin[idim2], fXmax[idim2]);
if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
for (Long_t iCell=0; iCell<=fLastCe; iCell++) {
if (!(fCells[iCell]->GetStat())) continue;
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
fCells[iCell]->GetHcub(cellPosi,cellSize);
Double_t var = GetProjectionCellValue(fCells[iCell], idim1, idim2, cell_value);
const Double_t xsmall = (1.e-20)*cellSize[idim1];
const Double_t ysmall = (1.e-20)*cellSize[idim2];
Double_t x1 = VarTransformInvers( idim1, cellPosi[idim1]+xsmall );
Double_t y1 = VarTransformInvers( idim2, cellPosi[idim2]+ysmall );
Double_t x2 = VarTransformInvers( idim1, cellPosi[idim1]+cellSize[idim1]-xsmall );
Double_t y2 = VarTransformInvers( idim2, cellPosi[idim2]+cellSize[idim2]-ysmall );
Int_t xbin_start = h1->GetXaxis()->FindBin(x1);
Int_t xbin_stop = h1->GetXaxis()->FindBin(x2);
Int_t ybin_start = h1->GetYaxis()->FindBin(y1);
Int_t ybin_stop = h1->GetYaxis()->FindBin(y2);
for (Int_t ibinx=xbin_start; ibinx<xbin_stop; ibinx++) {
for (Int_t ibiny=ybin_start; ibiny<ybin_stop; ibiny++) {
if (kernel == kGaus){
Double_t result = 0.;
Double_t norm = 0.;
Double_t x_curr =
VarTransform( idim1, ((x2-x1)*ibinx - x2*xbin_start + x1*xbin_stop)/(xbin_stop-xbin_start) );
Double_t y_curr =
VarTransform( idim2, ((y2-y1)*ibiny - y2*ybin_start + y1*ybin_stop)/(ybin_stop-ybin_start) );
for (Long_t ice=0; ice<=fLastCe; ice++) {
if (!(fCells[ice]->GetStat())) continue;
Double_t cell_var = GetProjectionCellValue(fCells[ice], idim1, idim2, cell_value);
std::vector<Float_t> coor;
for (Int_t i=0; i<GetTotDim(); i++) {
if (i == idim1)
coor.push_back(x_curr);
else if (i == idim2)
coor.push_back(y_curr);
else
coor.push_back(cellPosi[i] + 0.5*cellSize[i]);
}
Double_t weight_ = WeightGaus(fCells[ice], coor);
result += weight_ * cell_var;
norm += weight_;
}
var = result/norm;
}
else if (kernel == kLinN){
Double_t x_curr =
VarTransform( idim1, ((x2-x1)*ibinx - x2*xbin_start + x1*xbin_stop)/(xbin_stop-xbin_start) );
Double_t y_curr =
VarTransform( idim2, ((y2-y1)*ibiny - y2*ybin_start + y1*ybin_stop)/(ybin_stop-ybin_start) );
std::vector<Float_t> coor;
for (Int_t i=0; i<GetTotDim(); i++) {
if (i == idim1)
coor.push_back(x_curr);
else if (i == idim2)
coor.push_back(y_curr);
else
coor.push_back(cellPosi[i] + 0.5*cellSize[i]);
}
var = WeightLinNeighbors(coor, cell_value, idim1, idim2);
}
h1->SetBinContent(ibinx, ibiny, var + h1->GetBinContent(ibinx, ibiny));
}
}
}
return h1;
}
Double_t TMVA::PDEFoam::GetProjectionCellValue( PDEFoamCell* cell,
Int_t idim1,
Int_t idim2,
ECellValue cv )
{
Double_t val = 0.;
PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
cell->GetHcub(cellPosi,cellSize);
const Double_t foam_area = (fXmax[idim1]-fXmin[idim1])*(fXmax[idim2]-fXmin[idim2]);
if (cv == kNev){
Double_t area = cellSize[idim1] * cellSize[idim2];
if (area<1e-20){
Log() << kWARNING << "PDEFoam::Project2: Warning, cell volume too small --> skiping cell!" << Endl;
return 0;
}
val = GetCellValue(cell, kNev)/(area*foam_area);
}
else if (cv == kRms){
val = GetCellValue(cell, kRms);
}
else if (cv == kRmsOvMean){
val = GetCellValue(cell, kRmsOvMean);
}
else if (cv == kDiscriminator){
Double_t area_cell = 1.;
for (Int_t d1=0; d1<GetTotDim(); d1++){
if ((d1!=idim1) && (d1!=idim2))
area_cell *= cellSize[d1];
}
if (area_cell<1e-20){
Log() << kWARNING << "PDEFoam::Project2: Warning, cell volume too small --> skiping cell!" << Endl;
return 0;
}
val = GetCellValue(cell, kDiscriminator)*area_cell;
}
else if (cv == kDiscriminatorError){
val = GetCellValue(cell, kDiscriminator);
}
else if (cv == kTarget0){
val = GetCellValue(cell, kTarget0);
}
else {
Log() << kFATAL << "Project2: unknown option" << Endl;
return 0;
}
return val;
}
TVectorD* TMVA::PDEFoam::GetCellElements( std::vector<Float_t> xvec )
{
assert(unsigned(GetTotDim()) == xvec.size());
return dynamic_cast<TVectorD*>(FindCell(VarTransform(xvec))->GetElement());
}
Double_t TMVA::PDEFoam::GetCellElement( PDEFoamCell *cell, UInt_t i )
{
assert(i < GetNElements());
return (*dynamic_cast<TVectorD*>(cell->GetElement()))(i);
}
void TMVA::PDEFoam::SetCellElement( PDEFoamCell *cell, UInt_t i, Double_t value )
{
if (i >= GetNElements()){
Log() << kFATAL << "ERROR: Index out of range" << Endl;
return;
}
TVectorD *vec = dynamic_cast<TVectorD*>(cell->GetElement());
if (!vec)
Log() << kFATAL << "<SetCellElement> ERROR: cell element is not a TVectorD*" << Endl;
(*vec)(i) = value;
}
void TMVA::PDEFoam::OutputGrow( Bool_t finished )
{
if (finished) {
Log() << kINFO << "Elapsed time: " + fTimer->GetElapsedTime()
<< " " << Endl;
return;
}
Int_t modulo = 1;
if (fNCells >= 100) modulo = Int_t(fNCells/100);
if (fLastCe%modulo == 0) fTimer->DrawProgressBar( fLastCe );
}
void TMVA::PDEFoam::RootPlot2dim( const TString& filename, std::string what,
Bool_t CreateCanvas, Bool_t colors, Bool_t log_colors )
{
if (GetTotDim() != 2)
Log() << kFATAL << "RootPlot2dim() can only be used with "
<< "two-dimensional foams!" << Endl;
ECellValue cell_value = kNev;
Bool_t plotcellnumber = kFALSE;
Bool_t fillcells = kTRUE;
if (what == "mean")
cell_value = kMeanValue;
else if (what == "nevents")
cell_value = kNev;
else if (what == "density")
cell_value = kDensity;
else if (what == "rms")
cell_value = kRms;
else if (what == "rms_ov_mean")
cell_value = kRmsOvMean;
else if (what == "discr")
cell_value = kDiscriminator;
else if (what == "discrerr")
cell_value = kDiscriminatorError;
else if (what == "monotarget")
cell_value = kTarget0;
else if (what == "cellnumber")
plotcellnumber = kTRUE;
else if (what == "nofill") {
plotcellnumber = kTRUE;
fillcells = kFALSE;
} else {
cell_value = kMeanValue;
Log() << kWARNING << "Unknown option, plotting mean!" << Endl;
}
std::ofstream outfile(filename, std::ios::out);
Double_t x1,y1,x2,y2,x,y;
Long_t iCell;
Double_t offs =0.01;
Double_t lpag =1-2*offs;
outfile<<"{" << std::endl;
if (!colors) {
outfile << "TColor *graycolors[100];" << std::endl;
outfile << "for (Int_t i=0.; i<100; i++)" << std::endl;
outfile << " graycolors[i]=new TColor(1000+i, 1-(Float_t)i/100.,1-(Float_t)i/100.,1-(Float_t)i/100.);"<< std::endl;
}
if (CreateCanvas)
outfile << "cMap = new TCanvas(\"" << fName << "\",\"Cell Map for "
<< fName << "\",600,600);" << std::endl;
outfile<<"TBox*a=new TBox();"<<std::endl;
outfile<<"a->SetFillStyle(0);"<<std::endl;
outfile<<"a->SetLineWidth(4);"<<std::endl;
outfile<<"TBox *b1=new TBox();"<<std::endl;
if (fillcells) {
outfile << (colors ? "gStyle->SetPalette(1, 0);" : "gStyle->SetPalette(0);")
<< std::endl;
outfile <<"b1->SetFillStyle(1001);"<<std::endl;
outfile<<"TBox *b2=new TBox();"<<std::endl;
outfile <<"b2->SetFillStyle(0);"<<std::endl;
}
else {
outfile <<"b1->SetFillStyle(0);"<<std::endl;
}
Int_t lastcell = fLastCe;
if (fillcells)
(colors ? gStyle->SetPalette(1, 0) : gStyle->SetPalette(0) );
Double_t zmin = 1E8;
Double_t zmax = -1E8;
Double_t value=0.;
for (iCell=1; iCell<=lastcell; iCell++) {
if ( fCells[iCell]->GetStat() == 1) {
if (plotcellnumber)
value = iCell;
else
value = GetCellValue(fCells[iCell], cell_value);
if (value<zmin)
zmin=value;
if (value>zmax)
zmax=value;
}
}
outfile << "// observed minimum and maximum of distribution: " << std::endl;
outfile << "// Double_t zmin = "<< zmin << ";" << std::endl;
outfile << "// Double_t zmax = "<< zmax << ";" << std::endl;
if (log_colors) {
if (zmin<1)
zmin=1;
zmin=TMath::Log(zmin);
zmax=TMath::Log(zmax);
outfile << "// logarthmic color scale used " << std::endl;
} else
outfile << "// linear color scale used " << std::endl;
outfile << "// used minimum and maximum of distribution (taking into account log scale if applicable): " << std::endl;
outfile << "Double_t zmin = "<< zmin << ";" << std::endl;
outfile << "Double_t zmax = "<< zmax << ";" << std::endl;
Int_t ncolors = colors ? gStyle->GetNumberOfColors() : 100;
Double_t dz = zmax - zmin;
Double_t scale = (ncolors-1)/dz;
PDEFoamVect cellPosi(GetTotDim()); PDEFoamVect cellSize(GetTotDim());
outfile << "// =========== Rectangular cells ==========="<< std::endl;
for (iCell=1; iCell<=lastcell; iCell++) {
if ( fCells[iCell]->GetStat() == 1) {
fCells[iCell]->GetHcub(cellPosi,cellSize);
x1 = offs+lpag*(cellPosi[0]);
y1 = offs+lpag*(cellPosi[1]);
x2 = offs+lpag*(cellPosi[0]+cellSize[0]);
y2 = offs+lpag*(cellPosi[1]+cellSize[1]);
value = 0;
if (fillcells) {
if (plotcellnumber)
value = iCell;
else
value = GetCellValue(fCells[iCell], cell_value);
if (log_colors) {
if (value<1.) value=1;
value = TMath::Log(value);
}
Int_t color;
if (colors)
color = gStyle->GetColorPalette(Int_t((value-zmin)*scale));
else
color = 1000+(Int_t((value-zmin)*scale));
outfile << "b1->SetFillColor(" << color << ");" << std::endl;
}
outfile<<"b1->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
if (fillcells)
outfile<<"b2->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
if (lastcell<=250) {
x = offs+lpag*(cellPosi[0]+0.5*cellSize[0]);
y = offs+lpag*(cellPosi[1]+0.5*cellSize[1]);
}
}
}
outfile<<"// ============== End Rectangles ==========="<< std::endl;
outfile << "}" << std::endl;
outfile.flush();
outfile.close();
}
void TMVA::PDEFoam::SetVolumeFraction( Double_t vfr )
{
fDistr->SetVolumeFraction(vfr);
SetPDEFoamVolumeFraction(vfr);
}
void TMVA::PDEFoam::FillBinarySearchTree( const Event* ev, Bool_t NoNegWeights )
{
fDistr->FillBinarySearchTree(ev, GetFoamType(), NoNegWeights);
}
void TMVA::PDEFoam::Init()
{
fDistr->Initialize(GetTotDim());
}
void TMVA::PDEFoam::SetFoamType( EFoamType ft )
{
if (ft==kDiscr)
fDistr->SetDensityCalc(kDISCRIMINATOR);
else if (ft==kMonoTarget)
fDistr->SetDensityCalc(kTARGET);
else
fDistr->SetDensityCalc(kEVENT_DENSITY);
fFoamType = ft;
}
ostream& TMVA::operator<< ( ostream& os, const TMVA::PDEFoam& pdefoam )
{
pdefoam.PrintStream(os);
return os;
}
istream& TMVA::operator>> ( istream& istr, TMVA::PDEFoam& pdefoam )
{
pdefoam.ReadStream(istr);
return istr;
}
void TMVA::PDEFoam::ReadStream( istream & istr )
{
istr >> fLastCe;
istr >> fNCells;
istr >> fDim;
Double_t vfr = -1.;
istr >> vfr;
SetPDEFoamVolumeFraction(vfr);
Log() << kVERBOSE << "Foam dimension: " << GetTotDim() << Endl;
if (fXmin) delete [] fXmin;
if (fXmax) delete [] fXmax;
fXmin = new Double_t[GetTotDim()];
fXmax = new Double_t[GetTotDim()];
for (Int_t i=0; i<GetTotDim(); i++)
istr >> fXmin[i];
for (Int_t i=0; i<GetTotDim(); i++)
istr >> fXmax[i];
}
void TMVA::PDEFoam::PrintStream( ostream & ostr ) const
{
ostr << fLastCe << std::endl;
ostr << fNCells << std::endl;
ostr << fDim << std::endl;
ostr << GetPDEFoamVolumeFraction() << std::endl;
for (Int_t i=0; i<GetTotDim(); i++)
ostr << fXmin[i] << std::endl;
for (Int_t i=0; i<GetTotDim(); i++)
ostr << fXmax[i] << std::endl;
}
void TMVA::PDEFoam::AddXMLTo( void* parent ){
void *variables = gTools().xmlengine().NewChild( parent, 0, "Variables" );
gTools().AddAttr( variables, "LastCe", fLastCe );
gTools().AddAttr( variables, "nCells", fNCells );
gTools().AddAttr( variables, "Dim", fDim );
gTools().AddAttr( variables, "VolumeFraction", GetPDEFoamVolumeFraction() );
void *xmin_wrap;
for (Int_t i=0; i<GetTotDim(); i++){
xmin_wrap = gTools().xmlengine().NewChild( variables, 0, "Xmin" );
gTools().AddAttr( xmin_wrap, "Index", i );
gTools().AddAttr( xmin_wrap, "Value", fXmin[i] );
}
void *xmax_wrap;
for (Int_t i=0; i<GetTotDim(); i++){
xmax_wrap = gTools().xmlengine().NewChild( variables, 0, "Xmax" );
gTools().AddAttr( xmax_wrap, "Index", i );
gTools().AddAttr( xmax_wrap, "Value", fXmax[i] );
}
}
void TMVA::PDEFoam::ReadXML( void* parent ) {
void *variables = gTools().xmlengine().GetChild( parent );
gTools().ReadAttr( variables, "LastCe", fLastCe );
gTools().ReadAttr( variables, "nCells", fNCells );
gTools().ReadAttr( variables, "Dim", fDim );
Float_t volfr;
gTools().ReadAttr( variables, "VolumeFraction", volfr );
SetPDEFoamVolumeFraction( volfr );
if (fXmin) delete [] fXmin;
if (fXmax) delete [] fXmax;
fXmin = new Double_t[GetTotDim()];
fXmax = new Double_t[GetTotDim()];
void *xmin_wrap = gTools().xmlengine().GetChild( variables );
for (Int_t counter=0; counter<fDim; counter++) {
Int_t i=0;
gTools().ReadAttr( xmin_wrap , "Index", i );
if (i >= GetTotDim() || i<0)
Log() << kFATAL << "dimension index out of range:" << i << Endl;
gTools().ReadAttr( xmin_wrap , "Value", fXmin[i] );
xmin_wrap = gTools().xmlengine().GetNext( xmin_wrap );
}
void *xmax_wrap = xmin_wrap;
for (Int_t counter=0; counter<fDim; counter++) {
Int_t i=0;
gTools().ReadAttr( xmax_wrap , "Index", i );
if (i >= GetTotDim() || i<0)
Log() << kFATAL << "dimension index out of range:" << i << Endl;
gTools().ReadAttr( xmax_wrap , "Value", fXmax[i] );
xmax_wrap = gTools().xmlengine().GetNext( xmax_wrap );
}
}