How to save TCanvas in TTree correctly?

Hello!

I want to encapsulate my code in classes, because I will have a lot of code in project.
I am not expert in OOP, so I have some difficulties.

Usually I save variable in tree using this method:

int main(int argc, char *argv[])
{
	TApplication theApp("theApp", &argc, argv);
	gROOT->SetBatch(kTRUE);
	
	TFile *f_tree = new TFile("D:\\Data_work\\test_folder\\test_write.root", "RECREATE");
	TTree tree("t1", "Parser tree");

	double x;
	tree.Branch("x", &x, "x/D");
	for (int i = 0; i < 100; i++)
	{
		
		x = i;
		tree.Fill();

		if (i % 100 == 0)
			cout << "i = " << i << endl;
	}
	
		tree.Write();
	f_tree->Close();
	
	
	cout << "all is ok" << endl;
	system("pause");
	theApp.Terminate();
	theApp.Run();

	return 0;
}

But I can’t use the same method to save TCanvas, because copy constructor is private for this class

int main(int argc, char *argv[])
{
	TApplication theApp("theApp", &argc, argv);
	gROOT->SetBatch(kTRUE);
	
	TFile *f_tree = new TFile("D:\\Data_work\\test_folder\\test_write.root", "RECREATE");
	TTree tree("t1", "Parser tree");
	
	TCanvas canv;
	tree.Branch("canvas", "TCanvas", &canv);
	for (int i = 0; i < 100; i++)
	{		
		Canv canv_from_obj;
		canv = canv_from_obj.GetCanv(); // copy constructor is private
		tree.Fill();

		if (i % 100 == 0)
			cout << "i = " << i << endl;
	}
	
		tree.Write();
	f_tree->Close();
	
	
	cout << "all is ok" << endl;
	system("pause");
	theApp.Terminate();
	theApp.Run();

	return 0;
}

Canv.h :

#pragma once

#include "TCanvas.h"

class Canv
{
public:
	Canv();
	~Canv();
	TCanvas &GetCanv();
private:
	TCanvas canv;
};

Canv.cpp:

#include "Canv.h"

Canv::Canv() : canv("c", "c", 0, 0, 190, 100)
{
}


Canv::~Canv()
{
}

TCanvas &Canv::GetCanv()
{
	return canv;
}

If I move “tree.Branch” inside loop I have problem in my project: .root becomes too big.
I.e. (file size / N_events) becomes bigger and bigger with inctreasing N_events.
I tried to reproduce this effect, but test code work without this problem:

int main(int argc, char *argv[])
{
	TApplication theApp("theApp", &argc, argv);
	gROOT->SetBatch(kTRUE);
	
	TFile *f_tree = new TFile("D:\\Data_work\\test_folder\\test_write.root", "RECREATE");
	TTree tree("t1", "Parser tree");
	
		for (int i = 0; i < 100; i++)
	{
		Canv canv_from_obj;
		tree.Branch("canvas", "TCanvas", &( canv_from_obj.GetCanv() ) );
		tree.Fill();

		if (i % 100 == 0)
			cout << "i = " << i << endl;
	}
	
		tree.Write();
	f_tree->Close();
	
	
	cout << "all is ok" << endl;
	system("pause");
	theApp.Terminate();
	theApp.Run();

	return 0;
}

So I wrote another code with “tree.Branch” inside loop.
This code for “double x”, but in real project I have this problem for “TCanvas” too:

int main(int argc, char *argv[])
{
	TApplication theApp("theApp", &argc, argv);
	gROOT->SetBatch(kTRUE);
	
	TFile *f_tree = new TFile("D:\\Data_work\\test_folder\\test_write.root", "RECREATE");
	TTree tree("t1", "Parser tree");
	
		for (int i = 0; i < 1000; i++)
	{
		double x;
		x = i;
		tree.Branch("x", &x, "x/D");

		if (i % 100 == 0)
			cout << "i = " << i << endl;		
		
		tree.Fill();
	}
	
		tree.Write();
	f_tree->Close();
	
	
	cout << "all is ok" << endl;
	system("pause");
	theApp.Terminate();
	theApp.Run();

	return 0;
}

In table N - number of events in loop
Size - size of file
(Size / N) value is strange.

N Size, Byte Size / N, Byte
10 6620 662
100 28277 282.77
1000 860717 860.717
10000 84871897 8487.1897

As I undestood from this code I should not write “tree.Branch” inside loop.
So, could you explain how to save TCanvas to TTree if I get TCanvas by reference from class method?

Best regards, Vladislav.

Hi,

Can I ask you why you want to save canvases in a tree? Why don’t you simply save them in a ROOT file?

Cheers, Bertrand.

Hello!

I have data from detector.
When trigger is activated ADC writes voltage vs time from several channels.
One activation is one event.
I want to add some cut conditions for each event.
So I create tree and add cut conditions as branches.
At the same time each event in tree have to have raw data, not only cut conditions.
I chose way to save all information in TCanvas object.

Do you think it is better to save data in tree as simple arrays and use canvas only to display final result?

Best regards, Vladislav.

Hi Vladislav,

You can mix trees and canvases (and other objects) in the same ROOT files. And yes, I would advise to save your data in a tree (or save your histograms in a file), and only use canvas to display them. There are many example in the tutorials, and check also the ROOT primer

Cheers, Bertrand.

Hello!

But do you know how to solve problem mentioned in the first post?

Best regards, Vladislav.

Well, yes: don’t try to save TCanvas in a TTree. And please look at the ROOT tutorials and courses, the TTree specific Howtos and the the ROOT primer

Cheers, Bertrand.