Saving trees with branches into another tree as branches

I have 6 trees saved in a file, each with the same number of entries and 4 with the same structure of branches. Given this, I am attempting to create a new file with 3 trees. 2 of the trees are just copies of the 2 trees that have different structures from the other 4. I want the third tree to have 4 branches, with each of these branches containing one of the original tree’s branches.

I can copy the 2 trees that are different from the other 4 just fine, but I am not finding direction from the TTree or TBranch Class Reference pages on how to create a branch with a structure of branches. The most I can find is there is a TBranch constructor to create a branch as the child of another branch. After creating the 4 branches, would I then use this particular TBranch constructor to add child branches with the same leaf structures of the 4 tree’s branches? Would I then have to iterate over each event in the 4 trees and then fill the 4 branches, or is there something like CloneTree() that I could do?

Perhaps another way to say this is “copying a branch from a tree to inside a branch in another tree”.

Are you looking for Tree friends? https://root.cern.ch/root/htmldoc/guides/users-guide/Trees.html#example-3-adding-friends-to-trees

It is my understanding that adding a friend to a tree, or a branch to a tree as would be the case here, is like a symbolic link. That if you move the file which is friended, the file with the friends won’t behave as expected anymore. As such, I would like to copy (or clone?) the branches of a tree and write them to inside a parent branch. So that the resulting file with the tree containing these parent branches can be moved without the original file that it copied from.

Hi,

I am not sure about the usecase which would force you to need “to copy a branch in a branch”.
Suppose you have a tree T1 with a branche a1 and a tree called T2 with branches a2.
Would having in the end a tree T3 which has two branches, a1 and a2, be a viable solution?

Cheers,
D

Thank you for your response, D.

I will try to rephrase the question in your terminology. Suppose I have two trees T1 and T2 with the same number of entries and having the same branch structure. Let’s call the collective branches of T1 as b1 and T2 as b2. I would like to create an additional tree T3 with two parent branches b3a and b3b. The parent branch b3a would contain a copy of the branches b1, while the parent branch b3b would contain a copy of the branches b2.

Best,
John

Hi John,

while I can propose already some solutions for “transferring” branches, I am not sure about the grouping. Could a flat structure with different names, say with a prefix, do the job?

Cheers,
D

Hi D,

If I were to use a prefix on the branches inside of b1 and b2, I suppose I could then just add these prefixed branches directly into a tree T3, and then not use parent branches. I would prefer not to do that, though. What are some of these other solutions that you have?

Best,
John

Hi John,

why do those branches need to be boxed into other “super branches”?

D

I thought such “super branches” exist as “parent branches”? This is what the copy constructor in the TBranch class,

TBranch::TBranch(TBranch *parent, const char *name, void *address, const char *leaflist, Int_t basketsize, Int_t compress)

refers to?

Hi again D,

The trees these “super branches” correspond to are to have the same tree friends added to them. I could just add these friends directly every single time I load up the file containing these trees, but I would much rather prefer to only have to add friends to a single tree, rather than add the same friends over multiple friends. I would rather not write a for-loop to add these friends in one go, and I would like to also see proper usage of adding branches within branches, if that is possible.

Best,
John

I noticed under the TBranch Class Reference there is a friend class “TTreeCloner”. Can this be used somehow? I haven’t found referenceable applications of this class.

Note that TTreeCloner is the implementation of CloneTree …

I will try to rephrase the question in your terminology. Suppose I have two trees T1 and T2 with the same number of entries and having the same branch structure. Let’s call the collective branches of T1 as b1 and T2 as b2. I would like to create an additional tree T3 with two parent branches b3a and b3b. The parent branch b3a would contain a copy of the branches b1, while the parent branch b3b would contain a copy of the branches b2

This is essentially what AddFriend does, without having to copy the data. Why is that not working for you? (i.e what is missing)?

Cheers,
Philippe.

Hello Philippe,

Allow me to share the current implementation of the main function in the macro that I am trying to use. Included are lines commented out from previous attempts.

