48 TMVA::ROCCalc::ROCCalc(TH1* mvaS, TH1* mvaB) :
68 fLogger ( new TMVA::MsgLogger(
"ROCCalc") )
74 fmvaS = mvaS; fmvaS->SetTitle(
"MVA Signal");
75 fmvaB = mvaB; fmvaB->SetTitle(
"MVA Backgr");
76 fXmax = fmvaS->GetXaxis()->GetXmax();
77 fXmin = fmvaS->GetXaxis()->GetXmin();
79 if (TMath::Abs(fXmax-fmvaB->GetXaxis()->GetXmax()) > 0.000001 ||
80 TMath::Abs(fXmin-fmvaB->GetXaxis()->GetXmin()) > 0.000001 ||
81 fmvaB->GetNbinsX() != fmvaS->GetNbinsX()) {
82 Log() << kERROR <<
"Cannot cal ROC curve etc, as in put mvaS and mvaB have differen #nbins or range "<<Endl;
85 if (!strcmp(fmvaS->GetXaxis()->GetTitle(),
"")) fmvaS->SetXTitle(
"MVA-value");
86 if (!strcmp(fmvaB->GetXaxis()->GetTitle(),
"")) fmvaB->SetXTitle(
"MVA-value");
87 if (!strcmp(fmvaS->GetYaxis()->GetTitle(),
"")) fmvaS->SetYTitle(
"#entries");
88 if (!strcmp(fmvaB->GetYaxis()->GetTitle(),
"")) fmvaB->SetYTitle(
"#entries");
89 ApplySignalAndBackgroundStyle(fmvaS, fmvaB);
94 fmvaSpdf = mvaS->RebinX(mvaS->GetNbinsX()/10,
"MVA Signal PDF");
95 fmvaBpdf = mvaB->RebinX(mvaB->GetNbinsX()/10,
"MVA Backgr PDF");
96 if(fmvaSpdf==0||fmvaBpdf==0)
98 Log() << kERROR <<
"Cannot Rebin Histograms mvaS and mvaB, ROC values will be calculated without Rebin histograms."<<Endl;
100 fmvaSpdf = (TH1*)mvaS->Clone(
"MVA Signal PDF");
101 fmvaBpdf = (TH1*)mvaB->Clone(
"MVA Backgr PDF");
103 fmvaSpdf->SetTitle(
"MVA Signal PDF");
104 fmvaBpdf->SetTitle(
"MVA Backgr PDF");
105 fmvaSpdf->Scale(1./fmvaSpdf->GetSumOfWeights());
106 fmvaBpdf->Scale(1./fmvaBpdf->GetSumOfWeights());
107 fmvaSpdf->SetMaximum(TMath::Max(fmvaSpdf->GetMaximum(), fmvaBpdf->GetMaximum()));
108 fmvaBpdf->SetMaximum(TMath::Max(fmvaSpdf->GetMaximum(), fmvaBpdf->GetMaximum()));
109 ApplySignalAndBackgroundStyle(fmvaSpdf, fmvaBpdf);
111 fCutOrientation = (fmvaS->GetMean() > fmvaB->GetMean()) ? +1 : -1;
119 void TMVA::ROCCalc::ApplySignalAndBackgroundStyle( TH1* sig, TH1* bkg, TH1* any ) {
120 Int_t c_SignalLine = TColor::GetColor(
"#0000ee" );
121 Int_t c_SignalFill = TColor::GetColor(
"#7d99d1" );
122 Int_t c_BackgroundLine = TColor::GetColor(
"#ff0000" );
123 Int_t c_BackgroundFill = TColor::GetColor(
"#ff0000" );
129 Int_t FillColor__S = c_SignalFill;
130 Int_t FillStyle__S = 1001;
131 Int_t LineColor__S = c_SignalLine;
132 Int_t LineWidth__S = 2;
136 Int_t FillColor__B = c_BackgroundFill;
137 Int_t FillStyle__B = 3554;
138 Int_t LineColor__B = c_BackgroundLine;
139 Int_t LineWidth__B = 2;
142 sig->SetLineColor( LineColor__S );
143 sig->SetLineWidth( LineWidth__S );
144 sig->SetFillStyle( FillStyle__S );
145 sig->SetFillColor( FillColor__S );
149 bkg->SetLineColor( LineColor__B );
150 bkg->SetLineWidth( LineWidth__B );
151 bkg->SetFillStyle( FillStyle__B );
152 bkg->SetFillColor( FillColor__B );
156 any->SetLineColor( LineColor__S );
157 any->SetLineWidth( LineWidth__S );
158 any->SetFillStyle( FillStyle__S );
159 any->SetFillColor( FillColor__S );
166 TMVA::ROCCalc::~ROCCalc() {
168 if (fSplS) {
delete fSplS; fSplS = 0; }
169 if (fSplB) {
delete fSplB; fSplB = 0; }
170 if (fSpleffBvsS) {
delete fSpleffBvsS; fSpleffBvsS = 0; }
171 if (fSplmvaCumS) {
delete fSplmvaCumS; fSplmvaCumS = 0; }
172 if (fSplmvaCumB) {
delete fSplmvaCumB; fSplmvaCumB = 0; }
173 if (fmvaScumul) {
delete fmvaScumul; }
174 if (fmvaBcumul) {
delete fmvaBcumul; }
175 if (effBvsS) {
delete effBvsS; }
176 if (rejBvsS) {
delete rejBvsS; }
177 if (inveffBvsS) {
delete inveffBvsS; }
184 TH1D* TMVA::ROCCalc::GetROC(){
187 fNevtS = fmvaS->GetSumOfWeights();
189 Log() << kERROR <<
"I guess the mva distributions fed into ROCCalc were already normalized, therefore the calculated error on the efficiency will be incorrect !! " << Endl;
193 fmvaScumul = gTools().GetCumulativeDist(fmvaS);
194 fmvaBcumul = gTools().GetCumulativeDist(fmvaB);
195 fmvaScumul->Scale( 1.0/TMath::Max(std::numeric_limits<double>::epsilon(),fmvaScumul->GetMaximum()) );
196 fmvaBcumul->Scale( 1.0/TMath::Max(std::numeric_limits<double>::epsilon(),fmvaBcumul->GetMaximum()) );
197 fmvaScumul->SetMinimum(0);
198 fmvaBcumul->SetMinimum(0);
203 if(effBvsS==0) effBvsS =
new TH1D(
"effBvsS",
"ROC-Curve", fNbins, 0, 1 );
204 effBvsS->SetXTitle(
"Signal eff" );
205 effBvsS->SetYTitle(
"Backgr eff" );
208 if(rejBvsS==0) rejBvsS =
new TH1D(
"rejBvsS",
"ROC-Curve", fNbins, 0, 1 );
209 rejBvsS->SetXTitle(
"Signal eff" );
210 rejBvsS->SetYTitle(
"Backgr rejection (1-eff)" );
213 if(inveffBvsS ==0) inveffBvsS =
new TH1D(
"invBeffvsSeff",
"ROC-Curve" , fNbins, 0, 1 );
214 inveffBvsS->SetXTitle(
"Signal eff" );
215 inveffBvsS->SetYTitle(
"Inverse backgr. eff (1/eff)" );
221 fSplmvaCumS =
new TSpline1(
"spline2_signal",
new TGraph( fmvaScumul ) );
222 fSplmvaCumB =
new TSpline1(
"spline2_background",
new TGraph( fmvaBcumul ) );
224 gTools().CheckSplines( fmvaScumul, fSplmvaCumS );
225 gTools().CheckSplines( fmvaBcumul, fSplmvaCumB );
229 for (UInt_t bini=1; bini<=fNbins; bini++) {
232 Double_t effS = effBvsS->GetBinCenter( bini );
233 Double_t cut = Root( effS );
236 if (fUseSplines) effB = fSplmvaCumB->Eval( cut );
237 else effB = fmvaBcumul->GetBinContent( fmvaBcumul->FindBin( cut ) );
240 effBvsS->SetBinContent( bini, effB );
241 rejBvsS->SetBinContent( bini, 1.0-effB );
242 if (effB>std::numeric_limits<double>::epsilon())
243 inveffBvsS->SetBinContent( bini, 1.0/effB );
247 fSpleffBvsS =
new TSpline1(
"effBvsS",
new TGraph( effBvsS ) );
252 Double_t effS = 0., rejB = 0., effS_ = 0., rejB_ = 0.;
254 for (Int_t bini=1; bini<=nbins; bini++) {
257 effS = (bini - 0.5)/Float_t(nbins);
258 rejB = 1.0 - fSpleffBvsS->Eval( effS );
261 if ((effS - rejB)*(effS_ - rejB_) < 0)
break;
266 fSignalCut = Root( 0.5*(effS + effS_) );
274 Double_t TMVA::ROCCalc::GetROCIntegral(){
275 Double_t effS = 0, effB = 0;
277 if (fSpleffBvsS == 0) this->GetROC();
280 Double_t integral = 0;
281 for (Int_t bini=1; bini<=nbins; bini++) {
284 effS = (bini - 0.5)/Float_t(nbins);
285 effB = fSpleffBvsS->Eval( effS );
286 integral += (1.0 - effB);
298 Double_t TMVA::ROCCalc::GetEffSForEffBof(Double_t effBref, Double_t &effSerr){
300 Double_t effS=0., effB, effSOld=1., effBOld=0.;
302 if (fSpleffBvsS == 0) this->GetROC();
304 Float_t step=1./nbins;
305 for (Int_t bini=1; bini<=nbins; bini++) {
307 effS = (bini - 0.5)*step;
308 effB = fSpleffBvsS->Eval( effS );
311 if ((effB - effBref)*(effBOld - effBref) <= 0)
break;
317 effS = 0.5*(effS + effSOld);
320 if (fNevtS > 0) effSerr = TMath::Sqrt( effS*(1.0 - effS)/fNevtS );
329 Double_t TMVA::ROCCalc::GetEffForRoot( Double_t theCut )
334 if (fUseSplines) retVal = fSplmvaCumS->Eval( theCut );
335 else retVal = fmvaScumul->GetBinContent( fmvaScumul->FindBin( theCut ) );
343 Double_t eps = 1.0e-5;
344 if (theCut-fXmin < eps) retVal = (fCutOrientation > 0) ? 1.0 : 0.0;
345 else if (fXmax-theCut < eps) retVal = (fCutOrientation > 0) ? 0.0 : 1.0;
354 Double_t TMVA::ROCCalc::Root( Double_t refValue )
356 Double_t a = fXmin, b = fXmax;
357 Double_t fa = GetEffForRoot( a ) - refValue;
358 Double_t fb = GetEffForRoot( b ) - refValue;
360 Log() << kWARNING <<
"<ROCCalc::Root> initial interval w/o root: "
361 <<
"(a=" << a <<
", b=" << b <<
"),"
362 <<
" (Eff_a=" << GetEffForRoot( a )
363 <<
", Eff_b=" << GetEffForRoot( b ) <<
"), "
364 <<
"(fa=" << fa <<
", fb=" << fb <<
"), "
365 <<
"refValue = " << refValue << Endl;
369 Bool_t ac_equal(kFALSE);
371 Double_t c = 0, d = 0, e = 0;
372 for (Int_t iter= 0; iter <= fMaxIter; iter++) {
373 if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
378 d = b - a; e = b - a;
381 if (TMath::Abs(fc) < TMath::Abs(fb)) {
384 fa = fb; fb = fc; fc = fa;
387 Double_t tol = 0.5 * 2.2204460492503131e-16 * TMath::Abs(b);
388 Double_t m = 0.5 * (c - b);
389 if (fb == 0 || TMath::Abs(m) <= tol || TMath::Abs(fb) < fAbsTol)
return b;
392 if (TMath::Abs (e) < tol || TMath::Abs (fa) <= TMath::Abs (fb)) { d = m; e = m; }
396 Double_t s = fb / fa;
398 if (ac_equal) { p = 2 * m * s; q = 1 - s; }
400 q = fa / fc; r = fb / fc;
401 p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
402 q = (q - 1) * (r - 1) * (s - 1);
408 Double_t min1 = 3 * m * q - TMath::Abs (tol * q);
409 Double_t min2 = TMath::Abs (e * q);
410 if (2 * p < (min1 < min2 ? min1 : min2)) {
414 else { d = m; e = m; }
419 if (TMath::Abs(d) > tol) b += d;
420 else b += (m > 0 ? +tol : -tol);
422 fb = GetEffForRoot( b ) - refValue;
427 Log() << kWARNING <<
"<ROCCalc::Root> maximum iterations (" << fMaxIter
428 <<
") reached before convergence" << Endl;
435 TH1* TMVA::ROCCalc::GetPurity( Int_t nStot, Int_t nBtot)
437 if (fnStot!=nStot || fnBtot!=nBtot || !fSignificance) {
438 GetSignificance(nStot, nBtot);
446 TH1* TMVA::ROCCalc::GetSignificance( Int_t nStot, Int_t nBtot)
448 if (fnStot==nStot && fnBtot==nBtot && !fSignificance)
return fSignificance;
449 fnStot=nStot; fnBtot=nBtot;
451 fSignificance = (TH1*) fmvaScumul->Clone(
"Significance"); fSignificance->SetTitle(
"Significance");
452 fSignificance->Reset(); fSignificance->SetFillStyle(0);
453 fSignificance->SetXTitle(
"mva cut value");
454 fSignificance->SetYTitle(
"Stat. significance S/Sqrt(S+B)");
455 fSignificance->SetLineColor(2);
456 fSignificance->SetLineWidth(5);
458 fPurity = (TH1*) fmvaScumul->Clone(
"Purity"); fPurity->SetTitle(
"Purity");
459 fPurity->Reset(); fPurity->SetFillStyle(0);
460 fPurity->SetXTitle(
"mva cut value");
461 fPurity->SetYTitle(
"Purity: S/(S+B)");
462 fPurity->SetLineColor(3);
463 fPurity->SetLineWidth(5);
466 for (Int_t i=1; i<=fSignificance->GetNbinsX(); i++) {
467 Double_t S = fmvaScumul->GetBinContent( i ) * nStot;
468 Double_t B = fmvaBcumul->GetBinContent( i ) * nBtot;
473 sig = S/TMath::Sqrt(S+B);
481 cout <<
"S="<<S<<
" B="<<B<<
" purity="<<purity<< endl;
482 fPurity->SetBinContent( i, purity );
483 fSignificance->SetBinContent( i, sig );
500 return fSignificance;