// @(#)root/tmva $Id$
// Author: Tancredi Carli, Dominik Dannheim, Alexander Voigt

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Classes: PDEFoamDensityBase                                                    *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      This class provides an interface between the Binary search tree           *
 *      and the PDEFoam object.  In order to build-up the foam one needs to       *
 *      calculate the density of events at a given point (sampling during         *
 *      Foam build-up).  The function PDEFoamDensityBase::Density() does this job. It *
 *      uses a binary search tree, filled with training events, in order to       *
 *      provide this density.                                                     *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Tancredi Carli   - CERN, Switzerland                                      *
 *      Dominik Dannheim - CERN, Switzerland                                      *
 *      S. Jadach        - Institute of Nuclear Physics, Cracow, Poland           *
 *      Alexander Voigt  - TU Dresden, Germany                                    *
 *      Peter Speckmayer - CERN, Switzerland                                      *
 *                                                                                *
 * Copyright (c) 2008, 2010:                                                      *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_____________________________________________________________________
//
// PDEFoamDensityBase
//
// This is an abstract class, which provides an interface for a
// PDEFoam density estimator.  Derived classes have to implement the
// Density(...) function, which returns the density of a certain
// quantity at a given phase-space point during the foam build-up.
//
// Variants of PDEFoamDensityBase are:
//
//   - PDEFoamEventDensity
//   - PDEFoamDiscriminantDensity
//   - PDEFoamTargetDensity
//   - PDEFoamDecisionTreeDensity
//
// Usage:
//
// The user has to instantiate a child class of PDEFoamDensityBase and
// set the pointer to the owner, which is a PDEFoam object:
//
//   PDEFoamDensityBase *dens = new MyDensity();
//   pdefoam->SetDensity(dens);
//
// Afterwards the binary search tree should be filled with TMVA
// events, by either using
//
//   pdefoam->FillBinarySearchTree(event);
//
// or
//
//   dens->FillBinarySearchTree(event);
// _____________________________________________________________________

#include <numeric>
#include <functional>

#ifndef ROOT_TMVA_PDEFoamDensityBase
#include "TMVA/PDEFoamDensityBase.h"
#endif

ClassImp(TMVA::PDEFoamDensityBase)

//_____________________________________________________________________
TMVA::PDEFoamDensityBase::PDEFoamDensityBase()
   : TObject(),
     fBox(),
     fBoxVolume(1.0),
     fBoxHasChanged(kTRUE),
     fBst(new TMVA::BinarySearchTree()),
     fLogger(new MsgLogger("PDEFoamDensityBase"))
{}

//_____________________________________________________________________
TMVA::PDEFoamDensityBase::PDEFoamDensityBase(std::vector<Double_t> box)
   : TObject(),
     fBox(box),
     fBoxVolume(1.0),
     fBoxHasChanged(kTRUE),
     fBst(new TMVA::BinarySearchTree()),
     fLogger(new MsgLogger("PDEFoamDensityBase"))
{
   // User constructor
   //
   // - box - range-searching box, where box.size() == dimension of
   //         the PDEFoam == periode of the binary search tree

   if (box.empty())
      Log() << kFATAL << "Dimension of PDEFoamDensityBase is zero" << Endl;

   // set periode (number of variables) of binary search tree
   fBst->SetPeriode(box.size());
}

//_____________________________________________________________________
TMVA::PDEFoamDensityBase::~PDEFoamDensityBase()
{
   // destructor
   if (fBst)    delete fBst;
   if (fLogger) delete fLogger;
}

//_____________________________________________________________________
TMVA::PDEFoamDensityBase::PDEFoamDensityBase(const PDEFoamDensityBase &distr)
   : TObject(),
     fBox(distr.fBox),
     fBoxVolume(distr.fBoxVolume),
     fBoxHasChanged(distr.fBoxHasChanged),
     fBst(new BinarySearchTree(*distr.fBst)),
     fLogger(new MsgLogger(*distr.fLogger))
{
   // Copy constructor
   //
   // Creates a deep copy, using the copy constructor of
   // TMVA::BinarySearchTree
}

