Bug in TCanvas::SaveAs C-macro

Hi,

I noticed since quite some time, that there seem to be some bugs in saving a canvas to a C macro. I attached two pictures to show what I found:

The upper plot shows the original canvas stored as .png, the lower plot shows the .png stored after re-running the .C macro exported from the original canvas. The bugs are

a) The TLegend is not rebuild correctly. The problem obviously is in the code fragment

   TLegendEntry *entry=leg->AddEntry("","entry 1","PL");
   entry->SetLineColor(2);
   entry->SetLineStyle(1);
   ...
   entry=leg->AddEntry("","entry 2","PL");  
   entry->SetLineColor(4);
   ...

Replacing the new assignment to the existing pointer entry with a completely new TLegendEntry (like TLegendEntry *entry2 ...) doesn’t fix the problem. Using entry=leg->AddEntry(graph,"entry 2","PL"); does, but since the pointer graph is also used multiple times, in only fixes the problem for the last entry. This issue is pretty nasty in case you have many graphs and need to fix everything by hand afterwards.

b) Not so obviously to be noticed, the size of the canvas recreated by the .C macro is larger in height than the original one (in this case by 20 pixels). The reason seems to be that in the original canvas the event status bar is shown, in the re-created one it is not, but both windows have the same size. This enlarges the effective area of the re-created canvas by the area of the status bar.



Please read tips for efficient and successful posting and posting code

ROOT Version: 6.16/00
Platform: Not Provided
Compiler: Not Provided


Can you provide the faulty macro ?

here it is:

original.C (5.1 KB)

this macro gives me:

When I run it and save it as a .C file and run back the saved .C file I get the same.

Sorry for the confusion, the above is the exported macro that was saved from the original canvas. The original macro needs comprehensive data input and looks like

TString path="/some/path/to/data";

void anamissres()
{
  vector<double> ecm = {2.3,2.5,3.0,3.5,4.0,4.3,4.5,5.0,5.5};
  
  TGraph *gim = new TGraph();
  TGraph *gmm = new TGraph();
  
  gim->SetMarkerStyle(20);
  gim->SetMarkerSize(1.0);
  gim->SetMarkerColor(4);
  gim->SetLineColor(4);
  
  gmm->SetMarkerStyle(21);
  gmm->SetMarkerSize(1.0);
  gmm->SetMarkerColor(2);
  gmm->SetLineColor(2);
  
  for (auto x:ecm) {
    TString fname = Form("%sllbar%d_auto_0_ana.root", path.Data(), int(x*10));
    TFile *f = new TFile(fname);
    TTree *t = (TTree*) f->Get("ntp0");
    
    t->Draw("xm*1000>>h1","xmct","goff");
    TH1F *h1 = (TH1F*) gDirectory->Get("h1");
    h1->Fit("gaus");
    double rms_im = h1->GetFunction("gaus")->GetParameter(2);
   
   
    t->Draw("mmiss*1000>>h2","xmct","goff");
    TH1F *h2 = (TH1F*) gDirectory->Get("h2");
    h2->Fit("gaus");
    double rms_mm = h2->GetFunction("gaus")->GetParameter(2);
    
    gim->SetPoint(gim->GetN(), x, rms_im);
    gmm->SetPoint(gmm->GetN(), x, rms_mm);
  }
  
  gmm->Draw("ALP");
  gmm->GetHistogram()->SetMinimum(1);
  gmm->GetHistogram()->SetMaximum(400);
  gmm->GetHistogram()->SetTitle(";x;y");
  gim->Draw("LP same");
  
  gPad->SetLogy();
  gPad->SetGridy();
  
  TLegend *leg = new TLegend(0.2,0.75,0.45,0.9);
  leg->AddEntry(gmm, "entry 1", "PL");
  leg->AddEntry(gim, "entry 2", "PL");
  
  leg->Draw();
}

I need datallbar23_auto_0_ana.root

Here is a simpler version having the same problem:

If I run it, and then run the output macro canvas_bugdemo.C, I see the same effect.

void bugdemo()
{
  TCanvas *c1 = new TCanvas("c1","c1",20,20,500,500);
  
  vector<double> ecm = {2.3,2.5,3.0,3.5,4.0,4.3,4.5,5.0,5.5};
  double y1[] = {1,2,3,4,5,6,7,8,9};
  double y2[] = {2,4,6,8,10,12,14,16,18};
  
  TGraph *gim = new TGraph;
  TGraph *gmm = new TGraph;
  
  gim->SetMarkerStyle(20);
  gim->SetMarkerSize(1.0);
  gim->SetMarkerColor(4);
  gim->SetLineColor(4);
  
  gmm->SetMarkerStyle(21);
  gmm->SetMarkerSize(1.0);
  gmm->SetMarkerColor(2);
  gmm->SetLineColor(2);

  int i=0;
  for (int i=0;i<9;i++) {    
    gim->SetPoint(i, ecm[i], y1[i]);
    gmm->SetPoint(i, ecm[i], y2[i]);
  }
  
  c1->cd();
  
  gmm->Draw("ALP");
  gmm->GetHistogram()->SetMinimum(1);
  gmm->GetHistogram()->SetMaximum(400);
  gmm->GetHistogram()->SetTitle(";x;y");
  gim->Draw("LP same");
  
  gPad->SetLogy();
  gPad->SetGridy();
  
  TLegend *leg = new TLegend(0.2,0.75,0.45,0.9);
  leg->AddEntry(gmm, "entry 1", "PL");
  leg->AddEntry(gim, "entry 2", "PL");
  
  leg->Draw();
  
  c1->Update();
  c1->SaveAs("canvas_bugdemo.C");
}

Thanks for the reproducer.
I will investigate

Interesting to note: If I create the TGraphs by

  double x1[] = {2.3,2.5,3.0,3.5,4.0,4.3,4.5,5.0,5.5};
  double y1[] = {1,2,3,4,5,6,7,8,9};
  double y2[] = {2,4,6,8,10,12,14,16,18};
  
  TGraph *gim = new TGraph(9, x1, y1);
  TGraph *gmm = new TGraph(9, x1, y2);

the problem vanishes. In the exported .C macro the TLegend creation looks different:

   TLegend *leg = new TLegend(0.2,0.75,0.45,0.9,NULL,"brNDC");
   leg->SetBorderSize(1);
   leg->SetLineColor(1);
   leg->SetLineStyle(1);
   leg->SetLineWidth(1);
   leg->SetFillColor(0);
   leg->SetFillStyle(1001);
   TLegendEntry *entry=leg->AddEntry("Graph0","entry 1","PL");
   entry->SetLineColor(2);
   ...
   entry=leg->AddEntry("Graph1","entry 2","PL");
   entry->SetLineColor(4);
   ...
   leg->Draw();

There the entries have a reference to the TGraph names.

Yes that is the workaround.
When saving by address it is hard to find them when creating the C macro

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.