network.C

Go to the documentation of this file.
00001 #include "TArrow.h"
00002 #include "TEllipse.h"
00003 #include "TPaveLabel.h"
00004 #include "TCanvas.h"
00005 #include "TH2F.h"
00006 #include "TFile.h"
00007 #include "TString.h"
00008 #include "TDirectory.h"
00009 #include "TKey.h"
00010 #include "TText.h"
00011 
00012 #include "tmvaglob.C"
00013 
00014 // this macro prints out a neural network generated by MethodMLP graphically
00015 // @author: Matt Jachowski, jachowski@stanford.edu
00016 
00017 TFile* Network_GFile = 0;
00018 
00019 static Int_t c_DarkBackground = TColor::GetColor( "#6e7a85" );
00020 
00021 void     draw_layer_labels( Int_t nLayers );
00022 void     draw_layer       ( TCanvas* c, TH2F* h, Int_t iHist, Int_t nLayers, Double_t maxWeight );
00023 void     draw_synapse     ( Double_t cx1, Double_t cy1, Double_t cx2, Double_t cy2,
00024                             Double_t  rad1, Double_t rad2, Double_t weightNormed );
00025 TString* get_var_names    ( Int_t nVars );
00026 
00027 Bool_t MovieMode = kFALSE;
00028 
00029 void draw_network( TFile* f, TDirectory* d, const TString& hName = "weights_hist", 
00030                    Bool_t movieMode = kFALSE, const TString& epoch = "" )
00031 {
00032    Bool_t __PRINT_LOGO__ = kTRUE;
00033    Network_GFile = f;
00034 
00035    MovieMode = movieMode;
00036    if (MovieMode) c_DarkBackground = TColor::GetColor( "#707F7F" );
00037 
00038    // create canvas
00039    TStyle* TMVAStyle = gROOT->GetStyle("TMVA"); // the TMVA style
00040    Int_t canvasColor = TMVAStyle->GetCanvasColor(); // backup
00041    TMVAStyle->SetCanvasColor( c_DarkBackground );
00042 
00043    Int_t titleFillColor = TMVAStyle->GetTitleFillColor();
00044    Int_t titleTextColor = TMVAStyle->GetTitleTextColor();
00045    Int_t borderSize     = TMVAStyle->GetTitleBorderSize();
00046 
00047    TMVAStyle->SetTitleFillColor( c_DarkBackground );
00048    TMVAStyle->SetTitleTextColor( TColor::GetColor( "#FFFFFF" ) );
00049    TMVAStyle->SetTitleBorderSize( 0 );
00050    
00051    static Int_t icanvas = -1;
00052    Int_t ixc = 100 + (icanvas)*40;
00053    Int_t iyc =   0 + (icanvas+1)*20;   
00054    if (MovieMode) ixc = iyc = 0;
00055    TString canvasnumber =  Form( "c%i", icanvas );
00056    TString canvastitle = Form("Neural Network Layout for: %s", d->GetName());
00057    TCanvas* c = new TCanvas( canvasnumber, canvastitle, 
00058                              ixc, 0 + (icanvas+1)*20, 1000, 650  );
00059    icanvas++;
00060    TIter next = d->GetListOfKeys();
00061    TKey *key( 0 );
00062    Int_t numHists = 0;
00063 
00064    // loop over all histograms with hName in name again
00065    next.Reset();
00066    Double_t maxWeight = 0;
00067    // find max weight
00068    while ((key = (TKey*)next())) {
00069 
00070       TClass *cl = gROOT->GetClass(key->GetClassName());
00071       if (!cl->InheritsFrom("TH2F")) continue;    
00072  
00073       TH2F* h = (TH2F*)key->ReadObj();    
00074       if (!h) {
00075          cout << "Big troubles in \"draw_network\" (1)" << endl;
00076          exit(1);
00077       }
00078       if (TString(h->GetName()).Contains( hName )){
00079          numHists++;
00080  
00081          Int_t n1 = h->GetNbinsX();
00082          Int_t n2 = h->GetNbinsY();
00083          for (Int_t i = 0; i < n1; i++) {
00084             for (Int_t j = 0; j < n2; j++) {
00085                Double_t weight = TMath::Abs(h->GetBinContent(i+1, j+1));
00086                if (maxWeight < weight) maxWeight = weight;
00087             }
00088          }
00089       }
00090    }
00091    if (numHists == 0) {
00092       cout << "Error: could not find histograms" << endl;
00093       //exit(1);
00094    }
00095 
00096    // draw network
00097    next.Reset();
00098    //cout << "check4a" << endl;
00099 
00100    Int_t count = 0;
00101    while ((key = (TKey*)next())) {
00102       //cout << "check4b" << endl;
00103 
00104       TClass *cl = gROOT->GetClass(key->GetClassName());
00105       if (!cl->InheritsFrom("TH2F")) continue;    
00106       //cout << "check4c" << endl;
00107 
00108       TH2F* h = (TH2F*)key->ReadObj();    
00109       //cout << (h->GetName()) << endl;
00110       if (!h) {
00111          cout << "Big troubles in \"draw_network\" (2)" << endl;
00112          exit(1);
00113       }
00114       //cout << (h->GetName()) << endl;
00115       if (TString(h->GetName()).Contains( hName )) {
00116          //cout << (h->GetName()) << endl;
00117          draw_layer(c, h, count++, numHists+1, maxWeight);
00118       }
00119       //cout << "check4d" << endl;
00120 
00121    }
00122    draw_layer_labels(numHists+1);
00123 
00124    // add epoch
00125    if (MovieMode) {
00126       TText* t = new TText();            
00127       t->SetTextSize( 0.04 );
00128       t->SetTextColor( 0 );
00129       t->SetTextAlign( 31 );      
00130       t->DrawTextNDC( 1 - c->GetRightMargin(), 1 - c->GetTopMargin() - 0.033, 
00131                       Form( "Epoch: %s", epoch.Data() ) );
00132    }
00133 
00134    // ============================================================
00135    if (__PRINT_LOGO__) TMVAGlob::plot_logo();
00136    // ============================================================  
00137 
00138    c->Update();
00139    if (MovieMode) {
00140       // save to file
00141       TString dirname  = "movieplots";
00142       TString foutname = dirname + "/" + hName;
00143       foutname.Resize( foutname.Length()-5 );
00144       foutname.ReplaceAll("epochmonitoring___","");
00145       foutname += ".gif";
00146       
00147       cout << "storing file: " << foutname << endl;
00148       c->Print(foutname);     
00149       c->Clear();
00150       delete c;
00151    }
00152    else {
00153       TString fname = "plots/network";
00154       TMVAGlob::imgconv( c, fname );
00155    }
00156 
00157    // reset global style changes so that it does not affect other plots
00158    TMVAStyle->SetCanvasColor    ( canvasColor );
00159    TMVAStyle->SetTitleFillColor ( titleFillColor );
00160    TMVAStyle->SetTitleTextColor ( titleTextColor );
00161    TMVAStyle->SetTitleBorderSize( borderSize );
00162 
00163 }
00164 
00165 void draw_layer_labels(Int_t nLayers)
00166 {
00167    const Double_t LABEL_HEIGHT = 0.032;
00168    const Double_t LABEL_WIDTH  = 0.20;
00169    Double_t effWidth = 0.8*(1.0-LABEL_WIDTH)/nLayers;
00170    Double_t height = 0.8*LABEL_HEIGHT;
00171    Double_t margY = LABEL_HEIGHT - height;
00172 
00173    for (Int_t i = 0; i < nLayers; i++) {
00174       TString label = Form("Layer %i", i);
00175       if (i == nLayers-1) label = "Output layer";
00176       Double_t cx = i*(1.0-LABEL_WIDTH)/nLayers+1.0/(2.0*nLayers)+LABEL_WIDTH;
00177       Double_t x1 = cx-0.8*effWidth/2.0;
00178       Double_t x2 = cx+0.8*effWidth/2.0;
00179       Double_t y1 = margY;
00180       Double_t y2 = margY + height;
00181 
00182       TPaveLabel *p = new TPaveLabel(x1, y1, x2, y2, label+"", "br");
00183       p->SetFillColor(gStyle->GetTitleFillColor());
00184       p->SetTextColor(gStyle->GetTitleTextColor());
00185       p->SetFillStyle(1001);
00186       p->SetBorderSize( 0 );
00187       p->Draw();
00188    }
00189 }
00190 
00191 void draw_input_labels(Int_t nInputs, Double_t* cy, 
00192                        Double_t rad, Double_t layerWidth)
00193 {
00194    const Double_t LABEL_HEIGHT = 0.04;
00195    const Double_t LABEL_WIDTH  = 0.20;
00196    Double_t width = LABEL_WIDTH + (layerWidth-4*rad);
00197    Double_t margX = 0.01;
00198    Double_t effHeight = 0.8*LABEL_HEIGHT;
00199 
00200    TString *varNames = get_var_names(nInputs);
00201    if (varNames == 0) exit(1);
00202 
00203    TString input;
00204 
00205    for (Int_t i = 0; i < nInputs; i++) {
00206       if (i != nInputs-1) input = varNames[i];
00207       else                input = "Bias node";
00208       Double_t x1 = margX;
00209       Double_t x2 = margX + width;
00210       Double_t y1 = cy[i] - effHeight;
00211       Double_t y2 = cy[i] + effHeight;
00212 
00213       TText* t = new TText();
00214       t->SetTextColor(gStyle->GetTitleTextColor());
00215       t->SetTextAlign(31);
00216       t->SetTextSize(LABEL_HEIGHT);
00217       if (i == nInputs-1) t->SetTextColor( TColor::GetColor( "#AFDCEC" ) );
00218       t->DrawText( x2, y1+0.018, input + " :");
00219    }
00220 
00221    delete[] varNames;
00222 }
00223 
00224 TString* get_var_names( Int_t nVars )
00225 {
00226    const TString directories[6] = { "InputVariables_NoTransform",
00227                                     "InputVariables_DecorrTransform",
00228                                     "InputVariables_PCATransform",
00229                                     "InputVariables_Id",
00230                                     "InputVariables_Norm",
00231                                     "InputVariables_Deco"};
00232    
00233    TDirectory* dir = 0;
00234    for (Int_t i=0; i<6; i++) {
00235       dir = (TDirectory*)Network_GFile->Get( directories[i] );
00236       if (dir != 0) break;
00237    }
00238    if (dir==0) {
00239       cout << "*** Big troubles in macro \"network.C\": could not find directory for input variables, "
00240            << "and hence could not determine variable names --> abort" << endl;
00241       return 0;
00242    }
00243    dir->cd();
00244 
00245    TString* vars = new TString[nVars];
00246    Int_t ivar = 0;
00247 
00248    // loop over all objects in directory
00249    TIter next(dir->GetListOfKeys());
00250    TKey* key = 0;
00251    while ((key = (TKey*)next())) {
00252       if (key->GetCycle() != 1) continue;
00253 
00254       if (!TString(key->GetName()).Contains("__S") &&
00255           !TString(key->GetName()).Contains("__r") &&
00256           !TString(key->GetName()).Contains("Regression"))
00257          continue;
00258       if (TString(key->GetName()).Contains("target"))
00259          continue;
00260 
00261       // make sure, that we only look at histograms
00262       TClass *cl = gROOT->GetClass(key->GetClassName());
00263       if (!cl->InheritsFrom("TH1")) continue;
00264       TH1 *sig = (TH1*)key->ReadObj();
00265       TString hname = sig->GetTitle();
00266       
00267       vars[ivar] = hname; ivar++;
00268 
00269       if (ivar > nVars-1) break;
00270    }      
00271    
00272    if (ivar != nVars-1) { // bias layer and targets are also in nVars counts
00273       cout << "*** Troubles in \"network.C\": did not reproduce correct number of "
00274            << "input variables: " << ivar << " != " << nVars << endl;
00275    }
00276 
00277    return vars;
00278 }
00279 
00280 void draw_activation(TCanvas* c, Double_t cx, Double_t cy, 
00281                      Double_t radx, Double_t rady, Int_t whichActivation)
00282 {
00283    TImage *activation = NULL;
00284 
00285    switch (whichActivation) {
00286    case 0:
00287       activation = TImage::Open("sigmoid-small.png");
00288       break;
00289    case 1:
00290       activation = TImage::Open("line-small.png");
00291       break;
00292    default:
00293       cout << "Activation index " << whichActivation << " is not known." << endl;
00294       cout << "You messed up or you need to modify network.C to introduce a new "
00295            << "activation function (and image) corresponding to this index" << endl;
00296    }
00297 
00298    if (activation == NULL) {
00299       cout << "Could not create an image... exit" << endl;
00300       return;
00301    }
00302   
00303    activation->SetConstRatio(kFALSE);
00304 
00305    radx *= 0.7;
00306    rady *= 0.7;
00307    TString name = Form("activation%f%f", cx, cy);
00308    TPad* p = new TPad(name+"", name+"", cx-radx, cy-rady, cx+radx, cy+rady);
00309 
00310    p->Draw();
00311    p->cd();
00312 
00313    activation->Draw();
00314    c->cd();
00315 }
00316 
00317 void draw_layer(TCanvas* c, TH2F* h, Int_t iHist, 
00318                 Int_t nLayers, Double_t maxWeight)
00319 {
00320    const Double_t MAX_NEURONS_NICE = 12;
00321    const Double_t LABEL_HEIGHT = 0.03;
00322    const Double_t LABEL_WIDTH  = 0.20;
00323    Double_t ratio = ((Double_t)(c->GetWindowHeight())) / c->GetWindowWidth();
00324    Double_t rad, cx1, *cy1, cx2, *cy2;
00325 
00326    // this is the smallest radius that will still display the activation images
00327    rad = 0.04*650/c->GetWindowHeight();
00328 
00329    Int_t nNeurons1 = h->GetNbinsX();
00330    cx1 = iHist*(1.0-LABEL_WIDTH)/nLayers + 1.0/(2.0*nLayers) + LABEL_WIDTH;
00331    cy1 = new Double_t[nNeurons1];
00332 
00333    Int_t nNeurons2 = h->GetNbinsY();
00334    cx2 = (iHist+1)*(1.0-LABEL_WIDTH)/nLayers + 1.0/(2.0*nLayers) + LABEL_WIDTH;
00335    cy2 = new Double_t[nNeurons2];
00336 
00337    Double_t effRad1 = rad;
00338    if (nNeurons1 > MAX_NEURONS_NICE)
00339       effRad1 = 0.8*(1.0-LABEL_HEIGHT)/(2.0*nNeurons1);
00340 
00341    for (Int_t i = 0; i < nNeurons1; i++) {
00342       cy1[nNeurons1-i-1] = i*(1.0-LABEL_HEIGHT)/nNeurons1 + 1.0/(2.0*nNeurons1) + LABEL_HEIGHT;
00343 
00344       if (iHist == 0) {
00345 
00346          TEllipse *ellipse = new TEllipse( cx1, cy1[nNeurons1-i-1], 
00347                                            effRad1*ratio, effRad1, 0, 360, 0 );
00348          ellipse->SetFillColor(TColor::GetColor( "#fffffd" ));
00349          ellipse->SetFillStyle(1001);
00350          ellipse->Draw();
00351 
00352          if (i == 0) ellipse->SetLineColor(9);
00353 
00354          if (nNeurons1 > MAX_NEURONS_NICE) continue;
00355 
00356          Int_t whichActivation = 0;
00357          if (iHist==0 || iHist==nLayers-1 || i==0) whichActivation = 1;
00358          draw_activation(c, cx1, cy1[nNeurons1-i-1], 
00359                          rad*ratio, rad, whichActivation);
00360       }
00361    }
00362 
00363    if (iHist == 0) draw_input_labels(nNeurons1, cy1, rad, (1.0-LABEL_WIDTH)/nLayers);
00364 
00365    Double_t effRad2 = rad;
00366    if (nNeurons2 > MAX_NEURONS_NICE)
00367       effRad2 = 0.8*(1.0-LABEL_HEIGHT)/(2.0*nNeurons2);
00368 
00369    for (Int_t i = 0; i < nNeurons2; i++) {
00370       cy2[nNeurons2-i-1] = i*(1.0-LABEL_HEIGHT)/nNeurons2 + 1.0/(2.0*nNeurons2) + LABEL_HEIGHT;
00371 
00372       TEllipse *ellipse = 
00373          new TEllipse(cx2, cy2[nNeurons2-i-1], effRad2*ratio, effRad2, 0, 360, 0);
00374       ellipse->SetFillColor(TColor::GetColor( "#fffffd" ));
00375       ellipse->SetFillStyle(1001);
00376       ellipse->Draw();
00377 
00378       if (i == 0 && nNeurons2 > 1) ellipse->SetLineColor(9);
00379 
00380       if (nNeurons2 > MAX_NEURONS_NICE) continue;
00381 
00382       Int_t whichActivation = 0;
00383       if (iHist+1==0 || iHist+1==nLayers-1 || i==0) whichActivation = 1;
00384       draw_activation(c, cx2, cy2[nNeurons2-i-1], rad*ratio, rad, whichActivation);
00385    }
00386 
00387    for (Int_t i = 0; i < nNeurons1; i++) {
00388       for (Int_t j = 0; j < nNeurons2; j++) {
00389          draw_synapse(cx1, cy1[i], cx2, cy2[j], effRad1*ratio, effRad2*ratio,
00390                       h->GetBinContent(i+1, j+1)/maxWeight);
00391       }
00392    }
00393 
00394    delete [] cy1;
00395    delete [] cy2;
00396 }
00397 
00398 void draw_synapse(Double_t cx1, Double_t cy1, Double_t cx2, Double_t cy2,
00399                   Double_t  rad1, Double_t rad2, Double_t weightNormed)
00400 {
00401    const Double_t TIP_SIZE   = 0.01;
00402    const Double_t MAX_WEIGHT = 8;
00403    const Double_t MAX_COLOR  = 100;  // red
00404    const Double_t MIN_COLOR  = 60;   // blue
00405 
00406    if (weightNormed == 0) return;
00407 
00408    //   gStyle->SetPalette(100, NULL);
00409 
00410    TArrow *arrow = new TArrow(cx1+rad1, cy1, cx2-rad2, cy2, TIP_SIZE, ">");
00411    arrow->SetFillColor(1);
00412    arrow->SetFillStyle(1001);
00413    arrow->SetLineWidth((Int_t)(TMath::Abs(weightNormed)*MAX_WEIGHT+0.5));
00414    arrow->SetLineColor((Int_t)((weightNormed+1.0)/2.0*(MAX_COLOR-MIN_COLOR)+MIN_COLOR+0.5));
00415    arrow->Draw();
00416 }
00417 
00418 // input: - Input file (result from TMVA),
00419 //        - use of TMVA plotting TStyle
00420 void network( TString fin = "TMVA.root", Bool_t useTMVAStyle = kTRUE )
00421 {
00422    // set style and remove existing canvas'
00423    TMVAGlob::Initialize( useTMVAStyle );
00424 
00425    // checks if file with name "fin" is already open, and if not opens one
00426    TFile* file = TMVAGlob::OpenFile( fin );  
00427    TIter next(file->GetListOfKeys());
00428    TKey *key(0);
00429    while( (key = (TKey*)next()) ) {      
00430       if (!TString(key->GetName()).BeginsWith("Method_MLP")) continue;
00431       if( ! gROOT->GetClass(key->GetClassName())->InheritsFrom("TDirectory") ) continue;
00432 
00433       cout << "--- Found directory: " << ((TDirectory*)key->ReadObj())->GetName() << endl;
00434 
00435       TDirectory* mDir = (TDirectory*)key->ReadObj();
00436 
00437       TIter keyIt(mDir->GetListOfKeys());
00438       TKey *titkey;
00439       while((titkey = (TKey*)keyIt())) {
00440         if( ! gROOT->GetClass(titkey->GetClassName())->InheritsFrom("TDirectory") ) continue;
00441 
00442         TDirectory* dir = (TDirectory *)titkey->ReadObj();
00443         dir->cd();  
00444         TList titles;
00445         UInt_t ni = TMVAGlob::GetListOfTitles( dir, titles );
00446         if (ni==0) {
00447            cout << "No titles found for Method_MLP" << endl;
00448            return;
00449         }
00450         draw_network( file, dir );
00451       }
00452    }
00453 
00454    return;
00455 }
00456 

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