Saving same TTree under different names in a file

_ROOT Version: tags/v6-18-04@v6-18-04
_Platform: x86_64-centos7-gcc8-opt
_Compiler: ROOT macro

For some reasons I need to be able to access the exact same TTree using different tree names ( O(10) ). All trees should be accessible from the same file.

What is the smartest way to do this from a memory/size point of view? Are multiple hard copies (using CloneTree) unavoidable?

I thought about creating friends with only a single branch copied from the original tree but then the additional trees do not have the exact same structure (in terms of branch read directly from them or from the original tree) than the original and ROOT gets confused when both types are read at the same time e.g. in a TChain (see Behavior of TChain when adding Trees which have friends already defined)

Thanks a lot in advance for your ideas :slight_smile:

Cheers
Matthias

For some reasons I need to be able to access the exact same TTree using different tree names ( O(10) )

I am not quite understanding what that means. What is the higher level goal you are trying to achieve with that implementation?

I understand it is not obvious, it was not to me neither in the first place :slight_smile:

In the framework I am using, systematic uncertainties are evaluated by comparing a nominal tree to a systematic tree, e.g. :

treeMC_nominal -> treeMC_syst1_up

In practice there are TChains defined behind the scene and the tree name is swaped when evaluating nominal, syst1_up and syst1_down

This is now a special systematic where treeMC_syst1_up is actually defined by:

treeMC_syst1_up = treeMCsmeared_syst1_up - treePDsmeared_syst1_up + treeMC_nominal

(PD means pseudo-data here)

So that I need the nominal tree to be accessed as well when I call “treeMC_syst1_up”

treeMCsmeared_syst1_up and treePDsmeared_syst1_up have to be named “treeMC_syst1_up” and treePDsmeared_syst1_up need to be called with a negative sign but I figured out a way to do that already.

the only issue is for the nominal tree, as it has to be accessible under many different names

I am missing some practical details (eg implemenation of “tree name is swaped”) but tt sounds like something like:

TChain *copy = (TChain*)original->Clone(); // Note this is Clone not CloneTree, it will only copy the list of files, alternatively you can just create the copy the same way as the original.
original->AddFriend(copy, alternate_name);

would do …

Hi,

actually the goal is not to modify the framework I am using, and also more generally I was wondering if there is a smart way in a file which looks like this:

TFile* file.root
KEY: TTree tree_nom

to retrieve the tree_nom tree with another name without making a hard copy with CloneTree, i.e. some sort of symlink for ROOT objects which could be saved in this file on top of the original TTree.

Cheers
Matthias

Why is the code/idea I showed above not a way to do so?

AddFriend is the best of way of providing an alias to the tree name.

some sort of symlink for ROOT objects which could be saved in this file on top of the original TTree.

It all depends on how those “symlink” will be later used (does it need to be persistent? will they be read by a TChain or not?).

One thing that do something useful:

auto file = TFile::Open(filename, "UPDATE");
auto tree = file->Get<TTree>(treename);
auto tfriend = new TTree(trampolinename,"");
tfriend->AddFriend(tree, aliasname);
file->WriteObject(tfriend);
file->Write();
delete file;

I am not sure what you mean by “persistent” and yes, those “symlink” will have to be read by a TChain, together with other trees (in different files) with the same name but not using the “symlink” system

I thought about creating friends with only a single branch copied from the original tree but then the additional trees do not have the exact same structure (in terms of branch read directly from them or from the original tree) than the original and ROOT gets confused when both types are read at the same time e.g. in a TChain (see Behavior of TChain when adding Trees which have friends already defined)

I thought about using the TreeFriend system (which in general is very useful) but the issue is summarised above, ultimately I would like to include all three variations I need in a single TChain (using a single tree name) and only the “nominal” tree will include this friend system so the TChain will get confused, as reported in the thread mentioned above.

Maybe actually the easiest way would be to fix the weird TChain behavior? If you think so I can work on a reproducible example next week.

Ok I enclose here a reproducer of the Friend/TChain issue

reproducible_example.cxx (2.0 KB)

As one can see, since the two trees (with same name) added to the TChain have each a friend with a different name, the Draw function does not have the expected behavior and only the first tree is read correctly.

A similar non-expected behavior happens if one tree has for instance the “x” branch define in its friend and the other one has it defined directly.

Solving this would resolve my problem.

So in your example you have a TChain with 2 files:

(1) f_tree1.root with TTree t and friend t_friend1 inside file t_friend1.root
(2) f_tree2.root with TTree t and friend t_friend2 inside file t_friend2.root

When TTree::Draw parses the expression “x”, it notices it is in a friend named “t_friend1” and thus record the branch name as "t_friend1.x"

Upon opening the second file, it properly load the TTree t and its friend t_friend2 but can not find any trace of "t_friend1.x" and has not information to know that t_friend2 and t_friend1 are semantically the same.

thus the unexpected result.

To solve this problem, at least in the context of this example it is enough to call the TTree stored in the file t_friend2.root with the name t_friend1.

For the same reason that it is the ‘right’ thing to have the main TTree call t in both t_tree1.root and t_tree2.root, it is the right thing to call the friend with the same name in the 2 distinct files.

PS. The reason to record the “full name” of the branch (including the friend name as a prefix) is that some element of the chain could have a 2nd friend with a different tree name with the same branch name and TTree::Draw could pick up the wrong one if it did not record the friend name.

Hi Philip,

I understand that on the technical side there are reasons to do things this way, but on the user perspective this is a strong limitation which is quite unfortunate. A typical use case is the example I mentioned in my first post on this thread.

More generally, this limits quite a bit the usage of FriendTrees, which otherwise could bring a lot more additional flexibility in the bookkeeping, which is getting more and more complex given the size of the datasets e.g. at the LHC.

I played a bit more with the TTree Friends and realised there is the possibility to give to the FriendElement an alias when using AddFriend, I enclose an update of my reproducer where the feature is fixed

reproducible_example.cxx (2.0 KB)

Is this the expected behavior? So at the end it seems the technical limitation was not that hard.

Is it possible to do the same for branches? Then I think the issue below could also be fixed

A similar non-expected behavior happens if one tree has for instance the “x” branch define in its friend and the other one has it defined directly.

by defining branch aliases on a tree by tree basis

For completeness’ sake could extend the reproducible_example to include the situation that makes using

void CreateTree(std::string name, bool isFriend=true) {
...
   if(isFriend)
   {
     T = new TTree( "t_friend", "");
...
   }
   else
   {
     T = new TTree( "t","");
...
   }

a problem/downside.

Thanks,
Philippe.

This is clearly over simplified but I hope it still gives a better idea of the use case and related issue:

reproducible_example.cxx (4.2 KB)

I can also provide you with an other example illustration the use case for the branch issue I mentioned above.

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