void refactorPolarityTestsFileA4() {

//  Open original format file and access its trees.
TFile polarityTestsFile("waisPolCutFilesA4/polarityTestsFileA4.root");
TTree * eventTree = (TTree *) polarityTestsFile.Get("eventTree");
TTree * waisPointingTree = (TTree *) polarityTestsFile.Get("waisPointingTree");
TTree * polarityTestsTree = (TTree *) polarityTestsFile.Get("polarityTestsTree");
TTree * deconvPolarityTestsTree = (TTree *) polarityTestsFile.Get("deconvPolarityTestsTree");
TTree * windowedPolarityTestsTree = (TTree *) polarityTestsFile.Get("windowedPolarityTestsTree");
TTree * windowedDeconvPolarityTestsTree = (TTree *) polarityTestsFile.Get("windowedDeconvPolarityTestsTree");

//  Create file to store trees in, then new tree to store 4 trees.
TFile reformattedFile("waisPolCutFilesA4/polarityTestsFileA4reformatted.root", "recreate");
TTree reformattedTree("polarityTestsTree", "TTree storing polarity test results");
TBranch waveformTests, deconvTests, windowedTests, windowedDeconvTests;
reformattedTree.Branch("waveformTests.", & waveformTests);
reformattedTree.Branch("deconvTests.", & deconvTests);
reformattedTree.Branch("windowedTests.", & windowedTests);
reformattedTree.Branch("windowedDeconvTests.", & windowedDeconvTests);

//  Structure the branches of the reformatted tree.

// TBranch waveformBranch[6], deconvBranch[6], windowedBranch[6], windowedDeconvBranch[6];
// polarity waveformStruct[6], deconvStruct[6], windowedStruct[6], windowedDeconvStruct[6];
// addSubbranches(waveformTests, waveformBranch, waveformStruct);
// addSubbranches(deconvTests, deconvBranch, deconvStruct);
// addSubbranches(windowedTests, windowedBranch, windowedStruct);
// addSubbbranches(windowedDeconvTests, windowedDeconvBranch, windowedDeconvStruct);

//  Now, copy the branches.
CollectBranches(polarityTestsTree -> GetListOfBranches(), waveformTests.GetListOfBranches());
reformattedTree.CollectBranches(deconvPolarityTestsTree -> GetListOfBranches(), deconvTests.GetListOfBranches());
reformattedTree.CollectBranches(windowedPolarityTestsTree -> GetListOfBranches(), windowedTests.GetListOfBranches());
reformattedTree.CollectBranches(windowedDeconvPolarityTestsTree -> GetListOfBranches(), windowedDeconvTests.GetListOfBranches());

// waveformTests.GetListOfBranches() -> Add((TObjArray *) polarityTestsTree -> GetListOfBranches() -> Clone());
// deconvTests.GetListOfBranches() -> Add((TObjArray *) deconvPolarityTestsTree -> GetListOfBranches() -> Clone());
// windowedTests.GetListOfBranches() -> Add((TObjArray *) windowedPolarityTestsTree -> GetListOfBranches() -> Clone());
// windowedDeconvTests.GetListOfBranches() -> Add((TObjArray *) windowedDeconvPolarityTestsTree -> GetListOfBranches() -> Clone());
// branchCopy(polarityTestsTree, waveformTests);
// branchCopy(deconvPolarityTestsTree, deconvTests);
// branchCopy(windowedPolarityTestsTree, windowedTests);
// branchCopy(windowedDeconvPolarityTestsTree, windowedDeconvTests);

//  Now, to write to this new tree.

// for (int entryNum = 0; entryNum < waisPointingTree -> GetEntries(); ++entryNum) {
//
// polarityTestsTree -> GetEntry(entryNum);
// deconvPolarityTestsTree -> GetEntry(entryNum);
// windowedPolarityTestsTree -> GetEntry(entryNum);
// windowedDeconvPolarityTestsTree -> GetEntry(entryNum);
//
//// reformattedTree.Fill();
// waveformTests.Fill();
// deconvTests.Fill();
// windowedTests.Fill();
// windowedDeconvTests.Fill();
// }

//  Write to the relevant trees to the reformatted file.
reformattedFile.cd();
eventTree -> CloneTree() -> Write();
waisPointingTree -> CloneTree() -> Write();
reformattedTree.Write();

//  Closing files.
reformattedFile.Close();
polarityTestsFile.Close();

}

