#include "TMVA/variablesMultiClass.h" // this macro plots the distributions of the different input variables // used in TMVA (e.g. running TMVAnalysis.C). Signal and Background are overlayed. // input: - Input file (result from TMVA), // - normal/decorrelated/PCA // - use of TMVA plotting TStyle void TMVA::variablesMultiClass(TString dataset, TString fin , TString dirName , TString title, Bool_t /* isRegression */, Bool_t useTMVAStyle ) { TString outfname = dirName; TString tmp = dirName; tmp.ReplaceAll("InputVariables_",""); outfname.ToLower(); outfname.ReplaceAll( "input", "" ); // set style and remove existing canvas' TMVAGlob::Initialize( useTMVAStyle ); // obtain shorter histogram title TString htitle = title; htitle.ReplaceAll("variables ","variable"); htitle.ReplaceAll("and target(s)",""); htitle.ReplaceAll("(training sample)",""); // checks if file with name "fin" is already open, and if not opens one TFile* file = TMVAGlob::OpenFile( fin ); TDirectory* dir = (TDirectory*)file->GetDirectory(dataset.Data())->Get( dirName ); if (dir==0) { cout << "No information about " << title << " available in directory " << dirName << " of file " << fin << endl; return; } dir->cd(); // how many plots are in the directory? Int_t noPlots = TMVAGlob::GetNumberOfInputVariables( dir ); // define Canvas layout here! // default setting Int_t xPad; // no of plots in x Int_t yPad; // no of plots in y Int_t width; // size of canvas Int_t height; switch (noPlots) { case 1: xPad = 1; yPad = 1; width = 550; height = 0.90*width; break; case 2: xPad = 2; yPad = 1; width = 600; height = 0.50*width; break; case 3: xPad = 3; yPad = 1; width = 900; height = 0.4*width; break; case 4: xPad = 2; yPad = 2; width = 600; height = width; break; default: xPad = 3; yPad = 2; width = 800; height = 0.55*width; break; } Int_t noPadPerCanv = xPad * yPad ; // counter variables Int_t countCanvas = 0; Int_t countPad = 0; // loop over all objects in directory TCanvas* canv = 0; Bool_t createNewFig = kFALSE; TIter next(dir->GetListOfKeys()); std::vector varnames(TMVAGlob::GetInputVariableNames(dir)); std::vector classnames(TMVAGlob::GetClassNames(dir)); std::vector::iterator variter = varnames.begin(); std::vector::iterator classiter = classnames.begin(); /* std::vector::const_iterator variter = varnames.begin(); std::cout << "Available variables:" << std::endl; while(variter != varnames.end()){ std::cout << *variter << std::endl; variter++; } std::vector::const_iterator classiter = classnames.begin(); std::cout << "Available classes:" << std::endl; while(classiter != classnames.end()){ std::cout << *classiter << std::endl; classiter++; } */ variter = varnames.begin(); for(; variter!=varnames.end(); ++variter){ //create new canvas if (countPad%noPadPerCanv==0) { ++countCanvas; canv = new TCanvas( Form("canvas%d", countCanvas), title, countCanvas*50+50, countCanvas*20, width, height ); canv->Divide(xPad,yPad); canv->Draw(); } TPad* cPad = (TPad*)canv->cd(countPad++%noPadPerCanv+1); classiter = classnames.begin(); TObjArray hists; for(; classiter!=classnames.end(); ++classiter){ //assemble histogram names TString hname(*variter + "__" + *classiter + "_" + tmp); TH1 *hist = (TH1*)dir->Get(hname); //cout << "Looking for histgram " << hname << endl; if (hist == NULL) { cout << "ERROR!!! couldn't find " << *variter << " histogram for class " << *classiter << endl; //exit(1); return; } hists.Add(hist); } // this is set but not stored during plot creation in MVA_Factory //TMVAGlob::SetSignalAndBackgroundStyle(((TH1*)hists[0]), ((TH1*)hists[1])); TMVAGlob::SetMultiClassStyle( &hists ); ((TH1*)hists.First())->SetTitle( TString( htitle ) + ": " + *variter ); TMVAGlob::SetFrameStyle( ((TH1*)hists.First()), 1.2 ); // normalise all histograms and find maximum Float_t histmax = -1; for(Int_t i=0; iGetMaximum() > histmax) histmax = ((TH1*)hists[i])->GetMaximum(); } // finally plot and overlay Float_t sc = 1.1; if (countPad == 1) sc = 1.3; ((TH1*)hists.First())->SetMaximum( histmax*sc ); ((TH1*)hists.First())->Draw( "hist" ); cPad->SetLeftMargin( 0.17 ); ((TH1*)hists.First())->GetYaxis()->SetTitleOffset( 1.70 ); for(Int_t i=1; iDraw("histsame"); TString ytit = TString("(1/N) ") + ((TH1*)hists[i])->GetYaxis()->GetTitle(); ((TH1*)hists[i])->GetYaxis()->SetTitle( ytit ); // histograms are normalised } // Draw legend if (countPad == 1) { TLegend *legend= new TLegend( cPad->GetLeftMargin(), 1-cPad->GetTopMargin()-.15, cPad->GetLeftMargin()+.4, 1-cPad->GetTopMargin() ); legend->SetFillStyle(1); classiter = classnames.begin(); for(Int_t i=0; iAddEntry(((TH1*)hists[i]),*classiter,"F"); } legend->SetBorderSize(1); legend->SetMargin( 0.3 ); legend->Draw("same"); } // redraw axes ((TH1*)hists.First())->Draw("sameaxis"); // text for overflows Int_t nbin = ((TH1*)hists.First())->GetNbinsX(); Double_t dxu = ((TH1*)hists.First())->GetBinWidth(0); Double_t dxo = ((TH1*)hists.First())->GetBinWidth(nbin+1); TString uoflow = ""; classiter = classnames.begin(); for(Int_t i=0; iGetBinContent(0)!=0 || ((TH1*)hists[i])->GetBinContent(nbin+1)!=0){ uoflow += *classiter; uoflow += Form( " U/O-flow: %.1f / %.1f %%", ((TH1*)hists[i])->GetBinContent(0)*dxu*100, ((TH1*)hists[i])->GetBinContent(nbin+1)*dxo*100); } } TText* t = new TText( 0.98, 0.14, uoflow ); t->SetNDC(); t->SetTextSize( 0.040 ); t->SetTextAngle( 90 ); t->AppendPad(); // save canvas to file if (countPad%noPadPerCanv==0) { TString fname = dataset+Form( "/plots/%s_c%i", outfname.Data(), countCanvas ); TMVAGlob::plot_logo(); TMVAGlob::imgconv( canv, fname ); createNewFig = kFALSE; } else { createNewFig = kTRUE; } } if (createNewFig) { TString fname = dataset+Form( "/plots/%s_c%i", outfname.Data(), countCanvas ); TMVAGlob::plot_logo(); TMVAGlob::imgconv( canv, fname ); createNewFig = kFALSE; } return; }