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

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Classes: PDEFoamTarget                                                         *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation.                                                           *
 *                                                                                *
 * 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)                                          *
 **********************************************************************************/

//_____________________________________________________________________
//
// PDEFoamTarget
//
// This PDEFoam variant stores in every cell the average target
// fTarget (see the Constructor) as well as the statistical error on
// the target fTarget.  It therefore acts as a target estimator.  It
// should be booked together with the PDEFoamTargetDensity density
// estimator, which returns the target fTarget density at a given
// phase space point during the foam build-up.
//
//_____________________________________________________________________

#ifndef ROOT_TMath
#include "TMath.h"
#endif

#ifndef ROOT_TMVA_PDEFoamTarget
#include "TMVA/PDEFoamTarget.h"
#endif

ClassImp(TMVA::PDEFoamTarget)

//_____________________________________________________________________
TMVA::PDEFoamTarget::PDEFoamTarget()
   : PDEFoam()
   , fTarget(0)
{
   // Default constructor for streamer, user should not use it.
}

//_____________________________________________________________________
TMVA::PDEFoamTarget::PDEFoamTarget(const TString& name, UInt_t target)
   : PDEFoam(name)
   , fTarget(target)
{
   // User constructor
   //
   // Parameters:
   //
   // - name - name of PDEFoam object
   //
   // - target - target number to range-search for
}

//_____________________________________________________________________
TMVA::PDEFoamTarget::PDEFoamTarget(const PDEFoamTarget &from)
   : PDEFoam(from)
   , fTarget(from.fTarget)
{
   // Copy Constructor  NOT IMPLEMENTED (NEVER USED)
   Log() << kFATAL << "COPY CONSTRUCTOR NOT IMPLEMENTED" << Endl;
}

//_____________________________________________________________________
void TMVA::PDEFoamTarget::FillFoamCells(const Event* ev, Float_t wt)
{
   // This function fills an event into the discriminant PDEFoam.  The
   // weight 'wt' is filled into cell element 0 if the event is of
   // class 'fTarget', and filled into cell element 1 otherwise.

   // find corresponding foam cell
   std::vector<Float_t> values  = ev->GetValues();
   std::vector<Float_t> tvalues = VarTransform(values);
   std::vector<Float_t> targets = ev->GetTargets();
   PDEFoamCell *cell = FindCell(tvalues);

   // 0. Element: Number of events
   // 1. Element: Target 0
   SetCellElement(cell, 0, GetCellElement(cell, 0) + wt);
   SetCellElement(cell, 1, GetCellElement(cell, 1) + wt * targets.at(fTarget));
}

//_____________________________________________________________________
void TMVA::PDEFoamTarget::Finalize()
{
   // Calculate average cell target in every cell and save them to the
   // cell.  Cell element 0 will contain the average target and cell
   // element 1 will contain the error on the target.

   // loop over cells
   for (Long_t iCell = 0; iCell <= fLastCe; iCell++) {
      if (!(fCells[iCell]->GetStat()))
         continue;

      Double_t n_ev  = GetCellElement(fCells[iCell], 0); // get number of events
      Double_t tar   = GetCellElement(fCells[iCell], 1); // get sum of targets

      if (n_ev > 0) {
         SetCellElement(fCells[iCell], 0, tar / n_ev); // set average target
         SetCellElement(fCells[iCell], 1, tar / TMath::Sqrt(n_ev)); // set error on average target
      } else {
         SetCellElement(fCells[iCell], 0, 0.0);  // set mean target
         SetCellElement(fCells[iCell], 1, -1);   // set mean target error
      }
   }
}

//_____________________________________________________________________
Bool_t TMVA::PDEFoamTarget::CellValueIsUndefined(PDEFoamCell* cell)
{
   // Returns true, if the target error equals -1, as set in
   // Finalize() in case of no events in the cell
   return GetCellValue(cell, kValueError) == -1;
}