Beyond, the ‘how’ you are try to implement this construct/organization, I am trying to understand the why (as so far just replacing all the copy by using AddFriend seem likely to actually do what you need). So could you clarify why AddFriend would not satisfy you need (let you accomplish what you need to do in the end)?

Am I correct in assuming that by “using AddFriend()”, you mean to apply the same set of AddFriend() commands to each of the 4 trees? That does work, but I would like to see an alternative method where I could then use AddFriend() on a single tree with parent branches, rather than having to repeatedly issue the same AddFriend() command to each tree a given branch would correspond to.

Or do you mean to make a tree of friends? I would like to make a standalone restructured copy of the file, like how I try to do in the above, rather than that. The tree of friends would become unusable if the location of friends change, right?

you mean to apply the same set of AddFriend() commands to each of the 4 trees?

No, one of them is likely sufficient.

TFile polarityTestsFile("waisPolCutFilesA4/polarityTestsFileA4.root","UPDATE");
TTree * polarityTestsTree = (TTree *) polarityTestsFile.Get("polarityTestsTree");
polarityTestsTree->AddFriend("deconvPolarityTestsTree");
polarityTestsTree->AddFriend("windowedPolarityTestsTree");
polarityTestsTree->AddFriend("windowedDeconvPolarityTestsTree");
polarityTestsFile.Write();

and from then on use ‘just’ the polarityTestsTree to have all 4 sets of branches.

or maybe even

TFile polarityTestsFile("waisPolCutFilesA4/polarityTestsFileA4.root","UPDATE");
TTree * eventTree = (TTree *) polarityTestsFile.Get("eventTree");
eventTree->AddFriend("waisPointingTree");
eventTree->AddFriend("polarityTestsTree");
eventTree->AddFriend("deconvPolarityTestsTree");
eventTree->AddFriend("windowedPolarityTestsTree");
eventTree->AddFriend("windowedDeconvPolarityTestsTree");
polarityTestsFile.Write();

and from then on use ‘just’ the eventTree.

Cheers,
Philippe.

PS.

TBranch waveformTests, deconvTests, windowedTests, windowedDeconvTests;
reformattedTree.Branch("waveformTests.", & waveformTests);

This would create a Branch containing as data another ‘TBranch’ object (not your data objects).

Thank you Philippe,

I apologize, I seem to be having difficulty in trying to get across what it is that I want to see how to do. It seems like you are proposing a tree of friends, or a tree with friends.

PS.
TBranch waveformTests, deconvTests, windowedTests, windowedDeconvTests;
reformattedTree.Branch(“waveformTests.”, & waveformTests);

This would create a Branch containing as data another ‘TBranch’ object (not your data objects).

I would like to see how to take the branches inside of “polarityTestsTree”, “deconvPolarityTestsTree”, “windowedPolarityTestsTree”, and “windowedDeconvPolarityTestsTree”, and then copy them respectively into the parent branches of “waveformTests”, “deconvTests”, “windowedTests”, and “windowedDeconvTests”. The branches inside of the initial 4 trees contain only leaves, all with the same number of entries.

Best,
John

I understood that but I never grasped why you want it that way (and why Friend don’t help for what you need).

I think “want” and “need” are two different things here. I just want to see an application of the constructor

TBranch::TBranch(TBranch * parent, const char * name, void * address, const char * leaflist, Int_t basketsize = 32000, Int_t compress = -1)

Using AddFriend() in the way that you suggest gets what is needed to be done now, but if the trees were to be ultimately friended together, why not place them together into a single tree in the first place? Part of the problem is that each tree has a collection of branches with the same name, so to do that you would have to rename the branches. To avoid renaming the branches, we should be able to place each tree’s branches into a parent branch. Otherwise, what is the purpose of having the above constructor?