mvaeffs.C

Go to the documentation of this file.
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 // this macro plots the signal and background efficiencies
00034 // as a function of the MVA cut.
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       // chop off useless stuff
00094       sigE->SetTitle( Form("Cut efficiencies for %s classifier", methodTitle.Data()) );
00095          
00096       // set the histogram style
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       // the purity and quality
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    // slots
00171    void SetNSignal(); //*SIGNAL*
00172    void SetNBackground(); //*SIGNAL*
00173    void Redraw(); //*SIGNAL*
00174    void Close(); //*SIGNAL*
00175 
00176    // result printing
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    // main frame
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       // update the text in the lower left corner
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    // search for the right histograms in full list of keys
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    // counter variables
00407    Int_t countCanvas = 0;
00408 
00409    // define Canvas layout here!
00410    const Int_t width = 600;   // size of canvas
00411    Int_t signifColor = TColor::GetColor( "#00aa00" );
00412 
00413    TIter next(fInfoList);
00414    MethodInfo* info(0);
00415    while ( (info = (MethodInfo*)next()) ) {
00416 
00417       // create new canvas
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       // draw grid
00424       c->SetGrid(1);
00425       c->SetTickx(0);
00426       c->SetTicky(0);
00427 
00428       TStyle *TMVAStyle = gROOT->GetStyle("Plain"); // our style is based on Plain
00429       TMVAStyle->SetLineStyleString( 5, "[32 22]" );
00430       TMVAStyle->SetLineStyleString( 6, "[12 22]" );
00431          
00432       c->SetTopMargin(.2);
00433       
00434       // and the signal purity and quality
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       // overlay signal and background histograms
00454       info->sigE->Draw("samehistl");
00455       info->bgdE->Draw("samehistl");
00456 
00457       info->sSig->SetLineColor( signifColor );
00458       info->sSig->Draw("samehistl");
00459 
00460       // redraw axes
00461       info->effpurS->Draw( "sameaxis" );
00462 
00463       // Draw legend               
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       // line to indicate maximum efficiency
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       // print comments
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       // add comment for Method cuts
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       // save canvas to file
00505       c->Update();
00506 
00507       // Draw second axes
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       // switches
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 }

Generated on Tue Jul 5 15:25:45 2011 for ROOT_528-00b_version by  doxygen 1.5.1