00001 #include <iostream>
00002 #include <iomanip>
00003 using std::cout;
00004 using std::endl;
00005
00006 #include "tmvaglob.C"
00007
00008 #include "RQ_OBJECT.h"
00009
00010 #include "TH1.h"
00011 #include "TROOT.h"
00012 #include "TList.h"
00013 #include "TIterator.h"
00014 #include "TStyle.h"
00015 #include "TPad.h"
00016 #include "TCanvas.h"
00017 #include "TLatex.h"
00018 #include "TLegend.h"
00019 #include "TLine.h"
00020 #include "TH2.h"
00021 #include "TFormula.h"
00022 #include "TFile.h"
00023 #include "TApplication.h"
00024 #include "TKey.h"
00025 #include "TClass.h"
00026 #include "TGaxis.h"
00027
00028 #include "TGWindow.h"
00029 #include "TGButton.h"
00030 #include "TGLabel.h"
00031 #include "TGNumberEntry.h"
00032
00033
00034
00035
00036 enum PlotType { EffPurity = 0 };
00037
00038 class MethodInfo : public TNamed {
00039 public:
00040 MethodInfo() :
00041 methodName(""),
00042 methodTitle(""),
00043 sig(0),
00044 bgd(0),
00045 origSigE(0),
00046 origBgdE(0),
00047 sigE(0),
00048 bgdE(0),
00049 purS(0),
00050 sSig(0),
00051 effpurS(0),
00052 canvas(0),
00053 line1(0),
00054 line2(0),
00055 rightAxis(0),
00056 maxSignificance(0)
00057 {}
00058 virtual ~MethodInfo();
00059
00060 TString methodName;
00061 TString methodTitle;
00062 TH1* sig;
00063 TH1* bgd;
00064 TH1* origSigE;
00065 TH1* origBgdE;
00066 TH1* sigE;
00067 TH1* bgdE;
00068 TH1* purS;
00069 TH1* sSig;
00070 TH1* effpurS;
00071 TCanvas* canvas;
00072 TLatex* line1;
00073 TLatex* line2;
00074 TGaxis* rightAxis;
00075 Double_t maxSignificance;
00076
00077 void SetResultHists()
00078 {
00079 TString pname = "purS_" + methodTitle;
00080 TString epname = "effpurS_" + methodTitle;
00081 TString ssigname = "significance_" + methodTitle;
00082
00083 sigE = (TH1*)origSigE->Clone("sigEffi");
00084 bgdE = (TH1*)origBgdE->Clone("bgdEffi");
00085
00086 Int_t nbins = sigE->GetNbinsX();
00087 Double_t low = sigE->GetBinLowEdge(1);
00088 Double_t high = sigE->GetBinLowEdge(nbins+1);
00089 purS = new TH1F(pname, pname, nbins, low, high);
00090 sSig = new TH1F(ssigname, ssigname, nbins, low, high);
00091 effpurS = new TH1F(epname, epname, nbins, low, high);
00092
00093
00094 sigE->SetTitle( Form("Cut efficiencies for %s classifier", methodTitle.Data()) );
00095
00096
00097 TMVAGlob::SetSignalAndBackgroundStyle( sigE, bgdE );
00098 TMVAGlob::SetSignalAndBackgroundStyle( purS, bgdE );
00099 TMVAGlob::SetSignalAndBackgroundStyle( effpurS, bgdE );
00100 sigE->SetFillStyle( 0 );
00101 bgdE->SetFillStyle( 0 );
00102 sSig->SetFillStyle( 0 );
00103 sigE->SetLineWidth( 3 );
00104 bgdE->SetLineWidth( 3 );
00105 sSig->SetLineWidth( 3 );
00106
00107
00108 purS->SetFillStyle( 0 );
00109 purS->SetLineWidth( 2 );
00110 purS->SetLineStyle( 5 );
00111 effpurS->SetFillStyle( 0 );
00112 effpurS->SetLineWidth( 2 );
00113 effpurS->SetLineStyle( 6 );
00114 }
00115
00116 ClassDef(MethodInfo,0)
00117 };
00118
00119 MethodInfo::~MethodInfo()
00120 {
00121 delete sigE;
00122 delete bgdE;
00123 delete purS;
00124 delete sSig;
00125 delete effpurS;
00126 if(gROOT->GetListOfCanvases()->FindObject(canvas))
00127 delete canvas;
00128 }
00129
00130 class StatDialogMVAEffs {
00131
00132 RQ_OBJECT("StatDialogMVAEffs")
00133
00134 public:
00135
00136 StatDialogMVAEffs(const TGWindow* p, Float_t ns, Float_t nb);
00137 virtual ~StatDialogMVAEffs();
00138
00139 void SetFormula(const TString& f) { fFormula = f; }
00140 TString GetFormula();
00141 TString GetLatexFormula();
00142
00143 void ReadHistograms(TFile* file);
00144 void UpdateSignificanceHists();
00145 void DrawHistograms();
00146
00147 void RaiseDialog() { if (fMain) { fMain->RaiseWindow(); fMain->Layout(); fMain->MapWindow(); } }
00148
00149 private:
00150
00151 TGMainFrame *fMain;
00152 Float_t fNSignal;
00153 Float_t fNBackground;
00154 TString fFormula;
00155 TList * fInfoList;
00156
00157 TGNumberEntry* fSigInput;
00158 TGNumberEntry* fBkgInput;
00159
00160 TGHorizontalFrame* fButtons;
00161 TGTextButton* fDrawButton;
00162 TGTextButton* fCloseButton;
00163
00164 Int_t maxLenTitle;
00165
00166 void UpdateCanvases();
00167
00168 public:
00169
00170
00171 void SetNSignal();
00172 void SetNBackground();
00173 void Redraw();
00174 void Close();
00175
00176
00177 void PrintResults( const MethodInfo* info );
00178 };
00179
00180 void StatDialogMVAEffs::SetNSignal()
00181 {
00182 fNSignal = fSigInput->GetNumber();
00183 }
00184
00185 void StatDialogMVAEffs::SetNBackground()
00186 {
00187 fNBackground = fBkgInput->GetNumber();
00188 }
00189
00190 TString StatDialogMVAEffs::GetFormula()
00191 {
00192 TString f = fFormula;
00193 f.ReplaceAll("S","x");
00194 f.ReplaceAll("B","y");
00195 return f;
00196 }
00197
00198 TString StatDialogMVAEffs::GetLatexFormula()
00199 {
00200 TString f = fFormula;
00201 f.ReplaceAll("(","{");
00202 f.ReplaceAll(")","}");
00203 f.ReplaceAll("sqrt","#sqrt");
00204 return f;
00205 }
00206
00207 void StatDialogMVAEffs::Redraw()
00208 {
00209 UpdateSignificanceHists();
00210 UpdateCanvases();
00211 }
00212
00213 void StatDialogMVAEffs::Close()
00214 {
00215 delete this;
00216 }
00217
00218 StatDialogMVAEffs::~StatDialogMVAEffs()
00219 {
00220 if (fInfoList) {
00221 TIter next(fInfoList);
00222 MethodInfo *info(0);
00223 while ( (info = (MethodInfo*)next()) ) {
00224 delete info;
00225 }
00226 delete fInfoList;
00227 fInfoList=0;
00228 }
00229
00230
00231 fSigInput->Disconnect();
00232 fBkgInput->Disconnect();
00233 fDrawButton->Disconnect();
00234 fCloseButton->Disconnect();
00235
00236 fMain->CloseWindow();
00237 fMain->Cleanup();
00238 fMain = 0;
00239 }
00240
00241 StatDialogMVAEffs::StatDialogMVAEffs(const TGWindow* p, Float_t ns, Float_t nb) :
00242 fNSignal(ns),
00243 fNBackground(nb),
00244 fFormula(""),
00245 fInfoList(0),
00246 fSigInput(0),
00247 fBkgInput(0),
00248 fButtons(0),
00249 fDrawButton(0),
00250 fCloseButton(0),
00251 maxLenTitle(0)
00252 {
00253 UInt_t totalWidth = 500;
00254 UInt_t totalHeight = 300;
00255
00256
00257 fMain = new TGMainFrame(p, totalWidth, totalHeight, kMainFrame | kVerticalFrame);
00258
00259 TGLabel *sigLab = new TGLabel(fMain,"Signal events");
00260 fMain->AddFrame(sigLab, new TGLayoutHints(kLHintsLeft | kLHintsTop,5,5,5,5));
00261
00262 fSigInput = new TGNumberEntry(fMain, (Double_t) fNSignal,5,-1,(TGNumberFormat::EStyle) 5);
00263 fSigInput->SetLimits(TGNumberFormat::kNELLimitMin,0,1);
00264 fMain->AddFrame(fSigInput, new TGLayoutHints(kLHintsLeft | kLHintsTop,5,5,5,5));
00265 fSigInput->Resize(100,24);
00266
00267 TGLabel *bkgLab = new TGLabel(fMain, "Background events");
00268 fMain->AddFrame(bkgLab, new TGLayoutHints(kLHintsLeft | kLHintsTop,5,5,5,5));
00269
00270 fBkgInput = new TGNumberEntry(fMain, (Double_t) fNBackground,5,-1,(TGNumberFormat::EStyle) 5);
00271 fBkgInput->SetLimits(TGNumberFormat::kNELLimitMin,0,1);
00272 fMain->AddFrame(fBkgInput, new TGLayoutHints(kLHintsLeft | kLHintsTop,5,5,5,5));
00273 fBkgInput->Resize(100,24);
00274
00275 fButtons = new TGHorizontalFrame(fMain, totalWidth,30);
00276
00277 fCloseButton = new TGTextButton(fButtons,"&Close");
00278 fButtons->AddFrame(fCloseButton, new TGLayoutHints(kLHintsLeft | kLHintsTop));
00279
00280 fDrawButton = new TGTextButton(fButtons,"&Draw");
00281 fButtons->AddFrame(fDrawButton, new TGLayoutHints(kLHintsRight | kLHintsTop,15));
00282
00283 fMain->AddFrame(fButtons,new TGLayoutHints(kLHintsLeft | kLHintsBottom,5,5,5,5));
00284
00285 fMain->SetWindowName("Significance");
00286 fMain->SetWMPosition(0,0);
00287 fMain->MapSubwindows();
00288 fMain->Resize(fMain->GetDefaultSize());
00289 fMain->MapWindow();
00290
00291 fSigInput->Connect("ValueSet(Long_t)","StatDialogMVAEffs",this, "SetNSignal()");
00292 fBkgInput->Connect("ValueSet(Long_t)","StatDialogMVAEffs",this, "SetNBackground()");
00293
00294 fDrawButton->Connect("Clicked()","TGNumberEntry",fSigInput, "ValueSet(Long_t)");
00295 fDrawButton->Connect("Clicked()","TGNumberEntry",fBkgInput, "ValueSet(Long_t)");
00296 fDrawButton->Connect("Clicked()", "StatDialogMVAEffs", this, "Redraw()");
00297
00298 fCloseButton->Connect("Clicked()", "StatDialogMVAEffs", this, "Close()");
00299 }
00300
00301 void StatDialogMVAEffs::UpdateCanvases()
00302 {
00303 if (fInfoList==0) return;
00304 if (fInfoList->First()==0) return;
00305 MethodInfo* info = (MethodInfo*)fInfoList->First();
00306 if ( info->canvas==0 ) {
00307 DrawHistograms();
00308 return;
00309 }
00310 TIter next(fInfoList);
00311 while ( (info = (MethodInfo*)next()) ) {
00312 info->canvas->Update();
00313 info->rightAxis->SetWmax(1.1*info->maxSignificance);
00314 info->canvas->Modified(kTRUE);
00315 info->canvas->Update();
00316 info->canvas->Paint();
00317 }
00318 }
00319
00320 void StatDialogMVAEffs::UpdateSignificanceHists()
00321 {
00322 TFormula f("sigf",GetFormula());
00323 TIter next(fInfoList);
00324 MethodInfo* info(0);
00325 TString cname = "Classifier";
00326 if (cname.Length() > maxLenTitle) maxLenTitle = cname.Length();
00327 TString str = Form( "%*s ( #signal, #backgr.) Optimal-cut S/sqrt(S+B) NSig NBkg EffSig EffBkg",
00328 maxLenTitle, cname.Data() );
00329 cout << "--- " << setfill('=') << setw(str.Length()) << "" << setfill(' ') << endl;
00330 cout << "--- " << str << endl;
00331 cout << "--- " << setfill('-') << setw(str.Length()) << "" << setfill(' ') << endl;
00332 while ((info = (MethodInfo*)next())) {
00333 for (Int_t i=1; i<=info->origSigE->GetNbinsX(); i++) {
00334 Float_t eS = info->origSigE->GetBinContent( i );
00335 Float_t S = eS * fNSignal;
00336 Float_t B = info->origBgdE->GetBinContent( i ) * fNBackground;
00337 info->purS->SetBinContent( i, (S+B==0)?0:S/(S+B) );
00338 info->sSig->SetBinContent( i, f.Eval(S,B) );
00339 info->effpurS->SetBinContent( i, eS*info->purS->GetBinContent( i ) );
00340 }
00341
00342 info->maxSignificance = info->sSig->GetMaximum();
00343 info->sSig->Scale(1/info->maxSignificance);
00344
00345
00346 PrintResults( info );
00347 }
00348 cout << "--- " << setfill('-') << setw(str.Length()) << "" << setfill(' ') << endl << endl;
00349 }
00350
00351 void StatDialogMVAEffs::ReadHistograms(TFile* file)
00352 {
00353 if (fInfoList) {
00354 TIter next(fInfoList);
00355 MethodInfo *info(0);
00356 while ( (info = (MethodInfo*)next()) ) {
00357 delete info;
00358 }
00359 delete fInfoList;
00360 fInfoList=0;
00361 }
00362 fInfoList = new TList;
00363
00364
00365 TIter next(file->GetListOfKeys());
00366 TKey *key(0);
00367 while( (key = (TKey*)next()) ) {
00368
00369 if (!TString(key->GetName()).BeginsWith("Method_")) continue;
00370 if( ! gROOT->GetClass(key->GetClassName())->InheritsFrom("TDirectory") ) continue;
00371
00372 cout << "--- Found directory: " << ((TDirectory*)key->ReadObj())->GetName() << endl;
00373
00374 TDirectory* mDir = (TDirectory*)key->ReadObj();
00375
00376 TIter keyIt(mDir->GetListOfKeys());
00377 TKey *titkey;
00378 while((titkey = (TKey*)keyIt())) {
00379 if( ! gROOT->GetClass(titkey->GetClassName())->InheritsFrom("TDirectory") ) continue;
00380
00381 MethodInfo* info = new MethodInfo();
00382 TDirectory* titDir = (TDirectory *)titkey->ReadObj();
00383
00384 TMVAGlob::GetMethodName(info->methodName,key);
00385 TMVAGlob::GetMethodTitle(info->methodTitle,titDir);
00386 if (info->methodTitle.Length() > maxLenTitle) maxLenTitle = info->methodTitle.Length();
00387 TString hname = "MVA_" + info->methodTitle;
00388
00389 cout << "--- Classifier: " << info->methodTitle << endl;
00390
00391 info->sig = dynamic_cast<TH1*>(titDir->Get( hname + "_S" ));
00392 info->bgd = dynamic_cast<TH1*>(titDir->Get( hname + "_B" ));
00393 info->origSigE = dynamic_cast<TH1*>(titDir->Get( hname + "_effS" ));
00394 info->origBgdE = dynamic_cast<TH1*>(titDir->Get( hname + "_effB" ));
00395 if (info->origSigE==0 || info->origBgdE==0) { delete info; continue; }
00396
00397 info->SetResultHists();
00398 fInfoList->Add(info);
00399 }
00400 }
00401 return;
00402 }
00403
00404 void StatDialogMVAEffs::DrawHistograms()
00405 {
00406
00407 Int_t countCanvas = 0;
00408
00409
00410 const Int_t width = 600;
00411 Int_t signifColor = TColor::GetColor( "#00aa00" );
00412
00413 TIter next(fInfoList);
00414 MethodInfo* info(0);
00415 while ( (info = (MethodInfo*)next()) ) {
00416
00417
00418 TCanvas *c = new TCanvas( Form("canvas%d", countCanvas+1),
00419 Form("Cut efficiencies for %s classifier",info->methodTitle.Data()),
00420 countCanvas*50+200, countCanvas*20, width, Int_t(width*0.78) );
00421 info->canvas = c;
00422
00423
00424 c->SetGrid(1);
00425 c->SetTickx(0);
00426 c->SetTicky(0);
00427
00428 TStyle *TMVAStyle = gROOT->GetStyle("Plain");
00429 TMVAStyle->SetLineStyleString( 5, "[32 22]" );
00430 TMVAStyle->SetLineStyleString( 6, "[12 22]" );
00431
00432 c->SetTopMargin(.2);
00433
00434
00435 info->effpurS->SetTitle("Cut efficiencies and optimal cut value");
00436 if (info->methodTitle.Contains("Cuts")) {
00437 info->effpurS->GetXaxis()->SetTitle( "Signal Efficiency" );
00438 }
00439 else {
00440 info->effpurS->GetXaxis()->SetTitle( TString("Cut value applied on ") + info->methodTitle + " output" );
00441 }
00442 info->effpurS->GetYaxis()->SetTitle( "Efficiency (Purity)" );
00443 TMVAGlob::SetFrameStyle( info->effpurS );
00444
00445 c->SetTicks(0,0);
00446 c->SetRightMargin ( 2.0 );
00447
00448 info->effpurS->SetMaximum(1.1);
00449 info->effpurS->Draw("histl");
00450
00451 info->purS->Draw("samehistl");
00452
00453
00454 info->sigE->Draw("samehistl");
00455 info->bgdE->Draw("samehistl");
00456
00457 info->sSig->SetLineColor( signifColor );
00458 info->sSig->Draw("samehistl");
00459
00460
00461 info->effpurS->Draw( "sameaxis" );
00462
00463
00464 TLegend *legend1= new TLegend( c->GetLeftMargin(), 1 - c->GetTopMargin(),
00465 c->GetLeftMargin() + 0.4, 1 - c->GetTopMargin() + 0.12 );
00466 legend1->SetFillStyle( 1 );
00467 legend1->AddEntry(info->sigE,"Signal efficiency","L");
00468 legend1->AddEntry(info->bgdE,"Background efficiency","L");
00469 legend1->Draw("same");
00470 legend1->SetBorderSize(1);
00471 legend1->SetMargin( 0.3 );
00472
00473 TLegend *legend2= new TLegend( c->GetLeftMargin() + 0.4, 1 - c->GetTopMargin(),
00474 1 - c->GetRightMargin(), 1 - c->GetTopMargin() + 0.12 );
00475 legend2->SetFillStyle( 1 );
00476 legend2->AddEntry(info->purS,"Signal purity","L");
00477 legend2->AddEntry(info->effpurS,"Signal efficiency*purity","L");
00478 legend2->AddEntry(info->sSig,"S / #sqrt{S+B}","L");
00479 legend2->Draw("same");
00480 legend2->SetBorderSize(1);
00481 legend2->SetMargin( 0.3 );
00482
00483
00484 TLine* effline = new TLine( info->sSig->GetXaxis()->GetXmin(), 1, info->sSig->GetXaxis()->GetXmax(), 1 );
00485 effline->SetLineWidth( 1 );
00486 effline->SetLineColor( 1 );
00487 effline->Draw();
00488
00489
00490 TLatex tl;
00491 tl.SetNDC();
00492 tl.SetTextSize( 0.033 );
00493 Int_t maxbin = info->sSig->GetMaximumBin();
00494 info->line1 = tl.DrawLatex( 0.15, 0.23, Form("For %1.0f signal and %1.0f background", fNSignal, fNBackground));
00495 tl.DrawLatex( 0.15, 0.19, "events the maximum S / #sqrt{S+B} is");
00496 info->line2 = tl.DrawLatex( 0.15, 0.15, Form("%3.4f when cutting at %3.4f",
00497 info->maxSignificance,
00498 info->sSig->GetXaxis()->GetBinCenter(maxbin)) );
00499
00500 if (info->methodTitle.Contains("Cuts")){
00501 tl.DrawLatex( 0.13, 0.77, "Method Cuts provides a bundle of cut selections, each tuned to a");
00502 tl.DrawLatex(0.13, 0.74, "different signal efficiency. Shown is the purity for each cut selection.");
00503 }
00504
00505 c->Update();
00506
00507
00508 info->rightAxis = new TGaxis(c->GetUxmax(), c->GetUymin(),
00509 c->GetUxmax(), c->GetUymax(),0,1.1*info->maxSignificance,510,"+L");
00510 info->rightAxis->SetLineColor ( signifColor );
00511 info->rightAxis->SetLabelColor( signifColor );
00512 info->rightAxis->SetTitleColor( signifColor );
00513
00514 info->rightAxis->SetTitleSize( info->sSig->GetXaxis()->GetTitleSize() );
00515 info->rightAxis->SetTitle( "Significance" );
00516 info->rightAxis->Draw();
00517
00518 c->Update();
00519
00520
00521 const Bool_t Save_Images = kTRUE;
00522
00523 if (Save_Images) {
00524 TMVAGlob::imgconv( c, Form("plots/mvaeffs_%s", info->methodTitle.Data()) );
00525 }
00526 countCanvas++;
00527 }
00528 }
00529
00530 void StatDialogMVAEffs::PrintResults( const MethodInfo* info )
00531 {
00532 Int_t maxbin = info->sSig->GetMaximumBin();
00533 if (info->line1 !=0 )
00534 info->line1->SetText( 0.15, 0.23, Form("For %1.0f signal and %1.0f background", fNSignal, fNBackground));
00535
00536 if (info->line2 !=0 ) {
00537 info->line2->SetText( 0.15, 0.15, Form("%3.4f when cutting at %3.4f", info->maxSignificance,
00538 info->sSig->GetXaxis()->GetBinCenter(maxbin)) );
00539 }
00540
00541 TString opt = Form( "%%%is: (%%9.8g,%%9.8g) %%9.4f %%10.6g %%8.7g %%8.7g %%8.4g %%8.4g",
00542 maxLenTitle );
00543 cout << "--- "
00544 << Form( opt.Data(),
00545 info->methodTitle.Data(), fNSignal, fNBackground,
00546 info->sSig->GetXaxis()->GetBinCenter( maxbin ),
00547 info->maxSignificance,
00548 info->origSigE->GetBinContent( maxbin )*fNSignal,
00549 info->origBgdE->GetBinContent( maxbin )*fNBackground,
00550 info->origSigE->GetBinContent( maxbin ),
00551 info->origBgdE->GetBinContent( maxbin ) )
00552 << endl;
00553 }
00554
00555 void mvaeffs( TString fin = "TMVA.root",
00556 Bool_t useTMVAStyle = kTRUE, TString formula="S/sqrt(S+B)" )
00557 {
00558 TMVAGlob::Initialize( useTMVAStyle );
00559
00560 StatDialogMVAEffs* gGui = new StatDialogMVAEffs(gClient->GetRoot(), 1000, 1000);
00561
00562 TFile* file = TMVAGlob::OpenFile( fin );
00563 gGui->ReadHistograms(file);
00564 gGui->SetFormula(formula);
00565 gGui->UpdateSignificanceHists();
00566 gGui->DrawHistograms();
00567 gGui->RaiseDialog();
00568 }