How to save a TCanvas?


I try to save a TCanvas in a TFil e. But I have this problem :

TCanvas tc;
TPaveText tp(0.,0.,0.5,0.5,“ndc”);
tp.Draw(); // here on canvas, only one TPaveText is drawn
tc.Draw(); // even if I call again and again tp.Draw() or tc.Draw()

// But if I save tp and tc in a TFile :
TFile tf(“t.root”,“recreate”);

// and then I load them from an other TFile
TFile tf2(“t.root”);;
// getting canvas
TCanvas * ptc = ( TCanvas *) tf2.Get(“c1”);

// getting paveText
TPaveText * ptp = (TPaveText * ) tf2.Get(“TPave”);

// I would like to draw them
ptc->Draw(); // draw a canvas with a TPaveText
ptp->Draw(); // draw an other TPaveText on ptc :exclamation:

:question: I don’t understand why my TPaveText is duplicated once it has been read from a TFile.

Thanks for your attention

I do not understand your question. It is normal that you get 2 TPaveText.
When saving the canvas, all objects inside the canvas are saved too.
You do not need to save separately the objects in the canvas.


Thanks for your reply Rene.

Hi Rene

Pierre is my trainee on this projet. First of all we are using ROOT 5.10 on a Linux box running Mandriva 2006 (kernel 2.6 and gcc 4.01).

Actually the problem we have is the following.
We have a class call Graph which has an embedded TGraph, TLegend, TPaveText and its own TCanvas. TPaveText and TLegend are required by our users who may need to know (and display) under which conditions the graph has been created (data to plot the graph are accessed through a database).
Since we want users to add their own TArrows, TLine, TLatex… objects on the embedded TCanvas (using the toolbar), when saving the Graph we want to save the whole TCanvas as well. In this project, a Graph is more than merely a plot: it should contain all relevant infos. Here is a simplified version of what we would like to do:

Class Graph : public TNamed
void Draw(Option_t* drawOption) {
// simplified version of the actual code
if (myCanvas_) myCanvas_->Draw();
if (myGraph_) myGraph_->Draw(drawOption);
if (myLegend_) myLegend_->Draw();
if (myPaveText_) myPaveText_->Draw();
TPaveText* myPaveText_;
TGraph* myGraph_;
TLegend* myLegend_;
TCanvas* myCanvas_;

ClassDef(Graph, 1)

When we save it into a file and later on reload it, we have the problem mentionned by Pierre. I though that eventhough the embedded TCanvas contains the same pointer that, let’s say myGraph_, the I/O system was able to save only one instance of the TGraph refered to and rebuild everything according. So after reading back the Graph object, myGraph_ and the pointer inside TCanvas should have the same value.

Why in that case TPaveText would be drawn twice if we call the method TGraph::Draw method twice?



If you save an instance of your class Graph, you should get only one copy
of each object inside the file. It could be that you have a problem
with your default constructor. Are you creating the sub-objects directly
in the constructor or via some calls?
The pointers must be set to null in the default constructor.
If you cannot solve the problem, i will need a short file with Graph.h, Graph.cxx and a small script creating/filling/writing the Graph object.

Note that I still do not understand why you need this class. You only lose
compared to a normal TCanvas (you need your class to visualize the canvas!)
If you have a TCanvas *c1 , filled with TPavText, etc, you can do

TFile f("mycanvas.root","recreate"); c1->Write(); then in a different session (or same session) do

TFile f("mycanvas.root"( TCanvas *c1 = (TCanvas*)f.Get("canvas name") c1->Draw(); or from TBrowser, directly click on the canvas to draw it.


Hi René

I found the problem. It was a misunderstanding of the I/O system. There were comments like " //-> " after variables to be saved. We removed them and now it seems to work now.

The reason why I am not using a TCanvas directly is because the class is meant to draw data taken from a database. After that, users can choose, using a GUI, to display or not the legend, or the parameters selected in the database. Once the graph is displayed, they can decide to change the units of the axis through a non trivial transformation taken from the database, or switch the axis, and so on…The canvas is just here to display data manipulations and we save it because users may want to save data non taken from the database (such as their own comments …).

Anyway it seems to work now.