//_____________________________________________________________________
void TMVA::PDEFoamDensityBase::FillBinarySearchTree(const Event* ev)
{
   // This method inserts the given event 'ev' it into the binary
   // search tree.

   if (fBst == NULL)
      Log() << kFATAL << "<PDEFoamDensityBase::FillBinarySearchTree> "
            << "Binary tree is not set!" << Endl;

   // insert into binary search tree
   fBst->Insert(ev);
}

//_____________________________________________________________________
Double_t TMVA::PDEFoamDensityBase::GetBoxVolume()
{
   // Returns the volume of range searching box fBox.
   //
   // If the range searching box 'fBox' has changed (fBoxHasChanged is
   // kTRUE), recalculate the box volume and set fBoxHasChanged to
   // kFALSE
   if (fBoxHasChanged) {
      fBoxHasChanged = kFALSE;
      fBoxVolume = std::accumulate(fBox.begin(), fBox.end(), 1.0,
                                   std::multiplies<Double_t>());
   }
   return fBoxVolume;
}
 PDEFoamDensityBase.cxx:1
 PDEFoamDensityBase.cxx:2
 PDEFoamDensityBase.cxx:3
 PDEFoamDensityBase.cxx:4
 PDEFoamDensityBase.cxx:5
 PDEFoamDensityBase.cxx:6
 PDEFoamDensityBase.cxx:7
 PDEFoamDensityBase.cxx:8
 PDEFoamDensityBase.cxx:9
 PDEFoamDensityBase.cxx:10
 PDEFoamDensityBase.cxx:11
 PDEFoamDensityBase.cxx:12
 PDEFoamDensityBase.cxx:13
 PDEFoamDensityBase.cxx:14
 PDEFoamDensityBase.cxx:15
 PDEFoamDensityBase.cxx:16
 PDEFoamDensityBase.cxx:17
 PDEFoamDensityBase.cxx:18
 PDEFoamDensityBase.cxx:19
 PDEFoamDensityBase.cxx:20
 PDEFoamDensityBase.cxx:21
 PDEFoamDensityBase.cxx:22
 PDEFoamDensityBase.cxx:23
 PDEFoamDensityBase.cxx:24
 PDEFoamDensityBase.cxx:25
 PDEFoamDensityBase.cxx:26
 PDEFoamDensityBase.cxx:27
 PDEFoamDensityBase.cxx:28
 PDEFoamDensityBase.cxx:29
 PDEFoamDensityBase.cxx:30
 PDEFoamDensityBase.cxx:31
 PDEFoamDensityBase.cxx:32
 PDEFoamDensityBase.cxx:33
 PDEFoamDensityBase.cxx:34
 PDEFoamDensityBase.cxx:35
 PDEFoamDensityBase.cxx:36
 PDEFoamDensityBase.cxx:37
 PDEFoamDensityBase.cxx:38
 PDEFoamDensityBase.cxx:39
 PDEFoamDensityBase.cxx:40
 PDEFoamDensityBase.cxx:41
 PDEFoamDensityBase.cxx:42
 PDEFoamDensityBase.cxx:43
 PDEFoamDensityBase.cxx:44
 PDEFoamDensityBase.cxx:45
 PDEFoamDensityBase.cxx:46
 PDEFoamDensityBase.cxx:47
 PDEFoamDensityBase.cxx:48
 PDEFoamDensityBase.cxx:49
 PDEFoamDensityBase.cxx:50
 PDEFoamDensityBase.cxx:51
 PDEFoamDensityBase.cxx:52
 PDEFoamDensityBase.cxx:53
 PDEFoamDensityBase.cxx:54
 PDEFoamDensityBase.cxx:55
 PDEFoamDensityBase.cxx:56
 PDEFoamDensityBase.cxx:57
 PDEFoamDensityBase.cxx:58
 PDEFoamDensityBase.cxx:59
 PDEFoamDensityBase.cxx:60
 PDEFoamDensityBase.cxx:61
 PDEFoamDensityBase.cxx:62
 PDEFoamDensityBase.cxx:63
 PDEFoamDensityBase.cxx:64
 PDEFoamDensityBase.cxx:65
 PDEFoamDensityBase.cxx:66
 PDEFoamDensityBase.cxx:67
 PDEFoamDensityBase.cxx:68
 PDEFoamDensityBase.cxx:69
 PDEFoamDensityBase.cxx:70
 PDEFoamDensityBase.cxx:71
 PDEFoamDensityBase.cxx:72
 PDEFoamDensityBase.cxx:73
 PDEFoamDensityBase.cxx:74
 PDEFoamDensityBase.cxx:75
 PDEFoamDensityBase.cxx:76
 PDEFoamDensityBase.cxx:77
 PDEFoamDensityBase.cxx:78
 PDEFoamDensityBase.cxx:79
 PDEFoamDensityBase.cxx:80
 PDEFoamDensityBase.cxx:81
 PDEFoamDensityBase.cxx:82
 PDEFoamDensityBase.cxx:83
 PDEFoamDensityBase.cxx:84
 PDEFoamDensityBase.cxx:85
 PDEFoamDensityBase.cxx:86
 PDEFoamDensityBase.cxx:87
 PDEFoamDensityBase.cxx:88
 PDEFoamDensityBase.cxx:89
 PDEFoamDensityBase.cxx:90
 PDEFoamDensityBase.cxx:91
 PDEFoamDensityBase.cxx:92
 PDEFoamDensityBase.cxx:93
 PDEFoamDensityBase.cxx:94
 PDEFoamDensityBase.cxx:95
 PDEFoamDensityBase.cxx:96
 PDEFoamDensityBase.cxx:97
 PDEFoamDensityBase.cxx:98
 PDEFoamDensityBase.cxx:99
 PDEFoamDensityBase.cxx:100
 PDEFoamDensityBase.cxx:101
 PDEFoamDensityBase.cxx:102
 PDEFoamDensityBase.cxx:103
 PDEFoamDensityBase.cxx:104
 PDEFoamDensityBase.cxx:105
 PDEFoamDensityBase.cxx:106
 PDEFoamDensityBase.cxx:107
 PDEFoamDensityBase.cxx:108
 PDEFoamDensityBase.cxx:109
 PDEFoamDensityBase.cxx:110
 PDEFoamDensityBase.cxx:111
 PDEFoamDensityBase.cxx:112
 PDEFoamDensityBase.cxx:113
 PDEFoamDensityBase.cxx:114
 PDEFoamDensityBase.cxx:115
 PDEFoamDensityBase.cxx:116
 PDEFoamDensityBase.cxx:117
 PDEFoamDensityBase.cxx:118
 PDEFoamDensityBase.cxx:119
 PDEFoamDensityBase.cxx:120
 PDEFoamDensityBase.cxx:121
 PDEFoamDensityBase.cxx:122
 PDEFoamDensityBase.cxx:123
 PDEFoamDensityBase.cxx:124
 PDEFoamDensityBase.cxx:125
 PDEFoamDensityBase.cxx:126
 PDEFoamDensityBase.cxx:127
 PDEFoamDensityBase.cxx:128
 PDEFoamDensityBase.cxx:129
 PDEFoamDensityBase.cxx:130
 PDEFoamDensityBase.cxx:131
 PDEFoamDensityBase.cxx:132
 PDEFoamDensityBase.cxx:133
 PDEFoamDensityBase.cxx:134
 PDEFoamDensityBase.cxx:135
 PDEFoamDensityBase.cxx:136
 PDEFoamDensityBase.cxx:137
 PDEFoamDensityBase.cxx:138
 PDEFoamDensityBase.cxx:139
 PDEFoamDensityBase.cxx:140
 PDEFoamDensityBase.cxx:141
 PDEFoamDensityBase.cxx:142
 PDEFoamDensityBase.cxx:143
 PDEFoamDensityBase.cxx:144
 PDEFoamDensityBase.cxx:145
 PDEFoamDensityBase.cxx:146
 PDEFoamDensityBase.cxx:147
 PDEFoamDensityBase.cxx:148
 PDEFoamDensityBase.cxx:149
 PDEFoamDensityBase.cxx:150
 PDEFoamDensityBase.cxx:151
 PDEFoamDensityBase.cxx:152
 PDEFoamDensityBase.cxx:153
 PDEFoamDensityBase.cxx:154
 PDEFoamDensityBase.cxx:155
 PDEFoamDensityBase.cxx:156
 PDEFoamDensityBase.cxx:157
 PDEFoamDensityBase.cxx:158
 PDEFoamDensityBase.cxx:159