59 const Int_t TMVA::PDF::fgNbin_PdfHist = 10000;
60 const Bool_t TMVA::PDF::fgManualIntegration = kTRUE;
61 const Double_t TMVA::PDF::fgEpsilon = 1.0e-12;
68 TMVA::PDF::PDF(
const TString& name, Bool_t norm )
70 fUseHistogram ( kFALSE ),
76 fInterpolMethod( PDF::kSpline2 ),
83 fHistAvgEvtPerBin ( 0 ),
84 fHistDefinedNBins ( 0 ),
87 fBorderMethodString( 0 ),
88 fInterpolateString ( 0 ),
89 fKDEtype ( KDEKernel::kNone ),
90 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
91 fKDEborder ( KDEKernel::kNoTreatment ),
94 fCheckHist ( kFALSE ),
99 fLogger =
new MsgLogger(
this);
100 GetThisPdfThreadLocal() =
this;
106 TMVA::PDF::PDF(
const TString& name,
108 PDF::EInterpolateMethod method,
114 fUseHistogram ( kFALSE ),
116 fMinNsmooth ( minnsmooth ),
117 fMaxNsmooth ( maxnsmooth ),
119 fInterpolMethod( method ),
126 fHistAvgEvtPerBin ( 0 ),
127 fHistDefinedNBins ( 0 ),
128 fKDEtypeString ( 0 ),
129 fKDEiterString ( 0 ),
130 fBorderMethodString( 0 ),
131 fInterpolateString ( 0 ),
132 fKDEtype ( KDEKernel::kNone ),
133 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
134 fKDEborder ( KDEKernel::kNoTreatment ),
136 fReadingVersion( 0 ),
137 fCheckHist ( checkHist ),
142 fLogger =
new MsgLogger(
this);
149 TMVA::PDF::PDF(
const TString& name,
151 KDEKernel::EKernelType ktype,
152 KDEKernel::EKernelIter kiter,
153 KDEKernel::EKernelBorder kborder,
157 fUseHistogram ( kFALSE ),
163 fInterpolMethod( PDF::kKDE ),
170 fHistAvgEvtPerBin ( 0 ),
171 fHistDefinedNBins ( 0 ),
172 fKDEtypeString ( 0 ),
173 fKDEiterString ( 0 ),
174 fBorderMethodString( 0 ),
175 fInterpolateString ( 0 ),
178 fKDEborder ( kborder ),
179 fFineFactor ( FineFactor),
180 fReadingVersion( 0 ),
181 fCheckHist ( kFALSE ),
186 fLogger =
new MsgLogger(
this);
192 TMVA::PDF::PDF(
const TString& name,
193 const TString& options,
194 const TString& suffix,
197 Configurable (options),
198 fUseHistogram ( kFALSE ),
204 fInterpolMethod( PDF::kSpline0 ),
211 fHistAvgEvtPerBin ( 50 ),
212 fHistDefinedNBins ( 0 ),
213 fKDEtypeString (
"Gauss" ),
214 fKDEiterString (
"Nonadaptive" ),
215 fBorderMethodString(
"None" ),
216 fInterpolateString (
"Spline2" ),
217 fKDEtype ( KDEKernel::kNone ),
218 fKDEiter ( KDEKernel::kNonadaptiveKDE ),
219 fKDEborder ( KDEKernel::kNoTreatment ),
221 fReadingVersion( 0 ),
222 fCheckHist ( kFALSE ),
227 fLogger =
new MsgLogger(
this);
228 if (defaultPDF != 0) {
229 fNsmooth = defaultPDF->fNsmooth;
230 fMinNsmooth = defaultPDF->fMinNsmooth;
231 fMaxNsmooth = defaultPDF->fMaxNsmooth;
232 fHistAvgEvtPerBin = defaultPDF->fHistAvgEvtPerBin;
233 fHistAvgEvtPerBin = defaultPDF->fHistAvgEvtPerBin;
234 fInterpolateString = defaultPDF->fInterpolateString;
235 fKDEtypeString = defaultPDF->fKDEtypeString;
236 fKDEiterString = defaultPDF->fKDEiterString;
237 fFineFactor = defaultPDF->fFineFactor;
238 fBorderMethodString = defaultPDF->fBorderMethodString;
239 fCheckHist = defaultPDF->fCheckHist;
240 fHistDefinedNBins = defaultPDF->fHistDefinedNBins;
248 if (fSpline != NULL)
delete fSpline;
249 if (fHist != NULL)
delete fHist;
250 if (fPDFHist != NULL)
delete fPDFHist;
251 if (fHistOriginal != NULL)
delete fHistOriginal;
252 if (fIGetVal != NULL)
delete fIGetVal;
253 if (fGraph != NULL)
delete fGraph;
259 void TMVA::PDF::BuildPDF(
const TH1* hist )
261 GetThisPdfThreadLocal() =
this;
263 if (hist == NULL) Log() << kFATAL <<
"Called without valid histogram pointer!" << Endl;
266 if (hist->GetEntries() <= 0)
267 Log() << kFATAL <<
"Number of entries <= 0 (" << hist->GetEntries() <<
" in histogram: " << hist->GetTitle() <<
")" << Endl;
269 if (fInterpolMethod == PDF::kKDE) {
270 Log()<< kDEBUG <<
"Create "
271 << ((fKDEiter == KDEKernel::kNonadaptiveKDE) ?
"nonadaptive " :
272 (fKDEiter == KDEKernel::kAdaptiveKDE) ?
"adaptive " :
"??? ")
273 << ((fKDEtype == KDEKernel::kGauss) ?
"Gauss " :
"??? ")
274 <<
"type KDE kernel for histogram: \"" << hist->GetName() <<
"\""
280 Log() << kFATAL <<
"PDF construction called with minnsmooth<0" << Endl;
281 else if (fMaxNsmooth<=0)
282 fMaxNsmooth = fMinNsmooth;
283 else if (fMaxNsmooth<fMinNsmooth)
284 Log() << kFATAL <<
"PDF construction called with maxnsmooth<minnsmooth" << Endl;
287 fHistOriginal = (TH1F*)hist->Clone( TString(hist->GetName()) +
"_original" );
288 fHist = (TH1F*)hist->Clone( TString(hist->GetName()) +
"_smoothed" );
289 fHistOriginal->SetTitle( fHistOriginal->GetName() );
290 fHist ->SetTitle( fHist->GetName() );
293 fHistOriginal->SetDirectory(0);
294 fHist ->SetDirectory(0);
295 fUseHistogram = kFALSE;
297 if (fInterpolMethod == PDF::kKDE) BuildKDEPDF();
298 else BuildSplinePDF();
303 Int_t TMVA::PDF::GetHistNBins ( Int_t evtNum )
305 Int_t ResolutionFactor = (fInterpolMethod == PDF::kKDE) ? 5 : 1;
306 if (evtNum == 0 && fHistDefinedNBins == 0)
307 Log() << kFATAL <<
"No number of bins set for PDF" << Endl;
308 else if (fHistDefinedNBins > 0)
309 return fHistDefinedNBins * ResolutionFactor;
310 else if ( evtNum > 0 && fHistAvgEvtPerBin > 0 )
311 return evtNum / fHistAvgEvtPerBin * ResolutionFactor;
313 Log() << kFATAL <<
"No number of bins or average event per bin set for PDF" << fHistAvgEvtPerBin << Endl;
320 void TMVA::PDF::BuildSplinePDF()
323 if (fInterpolMethod != PDF::kSpline0 && fCheckHist) CheckHist();
326 if (fMaxNsmooth > 0 && fMinNsmooth >=0 ) SmoothHistogram();
332 switch (fInterpolMethod) {
337 fUseHistogram = kTRUE;
341 fSpline =
new TMVA::TSpline1(
"spline1",
new TGraph(*fGraph) );
345 fSpline =
new TMVA::TSpline2(
"spline2",
new TGraph(*fGraph) );
349 fSpline =
new TSpline3(
"spline3",
new TGraph(*fGraph) );
353 fSpline =
new TSpline5(
"spline5",
new TGraph(*fGraph) );
357 Log() << kWARNING <<
"No valid interpolation method given! Use Spline2" << Endl;
358 fSpline =
new TMVA::TSpline2(
"spline2",
new TGraph(*fGraph) );
359 Log() << kFATAL <<
" Well.. .thinking about it, I better quit so you notice you are forced to fix the mistake " << Endl;
365 if (!UseHistogram()) {
366 fSpline->SetTitle( (TString)fHist->GetTitle() + fSpline->GetTitle() );
367 fSpline->SetName ( (TString)fHist->GetName() + fSpline->GetName() );
372 Double_t integral = GetIntegral();
373 if (integral < 0) Log() << kFATAL <<
"Integral: " << integral <<
" <= 0" << Endl;
377 if (integral>0) fPDFHist->Scale( 1.0/integral );
379 fPDFHist->SetDirectory(0);
386 void TMVA::PDF::BuildKDEPDF()
388 fPDFHist =
new TH1F(
"",
"", fgNbin_PdfHist, GetXmin(), GetXmax() );
389 fPDFHist->SetTitle( (TString)fHist->GetTitle() +
"_hist from_KDE" );
390 fPDFHist->SetName ( (TString)fHist->GetName() +
"_hist_from_KDE" );
393 Float_t histoLowEdge = fHist->GetBinLowEdge(1);
394 Float_t histoUpperEdge = fPDFHist->GetBinLowEdge(fPDFHist->GetNbinsX()) + fPDFHist->GetBinWidth(fPDFHist->GetNbinsX());
395 KDEKernel *kern =
new TMVA::KDEKernel( fKDEiter,
396 fHist, histoLowEdge, histoUpperEdge,
397 fKDEborder, fFineFactor );
398 kern->SetKernelType(fKDEtype);
400 for (Int_t i=1;i<fHist->GetNbinsX();i++) {
402 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
404 fPDFHist->AddBinContent(j,fHist->GetBinContent(i)*
405 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
406 fPDFHist->GetBinLowEdge(j+1),
407 fHist->GetBinCenter(i),
411 if (fKDEborder == 3) {
415 if (i < fHist->GetNbinsX()/5 ) {
416 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
418 fPDFHist->AddBinContent(j,fHist->GetBinContent(i)*
419 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
420 fPDFHist->GetBinLowEdge(j+1),
421 2*histoLowEdge-fHist->GetBinCenter(i),
426 if (i > 4*fHist->GetNbinsX()/5) {
427 for (Int_t j=1;j<fPDFHist->GetNbinsX();j++) {
429 fPDFHist->AddBinContent( j,fHist->GetBinContent(i)*
430 kern->GetBinKernelIntegral(fPDFHist->GetBinLowEdge(j),
431 fPDFHist->GetBinLowEdge(j+1),
432 2*histoUpperEdge-fHist->GetBinCenter(i), i) );
438 fPDFHist->SetEntries(fHist->GetEntries());
443 Double_t integral = GetIntegral();
444 if (integral < 0) Log() << kFATAL <<
"Integral: " << integral <<
" <= 0" << Endl;
448 if (integral>0) fPDFHist->Scale( 1.0/integral );
449 fPDFHist->SetDirectory(0);
454 void TMVA::PDF::SmoothHistogram()
456 if(fHist->GetNbinsX()==1)
return;
457 if (fMaxNsmooth == fMinNsmooth) {
458 fHist->Smooth( fMinNsmooth );
464 Float_t Err=0, ErrAvg=0, ErrRMS=0 ; Int_t num=0, smooth;
465 for (Int_t bin=0; bin<fHist->GetNbinsX(); bin++) {
466 if (fHist->GetBinContent(bin+1) <= fHist->GetBinError(bin+1))
continue;
467 Err = fHist->GetBinError(bin+1) / fHist->GetBinContent(bin+1);
468 ErrAvg += Err; ErrRMS += Err*Err; num++;
471 ErrRMS = TMath::Sqrt(ErrRMS/num-ErrAvg*ErrAvg) ;
474 Float_t MaxErr=ErrAvg+ErrRMS, MinErr=ErrAvg-ErrRMS;
475 fNSmoothHist =
new TH1I(
"",
"",fHist->GetNbinsX(),0,fHist->GetNbinsX());
476 fNSmoothHist->SetTitle( (TString)fHist->GetTitle() +
"_Nsmooth" );
477 fNSmoothHist->SetName ( (TString)fHist->GetName() +
"_Nsmooth" );
478 for (Int_t bin=0; bin<fHist->GetNbinsX(); bin++) {
479 if (fHist->GetBinContent(bin+1) <= fHist->GetBinError(bin+1))
482 Err = fHist->GetBinError(bin+1) / fHist->GetBinContent(bin+1);
483 smooth=(Int_t)((Err-MinErr) /(MaxErr-MinErr) * (fMaxNsmooth-fMinNsmooth)) + fMinNsmooth;
485 smooth = TMath::Max(fMinNsmooth,TMath::Min(fMaxNsmooth,smooth));
486 fNSmoothHist->SetBinContent(bin+1,smooth);
491 for (Int_t n=fMaxNsmooth; n>=0; n--) {
493 if (n <= fMinNsmooth) { fHist->Smooth();
continue; }
494 Int_t MinBin=-1,MaxBin =-1;
495 for (Int_t bin=0; bin < fHist->GetNbinsX(); bin++) {
496 if (fNSmoothHist->GetBinContent(bin+1) >= n) {
497 if (MinBin==-1) MinBin = bin;
500 else if (MaxBin >= 0) {
501 fHist->Smooth(1,
"R");
513 void TMVA::PDF::FillHistToGraph()
515 fGraph=
new TGraph(fHist);
522 void TMVA::PDF::FillSplineToHist()
524 if (UseHistogram()) {
526 fPDFHist = (TH1*)fHist->Clone();
527 fPDFHist->SetTitle( (TString)fHist->GetTitle() +
"_hist from_spline0" );
528 fPDFHist->SetName ( (TString)fHist->GetName() +
"_hist_from_spline0" );
532 fPDFHist =
new TH1F(
"",
"", fgNbin_PdfHist, GetXmin(), GetXmax() );
533 fPDFHist->SetTitle( (TString)fHist->GetTitle() +
"_hist from_" + fSpline->GetTitle() );
534 fPDFHist->SetName ( (TString)fHist->GetName() +
"_hist_from_" + fSpline->GetTitle() );
536 for (Int_t bin=1; bin <= fgNbin_PdfHist; bin++) {
537 Double_t x = fPDFHist->GetBinCenter( bin );
538 Double_t y = fSpline->Eval( x );
542 if (y <= fgEpsilon) y = fHist->GetBinContent( fHist->FindBin( x ) );
543 fPDFHist->SetBinContent( bin, TMath::Max(y, fgEpsilon) );
546 fPDFHist->SetDirectory(0);
552 void TMVA::PDF::CheckHist()
const
555 Log() << kFATAL <<
"<CheckHist> Called without valid histogram pointer!" << Endl;
558 Int_t nbins = fHist->GetNbinsX();
562 for (Int_t bin=1; bin<=nbins; bin++)
563 if (fHist->GetBinContent(bin) == 0) emptyBins++;
565 if (((Float_t)emptyBins/(Float_t)nbins) > 0.5) {
566 Log() << kWARNING <<
"More than 50% (" << (((Float_t)emptyBins/(Float_t)nbins)*100)
567 <<"%) of the bins in hist '"
568 << fHist->GetName() << "' are empty!" << Endl;
569 Log() << kWARNING << "X_min=" << GetXmin()
570 << " mean=" << fHist->GetMean() << " X_max= " << GetXmax() << Endl;
577 void TMVA::PDF::ValidatePDF( TH1* originalHist )
const
580 if (!originalHist) originalHist = fHistOriginal;
582 Int_t nbins = originalHist->GetNbinsX();
585 if (originalHist->GetSumw2()->GetSize() == 0) originalHist->Sumw2();
595 for (Int_t bin=1; bin<=nbins; bin++) {
596 Double_t x = originalHist->GetBinCenter( bin );
597 Double_t y = originalHist->GetBinContent( bin );
598 Double_t ey = originalHist->GetBinError( bin );
600 Int_t binPdfHist = fPDFHist->FindBin( x );
601 if (binPdfHist<0)
continue;
603 Double_t yref = GetVal( x );
604 Double_t rref = ( originalHist->GetSumOfWeights()/fPDFHist->GetSumOfWeights() *
605 originalHist->GetBinWidth( bin )/fPDFHist->GetBinWidth( binPdfHist ) );
609 Double_t d = TMath::Abs( (y - yref*rref)/ey );
613 if (d > 1) { nc1++;
if (d > 2) { nc2++;
if (d > 3) { nc3++;
if (d > 6) nc6++; } } }
617 Log() << kDEBUG <<
"Validation result for PDF \"" << originalHist->GetTitle() <<
"\"" <<
": " << Endl;
618 Log() << kDEBUG << Form(
" chi2/ndof(!=0) = %.1f/%i = %.2f (Prob = %.2f)",
619 chi2, ndof, chi2/ndof, TMath::Prob( chi2, ndof ) ) << Endl;
620 if ((1.0 - TMath::Prob( chi2, ndof )) > 0.9999994) {
621 Log() << kDEBUG <<
"Comparison of the original histogram \"" << originalHist->GetTitle() <<
"\"" << Endl;
622 Log() << kDEBUG <<
"with the corresponding PDF gave a chi2/ndof of " << chi2/ndof <<
"," << Endl;
623 Log() << kDEBUG <<
"which corresponds to a deviation of more than 5 sigma! Please check!" << Endl;
625 Log() << kDEBUG << Form(
" #bins-found(#expected-bins) deviating > [1,2,3,6] sigmas: " \
626 "[%i(%i),%i(%i),%i(%i),%i(%i)]",
627 nc1, Int_t(TMath::Prob(1.0,1)*ndof), nc2, Int_t(TMath::Prob(4.0,1)*ndof),
628 nc3, Int_t(TMath::Prob(9.0,1)*ndof), nc6, Int_t(TMath::Prob(36.0,1)*ndof) ) << Endl;
634 Double_t TMVA::PDF::GetIntegral()
const
636 Double_t integral = fPDFHist->GetSumOfWeights();
637 integral *= GetPdfHistBinWidth();
645 Double_t TMVA::PDF::IGetVal( Double_t* x, Double_t* )
647 return ThisPDF()->GetVal( x[0] );
653 Double_t TMVA::PDF::GetIntegral( Double_t xmin, Double_t xmax )
655 Double_t integral = 0;
657 if (fgManualIntegration) {
660 Int_t imin = fPDFHist->FindBin(xmin);
661 Int_t imax = fPDFHist->FindBin(xmax);
662 if (imin < 1) imin = 1;
663 if (imax > fPDFHist->GetNbinsX()) imax = fPDFHist->GetNbinsX();
665 for (Int_t bini = imin; bini <= imax; bini++) {
666 Float_t dx = fPDFHist->GetBinWidth(bini);
668 if (bini == imin) dx = fPDFHist->GetBinLowEdge(bini+1) - xmin;
669 else if (bini == imax) dx = xmax - fPDFHist->GetBinLowEdge(bini);
670 if (dx < 0 && dx > -1.0e-8) dx = 0;
673 <<
"dx = " << dx << std::endl
674 <<
"bini = " << bini << std::endl
675 <<
"xmin = " << xmin << std::endl
676 <<
"xmax = " << xmax << std::endl
677 <<
"imin = " << imin << std::endl
678 <<
"imax = " << imax << std::endl
679 <<
"low edge of imin" << fPDFHist->GetBinLowEdge(imin) << std::endl
680 <<
"low edge of imin+1" << fPDFHist->GetBinLowEdge(imin+1) << Endl;
681 Log() << kFATAL <<
"<GetIntegral> dx = " << dx <<
" < 0" << Endl;
683 integral += fPDFHist->GetBinContent(bini)*dx;
690 if (fIGetVal == 0) fIGetVal =
new TF1(
"IGetVal", PDF::IGetVal, GetXmin(), GetXmax(), 0 );
691 integral = fIGetVal->Integral( xmin, xmax );
700 Double_t TMVA::PDF::GetVal( Double_t x )
const
703 Int_t bin = fPDFHist->FindBin(x);
704 bin = TMath::Max(bin,1);
705 bin = TMath::Min(bin,fPDFHist->GetNbinsX());
709 if (UseHistogram()) {
711 retval = fPDFHist->GetBinContent( bin );
716 if ((x > fPDFHist->GetBinCenter(bin) && bin != fPDFHist->GetNbinsX()) || bin == 1)
722 Double_t dx = fPDFHist->GetBinCenter( bin ) - fPDFHist->GetBinCenter( nextbin );
723 Double_t dy = fPDFHist->GetBinContent( bin ) - fPDFHist->GetBinContent( nextbin );
724 retval = fPDFHist->GetBinContent( bin ) + (x - fPDFHist->GetBinCenter( bin ))*dy/dx;
727 return TMath::Max( retval, fgEpsilon );
733 Double_t TMVA::PDF::GetValInverse( Double_t y, Bool_t isMonotonouslyIncreasingFunction )
const
735 Int_t lowerBin=0, higherBin=0;
736 Double_t lowerBinValue=0, higherBinValue=0;
737 FindBinInverse(fPDFHist,lowerBin,higherBin,lowerBinValue,higherBinValue,y,isMonotonouslyIncreasingFunction);
739 Double_t xValueLowerBin =fPDFHist->GetBinCenter (lowerBin);
740 Double_t xValueHigherBin=fPDFHist->GetBinCenter (higherBin);
742 Double_t length =(higherBinValue-lowerBinValue);
743 Double_t fraction=lowerBinValue;
745 fraction=(y-lowerBinValue)/length;
747 Double_t lengthX =xValueHigherBin-xValueLowerBin;
748 Double_t x =xValueLowerBin+lengthX*fraction;
760 void TMVA::PDF::FindBinInverse(
const TH1* histogram, Int_t& lowerBin, Int_t& higherBin, Double_t& lowerBinValue, Double_t& higherBinValue,
761 Double_t y, Bool_t isMonotonouslyIncreasingFunction )
const
763 if (isMonotonouslyIncreasingFunction) {
764 higherBin=histogram->GetNbinsX();
767 Int_t bin=higherBin/2;
769 while (bin>lowerBin && bin<higherBin) {
770 Double_t binContent=histogram->GetBinContent(bin);
774 higherBinValue=binContent;
776 else if (y>=binContent){
778 lowerBinValue =binContent;
780 bin=lowerBin+(higherBin-lowerBin)/2;
785 for (Int_t bin=0, binEnd=histogram->GetNbinsX(); bin<binEnd; ++bin) {
786 Double_t binContent=histogram->GetBinContent(bin);
790 lowerBinValue =binContent;
791 higherBinValue=binContent;
795 higherBinValue=binContent;
819 void TMVA::PDF::DeclareOptions()
821 DeclareOptionRef( fNsmooth, Form(
"NSmooth%s",fSuffix.Data()),
822 "Number of smoothing iterations for the input histograms" );
823 DeclareOptionRef( fMinNsmooth, Form(
"MinNSmooth%s",fSuffix.Data()),
824 "Min number of smoothing iterations, for bins with most data" );
826 DeclareOptionRef( fMaxNsmooth, Form(
"MaxNSmooth%s",fSuffix.Data()),
827 "Max number of smoothing iterations, for bins with least data" );
829 DeclareOptionRef( fHistAvgEvtPerBin, Form(
"NAvEvtPerBin%s",fSuffix.Data()),
830 "Average number of events per PDF bin" );
832 DeclareOptionRef( fHistDefinedNBins, Form(
"Nbins%s",fSuffix.Data()),
833 "Defined number of bins for the histogram from which the PDF is created" );
835 DeclareOptionRef( fCheckHist, Form(
"CheckHist%s",fSuffix.Data()),
836 "Whether or not to check the source histogram of the PDF" );
838 DeclareOptionRef( fInterpolateString, Form(
"PDFInterpol%s",fSuffix.Data()),
839 "Interpolation method for reference histograms (e.g. Spline2 or KDE)" );
840 AddPreDefVal(TString(
"Spline0"));
841 AddPreDefVal(TString(
"Spline1"));
842 AddPreDefVal(TString(
"Spline2"));
843 AddPreDefVal(TString(
"Spline3"));
844 AddPreDefVal(TString(
"Spline5"));
845 AddPreDefVal(TString(
"KDE"));
847 DeclareOptionRef( fKDEtypeString, Form(
"KDEtype%s",fSuffix.Data()),
"KDE kernel type (1=Gauss)" );
848 AddPreDefVal(TString(
"Gauss"));
850 DeclareOptionRef( fKDEiterString, Form(
"KDEiter%s",fSuffix.Data()),
"Number of iterations (1=non-adaptive, 2=adaptive)" );
851 AddPreDefVal(TString(
"Nonadaptive"));
852 AddPreDefVal(TString(
"Adaptive"));
854 DeclareOptionRef( fFineFactor , Form(
"KDEFineFactor%s",fSuffix.Data()),
855 "Fine tuning factor for Adaptive KDE: Factor to multiply the width of the kernel");
857 DeclareOptionRef( fBorderMethodString, Form(
"KDEborder%s",fSuffix.Data()),
858 "Border effects treatment (1=no treatment , 2=kernel renormalization, 3=sample mirroring)" );
859 AddPreDefVal(TString(
"None"));
860 AddPreDefVal(TString(
"Renorm"));
861 AddPreDefVal(TString(
"Mirror"));
863 SetConfigName( GetName() );
864 SetConfigDescription(
"Configuration options for the PDF class" );
869 void TMVA::PDF::ProcessOptions()
871 if (fNsmooth < 0) fNsmooth = 0;
873 if (fMaxNsmooth < 0 || fMinNsmooth < 0) {
874 fMinNsmooth = fMaxNsmooth = fNsmooth;
877 if (fMaxNsmooth < fMinNsmooth && fMinNsmooth >= 0) {
878 Log() << kFATAL <<
"ERROR: MaxNsmooth = "
879 << fMaxNsmooth <<
" < MinNsmooth = " << fMinNsmooth << Endl;
882 if (fMaxNsmooth < 0 || fMinNsmooth < 0) {
883 Log() << kFATAL <<
"ERROR: MaxNsmooth = "
884 << fMaxNsmooth <<
" or MinNsmooth = " << fMinNsmooth <<
" smaller than zero" << Endl;
888 if (fInterpolateString ==
"Spline0") fInterpolMethod = TMVA::PDF::kSpline0;
889 else if (fInterpolateString ==
"Spline1") fInterpolMethod = TMVA::PDF::kSpline1;
890 else if (fInterpolateString ==
"Spline2") fInterpolMethod = TMVA::PDF::kSpline2;
891 else if (fInterpolateString ==
"Spline3") fInterpolMethod = TMVA::PDF::kSpline3;
892 else if (fInterpolateString ==
"Spline5") fInterpolMethod = TMVA::PDF::kSpline5;
893 else if (fInterpolateString ==
"KDE" ) fInterpolMethod = TMVA::PDF::kKDE;
894 else if (fInterpolateString !=
"" ) {
895 Log() << kFATAL <<
"unknown setting for option 'InterpolateMethod': " << fKDEtypeString << ((fSuffix==
"")?
"":Form(
" for pdf with suffix %s",fSuffix.Data())) << Endl;
899 if (fKDEtypeString ==
"Gauss" ) fKDEtype = KDEKernel::kGauss;
900 else if (fKDEtypeString !=
"" )
901 Log() << kFATAL <<
"unknown setting for option 'KDEtype': " << fKDEtypeString << ((fSuffix==
"")?
"":Form(
" for pdf with suffix %s",fSuffix.Data())) << Endl;
902 if (fKDEiterString ==
"Nonadaptive") fKDEiter = KDEKernel::kNonadaptiveKDE;
903 else if (fKDEiterString ==
"Adaptive" ) fKDEiter = KDEKernel::kAdaptiveKDE;
904 else if (fKDEiterString !=
"" )
905 Log() << kFATAL <<
"unknown setting for option 'KDEiter': " << fKDEtypeString << ((fSuffix==
"")?
"":Form(
" for pdf with suffix %s",fSuffix.Data())) << Endl;
907 if ( fBorderMethodString ==
"None" ) fKDEborder= KDEKernel::kNoTreatment;
908 else if ( fBorderMethodString ==
"Renorm" ) fKDEborder= KDEKernel::kKernelRenorm;
909 else if ( fBorderMethodString ==
"Mirror" ) fKDEborder= KDEKernel::kSampleMirror;
910 else if ( fKDEiterString !=
"" ) {
911 Log() << kFATAL <<
"unknown setting for option 'KDEBorder': " << fKDEtypeString << ((fSuffix==
"")?
"":Form(
" for pdf with suffix %s",fSuffix.Data())) << Endl;
918 void TMVA::PDF::AddXMLTo(
void* parent )
920 void* pdfxml = gTools().AddChild(parent,
"PDF");
921 gTools().AddAttr(pdfxml,
"Name", fPDFName );
922 gTools().AddAttr(pdfxml,
"MinNSmooth", fMinNsmooth );
923 gTools().AddAttr(pdfxml,
"MaxNSmooth", fMaxNsmooth );
924 gTools().AddAttr(pdfxml,
"InterpolMethod", fInterpolMethod );
925 gTools().AddAttr(pdfxml,
"KDE_type", fKDEtype );
926 gTools().AddAttr(pdfxml,
"KDE_iter", fKDEiter );
927 gTools().AddAttr(pdfxml,
"KDE_border", fKDEborder );
928 gTools().AddAttr(pdfxml,
"KDE_finefactor", fFineFactor );
929 void* pdfhist = gTools().AddChild(pdfxml,
"Histogram" );
930 TH1* histToWrite = GetOriginalHist();
931 Bool_t hasEquidistantBinning = gTools().HistoHasEquidistantBins(*histToWrite);
932 gTools().AddAttr(pdfhist,
"Name", histToWrite->GetName() );
933 gTools().AddAttr(pdfhist,
"NBins", histToWrite->GetNbinsX() );
934 gTools().AddAttr(pdfhist,
"XMin", histToWrite->GetXaxis()->GetXmin() );
935 gTools().AddAttr(pdfhist,
"XMax", histToWrite->GetXaxis()->GetXmax() );
936 gTools().AddAttr(pdfhist,
"HasEquidistantBins", hasEquidistantBinning );
938 TString bincontent(
"");
939 for (Int_t i=0; i<histToWrite->GetNbinsX(); i++) {
940 bincontent += gTools().StringFromDouble(histToWrite->GetBinContent(i+1));
943 gTools().AddRawLine(pdfhist, bincontent );
945 if (!hasEquidistantBinning) {
946 void* pdfhistbins = gTools().AddChild(pdfxml,
"HistogramBinning" );
947 gTools().AddAttr(pdfhistbins,
"NBins", histToWrite->GetNbinsX() );
949 for (Int_t i=1; i<=histToWrite->GetNbinsX()+1; i++) {
950 binns += gTools().StringFromDouble(histToWrite->GetXaxis()->GetBinLowEdge(i));
953 gTools().AddRawLine(pdfhistbins, binns );
960 void TMVA::PDF::ReadXML(
void* pdfnode )
964 gTools().ReadAttr(pdfnode,
"MinNSmooth", fMinNsmooth );
965 gTools().ReadAttr(pdfnode,
"MaxNSmooth", fMaxNsmooth );
966 gTools().ReadAttr(pdfnode,
"InterpolMethod", enumint ); fInterpolMethod = EInterpolateMethod(enumint);
967 gTools().ReadAttr(pdfnode,
"KDE_type", enumint ); fKDEtype = KDEKernel::EKernelType(enumint);
968 gTools().ReadAttr(pdfnode,
"KDE_iter", enumint ); fKDEiter = KDEKernel::EKernelIter(enumint);
969 gTools().ReadAttr(pdfnode,
"KDE_border", enumint ); fKDEborder = KDEKernel::EKernelBorder(enumint);
970 gTools().ReadAttr(pdfnode,
"KDE_finefactor", fFineFactor );
975 Bool_t hasEquidistantBinning;
977 void* histch = gTools().GetChild(pdfnode);
978 gTools().ReadAttr( histch,
"Name", hname );
979 gTools().ReadAttr( histch,
"NBins", nbins );
980 gTools().ReadAttr( histch,
"XMin", xmin );
981 gTools().ReadAttr( histch,
"XMax", xmax );
982 gTools().ReadAttr( histch,
"HasEquidistantBins", hasEquidistantBinning );
986 if (hasEquidistantBinning) {
987 newhist =
new TH1F( hname, hname, nbins, xmin, xmax );
988 newhist->SetDirectory(0);
989 const char* content = gTools().GetContent(histch);
990 std::stringstream s(content);
992 for (UInt_t i=0; i<nbins; i++) {
994 newhist->SetBinContent(i+1,val);
998 const char* content = gTools().GetContent(histch);
999 std::stringstream s(content);
1001 void* binch = gTools().GetNextChild(histch);
1003 gTools().ReadAttr( binch,
"NBins", nbinning );
1004 TVectorD binns(nbinning+1);
1005 if (nbinning != nbins) {
1006 Log() << kFATAL <<
"Number of bins in content and binning array differs"<<Endl;
1008 const char* binString = gTools().GetContent(binch);
1009 std::stringstream sb(binString);
1010 for (UInt_t i=0; i<=nbins; i++) sb >> binns[i];
1011 newhist =
new TH1F( hname, hname, nbins, binns.GetMatrixArray() );
1012 newhist->SetDirectory(0);
1013 for (UInt_t i=0; i<nbins; i++) {
1015 newhist->SetBinContent(i+1,val);
1019 TString hnameSmooth = hname;
1020 hnameSmooth.ReplaceAll(
"_original",
"_smoothed" );
1022 if (fHistOriginal != 0)
delete fHistOriginal;
1023 fHistOriginal = newhist;
1024 fHist = (TH1F*)fHistOriginal->Clone( hnameSmooth );
1025 fHist->SetTitle( hnameSmooth );
1026 fHist->SetDirectory(0);
1028 if (fInterpolMethod == PDF::kKDE) BuildKDEPDF();
1029 else BuildSplinePDF();
1035 std::ostream& TMVA::operator<< ( std::ostream& os,
const PDF& pdf )
1037 Int_t dp = os.precision();
1038 os <<
"MinNSmooth " << pdf.fMinNsmooth << std::endl;
1039 os <<
"MaxNSmooth " << pdf.fMaxNsmooth << std::endl;
1040 os <<
"InterpolMethod " << pdf.fInterpolMethod << std::endl;
1041 os <<
"KDE_type " << pdf.fKDEtype << std::endl;
1042 os <<
"KDE_iter " << pdf.fKDEiter << std::endl;
1043 os <<
"KDE_border " << pdf.fKDEborder << std::endl;
1044 os <<
"KDE_finefactor " << pdf.fFineFactor << std::endl;
1046 TH1* histToWrite = pdf.GetOriginalHist();
1048 const Int_t nBins = histToWrite->GetNbinsX();
1052 << histToWrite->GetName()
1054 <<
" " << std::setprecision(12) << histToWrite->GetXaxis()->GetXmin()
1055 <<
" " << std::setprecision(12) << histToWrite->GetXaxis()->GetXmax()
1059 os <<
"Weights " << std::endl;
1060 os << std::setprecision(8);
1061 for (Int_t i=0; i<nBins; i++) {
1062 os << std::setw(15) << std::left << histToWrite->GetBinContent(i+1) << std::right <<
" ";
1063 if ((i+1)%5==0) os << std::endl;
1066 os << std::setprecision(dp);
1073 std::istream& TMVA::operator>> ( std::istream& istr, PDF& pdf )
1078 Float_t xmin=-1., xmax=-1.;
1079 TString hname=
"_original";
1080 Bool_t doneReading = kFALSE;
1081 while (!doneReading) {
1083 if (devnullS==
"NSmooth")
1084 {istr >> pdf.fMinNsmooth; pdf.fMaxNsmooth=pdf.fMinNsmooth;}
1085 else if (devnullS==
"MinNSmooth") istr >> pdf.fMinNsmooth;
1086 else if (devnullS==
"MaxNSmooth") istr >> pdf.fMaxNsmooth;
1088 else if (devnullS ==
"InterpolMethod") { istr >> valI; pdf.fInterpolMethod = PDF::EInterpolateMethod(valI);}
1089 else if (devnullS ==
"KDE_type") { istr >> valI; pdf.fKDEtype = KDEKernel::EKernelType(valI); }
1090 else if (devnullS ==
"KDE_iter") { istr >> valI; pdf.fKDEiter = KDEKernel::EKernelIter(valI);}
1091 else if (devnullS ==
"KDE_border") { istr >> valI; pdf.fKDEborder = KDEKernel::EKernelBorder(valI);}
1092 else if (devnullS ==
"KDE_finefactor") {
1093 istr >> pdf.fFineFactor;
1094 if (pdf.GetReadingVersion() != 0 && pdf.GetReadingVersion() < TMVA_VERSION(3,7,3)) {
1096 istr >> nbins >> xmin >> xmax;
1097 doneReading = kTRUE;
1100 else if (devnullS ==
"Histogram") { istr >> hname >> nbins >> xmin >> xmax; }
1101 else if (devnullS ==
"Weights") { doneReading = kTRUE; }
1104 TString hnameSmooth = hname;
1105 hnameSmooth.ReplaceAll(
"_original",
"_smoothed" );
1109 std::cout <<
"PDF, trying to create a histogram without defined binning"<< std::endl;
1112 TH1* newhist =
new TH1F( hname,hname, nbins, xmin, xmax );
1113 newhist->SetDirectory(0);
1115 for (Int_t i=0; i<nbins; i++) {
1117 newhist->SetBinContent(i+1,val);
1120 if (pdf.fHistOriginal != 0)
delete pdf.fHistOriginal;
1121 pdf.fHistOriginal = newhist;
1122 pdf.fHist = (TH1F*)pdf.fHistOriginal->Clone( hnameSmooth );
1123 pdf.fHist->SetTitle( hnameSmooth );
1124 pdf.fHist->SetDirectory(0);
1126 if (pdf.fMinNsmooth>=0) pdf.BuildSplinePDF();
1128 pdf.fInterpolMethod = PDF::kKDE;
1135 TMVA::PDF* TMVA::PDF::ThisPDF(
void )
1138 return GetThisPdfThreadLocal();