Logo ROOT  
Reference Guide
PDEFoam.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: S.Jadach, Tancredi Carli, Dominik Dannheim, Alexander Voigt
3
4/**********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6 * Package: TMVA *
7 * Classes: PDEFoam *
8 * Web : http://tmva.sourceforge.net *
9 * *
10 * Description: *
11 * Implementations *
12 * *
13 * Authors (alphabetical): *
14 * Tancredi Carli - CERN, Switzerland *
15 * Dominik Dannheim - CERN, Switzerland *
16 * S. Jadach - Institute of Nuclear Physics, Cracow, Poland *
17 * Alexander Voigt - TU Dresden, Germany *
18 * Peter Speckmayer - CERN, Switzerland *
19 * *
20 * Copyright (c) 2008, 2010: *
21 * CERN, Switzerland *
22 * MPI-K Heidelberg, Germany *
23 * *
24 * Redistribution and use in source and binary forms, with or without *
25 * modification, are permitted according to the terms listed in LICENSE *
26 * (http://tmva.sourceforge.net/LICENSE) *
27 **********************************************************************************/
28
29/*! \class TMVA::PDEFoam
30\ingroup TMVA
31
32Implementation of PDEFoam
33
34The PDEFoam method is an extension of the PDERS method, which uses
35self-adapting binning to divide the multi-dimensional phase space
36in a finite number of hyper-rectangles (boxes).
37
38For a given number of boxes, the binning algorithm adjusts the size
39and position of the boxes inside the multidimensional phase space,
40minimizing the variance of the signal and background densities inside
41the boxes. The binned density information is stored in binary trees,
42allowing for a very fast and memory-efficient classification of
43events.
44
45The implementation of the PDEFoam is based on the monte-carlo
46integration package TFoam included in the analysis package ROOT.
47
48The class TMVA::PDEFoam defines the default interface for the
49PDEFoam variants:
50
51 - PDEFoamEvent
52 - PDEFoamDiscriminant
53 - PDEFoamTarget
54 - PDEFoamMultiTarget
55 - PDEFoamDecisionTree
56
57Per default PDEFoam stores in the cells the number of events (event
58weights) and therefore acts as an event density estimator.
59However, the above listed derived classes override this behaviour
60to implement certain PDEFoam variations.
61
62In order to use PDEFoam the user has to set the density estimator
63of the type TMVA::PDEFoamDensityBase, which is used to during the foam
64build-up. The default PDEFoam should be used with
65PDEFoamEventDensity.
66*/
67
68#include "TMVA/PDEFoam.h"
69
70#include "TMVA/Event.h"
71#include "TMVA/MsgLogger.h"
73#include "TMVA/Timer.h"
74#include "TMVA/Tools.h"
75#include "TMVA/Types.h"
76
77#include "TStyle.h"
78#include "TObject.h"
79#include "TH1D.h"
80#include "TMath.h"
81#include "TVectorT.h"
82#include "TRandom3.h"
83#include "TColor.h"
84#include "TDirectory.h"
85#include "TObjArray.h"
86
87#include <cassert>
88#include <fstream>
89#include <iostream>
90#include <iomanip>
91#include <limits>
92#include <sstream>
93
95
96static const Float_t kHigh= FLT_MAX;
97static const Float_t kVlow=-FLT_MAX;
98
99using namespace std;
100
101////////////////////////////////////////////////////////////////////////////////
102/// Default constructor for streamer, user should not use it.
103
105 fName("PDEFoam"),
106 fDim(0),
107 fNCells(0),
108 fNBin(5),
109 fNSampl(2000),
110 fEvPerBin(0),
111 fMaskDiv(0),
112 fInhiDiv(0),
113 fNoAct(1),
114 fLastCe(-1),
115 fCells(0),
116 fHistEdg(0),
117 fRvec(0),
118 fPseRan(new TRandom3(4356)),
119 fAlpha(0),
120 fFoamType(kSeparate),
121 fXmin(0),
122 fXmax(0),
123 fNElements(0),
124 fNmin(100),
125 fMaxDepth(0),
126 fVolFrac(1.0/15.0),
127 fFillFoamWithOrigWeights(kFALSE),
128 fDTSeparation(kFoam),
129 fPeekMax(kTRUE),
130 fDistr(NULL),
131 fTimer(new Timer(0, "PDEFoam", kTRUE)),
132 fVariableNames(new TObjArray()),
133 fLogger(new MsgLogger("PDEFoam"))
134{
135 // fVariableNames may delete it's heap-based content
136 if (fVariableNames)
138}
139
140////////////////////////////////////////////////////////////////////////////////
141/// User constructor, to be employed by the user
142
144 fName(name),
145 fDim(0),
146 fNCells(1000),
147 fNBin(5),
148 fNSampl(2000),
149 fEvPerBin(0),
150 fMaskDiv(0),
151 fInhiDiv(0),
152 fNoAct(1),
153 fLastCe(-1),
154 fCells(0),
155 fHistEdg(0),
156 fRvec(0),
157 fPseRan(new TRandom3(4356)),
158 fAlpha(0),
159 fFoamType(kSeparate),
160 fXmin(0),
161 fXmax(0),
162 fNElements(0),
163 fNmin(100),
164 fMaxDepth(0),
165 fVolFrac(1.0/15.0),
166 fFillFoamWithOrigWeights(kFALSE),
167 fDTSeparation(kFoam),
168 fPeekMax(kTRUE),
169 fDistr(NULL),
170 fTimer(new Timer(1, "PDEFoam", kTRUE)),
171 fVariableNames(new TObjArray()),
172 fLogger(new MsgLogger("PDEFoam"))
173{
174 if(strlen(name) > 128)
175 Log() << kFATAL << "Name too long " << name.Data() << Endl;
176
177 // fVariableNames may delete it's heap-based content
178 if (fVariableNames)
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Default destructor
184
186{
187 delete fVariableNames;
188 delete fTimer;
189 if (fDistr) delete fDistr;
190 if (fPseRan) delete fPseRan;
191 if (fXmin) { delete [] fXmin; fXmin=0; }
192 if (fXmax) { delete [] fXmax; fXmax=0; }
193
194 ResetCellElements();
195 if(fCells!= 0) {
196 for(Int_t i=0; i<fNCells; i++) delete fCells[i]; // PDEFoamCell*[]
197 delete [] fCells;
198 }
199 delete [] fRvec; //double[]
200 delete [] fAlpha; //double[]
201 delete [] fMaskDiv; //int[]
202 delete [] fInhiDiv; //int[]
203
204 delete fLogger;
205}
206
207////////////////////////////////////////////////////////////////////////////////
208/// Copy Constructor NOT IMPLEMENTED (NEVER USED)
209
211 TObject(from)
212 , fDim(0)
213 , fNCells(0)
214 , fNBin(0)
215 , fNSampl(0)
216 , fEvPerBin(0)
217 , fMaskDiv(0)
218 , fInhiDiv(0)
219 , fNoAct(0)
220 , fLastCe(0)
221 , fCells(0)
222 , fHistEdg(0)
223 , fRvec(0)
224 , fPseRan(0)
225 , fAlpha(0)
226 , fFoamType(kSeparate)
227 , fXmin(0)
228 , fXmax(0)
229 , fNElements(0)
230 , fNmin(0)
231 , fMaxDepth(0)
232 , fVolFrac(1.0/15.0)
233 , fFillFoamWithOrigWeights(kFALSE)
234 , fDTSeparation(kFoam)
235 , fPeekMax(kTRUE)
236 , fDistr(0)
237 , fTimer(0)
238 , fVariableNames(0)
239 , fLogger(new MsgLogger(*from.fLogger))
240{
241 Log() << kFATAL << "COPY CONSTRUCTOR NOT IMPLEMENTED" << Endl;
242
243 // fVariableNames may delete it's heap-based content
244 if (fVariableNames)
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// Sets dimension of cubical space
250
252{
253 if (kDim < 1)
254 Log() << kFATAL << "<SetDim>: Dimension is zero or negative!" << Endl;
255
256 fDim = kDim;
257 if (fXmin) delete [] fXmin;
258 if (fXmax) delete [] fXmax;
259 fXmin = new Double_t[GetTotDim()];
260 fXmax = new Double_t[GetTotDim()];
261}
263////////////////////////////////////////////////////////////////////////////////
264/// set lower foam bound in dimension idim
265
267{
268 if (idim<0 || idim>=GetTotDim())
269 Log() << kFATAL << "<SetXmin>: Dimension out of bounds!" << Endl;
270
271 fXmin[idim]=wmin;
272}
273
274////////////////////////////////////////////////////////////////////////////////
275/// set upper foam bound in dimension idim
276
278{
279 if (idim<0 || idim>=GetTotDim())
280 Log() << kFATAL << "<SetXmax>: Dimension out of bounds!" << Endl;
281
282 fXmax[idim]=wmax;
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// Basic initialization of FOAM invoked by the user.
287/// IMPORTANT: Random number generator and the distribution object has to be
288/// provided using SetPseRan and SetRho prior to invoking this initializator!
289///
290/// After the foam is grown, space for 2 variables is reserved in
291/// every cell. They are used for filling the foam cells.
292
294{
295 Bool_t addStatus = TH1::AddDirectoryStatus();
297
298 if(fPseRan==0) Log() << kFATAL << "Random number generator not set" << Endl;
299 if(fDistr==0) Log() << kFATAL << "Distribution function not set" << Endl;
300 if(fDim==0) Log() << kFATAL << "Zero dimension not allowed" << Endl;
301
302 /////////////////////////////////////////////////////////////////////////
303 // ALLOCATE SMALL LISTS //
304 // it is done globally, not for each cell, to save on allocation time //
305 /////////////////////////////////////////////////////////////////////////
306 fRvec = new Double_t[fDim]; // Vector of random numbers
307 if(fRvec==0) Log() << kFATAL << "Cannot initialize buffer fRvec" << Endl;
308
309 if(fDim>0){
310 fAlpha = new Double_t[fDim]; // sum<1 for internal parametrization of the simplex
311 if(fAlpha==0) Log() << kFATAL << "Cannot initialize buffer fAlpha" << Endl;
312 }
313
314 //====== List of directions inhibited for division
315 if(fInhiDiv == 0){
316 fInhiDiv = new Int_t[fDim];
317 for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
318 }
319 //====== Dynamic mask used in Explore for edge determination
320 if(fMaskDiv == 0){
321 fMaskDiv = new Int_t[fDim];
322 for(Int_t i=0; i<fDim; i++) fMaskDiv[i]=1;
323 }
324 //====== Initialize list of histograms
325 fHistEdg = new TObjArray(fDim); // Initialize list of histograms
326 for(Int_t i=0; i<fDim; i++){
327 TString hname, htitle;
328 hname = fName+TString("_HistEdge_");
329 hname += i;
330 htitle = TString("Edge Histogram No. ");
331 htitle += i;
332 (*fHistEdg)[i] = new TH1D(hname.Data(),htitle.Data(),fNBin,0.0, 1.0); // Initialize histogram for each edge
333 ((TH1D*)(*fHistEdg)[i])->Sumw2();
334 }
335
336 // ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //
337 // BUILD-UP of the FOAM //
338 // ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //
339
340 // prepare PDEFoam for growing
341 ResetCellElements(); // reset all cell elements
342
343 // Define and explore root cell(s)
344 InitCells();
345 Grow();
346
347 TH1::AddDirectory(addStatus);
348
349 // prepare PDEFoam for the filling with events
350 ResetCellElements(); // reset all cell elements
351} // Create
352
353////////////////////////////////////////////////////////////////////////////////
354/// Internal subprogram used by Create.
355/// It initializes "root part" of the FOAM of the tree of cells.
356
358{
359 fLastCe =-1; // Index of the last cell
360 if(fCells!= 0) {
361 for(Int_t i=0; i<fNCells; i++) delete fCells[i];
362 delete [] fCells;
363 }
364
365 fCells = new(nothrow) PDEFoamCell*[fNCells];
366 if (!fCells) {
367 Log() << kFATAL << "not enough memory to create " << fNCells
368 << " cells" << Endl;
369 }
370 for(Int_t i=0; i<fNCells; i++){
371 fCells[i]= new PDEFoamCell(fDim); // Allocate BIG list of cells
372 fCells[i]->SetSerial(i);
373 }
374
375 /////////////////////////////////////////////////////////////////////////////
376 // Single Root Hypercube //
377 /////////////////////////////////////////////////////////////////////////////
378 CellFill(1, 0); // 0-th cell ACTIVE
379
380 // Exploration of the root cell(s)
381 for(Long_t iCell=0; iCell<=fLastCe; iCell++){
382 Explore( fCells[iCell] ); // Exploration of root cell(s)
383 }
384}//InitCells
385
386////////////////////////////////////////////////////////////////////////////////
387/// Internal subprogram used by Create.
388/// It initializes content of the newly allocated active cell.
389
391{
392 PDEFoamCell *cell;
393 if (fLastCe==fNCells){
394 Log() << kFATAL << "Too many cells" << Endl;
395 }
396 fLastCe++; // 0-th cell is the first
397
398 cell = fCells[fLastCe];
399
400 cell->Fill(status, parent, 0, 0);
401
402 cell->SetBest( -1); // pointer for planning division of the cell
403 cell->SetXdiv(0.5); // factor for division
404 Double_t xInt2,xDri2;
405 if(parent!=0){
406 xInt2 = 0.5*parent->GetIntg();
407 xDri2 = 0.5*parent->GetDriv();
408 cell->SetIntg(xInt2);
409 cell->SetDriv(xDri2);
410 }else{
411 cell->SetIntg(0.0);
412 cell->SetDriv(0.0);
413 }
414 return fLastCe;
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// Internal subprogram used by Create.
419/// It explores newly defined cell with help of special short MC sampling.
420/// As a result, estimates of kTRUE and drive volume is defined/determined
421/// Average and dispersion of the weight distribution will is found along
422/// each edge and the best edge (minimum dispersion, best maximum weight)
423/// is memorized for future use.
424/// The optimal division point for eventual future cell division is
425/// determined/recorded. Recorded are also minimum and maximum weight etc.
426/// The volume estimate in all (inactive) parent cells is updated.
427/// Note that links to parents and initial volume = 1/2 parent has to be
428/// already defined prior to calling this routine.
429///
430/// If fNmin > 0 then the total number of (training) events found in
431/// the cell during the exploration is stored in the cell. This
432/// information is used within PeekMax() to avoid splitting cells
433/// which contain less than fNmin events.
434
436{
437 Double_t wt, dx, xBest=0, yBest;
438 Double_t intOld, driOld;
439
440 Long_t iev;
441 Double_t nevMC;
442 Int_t i, j, k;
443 Int_t nProj, kBest;
444 Double_t ceSum[5], xproj;
445
446 Double_t event_density = 0;
447 Double_t totevents = 0;
448 Double_t toteventsOld = 0;
449
450 PDEFoamVect cellSize(fDim);
451 PDEFoamVect cellPosi(fDim);
452
453 cell->GetHcub(cellPosi,cellSize);
454
455 PDEFoamCell *parent;
456
457 Double_t *xRand = new Double_t[fDim];
458
459 Double_t *volPart=0;
460
461 // calculate volume scale
462 Double_t vol_scale = 1.0;
463 for (Int_t idim = 0; idim < fDim; ++idim)
464 vol_scale *= fXmax[idim] - fXmin[idim];
465
466 cell->CalcVolume();
467 dx = cell->GetVolume() * vol_scale;
468 intOld = cell->GetIntg(); //memorize old values,
469 driOld = cell->GetDriv(); //will be needed for correcting parent cells
470 toteventsOld = GetCellElement(cell, 0);
471
472 /////////////////////////////////////////////////////
473 // Special Short MC sampling to probe cell //
474 /////////////////////////////////////////////////////
475 ceSum[0]=0;
476 ceSum[1]=0;
477 ceSum[2]=0;
478 ceSum[3]=kHigh; //wtmin
479 ceSum[4]=kVlow; //wtmax
480
481 for (i=0;i<fDim;i++) ((TH1D *)(*fHistEdg)[i])->Reset(); // Reset histograms
482
483 Double_t nevEff=0.;
484 // ||||||||||||||||||||||||||BEGIN MC LOOP|||||||||||||||||||||||||||||
485 for (iev=0;iev<fNSampl;iev++){
486 MakeAlpha(); // generate uniformly vector inside hypercube
487
488 if (fDim>0) for (j=0; j<fDim; j++) xRand[j]= cellPosi[j] +fAlpha[j]*(cellSize[j]);
489
490 wt = dx*Eval(xRand, event_density);
491 totevents += event_density;
492
493 nProj = 0;
494 if (fDim>0) {
495 for (k=0; k<fDim; k++) {
496 xproj =fAlpha[k];
497 ((TH1D *)(*fHistEdg)[nProj])->Fill(xproj,wt);
498 nProj++;
499 }
500 }
501
502 ceSum[0] += wt; // sum of weights
503 ceSum[1] += wt*wt; // sum of weights squared
504 ceSum[2]++; // sum of 1
505 if (ceSum[3]>wt) ceSum[3]=wt; // minimum weight;
506 if (ceSum[4]<wt) ceSum[4]=wt; // maximum weight
507 // test MC loop exit condition
508 if (ceSum[1]>0) nevEff = ceSum[0]*ceSum[0]/ceSum[1];
509 else nevEff = 0;
510 if ( nevEff >= fNBin*fEvPerBin) break;
511 } // ||||||||||||||||||||||||||END MC LOOP|||||||||||||||||||||||||||||
512 totevents *= dx;
513
514 if (fNSampl>0) totevents /= fNSampl;
515
516 // make sure that, if root cell is explored, more than zero
517 // events were found.
518 if (cell==fCells[0] && ceSum[0]<=0.0){
519 if (ceSum[0]==0.0)
520 Log() << kFATAL << "No events were found during exploration of "
521 << "root cell. Please check PDEFoam parameters nSampl "
522 << "and VolFrac." << Endl;
523 else
524 Log() << kWARNING << "Negative number of events found during "
525 << "exploration of root cell" << Endl;
526 }
527
528 //------------------------------------------------------------------
529 //--- predefine logics of searching for the best division edge ---
530 for (k=0; k<fDim;k++){
531 fMaskDiv[k] =1; // default is all
532 if ( fInhiDiv[k]==1) fMaskDiv[k] =0; // inhibit some...
533 }
534 kBest=-1;
535
536 /////////////////////////////////////////////////////////////////////////////
537
538 nevMC = ceSum[2];
539 Double_t intTrue = ceSum[0]/(nevMC+0.000001);
540 Double_t intDriv=0.;
541
542 if (kBest == -1) Varedu(ceSum,kBest,xBest,yBest); // determine the best edge,
543 intDriv =sqrt(ceSum[1]/nevMC) -intTrue; // Foam build-up, sqrt(<w**2>) -<w>
544
545 //=================================================================================
546 cell->SetBest(kBest);
547 cell->SetXdiv(xBest);
548 cell->SetIntg(intTrue);
549 cell->SetDriv(intDriv);
550 SetCellElement(cell, 0, totevents);
551
552 // correct/update integrals in all parent cells to the top of the tree
553 Double_t parIntg, parDriv;
554 for (parent = cell->GetPare(); parent!=0; parent = parent->GetPare()){
555 parIntg = parent->GetIntg();
556 parDriv = parent->GetDriv();
557 parent->SetIntg( parIntg +intTrue -intOld );
558 parent->SetDriv( parDriv +intDriv -driOld );
559 SetCellElement( parent, 0, GetCellElement(parent, 0) + totevents - toteventsOld);
560 }
561 delete [] volPart;
562 delete [] xRand;
563}
564
565////////////////////////////////////////////////////////////////////////////////
566/// Internal subprogram used by Create.
567/// In determines the best edge candidate and the position of the cell division plane
568/// in case of the variance reduction for future cell division,
569/// using results of the MC exploration run stored in fHistEdg
570
571void TMVA::PDEFoam::Varedu(Double_t ceSum[5], Int_t &kBest, Double_t &xBest, Double_t &yBest)
572{
573 Double_t nent = ceSum[2];
574 // Double_t swAll = ceSum[0];
575 Double_t sswAll = ceSum[1];
576 Double_t ssw = sqrt(sswAll)/sqrt(nent);
577 //
578 Double_t sswIn,sswOut,xLo,xUp;
579 kBest =-1;
580 xBest =0.5;
581 yBest =1.0;
582 Double_t maxGain=0.0;
583 // Now go over all projections kProj
584 for(Int_t kProj=0; kProj<fDim; kProj++) {
585 if( fMaskDiv[kProj]) {
586 // initialize search over bins
587 // Double_t sigmIn =0.0; Double_t sigmOut =0.0;
588 Double_t sswtBest = kHigh;
589 Double_t gain =0.0;
590 Double_t xMin=0.0; Double_t xMax=0.0;
591 // Double loop over all pairs jLo<jUp
592 for(Int_t jLo=1; jLo<=fNBin; jLo++) {
593 Double_t aswIn=0; Double_t asswIn=0;
594 for(Int_t jUp=jLo; jUp<=fNBin;jUp++) {
595 aswIn += ((TH1D *)(*fHistEdg)[kProj])->GetBinContent(jUp);
596 asswIn += Sqr(((TH1D *)(*fHistEdg)[kProj])->GetBinError( jUp));
597 xLo=(jLo-1.0)/fNBin;
598 xUp=(jUp*1.0)/fNBin;
599 // swIn = aswIn/nent;
600 // swOut = (swAll-aswIn)/nent;
601 if ( (xUp-xLo) < std::numeric_limits<double>::epsilon()) sswIn=0.;
602 else sswIn = sqrt(asswIn) /sqrt(nent*(xUp-xLo)) *(xUp-xLo);
603 if ( (1.0-xUp+xLo) < std::numeric_limits<double>::epsilon()) sswOut=0.;
604 else if ( sswAll-asswIn < std::numeric_limits<double>::epsilon()) sswOut=0.;
605 else sswOut= sqrt(sswAll-asswIn)/sqrt(nent*(1.0-xUp+xLo)) *(1.0-xUp+xLo);
606 if( (sswIn+sswOut) < sswtBest) {
607 sswtBest = sswIn+sswOut;
608 gain = ssw-sswtBest;
609 // sigmIn = sswIn -swIn; // Debug
610 // sigmOut = sswOut-swOut; // Debug
611 xMin = xLo;
612 xMax = xUp;
613 }
614 }//jUp
615 }//jLo
616 Int_t iLo = (Int_t) (fNBin*xMin);
617 Int_t iUp = (Int_t) (fNBin*xMax);
618
619 if(gain>=maxGain) {
620 maxGain=gain;
621 kBest=kProj; // <--- !!!!! The best edge
622 xBest=xMin;
623 yBest=xMax;
624 if(iLo == 0) xBest=yBest; // The best division point
625 if(iUp == fNBin) yBest=xBest; // this is not really used
626 }
627 }
628 } //kProj
629
630 if( (kBest >= fDim) || (kBest<0) )
631 Log() << kFATAL << "Something wrong with kBest" << Endl;
632} //PDEFoam::Varedu
633
634////////////////////////////////////////////////////////////////////////////////
635/// Internal subprogram used by Create.
636/// Provides random vector Alpha 0< Alpha(i) < 1
637
639{
640 // simply generate and load kDim uniform random numbers
641 fPseRan->RndmArray(fDim,fRvec); // kDim random numbers needed
642 for(Int_t k=0; k<fDim; k++) fAlpha[k] = fRvec[k];
643} //MakeAlpha
644
645////////////////////////////////////////////////////////////////////////////////
646/// Internal subprogram used by Create. It finds cell with maximal
647/// driver integral for the purpose of the division. This function
648/// is overridden by the PDEFoam Class to apply cuts on the number
649/// of events in the cell (fNmin) and the cell tree depth
650/// (GetMaxDepth() > 0) during cell buildup.
651
653{
654 Long_t iCell = -1;
655
656 Long_t i;
657 Double_t drivMax, driv, xDiv;
658 Bool_t bCutNmin = kTRUE;
659 Bool_t bCutMaxDepth = kTRUE;
660 // drivMax = kVlow;
661 drivMax = 0; // only split cells if gain>0 (this also avoids splitting at cell boundary)
662 for(i=0; i<=fLastCe; i++) {//without root
663 if( fCells[i]->GetStat() == 1 ) {
664 // if driver integral < numeric limit, skip cell
665 driv = fCells[i]->GetDriv();
667 continue;
668
669 // do not split cell at the edges
670 xDiv = TMath::Abs(fCells[i]->GetXdiv());
673 continue;
674
675 // apply cut on depth
676 if (GetMaxDepth() > 0)
677 bCutMaxDepth = fCells[i]->GetDepth() < GetMaxDepth();
678
679 // apply Nmin-cut
680 if (GetNmin() > 0)
681 bCutNmin = GetCellElement(fCells[i], 0) > GetNmin();
682
683 // choose cell
684 if(driv > drivMax && bCutNmin && bCutMaxDepth) {
685 drivMax = driv;
686 iCell = i;
687 }
688 }
689 }
690
691 if (iCell == -1){
692 if (!bCutNmin)
693 Log() << kVERBOSE << "Warning: No cell with more than "
694 << GetNmin() << " events found!" << Endl;
695 else if (!bCutMaxDepth)
696 Log() << kVERBOSE << "Warning: Maximum depth reached: "
697 << GetMaxDepth() << Endl;
698 else
699 Log() << kWARNING << "<PDEFoam::PeekMax>: no more candidate cells (drivMax>0) found for further splitting." << Endl;
700 }
701
702 return(iCell);
703}
704
705////////////////////////////////////////////////////////////////////////////////
706/// Internal subprogram used by Create.
707/// It divides cell iCell into two daughter cells.
708/// The iCell is retained and tagged as inactive, daughter cells are appended
709/// at the end of the buffer.
710/// New vertex is added to list of vertices.
711/// List of active cells is updated, iCell removed, two daughters added
712/// and their properties set with help of MC sampling (PDEFoam_Explore)
713/// Returns Code RC=-1 of buffer limit is reached, fLastCe=fnBuf.
714
716{
717 // Double_t xdiv;
718 Int_t kBest;
719
720 if(fLastCe+1 >= fNCells) Log() << kFATAL << "Buffer limit is reached, fLastCe=fnBuf" << Endl;
721
722 cell->SetStat(0); // reset cell as inactive
723 fNoAct++;
724
725 // xdiv = cell->GetXdiv();
726 kBest = cell->GetBest();
727 if( kBest<0 || kBest>=fDim ) Log() << kFATAL << "Wrong kBest" << Endl;
728
729 //////////////////////////////////////////////////////////////////
730 // define two daughter cells (active) //
731 //////////////////////////////////////////////////////////////////
732
733 Int_t d1 = CellFill(1, cell);
734 Int_t d2 = CellFill(1, cell);
735 cell->SetDau0((fCells[d1]));
736 cell->SetDau1((fCells[d2]));
737
738 Explore( (fCells[d1]) );
739 Explore( (fCells[d2]) );
740
741 return 1;
742} // PDEFoam_Divide
743
744////////////////////////////////////////////////////////////////////////////////
745/// Internal subprogram.
746/// Evaluates (training) distribution.
747
749{
750 // Transform variable xRand, since Foam boundaries are [0,1] and
751 // fDistr is filled with events which range in [fXmin,fXmax]
752 //
753 // Transformation: [0, 1] --> [xmin, xmax]
754 std::vector<Double_t> xvec;
755 xvec.reserve(GetTotDim());
756 for (Int_t idim = 0; idim < GetTotDim(); ++idim)
757 xvec.push_back( VarTransformInvers(idim, xRand[idim]) );
758
759 return GetDistr()->Density(xvec, event_density);
760}
761
762////////////////////////////////////////////////////////////////////////////////
763/// Internal subprogram used by Create.
764/// It grow new cells by the binary division process.
765/// This function is overridden by the PDEFoam class to stop the foam buildup process
766/// if one of the cut conditions stop the cell split.
767
769{
770 fTimer->Init(fNCells);
771
772 Long_t iCell;
773 PDEFoamCell* newCell;
774
775 while ( (fLastCe+2) < fNCells ) { // this condition also checked inside Divide
776 iCell = PeekMax(); // peek up cell with maximum driver integral
777
778 if ( (iCell<0) || (iCell>fLastCe) ) {
779 Log() << kVERBOSE << "Break: "<< fLastCe+1 << " cells created" << Endl;
780 // remove remaining empty cells
781 for (Long_t jCell=fLastCe+1; jCell<fNCells; jCell++)
782 delete fCells[jCell];
783 fNCells = fLastCe+1;
784 break;
785 }
786 newCell = fCells[iCell];
787
788 OutputGrow();
789
790 if ( Divide( newCell )==0) break; // and divide it into two
791 }
792 OutputGrow( kTRUE );
793 CheckAll(1); // set arg=1 for more info
794
795 Log() << kVERBOSE << GetNActiveCells() << " active cells created" << Endl;
796}// Grow
797
798////////////////////////////////////////////////////////////////////////////////
799/// This can be called before Create, after setting kDim
800/// It defines which variables are excluded in the process of the cell division.
801/// For example 'FoamX->SetInhiDiv(1, 1);' inhibits division of y-variable.
802
804{
805 if(fDim==0) Log() << kFATAL << "SetInhiDiv: fDim=0" << Endl;
806 if(fInhiDiv == 0) {
807 fInhiDiv = new Int_t[ fDim ];
808 for(Int_t i=0; i<fDim; i++) fInhiDiv[i]=0;
809 }
810 //
811 if( ( 0<=iDim) && (iDim<fDim)) {
812 fInhiDiv[iDim] = inhiDiv;
813 } else
814 Log() << kFATAL << "Wrong iDim" << Endl;
815}//SetInhiDiv
816
817////////////////////////////////////////////////////////////////////////////////
818/// User utility, miscellaneous and debug.
819/// Checks all pointers in the tree of cells. This is useful auto-diagnostic.
820/// level=0, no printout, failures causes STOP
821/// level=1, printout, failures lead to WARNINGS only
822
824{
825 Int_t errors, warnings;
826 PDEFoamCell *cell;
827 Long_t iCell;
828
829 errors = 0; warnings = 0;
830 if (level==1) Log() << kVERBOSE << "Performing consistency checks for created foam" << Endl;
831 for(iCell=1; iCell<=fLastCe; iCell++) {
832 cell = fCells[iCell];
833 // checking general rules
834 if( ((cell->GetDau0()==0) && (cell->GetDau1()!=0) ) ||
835 ((cell->GetDau1()==0) && (cell->GetDau0()!=0) ) ) {
836 errors++;
837 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has only one daughter " << iCell << Endl;
838 }
839 if( (cell->GetDau0()==0) && (cell->GetDau1()==0) && (cell->GetStat()==0) ) {
840 errors++;
841 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has no daughter and is inactive " << iCell << Endl;
842 }
843 if( (cell->GetDau0()!=0) && (cell->GetDau1()!=0) && (cell->GetStat()==1) ) {
844 errors++;
845 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d has two daughters and is active " << iCell << Endl;
846 }
847
848 // checking parents
849 if( (cell->GetPare())!=fCells[0] ) { // not child of the root
850 if ( (cell != cell->GetPare()->GetDau0()) && (cell != cell->GetPare()->GetDau1()) ) {
851 errors++;
852 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d parent not pointing to this cell " << iCell << Endl;
853 }
854 }
855
856 // checking daughters
857 if(cell->GetDau0()!=0) {
858 if(cell != (cell->GetDau0())->GetPare()) {
859 errors++;
860 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d daughter 0 not pointing to this cell " << iCell << Endl;
861 }
862 }
863 if(cell->GetDau1()!=0) {
864 if(cell != (cell->GetDau1())->GetPare()) {
865 errors++;
866 if (level==1) Log() << kFATAL << "ERROR: Cell's no %d daughter 1 not pointing to this cell " << iCell << Endl;
867 }
868 }
869 if(cell->GetVolume()<1E-50) {
870 errors++;
871 if(level==1) Log() << kFATAL << "ERROR: Cell no. " << iCell << " has Volume of <1E-50" << Endl;
872 }
873 }// loop after cells;
874
875 // Check for cells with Volume=0
876 for(iCell=0; iCell<=fLastCe; iCell++) {
877 cell = fCells[iCell];
878 if( (cell->GetStat()==1) && (cell->GetVolume()<1E-11) ) {
879 errors++;
880 if(level==1) Log() << kFATAL << "ERROR: Cell no. " << iCell << " is active but Volume is 0 " << Endl;
881 }
882 }
883 // summary
884 if(level==1){
885 Log() << kVERBOSE << "Check has found " << errors << " errors and " << warnings << " warnings." << Endl;
886 }
887 if(errors>0){
888 Info("CheckAll","Check - found total %d errors \n",errors);
889 }
890} // Check
891
892////////////////////////////////////////////////////////////////////////////////
893/// Prints geometry of and elements of 'iCell', as well as relations
894/// to parent and daughter cells.
895
897{
898 if (iCell < 0 || iCell > fLastCe) {
899 Log() << kWARNING << "<PrintCell(iCell=" << iCell
900 << ")>: cell number " << iCell << " out of bounds!"
901 << Endl;
902 return;
903 }
904
905 PDEFoamVect cellPosi(fDim), cellSize(fDim);
906 fCells[iCell]->GetHcub(cellPosi,cellSize);
907 Int_t kBest = fCells[iCell]->GetBest();
908 Double_t xBest = fCells[iCell]->GetXdiv();
909
910 Log() << "Cell[" << iCell << "]={ ";
911 Log() << " " << fCells[iCell] << " " << Endl; // extra DEBUG
912 Log() << " Xdiv[abs. coord.]="
913 << VarTransformInvers(kBest,cellPosi[kBest] + xBest*cellSize[kBest])
914 << Endl;
915 Log() << " Abs. coord. = (";
916 for (Int_t idim=0; idim<fDim; idim++) {
917 Log() << "dim[" << idim << "]={"
918 << VarTransformInvers(idim,cellPosi[idim]) << ","
919 << VarTransformInvers(idim,cellPosi[idim] + cellSize[idim])
920 << "}";
921 if (idim < fDim-1)
922 Log() << ", ";
923 }
924 Log() << ")" << Endl;
925 fCells[iCell]->Print("1");
926 // print the cell elements
927 Log() << "Elements: [";
928 TVectorD *vec = (TVectorD*)fCells[iCell]->GetElement();
929 if (vec != NULL){
930 for (Int_t i=0; i<vec->GetNrows(); i++){
931 if (i>0) Log() << ", ";
932 Log() << GetCellElement(fCells[iCell], i);
933 }
934 } else
935 Log() << "not set";
936 Log() << "]" << Endl;
937 Log()<<"}"<<Endl;
938}
939
940////////////////////////////////////////////////////////////////////////////////
941/// Prints geometry of ALL cells of the FOAM
942
944{
945 for(Long_t iCell=0; iCell<=fLastCe; iCell++)
946 PrintCell(iCell);
947}
948
949////////////////////////////////////////////////////////////////////////////////
950/// This function fills a weight 'wt' into the PDEFoam cell, which
951/// corresponds to the given event 'ev'. Per default cell element 0
952/// is filled with the weight 'wt', and cell element 1 is filled
953/// with the squared weight. This function can be overridden by a
954/// subclass in order to change the values stored in the foam cells.
955
957{
958 // find corresponding foam cell
959 std::vector<Float_t> values = ev->GetValues();
960 std::vector<Float_t> tvalues = VarTransform(values);
961 PDEFoamCell *cell = FindCell(tvalues);
962
963 // 0. Element: Sum of weights 'wt'
964 // 1. Element: Sum of weights 'wt' squared
965 SetCellElement(cell, 0, GetCellElement(cell, 0) + wt);
966 SetCellElement(cell, 1, GetCellElement(cell, 1) + wt*wt);
967}
968
969////////////////////////////////////////////////////////////////////////////////
970/// Remove the cell elements from all cells.
971
973{
974 if (!fCells) return;
975
976 Log() << kVERBOSE << "Delete cell elements" << Endl;
977 for (Long_t iCell = 0; iCell < fNCells; ++iCell) {
978 TObject* elements = fCells[iCell]->GetElement();
979 if (elements) {
980 delete elements;
981 fCells[iCell]->SetElement(NULL);
982 }
983 }
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Returns true, if the value of the given cell is undefined.
988/// Default value: kFALSE. This function can be overridden by
989/// sub-classes.
990
992{
993 return kFALSE;
994}
995
996////////////////////////////////////////////////////////////////////////////////
997/// This function finds the cell, which corresponds to the given
998/// untransformed event vector 'xvec' and return its value, which is
999/// given by the parameter 'cv'. If kernel != NULL, then
1000/// PDEFoamKernelBase::Estimate() is called on the transformed event
1001/// variables.
1002///
1003/// Parameters:
1004///
1005/// - xvec - event vector (untransformed, [fXmin,fXmax])
1006///
1007/// - cv - the cell value to return
1008///
1009/// - kernel - PDEFoam kernel estimator. If NULL is given, than the
1010/// pure cell value is returned
1011///
1012/// Return:
1013///
1014/// The cell value, corresponding to 'xvec', estimated by the given
1015/// kernel.
1016
1017Float_t TMVA::PDEFoam::GetCellValue(const std::vector<Float_t> &xvec, ECellValue cv, PDEFoamKernelBase *kernel)
1018{
1019 std::vector<Float_t> txvec(VarTransform(xvec));
1020 if (kernel == NULL)
1021 return GetCellValue(FindCell(txvec), cv);
1022 else
1023 return kernel->Estimate(this, txvec, cv);
1024}
1025
1026////////////////////////////////////////////////////////////////////////////////
1027/// This function finds all cells, which corresponds to the given
1028/// (incomplete) untransformed event vector 'xvec' and returns the
1029/// cell values, according to the parameter 'cv'.
1030///
1031/// Parameters:
1032///
1033/// - xvec - map for the untransformed vector. The key (Int_t) is
1034/// the dimension, and the value (Float_t) is the event
1035/// coordinate. Note that not all coordinates have to be
1036/// specified.
1037///
1038/// - cv - cell values to return
1039///
1040/// Return:
1041///
1042/// cell values from all cells that were found
1043
1044std::vector<Float_t> TMVA::PDEFoam::GetCellValue( const std::map<Int_t,Float_t>& xvec, ECellValue cv )
1045{
1046 // transformed event
1047 std::map<Int_t,Float_t> txvec;
1048 for (std::map<Int_t,Float_t>::const_iterator it=xvec.begin(); it!=xvec.end(); ++it)
1049 txvec.insert(std::pair<Int_t, Float_t>(it->first, VarTransform(it->first, it->second)));
1050
1051 // find all cells, which correspond to the transformed event
1052 std::vector<PDEFoamCell*> cells = FindCells(txvec);
1053
1054 // get the cell values
1055 std::vector<Float_t> cell_values;
1056 cell_values.reserve(cells.size());
1057 for (std::vector<PDEFoamCell*>::const_iterator cell_it=cells.begin();
1058 cell_it != cells.end(); ++cell_it)
1059 cell_values.push_back(GetCellValue(*cell_it, cv));
1060
1061 return cell_values;
1062}
1063
1064////////////////////////////////////////////////////////////////////////////////
1065/// Find cell that contains 'xvec' (in foam coordinates [0,1]).
1066///
1067/// Loop to find cell that contains 'xvec' starting at root cell,
1068/// and traversing binary tree to find the cell quickly. Note, that
1069/// if 'xvec' lies outside the foam, the cell which is nearest to
1070/// 'xvec' is returned. (The returned pointer should never be
1071/// NULL.)
1072///
1073/// Parameters:
1074///
1075/// - xvec - event vector (in foam coordinates [0,1])
1076///
1077/// Return:
1078///
1079/// PDEFoam cell corresponding to 'xvec'
1080
1081TMVA::PDEFoamCell* TMVA::PDEFoam::FindCell( const std::vector<Float_t> &xvec ) const
1082{
1083 PDEFoamVect cellPosi0(GetTotDim()), cellSize0(GetTotDim());
1084 PDEFoamCell *cell, *cell0;
1085
1086 cell=fCells[0]; // start with root cell
1087 Int_t idim=0;
1088 while (cell->GetStat()!=1) { //go down binary tree until cell is found
1089 idim=cell->GetBest(); // dimension that changed
1090 cell0=cell->GetDau0();
1091 cell0->GetHcub(cellPosi0,cellSize0);
1092
1093 if (xvec.at(idim)<=cellPosi0[idim]+cellSize0[idim])
1094 cell=cell0;
1095 else
1096 cell=(cell->GetDau1());
1097 }
1098 return cell;
1099}
1100
1101////////////////////////////////////////////////////////////////////////////////
1102/// This is a helper function for std::vector<PDEFoamCell*>
1103/// FindCells(...) and a generalisation of PDEFoamCell* FindCell().
1104/// It saves in 'cells' all cells, which contain the coordinates
1105/// specifies in 'txvec'. Note, that not all coordinates have to be
1106/// specified in 'txvec'.
1107///
1108/// Parameters:
1109///
1110/// - txvec - event vector in foam coordinates [0,1]. The key is
1111/// the dimension and the value is the event coordinate. Note,
1112/// that not all coordinates have to be specified.
1113///
1114/// - cell - cell to start searching with (usually root cell
1115/// fCells[0])
1116///
1117/// - cells - list of cells that were found
1118
1119void TMVA::PDEFoam::FindCells(const std::map<Int_t, Float_t> &txvec, PDEFoamCell* cell, std::vector<PDEFoamCell*> &cells) const
1120{
1121 PDEFoamVect cellPosi0(GetTotDim()), cellSize0(GetTotDim());
1122 PDEFoamCell *cell0;
1123 Int_t idim=0;
1124
1125 while (cell->GetStat()!=1) { //go down binary tree until cell is found
1126 idim=cell->GetBest(); // dimension that changed
1127
1128 // check if dimension 'idim' is specified in 'txvec'
1129 map<Int_t, Float_t>::const_iterator it = txvec.find(idim);
1130
1131 if (it != txvec.end()){
1132 // case 1: cell is splitten in a dimension which is specified
1133 // in txvec
1134 cell0=cell->GetDau0();
1135 cell0->GetHcub(cellPosi0,cellSize0);
1136 // check, whether left daughter cell contains txvec
1137 if (it->second <= cellPosi0[idim] + cellSize0[idim])
1138 cell=cell0;
1139 else
1140 cell=cell->GetDau1();
1141 } else {
1142 // case 2: cell is splitten in target dimension
1143 FindCells(txvec, cell->GetDau0(), cells);
1144 FindCells(txvec, cell->GetDau1(), cells);
1145 return;
1146 }
1147 }
1148 cells.push_back(cell);
1149}
1150
1151////////////////////////////////////////////////////////////////////////////////
1152/// Find all cells, that contain txvec. This function can be used,
1153/// when the dimension of the foam is greater than the dimension of
1154/// txvec. E.g. this is the case for multi-target regression.
1155///
1156/// Parameters:
1157///
1158/// - txvec - event vector of variables, transformed into foam
1159/// coordinates [0,1]. The size of txvec can be smaller than the
1160/// dimension of the foam.
1161///
1162/// Return value:
1163///
1164/// - vector of cells, that fit txvec
1165
1166std::vector<TMVA::PDEFoamCell*> TMVA::PDEFoam::FindCells(const std::vector<Float_t> &txvec) const
1167{
1168 // copy the coordinates from 'txvec' into a map
1169 std::map<Int_t, Float_t> txvec_map;
1170 for (UInt_t i=0; i<txvec.size(); ++i)
1171 txvec_map.insert(std::pair<Int_t, Float_t>(i, txvec.at(i)));
1172
1173 // the cells found
1174 std::vector<PDEFoamCell*> cells(0);
1175
1176 // loop over all target dimensions
1177 FindCells(txvec_map, fCells[0], cells);
1178
1179 return cells;
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Find all cells, that contain the coordinates specified in txvec.
1184/// The key in 'txvec' is the dimension, and the corresponding value
1185/// is the coordinate. Note, that not all coordinates have to be
1186/// specified in txvec.
1187///
1188/// Parameters:
1189///
1190/// - txvec - map of coordinates (transformed into foam coordinates
1191/// [0,1])
1192///
1193/// Return value:
1194///
1195/// - vector of cells, that fit txvec
1196
1197std::vector<TMVA::PDEFoamCell*> TMVA::PDEFoam::FindCells(const std::map<Int_t, Float_t> &txvec) const
1198{
1199 // the cells found
1200 std::vector<PDEFoamCell*> cells(0);
1201
1202 // loop over all target dimensions
1203 FindCells(txvec, fCells[0], cells);
1204
1205 return cells;
1206}
1207
1208////////////////////////////////////////////////////////////////////////////////
1209/// Draws 1-dimensional foam (= histogram)
1210///
1211/// Parameters:
1212///
1213/// - cell_value - the cell value to draw
1214///
1215/// - nbin - number of bins of result histogram
1216///
1217/// - kernel - a PDEFoam kernel.
1218
1219TH1D* TMVA::PDEFoam::Draw1Dim( ECellValue cell_value, Int_t nbin, PDEFoamKernelBase *kernel )
1220{
1221 // avoid plotting of wrong dimensions
1222 if ( GetTotDim()!=1 )
1223 Log() << kFATAL << "<Draw1Dim>: function can only be used for 1-dimensional foams!"
1224 << Endl;
1225
1226 TString hname("h_1dim");
1227 TH1D* h1=(TH1D*)gDirectory->Get(hname);
1228 if (h1) delete h1;
1229 h1= new TH1D(hname, "1-dimensional Foam", nbin, fXmin[0], fXmax[0]);
1230
1231 if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
1232
1233 // loop over all bins
1234 for (Int_t ibinx=1; ibinx<=h1->GetNbinsX(); ++ibinx) {
1235 // get event vector corresponding to bin
1236 std::vector<Float_t> txvec;
1237 txvec.push_back( VarTransform(0, h1->GetBinCenter(ibinx)) );
1238 Float_t val = 0;
1239 if (kernel != NULL) {
1240 // get cell value using the kernel
1241 val = kernel->Estimate(this, txvec, cell_value);
1242 } else {
1243 val = GetCellValue(FindCell(txvec), cell_value);
1244 }
1245 // fill value to histogram
1246 h1->SetBinContent(ibinx, val + h1->GetBinContent(ibinx));
1247 }
1248
1249 return h1;
1250}
1251
1252////////////////////////////////////////////////////////////////////////////////
1253/// Project foam variable idim1 and variable idim2 to histogram.
1254///
1255/// Parameters:
1256///
1257/// - idim1, idim2 - dimensions to project to
1258///
1259/// - cell_value - the cell value to draw
1260///
1261/// - kernel - a PDEFoam kernel (optional). If NULL is given, the
1262/// kernel is ignored and the pure cell values are
1263/// plotted.
1264///
1265/// - nbin - number of bins in x and y direction of result histogram
1266/// (optional, default is 50).
1267///
1268/// Returns:
1269/// a 2-dimensional histogram
1270
1271TH2D* TMVA::PDEFoam::Project2( Int_t idim1, Int_t idim2, ECellValue cell_value, PDEFoamKernelBase *kernel, UInt_t nbin )
1272{
1273 // avoid plotting of wrong dimensions
1274 if ((idim1>=GetTotDim()) || (idim1<0) ||
1275 (idim2>=GetTotDim()) || (idim2<0) ||
1276 (idim1==idim2) )
1277 Log() << kFATAL << "<Project2>: wrong dimensions given: "
1278 << idim1 << ", " << idim2 << Endl;
1279
1280 // root can not handle too many bins in one histogram --> catch this
1281 // Furthermore, to have more than 1000 bins in the histogram doesn't make
1282 // sense.
1283 if (nbin>1000){
1284 Log() << kWARNING << "Warning: number of bins too big: " << nbin
1285 << " Using 1000 bins for each dimension instead." << Endl;
1286 nbin = 1000;
1287 } else if (nbin<1) {
1288 Log() << kWARNING << "Wrong bin number: " << nbin
1289 << "; set nbin=50" << Endl;
1290 nbin = 50;
1291 }
1292
1293 // create result histogram
1294 TString hname(Form("h_%d_vs_%d",idim1,idim2));
1295
1296 // if histogram with this name already exists, delete it
1297 TH2D* h1=(TH2D*)gDirectory->Get(hname.Data());
1298 if (h1) delete h1;
1299 h1= new TH2D(hname.Data(), Form("var%d vs var%d",idim1,idim2), nbin, fXmin[idim1], fXmax[idim1], nbin, fXmin[idim2], fXmax[idim2]);
1300
1301 if (!h1) Log() << kFATAL << "ERROR: Can not create histo" << hname << Endl;
1302
1303 // ============== start projection algorithm ================
1304 // loop over all histogram bins (2-dim)
1305 for (Int_t xbin = 1; xbin <= h1->GetNbinsX(); ++xbin) {
1306 for (Int_t ybin = 1; ybin <= h1->GetNbinsY(); ++ybin) {
1307 // calculate the phase space point, which corresponds to this
1308 // bin combination
1309 std::map<Int_t, Float_t> txvec;
1310 txvec[idim1] = VarTransform(idim1, h1->GetXaxis()->GetBinCenter(xbin));
1311 txvec[idim2] = VarTransform(idim2, h1->GetYaxis()->GetBinCenter(ybin));
1312
1313 // find the cells, which corresponds to this phase space
1314 // point
1315 std::vector<TMVA::PDEFoamCell*> cells = FindCells(txvec);
1316
1317 // loop over cells and fill the histogram with the cell
1318 // values
1319 Float_t sum_cv = 0; // sum of the cell values
1320 for (std::vector<TMVA::PDEFoamCell*>::const_iterator it = cells.begin();
1321 it != cells.end(); ++it) {
1322 // get cell position and size
1323 PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
1324 (*it)->GetHcub(cellPosi,cellSize);
1325 // Create complete event vector from txvec. The missing
1326 // coordinates of txvec are set to the cell center.
1327 std::vector<Float_t> tvec;
1328 for (Int_t i=0; i<GetTotDim(); ++i) {
1329 if ( i != idim1 && i != idim2 )
1330 tvec.push_back(cellPosi[i] + 0.5*cellSize[i]);
1331 else
1332 tvec.push_back(txvec[i]);
1333 }
1334 if (kernel != NULL) {
1335 // get the cell value using the kernel
1336 sum_cv += kernel->Estimate(this, tvec, cell_value);
1337 } else {
1338 sum_cv += GetCellValue(FindCell(tvec), cell_value);
1339 }
1340 }
1341
1342 // fill the bin content
1343 h1->SetBinContent(xbin, ybin, sum_cv + h1->GetBinContent(xbin, ybin));
1344 }
1345 }
1346
1347 return h1;
1348}
1349
1350////////////////////////////////////////////////////////////////////////////////
1351/// Returns the cell value of 'cell' corresponding to the given
1352/// option 'cv'. This function should be overridden by the subclass
1353/// in order to specify which cell elements to return for a given
1354/// cell value 'cv'. By default kValue returns cell element 0, and
1355/// kValueError returns cell element 1.
1356
1358{
1359 // calculate cell value (depending on the given option 'cv')
1360 switch (cv) {
1361
1362 case kValue:
1363 return GetCellElement(cell, 0);
1364
1365 case kValueError:
1366 return GetCellElement(cell, 1);
1367
1368 case kValueDensity: {
1369
1370 Double_t volume = cell->GetVolume();
1371 if (volume > numeric_limits<double>::epsilon()) {
1372 return GetCellValue(cell, kValue)/volume;
1373 } else {
1374 if (volume<=0){
1375 cell->Print("1"); // debug output
1376 Log() << kWARNING << "<GetCellDensity(cell)>: ERROR: cell volume"
1377 << " negative or zero!"
1378 << " ==> return cell density 0!"
1379 << " cell volume=" << volume
1380 << " cell entries=" << GetCellValue(cell, kValue) << Endl;
1381 } else {
1382 Log() << kWARNING << "<GetCellDensity(cell)>: WARNING: cell volume"
1383 << " close to zero!"
1384 << " cell volume: " << volume << Endl;
1385 }
1386 }
1387 }
1388 return 0;
1389
1390 case kMeanValue:
1391 return cell->GetIntg();
1392
1393 case kRms:
1394 return cell->GetDriv();
1395
1396 case kRmsOvMean:
1397 if (cell->GetIntg() != 0)
1398 return cell->GetDriv()/cell->GetIntg();
1399 else
1400 return 0;
1401
1402 case kCellVolume:
1403 return cell->GetVolume();
1404
1405 default:
1406 Log() << kFATAL << "<GetCellValue>: unknown cell value" << Endl;
1407 return 0;
1408 }
1409
1410 return 0;
1411}
1412
1413////////////////////////////////////////////////////////////////////////////////
1414/// Returns cell element i of cell 'cell'. If the cell has no
1415/// elements or the index 'i' is out of range, than 0 is returned.
1416
1418{
1419 // dynamic_cast doesn't seem to work here ?!
1420 TVectorD *vec = (TVectorD*)cell->GetElement();
1421
1422 // if vec is not set or index out of range, return 0
1423 if (!vec || i >= (UInt_t) vec->GetNrows())
1424 return 0;
1425
1426 return (*vec)(i);
1427}
1428
1429////////////////////////////////////////////////////////////////////////////////
1430/// Set cell element i of cell to value. If the cell element i does
1431/// not exist, it is created.
1432
1434{
1435 TVectorD *vec = NULL;
1436
1437 // if no cell elements are set, create TVectorD with i+1 entries,
1438 // ranging from [0,i]
1439 if (cell->GetElement() == NULL) {
1440 vec = new TVectorD(i+1);
1441 vec->Zero(); // set all values to zero
1442 (*vec)(i) = value; // set element i to value
1443 cell->SetElement(vec);
1444 } else {
1445 // dynamic_cast doesn't seem to work here ?!
1446 vec = (TVectorD*)cell->GetElement();
1447 if (!vec)
1448 Log() << kFATAL << "<SetCellElement> ERROR: cell element is not a TVectorD*" << Endl;
1449 // check vector size and resize if necessary
1450 if (i >= (UInt_t) vec->GetNrows())
1451 vec->ResizeTo(0,i);
1452 // set element i to value
1453 (*vec)(i) = value;
1454 }
1455}
1456
1457////////////////////////////////////////////////////////////////////////////////
1458/// Overridden function of PDEFoam to avoid native foam output.
1459/// Draw TMVA-process bar instead.
1460
1462{
1463 if (finished) {
1464 Log() << kINFO << "Elapsed time: " + fTimer->GetElapsedTime()
1465 << " " << Endl;
1466 return;
1467 }
1468
1469 Int_t modulo = 1;
1470
1471 if (fNCells >= 100) modulo = Int_t(fNCells/100);
1472 if (fLastCe%modulo == 0) fTimer->DrawProgressBar( fLastCe );
1473}
1474
1475////////////////////////////////////////////////////////////////////////////////
1476/// Debugging tool which plots the cells of a 2-dimensional PDEFoam
1477/// as rectangles in C++ format readable for ROOT.
1478///
1479/// Parameters:
1480/// - filename - filename of output root macro
1481///
1482/// - opt - cell_value, rms, rms_ov_mean
1483/// If cell_value is set, the following values will be filled into
1484/// the result histogram:
1485/// - number of events - in case of classification with 2 separate
1486/// foams or multi-target regression
1487/// - discriminator - in case of classification with one
1488/// unified foam
1489/// - target - in case of mono-target regression
1490/// If none of {cell_value, rms, rms_ov_mean} is given, the cells
1491/// will not be filled.
1492/// If 'opt' contains the string 'cellnumber', the index of
1493/// each cell is draw in addition.
1494///
1495/// - createCanvas - whether to create a new canvas or not
1496///
1497/// - colors - whether to fill cells with colors or shades of grey
1498///
1499/// Example:
1500///
1501/// The following commands load a mono-target regression foam from
1502/// file 'foam.root' and create a ROOT macro 'output.C', which
1503/// draws all PDEFoam cells with little boxes. The latter are
1504/// filled with colors according to the target value stored in the
1505/// cell. Also the cell number is drawn.
1506///
1507/// TFile file("foam.root");
1508/// TMVA::PDEFoam *foam = (TMVA::PDEFoam*) gDirectory->Get("MonoTargetRegressionFoam");
1509/// foam->RootPlot2dim("output.C","cell_value,cellnumber");
1510/// gROOT->Macro("output.C");
1511
1513 Bool_t createCanvas, Bool_t colors )
1514{
1515 if (GetTotDim() != 2)
1516 Log() << kFATAL << "RootPlot2dim() can only be used with "
1517 << "two-dimensional foams!" << Endl;
1518
1519 // select value to plot
1520 ECellValue cell_value = kValue;
1521 Bool_t plotcellnumber = kFALSE;
1522 Bool_t fillcells = kTRUE;
1523 if (opt.Contains("cell_value")){
1524 cell_value = kValue;
1525 } else if (opt.Contains("rms_ov_mean")){
1526 cell_value = kRmsOvMean;
1527 } else if (opt.Contains("rms")){
1528 cell_value = kRms;
1529 } else {
1530 fillcells = kFALSE;
1531 }
1532 if (opt.Contains("cellnumber"))
1533 plotcellnumber = kTRUE;
1534
1535 // open file (root macro)
1536 std::ofstream outfile(filename, std::ios::out);
1537
1538 outfile<<"{" << std::endl;
1539
1540 // declare boxes and set the fill styles
1541 if (!colors) { // define grayscale colors from light to dark,
1542 // starting from color index 1000
1543 outfile << "TColor *graycolors[100];" << std::endl;
1544 outfile << "for (Int_t i=0.; i<100; i++)" << std::endl;
1545 outfile << " graycolors[i]=new TColor(1000+i, 1-(Float_t)i/100.,1-(Float_t)i/100.,1-(Float_t)i/100.);"<< std::endl;
1546 }
1547 if (createCanvas)
1548 outfile << "cMap = new TCanvas(\"" << fName << "\",\"Cell Map for "
1549 << fName << "\",600,600);" << std::endl;
1550
1551 outfile<<"TBox*a=new TBox();"<<std::endl;
1552 outfile<<"a->SetFillStyle(0);"<<std::endl; // big frame
1553 outfile<<"a->SetLineWidth(4);"<<std::endl;
1554 outfile<<"TBox *b1=new TBox();"<<std::endl; // single cell
1555 outfile<<"TText*t=new TText();"<<std::endl; // text for numbering
1556 if (fillcells) {
1557 outfile << (colors ? "gStyle->SetPalette(1, 0);" : "gStyle->SetPalette(0);")
1558 << std::endl;
1559 outfile <<"b1->SetFillStyle(1001);"<<std::endl;
1560 outfile<<"TBox *b2=new TBox();"<<std::endl; // single cell
1561 outfile <<"b2->SetFillStyle(0);"<<std::endl;
1562 }
1563 else {
1564 outfile <<"b1->SetFillStyle(0);"<<std::endl;
1565 }
1566
1567 if (fillcells)
1568 (colors ? gStyle->SetPalette(1, 0) : gStyle->SetPalette(0) );
1569
1570 Float_t zmin = 1E8; // minimal value (for color calculation)
1571 Float_t zmax = -1E8; // maximal value (for color calculation)
1572
1573 // if cells shall be filled, calculate minimal and maximal plot
1574 // value --> store in zmin and zmax
1575 if (fillcells) {
1576 for (Long_t iCell=1; iCell<=fLastCe; iCell++) {
1577 if ( fCells[iCell]->GetStat() == 1) {
1578 Float_t value = GetCellValue(fCells[iCell], cell_value);
1579 if (value<zmin)
1580 zmin=value;
1581 if (value>zmax)
1582 zmax=value;
1583 }
1584 }
1585 outfile << "// observed minimum and maximum of distribution: " << std::endl;
1586 outfile << "// Float_t zmin = "<< zmin << ";" << std::endl;
1587 outfile << "// Float_t zmax = "<< zmax << ";" << std::endl;
1588 }
1589
1590 outfile << "// used minimum and maximum of distribution (taking into account log scale if applicable): " << std::endl;
1591 outfile << "Float_t zmin = "<< zmin << ";" << std::endl;
1592 outfile << "Float_t zmax = "<< zmax << ";" << std::endl;
1593
1594 Float_t x1,y1,x2,y2,x,y; // box and text coordinates
1595 Float_t offs = 0.01;
1596 Float_t lpag = 1-2*offs;
1597 Int_t ncolors = colors ? gStyle->GetNumberOfColors() : 100;
1598 Float_t scale = (ncolors-1)/(zmax - zmin);
1599 PDEFoamVect cellPosi(GetTotDim()), cellSize(GetTotDim());
1600
1601 // loop over cells and draw a box for every cell (and maybe the
1602 // cell number as well)
1603 outfile << "// =========== Rectangular cells ==========="<< std::endl;
1604 for (Long_t iCell=1; iCell<=fLastCe; iCell++) {
1605 if ( fCells[iCell]->GetStat() == 1) {
1606 fCells[iCell]->GetHcub(cellPosi,cellSize);
1607 x1 = offs+lpag*(cellPosi[0]);
1608 y1 = offs+lpag*(cellPosi[1]);
1609 x2 = offs+lpag*(cellPosi[0]+cellSize[0]);
1610 y2 = offs+lpag*(cellPosi[1]+cellSize[1]);
1611
1612 if (fillcells) {
1613 // get cell value
1614 Float_t value = GetCellValue(fCells[iCell], cell_value);
1615
1616 // calculate fill color
1617 Int_t color;
1618 if (colors)
1619 color = gStyle->GetColorPalette(Int_t((value-zmin)*scale));
1620 else
1621 color = 1000+(Int_t((value-zmin)*scale));
1622
1623 // set fill color of box b1
1624 outfile << "b1->SetFillColor(" << color << ");" << std::endl;
1625 }
1626
1627 // cell rectangle
1628 outfile<<"b1->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
1629 if (fillcells)
1630 outfile<<"b2->DrawBox("<<x1<<","<<y1<<","<<x2<<","<<y2<<");"<<std::endl;
1631
1632 // cell number
1633 if (plotcellnumber) {
1634 outfile<<"t->SetTextColor(4);"<<std::endl;
1635 if(fLastCe<51)
1636 outfile<<"t->SetTextSize(0.025);"<<std::endl; // text for numbering
1637 else if(fLastCe<251)
1638 outfile<<"t->SetTextSize(0.015);"<<std::endl;
1639 else
1640 outfile<<"t->SetTextSize(0.008);"<<std::endl;
1641 x = offs+lpag*(cellPosi[0]+0.5*cellSize[0]);
1642 y = offs+lpag*(cellPosi[1]+0.5*cellSize[1]);
1643 outfile<<"t->DrawText("<<x<<","<<y<<","<<"\""<<iCell<<"\""<<");"<<std::endl;
1644 }
1645 }
1646 }
1647 outfile<<"// ============== End Rectangles ==========="<< std::endl;
1648
1649 outfile << "}" << std::endl;
1650 outfile.flush();
1651 outfile.close();
1652}
1653
1654////////////////////////////////////////////////////////////////////////////////
1655/// Insert event to internal foam's density estimator
1656/// PDEFoamDensityBase.
1657
1659{
1660 GetDistr()->FillBinarySearchTree(ev);
1661}
1662
1663////////////////////////////////////////////////////////////////////////////////
1664/// Delete the foam's density estimator, which contains the binary
1665/// search tree.
1666
1668{
1669 if(fDistr) delete fDistr;
1670 fDistr = NULL;
1671}
static const Float_t kVlow
Definition: PDEFoam.cxx:97
static const Float_t kHigh
Definition: PDEFoam.cxx:96
static const double x2[5]
static const double x1[5]
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
float Float_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
#define gDirectory
Definition: TDirectory.h:229
void Info(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
double sqrt(double)
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:410
TVectorT< Double_t > TVectorD
Definition: TVectorDfwd.h:22
Color * colors
Definition: X3DBuffer.c:21
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:475
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:614
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:8597
virtual Int_t GetNbinsY() const
Definition: TH1.h:293
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1226
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:316
virtual Int_t GetNbinsX() const
Definition: TH1.h:292
TAxis * GetYaxis()
Definition: TH1.h:317
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition: TH1.cxx:8678
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4907
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition: TH1.cxx:706
2-D histogram with a double per channel (see TH1 documentation)}
Definition: TH2.h:292
std::vector< Float_t > & GetValues()
Definition: Event.h:94
ostringstream derivative to redirect and format output
Definition: MsgLogger.h:59
void Fill(Int_t, PDEFoamCell *, PDEFoamCell *, PDEFoamCell *)
Fills in certain data into newly allocated cell.
void SetDau0(PDEFoamCell *Daug)
Definition: PDEFoamCell.h:96
void SetXdiv(Double_t Xdiv)
Definition: PDEFoamCell.h:80
void Print(Option_t *option) const
Printout of the cell geometry parameters for the debug purpose.
void SetElement(TObject *fobj)
Definition: PDEFoamCell.h:106
Int_t GetStat() const
Definition: PDEFoamCell.h:91
void CalcVolume()
Calculates volume of the cell using size params which are calculated.
PDEFoamCell * GetPare() const
Definition: PDEFoamCell.h:93
PDEFoamCell * GetDau1() const
Definition: PDEFoamCell.h:95
Double_t GetIntg() const
Definition: PDEFoamCell.h:86
void SetStat(Int_t Stat)
Definition: PDEFoamCell.h:92
PDEFoamCell * GetDau0() const
Definition: PDEFoamCell.h:94
Int_t GetBest() const
Definition: PDEFoamCell.h:78
Double_t GetDriv() const
Definition: PDEFoamCell.h:87
void SetDau1(PDEFoamCell *Daug)
Definition: PDEFoamCell.h:97
Double_t GetVolume() const
Definition: PDEFoamCell.h:85
TObject * GetElement() const
Definition: PDEFoamCell.h:107
void SetDriv(Double_t Driv)
Definition: PDEFoamCell.h:89
void SetBest(Int_t Best)
Definition: PDEFoamCell.h:79
void GetHcub(PDEFoamVect &, PDEFoamVect &) const
Provides size and position of the cell These parameter are calculated by analyzing information in all...
void SetIntg(Double_t Intg)
Definition: PDEFoamCell.h:88
This class is the abstract kernel interface for PDEFoam.
virtual Float_t Estimate(PDEFoam *, std::vector< Float_t > &, ECellValue)=0
Implementation of PDEFoam.
Definition: PDEFoam.h:77
void Varedu(Double_t[], Int_t &, Double_t &, Double_t &)
Internal subprogram used by Create.
Definition: PDEFoam.cxx:571
Double_t GetCellElement(const PDEFoamCell *cell, UInt_t i) const
Returns cell element i of cell 'cell'.
Definition: PDEFoam.cxx:1417
void DeleteBinarySearchTree()
Delete the foam's density estimator, which contains the binary search tree.
Definition: PDEFoam.cxx:1667
void MakeAlpha()
Internal subprogram used by Create.
Definition: PDEFoam.cxx:638
TObjArray * fVariableNames
timer for graphical output
Definition: PDEFoam.h:115
virtual Float_t GetCellValue(const std::vector< Float_t > &xvec, ECellValue cv, PDEFoamKernelBase *)
This function finds the cell, which corresponds to the given untransformed event vector 'xvec' and re...
Definition: PDEFoam.cxx:1017
void OutputGrow(Bool_t finished=false)
message logger
Definition: PDEFoam.cxx:1461
void SetCellElement(PDEFoamCell *cell, UInt_t i, Double_t value)
Set cell element i of cell to value.
Definition: PDEFoam.cxx:1433
Int_t Divide(PDEFoamCell *)
Internal subprogram used by Create.
Definition: PDEFoam.cxx:715
MsgLogger & Log() const
Definition: PDEFoam.h:238
void PrintCell(Long_t iCell=0)
Prints geometry of and elements of 'iCell', as well as relations to parent and daughter cells.
Definition: PDEFoam.cxx:896
void ResetCellElements()
Remove the cell elements from all cells.
Definition: PDEFoam.cxx:972
void Grow()
Internal subprogram used by Create.
Definition: PDEFoam.cxx:768
Double_t Eval(Double_t *xRand, Double_t &event_density)
Internal subprogram.
Definition: PDEFoam.cxx:748
void PrintCells()
Prints geometry of ALL cells of the FOAM.
Definition: PDEFoam.cxx:943
void SetXmax(Int_t idim, Double_t wmax)
set upper foam bound in dimension idim
Definition: PDEFoam.cxx:277
virtual ~PDEFoam()
Default destructor.
Definition: PDEFoam.cxx:185
PDEFoam()
Default constructor for streamer, user should not use it.
Definition: PDEFoam.cxx:104
TH1D * Draw1Dim(ECellValue cell_value, Int_t nbin, PDEFoamKernelBase *kernel=NULL)
Draws 1-dimensional foam (= histogram)
Definition: PDEFoam.cxx:1219
virtual Bool_t CellValueIsUndefined(PDEFoamCell *)
Returns true, if the value of the given cell is undefined.
Definition: PDEFoam.cxx:991
virtual void FillFoamCells(const Event *ev, Float_t wt)
This function fills a weight 'wt' into the PDEFoam cell, which corresponds to the given event 'ev'.
Definition: PDEFoam.cxx:956
void Create()
Basic initialization of FOAM invoked by the user.
Definition: PDEFoam.cxx:293
void SetInhiDiv(Int_t, Int_t)
This can be called before Create, after setting kDim It defines which variables are excluded in the p...
Definition: PDEFoam.cxx:803
void InitCells()
Internal subprogram used by Create.
Definition: PDEFoam.cxx:357
PDEFoamCell * FindCell(const std::vector< Float_t > &) const
Find cell that contains 'xvec' (in foam coordinates [0,1]).
Definition: PDEFoam.cxx:1081
void FillBinarySearchTree(const Event *ev)
Insert event to internal foam's density estimator PDEFoamDensityBase.
Definition: PDEFoam.cxx:1658
virtual TH2D * Project2(Int_t idim1, Int_t idim2, ECellValue cell_value=kValue, PDEFoamKernelBase *kernel=NULL, UInt_t nbin=50)
Project foam variable idim1 and variable idim2 to histogram.
Definition: PDEFoam.cxx:1271
virtual void Explore(PDEFoamCell *Cell)
Internal subprogram used by Create.
Definition: PDEFoam.cxx:435
void SetXmin(Int_t idim, Double_t wmin)
set lower foam bound in dimension idim
Definition: PDEFoam.cxx:266
std::vector< TMVA::PDEFoamCell * > FindCells(const std::vector< Float_t > &) const
Find all cells, that contain txvec.
Definition: PDEFoam.cxx:1166
Int_t CellFill(Int_t, PDEFoamCell *)
Internal subprogram used by Create.
Definition: PDEFoam.cxx:390
Long_t PeekMax()
Internal subprogram used by Create.
Definition: PDEFoam.cxx:652
void RootPlot2dim(const TString &filename, TString opt, Bool_t createCanvas=kTRUE, Bool_t colors=kTRUE)
Debugging tool which plots the cells of a 2-dimensional PDEFoam as rectangles in C++ format readable ...
Definition: PDEFoam.cxx:1512
void CheckAll(Int_t)
User utility, miscellaneous and debug.
Definition: PDEFoam.cxx:823
void SetDim(Int_t kDim)
Sets dimension of cubical space.
Definition: PDEFoam.cxx:251
Timing information for training and evaluation of MVA methods.
Definition: Timer.h:58
An array of TObjects.
Definition: TObjArray.h:37
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:550
Random number generator class based on M.
Definition: TRandom3.h:27
Basic string class.
Definition: TString.h:131
const char * Data() const
Definition: TString.h:364
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
void SetPalette(Int_t ncolors=kBird, Int_t *colors=0, Float_t alpha=1.)
See TColor::SetPalette.
Definition: TStyle.cxx:1783
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition: TStyle.cxx:1056
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition: TStyle.cxx:1122
TVectorT< Element > & Zero()
Set vector elements to zero.
Definition: TVectorT.cxx:454
TVectorT< Element > & ResizeTo(Int_t lwb, Int_t upb)
Resize the vector to [lwb:upb] .
Definition: TVectorT.cxx:295
Int_t GetNrows() const
Definition: TVectorT.h:75
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
TH1F * h1
Definition: legend1.C:5
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:158
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:97
Double_t Log(Double_t x)
Definition: TMath.h:750
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
REAL epsilon
Definition: triangle.c:617