//_____________________________________________________________________
Float_t TMVA::PDEFoamTarget::GetCellValue(const std::vector<Float_t> &xvec, ECellValue cv, PDEFoamKernelBase *kernel)
{
   // This function finds the cell, which corresponds to the given
   // untransformed event vector 'xvec' and return its value, which is
   // given by the parameter 'cv'.
   //
   // If cv == kValue, it is checked wether the cell value is
   // undefined.  If this is the case, then the mean of the neighbor's
   // target values is returned, using GetAverageNeighborsValue().

   std::vector<Float_t> txvec(VarTransform(xvec));
   PDEFoamCell *cell = FindCell(txvec);

   if (!CellValueIsUndefined(cell)) {
      // cell is not empty
      if (kernel == NULL)
         return GetCellValue(cell, cv);
      else
         return kernel->Estimate(this, txvec, cv);
   } else
      // cell is empty -> calc average target of neighbor cells
      return GetAverageNeighborsValue(txvec, kValue);
}

//_____________________________________________________________________
Float_t TMVA::PDEFoamTarget::GetAverageNeighborsValue(std::vector<Float_t> &txvec,
                                                      ECellValue cv)
{
   // This function returns the average value 'cv' of only nearest
   // neighbor cells.  It is used in cases, where empty cells shall
   // not be evaluated.
   //
   // Parameters:
   // - txvec - event vector, transformed into foam coordinates [0, 1]
   // - cv - cell value, see definition of ECellValue

   const Float_t xoffset = 1.e-6;
   Float_t norm   = 0; // normalisation
   Float_t result = 0; // return value

   PDEFoamCell *cell = FindCell(txvec); // find cooresponding cell
   PDEFoamVect cellSize(GetTotDim());
   PDEFoamVect cellPosi(GetTotDim());
   cell->GetHcub(cellPosi, cellSize); // get cell coordinates

   // loop over all dimensions and find neighbor cells
   for (Int_t dim = 0; dim < GetTotDim(); dim++) {
      std::vector<Float_t> ntxvec(txvec);
      PDEFoamCell* left_cell  = 0; // left cell
      PDEFoamCell* right_cell = 0; // right cell

      // get left cell
      ntxvec[dim] = cellPosi[dim] - xoffset;
      left_cell = FindCell(ntxvec);
      if (!CellValueIsUndefined(left_cell)) {
         // if left cell is not empty, take its value
         result += GetCellValue(left_cell, cv);
         norm++;
      }
      // get right cell
      ntxvec[dim] = cellPosi[dim] + cellSize[dim] + xoffset;
      right_cell = FindCell(ntxvec);
      if (!CellValueIsUndefined(right_cell)) {
         // if right cell is not empty, take its value
         result += GetCellValue(right_cell, cv);
         norm++;
      }
   }
   if (norm > 0)  result /= norm; // calc average target
   else         result = 0;     // return null if all neighbors are empty

   return result;
}
 PDEFoamTarget.cxx:1
 PDEFoamTarget.cxx:2
 PDEFoamTarget.cxx:3
 PDEFoamTarget.cxx:4
 PDEFoamTarget.cxx:5
 PDEFoamTarget.cxx:6
 PDEFoamTarget.cxx:7
 PDEFoamTarget.cxx:8
 PDEFoamTarget.cxx:9
 PDEFoamTarget.cxx:10
 PDEFoamTarget.cxx:11
 PDEFoamTarget.cxx:12
 PDEFoamTarget.cxx:13
 PDEFoamTarget.cxx:14
 PDEFoamTarget.cxx:15
 PDEFoamTarget.cxx:16
 PDEFoamTarget.cxx:17
 PDEFoamTarget.cxx:18
 PDEFoamTarget.cxx:19
 PDEFoamTarget.cxx:20
 PDEFoamTarget.cxx:21
 PDEFoamTarget.cxx:22
 PDEFoamTarget.cxx:23
 PDEFoamTarget.cxx:24
 PDEFoamTarget.cxx:25
 PDEFoamTarget.cxx:26
 PDEFoamTarget.cxx:27
 PDEFoamTarget.cxx:28
 PDEFoamTarget.cxx:29
 PDEFoamTarget.cxx:30
 PDEFoamTarget.cxx:31
 PDEFoamTarget.cxx:32
 PDEFoamTarget.cxx:33
 PDEFoamTarget.cxx:34
 PDEFoamTarget.cxx:35
 PDEFoamTarget.cxx:36
 PDEFoamTarget.cxx:37
 PDEFoamTarget.cxx:38
 PDEFoamTarget.cxx:39
 PDEFoamTarget.cxx:40
 PDEFoamTarget.cxx:41
 PDEFoamTarget.cxx:42
 PDEFoamTarget.cxx:43
 PDEFoamTarget.cxx:44
 PDEFoamTarget.cxx:45
 PDEFoamTarget.cxx:46
 PDEFoamTarget.cxx:47
 PDEFoamTarget.cxx:48
 PDEFoamTarget.cxx:49
 PDEFoamTarget.cxx:50
 PDEFoamTarget.cxx:51
 PDEFoamTarget.cxx:52
 PDEFoamTarget.cxx:53
 PDEFoamTarget.cxx:54
 PDEFoamTarget.cxx:55
 PDEFoamTarget.cxx:56
 PDEFoamTarget.cxx:57
 PDEFoamTarget.cxx:58
 PDEFoamTarget.cxx:59
 PDEFoamTarget.cxx:60
 PDEFoamTarget.cxx:61
 PDEFoamTarget.cxx:62
 PDEFoamTarget.cxx:63
 PDEFoamTarget.cxx:64
 PDEFoamTarget.cxx:65
 PDEFoamTarget.cxx:66
 PDEFoamTarget.cxx:67
 PDEFoamTarget.cxx:68
 PDEFoamTarget.cxx:69
 PDEFoamTarget.cxx:70
 PDEFoamTarget.cxx:71
 PDEFoamTarget.cxx:72
 PDEFoamTarget.cxx:73
 PDEFoamTarget.cxx:74
 PDEFoamTarget.cxx:75
 PDEFoamTarget.cxx:76
 PDEFoamTarget.cxx:77
 PDEFoamTarget.cxx:78
 PDEFoamTarget.cxx:79
 PDEFoamTarget.cxx:80
 PDEFoamTarget.cxx:81
 PDEFoamTarget.cxx:82
 PDEFoamTarget.cxx:83
 PDEFoamTarget.cxx:84
 PDEFoamTarget.cxx:85
 PDEFoamTarget.cxx:86
 PDEFoamTarget.cxx:87
 PDEFoamTarget.cxx:88
 PDEFoamTarget.cxx:89
 PDEFoamTarget.cxx:90
 PDEFoamTarget.cxx:91
 PDEFoamTarget.cxx:92
 PDEFoamTarget.cxx:93
 PDEFoamTarget.cxx:94
 PDEFoamTarget.cxx:95
 PDEFoamTarget.cxx:96
 PDEFoamTarget.cxx:97
 PDEFoamTarget.cxx:98
 PDEFoamTarget.cxx:99
 PDEFoamTarget.cxx:100
 PDEFoamTarget.cxx:101
 PDEFoamTarget.cxx:102
 PDEFoamTarget.cxx:103
 PDEFoamTarget.cxx:104
 PDEFoamTarget.cxx:105
 PDEFoamTarget.cxx:106
 PDEFoamTarget.cxx:107
 PDEFoamTarget.cxx:108
 PDEFoamTarget.cxx:109
 PDEFoamTarget.cxx:110
 PDEFoamTarget.cxx:111
 PDEFoamTarget.cxx:112
 PDEFoamTarget.cxx:113
 PDEFoamTarget.cxx:114
 PDEFoamTarget.cxx:115
 PDEFoamTarget.cxx:116
 PDEFoamTarget.cxx:117
 PDEFoamTarget.cxx:118
 PDEFoamTarget.cxx:119
 PDEFoamTarget.cxx:120
 PDEFoamTarget.cxx:121
 PDEFoamTarget.cxx:122
 PDEFoamTarget.cxx:123
 PDEFoamTarget.cxx:124
 PDEFoamTarget.cxx:125
 PDEFoamTarget.cxx:126
 PDEFoamTarget.cxx:127
 PDEFoamTarget.cxx:128
 PDEFoamTarget.cxx:129
 PDEFoamTarget.cxx:130
 PDEFoamTarget.cxx:131
 PDEFoamTarget.cxx:132
 PDEFoamTarget.cxx:133
 PDEFoamTarget.cxx:134
 PDEFoamTarget.cxx:135
 PDEFoamTarget.cxx:136
 PDEFoamTarget.cxx:137
 PDEFoamTarget.cxx:138
 PDEFoamTarget.cxx:139
 PDEFoamTarget.cxx:140
 PDEFoamTarget.cxx:141
 PDEFoamTarget.cxx:142
 PDEFoamTarget.cxx:143
 PDEFoamTarget.cxx:144
 PDEFoamTarget.cxx:145
 PDEFoamTarget.cxx:146
 PDEFoamTarget.cxx:147
 PDEFoamTarget.cxx:148
 PDEFoamTarget.cxx:149
 PDEFoamTarget.cxx:150
 PDEFoamTarget.cxx:151
 PDEFoamTarget.cxx:152
 PDEFoamTarget.cxx:153
 PDEFoamTarget.cxx:154
 PDEFoamTarget.cxx:155
 PDEFoamTarget.cxx:156
 PDEFoamTarget.cxx:157
 PDEFoamTarget.cxx:158
 PDEFoamTarget.cxx:159
 PDEFoamTarget.cxx:160
 PDEFoamTarget.cxx:161
 PDEFoamTarget.cxx:162
 PDEFoamTarget.cxx:163
 PDEFoamTarget.cxx:164
 PDEFoamTarget.cxx:165
 PDEFoamTarget.cxx:166
 PDEFoamTarget.cxx:167
 PDEFoamTarget.cxx:168
 PDEFoamTarget.cxx:169
 PDEFoamTarget.cxx:170
 PDEFoamTarget.cxx:171
 PDEFoamTarget.cxx:172
 PDEFoamTarget.cxx:173
 PDEFoamTarget.cxx:174
 PDEFoamTarget.cxx:175
 PDEFoamTarget.cxx:176
 PDEFoamTarget.cxx:177
 PDEFoamTarget.cxx:178
 PDEFoamTarget.cxx:179
 PDEFoamTarget.cxx:180
 PDEFoamTarget.cxx:181
 PDEFoamTarget.cxx:182
 PDEFoamTarget.cxx:183
 PDEFoamTarget.cxx:184
 PDEFoamTarget.cxx:185
 PDEFoamTarget.cxx:186
 PDEFoamTarget.cxx:187
 PDEFoamTarget.cxx:188
 PDEFoamTarget.cxx:189
 PDEFoamTarget.cxx:190
 PDEFoamTarget.cxx:191
 PDEFoamTarget.cxx:192
 PDEFoamTarget.cxx:193
 PDEFoamTarget.cxx:194
 PDEFoamTarget.cxx:195
 PDEFoamTarget.cxx:196
 PDEFoamTarget.cxx:197
 PDEFoamTarget.cxx:198
 PDEFoamTarget.cxx:199
 PDEFoamTarget.cxx:200
 PDEFoamTarget.cxx:201
 PDEFoamTarget.cxx:202
 PDEFoamTarget.cxx:203
 PDEFoamTarget.cxx:204
 PDEFoamTarget.cxx:205
 PDEFoamTarget.cxx:206
 PDEFoamTarget.cxx:207
 PDEFoamTarget.cxx:208