Saving a canvas' sub-pad. TPad::SaveAs() bug?

Hello,

I am trying to save each pad of a divided canvas as an image. I have created a little demo script to show my problem.

[code]Int_t pad_save(){
TList graphs ;
TMultiGraph * mg = 0;

for(int i = 0; i<4;i++){
TH1F *h1 = new TH1F(Form(“h%d”,i),Form(“histo%d from a gaussian”,i), 100, -3, 3);
h1->FillRandom(“gaus”, 10000);
mg = new TMultiGraph();
mg->Add( new TGraphErrors(h1),“lp”);
graphs.Add( mg );
}

TCanvas * c = new TCanvas();
c->Divide(2,2);

for(int i = 0; i<4;i++){
c->cd(i+1);
mg = (TMultiGraph*)graphs.At(i);
mg->Draw(“a”);
gPad->SaveAs(Form(“test%d.png”,i));
}

return(0);
}
[/code]

Error output is :

[code]Processing pad_save.cxx…
Info in TPad::Print: png file test0.png has been created
Warning in TASImage::PutPixel: Out of range width=463 x=551, height=274 y=253
Warning in TASImage::PutPixel: Out of range width=463 x=555, height=274 y=251
Warning in TASImage::PutPixel: Out of range width=463 x=558, height=274 y=254
Warning in TASImage::PutPixel: Out of range width=463 x=562, height=274 y=249
Warning in TASImage::PutPixel: Out of range width=463 x=565, height=274 y=250

Info in TPad::Print: png file test1.png has been created

*** Break *** segmentation violation

