Accessing TLeaf inside TBranch inside TTree inside Folder

Hi!

I’ve been having issues while trying to access data from a root file with the following structure:
rootFileStructure
There are 4 branches inside one tree inside an event folder, and there are 100 event folders.

I don’t exactly know how to do that, however I wrote the following code:

TFile *myFile = new TFile(fileName,"READ");
	TBranch *myBranch;
	TLeaf *myLeaf;
	Float_t energy = 0;
	TString event = "";
	// loop through 100 events
	for(Int_t i = 0; i < 100; i++){
		cout << "Event" << i << endl;
		TTree *myTree = (TTree*)myFile->Get(Form("Event%d/fTreeR",i));
		cout << "flag0\n";
		if(!myTree){
			continue;
		}
		cout << "flag1\n";
		//myTree->Print();
		myTree->SetBranchAddress("AliFOCALClusterItr.fEnergy",&energy);
		//myBranch = (TBranch*)myTree->Branch("AliFOCALClusterItr");
		//myTree->SetBranchAddress("AliFOCALClusterItr.fEnergy",&energy);
		cout << "flag2\n";
		cout << "There were " << myTree->GetEntries() << " entries in the TTree.\n";
		cout << "flag3\n";
		for(int j = 0; j < myTree->GetEntries(); j++){
			cout << "flag4\n";
			myTree->GetEntry(j);
			cout << "flag5\n";
			cout << "energy = " << energy << endl;
		}
		cout << "i = " << i << endl;
		delete myTree;
	}
	
	
	
	//myTree->SetBranchAddress("AliFOCALClusterItr.fEnergy",&energy);
	//TBranch *branch = myTree->GetBranch("AliFOCALClusterItr.fEnergy");
	//branch->SetAdress(&energy);
	//TH1F *hist = new TH1F("Energy","AliFOCALClusterItr.fEnergy copy");
	
	
	
	myFile->Close();

I put some flags to try to figure out what was happening, and the following is what I get in the terminal:

So there are 2 problems:
i - how do I access the content of a leaf inside a branch inside the tree? And do I need to loop through this leaf data or is there a way of accessing the objet inside the leaf (e.g. a TH1F histogram)
ii - the events are read until the 29th, when a break segmentation violation occurs. Is this event 29 empty, is there a memory leakage in my code or what is going on?

As you can see, I’m a bit lost here and I appreciate any help.
Thank you already!

_ROOT Version: 6.24/06
_Platform: Ubuntu 20.04

Hi @Christian ,
first of all a couple of clarifications:

a) TTrees are datasets. You can think of them as sets of rows and columns, where the columns are called “branches”.
b) The distinction between leaves and branches is a bit of an advanced detail that you probably don’t need to care about for what you want to do. You can ignore leaves, and you can think of a branch as one column in your dataset, that takes a different value for each entry of the dataset.
c) What you call “event” is really a different TTree. Typically “event” is a synonym for “entry”. But I see that your ROOT file really contains different sub-directories where each is called “Event0”, “Event1”, etc, so the terminology might cause some confusion.

So your file has a bit of a surprising structure, where you have N sub-directories, each containing 1 dataset with 1 row. I would normally expect instead a single dataset (i.e. one TTree) with N entries/rows.

About the actual crash, as far as I can tell it happens at this line:

TTree *myTree = (TTree*)myFile->Get(Form("Event%d/fTreeR",i));

when i == 29. Do you have a sub-directory called Event29 in the file? Does it contain a TTree called fTreeR?

These sections of the manual might be useful: Trees - ROOT, ROOT files - ROOT

Cheers,
Enrico

P.S.
About your concrete questions:

i) you are doing it correctly: you extract the tree from the file, then call SetBranchAddress to bind the values of a branch/column to a certain variable, then when you call GetEntry the variable is updated with the value of the branch/column for the given entry/row

About “accessing the object inside the leaf”, is AliFOCALClusterItr a histogram? If not, there is no histogram.

ii) Hard to say with just this information. It needs debugging, see above

1 Like

Thanks for the reply and the clarifications @eguiraud.

