00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <iomanip>
00031 #include <cstdlib>
00032
00033 #include "TMath.h"
00034 #include "TF1.h"
00035 #include "TH1F.h"
00036 #include "TVectorD.h"
00037 #include "Riostream.h"
00038
00039 #include "TMVA/Tools.h"
00040 #include "TMVA/PDF.h"
00041 #include "TMVA/TSpline1.h"
00042 #include "TMVA/TSpline2.h"
00043 #include "TMVA/Version.h"
00044
00045
00046 const Int_t TMVA::PDF::fgNbin_PdfHist = 10000;
00047 const Bool_t TMVA::PDF::fgManualIntegration = kTRUE;
00048 const Double_t TMVA::PDF::fgEpsilon = 1.0e-12;
00049 TMVA::PDF* TMVA::PDF::fgThisPDF = 0;
00050
00051 ClassImp(TMVA::PDF)
00052
00053
00054 TMVA::PDF::PDF( const TString& name, Bool_t norm )
00055 : Configurable (""),
00056 fUseHistogram ( kFALSE ),
00057 fPDFName ( name ),
00058 fNsmooth ( 0 ),
00059 fMinNsmooth (-1 ),
00060 fMaxNsmooth (-1 ),
00061 fNSmoothHist ( 0 ),
00062 fInterpolMethod( PDF::kSpline2 ),
00063 fSpline ( 0 ),
00064 fPDFHist ( 0 ),
00065 fHist ( 0 ),
00066 fHistOriginal ( 0 ),
00067 fGraph ( 0 ),
00068 fIGetVal ( 0 ),
00069 fHistAvgEvtPerBin ( 0 ),
00070 fHistDefinedNBins ( 0 ),
00071 fKDEtypeString ( 0 ),
00072 fKDEiterString ( 0 ),
00073 fBorderMethodString( 0 ),
00074 fInterpolateString ( 0 ),
00075 fKDEtype ( KDEKernel::kNone ),
00076 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
00077 fKDEborder ( KDEKernel::kNoTreatment ),
00078 fFineFactor ( 0. ),
00079 fReadingVersion( 0 ),
00080 fCheckHist ( kFALSE ),
00081 fNormalize ( norm ),
00082 fSuffix ( "" ),
00083 fLogger ( 0 )
00084 {
00085
00086 fLogger = new MsgLogger(this);
00087 fgThisPDF = this;
00088 }
00089
00090
00091 TMVA::PDF::PDF( const TString& name,
00092 const TH1 *hist,
00093 PDF::EInterpolateMethod method,
00094 Int_t minnsmooth,
00095 Int_t maxnsmooth,
00096 Bool_t checkHist,
00097 Bool_t norm) :
00098 Configurable (""),
00099 fUseHistogram ( kFALSE ),
00100 fPDFName ( name ),
00101 fMinNsmooth ( minnsmooth ),
00102 fMaxNsmooth ( maxnsmooth ),
00103 fNSmoothHist ( 0 ),
00104 fInterpolMethod( method ),
00105 fSpline ( 0 ),
00106 fPDFHist ( 0 ),
00107 fHist ( 0 ),
00108 fHistOriginal ( 0 ),
00109 fGraph ( 0 ),
00110 fIGetVal ( 0 ),
00111 fHistAvgEvtPerBin ( 0 ),
00112 fHistDefinedNBins ( 0 ),
00113 fKDEtypeString ( 0 ),
00114 fKDEiterString ( 0 ),
00115 fBorderMethodString( 0 ),
00116 fInterpolateString ( 0 ),
00117 fKDEtype ( KDEKernel::kNone ),
00118 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
00119 fKDEborder ( KDEKernel::kNoTreatment ),
00120 fFineFactor ( 0. ),
00121 fReadingVersion( 0 ),
00122 fCheckHist ( checkHist ),
00123 fNormalize ( norm ),
00124 fSuffix ( "" ),
00125 fLogger ( 0 )
00126 {
00127
00128 fLogger = new MsgLogger(this);
00129 BuildPDF( hist );
00130 }
00131
00132
00133 TMVA::PDF::PDF( const TString& name,
00134 const TH1* hist,
00135 KDEKernel::EKernelType ktype,
00136 KDEKernel::EKernelIter kiter,
00137 KDEKernel::EKernelBorder kborder,
00138 Float_t FineFactor,
00139 Bool_t norm) :
00140 Configurable (""),
00141 fUseHistogram ( kFALSE ),
00142 fPDFName ( name ),
00143 fNsmooth ( 0 ),
00144 fMinNsmooth (-1 ),
00145 fMaxNsmooth (-1 ),
00146 fNSmoothHist ( 0 ),
00147 fInterpolMethod( PDF::kKDE ),
00148 fSpline ( 0 ),
00149 fPDFHist ( 0 ),
00150 fHist ( 0 ),
00151 fHistOriginal ( 0 ),
00152 fGraph ( 0 ),
00153 fIGetVal ( 0 ),
00154 fHistAvgEvtPerBin ( 0 ),
00155 fHistDefinedNBins ( 0 ),
00156 fKDEtypeString ( 0 ),
00157 fKDEiterString ( 0 ),
00158 fBorderMethodString( 0 ),
00159 fInterpolateString ( 0 ),
00160 fKDEtype ( ktype ),
00161 fKDEiter ( kiter ),
00162 fKDEborder ( kborder ),
00163 fFineFactor ( FineFactor),
00164 fReadingVersion( 0 ),
00165 fCheckHist ( kFALSE ),
00166 fNormalize ( norm ),
00167 fSuffix ( "" ),
00168 fLogger ( 0 )
00169 {
00170
00171 fLogger = new MsgLogger(this);
00172 BuildPDF( hist );
00173 }
00174
00175
00176 TMVA::PDF::PDF( const TString& name,
00177 const TString& options,
00178 const TString& suffix,
00179 PDF* defaultPDF,
00180 Bool_t norm) :
00181 Configurable (options),
00182 fUseHistogram ( kFALSE ),
00183 fPDFName ( name ),
00184 fNsmooth ( 0 ),
00185 fMinNsmooth ( -1 ),
00186 fMaxNsmooth ( -1 ),
00187 fNSmoothHist ( 0 ),
00188 fInterpolMethod( PDF::kSpline0 ),
00189 fSpline ( 0 ),
00190 fPDFHist ( 0 ),
00191 fHist ( 0 ),
00192 fHistOriginal ( 0 ),
00193 fGraph ( 0 ),
00194 fIGetVal ( 0 ),
00195 fHistAvgEvtPerBin ( 50 ),
00196 fHistDefinedNBins ( 0 ),
00197 fKDEtypeString ( "Gauss" ),
00198 fKDEiterString ( "Nonadaptive" ),
00199 fBorderMethodString( "None" ),
00200 fInterpolateString ( "Spline2" ),
00201 fKDEtype ( KDEKernel::kNone ),
00202 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
00203 fKDEborder ( KDEKernel::kNoTreatment ),
00204 fFineFactor ( 1. ),
00205 fReadingVersion( 0 ),
00206 fCheckHist ( kFALSE ),
00207 fNormalize ( norm ),
00208 fSuffix ( suffix ),
00209 fLogger ( 0 )
00210 {
00211 fLogger = new MsgLogger(this);
00212 if (defaultPDF != 0) {
00213 fNsmooth = defaultPDF->fNsmooth;
00214 fMinNsmooth = defaultPDF->fMinNsmooth;
00215 fMaxNsmooth = defaultPDF->fMaxNsmooth;
00216 fHistAvgEvtPerBin = defaultPDF->fHistAvgEvtPerBin;
00217 fHistAvgEvtPerBin = defaultPDF->fHistAvgEvtPerBin;
00218 fInterpolateString = defaultPDF->fInterpolateString;
00219 fKDEtypeString = defaultPDF->fKDEtypeString;
00220 fKDEiterString = defaultPDF->fKDEiterString;
00221 fFineFactor = defaultPDF->fFineFactor;
00222 fBorderMethodString = defaultPDF->fBorderMethodString;
00223 fCheckHist = defaultPDF->fCheckHist;
00224 fHistDefinedNBins = defaultPDF->fHistDefinedNBins;
00225 }
00226 }
00227
00228
00229 TMVA::PDF::~PDF()
00230 {
00231
00232 if (fSpline != NULL) delete fSpline;
00233 if (fHist != NULL) delete fHist;
00234 if (fPDFHist != NULL) delete fPDFHist;
00235 if (fHistOriginal != NULL) delete fHistOriginal;
00236 if (fIGetVal != NULL) delete fIGetVal;
00237 if (fGraph != NULL) delete fGraph;
00238 delete fLogger;
00239 }
00240
00241
00242 void TMVA::PDF::BuildPDF( const TH1* hist )
00243 {
00244 fgThisPDF = this;
00245
00246
00247 if (hist == NULL) Log() << kFATAL << "Called without valid histogram pointer!" << Endl;
00248
00249
00250 if (hist->GetEntries() <= 0)
00251 Log() << kFATAL << "Number of entries <= 0 in histogram: " << hist->GetTitle() << Endl;
00252
00253 if (fInterpolMethod == PDF::kKDE) {
00254 Log() << "Create "
00255 << ((fKDEiter == KDEKernel::kNonadaptiveKDE) ? "nonadaptive " :
00256 (fKDEiter == KDEKernel::kAdaptiveKDE) ? "adaptive " : "??? ")
00257 << ((fKDEtype == KDEKernel::kGauss) ? "Gauss " : "??? ")
00258 << "type KDE kernel for histogram: \"" << hist->GetName() << "\""
00259 << Endl;
00260 }
00261 else {
00262
00263 if (fMinNsmooth<0)
00264 Log() << kFATAL << "PDF construction called with minnsmooth<0" << Endl;
00265 else if (fMaxNsmooth<=0)
00266 fMaxNsmooth = fMinNsmooth;
00267 else if (fMaxNsmooth<fMinNsmooth)
00268 Log() << kFATAL << "PDF construction called with maxnsmooth<minnsmooth" << Endl;
00269 }
00270
00271 fHistOriginal = (TH1F*)hist->Clone( TString(hist->GetName()) + "_original" );
00272 fHist = (TH1F*)hist->Clone( TString(hist->GetName()) + "_smoothed" );
00273 fHistOriginal->SetTitle( fHistOriginal->GetName() );
00274 fHist ->SetTitle( fHist->GetName() );
00275
00276
00277 fHistOriginal->SetDirectory(0);
00278 fHist ->SetDirectory(0);
00279 fUseHistogram = kFALSE;
00280
00281 if (fInterpolMethod == PDF::kKDE) BuildKDEPDF();
00282 else BuildSplinePDF();
00283 }
00284
00285
00286 Int_t TMVA::PDF::GetHistNBins ( Int_t evtNum )
00287 {
00288 Int_t ResolutionFactor = (fInterpolMethod == PDF::kKDE) ? 5 : 1;
00289 if (evtNum == 0 && fHistDefinedNBins == 0)
00290 Log() << kFATAL << "No number of bins set for PDF" << Endl;
00291 else if (fHistDefinedNBins > 0)
00292 return fHistDefinedNBins * ResolutionFactor;
00293 else if ( evtNum > 0 && fHistAvgEvtPerBin > 0 )
00294 return evtNum / fHistAvgEvtPerBin * ResolutionFactor;
00295 else
00296 Log() << kFATAL << "No number of bins or average event per bin set for PDF" << fHistAvgEvtPerBin << Endl;
00297 return 0;
00298 }
00299
00300
00301 void TMVA::PDF::BuildSplinePDF()
00302 {
00303
00304
00305
00306 if (fInterpolMethod != PDF::kSpline0 && fCheckHist) CheckHist();
00307
00308 fNSmoothHist = 0;
00309 if (fMaxNsmooth > 0 && fMinNsmooth >=0 ) SmoothHistogram();
00310
00311
00312 FillHistToGraph();
00313
00314
00315 switch (fInterpolMethod) {
00316
00317 case kSpline0:
00318
00319
00320 fUseHistogram = kTRUE;
00321 break;
00322
00323 case kSpline1:
00324 fSpline = new TMVA::TSpline1( "spline1", new TGraph(*fGraph) );
00325 break;
00326
00327 case kSpline2:
00328 fSpline = new TMVA::TSpline2( "spline2", new TGraph(*fGraph) );
00329 break;
00330
00331 case kSpline3:
00332 fSpline = new TSpline3( "spline3", new TGraph(*fGraph) );
00333 break;
00334
00335 case kSpline5:
00336 fSpline = new TSpline5( "spline5", new TGraph(*fGraph) );
00337 break;
00338
00339 default:
00340 Log() << kWARNING << "No valid interpolation method given! Use Spline2" << Endl;
00341 fSpline = new TMVA::TSpline2( "spline2", new TGraph(*fGraph) );
00342 Log() << kFATAL << " Well.. .thinking about it, I better quit so you notice you are forced to fix the mistake " << Endl;
00343 std::exit(1);
00344 }
00345
00346 FillSplineToHist();
00347
00348 if (!UseHistogram()) {
00349 fSpline->SetTitle( (TString)fHist->GetTitle() + fSpline->GetTitle() );
00350 fSpline->SetName ( (TString)fHist->GetName() + fSpline->GetName() );
00351 }
00352
00353
00354
00355 Double_t integral = GetIntegral();
00356 if (integral < 0) Log() << kFATAL << "Integral: " << integral << " <= 0" << Endl;
00357
00358
00359 if (fNormalize)
00360 if (integral>0) fPDFHist->Scale( 1.0/integral );
00361
00362 fPDFHist->SetDirectory(0);
00363 }
00364
00365
00366 void TMVA::PDF::BuildKDEPDF()
00367 {
00368
00369
00370 fPDFHist = new TH1F( "", "", fgNbin_PdfHist, GetXmin(), GetXmax() );
00371 fPDFHist->SetTitle( (TString)fHist->GetTitle() + "_hist from_KDE" );
00372 fPDFHist->SetName ( (TString)fHist->GetName() + "_hist_from_KDE" );
00373
00374
00375 Float_t histoLowEdge = fHist->GetBinLowEdge(1);
00376 Float_t histoUpperEdge = fPDFHist->GetBinLowEdge(fPDFHist->GetNbinsX()) + fPDFHist->GetBinWidth(fPDFHist->GetNbinsX());
00377 KDEKernel *kern = new TMVA::KDEKernel( fKDEiter,
00378 fHist, histoLowEdge, histoUpperEdge,
00379 fKDEborder, fFineFactor );
00380 kern->SetKernelType(fKDEtype);
00381
00382 for (Int_t i=1;i<fHist->GetNbinsX();i++) {
00383
00384 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
00385
00386 fPDFHist->AddBinContent(j,fHist->GetBinContent(i)*
00387 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
00388 fPDFHist->GetBinLowEdge(j+1),
00389 fHist->GetBinCenter(i),
00390 i)
00391 );
00392 }
00393 if (fKDEborder == 3) {
00394
00395
00396
00397 if (i < fHist->GetNbinsX()/5 ) {
00398 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
00399
00400 fPDFHist->AddBinContent(j,fHist->GetBinContent(i)*
00401 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
00402 fPDFHist->GetBinLowEdge(j+1),
00403 2*histoLowEdge-fHist->GetBinCenter(i),
00404 i)
00405 );
00406 }
00407 }
00408 if (i > 4*fHist->GetNbinsX()/5) {
00409 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
00410
00411 fPDFHist->AddBinContent( j,fHist->GetBinContent(i)*
00412 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
00413 fPDFHist->GetBinLowEdge(j+1),
00414 2*histoUpperEdge-fHist->GetBinCenter(i), i) );
00415 }
00416 }
00417 }
00418 }
00419
00420 fPDFHist->SetEntries(fHist->GetEntries());
00421
00422 delete kern;
00423
00424
00425 Double_t integral = GetIntegral();
00426 if (integral < 0) Log() << kFATAL << "Integral: " << integral << " <= 0" << Endl;
00427
00428
00429 if (fNormalize)
00430 if (integral>0) fPDFHist->Scale( 1.0/integral );
00431 fPDFHist->SetDirectory(0);
00432 }
00433
00434
00435 void TMVA::PDF::SmoothHistogram()
00436 {
00437 if(fHist->GetNbinsX()==1) return;
00438 if (fMaxNsmooth == fMinNsmooth) {
00439 fHist->Smooth( fMinNsmooth );
00440 return;
00441 }
00442
00443
00444
00445 Float_t Err=0, ErrAvg=0, ErrRMS=0 ; Int_t num=0, smooth;
00446 for (Int_t bin=0; bin<fHist->GetNbinsX(); bin++) {
00447 if (fHist->GetBinContent(bin+1) <= fHist->GetBinError(bin+1)) continue;
00448 Err = fHist->GetBinError(bin+1) / fHist->GetBinContent(bin+1);
00449 ErrAvg += Err; ErrRMS += Err*Err; num++;
00450 }
00451 ErrAvg /= num;
00452 ErrRMS = TMath::Sqrt(ErrRMS/num-ErrAvg*ErrAvg) ;
00453
00454
00455 Float_t MaxErr=ErrAvg+ErrRMS, MinErr=ErrAvg-ErrRMS;
00456 fNSmoothHist = new TH1I("","",fHist->GetNbinsX(),0,fHist->GetNbinsX());
00457 fNSmoothHist->SetTitle( (TString)fHist->GetTitle() + "_Nsmooth" );
00458 fNSmoothHist->SetName ( (TString)fHist->GetName() + "_Nsmooth" );
00459 for (Int_t bin=0; bin<fHist->GetNbinsX(); bin++) {
00460 if (fHist->GetBinContent(bin+1) <= fHist->GetBinError(bin+1))
00461 smooth=fMaxNsmooth;
00462 else {
00463 Err = fHist->GetBinError(bin+1) / fHist->GetBinContent(bin+1);
00464 smooth=(Int_t)((Err-MinErr) /(MaxErr-MinErr) * (fMaxNsmooth-fMinNsmooth)) + fMinNsmooth;
00465 }
00466 smooth = TMath::Max(fMinNsmooth,TMath::Min(fMaxNsmooth,smooth));
00467 fNSmoothHist->SetBinContent(bin+1,smooth);
00468 }
00469
00470
00471
00472 for (Int_t n=fMaxNsmooth; n>=0; n--) {
00473
00474 if (n <= fMinNsmooth) { fHist->Smooth(); continue; }
00475 Int_t MinBin=-1,MaxBin =-1;
00476 for (Int_t bin=0; bin < fHist->GetNbinsX(); bin++) {
00477 if (fNSmoothHist->GetBinContent(bin+1) >= n) {
00478 if (MinBin==-1) MinBin = bin;
00479 else MaxBin=bin;
00480 }
00481 else if (MaxBin >= 0) {
00482 #if ROOT_VERSION_CODE > ROOT_VERSION(5,19,2)
00483 fHist->Smooth(1,"R");
00484 #else
00485 fHist->Smooth(1,MinBin+1,MaxBin+1);
00486 #endif
00487 MinBin=MaxBin=-1;
00488 }
00489 else
00490 MinBin = -1;
00491 }
00492 }
00493 }
00494
00495
00496 void TMVA::PDF::FillHistToGraph()
00497 {
00498
00499 fGraph=new TGraph(fHist);
00500 }
00501
00502
00503 void TMVA::PDF::FillSplineToHist()
00504 {
00505
00506
00507
00508 if (UseHistogram()) {
00509
00510 fPDFHist = (TH1*)fHist->Clone();
00511 fPDFHist->SetTitle( (TString)fHist->GetTitle() + "_hist from_spline0" );
00512 fPDFHist->SetName ( (TString)fHist->GetName() + "_hist_from_spline0" );
00513 }
00514 else {
00515
00516 fPDFHist = new TH1F( "", "", fgNbin_PdfHist, GetXmin(), GetXmax() );
00517 fPDFHist->SetTitle( (TString)fHist->GetTitle() + "_hist from_" + fSpline->GetTitle() );
00518 fPDFHist->SetName ( (TString)fHist->GetName() + "_hist_from_" + fSpline->GetTitle() );
00519
00520 for (Int_t bin=1; bin <= fgNbin_PdfHist; bin++) {
00521 Double_t x = fPDFHist->GetBinCenter( bin );
00522 Double_t y = fSpline->Eval( x );
00523
00524
00525
00526 if (y <= fgEpsilon) y = fHist->GetBinContent( fHist->FindBin( x ) );
00527 fPDFHist->SetBinContent( bin, TMath::Max(y, fgEpsilon) );
00528 }
00529 }
00530 fPDFHist->SetDirectory(0);
00531 }
00532
00533
00534 void TMVA::PDF::CheckHist() const
00535 {
00536
00537 if (fHist == NULL) {
00538 Log() << kFATAL << "<CheckHist> Called without valid histogram pointer!" << Endl;
00539 }
00540
00541 Int_t nbins = fHist->GetNbinsX();
00542
00543 Int_t emptyBins=0;
00544
00545 for (Int_t bin=1; bin<=nbins; bin++)
00546 if (fHist->GetBinContent(bin) == 0) emptyBins++;
00547
00548 if (((Float_t)emptyBins/(Float_t)nbins) > 0.5) {
00549 Log() << kWARNING << "More than 50% (" << (((Float_t)emptyBins/(Float_t)nbins)*100)
00550 <<"%) of the bins in hist '"
00551 << fHist->GetName() << "' are empty!" << Endl;
00552 Log() << kWARNING << "X_min=" << GetXmin()
00553 << " mean=" << fHist->GetMean() << " X_max= " << GetXmax() << Endl;
00554 }
00555 }
00556
00557
00558 void TMVA::PDF::ValidatePDF( TH1* originalHist ) const
00559 {
00560
00561
00562
00563 if (!originalHist) originalHist = fHistOriginal;
00564
00565 Int_t nbins = originalHist->GetNbinsX();
00566
00567
00568 if (originalHist->GetSumw2()->GetSize() == 0) originalHist->Sumw2();
00569
00570
00571
00572 Double_t chi2 = 0;
00573 Int_t ndof = 0;
00574 Int_t nc1 = 0;
00575 Int_t nc2 = 0;
00576 Int_t nc3 = 0;
00577 Int_t nc6 = 0;
00578 for (Int_t bin=1; bin<=nbins; bin++) {
00579 Double_t x = originalHist->GetBinCenter( bin );
00580 Double_t y = originalHist->GetBinContent( bin );
00581 Double_t ey = originalHist->GetBinError( bin );
00582
00583 Int_t binPdfHist = fPDFHist->FindBin( x );
00584 if (binPdfHist<0) continue;
00585
00586 Double_t yref = GetVal( x );
00587 Double_t rref = ( originalHist->GetSumOfWeights()/fPDFHist->GetSumOfWeights() *
00588 originalHist->GetBinWidth( bin )/fPDFHist->GetBinWidth( binPdfHist ) );
00589
00590 if (y > 0) {
00591 ndof++;
00592 Double_t d = TMath::Abs( (y - yref*rref)/ey );
00593
00594
00595 chi2 += d*d;
00596 if (d > 1) { nc1++; if (d > 2) { nc2++; if (d > 3) { nc3++; if (d > 6) nc6++; } } }
00597 }
00598 }
00599
00600 Log() << "Validation result for PDF \"" << originalHist->GetTitle() << "\"" << ": " << Endl;
00601 Log() << Form( " chi2/ndof(!=0) = %.1f/%i = %.2f (Prob = %.2f)",
00602 chi2, ndof, chi2/ndof, TMath::Prob( chi2, ndof ) ) << Endl;
00603 if ((1.0 - TMath::Prob( chi2, ndof )) > 0.9999994) {
00604 Log() << kWARNING << "Comparison of the original histogram \"" << originalHist->GetTitle() << "\"" << Endl;
00605 Log() << kWARNING << "with the corresponding PDF gave a chi2/ndof of " << chi2/ndof << "," << Endl;
00606 Log() << kWARNING << "which corresponds to a deviation of more than 5 sigma! Please check!" << Endl;
00607 }
00608 Log() << Form( " #bins-found(#expected-bins) deviating > [1,2,3,6] sigmas: " \
00609 "[%i(%i),%i(%i),%i(%i),%i(%i)]",
00610 nc1, Int_t(TMath::Prob(1.0,1)*ndof), nc2, Int_t(TMath::Prob(4.0,1)*ndof),
00611 nc3, Int_t(TMath::Prob(9.0,1)*ndof), nc6, Int_t(TMath::Prob(36.0,1)*ndof) ) << Endl;
00612 }
00613
00614
00615 Double_t TMVA::PDF::GetIntegral() const
00616 {
00617
00618
00619 Double_t integral = fPDFHist->GetSumOfWeights();
00620 integral *= GetPdfHistBinWidth();
00621
00622 return integral;
00623 }
00624
00625
00626 Double_t TMVA::PDF::IGetVal( Double_t* x, Double_t* )
00627 {
00628
00629 return ThisPDF()->GetVal( x[0] );
00630 }
00631
00632
00633 Double_t TMVA::PDF::GetIntegral( Double_t xmin, Double_t xmax )
00634 {
00635
00636 Double_t integral = 0;
00637
00638 if (fgManualIntegration) {
00639
00640
00641 Int_t imin = fPDFHist->FindBin(xmin);
00642 Int_t imax = fPDFHist->FindBin(xmax);
00643 if (imin < 1) imin = 1;
00644 if (imax > fPDFHist->GetNbinsX()) imax = fPDFHist->GetNbinsX();
00645
00646 for (Int_t bini = imin; bini <= imax; bini++) {
00647 Float_t dx = fPDFHist->GetBinWidth(bini);
00648
00649 if (bini == imin) dx = fPDFHist->GetBinLowEdge(bini+1) - xmin;
00650 else if (bini == imax) dx = xmax - fPDFHist->GetBinLowEdge(bini);
00651 if (dx < 0 && dx > -1.0e-8) dx = 0;
00652 if (dx<0) {
00653 Log() << kWARNING
00654 << "dx = " << dx << std::endl
00655 << "bini = " << bini << std::endl
00656 << "xmin = " << xmin << std::endl
00657 << "xmax = " << xmax << std::endl
00658 << "imin = " << imin << std::endl
00659 << "imax = " << imax << std::endl
00660 << "low edge of imin" << fPDFHist->GetBinLowEdge(imin) << std::endl
00661 << "low edge of imin+1" << fPDFHist->GetBinLowEdge(imin+1) << Endl;
00662 Log() << kFATAL << "<GetIntegral> dx = " << dx << " < 0" << Endl;
00663 }
00664 integral += fPDFHist->GetBinContent(bini)*dx;
00665 }
00666
00667 }
00668 else {
00669
00670
00671 if (fIGetVal == 0) fIGetVal = new TF1( "IGetVal", PDF::IGetVal, GetXmin(), GetXmax(), 0 );
00672 integral = fIGetVal->Integral( xmin, xmax );
00673 }
00674
00675 return integral;
00676 }
00677
00678
00679 Double_t TMVA::PDF::GetVal( Double_t x ) const
00680 {
00681
00682
00683
00684 Int_t bin = fPDFHist->FindBin(x);
00685 bin = TMath::Max(bin,1);
00686 bin = TMath::Min(bin,fPDFHist->GetNbinsX());
00687
00688 Double_t retval = 0;
00689
00690 if (UseHistogram()) {
00691
00692 retval = fPDFHist->GetBinContent( bin );
00693 }
00694 else {
00695
00696 Int_t nextbin = bin;
00697 if ((x > fPDFHist->GetBinCenter(bin) && bin != fPDFHist->GetNbinsX()) || bin == 1)
00698 nextbin++;
00699 else
00700 nextbin--;
00701
00702
00703 Double_t dx = fPDFHist->GetBinCenter( bin ) - fPDFHist->GetBinCenter( nextbin );
00704 Double_t dy = fPDFHist->GetBinContent( bin ) - fPDFHist->GetBinContent( nextbin );
00705 retval = fPDFHist->GetBinContent( bin ) + (x - fPDFHist->GetBinCenter( bin ))*dy/dx;
00706 }
00707
00708 return TMath::Max( retval, fgEpsilon );
00709 }
00710
00711
00712 void TMVA::PDF::DeclareOptions()
00713 {
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 DeclareOptionRef( fNsmooth, Form("NSmooth%s",fSuffix.Data()),
00729 "Number of smoothing iterations for the input histograms" );
00730 DeclareOptionRef( fMinNsmooth, Form("MinNSmooth%s",fSuffix.Data()),
00731 "Min number of smoothing iterations, for bins with most data" );
00732
00733 DeclareOptionRef( fMaxNsmooth, Form("MaxNSmooth%s",fSuffix.Data()),
00734 "Max number of smoothing iterations, for bins with least data" );
00735
00736 DeclareOptionRef( fHistAvgEvtPerBin, Form("NAvEvtPerBin%s",fSuffix.Data()),
00737 "Average number of events per PDF bin" );
00738
00739 DeclareOptionRef( fHistDefinedNBins, Form("Nbins%s",fSuffix.Data()),
00740 "Defined number of bins for the histogram from which the PDF is created" );
00741
00742 DeclareOptionRef( fCheckHist, Form("CheckHist%s",fSuffix.Data()),
00743 "Whether or not to check the source histogram of the PDF" );
00744
00745 DeclareOptionRef( fInterpolateString, Form("PDFInterpol%s",fSuffix.Data()),
00746 "Interpolation method for reference histograms (e.g. Spline2 or KDE)" );
00747 AddPreDefVal(TString("Spline0"));
00748 AddPreDefVal(TString("Spline1"));
00749 AddPreDefVal(TString("Spline2"));
00750 AddPreDefVal(TString("Spline3"));
00751 AddPreDefVal(TString("Spline5"));
00752 AddPreDefVal(TString("KDE"));
00753
00754 DeclareOptionRef( fKDEtypeString, Form("KDEtype%s",fSuffix.Data()), "KDE kernel type (1=Gauss)" );
00755 AddPreDefVal(TString("Gauss"));
00756
00757 DeclareOptionRef( fKDEiterString, Form("KDEiter%s",fSuffix.Data()), "Number of iterations (1=non-adaptive, 2=adaptive)" );
00758 AddPreDefVal(TString("Nonadaptive"));
00759 AddPreDefVal(TString("Adaptive"));
00760
00761 DeclareOptionRef( fFineFactor , Form("KDEFineFactor%s",fSuffix.Data()),
00762 "Fine tuning factor for Adaptive KDE: Factor to multyply the width of the kernel");
00763
00764 DeclareOptionRef( fBorderMethodString, Form("KDEborder%s",fSuffix.Data()),
00765 "Border effects treatment (1=no treatment , 2=kernel renormalization, 3=sample mirroring)" );
00766 AddPreDefVal(TString("None"));
00767 AddPreDefVal(TString("Renorm"));
00768 AddPreDefVal(TString("Mirror"));
00769
00770 SetConfigName( GetName() );
00771 SetConfigDescription( "Configuration options for the PDF class" );
00772 }
00773
00774
00775 void TMVA::PDF::ProcessOptions()
00776 {
00777
00778 if (fNsmooth < 0) fNsmooth = 0;
00779
00780 if (fMaxNsmooth < 0 || fMinNsmooth < 0) {
00781 fMinNsmooth = fMaxNsmooth = fNsmooth;
00782 }
00783
00784 if (fMaxNsmooth < fMinNsmooth && fMinNsmooth >= 0) {
00785 Log() << kFATAL << "ERROR: MaxNsmooth = "
00786 << fMaxNsmooth << " < MinNsmooth = " << fMinNsmooth << Endl;
00787 }
00788
00789 if (fMaxNsmooth < 0 || fMinNsmooth < 0) {
00790 Log() << kFATAL << "ERROR: MaxNsmooth = "
00791 << fMaxNsmooth << " or MinNsmooth = " << fMinNsmooth << " smaller than zero" << Endl;
00792 }
00793
00794
00795 if (fInterpolateString == "Spline0") fInterpolMethod = TMVA::PDF::kSpline0;
00796 else if (fInterpolateString == "Spline1") fInterpolMethod = TMVA::PDF::kSpline1;
00797 else if (fInterpolateString == "Spline2") fInterpolMethod = TMVA::PDF::kSpline2;
00798 else if (fInterpolateString == "Spline3") fInterpolMethod = TMVA::PDF::kSpline3;
00799 else if (fInterpolateString == "Spline5") fInterpolMethod = TMVA::PDF::kSpline5;
00800 else if (fInterpolateString == "KDE" ) fInterpolMethod = TMVA::PDF::kKDE;
00801 else if (fInterpolateString != "" ) {
00802 Log() << kFATAL << "unknown setting for option 'InterpolateMethod': " << fKDEtypeString << ((fSuffix=="")?"":Form(" for pdf with suffix %s",fSuffix.Data())) << Endl;
00803 }
00804
00805
00806 if (fKDEtypeString == "Gauss" ) fKDEtype = KDEKernel::kGauss;
00807 else if (fKDEtypeString != "" )
00808 Log() << kFATAL << "unknown setting for option 'KDEtype': " << fKDEtypeString << ((fSuffix=="")?"":Form(" for pdf with suffix %s",fSuffix.Data())) << Endl;
00809 if (fKDEiterString == "Nonadaptive") fKDEiter = KDEKernel::kNonadaptiveKDE;
00810 else if (fKDEiterString == "Adaptive" ) fKDEiter = KDEKernel::kAdaptiveKDE;
00811 else if (fKDEiterString != "" )
00812 Log() << kFATAL << "unknown setting for option 'KDEiter': " << fKDEtypeString << ((fSuffix=="")?"":Form(" for pdf with suffix %s",fSuffix.Data())) << Endl;
00813
00814 if ( fBorderMethodString == "None" ) fKDEborder= KDEKernel::kNoTreatment;
00815 else if ( fBorderMethodString == "Renorm" ) fKDEborder= KDEKernel::kKernelRenorm;
00816 else if ( fBorderMethodString == "Mirror" ) fKDEborder= KDEKernel::kSampleMirror;
00817 else if ( fKDEiterString != "" ) {
00818 Log() << kFATAL << "unknown setting for option 'KDEBorder': " << fKDEtypeString << ((fSuffix=="")?"":Form(" for pdf with suffix %s",fSuffix.Data())) << Endl;
00819 }
00820 }
00821
00822
00823 void TMVA::PDF::AddXMLTo( void* parent )
00824 {
00825
00826 void* pdfxml = gTools().AddChild(parent, "PDF");
00827 gTools().AddAttr(pdfxml, "Name", fPDFName );
00828 gTools().AddAttr(pdfxml, "MinNSmooth", fMinNsmooth );
00829 gTools().AddAttr(pdfxml, "MaxNSmooth", fMaxNsmooth );
00830 gTools().AddAttr(pdfxml, "InterpolMethod", fInterpolMethod );
00831 gTools().AddAttr(pdfxml, "KDE_type", fKDEtype );
00832 gTools().AddAttr(pdfxml, "KDE_iter", fKDEiter );
00833 gTools().AddAttr(pdfxml, "KDE_border", fKDEborder );
00834 gTools().AddAttr(pdfxml, "KDE_finefactor", fFineFactor );
00835 void* pdfhist = gTools().AddChild(pdfxml,"Histogram" );
00836 TH1* histToWrite = GetOriginalHist();
00837 Bool_t hasEquidistantBinning = gTools().HistoHasEquidistantBins(*histToWrite);
00838 gTools().AddAttr(pdfhist, "Name", histToWrite->GetName() );
00839 gTools().AddAttr(pdfhist, "NBins", histToWrite->GetNbinsX() );
00840 gTools().AddAttr(pdfhist, "XMin", histToWrite->GetXaxis()->GetXmin() );
00841 gTools().AddAttr(pdfhist, "XMax", histToWrite->GetXaxis()->GetXmax() );
00842 gTools().AddAttr(pdfhist, "HasEquidistantBins", hasEquidistantBinning );
00843
00844 TString bincontent("");
00845 for (Int_t i=0; i<histToWrite->GetNbinsX(); i++) {
00846 bincontent += gTools().StringFromDouble(histToWrite->GetBinContent(i+1));
00847 bincontent += " ";
00848 }
00849 gTools().AddRawLine(pdfhist, bincontent );
00850
00851 if (!hasEquidistantBinning) {
00852 void* pdfhistbins = gTools().AddChild(pdfxml,"HistogramBinning" );
00853 gTools().AddAttr(pdfhistbins, "NBins", histToWrite->GetNbinsX() );
00854 TString binns("");
00855 for (Int_t i=1; i<=histToWrite->GetNbinsX()+1; i++) {
00856 binns += gTools().StringFromDouble(histToWrite->GetXaxis()->GetBinLowEdge(i));
00857 binns += " ";
00858 }
00859 gTools().AddRawLine(pdfhistbins, binns );
00860 }
00861 }
00862
00863
00864 void TMVA::PDF::ReadXML( void* pdfnode )
00865 {
00866
00867 UInt_t enumint;
00868
00869 gTools().ReadAttr(pdfnode, "MinNSmooth", fMinNsmooth );
00870 gTools().ReadAttr(pdfnode, "MaxNSmooth", fMaxNsmooth );
00871 gTools().ReadAttr(pdfnode, "InterpolMethod", enumint ); fInterpolMethod = EInterpolateMethod(enumint);
00872 gTools().ReadAttr(pdfnode, "KDE_type", enumint ); fKDEtype = KDEKernel::EKernelType(enumint);
00873 gTools().ReadAttr(pdfnode, "KDE_iter", enumint ); fKDEiter = KDEKernel::EKernelIter(enumint);
00874 gTools().ReadAttr(pdfnode, "KDE_border", enumint ); fKDEborder = KDEKernel::EKernelBorder(enumint);
00875 gTools().ReadAttr(pdfnode, "KDE_finefactor", fFineFactor );
00876
00877 TString hname;
00878 UInt_t nbins;
00879 Double_t xmin, xmax;
00880 Bool_t hasEquidistantBinning;
00881
00882 void* histch = gTools().GetChild(pdfnode);
00883 gTools().ReadAttr( histch, "Name", hname );
00884 gTools().ReadAttr( histch, "NBins", nbins );
00885 gTools().ReadAttr( histch, "XMin", xmin );
00886 gTools().ReadAttr( histch, "XMax", xmax );
00887 gTools().ReadAttr( histch, "HasEquidistantBins", hasEquidistantBinning );
00888
00889
00890 TH1* newhist = 0;
00891 if (hasEquidistantBinning) {
00892 newhist = new TH1F( hname, hname, nbins, xmin, xmax );
00893 newhist->SetDirectory(0);
00894 const char* content = gTools().GetContent(histch);
00895 std::stringstream s(content);
00896 Double_t val;
00897 for (UInt_t i=0; i<nbins; i++) {
00898 s >> val;
00899 newhist->SetBinContent(i+1,val);
00900 }
00901 }
00902 else {
00903 const char* content = gTools().GetContent(histch);
00904 std::stringstream s(content);
00905 Double_t val;
00906 void* binch = gTools().GetNextChild(histch);
00907 UInt_t nbinning;
00908 gTools().ReadAttr( binch, "NBins", nbinning );
00909 TVectorD binns(nbinning+1);
00910 if (nbinning != nbins) {
00911 Log() << kFATAL << "Number of bins in content and binning array differs"<<Endl;
00912 }
00913 const char* binString = gTools().GetContent(binch);
00914 std::stringstream sb(binString);
00915 for (UInt_t i=0; i<=nbins; i++) sb >> binns[i];
00916 newhist = new TH1F( hname, hname, nbins, binns.GetMatrixArray() );
00917 newhist->SetDirectory(0);
00918 for (UInt_t i=0; i<nbins; i++) {
00919 s >> val;
00920 newhist->SetBinContent(i+1,val);
00921 }
00922 }
00923
00924 TString hnameSmooth = hname;
00925 hnameSmooth.ReplaceAll( "_original", "_smoothed" );
00926
00927 if (fHistOriginal != 0) delete fHistOriginal;
00928 fHistOriginal = newhist;
00929 fHist = (TH1F*)fHistOriginal->Clone( hnameSmooth );
00930 fHist->SetTitle( hnameSmooth );
00931 fHist->SetDirectory(0);
00932
00933 if (fInterpolMethod == PDF::kKDE) BuildKDEPDF();
00934 else BuildSplinePDF();
00935 }
00936
00937
00938 ostream& TMVA::operator<< ( ostream& os, const PDF& pdf )
00939 {
00940
00941 Int_t dp = os.precision();
00942 os << "MinNSmooth " << pdf.fMinNsmooth << std::endl;
00943 os << "MaxNSmooth " << pdf.fMaxNsmooth << std::endl;
00944 os << "InterpolMethod " << pdf.fInterpolMethod << std::endl;
00945 os << "KDE_type " << pdf.fKDEtype << std::endl;
00946 os << "KDE_iter " << pdf.fKDEiter << std::endl;
00947 os << "KDE_border " << pdf.fKDEborder << std::endl;
00948 os << "KDE_finefactor " << pdf.fFineFactor << std::endl;
00949
00950 TH1* histToWrite = pdf.GetOriginalHist();
00951
00952 const Int_t nBins = histToWrite->GetNbinsX();
00953
00954
00955 os << "Histogram "
00956 << histToWrite->GetName()
00957 << " " << nBins
00958 << " " << std::setprecision(12) << histToWrite->GetXaxis()->GetXmin()
00959 << " " << std::setprecision(12) << histToWrite->GetXaxis()->GetXmax()
00960 << std::endl;
00961
00962
00963 os << "Weights " << std::endl;
00964 os << std::setprecision(8);
00965 for (Int_t i=0; i<nBins; i++) {
00966 os << std::setw(15) << std::left << histToWrite->GetBinContent(i+1) << std::right << " ";
00967 if ((i+1)%5==0) os << std::endl;
00968 }
00969
00970 os << std::setprecision(dp);
00971 return os;
00972 }
00973
00974
00975 istream& TMVA::operator>> ( istream& istr, PDF& pdf )
00976 {
00977
00978 TString devnullS;
00979 Int_t valI;
00980 Int_t nbins;
00981 Float_t xmin, xmax;
00982 TString hname="_original";
00983 Bool_t doneReading = kFALSE;
00984 while (!doneReading) {
00985 istr >> devnullS;
00986 if (devnullS=="NSmooth")
00987 {istr >> pdf.fMinNsmooth; pdf.fMaxNsmooth=pdf.fMinNsmooth;}
00988 else if (devnullS=="MinNSmooth") istr >> pdf.fMinNsmooth;
00989 else if (devnullS=="MaxNSmooth") istr >> pdf.fMaxNsmooth;
00990
00991 else if (devnullS == "InterpolMethod") { istr >> valI; pdf.fInterpolMethod = PDF::EInterpolateMethod(valI);}
00992 else if (devnullS == "KDE_type") { istr >> valI; pdf.fKDEtype = KDEKernel::EKernelType(valI); }
00993 else if (devnullS == "KDE_iter") { istr >> valI; pdf.fKDEiter = KDEKernel::EKernelIter(valI);}
00994 else if (devnullS == "KDE_border") { istr >> valI; pdf.fKDEborder = KDEKernel::EKernelBorder(valI);}
00995 else if (devnullS == "KDE_finefactor") {
00996 istr >> pdf.fFineFactor;
00997 if (pdf.GetReadingVersion() != 0 && pdf.GetReadingVersion() < TMVA_VERSION(3,7,3)) {
00998
00999 istr >> nbins >> xmin >> xmax;
01000 doneReading = kTRUE;
01001 }
01002 }
01003 else if (devnullS == "Histogram") { istr >> hname >> nbins >> xmin >> xmax; }
01004 else if (devnullS == "Weights") { doneReading = kTRUE; }
01005 }
01006
01007 TString hnameSmooth = hname;
01008 hnameSmooth.ReplaceAll( "_original", "_smoothed" );
01009
01010
01011 TH1* newhist = new TH1F( hname,hname, nbins, xmin, xmax );
01012 newhist->SetDirectory(0);
01013 Float_t val;
01014 for (Int_t i=0; i<nbins; i++) {
01015 istr >> val;
01016 newhist->SetBinContent(i+1,val);
01017 }
01018
01019 if (pdf.fHistOriginal != 0) delete pdf.fHistOriginal;
01020 pdf.fHistOriginal = newhist;
01021 pdf.fHist = (TH1F*)pdf.fHistOriginal->Clone( hnameSmooth );
01022 pdf.fHist->SetTitle( hnameSmooth );
01023 pdf.fHist->SetDirectory(0);
01024
01025 if (pdf.fMinNsmooth>=0) pdf.BuildSplinePDF();
01026 else {
01027 pdf.fInterpolMethod = PDF::kKDE;
01028 pdf.BuildKDEPDF();
01029 }
01030
01031 return istr;
01032 }
01033
01034 TMVA::PDF* TMVA::PDF::ThisPDF( void )
01035 {
01036
01037 return fgThisPDF;
01038 }