===========================================================
There was a crash (#6 0xb79e570d in SigHandler ()).
This is the entire stack trace of all threads:

#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb758e6b3 in waitpid () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7533b8b in ?? () from /lib/tls/i686/cmov/libc.so.6
#3 0xb79e0d8d in TUnixSystem::Exec ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#4 0xb79e8eee in TUnixSystem::StackTrace ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#5 0xb79e563b in TUnixSystem::DispatchSignals ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#6 0xb79e570d in SigHandler ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#7 0xb79de0e4 in sighandler ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#8 0xb7a10d11 in textinput::TerminalConfigUnix::HandleSignal ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#9 0xb7a11156 in (anonymous namespace)::TerminalConfigUnix__handleSignal ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#10
#11 0xa1cff7fa in TASImage::DrawLineInternal ()
from /home/whit/root_build/root-v5-34/lib/libASImage.so
#12 0xa1cffc98 in TASImage::DrawPolyLine ()
from /home/whit/root_build/root-v5-34/lib/libASImage.so
#13 0xa3c48b60 in TImageDump::DrawPS ()
from /home/whit/root_build/root-v5-34/lib/libPostscript.so
#14 0xb5dae5f8 in TPad::PaintPolyLine ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#15 0xa1b39a04 in TGraphPainter::PaintGraph ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#16 0xa1b28bd6 in TGraphPainter::PaintGraphSimple ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#17 0xa1b2bb02 in TGraphPainter::PaintGraphErrors ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#18 0xa1b3470a in TGraphPainter::PaintHelper ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#19 0xb65afc86 in TGraph::Paint ()
from /home/whit/root_build/root-v5-34/lib/libHist.so
#20 0xb664c883 in TMultiGraph::Paint ()
from /home/whit/root_build/root-v5-34/lib/libHist.so
#21 0xb5db65c6 in TPad::Paint ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#22 0xb5dc0b4e in TPad::Print ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#23 0xb5db7fa3 in TPad::SaveAs ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#24 0xb7b2fc42 in G__G__Base2_10_0_48 ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#25 0xb6f04d5a in Cint::G__ExceptionWrapper ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#26 0xb6f1ab70 in G__exec_asm ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#27 0xb6ffd3ef in G__exec_loop ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#28 0xb6ff9aae in G__exec_statement ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#29 0xb6f99c63 in G__interpret_func ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#30 0xb6f8500a in G__getfunction ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#31 0xb6f589a1 in G__getitem ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#32 0xb6f62116 in G__getexpr ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#33 0xb6f690a6 in G__calc_internal ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#34 0xb7005bd5 in G__process_cmd ()
from /home/whit/root_build/root-v5-34/lib/libCint.so
#35 0xb7997833 in TCint::ProcessLine ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#36 0xb799744f in TCint::ProcessLineSynch ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#37 0xb78d7b86 in TApplication::ExecuteFile ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#38 0xb78d813c in TApplication::ProcessFile ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#39 0xb78d4aea in TApplication::ProcessLine ()
from /home/whit/root_build/root-v5-34/lib/libCore.so
#40 0xb779a4ac in TRint::Run ()
from /home/whit/root_build/root-v5-34/lib/libRint.so
#41 0x08048e63 in main ()

The lines below might hint at the cause of the crash.
If they do not help you then please submit a bug report at
http://root.cern.ch/bugs. Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.

#11 0xa1cff7fa in TASImage::DrawLineInternal ()
from /home/whit/root_build/root-v5-34/lib/libASImage.so
#12 0xa1cffc98 in TASImage::DrawPolyLine ()
from /home/whit/root_build/root-v5-34/lib/libASImage.so
#13 0xa3c48b60 in TImageDump::DrawPS ()
from /home/whit/root_build/root-v5-34/lib/libPostscript.so
#14 0xb5dae5f8 in TPad::PaintPolyLine ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#15 0xa1b39a04 in TGraphPainter::PaintGraph ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#16 0xa1b28bd6 in TGraphPainter::PaintGraphSimple ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#17 0xa1b2bb02 in TGraphPainter::PaintGraphErrors ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#18 0xa1b3470a in TGraphPainter::PaintHelper ()
from /home/whit/root_build/root-v5-34/lib/libHistPainter.so
#19 0xb65afc86 in TGraph::Paint ()
from /home/whit/root_build/root-v5-34/lib/libHist.so
#20 0xb664c883 in TMultiGraph::Paint ()
from /home/whit/root_build/root-v5-34/lib/libHist.so
#21 0xb5db65c6 in TPad::Paint ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#22 0xb5dc0b4e in TPad::Print ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so
#23 0xb5db7fa3 in TPad::SaveAs ()
from /home/whit/root_build/root-v5-34/lib/libGpad.so

Function pad_save() busy flag cleared
[/code]

It produces the first image just fine. The second image is missing the axes, then it crashes.
I am using 5.34/13.

Is this a bug in TPad::SaveAs()?
Also, calling TPad::Print() does the same thing.

Of course a work around is to create a new TCanvas for each TMultiGraph and redraw and then do TCanvas::SaveAs() but this is clunky and TPad::SaveAs() should work. Right?

Happy New Year!

Cheers,
Whit

SaveAs() or Print() are meant to work on a TCanvas… not really on sub-pads…

Hi,

I would propose to make these two methods fully abstract in TPad if we are not meant to use them. If they are available and implemented, it is a contract with the users that they can use them safely.

Cheers,
Barth

Sorry, I have just realized that what I said makes no sense. We obviously can’t make TPad fully abstract.

Still, I think that having a method in a class means that users can use it. Can’t we fix the implementation in TPad ?

Agreed. I will have a look. The thing is that TCanvas is a TPad. The printing code was put in TPad… May be it should have been put in TCanvas. Anyway you are right I will check.

Great ! thanks

Also using PDF or PS does not work properly on pure TPad.
So I added a protection in TPad::Print() for 5.34 and trunk to avoid this crash with png and the wrong
output with pdf/ps. Thanks for reporting.

Any news about this?
Is it possible to save a single sub-pad of a TCanvas?

1 Like

No… see the comment about PDF and PS.

Hi,
Is this feature considered as a request (in JIRA)?
I think it should be, I also would like to save sub-pads as images.

Andrey

There is one already:
https://sft.its.cern.ch/jira/browse/ROOT-7633

1 Like

It looks like the most recent activity on the bug report referenced was 2 years ago and referring to root 6.06/00.

I just spent a day trying to figure out why this wasn’t working and using root 6.18/02. At the very least, some comment should be put into the TPad::SaveAs and TPad:Print reference documentation informing users not to expect these to work for non-TCanvas pads. Very frustrating to find I wasted all day on a “well-known” bug!!

I am sorry to ear to lost a day. I think the mistake is to provide the SaveAs entry from the Pad menu as SaveAs works only on the full canvas. The best is to suppress the SaveAas entry from that menu. Thanks to have pop up again this issue.