I thought I had to somehow first find the branch, in this case AliFOCALClusterItr, and then the leaf, in this case fEnergy. But as I think you are saying, I can consider the branch directly as AliFOCALClusterItr.fEnergy, right?

I erased some things in my code, which I thought were irrelevant, now the code is

TFile *myFile = new TFile(fileName,"READ");
	Float_t energy = 0;
	// loop through 100 events
	for(Int_t i = 0; i < 100; i++){
		cout << "Event" << i << endl;
		TTree *myTree = (TTree*)myFile->Get(Form("Event%d/fTreeR",i));
		cout << "flag0\n";
		if(!myTree){
			continue;
		}
		cout << "flag1\n";
		myTree->SetBranchAddress("AliFOCALClusterItr.fEnergy",&energy);
		cout << "flag2\n";
		cout << "There were " << myTree->GetEntries() << " entries in the TTree.\n";
		cout << "flag3\n";
		for(int j = 0; j < myTree->GetEntries(); j++){
			cout << "flag4\n";
			myTree->GetEntry(j);
			cout << "flag5\n";
			cout << "energy = " << energy << endl;
		}
		cout << "i = " << i << endl;
		delete myTree;
	}
	
	myFile->Close();

And I don’t know why, now what I get in the terminal is

But I know for a fact that the branch is not empty as I open with a TBrowser:

About the concrete questions…I think I’ve been doing it correctly then?
If so, I have another doubt. myTree->GetEntries() gets me that the TTree has only one entry. But as you can see in the TBrowser, the branch has 3 entries. When you say I should do myTree->GetEntry(j), how would I get the other entries of the branch rather than the other entries of the TTree?

Thank you again,
Christian.

Maybe showing the full output of myTree->Print(); for Event1/fTreeR can help.
If instead of fEnergy you print fUniqueID, for instance, do you get what you expect?

That is probably because the branch type is not float, but array of floats (i.e. for every entry in the TTree, AliFOCALClusterItr.fEnergy contains multiple numbers), and you are reading only the first value of the array. A tree->Print() like @dastudillo suggests would confirm.

To actually debug the crash, the cause of which is still unclear, you can use gdb, e.g. by running the script as gdb --args root.exe -l -b -q yourprogram.C+g. Note the usage of root.exe instead of root and the +g after the script file name, which triggers compilation with debug symbols. You might have to add a few #include directives for the program to compile correctly. Here are some resources on using the debugger – just running the program and then calling backtrace at the point of crash should show the line at which the crash happens and then you can inspect the variable values to see what’s wrong.

If that fails you can share a minimal self-contained reproducer with us (including input data) so we can take a look.

Cheers,
Enrico

Thanks @dastudillo and @eguiraud for the help.

That is probably because the branch type is not float, but array of floats (i.e. for every entry in the TTree, AliFOCALClusterItr.fEnergy contains multiple numbers), and you are reading only the first value of the array. A tree->Print() like @dastudillo suggests would confirm.
I believe you two are right:

I think I figured it out, since my code runs fine now. I believe the mistake was trying to access the TTree entries starting from indice i = 0 in my for loop. What I did (and what is working now) was to start from i = 1. Is this a rule of thumb? Should every entry in a TTree start from 1 and not 0?

I also still have a problem which is: how exactly can I access all the value from the array of floats? Is there maybe a branch->GetEntry(j) type something? Or maybe I should set the address of the branch to an array? If the last one is the case, how do I get the entries?

Thanks again,
Christian.

No. Tree entries start from 0; so entry number being zero is not the problem.

1 Like

Yes that’s how you do it. How to get the number of entries depends on th type of AliFOCALClusterItr I think. @pcanal could you tell just from that snippet of TTree::Print?

Thank you @eguiraud and @dastudillo for the help. The branch I was looking at actually had many different types, however I found out that the right way of accessing my data is, in my case, using a class from this other software I’m using together and not inspecting the branches manually.

Anyway, you actually helped me visualizing in a concrete way how to read this root file structures. The ROOT user guide explains plenty however not everything.

Thanks again,
Christian.

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