Writing Data to TLeaf

Hi everyone

I was trying to write data from a vector into a ROOT file. I would like data arranged in TTrees subdivided into a varying number of TBranch objects. Each TBranch should contain 5 TLeaf objects. Each TLeaf is just a single number. Do you think this is possible?

I I have added a code below that is not quite the same as one I am working with, but should demonstrate what I am trying to do.

for(i = 0; i < 10; i++){

	TTree *fevent = new TTree("output_name", "output_name"); //Name the TTree that will hold a single complete event
	
	for(j = 1; j < 13; j++){ //Loop over 12 NaI detectors
	
		output_name = "NAID";
		nameformat << j; //Name the detector branch NAID + number of the detector
		output_name += nameformat.str();
		nameformat.str("");
		
		TBranch* fdetector = fevent->Branch(output_name, &Events[j], "bunch_number/I:movie_number/I:det_number/I:ToF/I:amplitude/I"); //Declare a TBranch that will be used to output a single detector event
	
		TLeaf* bunch_number = new TLeaf(fdetector, "dummyvar", "dummyvar/I"); //event bunch
		TLeaf* movie_number = new TLeaf(fdetector, "dummyvar2", "dummyvar2/I"); //event movie
		TLeaf* det_number = new TLeaf(fdetector, "dummyvar3", "dummyvar3/I"); //event det number
		TLeaf* ToF = new TLeaf(fdetector, "dummyvar4", "dummyvar4/I"); //event tof
		TLeaf* amplitude = new TLeaf(fdetector, "dummyvar5", "dummyvar5/I"); //event amplitude
	
		dummyvar = Events[j];
		dummyvar2 = Events[j + 1];
		dummyvar3 = Events[j + 2];
		dummyvar4 = Events[j + 3];
		dummyvar5 = Events[j + 4];
			
		j += 5;
			
	       fdetector->Fill();
	}
	
	fevent->Fill();
}

Hi,

before diving in technical details, perhaps it can be useful to understand better your usecase. Why wouldn’t a tree with 5 branches or a TNtuple work for you?

Cheers,
Danilo

Thanks for the reply! My plan was as follows. I have data broken up into experimental runs with various settings. I was hoping to have an output structure where each run corresponds to a single TFile, and each correlated event corresponds to a TTree, filled with TBranches of all the detectors that fired in that event. Each TBranch would have 5 TLeaves that correspond to various properties of each detector.

I think that such a data structure would be the most clear visually to a person analyzing it. If I skip TLeaves and use TBranches, then I would end up with a number of TBranches N = 5 * number of detectors. I think this will be annoying for the end-user to look at and manipulate. Same goes for the TNtuple option.

Hopefully this clarifies my thinking a bit. I am open to other options, as I am very new to ROOT, but this has been my thinking so far.

Hi,

thanks for the clarification. I think it is not per se annoying to have a flat data structure. On the contrary, it is a huge advantage. You will have N*5 branches but with clear names which are self-explanatory. All this is possible because your data model is simple enough not to require links among its components.
Said that, if the aforementioned scenario is still not convincing for you, your goal can be achieved with simple structs with 5 data members in each branch.

Cheers,
Danilo

1 Like

Thanks for the quick reply! I see your point. I will try to get TLeaf structure working some more, but if that doesn’t appear to work, I will use TBranches. Thanks for the advice!

As for TLeaves, I am a bit confused how I should intialize and fill everything (in particular I struggle understanding how to allocate memory addresses for TBranch so that TLeaves are filled correctly). For a struct E, would it be something like this:

for(i = 0; i < E.finalvalue;i++){

TBranch* bname = new TBranch(“name”, &E.firstvalue, “leaf1/I:/leaf2/I:/leaf3/I:/leaf4/I:/leaf5/I”);
TLeaf* leaf1 = new TLeaf(bname, &E.firstvalue, “E.firstvalue/I”);
TLeaf* leaf2 = new TLeaf(bname, &E.secondvalue, “E.secondvalue/I”);
…
bname->Fill();
}

Again, I am very new to ROOT, sorry if all of this is really stupid/obvious. Again, thanks for all the help!

You don’t need to call any new TLeaf at all if I understand you correctly.

Just do:

struct ElementsInBranch {
    Int_t leaf1, leaf2, leaf3, leaf4, leaf5;
};
...

ElementsInBranch e;
auto branch = tree->Branch("nameOfNewBranch", &e, 
                           "leaf1/I:/leaf2/I:/leaf3/I:/leaf4/I:/leaf5/I");

e.leaf1 = 1; e.leaf2 = 4; ...
branch->Fill();
1 Like

Thanks for the reply, it appears to work! Help much appreciated.

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